commit 0be88d7908197ffcf0be8848cbbe096016e1529e
Author: Elias <36868565+Prodigist@users.noreply.github.com>
Date: Sat Feb 1 09:31:17 2025 +0000
Initial commit: ReactiveNotes plugin
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..81f3ec3
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,10 @@
+# top-most EditorConfig file
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+insert_final_newline = true
+indent_style = tab
+indent_size = 4
+tab_width = 4
diff --git a/.env b/.env
new file mode 100644
index 0000000..edde2fa
--- /dev/null
+++ b/.env
@@ -0,0 +1,6 @@
+// .env file (Do NOT commit this file)
+ALPHA_VANTAGE_PRIMARY_KEY=7NMNWUG3QGNSK9J2
+ALPHA_VANTAGE_SECONDARY_KEY=9H7UI9KW24V8UXCW
+MARKET_DATA_CACHE_DURATION=86400000
+TIMEZONE=US/Eastern
+
diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..f249cda
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,5 @@
+// .env.example file
+ALPHA_VANTAGE_PRIMARY_KEY=your_primary_key_here
+ALPHA_VANTAGE_SECONDARY_KEY=your_secondary_key_here
+MARKET_DATA_CACHE_DURATION=86400000
+TIMEZONE=US/Eastern
\ No newline at end of file
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..e019f3c
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,3 @@
+node_modules/
+
+main.js
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..0807290
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,23 @@
+{
+ "root": true,
+ "parser": "@typescript-eslint/parser",
+ "env": { "node": true },
+ "plugins": [
+ "@typescript-eslint"
+ ],
+ "extends": [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/eslint-recommended",
+ "plugin:@typescript-eslint/recommended"
+ ],
+ "parserOptions": {
+ "sourceType": "module"
+ },
+ "rules": {
+ "no-unused-vars": "off",
+ "@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
+ "@typescript-eslint/ban-ts-comment": "off",
+ "no-prototype-builtins": "off",
+ "@typescript-eslint/no-empty-function": "off"
+ }
+ }
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..7c1cda3
Binary files /dev/null and b/.gitignore differ
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000..b973752
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+tag-version-prefix=""
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..c773152
--- /dev/null
+++ b/README.md
@@ -0,0 +1,94 @@
+# Obsidian Sample Plugin
+
+This is a sample plugin for Obsidian (https://obsidian.md).
+
+This project uses TypeScript to provide type checking and documentation.
+The repo depends on the latest plugin API (obsidian.d.ts) in TypeScript Definition format, which contains TSDoc comments describing what it does.
+
+This sample plugin demonstrates some of the basic functionality the plugin API can do.
+- Adds a ribbon icon, which shows a Notice when clicked.
+- Adds a command "Open Sample Modal" which opens a Modal.
+- Adds a plugin setting tab to the settings page.
+- Registers a global click event and output 'click' to the console.
+- Registers a global interval which logs 'setInterval' to the console.
+
+## First time developing plugins?
+
+Quick starting guide for new plugin devs:
+
+- Check if [someone already developed a plugin for what you want](https://obsidian.md/plugins)! There might be an existing plugin similar enough that you can partner up with.
+- Make a copy of this repo as a template with the "Use this template" button (login to GitHub if you don't see it).
+- Clone your repo to a local development folder. For convenience, you can place this folder in your `.obsidian/plugins/your-plugin-name` folder.
+- Install NodeJS, then run `npm i` in the command line under your repo folder.
+- Run `npm run dev` to compile your plugin from `main.ts` to `main.js`.
+- Make changes to `main.ts` (or create new `.ts` files). Those changes should be automatically compiled into `main.js`.
+- Reload Obsidian to load the new version of your plugin.
+- Enable plugin in settings window.
+- For updates to the Obsidian API run `npm update` in the command line under your repo folder.
+
+## Releasing new releases
+
+- Update your `manifest.json` with your new version number, such as `1.0.1`, and the minimum Obsidian version required for your latest release.
+- Update your `versions.json` file with `"new-plugin-version": "minimum-obsidian-version"` so older versions of Obsidian can download an older version of your plugin that's compatible.
+- Create new GitHub release using your new version number as the "Tag version". Use the exact version number, don't include a prefix `v`. See here for an example: https://github.com/obsidianmd/obsidian-sample-plugin/releases
+- Upload the files `manifest.json`, `main.js`, `styles.css` as binary attachments. Note: The manifest.json file must be in two places, first the root path of your repository and also in the release.
+- Publish the release.
+
+> You can simplify the version bump process by running `npm version patch`, `npm version minor` or `npm version major` after updating `minAppVersion` manually in `manifest.json`.
+> The command will bump version in `manifest.json` and `package.json`, and add the entry for the new version to `versions.json`
+
+## Adding your plugin to the community plugin list
+
+- Check the [plugin guidelines](https://docs.obsidian.md/Plugins/Releasing/Plugin+guidelines).
+- Publish an initial version.
+- Make sure you have a `README.md` file in the root of your repo.
+- Make a pull request at https://github.com/obsidianmd/obsidian-releases to add your plugin.
+
+## How to use
+
+- Clone this repo.
+- Make sure your NodeJS is at least v16 (`node --version`).
+- `npm i` or `yarn` to install dependencies.
+- `npm run dev` to start compilation in watch mode.
+
+## Manually installing the plugin
+
+- Copy over `main.js`, `styles.css`, `manifest.json` to your vault `VaultFolder/.obsidian/plugins/your-plugin-id/`.
+
+## Improve code quality with eslint (optional)
+- [ESLint](https://eslint.org/) is a tool that analyzes your code to quickly find problems. You can run ESLint against your plugin to find common bugs and ways to improve your code.
+- To use eslint with this project, make sure to install eslint from terminal:
+ - `npm install -g eslint`
+- To use eslint to analyze this project use this command:
+ - `eslint main.ts`
+ - eslint will then create a report with suggestions for code improvement by file and line number.
+- If your source code is in a folder, such as `src`, you can use eslint with this command to analyze all files in that folder:
+ - `eslint .\src\`
+
+## Funding URL
+
+You can include funding URLs where people who use your plugin can financially support it.
+
+The simple way is to set the `fundingUrl` field to your link in your `manifest.json` file:
+
+```json
+{
+ "fundingUrl": "https://buymeacoffee.com"
+}
+```
+
+If you have multiple URLs, you can also do:
+
+```json
+{
+ "fundingUrl": {
+ "Buy Me a Coffee": "https://buymeacoffee.com",
+ "GitHub Sponsor": "https://github.com/sponsors",
+ "Patreon": "https://www.patreon.com/"
+ }
+}
+```
+
+## API Documentation
+
+See https://github.com/obsidianmd/obsidian-api
diff --git a/esbuild.config.mjs b/esbuild.config.mjs
new file mode 100644
index 0000000..596aeaf
--- /dev/null
+++ b/esbuild.config.mjs
@@ -0,0 +1,66 @@
+import esbuild from "esbuild";
+import process from "process";
+import builtins from "builtin-modules";
+
+const banner =
+`/*
+THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
+if you want to view the source, please visit the github repository of this plugin
+*/
+`;
+
+const prod = (process.argv[2] === "production");
+
+const context = await esbuild.context({
+ banner: {
+ js: banner,
+ },
+ entryPoints: ["main.tsx"],
+ bundle: true,
+ external: [
+ "obsidian",
+ "electron",
+ "@codemirror/autocomplete",
+ "@codemirror/collab",
+ "@codemirror/commands",
+ "@codemirror/language",
+ "@codemirror/lint",
+ "@codemirror/search",
+ "@codemirror/state",
+ "@codemirror/view",
+ "@lezer/common",
+ "@lezer/highlight",
+ "@lezer/lr",
+ ...builtins],
+ format: "cjs",
+ target: "es2020",
+ platform: "node", // Add this for Node.js compatibility
+ logLevel: "info",
+ sourcemap: prod ? false : "inline",
+ treeShaking: true,
+ outfile: "main.js",
+ minify: prod,
+ jsx: "transform", // Add this line
+ loader: { // Add loader configuration
+ '.tsx': 'tsx',
+ '.ts': 'ts',
+ '.jsx': 'jsx',
+ '.js': 'js',
+ '.css': 'css', // Add CSS loader
+ '.json': 'json' // Add JSON loader for Tailwind config
+ },
+ define: { // Add environment definitions
+ 'process.env.NODE_ENV': prod ? '"production"' : '"development"',
+ global: 'window'
+ },
+ inject: [ // Add React shim
+ './react-shim.js'
+ ],
+});
+
+if (prod) {
+ await context.rebuild();
+ process.exit(0);
+} else {
+ await context.watch();
+}
diff --git a/lwc-plugin-custom-primitives/.gitignore b/lwc-plugin-custom-primitives/.gitignore
new file mode 100644
index 0000000..a90cc13
--- /dev/null
+++ b/lwc-plugin-custom-primitives/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+typings
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/lwc-plugin-custom-primitives/README.md b/lwc-plugin-custom-primitives/README.md
new file mode 100644
index 0000000..211250c
--- /dev/null
+++ b/lwc-plugin-custom-primitives/README.md
@@ -0,0 +1,38 @@
+# Custom Primitives - Lightweight Charts™ Plugin
+
+Description of the Plugin.
+
+- Developed for Lightweight Charts version: `v4.1.0`
+
+## Running Locally
+
+```shell
+npm install
+npm run dev
+```
+
+Visit `localhost:5173` in the browser.
+
+## Compiling
+
+```shell
+npm run compile
+```
+
+Check the output in the `dist` folder.
+
+## Publishing To NPM
+
+You can configure the contents of the package's `package.json` within the
+`compile.mjs` script.
+
+Once you have compiled the plugin (see above section) then you can publish the
+package to NPM with these commands:
+
+```shell
+cd dist
+npm publish
+```
+
+Hint: append `--dry-run` to the end of the publish command to see the results of
+the publish command without actually uploading the package to NPM.
diff --git a/lwc-plugin-custom-primitives/compile.mjs b/lwc-plugin-custom-primitives/compile.mjs
new file mode 100644
index 0000000..ffc34b5
--- /dev/null
+++ b/lwc-plugin-custom-primitives/compile.mjs
@@ -0,0 +1,116 @@
+import { dirname, resolve } from 'node:path';
+import { copyFileSync, existsSync, mkdirSync, writeFileSync } from 'node:fs';
+import { build, defineConfig } from 'vite';
+import { fileURLToPath } from 'url';
+import { generateDtsBundle } from 'dts-bundle-generator';
+
+function buildPackageJson(packageName) {
+ /*
+ Define the contents of the package's package.json here.
+ */
+ return {
+ name: packageName,
+ version: '1.0.0',
+ keywords: ['lwc-plugin', 'lightweight-charts'],
+ type: 'module',
+ main: `./${packageName}.umd.cjs`,
+ module: `./${packageName}.js`,
+ types: `./${packageName}.d.ts`,
+ exports: {
+ import: {
+ types: `./${packageName}.d.ts`,
+ default: `./${packageName}.js`,
+ },
+ require: {
+ types: `./${packageName}.d.cts`,
+ default: `./${packageName}.umd.cjs`,
+ },
+ },
+ };
+}
+
+const __filename = fileURLToPath(import.meta.url);
+const currentDir = dirname(__filename);
+
+const pluginFileName = 'custom-primitives';
+const pluginFile = resolve(currentDir, 'src', `${pluginFileName}.ts`);
+
+const pluginsToBuild = [
+ {
+ filepath: pluginFile,
+ exportName: 'lwc-plugin-custom-primitives',
+ name: 'CustomPrimitives',
+ },
+];
+
+const compiledFolder = resolve(currentDir, 'dist');
+if (!existsSync(compiledFolder)) {
+ mkdirSync(compiledFolder);
+}
+
+const buildConfig = ({
+ filepath,
+ name,
+ exportName,
+ formats = ['es', 'umd'],
+}) => {
+ return defineConfig({
+ publicDir: false,
+ build: {
+ outDir: `dist`,
+ emptyOutDir: true,
+ copyPublicDir: false,
+ lib: {
+ entry: filepath,
+ name,
+ formats,
+ fileName: exportName,
+ },
+ rollupOptions: {
+ external: ['lightweight-charts', 'fancy-canvas'],
+ output: {
+ globals: {
+ 'lightweight-charts': 'LightweightCharts',
+ },
+ },
+ },
+ },
+ });
+};
+
+const startTime = Date.now().valueOf();
+console.log('⚡️ Starting');
+console.log('Bundling the plugin...');
+const promises = pluginsToBuild.map(file => {
+ return build(buildConfig(file));
+});
+await Promise.all(promises);
+console.log('Generating the package.json file...');
+pluginsToBuild.forEach(file => {
+ const packagePath = resolve(compiledFolder, 'package.json');
+ const content = JSON.stringify(
+ buildPackageJson(file.exportName),
+ undefined,
+ 4
+ );
+ writeFileSync(packagePath, content, { encoding: 'utf-8' });
+});
+console.log('Generating the typings files...');
+pluginsToBuild.forEach(file => {
+ try {
+ const esModuleTyping = generateDtsBundle([
+ {
+ filePath: `./typings/${pluginFileName}.d.ts`,
+ },
+ ]);
+ const typingFilePath = resolve(compiledFolder, `${file.exportName}.d.ts`);
+ writeFileSync(typingFilePath, esModuleTyping.join('\n'), {
+ encoding: 'utf-8',
+ });
+ copyFileSync(typingFilePath, resolve(compiledFolder, `${file.exportName}.d.cts`));
+ } catch (e) {
+ console.error('Error generating typings for: ', file.exportName);
+ }
+});
+const endTime = Date.now().valueOf();
+console.log(`🎉 Done (${endTime - startTime}ms)`);
diff --git a/lwc-plugin-custom-primitives/index.html b/lwc-plugin-custom-primitives/index.html
new file mode 100644
index 0000000..3f1b3a1
--- /dev/null
+++ b/lwc-plugin-custom-primitives/index.html
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/lwc-plugin-custom-primitives/package.json b/lwc-plugin-custom-primitives/package.json
new file mode 100644
index 0000000..6bf8786
--- /dev/null
+++ b/lwc-plugin-custom-primitives/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "lwc-plugin-custom-primitives",
+ "type": "module",
+ "scripts": {
+ "dev": "vite --config src/vite.config.js",
+ "compile": "tsc && node compile.mjs"
+ },
+ "devDependencies": {
+ "typescript": "^5.0.4",
+ "vite": "^4.3.1"
+ },
+ "dependencies": {
+ "dts-bundle-generator": "^8.0.1",
+ "fancy-canvas": "^2.1.0",
+ "lightweight-charts": "^4.1.0-rc2"
+ }
+}
diff --git a/lwc-plugin-custom-primitives/src/axis-pane-renderer.ts b/lwc-plugin-custom-primitives/src/axis-pane-renderer.ts
new file mode 100644
index 0000000..49380b2
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/axis-pane-renderer.ts
@@ -0,0 +1,41 @@
+import { CanvasRenderingTarget2D } from 'fancy-canvas';
+import { ISeriesPrimitivePaneRenderer } from 'lightweight-charts';
+import { positionsBox } from './helpers/dimensions/positions';
+
+export class CustomPrimitivesAxisPaneRenderer implements ISeriesPrimitivePaneRenderer {
+ _p1: number | null;
+ _p2: number | null;
+ _fillColor: string;
+ _vertical: boolean = false;
+
+ constructor(
+ p1: number | null,
+ p2: number | null,
+ fillColor: string,
+ vertical: boolean
+ ) {
+ this._p1 = p1;
+ this._p2 = p2;
+ this._fillColor = fillColor;
+ this._vertical = vertical;
+ }
+
+ draw(target: CanvasRenderingTarget2D) {
+ target.useBitmapCoordinateSpace(scope => {
+ if (this._p1 === null || this._p2 === null) return;
+ const ctx = scope.context;
+ ctx.globalAlpha = 0.5;
+ const positions = positionsBox(
+ this._p1,
+ this._p2,
+ this._vertical ? scope.verticalPixelRatio : scope.horizontalPixelRatio
+ );
+ ctx.fillStyle = this._fillColor;
+ if (this._vertical) {
+ ctx.fillRect(0, positions.position, 15, positions.length);
+ } else {
+ ctx.fillRect(positions.position, 0, positions.length, 15);
+ }
+ });
+ }
+}
diff --git a/lwc-plugin-custom-primitives/src/axis-pane-view.ts b/lwc-plugin-custom-primitives/src/axis-pane-view.ts
new file mode 100644
index 0000000..a040e98
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/axis-pane-view.ts
@@ -0,0 +1,55 @@
+import {
+ Coordinate,
+ ISeriesPrimitivePaneView,
+ SeriesPrimitivePaneViewZOrder,
+} from 'lightweight-charts';
+import { CustomPrimitivesAxisPaneRenderer } from './axis-pane-renderer';
+import { CustomPrimitivesDataSource } from './data-source';
+
+abstract class CustomPrimitivesAxisPaneView implements ISeriesPrimitivePaneView {
+ _source: CustomPrimitivesDataSource;
+ _p1: number | null = null;
+ _p2: number | null = null;
+ _vertical: boolean = false;
+
+ constructor(source: CustomPrimitivesDataSource, vertical: boolean) {
+ this._source = source;
+ this._vertical = vertical;
+ }
+
+ abstract getPoints(): [Coordinate | null, Coordinate | null];
+
+ update() {
+ [this._p1, this._p2] = this.getPoints();
+ }
+
+ renderer() {
+ return new CustomPrimitivesAxisPaneRenderer(
+ this._p1,
+ this._p2,
+ this._source.options.fillColor,
+ this._vertical
+ );
+ }
+ zOrder(): SeriesPrimitivePaneViewZOrder {
+ return 'bottom';
+ }
+}
+
+export class CustomPrimitivesPriceAxisPaneView extends CustomPrimitivesAxisPaneView {
+ getPoints(): [Coordinate | null, Coordinate | null] {
+ const series = this._source.series;
+ const y1 = series.priceToCoordinate(this._source.p1.price);
+ const y2 = series.priceToCoordinate(this._source.p2.price);
+ return [y1, y2];
+ }
+}
+
+export class CustomPrimitivesTimeAxisPaneView extends CustomPrimitivesAxisPaneView {
+ getPoints(): [Coordinate | null, Coordinate | null] {
+ const timeScale = this._source.chart.timeScale();
+ const x1 = timeScale.timeToCoordinate(this._source.p1.time);
+ const x2 = timeScale.timeToCoordinate(this._source.p2.time);
+ return [x1, x2];
+ }
+}
diff --git a/lwc-plugin-custom-primitives/src/axis-view.ts b/lwc-plugin-custom-primitives/src/axis-view.ts
new file mode 100644
index 0000000..435f73f
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/axis-view.ts
@@ -0,0 +1,57 @@
+import { Coordinate, ISeriesPrimitiveAxisView } from 'lightweight-charts';
+import { Point, CustomPrimitivesDataSource } from './data-source';
+
+abstract class CustomPrimitivesAxisView implements ISeriesPrimitiveAxisView {
+ _source: CustomPrimitivesDataSource;
+ _p: Point;
+ _pos: Coordinate | null = null;
+ constructor(source: CustomPrimitivesDataSource, p: Point) {
+ this._source = source;
+ this._p = p;
+ }
+ abstract update(): void;
+ abstract text(): string;
+
+ coordinate() {
+ return this._pos ?? -1;
+ }
+
+ visible(): boolean {
+ return this._source.options.showLabels;
+ }
+
+ tickVisible(): boolean {
+ return this._source.options.showLabels;
+ }
+
+ textColor() {
+ return this._source.options.labelTextColor;
+ }
+ backColor() {
+ return this._source.options.labelColor;
+ }
+ movePoint(p: Point) {
+ this._p = p;
+ this.update();
+ }
+}
+
+export class CustomPrimitivesTimeAxisView extends CustomPrimitivesAxisView {
+ update() {
+ const timeScale = this._source.chart.timeScale();
+ this._pos = timeScale.timeToCoordinate(this._p.time);
+ }
+ text() {
+ return this._source.options.timeLabelFormatter(this._p.time);
+ }
+}
+
+export class CustomPrimitivesPriceAxisView extends CustomPrimitivesAxisView {
+ update() {
+ const series = this._source.series;
+ this._pos = series.priceToCoordinate(this._p.price);
+ }
+ text() {
+ return this._source.options.priceLabelFormatter(this._p.price);
+ }
+}
diff --git a/lwc-plugin-custom-primitives/src/custom-primitives.ts b/lwc-plugin-custom-primitives/src/custom-primitives.ts
new file mode 100644
index 0000000..1dc770b
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/custom-primitives.ts
@@ -0,0 +1,139 @@
+import { AutoscaleInfo, Logical, Time, DataChangedScope } from 'lightweight-charts';
+import {
+ CustomPrimitivesPriceAxisPaneView,
+ CustomPrimitivesTimeAxisPaneView,
+} from './axis-pane-view';
+import { CustomPrimitivesPriceAxisView, CustomPrimitivesTimeAxisView } from './axis-view';
+import { Point, CustomPrimitivesDataSource } from './data-source';
+import { CustomPrimitivesOptions, defaultOptions } from './options';
+import { CustomPrimitivesPaneView } from './pane-view';
+import { PluginBase } from './plugin-base';
+
+export class CustomPrimitives
+ extends PluginBase
+ implements CustomPrimitivesDataSource
+{
+ _options: CustomPrimitivesOptions;
+ _p1: Point;
+ _p2: Point;
+ _paneViews: CustomPrimitivesPaneView[];
+ _timeAxisViews: CustomPrimitivesTimeAxisView[];
+ _priceAxisViews: CustomPrimitivesPriceAxisView[];
+ _priceAxisPaneViews: CustomPrimitivesPriceAxisPaneView[];
+ _timeAxisPaneViews: CustomPrimitivesTimeAxisPaneView[];
+
+ constructor(
+ p1: Point,
+ p2: Point,
+ options: Partial = {}
+ ) {
+ super();
+ this._p1 = p1;
+ this._p2 = p2;
+ this._options = {
+ ...defaultOptions,
+ ...options,
+ };
+ this._paneViews = [new CustomPrimitivesPaneView(this)];
+ this._timeAxisViews = [
+ new CustomPrimitivesTimeAxisView(this, p1),
+ new CustomPrimitivesTimeAxisView(this, p2),
+ ];
+ this._priceAxisViews = [
+ new CustomPrimitivesPriceAxisView(this, p1),
+ new CustomPrimitivesPriceAxisView(this, p2),
+ ];
+ this._priceAxisPaneViews = [new CustomPrimitivesPriceAxisPaneView(this, true)];
+ this._timeAxisPaneViews = [new CustomPrimitivesTimeAxisPaneView(this, false)];
+ }
+
+ updateAllViews() {
+ //* Use this method to update any data required by the
+ //* views to draw.
+ this._paneViews.forEach(pw => pw.update());
+ this._timeAxisViews.forEach(pw => pw.update());
+ this._priceAxisViews.forEach(pw => pw.update());
+ this._priceAxisPaneViews.forEach(pw => pw.update());
+ this._timeAxisPaneViews.forEach(pw => pw.update());
+ }
+
+ priceAxisViews() {
+ //* Labels rendered on the price scale
+ return this._priceAxisViews;
+ }
+
+ timeAxisViews() {
+ //* labels rendered on the time scale
+ return this._timeAxisViews;
+ }
+
+ paneViews() {
+ //* rendering on the main chart pane
+ return this._paneViews;
+ }
+
+ priceAxisPaneViews() {
+ //* rendering on the price scale
+ return this._priceAxisPaneViews;
+ }
+
+ timeAxisPaneViews() {
+ //* rendering on the time scale
+ return this._timeAxisPaneViews;
+ }
+
+ autoscaleInfo(
+ startTimePoint: Logical,
+ endTimePoint: Logical
+ ): AutoscaleInfo | null {
+ //* Use this method to provide autoscale information if your primitive
+ //* should have the ability to remain in view automatically.
+ if (
+ this._timeCurrentlyVisible(this.p1.time, startTimePoint, endTimePoint) ||
+ this._timeCurrentlyVisible(this.p2.time, startTimePoint, endTimePoint)
+ ) {
+ return {
+ priceRange: {
+ minValue: Math.min(this.p1.price, this.p2.price),
+ maxValue: Math.max(this.p1.price, this.p2.price),
+ },
+ };
+ }
+ return null;
+ }
+
+ dataUpdated(scope: DataChangedScope): void {
+ //* This method will be called by PluginBase when the data on the
+ //* series has changed.
+ }
+
+ _timeCurrentlyVisible(
+ time: Time,
+ startTimePoint: Logical,
+ endTimePoint: Logical
+ ): boolean {
+ const ts = this.chart.timeScale();
+ const coordinate = ts.timeToCoordinate(time);
+ if (coordinate === null) return false;
+ const logical = ts.coordinateToLogical(coordinate);
+ if (logical === null) return false;
+ return logical <= endTimePoint && logical >= startTimePoint;
+ }
+
+ public get options(): CustomPrimitivesOptions {
+ return this._options;
+ }
+
+ applyOptions(options: Partial) {
+ this._options = { ...this._options, ...options };
+ this.requestUpdate();
+ }
+
+ public get p1(): Point {
+ return this._p1;
+ }
+
+ public get p2(): Point {
+ return this._p2;
+ }
+}
diff --git a/lwc-plugin-custom-primitives/src/data-source.ts b/lwc-plugin-custom-primitives/src/data-source.ts
new file mode 100644
index 0000000..6c14142
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/data-source.ts
@@ -0,0 +1,20 @@
+import {
+ IChartApi,
+ ISeriesApi,
+ SeriesOptionsMap,
+ Time,
+} from 'lightweight-charts';
+import { CustomPrimitivesOptions } from './options';
+
+export interface Point {
+ time: Time;
+ price: number;
+}
+
+export interface CustomPrimitivesDataSource {
+ chart: IChartApi;
+ series: ISeriesApi;
+ options: CustomPrimitivesOptions;
+ p1: Point;
+ p2: Point;
+}
diff --git a/lwc-plugin-custom-primitives/src/example/example.ts b/lwc-plugin-custom-primitives/src/example/example.ts
new file mode 100644
index 0000000..a884dbe
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/example/example.ts
@@ -0,0 +1,23 @@
+import { createChart } from 'lightweight-charts';
+import { generateLineData } from '../sample-data';
+import { CustomPrimitives } from '../custom-primitives';
+
+const chart = ((window as unknown as any).chart = createChart('chart', {
+ autoSize: true,
+}));
+
+const lineSeries = chart.addLineSeries({
+ color: '#000000',
+});
+const data = generateLineData();
+lineSeries.setData(data);
+
+const time1 = data[data.length - 50].time;
+const time2 = data[data.length - 10].time;
+
+const primitive = new CustomPrimitives(
+ { price: 100, time: time1 },
+ { price: 500, time: time2 }
+);
+
+lineSeries.attachPrimitive(primitive);
diff --git a/lwc-plugin-custom-primitives/src/example/index.html b/lwc-plugin-custom-primitives/src/example/index.html
new file mode 100644
index 0000000..ed1334b
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/example/index.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+ Template Drawing Primitive Plugin Example
+
+
+
+
+
+
+
diff --git a/lwc-plugin-custom-primitives/src/helpers/assertions.ts b/lwc-plugin-custom-primitives/src/helpers/assertions.ts
new file mode 100644
index 0000000..e68742f
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/helpers/assertions.ts
@@ -0,0 +1,33 @@
+/**
+ * Ensures that value is defined.
+ * Throws if the value is undefined, returns the original value otherwise.
+ *
+ * @param value - The value, or undefined.
+ * @returns The passed value, if it is not undefined
+ */
+export function ensureDefined(value: undefined): never;
+export function ensureDefined(value: T | undefined): T;
+export function ensureDefined(value: T | undefined): T {
+ if (value === undefined) {
+ throw new Error('Value is undefined');
+ }
+
+ return value;
+}
+
+/**
+ * Ensures that value is not null.
+ * Throws if the value is null, returns the original value otherwise.
+ *
+ * @param value - The value, or null.
+ * @returns The passed value, if it is not null
+ */
+export function ensureNotNull(value: null): never;
+export function ensureNotNull(value: T | null): T;
+export function ensureNotNull(value: T | null): T {
+ if (value === null) {
+ throw new Error('Value is null');
+ }
+
+ return value;
+}
diff --git a/lwc-plugin-custom-primitives/src/helpers/dimensions/common.ts b/lwc-plugin-custom-primitives/src/helpers/dimensions/common.ts
new file mode 100644
index 0000000..394c6bb
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/helpers/dimensions/common.ts
@@ -0,0 +1,6 @@
+export interface BitmapPositionLength {
+ /** coordinate for use with a bitmap rendering scope */
+ position: number;
+ /** length for use with a bitmap rendering scope */
+ length: number;
+}
diff --git a/lwc-plugin-custom-primitives/src/helpers/dimensions/crosshair-width.ts b/lwc-plugin-custom-primitives/src/helpers/dimensions/crosshair-width.ts
new file mode 100644
index 0000000..9d14991
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/helpers/dimensions/crosshair-width.ts
@@ -0,0 +1,23 @@
+/**
+ * Default grid / crosshair line width in Bitmap sizing
+ * @param horizontalPixelRatio - horizontal pixel ratio
+ * @returns default grid / crosshair line width in Bitmap sizing
+ */
+export function gridAndCrosshairBitmapWidth(
+ horizontalPixelRatio: number
+): number {
+ return Math.max(1, Math.floor(horizontalPixelRatio));
+}
+
+/**
+ * Default grid / crosshair line width in Media sizing
+ * @param horizontalPixelRatio - horizontal pixel ratio
+ * @returns default grid / crosshair line width in Media sizing
+ */
+export function gridAndCrosshairMediaWidth(
+ horizontalPixelRatio: number
+): number {
+ return (
+ gridAndCrosshairBitmapWidth(horizontalPixelRatio) / horizontalPixelRatio
+ );
+}
diff --git a/lwc-plugin-custom-primitives/src/helpers/dimensions/full-width.ts b/lwc-plugin-custom-primitives/src/helpers/dimensions/full-width.ts
new file mode 100644
index 0000000..6f4d40d
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/helpers/dimensions/full-width.ts
@@ -0,0 +1,29 @@
+import { BitmapPositionLength } from './common';
+
+/**
+ * Calculates the position and width which will completely full the space for the bar.
+ * Useful if you want to draw something that will not have any gaps between surrounding bars.
+ * @param xMedia - x coordinate of the bar defined in media sizing
+ * @param halfBarSpacingMedia - half the width of the current barSpacing (un-rounded)
+ * @param horizontalPixelRatio - horizontal pixel ratio
+ * @returns position and width which will completely full the space for the bar
+ */
+export function fullBarWidth(
+ xMedia: number,
+ halfBarSpacingMedia: number,
+ horizontalPixelRatio: number
+): BitmapPositionLength {
+ const fullWidthLeftMedia = xMedia - halfBarSpacingMedia;
+ const fullWidthRightMedia = xMedia + halfBarSpacingMedia;
+ const fullWidthLeftBitmap = Math.round(
+ fullWidthLeftMedia * horizontalPixelRatio
+ );
+ const fullWidthRightBitmap = Math.round(
+ fullWidthRightMedia * horizontalPixelRatio
+ );
+ const fullWidthBitmap = fullWidthRightBitmap - fullWidthLeftBitmap;
+ return {
+ position: fullWidthLeftBitmap,
+ length: fullWidthBitmap,
+ };
+}
diff --git a/lwc-plugin-custom-primitives/src/helpers/dimensions/positions.ts b/lwc-plugin-custom-primitives/src/helpers/dimensions/positions.ts
new file mode 100644
index 0000000..a021b07
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/helpers/dimensions/positions.ts
@@ -0,0 +1,48 @@
+import { BitmapPositionLength } from './common';
+
+function centreOffset(lineBitmapWidth: number): number {
+ return Math.floor(lineBitmapWidth * 0.5);
+}
+
+/**
+ * Calculates the bitmap position for an item with a desired length (height or width), and centred according to
+ * an position coordinate defined in media sizing.
+ * @param positionMedia - position coordinate for the bar (in media coordinates)
+ * @param pixelRatio - pixel ratio. Either horizontal for x positions, or vertical for y positions
+ * @param desiredWidthMedia - desired width (in media coordinates)
+ * @returns Position of of the start point and length dimension.
+ */
+export function positionsLine(
+ positionMedia: number,
+ pixelRatio: number,
+ desiredWidthMedia: number = 1,
+ widthIsBitmap?: boolean
+): BitmapPositionLength {
+ const scaledPosition = Math.round(pixelRatio * positionMedia);
+ const lineBitmapWidth = widthIsBitmap
+ ? desiredWidthMedia
+ : Math.round(desiredWidthMedia * pixelRatio);
+ const offset = centreOffset(lineBitmapWidth);
+ const position = scaledPosition - offset;
+ return { position, length: lineBitmapWidth };
+}
+
+/**
+ * Determines the bitmap position and length for a dimension of a shape to be drawn.
+ * @param position1Media - media coordinate for the first point
+ * @param position2Media - media coordinate for the second point
+ * @param pixelRatio - pixel ratio for the corresponding axis (vertical or horizontal)
+ * @returns Position of of the start point and length dimension.
+ */
+export function positionsBox(
+ position1Media: number,
+ position2Media: number,
+ pixelRatio: number
+): BitmapPositionLength {
+ const scaledPosition1 = Math.round(pixelRatio * position1Media);
+ const scaledPosition2 = Math.round(pixelRatio * position2Media);
+ return {
+ position: Math.min(scaledPosition1, scaledPosition2),
+ length: Math.abs(scaledPosition2 - scaledPosition1) + 1,
+ };
+}
diff --git a/lwc-plugin-custom-primitives/src/helpers/time.ts b/lwc-plugin-custom-primitives/src/helpers/time.ts
new file mode 100644
index 0000000..ed65475
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/helpers/time.ts
@@ -0,0 +1,34 @@
+import { Time, isUTCTimestamp, isBusinessDay } from 'lightweight-charts';
+
+export function convertTime(t: Time): number {
+ if (isUTCTimestamp(t)) return t * 1000;
+ if (isBusinessDay(t)) return new Date(t.year, t.month, t.day).valueOf();
+ const [year, month, day] = t.split('-').map(parseInt);
+ return new Date(year, month, day).valueOf();
+}
+
+export function displayTime(time: Time): string {
+ if (typeof time == 'string') return time;
+ const date = isBusinessDay(time)
+ ? new Date(time.year, time.month, time.day)
+ : new Date(time * 1000);
+ return date.toLocaleDateString();
+}
+
+export function formattedDateAndTime(timestamp: number | undefined): [string, string] {
+ if (!timestamp) return ['', ''];
+ const dateObj = new Date(timestamp);
+
+ // Format date string
+ const year = dateObj.getFullYear();
+ const month = dateObj.toLocaleString('default', { month: 'short' });
+ const date = dateObj.getDate().toString().padStart(2, '0');
+ const formattedDate = `${date} ${month} ${year}`;
+
+ // Format time string
+ const hours = dateObj.getHours().toString().padStart(2, '0');
+ const minutes = dateObj.getMinutes().toString().padStart(2, '0');
+ const formattedTime = `${hours}:${minutes}`;
+
+ return [formattedDate, formattedTime];
+}
diff --git a/lwc-plugin-custom-primitives/src/options.ts b/lwc-plugin-custom-primitives/src/options.ts
new file mode 100644
index 0000000..04fa40c
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/options.ts
@@ -0,0 +1,27 @@
+import { Time, isBusinessDay } from 'lightweight-charts';
+
+export interface CustomPrimitivesOptions {
+ //* Define the options for the primitive.
+ fillColor: string;
+ labelColor: string;
+ labelTextColor: string;
+ showLabels: boolean;
+ priceLabelFormatter: (price: number) => string;
+ timeLabelFormatter: (time: Time) => string;
+}
+
+export const defaultOptions: CustomPrimitivesOptions = {
+ //* Define the default values for all the primitive options.
+ fillColor: 'rgba(200, 50, 100, 0.75)',
+ labelColor: 'rgba(200, 50, 100, 1)',
+ labelTextColor: 'white',
+ showLabels: true,
+ priceLabelFormatter: (price: number) => price.toFixed(2),
+ timeLabelFormatter: (time: Time) => {
+ if (typeof time == 'string') return time;
+ const date = isBusinessDay(time)
+ ? new Date(time.year, time.month, time.day)
+ : new Date(time * 1000);
+ return date.toLocaleDateString();
+ },
+} as const;
diff --git a/lwc-plugin-custom-primitives/src/pane-renderer.ts b/lwc-plugin-custom-primitives/src/pane-renderer.ts
new file mode 100644
index 0000000..a69c6cd
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/pane-renderer.ts
@@ -0,0 +1,46 @@
+import { CanvasRenderingTarget2D } from 'fancy-canvas';
+import { ISeriesPrimitivePaneRenderer } from 'lightweight-charts';
+import { ViewPoint } from './pane-view';
+import { positionsBox } from './helpers/dimensions/positions';
+
+export class CustomPrimitivesPaneRenderer implements ISeriesPrimitivePaneRenderer {
+ _p1: ViewPoint;
+ _p2: ViewPoint;
+ _fillColor: string;
+
+ constructor(p1: ViewPoint, p2: ViewPoint, fillColor: string) {
+ this._p1 = p1;
+ this._p2 = p2;
+ this._fillColor = fillColor;
+ }
+
+ draw(target: CanvasRenderingTarget2D) {
+ target.useBitmapCoordinateSpace(scope => {
+ if (
+ this._p1.x === null ||
+ this._p1.y === null ||
+ this._p2.x === null ||
+ this._p2.y === null
+ )
+ return;
+ const ctx = scope.context;
+ const horizontalPositions = positionsBox(
+ this._p1.x,
+ this._p2.x,
+ scope.horizontalPixelRatio
+ );
+ const verticalPositions = positionsBox(
+ this._p1.y,
+ this._p2.y,
+ scope.verticalPixelRatio
+ );
+ ctx.fillStyle = this._fillColor;
+ ctx.fillRect(
+ horizontalPositions.position,
+ verticalPositions.position,
+ horizontalPositions.length,
+ verticalPositions.length
+ );
+ });
+ }
+}
diff --git a/lwc-plugin-custom-primitives/src/pane-view.ts b/lwc-plugin-custom-primitives/src/pane-view.ts
new file mode 100644
index 0000000..810538c
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/pane-view.ts
@@ -0,0 +1,37 @@
+import { Coordinate, ISeriesPrimitivePaneView } from 'lightweight-charts';
+import { CustomPrimitivesPaneRenderer } from './pane-renderer';
+import { CustomPrimitivesDataSource } from './data-source';
+
+export interface ViewPoint {
+ x: Coordinate | null;
+ y: Coordinate | null;
+}
+
+export class CustomPrimitivesPaneView implements ISeriesPrimitivePaneView {
+ _source: CustomPrimitivesDataSource;
+ _p1: ViewPoint = { x: null, y: null };
+ _p2: ViewPoint = { x: null, y: null };
+
+ constructor(source: CustomPrimitivesDataSource) {
+ this._source = source;
+ }
+
+ update() {
+ const series = this._source.series;
+ const y1 = series.priceToCoordinate(this._source.p1.price);
+ const y2 = series.priceToCoordinate(this._source.p2.price);
+ const timeScale = this._source.chart.timeScale();
+ const x1 = timeScale.timeToCoordinate(this._source.p1.time);
+ const x2 = timeScale.timeToCoordinate(this._source.p2.time);
+ this._p1 = { x: x1, y: y1 };
+ this._p2 = { x: x2, y: y2 };
+ }
+
+ renderer() {
+ return new CustomPrimitivesPaneRenderer(
+ this._p1,
+ this._p2,
+ this._source.options.fillColor
+ );
+ }
+}
diff --git a/lwc-plugin-custom-primitives/src/plugin-base.ts b/lwc-plugin-custom-primitives/src/plugin-base.ts
new file mode 100644
index 0000000..def9684
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/plugin-base.ts
@@ -0,0 +1,56 @@
+import {
+ DataChangedScope,
+ IChartApi,
+ ISeriesApi,
+ ISeriesPrimitive,
+ SeriesAttachedParameter,
+ SeriesOptionsMap,
+ Time,
+} from 'lightweight-charts';
+import { ensureDefined } from './helpers/assertions';
+
+//* PluginBase is a useful base to build a plugin upon which
+//* already handles creating getters for the chart and series,
+//* and provides a requestUpdate method.
+export abstract class PluginBase implements ISeriesPrimitive {
+ private _chart: IChartApi | undefined = undefined;
+ private _series: ISeriesApi | undefined = undefined;
+
+ protected dataUpdated?(scope: DataChangedScope): void;
+ protected requestUpdate(): void {
+ if (this._requestUpdate) this._requestUpdate();
+ }
+ private _requestUpdate?: () => void;
+
+ public attached({
+ chart,
+ series,
+ requestUpdate,
+ }: SeriesAttachedParameter) {
+ this._chart = chart;
+ this._series = series;
+ this._series.subscribeDataChanged(this._fireDataUpdated);
+ this._requestUpdate = requestUpdate;
+ this.requestUpdate();
+ }
+
+ public detached() {
+ this._chart = undefined;
+ this._series = undefined;
+ this._requestUpdate = undefined;
+ }
+
+ public get chart(): IChartApi {
+ return ensureDefined(this._chart);
+ }
+
+ public get series(): ISeriesApi {
+ return ensureDefined(this._series);
+ }
+
+ private _fireDataUpdated(scope: DataChangedScope) {
+ if (this.dataUpdated) {
+ this.dataUpdated(scope);
+ }
+ }
+}
diff --git a/lwc-plugin-custom-primitives/src/sample-data.ts b/lwc-plugin-custom-primitives/src/sample-data.ts
new file mode 100644
index 0000000..34d798c
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/sample-data.ts
@@ -0,0 +1,35 @@
+import type { Time } from 'lightweight-charts';
+
+type LineData = {
+ time: Time;
+ value: number;
+};
+
+let randomFactor = 25 + Math.random() * 25;
+const samplePoint = (i: number) =>
+ i *
+ (0.5 +
+ Math.sin(i / 10) * 0.2 +
+ Math.sin(i / 20) * 0.4 +
+ Math.sin(i / randomFactor) * 0.8 +
+ Math.sin(i / 500) * 0.5) +
+ 200;
+
+export function generateLineData(numberOfPoints: number = 500): LineData[] {
+ randomFactor = 25 + Math.random() * 25;
+ const res = [];
+ const date = new Date(Date.UTC(2023, 0, 1, 12, 0, 0, 0));
+ for (let i = 0; i < numberOfPoints; ++i) {
+ const time = (date.getTime() / 1000) as Time;
+ const value = samplePoint(i);
+ res.push({
+ time,
+ value,
+ });
+
+ date.setUTCDate(date.getUTCDate() + 1);
+ }
+
+ return res;
+}
+
diff --git a/lwc-plugin-custom-primitives/src/vite-env.d.ts b/lwc-plugin-custom-primitives/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/lwc-plugin-custom-primitives/src/vite.config.js b/lwc-plugin-custom-primitives/src/vite.config.js
new file mode 100644
index 0000000..a7ae019
--- /dev/null
+++ b/lwc-plugin-custom-primitives/src/vite.config.js
@@ -0,0 +1,13 @@
+import { defineConfig } from 'vite';
+
+const input = {
+ main: './src/example/index.html',
+};
+
+export default defineConfig({
+ build: {
+ rollupOptions: {
+ input,
+ },
+ },
+});
diff --git a/lwc-plugin-custom-primitives/tsconfig.json b/lwc-plugin-custom-primitives/tsconfig.json
new file mode 100644
index 0000000..99e948c
--- /dev/null
+++ b/lwc-plugin-custom-primitives/tsconfig.json
@@ -0,0 +1,21 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "useDefineForClassFields": true,
+ "module": "ESNext",
+ "lib": ["ESNext", "DOM"],
+ "moduleResolution": "Node",
+ "strict": true,
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "esModuleInterop": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noImplicitReturns": true,
+ "skipLibCheck": true,
+ "declaration": true,
+ "declarationDir": "typings",
+ "emitDeclarationOnly": true
+ },
+ "include": ["src"]
+}
diff --git a/main.tsx b/main.tsx
new file mode 100644
index 0000000..1b15010
--- /dev/null
+++ b/main.tsx
@@ -0,0 +1,407 @@
+import { Plugin, MarkdownPostProcessorContext, MarkdownRenderChild, MarkdownRenderer, TFile, App, stringifyYaml } from 'obsidian';
+import { createRoot } from 'react-dom/client';
+import { transform } from '@babel/standalone';
+import * as React from 'react';
+import postcss from 'postcss';
+import tailwindcss from 'tailwindcss';
+import autoprefixer from 'autoprefixer';
+import { StorageManager } from 'src/core/storage';
+import { useStorage } from 'src/hooks/useStorage';
+import { createChart } from 'lightweight-charts';
+import { Card, CardHeader, CardTitle, CardContent } from 'src/components/ui/card';
+import { Tabs, TabsContent, TabsList, TabsTrigger } from 'src/components/ui/tabs';
+import { ErrorBoundary } from 'src/components/ErrorBoundary';
+import { useMarketData } from 'src/core/useMarketData';
+import { createMarketDataHook } from 'src/core/useMarketData';
+import { MarketDataService } from 'src/services/marketDataService';
+import { Switch } from 'src/components/ui/switch';
+import { OrderBlockAnalysisService } from 'src/services/OrderBlockAnalysis';
+import { Upload, Activity,AlertCircle, TrendingUp, TrendingDown, } from 'lucide-react';
+import { forceSimulation, forceLink, forceManyBody, forceCenter } from 'd3-force';
+// Add all React components you want to make available
+import {
+ PieChart,
+ Pie,
+ Cell,
+ ResponsiveContainer,
+ Tooltip,
+ Legend,
+ ComposedChart,
+ BarChart,
+ XAxis,
+ YAxis,
+ Bar,
+ Line,
+ Area,
+ ReferenceLine,
+ LineChart,
+} from 'recharts';
+import { MarketDataStorage } from 'src/services/marketDataStorage';
+
+class ReactComponentChild extends MarkdownRenderChild {
+ private root: ReturnType;
+ private storage: StorageManager;
+ private static styleSheet: HTMLStyleElement | null = null;
+ private static componentStyles = new Set();
+ private noteFile: TFile;
+ private ctx: MarkdownPostProcessorContext;
+ private app: App;
+
+ constructor(containerEl: HTMLElement, plugin: Plugin, ctx: MarkdownPostProcessorContext) {
+ super(containerEl);
+ this.root = createRoot(containerEl);
+ this.storage = new StorageManager(plugin);
+ this.ctx = ctx;
+ this.app = plugin.app; // Get app from plugin
+ // Get the source file from context
+ if (ctx.sourcePath) {
+ this.noteFile = plugin.app.vault.getAbstractFileByPath(ctx.sourcePath) as TFile;
+ }
+ // Add these classes to the container
+ containerEl.classList.add('react-component-container');
+ if (document.body.hasClass('theme-dark')) {
+ containerEl.classList.add('theme-dark');
+ }else {
+ containerEl.classList.add('theme-light');
+ }
+ }
+
+ private async getFrontmatterData(key: string, defaultValue: T): Promise {
+ if (!this.noteFile) return defaultValue;
+
+ const cache = this.app.metadataCache.getFileCache(this.noteFile);
+ const frontmatter = cache?.frontmatter;
+ return frontmatter?.react_data?.[key] ?? defaultValue;
+ }
+
+ private async updateFrontmatterData(key: string, value: T): Promise {
+ if (!this.noteFile) return;
+
+ const content = await this.app.vault.read(this.noteFile);
+ const cache = this.app.metadataCache.getFileCache(this.noteFile);
+ const frontmatter = cache?.frontmatter || {};
+
+ const newFrontmatter = {
+ ...frontmatter,
+ react_data: {
+ ...(frontmatter.react_data || {}),
+ [key]: value
+ }
+ };
+
+ const yamlRegex = /^---\n([\s\S]*?)\n---/;
+ const yamlMatch = content.match(yamlRegex);
+
+ let newContent;
+ if (yamlMatch) {
+ newContent = content.replace(yamlRegex, `---\n${stringifyYaml(newFrontmatter)}---`);
+ } else {
+ newContent = `---\n${stringifyYaml(newFrontmatter)}---\n\n${content}`;
+ }
+
+ await this.app.vault.modify(this.noteFile, newContent);
+ }
+
+ // Add wrapper component for error boundary
+ private RenderWrapper: React.FC<{ children: React.ReactNode }> = ({ children }) => {
+ return (
+ (
+
+
Error in component:
+
+ {error.message}
+
+
+ )}
+ >
+ {children}
+
+ );
+ };
+ private preprocessCode(code: string): string {
+ // Remove imports more carefully
+ code = code.replace(/import\s+.*?['"]\s*;?\s*$/gm, '');
+ code = code.replace(/import\s*{[^}]*}\s*from\s*['"][^'"]*['"];?\s*$/gm, '');
+ code = code.replace(/import\s*\([^)]*\);?\s*$/gm, '');
+
+ // Handle both JS/TS exports
+ code = code.replace(/export\s+default\s+/, '');
+ code = code.replace(/export\s+const\s+/, 'const ');
+ code = code.replace(/export\s+function\s+/, 'function ');
+ code = code.replace(/export\s+class\s+/, 'class ');
+
+ // Remove type annotations
+ //code = code.replace(/:\s*[A-Za-z<>[\]]+/g, '');
+ //code = code.replace(/<[A-Za-z,\s]+>/g, '');
+ // Create a HOC wrapper for chart components
+ const chartWrapper = `
+ const withChartContainer = (WrappedComponent) => {
+ return function ChartContainer(props) {
+ const [mounted, setMounted] = React.useState(false);
+
+ React.useEffect(() => {
+ const timer = setTimeout(() => setMounted(true), 100);
+ return () => clearTimeout(timer);
+ }, []);
+
+ return React.createElement(
+ 'div',
+ { style: { width: '100%', minHeight: '400px' } },
+ mounted ? React.createElement(WrappedComponent, props) : null
+ );
+ };
+ };
+ `;
+
+ // Find the component name
+ const componentMatch = code.match(/(?:const|function|class)\s+(\w+)\s*=\s*(?:(?:\([^)]*\)|)\s*=>|function\s*\(|React\.memo\(|React\.forwardRef\(|class\s+extends\s+React\.Component)/);
+ const componentName = componentMatch ? componentMatch[1] : 'EmptyComponent';
+ console.log('Found component:', componentName); // Debug info
+ if (!componentMatch) {
+ throw new Error('No React component found');
+ }
+
+ // Combine everything
+ // added Component assignment
+ code = `
+ ${chartWrapper}
+ ${code}
+ const Component = (() => {
+ // Add error handling for component existence
+ if (typeof ${componentName} === 'undefined') {
+ throw new Error(\`Component "${componentName}" was matched but is undefined. Code context: ${code.slice(0, 100)}...\`);
+ }
+ const isChartComponent = ${componentName}.toString().includes('ResponsiveContainer') ||
+ ${componentName}.toString().includes('svg');
+ return isChartComponent ? withChartContainer(${componentName}) : ${componentName};
+ })();
+ `;
+
+ // Wrap code in async IIFE to allow for await
+ return `
+ (async () => {
+ ${code}
+ return Component;
+ })()
+ `;
+ }
+
+ async render(code: string) {
+ console.time('component-render');
+ try {
+ //console.log('Original code:', code);
+ console.time('preprocess');
+ // Preprocess code
+ const processedCode = this.preprocessCode(code);
+ //console.log('Processed code:', processedCode);
+ console.timeEnd('preprocess');
+
+ console.time('tailwind');
+ // Process Tailwind
+ //await this.processTailwind(processedCode);
+ console.timeEnd('tailwind');
+
+ console.time('babel');
+ const isTypeScript = code.includes(':') || code.includes('interface') || code.includes('<');
+
+ const presets: (string | [string, object])[] = isTypeScript ?
+ ['react', ['typescript', { isTSX: true, allExtensions: true }]] :
+ ['react'];
+ // Transform with Babel
+ const transformedCode = transform(processedCode, {
+ presets,
+ sourceType: 'module',
+ filename: isTypeScript ? 'dynamic-component.tsx' : 'dynamic-component.jsx',
+ configFile: false,
+ babelrc: false,
+ }).code;
+ console.timeEnd('babel');
+ //console.log('Transformed code:', transformedCode);
+
+ // Create bound storage hook
+ // Create bound storage hook with frontmatter support
+ const boundUseStorage = (key: string, defaultValue: T) => {
+ const [value, setValue] = React.useState(defaultValue);
+
+ React.useEffect(() => {
+ this.getFrontmatterData(key, defaultValue).then(setValue);
+ }, [key]);
+
+ const updateValue = React.useCallback(
+ async (newValue: T | ((prev: T) => T)) => {
+ const actualNewValue = newValue instanceof Function ?
+ newValue(value) : newValue;
+ setValue(actualNewValue);
+ await this.updateFrontmatterData(key, actualNewValue);
+ },
+ [key, value]
+ );
+
+ return [value, updateValue] as const;
+ };
+ // Create scoped market data hook
+ const useMarketData = createMarketDataHook(this.storage, this.noteFile);
+ // Create scope with all required dependencies
+ const scope = {
+ React,
+ useState: React.useState,
+ useEffect: React.useEffect,
+ useRef: React.useRef,
+ useMemo: React.useMemo,
+ useStorage: boundUseStorage,
+ useMarketData,
+ useCallback:React.useCallback,
+ MarketDataStorage,
+ OrderBlockAnalysisService,
+ MarketDataService,
+ // Chart library
+ createChart,
+ // UI Components
+ Card,
+ CardHeader,
+ CardTitle,
+ CardContent,
+ Tabs,
+ TabsContent,
+ TabsList,
+ TabsTrigger,
+ Switch,
+ PieChart,
+ Pie,
+ Cell,
+ ResponsiveContainer,
+ Tooltip,
+ Legend,
+ ComposedChart, // Add these chart components
+ BarChart,
+ XAxis,
+ YAxis,
+ Bar,
+ Upload,
+ Area,
+ Line,
+ ReferenceLine,
+ LineChart,
+ Activity,
+ AlertCircle,
+ TrendingUp, TrendingDown,
+ forceSimulation, forceLink, forceManyBody, forceCenter,
+ getTheme: () => document.body.hasClass('theme-dark') ? 'dark' : 'light',
+ // Add note context
+ noteContext: {
+ path: this.noteFile?.path,
+ basename: this.noteFile?.basename,
+ frontmatter: this.app.metadataCache.getFileCache(this.noteFile)?.frontmatter
+ },
+ // Add useful chart utilities
+ getChartTheme: () => document.body.hasClass('theme-dark') ? 'dark' : 'light',
+ getChartDefaults: () => ({
+ margin: { top: 10, right: 30, left: 0, bottom: 0 },
+ style: {
+ backgroundColor: document.body.hasClass('theme-dark') ? '#1a1b1e' : '#ffffff',
+ color: document.body.hasClass('theme-dark') ? '#ffffff' : '#000000'
+ }
+ }),
+ };
+
+ // Execute the code and get the component
+ const Component = await new Function(
+ ...Object.keys(scope),
+ `return ${transformedCode}`
+ )(...Object.values(scope));
+
+ // Wrap the rendered component in ErrorBoundary
+ this.root.render(
+
+
+
+ );
+ } catch (error) {
+ console.error('Rendering error:', error);
+ this.renderError(error instanceof Error ? error : new Error('Unknown error'));
+ }
+ console.timeEnd('component-render');
+ }
+
+ onunload() {
+ this.root.unmount();
+ }
+
+ renderError(error: Error) {
+ this.root.render(
+ React.createElement('div', {
+ style: {
+ color: 'red',
+ padding: '1rem',
+ border: '1px solid red',
+ borderRadius: '4px',
+ margin: '1rem 0'
+ }
+ }, `Error: ${error.message}`)
+ );
+ }
+
+ getStorage() {
+ return this.storage;
+ }
+}
+
+export default class ReactTestPlugin extends Plugin {
+ async onload() {
+ // Listen for theme changes
+ this.registerEvent(
+ this.app.workspace.on('css-change', this.updateTheme)
+ );
+ // Register markdown processor
+ this.registerMarkdownCodeBlockProcessor(
+ 'react',
+ (source: string, el: HTMLElement, ctx: MarkdownPostProcessorContext) => {
+ const child = new ReactComponentChild(el, this, ctx);
+ ctx.addChild(child);
+ child.render(source);
+ }
+ );
+ // Register a global Markdown postprocessor for HTML
+ this.registerMarkdownPostProcessor((element, context) => {
+ this.parseMarkdownInHtml(element);
+ });
+ // Initial theme setup
+ this.updateTheme();
+ }
+ private updateTheme = () => {
+ // Update theme class on all react component containers
+ document.querySelectorAll('.react-component-container').forEach(el => {
+ if (document.body.hasClass('theme-dark')) {
+ el.classList.add('theme-dark');
+ el.classList.remove('theme-light');
+ } else {
+ el.classList.add('theme-light');
+ el.classList.remove('theme-dark');
+ }
+ });
+ };
+ private async parseMarkdownInHtml(container: HTMLElement) {
+ // Query all divs or specific HTML blocks you want to process
+ const htmlBlocks = Array.from(container.querySelectorAll('div')) as HTMLDivElement[];
+
+ // Iterate over each div block
+ for (const block of htmlBlocks) {
+ // Check if it already contains rendered Markdown (to avoid double processing)
+ if (block.querySelector('.markdown-rendered')) continue;
+
+ // Render Markdown for the inner content of each block
+ await MarkdownRenderer.renderMarkdown(
+ block.innerHTML, // Raw HTML content
+ block, // Target container for rendered Markdown
+ '', // Path (optional, current file path if needed)
+ this // Plugin context
+ );
+
+ // After rendering, mark the block to avoid double processing
+ block.classList.add('markdown-rendered');
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/manifest.json b/manifest.json
new file mode 100644
index 0000000..c1765c5
--- /dev/null
+++ b/manifest.json
@@ -0,0 +1,11 @@
+{
+ "id": "reactive-notes",
+ "name": "Reactive Notes",
+ "version": "1.0.0",
+ "minAppVersion": "0.15.0",
+ "description": "Enhances the Obsidian API with react.",
+ "author": "Obsidian",
+ "authorUrl": "https://obsidian.md",
+ "fundingUrl": "https://obsidian.md/pricing",
+ "isDesktopOnly": true
+}
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 0000000..b74c701
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,6204 @@
+{
+ "name": "obsidian-sample-plugin",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "obsidian-sample-plugin",
+ "version": "1.0.0",
+ "license": "MIT",
+ "dependencies": {
+ "@codemirror/language": "^6.10.6",
+ "@emotion/css": "^11.13.5",
+ "@lezer/common": "^1.2.3",
+ "@radix-ui/react-switch": "^1.0.3",
+ "@radix-ui/react-tabs": "^1.1.1",
+ "autoprefixer": "^10.4.20",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "d3-force": "^3.0.0",
+ "dayjs": "^1.11.13",
+ "dotenv": "^16.4.7",
+ "lightweight-charts": "^4.2.1",
+ "lucide-react": "^0.462.0",
+ "postcss": "^8.4.49",
+ "react": "^18.3.1",
+ "react-apexcharts": "^1.6.0",
+ "react-dom": "^18.3.1",
+ "react-force-graph": "^1.46.0",
+ "recharts": "^2.13.3",
+ "shadcn": "^1.0.0",
+ "tailwind-merge": "^2.5.5",
+ "tailwindcss": "^3.4.16",
+ "yaml": "^2.6.1"
+ },
+ "devDependencies": {
+ "@babel/core": "^7.26.0",
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
+ "@babel/plugin-transform-modules-commonjs": "^7.25.9",
+ "@babel/preset-react": "^7.25.9",
+ "@babel/preset-typescript": "^7.26.0",
+ "@babel/standalone": "^7.26.2",
+ "@types/d3-force": "^3.0.10",
+ "@types/node": "^16.11.6",
+ "@types/react": "^18.3.12",
+ "@types/react-dom": "^18.3.1",
+ "@typescript-eslint/eslint-plugin": "5.29.0",
+ "@typescript-eslint/parser": "5.29.0",
+ "builtin-modules": "3.3.0",
+ "esbuild": "0.17.3",
+ "obsidian": "latest",
+ "tslib": "2.4.0",
+ "typescript": "^4.8.0"
+ }
+ },
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
+ "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz",
+ "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz",
+ "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==",
+ "dev": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.0",
+ "@babel/generator": "^7.26.0",
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.0",
+ "@babel/parser": "^7.26.0",
+ "@babel/template": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.26.0",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz",
+ "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==",
+ "dependencies": {
+ "@babel/parser": "^7.26.2",
+ "@babel/types": "^7.26.0",
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
+ "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz",
+ "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-create-class-features-plugin": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz",
+ "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-member-expression-to-functions": "^7.25.9",
+ "@babel/helper-optimise-call-expression": "^7.25.9",
+ "@babel/helper-replace-supers": "^7.25.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-member-expression-to-functions": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz",
+ "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
+ "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
+ "dependencies": {
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz",
+ "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-optimise-call-expression": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz",
+ "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz",
+ "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-replace-supers": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz",
+ "integrity": "sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-member-expression-to-functions": "^7.25.9",
+ "@babel/helper-optimise-call-expression": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz",
+ "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz",
+ "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
+ "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
+ "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz",
+ "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz",
+ "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.25.9",
+ "@babel/types": "^7.26.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz",
+ "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==",
+ "dependencies": {
+ "@babel/types": "^7.26.0"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-class-properties": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz",
+ "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==",
+ "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz",
+ "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz",
+ "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-commonjs": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz",
+ "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-simple-access": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-display-name": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz",
+ "integrity": "sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz",
+ "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/plugin-syntax-jsx": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-development": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz",
+ "integrity": "sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/plugin-transform-react-jsx": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-pure-annotations": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz",
+ "integrity": "sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-typescript": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.9.tgz",
+ "integrity": "sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-create-class-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
+ "@babel/plugin-syntax-typescript": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-react": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.25.9.tgz",
+ "integrity": "sha512-D3to0uSPiWE7rBrdIICCd0tJSIGpLaaGptna2+w7Pft5xMqLpA1sz99DK5TZ1TjGbdQ/VI1eCSZ06dv3lT4JOw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
+ "@babel/plugin-transform-react-display-name": "^7.25.9",
+ "@babel/plugin-transform-react-jsx": "^7.25.9",
+ "@babel/plugin-transform-react-jsx-development": "^7.25.9",
+ "@babel/plugin-transform-react-pure-annotations": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-typescript": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz",
+ "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
+ "@babel/plugin-syntax-jsx": "^7.25.9",
+ "@babel/plugin-transform-modules-commonjs": "^7.25.9",
+ "@babel/plugin-transform-typescript": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz",
+ "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
+ "dependencies": {
+ "regenerator-runtime": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/standalone": {
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/standalone/-/standalone-7.26.2.tgz",
+ "integrity": "sha512-i2VbegsRfwa9yq3xmfDX3tG2yh9K0cCqwpSyVG2nPxifh0EOnucAZUeO/g4lW2Zfg03aPJNtPfxQbDHzXc7H+w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
+ "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
+ "dependencies": {
+ "@babel/code-frame": "^7.25.9",
+ "@babel/parser": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz",
+ "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==",
+ "dependencies": {
+ "@babel/code-frame": "^7.25.9",
+ "@babel/generator": "^7.25.9",
+ "@babel/parser": "^7.25.9",
+ "@babel/template": "^7.25.9",
+ "@babel/types": "^7.25.9",
+ "debug": "^4.3.1",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse/node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz",
+ "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@codemirror/language": {
+ "version": "6.10.6",
+ "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.10.6.tgz",
+ "integrity": "sha512-KrsbdCnxEztLVbB5PycWXFxas4EOyk/fPAfruSOnDDppevQgid2XZ+KbJ9u+fDikP/e7MW7HPBTvTb8JlZK9vA==",
+ "dependencies": {
+ "@codemirror/state": "^6.0.0",
+ "@codemirror/view": "^6.23.0",
+ "@lezer/common": "^1.1.0",
+ "@lezer/highlight": "^1.0.0",
+ "@lezer/lr": "^1.0.0",
+ "style-mod": "^4.0.0"
+ }
+ },
+ "node_modules/@codemirror/state": {
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.4.1.tgz",
+ "integrity": "sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A=="
+ },
+ "node_modules/@codemirror/view": {
+ "version": "6.35.0",
+ "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.35.0.tgz",
+ "integrity": "sha512-I0tYy63q5XkaWsJ8QRv5h6ves7kvtrBWjBcnf/bzohFJQc5c14a1AQRdE8QpPF9eMp5Mq2FMm59TCj1gDfE7kw==",
+ "dependencies": {
+ "@codemirror/state": "^6.4.0",
+ "style-mod": "^4.1.0",
+ "w3c-keyname": "^2.2.4"
+ }
+ },
+ "node_modules/@emotion/babel-plugin": {
+ "version": "11.13.5",
+ "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz",
+ "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/runtime": "^7.18.3",
+ "@emotion/hash": "^0.9.2",
+ "@emotion/memoize": "^0.9.0",
+ "@emotion/serialize": "^1.3.3",
+ "babel-plugin-macros": "^3.1.0",
+ "convert-source-map": "^1.5.0",
+ "escape-string-regexp": "^4.0.0",
+ "find-root": "^1.1.0",
+ "source-map": "^0.5.7",
+ "stylis": "4.2.0"
+ }
+ },
+ "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
+ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
+ },
+ "node_modules/@emotion/babel-plugin/node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@emotion/cache": {
+ "version": "11.13.5",
+ "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.5.tgz",
+ "integrity": "sha512-Z3xbtJ+UcK76eWkagZ1onvn/wAVb1GOMuR15s30Fm2wrMgC7jzpnO2JZXr4eujTTqoQFUrZIw/rT0c6Zzjca1g==",
+ "dependencies": {
+ "@emotion/memoize": "^0.9.0",
+ "@emotion/sheet": "^1.4.0",
+ "@emotion/utils": "^1.4.2",
+ "@emotion/weak-memoize": "^0.4.0",
+ "stylis": "4.2.0"
+ }
+ },
+ "node_modules/@emotion/css": {
+ "version": "11.13.5",
+ "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.13.5.tgz",
+ "integrity": "sha512-wQdD0Xhkn3Qy2VNcIzbLP9MR8TafI0MJb7BEAXKp+w4+XqErksWR4OXomuDzPsN4InLdGhVe6EYcn2ZIUCpB8w==",
+ "dependencies": {
+ "@emotion/babel-plugin": "^11.13.5",
+ "@emotion/cache": "^11.13.5",
+ "@emotion/serialize": "^1.3.3",
+ "@emotion/sheet": "^1.4.0",
+ "@emotion/utils": "^1.4.2"
+ }
+ },
+ "node_modules/@emotion/hash": {
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
+ "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g=="
+ },
+ "node_modules/@emotion/memoize": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz",
+ "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ=="
+ },
+ "node_modules/@emotion/serialize": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz",
+ "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==",
+ "dependencies": {
+ "@emotion/hash": "^0.9.2",
+ "@emotion/memoize": "^0.9.0",
+ "@emotion/unitless": "^0.10.0",
+ "@emotion/utils": "^1.4.2",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@emotion/sheet": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz",
+ "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg=="
+ },
+ "node_modules/@emotion/unitless": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz",
+ "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg=="
+ },
+ "node_modules/@emotion/utils": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz",
+ "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA=="
+ },
+ "node_modules/@emotion/weak-memoize": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz",
+ "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg=="
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.3.tgz",
+ "integrity": "sha512-1Mlz934GvbgdDmt26rTLmf03cAgLg5HyOgJN+ZGCeP3Q9ynYTNMn2/LQxIl7Uy+o4K6Rfi2OuLsr12JQQR8gNg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.3.tgz",
+ "integrity": "sha512-XvJsYo3dO3Pi4kpalkyMvfQsjxPWHYjoX4MDiB/FUM4YMfWcXa5l4VCwFWVYI1+92yxqjuqrhNg0CZg3gSouyQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.3.tgz",
+ "integrity": "sha512-nuV2CmLS07Gqh5/GrZLuqkU9Bm6H6vcCspM+zjp9TdQlxJtIe+qqEXQChmfc7nWdyr/yz3h45Utk1tUn8Cz5+A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.3.tgz",
+ "integrity": "sha512-01Hxaaat6m0Xp9AXGM8mjFtqqwDjzlMP0eQq9zll9U85ttVALGCGDuEvra5Feu/NbP5AEP1MaopPwzsTcUq1cw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.3.tgz",
+ "integrity": "sha512-Eo2gq0Q/er2muf8Z83X21UFoB7EU6/m3GNKvrhACJkjVThd0uA+8RfKpfNhuMCl1bKRfBzKOk6xaYKQZ4lZqvA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.3.tgz",
+ "integrity": "sha512-CN62ESxaquP61n1ZjQP/jZte8CE09M6kNn3baos2SeUfdVBkWN5n6vGp2iKyb/bm/x4JQzEvJgRHLGd5F5b81w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.3.tgz",
+ "integrity": "sha512-feq+K8TxIznZE+zhdVurF3WNJ/Sa35dQNYbaqM/wsCbWdzXr5lyq+AaTUSER2cUR+SXPnd/EY75EPRjf4s1SLg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.3.tgz",
+ "integrity": "sha512-CLP3EgyNuPcg2cshbwkqYy5bbAgK+VhyfMU7oIYyn+x4Y67xb5C5ylxsNUjRmr8BX+MW3YhVNm6Lq6FKtRTWHQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.3.tgz",
+ "integrity": "sha512-JHeZXD4auLYBnrKn6JYJ0o5nWJI9PhChA/Nt0G4MvLaMrvXuWnY93R3a7PiXeJQphpL1nYsaMcoV2QtuvRnF/g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.3.tgz",
+ "integrity": "sha512-FyXlD2ZjZqTFh0sOQxFDiWG1uQUEOLbEh9gKN/7pFxck5Vw0qjWSDqbn6C10GAa1rXJpwsntHcmLqydY9ST9ZA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.3.tgz",
+ "integrity": "sha512-OrDGMvDBI2g7s04J8dh8/I7eSO+/E7nMDT2Z5IruBfUO/RiigF1OF6xoH33Dn4W/OwAWSUf1s2nXamb28ZklTA==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.3.tgz",
+ "integrity": "sha512-DcnUpXnVCJvmv0TzuLwKBC2nsQHle8EIiAJiJ+PipEVC16wHXaPEKP0EqN8WnBe0TPvMITOUlP2aiL5YMld+CQ==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.3.tgz",
+ "integrity": "sha512-BDYf/l1WVhWE+FHAW3FzZPtVlk9QsrwsxGzABmN4g8bTjmhazsId3h127pliDRRu5674k1Y2RWejbpN46N9ZhQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.3.tgz",
+ "integrity": "sha512-WViAxWYMRIi+prTJTyV1wnqd2mS2cPqJlN85oscVhXdb/ZTFJdrpaqm/uDsZPGKHtbg5TuRX/ymKdOSk41YZow==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.3.tgz",
+ "integrity": "sha512-Iw8lkNHUC4oGP1O/KhumcVy77u2s6+KUjieUqzEU3XuWJqZ+AY7uVMrrCbAiwWTkpQHkr00BuXH5RpC6Sb/7Ug==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.3.tgz",
+ "integrity": "sha512-0AGkWQMzeoeAtXQRNB3s4J1/T2XbigM2/Mn2yU1tQSmQRmHIZdkGbVq2A3aDdNslPyhb9/lH0S5GMTZ4xsjBqg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.3.tgz",
+ "integrity": "sha512-4+rR/WHOxIVh53UIQIICryjdoKdHsFZFD4zLSonJ9RRw7bhKzVyXbnRPsWSfwybYqw9sB7ots/SYyufL1mBpEg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.3.tgz",
+ "integrity": "sha512-cVpWnkx9IYg99EjGxa5Gc0XmqumtAwK3aoz7O4Dii2vko+qXbkHoujWA68cqXjhh6TsLaQelfDO4MVnyr+ODeA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.3.tgz",
+ "integrity": "sha512-RxmhKLbTCDAY2xOfrww6ieIZkZF+KBqG7S2Ako2SljKXRFi+0863PspK74QQ7JpmWwncChY25JTJSbVBYGQk2Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.3.tgz",
+ "integrity": "sha512-0r36VeEJ4efwmofxVJRXDjVRP2jTmv877zc+i+Pc7MNsIr38NfsjkQj23AfF7l0WbB+RQ7VUb+LDiqC/KY/M/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.3.tgz",
+ "integrity": "sha512-wgO6rc7uGStH22nur4aLFcq7Wh86bE9cOFmfTr/yxN3BXvDEdCSXyKkO+U5JIt53eTOgC47v9k/C1bITWL/Teg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.3.tgz",
+ "integrity": "sha512-FdVl64OIuiKjgXBjwZaJLKp0eaEckifbhn10dXWhysMJkWblg3OEEGKSIyhiD5RSgAya8WzP3DNkngtIg3Nt7g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
+ "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+ "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
+ "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^9.6.0",
+ "globals": "^13.19.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz",
+ "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@humanwhocodes/config-array": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz",
+ "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==",
+ "deprecated": "Use @eslint/config-array instead",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@humanwhocodes/object-schema": "^2.0.3",
+ "debug": "^4.3.1",
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=10.10.0"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/object-schema": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz",
+ "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==",
+ "deprecated": "Use @eslint/object-schema instead",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@lezer/common": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.2.3.tgz",
+ "integrity": "sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA=="
+ },
+ "node_modules/@lezer/highlight": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.1.tgz",
+ "integrity": "sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==",
+ "dependencies": {
+ "@lezer/common": "^1.0.0"
+ }
+ },
+ "node_modules/@lezer/lr": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.2.tgz",
+ "integrity": "sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==",
+ "dependencies": {
+ "@lezer/common": "^1.0.0"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@radix-ui/primitive": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz",
+ "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA=="
+ },
+ "node_modules/@radix-ui/react-collection": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz",
+ "integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.0",
+ "@radix-ui/react-context": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.0",
+ "@radix-ui/react-slot": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-context": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz",
+ "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz",
+ "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-context": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz",
+ "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-direction": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz",
+ "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-id": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz",
+ "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-presence": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.1.tgz",
+ "integrity": "sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.0",
+ "@radix-ui/react-use-layout-effect": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-primitive": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz",
+ "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-roving-focus": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz",
+ "integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.0",
+ "@radix-ui/react-collection": "1.1.0",
+ "@radix-ui/react-compose-refs": "1.1.0",
+ "@radix-ui/react-context": "1.1.0",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-id": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.0",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-use-controllable-state": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-roving-focus/node_modules/@radix-ui/react-context": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz",
+ "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-slot": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
+ "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-switch": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.1.2.tgz",
+ "integrity": "sha512-zGukiWHjEdBCRyXvKR6iXAQG6qXm2esuAD6kDOi9Cn+1X6ev3ASo4+CsYaD6Fov9r/AQFekqnD/7+V0Cs6/98g==",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.1",
+ "@radix-ui/react-compose-refs": "1.1.1",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-primitive": "2.0.1",
+ "@radix-ui/react-use-controllable-state": "1.1.0",
+ "@radix-ui/react-use-previous": "1.1.0",
+ "@radix-ui/react-use-size": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/primitive": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz",
+ "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="
+ },
+ "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-compose-refs": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz",
+ "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-primitive": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz",
+ "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==",
+ "dependencies": {
+ "@radix-ui/react-slot": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-slot": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz",
+ "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==",
+ "dependencies": {
+ "@radix-ui/react-compose-refs": "1.1.1"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-tabs": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.1.tgz",
+ "integrity": "sha512-3GBUDmP2DvzmtYLMsHmpA1GtR46ZDZ+OreXM/N+kkQJOPIgytFWWTfDQmBQKBvaFS0Vno0FktdbVzN28KGrMdw==",
+ "dependencies": {
+ "@radix-ui/primitive": "1.1.0",
+ "@radix-ui/react-context": "1.1.1",
+ "@radix-ui/react-direction": "1.1.0",
+ "@radix-ui/react-id": "1.1.0",
+ "@radix-ui/react-presence": "1.1.1",
+ "@radix-ui/react-primitive": "2.0.0",
+ "@radix-ui/react-roving-focus": "1.1.0",
+ "@radix-ui/react-use-controllable-state": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-callback-ref": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz",
+ "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-controllable-state": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz",
+ "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==",
+ "dependencies": {
+ "@radix-ui/react-use-callback-ref": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-layout-effect": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz",
+ "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-previous": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.0.tgz",
+ "integrity": "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==",
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@radix-ui/react-use-size": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz",
+ "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==",
+ "dependencies": {
+ "@radix-ui/react-use-layout-effect": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@sindresorhus/is": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz",
+ "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@svgdotjs/svg.draggable.js": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@svgdotjs/svg.draggable.js/-/svg.draggable.js-3.0.4.tgz",
+ "integrity": "sha512-vWi/Col5Szo74HJVBgMHz23kLVljt3jvngmh0DzST45iO2ubIZ487uUAHIxSZH2tVRyiaaTL+Phaasgp4gUD2g==",
+ "peer": true,
+ "peerDependencies": {
+ "@svgdotjs/svg.js": "^3.2.4"
+ }
+ },
+ "node_modules/@svgdotjs/svg.filter.js": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@svgdotjs/svg.filter.js/-/svg.filter.js-3.0.8.tgz",
+ "integrity": "sha512-YshF2YDaeRA2StyzAs5nUPrev7npQ38oWD0eTRwnsciSL2KrRPMoUw8BzjIXItb3+dccKGTX3IQOd2NFzmHkog==",
+ "peer": true,
+ "dependencies": {
+ "@svgdotjs/svg.js": "^3.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/@svgdotjs/svg.js": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/@svgdotjs/svg.js/-/svg.js-3.2.4.tgz",
+ "integrity": "sha512-BjJ/7vWNowlX3Z8O4ywT58DqbNRyYlkk6Yz/D13aB7hGmfQTvGX4Tkgtm/ApYlu9M7lCQi15xUEidqMUmdMYwg==",
+ "peer": true,
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Fuzzyma"
+ }
+ },
+ "node_modules/@svgdotjs/svg.resize.js": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@svgdotjs/svg.resize.js/-/svg.resize.js-2.0.5.tgz",
+ "integrity": "sha512-4heRW4B1QrJeENfi7326lUPYBCevj78FJs8kfeDxn5st0IYPIRXoTtOSYvTzFWgaWWXd3YCDE6ao4fmv91RthA==",
+ "peer": true,
+ "engines": {
+ "node": ">= 14.18"
+ },
+ "peerDependencies": {
+ "@svgdotjs/svg.js": "^3.2.4",
+ "@svgdotjs/svg.select.js": "^4.0.1"
+ }
+ },
+ "node_modules/@svgdotjs/svg.select.js": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@svgdotjs/svg.select.js/-/svg.select.js-4.0.2.tgz",
+ "integrity": "sha512-5gWdrvoQX3keo03SCmgaBbD+kFftq0F/f2bzCbNnpkkvW6tk4rl4MakORzFuNjvXPWwB4az9GwuvVxQVnjaK2g==",
+ "peer": true,
+ "engines": {
+ "node": ">= 14.18"
+ },
+ "peerDependencies": {
+ "@svgdotjs/svg.js": "^3.2.4"
+ }
+ },
+ "node_modules/@szmarczak/http-timer": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz",
+ "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==",
+ "dependencies": {
+ "defer-to-connect": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@tweenjs/tween.js": {
+ "version": "25.0.0",
+ "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-25.0.0.tgz",
+ "integrity": "sha512-XKLA6syeBUaPzx4j3qwMqzzq+V4uo72BnlbOjmuljLrRqdsd3qnzvZZoxvMHZ23ndsRS4aufU6JOZYpCbU6T1A=="
+ },
+ "node_modules/@types/codemirror": {
+ "version": "5.60.8",
+ "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.8.tgz",
+ "integrity": "sha512-VjFgDF/eB+Aklcy15TtOTLQeMjTo07k7KAjql8OK5Dirr7a6sJY4T1uVBDuTVG9VEmn1uUsohOpYnVfgC6/jyw==",
+ "dev": true,
+ "dependencies": {
+ "@types/tern": "*"
+ }
+ },
+ "node_modules/@types/d3-array": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz",
+ "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg=="
+ },
+ "node_modules/@types/d3-color": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
+ "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="
+ },
+ "node_modules/@types/d3-ease": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz",
+ "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="
+ },
+ "node_modules/@types/d3-force": {
+ "version": "3.0.10",
+ "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.10.tgz",
+ "integrity": "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==",
+ "dev": true
+ },
+ "node_modules/@types/d3-interpolate": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
+ "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
+ "dependencies": {
+ "@types/d3-color": "*"
+ }
+ },
+ "node_modules/@types/d3-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz",
+ "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ=="
+ },
+ "node_modules/@types/d3-scale": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz",
+ "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==",
+ "dependencies": {
+ "@types/d3-time": "*"
+ }
+ },
+ "node_modules/@types/d3-shape": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz",
+ "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==",
+ "dependencies": {
+ "@types/d3-path": "*"
+ }
+ },
+ "node_modules/@types/d3-time": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz",
+ "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="
+ },
+ "node_modules/@types/d3-timer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz",
+ "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
+ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
+ "dev": true
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "16.18.121",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.121.tgz",
+ "integrity": "sha512-Gk/pOy8H0cvX8qNrwzElYIECpcUn87w4EAEFXFvPJ8qsP9QR/YqukUORSy0zmyDyvdo149idPpy4W6iC5aSbQA==",
+ "dev": true
+ },
+ "node_modules/@types/parse-json": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
+ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.13",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
+ "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==",
+ "devOptional": true
+ },
+ "node_modules/@types/react": {
+ "version": "18.3.12",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz",
+ "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==",
+ "devOptional": true,
+ "dependencies": {
+ "@types/prop-types": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==",
+ "devOptional": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/tern": {
+ "version": "0.23.9",
+ "resolved": "https://registry.npmjs.org/@types/tern/-/tern-0.23.9.tgz",
+ "integrity": "sha512-ypzHFE/wBzh+BlH6rrBgS5I/Z7RD21pGhZ2rltb/+ZrVM1awdZwjx7hE5XfuYgHWk9uvV5HLZN3SloevCAp3Bw==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "*"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "5.29.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.29.0.tgz",
+ "integrity": "sha512-kgTsISt9pM53yRFQmLZ4npj99yGl3x3Pl7z4eA66OuTzAGC4bQB5H5fuLwPnqTKU3yyrrg4MIhjF17UYnL4c0w==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "5.29.0",
+ "@typescript-eslint/type-utils": "5.29.0",
+ "@typescript-eslint/utils": "5.29.0",
+ "debug": "^4.3.4",
+ "functional-red-black-tree": "^1.0.1",
+ "ignore": "^5.2.0",
+ "regexpp": "^3.2.0",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^5.0.0",
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "5.29.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.29.0.tgz",
+ "integrity": "sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "5.29.0",
+ "@typescript-eslint/types": "5.29.0",
+ "@typescript-eslint/typescript-estree": "5.29.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "5.29.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.29.0.tgz",
+ "integrity": "sha512-etbXUT0FygFi2ihcxDZjz21LtC+Eps9V2xVx09zFoN44RRHPrkMflidGMI+2dUs821zR1tDS6Oc9IXxIjOUZwA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.29.0",
+ "@typescript-eslint/visitor-keys": "5.29.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "5.29.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.29.0.tgz",
+ "integrity": "sha512-JK6bAaaiJozbox3K220VRfCzLa9n0ib/J+FHIwnaV3Enw/TO267qe0pM1b1QrrEuy6xun374XEAsRlA86JJnyg==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/utils": "5.29.0",
+ "debug": "^4.3.4",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "*"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "5.29.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.29.0.tgz",
+ "integrity": "sha512-X99VbqvAXOMdVyfFmksMy3u8p8yoRGITgU1joBJPzeYa0rhdf5ok9S56/itRoUSh99fiDoMtarSIJXo7H/SnOg==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "5.29.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.29.0.tgz",
+ "integrity": "sha512-mQvSUJ/JjGBdvo+1LwC+GY2XmSYjK1nAaVw2emp/E61wEVYEyibRHCqm1I1vEKbXCpUKuW4G7u9ZCaZhJbLoNQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.29.0",
+ "@typescript-eslint/visitor-keys": "5.29.0",
+ "debug": "^4.3.4",
+ "globby": "^11.1.0",
+ "is-glob": "^4.0.3",
+ "semver": "^7.3.7",
+ "tsutils": "^3.21.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "5.29.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.29.0.tgz",
+ "integrity": "sha512-3Eos6uP1nyLOBayc/VUdKZikV90HahXE5Dx9L5YlSd/7ylQPXhLk1BYb29SDgnBnTp+jmSZUU0QxUiyHgW4p7A==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.9",
+ "@typescript-eslint/scope-manager": "5.29.0",
+ "@typescript-eslint/types": "5.29.0",
+ "@typescript-eslint/typescript-estree": "5.29.0",
+ "eslint-scope": "^5.1.1",
+ "eslint-utils": "^3.0.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "5.29.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.29.0.tgz",
+ "integrity": "sha512-Hpb/mCWsjILvikMQoZIE3voc9wtQcS0A9FUw3h8bhr9UxBdtI/tw1ZDZUOXHXLOVMedKCH5NxyzATwnU78bWCQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "5.29.0",
+ "eslint-visitor-keys": "^3.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@ungap/structured-clone": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
+ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/@yr/monotone-cubic-spline": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@yr/monotone-cubic-spline/-/monotone-cubic-spline-1.0.3.tgz",
+ "integrity": "sha512-FQXkOta0XBSUPHndIKON2Y9JeQz5ZeMqLYZVVK93FliNBFm7LNMIZmY6FrMEB9XPcDbE2bekMbZD6kzDkxwYjA==",
+ "peer": true
+ },
+ "node_modules/3d-force-graph": {
+ "version": "1.76.0",
+ "resolved": "https://registry.npmjs.org/3d-force-graph/-/3d-force-graph-1.76.0.tgz",
+ "integrity": "sha512-XxqN6/b7v1NMWD7p9y0PT38T1CBCCv+ToE25pmfwvCFUzcvxdpc6RcleLdWgpcJWUa/KYJMVrnx/CkBulU64cA==",
+ "dependencies": {
+ "accessor-fn": "1",
+ "kapsule": "^1.16",
+ "three": ">=0.118 <1",
+ "three-forcegraph": "1",
+ "three-render-objects": "^1.35"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/3d-force-graph-ar": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/3d-force-graph-ar/-/3d-force-graph-ar-1.9.3.tgz",
+ "integrity": "sha512-KHcwKVF8394ioKhc4h3y5H9jPBvw+lUmD1BJd1AEV/SO+FM324CXVYTvbGg2IuW0nOPR/ChXvlWhvIZaOtyeTg==",
+ "dependencies": {
+ "aframe-forcegraph-component": "3",
+ "kapsule": "^1.16"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/3d-force-graph-vr": {
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/3d-force-graph-vr/-/3d-force-graph-vr-2.4.3.tgz",
+ "integrity": "sha512-os/IPpkWUqNnqWFQISaa5Snts1uUFf485SMPpPi2BIJLHbW9Jxt+1PQWc2rqT3tDFTh9J72BnxyuqegyMrqxdQ==",
+ "dependencies": {
+ "accessor-fn": "1",
+ "aframe": "^1.5",
+ "aframe-extras": "^7.2",
+ "aframe-forcegraph-component": "3",
+ "kapsule": "^1.16",
+ "polished": "4"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/accessor-fn": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/accessor-fn/-/accessor-fn-1.5.1.tgz",
+ "integrity": "sha512-zZpFYBqIL1Aqg+f2qmYHJ8+yIZF7/tP6PUGx2/QM0uGPSO5UegpinmkNwDohxWtOj586BpMPVRUjce2HI6xB3A==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.14.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
+ "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
+ "dev": true,
+ "peer": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peer": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/aframe": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/aframe/-/aframe-1.6.0.tgz",
+ "integrity": "sha512-+P1n2xKGZQbCNW4lTwfue9in2KmfAwYD/BZOU5uXKrJCTegPyUZZX/haJRR9Rb33ij+KPj3vFdwT5ALaucXTNA==",
+ "dependencies": {
+ "buffer": "^6.0.3",
+ "debug": "^4.3.4",
+ "deep-assign": "^2.0.0",
+ "load-bmfont": "^1.2.3",
+ "super-animejs": "^3.1.0",
+ "three": "npm:super-three@0.164.0",
+ "three-bmfont-text": "github:dmarcos/three-bmfont-text#eed4878795be9b3e38cf6aec6b903f56acd1f695",
+ "webvr-polyfill": "^0.10.12"
+ },
+ "engines": {
+ "node": ">= 4.6.0",
+ "npm": ">= 2.15.9"
+ }
+ },
+ "node_modules/aframe-extras": {
+ "version": "7.5.4",
+ "resolved": "https://registry.npmjs.org/aframe-extras/-/aframe-extras-7.5.4.tgz",
+ "integrity": "sha512-BWgVqzGh67hSqLGjCyBtXW4Auuf45fs+TwzIyK2Lsh2Wy36mNETwJfFxOR1i1OFEGEEYTMpbpGhMN6rbSdqc0w==",
+ "dependencies": {
+ "nipplejs": "^0.10.2",
+ "three": "^0.164.0",
+ "three-pathfinding": "^1.3.0"
+ }
+ },
+ "node_modules/aframe-extras/node_modules/three": {
+ "version": "0.164.1",
+ "resolved": "https://registry.npmjs.org/three/-/three-0.164.1.tgz",
+ "integrity": "sha512-iC/hUBbl1vzFny7f5GtqzVXYjMJKaTPxiCxXfrvVdBi1Sf+jhd1CAkitiFwC7mIBFCo3MrDLJG97yisoaWig0w=="
+ },
+ "node_modules/aframe-forcegraph-component": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aframe-forcegraph-component/-/aframe-forcegraph-component-3.1.0.tgz",
+ "integrity": "sha512-WJH++Au5LnIjISqkSkkQMN0PJdVzk5n7DSQe1iBy1juQm/FM0mIkHhW13BvmKwr1xgeA8NCQoLvMJFkhb6qX2g==",
+ "dependencies": {
+ "accessor-fn": "1",
+ "three-forcegraph": "1"
+ }
+ },
+ "node_modules/aframe/node_modules/three": {
+ "name": "super-three",
+ "version": "0.164.0",
+ "resolved": "https://registry.npmjs.org/super-three/-/super-three-0.164.0.tgz",
+ "integrity": "sha512-yMtOkw2hSXfIvGlwcghCbhHGsKRAmh8ksDeOo/0HI7KlEVoIYKHiYLYe9GF6QBViNwzKGpMIz77XUDRveZ4XJg=="
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/an-array": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/an-array/-/an-array-1.0.0.tgz",
+ "integrity": "sha512-M175GYI7RmsYu24Ok383yZQa3eveDfNnmhTe3OQ3bm70bEovz2gWenH+ST/n32M8lrwLWk74hcPds5CDRPe2wg=="
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/apexcharts": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/apexcharts/-/apexcharts-4.1.0.tgz",
+ "integrity": "sha512-TE0q0cXeS5k/AByLqlZAQ/aRQfdD3z0Ajd1uQWWZEjxiIC5qcBpMrTaG+aT+c3golqkvLH3u6kxDW8HBrggpLw==",
+ "peer": true,
+ "dependencies": {
+ "@svgdotjs/svg.draggable.js": "^3.0.4",
+ "@svgdotjs/svg.filter.js": "^3.0.8",
+ "@svgdotjs/svg.js": "^3.2.4",
+ "@svgdotjs/svg.resize.js": "^2.0.2",
+ "@svgdotjs/svg.select.js": "^4.0.1",
+ "@yr/monotone-cubic-spline": "^1.0.3"
+ }
+ },
+ "node_modules/arg": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/array-shuffle": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/array-shuffle/-/array-shuffle-1.0.1.tgz",
+ "integrity": "sha512-PBqgo1Y2XWSksBzq3GFPEb798ZrW2snAcmr4drbVeF/6MT/5aBlkGJEvu5A/CzXHf4EjbHOj/ZowatjlIiVidA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/as-number": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/as-number/-/as-number-1.0.0.tgz",
+ "integrity": "sha512-HkI/zLo2AbSRO4fqVkmyf3hms0bJDs3iboHqTrNuwTiCRvdYXM7HFhfhB6Dk51anV2LM/IMB83mtK9mHw4FlAg=="
+ },
+ "node_modules/autoprefixer": {
+ "version": "10.4.20",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
+ "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "browserslist": "^4.23.3",
+ "caniuse-lite": "^1.0.30001646",
+ "fraction.js": "^4.3.7",
+ "normalize-range": "^0.1.2",
+ "picocolors": "^1.0.1",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/babel-plugin-macros": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
+ "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "cosmiconfig": "^7.0.0",
+ "resolve": "^1.19.0"
+ },
+ "engines": {
+ "node": ">=10",
+ "npm": ">=6"
+ }
+ },
+ "node_modules/babel-plugin-macros/node_modules/cosmiconfig": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
+ "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
+ "dependencies": {
+ "@types/parse-json": "^4.0.0",
+ "import-fresh": "^3.2.1",
+ "parse-json": "^5.0.0",
+ "path-type": "^4.0.0",
+ "yaml": "^1.10.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/babel-plugin-macros/node_modules/yaml": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/bezier-js": {
+ "version": "6.1.4",
+ "resolved": "https://registry.npmjs.org/bezier-js/-/bezier-js-6.1.4.tgz",
+ "integrity": "sha512-PA0FW9ZpcHbojUCMu28z9Vg/fNkwTj5YhusSAjHHDfHDGLxJ6YUKrAN2vk1fP2MMOxVw4Oko16FMlRGVBGqLKg==",
+ "funding": {
+ "type": "individual",
+ "url": "https://github.com/Pomax/bezierjs/blob/master/FUNDING.md"
+ }
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.24.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz",
+ "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001669",
+ "electron-to-chromium": "^1.5.41",
+ "node-releases": "^2.0.18",
+ "update-browserslist-db": "^1.1.1"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ }
+ },
+ "node_modules/buffer-equal": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-0.0.1.tgz",
+ "integrity": "sha512-RgSV6InVQ9ODPdLWJ5UAqBqJBOg370Nz6ZQtRzpt6nUjc8v0St97uJ4PYC6NztqIScrAXafKM3mZPMygSe1ggA==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/builtin-modules": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
+ "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cacheable-request": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz",
+ "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==",
+ "dependencies": {
+ "clone-response": "^1.0.2",
+ "get-stream": "^5.1.0",
+ "http-cache-semantics": "^4.0.0",
+ "keyv": "^3.0.0",
+ "lowercase-keys": "^2.0.0",
+ "normalize-url": "^4.1.0",
+ "responselike": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/cacheable-request/node_modules/get-stream": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
+ "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cacheable-request/node_modules/json-buffer": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz",
+ "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ=="
+ },
+ "node_modules/cacheable-request/node_modules/keyv": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
+ "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==",
+ "dependencies": {
+ "json-buffer": "3.0.0"
+ }
+ },
+ "node_modules/cacheable-request/node_modules/lowercase-keys": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz",
+ "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase-css": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
+ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001685",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001685.tgz",
+ "integrity": "sha512-e/kJN1EMyHQzgcMEEgoo+YTCO1NGCmIYHk5Qk8jT6AazWemS5QFKJ5ShCJlH3GZrNIdZofcNCEwZqbMjjKzmnA==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ]
+ },
+ "node_modules/canvas-color-tracker": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/canvas-color-tracker/-/canvas-color-tracker-1.3.1.tgz",
+ "integrity": "sha512-eNycxGS7oQ3IS/9QQY41f/aQjiO9Y/MtedhCgSdsbLSxC9EyUD8L3ehl/Q3Kfmvt8um79S45PBV+5Rxm5ztdSw==",
+ "dependencies": {
+ "tinycolor2": "^1.6.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/cardboard-vr-display": {
+ "version": "1.0.19",
+ "resolved": "https://registry.npmjs.org/cardboard-vr-display/-/cardboard-vr-display-1.0.19.tgz",
+ "integrity": "sha512-+MjcnWKAkb95p68elqZLDPzoiF/dGncQilLGvPBM5ZorABp/ao3lCs7nnRcYBckmuNkg1V/5rdGDKoUaCVsHzQ==",
+ "dependencies": {
+ "gl-preserve-state": "^1.0.0",
+ "nosleep.js": "^0.7.0",
+ "webvr-polyfill-dpdb": "^1.0.17"
+ }
+ },
+ "node_modules/centra": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/centra/-/centra-2.7.0.tgz",
+ "integrity": "sha512-PbFMgMSrmgx6uxCdm57RUos9Tc3fclMvhLSATYN39XsDV29B89zZ3KA89jmY0vwSGazyU+uerqwa6t+KaodPcg==",
+ "dependencies": {
+ "follow-redirects": "^1.15.6"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/class-variance-authority": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
+ "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
+ "dependencies": {
+ "clsx": "^2.1.1"
+ },
+ "funding": {
+ "url": "https://polar.sh/cva"
+ }
+ },
+ "node_modules/clone-response": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz",
+ "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==",
+ "dependencies": {
+ "mimic-response": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/commander": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
+ },
+ "node_modules/d3-array": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
+ "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
+ "dependencies": {
+ "internmap": "1 - 2"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-binarytree": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/d3-binarytree/-/d3-binarytree-1.0.2.tgz",
+ "integrity": "sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw=="
+ },
+ "node_modules/d3-color": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
+ "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-dispatch": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
+ "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-drag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz",
+ "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==",
+ "dependencies": {
+ "d3-dispatch": "1 - 3",
+ "d3-selection": "3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-ease": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
+ "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-force": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-3.0.0.tgz",
+ "integrity": "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==",
+ "dependencies": {
+ "d3-dispatch": "1 - 3",
+ "d3-quadtree": "1 - 3",
+ "d3-timer": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-force-3d": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/d3-force-3d/-/d3-force-3d-3.0.5.tgz",
+ "integrity": "sha512-tdwhAhoTYZY/a6eo9nR7HP3xSW/C6XvJTbeRpR92nlPzH6OiE+4MliN9feuSFd0tPtEUo+191qOhCTWx3NYifg==",
+ "dependencies": {
+ "d3-binarytree": "1",
+ "d3-dispatch": "1 - 3",
+ "d3-octree": "1",
+ "d3-quadtree": "1 - 3",
+ "d3-timer": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-format": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
+ "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-interpolate": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
+ "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
+ "dependencies": {
+ "d3-color": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-octree": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.1.0.tgz",
+ "integrity": "sha512-F8gPlqpP+HwRPMO/8uOu5wjH110+6q4cgJvgJT6vlpy3BEaDIKlTZrgHKZSp/i1InRpVfh4puY/kvL6MxK930A=="
+ },
+ "node_modules/d3-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
+ "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-quadtree": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
+ "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-scale": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
+ "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
+ "dependencies": {
+ "d3-array": "2.10.0 - 3",
+ "d3-format": "1 - 3",
+ "d3-interpolate": "1.2.0 - 3",
+ "d3-time": "2.1.1 - 3",
+ "d3-time-format": "2 - 4"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-scale-chromatic": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
+ "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==",
+ "dependencies": {
+ "d3-color": "1 - 3",
+ "d3-interpolate": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-selection": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz",
+ "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-shape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
+ "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
+ "dependencies": {
+ "d3-path": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
+ "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
+ "dependencies": {
+ "d3-array": "2 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time-format": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz",
+ "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==",
+ "dependencies": {
+ "d3-time": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-timer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
+ "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-transition": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz",
+ "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==",
+ "dependencies": {
+ "d3-color": "1 - 3",
+ "d3-dispatch": "1 - 3",
+ "d3-ease": "1 - 3",
+ "d3-interpolate": "1 - 3",
+ "d3-timer": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "peerDependencies": {
+ "d3-selection": "2 - 3"
+ }
+ },
+ "node_modules/d3-zoom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz",
+ "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==",
+ "dependencies": {
+ "d3-dispatch": "1 - 3",
+ "d3-drag": "2 - 3",
+ "d3-interpolate": "1 - 3",
+ "d3-selection": "2 - 3",
+ "d3-transition": "2 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/data-bind-mapper": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-bind-mapper/-/data-bind-mapper-1.0.1.tgz",
+ "integrity": "sha512-xWkgLj/mSDs/Y2flAMXwLKxnCh+rFScf4N8hSOtpsMxXYXui7CbtIUYP52VXQze9HhRND2Ua/AiEHZ8j/vtB0w==",
+ "dependencies": {
+ "accessor-fn": "1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/dayjs": {
+ "version": "1.11.13",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
+ "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
+ },
+ "node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decimal.js-light": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
+ "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="
+ },
+ "node_modules/decompress-response": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz",
+ "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==",
+ "dependencies": {
+ "mimic-response": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/deep-assign": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-2.0.0.tgz",
+ "integrity": "sha512-2QhG3Kxulu4XIF3WL5C5x0sc/S17JLgm1SfvDfIRsR/5m7ZGmcejII7fZ2RyWhN0UWIJm0TNM/eKow6LAn3evQ==",
+ "dependencies": {
+ "is-obj": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/defer-to-connect": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz",
+ "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ=="
+ },
+ "node_modules/didyoumean": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/dlv": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
+ },
+ "node_modules/doctrine": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
+ "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "dependencies": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/dom-walk": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
+ "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="
+ },
+ "node_modules/dotenv": {
+ "version": "16.4.7",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
+ "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/dtype": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dtype/-/dtype-2.0.0.tgz",
+ "integrity": "sha512-s2YVcLKdFGS0hpFqJaTwscsyt0E8nNFdmo73Ocd81xNPj4URI4rj6D60A+vFMIw7BXWlb4yRkEwfBqcZzPGiZg==",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/duplexer3": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz",
+ "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA=="
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.67",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.67.tgz",
+ "integrity": "sha512-nz88NNBsD7kQSAGGJyp8hS6xSPtWwqNogA0mjtc2nUYeEf3nURK9qpV18TuBdDmEDgVWotS8Wkzf+V52dSQ/LQ=="
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.3.tgz",
+ "integrity": "sha512-9n3AsBRe6sIyOc6kmoXg2ypCLgf3eZSraWFRpnkto+svt8cZNuKTkb1bhQcitBcvIqjNiK7K0J3KPmwGSfkA8g==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.17.3",
+ "@esbuild/android-arm64": "0.17.3",
+ "@esbuild/android-x64": "0.17.3",
+ "@esbuild/darwin-arm64": "0.17.3",
+ "@esbuild/darwin-x64": "0.17.3",
+ "@esbuild/freebsd-arm64": "0.17.3",
+ "@esbuild/freebsd-x64": "0.17.3",
+ "@esbuild/linux-arm": "0.17.3",
+ "@esbuild/linux-arm64": "0.17.3",
+ "@esbuild/linux-ia32": "0.17.3",
+ "@esbuild/linux-loong64": "0.17.3",
+ "@esbuild/linux-mips64el": "0.17.3",
+ "@esbuild/linux-ppc64": "0.17.3",
+ "@esbuild/linux-riscv64": "0.17.3",
+ "@esbuild/linux-s390x": "0.17.3",
+ "@esbuild/linux-x64": "0.17.3",
+ "@esbuild/netbsd-x64": "0.17.3",
+ "@esbuild/openbsd-x64": "0.17.3",
+ "@esbuild/sunos-x64": "0.17.3",
+ "@esbuild/win32-arm64": "0.17.3",
+ "@esbuild/win32-ia32": "0.17.3",
+ "@esbuild/win32-x64": "0.17.3"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "8.57.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz",
+ "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
+ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.6.1",
+ "@eslint/eslintrc": "^2.1.4",
+ "@eslint/js": "8.57.1",
+ "@humanwhocodes/config-array": "^0.13.0",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@nodelib/fs.walk": "^1.2.8",
+ "@ungap/structured-clone": "^1.2.0",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "doctrine": "^3.0.0",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^7.2.2",
+ "eslint-visitor-keys": "^3.4.3",
+ "espree": "^9.6.1",
+ "esquery": "^1.4.2",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^6.0.1",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "globals": "^13.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "is-path-inside": "^3.0.3",
+ "js-yaml": "^4.1.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "levn": "^0.4.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/eslint-utils": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
+ "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^2.0.0"
+ },
+ "engines": {
+ "node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ },
+ "peerDependencies": {
+ "eslint": ">=5"
+ }
+ },
+ "node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-scope": {
+ "version": "7.2.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
+ "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/espree": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
+ "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "acorn": "^8.9.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^3.4.1"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esquery/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
+ },
+ "node_modules/fancy-canvas": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fancy-canvas/-/fancy-canvas-2.1.0.tgz",
+ "integrity": "sha512-nifxXJ95JNLFR2NgRV4/MxVP45G9909wJTEKz5fg/TZS20JJZA6hfgRVh/bC9bwl2zBtBNcYPjiBE4njQHVBwQ=="
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/fast-equals": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz",
+ "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/fastq": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
+ "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "flat-cache": "^3.0.4"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-root": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
+ "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+ "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.3",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": "^10.12.0 || >=12.0.0"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz",
+ "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/float-tooltip": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/float-tooltip/-/float-tooltip-1.7.3.tgz",
+ "integrity": "sha512-k7/1nX3J5POXBF+xXt1M33BpBpZgJn+GkFu+u89NuULOZmBCbWywNvS1EmdmADooAMz1MoONMiKvlGZ1kfTrqA==",
+ "dependencies": {
+ "d3-selection": "2 - 3",
+ "kapsule": "^1.16",
+ "preact": "10"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.9",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+ "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/force-graph": {
+ "version": "1.49.0",
+ "resolved": "https://registry.npmjs.org/force-graph/-/force-graph-1.49.0.tgz",
+ "integrity": "sha512-S8ODRE6eVtHtkIPCRu9Zj03uL/l8EpwKIZnIzLZO6aiZIMQLI8JguEeT3uCozT9kB2nLXem0xCiA7Pnk38Yy7g==",
+ "dependencies": {
+ "@tweenjs/tween.js": "18 - 25",
+ "accessor-fn": "1",
+ "bezier-js": "3 - 6",
+ "canvas-color-tracker": "^1.3",
+ "d3-array": "1 - 3",
+ "d3-drag": "2 - 3",
+ "d3-force-3d": "2 - 3",
+ "d3-scale": "1 - 4",
+ "d3-scale-chromatic": "1 - 3",
+ "d3-selection": "2 - 3",
+ "d3-zoom": "2 - 3",
+ "float-tooltip": "^1.6",
+ "index-array-by": "1",
+ "kapsule": "^1.16",
+ "lodash-es": "4"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
+ "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/fraction.js": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
+ "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "patreon",
+ "url": "https://github.com/sponsors/rawify"
+ }
+ },
+ "node_modules/fromentries": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz",
+ "integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functional-red-black-tree": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
+ "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
+ "dev": true
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
+ "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/gl-preserve-state": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/gl-preserve-state/-/gl-preserve-state-1.0.0.tgz",
+ "integrity": "sha512-zQZ25l3haD4hvgJZ6C9+s0ebdkW9y+7U2qxvGu1uWOJh8a4RU+jURIKEQhf8elIlFpMH6CrAY2tH0mYrRjet3Q=="
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/global": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
+ "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
+ "dependencies": {
+ "min-document": "^2.19.0",
+ "process": "^0.11.10"
+ }
+ },
+ "node_modules/globals": {
+ "version": "13.24.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
+ "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "type-fest": "^0.20.2"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/got": {
+ "version": "9.6.0",
+ "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz",
+ "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==",
+ "dependencies": {
+ "@sindresorhus/is": "^0.14.0",
+ "@szmarczak/http-timer": "^1.1.2",
+ "cacheable-request": "^6.0.0",
+ "decompress-response": "^3.3.0",
+ "duplexer3": "^0.1.4",
+ "get-stream": "^4.1.0",
+ "lowercase-keys": "^1.0.1",
+ "mimic-response": "^1.0.1",
+ "p-cancelable": "^1.0.0",
+ "to-readable-stream": "^1.0.0",
+ "url-parse-lax": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/http-cache-semantics": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz",
+ "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ=="
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/index-array-by": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/index-array-by/-/index-array-by-1.4.2.tgz",
+ "integrity": "sha512-SP23P27OUKzXWEC/TOyWlwLviofQkCSCKONnc62eItjp69yCZZPqDQtr3Pw5gJDnPeUMqExmKydNZaJO0FU9pw==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/internmap": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
+ "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
+ },
+ "node_modules/is-core-module": {
+ "version": "2.15.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
+ "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-function": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz",
+ "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ=="
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-obj": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
+ "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-path-inside": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
+ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
+ "node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/jerrypick": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/jerrypick/-/jerrypick-1.1.1.tgz",
+ "integrity": "sha512-XTtedPYEyVp4t6hJrXuRKr/jHj8SC4z+4K0b396PMkov6muL+i8IIamJIvZWe3jUspgIJak0P+BaWKawMYNBLg==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/jiti": {
+ "version": "1.21.6",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
+ "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
+ "bin": {
+ "jiti": "bin/jiti.js"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
+ "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/kapsule": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/kapsule/-/kapsule-1.16.0.tgz",
+ "integrity": "sha512-4f/z/Luu0cEXmagCwaFyzvfZai2HKgB4CQLwmsMUA+jlUbW94HfFSX+TWZxzWoMSO6b6aR+FD2Xd5z88VYZJTw==",
+ "dependencies": {
+ "lodash-es": "4"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/layout-bmfont-text": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/layout-bmfont-text/-/layout-bmfont-text-1.3.4.tgz",
+ "integrity": "sha512-mceomHZ8W7pSKQhTdLvOe1Im4n37u8xa5Gr0J3KPCHRMO/9o7+goWIOzZcUUd+Xgzy3+22bvoIQ0OaN3LRtgaw==",
+ "dependencies": {
+ "as-number": "^1.0.0",
+ "word-wrapper": "^1.0.7",
+ "xtend": "^4.0.0"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lightweight-charts": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/lightweight-charts/-/lightweight-charts-4.2.1.tgz",
+ "integrity": "sha512-nE2zCZ5Gp7KZbVHUJi6QhQLkYRvYyxsQTnSLEXIFmc8iHOFBT4rk/Dbyecq+CLW59FNuoCPNOYjZnS63/uHDrA==",
+ "dependencies": {
+ "fancy-canvas": "2.1.0"
+ }
+ },
+ "node_modules/lilconfig": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
+ "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antonk52"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
+ },
+ "node_modules/load-bmfont": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/load-bmfont/-/load-bmfont-1.4.2.tgz",
+ "integrity": "sha512-qElWkmjW9Oq1F9EI5Gt7aD9zcdHb9spJCW1L/dmPf7KzCCEJxq8nhHz5eCgI9aMf7vrG/wyaCqdsI+Iy9ZTlog==",
+ "dependencies": {
+ "buffer-equal": "0.0.1",
+ "mime": "^1.3.4",
+ "parse-bmfont-ascii": "^1.0.3",
+ "parse-bmfont-binary": "^1.0.5",
+ "parse-bmfont-xml": "^1.1.4",
+ "phin": "^3.7.1",
+ "xhr": "^2.0.1",
+ "xtend": "^4.0.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "node_modules/lodash-es": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
+ "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lowercase-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
+ "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/lucide-react": {
+ "version": "0.462.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.462.0.tgz",
+ "integrity": "sha512-NTL7EbAao9IFtuSivSZgrAh4fZd09Lr+6MTkqIxuHaH2nnYiYIzXPo06cOxHg9wKLdj6LL8TByG4qpePqwgx/g==",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc"
+ }
+ },
+ "node_modules/map-limit": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/map-limit/-/map-limit-0.0.1.tgz",
+ "integrity": "sha512-pJpcfLPnIF/Sk3taPW21G/RQsEEirGaFpCW3oXRwH9dnFHPHNGjNyvh++rdmC2fNqEaTw2MhYJraoJWAHx8kEg==",
+ "dependencies": {
+ "once": "~1.3.0"
+ }
+ },
+ "node_modules/map-limit/node_modules/once": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
+ "integrity": "sha512-6vaNInhu+CHxtONf3zw3vq4SP2DOQhjBvIa3rNcG0+P7eKWlYH6Peu7rHizSloRU2EwMz6GraLieis9Ac9+p1w==",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mimic-response": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz",
+ "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/min-document": {
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
+ "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==",
+ "dependencies": {
+ "dom-walk": "^0.1.0"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/moment": {
+ "version": "2.29.4",
+ "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
+ "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/mz": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+ "dependencies": {
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.8",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
+ "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/new-array": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/new-array/-/new-array-1.0.0.tgz",
+ "integrity": "sha512-K5AyFYbuHZ4e/ti52y7k18q8UHsS78FlRd85w2Fmsd6AkuLipDihPflKC0p3PN5i8II7+uHxo+CtkLiJDfmS5A=="
+ },
+ "node_modules/ngraph.events": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/ngraph.events/-/ngraph.events-1.2.2.tgz",
+ "integrity": "sha512-JsUbEOzANskax+WSYiAPETemLWYXmixuPAlmZmhIbIj6FH/WDgEGCGnRwUQBK0GjOnVm8Ui+e5IJ+5VZ4e32eQ=="
+ },
+ "node_modules/ngraph.forcelayout": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/ngraph.forcelayout/-/ngraph.forcelayout-3.3.1.tgz",
+ "integrity": "sha512-MKBuEh1wujyQHFTW57y5vd/uuEOK0XfXYxm3lC7kktjJLRdt/KEKEknyOlc6tjXflqBKEuYBBcu7Ax5VY+S6aw==",
+ "dependencies": {
+ "ngraph.events": "^1.0.0",
+ "ngraph.merge": "^1.0.0",
+ "ngraph.random": "^1.0.0"
+ }
+ },
+ "node_modules/ngraph.graph": {
+ "version": "20.0.1",
+ "resolved": "https://registry.npmjs.org/ngraph.graph/-/ngraph.graph-20.0.1.tgz",
+ "integrity": "sha512-VFsQ+EMkT+7lcJO1QP8Ik3w64WbHJl27Q53EO9hiFU9CRyxJ8HfcXtfWz/U8okuoYKDctbciL6pX3vG5dt1rYA==",
+ "dependencies": {
+ "ngraph.events": "^1.2.1"
+ }
+ },
+ "node_modules/ngraph.merge": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/ngraph.merge/-/ngraph.merge-1.0.0.tgz",
+ "integrity": "sha512-5J8YjGITUJeapsomtTALYsw7rFveYkM+lBj3QiYZ79EymQcuri65Nw3knQtFxQBU1r5iOaVRXrSwMENUPK62Vg=="
+ },
+ "node_modules/ngraph.random": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/ngraph.random/-/ngraph.random-1.1.0.tgz",
+ "integrity": "sha512-h25UdUN/g8U7y29TzQtRm/GvGr70lK37yQPvPKXXuVfs7gCm82WipYFZcksQfeKumtOemAzBIcT7lzzyK/edLw=="
+ },
+ "node_modules/nice-color-palettes": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/nice-color-palettes/-/nice-color-palettes-3.0.0.tgz",
+ "integrity": "sha512-lL4AjabAAFi313tjrtmgm/bxCRzp4l3vCshojfV/ij3IPdtnRqv6Chcw+SqJUhbe7g3o3BecaqCJYUNLswGBhQ==",
+ "dependencies": {
+ "got": "^9.2.2",
+ "map-limit": "0.0.1",
+ "minimist": "^1.2.0",
+ "new-array": "^1.0.0"
+ },
+ "bin": {
+ "nice-color-palettes": "bin/index.js"
+ }
+ },
+ "node_modules/nipplejs": {
+ "version": "0.10.2",
+ "resolved": "https://registry.npmjs.org/nipplejs/-/nipplejs-0.10.2.tgz",
+ "integrity": "sha512-XGxFY8C2DOtobf1fK+MXINTzkkXJLjZDDpfQhOUZf4TSytbc9s4bmA0lB9eKKM8iDivdr9NQkO7DpIQfsST+9g=="
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
+ "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g=="
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/normalize-range": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+ "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/normalize-url": {
+ "version": "4.5.1",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz",
+ "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/nosleep.js": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/nosleep.js/-/nosleep.js-0.7.0.tgz",
+ "integrity": "sha512-Z4B1HgvzR+en62ghwZf6BwAR6x4/pjezsiMcbF9KMLh7xoscpoYhaSXfY3lLkqC68AtW+/qLJ1lzvBIj0FGaTA=="
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-hash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
+ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/obsidian": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/obsidian/-/obsidian-1.7.2.tgz",
+ "integrity": "sha512-k9hN9brdknJC+afKr5FQzDRuEFGDKbDjfCazJwpgibwCAoZNYHYV8p/s3mM8I6AsnKrPKNXf8xGuMZ4enWelZQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/codemirror": "5.60.8",
+ "moment": "2.29.4"
+ },
+ "peerDependencies": {
+ "@codemirror/state": "^6.0.0",
+ "@codemirror/view": "^6.0.0"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-cancelable": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz",
+ "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-bmfont-ascii": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz",
+ "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA=="
+ },
+ "node_modules/parse-bmfont-binary": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz",
+ "integrity": "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA=="
+ },
+ "node_modules/parse-bmfont-xml": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.6.tgz",
+ "integrity": "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==",
+ "dependencies": {
+ "xml-parse-from-string": "^1.0.0",
+ "xml2js": "^0.5.0"
+ }
+ },
+ "node_modules/parse-headers": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.5.tgz",
+ "integrity": "sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA=="
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+ },
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/phin": {
+ "version": "3.7.1",
+ "resolved": "https://registry.npmjs.org/phin/-/phin-3.7.1.tgz",
+ "integrity": "sha512-GEazpTWwTZaEQ9RhL7Nyz0WwqilbqgLahDM3D0hxWwmVDI52nXEybHqiN6/elwpkJBhcuj+WbBu+QfT0uhPGfQ==",
+ "dependencies": {
+ "centra": "^2.7.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
+ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/polished": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz",
+ "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==",
+ "dependencies": {
+ "@babel/runtime": "^7.17.8"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.4.49",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
+ "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-import": {
+ "version": "15.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
+ "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
+ "dependencies": {
+ "postcss-value-parser": "^4.0.0",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
+ },
+ "node_modules/postcss-js": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
+ "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
+ "dependencies": {
+ "camelcase-css": "^2.0.1"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >= 16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.21"
+ }
+ },
+ "node_modules/postcss-load-config": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
+ "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "lilconfig": "^3.0.0",
+ "yaml": "^2.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ },
+ "peerDependencies": {
+ "postcss": ">=8.0.9",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "postcss": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/postcss-nested": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
+ "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "postcss-selector-parser": "^6.1.1"
+ },
+ "engines": {
+ "node": ">=12.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.14"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
+ },
+ "node_modules/preact": {
+ "version": "10.25.4",
+ "resolved": "https://registry.npmjs.org/preact/-/preact-10.25.4.tgz",
+ "integrity": "sha512-jLdZDb+Q+odkHJ+MpW/9U5cODzqnB+fy2EiHSZES7ldV5LK7yjlVzTp7R8Xy6W6y75kfK8iWYtFVH7lvjwrCMA==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/preact"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prepend-http": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz",
+ "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/prop-types/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/pump": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz",
+ "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/quad-indices": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/quad-indices/-/quad-indices-2.0.1.tgz",
+ "integrity": "sha512-6jtmCsEbGAh5npThXrBaubbTjPcF0rMbn57XCJVI7LkW8PUT56V+uIrRCCWCn85PSgJC9v8Pm5tnJDwmOBewvA==",
+ "dependencies": {
+ "an-array": "^1.0.0",
+ "dtype": "^2.0.0",
+ "is-buffer": "^1.0.2"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/react": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-apexcharts": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/react-apexcharts/-/react-apexcharts-1.6.0.tgz",
+ "integrity": "sha512-DmokF8EA2MPghdGuxdLMIDOB1rocqb8HhBTWGHQ+xs0U0nU3R0GFQCUP2EQ10siKUeD2aS2wDyCWuHoYYgSNKQ==",
+ "dependencies": {
+ "prop-types": "^15.8.1"
+ },
+ "peerDependencies": {
+ "apexcharts": ">=4.0.0",
+ "react": ">=0.13"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
+ "node_modules/react-force-graph": {
+ "version": "1.46.0",
+ "resolved": "https://registry.npmjs.org/react-force-graph/-/react-force-graph-1.46.0.tgz",
+ "integrity": "sha512-ha1C+2QZYKUdb4kaq65tjwfAslgXRK7PF39KseztMcskV5Is525pXzEKhAdvSLO0xfThEAX/eIHzC71/TrIkXw==",
+ "dependencies": {
+ "3d-force-graph": "^1.76",
+ "3d-force-graph-ar": "^1.9",
+ "3d-force-graph-vr": "^2.4",
+ "force-graph": "^1.49",
+ "prop-types": "15",
+ "react-kapsule": "^2.5"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "peerDependencies": {
+ "react": "*"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
+ },
+ "node_modules/react-kapsule": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/react-kapsule/-/react-kapsule-2.5.0.tgz",
+ "integrity": "sha512-bJm1K4dyfZ3xKaulvVgiLkoGqlxjmfoajlOErC2y9j1hJpzbc7cLwhoBWqRnZ/2IqgIMWpP2uIn8VMN2sgAsFA==",
+ "dependencies": {
+ "fromentries": "^1.3.2",
+ "jerrypick": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "peerDependencies": {
+ "react": ">=16.13.1"
+ }
+ },
+ "node_modules/react-smooth": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.1.tgz",
+ "integrity": "sha512-OE4hm7XqR0jNOq3Qmk9mFLyd6p2+j6bvbPJ7qlB7+oo0eNcL2l7WQzG6MBnT3EXY6xzkLMUBec3AfewJdA0J8w==",
+ "dependencies": {
+ "fast-equals": "^5.0.1",
+ "prop-types": "^15.8.1",
+ "react-transition-group": "^4.4.5"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0",
+ "react-dom": ">=16.6.0"
+ }
+ },
+ "node_modules/read-cache": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+ "dependencies": {
+ "pify": "^2.3.0"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/recharts": {
+ "version": "2.13.3",
+ "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.13.3.tgz",
+ "integrity": "sha512-YDZ9dOfK9t3ycwxgKbrnDlRC4BHdjlY73fet3a0C1+qGMjXVZe6+VXmpOIIhzkje5MMEL8AN4hLIe4AMskBzlA==",
+ "dependencies": {
+ "clsx": "^2.0.0",
+ "eventemitter3": "^4.0.1",
+ "lodash": "^4.17.21",
+ "react-is": "^18.3.1",
+ "react-smooth": "^4.0.0",
+ "recharts-scale": "^0.4.4",
+ "tiny-invariant": "^1.3.1",
+ "victory-vendor": "^36.6.8"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": "^16.0.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/recharts-scale": {
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz",
+ "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==",
+ "dependencies": {
+ "decimal.js-light": "^2.4.1"
+ }
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
+ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
+ },
+ "node_modules/regexpp": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
+ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/responselike": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz",
+ "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==",
+ "dependencies": {
+ "lowercase-keys": "^1.0.0"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/sax": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
+ "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg=="
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/shadcn": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/shadcn/-/shadcn-1.0.0.tgz",
+ "integrity": "sha512-kCxBIBiPS83WxrWkOQHamWpr9XlLtOtOlJM6QX90h9A5xZCBMhxu4ibcNT2ZnzZLdexkYbQrnijfPKdOsZxOpA=="
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "node_modules/string-width/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/string-width/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/style-mod": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz",
+ "integrity": "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw=="
+ },
+ "node_modules/stylis": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
+ "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="
+ },
+ "node_modules/sucrase": {
+ "version": "3.35.0",
+ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
+ "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "commander": "^4.0.0",
+ "glob": "^10.3.10",
+ "lines-and-columns": "^1.1.6",
+ "mz": "^2.7.0",
+ "pirates": "^4.0.1",
+ "ts-interface-checker": "^0.1.9"
+ },
+ "bin": {
+ "sucrase": "bin/sucrase",
+ "sucrase-node": "bin/sucrase-node"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/sucrase/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/sucrase/node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/sucrase/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/super-animejs": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/super-animejs/-/super-animejs-3.1.0.tgz",
+ "integrity": "sha512-6MFAFJDRuvwkovxQZPruuyHinTa4rgj4hNLOndjcYYhZLckoXtVRY9rJPuq8p6c/tgZJrFYEAYAfJ2/hhNtUCA=="
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/tailwind-merge": {
+ "version": "2.5.5",
+ "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.5.tgz",
+ "integrity": "sha512-0LXunzzAZzo0tEPxV3I297ffKZPlKDrjj7NXphC8V5ak9yHC5zRmxnOe2m/Rd/7ivsOMJe3JZ2JVocoDdQTRBA==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/dcastil"
+ }
+ },
+ "node_modules/tailwindcss": {
+ "version": "3.4.16",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.16.tgz",
+ "integrity": "sha512-TI4Cyx7gDiZ6r44ewaJmt0o6BrMCT5aK5e0rmJ/G9Xq3w7CX/5VXl/zIPEJZFUK5VEqwByyhqNPycPlvcK4ZNw==",
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "arg": "^5.0.2",
+ "chokidar": "^3.6.0",
+ "didyoumean": "^1.2.2",
+ "dlv": "^1.1.3",
+ "fast-glob": "^3.3.2",
+ "glob-parent": "^6.0.2",
+ "is-glob": "^4.0.3",
+ "jiti": "^1.21.6",
+ "lilconfig": "^3.1.3",
+ "micromatch": "^4.0.8",
+ "normalize-path": "^3.0.0",
+ "object-hash": "^3.0.0",
+ "picocolors": "^1.1.1",
+ "postcss": "^8.4.47",
+ "postcss-import": "^15.1.0",
+ "postcss-js": "^4.0.1",
+ "postcss-load-config": "^4.0.2",
+ "postcss-nested": "^6.2.0",
+ "postcss-selector-parser": "^6.1.2",
+ "resolve": "^1.22.8",
+ "sucrase": "^3.35.0"
+ },
+ "bin": {
+ "tailwind": "lib/cli.js",
+ "tailwindcss": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/thenify": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+ "dependencies": {
+ "any-promise": "^1.0.0"
+ }
+ },
+ "node_modules/thenify-all": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+ "dependencies": {
+ "thenify": ">= 3.1.0 < 4"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/three": {
+ "version": "0.172.0",
+ "resolved": "https://registry.npmjs.org/three/-/three-0.172.0.tgz",
+ "integrity": "sha512-6HMgMlzU97MsV7D/tY8Va38b83kz8YJX+BefKjspMNAv0Vx6dxMogHOrnRl/sbMIs3BPUKijPqDqJ/+UwJbIow=="
+ },
+ "node_modules/three-bmfont-text": {
+ "version": "3.0.0",
+ "resolved": "git+ssh://git@github.com/dmarcos/three-bmfont-text.git#eed4878795be9b3e38cf6aec6b903f56acd1f695",
+ "integrity": "sha512-1tv41kf1bo31dFvQeWyiAcurNg926wslmUQztsjbpIwEIJ7WqAQUOownrbHcAQVYlIdtcP4M+tXYaHzbUEF2GA==",
+ "license": "MIT",
+ "dependencies": {
+ "array-shuffle": "^1.0.1",
+ "layout-bmfont-text": "^1.2.0",
+ "nice-color-palettes": "^3.0.0",
+ "quad-indices": "^2.0.1"
+ }
+ },
+ "node_modules/three-forcegraph": {
+ "version": "1.42.11",
+ "resolved": "https://registry.npmjs.org/three-forcegraph/-/three-forcegraph-1.42.11.tgz",
+ "integrity": "sha512-MXESG+qXXzsZDaY1N0M3fW1sfgJinm/DjNwO9oS9XXT1NRK9KoRijYDt5ilzI8M4OdJ3pA4YdaV3nDBw2HPVOw==",
+ "dependencies": {
+ "accessor-fn": "1",
+ "d3-array": "1 - 3",
+ "d3-force-3d": "2 - 3",
+ "d3-scale": "1 - 4",
+ "d3-scale-chromatic": "1 - 3",
+ "data-bind-mapper": "1",
+ "kapsule": "^1.16",
+ "ngraph.forcelayout": "3",
+ "ngraph.graph": "20",
+ "tinycolor2": "1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "peerDependencies": {
+ "three": ">=0.118.3"
+ }
+ },
+ "node_modules/three-pathfinding": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/three-pathfinding/-/three-pathfinding-1.3.0.tgz",
+ "integrity": "sha512-LKxMI3/YqdMYvt6AdE2vB6s5ueDFczt/DWoxhtPNgRsH6E0D8LMYQxz+eIrmKo0MQpDvMVzXYUMBk+b86+k97w==",
+ "peerDependencies": {
+ "three": "0.x.x"
+ }
+ },
+ "node_modules/three-render-objects": {
+ "version": "1.35.0",
+ "resolved": "https://registry.npmjs.org/three-render-objects/-/three-render-objects-1.35.0.tgz",
+ "integrity": "sha512-rZ6tn5VOtp/G7sw2aGI+VH6HQ/ALIlexpf24Pk2D7vw5NAR0RZdNZZ1VZdl42NanQWNIcy/TuJ935BXiRpyusQ==",
+ "dependencies": {
+ "@tweenjs/tween.js": "18 - 25",
+ "accessor-fn": "1",
+ "float-tooltip": "^1.6",
+ "kapsule": "^1.16",
+ "polished": "4"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "peerDependencies": {
+ "three": ">=0.168"
+ }
+ },
+ "node_modules/tiny-invariant": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
+ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="
+ },
+ "node_modules/tinycolor2": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz",
+ "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw=="
+ },
+ "node_modules/to-readable-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz",
+ "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/ts-interface-checker": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
+ },
+ "node_modules/tslib": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz",
+ "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==",
+ "dev": true
+ },
+ "node_modules/tsutils": {
+ "version": "3.21.0",
+ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
+ "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^1.8.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ },
+ "peerDependencies": {
+ "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
+ }
+ },
+ "node_modules/tsutils/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.20.2",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
+ "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "4.9.5",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
+ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=4.2.0"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
+ "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.0"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/url-parse-lax": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz",
+ "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==",
+ "dependencies": {
+ "prepend-http": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ },
+ "node_modules/victory-vendor": {
+ "version": "36.9.2",
+ "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz",
+ "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==",
+ "dependencies": {
+ "@types/d3-array": "^3.0.3",
+ "@types/d3-ease": "^3.0.0",
+ "@types/d3-interpolate": "^3.0.1",
+ "@types/d3-scale": "^4.0.2",
+ "@types/d3-shape": "^3.1.0",
+ "@types/d3-time": "^3.0.0",
+ "@types/d3-timer": "^3.0.0",
+ "d3-array": "^3.1.6",
+ "d3-ease": "^3.0.1",
+ "d3-interpolate": "^3.0.1",
+ "d3-scale": "^4.0.2",
+ "d3-shape": "^3.1.0",
+ "d3-time": "^3.0.0",
+ "d3-timer": "^3.0.1"
+ }
+ },
+ "node_modules/w3c-keyname": {
+ "version": "2.2.8",
+ "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
+ "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="
+ },
+ "node_modules/webvr-polyfill": {
+ "version": "0.10.12",
+ "resolved": "https://registry.npmjs.org/webvr-polyfill/-/webvr-polyfill-0.10.12.tgz",
+ "integrity": "sha512-trDJEVUQnRIVAnmImjEQ0BlL1NfuWl8+eaEdu+bs4g59c7OtETi/5tFkgEFDRaWEYwHntXs/uFF3OXZuutNGGA==",
+ "dependencies": {
+ "cardboard-vr-display": "^1.0.19"
+ }
+ },
+ "node_modules/webvr-polyfill-dpdb": {
+ "version": "1.0.18",
+ "resolved": "https://registry.npmjs.org/webvr-polyfill-dpdb/-/webvr-polyfill-dpdb-1.0.18.tgz",
+ "integrity": "sha512-O0S1ZGEWyPvyZEkS2VbyV7mtir/NM9MNK3EuhbHPoJ8EHTky2pTXehjIl+IiDPr+Lldgx129QGt3NGly7rwRPw=="
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/word-wrapper": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/word-wrapper/-/word-wrapper-1.0.7.tgz",
+ "integrity": "sha512-VOPBFCm9b6FyYKQYfn9AVn2dQvdR/YOVFV6IBRA1TBMJWKffvhEX1af6FMGrttILs2Q9ikCRhLqkbY2weW6dOQ=="
+ },
+ "node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
+ "node_modules/xhr": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz",
+ "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==",
+ "dependencies": {
+ "global": "~4.4.0",
+ "is-function": "^1.0.1",
+ "parse-headers": "^2.0.0",
+ "xtend": "^4.0.0"
+ }
+ },
+ "node_modules/xml-parse-from-string": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz",
+ "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g=="
+ },
+ "node_modules/xml2js": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
+ "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
+ "dependencies": {
+ "sax": ">=0.6.0",
+ "xmlbuilder": "~11.0.0"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/xmlbuilder": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
+ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true
+ },
+ "node_modules/yaml": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz",
+ "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..1fdc926
--- /dev/null
+++ b/package.json
@@ -0,0 +1,58 @@
+{
+ "name": "obsidian-sample-plugin",
+ "version": "1.0.0",
+ "description": "This is a sample plugin for Obsidian (https://obsidian.md)",
+ "main": "main.js",
+ "scripts": {
+ "dev": "node esbuild.config.mjs",
+ "build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
+ "version": "node version-bump.mjs && git add manifest.json versions.json"
+ },
+ "keywords": [],
+ "author": "",
+ "license": "MIT",
+ "devDependencies": {
+ "@babel/core": "^7.26.0",
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
+ "@babel/plugin-transform-modules-commonjs": "^7.25.9",
+ "@babel/preset-react": "^7.25.9",
+ "@babel/preset-typescript": "^7.26.0",
+ "@babel/standalone": "^7.26.2",
+ "@types/d3-force": "^3.0.10",
+ "@types/node": "^16.11.6",
+ "@types/react": "^18.3.12",
+ "@types/react-dom": "^18.3.1",
+ "@typescript-eslint/eslint-plugin": "5.29.0",
+ "@typescript-eslint/parser": "5.29.0",
+ "builtin-modules": "3.3.0",
+ "esbuild": "0.17.3",
+ "obsidian": "latest",
+ "tslib": "2.4.0",
+ "typescript": "^4.8.0"
+ },
+ "dependencies": {
+ "@codemirror/language": "^6.10.6",
+ "@emotion/css": "^11.13.5",
+ "@lezer/common": "^1.2.3",
+ "@radix-ui/react-switch": "^1.0.3",
+ "@radix-ui/react-tabs": "^1.1.1",
+ "autoprefixer": "^10.4.20",
+ "class-variance-authority": "^0.7.1",
+ "clsx": "^2.1.1",
+ "d3-force": "^3.0.0",
+ "dayjs": "^1.11.13",
+ "dotenv": "^16.4.7",
+ "lightweight-charts": "^4.2.1",
+ "lucide-react": "^0.462.0",
+ "postcss": "^8.4.49",
+ "react": "^18.3.1",
+ "react-apexcharts": "^1.6.0",
+ "react-dom": "^18.3.1",
+ "react-force-graph": "^1.46.0",
+ "recharts": "^2.13.3",
+ "shadcn": "^1.0.0",
+ "tailwind-merge": "^2.5.5",
+ "tailwindcss": "^3.4.16",
+ "yaml": "^2.6.1"
+ }
+}
diff --git a/react-shim.js b/react-shim.js
new file mode 100644
index 0000000..0a61bf0
--- /dev/null
+++ b/react-shim.js
@@ -0,0 +1,4 @@
+// react-shim.js
+import React from 'react';
+import ReactDOM from 'react-dom';
+export { React, ReactDOM };
\ No newline at end of file
diff --git a/src/components/ComponentRenderer.tsx b/src/components/ComponentRenderer.tsx
new file mode 100644
index 0000000..bb654cb
--- /dev/null
+++ b/src/components/ComponentRenderer.tsx
@@ -0,0 +1,133 @@
+// src/components/ComponentRenderer.tsx
+import React, { useState, useEffect } from 'react';
+import { transform } from '@babel/standalone';
+import { ErrorBoundary } from './ErrorBoundary';
+import { App } from 'obsidian';
+import { useStorage } from '../hooks/useStorage';
+import { ComponentRegistry } from '../core/registry';
+import { StorageManager } from '../core/storage';
+
+interface ComponentRendererProps {
+ code: string;
+ scopeId: string;
+ inline?: boolean;
+ storage: StorageManager; // Add storage prop
+ children?: React.ReactNode;
+}
+
+interface TransformError {
+ message: string;
+ line?: number;
+ column?: number;
+}
+
+const ErrorDisplay: React.FC<{ error: TransformError }> = ({ error }) => {
+ return (
+
+
Error in component:
+
+ {error.message}
+ {error.line && error.column &&
+ `\nAt line ${error.line}, column ${error.column}`
+ }
+
+
+ );
+};
+
+export const ComponentRenderer: React.FC = ({
+ code,
+ scopeId,
+ storage, // Get storage from props
+ inline = false
+}) => {
+ const [Component, setComponent] = useState(null);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ const createComponent = async () => {
+ try {
+ const transformedCode = transform(code, {
+ presets: ['env','react'],
+ plugins: [
+ '@babel/plugin-syntax-jsx', // Add JSX syntax plugin explicitly
+ '@babel/plugin-transform-react-jsx', // Transforms JSX into JS
+ '@babel/plugin-proposal-class-properties', // Handles class properties
+ '@babel/plugin-proposal-object-rest-spread', // Handles object spread syntax
+ ],
+ filename: `component-${scopeId}`,
+ sourceType: 'module',
+ configFile: false,
+ babelrc: false
+ }).code;
+ console.log('Transformed Code:', transformedCode);
+ // Create storage hook bound to this storage instance
+ const boundUseStorage = (key: string, defaultValue: T) =>
+ useStorage(key, defaultValue, storage);
+
+ // Enhanced scope with registry and storage
+ const scope = {
+ React,
+ useState: React.useState,
+ useEffect: React.useEffect,
+ useRef: React.useRef,
+ useStorage: boundUseStorage, // Add bound storage hook
+ ...ComponentRegistry,
+ };
+
+ const componentFn = new Function(
+ ...Object.keys(scope),
+ `try {
+ ${transformedCode}
+ return Component;
+ } catch (err) {
+ console.error('Error in component execution:', err);
+ throw err;
+ }`
+ );
+
+ const ComponentType = componentFn(...Object.values(scope));
+ setComponent(() => ComponentType);
+ setError(null);
+ } catch (err) {
+ console.error('Component transformation failed:', err);
+ setError({
+ message: err instanceof Error ? err.message : 'Unknown error',
+ line: (err as any).loc?.line,
+ column: (err as any).loc?.column
+ });
+ setComponent(null);
+ }
+ };
+
+ createComponent();
+ }, [code, scopeId, storage]); // Add storage to dependencies
+
+ const Wrapper: React.FC<{ children: React.ReactNode }> =
+ inline ? ({ children }) => (
+ {children}
+ ) : ({ children }) => (
+ {children}
+ );
+
+ if (error) {
+ return ;
+ }
+
+ if (!Component) {
+ return null;
+ }
+
+ return (
+
+ e.stopPropagation()}
+ >
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/src/components/ErrorBoundary.tsx b/src/components/ErrorBoundary.tsx
new file mode 100644
index 0000000..3a29ef1
--- /dev/null
+++ b/src/components/ErrorBoundary.tsx
@@ -0,0 +1,135 @@
+// src/components/ErrorBoundary.tsx
+import React from 'react';
+import { RefreshCw } from 'lucide-react'; // Assuming you're using lucide-react for icons
+
+interface ErrorBoundaryProps {
+ children: React.ReactNode;
+ fallback?: React.ComponentType<{ error: Error }>;
+}
+
+interface ErrorBoundaryState {
+ hasError: boolean;
+ error: Error | null;
+ errorInfo: React.ErrorInfo | null;
+}
+
+export class ErrorBoundary extends React.Component {
+ constructor(props: ErrorBoundaryProps) {
+ super(props);
+ this.state = {
+ hasError: false,
+ error: null,
+ errorInfo: null
+ };
+ }
+
+ static getDerivedStateFromError(error: Error): Partial {
+ return {
+ hasError: true,
+ error
+ };
+ }
+
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
+ this.setState({
+ error,
+ errorInfo
+ });
+
+ // Log error to console for debugging
+ console.error('Error caught by boundary:', error, errorInfo);
+ }
+
+ handleRetry = (): void => {
+ this.setState({
+ hasError: false,
+ error: null,
+ errorInfo: null
+ });
+ };
+
+ render() {
+ if (this.state.hasError) {
+ // Use custom fallback if provided
+ if (this.props.fallback) {
+ const FallbackComponent = this.props.fallback;
+ return ;
+ }
+
+ // Default error UI
+ return (
+
+
+
+ Component Error
+
+
+
+ Retry
+
+
+
+
+ {this.state.error?.message || 'An unexpected error occurred'}
+
+
+ {process.env.NODE_ENV === 'development' && this.state.errorInfo && (
+
+
+ Stack trace
+
+
+ {this.state.errorInfo.componentStack}
+
+
+ )}
+
+ );
+ }
+
+ return (
+
+ {this.props.children}
+
+ );
+ }
+}
+
+// Higher-order component for easier usage
+export function withErrorBoundary(
+ Component: React.ComponentType
,
+ fallback?: React.ComponentType<{ error: Error }>
+): React.FC
{
+ return function WrappedComponent(props: P) {
+ return (
+
+
+
+ );
+ };
+}
+
+// Example usage of custom fallback:
+/*
+const CustomFallback: React.FC<{ error: Error }> = ({ error }) => (
+
+
Something went wrong
+
{error.message}
+
+);
+
+// Use with custom fallback
+
+
+
+
+// Or use HOC
+const SafeComponent = withErrorBoundary(YourComponent, CustomFallback);
+*/
\ No newline at end of file
diff --git a/src/components/OrderblockVisualiser.ts b/src/components/OrderblockVisualiser.ts
new file mode 100644
index 0000000..9eb01d8
--- /dev/null
+++ b/src/components/OrderblockVisualiser.ts
@@ -0,0 +1,36 @@
+// src/utils/orderBlockVisualization.ts
+import { IChartApi, ISeriesApi } from 'lightweight-charts';
+import { Rectangle } from '../plugins/RectanglePlugin';
+import { OrderBlock } from '../services/OrderBlockAnalysis';
+
+export function visualizeOrderBlocks(
+ chart: IChartApi,
+ mainSeries: ISeriesApi<"Candlestick">,
+ orderBlocks: OrderBlock[]
+) {
+ orderBlocks.forEach(block => {
+ const rectangle = new Rectangle(
+ {
+ time: block.startTime / 1000, // Convert to seconds for lightweight-charts
+ price: block.highPrice
+ },
+ {
+ time: block.endTime / 1000,
+ price: block.lowPrice
+ },
+ {
+ fillColor: block.type === 'bullish'
+ ? 'rgba(34, 197, 94, 0.2)' // Green
+ : 'rgba(239, 68, 68, 0.2)', // Red
+ borderColor: block.type === 'bullish'
+ ? 'rgba(34, 197, 94, 1)'
+ : 'rgba(239, 68, 68, 1)',
+ borderWidth: block.validationMetrics.impulseStrength > 1.5 ? 2 : 1,
+ opacity: block.validationMetrics.gapQuality,
+ extend: 'right' // Extend to the right of the chart
+ }
+ );
+
+ mainSeries.attachPrimitive(rectangle);
+ });
+}
\ No newline at end of file
diff --git a/src/components/RectPlugin.ts b/src/components/RectPlugin.ts
new file mode 100644
index 0000000..7804f03
--- /dev/null
+++ b/src/components/RectPlugin.ts
@@ -0,0 +1,92 @@
+// src/component/RectPlugin.ts
+interface Point {
+ time: number;
+ price: number;
+}
+
+interface RectangleOptions {
+ fillColor?: string;
+ borderColor?: string;
+ borderWidth?: number;
+ opacity?: number;
+ extend?: 'none' | 'right';
+}
+
+export class Rectangle {
+ private _point1: Point;
+ private _point2: Point;
+ private _options: Required;
+
+ private static readonly defaultOptions: Required = {
+ fillColor: 'rgba(255, 255, 255, 0.2)',
+ borderColor: 'rgba(255, 255, 255, 1)',
+ borderWidth: 1,
+ opacity: 0.2,
+ extend: 'none'
+ };
+
+ constructor(point1: Point, point2: Point, options: RectangleOptions = {}) {
+ this._point1 = point1;
+ this._point2 = point2;
+ this._options = { ...Rectangle.defaultOptions, ...options };
+ }
+
+ draw(ctx: CanvasRenderingContext2D, pixelRatio: number, model: any): void {
+ const points = this._calculatePoints(model);
+ if (!points) return;
+
+ const { x1, y1, x2, y2 } = points;
+
+ ctx.save();
+
+ // Set line style
+ ctx.lineWidth = this._options.borderWidth * pixelRatio;
+ ctx.strokeStyle = this._options.borderColor;
+ ctx.fillStyle = this._options.fillColor;
+
+ // Draw rectangle
+ ctx.beginPath();
+ ctx.rect(
+ Math.round(x1 * pixelRatio),
+ Math.round(y1 * pixelRatio),
+ Math.round((x2 - x1) * pixelRatio),
+ Math.round((y2 - y1) * pixelRatio)
+ );
+
+ // Fill with semi-transparency
+ ctx.globalAlpha = this._options.opacity;
+ ctx.fill();
+
+ // Draw border
+ ctx.globalAlpha = 1;
+ ctx.stroke();
+
+ ctx.restore();
+ }
+
+ hitTest(x: number, y: number): boolean {
+ // Implement hit testing if needed
+ return false;
+ }
+
+ private _calculatePoints(model: any) {
+ const point1X = model.timeScale().timeToCoordinate(this._point1.time);
+ const point2X = this._options.extend === 'right'
+ ? model.timeScale().getWidth()
+ : model.timeScale().timeToCoordinate(this._point2.time);
+
+ const point1Y = model.priceScale('right').priceToCoordinate(this._point1.price);
+ const point2Y = model.priceScale('right').priceToCoordinate(this._point2.price);
+
+ if (!point1X || !point2X || !point1Y || !point2Y) {
+ return null;
+ }
+
+ return {
+ x1: Math.min(point1X, point2X),
+ y1: Math.min(point1Y, point2Y),
+ x2: Math.max(point1X, point2X),
+ y2: Math.max(point1Y, point2Y)
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/components/styled.tsx b/src/components/styled.tsx
new file mode 100644
index 0000000..f0bda1c
--- /dev/null
+++ b/src/components/styled.tsx
@@ -0,0 +1,57 @@
+// components/styled.tsx
+import React from 'react';
+
+interface BoxProps extends React.HTMLAttributes {
+ mt?: number;
+ mb?: number;
+ p?: number;
+ flex?: boolean;
+ grid?: boolean;
+ cols?: number;
+ gap?: number;
+ center?: boolean;
+}
+
+export const Box = React.forwardRef(({
+ mt,
+ mb,
+ p,
+ flex,
+ grid,
+ cols,
+ gap,
+ center,
+ style,
+ ...props
+}, ref) => {
+ const computedStyle: React.CSSProperties = {
+ ...(mt && { marginTop: `${mt * 0.25}rem` }),
+ ...(mb && { marginBottom: `${mb * 0.25}rem` }),
+ ...(p && { padding: `${p * 0.25}rem` }),
+ ...(flex && { display: 'flex' }),
+ ...(grid && {
+ display: 'grid',
+ gridTemplateColumns: `repeat(${cols || 1}, minmax(0, 1fr))`,
+ gap: gap ? `${gap * 0.25}rem` : undefined
+ }),
+ ...(center && {
+ alignItems: 'center',
+ justifyContent: 'center'
+ }),
+ ...style
+ };
+
+ return
;
+});
+
+// Usage:
+const MyComponent = () => {
+ return (
+
+
+ Column 1
+ Column 2
+
+
+ );
+};
\ No newline at end of file
diff --git a/src/components/ui/card - Copy - Copy.tsx b/src/components/ui/card - Copy - Copy.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/ui/card.tsx b/src/components/ui/card.tsx
new file mode 100644
index 0000000..152bb32
--- /dev/null
+++ b/src/components/ui/card.tsx
@@ -0,0 +1,79 @@
+import * as React from "react"
+
+import { cn } from "src/lib/utils"
+
+const Card = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+Card.displayName = "Card"
+
+const CardHeader = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardHeader.displayName = "CardHeader"
+
+const CardTitle = React.forwardRef<
+ HTMLParagraphElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardTitle.displayName = "CardTitle"
+
+const CardDescription = React.forwardRef<
+ HTMLParagraphElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardDescription.displayName = "CardDescription"
+
+const CardContent = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardContent.displayName = "CardContent"
+
+const CardFooter = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+CardFooter.displayName = "CardFooter"
+
+export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
diff --git a/src/components/ui/switch.tsx b/src/components/ui/switch.tsx
new file mode 100644
index 0000000..39bea05
--- /dev/null
+++ b/src/components/ui/switch.tsx
@@ -0,0 +1,29 @@
+"use client"
+
+import * as React from "react"
+import * as SwitchPrimitives from "@radix-ui/react-switch"
+
+import { cn } from "src/lib/utils"
+
+const Switch = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+))
+Switch.displayName = SwitchPrimitives.Root.displayName
+
+export { Switch }
\ No newline at end of file
diff --git a/src/components/ui/tabs.tsx b/src/components/ui/tabs.tsx
new file mode 100644
index 0000000..7b5227b
--- /dev/null
+++ b/src/components/ui/tabs.tsx
@@ -0,0 +1,52 @@
+import * as React from "react"
+import * as TabsPrimitive from "@radix-ui/react-tabs"
+import { cn } from "src/lib/utils"
+
+const Tabs = TabsPrimitive.Root
+
+const TabsList = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+TabsList.displayName = TabsPrimitive.List.displayName
+
+const TabsTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
+
+const TabsContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+TabsContent.displayName = TabsPrimitive.Content.displayName
+
+export { Tabs, TabsList, TabsTrigger, TabsContent }
\ No newline at end of file
diff --git a/src/core/dynamic.tsx b/src/core/dynamic.tsx
new file mode 100644
index 0000000..229e42b
--- /dev/null
+++ b/src/core/dynamic.tsx
@@ -0,0 +1,84 @@
+// src/core/dynamic.tsx
+import React, {
+ useEffect,
+ useState,
+ ComponentType,
+ FC,
+ ComponentProps,
+ ReactElement
+} from 'react';
+
+interface DynamicOptions {
+ loading?: ComponentType;
+ error?: ComponentType<{ error: Error }>;
+}
+
+type ImportFunction = () => Promise<{ default: T }>;
+
+const DefaultError: FC<{ error: Error }> = ({ error }): ReactElement => {
+ return (
+
+ Error loading component: {error.message}
+
+ );
+};
+
+const DefaultLoading: FC = (): ReactElement => {
+ return Loading...
;
+};
+
+export function dynamic>(
+ importFn: ImportFunction,
+ options: DynamicOptions = {}
+): FC> {
+ const LoadingComponent: ComponentType = options.loading || DefaultLoading;
+ const ErrorComponent: ComponentType<{ error: Error }> = options.error || DefaultError;
+
+ const DynamicComponent: FC> = (props): ReactElement => {
+ const [Component, setComponent] = useState(null);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ let mounted = true;
+
+ const loadComponent = async (): Promise => {
+ try {
+ const module = await importFn();
+ if (mounted) {
+ setComponent(() => module.default);
+ }
+ } catch (err) {
+ if (mounted) {
+ setError(err instanceof Error ? err : new Error('Failed to load component'));
+ }
+ }
+ };
+
+ loadComponent();
+ return () => { mounted = false; };
+ }, []);
+
+ if (error) {
+ return ;
+ }
+
+ if (!Component) {
+ return ;
+ }
+
+ return ;
+ };
+
+ return DynamicComponent;
+}
+
+// Version for named exports
+export function dynamicNamed>(
+ importFn: () => Promise,
+ options: DynamicOptions = {}
+): FC> {
+ return dynamic(
+ async () => ({ default: await importFn() }),
+ options
+ );
+}
\ No newline at end of file
diff --git a/src/core/registry.tsx b/src/core/registry.tsx
new file mode 100644
index 0000000..9728271
--- /dev/null
+++ b/src/core/registry.tsx
@@ -0,0 +1,47 @@
+// src/core/registry.tsx
+import React, { FC, ComponentProps } from 'react';
+import { dynamic, dynamicNamed } from './dynamic';
+
+interface Registry {
+ PieChart: FC>;
+ Chart: FC>;
+ ForceGraph2D: FC>;
+ [key: string]: FC>; // Add index signature
+ Pie: FC>;
+ Cell: FC>;
+ ResponsiveContainer: FC>;
+ Tooltip: FC>;
+ Legend: FC>;
+}
+
+export const ComponentRegistry: Registry = {
+ // For named exports from recharts, use dynamicNamed
+ PieChart: dynamicNamed(() =>
+ import('recharts').then(mod => mod.PieChart)
+ ),
+ Pie: dynamicNamed(() =>
+ import('recharts').then(mod => mod.Pie)
+ ),
+ Cell: dynamicNamed(() =>
+ import('recharts').then(mod => mod.Cell)
+ ),
+ ResponsiveContainer: dynamicNamed(() =>
+ import('recharts').then(mod => mod.ResponsiveContainer)
+ ),
+ Tooltip: dynamicNamed(() =>
+ import('recharts').then(mod => mod.Tooltip)
+ ),
+ Legend: dynamicNamed(() =>
+ import('recharts').then(mod => mod.Legend)
+ ),
+
+ // For components with default exports, use dynamic
+ Chart: dynamic(() => import('react-apexcharts')),
+ ForceGraph2D: dynamicNamed(() =>
+ import('react-force-graph').then(mod => mod.ForceGraph2D)
+ )
+};
+
+export const getRegisteredComponent = (name: string): FC> | null => {
+ return ComponentRegistry[name] || null;
+};
\ No newline at end of file
diff --git a/src/core/scope.ts b/src/core/scope.ts
new file mode 100644
index 0000000..71db892
--- /dev/null
+++ b/src/core/scope.ts
@@ -0,0 +1,212 @@
+// src/core/scope.ts
+import React from 'react';
+import { App } from 'obsidian';
+
+interface ScopeOptions {
+ app?: App;
+ parentScope?: ComponentScope;
+ isGlobal?: boolean;
+}
+
+export class ComponentScope {
+ private static instances = new Map();
+ private static globalScope: ComponentScope | null = null;
+
+ private variables = new Map();
+ private children = new Set();
+ private readonly defaultScope: Record;
+
+ constructor(
+ private readonly id: string,
+ private readonly options: ScopeOptions = {}
+ ) {
+ // Initialize default React scope
+ this.defaultScope = {
+ React,
+ useState: React.useState,
+ useEffect: React.useEffect,
+ useRef: React.useRef,
+ useMemo: React.useMemo,
+ useCallback: React.useCallback,
+ useContext: React.useContext,
+ // Add Obsidian app if available
+ app: options.app,
+ };
+
+ if (options.isGlobal) {
+ ComponentScope.globalScope = this;
+ } else if (options.parentScope) {
+ options.parentScope.addChild(this);
+ }
+
+ ComponentScope.instances.set(id, this);
+ }
+
+ // Get a value from scope
+ get(name: string): any {
+ // Check local variables first
+ if (this.variables.has(name)) {
+ return this.variables.get(name);
+ }
+
+ // Check default scope
+ if (name in this.defaultScope) {
+ return this.defaultScope[name];
+ }
+
+ // Check parent scope
+ if (this.options.parentScope) {
+ return this.options.parentScope.get(name);
+ }
+
+ // Check global scope as last resort
+ if (!this.options.isGlobal && ComponentScope.globalScope) {
+ return ComponentScope.globalScope.get(name);
+ }
+
+ return undefined;
+ }
+
+ // Set a value in scope
+ set(name: string, value: any): void {
+ this.variables.set(name, value);
+ }
+
+ // Remove a value from scope
+ delete(name: string): boolean {
+ return this.variables.delete(name);
+ }
+
+ // Check if scope has a variable
+ has(name: string): boolean {
+ return (
+ this.variables.has(name) ||
+ name in this.defaultScope ||
+ (this.options.parentScope?.has(name) ?? false) ||
+ (!this.options.isGlobal && (ComponentScope.globalScope?.has(name) ?? false))
+ );
+ }
+
+ // Add a child scope
+ private addChild(scope: ComponentScope): void {
+ this.children.add(scope);
+ }
+
+ // Remove a child scope
+ private removeChild(scope: ComponentScope): void {
+ this.children.delete(scope);
+ }
+
+ // Clear all variables in this scope
+ clear(): void {
+ this.variables.clear();
+ }
+
+ // Dispose of this scope
+ dispose(): void {
+ if (this.options.parentScope) {
+ this.options.parentScope.removeChild(this);
+ }
+ ComponentScope.instances.delete(this.id);
+ this.clear();
+
+ // Dispose of all children
+ this.children.forEach(child => child.dispose());
+ this.children.clear();
+ }
+
+ // Get all variables in this scope (including inherited)
+ getAllVariables(): Record {
+ const variables: Record = {
+ ...this.defaultScope,
+ ...Object.fromEntries(this.variables)
+ };
+
+ if (this.options.parentScope) {
+ return {
+ ...this.options.parentScope.getAllVariables(),
+ ...variables
+ };
+ }
+
+ return variables;
+ }
+
+ // Static methods for scope management
+ static getScope(id: string): ComponentScope | undefined {
+ return this.instances.get(id);
+ }
+
+ static createScope(id: string, options: ScopeOptions = {}): ComponentScope {
+ if (this.instances.has(id)) {
+ throw new Error(`Scope with id "${id}" already exists`);
+ }
+ return new ComponentScope(id, options);
+ }
+
+ static getOrCreateScope(id: string, options: ScopeOptions = {}): ComponentScope {
+ return this.instances.get(id) || new ComponentScope(id, options);
+ }
+
+ static disposeScope(id: string): void {
+ const scope = this.instances.get(id);
+ if (scope) {
+ scope.dispose();
+ }
+ }
+
+ // Create a hook for React components to access scope
+ static createScopeHook(scopeId: string) {
+ return function useScopeValue(name: string) {
+ const scope = ComponentScope.getScope(scopeId);
+ if (!scope) {
+ throw new Error(`Scope "${scopeId}" not found`);
+ }
+ return scope.get(name);
+ };
+ }
+}
+
+// Helper function to create a new component scope
+export function createComponentScope(
+ id: string,
+ app?: App,
+ parentScope?: ComponentScope
+): ComponentScope {
+ return new ComponentScope(id, { app, parentScope });
+}
+
+// React hook for accessing scope
+export function useComponentScope(scopeId: string) {
+ return React.useMemo(() => {
+ const scope = ComponentScope.getScope(scopeId);
+ if (!scope) {
+ throw new Error(`Scope "${scopeId}" not found`);
+ }
+ return scope;
+ }, [scopeId]);
+}
+
+// Example usage:
+/*
+// Create a global scope
+const globalScope = new ComponentScope('global', { isGlobal: true });
+globalScope.set('sharedValue', 42);
+
+// Create a component scope
+const componentScope = createComponentScope('component-1', app);
+componentScope.set('localValue', 'hello');
+
+// In a React component:
+function MyComponent() {
+ const scope = useComponentScope('component-1');
+ const localValue = scope.get('localValue');
+ const sharedValue = scope.get('sharedValue');
+
+ return (
+
+ Local: {localValue}, Shared: {sharedValue}
+
+ );
+}
+*/
\ No newline at end of file
diff --git a/src/core/storage.ts b/src/core/storage.ts
new file mode 100644
index 0000000..96c6bff
--- /dev/null
+++ b/src/core/storage.ts
@@ -0,0 +1,109 @@
+// src/core/storage.tsx
+import { MarketDataService, MarketData } from '../services/marketDataService';
+import { Plugin, TFile,parseYaml,stringifyYaml } from 'obsidian';
+export class StorageManager {
+ private plugin: Plugin;
+ private cache: Map;
+
+ constructor(plugin: Plugin) {
+ this.plugin = plugin;
+ this.cache = new Map();
+ }
+
+ private getCacheKey(noteFile: TFile, key: string): string {
+ return `${noteFile.path}:${key}`;
+ }
+
+ private async getFrontmatter(noteFile: TFile) {
+ const metadata = this.plugin.app.metadataCache.getFileCache(noteFile)?.frontmatter;
+ return metadata?.react_data || {};
+ }
+ async getMarketData(symbol: string, interval: string, range: string, noteFile: TFile): Promise {
+ const cacheKey = `market-data-${symbol}-${interval}-${range}`;
+
+ // Get from frontmatter
+ const frontmatter = await this.getFrontmatter(noteFile);
+ const cached = frontmatter[cacheKey];
+
+ // Check if we have cached data and if it's still fresh (24 hours)
+ if (cached && Date.now() - cached.timestamp < 24 * 60 * 60 * 1000) {
+ return cached.data;
+ }
+
+ // Fetch new data
+ const data = (await MarketDataService.fetchHistoricalData(symbol)).data;
+
+ // Cache the data using existing set method
+ await this.set(cacheKey, {
+ data,
+ timestamp: Date.now()
+ }, noteFile);
+
+ return data;
+ }
+ async get(key: string, defaultValue: T, noteFile: TFile): Promise {
+ const cacheKey = this.getCacheKey(noteFile, key);
+
+ // Check cache first
+ if (this.cache.has(cacheKey)) {
+ return this.cache.get(cacheKey);
+ }
+
+ // Get from frontmatter
+ const frontmatter = await this.getFrontmatter(noteFile);
+ const value = frontmatter[key] ?? defaultValue;
+
+ // Update cache
+ this.cache.set(cacheKey, value);
+ return value;
+ }
+
+ async set(key: string, value: T, noteFile: TFile): Promise {
+ const cacheKey = this.getCacheKey(noteFile, key);
+ this.cache.set(cacheKey, value);
+
+ const content = await this.plugin.app.vault.read(noteFile);
+ const frontmatter = await this.getFrontmatter(noteFile);
+
+ // Prepare new frontmatter
+ const newFrontmatter = {
+ ...frontmatter,
+ [key]: value
+ };
+
+ // Update the file with new frontmatter
+ const updatedContent = this.updateFrontmatter(content, newFrontmatter);
+ await this.plugin.app.vault.modify(noteFile, updatedContent);
+ }
+
+ private updateFrontmatter(content: string, newData: any): string {
+ const frontmatterRegex = /^---\n([\s\S]*?)\n---/;
+ const frontmatterMatch = content.match(frontmatterRegex);
+
+ if (frontmatterMatch) {
+ // Update existing frontmatter
+ let frontmatter;
+ try {
+ frontmatter = parseYaml(frontmatterMatch[1]);
+ } catch (e) {
+ frontmatter = {};
+ }
+
+ frontmatter.react_data = {
+ ...frontmatter.react_data,
+ ...newData
+ };
+
+ const newFrontmatter = stringifyYaml(frontmatter);
+ return content.replace(frontmatterRegex, `---\n${newFrontmatter}---`);
+ } else {
+ // Create new frontmatter
+ const newFrontmatter = stringifyYaml({ react_data: newData });
+ return `---\n${newFrontmatter}---\n\n${content}`;
+ }
+ }
+
+ clearCache() {
+ this.cache.clear();
+ }
+}
\ No newline at end of file
diff --git a/src/core/styles.ts b/src/core/styles.ts
new file mode 100644
index 0000000..392ceaa
--- /dev/null
+++ b/src/core/styles.ts
@@ -0,0 +1,80 @@
+// src/core/styles.ts
+export const componentStyles = {
+ // Base component styles
+ reactComponent: `
+ padding: 1rem;
+ border-radius: 0.5rem;
+ box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
+ `,
+
+ // Button styles
+ reactComponentButton: `
+ padding: 0.5rem 1rem;
+ color: var(--text-on-accent);
+ background-color: var(--interactive-accent);
+ border-radius: 0.25rem;
+
+ &:hover {
+ background-color: var(--interactive-accent-hover);
+ }
+ `,
+
+ // Chart-specific styles
+ chartContainer: (theme: 'dark' | 'light') => `
+ background: ${theme === 'dark' ? '#1e293b' : '#ffffff'};
+ color: ${theme === 'dark' ? '#94a3b8' : '#475569'};
+ border: 1px solid var(--background-modifier-border);
+ border-radius: 0.5rem;
+ min-height: 400px;
+ `,
+
+ // List styles
+ listContent: `
+ margin: 0;
+ padding-left: 1.5rem;
+ list-style-type: none;
+
+ li {
+ margin-bottom: 0.5rem;
+ color: var(--text-normal);
+ }
+ `,
+};
+
+// Common utility classes that don't need runtime processing
+export const utilityClasses = {
+ layout: {
+ 'w-full': 'width: 100%;',
+ 'grid': 'display: grid;',
+ 'grid-cols-2': 'grid-template-columns: repeat(2, minmax(0, 1fr));',
+ 'gap-4': 'gap: 1rem;',
+ },
+ spacing: {
+ 'mt-4': 'margin-top: 1rem;',
+ 'mb-2': 'margin-bottom: 0.5rem;',
+ 'p-4': 'padding: 1rem;',
+ },
+ colors: {
+ 'text-green-500': 'color: var(--color-green);',
+ 'text-red-500': 'color: var(--color-red);',
+ 'text-blue-500': 'color: var(--interactive-accent);',
+ }
+};
+
+// Theme-aware chart configuration
+export const getChartConfig = (theme: 'dark' | 'light') => ({
+ layout: {
+ background: {
+ color: theme === 'dark' ? '#1e293b' : '#ffffff'
+ },
+ textColor: theme === 'dark' ? '#94a3b8' : '#475569',
+ },
+ grid: {
+ vertLines: {
+ color: theme === 'dark' ? '#334155' : '#e2e8f0'
+ },
+ horzLines: {
+ color: theme === 'dark' ? '#334155' : '#e2e8f0'
+ },
+ }
+});
\ No newline at end of file
diff --git a/src/core/tailwind.ts b/src/core/tailwind.ts
new file mode 100644
index 0000000..6e36170
--- /dev/null
+++ b/src/core/tailwind.ts
@@ -0,0 +1,34 @@
+// src/core/tailwind.ts
+import postcss from 'postcss';
+import tailwindcss from 'tailwindcss';
+import autoprefixer from 'autoprefixer';
+
+export class TailwindProcessor {
+ private config: any;
+
+ constructor() {
+ this.config = {
+ content: ['./src/**/*.{ts,tsx}'],
+ theme: {
+ extend: {},
+ },
+ // Disable preflight to avoid conflicts with Obsidian
+ corePlugins: {
+ preflight: false
+ }
+ };
+ }
+
+ // Process Tailwind CSS
+ async process(css: string): Promise {
+ const result = await postcss([
+ tailwindcss(this.config),
+ autoprefixer
+ ]).process(css, {
+ from: undefined
+ });
+
+ return result.css;
+ }
+}
+
diff --git a/src/core/transformer.ts b/src/core/transformer.ts
new file mode 100644
index 0000000..c4d5fc4
--- /dev/null
+++ b/src/core/transformer.ts
@@ -0,0 +1,205 @@
+// src/core/transformer.ts
+import { transform as babelTransform } from '@babel/standalone';
+
+interface TransformOptions {
+ scope?: Record;
+ filename?: string;
+ isTypeScript?: boolean;
+ isInline?: boolean;
+}
+
+interface TransformResult {
+ code: string;
+ component: React.ComponentType;
+ error?: Error;
+}
+
+export class ComponentTransformer {
+ private static defaultScope = {
+ React: window.React,
+ useState: window.React.useState,
+ useEffect: window.React.useEffect,
+ useRef: window.React.useRef,
+ useMemo: window.React.useMemo,
+ useCallback: window.React.useCallback,
+ };
+
+ static async transform(code: string, options: TransformOptions = {}): Promise {
+ try {
+ // Prepare the code
+ const processedCode = this.preprocessCode(code, options);
+
+ // Transform the code using Babel
+ const transformed = await this.babelTransform(processedCode, options);
+
+ // Create the component
+ const component = await this.createComponent(transformed, options);
+
+ return {
+ code: transformed,
+ component
+ };
+ } catch (error) {
+ console.error('Transformation error:', error);
+ throw this.enhanceError(error);
+ }
+ }
+
+ private static preprocessCode(code: string, options: TransformOptions): string {
+ // Remove imports and exports first
+ code = code.replace(/import\s+.*?['"];?\s*$/gm, '');
+ code = code.replace(/import\s*{[^}]*}\s*from\s*['"][^'"]*['"];?\s*$/gm, '');
+ code = code.replace(/import\s*\([^)]*\);?\s*$/gm, '');
+ code = code.replace(/export\s+default\s+/, '');
+ code = code.replace(/export\s+const\s+/, 'const ');
+ code = code.replace(/export\s+function\s+/, 'function ');
+ code = code.replace(/export\s+class\s+/, 'class ');
+
+ // Handle any named component/function conversion to Component
+ const namedComponentMatch = code.match(/const\s+(\w+)\s*=\s*\(\)\s*=>/);
+ if (namedComponentMatch) {
+ code = code.replace(
+ `const ${namedComponentMatch[1]} = () =>`,
+ 'const Component = () =>'
+ );
+ } else if (!code.includes('const Component =') && !code.includes('function Component')) {
+ code = `const Component = () => ${code}`;
+ }
+
+ return `
+ try {
+ ${code}
+ } catch (error) {
+ console.error('Error in component code:', error);
+ throw error;
+ }
+ `;
+ }
+
+ private static async babelTransform(code: string, options: TransformOptions): Promise {
+ const transformed = babelTransform(code, {
+ presets: [
+ 'react',
+ ...(options.isTypeScript ? ['typescript'] : [])
+ ] as string[],
+ filename: options.filename || 'component.jsx',
+ sourceType: 'module',
+ configFile: false,
+ babelrc: false,
+ plugins: [
+ // Add any custom plugins here
+ this.createScopePlugin(options.scope)
+ ]
+ });
+
+ return transformed.code;
+ }
+
+ private static async createComponent(code: string, options: TransformOptions): Promise {
+ // Create the scope with defaults and custom additions
+ const scope = {
+ ...this.defaultScope,
+ ...options.scope
+ };
+
+ // Create the component function
+ const componentFn = new Function(
+ ...Object.keys(scope),
+ `
+ ${code}
+ return typeof Component !== 'undefined'
+ ? Component
+ : () => null;
+ `
+ );
+
+ try {
+ // Execute with scope
+ return componentFn(...Object.values(scope));
+ } catch (error) {
+ throw new Error(`Error creating component: ${error.message}`);
+ }
+ }
+
+ private static createScopePlugin(customScope: Record = {}) {
+ // Custom babel plugin to handle scope
+ return {
+ visitor: {
+ Identifier(path: any) {
+ const name = path.node.name;
+ if (
+ path.scope.hasBinding(name) ||
+ this.defaultScope.hasOwnProperty(name) ||
+ customScope.hasOwnProperty(name)
+ ) {
+ return;
+ }
+
+ // Replace unknown identifiers with scoped access
+ path.replaceWith(
+ path.scope.buildUndefinedNode()
+ );
+ }
+ }
+ };
+ }
+
+ private static getImports(): string {
+ return `
+ // Add any necessary imports here
+ const { useState, useEffect, useRef, useMemo, useCallback } = React;
+ `;
+ }
+
+ private static getExports(): string {
+ return `
+ if (typeof Component === 'undefined') {
+ throw new Error('No component defined');
+ }
+ `;
+ }
+
+ private static stripTypeAnnotations(code: string): string {
+ // Basic TypeScript stripping - in a real implementation,
+ // you might want to use a proper TS transformer
+ return code
+ .replace(/:\s*[A-Za-z<>[\]]+/g, '')
+ .replace(/<[A-Za-z,\s]+>/g, '');
+ }
+
+ private static enhanceError(error: Error): Error {
+ // Enhance error messages for better debugging
+ if (error.message.includes('Component')) {
+ return new Error(`Component Error: ${error.message}`);
+ }
+ if (error.message.includes('React')) {
+ return new Error(`React Error: ${error.message}`);
+ }
+ return error;
+ }
+
+ // Utility method for checking if code is TypeScript
+ static isTypeScript(code: string): boolean {
+ return /:\s*[A-Za-z]+/.test(code) || /<[A-Za-z,\s]+>/.test(code);
+ }
+}
+
+// Example usage:
+/*
+const code = `
+ const [count, setCount] = useState(0);
+ return (
+ setCount(c => c + 1)}>
+ Count: {count}
+
+ );
+`;
+
+const { component: Counter } = await ComponentTransformer.transform(code, {
+ scope: {
+ // Additional scope variables
+ customVar: 'value'
+ },
+ isInline: true
+});
+*/
\ No newline at end of file
diff --git a/src/core/useMarketData.tsx b/src/core/useMarketData.tsx
new file mode 100644
index 0000000..e085d33
--- /dev/null
+++ b/src/core/useMarketData.tsx
@@ -0,0 +1,98 @@
+// src/hooks/useMarketData.tsx
+import { useState, useEffect } from 'react';
+import { TFile } from 'obsidian';
+import { StorageManager } from '../core/storage';
+import { MarketDataService } from 'src/services/marketDataService';
+import { MarketData, MarketDataCache } from '../services/marketDataService';
+
+interface UseMarketDataResult {
+ data: MarketData[];
+ loading: boolean;
+ error: Error | null;
+}
+export function useMarketData(
+ symbol: string,
+ interval: string,
+ range: string,
+ storage: StorageManager,
+ noteFile: TFile
+) {
+ const [data, setData] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ const fetchData = async () => {
+ try {
+ setLoading(true);
+ const marketData = await storage.getMarketData(
+ symbol,
+ interval,
+ range,
+ noteFile
+ );
+ setData(marketData);
+ } catch (err) {
+ setError(err instanceof Error ? err : new Error('Unknown error'));
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ fetchData();
+ }, [symbol, interval, range, noteFile, storage]);
+
+ return { data, loading, error };
+}
+export function createMarketDataHook(storage: StorageManager, noteFile: TFile) {
+ return function useMarketData(
+ symbol: string,
+ interval: string,
+ range: string
+ ): UseMarketDataResult {
+ const [data, setData] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ const fetchData = async () => {
+ try {
+ setLoading(true);
+ const cacheKey = `market-data-${symbol}-${interval}-${range}`;
+
+ // Try to get from storage first
+ const cached = await storage.get(
+ cacheKey,
+ null,
+ noteFile
+ );
+
+ if (cached && Date.now() - cached.timestamp < 24 * 60 * 60 * 1000) {
+ setData(cached.data);
+ return;
+ }
+
+ // Fetch fresh data
+ const {data:freshData} = await MarketDataService.fetchHistoricalData(symbol);
+
+ // Cache the new data
+ await storage.set(
+ cacheKey,
+ { data: freshData, timestamp: Date.now() },
+ noteFile
+ );
+
+ setData(freshData);
+ } catch (err) {
+ setError(err instanceof Error ? err : new Error('Unknown error'));
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ fetchData();
+ }, [symbol, interval, range]);
+
+ return { data, loading, error };
+ };
+}
\ No newline at end of file
diff --git a/src/hooks/useStorage.ts b/src/hooks/useStorage.ts
new file mode 100644
index 0000000..81da85f
--- /dev/null
+++ b/src/hooks/useStorage.ts
@@ -0,0 +1,27 @@
+// src/hooks/useStorage.tsx
+import { useState, useEffect } from 'react';
+import { TFile } from 'obsidian';
+import { StorageManager } from '../core/storage';
+
+export function useStorage(
+ key: string,
+ defaultValue: T,
+ storage: StorageManager,
+ noteFile: TFile
+): [T, (value: T | ((prev: T) => T)) => Promise] {
+ const [value, setValue] = useState(defaultValue);
+
+ // Load initial value
+ useEffect(() => {
+ storage.get(key, defaultValue, noteFile).then(setValue);
+ }, [key, defaultValue, noteFile]);
+
+ // Update function
+ const updateValue = async (newValue: T | ((prev: T) => T)) => {
+ const actualNewValue = newValue instanceof Function ? newValue(value) : newValue;
+ setValue(actualNewValue);
+ await storage.set(key, actualNewValue, noteFile);
+ };
+
+ return [value, updateValue];
+}
\ No newline at end of file
diff --git a/src/lib/utils.ts b/src/lib/utils.ts
new file mode 100644
index 0000000..0b988ed
--- /dev/null
+++ b/src/lib/utils.ts
@@ -0,0 +1,7 @@
+//src/lib/util.ts
+import { type ClassValue, clsx } from "clsx"
+import { twMerge } from "tailwind-merge"
+
+export function cn(...inputs: ClassValue[]) {
+ return twMerge(clsx(inputs))
+}
\ No newline at end of file
diff --git a/src/services/OrderBlockAnalysis.ts b/src/services/OrderBlockAnalysis.ts
new file mode 100644
index 0000000..5904362
--- /dev/null
+++ b/src/services/OrderBlockAnalysis.ts
@@ -0,0 +1,793 @@
+// src/services/OrderBlockAnalysis.ts
+import { TFile } from 'obsidian';
+import { MarketDataService, MarketData } from './marketDataService';
+import { MarketDataStorage } from './marketDataStorage';
+
+interface SwingPoint {
+ time: number;
+ price: number;
+ type: 'high' | 'low';
+ index: number;
+}
+interface TrendLeg {
+ startIndex: number;
+ endIndex: number;
+ startTime: number;
+ endTime: number;
+ direction: 'up' | 'down' | 'sideways';
+ strength: number;
+ startPrice: number;
+ endPrice: number;
+ swingPoints: SwingPoint[];
+}
+interface OrderBlock {
+ id: string;
+ type: 'bullish' | 'bearish';
+ startTime: number;
+ endTime: number;
+ highPrice: number;
+ lowPrice: number;
+ volume: number;
+ impulseMagnitude: number;
+ priceValueGap: number;
+ validationMetrics: {
+ trendAlignment: boolean;
+ hasBreakOfStructure: boolean;
+ gapQuality: number; // 0-1 score
+ impulseStrength: number; // Relative to average movement
+ };
+}
+
+interface AnalysisResult {
+ symbol: string;
+ timeframe: string;
+ analysisTime: number;
+ marketHours: {
+ start: number;
+ end: number;
+ };
+ marketData: MarketData[]; // Add this
+ trendLegs: TrendLeg[]; // Add this
+ trend: {
+ direction: 'up' | 'down' | 'none';
+ strength: number;
+ swingPoints: SwingPoint[];
+ };
+ orderBlocks: OrderBlock[];
+}
+
+export class OrderBlockAnalysisService {
+ private static readonly MARKET_HOURS = {
+ start: { hour: 9, minute: 30 },
+ end: { hour: 16, minute: 0 }
+ };
+// Analysis specific params
+ private static readonly ANALYSIS_PARAMS = {
+ minSwingPoints: 4,
+ lookbackPeriods: 20,
+ minImpulseStrength: 1.5,
+ minGapSize: 0.1, // 10% of average candle size
+ trendStrengthThreshold: 0.6
+ };
+ private static readonly TREND_PARAMS = {
+ minSwingPoints: 2, // Reduced minimum swing points
+ trendThreshold: 0.4, // Lowered threshold
+ minMovementSize: 0.1, // Minimum % move
+ swingPointConfirmation: 1, // Candles to confirm swing
+ momentumThreshold: 0.6, // New: Momentum strength threshold
+ priceChangeThreshold: 0.001 // New: Minimum price change (0.1%)
+ };
+ constructor(
+ private storage: MarketDataStorage,
+ private marketDataService: MarketDataService
+ ) {}
+
+ /**
+ * Main analysis function for a given symbol and timeframe
+ */
+ async analyzeOrderBlocks(
+ symbol: string,
+ timeframe: string,
+ noteFile: TFile
+ ): Promise {
+ try{
+ const today = new Date();
+ const startTime = new Date(
+ today.getFullYear(),
+ today.getMonth(),
+ today.getDate()-1,
+ OrderBlockAnalysisService.MARKET_HOURS.start.hour,
+ OrderBlockAnalysisService.MARKET_HOURS.start.minute
+ ).getTime();
+
+ const endTime = new Date(
+ today.getFullYear(),
+ today.getMonth(),
+ today.getDate()-1,
+ OrderBlockAnalysisService.MARKET_HOURS.end.hour,
+ OrderBlockAnalysisService.MARKET_HOURS.end.minute
+ ).getTime();
+
+ const config = {
+ interval: timeframe as any,
+ startTime,
+ endTime
+ };
+
+ // Use the marketDataService instance for fetching
+ const data = await MarketDataService.getMarketData(symbol, config, this.storage);
+
+ // Apply market hours filter
+ const marketHoursData = this.filterMarketHours(data);
+
+ const trend = this.analyzeTrend(marketHoursData);
+ const orderBlocks = this.findOrderBlocks(marketHoursData, trend);
+
+ return {
+ symbol,
+ timeframe,
+ analysisTime: Date.now(),
+ marketHours: {
+ start: startTime,
+ end: endTime
+ },
+ marketData: marketHoursData,
+ trendLegs: this.analyzeTrendLegs(marketHoursData),
+ trend,
+ orderBlocks
+ };
+ } catch (error) {
+ console.error('Error analyzing order blocks:', error);
+ throw error;
+ }
+ }
+
+ /**
+ * Filter data for market hours only
+ */
+ private filterMarketHours(data: MarketData[]): MarketData[] {
+ return data.filter(candle => {
+ const date = new Date(candle.time);
+ const hours = date.getHours();
+ const minutes = date.getMinutes();
+
+ if (hours < OrderBlockAnalysisService.MARKET_HOURS.start.hour ||
+ hours > OrderBlockAnalysisService.MARKET_HOURS.end.hour) return false;
+
+ if (hours === OrderBlockAnalysisService.MARKET_HOURS.start.hour &&
+ minutes < OrderBlockAnalysisService.MARKET_HOURS.start.minute) return false;
+
+ if (hours === OrderBlockAnalysisService.MARKET_HOURS.end.hour &&
+ minutes >= OrderBlockAnalysisService.MARKET_HOURS.end.minute) return false;
+
+ return true;
+ });
+ }
+
+/**
+ * Enhanced trend analysis that considers both structure and momentum
+ */
+private analyzeTrend(data: MarketData[]): {
+ direction: 'up' | 'down' | 'none';
+ strength: number;
+ swingPoints: SwingPoint[];
+} {
+ if (data.length < 10) return { direction: 'none', strength: 0, swingPoints: [] };
+
+ const atr = this.calculateATR(data, 14);
+ const swingPoints = this.findSignificantSwings(data, atr);
+
+ // Calculate overall momentum
+ const momentum = this.calculateMomentum(data);
+
+ // Calculate price movement
+ const priceChange = (data[data.length - 1].close - data[0].close) / data[0].close;
+ const absolutePriceChange = Math.abs(priceChange);
+
+ // Only proceed with detailed analysis if we have significant price movement
+ if (absolutePriceChange < OrderBlockAnalysisService.TREND_PARAMS.priceChangeThreshold) {
+ return { direction: 'none', strength: 0, swingPoints };
+ }
+
+ // Get structural analysis
+ const structure = this.analyzeTrendStructure(swingPoints, atr);
+
+ // Combine structural and momentum analysis
+ const direction = this.determineOverallTrend(structure, momentum, priceChange);
+ const strength = this.calculateOverallStrength(structure.strength, momentum.strength);
+
+ return {
+ direction,
+ strength,
+ swingPoints
+ };
+}
+
+ /**
+ * Calculate Average True Range
+ */
+private calculateATR(data: MarketData[], period: number): number {
+ if (data.length < period) return 0;
+
+ let tr = [];
+ for (let i = 1; i < data.length; i++) {
+ const high = data[i].high;
+ const low = data[i].low;
+ const prevClose = data[i-1].close;
+
+ tr.push(Math.max(
+ high - low,
+ Math.abs(high - prevClose),
+ Math.abs(low - prevClose)
+ ));
+ }
+
+ // Calculate simple moving average of TR
+ const atr = tr.slice(-period).reduce((sum, val) => sum + val, 0) / period;
+ return atr;
+}
+/**
+ * Calculate price momentum
+ */
+private calculateMomentum(data: MarketData[]): { direction: 'up' | 'down'; strength: number } {
+ const closes = data.map(d => d.close);
+ let upMoves = 0;
+ let downMoves = 0;
+
+ // Count consecutive moves
+ for (let i = 1; i < closes.length; i++) {
+ if (closes[i] > closes[i - 1]) upMoves++;
+ if (closes[i] < closes[i - 1]) downMoves++;
+ }
+
+ const totalMoves = upMoves + downMoves;
+ const upStrength = upMoves / totalMoves;
+ const downStrength = downMoves / totalMoves;
+
+ return {
+ direction: upStrength > downStrength ? 'up' : 'down',
+ strength: Math.max(upStrength, downStrength)
+ };
+}
+
+/**
+ * Determine overall trend combining structure and momentum
+ */
+private determineOverallTrend(
+ structure: { direction: 'up' | 'down' | 'none'; strength: number },
+ momentum: { direction: 'up' | 'down'; strength: number },
+ priceChange: number
+): 'up' | 'down' | 'none' {
+ // Strong momentum overrides structure
+ if (momentum.strength > OrderBlockAnalysisService.TREND_PARAMS.momentumThreshold) {
+ return momentum.direction;
+ }
+
+ // Strong structure with confirming price change
+ if (structure.direction !== 'none' &&
+ Math.sign(priceChange) === (structure.direction === 'up' ? 1 : -1)) {
+ return structure.direction;
+ }
+
+ // Default to momentum direction if price change confirms it
+ if (Math.sign(priceChange) === (momentum.direction === 'up' ? 1 : -1)) {
+ return momentum.direction;
+ }
+
+ return 'none';
+}
+
+/**
+ * Calculate overall trend strength
+ */
+private calculateOverallStrength(structureStrength: number, momentumStrength: number): number {
+ return (structureStrength * 0.6 + momentumStrength * 0.4);
+}
+/**
+ * Find significant swing points using ATR for context
+ */
+private findSignificantSwings(data: MarketData[], atr: number): SwingPoint[] {
+ const swingPoints: SwingPoint[] = [];
+ const minMove = atr * 0.3; // Reduced from 0.5 to catch more potential swings
+
+ for (let i = 2; i < data.length - 2; i++) {
+ const current = data[i];
+ const before = data.slice(i - 2, i);
+ const after = data.slice(i + 1, i + 3);
+
+ // Check for swing high with relaxed conditions
+ if (before.every(c => c.high <= current.high) &&
+ after[0].high < current.high) {
+ swingPoints.push({
+ type: 'high',
+ price: current.high,
+ time: current.time,
+ index: i
+ });
+ }
+
+ // Check for swing low with relaxed conditions
+ if (before.every(c => c.low >= current.low) &&
+ after[0].low > current.low) {
+ swingPoints.push({
+ type: 'low',
+ price: current.low,
+ time: current.time,
+ index: i
+ });
+ }
+ }
+
+ return swingPoints;
+}
+
+/**
+ * Analyze trend structure using swing points
+ */
+private analyzeTrendStructure(
+ swingPoints: SwingPoint[],
+ atr: number
+): { direction: 'up' | 'down' | 'none'; strength: number; } {
+ const highs = swingPoints.filter(p => p.type === 'high')
+ .sort((a, b) => a.time - b.time);
+ const lows = swingPoints.filter(p => p.type === 'low')
+ .sort((a, b) => a.time - b.time);
+
+ if (highs.length < 2 || lows.length < 2) {
+ return { direction: 'none', strength: 0 };
+ }
+
+ // Calculate trend metrics
+ const hhSequence = this.calculateSequenceStrength(highs, 'up', atr);
+ const lhSequence = this.calculateSequenceStrength(highs, 'down', atr);
+ const hlSequence = this.calculateSequenceStrength(lows, 'up', atr);
+ const llSequence = this.calculateSequenceStrength(lows, 'down', atr);
+
+ // Determine trend
+ const upStrength = (hhSequence + hlSequence) / 2;
+ const downStrength = (lhSequence + llSequence) / 2;
+
+ if (upStrength > OrderBlockAnalysisService.TREND_PARAMS.trendThreshold &&
+ upStrength > downStrength) {
+ return {
+ direction: 'up',
+ strength: upStrength
+ };
+ }
+
+ if (downStrength > OrderBlockAnalysisService.TREND_PARAMS.trendThreshold &&
+ downStrength > upStrength) {
+ return {
+ direction: 'down',
+ strength: downStrength
+ };
+ }
+
+ return { direction: 'none', strength: 0 };
+}
+private analyzeTrendLegs(data: MarketData[]): TrendLeg[] {
+ const trendLegs: TrendLeg[] = [];
+ const atr = this.calculateATR(data, 14);
+ let currentLegStart = 0;
+
+ // Minimum number of candles to consider a valid trend leg
+ const MIN_LEG_LENGTH = 5;
+
+ // Loop through data to identify trend changes
+ for (let i = MIN_LEG_LENGTH; i < data.length - MIN_LEG_LENGTH; i++) {
+ const currentSegment = data.slice(currentLegStart, i + 1);
+ const nextSegment = data.slice(i - MIN_LEG_LENGTH, i + MIN_LEG_LENGTH);
+
+ // Check for trend change
+ if (this.isTrendChange(currentSegment, nextSegment, atr)) {
+ // Add completed trend leg
+ if (i - currentLegStart >= MIN_LEG_LENGTH) {
+ const legData = data.slice(currentLegStart, i);
+ const trendLeg = this.analyzeSingleTrendLeg(legData, currentLegStart, i);
+ trendLegs.push(trendLeg);
+ }
+ currentLegStart = i;
+ }
+ }
+
+ // Add final trend leg
+ if (data.length - currentLegStart >= MIN_LEG_LENGTH) {
+ const finalLegData = data.slice(currentLegStart);
+ const finalTrendLeg = this.analyzeSingleTrendLeg(
+ finalLegData,
+ currentLegStart,
+ data.length - 1
+ );
+ trendLegs.push(finalTrendLeg);
+ }
+
+ return trendLegs;
+}
+
+private isTrendChange(
+ currentSegment: MarketData[],
+ nextSegment: MarketData[],
+ atr: number
+): boolean {
+ const currentDirection = this.determineTrendDirection(currentSegment);
+ const nextDirection = this.determineTrendDirection(nextSegment);
+
+ // Check for direction change
+ if (currentDirection !== nextDirection) {
+ // Verify change is significant (> 1 ATR)
+ const priceChange = Math.abs(
+ nextSegment[nextSegment.length - 1].close - nextSegment[0].close
+ );
+ return priceChange > atr;
+ }
+
+ return false;
+}
+
+private analyzeSingleTrendLeg(
+ data: MarketData[],
+ startIndex: number,
+ endIndex: number
+): TrendLeg {
+ const swingPoints = this.findSignificantSwings(data, this.calculateATR(data, 14));
+ const priceChange = (data[data.length - 1].close - data[0].close) / data[0].close;
+ const momentum = this.calculateMomentum(data);
+
+ // Determine trend direction
+ let direction: 'up' | 'down' | 'sideways';
+ if (Math.abs(priceChange) < OrderBlockAnalysisService.TREND_PARAMS.priceChangeThreshold) {
+ direction = 'sideways';
+ } else {
+ direction = priceChange > 0 ? 'up' : 'down';
+ }
+
+ // Calculate trend strength based on:
+ // 1. Price change magnitude
+ // 2. Momentum consistency
+ // 3. Swing point alignment
+ const priceStrength = Math.min(Math.abs(priceChange) * 10, 1); // Scale price change
+ const momentumStrength = momentum.strength;
+ const swingStrength = this.calculateSwingAlignment(swingPoints, direction);
+
+ const strength = (
+ priceStrength * 0.4 +
+ momentumStrength * 0.4 +
+ swingStrength * 0.2
+ ) * 100; // Convert to percentage
+
+ return {
+ startIndex,
+ endIndex,
+ startTime: data[0].time,
+ endTime: data[data.length - 1].time,
+ direction,
+ strength,
+ startPrice: data[0].close,
+ endPrice: data[data.length - 1].close,
+ swingPoints
+ };
+}
+
+private calculateSwingAlignment(
+ swingPoints: SwingPoint[],
+ direction: 'up' | 'down' | 'sideways'
+): number {
+ if (direction === 'sideways' || swingPoints.length < 2) return 0;
+
+ let aligned = 0;
+ let total = 0;
+
+ for (let i = 1; i < swingPoints.length; i++) {
+ if (direction === 'up') {
+ if (swingPoints[i].price > swingPoints[i - 1].price) aligned++;
+ } else {
+ if (swingPoints[i].price < swingPoints[i - 1].price) aligned++;
+ }
+ total++;
+ }
+
+ return total > 0 ? aligned / total : 0;
+}
+
+private determineTrendDirection(data: MarketData[]): 'up' | 'down' | 'sideways' {
+ const priceChange = (data[data.length - 1].close - data[0].close) / data[0].close;
+
+ if (Math.abs(priceChange) < OrderBlockAnalysisService.TREND_PARAMS.priceChangeThreshold) {
+ return 'sideways';
+ }
+ return priceChange > 0 ? 'up' : 'down';
+}
+/**
+ * Calculate sequence strength relative to ATR
+ */
+private calculateSequenceStrength(
+ points: SwingPoint[],
+ direction: 'up' | 'down',
+ atr: number
+): number {
+ if (points.length < 2) return 0;
+
+ let validMoves = 0;
+ let totalMoves = 0;
+
+ for (let i = 1; i < points.length; i++) {
+ const move = direction === 'up'
+ ? points[i].price - points[i-1].price
+ : points[i-1].price - points[i].price;
+
+ if (move > 0 && Math.abs(move) > atr * 0.5) {
+ validMoves++;
+ }
+ totalMoves++;
+ }
+
+ return totalMoves > 0 ? validMoves / totalMoves : 0;
+}
+
+ /**
+ * Calculate trend strength (0-1)
+ */
+ private calculateTrendStrength(
+ points: SwingPoint[],
+ direction: 'up' | 'down'
+ ): number {
+ if (points.length < 2) return 0;
+
+ let increasing = 0;
+ let total = 0;
+
+ for (let i = 1; i < points.length; i++) {
+ const current = points[i].price;
+ const previous = points[i - 1].price;
+
+ if (direction === 'up' && current > previous) increasing++;
+ if (direction === 'down' && current < previous) increasing++;
+ total++;
+ }
+
+ return total > 0 ? increasing / total : 0;
+ }
+ /**
+ * Find order blocks
+ */
+ private findOrderBlocks(
+ data: MarketData[],
+ trend: { direction: 'up' | 'down' | 'none'; strength: number; }
+ ): OrderBlock[] {
+ const orderBlocks: OrderBlock[] = [];
+
+ // Only proceed if we have a clear trend
+ if (trend.direction === 'none' || trend.strength < OrderBlockAnalysisService.ANALYSIS_PARAMS.trendStrengthThreshold) {
+ return orderBlocks;
+ }
+
+ // Use a sliding window of 7 candles (3 before, current, 3 after)
+ for (let i = 3; i < data.length - 3; i++) {
+ const window = {
+ before: data.slice(i - 3, i),
+ current: data[i],
+ after: data.slice(i + 1, i + 4)
+ };
+
+ // Check for potential order block
+ const orderBlock = this.validateOrderBlock(window, trend.direction);
+ if (orderBlock) {
+ orderBlocks.push(orderBlock);
+ }
+ }
+
+ return this.filterOverlappingBlocks(orderBlocks);
+ }
+
+ /**
+ * Validate potential order block
+ */
+ private validateOrderBlock(
+ window: {
+ before: MarketData[];
+ current: MarketData;
+ after: MarketData[];
+ },
+ trendDirection: 'up' | 'down'
+ ): OrderBlock | null {
+ const { before, current, after } = window;
+
+ // Check for bullish order block in uptrend
+ if (trendDirection === 'up') {
+ const isBearishCandle = current.close < current.open;
+ const hasImpulsiveMove = this.hasImpulsiveMove(after, 'up');
+ const pvg = this.calculatePriceValueGap([...before, current, ...after]);
+
+ if (isBearishCandle && hasImpulsiveMove && pvg > OrderBlockAnalysisService.ANALYSIS_PARAMS.minGapSize) {
+ return {
+ id: `OB_${current.time}`,
+ type: 'bullish',
+ startTime: current.time,
+ endTime: after[0].time,
+ highPrice: current.high,
+ lowPrice: current.low,
+ volume: current.volume,
+ impulseMagnitude: this.calculateImpulseMagnitude([...before, current, ...after]),
+ priceValueGap: pvg,
+ validationMetrics: {
+ trendAlignment: true,
+ hasBreakOfStructure: this.hasBreakOfStructure([...before, current, ...after], 'up'),
+ gapQuality: this.calculateGapQuality(pvg, current),
+ impulseStrength: this.calculateImpulseStrength(after, before)
+ }
+ };
+ }
+ }
+
+ // Check for bearish order block in downtrend
+ if (trendDirection === 'down') {
+ const isBullishCandle = current.close > current.open;
+ const hasImpulsiveMove = this.hasImpulsiveMove(after, 'down');
+ const pvg = this.calculatePriceValueGap([...before, current, ...after]);
+
+ if (isBullishCandle && hasImpulsiveMove && pvg > OrderBlockAnalysisService.ANALYSIS_PARAMS.minGapSize) {
+ return {
+ id: `OB_${current.time}`,
+ type: 'bearish',
+ startTime: current.time,
+ endTime: after[0].time,
+ highPrice: current.high,
+ lowPrice: current.low,
+ volume: current.volume,
+ impulseMagnitude: this.calculateImpulseMagnitude([...before, current, ...after]),
+ priceValueGap: pvg,
+ validationMetrics: {
+ trendAlignment: true,
+ hasBreakOfStructure: this.hasBreakOfStructure([...before, current, ...after], 'down'),
+ gapQuality: this.calculateGapQuality(pvg, current),
+ impulseStrength: this.calculateImpulseStrength(after, before)
+ }
+ };
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Calculate price value gap
+ */
+ private calculatePriceValueGap(candles: MarketData[]): number {
+ let maxGap = 0;
+
+ for (let i = 1; i < candles.length - 1; i++) {
+ const current = candles[i];
+ const next = candles[i + 1];
+
+ // Check for gap between candles
+ if (next.low > current.high) {
+ maxGap = Math.max(maxGap, next.low - current.high);
+ }
+ if (next.high < current.low) {
+ maxGap = Math.max(maxGap, current.low - next.high);
+ }
+ }
+
+ return maxGap;
+ }
+
+ /**
+ * Check for impulsive move
+ */
+ private hasImpulsiveMove(candles: MarketData[], direction: 'up' | 'down'): boolean {
+ const moves = candles.map(c => Math.abs(c.close - c.open));
+ const avgMove = moves.reduce((sum, move) => sum + move, 0) / moves.length;
+
+ if (direction === 'up') {
+ return candles[0].close > candles[0].open &&
+ avgMove > OrderBlockAnalysisService.ANALYSIS_PARAMS.minImpulseStrength;
+ } else {
+ return candles[0].close < candles[0].open &&
+ avgMove > OrderBlockAnalysisService.ANALYSIS_PARAMS.minImpulseStrength;
+ }
+ }
+
+ /**
+ * Calculate impulse magnitude
+ */
+ private calculateImpulseMagnitude(candles: MarketData[]): number {
+ const moves = candles.map(c => ({
+ move: Math.abs(c.close - c.open),
+ volume: c.volume
+ }));
+
+ // Volume-weighted average move
+ const weightedMoves = moves.map(m => m.move * (m.volume / Math.max(...moves.map(x => x.volume))));
+ return weightedMoves.reduce((sum, move) => sum + move, 0) / weightedMoves.length;
+ }
+
+ /**
+ * Calculate gap quality (0-1)
+ */
+ private calculateGapQuality(gap: number, candle: MarketData): number {
+ const candleSize = Math.abs(candle.high - candle.low);
+ return Math.min(gap / candleSize, 1);
+ }
+
+ /**
+ * Calculate impulse strength
+ */
+ private calculateImpulseStrength(after: MarketData[], before: MarketData[]): number {
+ const afterMoves = after.map(c => Math.abs(c.close - c.open));
+ const beforeMoves = before.map(c => Math.abs(c.close - c.open));
+
+ const avgAfter = afterMoves.reduce((sum, move) => sum + move, 0) / afterMoves.length;
+ const avgBefore = beforeMoves.reduce((sum, move) => sum + move, 0) / beforeMoves.length;
+
+ return avgAfter / avgBefore;
+ }
+
+ /**
+ * Check for break of structure
+ */
+ private hasBreakOfStructure(candles: MarketData[], direction: 'up' | 'down'): boolean {
+ const middle = Math.floor(candles.length / 2);
+ const before = candles.slice(0, middle);
+ const after = candles.slice(middle);
+
+ if (direction === 'up') {
+ const beforeHigh = Math.max(...before.map(c => c.high));
+ const afterHigh = Math.max(...after.map(c => c.high));
+ return afterHigh > beforeHigh;
+ } else {
+ const beforeLow = Math.min(...before.map(c => c.low));
+ const afterLow = Math.min(...after.map(c => c.low));
+ return afterLow < beforeLow;
+ }
+ }
+
+ /**
+ * Filter overlapping order blocks
+ */
+ private filterOverlappingBlocks(blocks: OrderBlock[]): OrderBlock[] {
+ return blocks.filter((block, index) => {
+ // Check if this block overlaps with any stronger blocks
+ const hasStrongerOverlap = blocks.some((otherBlock, otherIndex) => {
+ if (index === otherIndex) return false;
+
+ const timeOverlap = block.startTime <= otherBlock.endTime &&
+ block.endTime >= otherBlock.startTime;
+
+ const priceOverlap = block.lowPrice <= otherBlock.highPrice &&
+ block.highPrice >= otherBlock.lowPrice;
+
+ return timeOverlap && priceOverlap &&
+ otherBlock.validationMetrics.impulseStrength >
+ block.validationMetrics.impulseStrength;
+ });
+
+ return !hasStrongerOverlap;
+ });
+ }
+
+ private getTodayMarketOpen(): number {
+ const now = new Date();
+ return new Date(
+ now.getFullYear(),
+ now.getMonth(),
+ now.getDate(),
+ OrderBlockAnalysisService.MARKET_HOURS.start.hour,
+ OrderBlockAnalysisService.MARKET_HOURS.start.minute
+ ).getTime();
+ }
+
+ private getTodayMarketClose(): number {
+ const now = new Date();
+ return new Date(
+ now.getFullYear(),
+ now.getMonth(),
+ now.getDate(),
+ OrderBlockAnalysisService.MARKET_HOURS.end.hour,
+ OrderBlockAnalysisService.MARKET_HOURS.end.minute
+ ).getTime();
+ }
+
+
+}
+
+export type { AnalysisResult, OrderBlock, SwingPoint };
\ No newline at end of file
diff --git a/src/services/marketDataService.ts b/src/services/marketDataService.ts
new file mode 100644
index 0000000..06c0a5f
--- /dev/null
+++ b/src/services/marketDataService.ts
@@ -0,0 +1,459 @@
+// src/services/marketDataService.ts
+import { error, time } from "console";
+import { MarketDataStorage } from "./marketDataStorage";
+import { TFile } from "obsidian";
+import dotenv from 'dotenv';
+// Initialize dotenv
+dotenv.config();
+
+// Create a config object to manage environment variables
+const config = {
+ primaryApiKey: process.env.ALPHA_VANTAGE_PRIMARY_KEY,
+ secondaryApiKey: process.env.ALPHA_VANTAGE_SECONDARY_KEY,
+ cacheDuration: parseInt(process.env.MARKET_DATA_CACHE_DURATION || '86400000'),
+ timezone: process.env.TIMEZONE || 'US/Eastern',
+
+ // Validate environment variables
+ validate() {
+ if (!this.primaryApiKey) {
+ throw new Error('ALPHA_VANTAGE_PRIMARY_KEY is not set in environment variables');
+ }
+ if (!this.secondaryApiKey) {
+ throw new Error('ALPHA_VANTAGE_SECONDARY_KEY is not set in environment variables');
+ }
+ }
+};
+
+
+export interface MarketData {
+ time: number;
+ open: number;
+ high: number;
+ low: number;
+ close: number;
+ volume: number;
+ sma?: number; // Simple Moving Average
+ ema?: number; // Exponential Moving Average
+ rsi?: number; // Relative Strength Index
+}
+export interface MarketDataCache {
+ data: MarketData[];
+ timestamp: number;
+}
+export interface MarketHours {
+ start: number; // 4:00 AM ET
+ end: number; // 19:59 PM ET
+ timeZone: string; // 'America/New_York'
+}
+export type IntervalType = '1min' | '5min' | '15min' | '30min' | '60min' | 'daily';
+
+export interface TimeframeConfig {
+ interval: IntervalType;
+ startTime: number;
+ endTime: number;
+}
+
+export interface CacheEntry {
+ data: MarketData[];
+ timestamp: number;
+ interval: IntervalType;
+ startTime: number;
+ endTime: number;
+ timezone:string;
+}
+
+export interface CacheMetadata {
+ [symbol: string]: {
+ [interval in IntervalType]?: CacheEntry[];
+ };
+}
+export class MarketDataService {
+ static async fetchHistoricalData(
+ symbol: string,
+ outputsize: 'full' | 'compact' = 'full'
+ ): Promise<{data:MarketData[],timezone: string}> {
+ // Validate environment variables
+ config.validate();
+
+ const url = `https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=${symbol}&outputsize=${outputsize}&apikey=${config.primaryApiKey}`;
+
+ try {
+ const response = await fetch(url);
+ const data = await response.json();
+
+ // Check for API errors
+ if (data['Error Message']) {
+ throw new Error(data['Error Message']);
+ }
+
+ const timezone = data['Meta Data']['6. Time Zone'];
+ const timeSeries = data['Time Series (Daily)'];
+
+ const marketData= Object.entries(timeSeries).map(([date, values]: [string, any]) => ({
+ time: new Date(date).getTime(),
+ open: parseFloat(values['1. open']),
+ high: parseFloat(values['2. high']),
+ low: parseFloat(values['3. low']),
+ close: parseFloat(values['4. close']),
+ volume: parseInt(values['5. volume'])
+ })).reverse();
+ return{data:marketData,timezone}
+ } catch (error) {
+ console.error('Error fetching historical data:', error);
+ throw error;
+ }
+ }
+
+ static async fetchIntraday(
+ symbol: string,
+ interval: '1min' | '5min' | '15min' | '30min' | '60min' = '5min'
+ ): Promise<{data: MarketData[], timezone: string }> {
+ // Validate environment variables
+ config.validate();
+
+ const url = `https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=${symbol}&interval=${interval}&outputsize=full&apikey=${config.secondaryApiKey}`;
+
+ try {
+ const response = await fetch(url);
+ const data = await response.json();
+
+ // Check for rate limit message
+ /* if (data.Information && data.Information.includes('rate limit')) {
+ throw new Error('API rate limit reached. Please try again in a minute.');
+ }*/
+ // Log full response to see structure
+ console.log('Alpha Vantage Response:', data);
+
+ // Method 1: Log all top-level keys
+ console.log('Top level keys:', Object.keys(data));
+ const timezone = data['Meta Data']['5. Time Zone'];
+ const timeSeriesKey = `Time Series (${interval})`;
+ const timeSeries = data[timeSeriesKey];
+
+ if (!timeSeries) {
+ throw new Error('No data returned from API. You may have exceeded the daily limit.');
+ }
+
+ const marketData= Object.entries(timeSeries).map(([date, values]: [string, any]) => ({
+ time: new Date(date).getTime(),
+ open: parseFloat(values['1. open']),
+ high: parseFloat(values['2. high']),
+ low: parseFloat(values['3. low']),
+ close: parseFloat(values['4. close']),
+ volume: parseInt(values['5. volume'])
+ })).reverse();
+
+ return { data: marketData, timezone}
+ } catch (error) {
+ console.error('Error fetching intraday data:', error);
+ throw error;
+ //For when we want to hide implementation details
+ //throw new Error('Unable to fetch intraday data. Please try again later.');
+ }
+ }
+ static readonly MARKET_HOURS: MarketHours = {
+ start: 4 * 60, // 4:00 AM in minutes
+ end: 20 * 60 - 1, // 19:59 PM in minutes
+ timeZone: config.timezone
+ };
+
+ // Add method for getting multiple timeframes in one call
+ static async fetchMultiTimeframe(
+ symbol: string,
+ timeframes: Array<'1min' | '5min' | '15min' | '30min' | '60min' | 'daily'>
+ ): Promise> {
+ try {
+ const results: Record = {};
+
+ await Promise.all(
+ timeframes.map(async (timeframe) => {
+ if (timeframe === 'daily') {
+ results[timeframe] = (await this.fetchHistoricalData(symbol)).data;
+ } else {
+ data:results[timeframe] = (await this.fetchIntraday(symbol, timeframe)).data;
+ }
+ })
+ );
+
+ return results;
+ } catch (error) {
+ console.error('Error fetching multiple timeframes:', error);
+ throw error;
+ }
+ }
+ private static INTERVALS_MINUTES = {
+ '1min': 1,
+ '5min': 5,
+ '15min': 15,
+ '30min': 30,
+ '60min': 60,
+ 'daily': 1440
+ };
+
+
+
+
+ private static adjustTimeEndRequest(timestamp: number): number {
+ const date = new Date(timestamp);
+ const day = date.getDay(); // 0 = Sunday, 6 = Saturday
+ const hours = date.getHours();
+ const minutes = date.getMinutes();
+
+ // If weekend, adjust to Friday
+ if (day === 1&&hours<9) {date.setDate(date.getDate() - 3);date.setHours(19, 59, 0, 0);} // Monday -> Friday
+ if (day === 0) {date.setDate(date.getDate() - 2); date.setHours(19, 59, 0, 0);} // Sunday -> Friday
+ if (day === 6) {date.setDate(date.getDate() - 1);date.setHours(19, 59, 0, 0);} // Saturday -> Friday
+
+ // Set to 16:00 (4 PM) ET if after market close
+ if (hours > 19|| hours<4 ) {
+ date.setHours(19, 59, 0, 0);
+ date.setDate(date.getDate() - hours<4?1:0);
+ }
+ return date.getTime();
+ }
+ private static doesCacheCover(cache: CacheEntry, request: TimeframeConfig): boolean {
+
+ // If cache's last data point is within 24 hours, consider it current
+ const adjustedEndTime = this.adjustTimeEndRequest(
+ cache.endTime +24*60*60*1000>= request.endTime ? cache.endTime : request.endTime
+ );
+ console.log('Request Time:', {
+
+ Time: new Date(adjustedEndTime).toLocaleString()
+ });
+ return cache.interval === request.interval &&
+ cache.startTime <= request.startTime &&
+ cache.endTime >= adjustedEndTime;
+ }
+ private static aggregateToHigherTimeframe(
+ data: MarketData[],
+ fromInterval: IntervalType,
+ toInterval: IntervalType
+ ): MarketData[] {
+ const fromMinutes = this.INTERVALS_MINUTES[fromInterval];
+ const toMinutes = this.INTERVALS_MINUTES[toInterval];
+ const barsPerPeriod = toMinutes / fromMinutes;
+
+ // Group data into higher timeframe periods
+ const groupedData: { [key: number]: MarketData[] } = {};
+ data.forEach(bar => {
+ const periodStart = Math.floor(bar.time / (toMinutes * 60 * 1000)) * (toMinutes * 60 * 1000);
+ if (!groupedData[periodStart]) {
+ groupedData[periodStart] = [];
+ }
+ groupedData[periodStart].push(bar);
+ });
+
+ // Aggregate each period
+ return Object.entries(groupedData)
+ .filter(([_, bars]) => bars.length >= barsPerPeriod * 0.7) // Require at least 70% of bars
+ .map(([time, bars]) => ({
+ time: parseInt(time),
+ open: bars[0].open,
+ high: Math.max(...bars.map(b => b.high)),
+ low: Math.min(...bars.map(b => b.low)),
+ close: bars[bars.length - 1].close,
+ volume: bars.reduce((sum, b) => sum + b.volume, 0)
+ }));
+ }
+
+ static addMarketTime(time: number, minutesToAdd: number): number {
+ let date = new Date(time);
+ let currentMinutes = date.getHours() * 60 + date.getMinutes();
+ let newMinutes = currentMinutes + minutesToAdd;
+
+ // If would exceed market close
+ if (newMinutes > this.MARKET_HOURS.end) {
+ // Move to next day at market open
+ date.setDate(date.getDate() + 1);
+ date.setHours(this.MARKET_HOURS.start/60, 0, 0, 0);
+
+ // If weekend, move to Monday
+ while (date.getDay() === 0 || date.getDay() === 6) {
+ date.setDate(date.getDate() + 1);
+ }
+ } else {
+ // Stay on same day, just update time
+ date.setHours(Math.floor(newMinutes / 60), newMinutes % 60, 0, 0);
+ }
+
+ return date.getTime();
+ }
+ static async getMarketData(
+ symbol: string,
+ config: TimeframeConfig,
+ storage: MarketDataStorage
+ ): Promise {
+ console.log('Request Config:', {
+ symbol,
+ interval: config.interval,
+ startTime: new Date(config.startTime).toLocaleString(),
+ endTime: new Date(config.endTime).toLocaleString()
+ });
+ try{
+ // Get all cache entries for this symbol/interval
+ const cacheEntries = await storage.getMarketData(symbol, config.interval);
+ console.log(`Found ${cacheEntries.length} cache entries`);
+ //console.log(`Checking cache for ${symbol} ${config.interval} data...`);
+const overlappingEntries = cacheEntries.filter(cache =>
+ // Entry ends after request starts AND entry starts before request ends
+ this.addMarketTime(cache.endTime,1) >= config.startTime && cache.startTime <= this.addMarketTime(config.endTime,1)
+ );
+ if (cacheEntries.length > 0) {
+ // Find overlapping cache entries
+
+
+ /*
+ console.log('Found overlapping cache entries:', overlappingEntries.map(cache => ({
+ startTime: new Date(cache.startTime).toLocaleString(),
+ endTime: new Date(cache.endTime).toLocaleString(),
+ dataPoints: cache.data.length
+ })));*/
+
+ // Check if any single cache entry covers our request
+ const coveringEntry =overlappingEntries.find(cache => this.doesCacheCover(cache, config))
+
+ if(coveringEntry) {
+ console.log('Found complete coverage in cache:', {
+ start: new Date(coveringEntry.startTime).toLocaleString(),
+ end: new Date(coveringEntry.endTime).toLocaleString()
+ });
+ return coveringEntry.data.filter(d =>
+ d.time >= config.startTime && d.time <= config.endTime
+ );
+ }
+ console.log(`Found ${overlappingEntries.length} overlapping entries but no complete coverage`);
+ }
+ console.log(`Cache miss for ${symbol} ${config.interval}, fetching from API...`);
+ // Check if we can build from lower timeframe data
+ const intervals = Object.keys(this.INTERVALS_MINUTES) as IntervalType[];
+ const lowerIntervals = intervals.filter(interval =>
+ this.canDeriveFromCache(interval, config.interval)
+ );
+
+ for (const interval of lowerIntervals) {
+ const lowerCacheEntries = await storage.getMarketData(symbol, interval);
+ // Find overlapping entries from lower timeframe
+ const overlappingEntries = lowerCacheEntries.filter(cache =>
+ cache.endTime >= config.startTime && cache.startTime <= config.endTime
+ );
+
+ // Check if we have complete coverage from lower timeframe
+ const hasFullCoverage = overlappingEntries.some(cache =>
+ this.doesCacheCover(cache, {
+ ...config,
+ interval: interval
+ })
+ );
+
+ if (hasFullCoverage) {
+ // Merge overlapping lower timeframe data
+ const mergedLowerData = overlappingEntries.reduce((acc, cache) =>
+ [...acc, ...cache.data], [] as MarketData[]
+ ).sort((a, b) => a.time - b.time);
+
+ // We can build the higher timeframe from this data
+ const aggregatedData = this.aggregateToHigherTimeframe(
+ mergedLowerData,
+ interval,
+ config.interval
+ );
+
+ // Cache the aggregated data
+ await storage.saveMarketData(symbol, {
+ data: aggregatedData,
+ timestamp: Date.now(),
+ interval: config.interval,
+ startTime: Math.min(...aggregatedData.map(d => d.time)),
+ endTime: Math.max(...aggregatedData.map(d => d.time)),
+ timezone: overlappingEntries[0].timezone, // Assume timezone is consistent
+ });
+
+ return aggregatedData.filter(d =>
+ d.time >= config.startTime && d.time <= config.endTime
+ );
+ }
+}
+ // If we can't build from cache, fetch new data
+ const {data, timezone} = await this.fetchAppropriateData(symbol, config);
+ let mergedData = data;
+ // If we have existing cached data, try to merge
+ if (cacheEntries.length > 0) {
+
+ if (overlappingEntries.length > 0) {
+ console.log('Attempting to merge with cached data');
+ mergedData = this.mergeMarketData(
+ overlappingEntries.reduce((acc, cache) => [...acc, ...cache.data], [] as MarketData[]),
+ data);
+
+ console.log('Merged with overlapping cached data:', {
+ overlappingCachePoints: overlappingEntries.reduce((sum, cache) => sum + cache.data.length, 0),
+ newPoints: data.length,
+ finalPoints: mergedData.length
+ });
+ }
+ }
+ const newStartTime = Math.min(...mergedData.map(d => d.time));
+ const newEndTime = Math.max(...mergedData.map(d => d.time));
+
+ // Check if this exact time range already exists in cache
+ const exactMatch = overlappingEntries.some(entry =>
+ Math.abs(entry.startTime - newStartTime) < 60000 && // Within 1 minute
+ Math.abs(entry.endTime - newEndTime) < 60000 && // Within 1 minute
+ entry.interval === config.interval
+ );
+
+if (!exactMatch) {
+ await storage.saveMarketData(symbol, {
+ data: mergedData,
+ timestamp: Date.now(),
+ interval: config.interval,
+ startTime: Math.min(...mergedData.map(d => d.time)),
+ endTime: Math.max(...mergedData.map(d => d.time)),
+ timezone
+ });
+ } else {
+ console.log('Skipping cache save - exact time range already exists');
+ }
+
+ return mergedData;
+ }
+ catch (error) {
+ console.error('Error in getMarketData:', error);
+ throw error; // Re-throw to handle in component
+}
+
+}
+ private static canDeriveFromCache(sourceInterval: IntervalType, targetInterval: IntervalType): boolean {
+ const sourceMinutes = this.INTERVALS_MINUTES[sourceInterval];
+ const targetMinutes = this.INTERVALS_MINUTES[targetInterval];
+ return sourceMinutes < targetMinutes && targetMinutes % sourceMinutes === 0;
+ }
+
+
+ private static async fetchAppropriateData(
+ symbol: string,
+ config: TimeframeConfig
+ ): Promise<{data:MarketData[], timezone: string}> {
+ if (config.interval === 'daily') {
+ return await this.fetchHistoricalData(symbol);
+ } else {
+ return await this.fetchIntraday(symbol, config.interval);
+ }
+ }
+ private static mergeMarketData(existingData: MarketData[], newData: MarketData[]): MarketData[] {
+ // Combine both arrays
+ const combined = [...existingData, ...newData];
+
+ // Sort by time
+ combined.sort((a, b) => a.time - b.time);
+
+ // Remove duplicates based on timestamp
+ return combined.filter((item, index, self) =>
+ index === 0 || item.time !== self[index - 1].time
+ );
+ }
+}
+
+
+
diff --git a/src/services/marketDataStorage.ts b/src/services/marketDataStorage.ts
new file mode 100644
index 0000000..54d60d1
--- /dev/null
+++ b/src/services/marketDataStorage.ts
@@ -0,0 +1,257 @@
+// src/services/marketDataStorage.ts
+import { TFile, Vault } from 'obsidian';
+import { MarketData, CacheEntry, CacheMetadata, IntervalType } from './marketDataService';
+
+export class MarketDataStorage {
+ private vault: Vault;
+ private noteFile: TFile;
+ private basePath: string;
+
+ constructor(vault: Vault, noteFile: TFile) {
+ this.vault = vault;
+ this.noteFile = noteFile;
+
+ // Determine the appropriate base path
+ this.basePath = this.determineBasePath();
+ }
+ private determineBasePath(): string {
+ // Check if note exists and is a markdown file
+ if (!this.noteFile || this.noteFile.extension !== 'md') {
+ throw new Error('Invalid note file');
+ }
+
+ // Get the parent folder path, defaulting to root if none
+ const parentPath = this.noteFile.parent?.path ?? '';
+
+ // If at root, store in vault root
+ if (!parentPath) {
+ return '.market-data';
+ }
+
+ // Store in parent folder
+ return `${parentPath}/.market-data`;
+ }
+ getBasePath(): string {
+ return this.basePath;
+ }
+ private async ensureDirectory(path: string) {
+ try {
+ if (!(await this.vault.adapter.exists(path))) {
+ await this.vault.adapter.mkdir(path);
+ }
+ } catch (error) {
+ console.error(`Failed to create directory ${path}:`, error);
+ throw new Error(`Failed to create market data directory: ${error.message}`);
+ }
+ }
+
+ async initialize() {
+ try {
+ // Ensure base directory exists
+ await this.ensureDirectory(this.basePath);
+
+ // Create metadata file if it doesn't exist
+ const metadataPath = `${this.basePath}/metadata.json`;
+ if (!(await this.vault.adapter.exists(metadataPath))) {
+ await this.vault.adapter.write(
+ metadataPath,
+ JSON.stringify({
+ created: Date.now(),
+ noteSource: this.noteFile.path
+ })
+ );
+ }
+
+ return true;
+ } catch (error) {
+ console.error('Failed to initialize market data storage:', error);
+ throw error;
+ }
+ }
+ // Helper method to get absolute path in vault
+ getAbsolutePath(relativePath: string): string {
+ return `${this.basePath}/${relativePath}`;
+}
+
+// Method to check if storage is properly initialized
+async isInitialized(): Promise {
+ try {
+ return await this.vault.adapter.exists(this.basePath);
+ } catch {
+ return false;
+ }
+}
+
+// Method to get storage location info
+async getStorageInfo(): Promise<{
+ basePath: string;
+ isInitialized: boolean;
+ parentFolder: string;
+ noteFile: string;
+}> {
+ return {
+ basePath: this.basePath,
+ isInitialized: await this.isInitialized(),
+ parentFolder: this.noteFile.parent?.path ?? '(root)',
+ noteFile: this.noteFile.path
+ };
+}
+ private getSymbolPath(symbol: string) {
+ return `${this.basePath}/${symbol}`;
+ }
+
+ private getDataPath(symbol: string, interval: IntervalType) {
+ return `${this.getSymbolPath(symbol)}/${interval}.json`;
+ }
+
+ async saveMarketData(symbol: string, cacheEntry: CacheEntry): Promise {
+ await this.initialize();
+
+ // Ensure symbol directory exists
+ const symbolPath = this.getSymbolPath(symbol);
+ await this.ensureDirectory(symbolPath);
+
+ // Save data file
+ const dataPath = this.getDataPath(symbol, cacheEntry.interval);
+ await this.vault.adapter.write(
+ dataPath,
+ JSON.stringify(cacheEntry, null, 2)
+ );
+
+ // Update metadata
+ await this.updateMetadata(symbol, cacheEntry);
+ }
+
+ async getMarketData(symbol: string, interval: IntervalType): Promise {
+ const dataPath = this.getDataPath(symbol, interval);
+
+ if (await this.vault.adapter.exists(dataPath)) {
+ const content = await this.vault.adapter.read(dataPath);
+ const parsed = JSON.parse(content);
+ // Ensure we always return an array
+ return Array.isArray(parsed) ? parsed : [parsed];
+ }
+
+ return [];
+ }
+
+ private async updateMetadata(symbol: string, cacheEntry: CacheEntry) {
+ const metadataPath = `${this.basePath}/metadata.json`;
+ let metadata: CacheMetadata = {};
+ try{
+ if (await this.vault.adapter.exists(metadataPath)) {
+ const content = await this.vault.adapter.read(metadataPath);
+ metadata = JSON.parse(content);
+ }
+
+ // Update metadata for this symbol
+ metadata[symbol] = metadata[symbol] || {};
+ if (!metadata[symbol][cacheEntry.interval]) {
+ metadata[symbol][cacheEntry.interval] = [];
+ }
+
+ // Add new cache entry info
+ const cacheList = metadata[symbol][cacheEntry.interval];
+ if (cacheList) {
+ cacheList.push({
+ timestamp: cacheEntry.timestamp,
+ startTime: cacheEntry.startTime,
+ endTime: cacheEntry.endTime,
+ interval: cacheEntry.interval,
+ data: [], // Don't store actual data in metadata
+ timezone: cacheEntry.timezone
+ });
+
+ // Keep only last 5 entries
+ if (cacheList.length > 5) {
+ cacheList.shift();
+ }
+ }
+
+ await this.vault.adapter.write(
+ metadataPath,
+ JSON.stringify(metadata, null, 2)
+ );
+ }catch (error) {
+ console.error(`Failed to update metadata for ${symbol}:`, error);
+ throw new Error(`Failed to update metadata: ${error.message}`);
+ }
+ }
+
+ async getCacheStats(): Promise<{
+ totalSize: number;
+ symbolCount: number;
+ fileCount: number;
+ symbols: Record;
+ }> {
+ let totalSize = 0;
+ let fileCount = 0;
+ const symbols: Record = {};
+try{
+ if (await this.vault.adapter.exists(this.basePath)) {
+ const files = await this.vault.adapter.list(this.basePath);
+
+ for (const file of files.files) {
+ if (file.endsWith('.json')) {
+ const stat = await this.vault.adapter.stat(file);
+ if (!stat) continue; // Skip if stat is null
+ totalSize += stat.size;
+ fileCount++;
+
+ // Parse symbol and interval info
+ const pathParts = file.split('/');
+ if (pathParts.length >= 2) {
+ const symbol = pathParts[pathParts.length - 2];
+ const interval = pathParts[pathParts.length - 1].replace('.json', '') as IntervalType;
+
+ if (!symbols[symbol]) {
+ symbols[symbol] = {
+ intervals: [],
+ lastUpdated: stat.mtime
+ };
+ }
+ symbols[symbol].intervals.push(interval);
+ symbols[symbol].lastUpdated = Math.max(symbols[symbol].lastUpdated, stat.mtime);
+ }
+ }
+ }
+ }
+
+ return {
+ totalSize,
+ symbolCount: Object.keys(symbols).length,
+ fileCount,
+ symbols
+ };
+ } catch (error) {
+ console.error('Failed to get cache stats:', error);
+ return {
+ totalSize: 0,
+ symbolCount: 0,
+ fileCount: 0,
+ symbols: {}
+ };
+ }
+ }
+
+ async cleanup(maxAge: number = 7 * 24 * 60 * 60 * 1000) { // Default 7 days
+ const stats = await this.getCacheStats();
+ const now = Date.now();
+
+ for (const [symbol, info] of Object.entries(stats.symbols)) {
+ if (now - info.lastUpdated > maxAge) {
+ // Remove old symbol data
+ const symbolPath = this.getSymbolPath(symbol);
+ if (await this.vault.adapter.exists(symbolPath)) {
+ await this.vault.adapter.rmdir(symbolPath, true);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/types/babel-standalone.d.ts b/src/types/babel-standalone.d.ts
new file mode 100644
index 0000000..ac38a0a
--- /dev/null
+++ b/src/types/babel-standalone.d.ts
@@ -0,0 +1,31 @@
+// src/types/babel-standalone.d.ts
+declare module '@babel/standalone' {
+ export interface TransformOptions {
+ filename?: string;
+ presets?: (string | [string, object])[]; //Also allow tuple
+ plugins?: any[];
+ configFile?: boolean | string;
+ babelrc?: boolean;
+ sourceType?: 'script' | 'module' | 'unambiguous';
+ sourceMaps?: boolean;
+ sourceFileName?: string;
+ code?: boolean;
+ ast?: boolean;
+ minified?: boolean;
+ }
+
+ export interface TransformResult {
+ code: string;
+ map?: any;
+ ast?: any;
+ metadata?: any;
+ }
+
+ export function transform(
+ code: string,
+ options?: TransformOptions
+ ): TransformResult;
+
+ export const availablePresets: { [key: string]: any };
+ export const availablePlugins: { [key: string]: any };
+}
\ No newline at end of file
diff --git a/src/types/global.d.ts b/src/types/global.d.ts
new file mode 100644
index 0000000..1aa7d50
--- /dev/null
+++ b/src/types/global.d.ts
@@ -0,0 +1,7 @@
+declare global {
+ interface Window {
+ React: typeof import('react');
+ }
+}
+
+export {};
\ No newline at end of file
diff --git a/styles.css b/styles.css
new file mode 100644
index 0000000..8657e6a
--- /dev/null
+++ b/styles.css
@@ -0,0 +1,335 @@
+/* styles.css */
+
+/* Spacing utilities */
+.mt-1 { margin-top: 0.25rem; }
+.mt-2 { margin-top: 0.5rem; }
+.mt-4 { margin-top: 1rem; }
+.mb-2 { margin-bottom: 0.5rem; }
+.p-2 { padding: 0.5rem; }
+.p-4 { padding: 1rem; }
+
+/* Layout utilities */
+.flex { display: flex; }
+.grid { display: grid; }
+.grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
+.gap-2 { gap: 0.5rem; }
+.gap-4 { gap: 1rem; }
+
+.w-full { width: 100%; }
+.space-y-2 > * + * { margin-top: 0.5rem; }
+
+/* Colors - using Obsidian CSS variables */
+.text-green-500 { color: var(--color-green); }
+.text-red-500 { color: var(--color-red); }
+.text-blue-500 { color: var(--interactive-accent); }
+
+/* Font utilities */
+.font-medium { font-weight: 500; }
+.text-sm { font-size: 0.875rem; }
+.text-lg { font-size: 1.125rem; }
+
+
+/* Border utilities */
+.rounded { border-radius: 4px; }
+.border { border: 1px solid var(--background-modifier-border); }
+.border-slate-700 { border-color: var(--background-modifier-border-focus); }
+
+/* Component styles */
+.react-plugin-card {
+ border: 1px solid var(--background-modifier-border);
+ border-radius: 4px;
+ background: var(--background-primary);
+ margin-bottom: 1rem; }
+
+.react-plugin-card-header {
+ padding: 1rem;
+ border-bottom: 1px solid var(--background-modifier-border); }
+
+.react-plugin-card-title {
+ margin: 0;
+ font-size: 1.1em;
+ font-weight: 600;
+ color: var(--text-normal); }
+
+.react-plugin-card-content { padding: 1rem; }
+
+.react-plugin-tabs {
+ display: flex;
+ flex-direction: column;
+ gap: 1rem; }
+
+.react-plugin-tabs-list {
+ display: flex;
+ gap: 0.5rem;
+ border-bottom: 1px solid var(--background-modifier-border);
+ padding-bottom: 0.5rem; }
+
+.react-plugin-tab-trigger {
+ padding: 0.5rem 1rem;
+ border: none;
+ background: none;
+ cursor: pointer;
+ color: var(--text-muted);
+ border-radius: 4px; }
+
+.react-plugin-tab-trigger[data-state="active"] {
+ background: var(--background-modifier-hover);
+ color: var(--text-normal); }
+
+/* Chart container styles */
+.chart-container {
+ border: 1px solid var(--background-modifier-border);
+ border-radius: 4px;
+ padding: 0;
+ margin: 0;
+ overflow: hidden; /* Add this to prevent any overflow */
+ min-height: 400px;
+ background: var(--background-secondary); }
+
+ .tv-lightweight-charts {
+ height: 500px !important; /* Force height if needed
+ overflow: visible; /* Show x-axis labels if they overflow */
+ }
+
+
+/* List styles */
+.list-content {
+ margin: 0;
+ padding-left: 1.5rem;
+ list-style-type: none; }
+
+.list-content li {
+ margin-bottom: 0.5rem;
+ color: var(--text-normal); }
+
+.heading {
+ margin: 0 0 0.5rem 0;
+ font-weight: 600; }
+
+/* Prevent conflicts with Obsidian's styles */
+.react-plugin-card button { box-shadow: none; }
+
+.react-plugin-card button:hover { box-shadow: none; }
+.react-component-error {
+ margin: 0.5rem 0;
+ font-size: 0.875rem;
+}
+
+.react-component-error pre {
+ white-space: pre-wrap;
+ word-break: break-word;
+}
+
+
+/* Dark mode adjustments are handled by Tailwind classes */
+/*
+
+This CSS file will be included with your plugin, and
+available in the app when your plugin is enabled.
+
+If your plugin does not need CSS, delete this file.
+
+*/
+
+/* Chart container styles */
+.recharts-wrapper {
+ min-height: 400px !important;
+ min-width: 300px !important;
+}
+
+/* Ensure proper sizing for ResponsiveContainer */
+.recharts-responsive-container {
+ min-height: 400px !important;
+ width: 100% !important;
+}
+
+/* Dark mode adjustments for charts */
+.theme-dark .recharts-cartesian-grid line {
+ stroke: rgba(255, 255, 255, 0.1);
+}
+
+.theme-dark .recharts-text {
+ fill: rgba(255, 255, 255, 0.8);
+}
+
+.theme-dark .recharts-tooltip-wrapper {
+ background-color: #1a1b1e;
+ border: 1px solid rgba(255, 255, 255, 0.1);
+}
+
+
+/*Tail Wind stuff */
+/* styles.css */
+
+/* Layout */
+.w-full { width: 100%; }
+.w-3\/4 { width: 75%; }
+.w-1\/2 { width: 50%; }
+.h-64 { height: 16rem; }
+.h-32 { height: 8rem; }
+.h-16 { height: 4rem; }
+.relative { position: relative; }
+.absolute { position: absolute; }
+
+/* Spacing */
+.p-4 { padding: 1rem; }
+.mt-16 { margin-top: 4rem; }
+.mt-8 { margin-top: 2rem; }
+.mt-4 { margin-top: 1rem; }
+.mb-4 { margin-bottom: 1rem; }
+.ml-8 { margin-left: 2rem; }
+.top-2 { top: 0.5rem; }
+.left-2 { left: 0.5rem; }
+
+/* Block colors - with dark mode support */
+.bg-red-200 {
+ background-color: rgba(254, 202, 202, 0.8);
+}
+.bg-orange-200 {
+ background-color: rgba(254, 215, 170, 0.8);
+}
+.bg-yellow-200 {
+ background-color: rgba(254, 240, 138, 0.8);
+}
+.bg-slate-100 {
+ background-color: rgba(241, 245, 249, 0.8);
+}
+
+.theme-dark .bg-red-200 {
+ background-color: rgba(254, 202, 202, 0.2);
+}
+.theme-dark .bg-orange-200 {
+ background-color: rgba(254, 215, 170, 0.2);
+}
+.theme-dark .bg-yellow-200 {
+ background-color: rgba(254, 240, 138, 0.2);
+}
+.theme-dark .bg-slate-100 {
+ background-color: rgba(241, 245, 249, 0.1);
+}
+
+/* Border colors */
+.border-red-500 { border-color: rgb(239, 68, 68); }
+.border-orange-500 { border-color: rgb(249, 115, 22); }
+.border-yellow-500 { border-color: rgb(234, 179, 8); }
+
+/* Border styles */
+.border-2 { border-width: 2px; }
+.rounded-lg { border-radius: 0.5rem; }
+
+/* Grid */
+.grid { display: grid; }
+.grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
+.gap-4 { gap: 1rem; }
+
+/* Typography */
+.text-sm { font-size: 0.875rem; }
+.font-medium { font-weight: 500; }
+
+/* Flex */
+.flex { display: flex; }
+.items-center { align-items: center; }
+
+/* Spacing utilities */
+.space-y-4 > * + * { margin-top: 1rem; }
+.space-y-2 > * + * { margin-top: 0.5rem; }
+
+/* Container styles - ensures proper rendering in Obsidian */
+.react-component-container {
+ width: 100%;
+ margin: 1rem 0;
+ font-family: var(--font-interface);
+ color: var(--text-normal);
+}
+
+.theme-dark .react-component-container {
+ color-scheme: dark;
+}
+
+/* Card styles */
+.card {
+ background-color: var(--background-primary);
+ border: 1px solid var(--background-modifier-border);
+ border-radius: 0.5rem;
+ width: 100%;
+}
+
+.card-header {
+ padding: 1.5rem;
+}
+
+.card-title {
+ font-size: 1.5rem;
+ font-weight: 600;
+ margin: 0;
+}
+
+.card-content {
+ padding: 1.5rem;
+}
+
+
+
+
+
+/* Base text positioning */
+.nested-block-label {
+ position: absolute;
+ top: 8px;
+ left: 8px;
+ font-size: 0.875rem;
+ font-weight: 500;
+ z-index: 10; /* Ensure text stays above blocks */
+ background-color: inherit; /* Match parent block background */
+ padding: 2px 6px;
+ border-radius: 4px;
+}
+
+/* Ensure blocks stack properly */
+.nested-block {
+ position: relative;
+ border: 2px solid;
+ border-radius: 8px;
+ margin-bottom: 1rem;
+ z-index: 1; /* Base z-index */
+}
+
+/* Specific z-indices for each block type */
+.nested-block.primary {
+ z-index: 1;
+}
+
+.nested-block.secondary {
+ z-index: 2;
+}
+
+.nested-block.tertiary {
+ z-index: 3;
+}
+
+/* Adjust backgrounds to be slightly transparent */
+.bg-red-200 {
+ background-color: rgba(254, 202, 202, 0.95);
+}
+.bg-orange-200 {
+ background-color: rgba(254, 215, 170, 0.95);
+}
+.bg-yellow-200 {
+ background-color: rgba(254, 240, 138, 0.95);
+}
+
+/* Dark mode adjustments */
+.theme-dark .bg-red-200 {
+ background-color: rgba(254, 202, 202, 0.15);
+}
+.theme-dark .bg-orange-200 {
+ background-color: rgba(254, 215, 170, 0.15);
+}
+.theme-dark .bg-yellow-200 {
+ background-color: rgba(254, 240, 138, 0.15);
+}
+
+/* Ensure proper spacing */
+.nested-block + .nested-block {
+ margin-top: 2rem;
+}
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..5a6775c
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,37 @@
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "inlineSourceMap": true,
+ "inlineSources": true,
+ "module": "ESNext",
+ "target": "ES2020",
+ "allowJs": true,
+ "noImplicitAny": true,
+ "moduleResolution": "node",
+ "importHelpers": true,
+ "isolatedModules": true,
+ "strictNullChecks": true,
+ "allowSyntheticDefaultImports": true,
+ "jsx": "react",
+ "jsxFactory": "React.createElement", // Add this
+ "jsxFragmentFactory": "React.Fragment", // Add this
+ "lib": [
+ "DOM",
+ "ES5",
+ "ES6",
+ "ES7",
+ "ES2020"
+ ],
+ "typeRoots": [
+ "./node_modules/@types",
+ "./src/types"
+ ]
+ },
+ "include": [
+ "**/*.ts",
+ "**/*.tsx",
+ "src/**/*.ts",
+ "src/**/*.tsx",
+ "src/types/**/*.d.ts"
+ ]
+}
diff --git a/version-bump.mjs b/version-bump.mjs
new file mode 100644
index 0000000..d409fa0
--- /dev/null
+++ b/version-bump.mjs
@@ -0,0 +1,14 @@
+import { readFileSync, writeFileSync } from "fs";
+
+const targetVersion = process.env.npm_package_version;
+
+// read minAppVersion from manifest.json and bump version to target version
+let manifest = JSON.parse(readFileSync("manifest.json", "utf8"));
+const { minAppVersion } = manifest;
+manifest.version = targetVersion;
+writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t"));
+
+// update versions.json with target version and minAppVersion from manifest.json
+let versions = JSON.parse(readFileSync("versions.json", "utf8"));
+versions[targetVersion] = minAppVersion;
+writeFileSync("versions.json", JSON.stringify(versions, null, "\t"));
diff --git a/versions.json b/versions.json
new file mode 100644
index 0000000..26382a1
--- /dev/null
+++ b/versions.json
@@ -0,0 +1,3 @@
+{
+ "1.0.0": "0.15.0"
+}