diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 93276496..00000000 --- a/.babelrc +++ /dev/null @@ -1,13 +0,0 @@ -{ - "presets": ["@babel/preset-env"], - "plugins": [ - [ - "@babel/plugin-transform-regenerator", - { - "asyncGenerators": true, - "generators": true, - "async": true - } - ] - ] -} diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 04ba039a..00000000 --- a/.editorconfig +++ /dev/null @@ -1,20 +0,0 @@ -# EditorConfig helps developers define and maintain consistent -# coding styles between different editors and IDEs -# editorconfig.org - -root = true - -[*] - -# Change these settings to your own preference -indent_style = space -indent_size = 2 - -# We recommend you to keep these unchanged -end_of_line = lf -charset = utf-8 -trim_trailing_whitespace = true -insert_final_newline = true - -[*.md] -trim_trailing_whitespace = false diff --git a/.github/ISSUE_TEMPLATE/bug.md b/.github/ISSUE_TEMPLATE/bug.md deleted file mode 100644 index d2cca94d..00000000 --- a/.github/ISSUE_TEMPLATE/bug.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -name: 'Bug report' -about: 'Report a bug to help us improve' -labels: 'Bug :bug:' ---- - -Oh snap! Looks like something went south. Thank you for taking the time to report the issue. - -Before you file it, please: - -- [ ] Check for duplicate issues. -- [ ] Describe the bug: what did you do to trigger it, what was your expected behavior, and what did you experience instead. -- [ ] Use the latest versions of `regl-scatterplot`. -- [ ] Provide an [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) of the bug. -- [ ] If applicable, include error messages, screenshots, GIFs, videos, or working examples. diff --git a/.github/ISSUE_TEMPLATE/enhancement.md b/.github/ISSUE_TEMPLATE/enhancement.md deleted file mode 100644 index 455bb5f7..00000000 --- a/.github/ISSUE_TEMPLATE/enhancement.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -name: 'Enhancement' -about: 'Suggest a new idea or improvement for `regl-scatterplot`' -labels: 'Enhancement :tada:' ---- - -You have an idea how to enhance `regl-scatterplot`? That's awesome! - -Before you file your idea, please: - -- [ ] Check for duplicate issues. -- [ ] Describe the feature's goal, motivating use cases, its expected behavior, and impact. -- [ ] If you are proposing a new API, please explain how the current APIs fail to support your goal. -- [ ] If you are proposing to change an existing API, please explain if your proposed is backward compatible or incompatible. -- [ ] If applicable, include screenshots, GIFs, videos, or working examples. - -You are encouraged to prototype multiple alternative APIs or implementation approaches for your proposed feature. Doing so often leads to a better solution. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index a62e9abc..00000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,24 +0,0 @@ -> Write one to two sentences summarizing this PR - -## Description - -### What was changed in this pull request? - -> Explain in more detail what has changed on a technical level - -### Example - -> If feasable, add a screenshot or video demonstrating the new feature or bug fix - -### Why is this PR necessary? - -Fixes #___ - -## Checklist - -- [ ] Provided a concise title as a [semantic commit message](https://www.conventionalcommits.org) (e.g. "fix: correctly handle undefined properties") -- [ ] `CHANGELOG.md` updated -- [ ] Tests added or updated -- [ ] Documentation in `README.md` added or updated -- [ ] Example(s) added or updated -- [ ] Screenshot, gif, or video attached for visual changes diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 8ac6b8c4..00000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,6 +0,0 @@ -version: 2 -updates: - - package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "monthly" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 1bb182ae..00000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: build - -on: - push: - branches: [main] - pull_request: - branches: [main] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v7 - - uses: actions/setup-node@v7 - with: - node-version: '24' - - name: Install dependencies - run: npm ci - - name: Build - run: npm run build --if-present - env: - CI: true - - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v7 - - uses: actions/setup-node@v7 - with: - node-version: '24' - - name: Install dependencies - run: npm ci - - name: Install Playwright Browsers - run: npx playwright install --with-deps - - run: npm test - timeout-minutes: 5 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index f5dfc502..00000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,35 +0,0 @@ -name: publish - -on: - push: - tags: - - 'v*' - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v7 - - uses: actions/setup-node@v7 - with: - node-version: '24' - - run: npm ci - - run: npm run build --if-present - env: - CI: true - - publish-npm: - needs: build - runs-on: ubuntu-latest - permissions: - contents: read - id-token: write - steps: - - uses: actions/checkout@v7 - - uses: actions/setup-node@v7 - with: - node-version: '24' - registry-url: https://registry.npmjs.org/ - - run: npm ci - - run: npm run prerelease - - run: npm publish --provenance --access public --ignore-scripts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 3ae21728..00000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: release - -on: - push: - tags: - - 'v*' - -jobs: - release: - name: Create Release - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - name: Checkout code - uses: actions/checkout@v7 - - name: Create Release - env: - GH_TOKEN: ${{ github.token }} - run: gh release create "$GITHUB_REF_NAME" --generate-notes diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 14243865..00000000 --- a/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -coverage -*.seed -*.log -*.csv -*.dat -*.out -*.pid -*.gz -*.DS_cache - -pids -logs -results - -dist/* -dist.zip - -npm-debug.log -node_modules/* - -docs -stats.html - -tests/__screenshots__ diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 00000000..e69de29b diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index 209e3ef4..00000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -20 diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index f2b18d90..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,602 +0,0 @@ -## 1.16.0 - -- Feat: Added a `pointOrder` property that controls point draw order so users can ensure specific points (e.g., outliers) render on top without pre-sorting their data. - -## 1.15.0 - -- Feat: add programmatic lasso selection API via new `lassoSelect()` method that accept a polygon in either data or GL space. This enables automated point selection without manual interaction. Supports `merge` and `remove` options. Note, vertices in data space requires `xScale` and `yScale` to be defined. - -## 1.14.1 - -- Fix: ensure view aspect ratio is updated before the scales are updated on resize - -## 1.14.0 - -- Feat: expose a flag indicating a view change for events `draw`, `drawing`, and `view` -- Fix: clean up worker URL after creation - -## 1.13.2 - -- Fix: replace the even-odd rule based with the non-zero winding rule for `isPointInPolygon()` to correctly handle overlapping/looping selections. Previosuly points that would fall within the overlapping area would falsely be excluded from the selection instead of being included. -- Fix: Smooth the brush normal to avoid jitter - -## 1.13.1 - -- Fix: an issue where new colors wouldn't be set properly ([#214](https://github.com/flekschas/regl-scatterplot/issues/214)) - -## 1.13.0 - -- Feat: add support for two new lasso types: `'rectangle'` and `'brush'`. The lasso type can be changed via `lassoType`. Additionally, for the brush lasso, you can adjust the brush size via `lassoBrushSize`. The default lasso type is `'freeform'`. ([#186](https://github.com/flekschas/regl-scatterplot/issues/186)) -- Feat: replace `keyMap` with `actionKeyMap` to allow triggering multiple actions with the same modifier key. -- Feat: add `'remove'` key action to allow removing selecting points. By default, to rgitemove selected points hold down `ALT` and then lasso around selected points. ([#105](https://github.com/flekschas/regl-scatterplot/issues/105)) -- Feat: expose `renderPointsAsSquares` and `disableAlphaBlending` to allow finer control over performance increasing settings ([#206](https://github.com/flekschas/regl-scatterplot/issues/206)) - -## 1.12.1 - -- Fix: prevent drawing points if all are filtered out ([#201](https://github.com/flekschas/regl-scatterplot/issues/201)) -- Fix: destroy the encoding texture before recreating it -- Fix: reject `set()` calls if the instance was destroyed -- Fix: ensures unnecessary color and encoding texture updates are avoided -- Fix: color and encoding textures are destroyed upon calling `scatterplot.destroy()` -- Fix: prevent a minor memory leak in the newly added advanced exporter - -## 1.12.0 - -- Feat: add support for adjusting the anti-aliasing via `scatterplot.set({ antiAliasing: 1 })`. ([#175](https://github.com/flekschas/regl-scatterplot/issues/175)) -- Feat: add support for aligning points with the pixel grid via `scatterplot.set({ pixelAligned: true })`. ([#175](https://github.com/flekschas/regl-scatterplot/issues/175)) -- Feat: enhance `scatterplot.export()` by allowing to adjust the scale, anti-aliasing, and pixel alignment. Note that when customizing the render setting for export, the function returns a promise that resolves into `ImageData`. -- Feat: expose `resize()` method of the `renderer`. - -## 1.11.4 - -- Fix: allow setting the lasso long press indicator parent element - -## 1.11.3 - -- Fix: catch another edge case where `zoomToOrigin` was unsetting the camera fixed state - -## 1.11.2 - -- Fix: handle camera fixing better by adding a dedicated prop called `cameraIsFixed`. Previously, the lasso end interaction would unset the camera fixing. ([#94](https://github.com/flekschas/regl-scatterplot/issues/94)) - -## 1.11.1 - -- Fix: ensure that the drawing order of points cannot be manipulated via `scatterplot.filter()` ([#197](https://github.com/flekschas/regl-scatterplot/issues/197)) - -## 1.11.0 - -- Feat: add support for linear and constant point scaling via a new property called `pointScaleMode`. - -## 1.10.4 - -- Fix: restrict the renderer's canvas to be at most as large as the screen. Previously we had the canvas size bound to `window.innerWidth` and `window.innerHeight`. However, in VSCode it was possible that `window.innerHeight` was muuuuch larger than the actual screen, which in turn caused a WebGL error (invalid renderbuffer size). This issues was first reported at https://github.com/flekschas/jupyter-scatter/issues/37. - -## 1.10.3 - -- Fix: properly set mouse mode on initialization and add tests for it - -## 1.10.2 - -- Fix: expose x start/end and y start/end for horizontal and vertical line annotations. -- Fix: ensure KDBush worker works in prod build - -## 1.10.1 - -- Fix: ensure single annotations render properly ([#187](https://github.com/flekschas/regl-scatterplot/issues/187)) - -## 1.10.0 - -- Feat: add support for annotations via `scatterplot.drawAnnotations()` - -## 1.9.6 - -- Fix: try ensure `zoomToArea` works in cases where `aspectRatio` is not equal to `1` and add tests to verify this - -## 1.9.5 - -- Fix: option types of `zoomToLocation`, `zoomToOrigin`, `zoomToArea` -- Fix: ensure `zoomToArea` works in cases where `aspectRatio` is not equal to `1` - -## 1.9.4 - -- Fix: `scatterplot.draw(newPoints, { preventFilterReset })` should preserves the filter ([Jupyter-Scatter#134](https://github.com/flekschas/jupyter-scatter/issues/134)) -- Fix: `scatterplot.hover(filteredOutPoint)` should not trigger a hover event - -## 1.9.3 - -- Fix: point connection initial color map -- Fix: allow point connection color to be set to `inherit` (to inherit the point color) - -## 1.9.2 - -- Fix: update `regl-line` to include a critical bug fix related to drawing connected points. - -## 1.9.1 - -- Fix: add missing type definition for `scatterplot.get('spatialIndex')` ([#179](https://github.com/flekschas/regl-scatterplot/issues/179)) - -## 1.9.0 - -- Add: allow to retrieve KDBush's spatial index via `scatterplot.get('spatialIndex')`. The index refers to KDBush v4.0.2. -- Add: allow to pass a spatial index to `scatterplot.draw(newPoints, { spatialIndex })` to circumvent the indexing of `newPoints`. This can be useful when only the z or w coordinates of `newPoints` differ to previously drawn points or when you've computed the spatial index upfront. -- Add: run the computation of the spatial index in a worker when the number of points is larger or equal to one million. This behavior can be adjusted during the instantiation of the scatterplot via `createScatterplot({ spatialIndexUseWorker })`. If `true`, regl-scatterplot will always compute the spatial index in a worker. If `false`, regl-scatterplot will always compute the spatial index in the main browser thread. -- Add: export `createSpatialIndex` to allow creating a spatial index upfront conveniently -- Add: new `drawing` event that is _always fired synchronously_ before the end of a draw call. This event is useful for drawing other things as part of an animation frame. The main difference to the default `draw` event is that the `draw` event is fired asynchronously (like all other events) after the draw call such that the draw call itself isn't blocked. -- Fix: pass `{ camera, view, xScale, yScale }` as the payload of the `draw` event as specified in the docs. -- Fix: allow `scatterplot.set({ showPointConnections: true })` before points were drawn [#171](https://github.com/flekschas/regl-scatterplot/issues/171) -- Fix: pub-sub related types by updating `pub-sub-es` to version 3 - -## 1.8.5 - -- Fix: add `d3-scale` types as a dev dependency [#153](https://github.com/flekschas/regl-scatterplot/issues/153) -- Fix: run CI workflows on Ubuntu to ensure the `sed` replacement call works properly [#153](https://github.com/flekschas/regl-scatterplot/issues/153) - -## 1.8.4 - -- Fix a regression with the point opacity introduced in [v1.7.1](#1.7.1) - -## 1.8.3 - -- Fix typo in draw option type (renamed `focus` to `filter`) [#148](https://github.com/flekschas/regl-scatterplot/issues/148) - -## 1.8.2 - -- Improve hover detection - -## 1.8.1 - -- Fix: add ability to set `aspectRatio` in the constructor -- Fix: add missing type definition for `aspectRatio` -- Fix: extend `opacity` type to correctly allow `number[]` - -## 1.8.0 - -- Add `scatterplot.getScreenPosition(pointIdx)` to retrieve the screen position of a point by its index. - -## 1.7.1 - -- Improve data type inference of the z/w values and allow to explicitely specify their data type via `draw(newPoints, { zDataType: 'categorical', wDataType: 'continuous' })` - -## 1.7.0 - -- Add `preventFilterReset` option to `draw()` to allow re-drawing while keeping the current point filter. [#136](https://github.com/flekschas/regl-scatterplot/pull/136) -- Add ability to hover, select, and filter points immediately when calling `draw(points, { hover: 0, select: [1, 2], filter: [0, 2, 3] })`. Immediately hovering, selecting, or filtering points avoids a filter that can occur when first drawing points and then hovering, selecting, or filtering points subsequently. [#142](https://github.com/flekschas/regl-scatterplot/pull/142) -- Add missing `filteredPoints` type definition. [#139](https://github.com/flekschas/regl-scatterplot/pull/139) -- Add missing `selectedPoints` type definition. -- Fix drawing a single connecting line between points [#125](https://github.com/flekschas/regl-scatterplot/issues/125) -- Fix drawing a single point connection [#141](https://github.com/flekschas/regl-scatterplot/pull/141) -- Fix `draw()`'s promise resolution when `showPointConnections` is `true`. The promise is now resolved after both, the points and point connections, have been drawn. -- Set minimum Node version to `16` and minimum npm version to `7`. You might still be able to use `regl-scatterplot` with older version but it's not advised. - -## 1.6.10 - -- Fix `scatterplot.destroy()` to properly remove all event listeners bound during instance creation. [#135](https://github.com/flekschas/regl-scatterplot/pull/135) - -## v1.6.9 - -- Fix empty `select([])` handling [#132](https://github.com/flekschas/regl-scatterplot/issues/132) - -## v1.6.8 - -- Fix `filter()` to allow filtering out all points [#122](https://github.com/flekschas/regl-scatterplot/issues/122) -- Add `isPointsFiltered` to `get()` to allow determining if any points have been filtered out - -## v1.6.7 - -- Fix `zoomToPoints` behavior when points are not initialized [#123](https://github.com/flekschas/regl-scatterplot/issues/123) -- Add `isDestroyed` and `isPointsDrawn` to `get()` - -## v1.6.6 - -- Improve type annotations of the `select` event ([#119](https://github.com/flekschas/regl-scatterplot/issues/119)) -- Add type annotations for the `filter` and `unfilter` events - -## v1.6.5 - -- Fix typing issue related to `subscribe()` ([#117](https://github.com/flekschas/regl-scatterplot/issues/117)) - -## v1.6.4 - -- Fix a point hovering issue ([#112](https://github.com/flekschas/regl-scatterplot/issues/112)) - -## v1.6.3 - -- Fix an issue with repeated zooming to points -- Improve lasso on long press start - -## v1.6.2 - -- Fix a build regression from updating to Rollup v3 - -## v1.6.1 - -- Update third party libraries -- Improve lasso long press indicator styling -- Fix an issue where a lasso with less than three control points - -## v1.6.0 - -- Add the ability to filter down points via `scatterplot.filter(pointIdxs)`. This can be useful if you need to temporarily need to hide points without having to re-instantiate the regl-scatterplot instance. E.g., when calling `scatterplot.filter([0, 1, 2])`, only the first, second, and third point will remain visible. All other points (and their related point connections) will be visually and interactively hidden. - - To reset the filter call `scatterplot.unfilter()` or `scatterplot.filter([])`. - - https://user-images.githubusercontent.com/932103/222810324-3e048176-fd1d-4ede-a836-511c548f09ff.mp4 - -- Add the ability to retrieve selected and filtered point indices via `scatterplot.get('selectedPoints')` and `scatterplot.get('filteredPoints')` respectively. - -## v1.5.1 - -- Refactor lasso manager to support SSR ([#101](https://github.com/flekschas/regl-scatterplot/issues/101)) -- Fix a glitch where the scatterplot instance is destroyed after a `scatterplot.draw()` was called but before `scatterplot.draw()` finished. ([#101](https://github.com/flekschas/regl-scatterplot/issues/101)) - -## v1.5.0 - -- Add the ability to lasso select point upon long press via `scatterplot.set('lassoOnLongPress', true)`. -- Fix type issues ([#98](https://github.com/flekschas/regl-scatterplot/issues/98)) - -## v1.4.2 - -- Enforce the canvas width and height to be at least 1px to prevent view operations from breaking. - -## v1.4.1 - -- Bump `dom-2d-camera` to publish view updates on camera tweens ([#95](https://github.com/flekschas/regl-scatterplot/issues/95)) - -## v1.4.0 - -- Add zooming via the following four methods. All four methods supported animated transition just like `draw()`. - 1. `scatterplot.zoomToLocation(target, distance)` for zooming to a specific point location - 2. `scatterplot.zoomToArea(rectangle)` for zooming to an area specified by a rectangular bounding box - 3. `scatterplot.zoomToPoints(pointIndices)` for zooming to a set of points - 4. `scatterplot.zoomToOrigin()` for zooming to the origin - -## v1.3.2 - -- Add `scatterplot.isSupported` and `renderer.isSupported` as read-only properties to expose if all GL extensions are supported and enabled in the user's browser (#90) -- Add `checkSupport()` as a globally exported function for users to check if their browser supports and has enabled all required GL extensions (#90) - -## v1.3.1 - -- Add a missing `select` event name to the type definition (#87) - -## v1.3.0 - -- Add properties `opacityInactiveScale` and `opacityInactiveMax` to enable de-emphasizing unselected points and highlight selected points. The final point opacity is now set to `min(opacityInactiveMax, currentOpacity) * opacityInactiveScale` when at least one point is selected. By default `opacityInactiveScale` and `opacityInactiveMax` are set to `1`. I.e., the default behavior did not change. - -## v1.2.3 - -- Properly initialize new x/y scales upon calling `set()` - -## v1.2.2 - -- Fix a minor issue in `destroy()` that prevented disconnecting resize listeners - -## v1.2.1 - -- Update dom-2d-camera to fix internal tests - -## v1.2.0 - -- Outsource WebGL renderer to improve instancing: You can now use a single shared WebGL renderer (via `createRenderer()`) to power multiple scatter plot instances. See https://flekschas.github.io/regl-scatterplot/multiple-instances.html. -- Add `scatterplot.redraw()` to enforce a redrawing of the scene. This can be necessary when you manually updated the camera. -- Add `scatterplot.view(cameraView, { preventEvent })` as a shorthand for setting the scatter plot's camera view. The `preventEvent` option enables synchronizing multiple scatter plot instances. See https://flekschas.github.io/regl-scatterplot/multiple-instances.html. -- Allow passing typed arrays to `scatterplot.draw({ x, y, z, w })`. - -**Breaking changes:** - -- `scatterplot.export()` is now returning an [ImageData](https://developer.mozilla.org/en-US/docs/Web/API/ImageData) object for better utility. - -## v1.1.1 - -- Fix incorrect opacity handling (#74) - -## v1.1.0 - -- Add `scatterplot.get('pointsInView')` to retrieve the indices of the points currently visible within the view (#72). Shoutout to [@dulex123](https://github.com/dulex123) for his PR! -- Add `scatterplot.get('points')` to retrieve all currently drawn points. -- Add an example for demonstrating how labels can be rendered. The demo using `scatterplot.get('pointsInView')` to determine when to render text labels. See https://flekschas.github.io/regl-scatterplot/text-labels.html - -## v1.0.0 - -Woohoo 🥳 It's time to release v1! Nothing dramatic changed in this release but I felt that the library/API is now stable enough. Also, a big shoutout to [@manzt](https://github.com/manzt) and [@japrescott](https://github.com/japrescott) for their PRs. - -- Support drawing columnar data `scatterplot.draw({ x: [...], y: [...], ... })` (#59) -- Fix the rendering issue with with Safari 14 (#45) -- Replace webpack with vite (#64) - -## v0.19.2 - -- Fix an issue with not properly publishing the pointout event (#58) - -## v0.19.1 - -- Simplify drawing loop by using `regl.frame` and bailing out of when nothing needs to be redrawn -- Update regl-line to be compatible with regl v2 - -## v0.19.0 - -- Ensure inter buffers and viewports are properly updated on every draw call. - -**Breaking changes:** - -- Improve the handling of the connection order by switching from a structured 5th component to a 6th component. - - Previously to provide a specific order, the 5th component had to be a tuple of `[lineComponentId, orderIndex]`. With this update the 5th component will always just be `lineComponentId` and the 6th will be `orderIndex`. - -## v0.18.7 - -- Avoid text selection when lassoing - -## v0.18.6 - -- Optimize density-based opacity encoding - -## v0.18.5 - -- Fix an issue with the lasso position when the page is scrollable (#50) - -## v0.18.4 - -- Fix an issues when programmatically trying to `select()` or `hover()` non-existing points - -## v0.18.3 - -- Harmonize `hover(pointIdx, { showReticleOnce, preventEvent })` with `select()` API by allowing it to prevent the `pointover` and `pointout` from being published. - -## v0.18.2 - -- Add two events: `init` and `destroy` -- Add `lassoLineWidth` to allow adjusting the lasso line width -- Fix an issue with normalizing RGBA values -- Fix a camera issue when lassoing in non-`panZoom` mouse mode - -## v0.18.1 - -- Rename `showRecticle` to `showReticle` and `recticleColor` to `reticleColor` (#47) -- Fix reticle glitches by updating `regl-line` (#46) - -## v0.18.0 - -- Add density-based dynamic point opacity via `opacityBy: 'density'`. See - [dynamic-opacity.html](https://flekschas.github.io/regl-scatterplot/dynamic-opacity.html) for an example. - -## v0.17.1 - -- Add [`scatterplot.export`](README.md#scatterplot.export) for exporting the current view as pixels. -- Add default canvas width/height (`'auto'`) to fix an issue on high-dpi monitors that do not style the canvas element (#41) -- Add resize handler so when width/height is set to `'auto'` the canvas element is automatically resized on `resize` and `orientationchange` events. -- Improve framebuffer rendering and add `gamma` prop to allow controlling the opacity blending (#42) - -## v0.17.0 - -- Add the ability to color point connections by their segment via `pointConnectionColorBy: 'segment'` -- Fix an issue with normalizing RGB(A) values -- Avoid the unnecessary use of the logical-assignment-operators (#39) - -## v0.16.2 - -- Stop calling `camera.refresh()` as that is unnecessary since `v1.2.2` -- Avoid empty lasso events -- Fix incorrectly initialized `pointConnectionColorBy`, `pointConnectionOpacityBy`, and `pointConnectionSizeBy` -- Fix an issue with the color conversion to RGBA -- Fix an issue blurring an active point connection - -## v0.16.1 - -- Allow inheriting `pointConnectionColor` from `pointColor` by setting `pointConnectionColor: 'inherit'`. Same for `pointConnectionColorActive` and `pointConnectionColorHover`. -- Fix incorrectly initialized `opacity` -- Fix incorrectly initialized `colorBy`, `opacityBy`, and `sizeBy` -- Fix not assigned `pointConnectionOpacity` -- Rename `pointConnectionOpacitySelection` and `pointConnectionSizeSelected` to `pointConnectionOpacityActive` and `pointConnectionSizeActive` for consistency - -## v0.16.0 - -- Allow the point-associated data values to be either categorical or continuous instead of enforcing one to be categorical and the other one to be continuous. For continuous data, assign [0,1]-normalized data as the third or forth component of a point. For categorical data, assign an integer-based data. For instance, if a point looks `[1, 2, 3, 4]` we assume that the first (`3`) and second (`4`) data value is categorical. If you would instead have points like `[1, 2, 0.33, 0.44]` where the third and forth component are within [0,1] then we would assume that those components represent continuous data. For backward compatibility, `colorBy: 'category'` refers to coloring by the third component and `colorBy 'value'` refers to the forth component. Additionall, you can now reference the third components via `value1`, `valueA`, `valueZ`, or `z` and the forth component via`value2`, `valueB`, `valueW`, or `w`. - -- Add the ability to connect points visually via `draw(points, { connectPoints: true })`. This assumes that your points have a 5th component that identifies the point connection. Currently the order of points as they appear in `points` defines the order of how they would be connected. So assuming you have: - - ```javascript - // prettier-ignore - scatterplot.draw([ - 1, 1, 0, 0, 0, - 2, 2, 0, 0, 0, - 3, 3, 0, 0, 1, - 4, 4, 0, 0, 1, - 5, 5, 0, 0, 0, - ], { connectPoints: true }); - ``` - - Then we would connext the points as follows: - - ``` - 1 -> 2 -> 5 - 3 -> 4 - ``` - - For an example see [example/connected-points.js](example/connected-points.js). - -- Add support for multi-selections by holding down CMD (by default) during click- or lasso-selections. The modifier key for multi-selections can be adjusted via `scatterplot.set({ keyMap: { merge: 'ctrl' } })` -- Add `performanceMode` to allow drawing up to 20 million points -- Add `opacityBy` to allow encoding one of the two data properties as the point opacity. - -- Fix an issue with the point size between devices with different pixel ratios -- Fix an issue with detecting points when using variable point sizes -- Fix an issue that drew the background image before it was loaded - -**Breaking changes:** - -- Removed the following deplicated properties: - - `background` (use `backgroundColor` instead) - - `distance` (use `cameraDistance` instead) - - `rotation` (use `cameraRotation` instead) - - `target` (use `cameraTarget` instead) - - `view` (use `cameraView` instead) - -## v0.15.1 - -- Make sure the `keyMap` is properly initiated. -- Fix a memory leak by properly destroying the camera on `scatterplot.destroy()`. -- Add test for rotation, key mapping, and the lasso initiator - -## v0.15.0 - -- Add `mouseMode` for switching betweem mouse modes programmatically. Currently supported modes are `panZoom`, `lasso`, and `rotate`. -- Add `keyMap` for remapping modifier key-induced actions. Available modifier keys are `alt`, `shift`, `ctrl`, `cmd`, and `meta`. Available actions are `lasso` and `rotate`. -- Add `lassoInitiator` (boolean) for enabling a way to lasso points without having to use a modifier key. When activated, you can click into the void and a circle will appear. You can then start lassoing by mousing down + holding onto the circle and dragging. Since clicking into the void can be challenging when working with many points you can also long clicking anywhere and the circle for initiating the lasso will appear anywhere. -- Improve point selection - -## v0.14.0 - -- Add `lassoStart`, `lassoExtend`, and `lassoEnd` events - -**Breaking changes:** - -- Renamed event `background-image-ready` to `backgroundImageReady` for consistency -- Switched to asynchronously broadcasted events to decouple regl-scatterplot's execution flow from the event handler. You can switch back to the old behavior if you like by initializing the scatterplot via `createScatterplot({ syncEvents: true })` - -## v0.13.0 - -- Add support for transitioning points via `scatterplot.draw(updatedPoints, { transition: true})` -- Add support for size encoding the points' category or value via `scatterplot.set({ sizeBy })` - -## v0.12.0 - -- Add `deselectOnDblClick` and `deselectOnEscape` to allow disabling deselection on double click or escape when set to `false` (#31) -- Fix an issue updating the x and y scale domains (#30) - -## v0.11.0 - -- Allow synchronizing D3 x and y scales with the scatterplot view. See [README.md](README.md#synchronize-d3-x-and-y-scales-with-the-scatterplot-view) for more details. (#29) - -## v0.10.1 - -- Make sure `backgroundImage` supports base64-encoded images -- Fix missing texture destruction before recreating the texture (#22) - -## v0.10.0 - -- Add `lassoClearEvent` property to allow customizing when the lasso is cleared. -- Add `preventEvent` option to `scatterplot.select()` and `scatterplot.deselect()` to prevent publishing the `select` and `deselect` events -- Add Promise-based return value to `scatterplot.draw()` to enable the parent application to determine when the points were drawn -- Add support for `get('lassoMinDelay')` and `get('lassoMinDist')` - -## v0.9.1 - -- Only listen on mouse down events within the instance's canvas element (#16) - -## v0.9.0 - -- Renames `target`, `distance`, `rotation`, and `view` to `cameraTarget`, `cameraDistance`, `cameraRotation`, and `cameraView` -- Add getter and setter for `cameraTarget`, `cameraDistance`, `cameraRotation`, and `cameraView` -- Fix setting initial camera position (#15) -- Improve documentation on how to color points (#14) - -## v0.8.0 - -- Add background to lasso -- Fix horizontally-flipped background image (#13) -- Rename the `background` property to `backgroundColor` for clarity -- Split the `colors` property into `pointColor`, `pointColorActive`, and `pointColorHover` for clarity -- Update camera - -## v0.7.6 - -- Increase floating point precision -- Fix #5 - -## v0.7.5 - -- Add `clear()` to clear the scatter plot -- Update the camera on refresh -- Fix issue when drawing new points: do not wrap setting new points with withRaf(). Only wrap the pure draw call! -- Fix a regression from removed scroll library - -## v0.7.4 - -- Increase floating point precision (#5) -- Fix a rare glitch in the lasso selection where the lasso would be drawn with a far away point -- Smoothify lasso by lowering the min delay and min dist -- Update 2D camera and many dev packages -- Remove the minified ESM build as it's unnecessary - -## v0.7.3 - -- Fix glitch in the npm release of `v0.7.2`. - -## v0.7.2 - -- Provide proper ESM instead of pointing to the source code. - -## v0.7.1 - -- Replaced `hover` event with `pointover` and `pointout` to be able to know when a point is not hovered anymore. - -## v0.7.0 - -- Allow changing the lasso smoothness via `set({ lassoMinDelay, lassoMinDist })` where `lassoMinDelay` is the minimum number of milliseconds between mousemove events before the lasso is extended and `lassoMinDist` is the minimum number of pixels the mouse has to move. - -## v0.6.0 - -- Simplify API: `style()`, `attr()`, `scatterplot.canvas`, `scatterplot.regl`, and `scatterplot.version` are merged into `get()` and `set()`. The function signature is identical to `style()` and `attr()` so all you have to do is rename. -- Add recticle. It's not shown by default but can be activated with `set({ showRecticle, recticleColor })`. -- Fix a regression that caused interrupted panning - -## v0.5.1 - -- Fix a bug in categorical color encoding - -## v0.5.0 - -- Set default aspect ratio to 1. It can be changed via `attr({ aspectRatio })` -- Add property to set `lassoColor` via `style({ lassoColor })` -- Expose helper (`createTextureFromUrl`) for creating a texture from an image URL -- Expose regl instance via `scatterplot.regl` -- Replace `mouse-position` and `mouse-pressed` with internal code -- Avoid click selections upon mousedown + mousemove + mouseup -- Add tests for all public API endpoints -- Fix several smaller bugs - -## v0.4.0 - -- Use a combination of linear and log2 scaling for point size -- Add support for background images -- Add API documentation -- Switch to single quotes -- Export version - -## v0.3.3 - -- Add endpoint for changing the background color -- Allow setting view on initialization -- Remove event listeners on `destroy()` -- Rename `camera` event to `view` and publish the view matrix -- Fix issues with setting colors -- Fix resetting view - -## v0.3.2 - -- Update third party libraries -- Switch to browser-based tests -- Set more strict linting - -## v0.3.1 - -- Fix nasty floating point issue when working with large textures (> 100.000 points) -- Make point size dependent on zoom level - -## v0.3.0 - -- Optimize rendering: up to about 500K points render fine. Usable for up to 1M points. -- Add support for one categories and one value per point for color encoding. -- Add visual outline for selected points for better highlighting. -- Add test setup and some base tests. -- Many bug fixes and under the hood improvements. - -## v0.2.0 - -- Add fast lasso selection -- Support rotations - -## v0.1.0 - -- Initial working version. **Warning:** this version is not optimized yet and only works fluidly for up to 50.000 points. diff --git a/CITATION.cff b/CITATION.cff deleted file mode 100644 index 37401f17..00000000 --- a/CITATION.cff +++ /dev/null @@ -1,28 +0,0 @@ -cff-version: "1.2.0" -authors: -- family-names: Lekschas - given-names: Fritz - orcid: "https://orcid.org/0000-0001-8432-4835" -doi: 10.5281/zenodo.7796642 -message: If you use this software, please cite our article in the - Journal of Open Source Software. -preferred-citation: - authors: - - family-names: Lekschas - given-names: Fritz - orcid: "https://orcid.org/0000-0001-8432-4835" - date-published: 2023-04-11 - doi: 10.21105/joss.05275 - issn: 2475-9066 - issue: 84 - journal: Journal of Open Source Software - publisher: - name: Open Journals - start: 5275 - title: "Regl-Scatterplot: A Scalable Interactive JavaScript-based - Scatter Plot Library" - type: article - url: "https://joss.theoj.org/papers/10.21105/joss.05275" - volume: 8 -title: "Regl-Scatterplot: A Scalable Interactive JavaScript-based - Scatter Plot Library" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 0ef20872..00000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,37 +0,0 @@ -# Contributing to Regl-Scatterplot - -:wave: Welcome and thank you for considering to contribute to `regl-scatterplot`. - -In this guide you will get an overview of the contribution workflow from opening an issue, creating a PR, reviewing, and merging the PR. - -## Getting Started - -To get an overview of the tool, checkout the [demos](https://flekschas.github.io/regl-scatterplot/) and read the [README](README.md). In particular, you might find the following sections helpful: - -- [Getting started](https://github.com/flekschas/regl-scatterplot#getting-started) -- [API](https://github.com/flekschas/regl-scatterplot#api) - - [Properties](https://github.com/flekschas/regl-scatterplot#properties) - - [Events](https://github.com/flekschas/regl-scatterplot#events) -- [Trouble shooting](https://github.com/flekschas/regl-scatterplot#trouble-shooting) - -## Help! I am lost... :sob: - -Head over to our [discussion board](https://github.com/flekschas/regl-scatterplot/discussions) and we're happy to help. - -## Reporting Issues :bug: or Feature Requests :bulb: - -If you discover a bug in `regl-scatterplot` or have an idea for a new feature, please [submit a new issue](https://github.com/flekschas/regl-scatterplot/issues/new). Make sure the issue is following either the [bug report](/.github/ISSUE_TEMPLATE/bug.md) or [feature request](/.github/ISSUE_TEMPLATE/enhancement.md) template. - -For questions on how to use `regl-scatterplot`, please use the [discussion board](https://github.com/flekschas/regl-scatterplot/discussions). - -## Contribute Code :nail_care: - -If you have a concrete plan how to improve `regl-scatterplot` and have created a [ticket](#reporting-issues-or-feature-requests), send us your pull requests! If you're wondering what a pull request (PR) is, please check out [GitHub's how to](https://help.github.com/articles/using-pull-requests/). - -A maintainer will review your pull request. Once the pull request is approved and passes continuous integration checks, we will merge it and add it to the next scheduled release. - -#### Pull Request Checklist :white_check_mark: - -- Ensure that your pull request answers the relevant questions in the [pull request template](/.github/PULL_REQUEST_TEMPLATE.md). -- Ensure that your pull requests successfully passes all continuous integration tests with GH Actions. -- Optionally, if your pull request introduces a new feature, it'd be great to add a new demo to `/example`. diff --git a/LICENSE b/LICENSE deleted file mode 100644 index cd96150f..00000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2018 Fritz Lekschas - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index c90ad8e3..00000000 --- a/README.md +++ /dev/null @@ -1,1201 +0,0 @@ -# WebGl 2D Scatterplot with Regl - -[![npm version](https://img.shields.io/npm/v/regl-scatterplot.svg?color=1a8cff&style=flat-square)](https://www.npmjs.com/package/regl-scatterplot) -[![build status](https://img.shields.io/github/actions/workflow/status/flekschas/regl-scatterplot/build.yml?branch=master&color=139ce9&style=flat-square)](https://github.com/flekschas/regl-scatterplot/actions?query=workflow%3Abuild) -[![file size](http://img.badgesize.io/https://unpkg.com/regl-scatterplot/dist/regl-scatterplot.min.js?compression=gzip&color=0dacd4&style=flat-square)](https://bundlephobia.com/result?p=regl-scatterplot) -[![DOI](https://img.shields.io/badge/JOSS-10.21105/joss.05275-06bcbe.svg?style=flat-square)](https://doi.org/10.21105/joss.05275) -[![regl-scatterplot demo](https://img.shields.io/badge/demo-online-00cca9.svg?style=flat-square)](https://flekschas.github.io/regl-scatterplot/) - -A highly-scalable pan-and-zoomable scatter plot library that uses WebGL through [Regl](https://github.com/regl-project/regl). This library sacrifices feature richness for speed to allow rendering up to **20 million points** (depending on your hardware of course) including fast lasso selection. Further, the [footprint of regl-scatterplot](https://bundlephobia.com/result?p=regl-scatterplot) is kept small. **NEW:** Python lovers please see [jscatter](https://github.com/flekschas/jupyter-scatter): a Jupyter Notebook/Lab widget that uses regl-scatterplot. - -

- -

- -**Demo:** https://flekschas.github.io/regl-scatterplot/ - -**Live Playground:** https://observablehq.com/@flekschas/regl-scatterplot - -**Default Interactions:** - -- **Pan**: Click and drag your mouse. -- **Zoom**: Scroll vertically. -- **Rotate**: While pressing ALT, click and drag your mouse. -- **Select a dot**: Click on a dot with your mouse. -- **Select multiple dots**: - - - While pressing SHIFT, click and drag your mouse. All items within the lasso will be selected. - - Upon activating the lasso on long press (i.e., `lassoOnLongPress: true`) you can click and hold anywhere on the plot, and a circle will appear at your mouse cursor. Wait until the circle is closed, then drag your mouse to start lassoing. -
Click here to see how it works -

- - ![Lassso on Long Press](https://github.com/user-attachments/assets/5e6a7c2a-5686-4711-9b3d-36d45a96ca69) - -

-
- - - Upon activating the lasso initiator (i.e., `lassoInitiator: true`) you can click into the background and a circle will appear under your mouse cursor. Click inside this circle and drag your mouse to start lassoing. -
Click here to see how it works -

- - ![Lasso Initiator](https://user-images.githubusercontent.com/932103/106489598-f42c4480-6482-11eb-8286-92a9956e1d20.gif) - -

-
- -- **Deselect**: Double-click onto an empty region. - -Note, you can remap `rotate` and `lasso` to other modifier keys via the `keyMap` option! - -**Supported Visual Encodings:** - -- x/y point position (obviously) -- categorical and continuous color encoding (including opacity) -- categorical and continuous size encoding -- point connections (stemming, for example, from time series data) - -## Install - -```sh -npm i regl-scatterplot -``` - -_FYI, if you're using `npm` version prior to 7, you have to install regl-scatterplot's peer dependencies (`regl` and `pub-sub-es`) manually._ - -## Getting started - -### Basic Example - -```javascript -import createScatterplot from 'regl-scatterplot'; - -const canvas = document.querySelector('#canvas'); - -const { width, height } = canvas.getBoundingClientRect(); - -const scatterplot = createScatterplot({ - canvas, - width, - height, - pointSize: 5, -}); - -const points = new Array(10000) - .fill() - .map(() => [-1 + Math.random() * 2, -1 + Math.random() * 2, color]); - -scatterplot.draw(points); -``` - -**IMPORTANT:** Your points positions need to be normalized to `[-1, 1]` (normalized device coordinates). Why? Regl-scatterplot is designed to be a lower-level library, whose primary purpose is speed. As such it expects you to normalize the data upfront. - -### Color, Opacity, and Size Encoding - -In regl-scatterplot, points can be associated with two data values. These two values are defined as the third and forth component of the point quadruples (`[x, y, value, value]`). For instance: - -```javascript -scatterplot.draw([ - [0.2, -0.1, 0, 0.1337], - [0.3, 0.1, 1, 0.3371], - [-0.9, 0.8, 2, 0.3713], -]); -``` - -These two values can be visually encoded as the color, opacity, or the size. Integers are treated as categorical data and floats that range between [0, 1] are treated as continuous values. In the example above, the first point value would be treated as categorical data and the second would be treated as continuous data. - -In the edge case that you have continuous data but all data points are either `0` or `1` you can manually set the data type via the [`zDataType` and `wDatatype` draw options](#scatterplot.draw). - -To encode the two point values use the `colorBy`, `opacityBy`, and `sizeBy` property as follows: - -```javascript -scatterplot.set({ - opacityBy: 'valueA', - sizeBy: 'valueA', - colorBy: 'valueB', -}); -``` - -In this example we would encode the first categorical point values (`[0, 1, 2]`) as the point opacity and size. The second continuous point values (`[0.1337, 0.3317, 0.3713]`) would be encoded as the point color. - -The last thing we need to tell regl-scatterplot is what those point values should be translated to. We do this by specifying a color, opacity, and size map as an array of colors, opacities, and sizes as follows: - -```javascript -scatterplot.set({ - pointColor: ['#000000', '#111111', ..., '#eeeeee', '#ffffff'], - pointSize: [2, 4, 8], - opacity: [0.5, 0.75, 1], -}); -``` - -You can encode a point data value in multiple ways. For instance, as you can see in the example above, the categorical fist data value is encoded via the point size _and_ opacity. - -**What if I have more than two values associated to a point?** Unfortunately, this isn't supported currently. In case you're wondering, this limitation is due to how we store the point data. The whole point state is encoded as an RGBA texture where the x and y coordinate are stored as the red and green color components and the first and second data value are stored in the blue and alpha component of the color. However, this limitation might be addressed in future versions so make sure to check back or, even better, start a pull request! - -**Why can't I specify a range function instead of a map?** Until we have implemented enough scale functions in the shader it's easier to let _you_ pre-compute the map. For instance, if you wanted to encode a continuous values on a log scale of point size, you can simply do `pointSize: Array(100).fill().map((v, i) => Math.log(i + 1) + 1)`. - -[Code Example](example/index.js) | [Demo](https://flekschas.github.io/regl-scatterplot/index.html) - -### Connecting points - -You can connect points visually using spline curves by adding a 5th component to your point data and setting `showPointConnections: true`. - -The 5th component is needed to identify which points should be connected. By default, the order of how the points are connected is defined by the order in which the points appear in your data. - -```javascript -const points = [ - [1, 1, 0, 0, 0], - [2, 2, 0, 0, 0], - [3, 3, 0, 0, 1], - [4, 4, 0, 0, 1], - [5, 5, 0, 0, 0], -]; -``` - -In the example above, the points would be connected as follows: - -``` -0 -> 1 -> 4 -2 -> 3 -``` - -**Line Ordering:** - -To explicitely define or change the order of how points are connected, you can define a 6th component as follows: - -```javascript -const points = [ - [1, 1, 0, 0, 0, 2], - [2, 2, 0, 0, 0, 0], - [3, 3, 0, 0, 1, 1], - [4, 4, 0, 0, 1, 0], - [5, 5, 0, 0, 0, 1], -]; -``` - -would lead tp the following line segment ordering: - -``` -1 -> 4 -> 0 -3 -> 2 -``` - -Note, to visualize the point connections, make sure `scatterplot.set({ showPointConnection: true })` is set! - -[Code Example](example/connected-points.js) | [Demo](https://flekschas.github.io/regl-scatterplot/connected-points.html) - -### Synchronize D3 x and y scales with the scatterplot view - -Under the hood regl-scatterplot uses a [2D camera](https://github.com/flekschas/dom-2d-camera), which you can either get via `scatterplot.get('camera')` or `scatterplot.subscribe('view', ({ camera }) => {})`. You can use the camera's `view` matrix to compute the x and y scale domains. However, since this is tedious, regl-scatterplot allows you to specify D3 x and y scales that will automatically be synchronized. For example: - -```javascript -const xScale = scaleLinear().domain([0, 42]); -const yScale = scaleLinear().domain([-5, 5]); -const scatterplot = createScatterplot({ - canvas, - width, - height, - xScale, - yScale, -}); -``` - -Now whenever you pan or zoom, the domains of `xScale` and `yScale` will be updated according to your current view. Note, the ranges are automatically set to the width and height of your `canvas` object. - -[Code Example](example/axes.js) | [Demo](https://flekschas.github.io/regl-scatterplot/axes.html) - -### Translating Point Coordinates to Screen Coordinates - -Imagine you want to render additional features on top of points points, for which you need to know where on the canvas points are drawn. To determine the screen coordinates of points you can use [D3 scales](#synchronize-d3-x-and-y-scales-with-the-scatterplot-view) and `scatterplot.get('pointsInView')` as follows: - -```javascript -const points = Array.from({ length: 100 }, () => [Math.random() * 42, Math.random()]); -const [xScale, yScale] = [scaleLinear().domain([0, 42]), scaleLinear().domain([0, 1])]; - -const scatterplot = createScatterplot({ ..., xScale, yScale }); -scatterplot.draw(points); - -scatterplot.subscribe('view', ({ xScale, yScale }) => { - console.log('pointsInScreenCoords', scatterplot.get('pointsInView').map((pointIndex) => [ - xScale(points[pointIndex][0]), - yScale(points[pointIndex][1]) - ])); -}); -``` - -[Code Example](example/text-labels.js) | [Demo](https://flekschas.github.io/regl-scatterplot/text-labels.html) - -### Transition Points - -To make sense of two different states of points, it can help to show an animation by transitioning the points from their first to their second location. To do so, simple `draw()` the new points as follows: - -```javascript -const initialPoints = Array.from({ length: 100 }, () => [Math.random() * 42, Math.random()]); -const finalPoints = Array.from({ length: 100 }, () => [Math.random() * 42, Math.random()]); - -const scatterplot = createScatterplot({ ... }); -scatterplot.draw(initialPoints).then(() => { - scatterplot.draw(finalPoints, { transition: true }); -}) -``` - -It's important that the number of points is the same for the two `draw()` calls. Also note that the point correspondence is determined by their index. - -[Code Example](example/transition.js) | [Demo](https://flekschas.github.io/regl-scatterplot/transition.html) - -### Zoom to Points - -Sometimes it can be useful to programmatically zoom to a set of points. In regl-scatterplot you can do this with the `zoomToPoints()` method as follows: - -```javascript -const points = Array.from({ length: 100 }, () => [Math.random() * 42, Math.random()]); - -const scatterplot = createScatterplot({ ... }); -scatterplot.draw(initialPoints).then(() => { - // We'll select the first five points... - scatterplot.select([0, 1, 2, 3, 4]); - // ...and zoom into them - scatterplot.zoomToPoints([0, 1, 2, 3, 4], { transition: true }) -}) -``` - -Note that the zooming can be smoothly transitioned when `{ transition: true }` is passed to the function. - -[Code Example](example/multiple-instances.js) | [Demo](https://flekschas.github.io/regl-scatterplot/multiple-instances.html) - -### Update only the Z/W point coordinates - -If you only want to update the z/w points coordinates that can be used for encoding te point color, opacity, or size, you can improve the redrawing performance by reusing the existing spatial index, which is otherwise recomputed every time you draw new points. - -```javascript -const x = (length) => Array.from({ length }, () => -1 + Math.random() * 2); -const y = (length) => Array.from({ length }, () => -1 + Math.random() * 2); -const z = (length) => Array.from({ length }, () => Math.round(Math.random())); -const w = (length) => Array.from({ length }, () => Math.random()); - -const numPoints = 1000000; -const points = { - x: x(numPoints), - y: y(numPoints), - z: z(numPoints), - w: w(numPoints), -}; - -const scatterplot = createScatterplot({ ... }); -scatterplot.draw(initialPoints).then(() => { - // After the initial draw, we retrieve and save the KDBush spatial index. - const spatialIndex = scatterplot.get('spatialIndex'); - setInterval(() => { - // Update Z and W values - points.z = z(numPoints); - points.w = w(numPoints); - - // We redraw the scatter plot with the updates points. Importantly, since - // the x/y coordinates remain unchanged we pass in the saved spatial index - // to avoid having to re-index the points. - scatterplot.draw(points, { spatialIndex }); - }, 2000); -}) -``` - -## API - -### Constructors - -# createScatterplot(options = {}) - -**Returns:** a new scatterplot instance. - -**Options:** is an object that accepts any of the [properties](#properties). - -# createRenderer(options = {}) - -**Returns:** a new [Renderer](#renderer) instance with appropriate extensions being enabled. - -**Options:** is an object that accepts any of the following optional properties: - -- `regl`: a Regl instance to be used for rendering. -- `canvas`: background color of the scatterplot. -- `gamma`: the gamma value for alpha blending. - -# createRegl(canvas) - -**Returns:** a new [Regl](https://github.com/regl-project/regl) instance with appropriate extensions being enabled. - -**Canvas:** the canvas object on which the scatterplot will be rendered on. - -# createTextureFromUrl(regl, url) - -_DEPRECATED! Use [`scatterplot.createTextureFromUrl()`](#scatterplot.createTextureFromUrl) instead._ - -### Methods - -# scatterplot.draw(points, options) - -Sets and draws `points`. Importantly, the `points`' x and y coordinates need to have been normalized to `[-1, 1]` (normalized device coordinates). The two additional values (`valueA` and `valueB`) need to be normalized to `[0, 1]` (if they represent continuous data) or `[0, >1]` (if they represent categorical data). - -Note that repeatedly calling this method without specifying `points` will not clear previously set points. To clear points use [`scatterplot.clear()`](#scatterplot.clear). - -**Arguments:** - -- `points` can either be an array of quadruples (row-oriented) or an object of arrays (column-oriented): - - For row-oriented data, each nested array defines a point data of the form `[x, y, ?valueA, ?valueB, ?line, ?lineOrder]`. `valueA` and `valueB` are optional and can be used for [color, opacity, or size encoding](#property-by). `line` and `lineOrder` are also optional and can be used to [visually connect points by lines](#connecting-points). - - For column-oriented data, the object must be of the form `{ x: [], y: [], ?valueA: [], ?valueB: [], ?line: [], ?lineOrder: [] }`. -- `options` is an object with the following properties: - - `showPointConnectionsOnce` [default: `false`]: if `true` and if points contain a `line` component/dimension the points will be visually conntected. - - `transition` [default: `false`]: if `true` and if the current number of points equals `points.length`, the current points will be transitioned to the new points - - `transitionDuration` [default: `500`]: the duration in milliseconds over which the transition should occur - - `transitionEasing` [default: `cubicInOut`]: the easing function, which determines how intermediate values of the transition are calculated - - `preventFilterReset` [default: `false`]: if `true` and if the number of new points is the same as the current number of points, the current point filter will not be reset - - `hover` [default: `undefined`]: a shortcut for [`hover()`](#scatterplot.hover). This option allows to programmatically hover a point by specifying a point index - - `select` [default: `undefined`]: a shortcut for [`select()`](#scatterplot.select). This option allows to programmatically select points by specifying a list of point indices - - `filter` [default: `undefined`]: a shortcut for [`filter()`](#scatterplot.filter). This option allows to programmatically filter points by specifying a list of point indices - - `zDataType` [default: `undefined`]: This option allows to manually set the data type of the z/valueA value to either `continuous` or `categorical`. By default the data type is [determined automatically](#color-opacity-and-size-encoding). - - `wDataType` [default: `undefined`]: This option allows to manually set the data type of the w/valyeB value to either `continuous` or `categorical`. By default the data type is [determined automatically](#color-opacity-and-size-encoding). - - `spatialIndex` [default: `undefined`]: This option allows to pass in the array buffer of [KDBush](https://github.com/mourner/kdbush) to skip the manual creation of the spatial index. Caution: only use this option if you know what you're doing! The point data is not validated against the spatial index. - -**Returns:** a Promise object that resolves once the points have been drawn or transitioned. - -**Examples:** - -```javascript -const points = [ - [ - // The relative X position in [-1,1] (normalized device coordinates) - 0.9, - // The relative Y position in [-1,1] (normalized device coordinates) - 0.3, - // The category, which defaults to `0` if `undefined` - 0, - // A continuous value between [0,1], which defaults to `0` if `undefined` - 0.5, - ], -]; - -scatterplot.draw(points); - -// You can now do something else like changing the point size etc. - -// If we want to animate the transition of our point from above to another -// x,y position, we can also do this by drawing a new point while enableing -// transition via the `options` argument. -scatterplot.draw([[0.6, 0.6, 0, 0.6]], { transition: true }); - -// Let's unset the points. To do so, pass in an empty array to `draw()`. -// Or alternatively, call `scatterplot.clear()` -scatterplot.draw([]); - -// You can also specify the point data in a column-oriented format. The -// following call will draw three points: (1,3), (2,2), and (3,1) -scatterplot.draw({ - x: [1, 2, 3], - y: [3, 2, 1], -}); - -// Finally, you can also specify which point will be hovered, which points will -// be selected, and which points will be filtered. These options are useful to -// avoid a flicker which would occur if `hover()`, `select()`, and `filter()` -// are called after `draw()`. -scatterplot.draw( - { x: [1, 2, 3], y: [3, 2, 1] }, - { hover: 0, selected: [0, 1], filter: [0, 2] } -); -``` - -# scatterplot.redraw() - -Redraw the scatter plot at the next animation frame. - -Note, that regl-scatterlot automatically redraws the scatter plot whenever the -view changes in some ways. So theoretically, there should never be a need to -call this function! - -# scatterplot.clear() - -Clears previously drawn points, point connections, and annotations. - -# scatterplot.clearPoints() - -Clears previously drawn points and point connections. - -# scatterplot.clearPointConnections() - -Clears previously point connections. - -# scatterplot.drawAnnotations(annotations) - -Draw line-based annotations of the following kind in normalized device coordinates: - -- Horizontal line -- Vertical line -- Rectangle -- Polygon - -**Arguments:** - -- `annotations` is expected to be a list of the following objects: - - For horizontal lines: `{ y: number, x1?: number, x2?: number, lineColor?: Color, lineWidth?: number }` - - For vertical lines: `{ x: number, y1?: number, y2?: number, lineColor?: Color, lineWidth?: number }` - - For rectangle : `{ x1: number, y1: number, x2: number, y2: number, lineColor?: Color, lineWidth?: number }` or `{ x: number, y: number, width: number, height: number, lineColor?: Color, lineWidth?: number }` - - For polygons or lines: `{ vertices: [number, number][], lineColor?: Color, lineWidth?: number }` - -**Returns:** a Promise object that resolves once the annotations have been drawn or transitioned. - -**Examples:** - -```javascript -const scatterplot = createScatterplot({ - ..., - annotationLineColor: [1, 1, 1, 0.1], // Default line color - annotationLineWidth: 1, // Default line width -}); - -scatterplot.draw({ - x: Array.from({ length: 10000 }, () => -1 + Math.random() * 2), - y: Array.from({ length: 10000 }, () => -1 + Math.random() * 2), -}); - -scatterplot.drawAnnotations([ - // Horizontal line - { y: 0 }, - // Vertical line - { x: 0 }, - // Rectangle - { - x1: -0.5, y1: -0.5, x2: 0.5, y2: 0.5, - lineColor: [1, 0, 0, 0.33], - lineWidth: 2, - }, - // Polygon - { - vertices: [[-1, 0], [0, 1], [1, 0], [0, -1], [-1, 0]], - lineColor: [1, 1, 0, 0.33], - lineWidth: 3, - }, -]); -``` - -# scatterplot.clearAnnotations() - -Clears previously drawn annotations. - -# scatterplot.get(property) - -**Arguments:** - -- `property` is a string referencing a [property](#properties). - -**Returns:** the property value. - -# scatterplot.set(properties = {}) - -**Arguments:** - -- `properties` is an object of key-value pairs. [See below for a list of all properties.](#properties) - -# scatterplot.select(points, options = {}) - -Select some points, such that they get visually highlighted. This will trigger a `select` event unless `options.preventEvent === true`. - -**Arguments:** - -- `points` is an array of point indices referencing the points that you want to select. -- `options` [optional] is an object with the following properties: - - `preventEvent`: if `true` the `select` will not be published. - -**Examples:** - -```javascript -// Let's say we have three points -scatterplot.draw([ - [0.1, 0.1], - [0.2, 0.2], - [0.3, 0.3], -]); - -// To select the first and second point we have to do -scatterplot.select([0, 1]); -``` - -# scatterplot.lassoSelect(vertices, options = {}) - -Programmatically select points within a polygon region. This enables automated point selection without manual lasso interaction. This will trigger a `select` event (and `lassoEnd` event) unless `options.preventEvent === true`. - -**Arguments:** - -- `vertices` is an array of `[x, y]` coordinate pairs defining the polygon (minimum 3 vertices required). Coordinates are in **data space** by default (requires `xScale` and `yScale`), or **GL space** if `options.isGl === true`. -- `options` [optional] is an object with the following properties: - - `merge`: if `true`, add the selected points to the current selection instead of replacing it. - - `remove`: if `true`, remove the selected points from the current selection. - - `isGl`: if `true`, interpret vertices as GL space coordinates (NDC). If `false` (default), interpret vertices as data space coordinates. - - `preventEvent`: if `true` the `select` and `lassoEnd` events will not be published. - -**Notes:** - -- Polygons are automatically closed if the first and last vertices differ. -- Data space coordinates require `xScale` and `yScale` to be defined during scatterplot initialization. -- GL space coordinates work without scales and are useful for direct NDC coordinate selection. - -**Examples:** - -```javascript -import { scaleLinear } from 'd3-scale'; - -// Create scatterplot with scales for data space coordinates -const scatterplot = createScatterplot({ - canvas, - xScale: scaleLinear().domain([0, 100]), - yScale: scaleLinear().domain([0, 100]), -}); - -// Draw points (internally stored in NDC, but we think in data space) -scatterplot.draw([ - [-0.8, -0.8], // corresponds to data coords ~[10, 10] - [0.8, 0.8], // corresponds to data coords ~[90, 90] - [0, 0], // corresponds to data coords [50, 50] -]); - -// Select points within a triangular region (data space coordinates) -scatterplot.lassoSelect([ - [10, 20], - [50, 80], - [90, 30] -]); - -// Select points within a rectangle, merging with current selection -scatterplot.lassoSelect( - [ - [0, 0], - [100, 0], - [100, 100], - [0, 100] - ], - { merge: true } -); - -// Remove points in a polygon from the current selection -scatterplot.lassoSelect( - [ - [40, 40], - [60, 40], - [60, 60], - [40, 60] - ], - { remove: true } -); - -// Use GL space coordinates (useful without scales) -scatterplot.lassoSelect( - [ - [-0.5, -0.5], - [0.5, -0.5], - [0.5, 0.5], - [-0.5, 0.5] - ], - { isGl: true } -); -``` - -# scatterplot.deselect(options = {}) - -Deselect all selected points. This will trigger a `deselect` event unless `options.preventEvent === true`. - -# scatterplot.filter(points, options = {}) - -Filter down the currently drawn points, such that all points that are not included in the filter are visually and interactivelly hidden. This will trigger a `filter` event unless `options.preventEvent === true`. - -Note: filtering down points can affect previously selected points. Selected points that are filtered out are also deselected. - -**Arguments:** - -- `points` is an array of indices referencing the points that you want to filter down to. -- `options` [optional] is an object with the following properties: - - `preventEvent`: if `true` the `select` will not be published. - -**Examples:** - -```javascript -// Let's say we have three points -scatterplot.draw([ - [0.1, 0.1], - [0.2, 0.2], - [0.3, 0.3], -]); - -// To only show the first and second point we have to do -scatterplot.filter([0, 1]); -``` - -# scatterplot.unfilter(options = {}) - -Reset previously filtered out points. This will trigger an `unfilter` event unless `options.preventEvent === true`. - -# scatterplot.hover(point, options = {}) - -Programmatically hover a point, such that it gets visually highlighted. This will trigger a `pointover` or `pointout` event unless `options.preventEvent === true`. - -**Arguments:** - -- `point` is the point index referring to the point you want to hover. -- `options` [optional] is an object with the following properties: - - `showReticleOnce`: if `true` the reticle will be shown once, even if `showReticle === false`. - - `preventEvent`: if `true` the `pointover` and `pointout` will not be published. - -**Examples:** - -```javascript -scatterplot.draw([ - [0.1, 0.1], - [0.2, 0.2], - [0.3, 0.3], -]); - -scatterplot.hover(1); // To hover the second point -``` - -**Arguments:** - -- `options` [optional] is an object with the following properties: -- `preventEvent`: if `true` the `deselect` will not be published. - -# scatterplot.zoomToPoints(points, options = {}) - -Zoom to a set of points - -**Arguments:** - -- `points` is an array of point indices. -- `options` [optional] is an object with the following properties: - - `padding`: [default: `0`]: relative padding around the bounding box of the points to zoom to - - `transition` [default: `false`]: if `true`, the camera will smoothly transition to its new position - - `transitionDuration` [default: `500`]: the duration in milliseconds over which the transition should occur - - `transitionEasing` [default: `cubicInOut`]: the easing function, which determines how intermediate values of the transition are calculated - -**Examples:** - -```javascript -// Let's say we have three points -scatterplot.draw([ - [0.1, 0.1], - [0.2, 0.2], - [0.3, 0.3], -]); - -// To zoom to the first and second point we have to do -scatterplot.zoomToPoints([0, 1]); -``` - -# scatterplot.zoomToOrigin(options = {}) - -Zoom to the original camera position. This is similar to resetting the view - -**Arguments:** - -- `options` [optional] is an object with the following properties: - - `transition` [default: `false`]: if `true`, the camera will smoothly transition to its new position - - `transitionDuration` [default: `500`]: the duration in milliseconds over which the transition should occur - - `transitionEasing` [default: `cubicInOut`]: the easing function, which determines how intermediate values of the transition are calculated - -# scatterplot.zoomToLocation(target, distance, options = {}) - -Zoom to a specific location, specified in normalized device coordinates. This function is similar to [`scatterplot.lookAt()`](#scatterplot.lookAt), however, it allows to smoothly transition the camera position. - -**Arguments:** - -- `target` the camera target given as a `[x, y]` tuple. -- `distance` the camera distance to the target given as a number between `]0, Infinity]`. The smaller the number the closer moves the camera, i.e., the more the view is zoomed in. -- `options` [optional] is an object with the following properties: - - `transition` [default: `false`]: if `true`, the camera will smoothly transition to its new position - - `transitionDuration` [default: `500`]: the duration in milliseconds over which the transition should occur - - `transitionEasing` [default: `cubicInOut`]: the easing function, which determines how intermediate values of the transition are calculated - -**Examples:** - -```javascript -scatterplot.zoomToLocation([0.5, 0.5], 0.5, { transition: true }); -// => This will make the camera zoom into the top-right corner of the scatter plot -``` - -# scatterplot.zoomToArea(rectangle, options = {}) - -Zoom to a specific area specified by a recangle in normalized device coordinates. - -**Arguments:** - -- `rectangle` the rectangle must come in the form of `{ x, y, width, height }`. -- `options` [optional] is an object with the following properties: - - `transition` [default: `false`]: if `true`, the camera will smoothly transition to its new position - - `transitionDuration` [default: `500`]: the duration in milliseconds over which the transition should occur - - `transitionEasing` [default: `cubicInOut`]: the easing function, which determines how intermediate values of the transition are calculated - - `preventFilterReset` [default: `false`]: if `true` and if the number of new points equals the number of already drawn points, the point filter set is not being reset. - -**Examples:** - -```javascript -scatterplot.zoomToArea( - { x: 0, y: 0, width: 1, height: 1 }, - { transition: true } -); -// => This will make the camera zoom into the top-right corner of the scatter plot -``` - -# scatterplot.getScreenPosition(pointIdx) - -Get the screen position of a point - -**Arguments:** - -- `pointIdx` is a point indix. - -**Examples:** - -```javascript -// Let's say we have a 100x100 pixel scatter plot with three points -const scatterplot = createScatterplot({ width: 100, height: 100 }); -scatterplot.draw([ - [-1, -1], - [0, 0], - [1, 1], -]); - -// To retrieve the screen position of the second point you can call. If we -// haven't panned and zoomed, the returned position should be `50, 50` -scatterplot.getScreenPosition(1); -// => [50, 50] -``` - -# scatterplot.lookAt(view, options = {}) - -Update the camera's view matrix to change the viewport. This will trigger a `view` event unless `options.preventEvent === true`. - -_Note, this API is a shorthand to `scatterplot.set({ 'cameraView': view })` with the additional features of allowing to prevent `view` events._ - -# scatterplot.destroy() - -Destroys the scatterplot instance by disposing all event listeners, the pubSub -instance, regl, and the camera. - -# scatterplot.refresh() - -Refreshes the viewport of the scatterplot's regl instance. - -# scatterplot.reset(options) - -Sets the view back to the initially defined view. This will trigger a `view` event unless `options.preventEvent === true`. - -# scatterplot.export(options) - -**Arguments:** - -- `options` is an object for customizing the render settings during the export: - - `scale`: is a float number allowning to adjust the exported image size - - `antiAliasing`: is a float allowing to adjust the anti-aliasing factor - - `pixelAligned`: is a Boolean allowing to adjust the point alignment with the pixel grid - -**Returns:** an [`ImageData`](https://developer.mozilla.org/en-US/docs/Web/API/ImageData) object if `option` is `undefined`. Otherwise it returns a Promise resolving to an [`ImageData`](https://developer.mozilla.org/en-US/docs/Web/API/ImageData) object. - -# scatterplot.subscribe(eventName, eventHandler) - -Subscribe to an event. - -**Arguments:** - -- `eventName` needs to be [a valid event name](#events). -- `eventHandler` needs to be a callback function that can receive the payload. - -**Returns:** an unsubscriber object that can be passed into [`unsubscribe()`](#scatterplot.unsubscribe). - -# scatterplot.unsubscribe(eventName, eventHandler) - -Unsubscribe from an event. See [`scatterplot.subscribe()`](#scatterplot.subscribe) for a list of all -events. - -# scatterplot.createTextureFromUrl(url) - -**Returns:** a Promise that resolves to a [Regl texture](https://github.com/regl-project/regl/blob/gh-pages/API.md#textures) that can be used, for example, as the [background image](#). - -**url:** the URL to an image. - -### Properties - -You can customize the scatter plot according to the following properties that -can be read and written via [`scatterplot.get()`](#scatterplot.get) and [`scatterplot.set()`](#scatterplot.set). - -| Name | Type | Default | Constraints | Settable | Nullifiable | -| ------------------------------------- | -------------------------------------------- | ----------------------------------- | --------------------------------------------------------------- | -------- | ----------- | -| canvas | object | `document.createElement('canvas')` | | `false` | `false` | -| regl | [Regl](https://github.com/regl-project/regl) | `createRegl(canvas)` | | `false` | `false` | -| renderer | [Renderer](#renderer) | `createRenderer()` | | `false` | `false` | -| syncEvents | boolean | `false` | | `false` | `false` | -| version | string | | | `false` | `false` | -| spatialIndex | ArrayBuffer | | | `false` | `false` | -| spatialIndexUseWorker | undefined or boolean | `undefined` | | `true` | `false` | -| width | int or str | `'auto'` | `'auto'` or > 0 | `true` | `false` | -| height | int or str | `'auto'` | `'auto'` or > 0 | `true` | `false` | -| aspectRatio | float | `1.0` | > 0 | `true` | `false` | -| backgroundColor | string or array | rgba(0, 0, 0, 1) | hex, rgb, rgba | `true` | `false` | -| backgroundImage | function | `null` | Regl texture | `true` | `true` | -| camera | object | | See [dom-2d-camera](https://github.com/flekschas/dom-2d-camera) | `false` | `false` | -| cameraTarget | tuple | `[0, 0]` | | `true` | `false` | -| cameraDistance | float | `1` | > 0 | `true` | `false` | -| cameraRotation | float | `0` | | `true` | `false` | -| cameraView | Float32Array | `[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]` | | `true` | `false` | -| cameraIsFixed | boolean | `false` | | `true` | `false` | -| colorBy | string | `null` | See [data encoding](#property-by) | `true` | `true` | -| sizeBy | string | `null` | See [data encoding](#property-by) | `true` | `true` | -| opacityBy | string | `null` | See [data encoding](#property-by) | `true` | `true` | -| pointOrder | int[] | `null` | Array of point indices defining draw order | `true` | `true` | -| deselectOnDblClick | boolean | `true` | | `true` | `false` | -| deselectOnEscape | boolean | `true` | | `true` | `false` | -| opacity | float | `1` | Must be in ]0, 1] | `true` | `false` | -| opacityInactiveMax | float | `1` | Must be in [0, 1] | `true` | `false` | -| opacityInactiveScale | float | `1` | Must be in [0, 1] | `true` | `false` | -| points | tuple[] | `[[0.5, 2.3], ...]` | | `false` | `false` | -| selectedPoints | int[] | `[4, 2]` | | `false` | `false` | -| filteredPoints | int[] | `[4, 2]` | | `false` | `false` | -| pointsInView | int[] | `[1, 2, 12]` | | `false` | `false` | -| pointColor | quadruple | `[0.66, 0.66, 0.66, 1]` | single value or list of hex, rgb, rgba | `true` | `false` | -| pointColorActive | quadruple | `[0, 0.55, 1, 1]` | single value or list of hex, rgb, rgba | `true` | `false` | -| pointColorHover | quadruple | `[1, 1, 1, 1]` | single value or list of hex, rgb, rgba | `true` | `false` | -| pointOutlineWidth | int | `2` | >= 0 | `true` | `false` | -| pointSize | int | `6` | > 0 | `true` | `false` | -| pointSizeSelected | int | `2` | >= 0 | `true` | `false` | -| showPointConnection | boolean | `false` | | `true` | `false` | -| pointConnectionColor | quadruple | `[0.66, 0.66, 0.66, 0.2]` | | `true` | `false` | -| pointConnectionColorActive | quadruple | `[0, 0.55, 1, 1]` | | `true` | `false` | -| pointConnectionColorHover | quadruple | `[1, 1, 1, 1]` | | `true` | `false` | -| pointConnectionColorBy | string | `null` | See [data encoding](#property-point-conntection-by) | `true` | `false` | -| pointConnectionOpacity | float | `0.1` | | `true` | `false` | -| pointConnectionOpacityActive | float | `0.66` | | `true` | `false` | -| pointConnectionOpacityBy | string | `null` | See [data encoding](#property-point-conntection-by) | `true` | `false` | -| pointConnectionSize | float | `2` | | `true` | `false` | -| pointConnectionSizeActive | float | `2` | | `true` | `false` | -| pointConnectionSizeBy | string | `null` | See [data encoding](#property-point-conntection-by) | `true` | `false` | -| pointConnectionMaxIntPointsPerSegment | int | `100` | | `true` | `false` | -| pointConnectionTolerance | float | `0.002` | | `true` | `false` | -| pointScaleMode | string | `'asinh'` | `'asinh'`, `'linear'`, or `'constant'` | `true` | `false` | -| lassoType | string | `'freeform'` | `'freeform'`, `'rectangle'`, or `'brush'` | `true` | `false` | -| lassoColor | quadruple | rgba(0, 0.667, 1, 1) | hex, rgb, rgba | `true` | `false` | -| lassoLineWidth | float | 2 | >= 1 | `true` | `false` | -| lassoMinDelay | int | 15 | >= 0 | `true` | `false` | -| lassoMinDist | int | 4 | >= 0 | `true` | `false` | -| lassoClearEvent | string | `'lassoEnd'` | `'lassoEnd'` or `'deselect'` | `true` | `false` | -| lassoInitiator | boolean | `false` | | `true` | `false` | -| lassoInitiatorElement | object | the lasso dom element | | `false` | `false` | -| lassoInitiatorParentElement | object | `document.body` | | `true` | `false` | -| lassoLongPressIndicatorParentElement | object | `document.body` | | `true` | `false` | -| lassoOnLongPress | boolean | `false` | | `true` | `false` | -| lassoLongPressTime | int | `750` | | `true` | `false` | -| lassoLongPressAfterEffectTime | int | `500` | | `true` | `false` | -| lassoLongPressEffectDelay | int | `100` | | `true` | `false` | -| lassoLongPressRevertEffectTime | int | `250` | | `true` | `false` | -| lassoBrushSize | int | `24` | | `true` | `false` | -| showReticle | boolean | `false` | `true` or `false` | `true` | `false` | -| reticleColor | quadruple | rgba(1, 1, 1, .5) | hex, rgb, rgba | `true` | `false` | -| xScale | function | `null` | must follow the D3 scale API | `true` | `true` | -| yScale | function | `null` | must follow the D3 scale API | `true` | `true` | -| actionKeyMap | object | `{ remove: 'alt': rotate: 'alt', merge: 'cmd', lasso: 'shift' }` | See the notes below | `true` | `false` | -| mouseMode | string | `'panZoom'` | `'panZoom'`, `'lasso'`, or `'rotate'` | `true` | `false` | -| performanceMode | boolean | `false` | can only be set during initialization! | `true` | `false` | -| gamma | float | `1` | to control the opacity blending | `true` | `false` | -| isDestroyed | boolean | `false` | | `false` | `false` | -| isPointsDrawn | boolean | `false` | | `false` | `false` | -| isPointsFiltered | boolean | `false` | | `false` | `false` | -| annotationLineColor | string or quadruple | `[1, 1, 1, 0.1]` | hex, rgb, rgba | `true` | `false` | -| annotationLineWidth | number | `1` | | `true` | `false` | -| annotationHVLineLimit | number | `1000` | the extent of horizontal or vertical lines | `true` | `false` | -| antiAliasing | number | `0.5` | higher values result in more blurry points | `true` | `false` | -| pixelAligned | number | `false` | if true, points are aligned with the pixel grid | `true` | `false` | -| renderPointsAsSquares | boolean | `false` | true of `performanceMode` is true. can only be set on init! | `true` | `false` | -| disableAlphaBlending | boolean | `false` | true of `performanceMode` is true. can only be set on init! | `true` | `false` | - -# Notes: - -- An attribute is considered _nullifiable_ if it can be unset. Attributes that - are **not nullifiable** will be ignored if you try to set them to a falsy - value. For example, if you call `scatterplot.attr({ width: 0 });` the width - will not be changed as `0` is interpreted as a falsy value. - -- By default, the `width` and `height` are set to `'auto'`, which will make the - `canvas` stretch all the way to the bounds of its clostest parent element with - `position: relative`. When set to `'auto'` the library also takes care of - resizing the canvas on `resize` and `orientationchange` events. - -- The background of the scatterplot is transparent, i.e., you have to control - the background with CSS! `background` is used when drawing the - outline of selected points to simulate the padded border only. - -- The background image must be a Regl texture. To easily set a remote - image as the background please use [`createTextureFromUrl`](#const-texture--createTextureFromUrlregl-url-isCrossOrigin). - -- The scatterplot understan 4 colors per color representing 4 states, representing: - - - normal (`pointColor`): the normal color of points. - - active (`pointColorActive`): used for coloring selected points. - - hover (`pointColorHover`): used when mousing over a point. - - background (`backgroundColor`): used as the background color. - -- Points can currently by colored by _category_ and _value_. - -- The size of selected points is given by `pointSize + pointSizeSelected` - -- By default, events are published asynchronously to decouple regl-scatterplot's - execution flow from the event consumer's process. However, you can enable - synchronous event broadcasting at your own risk via - `createScatterplot({ syncEvents: true })`. This property can't be changed - after initialization! - -- If you need to draw more than 2 million points, you might want to set - `performanceMode` to `true` during the initialization to boost the - performance. In performance mode, points will be drawn as simple squares and - alpha blending is disabled. This should allow you to draw up to 20 million - points (or more depending on your hardware). Make sure to reduce the - `pointSize` as you render more and more points (e.g., `0.25` for 20 million - works for me) to ensure good performance. You can also enable squared points - and disable alpha blending individually via `renderPointsAsSquares` and - `disableAlphaBlending` respectively. - -# colorBy, opacityBy, sizeBy: - -To visual encode one of the two point values set `colorBy`, `opacityBy`, or `sizeBy` -to one of the following values referencing the third or forth component of your -points. To reference the third component you can use `category` (only for -backwards compatibility), `value1`, `valueA`, `valueZ`, or `z`. To reference -the forth component use `value` (only for backwards compatibility), `value2`, -`valueB`, `valueW`, or `w`. - -**Density-based opacity encoding:** In addition, the opacity can dynamically be -set based on the point density and zoom level via `opacityBy: 'density'`. As an -example go to [dynamic-opacity.html](https://flekschas.github.io/regl-scatterplot/dynamic-opacity.html). -The implementation is an extension of [Ricky Reusser's awesome notebook](https://observablehq.com/@rreusser/selecting-the-right-opacity-for-2d-point-clouds). -Huuuge kudos Ricky! 🙇‍♂️ - -# pointOrder: - -By default, points are drawn in the order they appear in the input data. Since depth testing is disabled, later-drawn points render on top of earlier ones. To control the draw order, set `pointOrder` to an array of point indices. Points are drawn in array order, so the last index renders on top. Any indices not included in the array are appended in sequential order. - -```javascript -// Ensure point 3 is drawn on top -scatterplot.set({ pointOrder: [0, 1, 2, 4, 3] }); - -// Reset to default input order -scatterplot.set({ pointOrder: null }); -``` - -The point order is respected when [filtering](#scatterplot.filter), and resets automatically when `draw()` is called with a different number of points. - -# pointConnectionColorBy, pointConnectionOpacityBy, and pointConnectionSizeBy: - -In addition to the properties understood by [`colorBy`, etc.](#property-by), -`pointConnectionColorBy`, `pointConnectionOpacityBy`, and `pointConnectionSizeBy` -also understand `"inherit"` and `"segment"`. When set to `"inherit"`, the value -will be inherited from its point-specific counterpart. When set to `"segment"`, -each segment of a point connection will be encoded separately. This allows you -to, for instance, color connection by a gradient from the start to the end of -each line. - -# lassoInitiator: - -When setting `lassoInitiator` to `true` you can initiate the lasso selection -without the need to hold down a modifier key. Simply click somewhere into the -background and a circle will appear under your mouse cursor. Now click into the -circle and drag you mouse to start lassoing. You can additionally invoke the -lasso initiator circle by a long click on a dot. - -![Lasso Initiator](https://user-images.githubusercontent.com/932103/106489598-f42c4480-6482-11eb-8286-92a9956e1d20.gif) - -You don't like the look of the lasso initiator? No problem. Simple get the DOM -element via `scatterplot.get('lassoInitiatorElement')` and adjust the style -via JavaScript. E.g.: `scatterplot.get('lassoInitiatorElement').style.background = 'green'`. - -# ActionKeyMap: - -The `actionKeyMap` property is an object defining which actions are enabled when -holding down which modifier key. E.g.: `{ lasso: 'shift' }`. Acceptable actions -are `lasso`, `rotate`, `merge` (for selecting multiple items by merging a series -of lasso or click selections), and `remove` (for removing selected points). -Acceptable modifier keys are `alt`, `cmd`, `ctrl`, `meta`, `shift`. - -You can also use the `actionKeyMap` option to disable the lasso selection and -rotation by setting `actionKeyMap` to an empty object. - -# Examples: - -```javascript -// Set width and height -scatterplot.set({ width: 300, height: 200 }); - -// get width -const width = scatterplot.get('width'); - -// Set the aspect ratio of the scatterplot. This aspect ratio is referring to -// your data source and **not** the aspect ratio of the canvas element! By -// default it is assumed that your data us following a 1:1 ratio and this ratio -// is preserved even if your canvas element has some other aspect ratio. But if -// you wanted you could provide data that's going from [0,2] in x and [0,1] in y -// in which case you'd have to set the aspect ratio as follows to `2`. -scatterplot.set({ aspectRatio: 2.0 }); - -// Set background color to red -scatterplot.set({ backgroundColor: '#00ff00' }); // hex string -scatterplot.set({ backgroundColor: [255, 0, 0] }); // rgb array -scatterplot.set({ backgroundColor: [255, 0, 0, 1.0] }); // rgba array -scatterplot.set({ backgroundColor: [1.0, 0, 0, 1.0] }); // normalized rgba - -// Set background image to an image -scatterplot.set({ backgroundImage: 'https://server.com/my-image.png' }); -// If you need to know when the image was loaded you have two options. First, -// you can listen to the following event -scatterplot.subscribe( - 'backgroundImageReady', - () => { - console.log('Background image is now loaded and rendered!'); - }, - 1 -); -// or you load the image yourself as follows -const backgroundImage = await scatterplot.createTextureFromUrl( - 'https://server.com/my-image.png' -); -scatterplot.set({ backgroundImage }); - -// Color by -scatterplot.set({ colorBy: 'category' }); - -// Set color map -scatterplot.set({ - pointColor: ['#ff0000', '#00ff00', '#0000ff'], - pointColorActive: ['#ff0000', '#00ff00', '#0000ff'], // optional - pointColorHover: ['#ff0000', '#00ff00', '#0000ff'], // optional -}); - -// Set base opacity -scatterplot.set({ opacity: 0.5 }); - -// If you want to deemphasize unselected points (when some points are selected) -// you can rescale the unselected points' opacity as follows -scatterplot.set({ opacityInactiveScale: 0.5 }); - -// Set the width of the outline of selected points -scatterplot.set({ pointOutlineWidth: 2 }); - -// Set the base point size -scatterplot.set({ pointSize: 10 }); - -// Set the additional point size of selected points -scatterplot.set({ pointSizeSelected: 2 }); - -// Change the lasso color and make it very smooth, i.e., do not wait before -// extending the lasso (i.e., `lassoMinDelay = 0`) and extend the lasso when -// the mouse moves at least 1 pixel -scatterplot.set({ - lassoColor: [1, 1, 1, 1], - lassoMinDelay: 0, - lassoMinDist: 1, - // This will keep the drawn lasso until the selected points are deselected - lassoClearEvent: 'deselect', -}); - -// Activate reticle and set reticle color to red -scatterplot.set({ showReticle: true, reticleColor: [1, 0, 0, 0.66] }); -``` - -### Renderer - -The renderer class is responsible for rendering pixels onto the scatter plot's -canvas using WebGL via Regl. It's created automatically internally but you can -also create it yourself, which can be useful when you want to instantiate -multiple scatter plot instances as they can share one renderer. - -#### Renderer API - -# renderer.canvas - -The renderer's canvas instance. (Read-only) - -# renderer.gamma - -The renderer's gamma value. This value influences the alpha blending. - -# renderer.regl - -The renderer's regl instance. (Read-only) - -# renderer.onFrame(function) - -Add a function to be called on every animation frame. - -**Arguments:** - -- `function`: The function to be called on every animation frame. - -**Returns:** A function to remove the added function from the animation frame cycle. - -# renderer.refresh() - -Updates Regl's viewport, drawingBufferWidth, and drawingBufferHeight. - -# renderer.render(drawFunction, targetCanvas) - -Render Regl draw instructions into a target canvas using the renderer. - -**Arguments:** - -- `drawFunction`: The draw function that triggers Regl draw instructions -- `targetCanvas`: The canvas to rendering the final pixels into. - -### Events - -| Name | Trigger | Payload | -| -------------------- | ------------------------------------------ | ------------------------------------------------- | -| init | when the scatter plot is initialized | `undefined` | -| destroy | when the scatter plot is destroyed | `undefined` | -| backgroundImageReady | when the background image was loaded | `undefined` | -| pointOver | when the mouse cursor is over a point | pointIndex | -| pointOut | when the mouse cursor moves out of a point | pointIndex | -| select | when points are selected | `{ points }` | -| deselect | when points are deselected | `undefined` | -| filter | when points are filtered | `{ points }` | -| unfilter | when the point filter is reset | `undefined` | -| view | when the view has changes | `{ camera, view, isViewChanged, xScale, yScale }` | -| draw | when the plot was drawn | `{ camera, view, isViewChanged, xScale, yScale }` | -| drawing | when the plot is being drawn | `{ camera, view, isViewChanged, xScale, yScale }` | -| lassoStart | when the lasso selection has started | `undefined` | -| lassoExtend | when the lasso selection has extended | `{ coordinates }` | -| lassoEnd | when the lasso selection has ended | `{ coordinates }` | -| transitionStart | when points started to transition | `undefined` | -| transitionEnd | when points ended to transition | `createRegl(canvas)` | -| pointConnectionsDraw | when point connections were drawn | `undefined` | - -## Trouble Shooting - -#### Resizing the scatterplot - -The chances are high that you use the regl-scatterplot in a dynamically-resizable or interactive web-app. Please note that **regl-scatterplot doesn't not automatically resize** when the dimensions of its parent container change. It's your job to keep the size of regl-scatterplot and its parent element in sync. Hence, every time the size of the parent or `canvas` element changed, you have to call: - -```javascript -const { width, height } = canvas.getBoundingClientRect(); -scatterplot.set({ width, height }); -``` - -#### Using regl-scatterplot with Vue - -Related to the resizing, when conditionally displaying regl-scatterplot in Vue you might have to update the `width` and `height` when the visibility is changed. See [issue #20](https://github.com/flekschas/regl-scatterplot/issues/20#issuecomment-639377810) for an example. - -## Citation - -If you like `regl-scatterplot` and are using it in your research, we'd appreciate if you could cite our paper: - -```bibtex -@article {lekschas2023reglscatterplot, - author = {Lekschas, Fritz}, - title = {Regl-Scatterplot: A Scalable Interactive JavaScript-based Scatter Plot Library}, - journal = {Journal of Open Source Software}, - volume = {8}, - number = {84}, - pages = {5275}, - year = {2023}, - month = {4}, - doi = {10.21105/joss.05275}, - url = {https://doi.org/10.21105/joss.05275}, -} -``` diff --git a/annotations.html b/annotations.html new file mode 100644 index 00000000..d938bc05 --- /dev/null +++ b/annotations.html @@ -0,0 +1,444 @@ + + + + + + + Regl Scatterplot + + + + + + + + + + + + + +

Regl Scatterplot

+ +
+
+ +
+
+ + + diff --git a/assets/annotations-Cvv6-ZaP.js b/assets/annotations-Cvv6-ZaP.js new file mode 100644 index 00000000..ae9def8d --- /dev/null +++ b/assets/annotations-Cvv6-ZaP.js @@ -0,0 +1,4 @@ +import{c as p,a as M,b as f}from"./menu-CKBxhbUC.js";import"./vendor-DRFCw67i.js";const v=document.querySelector("#canvas");let l={x:[],y:[],z:[],w:[]},z=1e5,S=2,W=.33,s=[];const w=10,A=2,$=!0,b=[1,1,.878431373,.33],d=(t=0,o=1)=>{const r=1-Math.random(),n=Math.random();return Math.sqrt(-2*Math.log(r))*Math.cos(2*Math.PI*n)*o+t},E=({points:t})=>{if(s=t,s.length===1){const o=l.x[s[0]],r=l.y[s[0]],n=l.z[s[0]],c=l.w[s[0]];console.log(`Selected: ${t}`,`X: ${o} +Y: ${r} +Category: ${n} +Value: ${c}`)}},P=()=>{s=[]},e=p({canvas:v,lassoMinDelay:w,lassoMinDist:A,pointSize:S,opacity:W,showReticle:$,reticleColor:b,lassoOnLongPress:!0});M(e);console.log(`Scatterplot v${e.get("version")}`);e.subscribe("select",E);e.subscribe("deselect",P);const B=t=>{const o=(Math.log10(t)/Math.log10(1e5))**2,r=[{length:t*(7/16),cx:-.48,cy:.46,stdx:.05*o,stdy:.1*o},{length:t*(5/16),cx:.49,cy:.5,stdx:.07*o,stdy:.066*o},{length:t*(3/16),cx:.48,cy:-.51,stdx:.12*o,stdy:.05*o},{length:t*(1/16),cx:-.49,cy:-.51,stdx:.033*o,stdy:.033*o}];let n=[],c=[],i=[],y=[];return r.forEach(({length:a,cx:x,cy:u,stdx:g,stdy:m},C)=>{n=n.concat(Array.from({length:a},()=>d(x,g))),c=c.concat(Array.from({length:a},()=>d(u,m))),i=i.concat(Array.from({length:a},()=>C)),y=y.concat(Array.from({length:a},()=>Math.random()))}),{x:n,y:c,z:i,w:y}},h=t=>{l=B(t),e.draw(l)};f({scatterplot:e,setNumPoints:h});const D=["#3a78aa","#aa3a99"];e.set({colorBy:"category",pointColor:D});const q=["#009E73","#CC79A7","#56B4E9","#F0E442"];e.set({colorBy:"z",pointColor:q});h(z);e.drawAnnotations([{x:0,lineColor:[1,1,1,.1],lineWidth:1},{y:0,lineColor:[1,1,1,.1],lineWidth:1},{y:.5,x1:-.9,x2:.9,lineColor:[1,1,1,1],lineWidth:1},{x1:-1,y1:-1,x2:1,y2:1,lineColor:[1,1,1,.25],lineWidth:1},{x1:-.5,y1:-.5,x2:.5,y2:.5,lineColor:[1,1,1,.25],lineWidth:1},{x1:-.25,y1:-.25,x2:.25,y2:.25,lineColor:[1,1,1,.25],lineWidth:1},{vertices:[[-.66,-.5],[-.5,-.33],[-.33,-.45],[-.33,-.6],[-.5,-.7],[-.66,-.5]],lineColor:"#D55E00",lineWidth:1}]); diff --git a/assets/apache-arrow-Bq3lZMkH.js b/assets/apache-arrow-Bq3lZMkH.js new file mode 100644 index 00000000..30a55c72 --- /dev/null +++ b/assets/apache-arrow-Bq3lZMkH.js @@ -0,0 +1,4 @@ +import{_ as St,a as O,b as Ee,c as ie,d as B,S as R,B as Ne,e as zn}from"./vendor-DRFCw67i.js";const dn=new TextDecoder("utf-8"),Ni=dn.decode.bind(dn),Wr=new TextEncoder,Pi=i=>Wr.encode(i),Yr=i=>typeof i=="number",Hr=i=>typeof i=="boolean",J=i=>typeof i=="function",yt=i=>i!=null&&Object(i)===i,Be=i=>yt(i)&&J(i.then),_i=i=>yt(i)&&J(i[Symbol.iterator]),ji=i=>yt(i)&&J(i[Symbol.asyncIterator]),Li=i=>yt(i)&&yt(i.schema),kn=i=>yt(i)&&"done"in i&&"value"in i,Pn=i=>yt(i)&&J(i.stat)&&Yr(i.fd),jn=i=>yt(i)&&$i(i.body),$n=i=>"_getDOMStream"in i&&"_getNodeStream"in i,$i=i=>yt(i)&&J(i.cancel)&&J(i.getReader)&&!$n(i),Wn=i=>yt(i)&&J(i.read)&&J(i.pipe)&&Hr(i.readable)&&!$n(i),Jr=i=>yt(i)&&J(i.clear)&&J(i.bytes)&&J(i.position)&&J(i.setPosition)&&J(i.capacity)&&J(i.getBufferIdentifier)&&J(i.createLong),Wi=typeof SharedArrayBuffer<"u"?SharedArrayBuffer:ArrayBuffer;function Kr(i){const t=i[0]?[i[0]]:[];let e,n,s,r;for(let o,a,c=0,u=0,d=i.length;++cd+f.byteLength,0);let s,r,o,a=0,c=-1;const u=Math.min(t||Number.POSITIVE_INFINITY,n);for(const d=e.length;++cU(Int32Array,i),fn=i=>U(BigInt64Array,i),F=i=>U(Uint8Array,i),Ti=i=>(i.next(),i);function*Gr(i,t){const e=function*(s){yield s},n=typeof t=="string"||ArrayBuffer.isView(t)||t instanceof ArrayBuffer||t instanceof Wi?e(t):_i(t)?t:e(t);return yield*Ti((function*(s){let r=null;do r=s.next(yield U(i,r));while(!r.done)})(n[Symbol.iterator]())),new i}const Zr=i=>Gr(Uint8Array,i);function Yn(i,t){return St(this,arguments,function*(){if(Be(t))return yield O(yield O(yield*Ee(ie(Yn(i,yield O(t))))));const n=function(o){return St(this,arguments,function*(){yield yield O(yield O(o))})},s=function(o){return St(this,arguments,function*(){yield O(yield*Ee(ie(Ti((function*(a){let c=null;do c=a.next(yield c?.value);while(!c.done)})(o[Symbol.iterator]())))))})},r=typeof t=="string"||ArrayBuffer.isView(t)||t instanceof ArrayBuffer||t instanceof Wi?n(t):_i(t)?s(t):ji(t)?t:n(t);return yield O(yield*Ee(ie(Ti((function(o){return St(this,arguments,function*(){let a=null;do a=yield O(o.next(yield yield O(U(i,a))));while(!a.done)})})(r[Symbol.asyncIterator]()))))),yield O(new i)})}const qr=i=>Yn(Uint8Array,i);function Xr(i,t){let e=0;const n=i.length;if(n!==t.length)return!1;if(n>0)do if(i[e]!==t[e])return!1;while(++e(i.next(),i);function*Qr(i){let t,e=!1,n=[],s,r,o,a=0;function c(){return r==="peek"?wt(n,o)[0]:([s,n,a]=wt(n,o),s)}({cmd:r,size:o}=(yield null)||{cmd:"read",size:0});const u=Zr(i)[Symbol.iterator]();try{do if({done:t,value:s}=Number.isNaN(o-a)?u.next():u.next(o-a),!t&&s.byteLength>0&&(n.push(s),a+=s.byteLength),t||o<=a)do({cmd:r,size:o}=yield c());while(o0&&(s.push(r),c+=r.byteLength),e||a<=c)do({cmd:o,size:a}=yield yield O(u()));while(a0&&(s.push(F(r)),c+=r.byteLength),e||a<=c)do({cmd:o,size:a}=yield yield O(u()));while(a{})}get closed(){return this.reader?this.reader.closed.catch(()=>{}):Promise.resolve()}releaseLock(){this.reader&&this.reader.releaseLock(),this.reader=null}cancel(t){return B(this,void 0,void 0,function*(){const{reader:e,source:n}=this;e&&(yield e.cancel(t).catch(()=>{})),n&&n.locked&&this.releaseLock()})}read(t){return B(this,void 0,void 0,function*(){if(t===0)return{done:this.reader==null,value:new Uint8Array(0)};const e=yield this.reader.read();return!e.done&&(e.value=F(e)),e})}}const Di=(i,t)=>{const e=s=>n([t,s]);let n;return[t,e,new Promise(s=>(n=s)&&i.once(t,e))]};function no(i){return St(this,arguments,function*(){const e=[];let n="error",s=!1,r=null,o,a,c=0,u=[],d;function f(){return o==="peek"?wt(u,a)[0]:([d,u,c]=wt(u,a),d)}if({cmd:o,size:a}=(yield yield O(null))||{cmd:"read",size:0},i.isTTY)return yield yield O(new Uint8Array(0)),yield O(null);try{e[0]=Di(i,"end"),e[1]=Di(i,"error");do{if(e[2]=Di(i,"readable"),[n,r]=yield O(Promise.race(e.map(W=>W[2]))),n==="error")break;if((s=n==="end")||(Number.isFinite(a-c)?(d=F(i.read(a-c)),d.byteLength0&&(u.push(d),c+=d.byteLength)),s||a<=c)do({cmd:o,size:a}=yield yield O(f()));while(a{for(const[$t,$r]of W)i.off($t,$r);try{const $t=i.destroy;$t&&$t.call(i,ut),ut=void 0}catch($t){ut=$t||ut}finally{ut!=null?jr(ut):un()}})}})}var P;(function(i){i[i.V1=0]="V1",i[i.V2=1]="V2",i[i.V3=2]="V3",i[i.V4=3]="V4",i[i.V5=4]="V5"})(P||(P={}));var X;(function(i){i[i.Sparse=0]="Sparse",i[i.Dense=1]="Dense"})(X||(X={}));var H;(function(i){i[i.HALF=0]="HALF",i[i.SINGLE=1]="SINGLE",i[i.DOUBLE=2]="DOUBLE"})(H||(H={}));var ct;(function(i){i[i.DAY=0]="DAY",i[i.MILLISECOND=1]="MILLISECOND"})(ct||(ct={}));var I;(function(i){i[i.SECOND=0]="SECOND",i[i.MILLISECOND=1]="MILLISECOND",i[i.MICROSECOND=2]="MICROSECOND",i[i.NANOSECOND=3]="NANOSECOND"})(I||(I={}));var $;(function(i){i[i.YEAR_MONTH=0]="YEAR_MONTH",i[i.DAY_TIME=1]="DAY_TIME",i[i.MONTH_DAY_NANO=2]="MONTH_DAY_NANO"})($||($={}));var De;(function(i){i[i.BUFFER=0]="BUFFER"})(De||(De={}));var kt;(function(i){i[i.LZ4_FRAME=0]="LZ4_FRAME",i[i.ZSTD=1]="ZSTD"})(kt||(kt={}));let pe=class Vt{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsBodyCompression(t,e){return(e||new Vt).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsBodyCompression(t,e){return t.setPosition(t.position()+R),(e||new Vt).__init(t.readInt32(t.position())+t.position(),t)}codec(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt8(this.bb_pos+t):kt.LZ4_FRAME}method(){const t=this.bb.__offset(this.bb_pos,6);return t?this.bb.readInt8(this.bb_pos+t):De.BUFFER}static startBodyCompression(t){t.startObject(2)}static addCodec(t,e){t.addFieldInt8(0,e,kt.LZ4_FRAME)}static addMethod(t,e){t.addFieldInt8(1,e,De.BUFFER)}static endBodyCompression(t){return t.endObject()}static createBodyCompression(t,e,n){return Vt.startBodyCompression(t),Vt.addCodec(t,e),Vt.addMethod(t,n),Vt.endBodyCompression(t)}};class Hn{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}offset(){return this.bb.readInt64(this.bb_pos)}length(){return this.bb.readInt64(this.bb_pos+8)}static sizeOf(){return 16}static createBuffer(t,e,n){return t.prep(8,16),t.writeInt64(BigInt(n??0)),t.writeInt64(BigInt(e??0)),t.offset()}}let Jn=class{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}length(){return this.bb.readInt64(this.bb_pos)}nullCount(){return this.bb.readInt64(this.bb_pos+8)}static sizeOf(){return 16}static createFieldNode(t,e,n){return t.prep(8,16),t.writeInt64(BigInt(n??0)),t.writeInt64(BigInt(e??0)),t.offset()}},gt=class Ui{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsRecordBatch(t,e){return(e||new Ui).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsRecordBatch(t,e){return t.setPosition(t.position()+R),(e||new Ui).__init(t.readInt32(t.position())+t.position(),t)}length(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt64(this.bb_pos+t):BigInt("0")}nodes(t,e){const n=this.bb.__offset(this.bb_pos,6);return n?(e||new Jn).__init(this.bb.__vector(this.bb_pos+n)+t*16,this.bb):null}nodesLength(){const t=this.bb.__offset(this.bb_pos,6);return t?this.bb.__vector_len(this.bb_pos+t):0}buffers(t,e){const n=this.bb.__offset(this.bb_pos,8);return n?(e||new Hn).__init(this.bb.__vector(this.bb_pos+n)+t*16,this.bb):null}buffersLength(){const t=this.bb.__offset(this.bb_pos,8);return t?this.bb.__vector_len(this.bb_pos+t):0}compression(t){const e=this.bb.__offset(this.bb_pos,10);return e?(t||new pe).__init(this.bb.__indirect(this.bb_pos+e),this.bb):null}static startRecordBatch(t){t.startObject(4)}static addLength(t,e){t.addFieldInt64(0,e,BigInt("0"))}static addNodes(t,e){t.addFieldOffset(1,e,0)}static startNodesVector(t,e){t.startVector(16,e,8)}static addBuffers(t,e){t.addFieldOffset(2,e,0)}static startBuffersVector(t,e){t.startVector(16,e,8)}static addCompression(t,e){t.addFieldOffset(3,e,0)}static endRecordBatch(t){return t.endObject()}},Yt=class Ri{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsDictionaryBatch(t,e){return(e||new Ri).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsDictionaryBatch(t,e){return t.setPosition(t.position()+R),(e||new Ri).__init(t.readInt32(t.position())+t.position(),t)}id(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt64(this.bb_pos+t):BigInt("0")}data(t){const e=this.bb.__offset(this.bb_pos,6);return e?(t||new gt).__init(this.bb.__indirect(this.bb_pos+e),this.bb):null}isDelta(){const t=this.bb.__offset(this.bb_pos,8);return t?!!this.bb.readInt8(this.bb_pos+t):!1}static startDictionaryBatch(t){t.startObject(3)}static addId(t,e){t.addFieldInt64(0,e,BigInt("0"))}static addData(t,e){t.addFieldOffset(1,e,0)}static addIsDelta(t,e){t.addFieldInt8(2,+e,0)}static endDictionaryBatch(t){return t.endObject()}};var ae;(function(i){i[i.Little=0]="Little",i[i.Big=1]="Big"})(ae||(ae={}));var He;(function(i){i[i.DenseArray=0]="DenseArray"})(He||(He={}));class et{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsInt(t,e){return(e||new et).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsInt(t,e){return t.setPosition(t.position()+R),(e||new et).__init(t.readInt32(t.position())+t.position(),t)}bitWidth(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt32(this.bb_pos+t):0}isSigned(){const t=this.bb.__offset(this.bb_pos,6);return t?!!this.bb.readInt8(this.bb_pos+t):!1}static startInt(t){t.startObject(2)}static addBitWidth(t,e){t.addFieldInt32(0,e,0)}static addIsSigned(t,e){t.addFieldInt8(1,+e,0)}static endInt(t){return t.endObject()}static createInt(t,e,n){return et.startInt(t),et.addBitWidth(t,e),et.addIsSigned(t,n),et.endInt(t)}}class Ft{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsDictionaryEncoding(t,e){return(e||new Ft).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsDictionaryEncoding(t,e){return t.setPosition(t.position()+R),(e||new Ft).__init(t.readInt32(t.position())+t.position(),t)}id(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt64(this.bb_pos+t):BigInt("0")}indexType(t){const e=this.bb.__offset(this.bb_pos,6);return e?(t||new et).__init(this.bb.__indirect(this.bb_pos+e),this.bb):null}isOrdered(){const t=this.bb.__offset(this.bb_pos,8);return t?!!this.bb.readInt8(this.bb_pos+t):!1}dictionaryKind(){const t=this.bb.__offset(this.bb_pos,10);return t?this.bb.readInt16(this.bb_pos+t):He.DenseArray}static startDictionaryEncoding(t){t.startObject(4)}static addId(t,e){t.addFieldInt64(0,e,BigInt("0"))}static addIndexType(t,e){t.addFieldOffset(1,e,0)}static addIsOrdered(t,e){t.addFieldInt8(2,+e,0)}static addDictionaryKind(t,e){t.addFieldInt16(3,e,He.DenseArray)}static endDictionaryEncoding(t){return t.endObject()}}class j{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsKeyValue(t,e){return(e||new j).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsKeyValue(t,e){return t.setPosition(t.position()+R),(e||new j).__init(t.readInt32(t.position())+t.position(),t)}key(t){const e=this.bb.__offset(this.bb_pos,4);return e?this.bb.__string(this.bb_pos+e,t):null}value(t){const e=this.bb.__offset(this.bb_pos,6);return e?this.bb.__string(this.bb_pos+e,t):null}static startKeyValue(t){t.startObject(2)}static addKey(t,e){t.addFieldOffset(0,e,0)}static addValue(t,e){t.addFieldOffset(1,e,0)}static endKeyValue(t){return t.endObject()}static createKeyValue(t,e,n){return j.startKeyValue(t),j.addKey(t,e),j.addValue(t,n),j.endKeyValue(t)}}let yn=class me{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsBinary(t,e){return(e||new me).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsBinary(t,e){return t.setPosition(t.position()+R),(e||new me).__init(t.readInt32(t.position())+t.position(),t)}static startBinary(t){t.startObject(0)}static endBinary(t){return t.endObject()}static createBinary(t){return me.startBinary(t),me.endBinary(t)}},pn=class ge{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsBool(t,e){return(e||new ge).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsBool(t,e){return t.setPosition(t.position()+R),(e||new ge).__init(t.readInt32(t.position())+t.position(),t)}static startBool(t){t.startObject(0)}static endBool(t){return t.endObject()}static createBool(t){return ge.startBool(t),ge.endBool(t)}},Ve=class Ht{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsDate(t,e){return(e||new Ht).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsDate(t,e){return t.setPosition(t.position()+R),(e||new Ht).__init(t.readInt32(t.position())+t.position(),t)}unit(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt16(this.bb_pos+t):ct.MILLISECOND}static startDate(t){t.startObject(1)}static addUnit(t,e){t.addFieldInt16(0,e,ct.MILLISECOND)}static endDate(t){return t.endObject()}static createDate(t,e){return Ht.startDate(t),Ht.addUnit(t,e),Ht.endDate(t)}},Jt=class Ut{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsDecimal(t,e){return(e||new Ut).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsDecimal(t,e){return t.setPosition(t.position()+R),(e||new Ut).__init(t.readInt32(t.position())+t.position(),t)}precision(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt32(this.bb_pos+t):0}scale(){const t=this.bb.__offset(this.bb_pos,6);return t?this.bb.readInt32(this.bb_pos+t):0}bitWidth(){const t=this.bb.__offset(this.bb_pos,8);return t?this.bb.readInt32(this.bb_pos+t):128}static startDecimal(t){t.startObject(3)}static addPrecision(t,e){t.addFieldInt32(0,e,0)}static addScale(t,e){t.addFieldInt32(1,e,0)}static addBitWidth(t,e){t.addFieldInt32(2,e,128)}static endDecimal(t){return t.endObject()}static createDecimal(t,e,n,s){return Ut.startDecimal(t),Ut.addPrecision(t,e),Ut.addScale(t,n),Ut.addBitWidth(t,s),Ut.endDecimal(t)}},ze=class Kt{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsDuration(t,e){return(e||new Kt).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsDuration(t,e){return t.setPosition(t.position()+R),(e||new Kt).__init(t.readInt32(t.position())+t.position(),t)}unit(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt16(this.bb_pos+t):I.MILLISECOND}static startDuration(t){t.startObject(1)}static addUnit(t,e){t.addFieldInt16(0,e,I.MILLISECOND)}static endDuration(t){return t.endObject()}static createDuration(t,e){return Kt.startDuration(t),Kt.addUnit(t,e),Kt.endDuration(t)}},ke=class Gt{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsFixedSizeBinary(t,e){return(e||new Gt).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsFixedSizeBinary(t,e){return t.setPosition(t.position()+R),(e||new Gt).__init(t.readInt32(t.position())+t.position(),t)}byteWidth(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt32(this.bb_pos+t):0}static startFixedSizeBinary(t){t.startObject(1)}static addByteWidth(t,e){t.addFieldInt32(0,e,0)}static endFixedSizeBinary(t){return t.endObject()}static createFixedSizeBinary(t,e){return Gt.startFixedSizeBinary(t),Gt.addByteWidth(t,e),Gt.endFixedSizeBinary(t)}},Pe=class Zt{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsFixedSizeList(t,e){return(e||new Zt).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsFixedSizeList(t,e){return t.setPosition(t.position()+R),(e||new Zt).__init(t.readInt32(t.position())+t.position(),t)}listSize(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt32(this.bb_pos+t):0}static startFixedSizeList(t){t.startObject(1)}static addListSize(t,e){t.addFieldInt32(0,e,0)}static endFixedSizeList(t){return t.endObject()}static createFixedSizeList(t,e){return Zt.startFixedSizeList(t),Zt.addListSize(t,e),Zt.endFixedSizeList(t)}};class _t{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsFloatingPoint(t,e){return(e||new _t).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsFloatingPoint(t,e){return t.setPosition(t.position()+R),(e||new _t).__init(t.readInt32(t.position())+t.position(),t)}precision(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt16(this.bb_pos+t):H.HALF}static startFloatingPoint(t){t.startObject(1)}static addPrecision(t,e){t.addFieldInt16(0,e,H.HALF)}static endFloatingPoint(t){return t.endObject()}static createFloatingPoint(t,e){return _t.startFloatingPoint(t),_t.addPrecision(t,e),_t.endFloatingPoint(t)}}class It{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsInterval(t,e){return(e||new It).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsInterval(t,e){return t.setPosition(t.position()+R),(e||new It).__init(t.readInt32(t.position())+t.position(),t)}unit(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt16(this.bb_pos+t):$.YEAR_MONTH}static startInterval(t){t.startObject(1)}static addUnit(t,e){t.addFieldInt16(0,e,$.YEAR_MONTH)}static endInterval(t){return t.endObject()}static createInterval(t,e){return It.startInterval(t),It.addUnit(t,e),It.endInterval(t)}}let mn=class be{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsLargeBinary(t,e){return(e||new be).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsLargeBinary(t,e){return t.setPosition(t.position()+R),(e||new be).__init(t.readInt32(t.position())+t.position(),t)}static startLargeBinary(t){t.startObject(0)}static endLargeBinary(t){return t.endObject()}static createLargeBinary(t){return be.startLargeBinary(t),be.endLargeBinary(t)}},gn=class ve{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsLargeUtf8(t,e){return(e||new ve).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsLargeUtf8(t,e){return t.setPosition(t.position()+R),(e||new ve).__init(t.readInt32(t.position())+t.position(),t)}static startLargeUtf8(t){t.startObject(0)}static endLargeUtf8(t){return t.endObject()}static createLargeUtf8(t){return ve.startLargeUtf8(t),ve.endLargeUtf8(t)}},bn=class _e{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsList(t,e){return(e||new _e).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsList(t,e){return t.setPosition(t.position()+R),(e||new _e).__init(t.readInt32(t.position())+t.position(),t)}static startList(t){t.startObject(0)}static endList(t){return t.endObject()}static createList(t){return _e.startList(t),_e.endList(t)}},je=class qt{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsMap(t,e){return(e||new qt).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsMap(t,e){return t.setPosition(t.position()+R),(e||new qt).__init(t.readInt32(t.position())+t.position(),t)}keysSorted(){const t=this.bb.__offset(this.bb_pos,4);return t?!!this.bb.readInt8(this.bb_pos+t):!1}static startMap(t){t.startObject(1)}static addKeysSorted(t,e){t.addFieldInt8(0,+e,0)}static endMap(t){return t.endObject()}static createMap(t,e){return qt.startMap(t),qt.addKeysSorted(t,e),qt.endMap(t)}},vn=class Ie{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsNull(t,e){return(e||new Ie).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsNull(t,e){return t.setPosition(t.position()+R),(e||new Ie).__init(t.readInt32(t.position())+t.position(),t)}static startNull(t){t.startObject(0)}static endNull(t){return t.endObject()}static createNull(t){return Ie.startNull(t),Ie.endNull(t)}};class zt{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsStruct_(t,e){return(e||new zt).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsStruct_(t,e){return t.setPosition(t.position()+R),(e||new zt).__init(t.readInt32(t.position())+t.position(),t)}static startStruct_(t){t.startObject(0)}static endStruct_(t){return t.endObject()}static createStruct_(t){return zt.startStruct_(t),zt.endStruct_(t)}}class rt{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsTime(t,e){return(e||new rt).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsTime(t,e){return t.setPosition(t.position()+R),(e||new rt).__init(t.readInt32(t.position())+t.position(),t)}unit(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt16(this.bb_pos+t):I.MILLISECOND}bitWidth(){const t=this.bb.__offset(this.bb_pos,6);return t?this.bb.readInt32(this.bb_pos+t):32}static startTime(t){t.startObject(2)}static addUnit(t,e){t.addFieldInt16(0,e,I.MILLISECOND)}static addBitWidth(t,e){t.addFieldInt32(1,e,32)}static endTime(t){return t.endObject()}static createTime(t,e,n){return rt.startTime(t),rt.addUnit(t,e),rt.addBitWidth(t,n),rt.endTime(t)}}class ot{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsTimestamp(t,e){return(e||new ot).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsTimestamp(t,e){return t.setPosition(t.position()+R),(e||new ot).__init(t.readInt32(t.position())+t.position(),t)}unit(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt16(this.bb_pos+t):I.SECOND}timezone(t){const e=this.bb.__offset(this.bb_pos,6);return e?this.bb.__string(this.bb_pos+e,t):null}static startTimestamp(t){t.startObject(2)}static addUnit(t,e){t.addFieldInt16(0,e,I.SECOND)}static addTimezone(t,e){t.addFieldOffset(1,e,0)}static endTimestamp(t){return t.endObject()}static createTimestamp(t,e,n){return ot.startTimestamp(t),ot.addUnit(t,e),ot.addTimezone(t,n),ot.endTimestamp(t)}}class q{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsUnion(t,e){return(e||new q).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsUnion(t,e){return t.setPosition(t.position()+R),(e||new q).__init(t.readInt32(t.position())+t.position(),t)}mode(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt16(this.bb_pos+t):X.Sparse}typeIds(t){const e=this.bb.__offset(this.bb_pos,6);return e?this.bb.readInt32(this.bb.__vector(this.bb_pos+e)+t*4):0}typeIdsLength(){const t=this.bb.__offset(this.bb_pos,6);return t?this.bb.__vector_len(this.bb_pos+t):0}typeIdsArray(){const t=this.bb.__offset(this.bb_pos,6);return t?new Int32Array(this.bb.bytes().buffer,this.bb.bytes().byteOffset+this.bb.__vector(this.bb_pos+t),this.bb.__vector_len(this.bb_pos+t)):null}static startUnion(t){t.startObject(2)}static addMode(t,e){t.addFieldInt16(0,e,X.Sparse)}static addTypeIds(t,e){t.addFieldOffset(1,e,0)}static createTypeIdsVector(t,e){t.startVector(4,e.length,4);for(let n=e.length-1;n>=0;n--)t.addInt32(e[n]);return t.endVector()}static startTypeIdsVector(t,e){t.startVector(4,e,4)}static endUnion(t){return t.endObject()}static createUnion(t,e,n){return q.startUnion(t),q.addMode(t,e),q.addTypeIds(t,n),q.endUnion(t)}}let _n=class Se{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsUtf8(t,e){return(e||new Se).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsUtf8(t,e){return t.setPosition(t.position()+R),(e||new Se).__init(t.readInt32(t.position())+t.position(),t)}static startUtf8(t){t.startObject(0)}static endUtf8(t){return t.endObject()}static createUtf8(t){return Se.startUtf8(t),Se.endUtf8(t)}};var C;(function(i){i[i.NONE=0]="NONE",i[i.Null=1]="Null",i[i.Int=2]="Int",i[i.FloatingPoint=3]="FloatingPoint",i[i.Binary=4]="Binary",i[i.Utf8=5]="Utf8",i[i.Bool=6]="Bool",i[i.Decimal=7]="Decimal",i[i.Date=8]="Date",i[i.Time=9]="Time",i[i.Timestamp=10]="Timestamp",i[i.Interval=11]="Interval",i[i.List=12]="List",i[i.Struct_=13]="Struct_",i[i.Union=14]="Union",i[i.FixedSizeBinary=15]="FixedSizeBinary",i[i.FixedSizeList=16]="FixedSizeList",i[i.Map=17]="Map",i[i.Duration=18]="Duration",i[i.LargeBinary=19]="LargeBinary",i[i.LargeUtf8=20]="LargeUtf8",i[i.LargeList=21]="LargeList",i[i.RunEndEncoded=22]="RunEndEncoded"})(C||(C={}));let nt=class $e{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsField(t,e){return(e||new $e).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsField(t,e){return t.setPosition(t.position()+R),(e||new $e).__init(t.readInt32(t.position())+t.position(),t)}name(t){const e=this.bb.__offset(this.bb_pos,4);return e?this.bb.__string(this.bb_pos+e,t):null}nullable(){const t=this.bb.__offset(this.bb_pos,6);return t?!!this.bb.readInt8(this.bb_pos+t):!1}typeType(){const t=this.bb.__offset(this.bb_pos,8);return t?this.bb.readUint8(this.bb_pos+t):C.NONE}type(t){const e=this.bb.__offset(this.bb_pos,10);return e?this.bb.__union(t,this.bb_pos+e):null}dictionary(t){const e=this.bb.__offset(this.bb_pos,12);return e?(t||new Ft).__init(this.bb.__indirect(this.bb_pos+e),this.bb):null}children(t,e){const n=this.bb.__offset(this.bb_pos,14);return n?(e||new $e).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos+n)+t*4),this.bb):null}childrenLength(){const t=this.bb.__offset(this.bb_pos,14);return t?this.bb.__vector_len(this.bb_pos+t):0}customMetadata(t,e){const n=this.bb.__offset(this.bb_pos,16);return n?(e||new j).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos+n)+t*4),this.bb):null}customMetadataLength(){const t=this.bb.__offset(this.bb_pos,16);return t?this.bb.__vector_len(this.bb_pos+t):0}static startField(t){t.startObject(7)}static addName(t,e){t.addFieldOffset(0,e,0)}static addNullable(t,e){t.addFieldInt8(1,+e,0)}static addTypeType(t,e){t.addFieldInt8(2,e,C.NONE)}static addType(t,e){t.addFieldOffset(3,e,0)}static addDictionary(t,e){t.addFieldOffset(4,e,0)}static addChildren(t,e){t.addFieldOffset(5,e,0)}static createChildrenVector(t,e){t.startVector(4,e.length,4);for(let n=e.length-1;n>=0;n--)t.addOffset(e[n]);return t.endVector()}static startChildrenVector(t,e){t.startVector(4,e,4)}static addCustomMetadata(t,e){t.addFieldOffset(6,e,0)}static createCustomMetadataVector(t,e){t.startVector(4,e.length,4);for(let n=e.length-1;n>=0;n--)t.addOffset(e[n]);return t.endVector()}static startCustomMetadataVector(t,e){t.startVector(4,e,4)}static endField(t){return t.endObject()}},bt=class Dt{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsSchema(t,e){return(e||new Dt).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsSchema(t,e){return t.setPosition(t.position()+R),(e||new Dt).__init(t.readInt32(t.position())+t.position(),t)}endianness(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt16(this.bb_pos+t):ae.Little}fields(t,e){const n=this.bb.__offset(this.bb_pos,6);return n?(e||new nt).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos+n)+t*4),this.bb):null}fieldsLength(){const t=this.bb.__offset(this.bb_pos,6);return t?this.bb.__vector_len(this.bb_pos+t):0}customMetadata(t,e){const n=this.bb.__offset(this.bb_pos,8);return n?(e||new j).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos+n)+t*4),this.bb):null}customMetadataLength(){const t=this.bb.__offset(this.bb_pos,8);return t?this.bb.__vector_len(this.bb_pos+t):0}features(t){const e=this.bb.__offset(this.bb_pos,10);return e?this.bb.readInt64(this.bb.__vector(this.bb_pos+e)+t*8):BigInt(0)}featuresLength(){const t=this.bb.__offset(this.bb_pos,10);return t?this.bb.__vector_len(this.bb_pos+t):0}static startSchema(t){t.startObject(4)}static addEndianness(t,e){t.addFieldInt16(0,e,ae.Little)}static addFields(t,e){t.addFieldOffset(1,e,0)}static createFieldsVector(t,e){t.startVector(4,e.length,4);for(let n=e.length-1;n>=0;n--)t.addOffset(e[n]);return t.endVector()}static startFieldsVector(t,e){t.startVector(4,e,4)}static addCustomMetadata(t,e){t.addFieldOffset(2,e,0)}static createCustomMetadataVector(t,e){t.startVector(4,e.length,4);for(let n=e.length-1;n>=0;n--)t.addOffset(e[n]);return t.endVector()}static startCustomMetadataVector(t,e){t.startVector(4,e,4)}static addFeatures(t,e){t.addFieldOffset(3,e,0)}static createFeaturesVector(t,e){t.startVector(8,e.length,8);for(let n=e.length-1;n>=0;n--)t.addInt64(e[n]);return t.endVector()}static startFeaturesVector(t,e){t.startVector(8,e,8)}static endSchema(t){return t.endObject()}static finishSchemaBuffer(t,e){t.finish(e)}static finishSizePrefixedSchemaBuffer(t,e){t.finish(e,void 0,!0)}static createSchema(t,e,n,s,r){return Dt.startSchema(t),Dt.addEndianness(t,e),Dt.addFields(t,n),Dt.addCustomMetadata(t,s),Dt.addFeatures(t,r),Dt.endSchema(t)}};var M;(function(i){i[i.NONE=0]="NONE",i[i.Schema=1]="Schema",i[i.DictionaryBatch=2]="DictionaryBatch",i[i.RecordBatch=3]="RecordBatch",i[i.Tensor=4]="Tensor",i[i.SparseTensor=5]="SparseTensor"})(M||(M={}));var l;(function(i){i[i.NONE=0]="NONE",i[i.Null=1]="Null",i[i.Int=2]="Int",i[i.Float=3]="Float",i[i.Binary=4]="Binary",i[i.Utf8=5]="Utf8",i[i.Bool=6]="Bool",i[i.Decimal=7]="Decimal",i[i.Date=8]="Date",i[i.Time=9]="Time",i[i.Timestamp=10]="Timestamp",i[i.Interval=11]="Interval",i[i.List=12]="List",i[i.Struct=13]="Struct",i[i.Union=14]="Union",i[i.FixedSizeBinary=15]="FixedSizeBinary",i[i.FixedSizeList=16]="FixedSizeList",i[i.Map=17]="Map",i[i.Duration=18]="Duration",i[i.LargeBinary=19]="LargeBinary",i[i.LargeUtf8=20]="LargeUtf8",i[i.Dictionary=-1]="Dictionary",i[i.Int8=-2]="Int8",i[i.Int16=-3]="Int16",i[i.Int32=-4]="Int32",i[i.Int64=-5]="Int64",i[i.Uint8=-6]="Uint8",i[i.Uint16=-7]="Uint16",i[i.Uint32=-8]="Uint32",i[i.Uint64=-9]="Uint64",i[i.Float16=-10]="Float16",i[i.Float32=-11]="Float32",i[i.Float64=-12]="Float64",i[i.DateDay=-13]="DateDay",i[i.DateMillisecond=-14]="DateMillisecond",i[i.TimestampSecond=-15]="TimestampSecond",i[i.TimestampMillisecond=-16]="TimestampMillisecond",i[i.TimestampMicrosecond=-17]="TimestampMicrosecond",i[i.TimestampNanosecond=-18]="TimestampNanosecond",i[i.TimeSecond=-19]="TimeSecond",i[i.TimeMillisecond=-20]="TimeMillisecond",i[i.TimeMicrosecond=-21]="TimeMicrosecond",i[i.TimeNanosecond=-22]="TimeNanosecond",i[i.DenseUnion=-23]="DenseUnion",i[i.SparseUnion=-24]="SparseUnion",i[i.IntervalDayTime=-25]="IntervalDayTime",i[i.IntervalYearMonth=-26]="IntervalYearMonth",i[i.DurationSecond=-27]="DurationSecond",i[i.DurationMillisecond=-28]="DurationMillisecond",i[i.DurationMicrosecond=-29]="DurationMicrosecond",i[i.DurationNanosecond=-30]="DurationNanosecond",i[i.IntervalMonthDayNano=-31]="IntervalMonthDayNano"})(l||(l={}));var At;(function(i){i[i.OFFSET=0]="OFFSET",i[i.DATA=1]="DATA",i[i.VALIDITY=2]="VALIDITY",i[i.TYPE=3]="TYPE"})(At||(At={}));const so=void 0;function Ae(i){if(i===null)return"null";if(i===so)return"undefined";switch(typeof i){case"number":return`${i}`;case"bigint":return`${i}`;case"string":return`"${i}"`}return typeof i[Symbol.toPrimitive]=="function"?i[Symbol.toPrimitive]("string"):ArrayBuffer.isView(i)?i instanceof BigInt64Array||i instanceof BigUint64Array?`[${[...i].map(t=>Ae(t))}]`:`[${i}]`:ArrayBuffer.isView(i)?`[${i}]`:JSON.stringify(i,(t,e)=>typeof e=="bigint"?`${e}`:e)}function V(i){if(typeof i=="bigint"&&(iNumber.MAX_SAFE_INTEGER))throw new TypeError(`${i} is not safe to convert to a number.`);return Number(i)}function Kn(i,t){return V(i/t)+V(i%t)/V(t)}const ro=Symbol.for("isArrowBigNum");function pt(i,...t){return t.length===0?Object.setPrototypeOf(U(this.TypedArray,i),this.constructor.prototype):Object.setPrototypeOf(new this.TypedArray(i,...t),this.constructor.prototype)}pt.prototype[ro]=!0;pt.prototype.toJSON=function(){return`"${Fe(this)}"`};pt.prototype.valueOf=function(i){return Gn(this,i)};pt.prototype.toString=function(){return Fe(this)};pt.prototype[Symbol.toPrimitive]=function(i="default"){switch(i){case"number":return Gn(this);case"string":return Fe(this);case"default":return co(this)}return Fe(this)};function ne(...i){return pt.apply(this,i)}function se(...i){return pt.apply(this,i)}function Oe(...i){return pt.apply(this,i)}Object.setPrototypeOf(ne.prototype,Object.create(Int32Array.prototype));Object.setPrototypeOf(se.prototype,Object.create(Uint32Array.prototype));Object.setPrototypeOf(Oe.prototype,Object.create(Uint32Array.prototype));Object.assign(ne.prototype,pt.prototype,{constructor:ne,signed:!0,TypedArray:Int32Array,BigIntArray:BigInt64Array});Object.assign(se.prototype,pt.prototype,{constructor:se,signed:!1,TypedArray:Uint32Array,BigIntArray:BigUint64Array});Object.assign(Oe.prototype,pt.prototype,{constructor:Oe,signed:!0,TypedArray:Uint32Array,BigIntArray:BigUint64Array});const oo=BigInt(4294967296)*BigInt(4294967296),ao=oo-BigInt(1);function Gn(i,t){const{buffer:e,byteOffset:n,byteLength:s,signed:r}=i,o=new BigUint64Array(e,n,s/8),a=r&&o.at(-1)&BigInt(1)<0){const d=BigInt("1".padEnd(t+1,"0")),f=c/d,k=a?-(c%d):c%d,W=V(f),ut=`${k}`.padStart(t,"0");return+`${a&&W===0?"-":""}${W}.${ut}`}return V(c)}function Fe(i){if(i.byteLength===8)return`${new i.BigIntArray(i.buffer,i.byteOffset,1)[0]}`;if(!i.signed)return Ai(i);let t=new Uint16Array(i.buffer,i.byteOffset,i.byteLength/2);if(new Int16Array([t.at(-1)])[0]>=0)return Ai(i);t=t.slice();let n=1;for(let r=0;r(i.children=null,i.ArrayType=Array,i.OffsetArrayType=Int32Array,i[Symbol.toStringTag]="DataType"))(h.prototype);class Rt extends h{constructor(){super(l.Null)}toString(){return"Null"}}qn=Symbol.toStringTag;Rt[qn]=(i=>i[Symbol.toStringTag]="Null")(Rt.prototype);class Pt extends h{constructor(t,e){super(l.Int),this.isSigned=t,this.bitWidth=e}get ArrayType(){switch(this.bitWidth){case 8:return this.isSigned?Int8Array:Uint8Array;case 16:return this.isSigned?Int16Array:Uint16Array;case 32:return this.isSigned?Int32Array:Uint32Array;case 64:return this.isSigned?BigInt64Array:BigUint64Array}throw new Error(`Unrecognized ${this[Symbol.toStringTag]} type`)}toString(){return`${this.isSigned?"I":"Ui"}nt${this.bitWidth}`}}Xn=Symbol.toStringTag;Pt[Xn]=(i=>(i.isSigned=null,i.bitWidth=null,i[Symbol.toStringTag]="Int"))(Pt.prototype);class Me extends Pt{constructor(){super(!0,32)}get ArrayType(){return Int32Array}}Object.defineProperty(Me.prototype,"ArrayType",{value:Int32Array});class Je extends h{constructor(t){super(l.Float),this.precision=t}get ArrayType(){switch(this.precision){case H.HALF:return Uint16Array;case H.SINGLE:return Float32Array;case H.DOUBLE:return Float64Array}throw new Error(`Unrecognized ${this[Symbol.toStringTag]} type`)}toString(){return`Float${this.precision<<5||16}`}}Qn=Symbol.toStringTag;Je[Qn]=(i=>(i.precision=null,i[Symbol.toStringTag]="Float"))(Je.prototype);class Ke extends h{constructor(){super(l.Binary)}toString(){return"Binary"}}ts=Symbol.toStringTag;Ke[ts]=(i=>(i.ArrayType=Uint8Array,i[Symbol.toStringTag]="Binary"))(Ke.prototype);class Ge extends h{constructor(){super(l.LargeBinary)}toString(){return"LargeBinary"}}es=Symbol.toStringTag;Ge[es]=(i=>(i.ArrayType=Uint8Array,i.OffsetArrayType=BigInt64Array,i[Symbol.toStringTag]="LargeBinary"))(Ge.prototype);class Ze extends h{constructor(){super(l.Utf8)}toString(){return"Utf8"}}is=Symbol.toStringTag;Ze[is]=(i=>(i.ArrayType=Uint8Array,i[Symbol.toStringTag]="Utf8"))(Ze.prototype);class qe extends h{constructor(){super(l.LargeUtf8)}toString(){return"LargeUtf8"}}ns=Symbol.toStringTag;qe[ns]=(i=>(i.ArrayType=Uint8Array,i.OffsetArrayType=BigInt64Array,i[Symbol.toStringTag]="LargeUtf8"))(qe.prototype);class Xe extends h{constructor(){super(l.Bool)}toString(){return"Bool"}}ss=Symbol.toStringTag;Xe[ss]=(i=>(i.ArrayType=Uint8Array,i[Symbol.toStringTag]="Bool"))(Xe.prototype);class Qe extends h{constructor(t,e,n=128){super(l.Decimal),this.scale=t,this.precision=e,this.bitWidth=n}toString(){return`Decimal[${this.precision}e${this.scale>0?"+":""}${this.scale}]`}}rs=Symbol.toStringTag;Qe[rs]=(i=>(i.scale=null,i.precision=null,i.ArrayType=Uint32Array,i[Symbol.toStringTag]="Decimal"))(Qe.prototype);class ti extends h{constructor(t){super(l.Date),this.unit=t}toString(){return`Date${(this.unit+1)*32}<${ct[this.unit]}>`}get ArrayType(){return this.unit===ct.DAY?Int32Array:BigInt64Array}}os=Symbol.toStringTag;ti[os]=(i=>(i.unit=null,i[Symbol.toStringTag]="Date"))(ti.prototype);class ei extends h{constructor(t,e){super(l.Time),this.unit=t,this.bitWidth=e}toString(){return`Time${this.bitWidth}<${I[this.unit]}>`}get ArrayType(){switch(this.bitWidth){case 32:return Int32Array;case 64:return BigInt64Array}throw new Error(`Unrecognized ${this[Symbol.toStringTag]} type`)}}as=Symbol.toStringTag;ei[as]=(i=>(i.unit=null,i.bitWidth=null,i[Symbol.toStringTag]="Time"))(ei.prototype);class ii extends h{constructor(t,e){super(l.Timestamp),this.unit=t,this.timezone=e}toString(){return`Timestamp<${I[this.unit]}${this.timezone?`, ${this.timezone}`:""}>`}}cs=Symbol.toStringTag;ii[cs]=(i=>(i.unit=null,i.timezone=null,i.ArrayType=BigInt64Array,i[Symbol.toStringTag]="Timestamp"))(ii.prototype);class ni extends h{constructor(t){super(l.Interval),this.unit=t}toString(){return`Interval<${$[this.unit]}>`}}ls=Symbol.toStringTag;ni[ls]=(i=>(i.unit=null,i.ArrayType=Int32Array,i[Symbol.toStringTag]="Interval"))(ni.prototype);class si extends h{constructor(t){super(l.Duration),this.unit=t}toString(){return`Duration<${I[this.unit]}>`}}us=Symbol.toStringTag;si[us]=(i=>(i.unit=null,i.ArrayType=BigInt64Array,i[Symbol.toStringTag]="Duration"))(si.prototype);class ri extends h{constructor(t){super(l.List),this.children=[t]}toString(){return`List<${this.valueType}>`}get valueType(){return this.children[0].type}get valueField(){return this.children[0]}get ArrayType(){return this.valueType.ArrayType}}ds=Symbol.toStringTag;ri[ds]=(i=>(i.children=null,i[Symbol.toStringTag]="List"))(ri.prototype);class K extends h{constructor(t){super(l.Struct),this.children=t}toString(){return`Struct<{${this.children.map(t=>`${t.name}:${t.type}`).join(", ")}}>`}}hs=Symbol.toStringTag;K[hs]=(i=>(i.children=null,i[Symbol.toStringTag]="Struct"))(K.prototype);class oi extends h{constructor(t,e,n){super(l.Union),this.mode=t,this.children=n,this.typeIds=e=Int32Array.from(e),this.typeIdToChildIndex=e.reduce((s,r,o)=>(s[r]=o)&&s||s,Object.create(null))}toString(){return`${this[Symbol.toStringTag]}<${this.children.map(t=>`${t.type}`).join(" | ")}>`}}fs=Symbol.toStringTag;oi[fs]=(i=>(i.mode=null,i.typeIds=null,i.children=null,i.typeIdToChildIndex=null,i.ArrayType=Int8Array,i[Symbol.toStringTag]="Union"))(oi.prototype);class ai extends h{constructor(t){super(l.FixedSizeBinary),this.byteWidth=t}toString(){return`FixedSizeBinary[${this.byteWidth}]`}}ys=Symbol.toStringTag;ai[ys]=(i=>(i.byteWidth=null,i.ArrayType=Uint8Array,i[Symbol.toStringTag]="FixedSizeBinary"))(ai.prototype);class ci extends h{constructor(t,e){super(l.FixedSizeList),this.listSize=t,this.children=[e]}get valueType(){return this.children[0].type}get valueField(){return this.children[0]}get ArrayType(){return this.valueType.ArrayType}toString(){return`FixedSizeList[${this.listSize}]<${this.valueType}>`}}ps=Symbol.toStringTag;ci[ps]=(i=>(i.children=null,i.listSize=null,i[Symbol.toStringTag]="FixedSizeList"))(ci.prototype);class li extends h{constructor(t,e=!1){var n,s,r;if(super(l.Map),this.children=[t],this.keysSorted=e,t&&(t.name="entries",!((n=t?.type)===null||n===void 0)&&n.children)){const o=(s=t?.type)===null||s===void 0?void 0:s.children[0];o&&(o.name="key");const a=(r=t?.type)===null||r===void 0?void 0:r.children[1];a&&(a.name="value")}}get keyType(){return this.children[0].type.children[0].type}get valueType(){return this.children[0].type.children[1].type}get childType(){return this.children[0].type}toString(){return`Map<{${this.children[0].type.children.map(t=>`${t.name}:${t.type}`).join(", ")}}>`}}ms=Symbol.toStringTag;li[ms]=(i=>(i.children=null,i.keysSorted=null,i[Symbol.toStringTag]="Map_"))(li.prototype);const lo=(i=>()=>++i)(-1);class ce extends h{constructor(t,e,n,s){super(l.Dictionary),this.indices=e,this.dictionary=t,this.isOrdered=s||!1,this.id=n==null?lo():V(n)}get children(){return this.dictionary.children}get valueType(){return this.dictionary}get ArrayType(){return this.dictionary.ArrayType}toString(){return`Dictionary<${this.indices}, ${this.dictionary}>`}}gs=Symbol.toStringTag;ce[gs]=(i=>(i.id=null,i.indices=null,i.isOrdered=null,i.dictionary=null,i[Symbol.toStringTag]="Dictionary"))(ce.prototype);function Ot(i){const t=i;switch(i.typeId){case l.Decimal:return i.bitWidth/32;case l.Interval:return t.unit===$.MONTH_DAY_NANO?4:1+t.unit;case l.FixedSizeList:return t.listSize;case l.FixedSizeBinary:return t.byteWidth;default:return 1}}class D{visitMany(t,...e){return t.map((n,s)=>this.visit(n,...e.map(r=>r[s])))}visit(...t){return this.getVisitFn(t[0],!1).apply(this,t)}getVisitFn(t,e=!0){return uo(this,t,e)}getVisitFnByTypeId(t,e=!0){return Xt(this,t,e)}visitNull(t,...e){return null}visitBool(t,...e){return null}visitInt(t,...e){return null}visitFloat(t,...e){return null}visitUtf8(t,...e){return null}visitLargeUtf8(t,...e){return null}visitBinary(t,...e){return null}visitLargeBinary(t,...e){return null}visitFixedSizeBinary(t,...e){return null}visitDate(t,...e){return null}visitTimestamp(t,...e){return null}visitTime(t,...e){return null}visitDecimal(t,...e){return null}visitList(t,...e){return null}visitStruct(t,...e){return null}visitUnion(t,...e){return null}visitDictionary(t,...e){return null}visitInterval(t,...e){return null}visitDuration(t,...e){return null}visitFixedSizeList(t,...e){return null}visitMap(t,...e){return null}}function uo(i,t,e=!0){return typeof t=="number"?Xt(i,t,e):typeof t=="string"&&t in l?Xt(i,l[t],e):t&&t instanceof h?Xt(i,In(t),e):t?.type&&t.type instanceof h?Xt(i,In(t.type),e):Xt(i,l.NONE,e)}function Xt(i,t,e=!0){let n=null;switch(t){case l.Null:n=i.visitNull;break;case l.Bool:n=i.visitBool;break;case l.Int:n=i.visitInt;break;case l.Int8:n=i.visitInt8||i.visitInt;break;case l.Int16:n=i.visitInt16||i.visitInt;break;case l.Int32:n=i.visitInt32||i.visitInt;break;case l.Int64:n=i.visitInt64||i.visitInt;break;case l.Uint8:n=i.visitUint8||i.visitInt;break;case l.Uint16:n=i.visitUint16||i.visitInt;break;case l.Uint32:n=i.visitUint32||i.visitInt;break;case l.Uint64:n=i.visitUint64||i.visitInt;break;case l.Float:n=i.visitFloat;break;case l.Float16:n=i.visitFloat16||i.visitFloat;break;case l.Float32:n=i.visitFloat32||i.visitFloat;break;case l.Float64:n=i.visitFloat64||i.visitFloat;break;case l.Utf8:n=i.visitUtf8;break;case l.LargeUtf8:n=i.visitLargeUtf8;break;case l.Binary:n=i.visitBinary;break;case l.LargeBinary:n=i.visitLargeBinary;break;case l.FixedSizeBinary:n=i.visitFixedSizeBinary;break;case l.Date:n=i.visitDate;break;case l.DateDay:n=i.visitDateDay||i.visitDate;break;case l.DateMillisecond:n=i.visitDateMillisecond||i.visitDate;break;case l.Timestamp:n=i.visitTimestamp;break;case l.TimestampSecond:n=i.visitTimestampSecond||i.visitTimestamp;break;case l.TimestampMillisecond:n=i.visitTimestampMillisecond||i.visitTimestamp;break;case l.TimestampMicrosecond:n=i.visitTimestampMicrosecond||i.visitTimestamp;break;case l.TimestampNanosecond:n=i.visitTimestampNanosecond||i.visitTimestamp;break;case l.Time:n=i.visitTime;break;case l.TimeSecond:n=i.visitTimeSecond||i.visitTime;break;case l.TimeMillisecond:n=i.visitTimeMillisecond||i.visitTime;break;case l.TimeMicrosecond:n=i.visitTimeMicrosecond||i.visitTime;break;case l.TimeNanosecond:n=i.visitTimeNanosecond||i.visitTime;break;case l.Decimal:n=i.visitDecimal;break;case l.List:n=i.visitList;break;case l.Struct:n=i.visitStruct;break;case l.Union:n=i.visitUnion;break;case l.DenseUnion:n=i.visitDenseUnion||i.visitUnion;break;case l.SparseUnion:n=i.visitSparseUnion||i.visitUnion;break;case l.Dictionary:n=i.visitDictionary;break;case l.Interval:n=i.visitInterval;break;case l.IntervalDayTime:n=i.visitIntervalDayTime||i.visitInterval;break;case l.IntervalYearMonth:n=i.visitIntervalYearMonth||i.visitInterval;break;case l.IntervalMonthDayNano:n=i.visitIntervalMonthDayNano||i.visitInterval;break;case l.Duration:n=i.visitDuration;break;case l.DurationSecond:n=i.visitDurationSecond||i.visitDuration;break;case l.DurationMillisecond:n=i.visitDurationMillisecond||i.visitDuration;break;case l.DurationMicrosecond:n=i.visitDurationMicrosecond||i.visitDuration;break;case l.DurationNanosecond:n=i.visitDurationNanosecond||i.visitDuration;break;case l.FixedSizeList:n=i.visitFixedSizeList;break;case l.Map:n=i.visitMap;break}if(typeof n=="function")return n;if(!e)return()=>null;throw new Error(`Unrecognized type '${l[t]}'`)}function In(i){switch(i.typeId){case l.Null:return l.Null;case l.Int:{const{bitWidth:t,isSigned:e}=i;switch(t){case 8:return e?l.Int8:l.Uint8;case 16:return e?l.Int16:l.Uint16;case 32:return e?l.Int32:l.Uint32;case 64:return e?l.Int64:l.Uint64}return l.Int}case l.Float:switch(i.precision){case H.HALF:return l.Float16;case H.SINGLE:return l.Float32;case H.DOUBLE:return l.Float64}return l.Float;case l.Binary:return l.Binary;case l.LargeBinary:return l.LargeBinary;case l.Utf8:return l.Utf8;case l.LargeUtf8:return l.LargeUtf8;case l.Bool:return l.Bool;case l.Decimal:return l.Decimal;case l.Time:switch(i.unit){case I.SECOND:return l.TimeSecond;case I.MILLISECOND:return l.TimeMillisecond;case I.MICROSECOND:return l.TimeMicrosecond;case I.NANOSECOND:return l.TimeNanosecond}return l.Time;case l.Timestamp:switch(i.unit){case I.SECOND:return l.TimestampSecond;case I.MILLISECOND:return l.TimestampMillisecond;case I.MICROSECOND:return l.TimestampMicrosecond;case I.NANOSECOND:return l.TimestampNanosecond}return l.Timestamp;case l.Date:switch(i.unit){case ct.DAY:return l.DateDay;case ct.MILLISECOND:return l.DateMillisecond}return l.Date;case l.Interval:switch(i.unit){case $.DAY_TIME:return l.IntervalDayTime;case $.YEAR_MONTH:return l.IntervalYearMonth;case $.MONTH_DAY_NANO:return l.IntervalMonthDayNano}return l.Interval;case l.Duration:switch(i.unit){case I.SECOND:return l.DurationSecond;case I.MILLISECOND:return l.DurationMillisecond;case I.MICROSECOND:return l.DurationMicrosecond;case I.NANOSECOND:return l.DurationNanosecond}return l.Duration;case l.Map:return l.Map;case l.List:return l.List;case l.Struct:return l.Struct;case l.Union:switch(i.mode){case X.Dense:return l.DenseUnion;case X.Sparse:return l.SparseUnion}return l.Union;case l.FixedSizeBinary:return l.FixedSizeBinary;case l.FixedSizeList:return l.FixedSizeList;case l.Dictionary:return l.Dictionary}throw new Error(`Unrecognized type '${l[i.typeId]}'`)}D.prototype.visitInt8=null;D.prototype.visitInt16=null;D.prototype.visitInt32=null;D.prototype.visitInt64=null;D.prototype.visitUint8=null;D.prototype.visitUint16=null;D.prototype.visitUint32=null;D.prototype.visitUint64=null;D.prototype.visitFloat16=null;D.prototype.visitFloat32=null;D.prototype.visitFloat64=null;D.prototype.visitDateDay=null;D.prototype.visitDateMillisecond=null;D.prototype.visitTimestampSecond=null;D.prototype.visitTimestampMillisecond=null;D.prototype.visitTimestampMicrosecond=null;D.prototype.visitTimestampNanosecond=null;D.prototype.visitTimeSecond=null;D.prototype.visitTimeMillisecond=null;D.prototype.visitTimeMicrosecond=null;D.prototype.visitTimeNanosecond=null;D.prototype.visitDenseUnion=null;D.prototype.visitSparseUnion=null;D.prototype.visitIntervalDayTime=null;D.prototype.visitIntervalYearMonth=null;D.prototype.visitIntervalMonthDayNano=null;D.prototype.visitDuration=null;D.prototype.visitDurationSecond=null;D.prototype.visitDurationMillisecond=null;D.prototype.visitDurationMicrosecond=null;D.prototype.visitDurationNanosecond=null;const bs=new Float64Array(1),Wt=new Uint32Array(bs.buffer);function vs(i){const t=(i&31744)>>10,e=(i&1023)/1024,n=Math.pow(-1,(i&32768)>>15);switch(t){case 31:return n*(e?Number.NaN:1/0);case 0:return n*(e?6103515625e-14*e:0)}return n*Math.pow(2,t-15)*(1+e)}function ho(i){if(i!==i)return 32256;bs[0]=i;const t=(Wt[1]&2147483648)>>16&65535;let e=Wt[1]&2146435072,n=0;return e>=1089470464?Wt[0]>0?e=31744:(e=(e&2080374784)>>16,n=(Wt[1]&1048575)>>10):e<=1056964608?(n=1048576+(Wt[1]&1048575),n=1048576+(n<<(e>>20)-998)>>21,e=0):(e=e-1056964608>>10,n=(Wt[1]&1048575)+512>>10),t|e|n&65535}class b extends D{}function S(i){return(t,e,n)=>{if(t.setValid(e,n!=null))return i(t,e,n)}}const fo=(i,t,e)=>{i[t]=Math.floor(e/864e5)},_s=(i,t,e,n)=>{if(e+1{const s=i+e;n?t[s>>3]|=1<>3]&=~(1<{i[t]=e},Hi=({values:i},t,e)=>{i[t]=e},Is=({values:i},t,e)=>{i[t]=ho(e)},po=(i,t,e)=>{switch(i.type.precision){case H.HALF:return Is(i,t,e);case H.SINGLE:case H.DOUBLE:return Hi(i,t,e)}},Ss=({values:i},t,e)=>{fo(i,t,e.valueOf())},ws=({values:i},t,e)=>{i[t]=BigInt(e)},mo=({stride:i,values:t},e,n)=>{t.set(n.subarray(0,i),i*e)},Bs=({values:i,valueOffsets:t},e,n)=>_s(i,t,e,n),Ds=({values:i,valueOffsets:t},e,n)=>_s(i,t,e,Pi(n)),go=(i,t,e)=>{i.type.unit===ct.DAY?Ss(i,t,e):ws(i,t,e)},As=({values:i},t,e)=>{i[t]=BigInt(e/1e3)},Os=({values:i},t,e)=>{i[t]=BigInt(e)},Fs=({values:i},t,e)=>{i[t]=BigInt(e*1e3)},Ms=({values:i},t,e)=>{i[t]=BigInt(e*1e6)},bo=(i,t,e)=>{switch(i.type.unit){case I.SECOND:return As(i,t,e);case I.MILLISECOND:return Os(i,t,e);case I.MICROSECOND:return Fs(i,t,e);case I.NANOSECOND:return Ms(i,t,e)}},Ns=({values:i},t,e)=>{i[t]=e},Ls=({values:i},t,e)=>{i[t]=e},Ts=({values:i},t,e)=>{i[t]=e},Us=({values:i},t,e)=>{i[t]=e},vo=(i,t,e)=>{switch(i.type.unit){case I.SECOND:return Ns(i,t,e);case I.MILLISECOND:return Ls(i,t,e);case I.MICROSECOND:return Ts(i,t,e);case I.NANOSECOND:return Us(i,t,e)}},_o=({values:i,stride:t},e,n)=>{i.set(n.subarray(0,t),t*e)},Io=(i,t,e)=>{const n=i.children[0],s=i.valueOffsets,r=lt.getVisitFn(n);if(Array.isArray(e))for(let o=-1,a=s[t],c=s[t+1];a{const n=i.children[0],{valueOffsets:s}=i,r=lt.getVisitFn(n);let{[t]:o,[t+1]:a}=s;const c=e instanceof Map?e.entries():Object.entries(e);for(const u of c)if(r(n,o,u),++o>=a)break},wo=(i,t)=>(e,n,s,r)=>n&&e(n,i,t[r]),Bo=(i,t)=>(e,n,s,r)=>n&&e(n,i,t.get(r)),Do=(i,t)=>(e,n,s,r)=>n&&e(n,i,t.get(s.name)),Ao=(i,t)=>(e,n,s,r)=>n&&e(n,i,t[s.name]),Oo=(i,t,e)=>{const n=i.type.children.map(r=>lt.getVisitFn(r.type)),s=e instanceof Map?Do(t,e):e instanceof x?Bo(t,e):Array.isArray(e)?wo(t,e):Ao(t,e);i.type.children.forEach((r,o)=>s(n[o],i.children[o],r,o))},Fo=(i,t,e)=>{i.type.mode===X.Dense?Rs(i,t,e):xs(i,t,e)},Rs=(i,t,e)=>{const n=i.type.typeIdToChildIndex[i.typeIds[t]],s=i.children[n];lt.visit(s,i.valueOffsets[t],e)},xs=(i,t,e)=>{const n=i.type.typeIdToChildIndex[i.typeIds[t]],s=i.children[n];lt.visit(s,t,e)},Mo=(i,t,e)=>{var n;(n=i.dictionary)===null||n===void 0||n.set(i.values[t],e)},No=(i,t,e)=>{switch(i.type.unit){case $.YEAR_MONTH:return Es(i,t,e);case $.DAY_TIME:return Cs(i,t,e);case $.MONTH_DAY_NANO:return Vs(i,t,e)}},Cs=({values:i},t,e)=>{i.set(e.subarray(0,2),2*t)},Es=({values:i},t,e)=>{i[t]=e[0]*12+e[1]%12},Vs=({values:i,stride:t},e,n)=>{i.set(n.subarray(0,t),t*e)},zs=({values:i},t,e)=>{i[t]=e},ks=({values:i},t,e)=>{i[t]=e},Ps=({values:i},t,e)=>{i[t]=e},js=({values:i},t,e)=>{i[t]=e},Lo=(i,t,e)=>{switch(i.type.unit){case I.SECOND:return zs(i,t,e);case I.MILLISECOND:return ks(i,t,e);case I.MICROSECOND:return Ps(i,t,e);case I.NANOSECOND:return js(i,t,e)}},To=(i,t,e)=>{const{stride:n}=i,s=i.children[0],r=lt.getVisitFn(s);if(Array.isArray(e))for(let o=-1,a=t*n;++o`${Ae(t)}: ${Ae(e)}`).join(", ")}}`}[Symbol.for("nodejs.util.inspect.custom")](){return this.toString()}[Symbol.iterator](){return new Uo(this[dt],this[re])}}class Uo{constructor(t,e){this.childIndex=0,this.children=t.children,this.rowIndex=e,this.childFields=t.type.children,this.numChildren=this.childFields.length}[Symbol.iterator](){return this}next(){const t=this.childIndex;return te.name)}has(t,e){return t[dt].type.children.some(n=>n.name===e)}getOwnPropertyDescriptor(t,e){if(t[dt].type.children.some(n=>n.name===e))return{writable:!0,enumerable:!0,configurable:!0}}get(t,e){if(Reflect.has(t,e))return t[e];const n=t[dt].type.children.findIndex(s=>s.name===e);if(n!==-1){const s=Q.visit(t[dt].children[n],t[re]);return Reflect.set(t,e,s),s}}set(t,e,n){const s=t[dt].type.children.findIndex(r=>r.name===e);return s!==-1?(lt.visit(t[dt].children[s],t[re],n),Reflect.set(t,e,n)):Reflect.has(t,e)||typeof e=="symbol"?Reflect.set(t,e,n):!1}}const xo=new Ro;class y extends D{}function v(i){return(t,e)=>t.getValid(e)?i(t,e):null}const Co=(i,t)=>864e5*i[t],Eo=(i,t)=>null,$s=(i,t,e)=>{if(e+1>=t.length)return null;const n=V(t[e]),s=V(t[e+1]);return i.subarray(n,s)},Vo=({offset:i,values:t},e)=>{const n=i+e;return(t[n>>3]&1<Co(i,t),Ys=({values:i},t)=>V(i[t]),Ct=({stride:i,values:t},e)=>t[i*e],zo=({stride:i,values:t},e)=>vs(t[i*e]),Hs=({values:i},t)=>i[t],ko=({stride:i,values:t},e)=>t.subarray(i*e,i*(e+1)),Js=({values:i,valueOffsets:t},e)=>$s(i,t,e),Ks=({values:i,valueOffsets:t},e)=>{const n=$s(i,t,e);return n!==null?Ni(n):null},Po=({values:i},t)=>i[t],jo=({type:i,values:t},e)=>i.precision!==H.HALF?t[e]:vs(t[e]),$o=(i,t)=>i.type.unit===ct.DAY?Ws(i,t):Ys(i,t),Gs=({values:i},t)=>1e3*V(i[t]),Zs=({values:i},t)=>V(i[t]),qs=({values:i},t)=>Kn(i[t],BigInt(1e3)),Xs=({values:i},t)=>Kn(i[t],BigInt(1e6)),Wo=(i,t)=>{switch(i.type.unit){case I.SECOND:return Gs(i,t);case I.MILLISECOND:return Zs(i,t);case I.MICROSECOND:return qs(i,t);case I.NANOSECOND:return Xs(i,t)}},Qs=({values:i},t)=>i[t],tr=({values:i},t)=>i[t],er=({values:i},t)=>i[t],ir=({values:i},t)=>i[t],Yo=(i,t)=>{switch(i.type.unit){case I.SECOND:return Qs(i,t);case I.MILLISECOND:return tr(i,t);case I.MICROSECOND:return er(i,t);case I.NANOSECOND:return ir(i,t)}},Ho=({values:i,stride:t},e)=>Yi.decimal(i.subarray(t*e,t*(e+1))),Jo=(i,t)=>{const{valueOffsets:e,stride:n,children:s}=i,{[t*n]:r,[t*n+1]:o}=e,c=s[0].slice(r,o-r);return new x([c])},Ko=(i,t)=>{const{valueOffsets:e,children:n}=i,{[t]:s,[t+1]:r}=e,o=n[0];return new Ki(o.slice(s,r-s))},Go=(i,t)=>new Ji(i,t),Zo=(i,t)=>i.type.mode===X.Dense?nr(i,t):sr(i,t),nr=(i,t)=>{const e=i.type.typeIdToChildIndex[i.typeIds[t]],n=i.children[e];return Q.visit(n,i.valueOffsets[t])},sr=(i,t)=>{const e=i.type.typeIdToChildIndex[i.typeIds[t]],n=i.children[e];return Q.visit(n,t)},qo=(i,t)=>{var e;return(e=i.dictionary)===null||e===void 0?void 0:e.get(i.values[t])},Xo=(i,t)=>i.type.unit===$.MONTH_DAY_NANO?ar(i,t):i.type.unit===$.DAY_TIME?rr(i,t):or(i,t),rr=({values:i},t)=>i.subarray(2*t,2*(t+1)),or=({values:i},t)=>{const e=i[t],n=new Int32Array(2);return n[0]=Math.trunc(e/12),n[1]=Math.trunc(e%12),n},ar=({values:i},t)=>i.subarray(4*t,4*(t+1)),cr=({values:i},t)=>i[t],lr=({values:i},t)=>i[t],ur=({values:i},t)=>i[t],dr=({values:i},t)=>i[t],Qo=(i,t)=>{switch(i.type.unit){case I.SECOND:return cr(i,t);case I.MILLISECOND:return lr(i,t);case I.MICROSECOND:return ur(i,t);case I.NANOSECOND:return dr(i,t)}},ta=(i,t)=>{const{stride:e,children:n}=i,r=n[0].slice(t*e,e);return new x([r])};y.prototype.visitNull=v(Eo);y.prototype.visitBool=v(Vo);y.prototype.visitInt=v(Po);y.prototype.visitInt8=v(Ct);y.prototype.visitInt16=v(Ct);y.prototype.visitInt32=v(Ct);y.prototype.visitInt64=v(Hs);y.prototype.visitUint8=v(Ct);y.prototype.visitUint16=v(Ct);y.prototype.visitUint32=v(Ct);y.prototype.visitUint64=v(Hs);y.prototype.visitFloat=v(jo);y.prototype.visitFloat16=v(zo);y.prototype.visitFloat32=v(Ct);y.prototype.visitFloat64=v(Ct);y.prototype.visitUtf8=v(Ks);y.prototype.visitLargeUtf8=v(Ks);y.prototype.visitBinary=v(Js);y.prototype.visitLargeBinary=v(Js);y.prototype.visitFixedSizeBinary=v(ko);y.prototype.visitDate=v($o);y.prototype.visitDateDay=v(Ws);y.prototype.visitDateMillisecond=v(Ys);y.prototype.visitTimestamp=v(Wo);y.prototype.visitTimestampSecond=v(Gs);y.prototype.visitTimestampMillisecond=v(Zs);y.prototype.visitTimestampMicrosecond=v(qs);y.prototype.visitTimestampNanosecond=v(Xs);y.prototype.visitTime=v(Yo);y.prototype.visitTimeSecond=v(Qs);y.prototype.visitTimeMillisecond=v(tr);y.prototype.visitTimeMicrosecond=v(er);y.prototype.visitTimeNanosecond=v(ir);y.prototype.visitDecimal=v(Ho);y.prototype.visitList=v(Jo);y.prototype.visitStruct=v(Go);y.prototype.visitUnion=v(Zo);y.prototype.visitDenseUnion=v(nr);y.prototype.visitSparseUnion=v(sr);y.prototype.visitDictionary=v(qo);y.prototype.visitInterval=v(Xo);y.prototype.visitIntervalDayTime=v(rr);y.prototype.visitIntervalYearMonth=v(or);y.prototype.visitIntervalMonthDayNano=v(ar);y.prototype.visitDuration=v(Qo);y.prototype.visitDurationSecond=v(cr);y.prototype.visitDurationMillisecond=v(lr);y.prototype.visitDurationMicrosecond=v(ur);y.prototype.visitDurationNanosecond=v(dr);y.prototype.visitFixedSizeList=v(ta);y.prototype.visitMap=v(Ko);const Q=new y,Qt=Symbol.for("keys"),oe=Symbol.for("vals"),te=Symbol.for("kKeysAsStrings"),xi=Symbol.for("_kKeysAsStrings");class Ki{constructor(t){return this[Qt]=new x([t.children[0]]).memoize(),this[oe]=t.children[1],new Proxy(this,new ia)}get[te](){return this[xi]||(this[xi]=Array.from(this[Qt].toArray(),String))}[Symbol.iterator](){return new ea(this[Qt],this[oe])}get size(){return this[Qt].length}toArray(){return Object.values(this.toJSON())}toJSON(){const t=this[Qt],e=this[oe],n={};for(let s=-1,r=t.length;++s`${Ae(t)}: ${Ae(e)}`).join(", ")}}`}[Symbol.for("nodejs.util.inspect.custom")](){return this.toString()}}class ea{constructor(t,e){this.keys=t,this.vals=e,this.keyIndex=0,this.numKeys=t.length}[Symbol.iterator](){return this}next(){const t=this.keyIndex;return t===this.numKeys?{done:!0,value:null}:(this.keyIndex++,{done:!1,value:[this.keys.get(t),Q.visit(this.vals,t)]})}}class ia{isExtensible(){return!1}deleteProperty(){return!1}preventExtensions(){return!0}ownKeys(t){return t[te]}has(t,e){return t[te].includes(e)}getOwnPropertyDescriptor(t,e){if(t[te].indexOf(e)!==-1)return{writable:!0,enumerable:!0,configurable:!0}}get(t,e){if(Reflect.has(t,e))return t[e];const n=t[te].indexOf(e);if(n!==-1){const s=Q.visit(Reflect.get(t,oe),n);return Reflect.set(t,e,s),s}}set(t,e,n){const s=t[te].indexOf(e);return s!==-1?(lt.visit(Reflect.get(t,oe),s,n),Reflect.set(t,e,n)):Reflect.has(t,e)?Reflect.set(t,e,n):!1}}Object.defineProperties(Ki.prototype,{[Symbol.toStringTag]:{enumerable:!1,configurable:!1,value:"Row"},[Qt]:{writable:!0,enumerable:!1,configurable:!1,value:null},[oe]:{writable:!0,enumerable:!1,configurable:!1,value:null},[xi]:{writable:!0,enumerable:!1,configurable:!1,value:null}});let Sn;function hr(i,t,e,n){const{length:s=0}=i;let r=typeof t!="number"?0:t,o=typeof e!="number"?s:e;return r<0&&(r=(r%s+s)%s),o<0&&(o=(o%s+s)%s),os&&(o=s),n?n(i,r,o):[r,o]}const Gi=(i,t)=>i<0?t+i:i,wn=i=>i!==i;function he(i){if(typeof i!=="object"||i===null)return wn(i)?wn:e=>e===i;if(i instanceof Date){const e=i.valueOf();return n=>n instanceof Date?n.valueOf()===e:!1}return ArrayBuffer.isView(i)?e=>e?Xr(i,e):!1:i instanceof Map?sa(i):Array.isArray(i)?na(i):i instanceof x?ra(i):oa(i,!0)}function na(i){const t=[];for(let e=-1,n=i.length;++e!1;const n=[];for(let s=-1,r=e.length;++s{if(!e||typeof e!="object")return!1;switch(e.constructor){case Array:return aa(i,e);case Map:return Bn(i,e,e.keys());case Ki:case Ji:case Object:case void 0:return Bn(i,e,t||Object.keys(e))}return e instanceof x?ca(i,e):!1}}function aa(i,t){const e=i.length;if(t.length!==e)return!1;for(let n=-1;++n>n}function Dn(i,t,e){const n=e.byteLength+7&-8;if(i>0||e.byteLength>3):Ci(new Zi(e,i,t,null,fr)).subarray(0,n)),s}return e}function Ci(i){const t=[];let e=0,n=0,s=0;for(const o of i)o&&(s|=1<0)&&(t[e++]=s);const r=new Uint8Array(t.length+7&-8);return r.set(t),r}class Zi{constructor(t,e,n,s,r){this.bytes=t,this.length=n,this.context=s,this.get=r,this.bit=e%8,this.byteIndex=e>>3,this.byte=t[this.byteIndex++],this.index=0}next(){return this.index>3<<3,s=t+(t%8===0?0:8-t%8);return Ei(i,t,s)+Ei(i,n,e)+ua(i,s>>3,n-s>>3)}function ua(i,t,e){let n=0,s=Math.trunc(t);const r=new DataView(i.buffer,i.byteOffset,i.byteLength),o=e===void 0?i.byteLength:s+e;for(;o-s>=4;)n+=Oi(r.getUint32(s)),s+=4;for(;o-s>=2;)n+=Oi(r.getUint16(s)),s+=2;for(;o-s>=1;)n+=Oi(r.getUint8(s)),s+=1;return n}function Oi(i){let t=Math.trunc(i);return t=t-(t>>>1&1431655765),t=(t&858993459)+(t>>>2&858993459),(t+(t>>>4)&252645135)*16843009>>>24}const da=-1;class L{get typeId(){return this.type.typeId}get ArrayType(){return this.type.ArrayType}get buffers(){return[this.valueOffsets,this.values,this.nullBitmap,this.typeIds]}get nullable(){if(this._nullCount!==0){const{type:t}=this;return h.isSparseUnion(t)?this.children.some(e=>e.nullable):h.isDenseUnion(t)?this.children.some(e=>e.nullable):this.nullBitmap&&this.nullBitmap.byteLength>0}return!0}get byteLength(){let t=0;const{valueOffsets:e,values:n,nullBitmap:s,typeIds:r}=this;return e&&(t+=e.byteLength),n&&(t+=n.byteLength),s&&(t+=s.byteLength),r&&(t+=r.byteLength),this.children.reduce((o,a)=>o+a.byteLength,t)}get nullCount(){if(h.isUnion(this.type))return this.children.reduce((n,s)=>n+s.nullCount,0);let t=this._nullCount,e;return t<=da&&(e=this.nullBitmap)&&(this._nullCount=t=e.length===0?0:this.length-Ei(e,this.offset,this.offset+this.length)),t}constructor(t,e,n,s,r,o=[],a){this.type=t,this.children=o,this.dictionary=a,this.offset=Math.floor(Math.max(e||0,0)),this.length=Math.floor(Math.max(n||0,0)),this._nullCount=Math.floor(Math.max(s||0,-1));let c;r instanceof L?(this.stride=r.stride,this.values=r.values,this.typeIds=r.typeIds,this.nullBitmap=r.nullBitmap,this.valueOffsets=r.valueOffsets):(this.stride=Ot(t),r&&((c=r[0])&&(this.valueOffsets=c),(c=r[1])&&(this.values=c),(c=r[2])&&(this.nullBitmap=c),(c=r[3])&&(this.typeIds=c)))}getValid(t){const{type:e}=this;if(h.isUnion(e)){const n=e,s=this.children[n.typeIdToChildIndex[this.typeIds[t]]],r=n.mode===X.Dense?this.valueOffsets[t]:t;return s.getValid(r)}if(this.nullable&&this.nullCount>0){const n=this.offset+t;return(this.nullBitmap[n>>3]&1<>3;(!r||r.byteLength<=d)&&(r=new Uint8Array((o+a+63&-64)>>3).fill(255),this.nullCount>0?(r.set(Dn(o,a,this.nullBitmap),0),Object.assign(this,{nullBitmap:r})):Object.assign(this,{nullBitmap:r,_nullCount:0}));const f=r[d];n=(f&u)!==0,r[d]=e?f|u:f&~u}return n!==!!e&&(this._nullCount=this.nullCount+(e?-1:1)),e}clone(t=this.type,e=this.offset,n=this.length,s=this._nullCount,r=this,o=this.children){return new L(t,e,n,s,r,o,this.dictionary)}slice(t,e){const{stride:n,typeId:s,children:r}=this,o=+(this._nullCount===0)-1,a=s===16?n:1,c=this._sliceBuffers(t,e,n,s);return this.clone(this.type,this.offset+t,e,o,c,r.length===0||this.valueOffsets?r:this._sliceChildren(r,a*t,a*e))}_changeLengthAndBackfillNullBitmap(t){if(this.typeId===l.Null)return this.clone(this.type,0,t,0);const{length:e,nullCount:n}=this,s=new Uint8Array((t+63&-64)>>3).fill(255,0,e>>3);s[e>>3]=(1<0&&s.set(Dn(this.offset,e,this.nullBitmap),0);const r=this.buffers;return r[At.VALIDITY]=s,this.clone(this.type,0,t,n+(t-e),r)}_sliceBuffers(t,e,n,s){let r;const{buffers:o}=this;return(r=o[At.TYPE])&&(o[At.TYPE]=r.subarray(t,t+e)),(r=o[At.OFFSET])&&(o[At.OFFSET]=r.subarray(t,t+e+1))||(r=o[At.DATA])&&(o[At.DATA]=s===6?r:r.subarray(n*t,n*(t+e))),o}_sliceChildren(t,e,n){return t.map(s=>s.slice(e,n))}}L.prototype.children=Object.freeze([]);class we extends D{visit(t){return this.getVisitFn(t.type).call(this,t)}visitNull(t){const{["type"]:e,["offset"]:n=0,["length"]:s=0}=t;return new L(e,n,s,s)}visitBool(t){const{["type"]:e,["offset"]:n=0}=t,s=F(t.nullBitmap),r=U(e.ArrayType,t.data),{["length"]:o=r.length>>3,["nullCount"]:a=t.nullBitmap?-1:0}=t;return new L(e,n,o,a,[void 0,r,s])}visitInt(t){const{["type"]:e,["offset"]:n=0}=t,s=F(t.nullBitmap),r=U(e.ArrayType,t.data),{["length"]:o=r.length,["nullCount"]:a=t.nullBitmap?-1:0}=t;return new L(e,n,o,a,[void 0,r,s])}visitFloat(t){const{["type"]:e,["offset"]:n=0}=t,s=F(t.nullBitmap),r=U(e.ArrayType,t.data),{["length"]:o=r.length,["nullCount"]:a=t.nullBitmap?-1:0}=t;return new L(e,n,o,a,[void 0,r,s])}visitUtf8(t){const{["type"]:e,["offset"]:n=0}=t,s=F(t.data),r=F(t.nullBitmap),o=ye(t.valueOffsets),{["length"]:a=o.length-1,["nullCount"]:c=t.nullBitmap?-1:0}=t;return new L(e,n,a,c,[o,s,r])}visitLargeUtf8(t){const{["type"]:e,["offset"]:n=0}=t,s=F(t.data),r=F(t.nullBitmap),o=fn(t.valueOffsets),{["length"]:a=o.length-1,["nullCount"]:c=t.nullBitmap?-1:0}=t;return new L(e,n,a,c,[o,s,r])}visitBinary(t){const{["type"]:e,["offset"]:n=0}=t,s=F(t.data),r=F(t.nullBitmap),o=ye(t.valueOffsets),{["length"]:a=o.length-1,["nullCount"]:c=t.nullBitmap?-1:0}=t;return new L(e,n,a,c,[o,s,r])}visitLargeBinary(t){const{["type"]:e,["offset"]:n=0}=t,s=F(t.data),r=F(t.nullBitmap),o=fn(t.valueOffsets),{["length"]:a=o.length-1,["nullCount"]:c=t.nullBitmap?-1:0}=t;return new L(e,n,a,c,[o,s,r])}visitFixedSizeBinary(t){const{["type"]:e,["offset"]:n=0}=t,s=F(t.nullBitmap),r=U(e.ArrayType,t.data),{["length"]:o=r.length/Ot(e),["nullCount"]:a=t.nullBitmap?-1:0}=t;return new L(e,n,o,a,[void 0,r,s])}visitDate(t){const{["type"]:e,["offset"]:n=0}=t,s=F(t.nullBitmap),r=U(e.ArrayType,t.data),{["length"]:o=r.length/Ot(e),["nullCount"]:a=t.nullBitmap?-1:0}=t;return new L(e,n,o,a,[void 0,r,s])}visitTimestamp(t){const{["type"]:e,["offset"]:n=0}=t,s=F(t.nullBitmap),r=U(e.ArrayType,t.data),{["length"]:o=r.length/Ot(e),["nullCount"]:a=t.nullBitmap?-1:0}=t;return new L(e,n,o,a,[void 0,r,s])}visitTime(t){const{["type"]:e,["offset"]:n=0}=t,s=F(t.nullBitmap),r=U(e.ArrayType,t.data),{["length"]:o=r.length/Ot(e),["nullCount"]:a=t.nullBitmap?-1:0}=t;return new L(e,n,o,a,[void 0,r,s])}visitDecimal(t){const{["type"]:e,["offset"]:n=0}=t,s=F(t.nullBitmap),r=U(e.ArrayType,t.data),{["length"]:o=r.length/Ot(e),["nullCount"]:a=t.nullBitmap?-1:0}=t;return new L(e,n,o,a,[void 0,r,s])}visitList(t){const{["type"]:e,["offset"]:n=0,["child"]:s}=t,r=F(t.nullBitmap),o=ye(t.valueOffsets),{["length"]:a=o.length-1,["nullCount"]:c=t.nullBitmap?-1:0}=t;return new L(e,n,a,c,[o,void 0,r],[s])}visitStruct(t){const{["type"]:e,["offset"]:n=0,["children"]:s=[]}=t,r=F(t.nullBitmap),{length:o=s.reduce((c,{length:u})=>Math.max(c,u),0),nullCount:a=t.nullBitmap?-1:0}=t;return new L(e,n,o,a,[void 0,void 0,r],s)}visitUnion(t){const{["type"]:e,["offset"]:n=0,["children"]:s=[]}=t,r=U(e.ArrayType,t.typeIds),{["length"]:o=r.length,["nullCount"]:a=-1}=t;if(h.isSparseUnion(e))return new L(e,n,o,a,[void 0,void 0,void 0,r],s);const c=ye(t.valueOffsets);return new L(e,n,o,a,[c,void 0,void 0,r],s)}visitDictionary(t){const{["type"]:e,["offset"]:n=0}=t,s=F(t.nullBitmap),r=U(e.indices.ArrayType,t.data),{["dictionary"]:o=new x([new we().visit({type:e.dictionary})])}=t,{["length"]:a=r.length,["nullCount"]:c=t.nullBitmap?-1:0}=t;return new L(e,n,a,c,[void 0,r,s],[],o)}visitInterval(t){const{["type"]:e,["offset"]:n=0}=t,s=F(t.nullBitmap),r=U(e.ArrayType,t.data),{["length"]:o=r.length/Ot(e),["nullCount"]:a=t.nullBitmap?-1:0}=t;return new L(e,n,o,a,[void 0,r,s])}visitDuration(t){const{["type"]:e,["offset"]:n=0}=t,s=F(t.nullBitmap),r=U(e.ArrayType,t.data),{["length"]:o=r.length,["nullCount"]:a=t.nullBitmap?-1:0}=t;return new L(e,n,o,a,[void 0,r,s])}visitFixedSizeList(t){const{["type"]:e,["offset"]:n=0,["child"]:s=new we().visit({type:e.valueType})}=t,r=F(t.nullBitmap),{["length"]:o=s.length/Ot(e),["nullCount"]:a=t.nullBitmap?-1:0}=t;return new L(e,n,o,a,[void 0,void 0,r],[s])}visitMap(t){const{["type"]:e,["offset"]:n=0,["child"]:s=new we().visit({type:e.childType})}=t,r=F(t.nullBitmap),o=ye(t.valueOffsets),{["length"]:a=o.length-1,["nullCount"]:c=t.nullBitmap?-1:0}=t;return new L(e,n,a,c,[o,void 0,r],[s])}}const ha=new we;function A(i){return ha.visit(i)}class An{constructor(t=0,e){this.numChunks=t,this.getChunkIterator=e,this.chunkIndex=0,this.chunkIterator=this.getChunkIterator(0)}next(){for(;this.chunkIndext.nullable)}function yr(i){return i.reduce((t,e)=>t+e.nullCount,0)}function pr(i){return i.reduce((t,e,n)=>(t[n+1]=t[n]+e.length,t),new Uint32Array(i.length+1))}function mr(i,t,e,n){const s=[];for(let r=-1,o=i.length;++r=n)break;if(e>=c+u)continue;if(c>=e&&c+u<=n){s.push(a);continue}const d=Math.max(0,e-c),f=Math.min(n-c,u);s.push(a.slice(d,f-d))}return s.length===0&&s.push(i[0].slice(0,0)),s}function qi(i,t,e,n){let s=0,r=0,o=t.length-1;do{if(s>=o-1)return e0?0:-1}function pa(i,t){const{nullBitmap:e}=i;if(!e||i.nullCount<=0)return-1;let n=0;for(const s of new Zi(e,i.offset+(t||0),i.length,e,fr)){if(!s)return n;++n}return-1}function w(i,t,e){if(t===void 0)return-1;if(t===null)switch(i.typeId){case l.Union:break;case l.Dictionary:break;default:return pa(i,e)}const n=Q.getVisitFn(i),s=he(t);for(let r=(e||0)-1,o=i.length;++r{const s=i.data[n];return s.values.subarray(0,s.length)[Symbol.iterator]()});let e=0;return new An(i.data.length,n=>{const r=i.data[n].length,o=i.slice(e,e+r);return e+=r,new ma(o)})}class ma{constructor(t){this.vector=t,this.index=0}next(){return this.indexa.data):t;if(r.length===0||r.some(a=>!(a instanceof L)))throw new TypeError("Vector constructor expects an Array of Data instances.");const o=(e=r[0])===null||e===void 0?void 0:e.type;switch(r.length){case 0:this._offsets=[0];break;case 1:{const{get:a,set:c,indexOf:u}=Ir[o.typeId],d=r[0];this.isValid=f=>Xi(d,f),this.get=f=>a(d,f),this.set=(f,k)=>c(d,f,k),this.indexOf=f=>u(d,f),this._offsets=[0,d.length];break}default:Object.setPrototypeOf(this,Sr[o.typeId]),this._offsets=pr(r);break}this.data=r,this.type=o,this.stride=Ot(o),this.numChildren=(s=(n=o.children)===null||n===void 0?void 0:n.length)!==null&&s!==void 0?s:0,this.length=this._offsets.at(-1)}get byteLength(){return this.data.reduce((t,e)=>t+e.byteLength,0)}get nullable(){return fa(this.data)}get nullCount(){return yr(this.data)}get ArrayType(){return this.type.ArrayType}get[Symbol.toStringTag](){return`${this.VectorName}<${this.type[Symbol.toStringTag]}>`}get VectorName(){return`${l[this.type.typeId]}Vector`}isValid(t){return!1}get(t){return null}at(t){return this.get(Gi(t,this.length))}set(t,e){}indexOf(t,e){return-1}includes(t,e){return this.indexOf(t,e)>-1}[Symbol.iterator](){return Qi.visit(this)}concat(...t){return new x(this.data.concat(t.flatMap(e=>e.data).flat(Number.POSITIVE_INFINITY)))}slice(t,e){return new x(hr(this,t,e,({data:n,_offsets:s},r,o)=>mr(n,s,r,o)))}toJSON(){return[...this]}toArray(){const{type:t,data:e,length:n,stride:s,ArrayType:r}=this;switch(t.typeId){case l.Int:case l.Float:case l.Decimal:case l.Time:case l.Timestamp:switch(e.length){case 0:return new r;case 1:return e[0].values.subarray(0,n*s);default:return e.reduce((o,{values:a,length:c})=>(o.array.set(a.subarray(0,c*s),o.offset),o.offset+=c*s,o),{array:new r(n*s),offset:0}).array}}return[...this]}toString(){return`[${[...this].join(",")}]`}getChild(t){var e;return this.getChildAt((e=this.type.children)===null||e===void 0?void 0:e.findIndex(n=>n.name===t))}getChildAt(t){return t>-1&&te[t])):null}get isMemoized(){return h.isDictionary(this.type)?this.data[0].dictionary.isMemoized:!1}memoize(){if(h.isDictionary(this.type)){const t=new hi(this.data[0].dictionary),e=this.data.map(n=>{const s=n.clone();return s.dictionary=t,s});return new x(e)}return new hi(this)}unmemoize(){if(h.isDictionary(this.type)&&this.isMemoized){const t=this.data[0].dictionary.unmemoize(),e=this.data.map(n=>{const s=n.clone();return s.dictionary=t,s});return new x(e)}return this}}_r=Symbol.toStringTag;x[_r]=(i=>{i.type=h.prototype,i.data=[],i.length=0,i.stride=1,i.numChildren=0,i._offsets=new Uint32Array([0]),i[Symbol.isConcatSpreadable]=!0;const t=Object.keys(l).map(e=>l[e]).filter(e=>typeof e=="number"&&e!==l.NONE);for(const e of t){const n=Q.getVisitFnByTypeId(e),s=lt.getVisitFnByTypeId(e),r=di.getVisitFnByTypeId(e);Ir[e]={get:n,set:s,indexOf:r},Sr[e]=Object.create(i,{isValid:{value:ui(Xi)},get:{value:ui(Q.getVisitFnByTypeId(e))},set:{value:gr(lt.getVisitFnByTypeId(e))},indexOf:{value:br(di.getVisitFnByTypeId(e))}})}return"Vector"})(x.prototype);class hi extends x{constructor(t){super(t.data);const e=this.get,n=this.set,s=this.slice,r=new Array(this.length);Object.defineProperty(this,"get",{value(o){const a=r[o];if(a!==void 0)return a;const c=e.call(this,o);return r[o]=c,c}}),Object.defineProperty(this,"set",{value(o,a){n.call(this,o,a),r[o]=a}}),Object.defineProperty(this,"slice",{value:(o,a)=>new hi(s.call(this,o,a))}),Object.defineProperty(this,"isMemoized",{value:!0}),Object.defineProperty(this,"unmemoize",{value:()=>new x(this.data)}),Object.defineProperty(this,"memoize",{value:()=>this})}}class Vi{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}offset(){return this.bb.readInt64(this.bb_pos)}metaDataLength(){return this.bb.readInt32(this.bb_pos+8)}bodyLength(){return this.bb.readInt64(this.bb_pos+16)}static sizeOf(){return 24}static createBlock(t,e,n,s){return t.prep(8,24),t.writeInt64(BigInt(s??0)),t.pad(4),t.writeInt32(n),t.writeInt64(BigInt(e??0)),t.offset()}}class tt{constructor(){this.bb=null,this.bb_pos=0}__init(t,e){return this.bb_pos=t,this.bb=e,this}static getRootAsFooter(t,e){return(e||new tt).__init(t.readInt32(t.position())+t.position(),t)}static getSizePrefixedRootAsFooter(t,e){return t.setPosition(t.position()+R),(e||new tt).__init(t.readInt32(t.position())+t.position(),t)}version(){const t=this.bb.__offset(this.bb_pos,4);return t?this.bb.readInt16(this.bb_pos+t):P.V1}schema(t){const e=this.bb.__offset(this.bb_pos,6);return e?(t||new bt).__init(this.bb.__indirect(this.bb_pos+e),this.bb):null}dictionaries(t,e){const n=this.bb.__offset(this.bb_pos,8);return n?(e||new Vi).__init(this.bb.__vector(this.bb_pos+n)+t*24,this.bb):null}dictionariesLength(){const t=this.bb.__offset(this.bb_pos,8);return t?this.bb.__vector_len(this.bb_pos+t):0}recordBatches(t,e){const n=this.bb.__offset(this.bb_pos,10);return n?(e||new Vi).__init(this.bb.__vector(this.bb_pos+n)+t*24,this.bb):null}recordBatchesLength(){const t=this.bb.__offset(this.bb_pos,10);return t?this.bb.__vector_len(this.bb_pos+t):0}customMetadata(t,e){const n=this.bb.__offset(this.bb_pos,12);return n?(e||new j).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos+n)+t*4),this.bb):null}customMetadataLength(){const t=this.bb.__offset(this.bb_pos,12);return t?this.bb.__vector_len(this.bb_pos+t):0}static startFooter(t){t.startObject(5)}static addVersion(t,e){t.addFieldInt16(0,e,P.V1)}static addSchema(t,e){t.addFieldOffset(1,e,0)}static addDictionaries(t,e){t.addFieldOffset(2,e,0)}static startDictionariesVector(t,e){t.startVector(24,e,8)}static addRecordBatches(t,e){t.addFieldOffset(3,e,0)}static startRecordBatchesVector(t,e){t.startVector(24,e,8)}static addCustomMetadata(t,e){t.addFieldOffset(4,e,0)}static createCustomMetadataVector(t,e){t.startVector(4,e.length,4);for(let n=e.length-1;n>=0;n--)t.addOffset(e[n]);return t.endVector()}static startCustomMetadataVector(t,e){t.startVector(4,e,4)}static endFooter(t){return t.endObject()}static finishFooterBuffer(t,e){t.finish(e)}static finishSizePrefixedFooterBuffer(t,e){t.finish(e,void 0,!0)}}class N{constructor(t=[],e,n,s=P.V5){this.fields=t||[],this.metadata=e||new Map,n||(n=zi(this.fields)),this.dictionaries=n,this.metadataVersion=s}get[Symbol.toStringTag](){return"Schema"}get names(){return this.fields.map(t=>t.name)}toString(){return`Schema<{ ${this.fields.map((t,e)=>`${e}: ${t}`).join(", ")} }>`}select(t){const e=new Set(t),n=this.fields.filter(s=>e.has(s.name));return new N(n,this.metadata)}selectAt(t){const e=t.map(n=>this.fields[n]).filter(Boolean);return new N(e,this.metadata)}assign(...t){const e=t[0]instanceof N?t[0]:Array.isArray(t[0])?new N(t[0]):new N(t),n=[...this.fields],s=Ce(Ce(new Map,this.metadata),e.metadata),r=e.fields.filter(a=>{const c=n.findIndex(u=>u.name===a.name);return~c?(n[c]=a.clone({metadata:Ce(Ce(new Map,n[c].metadata),a.metadata)}))&&!1:!0}),o=zi(r,new Map);return new N([...n,...r],s,new Map([...this.dictionaries,...o]))}}N.prototype.fields=null;N.prototype.metadata=null;N.prototype.dictionaries=null;class E{static new(...t){let[e,n,s,r]=t;return t[0]&&typeof t[0]=="object"&&({name:e}=t[0],n===void 0&&(n=t[0].type),s===void 0&&(s=t[0].nullable),r===void 0&&(r=t[0].metadata)),new E(`${e}`,n,s,r)}constructor(t,e,n=!1,s){this.name=t,this.type=e,this.nullable=n,this.metadata=s||new Map}get typeId(){return this.type.typeId}get[Symbol.toStringTag](){return"Field"}toString(){return`${this.name}: ${this.type}`}clone(...t){let[e,n,s,r]=t;return!t[0]||typeof t[0]!="object"?[e=this.name,n=this.type,s=this.nullable,r=this.metadata]=t:{name:e=this.name,type:n=this.type,nullable:s=this.nullable,metadata:r=this.metadata}=t[0],E.new(e,n,s,r)}}E.prototype.type=null;E.prototype.name=null;E.prototype.nullable=null;E.prototype.metadata=null;function Ce(i,t){return new Map([...i||new Map,...t||new Map])}function zi(i,t=new Map){for(let e=-1,n=i.length;++e0&&zi(r.children,t)}return t}var ga=zn,ba=Ne;class tn{static decode(t){t=new ba(F(t));const e=tt.getRootAsFooter(t),n=N.decode(e.schema(),new Map,e.version());return new va(n,e)}static encode(t){const e=new ga,n=N.encode(e,t.schema);tt.startRecordBatchesVector(e,t.numRecordBatches);for(const o of[...t.recordBatches()].slice().reverse())le.encode(e,o);const s=e.endVector();tt.startDictionariesVector(e,t.numDictionaries);for(const o of[...t.dictionaryBatches()].slice().reverse())le.encode(e,o);const r=e.endVector();return tt.startFooter(e),tt.addSchema(e,n),tt.addVersion(e,P.V5),tt.addRecordBatches(e,s),tt.addDictionaries(e,r),tt.finishFooterBuffer(e,tt.endFooter(e)),e.asUint8Array()}get numRecordBatches(){return this._recordBatches.length}get numDictionaries(){return this._dictionaryBatches.length}constructor(t,e=P.V5,n,s){this.schema=t,this.version=e,n&&(this._recordBatches=n),s&&(this._dictionaryBatches=s)}*recordBatches(){for(let t,e=-1,n=this.numRecordBatches;++e=0&&t=0&&t=0&&t=0&&t=0;n--)t.addOffset(e[n]);return t.endVector()}static startCustomMetadataVector(t,e){t.startVector(4,e,4)}static endMessage(t){return t.endObject()}static finishMessageBuffer(t,e){t.finish(e)}static finishSizePrefixedMessageBuffer(t,e){t.finish(e,void 0,!0)}static createMessage(t,e,n,s,r,o){return mt.startMessage(t),mt.addVersion(t,e),mt.addHeaderType(t,n),mt.addHeader(t,s),mt.addBodyLength(t,r),mt.addCustomMetadata(t,o),mt.endMessage(t)}};class _a extends D{visit(t,e){return t==null||e==null?void 0:super.visit(t,e)}visitNull(t,e){return vn.startNull(e),vn.endNull(e)}visitInt(t,e){return et.startInt(e),et.addBitWidth(e,t.bitWidth),et.addIsSigned(e,t.isSigned),et.endInt(e)}visitFloat(t,e){return _t.startFloatingPoint(e),_t.addPrecision(e,t.precision),_t.endFloatingPoint(e)}visitBinary(t,e){return yn.startBinary(e),yn.endBinary(e)}visitLargeBinary(t,e){return mn.startLargeBinary(e),mn.endLargeBinary(e)}visitBool(t,e){return pn.startBool(e),pn.endBool(e)}visitUtf8(t,e){return _n.startUtf8(e),_n.endUtf8(e)}visitLargeUtf8(t,e){return gn.startLargeUtf8(e),gn.endLargeUtf8(e)}visitDecimal(t,e){return Jt.startDecimal(e),Jt.addScale(e,t.scale),Jt.addPrecision(e,t.precision),Jt.addBitWidth(e,t.bitWidth),Jt.endDecimal(e)}visitDate(t,e){return Ve.startDate(e),Ve.addUnit(e,t.unit),Ve.endDate(e)}visitTime(t,e){return rt.startTime(e),rt.addUnit(e,t.unit),rt.addBitWidth(e,t.bitWidth),rt.endTime(e)}visitTimestamp(t,e){const n=t.timezone&&e.createString(t.timezone)||void 0;return ot.startTimestamp(e),ot.addUnit(e,t.unit),n!==void 0&&ot.addTimezone(e,n),ot.endTimestamp(e)}visitInterval(t,e){return It.startInterval(e),It.addUnit(e,t.unit),It.endInterval(e)}visitDuration(t,e){return ze.startDuration(e),ze.addUnit(e,t.unit),ze.endDuration(e)}visitList(t,e){return bn.startList(e),bn.endList(e)}visitStruct(t,e){return zt.startStruct_(e),zt.endStruct_(e)}visitUnion(t,e){q.startTypeIdsVector(e,t.typeIds.length);const n=q.createTypeIdsVector(e,t.typeIds);return q.startUnion(e),q.addMode(e,t.mode),q.addTypeIds(e,n),q.endUnion(e)}visitDictionary(t,e){const n=this.visit(t.indices,e);return Ft.startDictionaryEncoding(e),Ft.addId(e,BigInt(t.id)),Ft.addIsOrdered(e,t.isOrdered),n!==void 0&&Ft.addIndexType(e,n),Ft.endDictionaryEncoding(e)}visitFixedSizeBinary(t,e){return ke.startFixedSizeBinary(e),ke.addByteWidth(e,t.byteWidth),ke.endFixedSizeBinary(e)}visitFixedSizeList(t,e){return Pe.startFixedSizeList(e),Pe.addListSize(e,t.listSize),Pe.endFixedSizeList(e)}visitMap(t,e){return je.startMap(e),je.addKeysSorted(e,t.keysSorted),je.endMap(e)}}const Fi=new _a;function Ia(i,t=new Map){return new N(wa(i,t),We(i.metadata),t)}function wr(i){return new it(i.count,Br(i.columns),Dr(i.columns),null)}function Sa(i){return new Bt(wr(i.data),i.id,i.isDelta)}function wa(i,t){return(i.fields||[]).filter(Boolean).map(e=>E.fromJSON(e,t))}function On(i,t){return(i.children||[]).filter(Boolean).map(e=>E.fromJSON(e,t))}function Br(i){return(i||[]).reduce((t,e)=>[...t,new fe(e.count,Ba(e.VALIDITY)),...Br(e.children)],[])}function Dr(i,t=[]){for(let e=-1,n=(i||[]).length;++et+ +(e===0),0)}function Da(i,t){let e,n,s,r,o,a;return!t||!(r=i.dictionary)?(o=Mn(i,On(i,t)),s=new E(i.name,o,i.nullable,We(i.metadata))):t.has(e=r.id)?(n=(n=r.indexType)?Fn(n):new Me,a=new ce(t.get(e),n,e,r.isOrdered),s=new E(i.name,a,i.nullable,We(i.metadata))):(n=(n=r.indexType)?Fn(n):new Me,t.set(e,o=Mn(i,On(i,t))),a=new ce(o,n,e,r.isOrdered),s=new E(i.name,a,i.nullable,We(i.metadata))),s||null}function We(i=[]){return new Map(i.map(({key:t,value:e})=>[t,e]))}function Fn(i){return new Pt(i.isSigned,i.bitWidth)}function Mn(i,t){const e=i.type.name;switch(e){case"NONE":return new Rt;case"null":return new Rt;case"binary":return new Ke;case"largebinary":return new Ge;case"utf8":return new Ze;case"largeutf8":return new qe;case"bool":return new Xe;case"list":return new ri((t||[])[0]);case"struct":return new K(t||[]);case"struct_":return new K(t||[])}switch(e){case"int":{const n=i.type;return new Pt(n.isSigned,n.bitWidth)}case"floatingpoint":{const n=i.type;return new Je(H[n.precision])}case"decimal":{const n=i.type;return new Qe(n.scale,n.precision,n.bitWidth)}case"date":{const n=i.type;return new ti(ct[n.unit])}case"time":{const n=i.type;return new ei(I[n.unit],n.bitWidth)}case"timestamp":{const n=i.type;return new ii(I[n.unit],n.timezone)}case"interval":{const n=i.type;return new ni($[n.unit])}case"duration":{const n=i.type;return new si(I[n.unit])}case"union":{const n=i.type,[s,...r]=(n.mode+"").toLowerCase(),o=s.toUpperCase()+r.join("");return new oi(X[o],n.typeIds||[],t||[])}case"fixedsizebinary":{const n=i.type;return new ai(n.byteWidth)}case"fixedsizelist":{const n=i.type;return new ci(n.listSize,(t||[])[0])}case"map":{const n=i.type;return new li((t||[])[0],n.keysSorted)}}throw new Error(`Unrecognized type: "${e}"`)}var Aa=zn,Oa=Ne;class ht{static fromJSON(t,e){const n=new ht(0,P.V5,e);return n._createHeader=Fa(t,e),n}static decode(t){t=new Oa(F(t));const e=Tt.getRootAsMessage(t),n=e.bodyLength(),s=e.version(),r=e.headerType(),o=new ht(n,s,r);return o._createHeader=Ma(e,r),o}static encode(t){const e=new Aa;let n=-1;return t.isSchema()?n=N.encode(e,t.header()):t.isRecordBatch()?n=it.encode(e,t.header()):t.isDictionaryBatch()&&(n=Bt.encode(e,t.header())),Tt.startMessage(e),Tt.addVersion(e,P.V5),Tt.addHeader(e,n),Tt.addHeaderType(e,t.headerType),Tt.addBodyLength(e,BigInt(t.bodyLength)),Tt.finishMessageBuffer(e,Tt.endMessage(e)),e.asUint8Array()}static from(t,e=0){if(t instanceof N)return new ht(0,P.V5,M.Schema,t);if(t instanceof it)return new ht(e,P.V5,M.RecordBatch,t);if(t instanceof Bt)return new ht(e,P.V5,M.DictionaryBatch,t);throw new Error(`Unrecognized Message header: ${t}`)}get type(){return this.headerType}get version(){return this._version}get headerType(){return this._headerType}get compression(){return this._compression}get bodyLength(){return this._bodyLength}header(){return this._createHeader()}isSchema(){return this.headerType===M.Schema}isRecordBatch(){return this.headerType===M.RecordBatch}isDictionaryBatch(){return this.headerType===M.DictionaryBatch}constructor(t,e,n,s){this._version=e,this._headerType=n,this.body=new Uint8Array(0),this._compression=s?.compression,s&&(this._createHeader=()=>s),this._bodyLength=V(t)}}let it=class{get nodes(){return this._nodes}get length(){return this._length}get buffers(){return this._buffers}get compression(){return this._compression}constructor(t,e,n,s){this._nodes=e,this._buffers=n,this._length=V(t),this._compression=s}};class Bt{get id(){return this._id}get data(){return this._data}get isDelta(){return this._isDelta}get length(){return this.data.length}get nodes(){return this.data.nodes}get buffers(){return this.data.buffers}constructor(t,e,n=!1){this._data=t,this._isDelta=n,this._id=V(e)}}class ft{constructor(t,e){this.offset=V(t),this.length=V(e)}}class fe{constructor(t,e){this.length=V(t),this.nullCount=V(e)}}class en{constructor(t,e=De.BUFFER){this.type=t,this.method=e}}function Fa(i,t){return(()=>{switch(t){case M.Schema:return N.fromJSON(i);case M.RecordBatch:return it.fromJSON(i);case M.DictionaryBatch:return Bt.fromJSON(i)}throw new Error(`Unrecognized Message type: { name: ${M[t]}, type: ${t} }`)})}function Ma(i,t){return(()=>{switch(t){case M.Schema:return N.decode(i.header(new bt),new Map,i.version());case M.RecordBatch:return it.decode(i.header(new gt),i.version());case M.DictionaryBatch:return Bt.decode(i.header(new Yt),i.version())}throw new Error(`Unrecognized Message type: { name: ${M[t]}, type: ${t} }`)})}E.encode=ka;E.decode=Va;E.fromJSON=Da;N.encode=za;N.decode=Na;N.fromJSON=Ia;it.encode=Pa;it.decode=La;it.fromJSON=wr;Bt.encode=ja;Bt.decode=Ta;Bt.fromJSON=Sa;fe.encode=$a;fe.decode=Ra;ft.encode=Wa;ft.decode=Ua;en.encode=Or;en.decode=Ar;function Na(i,t=new Map,e=P.V5){const n=Ea(i,t);return new N(n,Ye(i),t,e)}function La(i,t=P.V5){return new it(i.length(),xa(i),Ca(i,t),Ar(i.compression()))}function Ta(i,t=P.V5){return new Bt(it.decode(i.data(),t),i.id(),i.isDelta())}function Ua(i){return new ft(i.offset(),i.length())}function Ra(i){return new fe(i.length(),i.nullCount())}function xa(i){const t=[];for(let e,n=-1,s=-1,r=i.nodesLength();++nE.encode(i,r));bt.startFieldsVector(i,e.length);const n=bt.createFieldsVector(i,e),s=t.metadata&&t.metadata.size>0?bt.createCustomMetadataVector(i,[...t.metadata].map(([r,o])=>{const a=i.createString(`${r}`),c=i.createString(`${o}`);return j.startKeyValue(i),j.addKey(i,a),j.addValue(i,c),j.endKeyValue(i)})):-1;return bt.startSchema(i),bt.addFields(i,n),bt.addEndianness(i,Ya?ae.Little:ae.Big),s!==-1&&bt.addCustomMetadata(i,s),bt.endSchema(i)}function ka(i,t){let e=-1,n=-1,s=-1;const r=t.type;let o=t.typeId;h.isDictionary(r)?(o=r.dictionary.typeId,s=Fi.visit(r,i),n=Fi.visit(r.dictionary,i)):n=Fi.visit(r,i);const a=(r.children||[]).map(d=>E.encode(i,d)),c=nt.createChildrenVector(i,a),u=t.metadata&&t.metadata.size>0?nt.createCustomMetadataVector(i,[...t.metadata].map(([d,f])=>{const k=i.createString(`${d}`),W=i.createString(`${f}`);return j.startKeyValue(i),j.addKey(i,k),j.addValue(i,W),j.endKeyValue(i)})):-1;return t.name&&(e=i.createString(t.name)),nt.startField(i),nt.addType(i,n),nt.addTypeType(i,o),nt.addChildren(i,c),nt.addNullable(i,!!t.nullable),e!==-1&&nt.addName(i,e),s!==-1&&nt.addDictionary(i,s),u!==-1&&nt.addCustomMetadata(i,u),nt.endField(i)}function Pa(i,t){const e=t.nodes||[],n=t.buffers||[];gt.startNodesVector(i,e.length);for(const a of e.slice().reverse())fe.encode(i,a);const s=i.endVector();gt.startBuffersVector(i,n.length);for(const a of n.slice().reverse())ft.encode(i,a);const r=i.endVector();let o=null;return t.compression!==null&&(o=Or(i,t.compression)),gt.startRecordBatch(i),gt.addLength(i,BigInt(t.length)),gt.addNodes(i,s),gt.addBuffers(i,r),t.compression!==null&&o&>.addCompression(i,o),gt.endRecordBatch(i)}function Or(i,t){return pe.startBodyCompression(i),pe.addCodec(i,t.type),pe.addMethod(i,t.method),pe.endBodyCompression(i)}function ja(i,t){const e=it.encode(i,t.data);return Yt.startDictionaryBatch(i),Yt.addId(i,BigInt(t.id)),Yt.addIsDelta(i,t.isDelta),Yt.addData(i,e),Yt.endDictionaryBatch(i)}function $a(i,t){return Jn.createFieldNode(i,BigInt(t.length),BigInt(t.nullCount))}function Wa(i,t){return Hn.createBuffer(i,BigInt(t.offset),BigInt(t.length))}const Ya=(()=>{const i=new ArrayBuffer(2);return new DataView(i).setInt16(0,256,!0),new Int16Array(i)[0]===256})(),z=Object.freeze({done:!0,value:void 0});class Un{constructor(t){this._json=t}get schema(){return this._json.schema}get batches(){return this._json.batches||[]}get dictionaries(){return this._json.dictionaries||[]}}class Fr{tee(){return this._getDOMStream().tee()}pipe(t,e){return this._getNodeStream().pipe(t,e)}pipeTo(t,e){return this._getDOMStream().pipeTo(t,e)}pipeThrough(t,e){return this._getDOMStream().pipeThrough(t,e)}_getDOMStream(){return this._DOMStream||(this._DOMStream=this.toDOMStream())}_getNodeStream(){return this._nodeStream||(this._nodeStream=this.toNodeStream())}}class Ha extends Fr{constructor(){super(),this._values=[],this.resolvers=[],this._closedPromise=new Promise(t=>this._closedPromiseResolve=t)}get closed(){return this._closedPromise}cancel(t){return B(this,void 0,void 0,function*(){yield this.return(t)})}write(t){this._ensureOpen()&&(this.resolvers.length<=0?this._values.push(t):this.resolvers.shift().resolve({done:!1,value:t}))}abort(t){this._closedPromiseResolve&&(this.resolvers.length<=0?this._error={error:t}:this.resolvers.shift().reject({done:!0,value:t}))}close(){if(this._closedPromiseResolve){const{resolvers:t}=this;for(;t.length>0;)t.shift().resolve(z);this._closedPromiseResolve(),this._closedPromiseResolve=void 0}}[Symbol.asyncIterator](){return this}toDOMStream(t){return st.toDOMStream(this._closedPromiseResolve||this._error?this:this._values,t)}toNodeStream(t){return st.toNodeStream(this._closedPromiseResolve||this._error?this:this._values,t)}throw(t){return B(this,void 0,void 0,function*(){return yield this.abort(t),z})}return(t){return B(this,void 0,void 0,function*(){return yield this.close(),z})}read(t){return B(this,void 0,void 0,function*(){return(yield this.next(t,"read")).value})}peek(t){return B(this,void 0,void 0,function*(){return(yield this.next(t,"peek")).value})}next(...t){return this._values.length>0?Promise.resolve({done:!1,value:this._values.shift()}):this._error?Promise.reject({done:!0,value:this._error.error}):this._closedPromiseResolve?new Promise((e,n)=>{this.resolvers.push({resolve:e,reject:n})}):Promise.resolve(z)}_ensureOpen(){if(this._closedPromiseResolve)return!0;throw new Error("AsyncQueue is closed")}}class Ja extends Ha{write(t){if((t=F(t)).byteLength>0)return super.write(t)}toString(t=!1){return t?Ni(this.toUint8Array(!0)):this.toUint8Array(!1).then(Ni)}toUint8Array(t=!1){return t?wt(this._values)[0]:B(this,void 0,void 0,function*(){var e,n,s,r;const o=[];let a=0;try{for(var c=!0,u=ie(this),d;d=yield u.next(),e=d.done,!e;c=!0){r=d.value,c=!1;const f=r;o.push(f),a+=f.byteLength}}catch(f){n={error:f}}finally{try{!c&&!e&&(s=u.return)&&(yield s.call(u))}finally{if(n)throw n.error}}return wt(o,a)[0]})}}class fi{constructor(t){t&&(this.source=new Ka(st.fromIterable(t)))}[Symbol.iterator](){return this}next(t){return this.source.next(t)}throw(t){return this.source.throw(t)}return(t){return this.source.return(t)}peek(t){return this.source.peek(t)}read(t){return this.source.read(t)}}class ue{constructor(t){t instanceof ue?this.source=t.source:t instanceof Ja?this.source=new Et(st.fromAsyncIterable(t)):Wn(t)?this.source=new Et(st.fromNodeStream(t)):$i(t)?this.source=new Et(st.fromDOMStream(t)):jn(t)?this.source=new Et(st.fromDOMStream(t.body)):_i(t)?this.source=new Et(st.fromIterable(t)):Be(t)?this.source=new Et(st.fromAsyncIterable(t)):ji(t)&&(this.source=new Et(st.fromAsyncIterable(t)))}[Symbol.asyncIterator](){return this}next(t){return this.source.next(t)}throw(t){return this.source.throw(t)}return(t){return this.source.return(t)}get closed(){return this.source.closed}cancel(t){return this.source.cancel(t)}peek(t){return this.source.peek(t)}read(t){return this.source.read(t)}}class Ka{constructor(t){this.source=t}cancel(t){this.return(t)}peek(t){return this.next(t,"peek").value}read(t){return this.next(t,"read").value}next(t,e="read"){return this.source.next({cmd:e,size:t})}throw(t){return Object.create(this.source.throw&&this.source.throw(t)||z)}return(t){return Object.create(this.source.return&&this.source.return(t)||z)}}class Et{constructor(t){this.source=t,this._closedPromise=new Promise(e=>this._closedPromiseResolve=e)}cancel(t){return B(this,void 0,void 0,function*(){yield this.return(t)})}get closed(){return this._closedPromise}read(t){return B(this,void 0,void 0,function*(){return(yield this.next(t,"read")).value})}peek(t){return B(this,void 0,void 0,function*(){return(yield this.next(t,"peek")).value})}next(t){return B(this,arguments,void 0,function*(e,n="read"){return yield this.source.next({cmd:n,size:e})})}throw(t){return B(this,void 0,void 0,function*(){const e=this.source.throw&&(yield this.source.throw(t))||z;return this._closedPromiseResolve&&this._closedPromiseResolve(),this._closedPromiseResolve=void 0,Object.create(e)})}return(t){return B(this,void 0,void 0,function*(){const e=this.source.return&&(yield this.source.return(t))||z;return this._closedPromiseResolve&&this._closedPromiseResolve(),this._closedPromiseResolve=void 0,Object.create(e)})}}class Rn extends fi{constructor(t,e){super(),this.position=0,this.buffer=F(t),this.size=e===void 0?this.buffer.byteLength:e}readInt32(t){const{buffer:e,byteOffset:n}=this.readAt(t,4);return new DataView(e,n).getInt32(0,!0)}seek(t){return this.position=Math.min(t,this.size),t>>16,this.buffer[1]&65535,this.buffer[0]>>>16,this.buffer[0]&65535]),n=new Uint32Array([t.buffer[1]>>>16,t.buffer[1]&65535,t.buffer[0]>>>16,t.buffer[0]&65535]);let s=e[3]*n[3];this.buffer[0]=s&65535;let r=s>>>16;return s=e[2]*n[3],r+=s,s=e[3]*n[2]>>>0,r+=s,this.buffer[0]+=r<<16,this.buffer[1]=r>>>0>>16,this.buffer[1]+=e[1]*n[3]+e[2]*n[2]+e[3]*n[1],this.buffer[1]+=e[0]*n[3]+e[1]*n[2]+e[2]*n[1]+e[3]*n[0]<<16,this}_plus(t){const e=this.buffer[0]+t.buffer[0]>>>0;this.buffer[1]+=t.buffer[1],e>>0&&++this.buffer[1],this.buffer[0]=e}lessThan(t){return this.buffer[1]>>0,e[2]=this.buffer[2]+t.buffer[2]>>>0,e[1]=this.buffer[1]+t.buffer[1]>>>0,e[0]=this.buffer[0]+t.buffer[0]>>>0,e[0]>>0&&++e[1],e[1]>>0&&++e[2],e[2]>>0&&++e[3],this.buffer[3]=e[3],this.buffer[2]=e[2],this.buffer[1]=e[1],this.buffer[0]=e[0],this}hex(){return`${ee(this.buffer[3])} ${ee(this.buffer[2])} ${ee(this.buffer[1])} ${ee(this.buffer[0])}`}static multiply(t,e){return new vt(new Uint32Array(t.buffer)).times(e)}static add(t,e){return new vt(new Uint32Array(t.buffer)).plus(e)}static from(t,e=new Uint32Array(4)){return vt.fromString(typeof t=="string"?t:t.toString(),e)}static fromNumber(t,e=new Uint32Array(4)){return vt.fromString(t.toString(),e)}static fromString(t,e=new Uint32Array(4)){const n=t.startsWith("-"),s=t.length,r=new vt(e);for(let o=n?1:0;o>BigInt(32))):o+=2}return s}class sn extends D{constructor(t,e,n,s,r=P.V5){super(),this.nodesIndex=-1,this.buffersIndex=-1,this.bytes=t,this.nodes=e,this.buffers=n,this.dictionaries=s,this.metadataVersion=r}visit(t){return super.visit(t instanceof E?t.type:t)}visitNull(t,{length:e}=this.nextFieldNode()){return A({type:t,length:e})}visitBool(t,{length:e,nullCount:n}=this.nextFieldNode()){return A({type:t,length:e,nullCount:n,nullBitmap:this.readNullBitmap(t,n),data:this.readData(t)})}visitInt(t,{length:e,nullCount:n}=this.nextFieldNode()){return A({type:t,length:e,nullCount:n,nullBitmap:this.readNullBitmap(t,n),data:this.readData(t)})}visitFloat(t,{length:e,nullCount:n}=this.nextFieldNode()){return A({type:t,length:e,nullCount:n,nullBitmap:this.readNullBitmap(t,n),data:this.readData(t)})}visitUtf8(t,{length:e,nullCount:n}=this.nextFieldNode()){return A({type:t,length:e,nullCount:n,nullBitmap:this.readNullBitmap(t,n),valueOffsets:this.readOffsets(t),data:this.readData(t)})}visitLargeUtf8(t,{length:e,nullCount:n}=this.nextFieldNode()){return A({type:t,length:e,nullCount:n,nullBitmap:this.readNullBitmap(t,n),valueOffsets:this.readOffsets(t),data:this.readData(t)})}visitBinary(t,{length:e,nullCount:n}=this.nextFieldNode()){return A({type:t,length:e,nullCount:n,nullBitmap:this.readNullBitmap(t,n),valueOffsets:this.readOffsets(t),data:this.readData(t)})}visitLargeBinary(t,{length:e,nullCount:n}=this.nextFieldNode()){return A({type:t,length:e,nullCount:n,nullBitmap:this.readNullBitmap(t,n),valueOffsets:this.readOffsets(t),data:this.readData(t)})}visitFixedSizeBinary(t,{length:e,nullCount:n}=this.nextFieldNode()){return A({type:t,length:e,nullCount:n,nullBitmap:this.readNullBitmap(t,n),data:this.readData(t)})}visitDate(t,{length:e,nullCount:n}=this.nextFieldNode()){return A({type:t,length:e,nullCount:n,nullBitmap:this.readNullBitmap(t,n),data:this.readData(t)})}visitTimestamp(t,{length:e,nullCount:n}=this.nextFieldNode()){return A({type:t,length:e,nullCount:n,nullBitmap:this.readNullBitmap(t,n),data:this.readData(t)})}visitTime(t,{length:e,nullCount:n}=this.nextFieldNode()){return A({type:t,length:e,nullCount:n,nullBitmap:this.readNullBitmap(t,n),data:this.readData(t)})}visitDecimal(t,{length:e,nullCount:n}=this.nextFieldNode()){return A({type:t,length:e,nullCount:n,nullBitmap:this.readNullBitmap(t,n),data:this.readData(t)})}visitList(t,{length:e,nullCount:n}=this.nextFieldNode()){return A({type:t,length:e,nullCount:n,nullBitmap:this.readNullBitmap(t,n),valueOffsets:this.readOffsets(t),child:this.visit(t.children[0])})}visitStruct(t,{length:e,nullCount:n}=this.nextFieldNode()){return A({type:t,length:e,nullCount:n,nullBitmap:this.readNullBitmap(t,n),children:this.visitMany(t.children)})}visitUnion(t,{length:e,nullCount:n}=this.nextFieldNode()){return this.metadataVersion0&&this.readData(t,n)||new Uint8Array(0)}readOffsets(t,e){return this.readData(t,e)}readTypeIds(t,e){return this.readData(t,e)}readData(t,{length:e,offset:n}=this.nextBufferRange()){return this.bytes.subarray(n,n+e)}readDictionary(t){return this.dictionaries.get(t.id)}}class Xa extends sn{constructor(t,e,n,s,r){super(new Uint8Array(0),e,n,s,r),this.sources=t}readNullBitmap(t,e,{offset:n}=this.nextBufferRange()){return e<=0?new Uint8Array(0):Ci(this.sources[n])}readOffsets(t,{offset:e}=this.nextBufferRange()){return U(Uint8Array,U(t.OffsetArrayType,this.sources[e]))}readTypeIds(t,{offset:e}=this.nextBufferRange()){return U(Uint8Array,U(t.ArrayType,this.sources[e]))}readData(t,{offset:e}=this.nextBufferRange()){const{sources:n}=this;if(h.isTimestamp(t))return U(Uint8Array,Z.convertArray(n[e]));if((h.isInt(t)||h.isTime(t))&&t.bitWidth===64||h.isDuration(t))return U(Uint8Array,Z.convertArray(n[e]));if(h.isDate(t)&&t.unit===ct.MILLISECOND)return U(Uint8Array,Z.convertArray(n[e]));if(h.isDecimal(t))return U(Uint8Array,vt.convertArray(n[e]));if(h.isBinary(t)||h.isLargeBinary(t)||h.isFixedSizeBinary(t))return Qa(n[e]);if(h.isBool(t))return Ci(n[e]);if(h.isUtf8(t)||h.isLargeUtf8(t))return Pi(n[e].join(""));if(h.isInterval(t))switch(t.unit){case $.DAY_TIME:return Za(n[e]);case $.MONTH_DAY_NANO:return qa(n[e])}return U(Uint8Array,U(t.ArrayType,n[e].map(s=>+s)))}}function Qa(i){const t=i.join(""),e=new Uint8Array(t.length/2);for(let n=0;n>1]=Number.parseInt(t.slice(n,n+2),16);return e}class tc extends sn{constructor(t,e,n,s,r){super(new Uint8Array(0),e,n,s,r),this.bodyChunks=t}readData(t,e=this.nextBufferRange()){return this.bodyChunks[this.buffersIndex]}}class g extends D{compareSchemas(t,e){return t===e||e instanceof t.constructor&&this.compareManyFields(t.fields,e.fields)}compareManyFields(t,e){return t===e||Array.isArray(t)&&Array.isArray(e)&&t.length===e.length&&t.every((n,s)=>this.compareFields(n,e[s]))}compareFields(t,e){return t===e||e instanceof t.constructor&&t.name===e.name&&t.nullable===e.nullable&&this.visit(t.type,e.type)}}function G(i,t){return t instanceof i.constructor}function jt(i,t){return i===t||G(i,t)}function Lt(i,t){return i===t||G(i,t)&&i.bitWidth===t.bitWidth&&i.isSigned===t.isSigned}function Si(i,t){return i===t||G(i,t)&&i.precision===t.precision}function ec(i,t){return i===t||G(i,t)&&i.byteWidth===t.byteWidth}function rn(i,t){return i===t||G(i,t)&&i.unit===t.unit}function Le(i,t){return i===t||G(i,t)&&i.unit===t.unit&&i.timezone===t.timezone}function Te(i,t){return i===t||G(i,t)&&i.unit===t.unit&&i.bitWidth===t.bitWidth}function ic(i,t){return i===t||G(i,t)&&i.children.length===t.children.length&&xt.compareManyFields(i.children,t.children)}function nc(i,t){return i===t||G(i,t)&&i.children.length===t.children.length&&xt.compareManyFields(i.children,t.children)}function on(i,t){return i===t||G(i,t)&&i.mode===t.mode&&i.typeIds.every((e,n)=>e===t.typeIds[n])&&xt.compareManyFields(i.children,t.children)}function sc(i,t){return i===t||G(i,t)&&i.id===t.id&&i.isOrdered===t.isOrdered&&xt.visit(i.indices,t.indices)&&xt.visit(i.dictionary,t.dictionary)}function wi(i,t){return i===t||G(i,t)&&i.unit===t.unit}function Ue(i,t){return i===t||G(i,t)&&i.unit===t.unit}function rc(i,t){return i===t||G(i,t)&&i.listSize===t.listSize&&i.children.length===t.children.length&&xt.compareManyFields(i.children,t.children)}function oc(i,t){return i===t||G(i,t)&&i.keysSorted===t.keysSorted&&i.children.length===t.children.length&&xt.compareManyFields(i.children,t.children)}g.prototype.visitNull=jt;g.prototype.visitBool=jt;g.prototype.visitInt=Lt;g.prototype.visitInt8=Lt;g.prototype.visitInt16=Lt;g.prototype.visitInt32=Lt;g.prototype.visitInt64=Lt;g.prototype.visitUint8=Lt;g.prototype.visitUint16=Lt;g.prototype.visitUint32=Lt;g.prototype.visitUint64=Lt;g.prototype.visitFloat=Si;g.prototype.visitFloat16=Si;g.prototype.visitFloat32=Si;g.prototype.visitFloat64=Si;g.prototype.visitUtf8=jt;g.prototype.visitLargeUtf8=jt;g.prototype.visitBinary=jt;g.prototype.visitLargeBinary=jt;g.prototype.visitFixedSizeBinary=ec;g.prototype.visitDate=rn;g.prototype.visitDateDay=rn;g.prototype.visitDateMillisecond=rn;g.prototype.visitTimestamp=Le;g.prototype.visitTimestampSecond=Le;g.prototype.visitTimestampMillisecond=Le;g.prototype.visitTimestampMicrosecond=Le;g.prototype.visitTimestampNanosecond=Le;g.prototype.visitTime=Te;g.prototype.visitTimeSecond=Te;g.prototype.visitTimeMillisecond=Te;g.prototype.visitTimeMicrosecond=Te;g.prototype.visitTimeNanosecond=Te;g.prototype.visitDecimal=jt;g.prototype.visitList=ic;g.prototype.visitStruct=nc;g.prototype.visitUnion=on;g.prototype.visitDenseUnion=on;g.prototype.visitSparseUnion=on;g.prototype.visitDictionary=sc;g.prototype.visitInterval=wi;g.prototype.visitIntervalDayTime=wi;g.prototype.visitIntervalYearMonth=wi;g.prototype.visitIntervalMonthDayNano=wi;g.prototype.visitDuration=Ue;g.prototype.visitDurationSecond=Ue;g.prototype.visitDurationMillisecond=Ue;g.prototype.visitDurationMicrosecond=Ue;g.prototype.visitDurationNanosecond=Ue;g.prototype.visitFixedSizeList=rc;g.prototype.visitMap=oc;const xt=new g;function ac(i,t){return xt.compareSchemas(i,t)}function Mi(i,t){return cc(i,t.map(e=>e.data.concat()))}function cc(i,t){const e=[...i.fields],n=[],s={numBatches:t.reduce((f,k)=>Math.max(f,k.length),0)};let r=0,o=0,a=-1;const c=t.length;let u,d=[];for(;s.numBatches-- >0;){for(o=Number.POSITIVE_INFINITY,a=-1;++a0&&(n[r++]=A({type:new K(e),length:o,nullCount:0,children:d.slice()})))}return[i=i.assign(e),n.map(f=>new Y(i,f))]}function lc(i,t,e,n,s){var r;const o=(t+63&-64)>>3;for(let a=-1,c=n.length;++a=t)d===t?e[a]=u:(e[a]=u.slice(0,t),s.numBatches=Math.max(s.numBatches,n[a].unshift(u.slice(t,d-t))));else{const f=i[a];i[a]=f.clone({nullable:!0}),e[a]=(r=u?._changeLengthAndBackfillNullBitmap(t))!==null&&r!==void 0?r:A({type:f.type,length:t,nullCount:t,nullBitmap:new Uint8Array(o)})}}return e}var Nr;class at{constructor(...t){var e,n;if(t.length===0)return this.batches=[],this.schema=new N([]),this._offsets=[0],this;let s,r;t[0]instanceof N&&(s=t.shift()),t.at(-1)instanceof Uint32Array&&(r=t.pop());const o=c=>{if(c){if(c instanceof Y)return[c];if(c instanceof at)return c.batches;if(c instanceof L){if(c.type instanceof K)return[new Y(new N(c.type.children),c)]}else{if(Array.isArray(c))return c.flatMap(u=>o(u));if(typeof c[Symbol.iterator]=="function")return[...c].flatMap(u=>o(u));if(typeof c=="object"){const u=Object.keys(c),d=u.map(W=>new x([c[W]])),f=s??new N(u.map((W,ut)=>new E(String(W),d[ut].type,d[ut].nullable))),[,k]=Mi(f,d);return k.length===0?[new Y(c)]:k}}}return[]},a=t.flatMap(c=>o(c));if(s=(n=s??((e=a[0])===null||e===void 0?void 0:e.schema))!==null&&n!==void 0?n:new N([]),!(s instanceof N))throw new TypeError("Table constructor expects a [Schema, RecordBatch[]] pair.");for(const c of a){if(!(c instanceof Y))throw new TypeError("Table constructor expects a [Schema, RecordBatch[]] pair.");if(!ac(s,c.schema))throw new TypeError("Table and inner RecordBatch schemas must be equivalent.")}this.schema=s,this.batches=a,this._offsets=r??pr(this.data)}get data(){return this.batches.map(({data:t})=>t)}get numCols(){return this.schema.fields.length}get numRows(){return this.data.reduce((t,e)=>t+e.length,0)}get nullCount(){return this._nullCount===-1&&(this._nullCount=yr(this.data)),this._nullCount}isValid(t){return!1}get(t){return null}at(t){return this.get(Gi(t,this.numRows))}set(t,e){}indexOf(t,e){return-1}[Symbol.iterator](){return this.batches.length>0?Qi.visit(new x(this.data)):new Array(0)[Symbol.iterator]()}toArray(){return[...this]}toString(){return`[ + ${this.toArray().join(`, + `)} +]`}concat(...t){const e=this.schema,n=this.data.concat(t.flatMap(({data:s})=>s));return new at(e,n.map(s=>new Y(e,s)))}slice(t,e){const n=this.schema;[t,e]=hr({length:this.numRows},t,e);const s=mr(this.data,this._offsets,t,e);return new at(n,s.map(r=>new Y(n,r)))}getChild(t){return this.getChildAt(this.schema.fields.findIndex(e=>e.name===t))}getChildAt(t){if(t>-1&&tn.children[t]);if(e.length===0){const{type:n}=this.schema.fields[t],s=A({type:n,length:0,nullCount:0});e.push(s._changeLengthAndBackfillNullBitmap(this.numRows))}return new x(e)}return null}setChild(t,e){var n;return this.setChildAt((n=this.schema.fields)===null||n===void 0?void 0:n.findIndex(s=>s.name===t),e)}setChildAt(t,e){let n=this.schema,s=[...this.batches];if(t>-1&&tthis.getChildAt(u));[r[t],a[t]]=[o,e],[n,s]=Mi(n,a)}return new at(n,s)}select(t){const e=this.schema.fields.reduce((n,s,r)=>n.set(s.name,r),new Map);return this.selectAt(t.map(n=>e.get(n)).filter(n=>n>-1))}selectAt(t){const e=this.schema.selectAt(t),n=this.batches.map(s=>s.selectAt(t));return new at(e,n)}assign(t){const e=this.schema.fields,[n,s]=t.schema.fields.reduce((a,c,u)=>{const[d,f]=a,k=e.findIndex(W=>W.name===c.name);return~k?f[k]=u:d.push(u),a},[[],[]]),r=this.schema.assign(t.schema),o=[...e.map((a,c)=>[c,s[c]]).map(([a,c])=>c===void 0?this.getChildAt(a):t.getChildAt(c)),...n.map(a=>t.getChildAt(a))].filter(Boolean);return new at(...Mi(r,o))}}Nr=Symbol.toStringTag;at[Nr]=(i=>(i.schema=null,i.batches=[],i._offsets=new Uint32Array([0]),i._nullCount=-1,i[Symbol.isConcatSpreadable]=!0,i.isValid=ui(Xi),i.get=ui(Q.getVisitFn(l.Struct)),i.set=gr(lt.getVisitFn(l.Struct)),i.indexOf=br(di.getVisitFn(l.Struct)),"Table"))(at.prototype);var Lr;class Y{constructor(...t){switch(t.length){case 2:{if([this.schema]=t,!(this.schema instanceof N))throw new TypeError("RecordBatch constructor expects a [Schema, Data] pair.");if([,this.data=A({nullCount:0,type:new K(this.schema.fields),children:this.schema.fields.map(e=>A({type:e.type,nullCount:0}))})]=t,!(this.data instanceof L))throw new TypeError("RecordBatch constructor expects a [Schema, Data] pair.");[this.schema,this.data]=xn(this.schema,this.data.children);break}case 1:{const[e]=t,{fields:n,children:s,length:r}=Object.keys(e).reduce((c,u,d)=>(c.children[d]=e[u],c.length=Math.max(c.length,e[u].length),c.fields[d]=E.new({name:u,type:e[u].type,nullable:!0}),c),{length:0,fields:new Array,children:new Array}),o=new N(n),a=A({type:new K(n),length:r,children:s,nullCount:0});[this.schema,this.data]=xn(o,a.children,r);break}default:throw new TypeError("RecordBatch constructor expects an Object mapping names to child Data, or a [Schema, Data] pair.")}}get dictionaries(){return this._dictionaries||(this._dictionaries=Tr(this.schema.fields,this.data.children))}get numCols(){return this.schema.fields.length}get numRows(){return this.data.length}get nullCount(){return this.data.nullCount}isValid(t){return this.data.getValid(t)}get(t){return Q.visit(this.data,t)}at(t){return this.get(Gi(t,this.numRows))}set(t,e){return lt.visit(this.data,t,e)}indexOf(t,e){return di.visit(this.data,t,e)}[Symbol.iterator](){return Qi.visit(new x([this.data]))}toArray(){return[...this]}concat(...t){return new at(this.schema,[this,...t])}slice(t,e){const[n]=new x([this.data]).slice(t,e).data;return new Y(this.schema,n)}getChild(t){var e;return this.getChildAt((e=this.schema.fields)===null||e===void 0?void 0:e.findIndex(n=>n.name===t))}getChildAt(t){return t>-1&&ts.name===t),e)}setChildAt(t,e){let n=this.schema,s=this.data;if(t>-1&&ta.name===r);~o&&(s[o]=this.data.children[o])}return new Y(e,A({type:n,length:this.numRows,children:s}))}selectAt(t){const e=this.schema.selectAt(t),n=t.map(r=>this.data.children[r]).filter(Boolean),s=A({type:new K(e.fields),length:this.numRows,children:n});return new Y(e,s)}}Lr=Symbol.toStringTag;Y[Lr]=(i=>(i._nullCount=-1,i[Symbol.isConcatSpreadable]=!0,"RecordBatch"))(Y.prototype);function xn(i,t,e=t.reduce((n,s)=>Math.max(n,s.length),0)){var n;const s=[...i.fields],r=[...t],o=(e+63&-64)>>3;for(const[a,c]of i.fields.entries()){const u=t[a];(!u||u.length!==e)&&(s[a]=c.clone({nullable:!0}),r[a]=(n=u?._changeLengthAndBackfillNullBitmap(e))!==null&&n!==void 0?n:A({type:c.type,length:e,nullCount:e,nullBitmap:new Uint8Array(o)}))}return[i.assign(s),A({type:new K(s),length:e,children:r})]}function Tr(i,t,e=new Map){var n,s;if(((n=i?.length)!==null&&n!==void 0?n:0)>0&&i?.length===t?.length)for(let r=-1,o=i.length;++rA({type:s.type})),n=A({type:new K(t.fields),nullCount:0,children:e});super(t,n)}}const an=i=>`Expected ${M[i]} Message in stream, but was null or length 0.`,cn=i=>`Header pointer of flatbuffer-encoded ${M[i]} Message is null or length 0.`,Rr=(i,t)=>`Expected to read ${i} metadata bytes, but only read ${t}.`,xr=(i,t)=>`Expected to read ${i} bytes for message body, but only read ${t}.`;class Cr{constructor(t){this.source=t instanceof fi?t:new fi(t)}[Symbol.iterator](){return this}next(){let t;return(t=this.readMetadataLength()).done||t.value===-1&&(t=this.readMetadataLength()).done||(t=this.readMetadata(t.value)).done?z:t}throw(t){return this.source.throw(t)}return(t){return this.source.return(t)}readMessage(t){let e;if((e=this.next()).done)return null;if(t!=null&&e.value.headerType!==t)throw new Error(an(t));return e.value}readMessageBody(t){if(t<=0)return new Uint8Array(0);const e=F(this.source.read(t));if(e.byteLength[...s,...r.VALIDITY&&[r.VALIDITY]||[],...r.TYPE_ID&&[r.TYPE_ID]||[],...r.OFFSET&&[r.OFFSET]||[],...r.DATA&&[r.DATA]||[],...e(r.children)],[])}}readMessage(t){let e;if((e=this.next()).done)return null;if(t!=null&&e.value.headerType!==t)throw new Error(an(t));return e.value}readSchema(){const t=M.Schema,e=this.readMessage(t),n=e?.header();if(!e||!n)throw new Error(cn(t));return n}}const Bi=4,ki="ARROW1",pi=new Uint8Array(ki.length);for(let i=0;i=this.MIN_HEADER_LENGTH}_hasValidMagicNumber(t){return this.LZ4_FRAME_MAGIC.every((e,n)=>t[n]===e)}_hasValidVersion(t){return(t[4]&192)>>6===1}}class yc{constructor(){this.ZSTD_MAGIC=new Uint8Array([40,181,47,253]),this.MIN_HEADER_LENGTH=6}isValidCodecEncode(t){const e=new Uint8Array([1,2,3,4,5,6,7,8]),n=t.encode(e);return this._isValidCompressed(n)}_isValidCompressed(t){return this._hasMinimumLength(t)&&this._hasValidMagicNumber(t)}_hasMinimumLength(t){return t.length>=this.MIN_HEADER_LENGTH}_hasValidMagicNumber(t){return this.ZSTD_MAGIC.every((e,n)=>t[n]===e)}}const pc={[kt.LZ4_FRAME]:new fc,[kt.ZSTD]:new yc};class mc{constructor(){this.registry={}}set(t,e){if(e?.encode&&typeof e.encode=="function"&&!pc[t].isValidCodecEncode(e))throw new Error(`Encoder for ${kt[t]} is not valid.`);this.registry[t]=e}get(t){var e;return((e=this.registry)===null||e===void 0?void 0:e[t])||null}}const Cn=new mc,gc=-1,bc=8;class Mt extends Fr{constructor(t){super(),this._impl=t}get closed(){return this._impl.closed}get schema(){return this._impl.schema}get autoDestroy(){return this._impl.autoDestroy}get dictionaries(){return this._impl.dictionaries}get numDictionaries(){return this._impl.numDictionaries}get numRecordBatches(){return this._impl.numRecordBatches}get footer(){return this._impl.isFile()?this._impl.footer:null}isSync(){return this._impl.isSync()}isAsync(){return this._impl.isAsync()}isFile(){return this._impl.isFile()}isStream(){return this._impl.isStream()}next(){return this._impl.next()}throw(t){return this._impl.throw(t)}return(t){return this._impl.return(t)}cancel(){return this._impl.cancel()}reset(t){return this._impl.reset(t),this._DOMStream=void 0,this._nodeStream=void 0,this}open(t){const e=this._impl.open(t);return Be(e)?e.then(()=>this):this}readRecordBatch(t){return this._impl.isFile()?this._impl.readRecordBatch(t):null}[Symbol.iterator](){return this._impl[Symbol.iterator]()}[Symbol.asyncIterator](){return this._impl[Symbol.asyncIterator]()}toDOMStream(){return st.toDOMStream(this.isSync()?{[Symbol.iterator]:()=>this}:{[Symbol.asyncIterator]:()=>this})}toNodeStream(){return st.toNodeStream(this.isSync()?{[Symbol.iterator]:()=>this}:{[Symbol.asyncIterator]:()=>this},{objectMode:!0})}static throughNode(t){throw new Error('"throughNode" not available in this environment')}static throughDOM(t,e){throw new Error('"throughDOM" not available in this environment')}static from(t){return t instanceof Mt?t:Li(t)?Sc(t):Pn(t)?Dc(t):Be(t)?B(this,void 0,void 0,function*(){return yield Mt.from(yield t)}):jn(t)||$i(t)||Wn(t)||ji(t)?Bc(new ue(t)):wc(new fi(t))}static readAll(t){return t instanceof Mt?t.isSync()?En(t):Vn(t):Li(t)||ArrayBuffer.isView(t)||_i(t)||kn(t)?En(t):Vn(t)}}class mi extends Mt{constructor(t){super(t),this._impl=t}readAll(){return[...this]}[Symbol.iterator](){return this._impl[Symbol.iterator]()}[Symbol.asyncIterator](){return St(this,arguments,function*(){yield O(yield*Ee(ie(this[Symbol.iterator]())))})}}class gi extends Mt{constructor(t){super(t),this._impl=t}readAll(){return B(this,void 0,void 0,function*(){var t,e,n,s;const r=new Array;try{for(var o=!0,a=ie(this),c;c=yield a.next(),t=c.done,!t;o=!0){s=c.value,o=!1;const u=s;r.push(u)}}catch(u){e={error:u}}finally{try{!o&&!t&&(n=a.return)&&(yield n.call(a))}finally{if(e)throw e.error}}return r})}[Symbol.iterator](){throw new Error("AsyncRecordBatchStreamReader is not Iterable")}[Symbol.asyncIterator](){return this._impl[Symbol.asyncIterator]()}}class Vr extends mi{constructor(t){super(t),this._impl=t}}class vc extends gi{constructor(t){super(t),this._impl=t}}class zr{get numDictionaries(){return this._dictionaryIndex}get numRecordBatches(){return this._recordBatchIndex}constructor(t=new Map){this.closed=!1,this.autoDestroy=!0,this._dictionaryIndex=0,this._recordBatchIndex=0,this.dictionaries=t}isSync(){return!1}isAsync(){return!1}isFile(){return!1}isStream(){return!1}reset(t){return this._dictionaryIndex=0,this._recordBatchIndex=0,this.schema=t,this.dictionaries=new Map,this}_loadRecordBatch(t,e){let n;if(t.compression!=null){const r=Cn.get(t.compression.type);if(r?.decode&&typeof r.decode=="function"){const{decommpressedBody:o,buffers:a}=this._decompressBuffers(t,e,r);n=this._loadCompressedVectors(t,o,this.schema.fields),t=new it(t.length,t.nodes,a,null)}else throw new Error("Record batch is compressed but codec not found")}else n=this._loadVectors(t,e,this.schema.fields);const s=A({type:new K(this.schema.fields),length:t.length,children:n});return new Y(this.schema,s)}_loadDictionaryBatch(t,e){const{id:n,isDelta:s}=t,{dictionaries:r,schema:o}=this,a=r.get(n),c=o.dictionaries.get(n);let u;if(t.data.compression!=null){const d=Cn.get(t.data.compression.type);if(d?.decode&&typeof d.decode=="function"){const{decommpressedBody:f,buffers:k}=this._decompressBuffers(t.data,e,d);u=this._loadCompressedVectors(t.data,f,[c]),t=new Bt(new it(t.data.length,t.data.nodes,k,null),n,s)}else throw new Error("Dictionary batch is compressed but codec not found")}else u=this._loadVectors(t.data,e,[c]);return(a&&s?a.concat(new x(u)):new x(u)).memoize()}_loadVectors(t,e,n){return new sn(e,t.nodes,t.buffers,this.dictionaries,this.schema.metadataVersion).visitMany(n)}_loadCompressedVectors(t,e,n){return new tc(e,t.nodes,t.buffers,this.dictionaries,this.schema.metadataVersion).visitMany(n)}_decompressBuffers(t,e,n){const s=[],r=[];let o=0;for(const{offset:a,length:c}of t.buffers){if(c===0){s.push(new Uint8Array(0)),r.push(new ft(o,0));continue}const u=new Ne(e.subarray(a,a+c)),d=V(u.readInt64(0)),f=u.bytes().subarray(bc),k=d===gc?f:n.decode(f);s.push(k);const W=(o+7&-8)-o;o+=W,r.push(new ft(o,k.length)),o+=k.length}return{decommpressedBody:s,buffers:r}}}class bi extends zr{constructor(t,e){super(e),this._reader=Li(t)?new dc(this._handle=t):new Cr(this._handle=t)}isSync(){return!0}isStream(){return!0}[Symbol.iterator](){return this}cancel(){!this.closed&&(this.closed=!0)&&(this.reset()._reader.return(),this._reader=null,this.dictionaries=null)}open(t){return this.closed||(this.autoDestroy=Pr(this,t),this.schema||(this.schema=this._reader.readSchema())||this.cancel()),this}throw(t){return!this.closed&&this.autoDestroy&&(this.closed=!0)?this.reset()._reader.throw(t):z}return(t){return!this.closed&&this.autoDestroy&&(this.closed=!0)?this.reset()._reader.return(t):z}next(){if(this.closed)return z;let t;const{_reader:e}=this;for(;t=this._readNextMessageAndValidate();)if(t.isSchema())this.reset(t.header());else if(t.isRecordBatch()){this._recordBatchIndex++;const n=t.header(),s=e.readMessageBody(t.bodyLength);return{done:!1,value:this._loadRecordBatch(n,s)}}else if(t.isDictionaryBatch()){this._dictionaryIndex++;const n=t.header(),s=e.readMessageBody(t.bodyLength),r=this._loadDictionaryBatch(n,s);this.dictionaries.set(n.id,r)}return this.schema&&this._recordBatchIndex===0?(this._recordBatchIndex++,{done:!1,value:new Ur(this.schema)}):this.return()}_readNextMessageAndValidate(t){return this._reader.readMessage(t)}}class vi extends zr{constructor(t,e){super(e),this._reader=new uc(this._handle=t)}isAsync(){return!0}isStream(){return!0}[Symbol.asyncIterator](){return this}cancel(){return B(this,void 0,void 0,function*(){!this.closed&&(this.closed=!0)&&(yield this.reset()._reader.return(),this._reader=null,this.dictionaries=null)})}open(t){return B(this,void 0,void 0,function*(){return this.closed||(this.autoDestroy=Pr(this,t),this.schema||(this.schema=yield this._reader.readSchema())||(yield this.cancel())),this})}throw(t){return B(this,void 0,void 0,function*(){return!this.closed&&this.autoDestroy&&(this.closed=!0)?yield this.reset()._reader.throw(t):z})}return(t){return B(this,void 0,void 0,function*(){return!this.closed&&this.autoDestroy&&(this.closed=!0)?yield this.reset()._reader.return(t):z})}next(){return B(this,void 0,void 0,function*(){if(this.closed)return z;let t;const{_reader:e}=this;for(;t=yield this._readNextMessageAndValidate();)if(t.isSchema())yield this.reset(t.header());else if(t.isRecordBatch()){this._recordBatchIndex++;const n=t.header(),s=yield e.readMessageBody(t.bodyLength);return{done:!1,value:this._loadRecordBatch(n,s)}}else if(t.isDictionaryBatch()){this._dictionaryIndex++;const n=t.header(),s=yield e.readMessageBody(t.bodyLength),r=this._loadDictionaryBatch(n,s);this.dictionaries.set(n.id,r)}return this.schema&&this._recordBatchIndex===0?(this._recordBatchIndex++,{done:!1,value:new Ur(this.schema)}):yield this.return()})}_readNextMessageAndValidate(t){return B(this,void 0,void 0,function*(){return yield this._reader.readMessage(t)})}}class kr extends bi{get footer(){return this._footer}get numDictionaries(){return this._footer?this._footer.numDictionaries:0}get numRecordBatches(){return this._footer?this._footer.numRecordBatches:0}constructor(t,e){super(t instanceof Rn?t:new Rn(t),e)}isSync(){return!0}isFile(){return!0}open(t){if(!this.closed&&!this._footer){this.schema=(this._footer=this._readFooter()).schema;for(const e of this._footer.dictionaryBatches())e&&this._readDictionaryBatch(this._dictionaryIndex++)}return super.open(t)}readRecordBatch(t){var e;if(this.closed)return null;this._footer||this.open();const n=(e=this._footer)===null||e===void 0?void 0:e.getRecordBatch(t);if(n&&this._handle.seek(n.offset)){const s=this._reader.readMessage(M.RecordBatch);if(s?.isRecordBatch()){const r=s.header(),o=this._reader.readMessageBody(s.bodyLength);return this._loadRecordBatch(r,o)}}return null}_readDictionaryBatch(t){var e;const n=(e=this._footer)===null||e===void 0?void 0:e.getDictionaryBatch(t);if(n&&this._handle.seek(n.offset)){const s=this._reader.readMessage(M.DictionaryBatch);if(s?.isDictionaryBatch()){const r=s.header(),o=this._reader.readMessageBody(s.bodyLength),a=this._loadDictionaryBatch(r,o);this.dictionaries.set(r.id,a)}}}_readFooter(){const{_handle:t}=this,e=t.size-Er,n=t.readInt32(e),s=t.readAt(e-n,n);return tn.decode(s)}_readNextMessageAndValidate(t){var e;if(this._footer||this.open(),this._footer&&this._recordBatchIndexsuper.open}});return B(this,void 0,void 0,function*(){if(!this.closed&&!this._footer){this.schema=(this._footer=yield this._readFooter()).schema;for(const n of this._footer.dictionaryBatches())n&&(yield this._readDictionaryBatch(this._dictionaryIndex++))}return yield e.open.call(this,t)})}readRecordBatch(t){return B(this,void 0,void 0,function*(){var e;if(this.closed)return null;this._footer||(yield this.open());const n=(e=this._footer)===null||e===void 0?void 0:e.getRecordBatch(t);if(n&&(yield this._handle.seek(n.offset))){const s=yield this._reader.readMessage(M.RecordBatch);if(s?.isRecordBatch()){const r=s.header(),o=yield this._reader.readMessageBody(s.bodyLength);return this._loadRecordBatch(r,o)}}return null})}_readDictionaryBatch(t){return B(this,void 0,void 0,function*(){var e;const n=(e=this._footer)===null||e===void 0?void 0:e.getDictionaryBatch(t);if(n&&(yield this._handle.seek(n.offset))){const s=yield this._reader.readMessage(M.DictionaryBatch);if(s?.isDictionaryBatch()){const r=s.header(),o=yield this._reader.readMessageBody(s.bodyLength),a=this._loadDictionaryBatch(r,o);this.dictionaries.set(r.id,a)}}})}_readFooter(){return B(this,void 0,void 0,function*(){const{_handle:t}=this;t._pending&&(yield t._pending);const e=t.size-Er,n=yield t.readInt32(e),s=yield t.readAt(e-n,n);return tn.decode(s)})}_readNextMessageAndValidate(t){return B(this,void 0,void 0,function*(){if(this._footer||(yield this.open()),this._footer&&this._recordBatchIndex=4?ln(t)?new Vr(new kr(i.read())):new mi(new bi(i)):new mi(new bi((function*(){})()))}function Bc(i){return B(this,void 0,void 0,function*(){const t=yield i.peek(Re+7&-8);return t&&t.byteLength>=4?ln(t)?new Vr(new kr(yield i.read())):new gi(new vi(i)):new gi(new vi((function(){return St(this,arguments,function*(){})})()))})}function Dc(i){return B(this,void 0,void 0,function*(){const{size:t}=yield i.stat(),e=new yi(i,t);return t>=hc&&ln(yield e.readAt(0,Re+7&-8))?new vc(new _c(e)):new gi(new vi(e))})}function Ac(i){const t=Mt.from(i);return Be(t)?t.then(e=>Ac(e)):t.isAsync()?t.readAll().then(e=>new at(e)):new at(t.readAll())}export{Ac as t}; diff --git a/assets/axes-Csd25CoG.js b/assets/axes-Csd25CoG.js new file mode 100644 index 00000000..b97cae09 --- /dev/null +++ b/assets/axes-Csd25CoG.js @@ -0,0 +1,4 @@ +import{c as h,a as b,b as w}from"./menu-CKBxhbUC.js";import{l as m,a as f,b as $,s as v}from"./d3-IoKfXBi0.js";import"./vendor-DRFCw67i.js";const z=document.querySelector("#parent-wrapper"),i=document.querySelector("#canvas-wrapper"),A=document.querySelector("#canvas"),C=[0,42],M=[0,4.2],y=m().domain(C),u=m().domain(M),a=f(y),o=$(u),n=v(z).append("svg"),d=n.append("g"),p=n.append("g"),k=20,I=40;n.node().style.position="absolute";n.node().style.top=0;n.node().style.left=0;n.node().style.width="100%";n.node().style.height="100%";n.node().style.pointerEvents="none";i.style.right=`${I}px`;i.style.bottom=`${k}px`;let{width:s,height:c}=i.getBoundingClientRect();d.attr("transform",`translate(0, ${c})`).call(a);p.attr("transform",`translate(${s}, 0)`).call(o);a.tickSizeInner(-c);o.tickSizeInner(-s);let g=[],B=1e5,P=2,R=.5,l=[];const q=({points:t})=>{if(console.log("Selected:",t),l=t,l.length===1){const r=g[l[0]];console.log(`X: ${r[0]} +Y: ${r[1]} +Category: ${r[2]} +Value: ${r[3]}`)}},D=()=>{console.log("Deselected:",l),l=[]},e=h({canvas:A,pointSize:P,opacity:R,xScale:y,yScale:u,showReticle:!0,lassoInitiator:!0});b(e);console.log(`Scatterplot v${e.get("version")}`);e.subscribe("select",q);e.subscribe("deselect",D);e.subscribe("view",t=>{d.call(a.scale(t.xScale)),p.call(o.scale(t.yScale))});e.subscribe("init",()=>{d.call(a.scale(e.get("xScale"))),p.call(o.scale(e.get("yScale")))},1);const x=()=>{({width:s,height:c}=i.getBoundingClientRect()),d.attr("transform",`translate(0, ${c})`).call(a),p.attr("transform",`translate(${s}, 0)`).call(o),a.tickSizeInner(-c),o.tickSizeInner(-s)};window.addEventListener("resize",x);window.addEventListener("orientationchange",x);const E=t=>new Array(t).fill().map(()=>[-1+Math.random()*2,-1+Math.random()*2,Math.round(Math.random()*9),Math.random()]),S=t=>{g=E(t),e.draw(g)};w({scatterplot:e,setNumPoints:S});e.set({colorBy:"category",pointColor:["#d192b7","#6fb2e4","#eecb62","#56bf92","#dca237","#3a84cc","#c76526"]});S(B); diff --git a/assets/connected-points-28ENO6C6.js b/assets/connected-points-28ENO6C6.js new file mode 100644 index 00000000..7fc966d0 --- /dev/null +++ b/assets/connected-points-28ENO6C6.js @@ -0,0 +1,4 @@ +import{c as y,a as S,b as m}from"./menu-CKBxhbUC.js";import"./vendor-DRFCw67i.js";const v=document.querySelector("#canvas");let r=[],g=9e3,p=1,d=.33,i=[];const h=10,P=10,z=2,f=!0,M=[1,1,.878431373,.33],b=!0,B=[1,1,1,.15],$=2,A=({points:o})=>{if(console.log("Selected:",o),i=o,i.length===1){const t=r[i[0]];console.log(`X: ${t[0]} +Y: ${t[1]} +Category: ${t[2]} +Value: ${t[3]}`)}},w=()=>{console.log("Deselected:",i),i=[]},n=y({canvas:v,lassoMinDelay:P,lassoMinDist:z,pointSize:p,opacity:d,showReticle:f,reticleColor:M,showPointConnections:b,pointConnectionColor:B,pointConnectionSize:$,lassoInitiator:!0});S(n);console.log(`Scatterplot v${n.get("version")}`);n.subscribe("select",A);n.subscribe("deselect",w);const D=o=>{const t=Math.round(o/3),s=Math.round(t/5),a=[];for(let e=0;e<3;e++)for(let c=0;c{r=D(o),n.draw(r)},H=o=>Array.from({length:100},(t,s)=>1+s/99*(o*h-1)),C=o=>{n.set({pointSize:H(o)})};m({scatterplot:n,setNumPoints:u,setPointSize:C});n.set({colorBy:"valueZ",sizeBy:"valueW",pointColor:[[255,128,203,128],[87,199,255,128],[238,228,98,128]],pointConnectionColorBy:"valueZ",pointConnectionColor:[[255,128,203,6],[87,199,255,6],[238,228,98,6]],pointConnectionColorActive:[[255,128,203,128],[87,199,255,128],[238,228,98,128]],pointConnectionColorHover:[[255,128,203,99],[87,199,255,99],[238,228,98,99]],pointConnectionOpacityBy:"valueW",pointConnectionOpacity:Array(10).fill().map((o,t)=>(t+1)/100),pointConnectionSizeBy:"valueW",pointConnectionSize:Array(18).fill().map((o,t)=>(t+1)/2)});C(p);u(g); diff --git a/assets/connected-points-by-segments-B9DR1Sdx.js b/assets/connected-points-by-segments-B9DR1Sdx.js new file mode 100644 index 00000000..63537c54 --- /dev/null +++ b/assets/connected-points-by-segments-B9DR1Sdx.js @@ -0,0 +1,4 @@ +import{c as g,a as y,b as C}from"./menu-CKBxhbUC.js";import"./vendor-DRFCw67i.js";const S=document.querySelector("#canvas");let r=[],d=9e3,p=1,h=.33,s=[];const P=10,f=10,v=2,z=!0,M=[1,1,.878431373,.33],b=!0,B=[1,1,1,.15],$=2,A=({points:t})=>{if(console.log("Selected:",t),s=t,s.length===1){const o=r[s[0]];console.log(`X: ${o[0]} +Y: ${o[1]} +Category: ${o[2]} +Value: ${o[3]}`)}},w=()=>{console.log("Deselected:",s),s=[]},n=g({canvas:S,lassoMinDelay:f,lassoMinDist:v,pointSize:p,opacity:h,showReticle:z,reticleColor:M,showPointConnections:b,pointConnectionColor:B,pointConnectionSize:$,lassoInitiator:!0});y(n);console.log(`Scatterplot v${n.get("version")}`);n.subscribe("select",A);n.subscribe("deselect",w);const D=t=>{const o=Math.round(t/3),i=Math.round(o/5),a=[];for(let e=0;e<3;e++)for(let c=0;c{r=D(t),n.draw(r)},H=t=>Array.from({length:100},(o,i)=>1+i/99*(t*P-1)),m=t=>{n.set({pointSize:H(t)})};C({scatterplot:n,setNumPoints:u,setPointSize:m});n.set({colorBy:"valueZ",sizeBy:"valueW",pointColor:[[255,128,203,128],[87,199,255,128],[238,228,98,128]],pointConnectionColorBy:"segment",pointConnectionColor:Array(200).fill().map((t,o)=>[o+55,o+55,o+55,10]),pointConnectionSizeBy:"segment",pointConnectionSize:Array(20).fill().map((t,o)=>1+o/4),pointConnectionOpacityBy:"segment",pointConnectionOpacity:Array(64).fill().map((t,o)=>(o+8)/256)});m(p);u(d); diff --git a/assets/d3-IoKfXBi0.js b/assets/d3-IoKfXBi0.js new file mode 100644 index 00000000..c40dca0d --- /dev/null +++ b/assets/d3-IoKfXBi0.js @@ -0,0 +1 @@ +function hn(t){return t}var ft=1,j=2,lt=3,Z=4,kt=1e-6;function dn(t){return"translate("+t+",0)"}function gn(t){return"translate(0,"+t+")"}function mn(t){return n=>+t(n)}function pn(t,n){return n=Math.max(0,t.bandwidth()-n*2)/2,t.round()&&(n=Math.round(n)),e=>+t(e)+n}function xn(){return!this.__axis}function Ut(t,n){var e=[],r=null,i=null,o=6,a=6,f=3,u=typeof window<"u"&&window.devicePixelRatio>1?0:.5,s=t===ft||t===Z?-1:1,c=t===Z||t===j?"x":"y",h=t===ft||t===lt?dn:gn;function l(d){var m=r??(n.ticks?n.ticks.apply(n,e):n.domain()),x=i??(n.tickFormat?n.tickFormat.apply(n,e):hn),w=Math.max(o,0)+f,y=n.range(),M=+y[0]+u,_=+y[y.length-1]+u,S=(n.bandwidth?pn:mn)(n.copy(),u),p=d.selection?d.selection():d,C=p.selectAll(".domain").data([null]),A=p.selectAll(".tick").data(m,n).order(),z=A.exit(),L=A.enter().append("g").attr("class","tick"),F=A.select("line"),g=A.select("text");C=C.merge(C.enter().insert("path",".tick").attr("class","domain").attr("stroke","currentColor")),A=A.merge(L),F=F.merge(L.append("line").attr("stroke","currentColor").attr(c+"2",s*o)),g=g.merge(L.append("text").attr("fill","currentColor").attr(c,s*w).attr("dy",t===ft?"0em":t===lt?"0.71em":"0.32em")),d!==p&&(C=C.transition(d),A=A.transition(d),F=F.transition(d),g=g.transition(d),z=z.transition(d).attr("opacity",kt).attr("transform",function(v){return isFinite(v=S(v))?h(v+u):this.getAttribute("transform")}),L.attr("opacity",kt).attr("transform",function(v){var b=this.parentNode.__axis;return h((b&&isFinite(b=b(v))?b:S(v))+u)})),z.remove(),C.attr("d",t===Z||t===j?a?"M"+s*a+","+M+"H"+u+"V"+_+"H"+s*a:"M"+u+","+M+"V"+_:a?"M"+M+","+s*a+"V"+u+"H"+_+"V"+s*a:"M"+M+","+u+"H"+_),A.attr("opacity",1).attr("transform",function(v){return h(S(v)+u)}),F.attr(c+"2",s*o),g.attr(c,s*w).text(x),p.filter(xn).attr("fill","none").attr("font-size",10).attr("font-family","sans-serif").attr("text-anchor",t===j?"start":t===Z?"end":"middle"),p.each(function(){this.__axis=S})}return l.scale=function(d){return arguments.length?(n=d,l):n},l.ticks=function(){return e=Array.from(arguments),l},l.tickArguments=function(d){return arguments.length?(e=d==null?[]:Array.from(d),l):e.slice()},l.tickValues=function(d){return arguments.length?(r=d==null?null:Array.from(d),l):r&&r.slice()},l.tickFormat=function(d){return arguments.length?(i=d,l):i},l.tickSize=function(d){return arguments.length?(o=a=+d,l):o},l.tickSizeInner=function(d){return arguments.length?(o=+d,l):o},l.tickSizeOuter=function(d){return arguments.length?(a=+d,l):a},l.tickPadding=function(d){return arguments.length?(f=+d,l):f},l.offset=function(d){return arguments.length?(u=+d,l):u},l}function ui(t){return Ut(j,t)}function si(t){return Ut(lt,t)}function tt(t,n){return t==null||n==null?NaN:tn?1:t>=n?0:NaN}function yn(t,n){return t==null||n==null?NaN:nt?1:n>=t?0:NaN}function Xt(t){let n,e,r;t.length!==2?(n=tt,e=(f,u)=>tt(t(f),u),r=(f,u)=>t(f)-u):(n=t===tt||t===yn?t:wn,e=t,r=t);function i(f,u,s=0,c=f.length){if(s>>1;e(f[h],u)<0?s=h+1:c=h}while(s>>1;e(f[h],u)<=0?s=h+1:c=h}while(ss&&r(f[h-1],u)>-r(f[h],u)?h-1:h}return{left:i,center:a,right:o}}function wn(){return 0}function _n(t){return t===null?NaN:+t}const bn=Xt(tt),vn=bn.right;Xt(_n).center;const Mn=Math.sqrt(50),kn=Math.sqrt(10),Nn=Math.sqrt(2);function nt(t,n,e){const r=(n-t)/Math.max(0,e),i=Math.floor(Math.log10(r)),o=r/Math.pow(10,i),a=o>=Mn?10:o>=kn?5:o>=Nn?2:1;let f,u,s;return i<0?(s=Math.pow(10,-i)/a,f=Math.round(t*s),u=Math.round(n*s),f/sn&&--u,s=-s):(s=Math.pow(10,i)*a,f=Math.round(t/s),u=Math.round(n/s),f*sn&&--u),u0))return[];if(t===n)return[t];const r=n=i))return[];const f=o-i+1,u=new Array(f);if(r)if(a<0)for(let s=0;s>8&15|n>>4&240,n>>4&15|n&240,(n&15)<<4|n&15,1):e===8?J(n>>24&255,n>>16&255,n>>8&255,(n&255)/255):e===4?J(n>>12&15|n>>8&240,n>>8&15|n>>4&240,n>>4&15|n&240,((n&15)<<4|n&15)/255):null):(n=Sn.exec(t))?new k(n[1],n[2],n[3],1):(n=En.exec(t))?new k(n[1]*255/100,n[2]*255/100,n[3]*255/100,1):(n=Rn.exec(t))?J(n[1],n[2],n[3],n[4]):(n=Cn.exec(t))?J(n[1]*255/100,n[2]*255/100,n[3]*255/100,n[4]):(n=Fn.exec(t))?Ct(n[1],n[2]/100,n[3]/100,1):(n=Pn.exec(t))?Ct(n[1],n[2]/100,n[3]/100,n[4]):Nt.hasOwnProperty(t)?St(Nt[t]):t==="transparent"?new k(NaN,NaN,NaN,0):null}function St(t){return new k(t>>16&255,t>>8&255,t&255,1)}function J(t,n,e,r){return r<=0&&(t=n=e=NaN),new k(t,n,e,r)}function Ln(t){return t instanceof X||(t=T(t)),t?(t=t.rgb(),new k(t.r,t.g,t.b,t.opacity)):new k}function dt(t,n,e,r){return arguments.length===1?Ln(t):new k(t,n,e,r??1)}function k(t,n,e,r){this.r=+t,this.g=+n,this.b=+e,this.opacity=+r}xt(k,dt,Yt(X,{brighter(t){return t=t==null?et:Math.pow(et,t),new k(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=t==null?D:Math.pow(D,t),new k(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new k(H(this.r),H(this.g),H(this.b),rt(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:Et,formatHex:Et,formatHex8:qn,formatRgb:Rt,toString:Rt}));function Et(){return`#${P(this.r)}${P(this.g)}${P(this.b)}`}function qn(){return`#${P(this.r)}${P(this.g)}${P(this.b)}${P((isNaN(this.opacity)?1:this.opacity)*255)}`}function Rt(){const t=rt(this.opacity);return`${t===1?"rgb(":"rgba("}${H(this.r)}, ${H(this.g)}, ${H(this.b)}${t===1?")":`, ${t})`}`}function rt(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function H(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function P(t){return t=H(t),(t<16?"0":"")+t.toString(16)}function Ct(t,n,e,r){return r<=0?t=n=e=NaN:e<=0||e>=1?t=n=NaN:n<=0&&(t=NaN),new $(t,n,e,r)}function Gt(t){if(t instanceof $)return new $(t.h,t.s,t.l,t.opacity);if(t instanceof X||(t=T(t)),!t)return new $;if(t instanceof $)return t;t=t.rgb();var n=t.r/255,e=t.g/255,r=t.b/255,i=Math.min(n,e,r),o=Math.max(n,e,r),a=NaN,f=o-i,u=(o+i)/2;return f?(n===o?a=(e-r)/f+(e0&&u<1?0:a,new $(a,f,u,t.opacity)}function In(t,n,e,r){return arguments.length===1?Gt(t):new $(t,n,e,r??1)}function $(t,n,e,r){this.h=+t,this.s=+n,this.l=+e,this.opacity=+r}xt($,In,Yt(X,{brighter(t){return t=t==null?et:Math.pow(et,t),new $(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=t==null?D:Math.pow(D,t),new $(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+(this.h<0)*360,n=isNaN(t)||isNaN(this.s)?0:this.s,e=this.l,r=e+(e<.5?e:1-e)*n,i=2*e-r;return new k(ut(t>=240?t-240:t+120,i,r),ut(t,i,r),ut(t<120?t+240:t-120,i,r),this.opacity)},clamp(){return new $(Ft(this.h),Q(this.s),Q(this.l),rt(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const t=rt(this.opacity);return`${t===1?"hsl(":"hsla("}${Ft(this.h)}, ${Q(this.s)*100}%, ${Q(this.l)*100}%${t===1?")":`, ${t})`}`}}));function Ft(t){return t=(t||0)%360,t<0?t+360:t}function Q(t){return Math.max(0,Math.min(1,t||0))}function ut(t,n,e){return(t<60?n+(e-n)*t/60:t<180?e:t<240?n+(e-n)*(240-t)/60:n)*255}const yt=t=>()=>t;function Vn(t,n){return function(e){return t+e*n}}function Bn(t,n,e){return t=Math.pow(t,e),n=Math.pow(n,e)-t,e=1/e,function(r){return Math.pow(t+r*n,e)}}function Dn(t){return(t=+t)==1?Zt:function(n,e){return e-n?Bn(n,e,t):yt(isNaN(n)?e:n)}}function Zt(t,n){var e=n-t;return e?Vn(t,e):yt(isNaN(t)?n:t)}const Pt=(function t(n){var e=Dn(n);function r(i,o){var a=e((i=dt(i)).r,(o=dt(o)).r),f=e(i.g,o.g),u=e(i.b,o.b),s=Zt(i.opacity,o.opacity);return function(c){return i.r=a(c),i.g=f(c),i.b=u(c),i.opacity=s(c),i+""}}return r.gamma=t,r})(1);function On(t,n){n||(n=[]);var e=t?Math.min(n.length,t.length):0,r=n.slice(),i;return function(o){for(i=0;ie&&(o=n.slice(e,o),f[a]?f[a]+=o:f[++a]=o),(r=r[0])===(i=i[0])?f[a]?f[a]+=i:f[++a]=i:(f[++a]=null,u.push({i:a,x:it(r,i)})),e=st.lastIndex;return en&&(e=t,t=n,n=e),function(r){return Math.max(t,Math.min(n,r))}}function te(t,n,e){var r=t[0],i=t[1],o=n[0],a=n[1];return i2?ne:te,u=s=null,h}function h(l){return l==null||isNaN(l=+l)?o:(u||(u=f(t.map(r),n,e)))(r(a(l)))}return h.invert=function(l){return a(i((s||(s=f(n,t.map(r),it)))(l)))},h.domain=function(l){return arguments.length?(t=Array.from(l,Wn),c()):t.slice()},h.range=function(l){return arguments.length?(n=Array.from(l),c()):n.slice()},h.rangeRound=function(l){return n=Array.from(l),e=Jn,c()},h.clamp=function(l){return arguments.length?(a=l?!0:I,c()):a!==I},h.interpolate=function(l){return arguments.length?(e=l,c()):e},h.unknown=function(l){return arguments.length?(o=l,h):o},function(l,d){return r=l,i=d,c()}}function ee(){return Qt()(I,I)}function re(t){return Math.abs(t=Math.round(t))>=1e21?t.toLocaleString("en").replace(/,/g,""):t.toString(10)}function ot(t,n){if((e=(t=n?t.toExponential(n-1):t.toExponential()).indexOf("e"))<0)return null;var e,r=t.slice(0,e);return[r.length>1?r[0]+r.slice(2):r,+t.slice(e+1)]}function B(t){return t=ot(Math.abs(t)),t?t[1]:NaN}function ie(t,n){return function(e,r){for(var i=e.length,o=[],a=0,f=t[0],u=0;i>0&&f>0&&(u+f+1>r&&(f=Math.max(1,r-u)),o.push(e.substring(i-=f,i+f)),!((u+=f+1)>r));)f=t[a=(a+1)%t.length];return o.reverse().join(n)}}function oe(t){return function(n){return n.replace(/[0-9]/g,function(e){return t[+e]})}}var ae=/^(?:(.)?([<>=^]))?([+\-( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?(~)?([a-z%])?$/i;function U(t){if(!(n=ae.exec(t)))throw new Error("invalid format: "+t);var n;return new _t({fill:n[1],align:n[2],sign:n[3],symbol:n[4],zero:n[5],width:n[6],comma:n[7],precision:n[8]&&n[8].slice(1),trim:n[9],type:n[10]})}U.prototype=_t.prototype;function _t(t){this.fill=t.fill===void 0?" ":t.fill+"",this.align=t.align===void 0?">":t.align+"",this.sign=t.sign===void 0?"-":t.sign+"",this.symbol=t.symbol===void 0?"":t.symbol+"",this.zero=!!t.zero,this.width=t.width===void 0?void 0:+t.width,this.comma=!!t.comma,this.precision=t.precision===void 0?void 0:+t.precision,this.trim=!!t.trim,this.type=t.type===void 0?"":t.type+""}_t.prototype.toString=function(){return this.fill+this.align+this.sign+this.symbol+(this.zero?"0":"")+(this.width===void 0?"":Math.max(1,this.width|0))+(this.comma?",":"")+(this.precision===void 0?"":"."+Math.max(0,this.precision|0))+(this.trim?"~":"")+this.type};function fe(t){t:for(var n=t.length,e=1,r=-1,i;e0&&(r=0);break}return r>0?t.slice(0,r)+t.slice(i+1):t}var Wt;function ue(t,n){var e=ot(t,n);if(!e)return t+"";var r=e[0],i=e[1],o=i-(Wt=Math.max(-8,Math.min(8,Math.floor(i/3)))*3)+1,a=r.length;return o===a?r:o>a?r+new Array(o-a+1).join("0"):o>0?r.slice(0,o)+"."+r.slice(o):"0."+new Array(1-o).join("0")+ot(t,Math.max(0,n+o-1))[0]}function zt(t,n){var e=ot(t,n);if(!e)return t+"";var r=e[0],i=e[1];return i<0?"0."+new Array(-i).join("0")+r:r.length>i+1?r.slice(0,i+1)+"."+r.slice(i+1):r+new Array(i-r.length+2).join("0")}const Lt={"%":(t,n)=>(t*100).toFixed(n),b:t=>Math.round(t).toString(2),c:t=>t+"",d:re,e:(t,n)=>t.toExponential(n),f:(t,n)=>t.toFixed(n),g:(t,n)=>t.toPrecision(n),o:t=>Math.round(t).toString(8),p:(t,n)=>zt(t*100,n),r:zt,s:ue,X:t=>Math.round(t).toString(16).toUpperCase(),x:t=>Math.round(t).toString(16)};function qt(t){return t}var It=Array.prototype.map,Vt=["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];function se(t){var n=t.grouping===void 0||t.thousands===void 0?qt:ie(It.call(t.grouping,Number),t.thousands+""),e=t.currency===void 0?"":t.currency[0]+"",r=t.currency===void 0?"":t.currency[1]+"",i=t.decimal===void 0?".":t.decimal+"",o=t.numerals===void 0?qt:oe(It.call(t.numerals,String)),a=t.percent===void 0?"%":t.percent+"",f=t.minus===void 0?"−":t.minus+"",u=t.nan===void 0?"NaN":t.nan+"";function s(h){h=U(h);var l=h.fill,d=h.align,m=h.sign,x=h.symbol,w=h.zero,y=h.width,M=h.comma,_=h.precision,S=h.trim,p=h.type;p==="n"?(M=!0,p="g"):Lt[p]||(_===void 0&&(_=12),S=!0,p="g"),(w||l==="0"&&d==="=")&&(w=!0,l="0",d="=");var C=x==="$"?e:x==="#"&&/[boxX]/.test(p)?"0"+p.toLowerCase():"",A=x==="$"?r:/[%p]/.test(p)?a:"",z=Lt[p],L=/[defgprs%]/.test(p);_=_===void 0?6:/[gprs]/.test(p)?Math.max(1,Math.min(21,_)):Math.max(0,Math.min(20,_));function F(g){var v=C,b=A,q,Mt,K;if(p==="c")b=z(g)+b,g="";else{g=+g;var Y=g<0||1/g<0;if(g=isNaN(g)?u:z(Math.abs(g),_),S&&(g=fe(g)),Y&&+g==0&&m!=="+"&&(Y=!1),v=(Y?m==="("?m:f:m==="-"||m==="("?"":m)+v,b=(p==="s"?Vt[8+Wt/3]:"")+b+(Y&&m==="("?")":""),L){for(q=-1,Mt=g.length;++qK||K>57){b=(K===46?i+g.slice(q+1):g.slice(q))+b,g=g.slice(0,q);break}}}M&&!w&&(g=n(g,1/0));var G=v.length+g.length+b.length,R=G>1)+v+g+b+R.slice(G);break;default:g=R+v+g+b;break}return o(g)}return F.toString=function(){return h+""},F}function c(h,l){var d=s((h=U(h),h.type="f",h)),m=Math.max(-8,Math.min(8,Math.floor(B(l)/3)))*3,x=Math.pow(10,-m),w=Vt[8+m/3];return function(y){return d(x*y)+w}}return{format:s,formatPrefix:c}}var W,bt,jt;le({thousands:",",grouping:[3],currency:["$",""]});function le(t){return W=se(t),bt=W.format,jt=W.formatPrefix,W}function ce(t){return Math.max(0,-B(Math.abs(t)))}function he(t,n){return Math.max(0,Math.max(-8,Math.min(8,Math.floor(B(n)/3)))*3-B(Math.abs(t)))}function de(t,n){return t=Math.abs(t),n=Math.abs(n)-t,Math.max(0,B(n)-B(t))+1}function ge(t,n,e,r){var i=An(t,n,e),o;switch(r=U(r??",f"),r.type){case"s":{var a=Math.max(Math.abs(t),Math.abs(n));return r.precision==null&&!isNaN(o=he(i,a))&&(r.precision=o),jt(r,a)}case"":case"e":case"g":case"p":case"r":{r.precision==null&&!isNaN(o=de(i,Math.max(Math.abs(t),Math.abs(n))))&&(r.precision=o-(r.type==="e"));break}case"f":case"%":{r.precision==null&&!isNaN(o=ce(i))&&(r.precision=o-(r.type==="%")*2);break}}return bt(r)}function me(t){var n=t.domain;return t.ticks=function(e){var r=n();return ct(r[0],r[r.length-1],e??10)},t.tickFormat=function(e,r){var i=n();return ge(i[0],i[i.length-1],e??10,r)},t.nice=function(e){e==null&&(e=10);var r=n(),i=0,o=r.length-1,a=r[i],f=r[o],u,s,c=10;for(f0;){if(s=ht(a,f,e),s===u)return r[i]=a,r[o]=f,n(r);if(s>0)a=Math.floor(a/s)*s,f=Math.ceil(f/s)*s;else if(s<0)a=Math.ceil(a*s)/s,f=Math.floor(f*s)/s;else break;u=s}return t},t}function pe(){var t=ee();return t.copy=function(){return Jt(t,pe())},Kt.apply(t,arguments),me(t)}function xe(t,n){t=t.slice();var e=0,r=t.length-1,i=t[e],o=t[r],a;return oMath.pow(t,n)}function ve(t){return t===Math.E?Math.log:t===10&&Math.log10||t===2&&Math.log2||(t=Math.log(t),n=>Math.log(n)/t)}function Ot(t){return(n,e)=>-t(-n,e)}function Me(t){const n=t(Bt,Dt),e=n.domain;let r=10,i,o;function a(){return i=ve(r),o=be(r),e()[0]<0?(i=Ot(i),o=Ot(o),t(ye,we)):t(Bt,Dt),n}return n.base=function(f){return arguments.length?(r=+f,a()):r},n.domain=function(f){return arguments.length?(e(f),a()):e()},n.ticks=f=>{const u=e();let s=u[0],c=u[u.length-1];const h=c0){for(;l<=d;++l)for(m=1;mc)break;y.push(x)}}else for(;l<=d;++l)for(m=r-1;m>=1;--m)if(x=l>0?m/o(-l):m*o(l),!(xc)break;y.push(x)}y.length*2{if(f==null&&(f=10),u==null&&(u=r===10?"s":","),typeof u!="function"&&(!(r%1)&&(u=U(u)).precision==null&&(u.trim=!0),u=bt(u)),f===1/0)return u;const s=Math.max(1,r*f/n.ticks().length);return c=>{let h=c/o(Math.round(i(c)));return h*re(xe(e(),{floor:f=>o(Math.floor(i(f))),ceil:f=>o(Math.ceil(i(f)))})),n}function ke(){const t=Me(Qt()).domain([1,10]);return t.copy=()=>Jt(t,ke()).base(t.base()),Kt.apply(t,arguments),t}var pt="http://www.w3.org/1999/xhtml";const Tt={svg:"http://www.w3.org/2000/svg",xhtml:pt,xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};function tn(t){var n=t+="",e=n.indexOf(":");return e>=0&&(n=t.slice(0,e))!=="xmlns"&&(t=t.slice(e+1)),Tt.hasOwnProperty(n)?{space:Tt[n],local:t}:t}function Ne(t){return function(){var n=this.ownerDocument,e=this.namespaceURI;return e===pt&&n.documentElement.namespaceURI===pt?n.createElement(t):n.createElementNS(e,t)}}function Ae(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function nn(t){var n=tn(t);return(n.local?Ae:Ne)(n)}function $e(){}function en(t){return t==null?$e:function(){return this.querySelector(t)}}function Se(t){typeof t!="function"&&(t=en(t));for(var n=this._groups,e=n.length,r=new Array(e),i=0;i=_&&(_=M+1);!(p=w[_])&&++_=0;)(a=r[i])&&(o&&a.compareDocumentPosition(o)^4&&o.parentNode.insertBefore(a,o),o=a);return this}function nr(t){t||(t=er);function n(h,l){return h&&l?t(h.__data__,l.__data__):!h-!l}for(var e=this._groups,r=e.length,i=new Array(r),o=0;on?1:t>=n?0:NaN}function rr(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this}function ir(){return Array.from(this)}function or(){for(var t=this._groups,n=0,e=t.length;n1?this.each((n==null?pr:typeof n=="function"?yr:xr)(t,n,e??"")):_r(this.node(),t)}function _r(t,n){return t.style.getPropertyValue(n)||an(t).getComputedStyle(t,null).getPropertyValue(n)}function br(t){return function(){delete this[t]}}function vr(t,n){return function(){this[t]=n}}function Mr(t,n){return function(){var e=n.apply(this,arguments);e==null?delete this[t]:this[t]=e}}function kr(t,n){return arguments.length>1?this.each((n==null?br:typeof n=="function"?Mr:vr)(t,n)):this.node()[t]}function fn(t){return t.trim().split(/^|\s+/)}function vt(t){return t.classList||new un(t)}function un(t){this._node=t,this._names=fn(t.getAttribute("class")||"")}un.prototype={add:function(t){var n=this._names.indexOf(t);n<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var n=this._names.indexOf(t);n>=0&&(this._names.splice(n,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};function sn(t,n){for(var e=vt(t),r=-1,i=n.length;++r=0&&(e=n.slice(r+1),n=n.slice(0,r)),{type:n,name:e}})}function Wr(t){return function(){var n=this.__on;if(n){for(var e=0,r=-1,i=n.length,o;e{if(console.log("Selected:",n),y=n,y.length===1){const t=b[y[0]];console.log(`X: ${t[0]} +Y: ${t[1]} +Category: ${t[2]} +Value: ${t[3]}`)}},A=()=>{console.log("Deselected:",y),y=[]},l=D({canvas:H,lassoMinDelay:B,lassoMinDist:N,pointSize:q,pointColor:"#fff",opacityBy:"density",showReticle:R,reticleColor:V,lassoInitiator:!0});M(l);console.log(`Scatterplot v${l.get("version")}`);l.subscribe("select",j);l.subscribe("deselect",A);const E=n=>{const t=[];let i=2.644838333129883,r=4.060488700866699,a=2.8982460498809814,o,s,x;const S=.2,z=.2,I=5.7,c=.006;let d=1/0,u=-1/0,p=1/0,f=-1/0;for(let e=0;e<=n;e++){let m=-r-a,g=i+S*r,h=z+a*(i-I);const $=i+.5*c*m,v=r+.5*c*g,X=a+.5*c*h;m=-v-X,g=$+S*v,h=z+X*($-I),o=i+c*m,s=r+c*g,x=a+c*h,t.push([o,s,0,0]),d=ou?o:u,p=sf?s:f,i=o,r=s,a=x}const w=u-d,C=f-p;for(let e=0;e<=n;e++)t[e][0]-=d,t[e][0]/=w/2,t[e][0]-=1,t[e][1]-=p,t[e][1]/=C/2,t[e][1]-=1;return t},Y=n=>{b=E(n),l.draw(b)};P({scatterplot:l,setNumPoints:Y});Y(k); diff --git a/assets/embedded-C8UqjovM.js b/assets/embedded-C8UqjovM.js new file mode 100644 index 00000000..2e83a549 --- /dev/null +++ b/assets/embedded-C8UqjovM.js @@ -0,0 +1,4 @@ +import{c as E,a as L,s as H,b as q}from"./menu-CKBxhbUC.js";import"./vendor-DRFCw67i.js";const d=document.querySelector("#canvas"),l=document.querySelector("#num-points"),p=document.querySelector("#num-points-value"),m=document.querySelector("#point-size"),M=document.querySelector("#point-size-value"),v=document.querySelector("#opacity"),k=document.querySelector("#opacity-value"),y=document.querySelector("#click-lasso-initiator"),b=document.querySelector("#reset"),I=document.querySelector("#export"),S=document.querySelector("#example-basic"),i=d.parentNode;i.style.padding="15rem 0";i.style.height="100vh";i.parentNode.style.overflow="auto";S.setAttribute("class","active");S.removeAttribute("href");let r=[],o=1e5,n=4,a=.33,c=[];const P=[1,1,.878431373,.33],z=({points:e})=>{if(c=e,c.length===1){const s=r[c[0]];console.log(`Selected: ${e}`,`X: ${s[0]} +Y: ${s[1]} +Category: ${s[2]} +Value: ${s[3]}`)}},$=()=>{c=[]},t=E({canvas:d,pointSize:n,showReticle:!0,reticleColor:P,lassoInitiator:!0});L(t);I.addEventListener("click",()=>H(t));console.log(`Scatterplot v${t.get("version")}`);t.subscribe("select",z);t.subscribe("deselect",$);const f=e=>new Array(e).fill().map(()=>[-.8+Math.random()*1.6,-.8+Math.random()*1.6,Math.round(Math.random()),Math.random()]),u=e=>{o=e,l.value=o,p.innerHTML=o,r=f(o),t.draw(r)};q({scatterplot:t,setNumPoints:u});const w=e=>{p.innerHTML=`${+e.target.value} release to redraw`};l.addEventListener("input",w);const C=e=>u(+e.target.value);l.addEventListener("change",C);const g=e=>{n=e,m.value=n,M.innerHTML=n,t.set({pointSize:n})},x=e=>g(+e.target.value);m.addEventListener("input",x);const h=e=>{a=e,v.value=a,k.innerHTML=a,t.set({opacity:a})},A=e=>h(+e.target.value);v.addEventListener("input",A);const T=e=>{t.set({lassoInitiator:e.target.checked})};y.addEventListener("change",T);y.checked=t.get("lassoInitiator");const V=()=>{t.reset()};b.addEventListener("click",V);g(n);h(a);u(o); diff --git a/assets/index-DZnwqjzW.js b/assets/index-DZnwqjzW.js new file mode 100644 index 00000000..43bdac50 --- /dev/null +++ b/assets/index-DZnwqjzW.js @@ -0,0 +1,10 @@ +import{c as u,a as y,b as i}from"./menu-CKBxhbUC.js";import"./vendor-DRFCw67i.js";const b=document.querySelector("#canvas");let e={x:[],y:[],z:[],w:[]},$=1e5,d=2,m=.33,c=[];const g=10,f=2,p=!0,v=[1,1,.878431373,.33],w=o=>{const s=e.x[o],a=e.y[o],n=e.z[o],r=e.w[o];console.log(`Out point: ${o}`,`X: ${s} +Y: ${a} +Category: ${n} +Value: ${r}`)},x=o=>{const s=e.x[o],a=e.y[o],n=e.z[o],r=e.w[o];console.log(`Out point: ${o}`,`X: ${s} +Y: ${a} +Category: ${n} +Value: ${r}`)},M=({points:o})=>{if(c=o,c.length===1){const s=e.x[c[0]],a=e.y[c[0]],n=e.z[c[0]],r=e.w[c[0]];console.log(`Selected: ${o}`,`X: ${s} +Y: ${a} +Category: ${n} +Value: ${r}`)}},C=()=>{console.log("Deselected:",c),c=[]},t=u({canvas:b,lassoMinDelay:g,lassoMinDist:f,pointSize:d,showReticle:p,reticleColor:v,opacity:m,lassoOnLongPress:!0,lassoType:"brush"});y(t);console.log(`Scatterplot v${t.get("version")}`);t.subscribe("pointover",w);t.subscribe("pointout",x);t.subscribe("select",M);t.subscribe("deselect",C);const S=o=>({x:Array.from({length:o},()=>-1+Math.random()*2),y:Array.from({length:o},()=>-1+Math.random()*2),z:Array.from({length:o},()=>Math.round(Math.random())),w:Array.from({length:o},()=>Math.random())}),l=o=>{e=S($),t.draw(e)};i({scatterplot:t,setNumPoints:l});const h=["#3a78aa","#aa3a99"];t.set({colorBy:"category",pointColor:h});const z=["#002072","#162b79","#233680","#2e4186","#394d8d","#425894","#4b649a","#5570a1","#5e7ca7","#6789ae","#7195b4","#7ba2ba","#85aec0","#90bbc6","#9cc7cc","#a9d4d2","#b8e0d7","#c8ecdc","#ddf7df","#ffffe0"];t.set({colorBy:"value",pointColor:z});l(); diff --git a/assets/menu-CKBxhbUC.js b/assets/menu-CKBxhbUC.js new file mode 100644 index 00000000..e8b55aeb --- /dev/null +++ b/assets/menu-CKBxhbUC.js @@ -0,0 +1,369 @@ +import{g as Ki,q as Va,h as Ha,i as Wa,l as Ga,j as Ya,k as Za,p as ja,m as Qe,n as kt,t as qi,w as Ka,o as qa,r as Ni,s as Xa,u as Ja,v as Qa,f as ec,x as tc,y as at,z as nc,A as dn,C as Cn,D as oc,E as To,F as Po,G as ic,H as Mi,I as sc,J as rc,K as Bi,L as ac,V as cc,M as lc,N as dc,O as uc,P as bn,Q as fc}from"./vendor-DRFCw67i.js";(function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const d of document.querySelectorAll('link[rel="modulepreload"]'))m(d);new MutationObserver(d=>{for(const a of d)if(a.type==="childList")for(const I of a.addedNodes)I.tagName==="LINK"&&I.rel==="modulepreload"&&m(I)}).observe(document,{childList:!0,subtree:!0});function i(d){const a={};return d.integrity&&(a.integrity=d.integrity),d.referrerPolicy&&(a.referrerPolicy=d.referrerPolicy),d.crossOrigin==="use-credentials"?a.credentials="include":d.crossOrigin==="anonymous"?a.credentials="omit":a.credentials="same-origin",a}function m(d){if(d.ep)return;d.ep=!0;const a=i(d);fetch(d.href,a)}})();const mc="1.15.0",hc=` +precision mediump float; + +uniform sampler2D texture; + +varying vec2 uv; + +void main () { + gl_FragColor = texture2D(texture, uv); +} +`,gc=` +precision mediump float; + +uniform mat4 modelViewProjection; + +attribute vec2 position; + +varying vec2 uv; + +void main () { + uv = position; + gl_Position = modelViewProjection * vec4(-1.0 + 2.0 * uv.x, 1.0 - 2.0 * uv.y, 0, 1); +} +`,Ye="auto",yc=0,Co=1,pc=2,Fi=3,Ec=4,xc=Float32Array.BYTES_PER_ELEMENT,Xi=["OES_texture_float","OES_element_index_uint","WEBGL_color_buffer_float","EXT_float_blend"],ki={color:[0,0,0,0],depth:1},Ln="panZoom",Ji="lasso",Ho="rotate",zi=[Ln,Ji,Ho],wc=Ln,Ac={cubicIn:Za,cubicInOut:Ki,cubicOut:Ya,linear:Ga,quadIn:Wa,quadInOut:Ha,quadOut:Va},$i=Ki,Ge="continuous",mn="categorical",Ui=[Ge,mn],Wo="deselect",Yo="lassoEnd",Sc=[Wo,Yo],Vi=3,Ic=[0,.666666667,1,1],Tc=2,Pc=!1,Cc=10,bc=3,vc=Yo,Lc=!1,_n=750,On=500,Dn=100,Rn=250,_c=24,Zo="lasso",Nn="rotate",Mn="merge",Bn="remove",Oc=[Zo,Nn,Mn,Bn],Fn="alt",jo="cmd",Qi="ctrl",es="meta",Ko="shift",Dc=[Fn,jo,Qi,es,Ko],Rc={[Bn]:Fn,[Nn]:Fn,[Zo]:Ko,[Mn]:jo},Nc=1,Mc=Ye,Bc=Ye,Fc=1,bo=1,kc="asinh",zc=6,$c=2,Uc=2,vo=null,Vc=2,Hc=2,Lo=null,Wc=null,_o=null,Gc=.66,Yc=1,Oo=null,Zc=.15,jc=25,Kc=1,qc=1,un=null,Xc=[.66,.66,.66,Yc],Jc=[0,.55,1,1],Qc=[1,1,1,1],el=[0,0,0,1],Do=null,tl=[.66,.66,.66,.2],nl=[0,.55,1,1],ol=[1,1,1,1],il=[1,1,1,.5],sl=1,rl=1e3,al=[0,0],cl=1,ll=0,dl=new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),ul="IMAGE_LOAD_ERROR",fl=null,ml=!1,hl=[1,1,1,.5],gl=!0,yl=!0,pl=!1,El=100,xl=1/500,wl="auto",Al=!1,Sl=200,Il=500,ts=new Set(["z","valueZ","valueA","value1","category"]),ns=new Set(["w","valueW","valueB","value2","value"]),qo=15e3,Tl=void 0,Pl=!1,Cl=.5,bl=!1,vl="lasso",os=Symbol("SKIP_DEPRECATION_VALUE_TRANSLATION"),Hi="Points have not been drawn",Ro="The instance was already destroyed",Ll="Ignoring draw call as the previous draw call has not yet finished. To avoid this warning `await` the draw call.";const is=()=>{const t=[Int8Array,Uint8Array,Uint8ClampedArray,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array],o=1,i=8;class m{static from(r){if(!(r instanceof ArrayBuffer))throw new Error("Data must be an instance of ArrayBuffer.");const[u,c]=new Uint8Array(r,0,2);if(u!==219)throw new Error("Data does not appear to be in a KDBush format.");const y=c>>4;if(y!==o)throw new Error(`Got v${y} data when expected v${o}.`);const x=t[c&15];if(!x)throw new Error("Unrecognized array type.");const[T]=new Uint16Array(r,2,1),[P]=new Uint32Array(r,4,1);return new m(P,T,x,r)}constructor(r,u=64,c=Float64Array,y){if(isNaN(r)||r<0)throw new Error(`Unexpected numItems value: ${r}.`);this.numItems=+r,this.nodeSize=Math.min(Math.max(+u,2),65535),this.ArrayType=c,this.IndexArrayType=r<65536?Uint16Array:Uint32Array;const x=t.indexOf(this.ArrayType),T=r*2*this.ArrayType.BYTES_PER_ELEMENT,P=r*this.IndexArrayType.BYTES_PER_ELEMENT,S=(8-P%8)%8;if(x<0)throw new Error(`Unexpected typed array class: ${c}.`);y&&y instanceof ArrayBuffer?(this.data=y,this.ids=new this.IndexArrayType(this.data,i,r),this.coords=new this.ArrayType(this.data,i+P+S,r*2),this._pos=r*2,this._finished=!0):(this.data=new ArrayBuffer(i+T+P+S),this.ids=new this.IndexArrayType(this.data,i,r),this.coords=new this.ArrayType(this.data,i+P+S,r*2),this._pos=0,this._finished=!1,new Uint8Array(this.data,0,2).set([219,(o<<4)+x]),new Uint16Array(this.data,2,1)[0]=u,new Uint32Array(this.data,4,1)[0]=r)}add(r,u){const c=this._pos>>1;return this.ids[c]=c,this.coords[this._pos++]=r,this.coords[this._pos++]=u,c}finish(){const r=this._pos>>1;if(r!==this.numItems)throw new Error(`Added ${r} items when expected ${this.numItems}.`);return d(this.ids,this.coords,this.nodeSize,0,this.numItems-1,0),this._finished=!0,this}range(r,u,c,y){if(!this._finished)throw new Error("Data not yet indexed - call index.finish().");const{ids:x,coords:T,nodeSize:P}=this,S=[0,x.length-1,0],C=[];for(;S.length;){const b=S.pop()||0,R=S.pop()||0,Y=S.pop()||0;if(R-Y<=P){for(let $=Y;$<=R;$++){const de=T[2*$],me=T[2*$+1];de>=r&&de<=c&&me>=u&&me<=y&&C.push(x[$])}continue}const H=Y+R>>1,L=T[2*H],z=T[2*H+1];L>=r&&L<=c&&z>=u&&z<=y&&C.push(x[H]),(b===0?r<=L:u<=z)&&(S.push(Y),S.push(H-1),S.push(1-b)),(b===0?c>=L:y>=z)&&(S.push(H+1),S.push(R),S.push(1-b))}return C}within(r,u,c){if(!this._finished)throw new Error("Data not yet indexed - call index.finish().");const{ids:y,coords:x,nodeSize:T}=this,P=[0,y.length-1,0],S=[],C=c*c;for(;P.length;){const b=P.pop()||0,R=P.pop()||0,Y=P.pop()||0;if(R-Y<=T){for(let $=Y;$<=R;$++)B(x[2*$],x[2*$+1],r,u)<=C&&S.push(y[$]);continue}const H=Y+R>>1,L=x[2*H],z=x[2*H+1];B(L,z,r,u)<=C&&S.push(y[H]),(b===0?r-c<=L:u-c<=z)&&(P.push(Y),P.push(H-1),P.push(1-b)),(b===0?r+c>=L:u+c>=z)&&(P.push(H+1),P.push(R),P.push(1-b))}return S}}function d(f,r,u,c,y,x){if(y-c<=u)return;const T=c+y>>1;a(f,r,T,c,y,x),d(f,r,u,c,T-1,1-x),d(f,r,u,T+1,y,1-x)}function a(f,r,u,c,y,x){for(;y>c;){if(y-c>600){const C=y-c+1,b=u-c+1,R=Math.log(C),Y=.5*Math.exp(2*R/3),H=.5*Math.sqrt(R*Y*(C-Y)/C)*(b-C/2<0?-1:1),L=Math.max(c,Math.floor(u-b*Y/C+H)),z=Math.min(y,Math.floor(u+(C-b)*Y/C+H));a(f,r,u,L,z,x)}const T=r[2*u+x];let P=c,S=y;for(I(f,r,c,u),r[2*y+x]>T&&I(f,r,c,y);PT;)S--}r[2*c+x]===T?I(f,r,c,S):(S++,I(f,r,S,y)),S<=u&&(c=S+1),u<=S&&(y=S-1)}}function I(f,r,u,c){_(f,u,c),_(r,2*u,2*c),_(r,2*u+1,2*c+1)}function _(f,r,u){const c=f[r];f[r]=f[u],f[u]=c}function B(f,r,u,c){const y=f-u,x=r-c;return y*y+x*x}return m},_l=()=>{addEventListener("message",t=>{const o=t.data.points;o.length===0&&self.postMessage({error:new Error("Invalid point data")});const i=new KDBush(o.length,t.data.nodeSize);for(const[m,d]of o)i.add(m,d);i.finish(),postMessage(i.data,[i.data])})},No=is(),Ol=1e6,Dl=t=>{const o=is.toString(),i=t.toString(),m=`const createKDBushClass = ${o};KDBush = createKDBushClass();const createWorker = ${i};createWorker();`,d=new Blob([m],{type:"text/javascript"}),a=URL.createObjectURL(d),I=new Worker(a,{name:"KDBush"});return URL.revokeObjectURL(a),I},Rl=(t,o={nodeSize:16,useWorker:void 0})=>new Promise((i,m)=>{if(t instanceof ArrayBuffer)i(No.from(t));else if((t.length{a.data.error?m(a.data.error):i(No.from(a.data)),d.terminate()},d.postMessage({points:t,nodeSize:o.nodeSize})}}),Nl=!0,Ml=8,Bl=2,Fl="freeform",kl=24,zl=2500,$l=250,Ul=(t,o,i)=>(1-t)*o+i,Vl=(t,o)=>`${t}ms ease-out mainIn ${o}ms 1 normal forwards`,Hl=(t,o)=>`${t}ms ease-out effectIn ${o}ms 1 normal forwards`,Wl=(t,o)=>`${t}ms linear leftSpinIn ${o}ms 1 normal forwards`,Gl=(t,o)=>`${t}ms linear rightSpinIn ${o}ms 1 normal forwards`,Yl=(t,o)=>`${t}ms linear circleIn ${o}ms 1 normal forwards`,Zl=(t,o,i)=>` + @keyframes mainIn { + 0% { + color: ${o}; + opacity: 0; + } + 0%, ${t}% { + color: ${o}; + opacity: 1; + } + 100% { + color: ${i}; + opacity: 0.8; + } + } +`,jl=(t,o,i,m)=>` + @keyframes effectIn { + 0%, ${t}% { + opacity: ${i}; + transform: scale(${m}); + } + ${o}% { + opacity: 0.66; + transform: scale(1.5); + } + 99% { + opacity: 0; + transform: scale(2); + } + 100% { + opacity: 0; + transform: scale(0); + } + } +`,Kl=(t,o,i)=>` + @keyframes circleIn { + 0% { + clip-path: ${o}; + opacity: ${i}; + } + ${t}% { + clip-path: ${o}; + opacity: 1; + } + ${t+.01}%, 100% { + clip-path: inset(0); + opacity: 1; + } + } +`,ql=(t,o)=>` + @keyframes leftSpinIn { + 0% { + transform: rotate(${o}deg); + } + ${t}%, 100% { + transform: rotate(360deg); + } + } +`,Xl=(t,o)=>` + @keyframes rightSpinIn { + 0% { + transform: rotate(${o}deg); + } + ${t}%, 100% { + transform: rotate(180deg); + } + } +`,Jl=({time:t=_n,extraTime:o=On,delay:i=Dn,currentColor:m,targetColor:d,effectOpacity:a,effectScale:I,circleLeftRotation:_,circleRightRotation:B,circleClipPath:f,circleOpacity:r})=>{const u=_/360,c=Ul(u,t,o),y=Math.round((1-u)*t/c*100),x=Math.round(y/2),T=y+(100-y)/4;return{rules:{main:Zl(y,m,d),effect:jl(y,T,a,I),circleRight:Xl(x,B),circleLeft:ql(y,_),circle:Kl(x,f,r)},names:{main:Vl(c,i),effect:Hl(c,i),circleLeft:Wl(c,i),circleRight:Gl(c,i),circle:Yl(c,i)}}},Ql=t=>`${t}ms linear mainOut 0s 1 normal forwards`,ed=t=>`${t}ms linear effectOut 0s 1 normal forwards`,td=t=>`${t}ms linear leftSpinOut 0s 1 normal forwards`,nd=t=>`${t}ms linear rightSpinOut 0s 1 normal forwards`,od=t=>`${t}ms linear circleOut 0s 1 normal forwards`,id=(t,o)=>` + @keyframes mainOut { + 0% { + color: ${t}; + } + 100% { + color: ${o}; + } + } +`,sd=(t,o)=>` + @keyframes effectOut { + 0% { + opacity: ${t}; + transform: scale(${o}); + } + 99% { + opacity: 0; + transform: scale(${o+.5}); + } + 100% { + opacity: 0; + transform: scale(0); + } + } +`,rd=(t,o)=>` + @keyframes rightSpinOut { + 0%, ${t}% { + transform: rotate(${o}deg); + } + 100% { + transform: rotate(0deg); + } +`,ad=t=>` + @keyframes leftSpinOut { + 0% { + transform: rotate(${t}deg); + } + 100% { + transform: rotate(0deg); + } + } +`,cd=(t,o,i)=>` + @keyframes circleOut { + 0%, ${t}% { + clip-path: ${o}; + opacity: ${i}; + } + ${t+.01}% { + clip-path: inset(0 0 0 50%); + opacity: ${i}; + } + 100% { + clip-path: inset(0 0 0 50%); + opacity: 0; + } + } +`,ld=({time:t=Rn,currentColor:o,targetColor:i,effectOpacity:m,effectScale:d,circleLeftRotation:a,circleRightRotation:I,circleClipPath:_,circleOpacity:B})=>{const f=a/360,r=f*t,u=Math.min(100,f*100),c=u>50?Math.round((1-50/u)*100):0;return{rules:{main:id(o,i),effect:sd(m,d),circleRight:rd(c,I),circleLeft:ad(a),circle:cd(c,_,B)},names:{main:Ql(r),effect:ed(r),circleRight:td(r),circleLeft:nd(r),circle:od(r)}}},dd=()=>{const t=document.createElement("div"),o=Math.random().toString(36).substring(2,5)+Math.random().toString(36).substring(2,5);t.id=`lasso-long-press-${o}`,t.style.position="fixed",t.style.width="1.25rem",t.style.height="1.25rem",t.style.pointerEvents="none",t.style.transform="translate(-50%,-50%)";const i=document.createElement("div");i.style.position="absolute",i.style.top=0,i.style.left=0,i.style.width="1.25rem",i.style.height="1.25rem",i.style.clipPath="inset(0px 0px 0px 50%)",i.style.opacity=0,t.appendChild(i);const m=document.createElement("div");m.style.position="absolute",m.style.top=0,m.style.left=0,m.style.width="0.8rem",m.style.height="0.8rem",m.style.border="0.2rem solid currentcolor",m.style.borderRadius="0.8rem",m.style.clipPath="inset(0px 50% 0px 0px)",m.style.transform="rotate(0deg)",i.appendChild(m);const d=document.createElement("div");d.style.position="absolute",d.style.top=0,d.style.left=0,d.style.width="0.8rem",d.style.height="0.8rem",d.style.border="0.2rem solid currentcolor",d.style.borderRadius="0.8rem",d.style.clipPath="inset(0px 50% 0px 0px)",d.style.transform="rotate(0deg)",i.appendChild(d);const a=document.createElement("div");return a.style.position="absolute",a.style.top=0,a.style.left=0,a.style.width="1.25rem",a.style.height="1.25rem",a.style.borderRadius="1.25rem",a.style.background="currentcolor",a.style.transform="scale(0)",a.style.opacity=0,t.appendChild(a),{longPress:t,longPressCircle:i,longPressCircleLeft:m,longPressCircleRight:d,longPressEffect:a}},ud=(t,o,i)=>{if(t.length===0)return 0;if(t.length===1)return t[0];const m=2**(-1/o),d=Math.max(0,t.length-i),a=t.slice(d);let I=0,_=0,B=0;for(let f=a.length-1;f>=0;f--){const r=a.length-1-f,u=m**r;I+=a[f][0]*u,_+=a[f][1]*u,B+=u}return[I/B,_/B]},ct=(t,o=null)=>t===null?o:t;let Mo;const ss=()=>{if(!Mo){const t=document.createElement("style");document.head.appendChild(t),Mo=t.sheet}return Mo},be=t=>{const o=ss(),i=o.rules.length;return o.insertRule(t,i),i},ve=t=>{ss().deleteRule(t)},fd=`${zl}ms ease scaleInFadeOut 0s 1 normal backwards`,md=(t,o,i)=>` +@keyframes scaleInFadeOut { + 0% { + opacity: ${t}; + transform: translate(-50%,-50%) scale(${o}) rotate(${i}deg); + } + 10% { + opacity: 1; + transform: translate(-50%,-50%) scale(1) rotate(${i+20}deg); + } + 100% { + opacity: 0; + transform: translate(-50%,-50%) scale(0.9) rotate(${i+60}deg); + } +} +`;let Bo=null;const hd=`${$l}ms ease fadeScaleOut 0s 1 normal backwards`,gd=(t,o,i)=>` +@keyframes fadeScaleOut { + 0% { + opacity: ${t}; + transform: translate(-50%,-50%) scale(${o}) rotate(${i}deg); + } + 100% { + opacity: 0; + transform: translate(-50%,-50%) scale(0) rotate(${i}deg); + } +} +`;let Fo=null;const rs=(t,{onDraw:o=Qe,onStart:i=Qe,onEnd:m=Qe,enableInitiator:d=Nl,initiatorParentElement:a=document.body,longPressIndicatorParentElement:I=document.body,minDelay:_=Ml,minDist:B=Bl,pointNorm:f=Qe,type:r=Fl,brushSize:u=kl}={})=>{let c=d,y=a,x=I,T=o,P=i,S=m,C=_,b=B,R=f,Y=r,H=u;const L=document.createElement("div"),z=Math.random().toString(36).substring(2,5)+Math.random().toString(36).substring(2,5);L.id=`lasso-initiator-${z}`,L.style.position="fixed",L.style.display="flex",L.style.justifyContent="center",L.style.alignItems="center",L.style.zIndex=99,L.style.width="4rem",L.style.height="4rem",L.style.borderRadius="4rem",L.style.opacity=.5,L.style.transform="translate(-50%,-50%) scale(0) rotate(0deg)";const{longPress:$,longPressCircle:de,longPressCircleLeft:me,longPressCircleRight:xe,longPressEffect:ue}=dd();let _e=!1,Pe=!1,ne=[],V=[],oe=[],ee=[],ye,te=!1,ae=null,ce=null,Oe=null,J=null,De=null,ft=null,se=null,Tt=null,Re=null,mt=null;const Pt=()=>{_e=!1},W=A=>{const{left:D,top:F}=t.getBoundingClientRect();return[A.clientX-D,A.clientY-F]};window.addEventListener("mouseup",Pt);const ze=()=>{L.style.opacity=.5,L.style.transform="translate(-50%,-50%) scale(0) rotate(0deg)"},we=(A,D)=>{const F=getComputedStyle(A),k=+F.opacity,N=F.transform.match(/([0-9.-]+)+/g),O=+N[0],G=+N[1],K=Math.sqrt(O*O+G*G);let U=Math.atan2(G,O)*(180/Math.PI);return U=D&&U<=0?360+U:U,{opacity:k,scale:K,rotate:U}},Ze=A=>{if(!c||_e)return;const D=A.clientX,F=A.clientY;L.style.top=`${F}px`,L.style.left=`${D}px`;const k=we(L),N=k.opacity,O=k.scale,G=k.rotate;L.style.opacity=N,L.style.transform=`translate(-50%,-50%) scale(${O}) rotate(${G}deg)`,L.style.animation="none",kt().then(()=>{Bo!==null&&ve(Bo),Bo=be(md(N,O,G)),L.style.animation=fd,kt().then(()=>{ze()})})},j=()=>{const{opacity:A,scale:D,rotate:F}=we(L);L.style.opacity=A,L.style.transform=`translate(-50%,-50%) scale(${D}) rotate(${F}deg)`,L.style.animation="none",kt(2).then(()=>{Fo!==null&&ve(Fo),Fo=be(gd(A,D,F)),L.style.animation=hd,kt().then(()=>{ze()})})},Ae=(A,D,{time:F=_n,extraTime:k=On,delay:N=Dn}={time:_n,extraTime:On,delay:Dn})=>{te=!0;const O=getComputedStyle($);$.style.color=O.color,$.style.top=`${D}px`,$.style.left=`${A}px`,$.style.animation="none";const G=getComputedStyle(de);de.style.clipPath=G.clipPath,de.style.opacity=G.opacity,de.style.animation="none";const K=we(ue);ue.style.opacity=K.opacity,ue.style.transform=`scale(${K.scale})`,ue.style.animation="none";const U=we(me);me.style.transform=`rotate(${U.rotate}deg)`,me.style.animation="none";const q=we(xe);xe.style.transform=`rotate(${q.rotate}deg)`,xe.style.animation="none",kt().then(()=>{if(!te)return;De!==null&&ve(De),J!==null&&ve(J),Oe!==null&&ve(Oe),ce!==null&&ve(ce),ae!==null&&ve(ae);const{rules:X,names:ie}=Jl({time:F,extraTime:k,delay:N,currentColor:O.color||"currentcolor",targetColor:$.dataset.activeColor,effectOpacity:K.opacity||0,effectScale:K.scale||0,circleLeftRotation:U.rotate||0,circleRightRotation:q.rotate||0,circleClipPath:G.clipPath||"inset(0 0 0 50%)",circleOpacity:G.opacity||0});ae=be(X.main),ce=be(X.effect),Oe=be(X.circleLeft),J=be(X.circleRight),De=be(X.circle),$.style.animation=ie.main,ue.style.animation=ie.effect,me.style.animation=ie.circleLeft,xe.style.animation=ie.circleRight,de.style.animation=ie.circle})},zt=({time:A=Rn}={time:Rn})=>{if(!te)return;te=!1;const D=getComputedStyle($);$.style.color=D.color,$.style.animation="none";const F=getComputedStyle(de);de.style.clipPath=F.clipPath,de.style.opacity=F.opacity,de.style.animation="none";const k=we(ue);ue.style.opacity=k.opacity,ue.style.transform=`scale(${k.scale})`,ue.style.animation="none";const N=F.clipPath.slice(-2,-1)==="x",O=we(me,N);me.style.transform=`rotate(${O.rotate}deg)`,me.style.animation="none";const G=we(xe);xe.style.transform=`rotate(${G.rotate}deg)`,xe.style.animation="none",kt().then(()=>{mt!==null&&ve(mt),Re!==null&&ve(Re),Tt!==null&&ve(Tt),se!==null&&ve(se),ft!==null&&ve(ft);const{rules:K,names:U}=ld({time:A,currentColor:D.color||"currentcolor",targetColor:$.dataset.color,effectOpacity:k.opacity||0,effectScale:k.scale||0,circleLeftRotation:O.rotate||0,circleRightRotation:G.rotate||0,circleClipPath:F.clipPath||"inset(0px)",circleOpacity:F.opacity||1});ft=be(K.main),se=be(K.effect),Tt=be(K.circleLeft),Re=be(K.circleRight),mt=be(K.circle),$.style.animation=U.main,ue.style.animation=U.effect,me.style.animation=U.circleLeft,xe.style.animation=U.circleRight,de.style.animation=U.circle})},Ct=()=>{T(ne,V)},je=A=>{ne.push(A),V.push(A[0],A[1])},$e=A=>{const[D,F]=A,[k,N]=ne[0];ne[1]=[D,N],ne[2]=[D,F],ne[3]=[k,F],ne[4]=[k,N],V[2]=D,V[3]=N,V[4]=D,V[5]=F,V[6]=k,V[7]=F,V[8]=k,V[9]=N},et=A=>{oe.push(A)},Se=()=>Math.abs(R([0,0])[0]-R([H/2,0])[0]),Ie=(A,D,F)=>{const[k,N]=A,[O,G]=D,K=k-O,U=N-G,q=Ja([K,U]);return[+U/q*F,-K/q*F]},bt=A=>{const D=oe.at(-1),F=Se();let[k,N]=Ie(A,D,F);const O=oe.length;if(O===1){const U=[D[0]+k,D[1]+N],q=[D[0]-k,D[1]-N];ne.push(U,q),V.push(U[0],U[1],q[0],q[1]),ee.push([k,N])}else{[k,N]=Ie(A,D,F);const U=[...ee,[k,N]];[k,N]=ud(U,1,10);const[q,X]=ee.at(-1),ie=(k+q)/2,yt=(N+X)/2,Ce=[D[0]+ie,D[1]+yt],Ve=[D[0]-ie,D[1]-yt];ne.splice(O-1,2,Ce,Ve),V.splice(2*(O-1),4,Ce[0],Ce[1],Ve[0],Ve[1]),ee.splice(O,1,[ie,yt])}const G=[A[0]+k,A[1]+N],K=[A[0]-k,A[1]-N];ne.splice(O,0,G,K),V.splice(2*O,0,G[0],G[1],K[0],K[1]),oe.push(A),ee.push([k,N])};let Ke=je,Ne=je;const Ue=A=>{if(ye)Xa(A[0],A[1],ye[0],ye[1])>b&&(ye=A,Ke(R(A)),ne.length>1&&Ct());else{Pe||(Pe=!0,P()),ye=A;const D=R(A);Ne(D)}},Te=qi(Ue,C,C),Me=(A,D)=>{const F=W(A);return D?Te(F):Ue(F)},ht=()=>{ne=[],V=[],oe=[],ee=[],ye=void 0,Ct()},$t=A=>{Ze(A)},Ut=()=>{_e=!0,Pe=!0,ht(),P()},gt=()=>{j()},hn=({merge:A=!1,remove:D=!1}={})=>{Pe=!1;const F=[...ne],k=[...V];return Te.cancel(),ht(),F.length>0&&S(F,k,{merge:A,remove:D}),F},vt=A=>{switch(A){case"rectangle":{Y=A,Ke=$e,Ne=je;break}case"brush":{Y=A,Ke=bt,Ne=et;break}default:{Y="freeform",Ke=je,Ne=je;break}}},qe=A=>{if(A==="onDraw")return T;if(A==="onStart")return P;if(A==="onEnd")return S;if(A==="enableInitiator")return c;if(A==="minDelay")return C;if(A==="minDist")return b;if(A==="pointNorm")return R;if(A==="type")return Y;if(A==="brushSize")return H},Lt=({onDraw:A=null,onStart:D=null,onEnd:F=null,enableInitiator:k=null,initiatorParentElement:N=null,longPressIndicatorParentElement:O=null,minDelay:G=null,minDist:K=null,pointNorm:U=null,type:q=null,brushSize:X=null}={})=>{T=ct(A,T),P=ct(D,P),S=ct(F,S),c=ct(k,c),C=ct(G,C),b=ct(K,b),R=ct(U,R),H=ct(X,H),N!==null&&N!==y&&(y.removeChild(L),N.appendChild(L),y=N),O!==null&&O!==x&&(x.removeChild($),O.appendChild($),x=O),c?(L.addEventListener("click",$t),L.addEventListener("mousedown",Ut),L.addEventListener("mouseleave",gt)):(L.removeEventListener("mousedown",Ut),L.removeEventListener("mouseleave",gt)),q!==null&&vt(q)},v=()=>{y.removeChild(L),x.removeChild($),window.removeEventListener("mouseup",Pt),L.removeEventListener("click",$t),L.removeEventListener("mousedown",Ut),L.removeEventListener("mouseleave",gt)},Be=()=>A=>qa(A,{clear:ht,destroy:v,end:hn,extend:Me,get:qe,set:Lt,showInitiator:Ze,hideInitiator:j,showLongPressIndicator:Ae,hideLongPressIndicator:zt});return y.appendChild(L),x.appendChild($),Lt({onDraw:T,onStart:P,onEnd:S,enableInitiator:c,initiatorParentElement:y,type:Y,brushSize:H}),ja(Ni("initiator",L),Ni("longPressIndicator",$),Be(),Ka(rs))({})},yd=` +precision highp float; + +uniform float antiAliasing; + +varying vec4 color; +varying float finalPointSize; + +float linearstep(float edge0, float edge1, float x) { + return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); +} + +void main() { + vec2 c = gl_PointCoord * 2.0 - 1.0; + float sdf = length(c) * finalPointSize; + float alpha = linearstep(finalPointSize + antiAliasing, finalPointSize - antiAliasing, sdf); + + gl_FragColor = vec4(color.rgb, alpha * color.a); +} +`,pd=t=>` +precision highp float; + +uniform sampler2D colorTex; +uniform float colorTexRes; +uniform float colorTexEps; +uniform sampler2D stateTex; +uniform float stateTexRes; +uniform float stateTexEps; +uniform float devicePixelRatio; +uniform sampler2D encodingTex; +uniform float encodingTexRes; +uniform float encodingTexEps; +uniform float pointSizeExtra; +uniform float pointOpacityMax; +uniform float pointOpacityScale; +uniform float numPoints; +uniform float globalState; +uniform float isColoredByZ; +uniform float isColoredByW; +uniform float isOpacityByZ; +uniform float isOpacityByW; +uniform float isOpacityByDensity; +uniform float isSizedByZ; +uniform float isSizedByW; +uniform float isPixelAligned; +uniform float colorMultiplicator; +uniform float opacityMultiplicator; +uniform float opacityDensity; +uniform float sizeMultiplicator; +uniform float numColorStates; +uniform float pointScale; +uniform float drawingBufferWidth; +uniform float drawingBufferHeight; +uniform mat4 modelViewProjection; + +attribute vec2 stateIndex; + +varying vec4 color; +varying float finalPointSize; + +void main() { + vec4 state = texture2D(stateTex, stateIndex); + + if (isPixelAligned < 0.5) { + gl_Position = modelViewProjection * vec4(state.x, state.y, 0.0, 1.0); + } else { + vec4 clipSpacePosition = modelViewProjection * vec4(state.x, state.y, 0.0, 1.0); + vec2 ndcPosition = clipSpacePosition.xy / clipSpacePosition.w; + vec2 pixelPos = 0.5 * (ndcPosition + 1.0) * vec2(drawingBufferWidth, drawingBufferHeight); + pixelPos = floor(pixelPos + 0.5); // Snap to nearest pixel + vec2 snappedPosition = (pixelPos / vec2(drawingBufferWidth, drawingBufferHeight)) * 2.0 - 1.0; + gl_Position = vec4(snappedPosition, 0.0, 1.0); + } + + + // Determine color index + float colorIndexZ = isColoredByZ * floor(state.z * colorMultiplicator); + float colorIndexW = isColoredByW * floor(state.w * colorMultiplicator); + + // Multiply by the number of color states per color + // I.e., normal, active, hover, background, etc. + float colorIndex = (colorIndexZ + colorIndexW) * numColorStates; + + // Half a "pixel" or "texel" in texture coordinates + float colorLinearIndex = colorIndex + globalState; + + // Need to add cEps here to avoid floating point issue that can lead to + // dramatic changes in which color is loaded as floor(3/2.9999) = 1 but + // floor(3/3.0001) = 0! + float colorRowIndex = floor((colorLinearIndex + colorTexEps) / colorTexRes); + + vec2 colorTexIndex = vec2( + (colorLinearIndex / colorTexRes) - colorRowIndex + colorTexEps, + colorRowIndex / colorTexRes + colorTexEps + ); + + color = texture2D(colorTex, colorTexIndex); + + // Retrieve point size + float pointSizeIndexZ = isSizedByZ * floor(state.z * sizeMultiplicator); + float pointSizeIndexW = isSizedByW * floor(state.w * sizeMultiplicator); + float pointSizeIndex = pointSizeIndexZ + pointSizeIndexW; + + float pointSizeRowIndex = floor((pointSizeIndex + encodingTexEps) / encodingTexRes); + vec2 pointSizeTexIndex = vec2( + (pointSizeIndex / encodingTexRes) - pointSizeRowIndex + encodingTexEps, + pointSizeRowIndex / encodingTexRes + encodingTexEps + ); + float pointSize = texture2D(encodingTex, pointSizeTexIndex).x; + + // Retrieve opacity + ${t===3?"":` + if (isOpacityByDensity < 0.5) { + float opacityIndexZ = isOpacityByZ * floor(state.z * opacityMultiplicator); + float opacityIndexW = isOpacityByW * floor(state.w * opacityMultiplicator); + float opacityIndex = opacityIndexZ + opacityIndexW; + + float opacityRowIndex = floor((opacityIndex + encodingTexEps) / encodingTexRes); + vec2 opacityTexIndex = vec2( + (opacityIndex / encodingTexRes) - opacityRowIndex + encodingTexEps, + opacityRowIndex / encodingTexRes + encodingTexEps + ); + color.a = texture2D(encodingTex, opacityTexIndex)[${1+t}]; + } else { + color.a = min(1.0, opacityDensity + globalState); + } + `} + + color.a = min(pointOpacityMax, color.a) * pointOpacityScale; + finalPointSize = (pointSize * pointScale) + pointSizeExtra; + gl_PointSize = finalPointSize; +} +`,Ed=`precision highp float; + +varying vec4 color; + +void main() { + gl_FragColor = color; +} +`,xd=`precision highp float; + +uniform sampler2D startStateTex; +uniform sampler2D endStateTex; +uniform float t; + +varying vec2 particleTextureIndex; + +void main() { + // Interpolate x, y, and value + vec3 start = texture2D(startStateTex, particleTextureIndex).xyw; + vec3 end = texture2D(endStateTex, particleTextureIndex).xyw; + vec3 curr = start * (1.0 - t) + end * t; + + // The category cannot be interpolated + float endCategory = texture2D(endStateTex, particleTextureIndex).z; + + gl_FragColor = vec4(curr.xy, endCategory, curr.z); +}`,wd=`precision highp float; + +attribute vec2 position; +varying vec2 particleTextureIndex; + +void main() { + // map normalized device coords to texture coords + particleTextureIndex = 0.5 * (1.0 + position); + + gl_Position = vec4(position, 0, 1); +}`,Ad=(t,o)=>t?Xi.reduce((i,m)=>t.hasExtension(m)?i:(console.warn(`WebGL: ${m} extension not supported. Scatterplot might not render properly`),!1),!0):!1,Sd=t=>{const o=t.getContext("webgl",{antialias:!0,preserveDrawingBuffer:!0}),i=[];for(const m of Xi)o.getExtension(m)?i.push(m):console.warn(`WebGL: ${m} extension not supported. Scatterplot might not render properly`);return Qa({gl:o,extensions:i})},ko=(t,o,i,m)=>Math.sqrt((t-i)**2+(o-m)**2),Id=t=>{let o=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY,m=Number.POSITIVE_INFINITY,d=Number.NEGATIVE_INFINITY;for(let a=0;ai?t[a]:i,m=t[a+1]d?t[a+1]:d;return[o,m,i,d]},Td=([t,o,i,m])=>Number.isFinite(t)&&Number.isFinite(o)&&Number.isFinite(i)&&Number.isFinite(m)&&i-t>0&&m-o>0,Pd=/^#?([a-f\d])([a-f\d])([a-f\d])$/i,Cd=(t,o=!1)=>t.replace(Pd,(i,m,d,a)=>`#${m}${m}${d}${d}${a}${a}`).substring(1).match(/.{2}/g).map(i=>Number.parseInt(i,16)/255**o),lt=(t,o,{minLength:i=0}={})=>Array.isArray(t)&&t.length>=i&&t.every(o),dt=t=>!Number.isNaN(+t)&&+t>=0,vn=t=>!Number.isNaN(+t)&&+t>0,zo=(t,o)=>i=>t.indexOf(i)>=0?i:o,bd=(t,o=!1,i=qo)=>new Promise((m,d)=>{const a=new Image;o&&(a.crossOrigin="anonymous"),a.src=t,a.onload=()=>{m(a)};const I=()=>{d(new Error(ul))};a.onerror=I,setTimeout(I,i)}),Wi=(t,o,i=qo)=>new Promise((m,d)=>{bd(o,o.indexOf(window.location.origin)!==0&&o.indexOf("base64")===-1,i).then(a=>{m(t.texture(a))}).catch(a=>{d(a)})}),vd=(t,o=!1)=>[...Cd(t,o),255**!o],Ld=/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i,_d=t=>Ld.test(t),Od=t=>t>=0&&t<=1,kn=t=>Array.isArray(t)&&t.every(Od);function Gi(t,o,i,m,d,a){return(i-t)*(a-o)-(d-t)*(m-o)}const Dd=(t,[o,i]=[])=>{let m=0;for(let d=0,a=t.length-2;di&&Gi(I,_,B,f,o,i)>0&&m++:f<=i&&Gi(I,_,B,f,o,i)<0&&m--,a=d}return m!==0},Go=t=>typeof t=="string"||t instanceof String,Rd=t=>Number.isInteger(t)&&t>=0&&t<=255,as=t=>Array.isArray(t)&&t.every(Rd),Nd=t=>t.length===3&&(kn(t)||as(t)),Md=t=>t.length===4&&(kn(t)||as(t)),ut=t=>Array.isArray(t)&&t.length>0&&(Array.isArray(t[0])||Go(t[0])),Bd=(t,o)=>!(Array.isArray(t)&&Array.isArray(o))||t.length!==o.length?!1:t.length===0?!0:Array.isArray(t[0])&&Array.isArray(o[0])?t.every(([i,m,d,a],I)=>{const[_,B,f,r]=o[I];return i===_&&m===B&&d===f&&a===r}):!1,fn=(t,o)=>t>o?t:o,Yi=(t,o)=>t{if(Md(t)){const i=kn(t);return o&&i||!(o||i)?t:o&&!i?t.map(m=>m/255):t.map(m=>m*255)}if(Nd(t)){const i=255**!o,m=kn(t);return o&&m||!(o||m)?[...t,i]:o&&!m?[...t.map(d=>d/255),i]:[...t.map(d=>d*255),i]}return _d(t)?vd(t,o):(console.warn("Only HEX, RGB, and RGBA are handled by this function. Returning white instead."),o?[1,1,1,1]:[255,255,255,255])},Fd=t=>Object.entries(t).reduce((o,[i,m])=>(o[m]?o[m]=[...o[m],i]:o[m]=i,o),{}),Zi=t=>.21*t[0]+.72*t[1]+.07*t[2],kd=(t,o,i)=>Math.min(i,Math.max(o,t)),zd=t=>new Promise((o,i)=>{if(!t||Array.isArray(t))o(t);else{const m=Array.isArray(t.x)||ArrayBuffer.isView(t.x)?t.x.length:0,d=(Array.isArray(t.x)||ArrayBuffer.isView(t.x))&&(u=>t.x[u]),a=(Array.isArray(t.y)||ArrayBuffer.isView(t.y))&&(u=>t.y[u]),I=(Array.isArray(t.line)||ArrayBuffer.isView(t.line))&&(u=>t.line[u]),_=(Array.isArray(t.lineOrder)||ArrayBuffer.isView(t.lineOrder))&&(u=>t.lineOrder[u]),B=Object.keys(t),f=(()=>{const u=B.find(c=>ts.has(c));return u&&(Array.isArray(t[u])||ArrayBuffer.isView(t[u]))&&(c=>t[u][c])})(),r=(()=>{const u=B.find(c=>ns.has(c));return u&&(Array.isArray(t[u])||ArrayBuffer.isView(t[u]))&&(c=>t[u][c])})();d&&a&&f&&r&&I&&_?o(t.x.map((u,c)=>[u,a(c),f(c),r(c),I(c),_(c)])):d&&a&&f&&r&&I?o(Array.from({length:m},(u,c)=>[d(c),a(c),f(c),r(c),I(c)])):d&&a&&f&&r?o(Array.from({length:m},(u,c)=>[d(c),a(c),f(c),r(c)])):d&&a&&f?o(Array.from({length:m},(u,c)=>[d(c),a(c),f(c)])):d&&a?o(Array.from({length:m},(u,c)=>[d(c),a(c)])):i(new Error("You need to specify at least x and y"))}}),$d=t=>Number.isFinite(t.y)&&!("x"in t),Ud=t=>Number.isFinite(t.x)&&!("y"in t),Vd=t=>Number.isFinite(t.x)&&Number.isFinite(t.y)&&Number.isFinite(t.width)&&Number.isFinite(t.height),Hd=t=>Number.isFinite(t.x1)&&Number.isFinite(t.y1)&&Number.isFinite(t.x2)&&Number.isFinite(t.x2),Wd=t=>"vertices"in t&&t.vertices.length>1,Gd=t=>{if(!Array.isArray(t)||t.length<3)return!1;for(const o of t)if(!Array.isArray(o)||o.length!==2||typeof o[0]!="number"||typeof o[1]!="number")return!1;return!0},Yd=t=>{const o=[...t],i=t.at(0),m=t.at(-1);return(i[0]!==m[0]||i[1]!==m[1])&&o.push(i),o},Zd=t=>{const o=t.length;for(let i=1;i-1&&m{let{regl:o,canvas:i=document.createElement("canvas"),gamma:m=Fc}=t,d=!1;o||(o=Sd(i));const a=Ad(o),I=[i.width,i.height],_=o.framebuffer({width:I[0],height:I[1],colorFormat:"rgba",colorType:"float"}),B=o({vert:` + precision highp float; + attribute vec2 xy; + void main () { + gl_Position = vec4(xy, 0, 1); + }`,frag:` + precision highp float; + uniform vec2 srcRes; + uniform sampler2D src; + uniform float gamma; + + vec3 approxLinearToSRGB (vec3 rgb, float gamma) { + return pow(clamp(rgb, vec3(0), vec3(1)), vec3(1.0 / gamma)); + } + + void main () { + vec4 color = texture2D(src, gl_FragCoord.xy / srcRes); + gl_FragColor = vec4(approxLinearToSRGB(color.rgb, gamma), color.a); + }`,attributes:{xy:[-4,-4,4,-4,0,4]},uniforms:{src:()=>_,srcRes:()=>I,gamma:()=>m},count:3,depth:{enable:!1},blend:{enable:!0,func:{srcRGB:"one",srcAlpha:"one",dstRGB:"one minus src alpha",dstAlpha:"one minus src alpha"}}}),f=C=>{const b=C.getContext("2d");b.clearRect(0,0,C.width,C.height),b.drawImage(i,(i.width-C.width)/2,(i.height-C.height)/2,C.width,C.height,0,0,C.width,C.height)},r=(C,b)=>{o.clear(ki),_.use(()=>{o.clear(ki),C()}),B(),f(b)},u=()=>{o.poll()},c=new Set,y=C=>(c.add(C),()=>{c.delete(C)}),x=o.frame(()=>{const C=c.values();let b=C.next();for(;!b.done;)b.value(),b=C.next()}),T=(C,b)=>{const R=C===void 0?Math.min(window.innerWidth,window.screen.availWidth):C,Y=b===void 0?Math.min(window.innerHeight,window.screen.availHeight):b;i.width=R*window.devicePixelRatio,i.height=Y*window.devicePixelRatio,I[0]=i.width,I[1]=i.height,_.resize(...I)},P=()=>{T()};return t.canvas||(window.addEventListener("resize",P),window.addEventListener("orientationchange",P),T()),{get canvas(){return i},get regl(){return o},get gamma(){return m},set gamma(C){m=+C},get isSupported(){return a},get isDestroyed(){return d},render:r,resize:T,onFrame:y,refresh:u,destroy:()=>{d=!0,window.removeEventListener("resize",P),window.removeEventListener("orientationchange",P),x.cancel(),i=void 0,o.destroy(),o=void 0}}},Kd=function(){const o=(f,r,u,c,y)=>{const x=(c-r)*.5,T=(y-u)*.5;return(2*u-2*c+x+T)*f*f*f+(-3*u+3*c-2*x-T)*f*f+x*f+u},i=(f,r,u)=>{const c=u*f,y=Math.floor(c),x=c-y,T=r[Math.max(0,y-1)],P=r[y],S=r[Math.min(u,y+1)],C=r[Math.min(u,y+2)];return[o(x,T[0],P[0],S[0],C[0]),o(x,T[1],P[1],S[1],C[1])]},m=(f,r,u,c)=>(f-u)**2+(r-c)**2;const d=(f,r,u)=>{let c=r[0],y=r[1],x=u[0]-c,T=u[1]-y;if(x!==0||T!==0){const P=((f[0]-c)*x+(f[1]-y)*T)/(x*x+T*T);P>1?(c=u[0],y=u[1]):P>0&&(c+=x*P,y+=T*P)}return x=f[0]-c,T=f[1]-y,x*x+T*T};const a=(f,r,u,c,y)=>{let x=c,T;for(let P=r+1;Px&&(T=P,x=S)}x>c&&(T-r>1&&a(f,r,T,c,y),y.push(f[T]),u-T>1&&a(f,T,u,c,y))};const I=(f,r)=>{const u=f.length-1,c=[f[0]];return a(f,0,u,r,c),c.push(f[u]),c},_=(f,{maxIntPointsPerSegment:r=100,tolerance:u=.002}={})=>{const c=f.length,y=c-1,x=y*r+1,T=u**2;let P=[],S;for(let C=0;CT&&(b.push(H),S=H)}b.push(f[C+1]),b=I(b,T),P=P.concat(b.slice(0,b.length-1))}return P.push(f[f.length-1].slice(0,2)),P.flat()},B=f=>{const r={},u=!Number.isNaN(+f[0][5]);return f.forEach(c=>{const y=c[4];r[y]||(r[y]=[]),u?r[y][c[5]]=c:r[y].push(c)}),Object.entries(r).forEach(c=>{r[c[0]]=c[1].filter(y=>y),r[c[0]].reference=c[1][0]}),r};self.onmessage=function(r){r.data.points&&+r.data.points.length||self.postMessage({error:new Error("No points provided")}),r.data.points;const c=B(r.data.points);self.postMessage({points:Object.entries(c).reduce((y,x)=>(y[x[0]]=_(x[1],r.data.options),y[x[0]].reference=x[1].reference,y),{})})}},qd=(t,o={tolerance:.002,maxIntPointsPerSegment:100})=>new Promise((i,m)=>{const d=ec(Kd);d.onmessage=a=>{a.data.error?m(a.data.error):i(a.data.points),d.terminate()},d.postMessage({points:t,options:o})}),$o={showRecticle:{replacement:"showReticle",removalVersion:"2",translation:Qe},recticleColor:{replacement:"reticleColor",removalVersion:"2",translation:Qe},keyMap:{replacement:"actionKeyMap",removalVersion:"2",translation:Fd}},Uo=t=>{const o=Object.keys(t).filter(i=>$o[i]);for(const i of o){const{replacement:m,removalVersion:d,translation:a}=$o[i];console.warn(`regl-scatterplot: the "${i}" property is deprecated and will be removed in v${d}. Please use "${m}" instead.`),t[$o[i].replacement]=t[i]!==os?a(t[i]):t[i],delete t[i]}return t},Le=(t,o,{allowSegment:i=!1,allowDensity:m=!1,allowInherit:d=!1}={})=>ts.has(t)?"valueZ":ns.has(t)?"valueW":t==="segment"?i?"segment":o:t==="density"?m?"density":o:t==="inherit"&&d?"inherit":o,Vo=t=>{switch(t){case"valueZ":return 2;case"valueW":return 3;default:return null}},au=(t={})=>{const o=tc({async:!t.syncEvents,caseInsensitive:!0}),i=new Float32Array(16),m=new Float32Array(16),d=[0,0];Uo(t);let{renderer:a,antiAliasing:I=Cl,pixelAligned:_=bl,backgroundColor:B=el,backgroundImage:f=fl,canvas:r=document.createElement("canvas"),colorBy:u=un,deselectOnDblClick:c=gl,deselectOnEscape:y=yl,lassoColor:x=Ic,lassoLineWidth:T=Tc,lassoMinDelay:P=Cc,lassoMinDist:S=bc,lassoClearEvent:C=vc,lassoInitiator:b=Pc,lassoInitiatorParentElement:R=document.body,lassoLongPressIndicatorParentElement:Y=document.body,lassoOnLongPress:H=Lc,lassoLongPressTime:L=_n,lassoLongPressAfterEffectTime:z=On,lassoLongPressEffectDelay:$=Dn,lassoLongPressRevertEffectTime:de=Rn,lassoType:me=vl,lassoBrushSize:xe=_c,actionKeyMap:ue=Rc,mouseMode:_e=wc,showReticle:Pe=ml,reticleColor:ne=hl,pointColor:V=Xc,pointColorActive:oe=Jc,pointColorHover:ee=Qc,showPointConnections:ye=pl,pointConnectionColor:te=tl,pointConnectionColorActive:ae=nl,pointConnectionColorHover:ce=ol,pointConnectionColorBy:Oe=Do,pointConnectionOpacity:J=Wc,pointConnectionOpacityBy:De=_o,pointConnectionOpacityActive:ft=Gc,pointConnectionSize:se=Vc,pointConnectionSizeActive:Tt=Hc,pointConnectionSizeBy:Re=Lo,pointConnectionMaxIntPointsPerSegment:mt=El,pointConnectionTolerance:Pt=xl,pointSize:W=zc,pointSizeSelected:ze=$c,pointSizeMouseDetection:we=wl,pointOutlineWidth:Ze=Uc,opacity:j=Ye,opacityBy:Ae=Oo,opacityByDensityFill:zt=Zc,opacityInactiveMax:Ct=Kc,opacityInactiveScale:je=qc,sizeBy:$e=vo,pointScaleMode:et=kc,height:Se=Bc,width:Ie=Mc,annotationLineColor:bt=il,annotationLineWidth:Ke=sl,annotationHVLineLimit:Ne=rl,cameraIsFixed:Ue=Pl}=t,Te=Ie===Ye?1:Ie,Me=Se===Ye?1:Se;const{performanceMode:ht=Al,opacityByDensityDebounceTime:$t=jc,spatialIndexUseWorker:Ut=Tl}=t,gt=!!(t.renderPointsAsSquares||ht),hn=!!(t.disableAlphaBlending||ht);_e=zo(zi,Ln)(_e),a||(a=jd({regl:t.regl,gamma:t.gamma})),B=ge(B,!0),x=ge(x,!0),ne=ge(ne,!0);let vt=!1,qe=!1,Lt=Zi(B),v,Be,A,D=!1,F=null,k=[0,0],N=-1,O=[];const G=new Set,K=new Set;let U=!1;const q=new Set;let X=[],ie=0,yt=0,Ce=!1,Ve=[],zn,Vt,gn=t.aspectRatio||Nc,$n,_t,pt,He,Fe,Un,Ht,Wt,Vn,Ot,Gt,Yt,Hn=!1,Z=!0,Et=!1,yn;V=ut(V)?[...V]:[V],oe=ut(oe)?[...oe]:[oe],ee=ut(ee)?[...ee]:[ee],V=V.map(e=>ge(e,!0)),oe=oe.map(e=>ge(e,!0)),ee=ee.map(e=>ge(e,!0)),j=!Array.isArray(j)&&Number.isNaN(+j)?V[0][3]:j,j=lt(j,dt,{minLength:1})?[...j]:[j],W=lt(W,dt,{minLength:1})?[...W]:[W];let Wn=bo/W[0];te==="inherit"?te=[...V]:(te=ut(te)?[...te]:[te],te=te.map(e=>ge(e,!0))),ae==="inherit"?ae=[...oe]:(ae=ut(ae)?[...ae]:[ae],ae=ae.map(e=>ge(e,!0))),ce==="inherit"?ce=[...ee]:(ce=ut(ce)?[...ce]:[ce],ce=ce.map(e=>ge(e,!0))),J==="inherit"?J=[...j]:J=lt(J,dt,{minLength:1})?[...J]:[J],se==="inherit"?se=[...W]:se=lt(se,dt,{minLength:1})?[...se]:[se],u=Le(u,un),Ae=Le(Ae,Oo,{allowDensity:!0}),$e=Le($e,vo),Oe=Le(Oe,Do,{allowSegment:!0,allowInherit:!0}),De=Le(De,_o,{allowSegment:!0}),Re=Le(Re,Lo,{allowSegment:!0});let tt,nt,ot,Xo,ke=0,Gn=0,Zt,Yn,jt,pn,En,xn,wn,xt=!1,Kt=null,Zn,jn,Jo=Pe,it,Dt=0,We,Rt=0,An=!1,pe=!1,Nt=!1,qt=!1,wt=mn,At=mn,le,Mt=!1,he=t.xScale||null,re=t.yScale||null,Xt=0,Jt=0,Qt=0,en=0;he&&(Xt=he.domain()[0],Jt=he.domain()[1]-he.domain()[0],he.range([0,Te])),re&&(Qt=re.domain()[0],en=re.domain()[1]-re.domain()[0],re.range([Me,0]));const Qo=e=>-1+e/Te*2,ei=e=>1+e/Me*-2,cs=()=>[Qo(d[0]),ei(d[1])],Xe=(e,n)=>{const s=[e,n,1,1],l=rc(i,at(i,$n,at(i,v.view,pt)));return Cn(s,s,l),s.slice(0,2)},ti=(e=0)=>{const n=rt(),l=(Gt[1]-Yt[1])/r.height;return(Vn*n+e)*l},Kn=()=>U?X.filter((e,n)=>q.has(n)):X,qn=(e,n,s,l)=>{const h=zn.range(e,n,s,l);return U?h.filter(E=>q.has(E)):h},ni=()=>{const[e,n]=cs(),[s,l]=Xe(e,n),h=ti(4),E=qn(s-h,l-h,s+h,l+h);let w=h,p=-1;for(const g of E){const[M,fe]=X[g],Ee=ko(M,fe,s,l);Ee{Ve=e,Be.setPoints(n),o.publish("lassoExtend",{coordinates:e})},ds=e=>{const n=Id(e);if(!Td(n))return[];const s=qn(...n),l=[];for(const h of s)Dd(e,X[h])&&l.push(h);return l},Sn=()=>{Ve=[],Be&&Be.clear()},tn=e=>e&&e.length>4,St=(e,n)=>{if(Un||!ye||!tn(X[e[0]]))return;const s=n===0,l=n===1?p=>K.add(p):Qe,h=Object.keys(e.reduce((p,g)=>{const M=X[g],Ee=Array.isArray(M[4])?M[4][0]:M[4];return p[Ee]=!0,p},{})),E=He.getData().opacities,w=h.filter(p=>!K.has(+p));for(const p of w){const g=Fe[p][0],M=Fe[p][2],fe=Fe[p][3],Ee=g*4+fe*2,Io=Ee+M*2+4;E.__original__===void 0&&(E.__original__=E.slice());for(let Ft=Ee;Ft[e%ke/ke+Gn,Math.floor(e/ke)/ke+Gn],us=e=>U&&!q.has(e),Tn=({preventEvent:e=!1}={})=>{C===Wo&&Sn(),O.length>0&&(e||o.publish("deselect"),K.clear(),St(O,0),O=[],G.clear(),Z=!0)},fs=e=>{if(!(he&&re))return console.warn("xScale and yScale must be defined for programmatic lasso selection"),null;const n=[];for(const[s,l]of e){const h=(s-Xt)/Jt,E=(l-Qt)/en,w=h*2-1,p=E*2-1,[g,M]=Xe(w,p);n.push(g,M)}return n},Bt=(e,{merge:n=!1,remove:s=!1,preventEvent:l=!1}={})=>{const h=Array.isArray(e)?e:[e],E=[...O];if(n){if(O=oc(O,h),E.length===O.length){Z=!0;return}}else if(s){const p=new Set(h);if(O=O.filter(g=>!p.has(g)),E.length===O.length){Z=!0;return}}else{if(O?.length>0&&St(O,0),E.length>0&&h.length===0){Tn({preventEvent:l});return}O=h}if(To(E,O)){Z=!0;return}const w=[];G.clear(),K.clear();for(let p=O.length-1;p>=0;p--){const g=O[p];if(g<0||g>=ie||us(g)){O.splice(p,1);continue}G.add(g),w.push.apply(w,In(g))}Yn({usage:"dynamic",type:"float",data:w}),St(O,1),l||o.publish("select",{points:O}),Z=!0},ms=(e,{merge:n=!1,remove:s=!1,isGl:l=!1}={})=>{if(!Gd(e))throw new Error("Lasso selection requires at least 3 vertices as [x, y] coordinate pairs");const h=Yd(e);let E,w;if(l)E=h,w=h.flat();else{if(w=fs(h),!w)throw new Error("xScale and yScale must be defined to convert lasso vertices from data space to GL space");E=[];for(let p=0;p{let l=!1;if(!(U&&!q.has(e))&&e>=0&&e=0&&w&&!G.has(E)&&St([E],0),le=e,jt.subdata(In(e)),G.has(e)||St([e],2),w&&!s&&o.publish("pointover",le)}else l=+le>=0,l&&(G.has(le)||St([le],0),s||o.publish("pointout",le)),le=void 0;l&&(Z=!0,Et=n)},Xn=e=>{const n=r.getBoundingClientRect();return d[0]=e.clientX-n.left,d[1]=e.clientY-n.top,[...d]},hs=()=>{v.config({isFixed:!0}),D=!0,Ce=!0,Sn(),N>=0&&(clearTimeout(N),N=-1),o.publish("lassoStart")},oi=(e,n,{merge:s=!1,remove:l=!1}={})=>{v.config({isFixed:Ue}),Ve=[...e];const h=ds(n);Bt(h,{merge:s,remove:l}),o.publish("lassoEnd",{coordinates:Ve}),C===Yo&&Sn()},Q=rs(r,{onStart:hs,onDraw:ls,onEnd:oi,enableInitiator:b,initiatorParentElement:R,longPressIndicatorParentElement:Y,pointNorm:([e,n])=>Xe(Qo(e),ei(n)),minDelay:P,minDist:me==="brush"?Math.max(Vi,S):S,type:me}),gs=()=>_e===Ji,on=(e,n)=>{switch(ue[n]){case Fn:return e.altKey;case jo:return e.metaKey;case Qi:return e.ctrlKey;case es:return e.metaKey;case Ko:return e.shiftKey;default:return!1}},ys=e=>document.elementsFromPoint(e.clientX,e.clientY).some(n=>n===r),ii=e=>{!pe||e.buttons!==1||(D=!0,F=performance.now(),k=Xn(e),Ce=gs()||on(e,Zo),!Ce&&H&&(Q.showLongPressIndicator(e.clientX,e.clientY,{time:L,extraTime:z,delay:$}),N=setTimeout(()=>{N=-1,Ce=!0},L)))},Jn=e=>{pe&&(D=!1,N>=0&&(clearTimeout(N),N=-1),Ce&&(e.preventDefault(),Ce=!1,Q.end({merge:on(e,Mn),remove:on(e,Bn)})),H&&Q.hideLongPressIndicator({time:de}))},si=e=>{if(!pe)return;e.preventDefault();const n=Xn(e);if(ko(...n,...k)>=S)return;const s=performance.now()-F;if(!b||s=0?(O.length>0&&C===Wo&&Sn(),Bt([l],{merge:on(e,Mn),remove:on(e,Bn)})):Ot||(Ot=setTimeout(()=>{Ot=null,Q.showInitiator(e)},Sl))}},ri=e=>{Q.hideInitiator(),Ot&&(clearTimeout(Ot),Ot=null),c&&(e.preventDefault(),Tn())},ai=e=>{if(qt||(Mt=ys(e),qt=!0),!(pe&&(Mt||D)))return;const n=Xn(e),l=ko(...n,...k)>=S;Mt&&!Ce&&nn(ni()),Ce?(e.preventDefault(),Q.extend(e,!0)):D&&H&&l&&Q.hideLongPressIndicator({time:de}),N>=0&&l&&(clearTimeout(N),N=-1),D&&(Z=!0)},ci=()=>{le=void 0,Mt=!1,qt=!1,pe&&(+le>=0&&!G.has(le)&&St([le],0),Jn(),Z=!0)},Qn=()=>{const e=Math.max(W.length,j.length);Rt=Math.max(2,Math.ceil(Math.sqrt(e)));const n=new Float32Array(Rt**2*4);for(let s=0;s{const l=e.length,h=n.length,E=s.length,w=[];if(l===h&&h===E)for(let p=0;p{const e=eo(),n=e.length;Dt=Math.max(2,Math.ceil(Math.sqrt(n)));const s=new Float32Array(Dt**2*4);return e.forEach((l,h)=>{s[h*4]=l[0],s[h*4+1]=l[1],s[h*4+2]=l[2],s[h*4+3]=l[3]}),a.regl.texture({data:s,shape:[Dt,Dt,4],type:"float"})},ps=(e,n)=>{_t[0]=e/Vt,_t[5]=n},no=()=>{Vt=Te/Me,$n=Po([],[1/Vt,1,1]),_t=Po([],[1/Vt,1,1]),pt=Po([],[gn,1,1])},Es=e=>{+e<=0||(gn=e)},oo=(e,n)=>s=>{if(!s||s.length===0)return;const h=[...e()];let E=ut(s)?s:[s];if(E=E.map(w=>ge(w,!0)),!Bd(h,E)){it&&it.destroy();try{n(E),it=to()}catch{console.error("Invalid colors. Switching back to default colors."),n(h),it=to()}}},xs=oo(()=>V,e=>{V=e}),ws=oo(()=>oe,e=>{oe=e}),As=oo(()=>ee,e=>{ee=e}),Ss=()=>{const e=Xe(-1,-1),n=Xe(1,1),s=(e[0]+1)/2,l=(n[0]+1)/2,h=(e[1]+1)/2,E=(n[1]+1)/2,w=[Xt+s*Jt,Xt+l*Jt],p=[Qt+h*en,Qt+E*en];return[w,p]},st=()=>{if(!(he||re))return;const[e,n]=Ss();he&&he.domain(e),re&&re.domain(n)},io=(e,n)=>{Me=Math.max(1,e),r.height=Math.floor(Me*window.devicePixelRatio),re&&(re.range([Me,0]),n||st())},so=e=>{if(e===Ye){Se=e,r.style.height="100%",window.requestAnimationFrame(()=>{r&&io(r.getBoundingClientRect().height)});return}!+e||+e<=0||(Se=+e,io(Se),r.style.height=`${Se}px`)},ro=()=>{Vn=we,we===Ye&&(Vn=Array.isArray(W)?sc(W):W)},ao=e=>{const n=Array.isArray(W)?[...W]:W;lt(e,dt,{minLength:1})?W=[...e]:vn(+e)&&(W=[+e]),!(n===W||To(n,W))&&(We&&We.destroy(),Wn=bo/W[0],We=Qn(),ro())},Is=e=>{!+e||+e<0||(ze=+e)},Ts=e=>{!+e||+e<0||(Ze=+e)},co=(e,n)=>{Te=Math.max(1,e),r.width=Math.floor(Te*window.devicePixelRatio),he&&(he.range([0,Te]),n||st())},lo=e=>{if(e===Ye){Ie=e,r.style.width="100%",window.requestAnimationFrame(()=>{r&&co(r.getBoundingClientRect().width)});return}!+e||+e<=0||(Ie=+e,co(Ie),r.style.width=`${Te}px`)},Ps=e=>{const n=Array.isArray(j)?[...j]:j;lt(e,dt,{minLength:1})?j=[...e]:vn(+e)&&(j=[+e]),!(n===j||To(n,j))&&(We&&We.destroy(),We=Qn())},uo=e=>{switch(e){case"valueZ":return wt;case"valueW":return At;default:return null}},fo=(e,n)=>e===Ge?s=>Math.round(s*(n.length-1)):Qe,Cs=e=>{u=Le(e,un)},bs=e=>{Ae=Le(e,Oo,{allowDensity:!0})},vs=e=>{$e=Le(e,vo)},Ls=e=>{Oe=Le(e,Do,{allowSegment:!0,allowInherit:!0})},_s=e=>{De=Le(e,_o,{allowSegment:!0})},Os=e=>{Re=Le(e,Lo,{allowSegment:!0})},Ds=()=>I,Rs=()=>[r.width,r.height],Ns=()=>f,Ms=()=>it,Bs=()=>Dt,Fs=()=>.5/Dt,ks=()=>window.devicePixelRatio,zs=()=>Zt,mo=()=>Yn,$s=()=>We,Us=()=>Rt,Vs=()=>.5/Rt,li=()=>0,Hs=()=>ot||tt,Ws=()=>ke,Gs=()=>.5/ke,ho=()=>_t,go=()=>v.view,yo=()=>pt,po=()=>at(m,_t,at(m,v.view,pt)),di=()=>window.devicePixelRatio,ui=()=>fn(Wn,v.scaling[0])*window.devicePixelRatio,fi=()=>v.scaling[0]>1?Math.asinh(fn(1,v.scaling[0]))/Math.asinh(1)*window.devicePixelRatio:fn(Wn,v.scaling[0])*window.devicePixelRatio;let rt=fi;et==="linear"?rt=ui:et==="constant"&&(rt=di);const mi=()=>U?q.size:ie,sn=()=>O.length,Ys=()=>sn()>0?Ct:1,Zs=()=>sn()>0?je:1,js=()=>+(u==="valueZ"),Ks=()=>+(u==="valueW"),qs=()=>+(Ae==="valueZ"),Xs=()=>+(Ae==="valueW"),Js=()=>+(Ae==="density"),Qs=()=>+($e==="valueZ"),er=()=>+($e==="valueW"),tr=()=>+_,nr=()=>u==="valueZ"?wt===Ge?V.length-1:1:At===Ge?V.length-1:1,or=()=>Ae==="valueZ"?wt===Ge?j.length-1:1:At===Ge?j.length-1:1,ir=()=>$e==="valueZ"?wt===Ge?W.length-1:1:At===Ge?W.length-1:1,sr=e=>{if(Ae!=="density")return 1;const n=rt(),s=W[0]*n,l=2/(2/v.view[0])*(2/(2/v.view[5])),h=e.viewportHeight,E=e.viewportWidth;let w=zt*E*h/(yt*s*s)*Yi(1,l);w*=gt?1:1/(.25*Math.PI);const p=fn(bo,s)+.5;return w*=(s/p)**2,Yi(1,fn(0,w))},rr=a.regl({framebuffer:()=>Xo,vert:wd,frag:xd,attributes:{position:[-4,0,4,4,4,-4]},uniforms:{startStateTex:()=>nt,endStateTex:()=>tt,t:(e,n)=>n.t},count:3}),It=(e,n,s,l=yc,h=Ys,E=Zs)=>a.regl({frag:gt?Ed:yd,vert:pd(l),blend:{enable:!hn,func:{srcRGB:"src alpha",srcAlpha:"one",dstRGB:"one minus src alpha",dstAlpha:"one minus src alpha"}},depth:{enable:!1},attributes:{stateIndex:{buffer:s,size:2}},uniforms:{antiAliasing:Ds,resolution:Rs,modelViewProjection:po,devicePixelRatio:ks,pointScale:()=>rt(),encodingTex:$s,encodingTexRes:Us,encodingTexEps:Vs,pointOpacityMax:h,pointOpacityScale:E,pointSizeExtra:e,globalState:l,colorTex:Ms,colorTexRes:Bs,colorTexEps:Fs,stateTex:Hs,stateTexRes:Ws,stateTexEps:Gs,isColoredByZ:js,isColoredByW:Ks,isOpacityByZ:qs,isOpacityByW:Xs,isOpacityByDensity:Js,isSizedByZ:Qs,isSizedByW:er,isPixelAligned:tr,colorMultiplicator:nr,opacityMultiplicator:or,opacityDensity:sr,sizeMultiplicator:ir,numColorStates:Ec,drawingBufferWidth:w=>w.drawingBufferWidth,drawingBufferHeight:w=>w.drawingBufferHeight},count:n,primitive:"points"}),ar=It(li,mi,zs),cr=It(li,()=>1,()=>jt,pc,()=>1,()=>1),lr=It(()=>(ze+Ze*2)*window.devicePixelRatio,sn,mo,Co,()=>1,()=>1),dr=It(()=>(ze+Ze)*window.devicePixelRatio,sn,mo,Fi,()=>1,()=>1),ur=It(()=>ze*window.devicePixelRatio,sn,mo,Co,()=>1,()=>1),fr=()=>{lr(),dr(),ur()},mr=a.regl({frag:hc,vert:gc,attributes:{position:[0,1,0,0,1,0,0,1,1,1,1,0]},uniforms:{modelViewProjection:po,texture:Ns},count:6}),hr=a.regl({vert:` + precision mediump float; + uniform mat4 modelViewProjection; + attribute vec2 position; + void main () { + gl_Position = modelViewProjection * vec4(position, 0, 1); + }`,frag:` + precision mediump float; + uniform vec4 color; + void main () { + gl_FragColor = vec4(color.rgb, 0.2); + }`,depth:{enable:!1},blend:{enable:!0,func:{srcRGB:"src alpha",srcAlpha:"one",dstRGB:"one minus src alpha",dstAlpha:"one minus src alpha"}},attributes:{position:()=>Ve},uniforms:{modelViewProjection:po,color:()=>x},elements:()=>nc(Be.getPoints())}),gr=()=>{if(!(le>=0))return;const[e,n]=X[le].slice(0,2),s=[e,n,0,1];at(i,_t,at(i,v.view,pt)),Cn(s,s,i),Ht.setPoints([-1,s[1],1,s[1]]),Wt.setPoints([s[0],1,s[0],-1]),Ht.draw(),Wt.draw(),It(()=>(ze+Ze*2)*window.devicePixelRatio,()=>1,jt,Co)(),It(()=>(ze+Ze)*window.devicePixelRatio,()=>1,jt,Fi)()},hi=e=>{const n=new Float32Array(e*2);let s=0;for(let l=0;l{const s=e.length;ke=Math.max(2,Math.ceil(Math.sqrt(s))),Gn=.5/ke;const l=new Float32Array(ke**2*4);let h=!0,E=!0,w=0,p=0,g=0;for(let M=0;M{if(!tt)return!1;if(xt){const s=nt;nt=ot,s.destroy()}else nt=tt;return ot=gi(e,n),Xo=a.regl.framebuffer({color:ot,depth:!1,stencil:!1}),tt=void 0,!0},pr=()=>!!(nt&&ot),Er=()=>{nt&&(nt.destroy(),nt=void 0),ot&&(ot.destroy(),ot=void 0)},yi=(e,n={})=>new Promise(s=>{pe=!1;const l=n?.preventFilterReset&&e.length===ie;ie=e.length,yt=ie,tt&&tt.destroy(),tt=gi(e,{z:n.zDataType,w:n.wDataType}),l||Zt({usage:"static",type:"float",data:hi(ie)}),Rl(n.spatialIndex||e,{useWorker:Ut}).then(h=>{zn=h,X=e,pe=!0}).then(s)}),pi=(e,n)=>{pn=v.target,En=e,xn=v.distance[0],wn=n},xr=()=>pn!==void 0&&En!==void 0&&xn!==void 0&&wn!==void 0,wr=()=>{pn=void 0,En=void 0,xn=void 0,wn=void 0},Ar=e=>{const n=Oe==="inherit"?u:Oe;if(n==="segment"){const s=te.length-1;return s<1?[]:e.reduce((l,h,E)=>{let w=0;const p=[];for(let M=2;M(h[E]=l(w[s])*4,h),[])}return new Array(Fe.length).fill(0)},Sr=()=>{const e=De==="inherit"?Ae:De;if(e==="segment"){const n=J.length-1;return n<1?[]:Fe.reduce((s,[l,h,E])=>(s[l]=Bi(E,w=>J[Math.floor(w/(E-1)*n)]),s),[])}if(e){const n=Vo(e),s=De==="inherit"?j:J,l=fo(uo(e),s);return Fe.reduce((h,[E,w])=>(h[E]=s[l(w[n])],h),[])}},Ir=()=>{const e=Re==="inherit"?$e:Re;if(e==="segment"){const n=se.length-1;return n<1?[]:Fe.reduce((s,[l,h,E])=>(s[l]=Bi(E,w=>se[Math.floor(w/(E-1)*n)]),s),[])}if(e){const n=Vo(e),s=Re==="inherit"?W:se,l=fo(uo(e),s);return Fe.reduce((h,[E,w])=>(h[E]=s[l(w[n])],h),[])}},Tr=e=>{Fe=[];let n=0;Object.keys(e).forEach((s,l)=>{Fe[s]=[l,e[s].reference,e[s].length/2,n],n+=e[s].length/2})},rn=e=>new Promise(n=>{He.setPoints([]),e?.length>0?(Un=!0,qd(e,{maxIntPointsPerSegment:mt,tolerance:Pt}).then(s=>{Tr(s);const l=Object.values(s);He.setPoints(l.length===1?l[0]:l,{colorIndices:Ar(l),opacities:Sr(),widths:Ir()}),Un=!1,n()})):n()}),Pr=({preventEvent:e=!1}={})=>(U=!1,q.clear(),Zt.subdata(hi(ie)),new Promise(n=>{const s=()=>{o.subscribe("draw",()=>{e||o.publish("unfilter"),n()},1),Z=!0};ye||tn(X[0])?rn(Kn()).then(()=>{e||o.publish("pointConnectionsDraw"),s()}):s()})),Ei=(e,{preventEvent:n=!1}={})=>{U=!0,q.clear();const s=Array.isArray(e)?e:[e],l=[],h=[],E=[];for(const p of s)!Number.isFinite(p)||p<0||p>=ie||(l.push(p),q.add(p),G.has(p)&&E.push(p));const w=Zd([...l]);for(const p of w)h.push.apply(h,In(p));return Zt.subdata(h),Bt(E,{preventEvent:n}),q.has(le)||nn(-1,{preventEvent:n}),new Promise(p=>{const g=()=>{o.subscribe("draw",()=>{n||o.publish("filter",{points:l}),p()},1),Z=!0};ye||tn(X[0])?rn(Kn()).then(()=>{n||o.publish("pointConnectionsDraw"),Bt(E,{preventEvent:n}),g()}):g()})},xi=()=>qn(Yt[0],Yt[1],Gt[0],Gt[1]),Cr=qi(()=>{yt=xi().length},$t),br=e=>{const[n,s]=pn,[l,h]=En,E=1-e,w=n*E+l*e,p=s*E+h*e,g=xn*E+wn*e;v.lookAt([w,p],g)},vr=()=>pr(),Lr=()=>xr(),_r=(e,n)=>{Kt||(Kt=performance.now());const s=performance.now()-Kt,l=kd(n(s/e),0,1);return vr()&&rr({t:l}),Lr()&&br(l),s{xt=!1,Kt=null,Zn=void 0,jn=void 0,Pe=Jo,Er(),wr(),o.publish("transitionEnd")},Eo=({duration:e=500,easing:n=$i})=>{xt&&o.publish("transitionEnd"),xt=!0,Kt=null,Zn=e,jn=Go(n)?Ac[n]||$i:n,Jo=Pe,Pe=!1,o.publish("transitionStart")},Dr=(e,n={})=>qe?Promise.reject(new Error(Ro)):vt?Promise.reject(new Error(Ll)):(vt=!0,zd(e).then(s=>new Promise(l=>{if(qe){l();return}let h=!1;(!n.preventFilterReset||s?.length!==ie)&&(U=!1,q.clear());const E=s&&tn(s[0])&&(ye||n.showPointConnectionsOnce),{zDataType:w,wDataType:p}=n;new Promise(g=>{s?(n.transition&&(s.length===ie?h=yr(s,{z:w,w:p}):console.warn("Cannot transition! The number of points between the previous and current draw call must be identical.")),yi(s,{zDataType:w,wDataType:p,preventFilterReset:n.preventFilterReset,spatialIndex:n.spatialIndex}).then(()=>{n.hover!==void 0&&nn(n.hover,{preventEvent:!0}),n.select!==void 0&&Bt(n.select,{preventEvent:!0}),n.filter!==void 0&&Ei(n.filter,{preventEvent:!0}),E?rn(s).then(()=>{o.publish("pointConnectionsDraw"),Z=!0,Et=n.showReticleOnce}).then(()=>l()):g()})):g()}).then(()=>{n.transition&&h?(E?Promise.all([new Promise(g=>{o.subscribe("transitionEnd",()=>{Z=!0,Et=n.showReticleOnce,g()},1)}),new Promise(g=>{o.subscribe("pointConnectionsDraw",g,1)})]).then(()=>l()):o.subscribe("transitionEnd",()=>{Z=!0,Et=n.showReticleOnce,l()},1),Eo({duration:n.transitionDuration,easing:n.transitionEasing})):(E?Promise.all([new Promise(g=>{o.subscribe("draw",g,1)}),new Promise(g=>{o.subscribe("pointConnectionsDraw",g,1)})]).then(()=>l()):o.subscribe("draw",()=>l(),1),Z=!0,Et=n.showReticleOnce)})}).finally(()=>{vt=!1}))),wi=e=>qe?Promise.reject(new Ro):(Nt=!1,e.length===0?new Promise(n=>{A.clear(),o.subscribe("draw",n,1),Nt=!0,Z=!0}):new Promise(n=>{const s=[],l=new Map,h=[],E=[];let w=-1;const p=g=>{E.push(g.lineWidth||Ke);const M=ge(g.lineColor||bt,!0),fe=`[${M.join(",")}]`;if(l.has(fe)){const{idx:Ee}=l.get(fe);h.push(Ee)}else{const Ee=++w;l.set(fe,{idx:Ee,color:M}),h.push(Ee)}};for(const g of e){if($d(g)){s.push([g.x1??-Ne,g.y,g.x2??Ne,g.y]),p(g);continue}if(Ud(g)){s.push([g.x,g.y1??-Ne,g.x,g.y2??Ne]),p(g);continue}if(Hd(g)){s.push([g.x1,g.y1,g.x2,g.y1,g.x2,g.y2,g.x1,g.y2,g.x1,g.y1]),p(g);continue}if(Vd(g)){s.push([g.x,g.y,g.x+g.width,g.y,g.x+g.width,g.y+g.height,g.x,g.y+g.height,g.x,g.y]),p(g);continue}Wd(g)&&(s.push(g.vertices.flatMap(Qe)),p(g))}A.setStyle({color:Array.from(l.values()).sort((g,M)=>g.idx>M.idx?1:-1).map(({color:g})=>g)}),A.setPoints(s.length===1?s.flat():s,{colorIndices:h,widths:E}),o.subscribe("draw",n,1),Nt=!0,Z=!0})),an=e=>(...n)=>{const s=e(...n);return Z=!0,new Promise(l=>{o.subscribe("draw",()=>l(s),1)})},Rr=e=>{let n=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY,l=Number.POSITIVE_INFINITY,h=Number.NEGATIVE_INFINITY;for(const E of e){const[w,p]=X[E];n=Math.min(n,w),s=Math.max(s,w),l=Math.min(l,p),h=Math.max(h,p)}return{x:n,y:l,width:s-n,height:h-l}},Ai=(e,n={})=>new Promise(s=>{const l=Cn([],[e.x+e.width/2,e.y+e.height/2,0,0],pt).slice(0,2),h=2*Math.atan(1),E=Vt/gn,w=e.height*E>=e.width?e.height/2/Math.tan(h/2):e.width/2/Math.tan(h/2)/E;n.transition?(v.config({isFixed:!0}),pi(l,w),o.subscribe("transitionEnd",()=>{s(),v.config({isFixed:Ue})},1),Eo({duration:n.transitionDuration,easing:n.transitionEasing})):(v.lookAt(l,w),o.subscribe("draw",s,1),Z=!0)}),Nr=(e,n={})=>{if(!pe)return Promise.reject(new Error(Hi));const s=Rr(e),l=s.x+s.width/2,h=s.y+s.height/2,E=ti(),w=1+(n.padding||0),p=Math.max(s.width,E)*w,g=Math.max(s.height,E)*w,M=l-p/2,fe=h-g/2;return Ai({x:M,y:fe,width:p,height:g},n)},Si=(e,n,s={})=>new Promise(l=>{s.transition?(v.config({isFixed:!0}),pi(e,n),o.subscribe("transitionEnd",()=>{l(),v.config({isFixed:Ue})},1),Eo({duration:s.transitionDuration,easing:s.transitionEasing})):(v.lookAt(e,n),o.subscribe("draw",l,1),Z=!0)}),Mr=(e={})=>Si([0,0],1,e),Br=e=>{if(!pe)throw new Error(Hi);const n=X[e];if(!n)return;const s=[n[0],n[1],0,1];at(i,$n,at(i,v.view,pt)),Cn(s,s,i);const l=Te*(s[0]+1)/2,h=Me*(.5-s[1]/2);return[l,h]},xo=()=>{He.setStyle({color:eo(te,ae,ce),opacity:J===null?null:J[0],width:se[0]})},Ii=()=>{const e=Math.round(Lt)>.5?0:255;Q.initiator.style.border=`1px dashed rgba(${e}, ${e}, ${e}, 0.33)`,Q.initiator.style.background=`rgba(${e}, ${e}, ${e}, 0.1)`},Ti=()=>{const e=Math.round(Lt)>.5?0:255;Q.longPressIndicator.style.color=`rgb(${e}, ${e}, ${e})`,Q.longPressIndicator.dataset.color=`rgb(${e}, ${e}, ${e})`;const n=x.map(s=>Math.round(s*255));Q.longPressIndicator.dataset.activeColor=`rgb(${n[0]}, ${n[1]}, ${n[2]})`},Fr=e=>{e&&(B=ge(e,!0),Lt=Zi(B),Ii(),Ti())},kr=e=>{e?Go(e)?Wi(a.regl,e).then(n=>{f=n,Z=!0,o.publish("backgroundImageReady")}).catch(()=>{console.error(`Count not create texture from ${e}`),f=null}):e._reglType==="texture2d"?f=e:f=null:f=null},zr=e=>{e>0&&v.lookAt(v.target,e,v.rotation)},$r=e=>{e!==null&&v.lookAt(v.target,v.distance[0],e)},Ur=e=>{e&&v.lookAt(e,v.distance[0],v.rotation)},Pi=e=>{e&&v.setView(e)},Vr=e=>{Ue=!!e,v.config({isFixed:Ue})},Hr=e=>{if(!e)return;x=ge(e,!0),Be.setStyle({color:x});const n=x.map(s=>Math.round(s*255));Q.longPressIndicator.dataset.activeColor=`rgb(${n[0]}, ${n[1]}, ${n[2]})`},Wr=e=>{Number.isNaN(+e)||+e<1||(T=+e,Be.setStyle({width:T}))},Gr=e=>{+e&&(P=+e,Q.set({minDelay:P}))},Yr=e=>{+e&&(S=+e,Q.set({minDist:S}))},Zr=e=>{C=zo(Sc,C)(e)},jr=e=>{b=!!e,Q.set({enableInitiator:b})},Kr=e=>{R=e,Q.set({initiatorParentElement:R})},qr=e=>{Y=e,Q.set({longPressIndicatorParentElement:Y})},Xr=e=>{H=!!e},Jr=e=>{L=Number(e)},Qr=e=>{z=Number(e)},ea=e=>{$=Number(e)},ta=e=>{de=Number(e)},na=e=>{e==="brush"?Q.set({type:e,minDist:Math.max(Vi,S)}):Q.set({type:e,minDist:S}),me=Q.get("type")},oa=e=>{xe=Number(e)||xe,Q.set({brushSize:xe})},ia=()=>{ue[Nn]?v.config({isRotate:!0,mouseDownMoveModKey:ue[Nn]}):v.config({isRotate:!1})},sa=e=>{ue=Object.entries(e).reduce((n,[s,l])=>(Dc.includes(l)&&Oc.includes(s)&&(n[s]=l),n),{}),ia()},ra=e=>{_e=zo(zi,Ln)(e),v.config({defaultMouseDownMoveAction:_e===Ho?"rotate":"pan"})},aa=e=>{e!==null&&(Pe=e)},ca=e=>{e&&(ne=ge(e,!0),Ht.setStyle({color:ne}),Wt.setStyle({color:ne}))},la=e=>{e&&(he=e,Xt=e.domain()[0],Jt=e?e.domain()[1]-e.domain()[0]:0,he.range([0,Te]),st())},da=e=>{e&&(re=e,Qt=re.domain()[0],en=re?re.domain()[1]-re.domain()[0]:0,re.range([Me,0]),st())},ua=e=>{c=!!e},fa=e=>{y=!!e},ma=e=>{ye=!!e,ye?pe&&tn(X[0])&&rn(Kn()).then(()=>{o.publish("pointConnectionsDraw"),Z=!0}):rn()},wo=(e,n)=>s=>{if(s==="inherit")e([...n()]);else{const l=ut(s)?s:[s];e(l.map(h=>ge(h,!0)))}xo()},ha=wo(e=>{te=e},()=>V),ga=wo(e=>{ae=e},()=>oe),ya=wo(e=>{ce=e},()=>ee),pa=e=>{lt(e,dt,{minLength:1})&&(J=[...e]),vn(+e)&&(J=[+e]),te=te.map(n=>(n[3]=Number.isNaN(+J[0])?n[3]:+J[0],n)),xo()},Ea=e=>{!Number.isNaN(+e)&&+e&&(ft=+e)},xa=e=>{lt(e,dt,{minLength:1})&&(se=[...e]),vn(+e)&&(se=[+e]),xo()},wa=e=>{!Number.isNaN(+e)&&+e&&(Tt=Math.max(0,e))},Aa=e=>{mt=Math.max(0,e)},Sa=e=>{Pt=Math.max(0,e)},Ia=e=>{we=e,ro()},Ta=e=>{switch(e){case"linear":{et=e,rt=ui;break}case"constant":{et=e,rt=di;break}default:{et="asinh",rt=fi;break}}},Pa=e=>{zt=+e},Ca=e=>{Ct=+e},ba=e=>{je=+e},va=e=>{bt=ge(e)},La=e=>{Ke=+e},_a=e=>{Ne=+e},Oa=e=>{a.gamma=e},Ao=e=>{I=Number(e)||.5},So=e=>{_=!!e},Da=e=>{const[n]=Object.keys(Uo({[e]:os}));if(n==="aspectRatio")return gn;if(n==="background"||n==="backgroundColor")return B;if(n==="backgroundImage")return f;if(n==="camera")return v;if(n==="cameraTarget")return v.target;if(n==="cameraDistance")return v.distance[0];if(n==="cameraRotation")return v.rotation;if(n==="cameraView")return v.view;if(n==="cameraIsFixed")return Ue;if(n==="canvas")return r;if(n==="colorBy")return u;if(n==="sizeBy")return $e;if(n==="deselectOnDblClick")return c;if(n==="deselectOnEscape")return y;if(n==="height")return Se;if(n==="lassoColor")return x;if(n==="lassoLineWidth")return T;if(n==="lassoMinDelay")return P;if(n==="lassoMinDist")return S;if(n==="lassoClearEvent")return C;if(n==="lassoInitiator")return b;if(n==="lassoInitiatorElement")return Q.initiator;if(n==="lassoInitiatorParentElement")return R;if(n==="lassoLongPressIndicatorParentElement")return Y;if(n==="lassoOnLongPress")return H;if(n==="lassoType")return me;if(n==="lassoBrushSize")return xe;if(n==="mouseMode")return _e;if(n==="opacity")return j.length===1?j[0]:j;if(n==="opacityBy")return Ae;if(n==="opacityByDensityFill")return zt;if(n==="opacityByDensityDebounceTime")return $t;if(n==="opacityInactiveMax")return Ct;if(n==="opacityInactiveScale")return je;if(n==="points")return X;if(n==="hoveredPoint")return le;if(n==="selectedPoints")return[...O];if(n==="filteredPoints")return U?Array.from(q):Array.from({length:X.length},(s,l)=>l);if(n==="pointsInView")return xi();if(n==="pointColor")return V.length===1?V[0]:V;if(n==="pointColorActive")return oe.length===1?oe[0]:oe;if(n==="pointColorHover")return ee.length===1?ee[0]:ee;if(n==="pointOutlineWidth")return Ze;if(n==="pointSize")return W.length===1?W[0]:W;if(n==="pointSizeSelected")return ze;if(n==="pointSizeMouseDetection")return we;if(n==="showPointConnections")return ye;if(n==="pointConnectionColor")return te.length===1?te[0]:te;if(n==="pointConnectionColorActive")return ae.length===1?ae[0]:ae;if(n==="pointConnectionColorHover")return ce.length===1?ce[0]:ce;if(n==="pointConnectionColorBy")return Oe;if(n==="pointConnectionOpacity")return J.length===1?J[0]:J;if(n==="pointConnectionOpacityBy")return De;if(n==="pointConnectionOpacityActive")return ft;if(n==="pointConnectionSize")return se.length===1?se[0]:se;if(n==="pointConnectionSizeActive")return Tt;if(n==="pointConnectionSizeBy")return Re;if(n==="pointConnectionMaxIntPointsPerSegment")return mt;if(n==="pointConnectionTolerance")return Pt;if(n==="pointScaleMode")return et;if(n==="reticleColor")return ne;if(n==="regl")return a.regl;if(n==="showReticle")return Pe;if(n==="version")return mc;if(n==="width")return Ie;if(n==="xScale")return he;if(n==="yScale")return re;if(n==="performanceMode")return ht;if(n==="renderPointsAsSquares")return gt;if(n==="disableAlphaBlending")return hn;if(n==="gamma")return a.gamma;if(n==="renderer")return a;if(n==="isDestroyed")return qe;if(n==="isDrawing")return vt;if(n==="isPointsDrawn")return pe;if(n==="isPointsFiltered")return U;if(n==="isAnnotationsDrawn")return Nt;if(n==="zDataType")return wt;if(n==="wDataType")return At;if(n==="spatialIndex")return zn?.data;if(n==="annotationLineColor")return bt;if(n==="annotationLineWidth")return Ke;if(n==="annotationHVLineLimit")return Ne;if(n==="antiAliasing")return I;if(n==="pixelAligned")return _;if(n==="actionKeyMap")return{...ue}},Ci=(e={})=>qe?Promise.reject(new Error(Ro)):(Uo(e),(e.backgroundColor!==void 0||e.background!==void 0)&&Fr(e.backgroundColor||e.background),e.backgroundImage!==void 0&&kr(e.backgroundImage),e.cameraTarget!==void 0&&Ur(e.cameraTarget),e.cameraDistance!==void 0&&zr(e.cameraDistance),e.cameraRotation!==void 0&&$r(e.cameraRotation),e.cameraView!==void 0&&Pi(e.cameraView),e.cameraIsFixed!==void 0&&Vr(e.cameraIsFixed),e.colorBy!==void 0&&Cs(e.colorBy),e.pointColor!==void 0&&xs(e.pointColor),e.pointColorActive!==void 0&&ws(e.pointColorActive),e.pointColorHover!==void 0&&As(e.pointColorHover),e.pointSize!==void 0&&ao(e.pointSize),e.pointSizeSelected!==void 0&&Is(e.pointSizeSelected),e.pointSizeMouseDetection!==void 0&&Ia(e.pointSizeMouseDetection),e.sizeBy!==void 0&&vs(e.sizeBy),e.opacity!==void 0&&Ps(e.opacity),e.showPointConnections!==void 0&&ma(e.showPointConnections),e.pointConnectionColor!==void 0&&ha(e.pointConnectionColor),e.pointConnectionColorActive!==void 0&&ga(e.pointConnectionColorActive),e.pointConnectionColorHover!==void 0&&ya(e.pointConnectionColorHover),e.pointConnectionColorBy!==void 0&&Ls(e.pointConnectionColorBy),e.pointConnectionOpacityBy!==void 0&&_s(e.pointConnectionOpacityBy),e.pointConnectionOpacity!==void 0&&pa(e.pointConnectionOpacity),e.pointConnectionOpacityActive!==void 0&&Ea(e.pointConnectionOpacityActive),e.pointConnectionSize!==void 0&&xa(e.pointConnectionSize),e.pointConnectionSizeActive!==void 0&&wa(e.pointConnectionSizeActive),e.pointConnectionSizeBy!==void 0&&Os(e.pointConnectionSizeBy),e.pointConnectionMaxIntPointsPerSegment!==void 0&&Aa(e.pointConnectionMaxIntPointsPerSegment),e.pointConnectionTolerance!==void 0&&Sa(e.pointConnectionTolerance),e.pointScaleMode!==void 0&&Ta(e.pointScaleMode),e.opacityBy!==void 0&&bs(e.opacityBy),e.lassoColor!==void 0&&Hr(e.lassoColor),e.lassoLineWidth!==void 0&&Wr(e.lassoLineWidth),e.lassoMinDelay!==void 0&&Gr(e.lassoMinDelay),e.lassoMinDist!==void 0&&Yr(e.lassoMinDist),e.lassoClearEvent!==void 0&&Zr(e.lassoClearEvent),e.lassoInitiator!==void 0&&jr(e.lassoInitiator),e.lassoInitiatorParentElement!==void 0&&Kr(e.lassoInitiatorParentElement),e.lassoLongPressIndicatorParentElement!==void 0&&qr(e.lassoLongPressIndicatorParentElement),e.lassoOnLongPress!==void 0&&Xr(e.lassoOnLongPress),e.lassoLongPressTime!==void 0&&Jr(e.lassoLongPressTime),e.lassoLongPressAfterEffectTime!==void 0&&Qr(e.lassoLongPressAfterEffectTime),e.lassoLongPressEffectDelay!==void 0&&ea(e.lassoLongPressEffectDelay),e.lassoLongPressRevertEffectTime!==void 0&&ta(e.lassoLongPressRevertEffectTime),e.lassoType!==void 0&&na(e.lassoType),e.lassoBrushSize!==void 0&&oa(e.lassoBrushSize),e.actionKeyMap!==void 0&&sa(e.actionKeyMap),e.mouseMode!==void 0&&ra(e.mouseMode),e.showReticle!==void 0&&aa(e.showReticle),e.reticleColor!==void 0&&ca(e.reticleColor),e.pointOutlineWidth!==void 0&&Ts(e.pointOutlineWidth),e.height!==void 0&&so(e.height),e.width!==void 0&&lo(e.width),e.aspectRatio!==void 0&&Es(e.aspectRatio),e.xScale!==void 0&&la(e.xScale),e.yScale!==void 0&&da(e.yScale),e.deselectOnDblClick!==void 0&&ua(e.deselectOnDblClick),e.deselectOnEscape!==void 0&&fa(e.deselectOnEscape),e.opacityByDensityFill!==void 0&&Pa(e.opacityByDensityFill),e.opacityInactiveMax!==void 0&&Ca(e.opacityInactiveMax),e.opacityInactiveScale!==void 0&&ba(e.opacityInactiveScale),e.gamma!==void 0&&Oa(e.gamma),e.annotationLineColor!==void 0&&va(e.annotationLineColor),e.annotationLineWidth!==void 0&&La(e.annotationLineWidth),e.annotationHVLineLimit!==void 0&&_a(e.annotationHVLineLimit),e.antiAliasing!==void 0&&Ao(e.antiAliasing),e.pixelAligned!==void 0&&So(e.pixelAligned),new Promise(n=>{window.requestAnimationFrame(()=>{qe||!r||(no(),v.refresh(),a.refresh(),Pn(),n())})})),Ra=(e,{preventEvent:n=!1}={})=>{Pi(e),Z=!0,Hn=n},bi=()=>{v||(v=ic(r,{isFixed:Ue,isPanInverted:[!1,!0],defaultMouseDownMoveAction:_e===Ho?"rotate":"pan"})),t.cameraView?v.setView(Mi(t.cameraView)):t.cameraTarget||t.cameraDistance||t.cameraRotation?v.lookAt([...t.cameraTarget||al],t.cameraDistance||cl,t.cameraRotation||ll):v.setView(Mi(dl)),Gt=Xe(1,1),Yt=Xe(-1,-1)},Na=({preventEvent:e=!1}={})=>{bi(),st(),!e&&o.publish("view",{view:v.view,camera:v,xScale:he,yScale:re})},vi=({key:e})=>{e==="Escape"&&y&&Tn()},Li=()=>{Mt=!0,qt=!0},_i=()=>{nn(),Mt=!1,qt=!0,Z=!0},Oi=()=>{Z=!0},Di=()=>{yi([]),He.clear()},Ma=()=>{He.clear()},Ri=()=>{wi([])},Ba=()=>{Di(),Ri()},cn=()=>{const e=Ie===Ye,n=Se===Ye;if(e||n){const{width:s,height:l}=r.getBoundingClientRect();e&&co(s,!0),n&&io(l,!0),no(),st(),Z=!0}v.refresh()},Fa=async e=>{r.style.userSelect="none";const n=window.devicePixelRatio,s=W,l=Ie,h=Se,E=a.canvas.width/n,w=a.canvas.height/n,p=_,g=I,M=e?.scale||1,fe=Array.isArray(W)?W.map(ln=>ln*M):W*M,Ee=Te*M,Io=Me*M;ao(fe),lo(Ee),so(Io),So(e?.pixelAligned||_),Ao(e?.antiAliasing||I),a.resize(Ie,Se),a.refresh(),await new Promise(ln=>{o.subscribe("draw",ln,1),Pn()});const Ft=r.getContext("2d").getImageData(0,0,r.width,r.height);return a.resize(E,w),a.refresh(),ao(s),lo(l),so(h),So(p),Ao(g),await new Promise(ln=>{o.subscribe("draw",ln,1),Pn()}),r.style.userSelect=null,Ft},ka=e=>e===void 0?r.getContext("2d").getImageData(0,0,r.width,r.height):Fa(e),za=()=>{no(),bi(),st(),Be=dn(a.regl,{color:x,width:T,is2d:!0}),He=dn(a.regl,{color:eo(te,ae,ce),opacity:J===null?null:J[0],width:se[0],is2d:!0}),Ht=dn(a.regl,{color:ne,width:1,is2d:!0}),Wt=dn(a.regl,{color:ne,width:1,is2d:!0}),A=dn(a.regl,{color:bt,width:Ke,is2d:!0}),ro(),r.addEventListener("wheel",Oi),Zt=a.regl.buffer(),Yn=a.regl.buffer(),jt=a.regl.buffer({usage:"dynamic",type:"float",length:xc*2}),it=to(),We=Qn();const e=Ci({backgroundImage:f,width:Ie,height:Se,actionKeyMap:ue});Ii(),Ti(),window.addEventListener("keyup",vi,!1),window.addEventListener("blur",ci,!1),window.addEventListener("mouseup",Jn,!1),window.addEventListener("mousemove",ai,!1),r.addEventListener("mousedown",ii,!1),r.addEventListener("mouseenter",Li,!1),r.addEventListener("mouseleave",_i,!1),r.addEventListener("click",si,!1),r.addEventListener("dblclick",ri,!1),"ResizeObserver"in window?(yn=new ResizeObserver(cn),yn.observe(r)):(window.addEventListener("resize",cn),window.addEventListener("orientationchange",cn)),e.then(()=>{o.publish("init")})},$a=a.onFrame(()=>{if(An=v.tick(),!((pe||Nt)&&(Z||xt)))return;xt&&!_r(Zn,jn)&&Or(),An&&(Gt=Xe(1,1),Yt=Xe(-1,-1),Ae==="density"&&Cr()),a.render(()=>{const n=r.width/a.canvas.width,s=r.height/a.canvas.height;ps(n,s),f?._reglType&&mr(),Ve.length>2&&hr(),xt||He.draw({projection:ho(),model:yo(),view:go()});const l=mi();pe&&l>0&&ar(),!D&&(Pe||Et)&&gr(),le>=0&&cr(),O.length>0&&fr(),A.draw({projection:ho(),model:yo(),view:go()}),Be.draw({projection:ho(),model:yo(),view:go()})},r);const e={view:v.view,isViewChanged:An,camera:v,xScale:he,yScale:re};An&&(st(),Hn?Hn=!1:o.publish("view",e)),Z=!1,Et=!1,o.publish("drawing",e,{async:!1}),o.publish("draw",e)}),Pn=()=>{Z=!0},Ua=()=>{pe=!1,Nt=!1,qe=!0,$a(),window.removeEventListener("keyup",vi,!1),window.removeEventListener("blur",ci,!1),window.removeEventListener("mouseup",Jn,!1),window.removeEventListener("mousemove",ai,!1),r.removeEventListener("mousedown",ii,!1),r.removeEventListener("mouseenter",Li,!1),r.removeEventListener("mouseleave",_i,!1),r.removeEventListener("click",si,!1),r.removeEventListener("dblclick",ri,!1),r.removeEventListener("wheel",Oi,!1),yn?yn.disconnect():(window.removeEventListener("resize",cn),window.removeEventListener("orientationchange",cn)),r=void 0,v.dispose(),v=void 0,Be.destroy(),Q.destroy(),He.destroy(),Ht.destroy(),Wt.destroy(),it&&it.destroy(),We&&We.destroy(),t.renderer||a.isDestroyed||a.destroy(),o.publish("destroy"),o.clear()};return za(),{get isSupported(){return a.isSupported},clear:an(Ba),clearPoints:an(Di),clearPointConnections:an(Ma),clearAnnotations:an(Ri),createTextureFromUrl:(e,n=qo)=>Wi(a.regl,e,n),deselect:Tn,destroy:Ua,draw:Dr,drawAnnotations:wi,filter:Ei,get:Da,getScreenPosition:Br,hover:nn,lassoSelect:ms,redraw:Pn,refresh:a.refresh,reset:an(Na),select:Bt,set:Ci,export:ka,subscribe:o.subscribe,unfilter:Pr,unsubscribe:o.unsubscribe,view:Ra,zoomToLocation:Si,zoomToArea:Ai,zoomToPoints:Nr,zoomToOrigin:Mr}};class ji extends dc{constructor(o,i){super({...i,view:new Xd(o,{props:i.props,viewProps:i.viewProps})})}}class Xd{constructor(o,{props:i,viewProps:m}){this.element=o.createElement("div"),this.element.classList.add("tp-link"),m.bindClassModifiers(this.element);const d=o.createElement("a");m.bindDisabled(d);function a(f){d.href=f??""}function I(f){d.textContent=f??""}function _(f){f?(d.classList.add("active"),d.removeAttribute("href"),d.removeAttribute("target")):(d.classList.remove("active"),a(i.get("link")),B(i.get("newPage")))}function B(f){f?d.target="_blank":d.removeAttribute("target")}bn(i.value("link"),a),bn(i.value("label"),I),bn(i.value("active"),_),bn(i.value("newPage"),B),this.element.appendChild(d),this.linkElement=d}}class Jd extends uc{get label(){return this.controller.props.get("label")??""}set label(o){this.controller.props.set("label",o)}get link(){return this.controller.props.get("link")}set link(o){this.controller.props.set("link",o)}get active(){return this.controller.props.get("active")}set active(o){this.controller.props.set("active",!!o)}get newPage(){return this.controller.props.get("newPage")}set newPage(o){this.controller.props.set("newPage",!!o)}}const Qd=ac({id:"link",type:"blade",accept(t){const o=lc(t,i=>({view:i.required.constant("link"),link:i.required.string,label:i.required.string,active:i.optional.boolean,newPage:i.optional.boolean}));return o?{params:o}:null},controller(t){return new ji(t.document,{blade:t.blade,props:cc.fromObject({label:t.params.label,link:t.params.link,active:t.params.active,newPage:t.params.newPage}),viewProps:t.viewProps})},api(t){return t.controller instanceof ji?new Jd(t.controller):null}});function eu(t,o="file.txt"){const i=document.createElement("a");i.href=URL.createObjectURL(t),i.download=o,document.body.appendChild(i),i.dispatchEvent(new MouseEvent("click",{bubbles:!0,cancelable:!0,view:window})),document.body.removeChild(i)}function tu(t){const o=new Image;o.onload=()=>{t.get("canvas").toBlob(i=>{eu(i,"regl-scatterplot.png")})},o.src=t.get("canvas").toDataURL()}function nu(){const t=document.querySelector("#modal"),o=document.querySelector("#modal-text");t.style.display="none",o.textContent=""}function ou(t,o,i){const m=document.querySelector("#modal");m.style.display="flex";const d=document.querySelector("#modal-text");d.style.color=o?"#cc79A7":"#bbb",d.textContent=t;const a=document.querySelector("#modal-close");i?(a.style.display="block",a.style.background=o?"#cc79A7":"#bbb",a.addEventListener("click",nu,{once:!0})):a.style.display="none"}function cu(t){t.isSupported||ou("Your browser does not support all necessary WebGL features. The scatter plot might not render properly.",!0,!0)}const iu={numPoints:1e5,pointSize:2,opacity:.33,opacityByDensity:!1,lassoInit:"longPress",lassoType:"freeform",lassoBrushSize:24},Je=(t,o)=>{if(Array.isArray(t))for(const i of t)i.set(o);else t.set(o)};function lu({scatterplot:t,setNumPoints:o,setPointSize:i,setOpacity:m,opacityChangesDisabled:d}){let a=!1;const I=Array.isArray(t)?t[0]:t,_={...iu,numPoints:0,pointSize:Array.isArray(I.get("pointSize"))?I.get("pointSize")[0]:I.get("pointSize"),opacity:I.get("opacity"),opacityByDensity:I.get("opacityBy")==="density",lassoType:I.get("lassoType"),lassoBrushSize:I.get("lassoBrushSize")},B={..._},f=new fc({title:"Details",container:document.getElementById("controls")});f.registerPlugin({id:"link",plugins:[Qd]});const r=f.addFolder({title:"Settings"}),u=r.addBinding(_,"numPoints",{label:"Num Points",min:1e3,step:1e3,max:2e6});u.disabled=!0,o&&u.on("change",({last:z,value:$})=>{a&&z&&o($)});const c=r.addBinding(_,"pointSize",{label:"Point Size",min:1,max:32,step:1});c.disabled=Array.isArray(I.get("pointSize")),c.on("change",({value:z})=>{i?i(z):Je(t,{pointSize:z})});const y=r.addBinding(_,"opacity",{label:"Opacity",min:.01,max:1,step:.01});y.disabled=_.opacityByDensity||!!d,y.on("change",({value:z})=>{m?m(z):Je(t,{opacity:z})});const x=r.addBinding(_,"opacityByDensity",{label:"Dynamic Opacity"});x.disabled=!!d,x.on("change",({value:z})=>{Je(t,{opacityBy:z?"density":null}),y.disabled=z}),r.addBinding(_,"lassoInit",{label:"Lasso Init",options:{"On Long Press":"longPress","Via Click Initiator":"clickInitiator"}}).on("change",({value:z})=>{switch(z){case"longPress":{Je(t,{lassoInitiator:!1,lassoOnLongPress:!0});break}case"clickInitiator":{Je(t,{lassoInitiator:!0,lassoOnLongPress:!1});break}}}),r.addBinding(_,"lassoType",{label:"Lasso Type",options:{Freeform:"freeform",Brush:"brush",Rectangle:"rectangle"}}).on("change",({value:z})=>{switch(z){case"freeform":{Je(t,{lassoType:"freeform"});break}case"brush":{Je(t,{lassoType:"brush"});break}case"rectangle":{Je(t,{lassoType:"rectangle"});break}}S.hidden=z!=="brush"});const S=r.addBinding(_,"lassoBrushSize",{label:"Brush Size",min:1,max:256,step:1});S.hidden=_.lassoType!=="brush",S.on("change",({value:z})=>{Je(t,{lassoBrushSize:z})}),r.addButton({title:"Reset"}).on("click",()=>{for(const[z,$]of Object.entries(B))_[z]=$;f.refresh()});const b=f.addFolder({title:"Examples"}),R=window.location.pathname.slice(1);b.addBlade({view:"link",label:"Color Encoding",link:"index.html",active:R===""||R==="index.html"}),b.addBlade({view:"link",label:"Size & Opacity Encoding",link:"size-encoding.html",active:R==="size-encoding.html"}),b.addBlade({view:"link",label:"Dynamic Opacity",link:"dynamic-opacity.html",active:R==="dynamic-opacity.html"}),b.addBlade({view:"link",label:"Axes",link:"axes.html",active:R==="axes.html"}),b.addBlade({view:"link",label:"Text Labels",link:"text-labels.html",active:R==="text-labels.html"}),b.addBlade({view:"link",label:"Annotations",link:"annotations.html",active:R==="annotations.html"}),b.addBlade({view:"link",label:"Programmatic Lasso",link:"programmatic-lasso.html",active:R==="programmatic-lasso.html"}),b.addBlade({view:"link",label:"Multiple Instances",link:"multiple-instances.html",active:R==="multiple-instances.html"}),b.addBlade({view:"link",label:"Transition",link:"transition.html",active:R==="transition.html"}),b.addBlade({view:"link",label:"Point Connections",link:"connected-points.html",active:R==="connected-points.html"}),b.addBlade({view:"link",label:"Point Connections by Line Segments",link:"connected-points-by-segments.html",active:R==="connected-points-by-segments.html"}),b.addBlade({view:"link",label:"Background Image",link:"texture-background.html",active:R==="texture-background.html"}),b.addBlade({view:"link",label:"Performance Mode (20M Points)",link:"performance-mode.html",active:R==="performance-mode.html"}),f.addFolder({title:"Info",expanded:!1}).addBlade({view:"text",label:"version",parse:z=>String(z),value:I.get("version"),disabled:!0}),f.addButton({title:"Download as PNG"}).on("click",()=>{tu(t)}),f.addButton({title:"Source Code"}).on("click",()=>{window.open("https://github.com/flekschas/regl-scatterplot","_blank").focus()}),I.subscribe("draw",()=>{_.numPoints=I.get("points").length,B.numPoints=_.numPoints,o&&(u.disabled=!1),f.refresh(),a=!0},1)}export{cu as a,lu as b,au as c,ou as d,nu as e,jd as f,tu as s}; diff --git a/assets/multiple-instances-DSFad-2K.js b/assets/multiple-instances-DSFad-2K.js new file mode 100644 index 00000000..3bac6a40 --- /dev/null +++ b/assets/multiple-instances-DSFad-2K.js @@ -0,0 +1,4 @@ +import{d as m,f as S,c as b,b as C,e as v}from"./menu-CKBxhbUC.js";import{t as E}from"./apache-arrow-Bq3lZMkH.js";import"./vendor-DRFCw67i.js";const u=2,F=2,w=3,I=.66,A=["T-shirt/top","Trouser","Pullover","Dress","Coat","Sandal","Shirt","Sneaker","Bag","Ankle boot"],p=["#FFFF00","#1CE6FF","#FF34FF","#FF4A46","#008941","#006FA6","#A30059","#FFDBE5","#7A4900","#0000A6"],N=fetch("https://storage.googleapis.com/flekschas/regl-scatterplot/fashion-mnist-embeddings.arrow");m("Loading...");const k=document.querySelector("#footer");k.classList.remove("hidden");const M=document.querySelector("#info-content");M.innerHTML=` +

Fashion MNIST embedding using four different techniques: PCA, t-SNE, UMAP, and a convolutional autoencoder.

+

Select a point so see the corresponding image.

+`;const l=document.querySelector("#parent-wrapper"),s=document.createElement("div");s.id="note";s.style.opacity=0;l.appendChild(s);const L=(t,e)=>{s.style.opacity=1,s.style.background=e,s.textContent=t},T=()=>{s.style.opacity=0},a=document.createElement("div");a.id="center-note";a.style.opacity=0;const i=document.createElement("div");i.style.width="56px";i.style.height="56px";i.style.backgroundColor="black";i.style.backgroundSize="cover";i.style.backgroundRepeat="no-repeat";a.appendChild(i);l.appendChild(a);const O=(t,e)=>String(t).padStart(e,"0"),z=(t,e)=>{const n=new Image,r=`https://storage.googleapis.com/flekschas/regl-scatterplot/fashion-mnist-images/${O(t,5)}.png`;n.onload=()=>{a.style.opacity=1,a.style.transform="translate(-50%, -50%) scale(1)",i.style.backgroundImage=`url("${r}")`,a.style.background=p[e]},n.src=r},_=()=>{a.style.opacity=0,a.style.transform="translate(-50%, -50%) scale(0)"};l.style.display="grid";l.style.gridTemplateColumns=`repeat(${u}, minmax(0, 1fr))`;l.style.gridTemplateRows="repeat(2, minmax(0, 1fr))";l.style.gap="1rem";const g=document.querySelector("#canvas"),h=document.querySelector("#canvas-wrapper");h.style.position="relative";const y=[g];for(let t=0;tb({renderer:f,canvas:t,pointSize:w,opacity:I,lassoOnLongPress:!0}));console.log(`Scatterplot v${c[0].get("version")}`);C({scatterplot:c});const q=(t,e,n)=>{c.filter(r=>r!==t).forEach(r=>{r.select(e,{preventEvent:!0})}),c.forEach(r=>{r.zoomToPoints(e,{padding:.2,transition:!0,transitionDuration:1500})});const o=e[Math.floor(Math.random()*(e.length-1))];z(o,n[o])},x=t=>{c.filter(e=>e!==t).forEach(e=>{e.deselect({preventEvent:!0})}),c.forEach(e=>{e.zoomToOrigin({transition:!0,transitionDuration:1500})}),_()};N.then(t=>E(t)).then(t=>{v();const e=t.data[0].children.map(o=>o.values),n=e[e.length-1];c.forEach((o,r)=>{o.draw({x:e[r*2],y:e[r*2+1],z:n}),o.set({colorBy:"z",pointColor:p}),o.subscribe("pointover",d=>{L(A[n[d]],p[n[d]])}),o.subscribe("pointout",T),o.subscribe("select",({points:d})=>q(o,d,n)),o.subscribe("deselect",()=>x(o))})}).catch(t=>{m("Could not load embedding... Damn...",!0),console.error(t)}); diff --git a/assets/performance-mode-9wJvbjTm.js b/assets/performance-mode-9wJvbjTm.js new file mode 100644 index 00000000..0f04ddfb --- /dev/null +++ b/assets/performance-mode-9wJvbjTm.js @@ -0,0 +1,4 @@ +import{c as $,a as T,s as V,b as A}from"./menu-CKBxhbUC.js";import{f as D}from"./vendor-DRFCw67i.js";const B=function(){self.onmessage=function(p){const c=p.data,d=10;try{let a=[];const u=2/d,w=c/d**2;for(let m=0;mr[0]-h[0]||r[1]-h[1]))}self.postMessage({points:a})}catch(a){self.postMessage({error:a})}}},E=document.querySelector("#modal"),b=document.querySelector("#modal span"),W=document.querySelector("#canvas"),v=document.querySelector("#num-points"),k=document.querySelector("#num-points-value"),q=document.querySelector("#point-size"),j=document.querySelector("#point-size-value"),H=document.querySelector("#opacity"),F=document.querySelector("#opacity-value"),L=document.querySelector("#click-lasso-initiator"),G=document.querySelector("#reset"),N=document.querySelector("#export"),x=document.querySelector("#example-performance-mode");x.setAttribute("class","active");x.removeAttribute("href");let y=[],n=2e7,s=.25,l=.33,i=[];const O=10,R=2,M=D(B),X=e=>new Promise((o,p)=>{M.onmessage=c=>{c.data.error?p(c.data.error):o(c.data.points)},M.postMessage(e)}),Y=e=>{E.style.display="flex",b.textContent=e},J=()=>{E.style.display="none",b.textContent=""},K=({points:e})=>{if(console.log("Selected:",e),i=e,i.length===1){const o=y[i[0]];console.log(`X: ${o[0]} +Y: ${o[1]} +Category: ${o[2]} +Value: ${o[3]}`)}},Q=()=>{console.log("Deselected:",i),i=[]},t=$({canvas:W,lassoMinDelay:O,lassoMinDist:R,pointSize:s,showReticle:!0,performanceMode:!0,lassoInitiator:!0});T(t);N.addEventListener("click",()=>V(t));console.log(`Scatterplot v${t.get("version")}`);t.subscribe("select",K);t.subscribe("deselect",Q);const S=e=>{Y(`Hang tight. Generating ${(n/1e6).toFixed(1)} million points...`),n=e,v.value=n,k.innerHTML=n,X(n).then(o=>{y=o,t.draw(y),J()})};A({scatterplot:t,setNumPoints:S});const U=e=>{k.innerHTML=`${+e.target.value} release to redraw`};v.addEventListener("input",U);const Z=e=>S(+e.target.value);v.addEventListener("change",Z);const P=e=>{s=e,q.value=s,j.innerHTML=s,t.set({pointSize:s})},_=e=>P(+e.target.value);q.addEventListener("input",_);const I=e=>{l=e,H.value=l,F.innerHTML=l,t.set({opacity:l})},ee=e=>I(+e.target.value);H.addEventListener("input",ee);const te=e=>{t.set({lassoInitiator:e.target.checked})};L.addEventListener("change",te);L.checked=t.get("lassoInitiator");const oe=()=>{t.reset()};G.addEventListener("click",oe);const ne=["#002072","#162b79","#233680","#2e4186","#394d8d","#425894","#4b649a","#5570a1","#5e7ca7","#6789ae","#7195b4","#7ba2ba","#85aec0","#90bbc6","#9cc7cc","#a9d4d2","#b8e0d7","#c8ecdc","#ddf7df","#ffffe0"];t.set({colorBy:"value",pointColor:ne});P(s);I(l);S(n); diff --git a/assets/programmatic-lasso-jbmzmB02.js b/assets/programmatic-lasso-jbmzmB02.js new file mode 100644 index 00000000..adb31b88 --- /dev/null +++ b/assets/programmatic-lasso-jbmzmB02.js @@ -0,0 +1,23 @@ +import{c as z,a as A,b as E}from"./menu-CKBxhbUC.js";import{l as C,a as I,b as P,s as $}from"./d3-IoKfXBi0.js";import"./vendor-DRFCw67i.js";const f=document.querySelector("#parent-wrapper"),x=document.querySelector("#canvas-wrapper"),B=document.querySelector("#canvas"),s=document.createElement("div");s.style.cssText=` + position: absolute; + top: 10px; + left: 10px; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 6px; + max-width: 400px; + max-height: calc(100vh - 20px); + overflow-y: auto; + z-index: 1000; +`;f.appendChild(s);const L=[0,100],D=[0,100],w=C().domain(L),M=C().domain(D),p=I(w),u=P(M),c=$(f).append("svg"),m=c.append("g"),y=c.append("g"),q=20,H=40;c.node().style.position="absolute";c.node().style.top=0;c.node().style.left=0;c.node().style.width="100%";c.node().style.height="100%";c.node().style.pointerEvents="none";x.style.right=`${H}px`;x.style.bottom=`${q}px`;let{width:h,height:g}=x.getBoundingClientRect();m.attr("transform",`translate(0, ${g})`).call(p);y.attr("transform",`translate(${h}, 0)`).call(u);p.tickSizeInner(-g);u.tickSizeInner(-h);let v=[],N=5e3,T=4,W=.66;const j=({points:n})=>{console.log("Selected:",n.length,"points")},F=()=>{console.log("Deselected")},e=z({canvas:B,pointSize:T,opacity:W,xScale:w,yScale:M,showReticle:!0,lassoInitiator:!0,pointColor:[.33,.5,1,1],pointColorActive:[1,.5,0,1]});A(e);console.log(`Scatterplot v${e.get("version")}`);e.subscribe("select",j);e.subscribe("deselect",F);e.subscribe("view",n=>{m.call(p.scale(n.xScale)),y.call(u.scale(n.yScale))});e.subscribe("init",()=>{m.call(p.scale(e.get("xScale"))),y.call(u.scale(e.get("yScale")))},1);const R=()=>{({width:h,height:g}=x.getBoundingClientRect()),m.attr("transform",`translate(0, ${g})`).call(p),y.attr("transform",`translate(${h}, 0)`).call(u),p.tickSizeInner(-g),u.tickSizeInner(-h)};window.addEventListener("resize",R);window.addEventListener("orientationchange",R);const G=n=>{const l=[];for(let i=0;i{v=G(n),e.draw(v)};E({scatterplot:e,setNumPoints:k});e.set({colorBy:"category",pointColor:["#3a84cc","#56bf92","#eecb62","#c76526","#d192b7"]});const r=(n,l,i=!1)=>{const t=document.createElement("button");return t.textContent=n,t.style.cssText=` + padding: 6px 10px; + background: #3a84cc; + color: white; + border: none; + border-radius: 3px; + cursor: pointer; + font-size: 11px; + white-space: nowrap; + text-align: center; + ${i?"grid-column: 1 / -1;":""} + `,t.addEventListener("mouseenter",()=>{t.style.background="#2a6cb0"}),t.addEventListener("mouseleave",()=>{t.style.background="#3a84cc"}),t.addEventListener("click",l),t};s.appendChild(r("△ Bottom-Left",()=>{e.lassoSelect([[10,10],[40,10],[10,40]])}));s.appendChild(r("○ Top-Right",()=>{const d=[];for(let a=0;a<16;a++){const o=a/16*Math.PI*2;d.push([75+Math.cos(o)*20,75+Math.sin(o)*20])}e.lassoSelect(d)}));s.appendChild(r("▭ Center",()=>{e.lassoSelect([[30,30],[70,30],[70,70],[30,70]])}));s.appendChild(r("+ Diagonal (Merge)",()=>{e.lassoSelect([[0,40],[60,100],[70,100],[10,40]],{merge:!0})}));s.appendChild(r("− Center (Remove)",()=>{e.lassoSelect([[40,40],[60,40],[60,60],[40,60]],{remove:!0})}));s.appendChild(r("★ Star",()=>{const a=[];for(let o=0;o<10;o++){const b=o/10*Math.PI*2-Math.PI/2,S=o%2===0?30:15;a.push([50+Math.cos(b)*S,50+Math.sin(b)*S])}e.lassoSelect(a)}));s.appendChild(r("✕ Deselect All",()=>{e.deselect()},!0));k(N); diff --git a/assets/size-encoding-DoLghy6x.js b/assets/size-encoding-DoLghy6x.js new file mode 100644 index 00000000..0a2521e8 --- /dev/null +++ b/assets/size-encoding-DoLghy6x.js @@ -0,0 +1,4 @@ +import{c as u,a as M,b as S}from"./menu-CKBxhbUC.js";import{r as l,c as w}from"./d3-IoKfXBi0.js";import"./vendor-DRFCw67i.js";const v=document.querySelector("#canvas");let r=[],A=1e5,m=2,p=1,a=[];const b=10,z=2,$=!0,B=[1,1,.878431373,.33],C=({points:t})=>{if(console.log("Selected:",t),a=t,a.length===1){const e=r[a[0]];console.log(`X: ${e[0]} +Y: ${e[1]} +Category: ${e[2]} +Value: ${e[3]}`)}},I=()=>{console.log("Deselected:",a),a=[]},o=u({canvas:v,lassoMinDelay:b,lassoMinDist:z,pointSize:m,opacity:p,showReticle:$,reticleColor:B,lassoInitiator:!0,opacityInactiveScale:.66});M(o);console.log(`Scatterplot v${o.get("version")}`);o.subscribe("select",C);o.subscribe("deselect",I);const P=l(2),R=l(4),x=l(5),D=t=>{const e=[...new Array(Math.round(t*2/12)).fill().map(()=>[-1+Math.random()*2*1/3,-1+Math.random()*2,0,P()]),...new Array(Math.round(t*4/12)).fill().map(()=>[-.33333333333333337+Math.random()*2*1/3,-1+Math.random()*2,1,R()]),...new Array(Math.round(t*6/12)).fill().map(()=>[.33333333333333326+Math.random()*2*1/3,-1+Math.random()*2,2,x()])],[n,s]=e.reduce(([c,f],i)=>[Math.min(c,i[3]),Math.max(f,i[3])],[1/0,-1/0]),h=s-n;return e.forEach(c=>{c[3]=(c[3]-n)/h}),e},d=t=>{r=D(t),o.draw(r)},V=t=>{const e=w().domain([1,10]).range([t,t*10]);return Array.from({length:100},(n,s)=>e(1+s/99*9))},y=t=>{o.set({pointSize:V(t)})},E=t=>Array.from({length:10},(e,n)=>(n+1)/10*t),g=t=>{o.set({opacity:E(t)})};S({scatterplot:o,setNumPoints:d,setPointSize:y,setOpacity:g});o.set({colorBy:"category",pointColor:["#ff80cb","#57c7ff","#eee462"],sizeBy:"w",opacityBy:"w"});y(m);g(p);d(A); diff --git a/assets/text-labels-CHxXQtMx.js b/assets/text-labels-CHxXQtMx.js new file mode 100644 index 00000000..8c78b67d --- /dev/null +++ b/assets/text-labels-CHxXQtMx.js @@ -0,0 +1,4 @@ +import{c as b,a as P,b as R}from"./menu-CKBxhbUC.js";import{l as h,c as C}from"./d3-IoKfXBi0.js";import"./vendor-DRFCw67i.js";const d=document.querySelector("#canvas"),p=document.querySelector("#canvas-wrapper"),g=document.createElement("div");g.id="note";g.textContent="Zoom in to see labels!";p.appendChild(g);const e=document.createElement("canvas");e.id="#text-overlay";e.style.position="absolute";e.style.top=0;e.style.right=0;e.style.bottom=0;e.style.left=0;e.style.pointerEvents="none";p.appendChild(e);const y=()=>{const{width:t,height:o}=p.getBoundingClientRect();e.width=t*window.devicePixelRatio,e.height=o*window.devicePixelRatio,e.style.width=`${t}px`,e.style.height=`${o}px`};y();window.addEventListener("resize",y);const m=12,s=e.getContext("2d");s.font=`${m*window.devicePixelRatio}px sans-serif`;s.textAlign="center";let r=[],$=1e4,w=4,u=1,a=[];const z=200,E=10,M=2,O=!0,A=[1,1,.878431373,.33],n=b({canvas:d,lassoMinDelay:E,lassoMinDist:M,pointSize:w,opacity:u,showReticle:O,reticleColor:A,xScale:h().domain([-1,1]),yScale:h().domain([-1,1]),pointColor:"#fff",opacityBy:"density",lassoInitiator:!0});P(n);console.log(`Scatterplot v${n.get("version")}`);n.subscribe("select",({points:t})=>{if(console.log("Selected:",t),a=t,a.length===1){const o=r[a[0]];console.log(`X: ${o[0]} +Y: ${o[1]} +Category: ${o[2]} +Value: ${o[3]}`)}});n.subscribe("deselect",()=>{a=[]});const L=(t,o,i)=>{s.clearRect(0,0,e.width,e.height),s.fillStyle="rgb(255, 255, 255)";const l=window.devicePixelRatio;for(let c=0;c{s.clearRect(0,0,d.width,d.height)};n.subscribe("drawing",({xScale:t,yScale:o})=>{const i=n.get("pointsInView");i.length<=z?L(i,t,o):q()});const B=t=>Array.from({length:t},()=>[-1+Math.random()*2,-1+Math.random()*2]),v=t=>{r=B(t),n.draw(r)},D=t=>{const o=C().domain([1,10]).range([t,t*10]);return Array.from({length:100},(i,l)=>o(1+l/99*9))},x=t=>{n.set({pointSize:D(t)})},T=t=>Array.from({length:10},(o,i)=>(i+1)/10*t),_=t=>{n.set({opacity:T(t)})};R({scatterplot:n,setNumPoints:v,setPointSize:x});x(w);_(u);v($); diff --git a/assets/texture-background-e5Fn1Ihg.js b/assets/texture-background-e5Fn1Ihg.js new file mode 100644 index 00000000..d0b1199e --- /dev/null +++ b/assets/texture-background-e5Fn1Ihg.js @@ -0,0 +1,4 @@ +import{c as l,a as r,b as i}from"./menu-CKBxhbUC.js";import"./vendor-DRFCw67i.js";const s=document.querySelector("#canvas"),{width:p,height:d}=s.getBoundingClientRect();let a=[],m=1e5,h=3,u=1,o=[];const g=({points:e})=>{if(console.log("Selected:",e),o=e,o.length===1){const n=a[o[0]];console.log(`X: ${n[0]} +Y: ${n[1]} +Category: ${n[2]} +Value: ${n[3]}`)}},M=()=>{console.log("Deselected:",o),o=[]},t=l({canvas:s,pointSize:h,opacity:u,showReticle:!0,backgroundImage:`https://picsum.photos/${Math.min(640,p)}/${Math.min(640,d)}/?random`,lassoInitiator:!0});r(t);console.log(`Scatterplot v${t.get("version")}`);t.subscribe("select",g);t.subscribe("deselect",M);const $=e=>new Array(e).fill().map(()=>[-1+Math.random()*2,-1+Math.random()*2,Math.round(Math.random()),Math.random()]),c=e=>{a=$(e),t.draw(a)};i({scatterplot:t,setNumPoints:c});t.set({colorBy:"category",pointColor:["#3a78aa","#aa3a99"]});c(m); diff --git a/assets/transition-B9gcaZDL.js b/assets/transition-B9gcaZDL.js new file mode 100644 index 00000000..3d23517a --- /dev/null +++ b/assets/transition-B9gcaZDL.js @@ -0,0 +1,3 @@ +import{d as p,c as h,a as u,b as g,e as F}from"./menu-CKBxhbUC.js";import{t as d}from"./apache-arrow-Bq3lZMkH.js";import"./vendor-DRFCw67i.js";const m=["#FFFF00","#1CFFD9","#FF34FF","#FF4A46","#008941","#1966FF","#C00069","#FFDBE5","#FF9900","#8148D5"],y=fetch("https://storage.googleapis.com/flekschas/regl-scatterplot/cities.arrow");p("Loading...");const w=document.querySelector("#footer");w.classList.remove("hidden");const f=document.querySelector("#info-content");f.innerHTML=` +

GeoNames – Cities Dataset visualized in three: by the cities' geographic location, by the total population across contintents, and by the citie's latitude distribution.

+`;const C=document.querySelector("#canvas");let S=1.5;const e=h({canvas:C,pointSize:S,lassoOnLongPress:!0});u(e);console.log(`Scatterplot v${e.get("version")}`);g({scatterplot:e,opacityChangesDisabled:!0});y.then(a=>d(a)).then(a=>{F();const o=a.data[0].children.map(t=>t.values),n=o[o.length-2],r=o[o.length-1],s=new Float32Array(n.length);for(let t=0;t.33+l/9*.33)});let i=0;const c=()=>{i++;const t=i%3*2;e.draw({x:o[t],y:o[t+1],z:r,w:[n,s,s][i%3]},{transition:!0,transitionDuration:750,transitionEasing:"quadInOut"}).then(()=>{setTimeout(c,2500)})};setTimeout(c,2500)}); diff --git a/assets/vendor-DRFCw67i.js b/assets/vendor-DRFCw67i.js new file mode 100644 index 00000000..27b56e31 --- /dev/null +++ b/assets/vendor-DRFCw67i.js @@ -0,0 +1,91 @@ +const j1=r=>r*r*r,U1=r=>r<.5?4*r*r*r:(r-1)*(2*r-2)*(2*r-2)+1,z1=r=>--r*r*r+1,H1=r=>r,K1=r=>r*r,q1=r=>r<.5?2*r*r:-1+(4-2*r)*r,X1=r=>r*(2-r),n_=r=>r,Y1=(r,e)=>{if(r===e)return!0;if(r.length!==e.length)return!1;const t=new Set(r),n=new Set(e);return t.size!==n.size?!1:e.every(i=>t.has(i))},W1=r=>Math.sqrt(r.reduce((e,t)=>e+t**2,0)),Z1=r=>r.reduce((e,t)=>t>e?t:e,Number.NEGATIVE_INFINITY),Q1=(r,e=n_)=>{const t=[];for(let n=0;n{const t=[];return r.forEach(n=>{t[n]=!0}),e.forEach(n=>{t[n]=!0}),t.reduce((n,i,s)=>(i&&n.push(s),n),[])},Nh=(r,...e)=>(e.forEach(t=>{const n=Object.keys(t).reduce((i,s)=>(i[s]=Object.getOwnPropertyDescriptor(t,s),i),{});Object.getOwnPropertySymbols(t).forEach(i=>{const s=Object.getOwnPropertyDescriptor(t,i);s?.enumerable&&(n[i]=s)}),Object.defineProperties(r,n)}),r);function eP(...r){return e=>r.reduce((t,n)=>n(t),e)}const tP=r=>e=>Nh({__proto__:{constructor:r}},e),rP=(r,e)=>t=>Nh(t,{get[r](){return e}}),nP=(r,e,t,n)=>Math.sqrt((r-t)**2+(e-n)**2),iP=r=>new Worker(window.URL.createObjectURL(new Blob([`(${r.toString()})()`],{type:"text/javascript"}))),sP=(r=1)=>new Promise(e=>{let t=0;const n=()=>requestAnimationFrame(()=>{t++,t{let n,i=0;t=t===null?e:t;const s=(...y)=>{const x=()=>{i>0&&(r(...y),i=0)};clearTimeout(n),n=setTimeout(x,t)};let o=!1;const l=(...y)=>{o?(i++,s(...y)):(r(...y),s(...y),o=!0,i=0,setTimeout(()=>{o=!1},e))};return l.reset=()=>{o=!1},l.cancel=()=>{clearTimeout(n)},l.now=(...y)=>r(...y),l};var i_=1e-6,Qn=typeof Float32Array<"u"?Float32Array:Array;function nl(){var r=new Qn(16);return Qn!=Float32Array&&(r[1]=0,r[2]=0,r[3]=0,r[4]=0,r[6]=0,r[7]=0,r[8]=0,r[9]=0,r[11]=0,r[12]=0,r[13]=0,r[14]=0),r[0]=1,r[5]=1,r[10]=1,r[15]=1,r}function oP(r){var e=new Qn(16);return e[0]=r[0],e[1]=r[1],e[2]=r[2],e[3]=r[3],e[4]=r[4],e[5]=r[5],e[6]=r[6],e[7]=r[7],e[8]=r[8],e[9]=r[9],e[10]=r[10],e[11]=r[11],e[12]=r[12],e[13]=r[13],e[14]=r[14],e[15]=r[15],e}function Id(r,e){var t=e[0],n=e[1],i=e[2],s=e[3],o=e[4],l=e[5],y=e[6],x=e[7],B=e[8],U=e[9],de=e[10],Se=e[11],Ce=e[12],Ie=e[13],Ge=e[14],He=e[15],nt=t*l-n*o,_e=t*y-i*o,we=t*x-s*o,$e=n*y-i*l,Ne=n*x-s*l,Mt=i*x-s*y,Ve=B*Ie-U*Ce,Ut=B*Ge-de*Ce,It=B*He-Se*Ce,Ft=U*Ge-de*Ie,ht=U*He-Se*Ie,_t=de*He-Se*Ge,je=nt*_t-_e*ht+we*Ft+$e*It-Ne*Ut+Mt*Ve;return je?(je=1/je,r[0]=(l*_t-y*ht+x*Ft)*je,r[1]=(i*ht-n*_t-s*Ft)*je,r[2]=(Ie*Mt-Ge*Ne+He*$e)*je,r[3]=(de*Ne-U*Mt-Se*$e)*je,r[4]=(y*It-o*_t-x*Ut)*je,r[5]=(t*_t-i*It+s*Ut)*je,r[6]=(Ge*we-Ce*Mt-He*_e)*je,r[7]=(B*Mt-de*we+Se*_e)*je,r[8]=(o*ht-l*It+x*Ve)*je,r[9]=(n*It-t*ht-s*Ve)*je,r[10]=(Ce*Ne-Ie*we+He*nt)*je,r[11]=(U*we-B*Ne-Se*nt)*je,r[12]=(l*Ut-o*Ft-y*Ve)*je,r[13]=(t*Ft-n*Ut+i*Ve)*je,r[14]=(Ie*_e-Ce*$e-Ge*nt)*je,r[15]=(B*$e-U*_e+de*nt)*je,r):null}function Wn(r,e,t){var n=e[0],i=e[1],s=e[2],o=e[3],l=e[4],y=e[5],x=e[6],B=e[7],U=e[8],de=e[9],Se=e[10],Ce=e[11],Ie=e[12],Ge=e[13],He=e[14],nt=e[15],_e=t[0],we=t[1],$e=t[2],Ne=t[3];return r[0]=_e*n+we*l+$e*U+Ne*Ie,r[1]=_e*i+we*y+$e*de+Ne*Ge,r[2]=_e*s+we*x+$e*Se+Ne*He,r[3]=_e*o+we*B+$e*Ce+Ne*nt,_e=t[4],we=t[5],$e=t[6],Ne=t[7],r[4]=_e*n+we*l+$e*U+Ne*Ie,r[5]=_e*i+we*y+$e*de+Ne*Ge,r[6]=_e*s+we*x+$e*Se+Ne*He,r[7]=_e*o+we*B+$e*Ce+Ne*nt,_e=t[8],we=t[9],$e=t[10],Ne=t[11],r[8]=_e*n+we*l+$e*U+Ne*Ie,r[9]=_e*i+we*y+$e*de+Ne*Ge,r[10]=_e*s+we*x+$e*Se+Ne*He,r[11]=_e*o+we*B+$e*Ce+Ne*nt,_e=t[12],we=t[13],$e=t[14],Ne=t[15],r[12]=_e*n+we*l+$e*U+Ne*Ie,r[13]=_e*i+we*y+$e*de+Ne*Ge,r[14]=_e*s+we*x+$e*Se+Ne*He,r[15]=_e*o+we*B+$e*Ce+Ne*nt,r}function Fd(r,e){return r[0]=1,r[1]=0,r[2]=0,r[3]=0,r[4]=0,r[5]=1,r[6]=0,r[7]=0,r[8]=0,r[9]=0,r[10]=1,r[11]=0,r[12]=e[0],r[13]=e[1],r[14]=e[2],r[15]=1,r}function s_(r,e){return r[0]=e[0],r[1]=0,r[2]=0,r[3]=0,r[4]=0,r[5]=e[1],r[6]=0,r[7]=0,r[8]=0,r[9]=0,r[10]=e[2],r[11]=0,r[12]=0,r[13]=0,r[14]=0,r[15]=1,r}function a_(r,e,t){var n=t[0],i=t[1],s=t[2],o=Math.sqrt(n*n+i*i+s*s),l,y,x;return o{const o=new Float32Array(16),l=new Float32Array(16),y=new Float32Array(16);let x=nl(),B=[...n.slice(0,2),0,1];const U=Array.isArray(i[0])?[...i[0]]:[...i],de=Array.isArray(i[0])?[...i[1]]:[...i],Se=Array.isArray(s[0])?[...s[0]]:[...s],Ce=Array.isArray(s[0])?[...s[1]]:[...s],Ie=()=>l_(o,x).slice(0,2),Ge=()=>{const Ae=Ie();return Math.min(Ae[0],Ae[1])},He=()=>{const Ae=Ie();return Math.max(Ae[0],Ae[1])},nt=()=>Math.acos(x[0]/He()),_e=()=>[[...U],[...de]],we=()=>[[...Se],[...Ce]],$e=()=>{const Ae=Ie();return[1/Ae[0],1/Ae[1]]},Ne=()=>1/Ge(),Mt=()=>1/He(),Ve=()=>o_(o,x).slice(0,2),Ut=()=>c_(o,B,Id(y,x)).slice(0,2),It=()=>x,Ft=()=>B.slice(0,2),ht=([Ae=0,We=0]=[],Ht=1,$t=0)=>{x=nl(),_t([-Ae,-We]),er($t),je(1/Ht)},_t=([Ae=0,We=0]=[])=>{o[0]=Ae,o[1]=We,o[2]=0;const Ht=Fd(l,o);Wn(x,Ht,x)},je=(Ae,We)=>{const Ht=Array.isArray(Ae);let $t=Ht?Ae[0]:Ae,nr=Ht?Ae[1]:Ae;if($t<=0||nr<=0||$t===1&&nr===1)return;const br=Ie(),Kr=br[0]*$t,Vr=br[1]*nr;if($t=Math.max(U[0],Math.min(Kr,U[1]))/br[0],nr=Math.max(de[0],Math.min(Vr,de[1]))/br[1],$t===1&&nr===1)return;o[0]=$t,o[1]=nr,o[2]=1;const Or=s_(l,o),cn=We?[...We,0]:B,dn=Fd(o,cn);Wn(x,dn,Wn(x,Or,Wn(x,Id(y,dn),x)))},er=Ae=>{const We=nl();a_(We,Ae,[0,0,1]),Wn(x,We,x)},Ar=Ae=>{const We=Array.isArray(Ae[0]);U[0]=We?Ae[0][0]:Ae[0],U[1]=We?Ae[0][1]:Ae[1],de[0]=We?Ae[1][0]:Ae[0],de[1]=We?Ae[1][1]:Ae[1]},zt=Ae=>{const We=Array.isArray(Ae[0]);Se[0]=We?Ae[0][0]:Ae[0],Se[1]=We?Ae[0][1]:Ae[1],Ce[0]=We?Ae[1][0]:Ae[0],Ce[1]=We?Ae[1][1]:Ae[1]},tr=Ae=>{!Ae||Ae.length<16||(x=Ae)},Lr=Ae=>{B=[...Ae.slice(0,2),0,1]},rr=()=>{ht(r,e,t)};return ht(r,e,t),{get translation(){return Ve()},get target(){return Ut()},get scaling(){return Ie()},get minScaling(){return Ge()},get maxScaling(){return He()},get scaleBounds(){return _e()},get translationBounds(){return we()},get distance(){return $e()},get minDistance(){return Ne()},get maxDistance(){return Mt()},get rotation(){return nt()},get view(){return It()},get viewCenter(){return Ft()},lookAt:ht,translate:_t,pan:_t,rotate:er,scale:je,zoom:je,reset:rr,set:(...Ae)=>(console.warn("`set()` is deprecated. Please use `setView()` instead."),tr(...Ae)),setScaleBounds:Ar,setTranslationBounds:zt,setView:tr,setViewCenter:Lr}},f_=["pan","rotate"],$d={alt:"altKey",cmd:"metaKey",ctrl:"ctrlKey",meta:"metaKey",shift:"shiftKey"},lP=(r,{distance:e=1,target:t=[0,0],rotation:n=0,isNdc:i=!0,isFixed:s=!1,isPan:o=!0,isPanInverted:l=[!1,!0],panSpeed:y=1,isRotate:x=!0,rotateSpeed:B=1,defaultMouseDownMoveAction:U="pan",mouseDownMoveModKey:de="alt",isZoom:Se=!0,zoomSpeed:Ce=1,viewCenter:Ie,scaleBounds:Ge,translationBounds:He,onKeyDown:nt=()=>{},onKeyUp:_e=()=>{},onMouseDown:we=()=>{},onMouseUp:$e=()=>{},onMouseMove:Ne=()=>{},onWheel:Mt=()=>{}}={})=>{let Ve=p_(t,e,n,Ie,Ge,He),Ut=0,It=0,Ft=0,ht=0,_t=0,je=0,er=!1,Ar=0,zt=1,tr=1,Lr=1,rr=!1,Ae=!1,We=!1,Ht=U==="pan",$t=o,nr=o,br=l,Kr=l,Vr=Se,Or=Se;const cn=()=>{$t=Array.isArray(o)?!!o[0]:o,nr=Array.isArray(o)?!!o[1]:o,br=Array.isArray(l)?!!l[0]:l,Kr=Array.isArray(l)?!!l[1]:l,Vr=Array.isArray(Se)?!!Se[0]:Se,Or=Array.isArray(Se)?!!Se[1]:Se};cn();const dn=i?ye=>ye/zt*2*Lr:ye=>ye,li=i?ye=>ye/tr*2:ye=>-ye,Ke=i?ye=>(-1+ye/zt*2)*Lr:ye=>ye,qe=i?ye=>1-ye/tr*2:ye=>ye,it=()=>{if(s){const ir=Ae;return Ae=!1,ir}rr=!1;const ye=Ut,Lt=It;if(($t||nr)&&er&&(Ht&&!We||!Ht&&We)){const ir=br?_t-ye:ye-_t,_r=$t?dn(y*ir):0,wr=Kr?je-Lt:Lt-je,wt=nr?li(y*wr):0;(_r!==0||wt!==0)&&(Ve.pan([_r,wt]),rr=!0)}if((Vr||Or)&&Ar){const ir=Ce*Math.exp(Ar/tr),_r=Ke(Ft),wr=qe(ht);Ve.scale([Vr?1/ir:1,Or?1/ir:1],[_r,wr]),rr=!0}if(x&&er&&(Ht&&We||!Ht&&!We)&&Math.abs(_t-ye)+Math.abs(je-Lt)>0){const ir=zt/2,_r=tr/2,wr=_t-ir,wt=_r-je,qr=ye-ir,hn=_r-Lt,In=h_([wr,wt],[qr,hn]),so=wr*hn-qr*wt;Ve.rotate(B*In*Math.sign(so)),rr=!0}Ar=0,_t=ye,je=Lt;const Mn=rr||Ae;return Ae=!1,Mn},st=({defaultMouseDownMoveAction:ye=null,isFixed:Lt=null,isPan:Mn=null,isPanInverted:ir=null,isRotate:_r=null,isZoom:wr=null,panSpeed:wt=null,rotateSpeed:qr=null,zoomSpeed:hn=null,mouseDownMoveModKey:In=null}={})=>{U=ye!==null&&f_.includes(ye)?ye:U,Ht=U==="pan",s=Lt!==null?Lt:s,o=Mn!==null?Mn:o,l=ir!==null?ir:l,x=_r!==null?_r:x,Se=wr!==null?wr:Se,y=+wt>0?wt:y,B=+qr>0?qr:B,Ce=+hn>0?hn:Ce,cn(),de=In!==null&&Object.keys($d).includes(In)?In:de},cr=()=>{const ye=r.getBoundingClientRect();zt=ye.width,tr=ye.height,Lr=zt/tr},at=ye=>{We=!1,_e(ye)},Rn=ye=>{We=ye[$d[de]],nt(ye)},Dn=ye=>{er=!1,$e(ye)},Us=ye=>{er=ye.buttons===1,we(ye)},h=document.createEvent("MouseEvent").offsetX!==void 0?ye=>{Ft=ye.offsetX,ht=ye.offsetY}:ye=>{const Lt=r.getBoundingClientRect();Ft=ye.clientX-Lt.left,ht=ye.clientY-Lt.top},zs=ye=>{Ut=ye.clientX,It=ye.clientY},Hs=ye=>{zs(ye),Ne(ye)},Ks=ye=>{if((Vr||Or)&&!s){ye.preventDefault(),zs(ye),h(ye);const Lt=ye.deltaMode===1?12:1;Ar+=Lt*(ye.deltaY||ye.deltaX||0)}Mt(ye)},io=()=>{Ve=void 0,window.removeEventListener("keydown",Rn),window.removeEventListener("keyup",at),r.removeEventListener("mousedown",Us),window.removeEventListener("mouseup",Dn),window.removeEventListener("mousemove",Hs),r.removeEventListener("wheel",Ks)};window.addEventListener("keydown",Rn,{passive:!0}),window.addEventListener("keyup",at,{passive:!0}),r.addEventListener("mousedown",Us,{passive:!0}),window.addEventListener("mouseup",Dn,{passive:!0}),window.addEventListener("mousemove",Hs,{passive:!0}),r.addEventListener("wheel",Ks,{passive:!1}),Ve.config=st,Ve.dispose=io,Ve.refresh=cr,Ve.tick=it;const St=ye=>function(){ye.apply(null,arguments),Ae=!0};return Ve.lookAt=St(Ve.lookAt),Ve.translate=St(Ve.translate),Ve.pan=St(Ve.pan),Ve.rotate=St(Ve.rotate),Ve.scale=St(Ve.scale),Ve.zoom=St(Ve.zoom),Ve.reset=St(Ve.reset),Ve.set=St(Ve.set),Ve.setScaleBounds=St(Ve.setScaleBounds),Ve.setTranslationBounds=St(Ve.setTranslationBounds),Ve.setView=St(Ve.setView),Ve.setViewCenter=St(Ve.setViewCenter),cr(),Ve};function uP(r,e,t=2){const n=r.length;let i=m_(r,0,n,t,!0);const s=[];if(!i||i.next===i.prev)return s;let o,l,y;if(r.length>80*t){o=r[0],l=r[1];let x=o,B=l;for(let U=t;Ux&&(x=de),Se>B&&(B=Se)}y=Math.max(x-o,B-l),y=y!==0?32767/y:0}return vs(i,s,t,o,l,y,0),s}function m_(r,e,t,n,i){let s;if(i===S_(r,e,t,n)>0)for(let o=e;o=e;o-=n)s=Bd(o/n|0,r[o],r[o+1],s);return s&&Ka(s,s.next)&&(bs(s),s=s.next),s}function ms(r,e){if(!r)return r;e||(e=r);let t=r,n;do if(n=!1,!t.steiner&&(Ka(t,t.next)||At(t.prev,t,t.next)===0)){if(bs(t),t=e=t.prev,t===t.next)break;n=!0}else t=t.next;while(n||t!==e);return e}function vs(r,e,t,n,i,s,o){if(!r)return;!o&&s&&g_(r,n,i,s);let l=r;for(;r.prev!==r.next;){const y=r.prev,x=r.next;if(s?b_(r,n,i,s):v_(r)){e.push(y.i,r.i,x.i),bs(r),r=x.next,l=x.next;continue}if(r=x,r===l){o?o===1?(r=__(ms(r),e),vs(r,e,t,n,i,s,2)):o===2&&w_(r,e,t,n,i,s):vs(ms(r),e,t,n,i,s,1);break}}}function v_(r){const e=r.prev,t=r,n=r.next;if(At(e,t,n)>=0)return!1;const i=e.x,s=t.x,o=n.x,l=e.y,y=t.y,x=n.y,B=Math.min(i,s,o),U=Math.min(l,y,x),de=Math.max(i,s,o),Se=Math.max(l,y,x);let Ce=n.next;for(;Ce!==e;){if(Ce.x>=B&&Ce.x<=de&&Ce.y>=U&&Ce.y<=Se&&fs(i,l,s,y,o,x,Ce.x,Ce.y)&&At(Ce.prev,Ce,Ce.next)>=0)return!1;Ce=Ce.next}return!0}function b_(r,e,t,n){const i=r.prev,s=r,o=r.next;if(At(i,s,o)>=0)return!1;const l=i.x,y=s.x,x=o.x,B=i.y,U=s.y,de=o.y,Se=Math.min(l,y,x),Ce=Math.min(B,U,de),Ie=Math.max(l,y,x),Ge=Math.max(B,U,de),He=Cl(Se,Ce,e,t,n),nt=Cl(Ie,Ge,e,t,n);let _e=r.prevZ,we=r.nextZ;for(;_e&&_e.z>=He&&we&&we.z<=nt;){if(_e.x>=Se&&_e.x<=Ie&&_e.y>=Ce&&_e.y<=Ge&&_e!==i&&_e!==o&&fs(l,B,y,U,x,de,_e.x,_e.y)&&At(_e.prev,_e,_e.next)>=0||(_e=_e.prevZ,we.x>=Se&&we.x<=Ie&&we.y>=Ce&&we.y<=Ge&&we!==i&&we!==o&&fs(l,B,y,U,x,de,we.x,we.y)&&At(we.prev,we,we.next)>=0))return!1;we=we.nextZ}for(;_e&&_e.z>=He;){if(_e.x>=Se&&_e.x<=Ie&&_e.y>=Ce&&_e.y<=Ge&&_e!==i&&_e!==o&&fs(l,B,y,U,x,de,_e.x,_e.y)&&At(_e.prev,_e,_e.next)>=0)return!1;_e=_e.prevZ}for(;we&&we.z<=nt;){if(we.x>=Se&&we.x<=Ie&&we.y>=Ce&&we.y<=Ge&&we!==i&&we!==o&&fs(l,B,y,U,x,de,we.x,we.y)&&At(we.prev,we,we.next)>=0)return!1;we=we.nextZ}return!0}function __(r,e){let t=r;do{const n=t.prev,i=t.next.next;!Ka(n,i)&&Gh(n,t,t.next,i)&&Ma(n,i)&&Ma(i,n)&&(e.push(n.i,t.i,i.i),bs(t),bs(t.next),t=r=i),t=t.next}while(t!==r);return ms(t)}function w_(r,e,t,n,i,s){let o=r;do{let l=o.next.next;for(;l!==o.prev;){if(o.i!==l.i&&C_(o,l)){let y=A_(o,l);o=ms(o,o.next),y=ms(y,y.next),vs(o,e,t,n,i,s,0),vs(y,e,t,n,i,s,0);return}l=l.next}o=o.next}while(o!==r)}function g_(r,e,t,n){let i=r;do i.z===0&&(i.z=Cl(i.x,i.y,e,t,n)),i.prevZ=i.prev,i.nextZ=i.next,i=i.next;while(i!==r);i.prevZ.nextZ=null,i.prevZ=null,y_(i)}function y_(r){let e,t=1;do{let n=r,i;r=null;let s=null;for(e=0;n;){e++;let o=n,l=0;for(let x=0;x0||y>0&&o;)l!==0&&(y===0||!o||n.z<=o.z)?(i=n,n=n.nextZ,l--):(i=o,o=o.nextZ,y--),s?s.nextZ=i:r=i,i.prevZ=s,s=i;n=o}s.nextZ=null,t*=2}while(e>1);return r}function Cl(r,e,t,n,i){return r=(r-t)*i|0,e=(e-n)*i|0,r=(r|r<<8)&16711935,r=(r|r<<4)&252645135,r=(r|r<<2)&858993459,r=(r|r<<1)&1431655765,e=(e|e<<8)&16711935,e=(e|e<<4)&252645135,e=(e|e<<2)&858993459,e=(e|e<<1)&1431655765,r|e<<1}function x_(r,e,t,n,i,s,o,l){return(i-o)*(e-l)>=(r-o)*(s-l)&&(r-o)*(n-l)>=(t-o)*(e-l)&&(t-o)*(s-l)>=(i-o)*(n-l)}function fs(r,e,t,n,i,s,o,l){return!(r===o&&e===l)&&x_(r,e,t,n,i,s,o,l)}function C_(r,e){return r.next.i!==e.i&&r.prev.i!==e.i&&!E_(r,e)&&(Ma(r,e)&&Ma(e,r)&&P_(r,e)&&(At(r.prev,r,e.prev)||At(r,e.prev,e))||Ka(r,e)&&At(r.prev,r,r.next)>0&&At(e.prev,e,e.next)>0)}function At(r,e,t){return(e.y-r.y)*(t.x-e.x)-(e.x-r.x)*(t.y-e.y)}function Ka(r,e){return r.x===e.x&&r.y===e.y}function Gh(r,e,t,n){const i=Ea(At(r,e,t)),s=Ea(At(r,e,n)),o=Ea(At(t,n,r)),l=Ea(At(t,n,e));return!!(i!==s&&o!==l||i===0&&Ca(r,t,e)||s===0&&Ca(r,n,e)||o===0&&Ca(t,r,n)||l===0&&Ca(t,e,n))}function Ca(r,e,t){return e.x<=Math.max(r.x,t.x)&&e.x>=Math.min(r.x,t.x)&&e.y<=Math.max(r.y,t.y)&&e.y>=Math.min(r.y,t.y)}function Ea(r){return r>0?1:r<0?-1:0}function E_(r,e){let t=r;do{if(t.i!==r.i&&t.next.i!==r.i&&t.i!==e.i&&t.next.i!==e.i&&Gh(t,t.next,r,e))return!0;t=t.next}while(t!==r);return!1}function Ma(r,e){return At(r.prev,r,r.next)<0?At(r,e,r.next)>=0&&At(r,r.prev,e)>=0:At(r,e,r.prev)<0||At(r,r.next,e)<0}function P_(r,e){let t=r,n=!1;const i=(r.x+e.x)/2,s=(r.y+e.y)/2;do t.y>s!=t.next.y>s&&t.next.y!==t.y&&i<(t.next.x-t.x)*(s-t.y)/(t.next.y-t.y)+t.x&&(n=!n),t=t.next;while(t!==r);return n}function A_(r,e){const t=El(r.i,r.x,r.y),n=El(e.i,e.x,e.y),i=r.next,s=e.prev;return r.next=e,e.prev=r,t.next=i,i.prev=t,n.next=t,t.prev=n,s.next=n,n.prev=s,n}function Bd(r,e,t,n){const i=El(r,e,t);return n?(i.next=n.next,i.prev=n,n.next.prev=i,n.next=i):(i.prev=i,i.next=i),i}function bs(r){r.next.prev=r.prev,r.prev.next=r.next,r.prevZ&&(r.prevZ.nextZ=r.nextZ),r.nextZ&&(r.nextZ.prevZ=r.prevZ)}function El(r,e,t){return{i:r,x:e,y:t,prev:null,next:null,z:0,prevZ:null,nextZ:null,steiner:!1}}function S_(r,e,t,n){let i=0;for(let s=e,o=t-n;stypeof r=="string",Bl=(r,e)=>T_(r)&&e?r.toLowerCase():r,Uh=(r,e)=>(t,n,i=Number.POSITIVE_INFINITY)=>{const s=Bl(t,e?.caseInsensitive),o=r[s]||[];return o.push({handler:n,times:+i||Number.POSITIVE_INFINITY}),r[s]=o,{event:s,handler:n}},k_=r=>typeof r=="object";function Nl(r,e){function t(n,i){let s,o;k_(n)?(o=n.handler,s=n.event):(s=n,o=i);const l=Bl(s,e?.caseInsensitive),y=r[l];if(!y)return;const x=y.findIndex(B=>B.handler===o);x===-1||x>=y.length||y.splice(x,1)}return t}const L_=r=>!!r,zh=(r,e)=>{const t=Nl(r);return(...n)=>{const[i,s,o]=n,l=Bl(i,e?.caseInsensitive),y=r[l];if(!L_(y))return;const x=[...y];for(const de of x)--de.times<1&&t(l,de.handler);const B=o?.async!==void 0?o.async:e?.async,U=()=>{for(const de of x)de.handler(s)};if(B?setTimeout(U,0):U(),e?.isGlobal&&!o?.isNoGlobalBroadcast)try{jh.postMessage({event:l,news:s})}catch(de){if(de instanceof Error&&de.name==="DataCloneError")console.warn(`Could not broadcast '${l.toString()}' globally. Payload is not clonable.`);else throw de}}};function V_(r){return Object.keys(r)}const Hh=r=>()=>{for(const e of V_(r))delete r[e]},Kh=()=>({}),cP=r=>{const e=!!r?.async,t=!!r?.caseInsensitive,n=r?.stack||Kh();return{publish:zh(n,{async:e,caseInsensitive:t}),subscribe:Uh(n,{caseInsensitive:t}),unsubscribe:Nl(n,{caseInsensitive:t}),clear:Hh(n),stack:n}},ss=Kh(),O_={publish:zh(ss,{isGlobal:!0}),subscribe:Uh(ss),unsubscribe:Nl(ss),clear:Hh(ss),stack:ss};jh.onmessage=({data:{event:r,news:e}})=>O_.publish(r,e,{isNoGlobalBroadcast:!0});const R_=` +precision mediump float; +varying vec4 color; +void main() { + gl_FragColor = color; +}`,D_=` +uniform mat4 projectionViewModel; +uniform float aspectRatio; + +uniform sampler2D colorTex; +uniform float colorTexRes; +uniform float colorTexEps; +uniform float width; +uniform float useOpacity; +uniform float useColorOpacity; +uniform int miter; + +attribute vec3 prevPosition; +attribute vec3 currPosition; +attribute vec3 nextPosition; +attribute float opacity; +attribute float offsetScale; +attribute float colorIndex; + +varying vec4 color; + +void main() { + vec2 aspectVec = vec2(aspectRatio, 1.0); + vec4 prevProjected = projectionViewModel * vec4(prevPosition, 1.0); + vec4 currProjected = projectionViewModel * vec4(currPosition, 1.0); + vec4 nextProjected = projectionViewModel * vec4(nextPosition, 1.0); + + // get 2D screen space with W divide and aspect correction + vec2 prevScreen = prevProjected.xy / prevProjected.w * aspectVec; + vec2 currScreen = currProjected.xy / currProjected.w * aspectVec; + vec2 nextScreen = nextProjected.xy / nextProjected.w * aspectVec; + + float len = width; + + // starting point uses (next - current) + vec2 dir = vec2(0.0); + if (currScreen == prevScreen) { + dir = normalize(nextScreen - currScreen); + } + // ending point uses (current - previous) + else if (currScreen == nextScreen) { + dir = normalize(currScreen - prevScreen); + } + // somewhere in middle, needs a join + else { + // get directions from (C - B) and (B - A) + vec2 dirA = normalize((currScreen - prevScreen)); + if (miter == 1) { + vec2 dirB = normalize((nextScreen - currScreen)); + // now compute the miter join normal and length + vec2 tangent = normalize(dirA + dirB); + vec2 perp = vec2(-dirA.y, dirA.x); + vec2 miter = vec2(-tangent.y, tangent.x); + len = width / dot(miter, perp); + dir = tangent; + } else { + dir = dirA; + } + } + + vec2 normal = vec2(-dir.y, dir.x) * len; + normal.x /= aspectRatio; + vec4 offset = vec4(normal * offsetScale, 0.0, 0.0); + gl_Position = currProjected + offset; + + // Get color from texture + float colorRowIndex = floor((colorIndex + colorTexEps) / colorTexRes); + vec2 colorTexIndex = vec2( + (colorIndex / colorTexRes) - colorRowIndex + colorTexEps, + colorRowIndex / colorTexRes + colorTexEps + ); + + color = texture2D(colorTex, colorTexIndex); + color.a = useColorOpacity * color.a + useOpacity * opacity; +}`,il=new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),Yt=Float32Array.BYTES_PER_ELEMENT,M_=r=>r!==void 0&&Number.isFinite(r),sl=r=>r.length>0&&Array.isArray(r[0]),{push:qh,splice:I_}=Array.prototype,F_=(r,e=[])=>{let t=0;for(const n of r){for(let i=0;i{if(!r){console.error("Regl instance is undefined.");return}const Ce=new Float32Array(16);let Ie,Ge,He,nt,_e,we,$e,Ne,Mt,Ve,Ut,It,Ft,ht,_t,je,er,Ar,zt=de?2:3;const tr=()=>+(y.length===Ge||l!==null),Lr=()=>{Ve=r.buffer(),Ut=r.buffer(),It=r.buffer(),_t=r.buffer(),je={prevPosition:{buffer:(()=>Ve),offset:0,stride:Yt*3},currPosition:{buffer:(()=>Ve),offset:Yt*3*2,stride:Yt*3},nextPosition:{buffer:(()=>Ve),offset:Yt*3*4,stride:Yt*3},opacity:{buffer:(()=>Ut),offset:Yt*2,stride:Yt},offsetScale:{buffer:(()=>It),offset:Yt*2,stride:Yt},colorIndex:{buffer:(()=>_t),offset:Yt*2,stride:Yt}},er=r.elements(),Ar=r({attributes:je,depth:{enable:!de},blend:{enable:!0,func:{srcRGB:"src alpha",srcAlpha:"one",dstRGB:"one minus src alpha",dstAlpha:"one minus src alpha"}},uniforms:{projectionViewModel:(Ke,qe)=>{const it=Ke.projection||qe.projection,st=Ke.model||qe.model,cr=Ke.view||qe.view;return Wn(Ce,it,Wn(Ce,cr,st))},aspectRatio:({viewportWidth:Ke,viewportHeight:qe})=>Ke/qe,colorTex:()=>Ft,colorTexRes:()=>ht,colorTexEps:()=>.5/ht,pixelRatio:({pixelRatio:Ke})=>Ke,width:({pixelRatio:Ke,viewportHeight:qe})=>x/qe*Ke,useOpacity:tr,useColorOpacity:()=>+!tr(),miter:+!!U},elements:()=>er,vert:D_,frag:R_})},rr=()=>{Ie===1&&i.length%zt>0&&console.warn(`The length of points (${Ge}) does not match the dimensions (${zt}). Incomplete points are ignored.`),nt=i.flat().slice(0,Ge*zt),de&&(nt=$_(nt,2,3,Se)),s.length!==Ge&&(s=new Array(Ge).fill(0)),B.length!==Ge&&(B=new Array(Ge).fill(1));const Ke=s.slice(),qe=y.length===Ge?y.slice():new Array(Ge).fill(l===null?1:l),it=B.slice();let st=0;for(const cr of He){const at=st+cr-1;wn(nt,at,at,3),wn(nt,st,st,3),wn(Ke,at,at,1),wn(Ke,st,st,1),wn(qe,at,at,1),wn(qe,st,st,1),wn(it,at,at,1),wn(it,st,st,1),st+=cr+2}_e=new Float32Array(Pa(nt,3)),we=Pa(Ke),$e=Pa(qe),Ne=Pa(it,1,-1),Mt=F_(He),Ve({usage:"dynamic",type:"float",length:_e.length*Yt,data:_e}),Ut({usage:"dynamic",type:"float",length:$e.length*Yt,data:$e}),It({usage:"dynamic",type:"float",length:Ne.length*Yt,data:Ne}),_t({usage:"dynamic",type:"float",length:we.length*Yt,data:we}),er({primitive:"triangles",usage:"dynamic",type:Mt.length>2**16?"uint32":"uint16",data:Mt})},Ae=()=>{We(),Lr()},We=()=>{i=[],nt=[],_e=new Float32Array,Ne=[],Mt=[],Ve.destroy(),It.destroy(),er.destroy()},Ht=({projection:Ke,model:qe,view:it}={})=>{Ke&&(e=Ke),qe&&(t=qe),it&&(n=it),i&&i.length>1&&Ar({projection:e,model:t,view:n})},$t=(Ke,qe)=>{const it=qe.flat(2);return it.length===Ge?it:it.length===Ie?He.flatMap((st,cr)=>Array(st).fill(it[cr])):Ke},nr=()=>i,br=(Ke=[],{colorIndices:qe=s,opacities:it=y,widths:st=B,is2d:cr=de}={})=>{i=Ke,de=cr,zt=de?2:3,Ie=sl(i)?i.length:1,He=sl(i)?i.map(at=>Math.floor(at.length/zt)):[Math.floor(i.length/zt)],Ge=He.reduce((at,Rn)=>at+Rn,0),s=$t(s,qe),y=$t(y,it),B=$t(B,st),i&&Ge>1?rr():Ae()},Kr=()=>{const Ke=sl(o)?o:[o];ht=Math.max(2,Math.ceil(Math.sqrt(Ke.length)));const qe=new Uint8Array(ht**2*4);Ke.forEach((it,st)=>{qe[st*4]=Math.min(255,Math.max(0,Math.round(it[0]*255))),qe[st*4+1]=Math.min(255,Math.max(0,Math.round(it[1]*255))),qe[st*4+2]=Math.min(255,Math.max(0,Math.round(it[2]*255))),qe[st*4+3]=Number.isNaN(+it[3])?255:Math.min(255,Math.max(0,Math.round(it[3]*255)))}),Ft=r.texture({data:qe,shape:[ht,ht,4]})},Vr=(Ke,qe=l)=>{o=Ke,l=qe,Ft&&Ft.destroy(),Kr()},Or=()=>({color:o,miter:U,width:x}),cn=({color:Ke,opacity:qe,miter:it,width:st}={})=>{Ke&&Vr(Ke,qe||l),it&&(U=!!it),M_(st)&&(x=st)},dn=()=>({points:Ve,widths:It,opacities:Ut,colorIndices:_t}),li=()=>({points:_e,widths:Ne,opacities:$e,colorIndices:we});return Lr(),Kr(),i&&i.length>1&&br(i),{clear:Ae,destroy:We,draw:Ht,getPoints:nr,setPoints:br,getData:li,getBuffer:dn,getStyle:Or,setStyle:cn}};function B_(r){return r&&r.__esModule&&Object.prototype.hasOwnProperty.call(r,"default")?r.default:r}var ka={exports:{}},N_=ka.exports,Nd;function G_(){return Nd||(Nd=1,(function(r,e){(function(t,n){r.exports=n()})(N_,(function(){var t=function(a){return a instanceof Uint8Array||a instanceof Uint16Array||a instanceof Uint32Array||a instanceof Int8Array||a instanceof Int16Array||a instanceof Int32Array||a instanceof Float32Array||a instanceof Float64Array||a instanceof Uint8ClampedArray},n=function(a,c){for(var v=Object.keys(c),V=0;V"u";case"symbol":return typeof a=="symbol"}}function de(a,c,v){U(a,c)||o("invalid parameter type"+y(v)+". expected "+c+", got "+typeof a)}function Se(a,c){a>=0&&(a|0)===a||o("invalid parameter type, ("+a+")"+y(c)+". must be a nonnegative integer")}function Ce(a,c,v){c.indexOf(a)<0&&o("invalid value"+y(v)+". must be one of: "+c)}var Ie=["gl","canvas","container","attributes","pixelRatio","extensions","optionalExtensions","profile","onDone"];function Ge(a){Object.keys(a).forEach(function(c){Ie.indexOf(c)<0&&o('invalid regl constructor argument "'+c+'". must be one of '+Ie)})}function He(a,c){for(a=a+"";a.length0&&c.push(new we("unknown",0,v))}}),c}function Ut(a,c){c.forEach(function(v){var V=a[v.file];if(V){var I=V.index[v.line];if(I){I.errors.push(v),V.hasErrors=!0;return}}a.unknown.hasErrors=!0,a.unknown.lines[0].errors.push(v)})}function It(a,c,v,V,I){if(!a.getShaderParameter(c,a.COMPILE_STATUS)){var L=a.getShaderInfoLog(c),D=V===a.FRAGMENT_SHADER?"fragment":"vertex";zt(v,"string",D+" shader source must be a string",I);var j=Mt(v,I),G=Ve(L);Ut(j,G),Object.keys(j).forEach(function(X){var W=j[X];if(!W.hasErrors)return;var Y=[""],ee=[""];function z(q,P){Y.push(q),ee.push(P||"")}z("file number "+X+": "+W.name+` +`,"color:red;text-decoration:underline;font-weight:bold"),W.lines.forEach(function(q){if(q.errors.length>0){z(He(q.number,4)+"| ","background-color:yellow; font-weight:bold"),z(q.line+i,"color:red; background-color:yellow; font-weight:bold");var P=0;q.errors.forEach(function(R){var K=R.message,ue=/^\s*'(.*)'\s*:\s*(.*)$/.exec(K);if(ue){var N=ue[1];K=ue[2],N==="assign"&&(N="="),P=Math.max(q.line.indexOf(N,P),0)}else P=0;z(He("| ",6)),z(He("^^^",P+3)+i,"font-weight:bold"),z(He("| ",6)),z(K+i,"font-weight:bold")}),z(He("| ",6)+i)}else z(He(q.number,4)+"| "),z(q.line+i,"color:red")}),typeof document<"u"&&!window.chrome?(ee[0]=Y.join("%c"),console.log.apply(console,ee)):console.log(Y.join(""))}),l.raise("Error compiling "+D+" shader, "+j[0].name)}}function Ft(a,c,v,V,I){if(!a.getProgramParameter(c,a.LINK_STATUS)){var L=a.getProgramInfoLog(c),D=Mt(v,I),j=Mt(V,I),G='Error linking program with vertex shader, "'+j[0].name+'", and fragment shader "'+D[0].name+'"';typeof document<"u"?console.log("%c"+G+i+"%c"+L,"color:red;text-decoration:underline;font-weight:bold","color:red"):console.log(G+i+L),l.raise(G)}}function ht(a){a._commandRef=$e()}function _t(a,c,v,V){ht(a);function I(G){return G?V.id(G):0}a._fragId=I(a.static.frag),a._vertId=I(a.static.vert);function L(G,X){Object.keys(X).forEach(function(W){G[V.id(W)]=!0})}var D=a._uniformSet={};L(D,c.static),L(D,c.dynamic);var j=a._attributeSet={};L(j,v.static),L(j,v.dynamic),a._hasCount="count"in a.static||"count"in a.dynamic||"elements"in a.static||"elements"in a.dynamic}function je(a,c){var v=Ne();o(a+" in command "+(c||$e())+(v==="unknown"?"":" called from "+v))}function er(a,c,v){a||je(c,v||$e())}function Ar(a,c,v,V){a in c||je("unknown parameter ("+a+")"+y(v)+". possible values: "+Object.keys(c).join(),V||$e())}function zt(a,c,v,V){U(a,c)||je("invalid parameter type"+y(v)+". expected "+c+", got "+typeof a,V||$e())}function tr(a){a()}function Lr(a,c,v){a.texture?Ce(a.texture._texture.internalformat,c,"unsupported texture format for attachment"):Ce(a.renderbuffer._renderbuffer.format,v,"unsupported renderbuffer format for attachment")}var rr=33071,Ae=9728,We=9984,Ht=9985,$t=9986,nr=9987,br=5120,Kr=5121,Vr=5122,Or=5123,cn=5124,dn=5125,li=5126,Ke=32819,qe=32820,it=33635,st=34042,cr=36193,at={};at[br]=at[Kr]=1,at[Vr]=at[Or]=at[cr]=at[it]=at[Ke]=at[qe]=2,at[cn]=at[dn]=at[li]=at[st]=4;function Rn(a,c){return a===qe||a===Ke||a===it?2:a===st?4:at[a]*c}function Dn(a){return!(a&a-1)&&!!a}function Us(a,c,v){var V,I=c.width,L=c.height,D=c.channels;l(I>0&&I<=v.maxTextureSize&&L>0&&L<=v.maxTextureSize,"invalid texture shape"),(a.wrapS!==rr||a.wrapT!==rr)&&l(Dn(I)&&Dn(L),"incompatible wrap mode for texture, both width and height must be power of 2"),c.mipmask===1?I!==1&&L!==1&&l(a.minFilter!==We&&a.minFilter!==$t&&a.minFilter!==Ht&&a.minFilter!==nr,"min filter requires mipmap"):(l(Dn(I)&&Dn(L),"texture must be a square power of 2 to support mipmapping"),l(c.mipmask===(I<<1)-1,"missing or incomplete mipmap data")),c.type===li&&(v.extensions.indexOf("oes_texture_float_linear")<0&&l(a.minFilter===Ae&&a.magFilter===Ae,"filter not supported, must enable oes_texture_float_linear"),l(!a.genMipmaps,"mipmap generation not supported with float textures"));var j=c.images;for(V=0;V<16;++V)if(j[V]){var G=I>>V,X=L>>V;l(c.mipmask&1<0&&I<=V.maxTextureSize&&L>0&&L<=V.maxTextureSize,"invalid texture shape"),l(I===L,"cube map must be square"),l(c.wrapS===rr&&c.wrapT===rr,"wrap mode not supported by cube map");for(var j=0;j>W,z=L>>W;l(G.mipmask&1<1&&c===v&&(c==='"'||c==="'"))return['"'+ye(a.substr(1,a.length-2))+'"'];var V=/\[(false|true|null|\d+|'[^']*'|"[^"]*")\]/.exec(a);if(V)return Lt(a.substr(0,V.index)).concat(Lt(V[1])).concat(Lt(a.substr(V.index+V[0].length)));var I=a.split(".");if(I.length===1)return['"'+ye(a)+'"'];for(var L=[],D=0;D"u"?1:window.devicePixelRatio,W=!1,Y=function(q){q&&h.raise(q)},ee=function(){};if(typeof c=="string"?(h(typeof document<"u","selector queries only supported in DOM environments"),v=document.querySelector(c),h(v,"invalid query string for element")):typeof c=="object"?Qf(c)?v=c:Jf(c)?(L=c,I=L.canvas):(h.constructor(c),"gl"in c?L=c.gl:"canvas"in c?I=Uu(c.canvas):"container"in c&&(V=Uu(c.container)),"attributes"in c&&(D=c.attributes,h.type(D,"object","invalid context attributes")),"extensions"in c&&(j=ju(c.extensions)),"optionalExtensions"in c&&(G=ju(c.optionalExtensions)),"onDone"in c&&(h.type(c.onDone,"function","invalid or missing onDone callback"),Y=c.onDone),"profile"in c&&(W=!!c.profile),"pixelRatio"in c&&(X=+c.pixelRatio,h(X>0,"invalid pixel ratio"))):h.raise("invalid arguments to regl"),v&&(v.nodeName.toLowerCase()==="canvas"?I=v:V=v),!L){if(!I){h(typeof document<"u","must manually specify webgl context outside of DOM environments");var z=so(V||document.body,Y,X);if(!z)return null;I=z.canvas,ee=z.onDestroy}D.premultipliedAlpha===void 0&&(D.premultipliedAlpha=!0),L=Zf(I,D)}return L?{gl:L,canvas:I,container:V,extensions:j,optionalExtensions:G,pixelRatio:X,profile:W,onDone:Y,onDestroy:ee}:(ee(),Y("webgl not supported, try upgrading your browser or graphics drivers http://get.webgl.org"),null)}function tm(a,c){var v={};function V(D){h.type(D,"string","extension name must be string");var j=D.toLowerCase(),G;try{G=v[j]=a.getExtension(j)}catch{}return!!G}for(var I=0;I65535)<<4,a>>>=c,v=(a>255)<<3,a>>>=v,c|=v,v=(a>15)<<2,a>>>=v,c|=v,v=(a>3)<<1,a>>>=v,c|=v,c|a>>1}function Hu(){var a=dr(8,function(){return[]});function c(L){var D=um(L),j=a[zu(D)>>2];return j.length>0?j.pop():new ArrayBuffer(D)}function v(L){a[zu(L.byteLength)>>2].push(L)}function V(L,D){var j=null;switch(L){case rm:j=new Int8Array(c(D),0,D);break;case nm:j=new Uint8Array(c(D),0,D);break;case im:j=new Int16Array(c(2*D),0,D);break;case sm:j=new Uint16Array(c(2*D),0,D);break;case am:j=new Int32Array(c(4*D),0,D);break;case om:j=new Uint32Array(c(4*D),0,D);break;case lm:j=new Float32Array(c(4*D),0,D);break;default:return null}return j.length!==D?j.subarray(0,D):j}function I(L){v(L.buffer)}return{alloc:c,free:v,allocType:V,freeType:I}}var gt=Hu();gt.zero=Hu();var cm=3408,dm=3410,hm=3411,pm=3412,fm=3413,mm=3414,vm=3415,bm=33901,_m=33902,wm=3379,gm=3386,ym=34921,xm=36347,Cm=36348,Em=35661,Pm=35660,Am=34930,Sm=36349,Tm=34076,km=34024,Lm=7936,Vm=7937,Om=7938,Rm=35724,Dm=34047,Mm=36063,Im=34852,qs=3553,Ku=34067,Fm=34069,$m=33984,ji=6408,ao=5126,qu=5121,oo=36160,Bm=36053,Nm=36064,Gm=16384,jm=function(a,c){var v=1;c.ext_texture_filter_anisotropic&&(v=a.getParameter(Dm));var V=1,I=1;c.webgl_draw_buffers&&(V=a.getParameter(Im),I=a.getParameter(Mm));var L=!!c.oes_texture_float;if(L){var D=a.createTexture();a.bindTexture(qs,D),a.texImage2D(qs,0,ji,1,1,0,ji,ao,null);var j=a.createFramebuffer();if(a.bindFramebuffer(oo,j),a.framebufferTexture2D(oo,Nm,qs,D,0),a.bindTexture(qs,null),a.checkFramebufferStatus(oo)!==Bm)L=!1;else{a.viewport(0,0,1,1),a.clearColor(1,0,0,1),a.clear(Gm);var G=gt.allocType(ao,4);a.readPixels(0,0,1,1,ji,ao,G),a.getError()?L=!1:(a.deleteFramebuffer(j),a.deleteTexture(D),L=G[0]===1),gt.freeType(G)}}var X=typeof navigator<"u"&&(/MSIE/.test(navigator.userAgent)||/Trident\//.test(navigator.appVersion)||/Edge/.test(navigator.userAgent)),W=!0;if(!X){var Y=a.createTexture(),ee=gt.allocType(qu,36);a.activeTexture($m),a.bindTexture(Ku,Y),a.texImage2D(Fm,0,ji,3,3,0,ji,qu,ee),gt.freeType(ee),a.bindTexture(Ku,null),a.deleteTexture(Y),W=!a.getError()}return{colorBits:[a.getParameter(dm),a.getParameter(hm),a.getParameter(pm),a.getParameter(fm)],depthBits:a.getParameter(mm),stencilBits:a.getParameter(vm),subpixelBits:a.getParameter(cm),extensions:Object.keys(c).filter(function(z){return!!c[z]}),maxAnisotropic:v,maxDrawbuffers:V,maxColorAttachments:I,pointSizeDims:a.getParameter(bm),lineWidthDims:a.getParameter(_m),maxViewportDims:a.getParameter(gm),maxCombinedTextureUnits:a.getParameter(Em),maxCubeMapSize:a.getParameter(Tm),maxRenderbufferSize:a.getParameter(km),maxTextureUnits:a.getParameter(Am),maxTextureSize:a.getParameter(wm),maxAttributes:a.getParameter(ym),maxVertexUniforms:a.getParameter(xm),maxVertexTextureUnits:a.getParameter(Pm),maxVaryingVectors:a.getParameter(Cm),maxFragmentUniforms:a.getParameter(Sm),glsl:a.getParameter(Rm),renderer:a.getParameter(Vm),vendor:a.getParameter(Lm),version:a.getParameter(Om),readFloat:L,npotTextureCube:W}};function Sr(a){return!!a&&typeof a=="object"&&Array.isArray(a.shape)&&Array.isArray(a.stride)&&typeof a.offset=="number"&&a.shape.length===a.stride.length&&(Array.isArray(a.data)||t(a.data))}var hr=function(a){return Object.keys(a).map(function(c){return a[c]})},Xs={shape:Km,flatten:Hm};function Um(a,c,v){for(var V=0;V0){var ge;if(Array.isArray(R[0])){ie=Wu(R);for(var F=1,M=1;M0)if(typeof F[0]=="number"){var H=gt.allocType(N.dtype,F.length);Qu(H,F),ie(H,pe),gt.freeType(H)}else if(Array.isArray(F[0])||t(F[0])){te=Wu(F);var re=uo(F,te,N.dtype);ie(re,pe),gt.freeType(re)}else h.raise("invalid buffer data")}else if(Sr(F)){te=F.shape;var ne=F.stride,Le=0,Te=0,se=0,le=0;te.length===1?(Le=te[0],Te=1,se=ne[0],le=0):te.length===2?(Le=te[0],Te=te[1],se=ne[0],le=ne[1]):h.raise("invalid shape");var Ee=Array.isArray(F.data)?N.dtype:Ws(F.data),ke=gt.allocType(Ee,Le*Te);Ju(ke,F.data,Le,Te,se,le,F.offset),ie(ke,pe),gt.freeType(ke)}else h.raise("invalid data for buffer subdata");return oe}return K||oe(P),oe._reglType="buffer",oe._buffer=N,oe.subdata=ge,v.profile&&(oe.stats=N.stats),oe.destroy=function(){ee(N)},oe}function q(){hr(L).forEach(function(P){P.buffer=a.createBuffer(),a.bindBuffer(P.type,P.buffer),a.bufferData(P.type,P.persistentData||P.byteLength,P.usage)})}return v.profile&&(c.getTotalBufferSize=function(){var P=0;return Object.keys(L).forEach(function(R){P+=L[R].stats.size}),P}),{create:z,createStream:G,destroyStream:X,clear:function(){hr(L).forEach(ee),j.forEach(ee)},getBuffer:function(P){return P&&P._buffer instanceof D?P._buffer:null},restore:q,_initBuffer:Y}}var sv=0,av=0,ov=1,lv=1,uv=4,cv=4,fn={points:sv,point:av,lines:ov,line:lv,triangles:uv,triangle:cv,"line loop":2,"line strip":3,"triangle strip":5,"triangle fan":6},dv=0,hv=1,Ui=4,pv=5120,ui=5121,ec=5122,ci=5123,tc=5124,$n=5125,po=34963,fv=35040,mv=35044;function vv(a,c,v,V){var I={},L=0,D={uint8:ui,uint16:ci};c.oes_element_index_uint&&(D.uint32=$n);function j(q){this.id=L++,I[this.id]=this,this.buffer=q,this.primType=Ui,this.vertCount=0,this.type=0}j.prototype.bind=function(){this.buffer.bind()};var G=[];function X(q){var P=G.pop();return P||(P=new j(v.create(null,po,!0,!1)._buffer)),Y(P,q,fv,-1,-1,0,0),P}function W(q){G.push(q)}function Y(q,P,R,K,ue,N,oe){q.buffer.bind();var ie;if(P){var ge=oe;!oe&&(!t(P)||Sr(P)&&!t(P.data))&&(ge=c.oes_element_index_uint?$n:ci),v._initBuffer(q.buffer,P,R,ge,3)}else a.bufferData(po,N,R),q.buffer.dtype=ie||ui,q.buffer.usage=R,q.buffer.dimension=3,q.buffer.byteLength=N;if(ie=oe,!oe){switch(q.buffer.dtype){case ui:case pv:ie=ui;break;case ci:case ec:ie=ci;break;case $n:case tc:ie=$n;break;default:h.raise("unsupported type for element array")}q.buffer.dtype=ie}q.type=ie,h(ie!==$n||!!c.oes_element_index_uint,"32 bit element buffers not supported, enable oes_element_index_uint first");var F=ue;F<0&&(F=q.buffer.byteLength,ie===ci?F>>=1:ie===$n&&(F>>=2)),q.vertCount=F;var M=K;if(K<0){M=Ui;var pe=q.buffer.dimension;pe===1&&(M=dv),pe===2&&(M=hv),pe===3&&(M=Ui)}q.primType=M}function ee(q){V.elementsCount--,h(q.buffer!==null,"must not double destroy elements"),delete I[q.id],q.buffer.destroy(),q.buffer=null}function z(q,P){var R=v.create(null,po,!0),K=new j(R._buffer);V.elementsCount++;function ue(N){if(!N)R(),K.primType=Ui,K.vertCount=0,K.type=ui;else if(typeof N=="number")R(N),K.primType=Ui,K.vertCount=N|0,K.type=ui;else{var oe=null,ie=mv,ge=-1,F=-1,M=0,pe=0;Array.isArray(N)||t(N)||Sr(N)?oe=N:(h.type(N,"object","invalid arguments for elements"),"data"in N&&(oe=N.data,h(Array.isArray(oe)||t(oe)||Sr(oe),"invalid data for element buffer")),"usage"in N&&(h.parameter(N.usage,Ys,"invalid element buffer usage"),ie=Ys[N.usage]),"primitive"in N&&(h.parameter(N.primitive,fn,"invalid element buffer primitive"),ge=fn[N.primitive]),"count"in N&&(h(typeof N.count=="number"&&N.count>=0,"invalid vertex count for elements"),F=N.count|0),"type"in N&&(h.parameter(N.type,D,"invalid buffer type"),pe=D[N.type]),"length"in N?M=N.length|0:(M=F,pe===ci||pe===ec?M*=2:(pe===$n||pe===tc)&&(M*=4))),Y(K,oe,ie,ge,F,M,pe)}return ue}return ue(q),ue._reglType="elements",ue._elements=K,ue.subdata=function(N,oe){return R.subdata(N,oe),ue},ue.destroy=function(){ee(K)},ue}return{create:z,createStream:X,destroyStream:W,getElements:function(q){return typeof q=="function"&&q._elements instanceof j?q._elements:null},clear:function(){hr(I).forEach(ee)}}}var rc=new Float32Array(1),bv=new Uint32Array(rc.buffer),_v=5123;function nc(a){for(var c=gt.allocType(_v,a.length),v=0;v>>31<<15,L=(V<<1>>>24)-127,D=V>>13&1023;if(L<-24)c[v]=I;else if(L<-14){var j=-14-L;c[v]=I+(D+1024>>j)}else L>15?c[v]=I+31744:c[v]=I+(L+15<<10)+D}return c}function pt(a){return Array.isArray(a)||t(a)}var ic=function(a){return!(a&a-1)&&!!a},wv=34467,Rr=3553,fo=34067,Zs=34069,Bn=6408,mo=6406,Qs=6407,zi=6409,Js=6410,sc=32854,vo=32855,ac=36194,gv=32819,yv=32820,xv=33635,Cv=34042,bo=6402,ea=34041,_o=35904,wo=35906,di=36193,go=33776,yo=33777,xo=33778,Co=33779,oc=35986,lc=35987,uc=34798,cc=35840,dc=35841,hc=35842,pc=35843,fc=36196,hi=5121,Eo=5123,Po=5125,Hi=5126,Ev=10242,Pv=10243,Av=10497,Ao=33071,Sv=33648,Tv=10240,kv=10241,So=9728,Lv=9729,To=9984,mc=9985,vc=9986,ko=9987,Vv=33170,ta=4352,Ov=4353,Rv=4354,Dv=34046,Mv=3317,Iv=37440,Fv=37441,$v=37443,bc=37444,Ki=33984,Bv=[To,vc,mc,ko],ra=[0,zi,Js,Qs,Bn],gr={};gr[zi]=gr[mo]=gr[bo]=1,gr[ea]=gr[Js]=2,gr[Qs]=gr[_o]=3,gr[Bn]=gr[wo]=4;function pi(a){return"[object "+a+"]"}var _c=pi("HTMLCanvasElement"),wc=pi("OffscreenCanvas"),gc=pi("CanvasRenderingContext2D"),yc=pi("ImageBitmap"),xc=pi("HTMLImageElement"),Cc=pi("HTMLVideoElement"),Nv=Object.keys(lo).concat([_c,wc,gc,yc,xc,Cc]),fi=[];fi[hi]=1,fi[Hi]=4,fi[di]=2,fi[Eo]=2,fi[Po]=4;var Bt=[];Bt[sc]=2,Bt[vo]=2,Bt[ac]=2,Bt[ea]=4,Bt[go]=.5,Bt[yo]=.5,Bt[xo]=1,Bt[Co]=1,Bt[oc]=.5,Bt[lc]=1,Bt[uc]=1,Bt[cc]=.5,Bt[dc]=.25,Bt[hc]=.5,Bt[pc]=.25,Bt[fc]=.5;function Ec(a){return Array.isArray(a)&&(a.length===0||typeof a[0]=="number")}function Pc(a){if(!Array.isArray(a))return!1;var c=a.length;return!(c===0||!pt(a[0]))}function Nn(a){return Object.prototype.toString.call(a)}function Ac(a){return Nn(a)===_c}function Sc(a){return Nn(a)===wc}function Gv(a){return Nn(a)===gc}function jv(a){return Nn(a)===yc}function Uv(a){return Nn(a)===xc}function zv(a){return Nn(a)===Cc}function Lo(a){if(!a)return!1;var c=Nn(a);return Nv.indexOf(c)>=0?!0:Ec(a)||Pc(a)||Sr(a)}function Tc(a){return lo[Object.prototype.toString.call(a)]|0}function Hv(a,c){var v=c.length;switch(a.type){case hi:case Eo:case Po:case Hi:var V=gt.allocType(a.type,v);V.set(c),a.data=V;break;case di:a.data=nc(c);break;default:h.raise("unsupported texture type, must specify a typed array")}}function kc(a,c){return gt.allocType(a.type===di?Hi:a.type,c)}function Lc(a,c){a.type===di?(a.data=nc(c),gt.freeType(c)):a.data=c}function Kv(a,c,v,V,I,L){for(var D=a.width,j=a.height,G=a.channels,X=D*j*G,W=kc(a,X),Y=0,ee=0;ee=1;)j+=D*G*G,G/=2;return j}else return D*v*V}function qv(a,c,v,V,I,L,D){var j={"don't care":ta,"dont care":ta,nice:Rv,fast:Ov},G={repeat:Av,clamp:Ao,mirror:Sv},X={nearest:So,linear:Lv},W=n({mipmap:ko,"nearest mipmap nearest":To,"linear mipmap nearest":mc,"nearest mipmap linear":vc,"linear mipmap linear":ko},X),Y={none:0,browser:bc},ee={uint8:hi,rgba4:gv,rgb565:xv,"rgb5 a1":yv},z={alpha:mo,luminance:zi,"luminance alpha":Js,rgb:Qs,rgba:Bn,rgba4:sc,"rgb5 a1":vo,rgb565:ac},q={};c.ext_srgb&&(z.srgb=_o,z.srgba=wo),c.oes_texture_float&&(ee.float32=ee.float=Hi),c.oes_texture_half_float&&(ee.float16=ee["half float"]=di),c.webgl_depth_texture&&(n(z,{depth:bo,"depth stencil":ea}),n(ee,{uint16:Eo,uint32:Po,"depth stencil":Cv})),c.webgl_compressed_texture_s3tc&&n(q,{"rgb s3tc dxt1":go,"rgba s3tc dxt1":yo,"rgba s3tc dxt3":xo,"rgba s3tc dxt5":Co}),c.webgl_compressed_texture_atc&&n(q,{"rgb atc":oc,"rgba atc explicit alpha":lc,"rgba atc interpolated alpha":uc}),c.webgl_compressed_texture_pvrtc&&n(q,{"rgb pvrtc 4bppv1":cc,"rgb pvrtc 2bppv1":dc,"rgba pvrtc 4bppv1":hc,"rgba pvrtc 2bppv1":pc}),c.webgl_compressed_texture_etc1&&(q["rgb etc1"]=fc);var P=Array.prototype.slice.call(a.getParameter(wv));Object.keys(q).forEach(function(m){var O=q[m];P.indexOf(O)>=0&&(z[m]=O)});var R=Object.keys(z);v.textureFormats=R;var K=[];Object.keys(z).forEach(function(m){var O=z[m];K[O]=m});var ue=[];Object.keys(ee).forEach(function(m){var O=ee[m];ue[O]=m});var N=[];Object.keys(X).forEach(function(m){var O=X[m];N[O]=m});var oe=[];Object.keys(W).forEach(function(m){var O=W[m];oe[O]=m});var ie=[];Object.keys(G).forEach(function(m){var O=G[m];ie[O]=m});var ge=R.reduce(function(m,O){var k=z[O];return k===zi||k===mo||k===zi||k===Js||k===bo||k===ea||c.ext_srgb&&(k===_o||k===wo)?m[k]=k:k===vo||O.indexOf("rgba")>=0?m[k]=Bn:m[k]=Qs,m},{});function F(){this.internalformat=Bn,this.format=Bn,this.type=hi,this.compressed=!1,this.premultiplyAlpha=!1,this.flipY=!1,this.unpackAlignment=1,this.colorSpace=bc,this.width=0,this.height=0,this.channels=0}function M(m,O){m.internalformat=O.internalformat,m.format=O.format,m.type=O.type,m.compressed=O.compressed,m.premultiplyAlpha=O.premultiplyAlpha,m.flipY=O.flipY,m.unpackAlignment=O.unpackAlignment,m.colorSpace=O.colorSpace,m.width=O.width,m.height=O.height,m.channels=O.channels}function pe(m,O){if(!(typeof O!="object"||!O)){if("premultiplyAlpha"in O&&(h.type(O.premultiplyAlpha,"boolean","invalid premultiplyAlpha"),m.premultiplyAlpha=O.premultiplyAlpha),"flipY"in O&&(h.type(O.flipY,"boolean","invalid texture flip"),m.flipY=O.flipY),"alignment"in O&&(h.oneOf(O.alignment,[1,2,4,8],"invalid texture unpack alignment"),m.unpackAlignment=O.alignment),"colorSpace"in O&&(h.parameter(O.colorSpace,Y,"invalid colorSpace"),m.colorSpace=Y[O.colorSpace]),"type"in O){var k=O.type;h(c.oes_texture_float||!(k==="float"||k==="float32"),"you must enable the OES_texture_float extension in order to use floating point textures."),h(c.oes_texture_half_float||!(k==="half float"||k==="float16"),"you must enable the OES_texture_half_float extension in order to use 16-bit floating point textures."),h(c.webgl_depth_texture||!(k==="uint16"||k==="uint32"||k==="depth stencil"),"you must enable the WEBGL_depth_texture extension in order to use depth/stencil textures."),h.parameter(k,ee,"invalid texture type"),m.type=ee[k]}var he=m.width,Re=m.height,p=m.channels,u=!1;"shape"in O?(h(Array.isArray(O.shape)&&O.shape.length>=2,"shape must be an array"),he=O.shape[0],Re=O.shape[1],O.shape.length===3&&(p=O.shape[2],h(p>0&&p<=4,"invalid number of channels"),u=!0),h(he>=0&&he<=v.maxTextureSize,"invalid width"),h(Re>=0&&Re<=v.maxTextureSize,"invalid height")):("radius"in O&&(he=Re=O.radius,h(he>=0&&he<=v.maxTextureSize,"invalid radius")),"width"in O&&(he=O.width,h(he>=0&&he<=v.maxTextureSize,"invalid width")),"height"in O&&(Re=O.height,h(Re>=0&&Re<=v.maxTextureSize,"invalid height")),"channels"in O&&(p=O.channels,h(p>0&&p<=4,"invalid number of channels"),u=!0)),m.width=he|0,m.height=Re|0,m.channels=p|0;var _=!1;if("format"in O){var E=O.format;h(c.webgl_depth_texture||!(E==="depth"||E==="depth stencil"),"you must enable the WEBGL_depth_texture extension in order to use depth/stencil textures."),h.parameter(E,z,"invalid texture format");var S=m.internalformat=z[E];m.format=ge[S],E in ee&&("type"in O||(m.type=ee[E])),E in q&&(m.compressed=!0),_=!0}!u&&_?m.channels=gr[m.format]:u&&!_?m.channels!==ra[m.format]&&(m.format=m.internalformat=ra[m.channels]):_&&u&&h(m.channels===gr[m.format],"number of channels inconsistent with specified format")}}function te(m){a.pixelStorei(Iv,m.flipY),a.pixelStorei(Fv,m.premultiplyAlpha),a.pixelStorei($v,m.colorSpace),a.pixelStorei(Mv,m.unpackAlignment)}function H(){F.call(this),this.xOffset=0,this.yOffset=0,this.data=null,this.needsFree=!1,this.element=null,this.needsCopy=!1}function re(m,O){var k=null;if(Lo(O)?k=O:O&&(h.type(O,"object","invalid pixel data type"),pe(m,O),"x"in O&&(m.xOffset=O.x|0),"y"in O&&(m.yOffset=O.y|0),Lo(O.data)&&(k=O.data)),h(!m.compressed||k instanceof Uint8Array,"compressed texture data must be stored in a uint8array"),O.copy){h(!k,"can not specify copy and data field for the same texture");var he=I.viewportWidth,Re=I.viewportHeight;m.width=m.width||he-m.xOffset,m.height=m.height||Re-m.yOffset,m.needsCopy=!0,h(m.xOffset>=0&&m.xOffset=0&&m.yOffset0&&m.width<=he&&m.height>0&&m.height<=Re,"copy texture read out of bounds")}else if(!k)m.width=m.width||1,m.height=m.height||1,m.channels=m.channels||4;else if(t(k))m.channels=m.channels||4,m.data=k,!("type"in O)&&m.type===hi&&(m.type=Tc(k));else if(Ec(k))m.channels=m.channels||4,Hv(m,k),m.alignment=1,m.needsFree=!0;else if(Sr(k)){var p=k.data;!Array.isArray(p)&&m.type===hi&&(m.type=Tc(p));var u=k.shape,_=k.stride,E,S,g,w,C,d;u.length===3?(g=u[2],d=_[2]):(h(u.length===2,"invalid ndarray pixel data, must be 2 or 3D"),g=1,d=1),E=u[0],S=u[1],w=_[0],C=_[1],m.alignment=1,m.width=E,m.height=S,m.channels=g,m.format=m.internalformat=ra[g],m.needsFree=!0,Kv(m,p,w,C,d,k.offset)}else if(Ac(k)||Sc(k)||Gv(k))Ac(k)||Sc(k)?m.element=k:m.element=k.canvas,m.width=m.element.width,m.height=m.element.height,m.channels=4;else if(jv(k))m.element=k,m.width=k.width,m.height=k.height,m.channels=4;else if(Uv(k))m.element=k,m.width=k.naturalWidth,m.height=k.naturalHeight,m.channels=4;else if(zv(k))m.element=k,m.width=k.videoWidth,m.height=k.videoHeight,m.channels=4;else if(Pc(k)){var b=m.width||k[0].length,f=m.height||k.length,A=m.channels;pt(k[0][0])?A=A||k[0][0].length:A=A||1;for(var T=Xs.shape(k),$=1,Q=0;Q=0,"oes_texture_float extension not enabled"):m.type===di&&h(v.extensions.indexOf("oes_texture_half_float")>=0,"oes_texture_half_float extension not enabled")}function ne(m,O,k){var he=m.element,Re=m.data,p=m.internalformat,u=m.format,_=m.type,E=m.width,S=m.height;te(m),he?a.texImage2D(O,k,u,u,_,he):m.compressed?a.compressedTexImage2D(O,k,p,E,S,0,Re):m.needsCopy?(V(),a.copyTexImage2D(O,k,u,m.xOffset,m.yOffset,E,S,0)):a.texImage2D(O,k,u,E,S,0,u,_,Re||null)}function Le(m,O,k,he,Re){var p=m.element,u=m.data,_=m.internalformat,E=m.format,S=m.type,g=m.width,w=m.height;te(m),p?a.texSubImage2D(O,Re,k,he,E,S,p):m.compressed?a.compressedTexSubImage2D(O,Re,k,he,_,g,w,u):m.needsCopy?(V(),a.copyTexSubImage2D(O,Re,k,he,m.xOffset,m.yOffset,g,w)):a.texSubImage2D(O,Re,k,he,g,w,E,S,u)}var Te=[];function se(){return Te.pop()||new H}function le(m){m.needsFree&>.freeType(m.data),H.call(m),Te.push(m)}function Ee(){F.call(this),this.genMipmaps=!1,this.mipmapHint=ta,this.mipmask=0,this.images=Array(16)}function ke(m,O,k){var he=m.images[0]=se();m.mipmask=1,he.width=m.width=O,he.height=m.height=k,he.channels=m.channels=4}function De(m,O){var k=null;if(Lo(O))k=m.images[0]=se(),M(k,m),re(k,O),m.mipmask=1;else if(pe(m,O),Array.isArray(O.mipmap))for(var he=O.mipmap,Re=0;Re>=Re,k.height>>=Re,re(k,he[Re]),m.mipmask|=1<=0&&!("faces"in O)&&(m.genMipmaps=!0)}if("mag"in O){var he=O.mag;h.parameter(he,X),m.magFilter=X[he]}var Re=m.wrapS,p=m.wrapT;if("wrap"in O){var u=O.wrap;typeof u=="string"?(h.parameter(u,G),Re=p=G[u]):Array.isArray(u)&&(h.parameter(u[0],G),h.parameter(u[1],G),Re=G[u[0]],p=G[u[1]])}else{if("wrapS"in O){var _=O.wrapS;h.parameter(_,G),Re=G[_]}if("wrapT"in O){var E=O.wrapT;h.parameter(E,G),p=G[E]}}if(m.wrapS=Re,m.wrapT=p,"anisotropic"in O){var S=O.anisotropic;h(typeof S=="number"&&S>=1&&S<=v.maxAnisotropic,"aniso samples must be between 1 and "),m.anisotropic=O.anisotropic}if("mipmap"in O){var g=!1;switch(typeof O.mipmap){case"string":h.parameter(O.mipmap,j,"invalid mipmap hint"),m.mipmapHint=j[O.mipmap],m.genMipmaps=!0,g=!0;break;case"boolean":g=m.genMipmaps=O.mipmap;break;case"object":h(Array.isArray(O.mipmap),"invalid mipmap type"),m.genMipmaps=!1,g=!0;break;default:h.raise("invalid mipmap type")}g&&!("min"in O)&&(m.minFilter=To)}}function Et(m,O){a.texParameteri(O,kv,m.minFilter),a.texParameteri(O,Tv,m.magFilter),a.texParameteri(O,Ev,m.wrapS),a.texParameteri(O,Pv,m.wrapT),c.ext_texture_filter_anisotropic&&a.texParameteri(O,Dv,m.anisotropic),m.genMipmaps&&(a.hint(Vv,m.mipmapHint),a.generateMipmap(O))}var Pt=0,Vt={},Nt=v.maxTextureUnits,ft=Array(Nt).map(function(){return null});function Oe(m){F.call(this),this.mipmask=0,this.internalformat=Bn,this.id=Pt++,this.refCount=1,this.target=m,this.texture=a.createTexture(),this.unit=-1,this.bindCount=0,this.texInfo=new ot,D.profile&&(this.stats={size:0})}function Gt(m){a.activeTexture(Ki),a.bindTexture(m.target,m.texture)}function ze(){var m=ft[0];m?a.bindTexture(m.target,m.texture):a.bindTexture(Rr,null)}function xe(m){var O=m.texture;h(O,"must not double destroy texture");var k=m.unit,he=m.target;k>=0&&(a.activeTexture(Ki+k),a.bindTexture(he,null),ft[k]=null),a.deleteTexture(O),m.texture=null,m.params=null,m.pixels=null,m.refCount=0,delete Vt[m.id],L.textureCount--}n(Oe.prototype,{bind:function(){var m=this;m.bindCount+=1;var O=m.unit;if(O<0){for(var k=0;k0)continue;he.unit=-1}ft[k]=m,O=k;break}O>=Nt&&h.raise("insufficient number of texture units"),D.profile&&L.maxTextureUnits>C)-g,d.height=d.height||(k.height>>C)-w,h(k.type===d.type&&k.format===d.format&&k.internalformat===d.internalformat,"incompatible format for texture.subimage"),h(g>=0&&w>=0&&g+d.width<=k.width&&w+d.height<=k.height,"texture.subimage write out of bounds"),h(k.mipmask&1<>g;++g){var w=E>>g,C=S>>g;if(!w||!C)break;a.texImage2D(Rr,g,k.format,w,C,0,k.format,k.type,null)}return ze(),D.profile&&(k.stats.size=na(k.internalformat,k.type,E,S,!1,!1)),he}return he(m,O),he.subimage=Re,he.resize=p,he._reglType="texture2d",he._texture=k,D.profile&&(he.stats=k.stats),he.destroy=function(){k.decRef()},he}function Be(m,O,k,he,Re,p){var u=new Oe(fo);Vt[u.id]=u,L.cubeCount++;var _=new Array(6);function E(w,C,d,b,f,A){var T,$=u.texInfo;for(ot.call($),T=0;T<6;++T)_[T]=Fe();if(typeof w=="number"||!w){var Q=w|0||1;for(T=0;T<6;++T)ke(_[T],Q,Q)}else if(typeof w=="object")if(C)De(_[0],w),De(_[1],C),De(_[2],d),De(_[3],b),De(_[4],f),De(_[5],A);else if(xt($,w),pe(u,w),"faces"in w){var J=w.faces;for(h(Array.isArray(J)&&J.length===6,"cube faces must be a length 6 array"),T=0;T<6;++T)h(typeof J[T]=="object"&&!!J[T],"invalid input for cube map face"),M(_[T],u),De(_[T],J[T])}else for(T=0;T<6;++T)De(_[T],w);else h.raise("invalid arguments to cube map");for(M(u,_[0]),h.optional(function(){v.npotTextureCube||h(ic(u.width)&&ic(u.height),"your browser does not support non power or two texture dimensions")}),$.genMipmaps?u.mipmask=(_[0].width<<1)-1:u.mipmask=_[0].mipmask,h.textureCube(u,$,_,v),u.internalformat=_[0].internalformat,E.width=_[0].width,E.height=_[0].height,Gt(u),T=0;T<6;++T)lt(_[T],Zs+T);for(Et($,fo),ze(),D.profile&&(u.stats.size=na(u.internalformat,u.type,E.width,E.height,$.genMipmaps,!0)),E.format=K[u.internalformat],E.type=ue[u.type],E.mag=N[$.magFilter],E.min=oe[$.minFilter],E.wrapS=ie[$.wrapS],E.wrapT=ie[$.wrapT],T=0;T<6;++T)Ct(_[T]);return E}function S(w,C,d,b,f){h(!!C,"must specify image data"),h(typeof w=="number"&&w===(w|0)&&w>=0&&w<6,"invalid face");var A=d|0,T=b|0,$=f|0,Q=se();return M(Q,u),Q.width=0,Q.height=0,re(Q,C),Q.width=Q.width||(u.width>>$)-A,Q.height=Q.height||(u.height>>$)-T,h(u.type===Q.type&&u.format===Q.format&&u.internalformat===Q.internalformat,"incompatible format for texture.subimage"),h(A>=0&&T>=0&&A+Q.width<=u.width&&T+Q.height<=u.height,"texture.subimage write out of bounds"),h(u.mipmask&1<<$,"missing mipmap data"),h(Q.data||Q.element||Q.needsCopy,"missing image data"),Gt(u),Le(Q,Zs+w,A,T,$),ze(),le(Q),E}function g(w){var C=w|0;if(C!==u.width){E.width=u.width=C,E.height=u.height=C,Gt(u);for(var d=0;d<6;++d)for(var b=0;u.mipmask>>b;++b)a.texImage2D(Zs+d,b,u.format,C>>b,C>>b,0,u.format,u.type,null);return ze(),D.profile&&(u.stats.size=na(u.internalformat,u.type,E.width,E.height,!1,!0)),E}}return E(m,O,k,he,Re,p),E.subimage=S,E.resize=g,E._reglType="textureCube",E._texture=u,D.profile&&(E.stats=u.stats),E.destroy=function(){u.decRef()},E}function mt(){for(var m=0;m>he,k.height>>he,0,k.internalformat,k.type,null);else for(var Re=0;Re<6;++Re)a.texImage2D(Zs+Re,he,k.internalformat,k.width>>he,k.height>>he,0,k.internalformat,k.type,null);Et(k.texInfo,k.target)})}function qn(){for(var m=0;m=2,"invalid renderbuffer shape"),oe=M[0]|0,ie=M[1]|0}else"radius"in F&&(oe=ie=F.radius|0),"width"in F&&(oe=F.width|0),"height"in F&&(ie=F.height|0);"format"in F&&(h.parameter(F.format,L,"invalid renderbuffer format"),ge=L[F.format])}else typeof ue=="number"?(oe=ue|0,typeof N=="number"?ie=N|0:ie=oe):ue?h.raise("invalid arguments to renderbuffer constructor"):oe=ie=1;if(h(oe>0&&ie>0&&oe<=v.maxRenderbufferSize&&ie<=v.maxRenderbufferSize,"invalid renderbuffer size"),!(oe===P.width&&ie===P.height&&ge===P.format))return R.width=P.width=oe,R.height=P.height=ie,P.format=ge,a.bindRenderbuffer(mn,P.renderbuffer),a.renderbufferStorage(mn,ge,oe,ie),h(a.getError()===0,"invalid render buffer format"),I.profile&&(P.stats.size=Nc(P.format,P.width,P.height)),R.format=D[P.format],R}function K(ue,N){var oe=ue|0,ie=N|0||oe;return oe===P.width&&ie===P.height||(h(oe>0&&ie>0&&oe<=v.maxRenderbufferSize&&ie<=v.maxRenderbufferSize,"invalid renderbuffer size"),R.width=P.width=oe,R.height=P.height=ie,a.bindRenderbuffer(mn,P.renderbuffer),a.renderbufferStorage(mn,P.format,oe,ie),h(a.getError()===0,"invalid render buffer format"),I.profile&&(P.stats.size=Nc(P.format,P.width,P.height))),R}return R(z,q),R.resize=K,R._reglType="renderbuffer",R._renderbuffer=P,I.profile&&(R.stats=P.stats),R.destroy=function(){P.decRef()},R}I.profile&&(V.getTotalRenderbufferSize=function(){var z=0;return Object.keys(G).forEach(function(q){z+=G[q].stats.size}),z});function ee(){hr(G).forEach(function(z){z.renderbuffer=a.createRenderbuffer(),a.bindRenderbuffer(mn,z.renderbuffer),a.renderbufferStorage(mn,z.format,z.width,z.height)}),a.bindRenderbuffer(mn,null)}return{create:Y,clear:function(){hr(G).forEach(W)},restore:ee}},Xr=36160,Vo=36161,Gn=3553,sa=34069,Gc=36064,jc=36096,Uc=36128,zc=33306,Hc=36053,Yv=36054,Wv=36055,Zv=36057,Qv=36061,Jv=36193,eb=5121,tb=5126,Kc=6407,qc=6408,rb=6402,nb=[Kc,qc],Oo=[];Oo[qc]=4,Oo[Kc]=3;var aa=[];aa[eb]=1,aa[tb]=4,aa[Jv]=2;var ib=32854,sb=32855,ab=36194,ob=33189,lb=36168,Xc=34041,ub=35907,cb=34836,db=34842,hb=34843,pb=[ib,sb,ab,ub,db,hb,cb],mi={};mi[Hc]="complete",mi[Yv]="incomplete attachment",mi[Zv]="incomplete dimensions",mi[Wv]="incomplete, missing attachment",mi[Qv]="unsupported";function fb(a,c,v,V,I,L){var D={cur:null,next:null,dirty:!1,setFBO:null},j=["rgba"],G=["rgba4","rgb565","rgb5 a1"];c.ext_srgb&&G.push("srgba"),c.ext_color_buffer_half_float&&G.push("rgba16f","rgb16f"),c.webgl_color_buffer_float&&G.push("rgba32f");var X=["uint8"];c.oes_texture_half_float&&X.push("half float","float16"),c.oes_texture_float&&X.push("float","float32");function W(H,re,ne){this.target=H,this.texture=re,this.renderbuffer=ne;var Le=0,Te=0;re?(Le=re.width,Te=re.height):ne&&(Le=ne.width,Te=ne.height),this.width=Le,this.height=Te}function Y(H){H&&(H.texture&&H.texture._texture.decRef(),H.renderbuffer&&H.renderbuffer._renderbuffer.decRef())}function ee(H,re,ne){if(H)if(H.texture){var Le=H.texture._texture,Te=Math.max(1,Le.width),se=Math.max(1,Le.height);h(Te===re&&se===ne,"inconsistent width/height for supplied texture"),Le.refCount+=1}else{var le=H.renderbuffer._renderbuffer;h(le.width===re&&le.height===ne,"inconsistent width/height for renderbuffer"),le.refCount+=1}}function z(H,re){re&&(re.texture?a.framebufferTexture2D(Xr,H,re.target,re.texture._texture.texture,0):a.framebufferRenderbuffer(Xr,H,Vo,re.renderbuffer._renderbuffer.renderbuffer))}function q(H){var re=Gn,ne=null,Le=null,Te=H;typeof H=="object"&&(Te=H.data,"target"in H&&(re=H.target|0)),h.type(Te,"function","invalid attachment data");var se=Te._reglType;return se==="texture2d"?(ne=Te,h(re===Gn)):se==="textureCube"?(ne=Te,h(re>=sa&&re=2,"invalid shape for framebuffer"),ke=Gt[0],De=Gt[1]}else"radius"in Oe&&(ke=De=Oe.radius),"width"in Oe&&(ke=Oe.width),"height"in Oe&&(De=Oe.height);("color"in Oe||"colors"in Oe)&&(Fe=Oe.color||Oe.colors,Array.isArray(Fe)&&h(Fe.length===1||c.webgl_draw_buffers,"multiple render targets not supported")),Fe||("colorCount"in Oe&&(Et=Oe.colorCount|0,h(Et>0,"invalid color buffer count")),"colorTexture"in Oe&&(Ct=!!Oe.colorTexture,ot="rgba4"),"colorType"in Oe&&(xt=Oe.colorType,Ct?(h(c.oes_texture_float||!(xt==="float"||xt==="float32"),"you must enable OES_texture_float in order to use floating point framebuffer objects"),h(c.oes_texture_half_float||!(xt==="half float"||xt==="float16"),"you must enable OES_texture_half_float in order to use 16-bit floating point framebuffer objects")):xt==="half float"||xt==="float16"?(h(c.ext_color_buffer_half_float,"you must enable EXT_color_buffer_half_float to use 16-bit render buffers"),ot="rgba16f"):(xt==="float"||xt==="float32")&&(h(c.webgl_color_buffer_float,"you must enable WEBGL_color_buffer_float in order to use 32-bit floating point renderbuffers"),ot="rgba32f"),h.oneOf(xt,X,"invalid color type")),"colorFormat"in Oe&&(ot=Oe.colorFormat,j.indexOf(ot)>=0?Ct=!0:G.indexOf(ot)>=0?Ct=!1:h.optional(function(){Ct?h.oneOf(Oe.colorFormat,j,"invalid color format for texture"):h.oneOf(Oe.colorFormat,G,"invalid color format for renderbuffer")}))),("depthTexture"in Oe||"depthStencilTexture"in Oe)&&(ft=!!(Oe.depthTexture||Oe.depthStencilTexture),h(!ft||c.webgl_depth_texture,"webgl_depth_texture extension not supported")),"depth"in Oe&&(typeof Oe.depth=="boolean"?lt=Oe.depth:(Pt=Oe.depth,ct=!1)),"stencil"in Oe&&(typeof Oe.stencil=="boolean"?ct=Oe.stencil:(Vt=Oe.stencil,lt=!1)),"depthStencil"in Oe&&(typeof Oe.depthStencil=="boolean"?lt=ct=Oe.depthStencil:(Nt=Oe.depthStencil,lt=!1,ct=!1))}var ze=null,xe=null,Me=null,Be=null;if(Array.isArray(Fe))ze=Fe.map(q);else if(Fe)ze=[q(Fe)];else for(ze=new Array(Et),Ee=0;Ee=0||ze[Ee].renderbuffer&&pb.indexOf(ze[Ee].renderbuffer._renderbuffer.format)>=0,"framebuffer color attachment "+Ee+" is invalid"),ze[Ee]&&ze[Ee].texture){var Mr=Oo[ze[Ee].texture._texture.format]*aa[ze[Ee].texture._texture.type];mt===null?mt=Mr:h(mt===Mr,"all color attachments much have the same number of bits per pixel.")}return ee(xe,ke,De),h(!xe||xe.texture&&xe.texture._texture.format===rb||xe.renderbuffer&&xe.renderbuffer._renderbuffer.format===ob,"invalid depth attachment for framebuffer object"),ee(Me,ke,De),h(!Me||Me.renderbuffer&&Me.renderbuffer._renderbuffer.format===lb,"invalid stencil attachment for framebuffer object"),ee(Be,ke,De),h(!Be||Be.texture&&Be.texture._texture.format===Xc||Be.renderbuffer&&Be.renderbuffer._renderbuffer.format===Xc,"invalid depth-stencil attachment for framebuffer object"),ie(ne),ne.width=ke,ne.height=De,ne.colorAttachments=ze,ne.depthAttachment=xe,ne.stencilAttachment=Me,ne.depthStencilAttachment=Be,Le.color=ze.map(R),Le.depth=R(xe),Le.stencil=R(Me),Le.depthStencil=R(Be),Le.width=ne.width,Le.height=ne.height,F(ne),Le}function Te(se,le){h(D.next!==ne,"can not resize a framebuffer which is currently in use");var Ee=Math.max(se|0,1),ke=Math.max(le|0||Ee,1);if(Ee===ne.width&&ke===ne.height)return Le;for(var De=ne.colorAttachments,lt=0;lt=2,"invalid shape for framebuffer"),h(Ct[0]===Ct[1],"cube framebuffer must be square"),Ee=Ct[0]}else"radius"in Fe&&(Ee=Fe.radius|0),"width"in Fe?(Ee=Fe.width|0,"height"in Fe&&h(Fe.height===Ee,"must be square")):"height"in Fe&&(Ee=Fe.height|0);("color"in Fe||"colors"in Fe)&&(ke=Fe.color||Fe.colors,Array.isArray(ke)&&h(ke.length===1||c.webgl_draw_buffers,"multiple render targets not supported")),ke||("colorCount"in Fe&&(ct=Fe.colorCount|0,h(ct>0,"invalid color buffer count")),"colorType"in Fe&&(h.oneOf(Fe.colorType,X,"invalid color type"),lt=Fe.colorType),"colorFormat"in Fe&&(De=Fe.colorFormat,h.oneOf(Fe.colorFormat,j,"invalid color format for texture"))),"depth"in Fe&&(le.depth=Fe.depth),"stencil"in Fe&&(le.stencil=Fe.stencil),"depthStencil"in Fe&&(le.depthStencil=Fe.depthStencil)}var ot;if(ke)if(Array.isArray(ke))for(ot=[],se=0;se0&&(le.depth=re[0].depth,le.stencil=re[0].stencil,le.depthStencil=re[0].depthStencil),re[se]?re[se](le):re[se]=M(le)}return n(ne,{width:Ee,height:Ee,color:ot})}function Le(Te){var se,le=Te|0;if(h(le>0&&le<=v.maxCubeMapSize,"invalid radius for cube fbo"),le===ne.width)return ne;var Ee=ne.color;for(se=0;se{for(var lt=Object.keys(te),ct=0;ct=0,'invalid option for vao: "'+lt[ct]+'" valid options are '+Wc)}),h(Array.isArray(H),"attributes must be an array")}h(H.length0,"must specify at least one attribute");var ne={},Le=M.attributes;Le.length=H.length;for(var Te=0;Te=Ee.byteLength?ke.subdata(Ee):(ke.destroy(),M.buffers[Te]=null)),M.buffers[Te]||(ke=M.buffers[Te]=I.create(se,Yc,!1,!0)),le.buffer=I.getBuffer(ke),le.size=le.buffer.dimension|0,le.normalized=!1,le.type=le.buffer.dtype,le.offset=0,le.stride=0,le.divisor=0,le.state=1,ne[Te]=1}else I.getBuffer(se)?(le.buffer=I.getBuffer(se),le.size=le.buffer.dimension|0,le.normalized=!1,le.type=le.buffer.dtype,le.offset=0,le.stride=0,le.divisor=0,le.state=1):I.getBuffer(se.buffer)?(le.buffer=I.getBuffer(se.buffer),le.size=(+se.size||le.buffer.dimension)|0,le.normalized=!!se.normalized||!1,"type"in se?(h.parameter(se.type,Fn,"invalid buffer type"),le.type=Fn[se.type]):le.type=le.buffer.dtype,le.offset=(se.offset||0)|0,le.stride=(se.stride||0)|0,le.divisor=(se.divisor||0)|0,le.state=1,h(le.size>=1&&le.size<=4,"size must be between 1 and 4"),h(le.offset>=0,"invalid offset"),h(le.stride>=0&&le.stride<=255,"stride must be between 0 and 255"),h(le.divisor>=0,"divisor must be positive"),h(!le.divisor||!!c.angle_instanced_arrays,"ANGLE_instanced_arrays must be enabled to use divisor")):"x"in se?(h(Te>0,"first attribute must not be a constant"),le.x=+se.x||0,le.y=+se.y||0,le.z=+se.z||0,le.w=+se.w||0,le.state=2):h(!1,"invalid attribute spec for location "+Te)}for(var De=0;De1)for(var te=0;teP&&(P=R.stats.uniformsCount)}),P},v.getMaxAttributesCount=function(){var P=0;return W.forEach(function(R){R.stats.attributesCount>P&&(P=R.stats.attributesCount)}),P});function q(){I={},L={};for(var P=0;P=0,"missing vertex shader",K),h.command(R>=0,"missing fragment shader",K);var N=X[R];N||(N=X[R]={});var oe=N[P];if(oe&&(oe.refCount++,!ue))return oe;var ie=new ee(R,P);return v.shaderCount++,z(ie,K,ue),oe||(N[P]=ie),W.push(ie),n(ie,{destroy:function(){if(ie.refCount--,ie.refCount<=0){a.deleteProgram(ie.program);var ge=W.indexOf(ie);W.splice(ge,1),v.shaderCount--}N[ie.vertId].refCount<=0&&(a.deleteShader(L[ie.vertId]),delete L[ie.vertId],delete X[ie.fragId][ie.vertId]),Object.keys(X[ie.fragId]).length||(a.deleteShader(I[ie.fragId]),delete I[ie.fragId],delete X[ie.fragId])}})},restore:q,shader:G,frag:-1,vert:-1}}var yb=6408,qi=5121,xb=3333,la=5126;function Cb(a,c,v,V,I,L,D){function j(W){var Y;c.next===null?(h(I.preserveDrawingBuffer,'you must create a webgl context with "preserveDrawingBuffer":true in order to read pixels from the drawing buffer'),Y=qi):(h(c.next.colorAttachments[0].texture!==null,"You cannot read from a renderbuffer"),Y=c.next.colorAttachments[0].texture._texture.type,h.optional(function(){L.oes_texture_float?(h(Y===qi||Y===la,"Reading from a framebuffer is only allowed for the types 'uint8' and 'float'"),Y===la&&h(D.readFloat,"Reading 'float' values is not permitted in your browser. For a fallback, please see: https://www.npmjs.com/package/glsl-read-float")):h(Y===qi,"Reading from a framebuffer is only allowed for the type 'uint8'")}));var ee=0,z=0,q=V.framebufferWidth,P=V.framebufferHeight,R=null;t(W)?R=W:W&&(h.type(W,"object","invalid arguments to regl.read()"),ee=W.x|0,z=W.y|0,h(ee>=0&&ee=0&&z0&&q+ee<=V.framebufferWidth,"invalid width for read pixels"),h(P>0&&P+z<=V.framebufferHeight,"invalid height for read pixels"),v();var K=q*P*4;return R||(Y===qi?R=new Uint8Array(K):Y===la&&(R=R||new Float32Array(K))),h.isTypedArray(R,"data buffer for regl.read() must be a typedarray"),h(R.byteLength>=K,"data buffer for regl.read() too small"),a.pixelStorei(xb,4),a.readPixels(ee,z,q,P,yb,Y,R),R}function G(W){var Y;return c.setFBO({framebuffer:W.framebuffer},function(){Y=j(W)}),Y}function X(W){return!W||!("framebuffer"in W)?j(W):G(W)}return X}function vi(a){return Array.prototype.slice.call(a)}function bi(a){return vi(a).join("")}function Eb(){var a=0,c=[],v=[];function V(Y){for(var ee=0;ee0&&(Y.push(P,"="),Y.push.apply(Y,vi(arguments)),Y.push(";")),P}return n(ee,{def:q,toString:function(){return bi([z.length>0?"var "+z.join(",")+";":"",bi(Y)])}})}function L(){var Y=I(),ee=I(),z=Y.toString,q=ee.toString;function P(R,K){ee(R,K,"=",Y.def(R,K),";")}return n(function(){Y.apply(Y,vi(arguments))},{def:Y.def,entry:Y,exit:ee,save:P,set:function(R,K,ue){P(R,K),Y(R,K,"=",ue,";")},toString:function(){return z()+q()}})}function D(){var Y=bi(arguments),ee=L(),z=L(),q=ee.toString,P=z.toString;return n(ee,{then:function(){return ee.apply(ee,vi(arguments)),this},else:function(){return z.apply(z,vi(arguments)),this},toString:function(){var R=P();return R&&(R="else{"+R+"}"),bi(["if(",Y,"){",q(),"}",R])}})}var j=I(),G={};function X(Y,ee){var z=[];function q(){var N="a"+z.length;return z.push(N),N}ee=ee||0;for(var P=0;P":516,notequal:517,"!=":517,"!==":517,gequal:518,">=":518,always:519},bn={0:0,zero:0,keep:7680,replace:7681,increment:7682,decrement:7683,"increment wrap":34055,"decrement wrap":34056,invert:5386},Ad={frag:Tb,vert:kb},rl={cw:gd,ccw:tl};function xa(a){return Array.isArray(a)||t(a)||Sr(a)}function Sd(a){return a.sort(function(c,v){return c===Yr?-1:v===Yr?1:c=1,V>=2,c)}else if(v===ua){var I=a.data;return new Tt(I.thisDep,I.contextDep,I.propDep,c)}else{if(v===Jc)return new Tt(!1,!1,!1,c);if(v===ed){for(var L=!1,D=!1,j=!1,G=0;G=1&&(D=!0),W>=2&&(j=!0)}else X.type===ua&&(L=L||X.data.thisDep,D=D||X.data.contextDep,j=j||X.data.propDep)}return new Tt(L,D,j,c)}else return new Tt(v===$o,v===Fo,v===Io,c)}}var Td=new Tt(!1,!1,!1,function(){});function Hb(a,c,v,V,I,L,D,j,G,X,W,Y,ee,z,q){var P=X.Record,R={add:32774,subtract:32778,"reverse subtract":32779};v.ext_blend_minmax&&(R.min=Nb,R.max=Gb);var K=v.angle_instanced_arrays,ue=v.webgl_draw_buffers,N=v.oes_vertex_array_object,oe={dirty:!0,profile:q.profile},ie={},ge=[],F={},M={};function pe(p){return p.replace(".","_")}function te(p,u,_){var E=pe(p);ge.push(p),ie[E]=oe[E]=!!_,F[E]=u}function H(p,u,_){var E=pe(p);ge.push(p),Array.isArray(_)?(oe[E]=_.slice(),ie[E]=_.slice()):oe[E]=ie[E]=_,M[E]=u}te(td,Rb),te(rd,Ob),H(nd,"blendColor",[0,0,0,0]),H(Bo,"blendEquationSeparate",[Cd,Cd]),H(No,"blendFuncSeparate",[xd,yd,xd,yd]),te(id,Mb,!0),H(sd,"depthFunc",Ub),H(ad,"depthRange",[0,1]),H(od,"depthMask",!0),H(Go,Go,[!0,!0,!0,!0]),te(ld,Vb),H(ud,"cullFace",Kn),H(jo,jo,tl),H(Uo,Uo,1),te(cd,Fb),H(zo,"polygonOffset",[0,0]),te(dd,$b),te(hd,Bb),H(Ho,"sampleCoverage",[1,!1]),te(pd,Db),H(fd,"stencilMask",-1),H(Ko,"stencilFunc",[jb,0,-1]),H(qo,"stencilOpSeparate",[is,vn,vn,vn]),H(Xi,"stencilOpSeparate",[Kn,vn,vn,vn]),te(md,Ib),H(ca,"scissor",[0,0,a.drawingBufferWidth,a.drawingBufferHeight]),H(Yr,Yr,[0,0,a.drawingBufferWidth,a.drawingBufferHeight]);var re={gl:a,context:ee,strings:c,next:ie,current:oe,draw:Y,elements:L,buffer:I,shader:W,attributes:X.state,vao:X,uniforms:G,framebuffer:j,extensions:v,timer:z,isBufferArgs:xa},ne={primTypes:fn,compareFuncs:Ci,blendFuncs:Dr,blendEquations:R,stencilOps:bn,glTypes:Fn,orientationType:rl};h.optional(function(){re.isArrayLike=pt}),ue&&(ne.backBuffer=[Kn],ne.drawBuffer=dr(V.maxDrawbuffers,function(p){return p===0?[0]:dr(p,function(u){return zb+u})}));var Le=0;function Te(){var p=Eb(),u=p.link,_=p.global;p.id=Le++,p.batchId="0";var E=u(re),S=p.shared={props:"a0"};Object.keys(re).forEach(function(b){S[b]=_.def(E,".",b)}),h.optional(function(){p.CHECK=u(h),p.commandStr=h.guessCommand(),p.command=u(p.commandStr),p.assert=function(b,f,A){b("if(!(",f,"))",this.CHECK,".commandRaise(",u(A),",",this.command,");")},ne.invalidBlendCombinations=Pd});var g=p.next={},w=p.current={};Object.keys(M).forEach(function(b){Array.isArray(oe[b])&&(g[b]=_.def(S.next,".",b),w[b]=_.def(S.current,".",b))});var C=p.constants={};Object.keys(ne).forEach(function(b){C[b]=_.def(JSON.stringify(ne[b]))}),p.invoke=function(b,f){switch(f.type){case Mo:var A=["this",S.context,S.props,p.batchId];return b.def(u(f.data),".call(",A.slice(0,Math.max(f.data.length+1,4)),")");case Io:return b.def(S.props,f.data);case Fo:return b.def(S.context,f.data);case $o:return b.def("this",f.data);case ua:return f.data.append(p,b),f.data.ref;case Jc:return f.data.toString();case ed:return f.data.map(function(T){return p.invoke(b,T)})}},p.attribCache={};var d={};return p.scopeAttrib=function(b){var f=c.id(b);if(f in d)return d[f];var A=X.scope[f];A||(A=X.scope[f]=new P);var T=d[f]=u(A);return T},p}function se(p){var u=p.static,_=p.dynamic,E;if(Yi in u){var S=!!u[Yi];E=yt(function(w,C){return S}),E.enable=S}else if(Yi in _){var g=_[Yi];E=sr(g,function(w,C){return w.invoke(C,g)})}return E}function le(p,u){var _=p.static,E=p.dynamic;if(jn in _){var S=_[jn];return S?(S=j.getFramebuffer(S),h.command(S,"invalid framebuffer object"),yt(function(w,C){var d=w.link(S),b=w.shared;C.set(b.framebuffer,".next",d);var f=b.context;return C.set(f,"."+gi,d+".width"),C.set(f,"."+yi,d+".height"),d})):yt(function(w,C){var d=w.shared;C.set(d.framebuffer,".next","null");var b=d.context;return C.set(b,"."+gi,b+"."+bd),C.set(b,"."+yi,b+"."+_d),"null"})}else if(jn in E){var g=E[jn];return sr(g,function(w,C){var d=w.invoke(C,g),b=w.shared,f=b.framebuffer,A=C.def(f,".getFramebuffer(",d,")");h.optional(function(){w.assert(C,"!"+d+"||"+A,"invalid framebuffer object")}),C.set(f,".next",A);var T=b.context;return C.set(T,"."+gi,A+"?"+A+".width:"+T+"."+bd),C.set(T,"."+yi,A+"?"+A+".height:"+T+"."+_d),A})}else return null}function Ee(p,u,_){var E=p.static,S=p.dynamic;function g(d){if(d in E){var b=E[d];h.commandType(b,"object","invalid "+d,_.commandStr);var f=!0,A=b.x|0,T=b.y|0,$,Q;return"width"in b?($=b.width|0,h.command($>=0,"invalid "+d,_.commandStr)):f=!1,"height"in b?(Q=b.height|0,h.command(Q>=0,"invalid "+d,_.commandStr)):f=!1,new Tt(!f&&u&&u.thisDep,!f&&u&&u.contextDep,!f&&u&&u.propDep,function(Z,ve){var ce=Z.shared.context,fe=$;"width"in b||(fe=ve.def(ce,".",gi,"-",A));var me=Q;return"height"in b||(me=ve.def(ce,".",yi,"-",T)),[A,T,fe,me]})}else if(d in S){var J=S[d],ae=sr(J,function(Z,ve){var ce=Z.invoke(ve,J);h.optional(function(){Z.assert(ve,ce+"&&typeof "+ce+'==="object"',"invalid "+d)});var fe=Z.shared.context,me=ve.def(ce,".x|0"),be=ve.def(ce,".y|0"),Pe=ve.def('"width" in ',ce,"?",ce,".width|0:","(",fe,".",gi,"-",me,")"),Je=ve.def('"height" in ',ce,"?",ce,".height|0:","(",fe,".",yi,"-",be,")");return h.optional(function(){Z.assert(ve,Pe+">=0&&"+Je+">=0","invalid "+d)}),[me,be,Pe,Je]});return u&&(ae.thisDep=ae.thisDep||u.thisDep,ae.contextDep=ae.contextDep||u.contextDep,ae.propDep=ae.propDep||u.propDep),ae}else return u?new Tt(u.thisDep,u.contextDep,u.propDep,function(Z,ve){var ce=Z.shared.context;return[0,0,ve.def(ce,".",gi),ve.def(ce,".",yi)]}):null}var w=g(Yr);if(w){var C=w;w=new Tt(w.thisDep,w.contextDep,w.propDep,function(d,b){var f=C.append(d,b),A=d.shared.context;return b.set(A,"."+Pb,f[2]),b.set(A,"."+Ab,f[3]),f})}return{viewport:w,scissor_box:g(ca)}}function ke(p,u){var _=p.static,E=typeof _[Zi]=="string"&&typeof _[Wi]=="string";if(E){if(Object.keys(u.dynamic).length>0)return null;var S=u.static,g=Object.keys(S);if(g.length>0&&typeof S[g[0]]=="number"){for(var w=[],C=0;C=0,"invalid "+ve,u.commandStr),yt(function(be,Pe){return ce&&(be.OFFSET=fe),fe})}else if(ve in E){var me=E[ve];return sr(me,function(be,Pe){var Je=be.invoke(Pe,me);return ce&&(be.OFFSET=Je,h.optional(function(){be.assert(Pe,Je+">=0","invalid "+ve)})),Je})}else if(ce){if(d)return yt(function(be,Pe){return be.OFFSET=0,0});if(g)return new Tt(C.thisDep,C.contextDep,C.propDep,function(be,Pe){return Pe.def(be.shared.vao+".currentVAO?"+be.shared.vao+".currentVAO.offset:0")})}else if(g)return new Tt(C.thisDep,C.contextDep,C.propDep,function(be,Pe){return Pe.def(be.shared.vao+".currentVAO?"+be.shared.vao+".currentVAO.instances:-1")});return null}var $=T(da,!0);function Q(){if(Hn in _){var ve=_[Hn]|0;return S.count=ve,h.command(typeof ve=="number"&&ve>=0,"invalid vertex count",u.commandStr),yt(function(){return ve})}else if(Hn in E){var ce=E[Hn];return sr(ce,function(Pe,Je){var Ot=Pe.invoke(Je,ce);return h.optional(function(){Pe.assert(Je,"typeof "+Ot+'==="number"&&'+Ot+">=0&&"+Ot+"===("+Ot+"|0)","invalid vertex count")}),Ot})}else if(d)if(_n(f)){if(f)return $?new Tt($.thisDep,$.contextDep,$.propDep,function(Pe,Je){var Ot=Je.def(Pe.ELEMENTS,".vertCount-",Pe.OFFSET);return h.optional(function(){Pe.assert(Je,Ot+">=0","invalid vertex offset/element buffer too small")}),Ot}):yt(function(Pe,Je){return Je.def(Pe.ELEMENTS,".vertCount")});var fe=yt(function(){return-1});return h.optional(function(){fe.MISSING=!0}),fe}else{var me=new Tt(f.thisDep||$.thisDep,f.contextDep||$.contextDep,f.propDep||$.propDep,function(Pe,Je){var Ot=Pe.ELEMENTS;return Pe.OFFSET?Je.def(Ot,"?",Ot,".vertCount-",Pe.OFFSET,":-1"):Je.def(Ot,"?",Ot,".vertCount:-1")});return h.optional(function(){me.DYNAMIC=!0}),me}else if(g){var be=new Tt(C.thisDep,C.contextDep,C.propDep,function(Pe,Je){return Je.def(Pe.shared.vao,".currentVAO?",Pe.shared.vao,".currentVAO.count:-1")});return be}return null}var J=A(),ae=Q(),Z=T(ha,!1);return{elements:f,primitive:J,count:ae,instances:Z,offset:$,vao:C,vaoActive:g,elementsActive:d,static:S}}function ct(p,u){var _=p.static,E=p.dynamic,S={};return ge.forEach(function(g){var w=pe(g);function C(d,b){if(g in _){var f=d(_[g]);S[w]=yt(function(){return f})}else if(g in E){var A=E[g];S[w]=sr(A,function(T,$){return b(T,$,T.invoke($,A))})}}switch(g){case ld:case rd:case td:case pd:case id:case md:case cd:case dd:case hd:case od:return C(function(d){return h.commandType(d,"boolean",g,u.commandStr),d},function(d,b,f){return h.optional(function(){d.assert(b,"typeof "+f+'==="boolean"',"invalid flag "+g,d.commandStr)}),f});case sd:return C(function(d){return h.commandParameter(d,Ci,"invalid "+g,u.commandStr),Ci[d]},function(d,b,f){var A=d.constants.compareFuncs;return h.optional(function(){d.assert(b,f+" in "+A,"invalid "+g+", must be one of "+Object.keys(Ci))}),b.def(A,"[",f,"]")});case ad:return C(function(d){return h.command(pt(d)&&d.length===2&&typeof d[0]=="number"&&typeof d[1]=="number"&&d[0]<=d[1],"depth range is 2d array",u.commandStr),d},function(d,b,f){h.optional(function(){d.assert(b,d.shared.isArrayLike+"("+f+")&&"+f+".length===2&&typeof "+f+'[0]==="number"&&typeof '+f+'[1]==="number"&&'+f+"[0]<="+f+"[1]","depth range must be a 2d array")});var A=b.def("+",f,"[0]"),T=b.def("+",f,"[1]");return[A,T]});case No:return C(function(d){h.commandType(d,"object","blend.func",u.commandStr);var b="srcRGB"in d?d.srcRGB:d.src,f="srcAlpha"in d?d.srcAlpha:d.src,A="dstRGB"in d?d.dstRGB:d.dst,T="dstAlpha"in d?d.dstAlpha:d.dst;return h.commandParameter(b,Dr,w+".srcRGB",u.commandStr),h.commandParameter(f,Dr,w+".srcAlpha",u.commandStr),h.commandParameter(A,Dr,w+".dstRGB",u.commandStr),h.commandParameter(T,Dr,w+".dstAlpha",u.commandStr),h.command(Pd.indexOf(b+", "+A)===-1,"unallowed blending combination (srcRGB, dstRGB) = ("+b+", "+A+")",u.commandStr),[Dr[b],Dr[A],Dr[f],Dr[T]]},function(d,b,f){var A=d.constants.blendFuncs;h.optional(function(){d.assert(b,f+"&&typeof "+f+'==="object"',"invalid blend func, must be an object")});function T(ce,fe){var me=b.def('"',ce,fe,'" in ',f,"?",f,".",ce,fe,":",f,".",ce);return h.optional(function(){d.assert(b,me+" in "+A,"invalid "+g+"."+ce+fe+", must be one of "+Object.keys(Dr))}),me}var $=T("src","RGB"),Q=T("dst","RGB");h.optional(function(){var ce=d.constants.invalidBlendCombinations;d.assert(b,ce+".indexOf("+$+'+", "+'+Q+") === -1 ","unallowed blending combination for (srcRGB, dstRGB)")});var J=b.def(A,"[",$,"]"),ae=b.def(A,"[",T("src","Alpha"),"]"),Z=b.def(A,"[",Q,"]"),ve=b.def(A,"[",T("dst","Alpha"),"]");return[J,Z,ae,ve]});case Bo:return C(function(d){if(typeof d=="string")return h.commandParameter(d,R,"invalid "+g,u.commandStr),[R[d],R[d]];if(typeof d=="object")return h.commandParameter(d.rgb,R,g+".rgb",u.commandStr),h.commandParameter(d.alpha,R,g+".alpha",u.commandStr),[R[d.rgb],R[d.alpha]];h.commandRaise("invalid blend.equation",u.commandStr)},function(d,b,f){var A=d.constants.blendEquations,T=b.def(),$=b.def(),Q=d.cond("typeof ",f,'==="string"');return h.optional(function(){function J(ae,Z,ve){d.assert(ae,ve+" in "+A,"invalid "+Z+", must be one of "+Object.keys(R))}J(Q.then,g,f),d.assert(Q.else,f+"&&typeof "+f+'==="object"',"invalid "+g),J(Q.else,g+".rgb",f+".rgb"),J(Q.else,g+".alpha",f+".alpha")}),Q.then(T,"=",$,"=",A,"[",f,"];"),Q.else(T,"=",A,"[",f,".rgb];",$,"=",A,"[",f,".alpha];"),b(Q),[T,$]});case nd:return C(function(d){return h.command(pt(d)&&d.length===4,"blend.color must be a 4d array",u.commandStr),dr(4,function(b){return+d[b]})},function(d,b,f){return h.optional(function(){d.assert(b,d.shared.isArrayLike+"("+f+")&&"+f+".length===4","blend.color must be a 4d array")}),dr(4,function(A){return b.def("+",f,"[",A,"]")})});case fd:return C(function(d){return h.commandType(d,"number",w,u.commandStr),d|0},function(d,b,f){return h.optional(function(){d.assert(b,"typeof "+f+'==="number"',"invalid stencil.mask")}),b.def(f,"|0")});case Ko:return C(function(d){h.commandType(d,"object",w,u.commandStr);var b=d.cmp||"keep",f=d.ref||0,A="mask"in d?d.mask:-1;return h.commandParameter(b,Ci,g+".cmp",u.commandStr),h.commandType(f,"number",g+".ref",u.commandStr),h.commandType(A,"number",g+".mask",u.commandStr),[Ci[b],f,A]},function(d,b,f){var A=d.constants.compareFuncs;h.optional(function(){function J(){d.assert(b,Array.prototype.join.call(arguments,""),"invalid stencil.func")}J(f+"&&typeof ",f,'==="object"'),J('!("cmp" in ',f,")||(",f,".cmp in ",A,")")});var T=b.def('"cmp" in ',f,"?",A,"[",f,".cmp]",":",vn),$=b.def(f,".ref|0"),Q=b.def('"mask" in ',f,"?",f,".mask|0:-1");return[T,$,Q]});case qo:case Xi:return C(function(d){h.commandType(d,"object",w,u.commandStr);var b=d.fail||"keep",f=d.zfail||"keep",A=d.zpass||"keep";return h.commandParameter(b,bn,g+".fail",u.commandStr),h.commandParameter(f,bn,g+".zfail",u.commandStr),h.commandParameter(A,bn,g+".zpass",u.commandStr),[g===Xi?Kn:is,bn[b],bn[f],bn[A]]},function(d,b,f){var A=d.constants.stencilOps;h.optional(function(){d.assert(b,f+"&&typeof "+f+'==="object"',"invalid "+g)});function T($){return h.optional(function(){d.assert(b,'!("'+$+'" in '+f+")||("+f+"."+$+" in "+A+")","invalid "+g+"."+$+", must be one of "+Object.keys(bn))}),b.def('"',$,'" in ',f,"?",A,"[",f,".",$,"]:",vn)}return[g===Xi?Kn:is,T("fail"),T("zfail"),T("zpass")]});case zo:return C(function(d){h.commandType(d,"object",w,u.commandStr);var b=d.factor|0,f=d.units|0;return h.commandType(b,"number",w+".factor",u.commandStr),h.commandType(f,"number",w+".units",u.commandStr),[b,f]},function(d,b,f){h.optional(function(){d.assert(b,f+"&&typeof "+f+'==="object"',"invalid "+g)});var A=b.def(f,".factor|0"),T=b.def(f,".units|0");return[A,T]});case ud:return C(function(d){var b=0;return d==="front"?b=is:d==="back"&&(b=Kn),h.command(!!b,w,u.commandStr),b},function(d,b,f){return h.optional(function(){d.assert(b,f+'==="front"||'+f+'==="back"',"invalid cull.face")}),b.def(f,'==="front"?',is,":",Kn)});case Uo:return C(function(d){return h.command(typeof d=="number"&&d>=V.lineWidthDims[0]&&d<=V.lineWidthDims[1],"invalid line width, must be a positive number between "+V.lineWidthDims[0]+" and "+V.lineWidthDims[1],u.commandStr),d},function(d,b,f){return h.optional(function(){d.assert(b,"typeof "+f+'==="number"&&'+f+">="+V.lineWidthDims[0]+"&&"+f+"<="+V.lineWidthDims[1],"invalid line width")}),f});case jo:return C(function(d){return h.commandParameter(d,rl,w,u.commandStr),rl[d]},function(d,b,f){return h.optional(function(){d.assert(b,f+'==="cw"||'+f+'==="ccw"',"invalid frontFace, must be one of cw,ccw")}),b.def(f+'==="cw"?'+gd+":"+tl)});case Go:return C(function(d){return h.command(pt(d)&&d.length===4,"color.mask must be length 4 array",u.commandStr),d.map(function(b){return!!b})},function(d,b,f){return h.optional(function(){d.assert(b,d.shared.isArrayLike+"("+f+")&&"+f+".length===4","invalid color.mask")}),dr(4,function(A){return"!!"+f+"["+A+"]"})});case Ho:return C(function(d){h.command(typeof d=="object"&&d,w,u.commandStr);var b="value"in d?d.value:1,f=!!d.invert;return h.command(typeof b=="number"&&b>=0&&b<=1,"sample.coverage.value must be a number between 0 and 1",u.commandStr),[b,f]},function(d,b,f){h.optional(function(){d.assert(b,f+"&&typeof "+f+'==="object"',"invalid sample.coverage")});var A=b.def('"value" in ',f,"?+",f,".value:1"),T=b.def("!!",f,".invert");return[A,T]})}}),S}function Fe(p,u){var _=p.static,E=p.dynamic,S={};return Object.keys(_).forEach(function(g){var w=_[g],C;if(typeof w=="number"||typeof w=="boolean")C=yt(function(){return w});else if(typeof w=="function"){var d=w._reglType;d==="texture2d"||d==="textureCube"?C=yt(function(b){return b.link(w)}):d==="framebuffer"||d==="framebufferCube"?(h.command(w.color.length>0,'missing color attachment for framebuffer sent to uniform "'+g+'"',u.commandStr),C=yt(function(b){return b.link(w.color[0])})):h.commandRaise('invalid data for uniform "'+g+'"',u.commandStr)}else pt(w)?C=yt(function(b){var f=b.global.def("[",dr(w.length,function(A){return h.command(typeof w[A]=="number"||typeof w[A]=="boolean","invalid uniform "+g,b.commandStr),w[A]}),"]");return f}):h.commandRaise('invalid or missing data for uniform "'+g+'"',u.commandStr);C.value=w,S[g]=C}),Object.keys(E).forEach(function(g){var w=E[g];S[g]=sr(w,function(C,d){return C.invoke(d,w)})}),S}function Ct(p,u){var _=p.static,E=p.dynamic,S={};return Object.keys(_).forEach(function(g){var w=_[g],C=c.id(g),d=new P;if(xa(w))d.state=wi,d.buffer=I.getBuffer(I.create(w,xi,!1,!0)),d.type=0;else{var b=I.getBuffer(w);if(b)d.state=wi,d.buffer=b,d.type=0;else if(h.command(typeof w=="object"&&w,"invalid data for attribute "+g,u.commandStr),"constant"in w){var f=w.constant;d.buffer="null",d.state=Do,typeof f=="number"?d.x=f:(h.command(pt(f)&&f.length>0&&f.length<=4,"invalid constant for attribute "+g,u.commandStr),_i.forEach(function(Z,ve){ve=0,'invalid offset for attribute "'+g+'"',u.commandStr);var T=w.stride|0;h.command(T>=0&&T<256,'invalid stride for attribute "'+g+'", must be integer betweeen [0, 255]',u.commandStr);var $=w.size|0;h.command(!("size"in w)||$>0&&$<=4,'invalid size for attribute "'+g+'", must be 1,2,3,4',u.commandStr);var Q=!!w.normalized,J=0;"type"in w&&(h.commandParameter(w.type,Fn,"invalid type for attribute "+g,u.commandStr),J=Fn[w.type]);var ae=w.divisor|0;h.optional(function(){"divisor"in w&&(h.command(ae===0||K,'cannot specify divisor for attribute "'+g+'", instancing not supported',u.commandStr),h.command(ae>=0,'invalid divisor for attribute "'+g+'"',u.commandStr));var Z=u.commandStr,ve=["buffer","offset","divisor","normalized","type","size","stride"];Object.keys(w).forEach(function(ce){h.command(ve.indexOf(ce)>=0,'unknown parameter "'+ce+'" for attribute pointer "'+g+'" (valid parameters are '+ve+")",Z)})}),d.buffer=b,d.state=wi,d.size=$,d.normalized=Q,d.type=J||b.dtype,d.offset=A,d.stride=T,d.divisor=ae}}S[g]=yt(function(Z,ve){var ce=Z.attribCache;if(C in ce)return ce[C];var fe={isStream:!1};return Object.keys(d).forEach(function(me){fe[me]=d[me]}),d.buffer&&(fe.buffer=Z.link(d.buffer),fe.type=fe.type||fe.buffer+".dtype"),ce[C]=fe,fe})}),Object.keys(E).forEach(function(g){var w=E[g];function C(d,b){var f=d.invoke(b,w),A=d.shared,T=d.constants,$=A.isBufferArgs,Q=A.buffer;h.optional(function(){d.assert(b,f+"&&(typeof "+f+'==="object"||typeof '+f+'==="function")&&('+$+"("+f+")||"+Q+".getBuffer("+f+")||"+Q+".getBuffer("+f+".buffer)||"+$+"("+f+'.buffer)||("constant" in '+f+"&&(typeof "+f+'.constant==="number"||'+A.isArrayLike+"("+f+".constant))))",'invalid dynamic attribute "'+g+'"')});var J={isStream:b.def(!1)},ae=new P;ae.state=wi,Object.keys(ae).forEach(function(fe){J[fe]=b.def(""+ae[fe])});var Z=J.buffer,ve=J.type;b("if(",$,"(",f,")){",J.isStream,"=true;",Z,"=",Q,".createStream(",xi,",",f,");",ve,"=",Z,".dtype;","}else{",Z,"=",Q,".getBuffer(",f,");","if(",Z,"){",ve,"=",Z,".dtype;",'}else if("constant" in ',f,"){",J.state,"=",Do,";","if(typeof "+f+'.constant === "number"){',J[_i[0]],"=",f,".constant;",_i.slice(1).map(function(fe){return J[fe]}).join("="),"=0;","}else{",_i.map(function(fe,me){return J[fe]+"="+f+".constant.length>"+me+"?"+f+".constant["+me+"]:0;"}).join(""),"}}else{","if(",$,"(",f,".buffer)){",Z,"=",Q,".createStream(",xi,",",f,".buffer);","}else{",Z,"=",Q,".getBuffer(",f,".buffer);","}",ve,'="type" in ',f,"?",T.glTypes,"[",f,".type]:",Z,".dtype;",J.normalized,"=!!",f,".normalized;");function ce(fe){b(J[fe],"=",f,".",fe,"|0;")}return ce("size"),ce("offset"),ce("stride"),ce("divisor"),b("}}"),b.exit("if(",J.isStream,"){",Q,".destroyStream(",Z,");","}"),J}S[g]=sr(w,C)}),S}function ot(p){var u=p.static,_=p.dynamic,E={};return Object.keys(u).forEach(function(S){var g=u[S];E[S]=yt(function(w,C){return typeof g=="number"||typeof g=="boolean"?""+g:w.link(g)})}),Object.keys(_).forEach(function(S){var g=_[S];E[S]=sr(g,function(w,C){return w.invoke(C,g)})}),E}function xt(p,u,_,E,S){var g=p.static,w=p.dynamic;h.optional(function(){var ce=[jn,Wi,Zi,Un,zn,da,Hn,ha,Yi,Qi].concat(ge);function fe(me){Object.keys(me).forEach(function(be){h.command(ce.indexOf(be)>=0,'unknown parameter "'+be+'"',S.commandStr)})}fe(g),fe(w)});var C=ke(p,u),d=le(p),b=Ee(p,d,S),f=lt(p,S),A=ct(p,S),T=De(p,S,C);function $(ce){var fe=b[ce];fe&&(A[ce]=fe)}$(Yr),$(pe(ca));var Q=Object.keys(A).length>0,J={framebuffer:d,draw:f,shader:T,state:A,dirty:Q,scopeVAO:null,drawVAO:null,useVAO:!1,attributes:{}};if(J.profile=se(p),J.uniforms=Fe(_,S),J.drawVAO=J.scopeVAO=f.vao,!J.drawVAO&&T.program&&!C&&v.angle_instanced_arrays&&f.static.elements){var ae=!0,Z=T.program.attributes.map(function(ce){var fe=u.static[ce];return ae=ae&&!!fe,fe});if(ae&&Z.length>0){var ve=X.getVAO(X.createVAO({attributes:Z,elements:f.static.elements}));J.drawVAO=new Tt(null,null,null,function(ce,fe){return ce.link(ve)}),J.useVAO=!0}}return C?J.useVAO=!0:J.attributes=Ct(u,S),J.context=ot(E),J}function Et(p,u,_){var E=p.shared,S=E.context,g=p.scope();Object.keys(_).forEach(function(w){u.save(S,"."+w);var C=_[w],d=C.append(p,u);Array.isArray(d)?g(S,".",w,"=[",d.join(),"];"):g(S,".",w,"=",d,";")}),u(g)}function Pt(p,u,_,E){var S=p.shared,g=S.gl,w=S.framebuffer,C;ue&&(C=u.def(S.extensions,".webgl_draw_buffers"));var d=p.constants,b=d.drawBuffer,f=d.backBuffer,A;_?A=_.append(p,u):A=u.def(w,".next"),E||u("if(",A,"!==",w,".cur){"),u("if(",A,"){",g,".bindFramebuffer(",Ed,",",A,".framebuffer);"),ue&&u(C,".drawBuffersWEBGL(",b,"[",A,".colorAttachments.length]);"),u("}else{",g,".bindFramebuffer(",Ed,",null);"),ue&&u(C,".drawBuffersWEBGL(",f,");"),u("}",w,".cur=",A,";"),E||u("}")}function Vt(p,u,_){var E=p.shared,S=E.gl,g=p.current,w=p.next,C=E.current,d=E.next,b=p.cond(C,".dirty");ge.forEach(function(f){var A=pe(f);if(!(A in _.state)){var T,$;if(A in w){T=w[A],$=g[A];var Q=dr(oe[A].length,function(ae){return b.def(T,"[",ae,"]")});b(p.cond(Q.map(function(ae,Z){return ae+"!=="+$+"["+Z+"]"}).join("||")).then(S,".",M[A],"(",Q,");",Q.map(function(ae,Z){return $+"["+Z+"]="+ae}).join(";"),";"))}else{T=b.def(d,".",A);var J=p.cond(T,"!==",C,".",A);b(J),A in F?J(p.cond(T).then(S,".enable(",F[A],");").else(S,".disable(",F[A],");"),C,".",A,"=",T,";"):J(S,".",M[A],"(",T,");",C,".",A,"=",T,";")}}}),Object.keys(_.state).length===0&&b(C,".dirty=false;"),u(b)}function Nt(p,u,_,E){var S=p.shared,g=p.current,w=S.current,C=S.gl;Sd(Object.keys(_)).forEach(function(d){var b=_[d];if(!(E&&!E(b))){var f=b.append(p,u);if(F[d]){var A=F[d];_n(b)?f?u(C,".enable(",A,");"):u(C,".disable(",A,");"):u(p.cond(f).then(C,".enable(",A,");").else(C,".disable(",A,");")),u(w,".",d,"=",f,";")}else if(pt(f)){var T=g[d];u(C,".",M[d],"(",f,");",f.map(function($,Q){return T+"["+Q+"]="+$}).join(";"),";")}else u(C,".",M[d],"(",f,");",w,".",d,"=",f,";")}})}function ft(p,u){K&&(p.instancing=u.def(p.shared.extensions,".angle_instanced_arrays"))}function Oe(p,u,_,E,S){var g=p.shared,w=p.stats,C=g.current,d=g.timer,b=_.profile;function f(){return typeof performance>"u"?"Date.now()":"performance.now()"}var A,T;function $(ce){A=u.def(),ce(A,"=",f(),";"),typeof S=="string"?ce(w,".count+=",S,";"):ce(w,".count++;"),z&&(E?(T=u.def(),ce(T,"=",d,".getNumPendingQueries();")):ce(d,".beginQuery(",w,");"))}function Q(ce){ce(w,".cpuTime+=",f(),"-",A,";"),z&&(E?ce(d,".pushScopeStats(",T,",",d,".getNumPendingQueries(),",w,");"):ce(d,".endQuery();"))}function J(ce){var fe=u.def(C,".profile");u(C,".profile=",ce,";"),u.exit(C,".profile=",fe,";")}var ae;if(b){if(_n(b)){b.enable?($(u),Q(u.exit),J("true")):J("false");return}ae=b.append(p,u),J(ae)}else ae=u.def(C,".profile");var Z=p.block();$(Z),u("if(",ae,"){",Z,"}");var ve=p.block();Q(ve),u.exit("if(",ae,"){",ve,"}")}function Gt(p,u,_,E,S){var g=p.shared;function w(d){switch(d){case pa:case va:case wa:return 2;case fa:case ba:case ga:return 3;case ma:case _a:case ya:return 4;default:return 1}}function C(d,b,f){var A=g.gl,T=u.def(d,".location"),$=u.def(g.attributes,"[",T,"]"),Q=f.state,J=f.buffer,ae=[f.x,f.y,f.z,f.w],Z=["buffer","normalized","offset","stride"];function ve(){u("if(!",$,".buffer){",A,".enableVertexAttribArray(",T,");}");var fe=f.type,me;if(f.size?me=u.def(f.size,"||",b):me=b,u("if(",$,".type!==",fe,"||",$,".size!==",me,"||",Z.map(function(Pe){return $+"."+Pe+"!=="+f[Pe]}).join("||"),"){",A,".bindBuffer(",xi,",",J,".buffer);",A,".vertexAttribPointer(",[T,me,fe,f.normalized,f.stride,f.offset],");",$,".type=",fe,";",$,".size=",me,";",Z.map(function(Pe){return $+"."+Pe+"="+f[Pe]+";"}).join(""),"}"),K){var be=f.divisor;u("if(",$,".divisor!==",be,"){",p.instancing,".vertexAttribDivisorANGLE(",[T,be],");",$,".divisor=",be,";}")}}function ce(){u("if(",$,".buffer){",A,".disableVertexAttribArray(",T,");",$,".buffer=null;","}if(",_i.map(function(fe,me){return $+"."+fe+"!=="+ae[me]}).join("||"),"){",A,".vertexAttrib4f(",T,",",ae,");",_i.map(function(fe,me){return $+"."+fe+"="+ae[me]+";"}).join(""),"}")}Q===wi?ve():Q===Do?ce():(u("if(",Q,"===",wi,"){"),ve(),u("}else{"),ce(),u("}"))}E.forEach(function(d){var b=d.name,f=_.attributes[b],A;if(f){if(!S(f))return;A=f.append(p,u)}else{if(!S(Td))return;var T=p.scopeAttrib(b);h.optional(function(){p.assert(u,T+".state","missing attribute "+b)}),A={},Object.keys(new P).forEach(function($){A[$]=u.def(T,".",$)})}C(p.link(d),w(d.info.type),A)})}function ze(p,u,_,E,S,g){for(var w=p.shared,C=w.gl,d,b=0;b1){for(var Ot=[],Wr=[],Zr=0;Zr=0","missing vertex count")})):(be=Pe.def(w,".",Hn),h.optional(function(){p.assert(Pe,be+">=0","missing vertex count")})),be}var f=d();function A(me){var be=C[me];return be?be.contextDep&&E.contextDynamic||be.propDep?be.append(p,_):be.append(p,u):u.def(w,".",me)}var T=A(zn),$=A(da),Q=b();if(typeof Q=="number"){if(Q===0)return}else _("if(",Q,"){"),_.exit("}");var J,ae;K&&(J=A(ha),ae=p.instancing);var Z=f+".type",ve=C.elements&&_n(C.elements)&&!C.vaoActive;function ce(){function me(){_(ae,".drawElementsInstancedANGLE(",[T,Q,Z,$+"<<(("+Z+"-"+Qc+")>>1)",J],");")}function be(){_(ae,".drawArraysInstancedANGLE(",[T,$,Q,J],");")}f&&f!=="null"?ve?me():(_("if(",f,"){"),me(),_("}else{"),be(),_("}")):be()}function fe(){function me(){_(g+".drawElements("+[T,Q,Z,$+"<<(("+Z+"-"+Qc+")>>1)"]+");")}function be(){_(g+".drawArrays("+[T,$,Q]+");")}f&&f!=="null"?ve?me():(_("if(",f,"){"),me(),_("}else{"),be(),_("}")):be()}K&&(typeof J!="number"||J>=0)?typeof J=="string"?(_("if(",J,">0){"),ce(),_("}else if(",J,"<0){"),fe(),_("}")):ce():fe()}function Me(p,u,_,E,S){var g=Te(),w=g.proc("body",S);return h.optional(function(){g.commandStr=u.commandStr,g.command=g.link(u.commandStr)}),K&&(g.instancing=w.def(g.shared.extensions,".angle_instanced_arrays")),p(g,w,_,E),g.compile().body}function Be(p,u,_,E){ft(p,u),_.useVAO?_.drawVAO?u(p.shared.vao,".setVAO(",_.drawVAO.append(p,u),");"):u(p.shared.vao,".setVAO(",p.shared.vao,".targetVAO);"):(u(p.shared.vao,".setVAO(null);"),Gt(p,u,_,E.attributes,function(){return!0})),ze(p,u,_,E.uniforms,function(){return!0},!1),xe(p,u,u,_)}function mt(p,u){var _=p.proc("draw",1);ft(p,_),Et(p,_,u.context),Pt(p,_,u.framebuffer),Vt(p,_,u),Nt(p,_,u.state),Oe(p,_,u,!1,!0);var E=u.shader.progVar.append(p,_);if(_(p.shared.gl,".useProgram(",E,".program);"),u.shader.program)Be(p,_,u,u.shader.program);else{_(p.shared.vao,".setVAO(null);");var S=p.global.def("{}"),g=_.def(E,".id"),w=_.def(S,"[",g,"]");_(p.cond(w).then(w,".call(this,a0);").else(w,"=",S,"[",g,"]=",p.link(function(C){return Me(Be,p,u,C,1)}),"(",E,");",w,".call(this,a0);"))}Object.keys(u.state).length>0&&_(p.shared.current,".dirty=true;"),p.shared.vao&&_(p.shared.vao,".setVAO(null);")}function Mr(p,u,_,E){p.batchId="a1",ft(p,u);function S(){return!0}Gt(p,u,_,E.attributes,S),ze(p,u,_,E.uniforms,S,!1),xe(p,u,u,_)}function qn(p,u,_,E){ft(p,u);var S=_.contextDep,g=u.def(),w="a0",C="a1",d=u.def();p.shared.props=d,p.batchId=g;var b=p.scope(),f=p.scope();u(b.entry,"for(",g,"=0;",g,"<",C,";++",g,"){",d,"=",w,"[",g,"];",f,"}",b.exit);function A(Z){return Z.contextDep&&S||Z.propDep}function T(Z){return!A(Z)}if(_.needsContext&&Et(p,f,_.context),_.needsFramebuffer&&Pt(p,f,_.framebuffer),Nt(p,f,_.state,A),_.profile&&A(_.profile)&&Oe(p,f,_,!1,!0),E)_.useVAO?_.drawVAO?A(_.drawVAO)?f(p.shared.vao,".setVAO(",_.drawVAO.append(p,f),");"):b(p.shared.vao,".setVAO(",_.drawVAO.append(p,b),");"):b(p.shared.vao,".setVAO(",p.shared.vao,".targetVAO);"):(b(p.shared.vao,".setVAO(null);"),Gt(p,b,_,E.attributes,T),Gt(p,f,_,E.attributes,A)),ze(p,b,_,E.uniforms,T,!1),ze(p,f,_,E.uniforms,A,!0),xe(p,b,f,_);else{var $=p.global.def("{}"),Q=_.shader.progVar.append(p,f),J=f.def(Q,".id"),ae=f.def($,"[",J,"]");f(p.shared.gl,".useProgram(",Q,".program);","if(!",ae,"){",ae,"=",$,"[",J,"]=",p.link(function(Z){return Me(Mr,p,_,Z,2)}),"(",Q,");}",ae,".call(this,a0[",g,"],",g,");")}}function m(p,u){var _=p.proc("batch",2);p.batchId="0",ft(p,_);var E=!1,S=!0;Object.keys(u.context).forEach(function($){E=E||u.context[$].propDep}),E||(Et(p,_,u.context),S=!1);var g=u.framebuffer,w=!1;g?(g.propDep?E=w=!0:g.contextDep&&E&&(w=!0),w||Pt(p,_,g)):Pt(p,_,null),u.state.viewport&&u.state.viewport.propDep&&(E=!0);function C($){return $.contextDep&&E||$.propDep}Vt(p,_,u),Nt(p,_,u.state,function($){return!C($)}),(!u.profile||!C(u.profile))&&Oe(p,_,u,!1,"a1"),u.contextDep=E,u.needsContext=S,u.needsFramebuffer=w;var d=u.shader.progVar;if(d.contextDep&&E||d.propDep)qn(p,_,u,null);else{var b=d.append(p,_);if(_(p.shared.gl,".useProgram(",b,".program);"),u.shader.program)qn(p,_,u,u.shader.program);else{_(p.shared.vao,".setVAO(null);");var f=p.global.def("{}"),A=_.def(b,".id"),T=_.def(f,"[",A,"]");_(p.cond(T).then(T,".call(this,a0,a1);").else(T,"=",f,"[",A,"]=",p.link(function($){return Me(qn,p,u,$,2)}),"(",b,");",T,".call(this,a0,a1);"))}}Object.keys(u.state).length>0&&_(p.shared.current,".dirty=true;"),p.shared.vao&&_(p.shared.vao,".setVAO(null);")}function O(p,u){var _=p.proc("scope",3);p.batchId="a2";var E=p.shared,S=E.current;Et(p,_,u.context),u.framebuffer&&u.framebuffer.append(p,_),Sd(Object.keys(u.state)).forEach(function(w){var C=u.state[w],d=C.append(p,_);pt(d)?d.forEach(function(b,f){_.set(p.next[w],"["+f+"]",b)}):_.set(E.next,"."+w,d)}),Oe(p,_,u,!0,!0),[Un,da,Hn,ha,zn].forEach(function(w){var C=u.draw[w];C&&_.set(E.draw,"."+w,""+C.append(p,_))}),Object.keys(u.uniforms).forEach(function(w){var C=u.uniforms[w].append(p,_);Array.isArray(C)&&(C="["+C.join()+"]"),_.set(E.uniforms,"["+c.id(w)+"]",C)}),Object.keys(u.attributes).forEach(function(w){var C=u.attributes[w].append(p,_),d=p.scopeAttrib(w);Object.keys(new P).forEach(function(b){_.set(d,"."+b,C[b])})}),u.scopeVAO&&_.set(E.vao,".targetVAO",u.scopeVAO.append(p,_));function g(w){var C=u.shader[w];C&&_.set(E.shader,"."+w,C.append(p,_))}g(Wi),g(Zi),Object.keys(u.state).length>0&&(_(S,".dirty=true;"),_.exit(S,".dirty=true;")),_("a1(",p.shared.context,",a0,",p.batchId,");")}function k(p){if(!(typeof p!="object"||pt(p))){for(var u=Object.keys(p),_=0;_=0;--xe){var Me=ne[xe];Me&&Me(z,null,0)}v.flush(),X&&X.update()}function ke(){!le&&ne.length>0&&(le=qr.next(Ee))}function De(){le&&(qr.cancel(Ee),le=null)}function lt(xe){xe.preventDefault(),I=!0,De(),Le.forEach(function(Me){Me()})}function ct(xe){v.getError(),I=!1,L.restore(),ie.restore(),K.restore(),ge.restore(),F.restore(),M.restore(),N.restore(),X&&X.restore(),pe.procs.refresh(),ke(),Te.forEach(function(Me){Me()})}re&&(re.addEventListener(Ld,lt,!1),re.addEventListener(Vd,ct,!1));function Fe(){ne.length=0,De(),re&&(re.removeEventListener(Ld,lt),re.removeEventListener(Vd,ct)),ie.clear(),M.clear(),F.clear(),N.clear(),ge.clear(),ue.clear(),K.clear(),X&&X.clear(),se.forEach(function(xe){xe()})}function Ct(xe){h(!!xe,"invalid args to regl({...})"),h.type(xe,"object","invalid args to regl({...})");function Me(S){var g=n({},S);delete g.uniforms,delete g.attributes,delete g.context,delete g.vao,"stencil"in g&&g.stencil.op&&(g.stencil.opBack=g.stencil.opFront=g.stencil.op,delete g.stencil.op);function w(C){if(C in g){var d=g[C];delete g[C],Object.keys(d).forEach(function(b){g[C+"."+b]=d[b]})}}return w("blend"),w("depth"),w("cull"),w("stencil"),w("polygonOffset"),w("scissor"),w("sample"),"vao"in S&&(g.vao=S.vao),g}function Be(S,g){var w={},C={};return Object.keys(S).forEach(function(d){var b=S[d];if(wt.isDynamic(b)){C[d]=wt.unbox(b,d);return}else if(g&&Array.isArray(b)){for(var f=0;f0)return Re.call(this,_(S|0),S|0)}else if(Array.isArray(S)){if(S.length)return Re.call(this,S,S.length)}else return he.call(this,S)}return n(E,{stats:O,destroy:function(){k.destroy()}})}var ot=M.setFBO=Ct({framebuffer:wt.define.call(null,Od,"framebuffer")});function xt(xe,Me){var Be=0;pe.procs.poll();var mt=Me.color;mt&&(v.clearColor(+mt[0]||0,+mt[1]||0,+mt[2]||0,+mt[3]||0),Be|=Wb),"depth"in Me&&(v.clearDepth(+Me.depth),Be|=Zb),"stencil"in Me&&(v.clearStencil(Me.stencil|0),Be|=Qb),h(!!Be,"called regl.clear with no buffer specified"),v.clear(Be)}function Et(xe){if(h(typeof xe=="object"&&xe,"regl.clear() takes an object as input"),"framebuffer"in xe)if(xe.framebuffer&&xe.framebuffer_reglType==="framebufferCube")for(var Me=0;Me<6;++Me)ot(n({framebuffer:xe.framebuffer.faces[Me]},xe),xt);else ot(xe,xt);else xt(null,xe)}function Pt(xe){h.type(xe,"function","regl.frame() callback must be a function"),ne.push(xe);function Me(){var Be=Rd(ne,xe);h(Be>=0,"cannot cancel a frame twice");function mt(){var Mr=Rd(ne,mt);ne[Mr]=ne[ne.length-1],ne.length-=1,ne.length<=0&&De()}ne[Be]=mt}return ke(),{cancel:Me}}function Vt(){var xe=H.viewport,Me=H.scissor_box;xe[0]=xe[1]=Me[0]=Me[1]=0,z.viewportWidth=z.framebufferWidth=z.drawingBufferWidth=xe[2]=Me[2]=v.drawingBufferWidth,z.viewportHeight=z.framebufferHeight=z.drawingBufferHeight=xe[3]=Me[3]=v.drawingBufferHeight}function Nt(){z.tick+=1,z.time=Oe(),Vt(),pe.procs.poll()}function ft(){ge.refresh(),Vt(),pe.procs.refresh(),X&&X.update()}function Oe(){return(hn()-W)/1e3}ft();function Gt(xe,Me){h.type(Me,"function","listener callback must be a function");var Be;switch(xe){case"frame":return Pt(Me);case"lost":Be=Le;break;case"restore":Be=Te;break;case"destroy":Be=se;break;default:h.raise("invalid event, must be one of frame,lost,restore,destroy")}return Be.push(Me),{cancel:function(){for(var mt=0;mt=0},read:te,destroy:Fe,_gl:v,_refresh:ft,poll:function(){Nt(),X&&X.update()},now:Oe,stats:j});return c.onDone(null,ze),ze}return r_}))})(ka)),ka.exports}var j_=G_();const hP=B_(j_);function ut(r){return r==null}function Gl(r){return r!==null&&typeof r=="object"}function Pl(r){return r!==null&&typeof r=="object"}function U_(r,e){if(r.length!==e.length)return!1;for(let t=0;t{const s=r[i],o=e[i];return Pl(s)&&Pl(o)?Object.assign(Object.assign({},n),{[i]:Jn(s,o)}):Object.assign(Object.assign({},n),{[i]:i in e?o:s})},{})}function jl(r){return Gl(r)?"target"in r:!1}const z_={alreadydisposed:()=>"View has been already disposed",invalidparams:r=>`Invalid parameters for '${r.name}'`,nomatchingcontroller:r=>`No matching controller for '${r.key}'`,nomatchingview:r=>`No matching view for '${JSON.stringify(r.params)}'`,notbindable:()=>"Value is not bindable",notcompatible:r=>`Not compatible with plugin '${r.id}'`,propertynotfound:r=>`Property '${r.name}' not found`,shouldneverhappen:()=>"This error should never happen"};let qt=class Ti{static alreadyDisposed(){return new Ti({type:"alreadydisposed"})}static notBindable(){return new Ti({type:"notbindable"})}static notCompatible(e,t){return new Ti({type:"notcompatible",context:{id:`${e}.${t}`}})}static propertyNotFound(e){return new Ti({type:"propertynotfound",context:{name:e}})}static shouldNeverHappen(){return new Ti({type:"shouldneverhappen"})}constructor(e){var t;this.message=(t=z_[e.type](e.context))!==null&&t!==void 0?t:"Unexpected error",this.name=this.constructor.name,this.stack=new Error(this.message).stack,this.type=e.type}toString(){return this.message}},Gd=class Xh{constructor(e,t){this.obj_=e,this.key=t}static isBindable(e){return!(e===null||typeof e!="object"&&typeof e!="function")}read(){return this.obj_[this.key]}write(e){this.obj_[this.key]=e}writeProperty(e,t){const n=this.read();if(!Xh.isBindable(n))throw qt.notBindable();if(!(e in n))throw qt.propertyNotFound(e);n[e]=t}},kt=class{constructor(){this.observers_={}}on(e,t,n){var i;let s=this.observers_[e];return s||(s=this.observers_[e]=[]),s.push({handler:t,key:(i=n?.key)!==null&&i!==void 0?i:t}),this}off(e,t){const n=this.observers_[e];return n&&(this.observers_[e]=n.filter(i=>i.key!==t)),this}emit(e,t){const n=this.observers_[e];n&&n.forEach(i=>{i.handler(t)})}},H_=class{constructor(e,t){var n;this.constraint_=t?.constraint,this.equals_=(n=t?.equals)!==null&&n!==void 0?n:((i,s)=>i===s),this.emitter=new kt,this.rawValue_=e}get constraint(){return this.constraint_}get rawValue(){return this.rawValue_}set rawValue(e){this.setRawValue(e,{forceEmit:!1,last:!0})}setRawValue(e,t){const n=t??{forceEmit:!1,last:!0},i=this.constraint_?this.constraint_.constrain(e):e,s=this.rawValue_;this.equals_(s,i)&&!n.forceEmit||(this.emitter.emit("beforechange",{sender:this}),this.rawValue_=i,this.emitter.emit("change",{options:n,previousRawValue:s,rawValue:i,sender:this}))}},K_=class{constructor(e){this.emitter=new kt,this.value_=e}get rawValue(){return this.value_}set rawValue(e){this.setRawValue(e,{forceEmit:!1,last:!0})}setRawValue(e,t){const n=t??{forceEmit:!1,last:!0},i=this.value_;i===e&&!n.forceEmit||(this.emitter.emit("beforechange",{sender:this}),this.value_=e,this.emitter.emit("change",{options:n,previousRawValue:i,rawValue:this.value_,sender:this}))}},q_=class{constructor(e){this.emitter=new kt,this.onValueBeforeChange_=this.onValueBeforeChange_.bind(this),this.onValueChange_=this.onValueChange_.bind(this),this.value_=e,this.value_.emitter.on("beforechange",this.onValueBeforeChange_),this.value_.emitter.on("change",this.onValueChange_)}get rawValue(){return this.value_.rawValue}onValueBeforeChange_(e){this.emitter.emit("beforechange",Object.assign(Object.assign({},e),{sender:this}))}onValueChange_(e){this.emitter.emit("change",Object.assign(Object.assign({},e),{sender:this}))}};function dt(r,e){const t=e?.constraint,n=e?.equals;return!t&&!n?new K_(r):new H_(r,e)}function X_(r){return[new q_(r),(e,t)=>{r.setRawValue(e,t)}]}let Ue=class Yh{constructor(e){this.emitter=new kt,this.valMap_=e;for(const t in this.valMap_)this.valMap_[t].emitter.on("change",()=>{this.emitter.emit("change",{key:t,sender:this})})}static createCore(e){return Object.keys(e).reduce((n,i)=>Object.assign(n,{[i]:dt(e[i])}),{})}static fromObject(e){const t=this.createCore(e);return new Yh(t)}get(e){return this.valMap_[e].rawValue}set(e,t){this.valMap_[e].rawValue=t}value(e){return this.valMap_[e]}},Ts=class{constructor(e){this.values=Ue.fromObject({max:e.max,min:e.min})}constrain(e){const t=this.values.get("max"),n=this.values.get("min");return Math.min(Math.max(e,n),t)}},Y_=class{constructor(e){this.values=Ue.fromObject({max:e.max,min:e.min})}constrain(e){const t=this.values.get("max"),n=this.values.get("min");let i=e;return ut(n)||(i=Math.max(i,n)),ut(t)||(i=Math.min(i,t)),i}},W_=class{constructor(e,t=0){this.step=e,this.origin=t}constrain(e){const t=this.origin%this.step,n=Math.round((e-t)/this.step);return t+n*this.step}},Z_=class{constructor(e){this.text=e}evaluate(){return Number(this.text)}toString(){return this.text}};const Q_={"**":(r,e)=>Math.pow(r,e),"*":(r,e)=>r*e,"/":(r,e)=>r/e,"%":(r,e)=>r%e,"+":(r,e)=>r+e,"-":(r,e)=>r-e,"<<":(r,e)=>r<>":(r,e)=>r>>e,">>>":(r,e)=>r>>>e,"&":(r,e)=>r&e,"^":(r,e)=>r^e,"|":(r,e)=>r|e};let J_=class{constructor(e,t,n){this.left=t,this.operator=e,this.right=n}evaluate(){const e=Q_[this.operator];if(!e)throw new Error(`unexpected binary operator: '${this.operator}`);return e(this.left.evaluate(),this.right.evaluate())}toString(){return["b(",this.left.toString(),this.operator,this.right.toString(),")"].join(" ")}};const ew={"+":r=>r,"-":r=>-r,"~":r=>~r};let tw=class{constructor(e,t){this.operator=e,this.expression=t}evaluate(){const e=ew[this.operator];if(!e)throw new Error(`unexpected unary operator: '${this.operator}`);return e(this.expression.evaluate())}toString(){return["u(",this.operator,this.expression.toString(),")"].join(" ")}};function Ul(r){return(e,t)=>{for(let n=0;ne.startsWith(i,t))[0];return n?(t+=n.length,t+=_s(e,t).length,{cursor:t,operator:n}):null}function gw(r,e){return(t,n)=>{const i=r(t,n);if(!i)return null;n=i.cursor;let s=i.evaluable;for(;;){const o=ww(e,t,n);if(!o)break;n=o.cursor;const l=r(t,n);if(!l)return null;n=l.cursor,s=new J_(o.operator,s,l.evaluable)}return s?{cursor:n,evaluable:s}:null}}const yw=[["**"],["*","/","%"],["+","-"],["<<",">>>",">>"],["&"],["^"],["|"]].reduce((r,e)=>gw(r,e),Zh);function Qh(r,e){return e+=_s(r,e).length,yw(r,e)}function xw(r){const e=Qh(r,0);return!e||e.cursor+_s(r,e.cursor).length!==r.length?null:e.evaluable}function on(r){var e;const t=xw(r);return(e=t?.evaluate())!==null&&e!==void 0?e:null}function Jh(r){if(typeof r=="number")return r;if(typeof r=="string"){const e=on(r);if(!ut(e))return e}return 0}function Cw(r){return String(r)}function lr(r){return e=>e.toFixed(Math.max(Math.min(r,20),0))}function et(r,e,t,n,i){const s=(r-e)/(t-e);return n+s*(i-n)}function jd(r){return String(r.toFixed(10)).split(".")[1].replace(/0+$/,"").length}function Rt(r,e,t){return Math.min(Math.max(r,e),t)}function ep(r,e){return(r%e+e)%e}function Ew(r,e){return ut(r.step)?Math.max(jd(e),2):jd(r.step)}function tp(r){var e;return(e=r.step)!==null&&e!==void 0?e:1}function rp(r,e){var t;const n=Math.abs((t=r.step)!==null&&t!==void 0?t:e);return n===0?.1:Math.pow(10,Math.floor(Math.log10(n))-1)}function np(r,e){return ut(r.step)?null:new W_(r.step,e)}function ip(r){return!ut(r.max)&&!ut(r.min)?new Ts({max:r.max,min:r.min}):!ut(r.max)||!ut(r.min)?new Y_({max:r.max,min:r.min}):null}function sp(r,e){var t,n,i;return{formatter:(t=r.format)!==null&&t!==void 0?t:lr(Ew(r,e)),keyScale:(n=r.keyScale)!==null&&n!==void 0?n:tp(r),pointerScale:(i=r.pointerScale)!==null&&i!==void 0?i:rp(r,e)}}function ap(r){return{format:r.optional.function,keyScale:r.optional.number,max:r.optional.number,min:r.optional.number,pointerScale:r.optional.number,step:r.optional.number}}function Hl(r){return{constraint:r.constraint,textProps:Ue.fromObject(sp(r.params,r.initialValue))}}let ii=class{constructor(e){this.controller=e}get element(){return this.controller.view.element}get disabled(){return this.controller.viewProps.get("disabled")}set disabled(e){this.controller.viewProps.set("disabled",e)}get hidden(){return this.controller.viewProps.get("hidden")}set hidden(e){this.controller.viewProps.set("hidden",e)}dispose(){this.controller.viewProps.set("disposed",!0)}importState(e){return this.controller.importState(e)}exportState(){return this.controller.exportState()}},qa=class{constructor(e){this.target=e}},ks=class extends qa{constructor(e,t,n){super(e),this.value=t,this.last=n??!0}},Pw=class extends qa{constructor(e,t){super(e),this.expanded=t}},Aw=class extends qa{constructor(e,t){super(e),this.index=t}},Sw=class extends qa{constructor(e,t){super(e),this.native=t}},gs=class extends ii{constructor(e){super(e),this.onValueChange_=this.onValueChange_.bind(this),this.emitter_=new kt,this.controller.value.emitter.on("change",this.onValueChange_)}get label(){return this.controller.labelController.props.get("label")}set label(e){this.controller.labelController.props.set("label",e)}get key(){return this.controller.value.binding.target.key}get tag(){return this.controller.tag}set tag(e){this.controller.tag=e}on(e,t){const n=t.bind(this);return this.emitter_.on(e,i=>{n(i)},{key:t}),this}off(e,t){return this.emitter_.off(e,t),this}refresh(){this.controller.value.fetch()}onValueChange_(e){const t=this.controller.value;this.emitter_.emit("change",new ks(this,t.binding.target.read(),e.options.last))}};class Tw{constructor(e,t){this.onValueBeforeChange_=this.onValueBeforeChange_.bind(this),this.onValueChange_=this.onValueChange_.bind(this),this.binding=t,this.value_=e,this.value_.emitter.on("beforechange",this.onValueBeforeChange_),this.value_.emitter.on("change",this.onValueChange_),this.emitter=new kt}get rawValue(){return this.value_.rawValue}set rawValue(e){this.value_.rawValue=e}setRawValue(e,t){this.value_.setRawValue(e,t)}fetch(){this.value_.rawValue=this.binding.read()}push(){this.binding.write(this.value_.rawValue)}onValueBeforeChange_(e){this.emitter.emit("beforechange",Object.assign(Object.assign({},e),{sender:this}))}onValueChange_(e){this.push(),this.emitter.emit("change",Object.assign(Object.assign({},e),{sender:this}))}}function kw(r){if(!("binding"in r))return!1;const e=r.binding;return jl(e)&&"read"in e&&"write"in e}function Lw(r,e){const n=Object.keys(e).reduce((i,s)=>{if(i===void 0)return;const o=e[s],l=o(r[s]);return l.succeeded?Object.assign(Object.assign({},i),{[s]:l.value}):void 0},{});return n}function Vw(r,e){return r.reduce((t,n)=>{if(t===void 0)return;const i=e(n);if(!(!i.succeeded||i.value===void 0))return[...t,i.value]},[])}function Ow(r){return r===null?!1:typeof r=="object"}function Jr(r){return e=>t=>{if(!e&&t===void 0)return{succeeded:!1,value:void 0};if(e&&t===void 0)return{succeeded:!0,value:void 0};const n=r(t);return n!==void 0?{succeeded:!0,value:n}:{succeeded:!1,value:void 0}}}function Ud(r){return{custom:e=>Jr(e)(r),boolean:Jr(e=>typeof e=="boolean"?e:void 0)(r),number:Jr(e=>typeof e=="number"?e:void 0)(r),string:Jr(e=>typeof e=="string"?e:void 0)(r),function:Jr(e=>typeof e=="function"?e:void 0)(r),constant:e=>Jr(t=>t===e?e:void 0)(r),raw:Jr(e=>e)(r),object:e=>Jr(t=>{if(Ow(t))return Lw(t,e)})(r),array:e=>Jr(t=>{if(Array.isArray(t))return Vw(t,e)})(r)}}const Al={optional:Ud(!0),required:Ud(!1)};function bt(r,e){const t=e(Al),n=Al.required.object(t)(r);return n.succeeded?n.value:void 0}function fr(r,e,t,n){if(e&&!e(r))return!1;const i=bt(r,t);return i?n(i):!1}function mr(r,e){var t;return Jn((t=r?.())!==null&&t!==void 0?t:{},e)}function Zn(r){return"value"in r}function op(r){if(!Gl(r)||!("binding"in r))return!1;const e=r.binding;return jl(e)}const $r="http://www.w3.org/2000/svg";function Ia(r){r.offsetHeight}function Rw(r,e){const t=r.style.transition;r.style.transition="none",e(),r.style.transition=t}function Kl(r){return r.ontouchstart!==void 0}function Dw(){return globalThis}function Mw(){return Dw().document}function Iw(r){const e=r.ownerDocument.defaultView;return e&&"document"in e?r.getContext("2d",{willReadFrequently:!0}):null}const Fw={check:'',dropdown:'',p2dpad:''};function Xa(r,e){const t=r.createElementNS($r,"svg");return t.innerHTML=Fw[e],t}function lp(r,e,t){r.insertBefore(e,r.children[t])}function ql(r){r.parentElement&&r.parentElement.removeChild(r)}function up(r){for(;r.children.length>0;)r.removeChild(r.children[0])}function $w(r){for(;r.childNodes.length>0;)r.removeChild(r.childNodes[0])}function cp(r){return r.relatedTarget?r.relatedTarget:"explicitOriginalTarget"in r?r.explicitOriginalTarget:null}function sn(r,e){r.emitter.on("change",t=>{e(t.rawValue)}),e(r.rawValue)}function Nr(r,e,t){sn(r.value(e),t)}const Bw="tp";function Xe(r){return(t,n)=>[Bw,"-",r,"v",t?`_${t}`:"",n?`-${n}`:""].join("")}const as=Xe("lbl");function Nw(r,e){const t=r.createDocumentFragment();return e.split(` +`).map(i=>r.createTextNode(i)).forEach((i,s)=>{s>0&&t.appendChild(r.createElement("br")),t.appendChild(i)}),t}let dp=class{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(as()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("div");n.classList.add(as("l")),Nr(t.props,"label",s=>{ut(s)?this.element.classList.add(as(void 0,"nol")):(this.element.classList.remove(as(void 0,"nol")),$w(n),n.appendChild(Nw(e,s)))}),this.element.appendChild(n),this.labelElement=n;const i=e.createElement("div");i.classList.add(as("v")),this.element.appendChild(i),this.valueElement=i}},hp=class{constructor(e,t){this.props=t.props,this.valueController=t.valueController,this.viewProps=t.valueController.viewProps,this.view=new dp(e,{props:t.props,viewProps:this.viewProps}),this.view.valueElement.appendChild(this.valueController.view.element)}importProps(e){return fr(e,null,t=>({label:t.optional.string}),t=>(this.props.set("label",t.label),!0))}exportProps(){return mr(null,{label:this.props.get("label")})}};function Gw(){return["veryfirst","first","last","verylast"]}const zd=Xe(""),Hd={veryfirst:"vfst",first:"fst",last:"lst",verylast:"vlst"};let Ya=class{constructor(e){this.parent_=null,this.blade=e.blade,this.view=e.view,this.viewProps=e.viewProps;const t=this.view.element;this.blade.value("positions").emitter.on("change",()=>{Gw().forEach(n=>{t.classList.remove(zd(void 0,Hd[n]))}),this.blade.get("positions").forEach(n=>{t.classList.add(zd(void 0,Hd[n]))})}),this.viewProps.handleDispose(()=>{ql(t)})}get parent(){return this.parent_}set parent(e){this.parent_=e,this.viewProps.set("parent",this.parent_?this.parent_.viewProps:null)}importState(e){return fr(e,null,t=>({disabled:t.required.boolean,hidden:t.required.boolean}),t=>(this.viewProps.importState(t),!0))}exportState(){return mr(null,Object.assign({},this.viewProps.exportState()))}};class ei extends Ya{constructor(e,t){if(t.value!==t.valueController.value)throw qt.shouldNeverHappen();const n=t.valueController.viewProps,i=new hp(e,{blade:t.blade,props:t.props,valueController:t.valueController});super(Object.assign(Object.assign({},t),{view:new dp(e,{props:t.props,viewProps:n}),viewProps:n})),this.labelController=i,this.value=t.value,this.valueController=t.valueController,this.view.valueElement.appendChild(this.valueController.view.element)}importState(e){return fr(e,t=>{var n,i,s;return super.importState(t)&&this.labelController.importProps(t)&&((s=(i=(n=this.valueController).importProps)===null||i===void 0?void 0:i.call(n,e))!==null&&s!==void 0?s:!0)},t=>({value:t.optional.raw}),t=>(t.value&&(this.value.rawValue=t.value),!0))}exportState(){var e,t,n;return mr(()=>super.exportState(),Object.assign(Object.assign({value:this.value.rawValue},this.labelController.exportProps()),(n=(t=(e=this.valueController).exportProps)===null||t===void 0?void 0:t.call(e))!==null&&n!==void 0?n:{}))}}function Kd(r){const e=Object.assign({},r);return delete e.value,e}class pp extends ei{constructor(e,t){super(e,t),this.tag=t.tag}importState(e){return fr(e,t=>super.importState(Kd(e)),t=>({tag:t.optional.string}),t=>(this.tag=t.tag,!0))}exportState(){return mr(()=>Kd(super.exportState()),{binding:{key:this.value.binding.target.key,value:this.value.binding.target.read()},tag:this.tag})}}function jw(r){return Zn(r)&&op(r.value)}class Uw extends pp{importState(e){return fr(e,t=>super.importState(t),t=>({binding:t.required.object({value:t.required.raw})}),t=>(this.value.binding.inject(t.binding.value),this.value.fetch(),!0))}}function zw(r){return Zn(r)&&kw(r.value)}function fp(r,e){for(;r.lengthr.length?t.splice(0,t.length-r.length):fp(t,r.length),t}class Xw{constructor(e){this.emitter=new kt,this.onTick_=this.onTick_.bind(this),this.onValueBeforeChange_=this.onValueBeforeChange_.bind(this),this.onValueChange_=this.onValueChange_.bind(this),this.binding=e.binding,this.value_=dt(Hw(e.bufferSize)),this.value_.emitter.on("beforechange",this.onValueBeforeChange_),this.value_.emitter.on("change",this.onValueChange_),this.ticker=e.ticker,this.ticker.emitter.on("tick",this.onTick_),this.fetch()}get rawValue(){return this.value_.rawValue}set rawValue(e){this.value_.rawValue=e}setRawValue(e,t){this.value_.setRawValue(e,t)}fetch(){this.value_.rawValue=qw(this.value_.rawValue,this.binding.read())}onTick_(){this.fetch()}onValueBeforeChange_(e){this.emitter.emit("beforechange",Object.assign(Object.assign({},e),{sender:this}))}onValueChange_(e){this.emitter.emit("change",Object.assign(Object.assign({},e),{sender:this}))}}function Yw(r){if(!("binding"in r))return!1;const e=r.binding;return jl(e)&&"read"in e&&!("write"in e)}class Ww extends pp{exportState(){return mr(()=>super.exportState(),{binding:{readonly:!0}})}}function Zw(r){return Zn(r)&&Yw(r.value)}let Qw=class extends ii{get label(){return this.controller.labelController.props.get("label")}set label(e){this.controller.labelController.props.set("label",e)}get title(){var e;return(e=this.controller.buttonController.props.get("title"))!==null&&e!==void 0?e:""}set title(e){this.controller.buttonController.props.set("title",e)}on(e,t){const n=t.bind(this);return this.controller.buttonController.emitter.on(e,s=>{n(new Sw(this,s.nativeEvent))}),this}off(e,t){return this.controller.buttonController.emitter.off(e,t),this}};function Jw(r,e,t){t?r.classList.add(e):r.classList.remove(e)}function Ii(r,e){return t=>{Jw(r,e,t)}}function Xl(r,e){sn(r,t=>{e.textContent=t??""})}const al=Xe("btn");let e0=class{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(al()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("button");n.classList.add(al("b")),t.viewProps.bindDisabled(n),this.element.appendChild(n),this.buttonElement=n;const i=e.createElement("div");i.classList.add(al("t")),Xl(t.props.value("title"),i),this.buttonElement.appendChild(i)}},t0=class{constructor(e,t){this.emitter=new kt,this.onClick_=this.onClick_.bind(this),this.props=t.props,this.viewProps=t.viewProps,this.view=new e0(e,{props:this.props,viewProps:this.viewProps}),this.view.buttonElement.addEventListener("click",this.onClick_)}importProps(e){return fr(e,null,t=>({title:t.optional.string}),t=>(this.props.set("title",t.title),!0))}exportProps(){return mr(null,{title:this.props.get("title")})}onClick_(e){this.emitter.emit("click",{nativeEvent:e,sender:this})}},qd=class extends Ya{constructor(e,t){const n=new t0(e,{props:t.buttonProps,viewProps:t.viewProps}),i=new hp(e,{blade:t.blade,props:t.labelProps,valueController:n});super({blade:t.blade,view:i.view,viewProps:t.viewProps}),this.buttonController=n,this.labelController=i}importState(e){return fr(e,t=>super.importState(t)&&this.buttonController.importProps(t)&&this.labelController.importProps(t),()=>({}),()=>!0)}exportState(){return mr(()=>super.exportState(),Object.assign(Object.assign({},this.buttonController.exportProps()),this.labelController.exportProps()))}},mp=class{constructor(e){const[t,n]=e.split("-"),i=t.split(".");this.major=parseInt(i[0],10),this.minor=parseInt(i[1],10),this.patch=parseInt(i[2],10),this.prerelease=n??null}toString(){const e=[this.major,this.minor,this.patch].join(".");return this.prerelease!==null?[e,this.prerelease].join("-"):e}};const Fi=new mp("2.0.5");function Qt(r){return Object.assign({core:Fi},r)}const r0=Qt({id:"button",type:"blade",accept(r){const e=bt(r,t=>({title:t.required.string,view:t.required.constant("button"),label:t.optional.string}));return e?{params:e}:null},controller(r){return new qd(r.document,{blade:r.blade,buttonProps:Ue.fromObject({title:r.params.title}),labelProps:Ue.fromObject({label:r.params.label}),viewProps:r.viewProps})},api(r){return r.controller instanceof qd?new Qw(r.controller):null}});function n0(r,e){return r.addBlade(Object.assign(Object.assign({},e),{view:"button"}))}function i0(r,e){return r.addBlade(Object.assign(Object.assign({},e),{view:"folder"}))}function s0(r,e){return r.addBlade(Object.assign(Object.assign({},e),{view:"tab"}))}function a0(r){return Gl(r)?"refresh"in r&&typeof r.refresh=="function":!1}function o0(r,e){if(!Gd.isBindable(r))throw qt.notBindable();return new Gd(r,e)}let l0=class{constructor(e,t){this.onRackValueChange_=this.onRackValueChange_.bind(this),this.controller_=e,this.emitter_=new kt,this.pool_=t,this.controller_.rack.emitter.on("valuechange",this.onRackValueChange_)}get children(){return this.controller_.rack.children.map(e=>this.pool_.createApi(e))}addBinding(e,t,n){const i=n??{},s=this.controller_.element.ownerDocument,o=this.pool_.createBinding(s,o0(e,t),i),l=this.pool_.createBindingApi(o);return this.add(l,i.index)}addFolder(e){return i0(this,e)}addButton(e){return n0(this,e)}addTab(e){return s0(this,e)}add(e,t){const n=e.controller;return this.controller_.rack.add(n,t),e}remove(e){this.controller_.rack.remove(e.controller)}addBlade(e){const t=this.controller_.element.ownerDocument,n=this.pool_.createBlade(t,e),i=this.pool_.createApi(n);return this.add(i,e.index)}on(e,t){const n=t.bind(this);return this.emitter_.on(e,i=>{n(i)},{key:t}),this}off(e,t){return this.emitter_.off(e,t),this}refresh(){this.children.forEach(e=>{a0(e)&&e.refresh()})}onRackValueChange_(e){const t=e.bladeController,n=this.pool_.createApi(t),i=op(t.value)?t.value.binding:null;this.emitter_.emit("change",new ks(n,i?i.target.read():t.value.rawValue,e.options.last))}},Yl=class extends ii{constructor(e,t){super(e),this.rackApi_=new l0(e.rackController,t)}refresh(){this.rackApi_.refresh()}},Wl=class extends Ya{constructor(e){super({blade:e.blade,view:e.view,viewProps:e.rackController.viewProps}),this.rackController=e.rackController}importState(e){return fr(e,t=>super.importState(t),t=>({children:t.required.array(t.required.raw)}),t=>this.rackController.rack.children.every((n,i)=>n.importState(t.children[i])))}exportState(){return mr(()=>super.exportState(),{children:this.rackController.rack.children.map(e=>e.exportState())})}};function Sl(r){return"rackController"in r}let u0=class{constructor(e){this.emitter=new kt,this.items_=[],this.cache_=new Set,this.onSubListAdd_=this.onSubListAdd_.bind(this),this.onSubListRemove_=this.onSubListRemove_.bind(this),this.extract_=e}get items(){return this.items_}allItems(){return Array.from(this.cache_)}find(e){for(const t of this.allItems())if(e(t))return t;return null}includes(e){return this.cache_.has(e)}add(e,t){if(this.includes(e))throw qt.shouldNeverHappen();const n=t!==void 0?t:this.items_.length;this.items_.splice(n,0,e),this.cache_.add(e);const i=this.extract_(e);i&&(i.emitter.on("add",this.onSubListAdd_),i.emitter.on("remove",this.onSubListRemove_),i.allItems().forEach(s=>{this.cache_.add(s)})),this.emitter.emit("add",{index:n,item:e,root:this,target:this})}remove(e){const t=this.items_.indexOf(e);if(t<0)return;this.items_.splice(t,1),this.cache_.delete(e);const n=this.extract_(e);n&&(n.allItems().forEach(i=>{this.cache_.delete(i)}),n.emitter.off("add",this.onSubListAdd_),n.emitter.off("remove",this.onSubListRemove_)),this.emitter.emit("remove",{index:t,item:e,root:this,target:this})}onSubListAdd_(e){this.cache_.add(e.item),this.emitter.emit("add",{index:e.index,item:e.item,root:this,target:e.target})}onSubListRemove_(e){this.cache_.delete(e.item),this.emitter.emit("remove",{index:e.index,item:e.item,root:this,target:e.target})}};function c0(r,e){for(let t=0;t!i.viewProps.get("hidden")),t=e[0],n=e[e.length-1];this.bcSet_.items.forEach(i=>{const s=[];i===t&&(s.push("first"),(!this.blade_||this.blade_.get("positions").includes("veryfirst"))&&s.push("veryfirst")),i===n&&(s.push("last"),(!this.blade_||this.blade_.get("positions").includes("verylast"))&&s.push("verylast")),i.blade.set("positions",s)})}onChildPositionsChange_(){this.updatePositions_(),this.emitter.emit("layout",{sender:this})}onChildViewPropsChange_(e){this.updatePositions_(),this.emitter.emit("layout",{sender:this})}onChildDispose_(){this.bcSet_.items.filter(t=>t.viewProps.get("disposed")).forEach(t=>{this.bcSet_.remove(t)})}onChildValueChange_(e){const t=c0(this.find(Zn),e.sender);if(!t)throw qt.alreadyDisposed();this.emitter.emit("valuechange",{bladeController:t,options:e.options,sender:this})}onRackLayout_(e){this.updatePositions_(),this.emitter.emit("layout",{sender:this})}onRackValueChange_(e){this.emitter.emit("valuechange",{bladeController:e.bladeController,options:e.options,sender:this})}onBladePositionsChange_(){this.updatePositions_()}},Zl=class{constructor(e){this.onRackAdd_=this.onRackAdd_.bind(this),this.onRackRemove_=this.onRackRemove_.bind(this),this.element=e.element,this.viewProps=e.viewProps;const t=new h0({blade:e.root?void 0:e.blade,viewProps:e.viewProps});t.emitter.on("add",this.onRackAdd_),t.emitter.on("remove",this.onRackRemove_),this.rack=t,this.viewProps.handleDispose(()=>{for(let n=this.rack.children.length-1;n>=0;n--)this.rack.children[n].viewProps.set("disposed",!0)})}onRackAdd_(e){e.root&&lp(this.element,e.bladeController.view.element,e.index)}onRackRemove_(e){e.root&&ql(e.bladeController.view.element)}};function $i(){return new Ue({positions:dt([],{equals:U_})})}let Ql=class vp extends Ue{constructor(e){super(e)}static create(e){const t={completed:!0,expanded:e,expandedHeight:null,shouldFixHeight:!1,temporaryExpanded:null},n=Ue.createCore(t);return new vp(n)}get styleExpanded(){var e;return(e=this.get("temporaryExpanded"))!==null&&e!==void 0?e:this.get("expanded")}get styleHeight(){if(!this.styleExpanded)return"0";const e=this.get("expandedHeight");return this.get("shouldFixHeight")&&!ut(e)?`${e}px`:"auto"}bindExpandedClass(e,t){const n=()=>{this.styleExpanded?e.classList.add(t):e.classList.remove(t)};Nr(this,"expanded",n),Nr(this,"temporaryExpanded",n)}cleanUpTransition(){this.set("shouldFixHeight",!1),this.set("expandedHeight",null),this.set("completed",!0)}};function p0(r,e){let t=0;return Rw(e,()=>{r.set("expandedHeight",null),r.set("temporaryExpanded",!0),Ia(e),t=e.clientHeight,r.set("temporaryExpanded",null),Ia(e)}),t}function Xd(r,e){e.style.height=r.styleHeight}function Jl(r,e){r.value("expanded").emitter.on("beforechange",()=>{if(r.set("completed",!1),ut(r.get("expandedHeight"))){const t=p0(r,e);t>0&&r.set("expandedHeight",t)}r.set("shouldFixHeight",!0),Ia(e)}),r.emitter.on("change",()=>{Xd(r,e)}),Xd(r,e),e.addEventListener("transitionend",t=>{t.propertyName==="height"&&r.cleanUpTransition()})}let bp=class extends Yl{constructor(e,t){super(e,t),this.emitter_=new kt,this.controller.foldable.value("expanded").emitter.on("change",n=>{this.emitter_.emit("fold",new Pw(this,n.sender.rawValue))}),this.rackApi_.on("change",n=>{this.emitter_.emit("change",n)})}get expanded(){return this.controller.foldable.get("expanded")}set expanded(e){this.controller.foldable.set("expanded",e)}get title(){return this.controller.props.get("title")}set title(e){this.controller.props.set("title",e)}get children(){return this.rackApi_.children}addBinding(e,t,n){return this.rackApi_.addBinding(e,t,n)}addFolder(e){return this.rackApi_.addFolder(e)}addButton(e){return this.rackApi_.addButton(e)}addTab(e){return this.rackApi_.addTab(e)}add(e,t){return this.rackApi_.add(e,t)}remove(e){this.rackApi_.remove(e)}addBlade(e){return this.rackApi_.addBlade(e)}on(e,t){const n=t.bind(this);return this.emitter_.on(e,i=>{n(i)},{key:t}),this}off(e,t){return this.emitter_.off(e,t),this}};const _p=Xe("cnt");let f0=class{constructor(e,t){var n;this.className_=Xe((n=t.viewName)!==null&&n!==void 0?n:"fld"),this.element=e.createElement("div"),this.element.classList.add(this.className_(),_p()),t.viewProps.bindClassModifiers(this.element),this.foldable_=t.foldable,this.foldable_.bindExpandedClass(this.element,this.className_(void 0,"expanded")),Nr(this.foldable_,"completed",Ii(this.element,this.className_(void 0,"cpl")));const i=e.createElement("button");i.classList.add(this.className_("b")),Nr(t.props,"title",x=>{ut(x)?this.element.classList.add(this.className_(void 0,"not")):this.element.classList.remove(this.className_(void 0,"not"))}),t.viewProps.bindDisabled(i),this.element.appendChild(i),this.buttonElement=i;const s=e.createElement("div");s.classList.add(this.className_("i")),this.element.appendChild(s);const o=e.createElement("div");o.classList.add(this.className_("t")),Xl(t.props.value("title"),o),this.buttonElement.appendChild(o),this.titleElement=o;const l=e.createElement("div");l.classList.add(this.className_("m")),this.buttonElement.appendChild(l);const y=e.createElement("div");y.classList.add(this.className_("c")),this.element.appendChild(y),this.containerElement=y}},Tl=class extends Wl{constructor(e,t){var n;const i=Ql.create((n=t.expanded)!==null&&n!==void 0?n:!0),s=new f0(e,{foldable:i,props:t.props,viewName:t.root?"rot":void 0,viewProps:t.viewProps});super(Object.assign(Object.assign({},t),{rackController:new Zl({blade:t.blade,element:s.containerElement,root:t.root,viewProps:t.viewProps}),view:s})),this.onTitleClick_=this.onTitleClick_.bind(this),this.props=t.props,this.foldable=i,Jl(this.foldable,this.view.containerElement),this.rackController.rack.emitter.on("add",()=>{this.foldable.cleanUpTransition()}),this.rackController.rack.emitter.on("remove",()=>{this.foldable.cleanUpTransition()}),this.view.buttonElement.addEventListener("click",this.onTitleClick_)}get document(){return this.view.element.ownerDocument}importState(e){return fr(e,t=>super.importState(t),t=>({expanded:t.required.boolean,title:t.optional.string}),t=>(this.foldable.set("expanded",t.expanded),this.props.set("title",t.title),!0))}exportState(){return mr(()=>super.exportState(),{expanded:this.foldable.get("expanded"),title:this.props.get("title")})}onTitleClick_(){this.foldable.set("expanded",!this.foldable.get("expanded"))}};const m0=Qt({id:"folder",type:"blade",accept(r){const e=bt(r,t=>({title:t.required.string,view:t.required.constant("folder"),expanded:t.optional.boolean}));return e?{params:e}:null},controller(r){return new Tl(r.document,{blade:r.blade,expanded:r.params.expanded,props:Ue.fromObject({title:r.params.title}),viewProps:r.viewProps})},api(r){return r.controller instanceof Tl?new bp(r.controller,r.pool):null}}),v0=Xe("");function Yd(r,e){return Ii(r,v0(void 0,e))}let si=class wp extends Ue{constructor(e){var t;super(e),this.onDisabledChange_=this.onDisabledChange_.bind(this),this.onParentChange_=this.onParentChange_.bind(this),this.onParentGlobalDisabledChange_=this.onParentGlobalDisabledChange_.bind(this),[this.globalDisabled_,this.setGlobalDisabled_]=X_(dt(this.getGlobalDisabled_())),this.value("disabled").emitter.on("change",this.onDisabledChange_),this.value("parent").emitter.on("change",this.onParentChange_),(t=this.get("parent"))===null||t===void 0||t.globalDisabled.emitter.on("change",this.onParentGlobalDisabledChange_)}static create(e){var t,n,i;const s=e??{};return new wp(Ue.createCore({disabled:(t=s.disabled)!==null&&t!==void 0?t:!1,disposed:!1,hidden:(n=s.hidden)!==null&&n!==void 0?n:!1,parent:(i=s.parent)!==null&&i!==void 0?i:null}))}get globalDisabled(){return this.globalDisabled_}bindClassModifiers(e){sn(this.globalDisabled_,Yd(e,"disabled")),Nr(this,"hidden",Yd(e,"hidden"))}bindDisabled(e){sn(this.globalDisabled_,t=>{e.disabled=t})}bindTabIndex(e){sn(this.globalDisabled_,t=>{e.tabIndex=t?-1:0})}handleDispose(e){this.value("disposed").emitter.on("change",t=>{t&&e()})}importState(e){this.set("disabled",e.disabled),this.set("hidden",e.hidden)}exportState(){return{disabled:this.get("disabled"),hidden:this.get("hidden")}}getGlobalDisabled_(){const e=this.get("parent");return(e?e.globalDisabled.rawValue:!1)||this.get("disabled")}updateGlobalDisabled_(){this.setGlobalDisabled_(this.getGlobalDisabled_())}onDisabledChange_(){this.updateGlobalDisabled_()}onParentGlobalDisabledChange_(){this.updateGlobalDisabled_()}onParentChange_(e){var t;const n=e.previousRawValue;n?.globalDisabled.emitter.off("change",this.onParentGlobalDisabledChange_),(t=this.get("parent"))===null||t===void 0||t.globalDisabled.emitter.on("change",this.onParentGlobalDisabledChange_),this.updateGlobalDisabled_()}};const Wd=Xe("tbp");let b0=class{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(Wd()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("div");n.classList.add(Wd("c")),this.element.appendChild(n),this.containerElement=n}};const os=Xe("tbi");let _0=class{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(os()),t.viewProps.bindClassModifiers(this.element),Nr(t.props,"selected",s=>{s?this.element.classList.add(os(void 0,"sel")):this.element.classList.remove(os(void 0,"sel"))});const n=e.createElement("button");n.classList.add(os("b")),t.viewProps.bindDisabled(n),this.element.appendChild(n),this.buttonElement=n;const i=e.createElement("div");i.classList.add(os("t")),Xl(t.props.value("title"),i),this.buttonElement.appendChild(i),this.titleElement=i}},w0=class{constructor(e,t){this.emitter=new kt,this.onClick_=this.onClick_.bind(this),this.props=t.props,this.viewProps=t.viewProps,this.view=new _0(e,{props:t.props,viewProps:t.viewProps}),this.view.buttonElement.addEventListener("click",this.onClick_)}onClick_(){this.emitter.emit("click",{sender:this})}},kl=class extends Wl{constructor(e,t){const n=new b0(e,{viewProps:t.viewProps});super(Object.assign(Object.assign({},t),{rackController:new Zl({blade:t.blade,element:n.containerElement,viewProps:t.viewProps}),view:n})),this.onItemClick_=this.onItemClick_.bind(this),this.ic_=new w0(e,{props:t.itemProps,viewProps:si.create()}),this.ic_.emitter.on("click",this.onItemClick_),this.props=t.props,Nr(this.props,"selected",i=>{this.itemController.props.set("selected",i),this.viewProps.set("hidden",!i)})}get itemController(){return this.ic_}importState(e){return fr(e,t=>super.importState(t),t=>({selected:t.required.boolean,title:t.required.string}),t=>(this.ic_.props.set("selected",t.selected),this.ic_.props.set("title",t.title),!0))}exportState(){return mr(()=>super.exportState(),{selected:this.ic_.props.get("selected"),title:this.ic_.props.get("title")})}onItemClick_(){this.props.set("selected",!0)}},g0=class extends Yl{constructor(e,t){super(e,t),this.emitter_=new kt,this.onSelect_=this.onSelect_.bind(this),this.pool_=t,this.rackApi_.on("change",n=>{this.emitter_.emit("change",n)}),this.controller.tab.selectedIndex.emitter.on("change",this.onSelect_)}get pages(){return this.rackApi_.children}addPage(e){const t=this.controller.view.element.ownerDocument,n=new kl(t,{blade:$i(),itemProps:Ue.fromObject({selected:!1,title:e.title}),props:Ue.fromObject({selected:!1}),viewProps:si.create()}),i=this.pool_.createApi(n);return this.rackApi_.add(i,e.index)}removePage(e){this.rackApi_.remove(this.rackApi_.children[e])}on(e,t){const n=t.bind(this);return this.emitter_.on(e,i=>{n(i)},{key:t}),this}off(e,t){return this.emitter_.off(e,t),this}onSelect_(e){this.emitter_.emit("select",new Aw(this,e.rawValue))}},y0=class extends Yl{get title(){var e;return(e=this.controller.itemController.props.get("title"))!==null&&e!==void 0?e:""}set title(e){this.controller.itemController.props.set("title",e)}get selected(){return this.controller.props.get("selected")}set selected(e){this.controller.props.set("selected",e)}get children(){return this.rackApi_.children}addButton(e){return this.rackApi_.addButton(e)}addFolder(e){return this.rackApi_.addFolder(e)}addTab(e){return this.rackApi_.addTab(e)}add(e,t){this.rackApi_.add(e,t)}remove(e){this.rackApi_.remove(e)}addBinding(e,t,n){return this.rackApi_.addBinding(e,t,n)}addBlade(e){return this.rackApi_.addBlade(e)}};const Zd=-1;let x0=class{constructor(){this.onItemSelectedChange_=this.onItemSelectedChange_.bind(this),this.empty=dt(!0),this.selectedIndex=dt(Zd),this.items_=[]}add(e,t){const n=t??this.items_.length;this.items_.splice(n,0,e),e.emitter.on("change",this.onItemSelectedChange_),this.keepSelection_()}remove(e){const t=this.items_.indexOf(e);t<0||(this.items_.splice(t,1),e.emitter.off("change",this.onItemSelectedChange_),this.keepSelection_())}keepSelection_(){if(this.items_.length===0){this.selectedIndex.rawValue=Zd,this.empty.rawValue=!0;return}const e=this.items_.findIndex(t=>t.rawValue);e<0?(this.items_.forEach((t,n)=>{t.rawValue=n===0}),this.selectedIndex.rawValue=0):(this.items_.forEach((t,n)=>{t.rawValue=n===e}),this.selectedIndex.rawValue=e),this.empty.rawValue=!1}onItemSelectedChange_(e){if(e.rawValue){const t=this.items_.findIndex(n=>n===e.sender);this.items_.forEach((n,i)=>{n.rawValue=i===t}),this.selectedIndex.rawValue=t}else this.keepSelection_()}};const ls=Xe("tab");let C0=class{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(ls(),_p()),t.viewProps.bindClassModifiers(this.element),sn(t.empty,Ii(this.element,ls(void 0,"nop")));const n=e.createElement("div");n.classList.add(ls("t")),this.element.appendChild(n),this.itemsElement=n;const i=e.createElement("div");i.classList.add(ls("i")),this.element.appendChild(i);const s=e.createElement("div");s.classList.add(ls("c")),this.element.appendChild(s),this.contentsElement=s}},Qd=class extends Wl{constructor(e,t){const n=new x0,i=new C0(e,{empty:n.empty,viewProps:t.viewProps});super({blade:t.blade,rackController:new Zl({blade:t.blade,element:i.contentsElement,viewProps:t.viewProps}),view:i}),this.onRackAdd_=this.onRackAdd_.bind(this),this.onRackRemove_=this.onRackRemove_.bind(this);const s=this.rackController.rack;s.emitter.on("add",this.onRackAdd_),s.emitter.on("remove",this.onRackRemove_),this.tab=n}add(e,t){this.rackController.rack.add(e,t)}remove(e){this.rackController.rack.remove(this.rackController.rack.children[e])}onRackAdd_(e){if(!e.root)return;const t=e.bladeController;lp(this.view.itemsElement,t.itemController.view.element,e.index),t.itemController.viewProps.set("parent",this.viewProps),this.tab.add(t.props.value("selected"))}onRackRemove_(e){if(!e.root)return;const t=e.bladeController;ql(t.itemController.view.element),t.itemController.viewProps.set("parent",null),this.tab.remove(t.props.value("selected"))}};const gp=Qt({id:"tab",type:"blade",accept(r){const e=bt(r,t=>({pages:t.required.array(t.required.object({title:t.required.string})),view:t.required.constant("tab")}));return!e||e.pages.length===0?null:{params:e}},controller(r){const e=new Qd(r.document,{blade:r.blade,viewProps:r.viewProps});return r.params.pages.forEach(t=>{const n=new kl(r.document,{blade:$i(),itemProps:Ue.fromObject({selected:!1,title:t.title}),props:Ue.fromObject({selected:!1}),viewProps:si.create()});e.add(n)}),e},api(r){return r.controller instanceof Qd?new g0(r.controller,r.pool):r.controller instanceof kl?new y0(r.controller,r.pool):null}});function E0(r,e){const t=r.accept(e.params);if(!t)return null;const n=bt(e.params,i=>({disabled:i.optional.boolean,hidden:i.optional.boolean}));return r.controller({blade:$i(),document:e.document,params:Object.assign(Object.assign({},t.params),{disabled:n?.disabled,hidden:n?.hidden}),viewProps:si.create({disabled:n?.disabled,hidden:n?.hidden})})}let eu=class extends gs{get options(){return this.controller.valueController.props.get("options")}set options(e){this.controller.valueController.props.set("options",e)}};class P0{constructor(){this.disabled=!1,this.emitter=new kt}dispose(){}tick(){this.disabled||this.emitter.emit("tick",{sender:this})}}class A0{constructor(e,t){this.disabled_=!1,this.timerId_=null,this.onTick_=this.onTick_.bind(this),this.doc_=e,this.emitter=new kt,this.interval_=t,this.setTimer_()}get disabled(){return this.disabled_}set disabled(e){this.disabled_=e,this.disabled_?this.clearTimer_():this.setTimer_()}dispose(){this.clearTimer_()}clearTimer_(){if(this.timerId_===null)return;const e=this.doc_.defaultView;e&&e.clearInterval(this.timerId_),this.timerId_=null}setTimer_(){if(this.clearTimer_(),this.interval_<=0)return;const e=this.doc_.defaultView;e&&(this.timerId_=e.setInterval(this.onTick_,this.interval_))}onTick_(){this.disabled_||this.emitter.emit("tick",{sender:this})}}let Ls=class{constructor(e){this.constraints=e}constrain(e){return this.constraints.reduce((t,n)=>n.constrain(t),e)}};function Fa(r,e){if(r instanceof e)return r;if(r instanceof Ls){const t=r.constraints.reduce((n,i)=>n||(i instanceof e?i:null),null);if(t)return t}return null}let Vs=class{constructor(e){this.values=Ue.fromObject({options:e})}constrain(e){const t=this.values.get("options");return t.length===0||t.filter(i=>i.value===e).length>0?e:t[0].value}};function Os(r){var e;const t=Al;if(Array.isArray(r))return(e=bt({items:r},n=>({items:n.required.array(n.required.object({text:n.required.string,value:n.required.raw}))})))===null||e===void 0?void 0:e.items;if(typeof r=="object")return t.required.raw(r).value}function tu(r){if(Array.isArray(r))return r;const e=[];return Object.keys(r).forEach(t=>{e.push({text:t,value:r[t]})}),e}function ru(r){return ut(r)?null:new Vs(tu(r))}const ol=Xe("lst");let S0=class{constructor(e,t){this.onValueChange_=this.onValueChange_.bind(this),this.props_=t.props,this.element=e.createElement("div"),this.element.classList.add(ol()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("select");n.classList.add(ol("s")),t.viewProps.bindDisabled(n),this.element.appendChild(n),this.selectElement=n;const i=e.createElement("div");i.classList.add(ol("m")),i.appendChild(Xa(e,"dropdown")),this.element.appendChild(i),t.value.emitter.on("change",this.onValueChange_),this.value_=t.value,Nr(this.props_,"options",s=>{up(this.selectElement),s.forEach(o=>{const l=e.createElement("option");l.textContent=o.text,this.selectElement.appendChild(l)}),this.update_()})}update_(){const e=this.props_.get("options").map(t=>t.value);this.selectElement.selectedIndex=e.indexOf(this.value_.rawValue)}onValueChange_(){this.update_()}},Vn=class{constructor(e,t){this.onSelectChange_=this.onSelectChange_.bind(this),this.props=t.props,this.value=t.value,this.viewProps=t.viewProps,this.view=new S0(e,{props:this.props,value:this.value,viewProps:this.viewProps}),this.view.selectElement.addEventListener("change",this.onSelectChange_)}onSelectChange_(e){const t=e.currentTarget;this.value.rawValue=this.props.get("options")[t.selectedIndex].value}importProps(e){return fr(e,null,t=>({options:t.required.custom(Os)}),t=>(this.props.set("options",tu(t.options)),!0))}exportProps(){return mr(null,{options:this.props.get("options")})}};const Jd=Xe("pop");let T0=class{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(Jd()),t.viewProps.bindClassModifiers(this.element),sn(t.shows,Ii(this.element,Jd(void 0,"v")))}},yp=class{constructor(e,t){this.shows=dt(!1),this.viewProps=t.viewProps,this.view=new T0(e,{shows:this.shows,viewProps:this.viewProps})}};const eh=Xe("txt");let k0=class{constructor(e,t){this.onChange_=this.onChange_.bind(this),this.element=e.createElement("div"),this.element.classList.add(eh()),t.viewProps.bindClassModifiers(this.element),this.props_=t.props,this.props_.emitter.on("change",this.onChange_);const n=e.createElement("input");n.classList.add(eh("i")),n.type="text",t.viewProps.bindDisabled(n),this.element.appendChild(n),this.inputElement=n,t.value.emitter.on("change",this.onChange_),this.value_=t.value,this.refresh()}refresh(){const e=this.props_.get("formatter");this.inputElement.value=e(this.value_.rawValue)}onChange_(){this.refresh()}},ys=class{constructor(e,t){this.onInputChange_=this.onInputChange_.bind(this),this.parser_=t.parser,this.props=t.props,this.value=t.value,this.viewProps=t.viewProps,this.view=new k0(e,{props:t.props,value:this.value,viewProps:this.viewProps}),this.view.inputElement.addEventListener("change",this.onInputChange_)}onInputChange_(e){const n=e.currentTarget.value,i=this.parser_(n);ut(i)||(this.value.rawValue=i),this.view.refresh()}};function L0(r){return String(r)}function xp(r){return r==="false"?!1:!!r}function th(r){return L0(r)}function V0(r){return e=>r.reduce((t,n)=>t!==null?t:n(e),null)}const O0=lr(0);function $a(r){return O0(r)+"%"}function Cp(r){return String(r)}function Ll(r){return r}function Bi({primary:r,secondary:e,forward:t,backward:n}){let i=!1;function s(o){i||(i=!0,o(),i=!1)}r.emitter.on("change",o=>{s(()=>{e.setRawValue(t(r.rawValue,e.rawValue),o.options)})}),e.emitter.on("change",o=>{s(()=>{r.setRawValue(n(r.rawValue,e.rawValue),o.options)}),s(()=>{e.setRawValue(t(r.rawValue,e.rawValue),o.options)})}),s(()=>{e.setRawValue(t(r.rawValue,e.rawValue),{forceEmit:!1,last:!0})})}function ar(r,e){const t=r*(e.altKey?.1:1)*(e.shiftKey?10:1);return e.upKey?+t:e.downKey?-t:0}function xs(r){return{altKey:r.altKey,downKey:r.key==="ArrowDown",shiftKey:r.shiftKey,upKey:r.key==="ArrowUp"}}function ln(r){return{altKey:r.altKey,downKey:r.key==="ArrowLeft",shiftKey:r.shiftKey,upKey:r.key==="ArrowRight"}}function R0(r){return r==="ArrowUp"||r==="ArrowDown"}function Ep(r){return R0(r)||r==="ArrowLeft"||r==="ArrowRight"}function ll(r,e){var t,n;const i=e.ownerDocument.defaultView,s=e.getBoundingClientRect();return{x:r.pageX-(((t=i&&i.scrollX)!==null&&t!==void 0?t:0)+s.left),y:r.pageY-(((n=i&&i.scrollY)!==null&&n!==void 0?n:0)+s.top)}}let ai=class{constructor(e){this.lastTouch_=null,this.onDocumentMouseMove_=this.onDocumentMouseMove_.bind(this),this.onDocumentMouseUp_=this.onDocumentMouseUp_.bind(this),this.onMouseDown_=this.onMouseDown_.bind(this),this.onTouchEnd_=this.onTouchEnd_.bind(this),this.onTouchMove_=this.onTouchMove_.bind(this),this.onTouchStart_=this.onTouchStart_.bind(this),this.elem_=e,this.emitter=new kt,e.addEventListener("touchstart",this.onTouchStart_,{passive:!1}),e.addEventListener("touchmove",this.onTouchMove_,{passive:!0}),e.addEventListener("touchend",this.onTouchEnd_),e.addEventListener("mousedown",this.onMouseDown_)}computePosition_(e){const t=this.elem_.getBoundingClientRect();return{bounds:{width:t.width,height:t.height},point:e?{x:e.x,y:e.y}:null}}onMouseDown_(e){var t;e.preventDefault(),(t=e.currentTarget)===null||t===void 0||t.focus();const n=this.elem_.ownerDocument;n.addEventListener("mousemove",this.onDocumentMouseMove_),n.addEventListener("mouseup",this.onDocumentMouseUp_),this.emitter.emit("down",{altKey:e.altKey,data:this.computePosition_(ll(e,this.elem_)),sender:this,shiftKey:e.shiftKey})}onDocumentMouseMove_(e){this.emitter.emit("move",{altKey:e.altKey,data:this.computePosition_(ll(e,this.elem_)),sender:this,shiftKey:e.shiftKey})}onDocumentMouseUp_(e){const t=this.elem_.ownerDocument;t.removeEventListener("mousemove",this.onDocumentMouseMove_),t.removeEventListener("mouseup",this.onDocumentMouseUp_),this.emitter.emit("up",{altKey:e.altKey,data:this.computePosition_(ll(e,this.elem_)),sender:this,shiftKey:e.shiftKey})}onTouchStart_(e){e.preventDefault();const t=e.targetTouches.item(0),n=this.elem_.getBoundingClientRect();this.emitter.emit("down",{altKey:e.altKey,data:this.computePosition_(t?{x:t.clientX-n.left,y:t.clientY-n.top}:void 0),sender:this,shiftKey:e.shiftKey}),this.lastTouch_=t}onTouchMove_(e){const t=e.targetTouches.item(0),n=this.elem_.getBoundingClientRect();this.emitter.emit("move",{altKey:e.altKey,data:this.computePosition_(t?{x:t.clientX-n.left,y:t.clientY-n.top}:void 0),sender:this,shiftKey:e.shiftKey}),this.lastTouch_=t}onTouchEnd_(e){var t;const n=(t=e.targetTouches.item(0))!==null&&t!==void 0?t:this.lastTouch_,i=this.elem_.getBoundingClientRect();this.emitter.emit("up",{altKey:e.altKey,data:this.computePosition_(n?{x:n.clientX-i.left,y:n.clientY-i.top}:void 0),sender:this,shiftKey:e.shiftKey})}};const xr=Xe("txt");let D0=class{constructor(e,t){this.onChange_=this.onChange_.bind(this),this.props_=t.props,this.props_.emitter.on("change",this.onChange_),this.element=e.createElement("div"),this.element.classList.add(xr(),xr(void 0,"num")),t.arrayPosition&&this.element.classList.add(xr(void 0,t.arrayPosition)),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("input");n.classList.add(xr("i")),n.type="text",t.viewProps.bindDisabled(n),this.element.appendChild(n),this.inputElement=n,this.onDraggingChange_=this.onDraggingChange_.bind(this),this.dragging_=t.dragging,this.dragging_.emitter.on("change",this.onDraggingChange_),this.element.classList.add(xr()),this.inputElement.classList.add(xr("i"));const i=e.createElement("div");i.classList.add(xr("k")),this.element.appendChild(i),this.knobElement=i;const s=e.createElementNS($r,"svg");s.classList.add(xr("g")),this.knobElement.appendChild(s);const o=e.createElementNS($r,"path");o.classList.add(xr("gb")),s.appendChild(o),this.guideBodyElem_=o;const l=e.createElementNS($r,"path");l.classList.add(xr("gh")),s.appendChild(l),this.guideHeadElem_=l;const y=e.createElement("div");y.classList.add(Xe("tt")()),this.knobElement.appendChild(y),this.tooltipElem_=y,t.value.emitter.on("change",this.onChange_),this.value=t.value,this.refresh()}onDraggingChange_(e){if(e.rawValue===null){this.element.classList.remove(xr(void 0,"drg"));return}this.element.classList.add(xr(void 0,"drg"));const t=e.rawValue/this.props_.get("pointerScale"),n=t+(t>0?-1:t<0?1:0),i=Rt(-n,-4,4);this.guideHeadElem_.setAttributeNS(null,"d",[`M ${n+i},0 L${n},4 L${n+i},8`,`M ${t},-1 L${t},9`].join(" ")),this.guideBodyElem_.setAttributeNS(null,"d",`M 0,4 L${t},4`);const s=this.props_.get("formatter");this.tooltipElem_.textContent=s(this.value.rawValue),this.tooltipElem_.style.left=`${t}px`}refresh(){const e=this.props_.get("formatter");this.inputElement.value=e(this.value.rawValue)}onChange_(){this.refresh()}},Rs=class{constructor(e,t){var n;this.originRawValue_=0,this.onInputChange_=this.onInputChange_.bind(this),this.onInputKeyDown_=this.onInputKeyDown_.bind(this),this.onInputKeyUp_=this.onInputKeyUp_.bind(this),this.onPointerDown_=this.onPointerDown_.bind(this),this.onPointerMove_=this.onPointerMove_.bind(this),this.onPointerUp_=this.onPointerUp_.bind(this),this.parser_=t.parser,this.props=t.props,this.sliderProps_=(n=t.sliderProps)!==null&&n!==void 0?n:null,this.value=t.value,this.viewProps=t.viewProps,this.dragging_=dt(null),this.view=new D0(e,{arrayPosition:t.arrayPosition,dragging:this.dragging_,props:this.props,value:this.value,viewProps:this.viewProps}),this.view.inputElement.addEventListener("change",this.onInputChange_),this.view.inputElement.addEventListener("keydown",this.onInputKeyDown_),this.view.inputElement.addEventListener("keyup",this.onInputKeyUp_);const i=new ai(this.view.knobElement);i.emitter.on("down",this.onPointerDown_),i.emitter.on("move",this.onPointerMove_),i.emitter.on("up",this.onPointerUp_)}constrainValue_(e){var t,n;const i=(t=this.sliderProps_)===null||t===void 0?void 0:t.get("min"),s=(n=this.sliderProps_)===null||n===void 0?void 0:n.get("max");let o=e;return i!==void 0&&(o=Math.max(o,i)),s!==void 0&&(o=Math.min(o,s)),o}onInputChange_(e){const n=e.currentTarget.value,i=this.parser_(n);ut(i)||(this.value.rawValue=this.constrainValue_(i)),this.view.refresh()}onInputKeyDown_(e){const t=ar(this.props.get("keyScale"),xs(e));t!==0&&this.value.setRawValue(this.constrainValue_(this.value.rawValue+t),{forceEmit:!1,last:!1})}onInputKeyUp_(e){ar(this.props.get("keyScale"),xs(e))!==0&&this.value.setRawValue(this.value.rawValue,{forceEmit:!0,last:!0})}onPointerDown_(){this.originRawValue_=this.value.rawValue,this.dragging_.rawValue=0}computeDraggingValue_(e){if(!e.point)return null;const t=e.point.x-e.bounds.width/2;return this.constrainValue_(this.originRawValue_+t*this.props.get("pointerScale"))}onPointerMove_(e){const t=this.computeDraggingValue_(e.data);t!==null&&(this.value.setRawValue(t,{forceEmit:!1,last:!1}),this.dragging_.rawValue=this.value.rawValue-this.originRawValue_)}onPointerUp_(e){const t=this.computeDraggingValue_(e.data);t!==null&&(this.value.setRawValue(t,{forceEmit:!0,last:!0}),this.dragging_.rawValue=null)}};const ul=Xe("sld");let M0=class{constructor(e,t){this.onChange_=this.onChange_.bind(this),this.props_=t.props,this.props_.emitter.on("change",this.onChange_),this.element=e.createElement("div"),this.element.classList.add(ul()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("div");n.classList.add(ul("t")),t.viewProps.bindTabIndex(n),this.element.appendChild(n),this.trackElement=n;const i=e.createElement("div");i.classList.add(ul("k")),this.trackElement.appendChild(i),this.knobElement=i,t.value.emitter.on("change",this.onChange_),this.value=t.value,this.update_()}update_(){const e=Rt(et(this.value.rawValue,this.props_.get("min"),this.props_.get("max"),0,100),0,100);this.knobElement.style.width=`${e}%`}onChange_(){this.update_()}},I0=class{constructor(e,t){this.onKeyDown_=this.onKeyDown_.bind(this),this.onKeyUp_=this.onKeyUp_.bind(this),this.onPointerDownOrMove_=this.onPointerDownOrMove_.bind(this),this.onPointerUp_=this.onPointerUp_.bind(this),this.value=t.value,this.viewProps=t.viewProps,this.props=t.props,this.view=new M0(e,{props:this.props,value:this.value,viewProps:this.viewProps}),this.ptHandler_=new ai(this.view.trackElement),this.ptHandler_.emitter.on("down",this.onPointerDownOrMove_),this.ptHandler_.emitter.on("move",this.onPointerDownOrMove_),this.ptHandler_.emitter.on("up",this.onPointerUp_),this.view.trackElement.addEventListener("keydown",this.onKeyDown_),this.view.trackElement.addEventListener("keyup",this.onKeyUp_)}handlePointerEvent_(e,t){e.point&&this.value.setRawValue(et(Rt(e.point.x,0,e.bounds.width),0,e.bounds.width,this.props.get("min"),this.props.get("max")),t)}onPointerDownOrMove_(e){this.handlePointerEvent_(e.data,{forceEmit:!1,last:!1})}onPointerUp_(e){this.handlePointerEvent_(e.data,{forceEmit:!0,last:!0})}onKeyDown_(e){const t=ar(this.props.get("keyScale"),ln(e));t!==0&&this.value.setRawValue(this.value.rawValue+t,{forceEmit:!1,last:!1})}onKeyUp_(e){ar(this.props.get("keyScale"),ln(e))!==0&&this.value.setRawValue(this.value.rawValue,{forceEmit:!0,last:!0})}};const cl=Xe("sldtxt");let F0=class{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(cl());const n=e.createElement("div");n.classList.add(cl("s")),this.sliderView_=t.sliderView,n.appendChild(this.sliderView_.element),this.element.appendChild(n);const i=e.createElement("div");i.classList.add(cl("t")),this.textView_=t.textView,i.appendChild(this.textView_.element),this.element.appendChild(i)}},Ba=class{constructor(e,t){this.value=t.value,this.viewProps=t.viewProps,this.sliderC_=new I0(e,{props:t.sliderProps,value:t.value,viewProps:this.viewProps}),this.textC_=new Rs(e,{parser:t.parser,props:t.textProps,sliderProps:t.sliderProps,value:t.value,viewProps:t.viewProps}),this.view=new F0(e,{sliderView:this.sliderC_.view,textView:this.textC_.view})}get sliderController(){return this.sliderC_}get textController(){return this.textC_}importProps(e){return fr(e,null,t=>({max:t.required.number,min:t.required.number}),t=>{const n=this.sliderC_.props;return n.set("max",t.max),n.set("min",t.min),!0})}exportProps(){const e=this.sliderC_.props;return mr(null,{max:e.get("max"),min:e.get("min")})}};function Pp(r){return{sliderProps:new Ue({keyScale:r.keyScale,max:r.max,min:r.min}),textProps:new Ue({formatter:dt(r.formatter),keyScale:r.keyScale,pointerScale:dt(r.pointerScale)})}}const $0={containerUnitSize:"cnt-usz"};function Ap(r){return`--${$0[r]}`}function Cs(r){return ap(r)}function Sn(r){if(Pl(r))return bt(r,Cs)}function rn(r,e){if(!r)return;const t=[],n=np(r,e);n&&t.push(n);const i=ip(r);return i&&t.push(i),new Ls(t)}function B0(r){return r?r.major===Fi.major:!1}function Sp(r){if(r==="inline"||r==="popup")return r}function Ds(r,e){r.write(e)}const Aa=Xe("ckb");let N0=class{constructor(e,t){this.onValueChange_=this.onValueChange_.bind(this),this.element=e.createElement("div"),this.element.classList.add(Aa()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("label");n.classList.add(Aa("l")),this.element.appendChild(n),this.labelElement=n;const i=e.createElement("input");i.classList.add(Aa("i")),i.type="checkbox",this.labelElement.appendChild(i),this.inputElement=i,t.viewProps.bindDisabled(this.inputElement);const s=e.createElement("div");s.classList.add(Aa("w")),this.labelElement.appendChild(s);const o=Xa(e,"check");s.appendChild(o),t.value.emitter.on("change",this.onValueChange_),this.value=t.value,this.update_()}update_(){this.inputElement.checked=this.value.rawValue}onValueChange_(){this.update_()}},G0=class{constructor(e,t){this.onInputChange_=this.onInputChange_.bind(this),this.onLabelMouseDown_=this.onLabelMouseDown_.bind(this),this.value=t.value,this.viewProps=t.viewProps,this.view=new N0(e,{value:this.value,viewProps:this.viewProps}),this.view.inputElement.addEventListener("change",this.onInputChange_),this.view.labelElement.addEventListener("mousedown",this.onLabelMouseDown_)}onInputChange_(e){const t=e.currentTarget;this.value.rawValue=t.checked,e.preventDefault(),e.stopPropagation()}onLabelMouseDown_(e){e.preventDefault()}};function j0(r){const e=[],t=ru(r.options);return t&&e.push(t),new Ls(e)}const U0=Qt({id:"input-bool",type:"input",accept:(r,e)=>{if(typeof r!="boolean")return null;const t=bt(e,n=>({options:n.optional.custom(Os),readonly:n.optional.constant(!1)}));return t?{initialValue:r,params:t}:null},binding:{reader:r=>xp,constraint:r=>j0(r.params),writer:r=>Ds},controller:r=>{const e=r.document,t=r.value,n=r.constraint,i=n&&Fa(n,Vs);return i?new Vn(e,{props:new Ue({options:i.values.value("options")}),value:t,viewProps:r.viewProps}):new G0(e,{value:t,viewProps:r.viewProps})},api(r){return typeof r.controller.value.rawValue!="boolean"?null:r.controller.valueController instanceof Vn?new eu(r.controller):null}}),Xn=Xe("col");let z0=class{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(Xn()),t.foldable.bindExpandedClass(this.element,Xn(void 0,"expanded")),Nr(t.foldable,"completed",Ii(this.element,Xn(void 0,"cpl")));const n=e.createElement("div");n.classList.add(Xn("h")),this.element.appendChild(n);const i=e.createElement("div");i.classList.add(Xn("s")),n.appendChild(i),this.swatchElement=i;const s=e.createElement("div");if(s.classList.add(Xn("t")),n.appendChild(s),this.textElement=s,t.pickerLayout==="inline"){const o=e.createElement("div");o.classList.add(Xn("p")),this.element.appendChild(o),this.pickerElement=o}else this.pickerElement=null}};function H0(r,e,t){const n=Rt(r/255,0,1),i=Rt(e/255,0,1),s=Rt(t/255,0,1),o=Math.max(n,i,s),l=Math.min(n,i,s),y=o-l;let x=0,B=0;const U=(l+o)/2;return y!==0&&(B=y/(1-Math.abs(o+l-1)),n===o?x=(i-s)/y:i===o?x=2+(s-n)/y:x=4+(n-i)/y,x=x/6+(x<0?1:0)),[x*360,B*100,U*100]}function K0(r,e,t){const n=(r%360+360)%360,i=Rt(e/100,0,1),s=Rt(t/100,0,1),o=(1-Math.abs(2*s-1))*i,l=o*(1-Math.abs(n/60%2-1)),y=s-o/2;let x,B,U;return n>=0&&n<60?[x,B,U]=[o,l,0]:n>=60&&n<120?[x,B,U]=[l,o,0]:n>=120&&n<180?[x,B,U]=[0,o,l]:n>=180&&n<240?[x,B,U]=[0,l,o]:n>=240&&n<300?[x,B,U]=[l,0,o]:[x,B,U]=[o,0,l],[(x+y)*255,(B+y)*255,(U+y)*255]}function q0(r,e,t){const n=Rt(r/255,0,1),i=Rt(e/255,0,1),s=Rt(t/255,0,1),o=Math.max(n,i,s),l=Math.min(n,i,s),y=o-l;let x;y===0?x=0:o===n?x=60*(((i-s)/y%6+6)%6):o===i?x=60*((s-n)/y+2):x=60*((n-i)/y+4);const B=o===0?0:y/o,U=o;return[x,B*100,U*100]}function Tp(r,e,t){const n=ep(r,360),i=Rt(e/100,0,1),s=Rt(t/100,0,1),o=s*i,l=o*(1-Math.abs(n/60%2-1)),y=s-o;let x,B,U;return n>=0&&n<60?[x,B,U]=[o,l,0]:n>=60&&n<120?[x,B,U]=[l,o,0]:n>=120&&n<180?[x,B,U]=[0,o,l]:n>=180&&n<240?[x,B,U]=[0,l,o]:n>=240&&n<300?[x,B,U]=[l,0,o]:[x,B,U]=[o,0,l],[(x+y)*255,(B+y)*255,(U+y)*255]}function X0(r,e,t){const n=t+e*(100-Math.abs(2*t-100))/200;return[r,n!==0?e*(100-Math.abs(2*t-100))/n:0,t+e*(100-Math.abs(2*t-100))/200]}function Y0(r,e,t){const n=100-Math.abs(t*(200-e)/100-100);return[r,n!==0?e*t/n:0,t*(200-e)/200]}function Gr(r){return[r[0],r[1],r[2]]}function Wa(r,e){return[r[0],r[1],r[2],e]}const W0={hsl:{hsl:(r,e,t)=>[r,e,t],hsv:X0,rgb:K0},hsv:{hsl:Y0,hsv:(r,e,t)=>[r,e,t],rgb:Tp},rgb:{hsl:H0,hsv:q0,rgb:(r,e,t)=>[r,e,t]}};function Ri(r,e){return[e==="float"?1:r==="rgb"?255:360,e==="float"?1:r==="rgb"?255:100,e==="float"?1:r==="rgb"?255:100]}function Z0(r,e){return r===e?e:ep(r,e)}function kp(r,e,t){var n;const i=Ri(e,t);return[e==="rgb"?Rt(r[0],0,i[0]):Z0(r[0],i[0]),Rt(r[1],0,i[1]),Rt(r[2],0,i[2]),Rt((n=r[3])!==null&&n!==void 0?n:1,0,1)]}function rh(r,e,t,n){const i=Ri(e,t),s=Ri(e,n);return r.map((o,l)=>o/i[l]*s[l])}function Lp(r,e,t){const n=rh(r,e.mode,e.type,"int"),i=W0[e.mode][t.mode](...n);return rh(i,t.mode,"int",t.type)}let rt=class Vp{static black(){return new Vp([0,0,0],"rgb")}constructor(e,t){this.type="int",this.mode=t,this.comps_=kp(e,t,this.type)}getComponents(e){return Wa(Lp(Gr(this.comps_),{mode:this.mode,type:this.type},{mode:e??this.mode,type:this.type}),this.comps_[3])}toRgbaObject(){const e=this.getComponents("rgb");return{r:e[0],g:e[1],b:e[2],a:e[3]}}};const gn=Xe("colp");let Q0=class{constructor(e,t){this.alphaViews_=null,this.element=e.createElement("div"),this.element.classList.add(gn()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("div");n.classList.add(gn("hsv"));const i=e.createElement("div");i.classList.add(gn("sv")),this.svPaletteView_=t.svPaletteView,i.appendChild(this.svPaletteView_.element),n.appendChild(i);const s=e.createElement("div");s.classList.add(gn("h")),this.hPaletteView_=t.hPaletteView,s.appendChild(this.hPaletteView_.element),n.appendChild(s),this.element.appendChild(n);const o=e.createElement("div");if(o.classList.add(gn("rgb")),this.textsView_=t.textsView,o.appendChild(this.textsView_.element),this.element.appendChild(o),t.alphaViews){this.alphaViews_={palette:t.alphaViews.palette,text:t.alphaViews.text};const l=e.createElement("div");l.classList.add(gn("a"));const y=e.createElement("div");y.classList.add(gn("ap")),y.appendChild(this.alphaViews_.palette.element),l.appendChild(y);const x=e.createElement("div");x.classList.add(gn("at")),x.appendChild(this.alphaViews_.text.element),l.appendChild(x),this.element.appendChild(l)}}get allFocusableElements(){const e=[this.svPaletteView_.element,this.hPaletteView_.element,this.textsView_.modeSelectElement,...this.textsView_.inputViews.map(t=>t.inputElement)];return this.alphaViews_&&e.push(this.alphaViews_.palette.element,this.alphaViews_.text.inputElement),e}};function J0(r){return r==="int"?"int":r==="float"?"float":void 0}function nu(r){return bt(r,e=>({color:e.optional.object({alpha:e.optional.boolean,type:e.optional.custom(J0)}),expanded:e.optional.boolean,picker:e.optional.custom(Sp),readonly:e.optional.constant(!1)}))}function ti(r){return r?.1:1}function Op(r){var e;return(e=r.color)===null||e===void 0?void 0:e.type}let iu=class{constructor(e,t){this.type="float",this.mode=t,this.comps_=kp(e,t,this.type)}getComponents(e){return Wa(Lp(Gr(this.comps_),{mode:this.mode,type:this.type},{mode:e??this.mode,type:this.type}),this.comps_[3])}toRgbaObject(){const e=this.getComponents("rgb");return{r:e[0],g:e[1],b:e[2],a:e[3]}}};const eg={int:(r,e)=>new rt(r,e),float:(r,e)=>new iu(r,e)};function su(r,e,t){return eg[t](r,e)}function tg(r){return r.type==="float"}function rg(r){return r.type==="int"}function ng(r){const e=r.getComponents(),t=Ri(r.mode,"int");return new rt([Math.round(et(e[0],0,1,0,t[0])),Math.round(et(e[1],0,1,0,t[1])),Math.round(et(e[2],0,1,0,t[2])),e[3]],r.mode)}function ig(r){const e=r.getComponents(),t=Ri(r.mode,"int");return new iu([et(e[0],0,t[0],0,1),et(e[1],0,t[1],0,1),et(e[2],0,t[2],0,1),e[3]],r.mode)}function Wt(r,e){if(r.type===e)return r;if(rg(r)&&e==="float")return ig(r);if(tg(r)&&e==="int")return ng(r);throw qt.shouldNeverHappen()}function sg(r,e){return r.alpha===e.alpha&&r.mode===e.mode&&r.notation===e.notation&&r.type===e.type}function Er(r,e){const t=r.match(/^(.+)%$/);return Math.min(t?parseFloat(t[1])*.01*e:parseFloat(r),e)}const ag={deg:r=>r,grad:r=>r*360/400,rad:r=>r*360/(2*Math.PI),turn:r=>r*360};function Rp(r){const e=r.match(/^([0-9.]+?)(deg|grad|rad|turn)$/);if(!e)return parseFloat(r);const t=parseFloat(e[1]),n=e[2];return ag[n](t)}function Dp(r){const e=r.match(/^rgb\(\s*([0-9A-Fa-f.]+%?)\s*,\s*([0-9A-Fa-f.]+%?)\s*,\s*([0-9A-Fa-f.]+%?)\s*\)$/);if(!e)return null;const t=[Er(e[1],255),Er(e[2],255),Er(e[3],255)];return isNaN(t[0])||isNaN(t[1])||isNaN(t[2])?null:t}function og(r){const e=Dp(r);return e?new rt(e,"rgb"):null}function Mp(r){const e=r.match(/^rgba\(\s*([0-9A-Fa-f.]+%?)\s*,\s*([0-9A-Fa-f.]+%?)\s*,\s*([0-9A-Fa-f.]+%?)\s*,\s*([0-9A-Fa-f.]+%?)\s*\)$/);if(!e)return null;const t=[Er(e[1],255),Er(e[2],255),Er(e[3],255),Er(e[4],1)];return isNaN(t[0])||isNaN(t[1])||isNaN(t[2])||isNaN(t[3])?null:t}function lg(r){const e=Mp(r);return e?new rt(e,"rgb"):null}function Ip(r){const e=r.match(/^hsl\(\s*([0-9A-Fa-f.]+(?:deg|grad|rad|turn)?)\s*,\s*([0-9A-Fa-f.]+%?)\s*,\s*([0-9A-Fa-f.]+%?)\s*\)$/);if(!e)return null;const t=[Rp(e[1]),Er(e[2],100),Er(e[3],100)];return isNaN(t[0])||isNaN(t[1])||isNaN(t[2])?null:t}function ug(r){const e=Ip(r);return e?new rt(e,"hsl"):null}function Fp(r){const e=r.match(/^hsla\(\s*([0-9A-Fa-f.]+(?:deg|grad|rad|turn)?)\s*,\s*([0-9A-Fa-f.]+%?)\s*,\s*([0-9A-Fa-f.]+%?)\s*,\s*([0-9A-Fa-f.]+%?)\s*\)$/);if(!e)return null;const t=[Rp(e[1]),Er(e[2],100),Er(e[3],100),Er(e[4],1)];return isNaN(t[0])||isNaN(t[1])||isNaN(t[2])||isNaN(t[3])?null:t}function cg(r){const e=Fp(r);return e?new rt(e,"hsl"):null}function $p(r){const e=r.match(/^#([0-9A-Fa-f])([0-9A-Fa-f])([0-9A-Fa-f])$/);if(e)return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16)];const t=r.match(/^(?:#|0x)([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})$/);return t?[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)]:null}function dg(r){const e=$p(r);return e?new rt(e,"rgb"):null}function Bp(r){const e=r.match(/^#([0-9A-Fa-f])([0-9A-Fa-f])([0-9A-Fa-f])([0-9A-Fa-f])$/);if(e)return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16),et(parseInt(e[4]+e[4],16),0,255,0,1)];const t=r.match(/^(?:#|0x)?([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})$/);return t?[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16),et(parseInt(t[4],16),0,255,0,1)]:null}function hg(r){const e=Bp(r);return e?new rt(e,"rgb"):null}function Np(r){const e=r.match(/^\{\s*r\s*:\s*([0-9A-Fa-f.]+%?)\s*,\s*g\s*:\s*([0-9A-Fa-f.]+%?)\s*,\s*b\s*:\s*([0-9A-Fa-f.]+%?)\s*\}$/);if(!e)return null;const t=[parseFloat(e[1]),parseFloat(e[2]),parseFloat(e[3])];return isNaN(t[0])||isNaN(t[1])||isNaN(t[2])?null:t}function pg(r){return e=>{const t=Np(e);return t?su(t,"rgb",r):null}}function Gp(r){const e=r.match(/^\{\s*r\s*:\s*([0-9A-Fa-f.]+%?)\s*,\s*g\s*:\s*([0-9A-Fa-f.]+%?)\s*,\s*b\s*:\s*([0-9A-Fa-f.]+%?)\s*,\s*a\s*:\s*([0-9A-Fa-f.]+%?)\s*\}$/);if(!e)return null;const t=[parseFloat(e[1]),parseFloat(e[2]),parseFloat(e[3]),parseFloat(e[4])];return isNaN(t[0])||isNaN(t[1])||isNaN(t[2])||isNaN(t[3])?null:t}function fg(r){return e=>{const t=Gp(e);return t?su(t,"rgb",r):null}}const mg=[{parser:$p,result:{alpha:!1,mode:"rgb",notation:"hex"}},{parser:Bp,result:{alpha:!0,mode:"rgb",notation:"hex"}},{parser:Dp,result:{alpha:!1,mode:"rgb",notation:"func"}},{parser:Mp,result:{alpha:!0,mode:"rgb",notation:"func"}},{parser:Ip,result:{alpha:!1,mode:"hsl",notation:"func"}},{parser:Fp,result:{alpha:!0,mode:"hsl",notation:"func"}},{parser:Np,result:{alpha:!1,mode:"rgb",notation:"object"}},{parser:Gp,result:{alpha:!0,mode:"rgb",notation:"object"}}];function vg(r){return mg.reduce((e,{parser:t,result:n})=>e||(t(r)?n:null),null)}function bg(r,e="int"){const t=vg(r);return t?t.notation==="hex"&&e!=="float"?Object.assign(Object.assign({},t),{type:"int"}):t.notation==="func"?Object.assign(Object.assign({},t),{type:e}):null:null}function Ms(r){const e=[dg,hg,og,lg,ug,cg];e.push(pg("int"),fg("int"));const t=V0(e);return n=>{const i=t(n);return i?Wt(i,r):null}}function _g(r){const e=Ms("int");if(typeof r!="string")return rt.black();const t=e(r);return t??rt.black()}function jp(r){const e=Rt(Math.floor(r),0,255).toString(16);return e.length===1?`0${e}`:e}function au(r,e="#"){const t=Gr(r.getComponents("rgb")).map(jp).join("");return`${e}${t}`}function ou(r,e="#"){const t=r.getComponents("rgb"),n=[t[0],t[1],t[2],t[3]*255].map(jp).join("");return`${e}${n}`}function Up(r){const e=lr(0),t=Wt(r,"int");return`rgb(${Gr(t.getComponents("rgb")).map(i=>e(i)).join(", ")})`}function La(r){const e=lr(2),t=lr(0);return`rgba(${Wt(r,"int").getComponents("rgb").map((s,o)=>(o===3?e:t)(s)).join(", ")})`}function wg(r){const e=[lr(0),$a,$a],t=Wt(r,"int");return`hsl(${Gr(t.getComponents("hsl")).map((i,s)=>e[s](i)).join(", ")})`}function gg(r){const e=[lr(0),$a,$a,lr(2)];return`hsla(${Wt(r,"int").getComponents("hsl").map((i,s)=>e[s](i)).join(", ")})`}function zp(r,e){const t=lr(e==="float"?2:0),n=["r","g","b"],i=Wt(r,e);return`{${Gr(i.getComponents("rgb")).map((o,l)=>`${n[l]}: ${t(o)}`).join(", ")}}`}function yg(r){return e=>zp(e,r)}function Hp(r,e){const t=lr(2),n=lr(e==="float"?2:0),i=["r","g","b","a"];return`{${Wt(r,e).getComponents("rgb").map((l,y)=>{const x=y===3?t:n;return`${i[y]}: ${x(l)}`}).join(", ")}}`}function xg(r){return e=>Hp(e,r)}const Cg=[{format:{alpha:!1,mode:"rgb",notation:"hex",type:"int"},stringifier:au},{format:{alpha:!0,mode:"rgb",notation:"hex",type:"int"},stringifier:ou},{format:{alpha:!1,mode:"rgb",notation:"func",type:"int"},stringifier:Up},{format:{alpha:!0,mode:"rgb",notation:"func",type:"int"},stringifier:La},{format:{alpha:!1,mode:"hsl",notation:"func",type:"int"},stringifier:wg},{format:{alpha:!0,mode:"hsl",notation:"func",type:"int"},stringifier:gg},...["int","float"].reduce((r,e)=>[...r,{format:{alpha:!1,mode:"rgb",notation:"object",type:e},stringifier:yg(e)},{format:{alpha:!0,mode:"rgb",notation:"object",type:e},stringifier:xg(e)}],[])];function Kp(r){return Cg.reduce((e,t)=>e||(sg(t.format,r)?t.stringifier:null),null)}const us=Xe("apl");let Eg=class{constructor(e,t){this.onValueChange_=this.onValueChange_.bind(this),this.value=t.value,this.value.emitter.on("change",this.onValueChange_),this.element=e.createElement("div"),this.element.classList.add(us()),t.viewProps.bindClassModifiers(this.element),t.viewProps.bindTabIndex(this.element);const n=e.createElement("div");n.classList.add(us("b")),this.element.appendChild(n);const i=e.createElement("div");i.classList.add(us("c")),n.appendChild(i),this.colorElem_=i;const s=e.createElement("div");s.classList.add(us("m")),this.element.appendChild(s),this.markerElem_=s;const o=e.createElement("div");o.classList.add(us("p")),this.markerElem_.appendChild(o),this.previewElem_=o,this.update_()}update_(){const e=this.value.rawValue,t=e.getComponents("rgb"),n=new rt([t[0],t[1],t[2],0],"rgb"),i=new rt([t[0],t[1],t[2],255],"rgb"),s=["to right",La(n),La(i)];this.colorElem_.style.background=`linear-gradient(${s.join(",")})`,this.previewElem_.style.backgroundColor=La(e);const o=et(t[3],0,1,0,100);this.markerElem_.style.left=`${o}%`}onValueChange_(){this.update_()}},Pg=class{constructor(e,t){this.onKeyDown_=this.onKeyDown_.bind(this),this.onKeyUp_=this.onKeyUp_.bind(this),this.onPointerDown_=this.onPointerDown_.bind(this),this.onPointerMove_=this.onPointerMove_.bind(this),this.onPointerUp_=this.onPointerUp_.bind(this),this.value=t.value,this.viewProps=t.viewProps,this.view=new Eg(e,{value:this.value,viewProps:this.viewProps}),this.ptHandler_=new ai(this.view.element),this.ptHandler_.emitter.on("down",this.onPointerDown_),this.ptHandler_.emitter.on("move",this.onPointerMove_),this.ptHandler_.emitter.on("up",this.onPointerUp_),this.view.element.addEventListener("keydown",this.onKeyDown_),this.view.element.addEventListener("keyup",this.onKeyUp_)}handlePointerEvent_(e,t){if(!e.point)return;const n=e.point.x/e.bounds.width,i=this.value.rawValue,[s,o,l]=i.getComponents("hsv");this.value.setRawValue(new rt([s,o,l,n],"hsv"),t)}onPointerDown_(e){this.handlePointerEvent_(e.data,{forceEmit:!1,last:!1})}onPointerMove_(e){this.handlePointerEvent_(e.data,{forceEmit:!1,last:!1})}onPointerUp_(e){this.handlePointerEvent_(e.data,{forceEmit:!0,last:!0})}onKeyDown_(e){const t=ar(ti(!0),ln(e));if(t===0)return;const n=this.value.rawValue,[i,s,o,l]=n.getComponents("hsv");this.value.setRawValue(new rt([i,s,o,l+t],"hsv"),{forceEmit:!1,last:!1})}onKeyUp_(e){ar(ti(!0),ln(e))!==0&&this.value.setRawValue(this.value.rawValue,{forceEmit:!0,last:!0})}};const Ei=Xe("coltxt");function Ag(r){const e=r.createElement("select"),t=[{text:"RGB",value:"rgb"},{text:"HSL",value:"hsl"},{text:"HSV",value:"hsv"},{text:"HEX",value:"hex"}];return e.appendChild(t.reduce((n,i)=>{const s=r.createElement("option");return s.textContent=i.text,s.value=i.value,n.appendChild(s),n},r.createDocumentFragment())),e}let Sg=class{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(Ei()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("div");n.classList.add(Ei("m")),this.modeElem_=Ag(e),this.modeElem_.classList.add(Ei("ms")),n.appendChild(this.modeSelectElement),t.viewProps.bindDisabled(this.modeElem_);const i=e.createElement("div");i.classList.add(Ei("mm")),i.appendChild(Xa(e,"dropdown")),n.appendChild(i),this.element.appendChild(n);const s=e.createElement("div");s.classList.add(Ei("w")),this.element.appendChild(s),this.inputsElem_=s,this.inputViews_=t.inputViews,this.applyInputViews_(),sn(t.mode,o=>{this.modeElem_.value=o})}get modeSelectElement(){return this.modeElem_}get inputViews(){return this.inputViews_}set inputViews(e){this.inputViews_=e,this.applyInputViews_()}applyInputViews_(){up(this.inputsElem_);const e=this.element.ownerDocument;this.inputViews_.forEach(t=>{const n=e.createElement("div");n.classList.add(Ei("c")),n.appendChild(t.element),this.inputsElem_.appendChild(n)})}};function Tg(r){return lr(r==="float"?2:0)}function kg(r,e,t){const n=Ri(r,e)[t];return new Ts({min:0,max:n})}function Lg(r,e,t){return new Rs(r,{arrayPosition:t===0?"fst":t===2?"lst":"mid",parser:e.parser,props:Ue.fromObject({formatter:Tg(e.colorType),keyScale:ti(!1),pointerScale:e.colorType==="float"?.01:1}),value:dt(0,{constraint:kg(e.colorMode,e.colorType,t)}),viewProps:e.viewProps})}function Vg(r,e){const t={colorMode:e.colorMode,colorType:e.colorType,parser:on,viewProps:e.viewProps};return[0,1,2].map(n=>{const i=Lg(r,t,n);return Bi({primary:e.value,secondary:i.value,forward(s){return Wt(s,e.colorType).getComponents(e.colorMode)[n]},backward(s,o){const l=e.colorMode,x=Wt(s,e.colorType).getComponents(l);x[n]=o;const B=su(Wa(Gr(x),x[3]),l,e.colorType);return Wt(B,"int")}}),i})}function Og(r,e){const t=new ys(r,{parser:Ms("int"),props:Ue.fromObject({formatter:au}),value:dt(rt.black()),viewProps:e.viewProps});return Bi({primary:e.value,secondary:t.value,forward:n=>new rt(Gr(n.getComponents()),n.mode),backward:(n,i)=>new rt(Wa(Gr(i.getComponents(n.mode)),n.getComponents()[3]),n.mode)}),[t]}function Rg(r){return r!=="hex"}let Dg=class{constructor(e,t){this.onModeSelectChange_=this.onModeSelectChange_.bind(this),this.colorType_=t.colorType,this.value=t.value,this.viewProps=t.viewProps,this.colorMode=dt(this.value.rawValue.mode),this.ccs_=this.createComponentControllers_(e),this.view=new Sg(e,{mode:this.colorMode,inputViews:[this.ccs_[0].view,this.ccs_[1].view,this.ccs_[2].view],viewProps:this.viewProps}),this.view.modeSelectElement.addEventListener("change",this.onModeSelectChange_)}createComponentControllers_(e){const t=this.colorMode.rawValue;return Rg(t)?Vg(e,{colorMode:t,colorType:this.colorType_,value:this.value,viewProps:this.viewProps}):Og(e,{value:this.value,viewProps:this.viewProps})}onModeSelectChange_(e){const t=e.currentTarget;this.colorMode.rawValue=t.value,this.ccs_=this.createComponentControllers_(this.view.element.ownerDocument),this.view.inputViews=this.ccs_.map(n=>n.view)}};const dl=Xe("hpl");let Mg=class{constructor(e,t){this.onValueChange_=this.onValueChange_.bind(this),this.value=t.value,this.value.emitter.on("change",this.onValueChange_),this.element=e.createElement("div"),this.element.classList.add(dl()),t.viewProps.bindClassModifiers(this.element),t.viewProps.bindTabIndex(this.element);const n=e.createElement("div");n.classList.add(dl("c")),this.element.appendChild(n);const i=e.createElement("div");i.classList.add(dl("m")),this.element.appendChild(i),this.markerElem_=i,this.update_()}update_(){const e=this.value.rawValue,[t]=e.getComponents("hsv");this.markerElem_.style.backgroundColor=Up(new rt([t,100,100],"hsv"));const n=et(t,0,360,0,100);this.markerElem_.style.left=`${n}%`}onValueChange_(){this.update_()}},Ig=class{constructor(e,t){this.onKeyDown_=this.onKeyDown_.bind(this),this.onKeyUp_=this.onKeyUp_.bind(this),this.onPointerDown_=this.onPointerDown_.bind(this),this.onPointerMove_=this.onPointerMove_.bind(this),this.onPointerUp_=this.onPointerUp_.bind(this),this.value=t.value,this.viewProps=t.viewProps,this.view=new Mg(e,{value:this.value,viewProps:this.viewProps}),this.ptHandler_=new ai(this.view.element),this.ptHandler_.emitter.on("down",this.onPointerDown_),this.ptHandler_.emitter.on("move",this.onPointerMove_),this.ptHandler_.emitter.on("up",this.onPointerUp_),this.view.element.addEventListener("keydown",this.onKeyDown_),this.view.element.addEventListener("keyup",this.onKeyUp_)}handlePointerEvent_(e,t){if(!e.point)return;const n=et(Rt(e.point.x,0,e.bounds.width),0,e.bounds.width,0,360),i=this.value.rawValue,[,s,o,l]=i.getComponents("hsv");this.value.setRawValue(new rt([n,s,o,l],"hsv"),t)}onPointerDown_(e){this.handlePointerEvent_(e.data,{forceEmit:!1,last:!1})}onPointerMove_(e){this.handlePointerEvent_(e.data,{forceEmit:!1,last:!1})}onPointerUp_(e){this.handlePointerEvent_(e.data,{forceEmit:!0,last:!0})}onKeyDown_(e){const t=ar(ti(!1),ln(e));if(t===0)return;const n=this.value.rawValue,[i,s,o,l]=n.getComponents("hsv");this.value.setRawValue(new rt([i+t,s,o,l],"hsv"),{forceEmit:!1,last:!1})}onKeyUp_(e){ar(ti(!1),ln(e))!==0&&this.value.setRawValue(this.value.rawValue,{forceEmit:!0,last:!0})}};const hl=Xe("svp"),nh=64;let Fg=class{constructor(e,t){this.onValueChange_=this.onValueChange_.bind(this),this.value=t.value,this.value.emitter.on("change",this.onValueChange_),this.element=e.createElement("div"),this.element.classList.add(hl()),t.viewProps.bindClassModifiers(this.element),t.viewProps.bindTabIndex(this.element);const n=e.createElement("canvas");n.height=nh,n.width=nh,n.classList.add(hl("c")),this.element.appendChild(n),this.canvasElement=n;const i=e.createElement("div");i.classList.add(hl("m")),this.element.appendChild(i),this.markerElem_=i,this.update_()}update_(){const e=Iw(this.canvasElement);if(!e)return;const n=this.value.rawValue.getComponents("hsv"),i=this.canvasElement.width,s=this.canvasElement.height,o=e.getImageData(0,0,i,s),l=o.data;for(let B=0;Bn.getComponents()[3],backward:(n,i)=>{const s=n.getComponents();return s[3]=i,new rt(s,n.mode)}}),this.textsC_=new Dg(e,{colorType:t.colorType,value:this.value,viewProps:this.viewProps}),this.view=new Q0(e,{alphaViews:this.alphaIcs_?{palette:this.alphaIcs_.palette.view,text:this.alphaIcs_.text.view}:null,hPaletteView:this.hPaletteC_.view,supportsAlpha:t.supportsAlpha,svPaletteView:this.svPaletteC_.view,textsView:this.textsC_.view,viewProps:this.viewProps})}get textsController(){return this.textsC_}};const pl=Xe("colsw");let Ng=class{constructor(e,t){this.onValueChange_=this.onValueChange_.bind(this),t.value.emitter.on("change",this.onValueChange_),this.value=t.value,this.element=e.createElement("div"),this.element.classList.add(pl()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("div");n.classList.add(pl("sw")),this.element.appendChild(n),this.swatchElem_=n;const i=e.createElement("button");i.classList.add(pl("b")),t.viewProps.bindDisabled(i),this.element.appendChild(i),this.buttonElement=i,this.update_()}update_(){const e=this.value.rawValue;this.swatchElem_.style.backgroundColor=ou(e)}onValueChange_(){this.update_()}},Gg=class{constructor(e,t){this.value=t.value,this.viewProps=t.viewProps,this.view=new Ng(e,{value:this.value,viewProps:this.viewProps})}},lu=class{constructor(e,t){this.onButtonBlur_=this.onButtonBlur_.bind(this),this.onButtonClick_=this.onButtonClick_.bind(this),this.onPopupChildBlur_=this.onPopupChildBlur_.bind(this),this.onPopupChildKeydown_=this.onPopupChildKeydown_.bind(this),this.value=t.value,this.viewProps=t.viewProps,this.foldable_=Ql.create(t.expanded),this.swatchC_=new Gg(e,{value:this.value,viewProps:this.viewProps});const n=this.swatchC_.view.buttonElement;n.addEventListener("blur",this.onButtonBlur_),n.addEventListener("click",this.onButtonClick_),this.textC_=new ys(e,{parser:t.parser,props:Ue.fromObject({formatter:t.formatter}),value:this.value,viewProps:this.viewProps}),this.view=new z0(e,{foldable:this.foldable_,pickerLayout:t.pickerLayout}),this.view.swatchElement.appendChild(this.swatchC_.view.element),this.view.textElement.appendChild(this.textC_.view.element),this.popC_=t.pickerLayout==="popup"?new yp(e,{viewProps:this.viewProps}):null;const i=new Bg(e,{colorType:t.colorType,supportsAlpha:t.supportsAlpha,value:this.value,viewProps:this.viewProps});i.view.allFocusableElements.forEach(s=>{s.addEventListener("blur",this.onPopupChildBlur_),s.addEventListener("keydown",this.onPopupChildKeydown_)}),this.pickerC_=i,this.popC_?(this.view.element.appendChild(this.popC_.view.element),this.popC_.view.element.appendChild(i.view.element),Bi({primary:this.foldable_.value("expanded"),secondary:this.popC_.shows,forward:s=>s,backward:(s,o)=>o})):this.view.pickerElement&&(this.view.pickerElement.appendChild(this.pickerC_.view.element),Jl(this.foldable_,this.view.pickerElement))}get textController(){return this.textC_}onButtonBlur_(e){if(!this.popC_)return;const t=this.view.element,n=e.relatedTarget;(!n||!t.contains(n))&&(this.popC_.shows.rawValue=!1)}onButtonClick_(){this.foldable_.set("expanded",!this.foldable_.get("expanded")),this.foldable_.get("expanded")&&this.pickerC_.view.allFocusableElements[0].focus()}onPopupChildBlur_(e){if(!this.popC_)return;const t=this.popC_.view.element,n=cp(e);n&&t.contains(n)||n&&n===this.swatchC_.view.buttonElement&&!Kl(t.ownerDocument)||(this.popC_.shows.rawValue=!1)}onPopupChildKeydown_(e){this.popC_?e.key==="Escape"&&(this.popC_.shows.rawValue=!1):this.view.pickerElement&&e.key==="Escape"&&this.swatchC_.view.buttonElement.focus()}};function jg(r){return Gr(r.getComponents("rgb")).reduce((e,t)=>e<<8|Math.floor(t)&255,0)}function Ug(r){return r.getComponents("rgb").reduce((e,t,n)=>{const i=Math.floor(n===3?t*255:t)&255;return e<<8|i},0)>>>0}function zg(r){return new rt([r>>16&255,r>>8&255,r&255],"rgb")}function Hg(r){return new rt([r>>24&255,r>>16&255,r>>8&255,et(r&255,0,255,0,1)],"rgb")}function Kg(r){return typeof r!="number"?rt.black():zg(r)}function qg(r){return typeof r!="number"?rt.black():Hg(r)}function Va(r,e){return typeof r!="object"||ut(r)?!1:e in r&&typeof r[e]=="number"}function qp(r){return Va(r,"r")&&Va(r,"g")&&Va(r,"b")}function Xp(r){return qp(r)&&Va(r,"a")}function Yp(r){return qp(r)}function uu(r,e){if(r.mode!==e.mode||r.type!==e.type)return!1;const t=r.getComponents(),n=e.getComponents();for(let i=0;i{Ds(t,e(n))}:null}function Yg(r){const e=r?Ug:jg;return(t,n)=>{Ds(t,e(n))}}function Wg(r,e,t){const i=Wt(e,t).toRgbaObject();r.writeProperty("r",i.r),r.writeProperty("g",i.g),r.writeProperty("b",i.b),r.writeProperty("a",i.a)}function Zg(r,e,t){const i=Wt(e,t).toRgbaObject();r.writeProperty("r",i.r),r.writeProperty("g",i.g),r.writeProperty("b",i.b)}function Qg(r,e){return(t,n)=>{r?Wg(t,n,e):Zg(t,n,e)}}function Jg(r){var e;return!!(!((e=r?.color)===null||e===void 0)&&e.alpha)}function ey(r){return r?e=>ou(e,"0x"):e=>au(e,"0x")}function ty(r){return"color"in r||r.view==="color"}const ry=Qt({id:"input-color-number",type:"input",accept:(r,e)=>{if(typeof r!="number"||!ty(e))return null;const t=nu(e);return t?{initialValue:r,params:Object.assign(Object.assign({},t),{supportsAlpha:Jg(e)})}:null},binding:{reader:r=>r.params.supportsAlpha?qg:Kg,equals:uu,writer:r=>Yg(r.params.supportsAlpha)},controller:r=>{var e,t;return new lu(r.document,{colorType:"int",expanded:(e=r.params.expanded)!==null&&e!==void 0?e:!1,formatter:ey(r.params.supportsAlpha),parser:Ms("int"),pickerLayout:(t=r.params.picker)!==null&&t!==void 0?t:"popup",supportsAlpha:r.params.supportsAlpha,value:r.value,viewProps:r.viewProps})}});function ny(r,e){if(!Yp(r))return Wt(rt.black(),e);if(e==="int"){const t=ih(r);return new rt(t,"rgb")}if(e==="float"){const t=ih(r);return new iu(t,"rgb")}return Wt(rt.black(),"int")}function iy(r){return Xp(r)}function sy(r){return e=>{const t=ny(e,r);return Wt(t,"int")}}function ay(r,e){return t=>r?Hp(t,e):zp(t,e)}const oy=Qt({id:"input-color-object",type:"input",accept:(r,e)=>{var t;if(!Yp(r))return null;const n=nu(e);return n?{initialValue:r,params:Object.assign(Object.assign({},n),{colorType:(t=Op(e))!==null&&t!==void 0?t:"int"})}:null},binding:{reader:r=>sy(r.params.colorType),equals:uu,writer:r=>Qg(iy(r.initialValue),r.params.colorType)},controller:r=>{var e,t;const n=Xp(r.initialValue);return new lu(r.document,{colorType:r.params.colorType,expanded:(e=r.params.expanded)!==null&&e!==void 0?e:!1,formatter:ay(n,r.params.colorType),parser:Ms("int"),pickerLayout:(t=r.params.picker)!==null&&t!==void 0?t:"popup",supportsAlpha:n,value:r.value,viewProps:r.viewProps})}}),ly=Qt({id:"input-color-string",type:"input",accept:(r,e)=>{if(typeof r!="string"||e.view==="text")return null;const t=bg(r,Op(e));if(!t)return null;const n=Kp(t);if(!n)return null;const i=nu(e);return i?{initialValue:r,params:Object.assign(Object.assign({},i),{format:t,stringifier:n})}:null},binding:{reader:()=>_g,equals:uu,writer:r=>{const e=Xg(r.params.format);if(!e)throw qt.notBindable();return e}},controller:r=>{var e,t;return new lu(r.document,{colorType:r.params.format.type,expanded:(e=r.params.expanded)!==null&&e!==void 0?e:!1,formatter:r.params.stringifier,parser:Ms("int"),pickerLayout:(t=r.params.picker)!==null&&t!==void 0?t:"popup",supportsAlpha:r.params.format.alpha,value:r.value,viewProps:r.viewProps})}});let cu=class{constructor(e){this.components=e.components,this.asm_=e.assembly}constrain(e){const t=this.asm_.toComponents(e).map((n,i)=>{var s,o;return(o=(s=this.components[i])===null||s===void 0?void 0:s.constrain(n))!==null&&o!==void 0?o:n});return this.asm_.fromComponents(t)}};const sh=Xe("pndtxt");let uy=class{constructor(e,t){this.textViews=t.textViews,this.element=e.createElement("div"),this.element.classList.add(sh()),this.textViews.forEach(n=>{const i=e.createElement("div");i.classList.add(sh("a")),i.appendChild(n.element),this.element.appendChild(i)})}};function cy(r,e,t){return new Rs(r,{arrayPosition:t===0?"fst":t===e.axes.length-1?"lst":"mid",parser:e.parser,props:e.axes[t].textProps,value:dt(0,{constraint:e.axes[t].constraint}),viewProps:e.viewProps})}let du=class{constructor(e,t){this.value=t.value,this.viewProps=t.viewProps,this.acs_=t.axes.map((n,i)=>cy(e,t,i)),this.acs_.forEach((n,i)=>{Bi({primary:this.value,secondary:n.value,forward:s=>t.assembly.toComponents(s)[i],backward:(s,o)=>{const l=t.assembly.toComponents(s);return l[i]=o,t.assembly.fromComponents(l)}})}),this.view=new uy(e,{textViews:this.acs_.map(n=>n.view)})}get textControllers(){return this.acs_}},dy=class extends gs{get max(){return this.controller.valueController.sliderController.props.get("max")}set max(e){this.controller.valueController.sliderController.props.set("max",e)}get min(){return this.controller.valueController.sliderController.props.get("min")}set min(e){this.controller.valueController.sliderController.props.set("min",e)}};function hy(r,e){const t=[],n=np(r,e);n&&t.push(n);const i=ip(r);i&&t.push(i);const s=ru(r.options);return s&&t.push(s),new Ls(t)}const py=Qt({id:"input-number",type:"input",accept:(r,e)=>{if(typeof r!="number")return null;const t=bt(e,n=>Object.assign(Object.assign({},ap(n)),{options:n.optional.custom(Os),readonly:n.optional.constant(!1)}));return t?{initialValue:r,params:t}:null},binding:{reader:r=>Jh,constraint:r=>hy(r.params,r.initialValue),writer:r=>Ds},controller:r=>{const e=r.value,t=r.constraint,n=t&&Fa(t,Vs);if(n)return new Vn(r.document,{props:new Ue({options:n.values.value("options")}),value:e,viewProps:r.viewProps});const i=sp(r.params,e.rawValue),s=t&&Fa(t,Ts);return s?new Ba(r.document,Object.assign(Object.assign({},Pp(Object.assign(Object.assign({},i),{keyScale:dt(i.keyScale),max:s.values.value("max"),min:s.values.value("min")}))),{parser:on,value:e,viewProps:r.viewProps})):new Rs(r.document,{parser:on,props:Ue.fromObject(i),value:e,viewProps:r.viewProps})},api(r){return typeof r.controller.value.rawValue!="number"?null:r.controller.valueController instanceof Ba?new dy(r.controller):r.controller.valueController instanceof Vn?new eu(r.controller):null}});let kn=class{constructor(e=0,t=0){this.x=e,this.y=t}getComponents(){return[this.x,this.y]}static isObject(e){if(ut(e))return!1;const t=e.x,n=e.y;return!(typeof t!="number"||typeof n!="number")}static equals(e,t){return e.x===t.x&&e.y===t.y}toObject(){return{x:this.x,y:this.y}}};const Wp={toComponents:r=>r.getComponents(),fromComponents:r=>new kn(...r)},Pi=Xe("p2d");let fy=class{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(Pi()),t.viewProps.bindClassModifiers(this.element),sn(t.expanded,Ii(this.element,Pi(void 0,"expanded")));const n=e.createElement("div");n.classList.add(Pi("h")),this.element.appendChild(n);const i=e.createElement("button");i.classList.add(Pi("b")),i.appendChild(Xa(e,"p2dpad")),t.viewProps.bindDisabled(i),n.appendChild(i),this.buttonElement=i;const s=e.createElement("div");if(s.classList.add(Pi("t")),n.appendChild(s),this.textElement=s,t.pickerLayout==="inline"){const o=e.createElement("div");o.classList.add(Pi("p")),this.element.appendChild(o),this.pickerElement=o}else this.pickerElement=null}};const yn=Xe("p2dp");let my=class{constructor(e,t){this.onFoldableChange_=this.onFoldableChange_.bind(this),this.onPropsChange_=this.onPropsChange_.bind(this),this.onValueChange_=this.onValueChange_.bind(this),this.props_=t.props,this.props_.emitter.on("change",this.onPropsChange_),this.element=e.createElement("div"),this.element.classList.add(yn()),t.layout==="popup"&&this.element.classList.add(yn(void 0,"p")),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("div");n.classList.add(yn("p")),t.viewProps.bindTabIndex(n),this.element.appendChild(n),this.padElement=n;const i=e.createElementNS($r,"svg");i.classList.add(yn("g")),this.padElement.appendChild(i),this.svgElem_=i;const s=e.createElementNS($r,"line");s.classList.add(yn("ax")),s.setAttributeNS(null,"x1","0"),s.setAttributeNS(null,"y1","50%"),s.setAttributeNS(null,"x2","100%"),s.setAttributeNS(null,"y2","50%"),this.svgElem_.appendChild(s);const o=e.createElementNS($r,"line");o.classList.add(yn("ax")),o.setAttributeNS(null,"x1","50%"),o.setAttributeNS(null,"y1","0"),o.setAttributeNS(null,"x2","50%"),o.setAttributeNS(null,"y2","100%"),this.svgElem_.appendChild(o);const l=e.createElementNS($r,"line");l.classList.add(yn("l")),l.setAttributeNS(null,"x1","50%"),l.setAttributeNS(null,"y1","50%"),this.svgElem_.appendChild(l),this.lineElem_=l;const y=e.createElement("div");y.classList.add(yn("m")),this.padElement.appendChild(y),this.markerElem_=y,t.value.emitter.on("change",this.onValueChange_),this.value=t.value,this.update_()}get allFocusableElements(){return[this.padElement]}update_(){const[e,t]=this.value.rawValue.getComponents(),n=this.props_.get("max"),i=et(e,-n,+n,0,100),s=et(t,-n,+n,0,100),o=this.props_.get("invertsY")?100-s:s;this.lineElem_.setAttributeNS(null,"x2",`${i}%`),this.lineElem_.setAttributeNS(null,"y2",`${o}%`),this.markerElem_.style.left=`${i}%`,this.markerElem_.style.top=`${o}%`}onValueChange_(){this.update_()}onPropsChange_(){this.update_()}onFoldableChange_(){this.update_()}};function ah(r,e,t){return[ar(e[0],ln(r)),ar(e[1],xs(r))*(t?1:-1)]}let vy=class{constructor(e,t){this.onPadKeyDown_=this.onPadKeyDown_.bind(this),this.onPadKeyUp_=this.onPadKeyUp_.bind(this),this.onPointerDown_=this.onPointerDown_.bind(this),this.onPointerMove_=this.onPointerMove_.bind(this),this.onPointerUp_=this.onPointerUp_.bind(this),this.props=t.props,this.value=t.value,this.viewProps=t.viewProps,this.view=new my(e,{layout:t.layout,props:this.props,value:this.value,viewProps:this.viewProps}),this.ptHandler_=new ai(this.view.padElement),this.ptHandler_.emitter.on("down",this.onPointerDown_),this.ptHandler_.emitter.on("move",this.onPointerMove_),this.ptHandler_.emitter.on("up",this.onPointerUp_),this.view.padElement.addEventListener("keydown",this.onPadKeyDown_),this.view.padElement.addEventListener("keyup",this.onPadKeyUp_)}handlePointerEvent_(e,t){if(!e.point)return;const n=this.props.get("max"),i=et(e.point.x,0,e.bounds.width,-n,+n),s=et(this.props.get("invertsY")?e.bounds.height-e.point.y:e.point.y,0,e.bounds.height,-n,+n);this.value.setRawValue(new kn(i,s),t)}onPointerDown_(e){this.handlePointerEvent_(e.data,{forceEmit:!1,last:!1})}onPointerMove_(e){this.handlePointerEvent_(e.data,{forceEmit:!1,last:!1})}onPointerUp_(e){this.handlePointerEvent_(e.data,{forceEmit:!0,last:!0})}onPadKeyDown_(e){Ep(e.key)&&e.preventDefault();const[t,n]=ah(e,[this.props.get("xKeyScale"),this.props.get("yKeyScale")],this.props.get("invertsY"));t===0&&n===0||this.value.setRawValue(new kn(this.value.rawValue.x+t,this.value.rawValue.y+n),{forceEmit:!1,last:!1})}onPadKeyUp_(e){const[t,n]=ah(e,[this.props.get("xKeyScale"),this.props.get("yKeyScale")],this.props.get("invertsY"));t===0&&n===0||this.value.setRawValue(this.value.rawValue,{forceEmit:!0,last:!0})}},by=class{constructor(e,t){var n,i;this.onPopupChildBlur_=this.onPopupChildBlur_.bind(this),this.onPopupChildKeydown_=this.onPopupChildKeydown_.bind(this),this.onPadButtonBlur_=this.onPadButtonBlur_.bind(this),this.onPadButtonClick_=this.onPadButtonClick_.bind(this),this.value=t.value,this.viewProps=t.viewProps,this.foldable_=Ql.create(t.expanded),this.popC_=t.pickerLayout==="popup"?new yp(e,{viewProps:this.viewProps}):null;const s=new vy(e,{layout:t.pickerLayout,props:new Ue({invertsY:dt(t.invertsY),max:dt(t.max),xKeyScale:t.axes[0].textProps.value("keyScale"),yKeyScale:t.axes[1].textProps.value("keyScale")}),value:this.value,viewProps:this.viewProps});s.view.allFocusableElements.forEach(o=>{o.addEventListener("blur",this.onPopupChildBlur_),o.addEventListener("keydown",this.onPopupChildKeydown_)}),this.pickerC_=s,this.textC_=new du(e,{assembly:Wp,axes:t.axes,parser:t.parser,value:this.value,viewProps:this.viewProps}),this.view=new fy(e,{expanded:this.foldable_.value("expanded"),pickerLayout:t.pickerLayout,viewProps:this.viewProps}),this.view.textElement.appendChild(this.textC_.view.element),(n=this.view.buttonElement)===null||n===void 0||n.addEventListener("blur",this.onPadButtonBlur_),(i=this.view.buttonElement)===null||i===void 0||i.addEventListener("click",this.onPadButtonClick_),this.popC_?(this.view.element.appendChild(this.popC_.view.element),this.popC_.view.element.appendChild(this.pickerC_.view.element),Bi({primary:this.foldable_.value("expanded"),secondary:this.popC_.shows,forward:o=>o,backward:(o,l)=>l})):this.view.pickerElement&&(this.view.pickerElement.appendChild(this.pickerC_.view.element),Jl(this.foldable_,this.view.pickerElement))}get textController(){return this.textC_}onPadButtonBlur_(e){if(!this.popC_)return;const t=this.view.element,n=e.relatedTarget;(!n||!t.contains(n))&&(this.popC_.shows.rawValue=!1)}onPadButtonClick_(){this.foldable_.set("expanded",!this.foldable_.get("expanded")),this.foldable_.get("expanded")&&this.pickerC_.view.allFocusableElements[0].focus()}onPopupChildBlur_(e){if(!this.popC_)return;const t=this.popC_.view.element,n=cp(e);n&&t.contains(n)||n&&n===this.view.buttonElement&&!Kl(t.ownerDocument)||(this.popC_.shows.rawValue=!1)}onPopupChildKeydown_(e){this.popC_?e.key==="Escape"&&(this.popC_.shows.rawValue=!1):this.view.pickerElement&&e.key==="Escape"&&this.view.buttonElement.focus()}};function _y(r){return kn.isObject(r)?new kn(r.x,r.y):new kn}function wy(r,e){r.writeProperty("x",e.x),r.writeProperty("y",e.y)}function gy(r,e){return new cu({assembly:Wp,components:[rn(Object.assign(Object.assign({},r),r.x),e.x),rn(Object.assign(Object.assign({},r),r.y),e.y)]})}function oh(r,e){var t,n;if(!ut(r.min)||!ut(r.max))return Math.max(Math.abs((t=r.min)!==null&&t!==void 0?t:0),Math.abs((n=r.max)!==null&&n!==void 0?n:0));const i=tp(r);return Math.max(Math.abs(i)*10,Math.abs(e)*10)}function yy(r,e){var t,n;const i=oh(Jn(r,(t=r.x)!==null&&t!==void 0?t:{}),e.x),s=oh(Jn(r,(n=r.y)!==null&&n!==void 0?n:{}),e.y);return Math.max(i,s)}function xy(r){if(!("y"in r))return!1;const e=r.y;return e&&"inverted"in e?!!e.inverted:!1}const Cy=Qt({id:"input-point2d",type:"input",accept:(r,e)=>{if(!kn.isObject(r))return null;const t=bt(e,n=>Object.assign(Object.assign({},Cs(n)),{expanded:n.optional.boolean,picker:n.optional.custom(Sp),readonly:n.optional.constant(!1),x:n.optional.custom(Sn),y:n.optional.object(Object.assign(Object.assign({},Cs(n)),{inverted:n.optional.boolean}))}));return t?{initialValue:r,params:t}:null},binding:{reader:()=>_y,constraint:r=>gy(r.params,r.initialValue),equals:kn.equals,writer:()=>wy},controller:r=>{var e,t;const n=r.document,i=r.value,s=r.constraint,o=[r.params.x,r.params.y];return new by(n,{axes:i.rawValue.getComponents().map((l,y)=>{var x;return Hl({constraint:s.components[y],initialValue:l,params:Jn(r.params,(x=o[y])!==null&&x!==void 0?x:{})})}),expanded:(e=r.params.expanded)!==null&&e!==void 0?e:!1,invertsY:xy(r.params),max:yy(r.params,i.rawValue),parser:on,pickerLayout:(t=r.params.picker)!==null&&t!==void 0?t:"popup",value:i,viewProps:r.viewProps})}});let ki=class{constructor(e=0,t=0,n=0){this.x=e,this.y=t,this.z=n}getComponents(){return[this.x,this.y,this.z]}static isObject(e){if(ut(e))return!1;const t=e.x,n=e.y,i=e.z;return!(typeof t!="number"||typeof n!="number"||typeof i!="number")}static equals(e,t){return e.x===t.x&&e.y===t.y&&e.z===t.z}toObject(){return{x:this.x,y:this.y,z:this.z}}};const Zp={toComponents:r=>r.getComponents(),fromComponents:r=>new ki(...r)};function Ey(r){return ki.isObject(r)?new ki(r.x,r.y,r.z):new ki}function Py(r,e){r.writeProperty("x",e.x),r.writeProperty("y",e.y),r.writeProperty("z",e.z)}function Ay(r,e){return new cu({assembly:Zp,components:[rn(Object.assign(Object.assign({},r),r.x),e.x),rn(Object.assign(Object.assign({},r),r.y),e.y),rn(Object.assign(Object.assign({},r),r.z),e.z)]})}const Sy=Qt({id:"input-point3d",type:"input",accept:(r,e)=>{if(!ki.isObject(r))return null;const t=bt(e,n=>Object.assign(Object.assign({},Cs(n)),{readonly:n.optional.constant(!1),x:n.optional.custom(Sn),y:n.optional.custom(Sn),z:n.optional.custom(Sn)}));return t?{initialValue:r,params:t}:null},binding:{reader:r=>Ey,constraint:r=>Ay(r.params,r.initialValue),equals:ki.equals,writer:r=>Py},controller:r=>{const e=r.value,t=r.constraint,n=[r.params.x,r.params.y,r.params.z];return new du(r.document,{assembly:Zp,axes:e.rawValue.getComponents().map((i,s)=>{var o;return Hl({constraint:t.components[s],initialValue:i,params:Jn(r.params,(o=n[s])!==null&&o!==void 0?o:{})})}),parser:on,value:e,viewProps:r.viewProps})}});let Li=class{constructor(e=0,t=0,n=0,i=0){this.x=e,this.y=t,this.z=n,this.w=i}getComponents(){return[this.x,this.y,this.z,this.w]}static isObject(e){if(ut(e))return!1;const t=e.x,n=e.y,i=e.z,s=e.w;return!(typeof t!="number"||typeof n!="number"||typeof i!="number"||typeof s!="number")}static equals(e,t){return e.x===t.x&&e.y===t.y&&e.z===t.z&&e.w===t.w}toObject(){return{x:this.x,y:this.y,z:this.z,w:this.w}}};const Qp={toComponents:r=>r.getComponents(),fromComponents:r=>new Li(...r)};function Ty(r){return Li.isObject(r)?new Li(r.x,r.y,r.z,r.w):new Li}function ky(r,e){r.writeProperty("x",e.x),r.writeProperty("y",e.y),r.writeProperty("z",e.z),r.writeProperty("w",e.w)}function Ly(r,e){return new cu({assembly:Qp,components:[rn(Object.assign(Object.assign({},r),r.x),e.x),rn(Object.assign(Object.assign({},r),r.y),e.y),rn(Object.assign(Object.assign({},r),r.z),e.z),rn(Object.assign(Object.assign({},r),r.w),e.w)]})}const Vy=Qt({id:"input-point4d",type:"input",accept:(r,e)=>{if(!Li.isObject(r))return null;const t=bt(e,n=>Object.assign(Object.assign({},Cs(n)),{readonly:n.optional.constant(!1),w:n.optional.custom(Sn),x:n.optional.custom(Sn),y:n.optional.custom(Sn),z:n.optional.custom(Sn)}));return t?{initialValue:r,params:t}:null},binding:{reader:r=>Ty,constraint:r=>Ly(r.params,r.initialValue),equals:Li.equals,writer:r=>ky},controller:r=>{const e=r.value,t=r.constraint,n=[r.params.x,r.params.y,r.params.z,r.params.w];return new du(r.document,{assembly:Qp,axes:e.rawValue.getComponents().map((i,s)=>{var o;return Hl({constraint:t.components[s],initialValue:i,params:Jn(r.params,(o=n[s])!==null&&o!==void 0?o:{})})}),parser:on,value:e,viewProps:r.viewProps})}});function Oy(r){const e=[],t=ru(r.options);return t&&e.push(t),new Ls(e)}const Ry=Qt({id:"input-string",type:"input",accept:(r,e)=>{if(typeof r!="string")return null;const t=bt(e,n=>({readonly:n.optional.constant(!1),options:n.optional.custom(Os)}));return t?{initialValue:r,params:t}:null},binding:{reader:r=>Cp,constraint:r=>Oy(r.params),writer:r=>Ds},controller:r=>{const e=r.document,t=r.value,n=r.constraint,i=n&&Fa(n,Vs);return i?new Vn(e,{props:new Ue({options:i.values.value("options")}),value:t,viewProps:r.viewProps}):new ys(e,{parser:s=>s,props:Ue.fromObject({formatter:Ll}),value:t,viewProps:r.viewProps})},api(r){return typeof r.controller.value.rawValue!="string"?null:r.controller.valueController instanceof Vn?new eu(r.controller):null}}),Is={monitor:{defaultInterval:200,defaultRows:3}},lh=Xe("mll");let Dy=class{constructor(e,t){this.onValueUpdate_=this.onValueUpdate_.bind(this),this.formatter_=t.formatter,this.element=e.createElement("div"),this.element.classList.add(lh()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("textarea");n.classList.add(lh("i")),n.style.height=`calc(var(${Ap("containerUnitSize")}) * ${t.rows})`,n.readOnly=!0,t.viewProps.bindDisabled(n),this.element.appendChild(n),this.textareaElem_=n,t.value.emitter.on("change",this.onValueUpdate_),this.value=t.value,this.update_()}update_(){const e=this.textareaElem_,t=e.scrollTop===e.scrollHeight-e.clientHeight,n=[];this.value.rawValue.forEach(i=>{i!==void 0&&n.push(this.formatter_(i))}),e.textContent=n.join(` +`),t&&(e.scrollTop=e.scrollHeight)}onValueUpdate_(){this.update_()}},hu=class{constructor(e,t){this.value=t.value,this.viewProps=t.viewProps,this.view=new Dy(e,{formatter:t.formatter,rows:t.rows,value:this.value,viewProps:this.viewProps})}};const uh=Xe("sgl");let My=class{constructor(e,t){this.onValueUpdate_=this.onValueUpdate_.bind(this),this.formatter_=t.formatter,this.element=e.createElement("div"),this.element.classList.add(uh()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("input");n.classList.add(uh("i")),n.readOnly=!0,n.type="text",t.viewProps.bindDisabled(n),this.element.appendChild(n),this.inputElement=n,t.value.emitter.on("change",this.onValueUpdate_),this.value=t.value,this.update_()}update_(){const e=this.value.rawValue,t=e[e.length-1];this.inputElement.value=t!==void 0?this.formatter_(t):""}onValueUpdate_(){this.update_()}},pu=class{constructor(e,t){this.value=t.value,this.viewProps=t.viewProps,this.view=new My(e,{formatter:t.formatter,value:this.value,viewProps:this.viewProps})}};const Iy=Qt({id:"monitor-bool",type:"monitor",accept:(r,e)=>{if(typeof r!="boolean")return null;const t=bt(e,n=>({readonly:n.required.constant(!0),rows:n.optional.number}));return t?{initialValue:r,params:t}:null},binding:{reader:r=>xp},controller:r=>{var e;return r.value.rawValue.length===1?new pu(r.document,{formatter:th,value:r.value,viewProps:r.viewProps}):new hu(r.document,{formatter:th,rows:(e=r.params.rows)!==null&&e!==void 0?e:Is.monitor.defaultRows,value:r.value,viewProps:r.viewProps})}});let Fy=class extends gs{get max(){return this.controller.valueController.props.get("max")}set max(e){this.controller.valueController.props.set("max",e)}get min(){return this.controller.valueController.props.get("min")}set min(e){this.controller.valueController.props.set("min",e)}};const xn=Xe("grl");let $y=class{constructor(e,t){this.onCursorChange_=this.onCursorChange_.bind(this),this.onValueUpdate_=this.onValueUpdate_.bind(this),this.element=e.createElement("div"),this.element.classList.add(xn()),t.viewProps.bindClassModifiers(this.element),this.formatter_=t.formatter,this.props_=t.props,this.cursor_=t.cursor,this.cursor_.emitter.on("change",this.onCursorChange_);const n=e.createElementNS($r,"svg");n.classList.add(xn("g")),n.style.height=`calc(var(${Ap("containerUnitSize")}) * ${t.rows})`,this.element.appendChild(n),this.svgElem_=n;const i=e.createElementNS($r,"polyline");this.svgElem_.appendChild(i),this.lineElem_=i;const s=e.createElement("div");s.classList.add(xn("t"),Xe("tt")()),this.element.appendChild(s),this.tooltipElem_=s,t.value.emitter.on("change",this.onValueUpdate_),this.value=t.value,this.update_()}get graphElement(){return this.svgElem_}update_(){const{clientWidth:e,clientHeight:t}=this.element,n=this.value.rawValue.length-1,i=this.props_.get("min"),s=this.props_.get("max"),o=[];this.value.rawValue.forEach((U,de)=>{if(U===void 0)return;const Se=et(de,0,n,0,e),Ce=et(U,i,s,t,0);o.push([Se,Ce].join(","))}),this.lineElem_.setAttributeNS(null,"points",o.join(" "));const l=this.tooltipElem_,y=this.value.rawValue[this.cursor_.rawValue];if(y===void 0){l.classList.remove(xn("t","a"));return}const x=et(this.cursor_.rawValue,0,n,0,e),B=et(y,i,s,t,0);l.style.left=`${x}px`,l.style.top=`${B}px`,l.textContent=`${this.formatter_(y)}`,l.classList.contains(xn("t","a"))||(l.classList.add(xn("t","a"),xn("t","in")),Ia(l),l.classList.remove(xn("t","in")))}onValueUpdate_(){this.update_()}onCursorChange_(){this.update_()}},Jp=class{constructor(e,t){if(this.onGraphMouseMove_=this.onGraphMouseMove_.bind(this),this.onGraphMouseLeave_=this.onGraphMouseLeave_.bind(this),this.onGraphPointerDown_=this.onGraphPointerDown_.bind(this),this.onGraphPointerMove_=this.onGraphPointerMove_.bind(this),this.onGraphPointerUp_=this.onGraphPointerUp_.bind(this),this.props=t.props,this.value=t.value,this.viewProps=t.viewProps,this.cursor_=dt(-1),this.view=new $y(e,{cursor:this.cursor_,formatter:t.formatter,rows:t.rows,props:this.props,value:this.value,viewProps:this.viewProps}),!Kl(e))this.view.element.addEventListener("mousemove",this.onGraphMouseMove_),this.view.element.addEventListener("mouseleave",this.onGraphMouseLeave_);else{const n=new ai(this.view.element);n.emitter.on("down",this.onGraphPointerDown_),n.emitter.on("move",this.onGraphPointerMove_),n.emitter.on("up",this.onGraphPointerUp_)}}importProps(e){return fr(e,null,t=>({max:t.required.number,min:t.required.number}),t=>(this.props.set("max",t.max),this.props.set("min",t.min),!0))}exportProps(){return mr(null,{max:this.props.get("max"),min:this.props.get("min")})}onGraphMouseLeave_(){this.cursor_.rawValue=-1}onGraphMouseMove_(e){const{clientWidth:t}=this.view.element;this.cursor_.rawValue=Math.floor(et(e.offsetX,0,t,0,this.value.rawValue.length))}onGraphPointerDown_(e){this.onGraphPointerMove_(e)}onGraphPointerMove_(e){if(!e.data.point){this.cursor_.rawValue=-1;return}this.cursor_.rawValue=Math.floor(et(e.data.point.x,0,e.data.bounds.width,0,this.value.rawValue.length))}onGraphPointerUp_(){this.cursor_.rawValue=-1}};function Vl(r){return ut(r.format)?lr(2):r.format}function By(r){var e;return r.value.rawValue.length===1?new pu(r.document,{formatter:Vl(r.params),value:r.value,viewProps:r.viewProps}):new hu(r.document,{formatter:Vl(r.params),rows:(e=r.params.rows)!==null&&e!==void 0?e:Is.monitor.defaultRows,value:r.value,viewProps:r.viewProps})}function Ny(r){var e,t,n;return new Jp(r.document,{formatter:Vl(r.params),rows:(e=r.params.rows)!==null&&e!==void 0?e:Is.monitor.defaultRows,props:Ue.fromObject({max:(t=r.params.max)!==null&&t!==void 0?t:100,min:(n=r.params.min)!==null&&n!==void 0?n:0}),value:r.value,viewProps:r.viewProps})}function ch(r){return r.view==="graph"}const Gy=Qt({id:"monitor-number",type:"monitor",accept:(r,e)=>{if(typeof r!="number")return null;const t=bt(e,n=>({format:n.optional.function,max:n.optional.number,min:n.optional.number,readonly:n.required.constant(!0),rows:n.optional.number,view:n.optional.string}));return t?{initialValue:r,params:t}:null},binding:{defaultBufferSize:r=>ch(r)?64:1,reader:r=>Jh},controller:r=>ch(r.params)?Ny(r):By(r),api:r=>r.controller.valueController instanceof Jp?new Fy(r.controller):null}),jy=Qt({id:"monitor-string",type:"monitor",accept:(r,e)=>{if(typeof r!="string")return null;const t=bt(e,n=>({multiline:n.optional.boolean,readonly:n.required.constant(!0),rows:n.optional.number}));return t?{initialValue:r,params:t}:null},binding:{reader:r=>Cp},controller:r=>{var e;const t=r.value;return t.rawValue.length>1||r.params.multiline?new hu(r.document,{formatter:Ll,rows:(e=r.params.rows)!==null&&e!==void 0?e:Is.monitor.defaultRows,value:t,viewProps:r.viewProps}):new pu(r.document,{formatter:Ll,value:t,viewProps:r.viewProps})}});class Uy{constructor(){this.map_=new Map}get(e){var t;return(t=this.map_.get(e))!==null&&t!==void 0?t:null}has(e){return this.map_.has(e)}add(e,t){return this.map_.set(e,t),e.viewProps.handleDispose(()=>{this.map_.delete(e)}),t}}class zy{constructor(e){this.target=e.target,this.reader_=e.reader,this.writer_=e.writer}read(){return this.reader_(this.target.read())}write(e){this.writer_(this.target,e)}inject(e){this.write(this.reader_(e))}}function Hy(r,e){var t;const n=r.accept(e.target.read(),e.params);if(ut(n))return null;const i={target:e.target,initialValue:n.initialValue,params:n.params},s=bt(e.params,U=>({disabled:U.optional.boolean,hidden:U.optional.boolean,label:U.optional.string,tag:U.optional.string})),o=r.binding.reader(i),l=r.binding.constraint?r.binding.constraint(i):void 0,y=new zy({reader:o,target:e.target,writer:r.binding.writer(i)}),x=new Tw(dt(o(n.initialValue),{constraint:l,equals:r.binding.equals}),y),B=r.controller({constraint:l,document:e.document,initialValue:n.initialValue,params:n.params,value:x,viewProps:si.create({disabled:s?.disabled,hidden:s?.hidden})});return new Uw(e.document,{blade:$i(),props:Ue.fromObject({label:"label"in e.params?(t=s?.label)!==null&&t!==void 0?t:null:e.target.key}),tag:s?.tag,value:x,valueController:B})}class Ky{constructor(e){this.target=e.target,this.reader_=e.reader}read(){return this.reader_(this.target.read())}}function qy(r,e){return e===0?new P0:new A0(r,e??Is.monitor.defaultInterval)}function Xy(r,e){var t,n,i;const s=r.accept(e.target.read(),e.params);if(ut(s))return null;const o={target:e.target,initialValue:s.initialValue,params:s.params},l=bt(e.params,de=>({bufferSize:de.optional.number,disabled:de.optional.boolean,hidden:de.optional.boolean,interval:de.optional.number,label:de.optional.string})),y=r.binding.reader(o),x=(n=(t=l?.bufferSize)!==null&&t!==void 0?t:r.binding.defaultBufferSize&&r.binding.defaultBufferSize(s.params))!==null&&n!==void 0?n:1,B=new Xw({binding:new Ky({reader:y,target:e.target}),bufferSize:x,ticker:qy(e.document,l?.interval)}),U=r.controller({document:e.document,params:s.params,value:B,viewProps:si.create({disabled:l?.disabled,hidden:l?.hidden})});return U.viewProps.bindDisabled(B.ticker),U.viewProps.handleDispose(()=>{B.ticker.dispose()}),new Ww(e.document,{blade:$i(),props:Ue.fromObject({label:"label"in e.params?(i=l?.label)!==null&&i!==void 0?i:null:e.target.key}),value:B,valueController:U})}class Yy{constructor(e){this.pluginsMap_={blades:[],inputs:[],monitors:[]},this.apiCache_=e}getAll(){return[...this.pluginsMap_.blades,...this.pluginsMap_.inputs,...this.pluginsMap_.monitors]}register(e,t){if(!B0(t.core))throw qt.notCompatible(e,t.id);t.type==="blade"?this.pluginsMap_.blades.unshift(t):t.type==="input"?this.pluginsMap_.inputs.unshift(t):t.type==="monitor"&&this.pluginsMap_.monitors.unshift(t)}createInput_(e,t,n){return this.pluginsMap_.inputs.reduce((i,s)=>i??Hy(s,{document:e,target:t,params:n}),null)}createMonitor_(e,t,n){return this.pluginsMap_.monitors.reduce((i,s)=>i??Xy(s,{document:e,params:n,target:t}),null)}createBinding(e,t,n){const i=t.read();if(ut(i))throw new qt({context:{key:t.key},type:"nomatchingcontroller"});const s=this.createInput_(e,t,n);if(s)return s;const o=this.createMonitor_(e,t,n);if(o)return o;throw new qt({context:{key:t.key},type:"nomatchingcontroller"})}createBlade(e,t){const n=this.pluginsMap_.blades.reduce((i,s)=>i??E0(s,{document:e,params:t}),null);if(!n)throw new qt({type:"nomatchingview",context:{params:t}});return n}createInputBindingApi_(e){const t=this.pluginsMap_.inputs.reduce((n,i)=>{var s,o;return n||((o=(s=i.api)===null||s===void 0?void 0:s.call(i,{controller:e}))!==null&&o!==void 0?o:null)},null);return this.apiCache_.add(e,t??new gs(e))}createMonitorBindingApi_(e){const t=this.pluginsMap_.monitors.reduce((n,i)=>{var s,o;return n||((o=(s=i.api)===null||s===void 0?void 0:s.call(i,{controller:e}))!==null&&o!==void 0?o:null)},null);return this.apiCache_.add(e,t??new gs(e))}createBindingApi(e){if(this.apiCache_.has(e))return this.apiCache_.get(e);if(zw(e))return this.createInputBindingApi_(e);if(Zw(e))return this.createMonitorBindingApi_(e);throw qt.shouldNeverHappen()}createApi(e){if(this.apiCache_.has(e))return this.apiCache_.get(e);if(jw(e))return this.createBindingApi(e);const t=this.pluginsMap_.blades.reduce((n,i)=>n??i.api({controller:e,pool:this}),null);if(!t)throw qt.shouldNeverHappen();return this.apiCache_.add(e,t)}}const Wy=new Uy;function Zy(){const r=new Yy(Wy);return[Cy,Sy,Vy,Ry,py,ly,oy,ry,U0,Iy,jy,Gy,r0,m0,gp].forEach(e=>{r.register("core",e)}),r}class Qy extends ii{constructor(e){super(e),this.emitter_=new kt,this.controller.value.emitter.on("change",t=>{this.emitter_.emit("change",new ks(this,t.rawValue))})}get label(){return this.controller.labelController.props.get("label")}set label(e){this.controller.labelController.props.set("label",e)}get options(){return this.controller.valueController.props.get("options")}set options(e){this.controller.valueController.props.set("options",e)}get value(){return this.controller.value.rawValue}set value(e){this.controller.value.rawValue=e}on(e,t){const n=t.bind(this);return this.emitter_.on(e,i=>{n(i)},{key:t}),this}off(e,t){return this.emitter_.off(e,t),this}}class Jy extends ii{}class ex extends ii{constructor(e){super(e),this.emitter_=new kt,this.controller.value.emitter.on("change",t=>{this.emitter_.emit("change",new ks(this,t.rawValue))})}get label(){return this.controller.labelController.props.get("label")}set label(e){this.controller.labelController.props.set("label",e)}get max(){return this.controller.valueController.sliderController.props.get("max")}set max(e){this.controller.valueController.sliderController.props.set("max",e)}get min(){return this.controller.valueController.sliderController.props.get("min")}set min(e){this.controller.valueController.sliderController.props.set("min",e)}get value(){return this.controller.value.rawValue}set value(e){this.controller.value.rawValue=e}on(e,t){const n=t.bind(this);return this.emitter_.on(e,i=>{n(i)},{key:t}),this}off(e,t){return this.emitter_.off(e,t),this}}class tx extends ii{constructor(e){super(e),this.emitter_=new kt,this.controller.value.emitter.on("change",t=>{this.emitter_.emit("change",new ks(this,t.rawValue))})}get label(){return this.controller.labelController.props.get("label")}set label(e){this.controller.labelController.props.set("label",e)}get formatter(){return this.controller.valueController.props.get("formatter")}set formatter(e){this.controller.valueController.props.set("formatter",e)}get value(){return this.controller.value.rawValue}set value(e){this.controller.value.rawValue=e}on(e,t){const n=t.bind(this);return this.emitter_.on(e,i=>{n(i)},{key:t}),this}off(e,t){return this.emitter_.off(e,t),this}}const rx=(function(){return{id:"list",type:"blade",core:Fi,accept(r){const e=bt(r,t=>({options:t.required.custom(Os),value:t.required.raw,view:t.required.constant("list"),label:t.optional.string}));return e?{params:e}:null},controller(r){const e=new Vs(tu(r.params.options)),t=dt(r.params.value,{constraint:e}),n=new Vn(r.document,{props:new Ue({options:e.values.value("options")}),value:t,viewProps:r.viewProps});return new ei(r.document,{blade:r.blade,props:Ue.fromObject({label:r.params.label}),value:t,valueController:n})},api(r){return!(r.controller instanceof ei)||!(r.controller.valueController instanceof Vn)?null:new Qy(r.controller)}}})();class nx extends bp{constructor(e,t){super(e,t)}get element(){return this.controller.view.element}}class ix extends Tl{constructor(e,t){super(e,{expanded:t.expanded,blade:t.blade,props:t.props,root:!0,viewProps:t.viewProps})}}const dh=Xe("spr");class sx{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(dh()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("hr");n.classList.add(dh("r")),this.element.appendChild(n)}}class hh extends Ya{constructor(e,t){super(Object.assign(Object.assign({},t),{view:new sx(e,{viewProps:t.viewProps})}))}}const ax={id:"separator",type:"blade",core:Fi,accept(r){const e=bt(r,t=>({view:t.required.constant("separator")}));return e?{params:e}:null},controller(r){return new hh(r.document,{blade:r.blade,viewProps:r.viewProps})},api(r){return r.controller instanceof hh?new Jy(r.controller):null}},ox={id:"slider",type:"blade",core:Fi,accept(r){const e=bt(r,t=>({max:t.required.number,min:t.required.number,view:t.required.constant("slider"),format:t.optional.function,label:t.optional.string,value:t.optional.number}));return e?{params:e}:null},controller(r){var e,t;const n=(e=r.params.value)!==null&&e!==void 0?e:0,i=new Ts({max:r.params.max,min:r.params.min}),s=dt(n,{constraint:i}),o=new Ba(r.document,Object.assign(Object.assign({},Pp({formatter:(t=r.params.format)!==null&&t!==void 0?t:Cw,keyScale:dt(1),max:i.values.value("max"),min:i.values.value("min"),pointerScale:rp(r.params,n)})),{parser:on,value:s,viewProps:r.viewProps}));return new ei(r.document,{blade:r.blade,props:Ue.fromObject({label:r.params.label}),value:s,valueController:o})},api(r){return!(r.controller instanceof ei)||!(r.controller.valueController instanceof Ba)?null:new ex(r.controller)}},lx=(function(){return{id:"text",type:"blade",core:Fi,accept(r){const e=bt(r,t=>({parse:t.required.function,value:t.required.raw,view:t.required.constant("text"),format:t.optional.function,label:t.optional.string}));return e?{params:e}:null},controller(r){var e;const t=dt(r.params.value),n=new ys(r.document,{parser:r.params.parse,props:Ue.fromObject({formatter:(e=r.params.format)!==null&&e!==void 0?e:(i=>String(i))}),value:t,viewProps:r.viewProps});return new ei(r.document,{blade:r.blade,props:Ue.fromObject({label:r.params.label}),value:t,valueController:n})},api(r){return!(r.controller instanceof ei)||!(r.controller.valueController instanceof ys)?null:new tx(r.controller)}}})();function ux(r){const e=r.createElement("div");return e.classList.add(Xe("dfw")()),r.body&&r.body.appendChild(e),e}function cx(r,e,t){if(r.querySelector(`style[data-tp-style=${e}]`))return;const n=r.createElement("style");n.dataset.tpStyle=e,n.textContent=t,r.head.appendChild(n)}class JA extends nx{constructor(e){var t,n;const i=e??{},s=(t=i.document)!==null&&t!==void 0?t:Mw(),o=Zy(),l=new ix(s,{expanded:i.expanded,blade:$i(),props:Ue.fromObject({title:i.title}),viewProps:si.create()});super(l,o),this.pool_=o,this.containerElem_=(n=i.container)!==null&&n!==void 0?n:ux(s),this.containerElem_.appendChild(this.element),this.doc_=s,this.usesDefaultWrapper_=!i.container,this.setUpDefaultPlugins_()}get document(){if(!this.doc_)throw qt.alreadyDisposed();return this.doc_}dispose(){const e=this.containerElem_;if(!e)throw qt.alreadyDisposed();if(this.usesDefaultWrapper_){const t=e.parentElement;t&&t.removeChild(e)}this.containerElem_=null,this.doc_=null,super.dispose()}registerPlugin(e){e.css&&cx(this.document,`plugin-${e.id}`,e.css),("plugin"in e?[e.plugin]:"plugins"in e?e.plugins:[]).forEach(n=>{this.pool_.register(e.id,n)})}setUpDefaultPlugins_(){this.registerPlugin({id:"default",css:'.tp-tbiv_b,.tp-coltxtv_ms,.tp-colswv_b,.tp-ckbv_i,.tp-sglv_i,.tp-mllv_i,.tp-grlv_g,.tp-txtv_i,.tp-p2dpv_p,.tp-colswv_sw,.tp-rotv_b,.tp-fldv_b,.tp-p2dv_b,.tp-btnv_b,.tp-lstv_s{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:rgba(0,0,0,0);border-width:0;font-family:inherit;font-size:inherit;font-weight:inherit;margin:0;outline:none;padding:0}.tp-p2dv_b,.tp-btnv_b,.tp-lstv_s{background-color:var(--btn-bg);border-radius:var(--bld-br);color:var(--btn-fg);cursor:pointer;display:block;font-weight:bold;height:var(--cnt-usz);line-height:var(--cnt-usz);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tp-p2dv_b:hover,.tp-btnv_b:hover,.tp-lstv_s:hover{background-color:var(--btn-bg-h)}.tp-p2dv_b:focus,.tp-btnv_b:focus,.tp-lstv_s:focus{background-color:var(--btn-bg-f)}.tp-p2dv_b:active,.tp-btnv_b:active,.tp-lstv_s:active{background-color:var(--btn-bg-a)}.tp-p2dv_b:disabled,.tp-btnv_b:disabled,.tp-lstv_s:disabled{opacity:.5}.tp-rotv_c>.tp-cntv.tp-v-lst,.tp-tbpv_c>.tp-cntv.tp-v-lst,.tp-fldv_c>.tp-cntv.tp-v-lst{margin-bottom:calc(-1*var(--cnt-vp))}.tp-rotv_c>.tp-fldv.tp-v-lst .tp-fldv_c,.tp-tbpv_c>.tp-fldv.tp-v-lst .tp-fldv_c,.tp-fldv_c>.tp-fldv.tp-v-lst .tp-fldv_c{border-bottom-left-radius:0}.tp-rotv_c>.tp-fldv.tp-v-lst .tp-fldv_b,.tp-tbpv_c>.tp-fldv.tp-v-lst .tp-fldv_b,.tp-fldv_c>.tp-fldv.tp-v-lst .tp-fldv_b{border-bottom-left-radius:0}.tp-rotv_c>*:not(.tp-v-fst),.tp-tbpv_c>*:not(.tp-v-fst),.tp-fldv_c>*:not(.tp-v-fst){margin-top:var(--cnt-usp)}.tp-rotv_c>.tp-sprv:not(.tp-v-fst),.tp-tbpv_c>.tp-sprv:not(.tp-v-fst),.tp-fldv_c>.tp-sprv:not(.tp-v-fst),.tp-rotv_c>.tp-cntv:not(.tp-v-fst),.tp-tbpv_c>.tp-cntv:not(.tp-v-fst),.tp-fldv_c>.tp-cntv:not(.tp-v-fst){margin-top:var(--cnt-vp)}.tp-rotv_c>.tp-sprv+*:not(.tp-v-hidden),.tp-tbpv_c>.tp-sprv+*:not(.tp-v-hidden),.tp-fldv_c>.tp-sprv+*:not(.tp-v-hidden),.tp-rotv_c>.tp-cntv+*:not(.tp-v-hidden),.tp-tbpv_c>.tp-cntv+*:not(.tp-v-hidden),.tp-fldv_c>.tp-cntv+*:not(.tp-v-hidden){margin-top:var(--cnt-vp)}.tp-rotv_c>.tp-sprv:not(.tp-v-hidden)+.tp-sprv,.tp-tbpv_c>.tp-sprv:not(.tp-v-hidden)+.tp-sprv,.tp-fldv_c>.tp-sprv:not(.tp-v-hidden)+.tp-sprv,.tp-rotv_c>.tp-cntv:not(.tp-v-hidden)+.tp-cntv,.tp-tbpv_c>.tp-cntv:not(.tp-v-hidden)+.tp-cntv,.tp-fldv_c>.tp-cntv:not(.tp-v-hidden)+.tp-cntv{margin-top:0}.tp-tbpv_c>.tp-cntv,.tp-fldv_c>.tp-cntv{margin-left:4px}.tp-tbpv_c>.tp-fldv>.tp-fldv_b,.tp-fldv_c>.tp-fldv>.tp-fldv_b{border-top-left-radius:var(--bld-br);border-bottom-left-radius:var(--bld-br)}.tp-tbpv_c>.tp-fldv.tp-fldv-expanded>.tp-fldv_b,.tp-fldv_c>.tp-fldv.tp-fldv-expanded>.tp-fldv_b{border-bottom-left-radius:0}.tp-tbpv_c .tp-fldv>.tp-fldv_c,.tp-fldv_c .tp-fldv>.tp-fldv_c{border-bottom-left-radius:var(--bld-br)}.tp-tbpv_c>.tp-cntv+.tp-fldv>.tp-fldv_b,.tp-fldv_c>.tp-cntv+.tp-fldv>.tp-fldv_b{border-top-left-radius:0}.tp-tbpv_c>.tp-cntv+.tp-tabv>.tp-tabv_t,.tp-fldv_c>.tp-cntv+.tp-tabv>.tp-tabv_t{border-top-left-radius:0}.tp-tbpv_c>.tp-tabv>.tp-tabv_t,.tp-fldv_c>.tp-tabv>.tp-tabv_t{border-top-left-radius:var(--bld-br)}.tp-tbpv_c .tp-tabv>.tp-tabv_c,.tp-fldv_c .tp-tabv>.tp-tabv_c{border-bottom-left-radius:var(--bld-br)}.tp-rotv_b,.tp-fldv_b{background-color:var(--cnt-bg);color:var(--cnt-fg);cursor:pointer;display:block;height:calc(var(--cnt-usz) + 4px);line-height:calc(var(--cnt-usz) + 4px);overflow:hidden;padding-left:var(--cnt-hp);padding-right:calc(4px + var(--cnt-usz) + var(--cnt-hp));position:relative;text-align:left;text-overflow:ellipsis;white-space:nowrap;width:100%;transition:border-radius .2s ease-in-out .2s}.tp-rotv_b:hover,.tp-fldv_b:hover{background-color:var(--cnt-bg-h)}.tp-rotv_b:focus,.tp-fldv_b:focus{background-color:var(--cnt-bg-f)}.tp-rotv_b:active,.tp-fldv_b:active{background-color:var(--cnt-bg-a)}.tp-rotv_b:disabled,.tp-fldv_b:disabled{opacity:.5}.tp-rotv_m,.tp-fldv_m{background:linear-gradient(to left, var(--cnt-fg), var(--cnt-fg) 2px, transparent 2px, transparent 4px, var(--cnt-fg) 4px);border-radius:2px;bottom:0;content:"";display:block;height:6px;right:calc(var(--cnt-hp) + (var(--cnt-usz) + 4px - 6px)/2 - 2px);margin:auto;opacity:.5;position:absolute;top:0;transform:rotate(90deg);transition:transform .2s ease-in-out;width:6px}.tp-rotv.tp-rotv-expanded .tp-rotv_m,.tp-fldv.tp-fldv-expanded>.tp-fldv_b>.tp-fldv_m{transform:none}.tp-rotv_c,.tp-fldv_c{box-sizing:border-box;height:0;opacity:0;overflow:hidden;padding-bottom:0;padding-top:0;position:relative;transition:height .2s ease-in-out,opacity .2s linear,padding .2s ease-in-out}.tp-rotv.tp-rotv-cpl:not(.tp-rotv-expanded) .tp-rotv_c,.tp-fldv.tp-fldv-cpl:not(.tp-fldv-expanded)>.tp-fldv_c{display:none}.tp-rotv.tp-rotv-expanded .tp-rotv_c,.tp-fldv.tp-fldv-expanded>.tp-fldv_c{opacity:1;padding-bottom:var(--cnt-vp);padding-top:var(--cnt-vp);transform:none;overflow:visible;transition:height .2s ease-in-out,opacity .2s linear .2s,padding .2s ease-in-out}.tp-txtv_i,.tp-p2dpv_p,.tp-colswv_sw{background-color:var(--in-bg);border-radius:var(--bld-br);box-sizing:border-box;color:var(--in-fg);font-family:inherit;height:var(--cnt-usz);line-height:var(--cnt-usz);min-width:0;width:100%}.tp-txtv_i:hover,.tp-p2dpv_p:hover,.tp-colswv_sw:hover{background-color:var(--in-bg-h)}.tp-txtv_i:focus,.tp-p2dpv_p:focus,.tp-colswv_sw:focus{background-color:var(--in-bg-f)}.tp-txtv_i:active,.tp-p2dpv_p:active,.tp-colswv_sw:active{background-color:var(--in-bg-a)}.tp-txtv_i:disabled,.tp-p2dpv_p:disabled,.tp-colswv_sw:disabled{opacity:.5}.tp-lstv,.tp-coltxtv_m{position:relative}.tp-lstv_s{padding:0 20px 0 4px;width:100%}.tp-lstv_m,.tp-coltxtv_mm{bottom:0;margin:auto;pointer-events:none;position:absolute;right:2px;top:0}.tp-lstv_m svg,.tp-coltxtv_mm svg{bottom:0;height:16px;margin:auto;position:absolute;right:0;top:0;width:16px}.tp-lstv_m svg path,.tp-coltxtv_mm svg path{fill:currentColor}.tp-sglv_i,.tp-mllv_i,.tp-grlv_g{background-color:var(--mo-bg);border-radius:var(--bld-br);box-sizing:border-box;color:var(--mo-fg);height:var(--cnt-usz);scrollbar-color:currentColor rgba(0,0,0,0);scrollbar-width:thin;width:100%}.tp-sglv_i::-webkit-scrollbar,.tp-mllv_i::-webkit-scrollbar,.tp-grlv_g::-webkit-scrollbar{height:8px;width:8px}.tp-sglv_i::-webkit-scrollbar-corner,.tp-mllv_i::-webkit-scrollbar-corner,.tp-grlv_g::-webkit-scrollbar-corner{background-color:rgba(0,0,0,0)}.tp-sglv_i::-webkit-scrollbar-thumb,.tp-mllv_i::-webkit-scrollbar-thumb,.tp-grlv_g::-webkit-scrollbar-thumb{background-clip:padding-box;background-color:currentColor;border:rgba(0,0,0,0) solid 2px;border-radius:4px}.tp-pndtxtv,.tp-coltxtv_w{display:flex}.tp-pndtxtv_a,.tp-coltxtv_c{width:100%}.tp-pndtxtv_a+.tp-pndtxtv_a,.tp-coltxtv_c+.tp-pndtxtv_a,.tp-pndtxtv_a+.tp-coltxtv_c,.tp-coltxtv_c+.tp-coltxtv_c{margin-left:2px}.tp-rotv{--bs-bg: var(--tp-base-background-color, hsl(230, 7%, 17%));--bs-br: var(--tp-base-border-radius, 6px);--bs-ff: var(--tp-base-font-family, Roboto Mono, Source Code Pro, Menlo, Courier, monospace);--bs-sh: var(--tp-base-shadow-color, rgba(0, 0, 0, 0.2));--bld-br: var(--tp-blade-border-radius, 2px);--bld-hp: var(--tp-blade-horizontal-padding, 4px);--bld-vw: var(--tp-blade-value-width, 160px);--btn-bg: var(--tp-button-background-color, hsl(230, 7%, 70%));--btn-bg-a: var(--tp-button-background-color-active, #d6d7db);--btn-bg-f: var(--tp-button-background-color-focus, #c8cad0);--btn-bg-h: var(--tp-button-background-color-hover, #bbbcc4);--btn-fg: var(--tp-button-foreground-color, hsl(230, 7%, 17%));--cnt-bg: var(--tp-container-background-color, rgba(187, 188, 196, 0.1));--cnt-bg-a: var(--tp-container-background-color-active, rgba(187, 188, 196, 0.25));--cnt-bg-f: var(--tp-container-background-color-focus, rgba(187, 188, 196, 0.2));--cnt-bg-h: var(--tp-container-background-color-hover, rgba(187, 188, 196, 0.15));--cnt-fg: var(--tp-container-foreground-color, hsl(230, 7%, 75%));--cnt-hp: var(--tp-container-horizontal-padding, 4px);--cnt-vp: var(--tp-container-vertical-padding, 4px);--cnt-usp: var(--tp-container-unit-spacing, 4px);--cnt-usz: var(--tp-container-unit-size, 20px);--in-bg: var(--tp-input-background-color, rgba(187, 188, 196, 0.1));--in-bg-a: var(--tp-input-background-color-active, rgba(187, 188, 196, 0.25));--in-bg-f: var(--tp-input-background-color-focus, rgba(187, 188, 196, 0.2));--in-bg-h: var(--tp-input-background-color-hover, rgba(187, 188, 196, 0.15));--in-fg: var(--tp-input-foreground-color, hsl(230, 7%, 75%));--lbl-fg: var(--tp-label-foreground-color, rgba(187, 188, 196, 0.7));--mo-bg: var(--tp-monitor-background-color, rgba(0, 0, 0, 0.2));--mo-fg: var(--tp-monitor-foreground-color, rgba(187, 188, 196, 0.7));--grv-fg: var(--tp-groove-foreground-color, rgba(187, 188, 196, 0.1))}.tp-btnv_b{width:100%}.tp-btnv_t{text-align:center}.tp-ckbv_l{display:block;position:relative}.tp-ckbv_i{left:0;opacity:0;position:absolute;top:0}.tp-ckbv_w{background-color:var(--in-bg);border-radius:var(--bld-br);cursor:pointer;display:block;height:var(--cnt-usz);position:relative;width:var(--cnt-usz)}.tp-ckbv_w svg{display:block;height:16px;inset:0;margin:auto;opacity:0;position:absolute;width:16px}.tp-ckbv_w svg path{fill:none;stroke:var(--in-fg);stroke-width:2}.tp-ckbv_i:hover+.tp-ckbv_w{background-color:var(--in-bg-h)}.tp-ckbv_i:focus+.tp-ckbv_w{background-color:var(--in-bg-f)}.tp-ckbv_i:active+.tp-ckbv_w{background-color:var(--in-bg-a)}.tp-ckbv_i:checked+.tp-ckbv_w svg{opacity:1}.tp-ckbv.tp-v-disabled .tp-ckbv_w{opacity:.5}.tp-colv{position:relative}.tp-colv_h{display:flex}.tp-colv_s{flex-grow:0;flex-shrink:0;width:var(--cnt-usz)}.tp-colv_t{flex:1;margin-left:4px}.tp-colv_p{height:0;margin-top:0;opacity:0;overflow:hidden;transition:height .2s ease-in-out,opacity .2s linear,margin .2s ease-in-out}.tp-colv.tp-colv-expanded.tp-colv-cpl .tp-colv_p{overflow:visible}.tp-colv.tp-colv-expanded .tp-colv_p{margin-top:var(--cnt-usp);opacity:1}.tp-colv .tp-popv{left:calc(-1*var(--cnt-hp));right:calc(-1*var(--cnt-hp));top:var(--cnt-usz)}.tp-colpv_h,.tp-colpv_ap{margin-left:6px;margin-right:6px}.tp-colpv_h{margin-top:var(--cnt-usp)}.tp-colpv_rgb{display:flex;margin-top:var(--cnt-usp);width:100%}.tp-colpv_a{display:flex;margin-top:var(--cnt-vp);padding-top:calc(var(--cnt-vp) + 2px);position:relative}.tp-colpv_a::before{background-color:var(--grv-fg);content:"";height:2px;left:calc(-1*var(--cnt-hp));position:absolute;right:calc(-1*var(--cnt-hp));top:0}.tp-colpv.tp-v-disabled .tp-colpv_a::before{opacity:.5}.tp-colpv_ap{align-items:center;display:flex;flex:3}.tp-colpv_at{flex:1;margin-left:4px}.tp-svpv{border-radius:var(--bld-br);outline:none;overflow:hidden;position:relative}.tp-svpv.tp-v-disabled{opacity:.5}.tp-svpv_c{cursor:crosshair;display:block;height:calc(var(--cnt-usz)*4);width:100%}.tp-svpv_m{border-radius:100%;border:rgba(255,255,255,.75) solid 2px;box-sizing:border-box;filter:drop-shadow(0 0 1px rgba(0, 0, 0, 0.3));height:12px;margin-left:-6px;margin-top:-6px;pointer-events:none;position:absolute;width:12px}.tp-svpv:focus .tp-svpv_m{border-color:#fff}.tp-hplv{cursor:pointer;height:var(--cnt-usz);outline:none;position:relative}.tp-hplv.tp-v-disabled{opacity:.5}.tp-hplv_c{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAABCAYAAABubagXAAAAQ0lEQVQoU2P8z8Dwn0GCgQEDi2OK/RBgYHjBgIpfovFh8j8YBIgzFGQxuqEgPhaDOT5gOhPkdCxOZeBg+IDFZZiGAgCaSSMYtcRHLgAAAABJRU5ErkJggg==);background-position:left top;background-repeat:no-repeat;background-size:100% 100%;border-radius:2px;display:block;height:4px;left:0;margin-top:-2px;position:absolute;top:50%;width:100%}.tp-hplv_m{border-radius:var(--bld-br);border:rgba(255,255,255,.75) solid 2px;box-shadow:0 0 2px rgba(0,0,0,.1);box-sizing:border-box;height:12px;left:50%;margin-left:-6px;margin-top:-6px;position:absolute;top:50%;width:12px}.tp-hplv:focus .tp-hplv_m{border-color:#fff}.tp-aplv{cursor:pointer;height:var(--cnt-usz);outline:none;position:relative;width:100%}.tp-aplv.tp-v-disabled{opacity:.5}.tp-aplv_b{background-color:#fff;background-image:linear-gradient(to top right, #ddd 25%, transparent 25%, transparent 75%, #ddd 75%),linear-gradient(to top right, #ddd 25%, transparent 25%, transparent 75%, #ddd 75%);background-size:4px 4px;background-position:0 0,2px 2px;border-radius:2px;display:block;height:4px;left:0;margin-top:-2px;overflow:hidden;position:absolute;top:50%;width:100%}.tp-aplv_c{inset:0;position:absolute}.tp-aplv_m{background-color:#fff;background-image:linear-gradient(to top right, #ddd 25%, transparent 25%, transparent 75%, #ddd 75%),linear-gradient(to top right, #ddd 25%, transparent 25%, transparent 75%, #ddd 75%);background-size:12px 12px;background-position:0 0,6px 6px;border-radius:var(--bld-br);box-shadow:0 0 2px rgba(0,0,0,.1);height:12px;left:50%;margin-left:-6px;margin-top:-6px;overflow:hidden;position:absolute;top:50%;width:12px}.tp-aplv_p{border-radius:var(--bld-br);border:rgba(255,255,255,.75) solid 2px;box-sizing:border-box;inset:0;position:absolute}.tp-aplv:focus .tp-aplv_p{border-color:#fff}.tp-colswv{background-color:#fff;background-image:linear-gradient(to top right, #ddd 25%, transparent 25%, transparent 75%, #ddd 75%),linear-gradient(to top right, #ddd 25%, transparent 25%, transparent 75%, #ddd 75%);background-size:10px 10px;background-position:0 0,5px 5px;border-radius:var(--bld-br);overflow:hidden}.tp-colswv.tp-v-disabled{opacity:.5}.tp-colswv_sw{border-radius:0}.tp-colswv_b{cursor:pointer;display:block;height:var(--cnt-usz);left:0;position:absolute;top:0;width:var(--cnt-usz)}.tp-colswv_b:focus::after{border:rgba(255,255,255,.75) solid 2px;border-radius:var(--bld-br);content:"";display:block;inset:0;position:absolute}.tp-coltxtv{display:flex;width:100%}.tp-coltxtv_m{margin-right:4px}.tp-coltxtv_ms{border-radius:var(--bld-br);color:var(--lbl-fg);cursor:pointer;height:var(--cnt-usz);line-height:var(--cnt-usz);padding:0 18px 0 4px}.tp-coltxtv_ms:hover{background-color:var(--in-bg-h)}.tp-coltxtv_ms:focus{background-color:var(--in-bg-f)}.tp-coltxtv_ms:active{background-color:var(--in-bg-a)}.tp-coltxtv_mm{color:var(--lbl-fg)}.tp-coltxtv.tp-v-disabled .tp-coltxtv_mm{opacity:.5}.tp-coltxtv_w{flex:1}.tp-dfwv{position:absolute;top:8px;right:8px;width:256px}.tp-fldv{position:relative}.tp-fldv_t{padding-left:4px}.tp-fldv_b:disabled .tp-fldv_m{display:none}.tp-fldv_c{padding-left:4px}.tp-fldv_i{bottom:0;color:var(--cnt-bg);left:0;overflow:hidden;position:absolute;top:calc(var(--cnt-usz) + 4px);width:max(var(--bs-br),4px)}.tp-fldv_i::before{background-color:currentColor;bottom:0;content:"";left:0;position:absolute;top:0;width:4px}.tp-fldv_b:hover+.tp-fldv_i{color:var(--cnt-bg-h)}.tp-fldv_b:focus+.tp-fldv_i{color:var(--cnt-bg-f)}.tp-fldv_b:active+.tp-fldv_i{color:var(--cnt-bg-a)}.tp-fldv.tp-v-disabled>.tp-fldv_i{opacity:.5}.tp-grlv{position:relative}.tp-grlv_g{display:block;height:calc(var(--cnt-usz)*3)}.tp-grlv_g polyline{fill:none;stroke:var(--mo-fg);stroke-linejoin:round}.tp-grlv_t{margin-top:-4px;transition:left .05s,top .05s;visibility:hidden}.tp-grlv_t.tp-grlv_t-a{visibility:visible}.tp-grlv_t.tp-grlv_t-in{transition:none}.tp-grlv.tp-v-disabled .tp-grlv_g{opacity:.5}.tp-grlv .tp-ttv{background-color:var(--mo-fg)}.tp-grlv .tp-ttv::before{border-top-color:var(--mo-fg)}.tp-lblv{align-items:center;display:flex;line-height:1.3;padding-left:var(--cnt-hp);padding-right:var(--cnt-hp)}.tp-lblv.tp-lblv-nol{display:block}.tp-lblv_l{color:var(--lbl-fg);flex:1;-webkit-hyphens:auto;hyphens:auto;overflow:hidden;padding-left:4px;padding-right:16px}.tp-lblv.tp-v-disabled .tp-lblv_l{opacity:.5}.tp-lblv.tp-lblv-nol .tp-lblv_l{display:none}.tp-lblv_v{align-self:flex-start;flex-grow:0;flex-shrink:0;width:var(--bld-vw)}.tp-lblv.tp-lblv-nol .tp-lblv_v{width:100%}.tp-lstv_s{padding:0 20px 0 var(--bld-hp);width:100%}.tp-lstv_m{color:var(--btn-fg)}.tp-sglv_i{padding-left:var(--bld-hp);padding-right:var(--bld-hp)}.tp-sglv.tp-v-disabled .tp-sglv_i{opacity:.5}.tp-mllv_i{display:block;height:calc(var(--cnt-usz)*3);line-height:var(--cnt-usz);padding-left:var(--bld-hp);padding-right:var(--bld-hp);resize:none;white-space:pre}.tp-mllv.tp-v-disabled .tp-mllv_i{opacity:.5}.tp-p2dv{position:relative}.tp-p2dv_h{display:flex}.tp-p2dv_b{height:var(--cnt-usz);margin-right:4px;position:relative;width:var(--cnt-usz)}.tp-p2dv_b svg{display:block;height:16px;left:50%;margin-left:-8px;margin-top:-8px;position:absolute;top:50%;width:16px}.tp-p2dv_b svg path{stroke:currentColor;stroke-width:2}.tp-p2dv_b svg circle{fill:currentColor}.tp-p2dv_t{flex:1}.tp-p2dv_p{height:0;margin-top:0;opacity:0;overflow:hidden;transition:height .2s ease-in-out,opacity .2s linear,margin .2s ease-in-out}.tp-p2dv.tp-p2dv-expanded .tp-p2dv_p{margin-top:var(--cnt-usp);opacity:1}.tp-p2dv .tp-popv{left:calc(-1*var(--cnt-hp));right:calc(-1*var(--cnt-hp));top:var(--cnt-usz)}.tp-p2dpv{padding-left:calc(var(--cnt-usz) + 4px)}.tp-p2dpv_p{cursor:crosshair;height:0;overflow:hidden;padding-bottom:100%;position:relative}.tp-p2dpv.tp-v-disabled .tp-p2dpv_p{opacity:.5}.tp-p2dpv_g{display:block;height:100%;left:0;pointer-events:none;position:absolute;top:0;width:100%}.tp-p2dpv_ax{opacity:.1;stroke:var(--in-fg);stroke-dasharray:1}.tp-p2dpv_l{opacity:.5;stroke:var(--in-fg);stroke-dasharray:1}.tp-p2dpv_m{border:var(--in-fg) solid 1px;border-radius:50%;box-sizing:border-box;height:4px;margin-left:-2px;margin-top:-2px;position:absolute;width:4px}.tp-p2dpv_p:focus .tp-p2dpv_m{background-color:var(--in-fg);border-width:0}.tp-popv{background-color:var(--bs-bg);border-radius:var(--bs-br);box-shadow:0 2px 4px var(--bs-sh);display:none;max-width:var(--bld-vw);padding:var(--cnt-vp) var(--cnt-hp);position:absolute;visibility:hidden;z-index:1000}.tp-popv.tp-popv-v{display:block;visibility:visible}.tp-sldv.tp-v-disabled{opacity:.5}.tp-sldv_t{box-sizing:border-box;cursor:pointer;height:var(--cnt-usz);margin:0 6px;outline:none;position:relative}.tp-sldv_t::before{background-color:var(--in-bg);border-radius:1px;content:"";display:block;height:2px;inset:0;margin:auto;position:absolute}.tp-sldv_k{height:100%;left:0;position:absolute;top:0}.tp-sldv_k::before{background-color:var(--in-fg);border-radius:1px;content:"";display:block;height:2px;inset:0;margin-bottom:auto;margin-top:auto;position:absolute}.tp-sldv_k::after{background-color:var(--btn-bg);border-radius:var(--bld-br);bottom:0;content:"";display:block;height:12px;margin-bottom:auto;margin-top:auto;position:absolute;right:-6px;top:0;width:12px}.tp-sldv_t:hover .tp-sldv_k::after{background-color:var(--btn-bg-h)}.tp-sldv_t:focus .tp-sldv_k::after{background-color:var(--btn-bg-f)}.tp-sldv_t:active .tp-sldv_k::after{background-color:var(--btn-bg-a)}.tp-sldtxtv{display:flex}.tp-sldtxtv_s{flex:2}.tp-sldtxtv_t{flex:1;margin-left:4px}.tp-tabv{position:relative}.tp-tabv_t{align-items:flex-end;color:var(--cnt-bg);display:flex;overflow:hidden;position:relative}.tp-tabv_t:hover{color:var(--cnt-bg-h)}.tp-tabv_t:has(*:focus){color:var(--cnt-bg-f)}.tp-tabv_t:has(*:active){color:var(--cnt-bg-a)}.tp-tabv_t::before{background-color:currentColor;bottom:0;content:"";height:2px;left:0;pointer-events:none;position:absolute;right:0}.tp-tabv.tp-v-disabled .tp-tabv_t::before{opacity:.5}.tp-tabv.tp-tabv-nop .tp-tabv_t{height:calc(var(--cnt-usz) + 4px);position:relative}.tp-tabv.tp-tabv-nop .tp-tabv_t::before{background-color:var(--cnt-bg);bottom:0;content:"";height:2px;left:0;position:absolute;right:0}.tp-tabv_i{bottom:0;color:var(--cnt-bg);left:0;overflow:hidden;position:absolute;top:calc(var(--cnt-usz) + 4px);width:max(var(--bs-br),4px)}.tp-tabv_i::before{background-color:currentColor;bottom:0;content:"";left:0;position:absolute;top:0;width:4px}.tp-tabv_t:hover+.tp-tabv_i{color:var(--cnt-bg-h)}.tp-tabv_t:has(*:focus)+.tp-tabv_i{color:var(--cnt-bg-f)}.tp-tabv_t:has(*:active)+.tp-tabv_i{color:var(--cnt-bg-a)}.tp-tabv.tp-v-disabled>.tp-tabv_i{opacity:.5}.tp-tbiv{flex:1;min-width:0;position:relative}.tp-tbiv+.tp-tbiv{margin-left:2px}.tp-tbiv+.tp-tbiv.tp-v-disabled::before{opacity:.5}.tp-tbiv_b{display:block;padding-left:calc(var(--cnt-hp) + 4px);padding-right:calc(var(--cnt-hp) + 4px);position:relative;width:100%}.tp-tbiv_b:disabled{opacity:.5}.tp-tbiv_b::before{background-color:var(--cnt-bg);content:"";inset:0 0 2px;pointer-events:none;position:absolute}.tp-tbiv_b:hover::before{background-color:var(--cnt-bg-h)}.tp-tbiv_b:focus::before{background-color:var(--cnt-bg-f)}.tp-tbiv_b:active::before{background-color:var(--cnt-bg-a)}.tp-tbiv_t{color:var(--cnt-fg);height:calc(var(--cnt-usz) + 4px);line-height:calc(var(--cnt-usz) + 4px);opacity:.5;overflow:hidden;position:relative;text-overflow:ellipsis}.tp-tbiv.tp-tbiv-sel .tp-tbiv_t{opacity:1}.tp-tbpv_c{padding-bottom:var(--cnt-vp);padding-left:4px;padding-top:var(--cnt-vp)}.tp-txtv{position:relative}.tp-txtv_i{padding-left:var(--bld-hp);padding-right:var(--bld-hp)}.tp-txtv.tp-txtv-fst .tp-txtv_i{border-bottom-right-radius:0;border-top-right-radius:0}.tp-txtv.tp-txtv-mid .tp-txtv_i{border-radius:0}.tp-txtv.tp-txtv-lst .tp-txtv_i{border-bottom-left-radius:0;border-top-left-radius:0}.tp-txtv.tp-txtv-num .tp-txtv_i{text-align:right}.tp-txtv.tp-txtv-drg .tp-txtv_i{opacity:.3}.tp-txtv_k{cursor:pointer;height:100%;left:calc(var(--bld-hp) - 5px);position:absolute;top:0;width:12px}.tp-txtv_k::before{background-color:var(--in-fg);border-radius:1px;bottom:0;content:"";height:calc(var(--cnt-usz) - 4px);left:50%;margin-bottom:auto;margin-left:-1px;margin-top:auto;opacity:.1;position:absolute;top:0;transition:border-radius .1s,height .1s,transform .1s,width .1s;width:2px}.tp-txtv_k:hover::before,.tp-txtv.tp-txtv-drg .tp-txtv_k::before{opacity:1}.tp-txtv.tp-txtv-drg .tp-txtv_k::before{border-radius:50%;height:4px;transform:translateX(-1px);width:4px}.tp-txtv_g{bottom:0;display:block;height:8px;left:50%;margin:auto;overflow:visible;pointer-events:none;position:absolute;top:0;visibility:hidden;width:100%}.tp-txtv.tp-txtv-drg .tp-txtv_g{visibility:visible}.tp-txtv_gb{fill:none;stroke:var(--in-fg);stroke-dasharray:1}.tp-txtv_gh{fill:none;stroke:var(--in-fg)}.tp-txtv .tp-ttv{margin-left:6px;visibility:hidden}.tp-txtv.tp-txtv-drg .tp-ttv{visibility:visible}.tp-ttv{background-color:var(--in-fg);border-radius:var(--bld-br);color:var(--bs-bg);padding:2px 4px;pointer-events:none;position:absolute;transform:translate(-50%, -100%)}.tp-ttv::before{border-color:var(--in-fg) rgba(0,0,0,0) rgba(0,0,0,0) rgba(0,0,0,0);border-style:solid;border-width:2px;box-sizing:border-box;content:"";font-size:.9em;height:4px;left:50%;margin-left:-2px;position:absolute;top:100%;width:4px}.tp-rotv{background-color:var(--bs-bg);border-radius:var(--bs-br);box-shadow:0 2px 4px var(--bs-sh);font-family:var(--bs-ff);font-size:11px;font-weight:500;line-height:1;text-align:left}.tp-rotv_b{border-bottom-left-radius:var(--bs-br);border-bottom-right-radius:var(--bs-br);border-top-left-radius:var(--bs-br);border-top-right-radius:var(--bs-br);padding-left:calc(4px + var(--cnt-usz) + var(--cnt-hp));text-align:center}.tp-rotv.tp-rotv-expanded .tp-rotv_b{border-bottom-left-radius:0;border-bottom-right-radius:0;transition-delay:0s;transition-duration:0s}.tp-rotv.tp-rotv-not>.tp-rotv_b{display:none}.tp-rotv_b:disabled .tp-rotv_m{display:none}.tp-rotv_c>.tp-fldv.tp-v-lst>.tp-fldv_c{border-bottom-left-radius:var(--bs-br);border-bottom-right-radius:var(--bs-br)}.tp-rotv_c>.tp-fldv.tp-v-lst>.tp-fldv_i{border-bottom-left-radius:var(--bs-br)}.tp-rotv_c>.tp-fldv.tp-v-lst:not(.tp-fldv-expanded)>.tp-fldv_b{border-bottom-left-radius:var(--bs-br);border-bottom-right-radius:var(--bs-br)}.tp-rotv_c>.tp-fldv.tp-v-lst.tp-fldv-expanded>.tp-fldv_b{transition-delay:0s;transition-duration:0s}.tp-rotv_c .tp-fldv.tp-v-vlst:not(.tp-fldv-expanded)>.tp-fldv_b{border-bottom-right-radius:var(--bs-br)}.tp-rotv.tp-rotv-not .tp-rotv_c>.tp-fldv.tp-v-fst{margin-top:calc(-1*var(--cnt-vp))}.tp-rotv.tp-rotv-not .tp-rotv_c>.tp-fldv.tp-v-fst>.tp-fldv_b{border-top-left-radius:var(--bs-br);border-top-right-radius:var(--bs-br)}.tp-rotv_c>.tp-tabv.tp-v-lst>.tp-tabv_c{border-bottom-left-radius:var(--bs-br);border-bottom-right-radius:var(--bs-br)}.tp-rotv_c>.tp-tabv.tp-v-lst>.tp-tabv_i{border-bottom-left-radius:var(--bs-br)}.tp-rotv.tp-rotv-not .tp-rotv_c>.tp-tabv.tp-v-fst{margin-top:calc(-1*var(--cnt-vp))}.tp-rotv.tp-rotv-not .tp-rotv_c>.tp-tabv.tp-v-fst>.tp-tabv_t{border-top-left-radius:var(--bs-br);border-top-right-radius:var(--bs-br)}.tp-rotv.tp-v-disabled,.tp-rotv .tp-v-disabled{pointer-events:none}.tp-rotv.tp-v-hidden,.tp-rotv .tp-v-hidden{display:none}.tp-sprv_r{background-color:var(--grv-fg);border-width:0;display:block;height:2px;margin:0;width:100%}.tp-sprv.tp-v-disabled .tp-sprv_r{opacity:.5}',plugins:[rx,ax,ox,gp,lx]})}}new mp("4.0.5");function vt(r){return r==null}function fu(r){return r!==null&&typeof r=="object"}function Ol(r){return r!==null&&typeof r=="object"}function dx(r,e){if(r.length!==e.length)return!1;for(let t=0;t{const s=r[i],o=e[i];return Ol(s)&&Ol(o)?Object.assign(Object.assign({},n),{[i]:ri(s,o)}):Object.assign(Object.assign({},n),{[i]:i in e?o:s})},{})}function hx(r){return fu(r)?"target"in r:!1}const px={alreadydisposed:()=>"View has been already disposed",invalidparams:r=>`Invalid parameters for '${r.name}'`,nomatchingcontroller:r=>`No matching controller for '${r.key}'`,nomatchingview:r=>`No matching view for '${JSON.stringify(r.params)}'`,notbindable:()=>"Value is not bindable",notcompatible:r=>`Not compatible with plugin '${r.id}'`,propertynotfound:r=>`Property '${r.name}' not found`,shouldneverhappen:()=>"This error should never happen"};class pr{static alreadyDisposed(){return new pr({type:"alreadydisposed"})}static notBindable(){return new pr({type:"notbindable"})}static notCompatible(e,t){return new pr({type:"notcompatible",context:{id:`${e}.${t}`}})}static propertyNotFound(e){return new pr({type:"propertynotfound",context:{name:e}})}static shouldNeverHappen(){return new pr({type:"shouldneverhappen"})}constructor(e){var t;this.message=(t=px[e.type](e.context))!==null&&t!==void 0?t:"Unexpected error",this.name=this.constructor.name,this.stack=new Error(this.message).stack,this.type=e.type}toString(){return this.message}}class Na{constructor(e,t){this.obj_=e,this.key=t}static isBindable(e){return!(e===null||typeof e!="object"&&typeof e!="function")}read(){return this.obj_[this.key]}write(e){this.obj_[this.key]=e}writeProperty(e,t){const n=this.read();if(!Na.isBindable(n))throw pr.notBindable();if(!(e in n))throw pr.propertyNotFound(e);n[e]=t}}class vr{constructor(){this.observers_={}}on(e,t,n){var i;let s=this.observers_[e];return s||(s=this.observers_[e]=[]),s.push({handler:t,key:(i=n?.key)!==null&&i!==void 0?i:t}),this}off(e,t){const n=this.observers_[e];return n&&(this.observers_[e]=n.filter(i=>i.key!==t)),this}emit(e,t){const n=this.observers_[e];n&&n.forEach(i=>{i.handler(t)})}}class fx{constructor(e,t){var n;this.constraint_=t?.constraint,this.equals_=(n=t?.equals)!==null&&n!==void 0?n:((i,s)=>i===s),this.emitter=new vr,this.rawValue_=e}get constraint(){return this.constraint_}get rawValue(){return this.rawValue_}set rawValue(e){this.setRawValue(e,{forceEmit:!1,last:!0})}setRawValue(e,t){const n=t??{forceEmit:!1,last:!0},i=this.constraint_?this.constraint_.constrain(e):e,s=this.rawValue_;this.equals_(s,i)&&!n.forceEmit||(this.emitter.emit("beforechange",{sender:this}),this.rawValue_=i,this.emitter.emit("change",{options:n,previousRawValue:s,rawValue:i,sender:this}))}}class mx{constructor(e){this.emitter=new vr,this.value_=e}get rawValue(){return this.value_}set rawValue(e){this.setRawValue(e,{forceEmit:!1,last:!0})}setRawValue(e,t){const n=t??{forceEmit:!1,last:!0},i=this.value_;i===e&&!n.forceEmit||(this.emitter.emit("beforechange",{sender:this}),this.value_=e,this.emitter.emit("change",{options:n,previousRawValue:i,rawValue:this.value_,sender:this}))}}class vx{constructor(e){this.emitter=new vr,this.onValueBeforeChange_=this.onValueBeforeChange_.bind(this),this.onValueChange_=this.onValueChange_.bind(this),this.value_=e,this.value_.emitter.on("beforechange",this.onValueBeforeChange_),this.value_.emitter.on("change",this.onValueChange_)}get rawValue(){return this.value_.rawValue}onValueBeforeChange_(e){this.emitter.emit("beforechange",Object.assign(Object.assign({},e),{sender:this}))}onValueChange_(e){this.emitter.emit("change",Object.assign(Object.assign({},e),{sender:this}))}}function jt(r,e){const t=e?.constraint,n=e?.equals;return!t&&!n?new mx(r):new fx(r,e)}function bx(r){return[new vx(r),(e,t)=>{r.setRawValue(e,t)}]}class Ze{constructor(e){this.emitter=new vr,this.valMap_=e;for(const t in this.valMap_)this.valMap_[t].emitter.on("change",()=>{this.emitter.emit("change",{key:t,sender:this})})}static createCore(e){return Object.keys(e).reduce((n,i)=>Object.assign(n,{[i]:jt(e[i])}),{})}static fromObject(e){const t=this.createCore(e);return new Ze(t)}get(e){return this.valMap_[e].rawValue}set(e,t){this.valMap_[e].rawValue=t}value(e){return this.valMap_[e]}}class Za{constructor(e){this.values=Ze.fromObject({max:e.max,min:e.min})}constrain(e){const t=this.values.get("max"),n=this.values.get("min");return Math.min(Math.max(e,n),t)}}class _x{constructor(e){this.values=Ze.fromObject({max:e.max,min:e.min})}constrain(e){const t=this.values.get("max"),n=this.values.get("min");let i=e;return vt(n)||(i=Math.max(i,n)),vt(t)||(i=Math.min(i,t)),i}}class wx{constructor(e,t=0){this.step=e,this.origin=t}constrain(e){const t=this.origin%this.step,n=Math.round((e-t)/this.step);return t+n*this.step}}class gx{constructor(e){this.text=e}evaluate(){return Number(this.text)}toString(){return this.text}}const yx={"**":(r,e)=>Math.pow(r,e),"*":(r,e)=>r*e,"/":(r,e)=>r/e,"%":(r,e)=>r%e,"+":(r,e)=>r+e,"-":(r,e)=>r-e,"<<":(r,e)=>r<>":(r,e)=>r>>e,">>>":(r,e)=>r>>>e,"&":(r,e)=>r&e,"^":(r,e)=>r^e,"|":(r,e)=>r|e};class xx{constructor(e,t,n){this.left=t,this.operator=e,this.right=n}evaluate(){const e=yx[this.operator];if(!e)throw new Error(`unexpected binary operator: '${this.operator}`);return e(this.left.evaluate(),this.right.evaluate())}toString(){return["b(",this.left.toString(),this.operator,this.right.toString(),")"].join(" ")}}const Cx={"+":r=>r,"-":r=>-r,"~":r=>~r};class Ex{constructor(e,t){this.operator=e,this.expression=t}evaluate(){const e=Cx[this.operator];if(!e)throw new Error(`unexpected unary operator: '${this.operator}`);return e(this.expression.evaluate())}toString(){return["u(",this.operator,this.expression.toString(),")"].join(" ")}}function mu(r){return(e,t)=>{for(let n=0;ne.startsWith(i,t))[0];return n?(t+=n.length,t+=Es(e,t).length,{cursor:t,operator:n}):null}function Ux(r,e){return(t,n)=>{const i=r(t,n);if(!i)return null;n=i.cursor;let s=i.evaluable;for(;;){const o=jx(e,t,n);if(!o)break;n=o.cursor;const l=r(t,n);if(!l)return null;n=l.cursor,s=new xx(o.operator,s,l.evaluable)}return s?{cursor:n,evaluable:s}:null}}const zx=[["**"],["*","/","%"],["+","-"],["<<",">>>",">>"],["&"],["^"],["|"]].reduce((r,e)=>Ux(r,e),tf);function rf(r,e){return e+=Es(r,e).length,zx(r,e)}function Hx(r){const e=rf(r,0);return!e||e.cursor+Es(r,e.cursor).length!==r.length?null:e.evaluable}function On(r){var e;const t=Hx(r);return(e=t?.evaluate())!==null&&e!==void 0?e:null}function nf(r){if(typeof r=="number")return r;if(typeof r=="string"){const e=On(r);if(!vt(e))return e}return 0}function ur(r){return e=>e.toFixed(Math.max(Math.min(r,20),0))}function tt(r,e,t,n,i){const s=(r-e)/(t-e);return n+s*(i-n)}function ph(r){return String(r.toFixed(10)).split(".")[1].replace(/0+$/,"").length}function Dt(r,e,t){return Math.min(Math.max(r,e),t)}function sf(r,e){return(r%e+e)%e}function Kx(r,e){return vt(r.step)?Math.max(ph(e),2):ph(r.step)}function af(r){var e;return(e=r.step)!==null&&e!==void 0?e:1}function qx(r,e){var t;const n=Math.abs((t=r.step)!==null&&t!==void 0?t:e);return n===0?.1:Math.pow(10,Math.floor(Math.log10(n))-1)}function of(r,e){return vt(r.step)?null:new wx(r.step,e)}function lf(r){return!vt(r.max)&&!vt(r.min)?new Za({max:r.max,min:r.min}):!vt(r.max)||!vt(r.min)?new _x({max:r.max,min:r.min}):null}function uf(r,e){var t,n,i;return{formatter:(t=r.format)!==null&&t!==void 0?t:ur(Kx(r,e)),keyScale:(n=r.keyScale)!==null&&n!==void 0?n:af(r),pointerScale:(i=r.pointerScale)!==null&&i!==void 0?i:qx(r,e)}}function cf(r){return{format:r.optional.function,keyScale:r.optional.number,max:r.optional.number,min:r.optional.number,pointerScale:r.optional.number,step:r.optional.number}}function bu(r){return{constraint:r.constraint,textProps:Ze.fromObject(uf(r.params,r.initialValue))}}class _u{constructor(e){this.controller=e}get element(){return this.controller.view.element}get disabled(){return this.controller.viewProps.get("disabled")}set disabled(e){this.controller.viewProps.set("disabled",e)}get hidden(){return this.controller.viewProps.get("hidden")}set hidden(e){this.controller.viewProps.set("hidden",e)}dispose(){this.controller.viewProps.set("disposed",!0)}importState(e){return this.controller.importState(e)}exportState(){return this.controller.exportState()}}class Qa{constructor(e){this.target=e}}class df extends Qa{constructor(e,t,n){super(e),this.value=t,this.last=n??!0}}class Xx extends Qa{constructor(e,t){super(e),this.expanded=t}}class Yx extends Qa{constructor(e,t){super(e),this.index=t}}class Wx extends Qa{constructor(e,t){super(e),this.native=t}}class wu extends _u{constructor(e){super(e),this.onValueChange_=this.onValueChange_.bind(this),this.emitter_=new vr,this.controller.value.emitter.on("change",this.onValueChange_)}get label(){return this.controller.labelController.props.get("label")}set label(e){this.controller.labelController.props.set("label",e)}get key(){return this.controller.value.binding.target.key}get tag(){return this.controller.tag}set tag(e){this.controller.tag=e}on(e,t){const n=t.bind(this);return this.emitter_.on(e,i=>{n(i)},{key:t}),this}off(e,t){return this.emitter_.off(e,t),this}refresh(){this.controller.value.fetch()}onValueChange_(e){const t=this.controller.value;this.emitter_.emit("change",new df(this,t.binding.target.read(),e.options.last))}}function Zx(r,e){const n=Object.keys(e).reduce((i,s)=>{if(i===void 0)return;const o=e[s],l=o(r[s]);return l.succeeded?Object.assign(Object.assign({},i),{[s]:l.value}):void 0},{});return n}function Qx(r,e){return r.reduce((t,n)=>{if(t===void 0)return;const i=e(n);if(!(!i.succeeded||i.value===void 0))return[...t,i.value]},[])}function Jx(r){return r===null?!1:typeof r=="object"}function en(r){return e=>t=>{if(!e&&t===void 0)return{succeeded:!1,value:void 0};if(e&&t===void 0)return{succeeded:!0,value:void 0};const n=r(t);return n!==void 0?{succeeded:!0,value:n}:{succeeded:!1,value:void 0}}}function fh(r){return{custom:e=>en(e)(r),boolean:en(e=>typeof e=="boolean"?e:void 0)(r),number:en(e=>typeof e=="number"?e:void 0)(r),string:en(e=>typeof e=="string"?e:void 0)(r),function:en(e=>typeof e=="function"?e:void 0)(r),constant:e=>en(t=>t===e?e:void 0)(r),raw:en(e=>e)(r),object:e=>en(t=>{if(Jx(t))return Zx(t,e)})(r),array:e=>en(t=>{if(Array.isArray(t))return Qx(t,e)})(r)}}const Rl={optional:fh(!0),required:fh(!1)};function Xt(r,e){const t=e(Rl),n=Rl.required.object(t)(r);return n.succeeded?n.value:void 0}function zr(r,e,t,n){if(e&&!e(r))return!1;const i=Xt(r,t);return i?n(i):!1}function Hr(r,e){var t;return ri((t=r?.())!==null&&t!==void 0?t:{},e)}function Oa(r){return"value"in r}function eC(r){if(!fu(r)||!("binding"in r))return!1;const e=r.binding;return hx(e)}const Br="http://www.w3.org/2000/svg";function Ga(r){r.offsetHeight}function tC(r,e){const t=r.style.transition;r.style.transition="none",e(),r.style.transition=t}function gu(r){return r.ontouchstart!==void 0}function rC(r){const e=r.ownerDocument.defaultView;return e&&"document"in e?r.getContext("2d",{willReadFrequently:!0}):null}const nC={check:'',dropdown:'',p2dpad:''};function Ja(r,e){const t=r.createElementNS(Br,"svg");return t.innerHTML=nC[e],t}function hf(r,e,t){r.insertBefore(e,r.children[t])}function yu(r){r.parentElement&&r.parentElement.removeChild(r)}function pf(r){for(;r.children.length>0;)r.removeChild(r.children[0])}function iC(r){for(;r.childNodes.length>0;)r.removeChild(r.childNodes[0])}function ff(r){return r.relatedTarget?r.relatedTarget:"explicitOriginalTarget"in r?r.explicitOriginalTarget:null}function an(r,e){r.emitter.on("change",t=>{e(t.rawValue)}),e(r.rawValue)}function jr(r,e,t){an(r.value(e),t)}const sC="tp";function Qe(r){return(t,n)=>[sC,"-",r,"v",t?`_${t}`:"",n?`-${n}`:""].join("")}const cs=Qe("lbl");function aC(r,e){const t=r.createDocumentFragment();return e.split(` +`).map(i=>r.createTextNode(i)).forEach((i,s)=>{s>0&&t.appendChild(r.createElement("br")),t.appendChild(i)}),t}class oC{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(cs()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("div");n.classList.add(cs("l")),jr(t.props,"label",s=>{vt(s)?this.element.classList.add(cs(void 0,"nol")):(this.element.classList.remove(cs(void 0,"nol")),iC(n),n.appendChild(aC(e,s)))}),this.element.appendChild(n),this.labelElement=n;const i=e.createElement("div");i.classList.add(cs("v")),this.element.appendChild(i),this.valueElement=i}}class lC{constructor(e,t){this.props=t.props,this.valueController=t.valueController,this.viewProps=t.valueController.viewProps,this.view=new oC(e,{props:t.props,viewProps:this.viewProps}),this.view.valueElement.appendChild(this.valueController.view.element)}importProps(e){return zr(e,null,t=>({label:t.optional.string}),t=>(this.props.set("label",t.label),!0))}exportProps(){return Hr(null,{label:this.props.get("label")})}}function uC(){return["veryfirst","first","last","verylast"]}const mh=Qe(""),vh={veryfirst:"vfst",first:"fst",last:"lst",verylast:"vlst"};class mf{constructor(e){this.parent_=null,this.blade=e.blade,this.view=e.view,this.viewProps=e.viewProps;const t=this.view.element;this.blade.value("positions").emitter.on("change",()=>{uC().forEach(n=>{t.classList.remove(mh(void 0,vh[n]))}),this.blade.get("positions").forEach(n=>{t.classList.add(mh(void 0,vh[n]))})}),this.viewProps.handleDispose(()=>{yu(t)})}get parent(){return this.parent_}set parent(e){this.parent_=e,this.viewProps.set("parent",this.parent_?this.parent_.viewProps:null)}importState(e){return zr(e,null,t=>({disabled:t.required.boolean,hidden:t.required.boolean}),t=>(this.viewProps.importState(t),!0))}exportState(){return Hr(null,Object.assign({},this.viewProps.exportState()))}}class cC extends _u{get label(){return this.controller.labelController.props.get("label")}set label(e){this.controller.labelController.props.set("label",e)}get title(){var e;return(e=this.controller.buttonController.props.get("title"))!==null&&e!==void 0?e:""}set title(e){this.controller.buttonController.props.set("title",e)}on(e,t){const n=t.bind(this);return this.controller.buttonController.emitter.on(e,s=>{n(new Wx(this,s.nativeEvent))}),this}off(e,t){return this.controller.buttonController.emitter.off(e,t),this}}function dC(r,e,t){t?r.classList.add(e):r.classList.remove(e)}function Ni(r,e){return t=>{dC(r,e,t)}}function xu(r,e){an(r,t=>{e.textContent=t??""})}const fl=Qe("btn");class hC{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(fl()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("button");n.classList.add(fl("b")),t.viewProps.bindDisabled(n),this.element.appendChild(n),this.buttonElement=n;const i=e.createElement("div");i.classList.add(fl("t")),xu(t.props.value("title"),i),this.buttonElement.appendChild(i)}}class pC{constructor(e,t){this.emitter=new vr,this.onClick_=this.onClick_.bind(this),this.props=t.props,this.viewProps=t.viewProps,this.view=new hC(e,{props:this.props,viewProps:this.viewProps}),this.view.buttonElement.addEventListener("click",this.onClick_)}importProps(e){return zr(e,null,t=>({title:t.optional.string}),t=>(this.props.set("title",t.title),!0))}exportProps(){return Hr(null,{title:this.props.get("title")})}onClick_(e){this.emitter.emit("click",{nativeEvent:e,sender:this})}}class bh extends mf{constructor(e,t){const n=new pC(e,{props:t.buttonProps,viewProps:t.viewProps}),i=new lC(e,{blade:t.blade,props:t.labelProps,valueController:n});super({blade:t.blade,view:i.view,viewProps:t.viewProps}),this.buttonController=n,this.labelController=i}importState(e){return zr(e,t=>super.importState(t)&&this.buttonController.importProps(t)&&this.labelController.importProps(t),()=>({}),()=>!0)}exportState(){return Hr(()=>super.exportState(),Object.assign(Object.assign({},this.buttonController.exportProps()),this.labelController.exportProps()))}}class fC{constructor(e){const[t,n]=e.split("-"),i=t.split(".");this.major=parseInt(i[0],10),this.minor=parseInt(i[1],10),this.patch=parseInt(i[2],10),this.prerelease=n??null}toString(){const e=[this.major,this.minor,this.patch].join(".");return this.prerelease!==null?[e,this.prerelease].join("-"):e}}const mC=new fC("2.0.5");function Jt(r){return Object.assign({core:mC},r)}Jt({id:"button",type:"blade",accept(r){const e=Xt(r,t=>({title:t.required.string,view:t.required.constant("button"),label:t.optional.string}));return e?{params:e}:null},controller(r){return new bh(r.document,{blade:r.blade,buttonProps:Ze.fromObject({title:r.params.title}),labelProps:Ze.fromObject({label:r.params.label}),viewProps:r.viewProps})},api(r){return r.controller instanceof bh?new cC(r.controller):null}});function vC(r,e){return r.addBlade(Object.assign(Object.assign({},e),{view:"button"}))}function bC(r,e){return r.addBlade(Object.assign(Object.assign({},e),{view:"folder"}))}function _C(r,e){return r.addBlade(Object.assign(Object.assign({},e),{view:"tab"}))}function wC(r){return fu(r)?"refresh"in r&&typeof r.refresh=="function":!1}function gC(r,e){if(!Na.isBindable(r))throw pr.notBindable();return new Na(r,e)}class yC{constructor(e,t){this.onRackValueChange_=this.onRackValueChange_.bind(this),this.controller_=e,this.emitter_=new vr,this.pool_=t,this.controller_.rack.emitter.on("valuechange",this.onRackValueChange_)}get children(){return this.controller_.rack.children.map(e=>this.pool_.createApi(e))}addBinding(e,t,n){const i=n??{},s=this.controller_.element.ownerDocument,o=this.pool_.createBinding(s,gC(e,t),i),l=this.pool_.createBindingApi(o);return this.add(l,i.index)}addFolder(e){return bC(this,e)}addButton(e){return vC(this,e)}addTab(e){return _C(this,e)}add(e,t){const n=e.controller;return this.controller_.rack.add(n,t),e}remove(e){this.controller_.rack.remove(e.controller)}addBlade(e){const t=this.controller_.element.ownerDocument,n=this.pool_.createBlade(t,e),i=this.pool_.createApi(n);return this.add(i,e.index)}on(e,t){const n=t.bind(this);return this.emitter_.on(e,i=>{n(i)},{key:t}),this}off(e,t){return this.emitter_.off(e,t),this}refresh(){this.children.forEach(e=>{wC(e)&&e.refresh()})}onRackValueChange_(e){const t=e.bladeController,n=this.pool_.createApi(t),i=eC(t.value)?t.value.binding:null;this.emitter_.emit("change",new df(n,i?i.target.read():t.value.rawValue,e.options.last))}}class Cu extends _u{constructor(e,t){super(e),this.rackApi_=new yC(e.rackController,t)}refresh(){this.rackApi_.refresh()}}class Eu extends mf{constructor(e){super({blade:e.blade,view:e.view,viewProps:e.rackController.viewProps}),this.rackController=e.rackController}importState(e){return zr(e,t=>super.importState(t),t=>({children:t.required.array(t.required.raw)}),t=>this.rackController.rack.children.every((n,i)=>n.importState(t.children[i])))}exportState(){return Hr(()=>super.exportState(),{children:this.rackController.rack.children.map(e=>e.exportState())})}}function Dl(r){return"rackController"in r}class xC{constructor(e){this.emitter=new vr,this.items_=[],this.cache_=new Set,this.onSubListAdd_=this.onSubListAdd_.bind(this),this.onSubListRemove_=this.onSubListRemove_.bind(this),this.extract_=e}get items(){return this.items_}allItems(){return Array.from(this.cache_)}find(e){for(const t of this.allItems())if(e(t))return t;return null}includes(e){return this.cache_.has(e)}add(e,t){if(this.includes(e))throw pr.shouldNeverHappen();const n=t!==void 0?t:this.items_.length;this.items_.splice(n,0,e),this.cache_.add(e);const i=this.extract_(e);i&&(i.emitter.on("add",this.onSubListAdd_),i.emitter.on("remove",this.onSubListRemove_),i.allItems().forEach(s=>{this.cache_.add(s)})),this.emitter.emit("add",{index:n,item:e,root:this,target:this})}remove(e){const t=this.items_.indexOf(e);if(t<0)return;this.items_.splice(t,1),this.cache_.delete(e);const n=this.extract_(e);n&&(n.allItems().forEach(i=>{this.cache_.delete(i)}),n.emitter.off("add",this.onSubListAdd_),n.emitter.off("remove",this.onSubListRemove_)),this.emitter.emit("remove",{index:t,item:e,root:this,target:this})}onSubListAdd_(e){this.cache_.add(e.item),this.emitter.emit("add",{index:e.index,item:e.item,root:this,target:e.target})}onSubListRemove_(e){this.cache_.delete(e.item),this.emitter.emit("remove",{index:e.index,item:e.item,root:this,target:e.target})}}function CC(r,e){for(let t=0;t!i.viewProps.get("hidden")),t=e[0],n=e[e.length-1];this.bcSet_.items.forEach(i=>{const s=[];i===t&&(s.push("first"),(!this.blade_||this.blade_.get("positions").includes("veryfirst"))&&s.push("veryfirst")),i===n&&(s.push("last"),(!this.blade_||this.blade_.get("positions").includes("verylast"))&&s.push("verylast")),i.blade.set("positions",s)})}onChildPositionsChange_(){this.updatePositions_(),this.emitter.emit("layout",{sender:this})}onChildViewPropsChange_(e){this.updatePositions_(),this.emitter.emit("layout",{sender:this})}onChildDispose_(){this.bcSet_.items.filter(t=>t.viewProps.get("disposed")).forEach(t=>{this.bcSet_.remove(t)})}onChildValueChange_(e){const t=CC(this.find(Oa),e.sender);if(!t)throw pr.alreadyDisposed();this.emitter.emit("valuechange",{bladeController:t,options:e.options,sender:this})}onRackLayout_(e){this.updatePositions_(),this.emitter.emit("layout",{sender:this})}onRackValueChange_(e){this.emitter.emit("valuechange",{bladeController:e.bladeController,options:e.options,sender:this})}onBladePositionsChange_(){this.updatePositions_()}}class Pu{constructor(e){this.onRackAdd_=this.onRackAdd_.bind(this),this.onRackRemove_=this.onRackRemove_.bind(this),this.element=e.element,this.viewProps=e.viewProps;const t=new PC({blade:e.root?void 0:e.blade,viewProps:e.viewProps});t.emitter.on("add",this.onRackAdd_),t.emitter.on("remove",this.onRackRemove_),this.rack=t,this.viewProps.handleDispose(()=>{for(let n=this.rack.children.length-1;n>=0;n--)this.rack.children[n].viewProps.set("disposed",!0)})}onRackAdd_(e){e.root&&hf(this.element,e.bladeController.view.element,e.index)}onRackRemove_(e){e.root&&yu(e.bladeController.view.element)}}function vf(){return new Ze({positions:jt([],{equals:dx})})}class Fs extends Ze{constructor(e){super(e)}static create(e){const t={completed:!0,expanded:e,expandedHeight:null,shouldFixHeight:!1,temporaryExpanded:null},n=Ze.createCore(t);return new Fs(n)}get styleExpanded(){var e;return(e=this.get("temporaryExpanded"))!==null&&e!==void 0?e:this.get("expanded")}get styleHeight(){if(!this.styleExpanded)return"0";const e=this.get("expandedHeight");return this.get("shouldFixHeight")&&!vt(e)?`${e}px`:"auto"}bindExpandedClass(e,t){const n=()=>{this.styleExpanded?e.classList.add(t):e.classList.remove(t)};jr(this,"expanded",n),jr(this,"temporaryExpanded",n)}cleanUpTransition(){this.set("shouldFixHeight",!1),this.set("expandedHeight",null),this.set("completed",!0)}}function AC(r,e){let t=0;return tC(e,()=>{r.set("expandedHeight",null),r.set("temporaryExpanded",!0),Ga(e),t=e.clientHeight,r.set("temporaryExpanded",null),Ga(e)}),t}function _h(r,e){e.style.height=r.styleHeight}function Au(r,e){r.value("expanded").emitter.on("beforechange",()=>{if(r.set("completed",!1),vt(r.get("expandedHeight"))){const t=AC(r,e);t>0&&r.set("expandedHeight",t)}r.set("shouldFixHeight",!0),Ga(e)}),r.emitter.on("change",()=>{_h(r,e)}),_h(r,e),e.addEventListener("transitionend",t=>{t.propertyName==="height"&&r.cleanUpTransition()})}class SC extends Cu{constructor(e,t){super(e,t),this.emitter_=new vr,this.controller.foldable.value("expanded").emitter.on("change",n=>{this.emitter_.emit("fold",new Xx(this,n.sender.rawValue))}),this.rackApi_.on("change",n=>{this.emitter_.emit("change",n)})}get expanded(){return this.controller.foldable.get("expanded")}set expanded(e){this.controller.foldable.set("expanded",e)}get title(){return this.controller.props.get("title")}set title(e){this.controller.props.set("title",e)}get children(){return this.rackApi_.children}addBinding(e,t,n){return this.rackApi_.addBinding(e,t,n)}addFolder(e){return this.rackApi_.addFolder(e)}addButton(e){return this.rackApi_.addButton(e)}addTab(e){return this.rackApi_.addTab(e)}add(e,t){return this.rackApi_.add(e,t)}remove(e){this.rackApi_.remove(e)}addBlade(e){return this.rackApi_.addBlade(e)}on(e,t){const n=t.bind(this);return this.emitter_.on(e,i=>{n(i)},{key:t}),this}off(e,t){return this.emitter_.off(e,t),this}}const bf=Qe("cnt");class TC{constructor(e,t){var n;this.className_=Qe((n=t.viewName)!==null&&n!==void 0?n:"fld"),this.element=e.createElement("div"),this.element.classList.add(this.className_(),bf()),t.viewProps.bindClassModifiers(this.element),this.foldable_=t.foldable,this.foldable_.bindExpandedClass(this.element,this.className_(void 0,"expanded")),jr(this.foldable_,"completed",Ni(this.element,this.className_(void 0,"cpl")));const i=e.createElement("button");i.classList.add(this.className_("b")),jr(t.props,"title",x=>{vt(x)?this.element.classList.add(this.className_(void 0,"not")):this.element.classList.remove(this.className_(void 0,"not"))}),t.viewProps.bindDisabled(i),this.element.appendChild(i),this.buttonElement=i;const s=e.createElement("div");s.classList.add(this.className_("i")),this.element.appendChild(s);const o=e.createElement("div");o.classList.add(this.className_("t")),xu(t.props.value("title"),o),this.buttonElement.appendChild(o),this.titleElement=o;const l=e.createElement("div");l.classList.add(this.className_("m")),this.buttonElement.appendChild(l);const y=e.createElement("div");y.classList.add(this.className_("c")),this.element.appendChild(y),this.containerElement=y}}class wh extends Eu{constructor(e,t){var n;const i=Fs.create((n=t.expanded)!==null&&n!==void 0?n:!0),s=new TC(e,{foldable:i,props:t.props,viewName:t.root?"rot":void 0,viewProps:t.viewProps});super(Object.assign(Object.assign({},t),{rackController:new Pu({blade:t.blade,element:s.containerElement,root:t.root,viewProps:t.viewProps}),view:s})),this.onTitleClick_=this.onTitleClick_.bind(this),this.props=t.props,this.foldable=i,Au(this.foldable,this.view.containerElement),this.rackController.rack.emitter.on("add",()=>{this.foldable.cleanUpTransition()}),this.rackController.rack.emitter.on("remove",()=>{this.foldable.cleanUpTransition()}),this.view.buttonElement.addEventListener("click",this.onTitleClick_)}get document(){return this.view.element.ownerDocument}importState(e){return zr(e,t=>super.importState(t),t=>({expanded:t.required.boolean,title:t.optional.string}),t=>(this.foldable.set("expanded",t.expanded),this.props.set("title",t.title),!0))}exportState(){return Hr(()=>super.exportState(),{expanded:this.foldable.get("expanded"),title:this.props.get("title")})}onTitleClick_(){this.foldable.set("expanded",!this.foldable.get("expanded"))}}Jt({id:"folder",type:"blade",accept(r){const e=Xt(r,t=>({title:t.required.string,view:t.required.constant("folder"),expanded:t.optional.boolean}));return e?{params:e}:null},controller(r){return new wh(r.document,{blade:r.blade,expanded:r.params.expanded,props:Ze.fromObject({title:r.params.title}),viewProps:r.viewProps})},api(r){return r.controller instanceof wh?new SC(r.controller,r.pool):null}});const kC=Qe("");function gh(r,e){return Ni(r,kC(void 0,e))}class $s extends Ze{constructor(e){var t;super(e),this.onDisabledChange_=this.onDisabledChange_.bind(this),this.onParentChange_=this.onParentChange_.bind(this),this.onParentGlobalDisabledChange_=this.onParentGlobalDisabledChange_.bind(this),[this.globalDisabled_,this.setGlobalDisabled_]=bx(jt(this.getGlobalDisabled_())),this.value("disabled").emitter.on("change",this.onDisabledChange_),this.value("parent").emitter.on("change",this.onParentChange_),(t=this.get("parent"))===null||t===void 0||t.globalDisabled.emitter.on("change",this.onParentGlobalDisabledChange_)}static create(e){var t,n,i;const s=e??{};return new $s(Ze.createCore({disabled:(t=s.disabled)!==null&&t!==void 0?t:!1,disposed:!1,hidden:(n=s.hidden)!==null&&n!==void 0?n:!1,parent:(i=s.parent)!==null&&i!==void 0?i:null}))}get globalDisabled(){return this.globalDisabled_}bindClassModifiers(e){an(this.globalDisabled_,gh(e,"disabled")),jr(this,"hidden",gh(e,"hidden"))}bindDisabled(e){an(this.globalDisabled_,t=>{e.disabled=t})}bindTabIndex(e){an(this.globalDisabled_,t=>{e.tabIndex=t?-1:0})}handleDispose(e){this.value("disposed").emitter.on("change",t=>{t&&e()})}importState(e){this.set("disabled",e.disabled),this.set("hidden",e.hidden)}exportState(){return{disabled:this.get("disabled"),hidden:this.get("hidden")}}getGlobalDisabled_(){const e=this.get("parent");return(e?e.globalDisabled.rawValue:!1)||this.get("disabled")}updateGlobalDisabled_(){this.setGlobalDisabled_(this.getGlobalDisabled_())}onDisabledChange_(){this.updateGlobalDisabled_()}onParentGlobalDisabledChange_(){this.updateGlobalDisabled_()}onParentChange_(e){var t;const n=e.previousRawValue;n?.globalDisabled.emitter.off("change",this.onParentGlobalDisabledChange_),(t=this.get("parent"))===null||t===void 0||t.globalDisabled.emitter.on("change",this.onParentGlobalDisabledChange_),this.updateGlobalDisabled_()}}const yh=Qe("tbp");class LC{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(yh()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("div");n.classList.add(yh("c")),this.element.appendChild(n),this.containerElement=n}}const ds=Qe("tbi");class VC{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(ds()),t.viewProps.bindClassModifiers(this.element),jr(t.props,"selected",s=>{s?this.element.classList.add(ds(void 0,"sel")):this.element.classList.remove(ds(void 0,"sel"))});const n=e.createElement("button");n.classList.add(ds("b")),t.viewProps.bindDisabled(n),this.element.appendChild(n),this.buttonElement=n;const i=e.createElement("div");i.classList.add(ds("t")),xu(t.props.value("title"),i),this.buttonElement.appendChild(i),this.titleElement=i}}class OC{constructor(e,t){this.emitter=new vr,this.onClick_=this.onClick_.bind(this),this.props=t.props,this.viewProps=t.viewProps,this.view=new VC(e,{props:t.props,viewProps:t.viewProps}),this.view.buttonElement.addEventListener("click",this.onClick_)}onClick_(){this.emitter.emit("click",{sender:this})}}class Ml extends Eu{constructor(e,t){const n=new LC(e,{viewProps:t.viewProps});super(Object.assign(Object.assign({},t),{rackController:new Pu({blade:t.blade,element:n.containerElement,viewProps:t.viewProps}),view:n})),this.onItemClick_=this.onItemClick_.bind(this),this.ic_=new OC(e,{props:t.itemProps,viewProps:$s.create()}),this.ic_.emitter.on("click",this.onItemClick_),this.props=t.props,jr(this.props,"selected",i=>{this.itemController.props.set("selected",i),this.viewProps.set("hidden",!i)})}get itemController(){return this.ic_}importState(e){return zr(e,t=>super.importState(t),t=>({selected:t.required.boolean,title:t.required.string}),t=>(this.ic_.props.set("selected",t.selected),this.ic_.props.set("title",t.title),!0))}exportState(){return Hr(()=>super.exportState(),{selected:this.ic_.props.get("selected"),title:this.ic_.props.get("title")})}onItemClick_(){this.props.set("selected",!0)}}class RC extends Cu{constructor(e,t){super(e,t),this.emitter_=new vr,this.onSelect_=this.onSelect_.bind(this),this.pool_=t,this.rackApi_.on("change",n=>{this.emitter_.emit("change",n)}),this.controller.tab.selectedIndex.emitter.on("change",this.onSelect_)}get pages(){return this.rackApi_.children}addPage(e){const t=this.controller.view.element.ownerDocument,n=new Ml(t,{blade:vf(),itemProps:Ze.fromObject({selected:!1,title:e.title}),props:Ze.fromObject({selected:!1}),viewProps:$s.create()}),i=this.pool_.createApi(n);return this.rackApi_.add(i,e.index)}removePage(e){this.rackApi_.remove(this.rackApi_.children[e])}on(e,t){const n=t.bind(this);return this.emitter_.on(e,i=>{n(i)},{key:t}),this}off(e,t){return this.emitter_.off(e,t),this}onSelect_(e){this.emitter_.emit("select",new Yx(this,e.rawValue))}}class DC extends Cu{get title(){var e;return(e=this.controller.itemController.props.get("title"))!==null&&e!==void 0?e:""}set title(e){this.controller.itemController.props.set("title",e)}get selected(){return this.controller.props.get("selected")}set selected(e){this.controller.props.set("selected",e)}get children(){return this.rackApi_.children}addButton(e){return this.rackApi_.addButton(e)}addFolder(e){return this.rackApi_.addFolder(e)}addTab(e){return this.rackApi_.addTab(e)}add(e,t){this.rackApi_.add(e,t)}remove(e){this.rackApi_.remove(e)}addBinding(e,t,n){return this.rackApi_.addBinding(e,t,n)}addBlade(e){return this.rackApi_.addBlade(e)}}const xh=-1;class MC{constructor(){this.onItemSelectedChange_=this.onItemSelectedChange_.bind(this),this.empty=jt(!0),this.selectedIndex=jt(xh),this.items_=[]}add(e,t){const n=t??this.items_.length;this.items_.splice(n,0,e),e.emitter.on("change",this.onItemSelectedChange_),this.keepSelection_()}remove(e){const t=this.items_.indexOf(e);t<0||(this.items_.splice(t,1),e.emitter.off("change",this.onItemSelectedChange_),this.keepSelection_())}keepSelection_(){if(this.items_.length===0){this.selectedIndex.rawValue=xh,this.empty.rawValue=!0;return}const e=this.items_.findIndex(t=>t.rawValue);e<0?(this.items_.forEach((t,n)=>{t.rawValue=n===0}),this.selectedIndex.rawValue=0):(this.items_.forEach((t,n)=>{t.rawValue=n===e}),this.selectedIndex.rawValue=e),this.empty.rawValue=!1}onItemSelectedChange_(e){if(e.rawValue){const t=this.items_.findIndex(n=>n===e.sender);this.items_.forEach((n,i)=>{n.rawValue=i===t}),this.selectedIndex.rawValue=t}else this.keepSelection_()}}const hs=Qe("tab");class IC{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(hs(),bf()),t.viewProps.bindClassModifiers(this.element),an(t.empty,Ni(this.element,hs(void 0,"nop")));const n=e.createElement("div");n.classList.add(hs("t")),this.element.appendChild(n),this.itemsElement=n;const i=e.createElement("div");i.classList.add(hs("i")),this.element.appendChild(i);const s=e.createElement("div");s.classList.add(hs("c")),this.element.appendChild(s),this.contentsElement=s}}class Ch extends Eu{constructor(e,t){const n=new MC,i=new IC(e,{empty:n.empty,viewProps:t.viewProps});super({blade:t.blade,rackController:new Pu({blade:t.blade,element:i.contentsElement,viewProps:t.viewProps}),view:i}),this.onRackAdd_=this.onRackAdd_.bind(this),this.onRackRemove_=this.onRackRemove_.bind(this);const s=this.rackController.rack;s.emitter.on("add",this.onRackAdd_),s.emitter.on("remove",this.onRackRemove_),this.tab=n}add(e,t){this.rackController.rack.add(e,t)}remove(e){this.rackController.rack.remove(this.rackController.rack.children[e])}onRackAdd_(e){if(!e.root)return;const t=e.bladeController;hf(this.view.itemsElement,t.itemController.view.element,e.index),t.itemController.viewProps.set("parent",this.viewProps),this.tab.add(t.props.value("selected"))}onRackRemove_(e){if(!e.root)return;const t=e.bladeController;yu(t.itemController.view.element),t.itemController.viewProps.set("parent",null),this.tab.remove(t.props.value("selected"))}}Jt({id:"tab",type:"blade",accept(r){const e=Xt(r,t=>({pages:t.required.array(t.required.object({title:t.required.string})),view:t.required.constant("tab")}));return!e||e.pages.length===0?null:{params:e}},controller(r){const e=new Ch(r.document,{blade:r.blade,viewProps:r.viewProps});return r.params.pages.forEach(t=>{const n=new Ml(r.document,{blade:vf(),itemProps:Ze.fromObject({selected:!1,title:t.title}),props:Ze.fromObject({selected:!1}),viewProps:$s.create()});e.add(n)}),e},api(r){return r.controller instanceof Ch?new RC(r.controller,r.pool):r.controller instanceof Ml?new DC(r.controller,r.pool):null}});class Su extends wu{get options(){return this.controller.valueController.props.get("options")}set options(e){this.controller.valueController.props.set("options",e)}}class Bs{constructor(e){this.constraints=e}constrain(e){return this.constraints.reduce((t,n)=>n.constrain(t),e)}}function ja(r,e){if(r instanceof e)return r;if(r instanceof Bs){const t=r.constraints.reduce((n,i)=>n||(i instanceof e?i:null),null);if(t)return t}return null}class eo{constructor(e){this.values=Ze.fromObject({options:e})}constrain(e){const t=this.values.get("options");return t.length===0||t.filter(i=>i.value===e).length>0?e:t[0].value}}function to(r){var e;const t=Rl;if(Array.isArray(r))return(e=Xt({items:r},n=>({items:n.required.array(n.required.object({text:n.required.string,value:n.required.raw}))})))===null||e===void 0?void 0:e.items;if(typeof r=="object")return t.required.raw(r).value}function _f(r){if(Array.isArray(r))return r;const e=[];return Object.keys(r).forEach(t=>{e.push({text:t,value:r[t]})}),e}function Tu(r){return vt(r)?null:new eo(_f(r))}const ml=Qe("lst");class FC{constructor(e,t){this.onValueChange_=this.onValueChange_.bind(this),this.props_=t.props,this.element=e.createElement("div"),this.element.classList.add(ml()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("select");n.classList.add(ml("s")),t.viewProps.bindDisabled(n),this.element.appendChild(n),this.selectElement=n;const i=e.createElement("div");i.classList.add(ml("m")),i.appendChild(Ja(e,"dropdown")),this.element.appendChild(i),t.value.emitter.on("change",this.onValueChange_),this.value_=t.value,jr(this.props_,"options",s=>{pf(this.selectElement),s.forEach(o=>{const l=e.createElement("option");l.textContent=o.text,this.selectElement.appendChild(l)}),this.update_()})}update_(){const e=this.props_.get("options").map(t=>t.value);this.selectElement.selectedIndex=e.indexOf(this.value_.rawValue)}onValueChange_(){this.update_()}}class Di{constructor(e,t){this.onSelectChange_=this.onSelectChange_.bind(this),this.props=t.props,this.value=t.value,this.viewProps=t.viewProps,this.view=new FC(e,{props:this.props,value:this.value,viewProps:this.viewProps}),this.view.selectElement.addEventListener("change",this.onSelectChange_)}onSelectChange_(e){const t=e.currentTarget;this.value.rawValue=this.props.get("options")[t.selectedIndex].value}importProps(e){return zr(e,null,t=>({options:t.required.custom(to)}),t=>(this.props.set("options",_f(t.options)),!0))}exportProps(){return Hr(null,{options:this.props.get("options")})}}const Eh=Qe("pop");class $C{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(Eh()),t.viewProps.bindClassModifiers(this.element),an(t.shows,Ni(this.element,Eh(void 0,"v")))}}class wf{constructor(e,t){this.shows=jt(!1),this.viewProps=t.viewProps,this.view=new $C(e,{shows:this.shows,viewProps:this.viewProps})}}const Ph=Qe("txt");class BC{constructor(e,t){this.onChange_=this.onChange_.bind(this),this.element=e.createElement("div"),this.element.classList.add(Ph()),t.viewProps.bindClassModifiers(this.element),this.props_=t.props,this.props_.emitter.on("change",this.onChange_);const n=e.createElement("input");n.classList.add(Ph("i")),n.type="text",t.viewProps.bindDisabled(n),this.element.appendChild(n),this.inputElement=n,t.value.emitter.on("change",this.onChange_),this.value_=t.value,this.refresh()}refresh(){const e=this.props_.get("formatter");this.inputElement.value=e(this.value_.rawValue)}onChange_(){this.refresh()}}class ku{constructor(e,t){this.onInputChange_=this.onInputChange_.bind(this),this.parser_=t.parser,this.props=t.props,this.value=t.value,this.viewProps=t.viewProps,this.view=new BC(e,{props:t.props,value:this.value,viewProps:this.viewProps}),this.view.inputElement.addEventListener("change",this.onInputChange_)}onInputChange_(e){const n=e.currentTarget.value,i=this.parser_(n);vt(i)||(this.value.rawValue=i),this.view.refresh()}}function NC(r){return String(r)}function gf(r){return r==="false"?!1:!!r}function Ah(r){return NC(r)}function GC(r){return e=>r.reduce((t,n)=>t!==null?t:n(e),null)}const jC=ur(0);function Ua(r){return jC(r)+"%"}function yf(r){return String(r)}function Il(r){return r}function Gi({primary:r,secondary:e,forward:t,backward:n}){let i=!1;function s(o){i||(i=!0,o(),i=!1)}r.emitter.on("change",o=>{s(()=>{e.setRawValue(t(r.rawValue,e.rawValue),o.options)})}),e.emitter.on("change",o=>{s(()=>{r.setRawValue(n(r.rawValue,e.rawValue),o.options)}),s(()=>{e.setRawValue(t(r.rawValue,e.rawValue),o.options)})}),s(()=>{e.setRawValue(t(r.rawValue,e.rawValue),{forceEmit:!1,last:!0})})}function or(r,e){const t=r*(e.altKey?.1:1)*(e.shiftKey?10:1);return e.upKey?+t:e.downKey?-t:0}function As(r){return{altKey:r.altKey,downKey:r.key==="ArrowDown",shiftKey:r.shiftKey,upKey:r.key==="ArrowUp"}}function un(r){return{altKey:r.altKey,downKey:r.key==="ArrowLeft",shiftKey:r.shiftKey,upKey:r.key==="ArrowRight"}}function UC(r){return r==="ArrowUp"||r==="ArrowDown"}function xf(r){return UC(r)||r==="ArrowLeft"||r==="ArrowRight"}function vl(r,e){var t,n;const i=e.ownerDocument.defaultView,s=e.getBoundingClientRect();return{x:r.pageX-(((t=i&&i.scrollX)!==null&&t!==void 0?t:0)+s.left),y:r.pageY-(((n=i&&i.scrollY)!==null&&n!==void 0?n:0)+s.top)}}class oi{constructor(e){this.lastTouch_=null,this.onDocumentMouseMove_=this.onDocumentMouseMove_.bind(this),this.onDocumentMouseUp_=this.onDocumentMouseUp_.bind(this),this.onMouseDown_=this.onMouseDown_.bind(this),this.onTouchEnd_=this.onTouchEnd_.bind(this),this.onTouchMove_=this.onTouchMove_.bind(this),this.onTouchStart_=this.onTouchStart_.bind(this),this.elem_=e,this.emitter=new vr,e.addEventListener("touchstart",this.onTouchStart_,{passive:!1}),e.addEventListener("touchmove",this.onTouchMove_,{passive:!0}),e.addEventListener("touchend",this.onTouchEnd_),e.addEventListener("mousedown",this.onMouseDown_)}computePosition_(e){const t=this.elem_.getBoundingClientRect();return{bounds:{width:t.width,height:t.height},point:e?{x:e.x,y:e.y}:null}}onMouseDown_(e){var t;e.preventDefault(),(t=e.currentTarget)===null||t===void 0||t.focus();const n=this.elem_.ownerDocument;n.addEventListener("mousemove",this.onDocumentMouseMove_),n.addEventListener("mouseup",this.onDocumentMouseUp_),this.emitter.emit("down",{altKey:e.altKey,data:this.computePosition_(vl(e,this.elem_)),sender:this,shiftKey:e.shiftKey})}onDocumentMouseMove_(e){this.emitter.emit("move",{altKey:e.altKey,data:this.computePosition_(vl(e,this.elem_)),sender:this,shiftKey:e.shiftKey})}onDocumentMouseUp_(e){const t=this.elem_.ownerDocument;t.removeEventListener("mousemove",this.onDocumentMouseMove_),t.removeEventListener("mouseup",this.onDocumentMouseUp_),this.emitter.emit("up",{altKey:e.altKey,data:this.computePosition_(vl(e,this.elem_)),sender:this,shiftKey:e.shiftKey})}onTouchStart_(e){e.preventDefault();const t=e.targetTouches.item(0),n=this.elem_.getBoundingClientRect();this.emitter.emit("down",{altKey:e.altKey,data:this.computePosition_(t?{x:t.clientX-n.left,y:t.clientY-n.top}:void 0),sender:this,shiftKey:e.shiftKey}),this.lastTouch_=t}onTouchMove_(e){const t=e.targetTouches.item(0),n=this.elem_.getBoundingClientRect();this.emitter.emit("move",{altKey:e.altKey,data:this.computePosition_(t?{x:t.clientX-n.left,y:t.clientY-n.top}:void 0),sender:this,shiftKey:e.shiftKey}),this.lastTouch_=t}onTouchEnd_(e){var t;const n=(t=e.targetTouches.item(0))!==null&&t!==void 0?t:this.lastTouch_,i=this.elem_.getBoundingClientRect();this.emitter.emit("up",{altKey:e.altKey,data:this.computePosition_(n?{x:n.clientX-i.left,y:n.clientY-i.top}:void 0),sender:this,shiftKey:e.shiftKey})}}const Cr=Qe("txt");class zC{constructor(e,t){this.onChange_=this.onChange_.bind(this),this.props_=t.props,this.props_.emitter.on("change",this.onChange_),this.element=e.createElement("div"),this.element.classList.add(Cr(),Cr(void 0,"num")),t.arrayPosition&&this.element.classList.add(Cr(void 0,t.arrayPosition)),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("input");n.classList.add(Cr("i")),n.type="text",t.viewProps.bindDisabled(n),this.element.appendChild(n),this.inputElement=n,this.onDraggingChange_=this.onDraggingChange_.bind(this),this.dragging_=t.dragging,this.dragging_.emitter.on("change",this.onDraggingChange_),this.element.classList.add(Cr()),this.inputElement.classList.add(Cr("i"));const i=e.createElement("div");i.classList.add(Cr("k")),this.element.appendChild(i),this.knobElement=i;const s=e.createElementNS(Br,"svg");s.classList.add(Cr("g")),this.knobElement.appendChild(s);const o=e.createElementNS(Br,"path");o.classList.add(Cr("gb")),s.appendChild(o),this.guideBodyElem_=o;const l=e.createElementNS(Br,"path");l.classList.add(Cr("gh")),s.appendChild(l),this.guideHeadElem_=l;const y=e.createElement("div");y.classList.add(Qe("tt")()),this.knobElement.appendChild(y),this.tooltipElem_=y,t.value.emitter.on("change",this.onChange_),this.value=t.value,this.refresh()}onDraggingChange_(e){if(e.rawValue===null){this.element.classList.remove(Cr(void 0,"drg"));return}this.element.classList.add(Cr(void 0,"drg"));const t=e.rawValue/this.props_.get("pointerScale"),n=t+(t>0?-1:t<0?1:0),i=Dt(-n,-4,4);this.guideHeadElem_.setAttributeNS(null,"d",[`M ${n+i},0 L${n},4 L${n+i},8`,`M ${t},-1 L${t},9`].join(" ")),this.guideBodyElem_.setAttributeNS(null,"d",`M 0,4 L${t},4`);const s=this.props_.get("formatter");this.tooltipElem_.textContent=s(this.value.rawValue),this.tooltipElem_.style.left=`${t}px`}refresh(){const e=this.props_.get("formatter");this.inputElement.value=e(this.value.rawValue)}onChange_(){this.refresh()}}class Ns{constructor(e,t){var n;this.originRawValue_=0,this.onInputChange_=this.onInputChange_.bind(this),this.onInputKeyDown_=this.onInputKeyDown_.bind(this),this.onInputKeyUp_=this.onInputKeyUp_.bind(this),this.onPointerDown_=this.onPointerDown_.bind(this),this.onPointerMove_=this.onPointerMove_.bind(this),this.onPointerUp_=this.onPointerUp_.bind(this),this.parser_=t.parser,this.props=t.props,this.sliderProps_=(n=t.sliderProps)!==null&&n!==void 0?n:null,this.value=t.value,this.viewProps=t.viewProps,this.dragging_=jt(null),this.view=new zC(e,{arrayPosition:t.arrayPosition,dragging:this.dragging_,props:this.props,value:this.value,viewProps:this.viewProps}),this.view.inputElement.addEventListener("change",this.onInputChange_),this.view.inputElement.addEventListener("keydown",this.onInputKeyDown_),this.view.inputElement.addEventListener("keyup",this.onInputKeyUp_);const i=new oi(this.view.knobElement);i.emitter.on("down",this.onPointerDown_),i.emitter.on("move",this.onPointerMove_),i.emitter.on("up",this.onPointerUp_)}constrainValue_(e){var t,n;const i=(t=this.sliderProps_)===null||t===void 0?void 0:t.get("min"),s=(n=this.sliderProps_)===null||n===void 0?void 0:n.get("max");let o=e;return i!==void 0&&(o=Math.max(o,i)),s!==void 0&&(o=Math.min(o,s)),o}onInputChange_(e){const n=e.currentTarget.value,i=this.parser_(n);vt(i)||(this.value.rawValue=this.constrainValue_(i)),this.view.refresh()}onInputKeyDown_(e){const t=or(this.props.get("keyScale"),As(e));t!==0&&this.value.setRawValue(this.constrainValue_(this.value.rawValue+t),{forceEmit:!1,last:!1})}onInputKeyUp_(e){or(this.props.get("keyScale"),As(e))!==0&&this.value.setRawValue(this.value.rawValue,{forceEmit:!0,last:!0})}onPointerDown_(){this.originRawValue_=this.value.rawValue,this.dragging_.rawValue=0}computeDraggingValue_(e){if(!e.point)return null;const t=e.point.x-e.bounds.width/2;return this.constrainValue_(this.originRawValue_+t*this.props.get("pointerScale"))}onPointerMove_(e){const t=this.computeDraggingValue_(e.data);t!==null&&(this.value.setRawValue(t,{forceEmit:!1,last:!1}),this.dragging_.rawValue=this.value.rawValue-this.originRawValue_)}onPointerUp_(e){const t=this.computeDraggingValue_(e.data);t!==null&&(this.value.setRawValue(t,{forceEmit:!0,last:!0}),this.dragging_.rawValue=null)}}const bl=Qe("sld");class HC{constructor(e,t){this.onChange_=this.onChange_.bind(this),this.props_=t.props,this.props_.emitter.on("change",this.onChange_),this.element=e.createElement("div"),this.element.classList.add(bl()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("div");n.classList.add(bl("t")),t.viewProps.bindTabIndex(n),this.element.appendChild(n),this.trackElement=n;const i=e.createElement("div");i.classList.add(bl("k")),this.trackElement.appendChild(i),this.knobElement=i,t.value.emitter.on("change",this.onChange_),this.value=t.value,this.update_()}update_(){const e=Dt(tt(this.value.rawValue,this.props_.get("min"),this.props_.get("max"),0,100),0,100);this.knobElement.style.width=`${e}%`}onChange_(){this.update_()}}class KC{constructor(e,t){this.onKeyDown_=this.onKeyDown_.bind(this),this.onKeyUp_=this.onKeyUp_.bind(this),this.onPointerDownOrMove_=this.onPointerDownOrMove_.bind(this),this.onPointerUp_=this.onPointerUp_.bind(this),this.value=t.value,this.viewProps=t.viewProps,this.props=t.props,this.view=new HC(e,{props:this.props,value:this.value,viewProps:this.viewProps}),this.ptHandler_=new oi(this.view.trackElement),this.ptHandler_.emitter.on("down",this.onPointerDownOrMove_),this.ptHandler_.emitter.on("move",this.onPointerDownOrMove_),this.ptHandler_.emitter.on("up",this.onPointerUp_),this.view.trackElement.addEventListener("keydown",this.onKeyDown_),this.view.trackElement.addEventListener("keyup",this.onKeyUp_)}handlePointerEvent_(e,t){e.point&&this.value.setRawValue(tt(Dt(e.point.x,0,e.bounds.width),0,e.bounds.width,this.props.get("min"),this.props.get("max")),t)}onPointerDownOrMove_(e){this.handlePointerEvent_(e.data,{forceEmit:!1,last:!1})}onPointerUp_(e){this.handlePointerEvent_(e.data,{forceEmit:!0,last:!0})}onKeyDown_(e){const t=or(this.props.get("keyScale"),un(e));t!==0&&this.value.setRawValue(this.value.rawValue+t,{forceEmit:!1,last:!1})}onKeyUp_(e){or(this.props.get("keyScale"),un(e))!==0&&this.value.setRawValue(this.value.rawValue,{forceEmit:!0,last:!0})}}const _l=Qe("sldtxt");class qC{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(_l());const n=e.createElement("div");n.classList.add(_l("s")),this.sliderView_=t.sliderView,n.appendChild(this.sliderView_.element),this.element.appendChild(n);const i=e.createElement("div");i.classList.add(_l("t")),this.textView_=t.textView,i.appendChild(this.textView_.element),this.element.appendChild(i)}}class Sh{constructor(e,t){this.value=t.value,this.viewProps=t.viewProps,this.sliderC_=new KC(e,{props:t.sliderProps,value:t.value,viewProps:this.viewProps}),this.textC_=new Ns(e,{parser:t.parser,props:t.textProps,sliderProps:t.sliderProps,value:t.value,viewProps:t.viewProps}),this.view=new qC(e,{sliderView:this.sliderC_.view,textView:this.textC_.view})}get sliderController(){return this.sliderC_}get textController(){return this.textC_}importProps(e){return zr(e,null,t=>({max:t.required.number,min:t.required.number}),t=>{const n=this.sliderC_.props;return n.set("max",t.max),n.set("min",t.min),!0})}exportProps(){const e=this.sliderC_.props;return Hr(null,{max:e.get("max"),min:e.get("min")})}}function XC(r){return{sliderProps:new Ze({keyScale:r.keyScale,max:r.max,min:r.min}),textProps:new Ze({formatter:jt(r.formatter),keyScale:r.keyScale,pointerScale:jt(r.pointerScale)})}}const YC={containerUnitSize:"cnt-usz"};function Cf(r){return`--${YC[r]}`}function Ss(r){return cf(r)}function Tn(r){if(Ol(r))return Xt(r,Ss)}function nn(r,e){if(!r)return;const t=[],n=of(r,e);n&&t.push(n);const i=lf(r);return i&&t.push(i),new Bs(t)}function Ef(r){if(r==="inline"||r==="popup")return r}function Gs(r,e){r.write(e)}const Sa=Qe("ckb");class WC{constructor(e,t){this.onValueChange_=this.onValueChange_.bind(this),this.element=e.createElement("div"),this.element.classList.add(Sa()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("label");n.classList.add(Sa("l")),this.element.appendChild(n),this.labelElement=n;const i=e.createElement("input");i.classList.add(Sa("i")),i.type="checkbox",this.labelElement.appendChild(i),this.inputElement=i,t.viewProps.bindDisabled(this.inputElement);const s=e.createElement("div");s.classList.add(Sa("w")),this.labelElement.appendChild(s);const o=Ja(e,"check");s.appendChild(o),t.value.emitter.on("change",this.onValueChange_),this.value=t.value,this.update_()}update_(){this.inputElement.checked=this.value.rawValue}onValueChange_(){this.update_()}}class ZC{constructor(e,t){this.onInputChange_=this.onInputChange_.bind(this),this.onLabelMouseDown_=this.onLabelMouseDown_.bind(this),this.value=t.value,this.viewProps=t.viewProps,this.view=new WC(e,{value:this.value,viewProps:this.viewProps}),this.view.inputElement.addEventListener("change",this.onInputChange_),this.view.labelElement.addEventListener("mousedown",this.onLabelMouseDown_)}onInputChange_(e){const t=e.currentTarget;this.value.rawValue=t.checked,e.preventDefault(),e.stopPropagation()}onLabelMouseDown_(e){e.preventDefault()}}function QC(r){const e=[],t=Tu(r.options);return t&&e.push(t),new Bs(e)}Jt({id:"input-bool",type:"input",accept:(r,e)=>{if(typeof r!="boolean")return null;const t=Xt(e,n=>({options:n.optional.custom(to),readonly:n.optional.constant(!1)}));return t?{initialValue:r,params:t}:null},binding:{reader:r=>gf,constraint:r=>QC(r.params),writer:r=>Gs},controller:r=>{const e=r.document,t=r.value,n=r.constraint,i=n&&ja(n,eo);return i?new Di(e,{props:new Ze({options:i.values.value("options")}),value:t,viewProps:r.viewProps}):new ZC(e,{value:t,viewProps:r.viewProps})},api(r){return typeof r.controller.value.rawValue!="boolean"?null:r.controller.valueController instanceof Di?new Su(r.controller):null}});const Yn=Qe("col");class JC{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(Yn()),t.foldable.bindExpandedClass(this.element,Yn(void 0,"expanded")),jr(t.foldable,"completed",Ni(this.element,Yn(void 0,"cpl")));const n=e.createElement("div");n.classList.add(Yn("h")),this.element.appendChild(n);const i=e.createElement("div");i.classList.add(Yn("s")),n.appendChild(i),this.swatchElement=i;const s=e.createElement("div");if(s.classList.add(Yn("t")),n.appendChild(s),this.textElement=s,t.pickerLayout==="inline"){const o=e.createElement("div");o.classList.add(Yn("p")),this.element.appendChild(o),this.pickerElement=o}else this.pickerElement=null}}function eE(r,e,t){const n=Dt(r/255,0,1),i=Dt(e/255,0,1),s=Dt(t/255,0,1),o=Math.max(n,i,s),l=Math.min(n,i,s),y=o-l;let x=0,B=0;const U=(l+o)/2;return y!==0&&(B=y/(1-Math.abs(o+l-1)),n===o?x=(i-s)/y:i===o?x=2+(s-n)/y:x=4+(n-i)/y,x=x/6+(x<0?1:0)),[x*360,B*100,U*100]}function tE(r,e,t){const n=(r%360+360)%360,i=Dt(e/100,0,1),s=Dt(t/100,0,1),o=(1-Math.abs(2*s-1))*i,l=o*(1-Math.abs(n/60%2-1)),y=s-o/2;let x,B,U;return n>=0&&n<60?[x,B,U]=[o,l,0]:n>=60&&n<120?[x,B,U]=[l,o,0]:n>=120&&n<180?[x,B,U]=[0,o,l]:n>=180&&n<240?[x,B,U]=[0,l,o]:n>=240&&n<300?[x,B,U]=[l,0,o]:[x,B,U]=[o,0,l],[(x+y)*255,(B+y)*255,(U+y)*255]}function rE(r,e,t){const n=Dt(r/255,0,1),i=Dt(e/255,0,1),s=Dt(t/255,0,1),o=Math.max(n,i,s),l=Math.min(n,i,s),y=o-l;let x;y===0?x=0:o===n?x=60*(((i-s)/y%6+6)%6):o===i?x=60*((s-n)/y+2):x=60*((n-i)/y+4);const B=o===0?0:y/o,U=o;return[x,B*100,U*100]}function Pf(r,e,t){const n=sf(r,360),i=Dt(e/100,0,1),s=Dt(t/100,0,1),o=s*i,l=o*(1-Math.abs(n/60%2-1)),y=s-o;let x,B,U;return n>=0&&n<60?[x,B,U]=[o,l,0]:n>=60&&n<120?[x,B,U]=[l,o,0]:n>=120&&n<180?[x,B,U]=[0,o,l]:n>=180&&n<240?[x,B,U]=[0,l,o]:n>=240&&n<300?[x,B,U]=[l,0,o]:[x,B,U]=[o,0,l],[(x+y)*255,(B+y)*255,(U+y)*255]}function nE(r,e,t){const n=t+e*(100-Math.abs(2*t-100))/200;return[r,n!==0?e*(100-Math.abs(2*t-100))/n:0,t+e*(100-Math.abs(2*t-100))/200]}function iE(r,e,t){const n=100-Math.abs(t*(200-e)/100-100);return[r,n!==0?e*t/n:0,t*(200-e)/200]}function Ur(r){return[r[0],r[1],r[2]]}function ro(r,e){return[r[0],r[1],r[2],e]}const sE={hsl:{hsl:(r,e,t)=>[r,e,t],hsv:nE,rgb:tE},hsv:{hsl:iE,hsv:(r,e,t)=>[r,e,t],rgb:Pf},rgb:{hsl:eE,hsv:rE,rgb:(r,e,t)=>[r,e,t]}};function Mi(r,e){return[e==="float"?1:r==="rgb"?255:360,e==="float"?1:r==="rgb"?255:100,e==="float"?1:r==="rgb"?255:100]}function aE(r,e){return r===e?e:sf(r,e)}function Af(r,e,t){var n;const i=Mi(e,t);return[e==="rgb"?Dt(r[0],0,i[0]):aE(r[0],i[0]),Dt(r[1],0,i[1]),Dt(r[2],0,i[2]),Dt((n=r[3])!==null&&n!==void 0?n:1,0,1)]}function Th(r,e,t,n){const i=Mi(e,t),s=Mi(e,n);return r.map((o,l)=>o/i[l]*s[l])}function Sf(r,e,t){const n=Th(r,e.mode,e.type,"int"),i=sE[e.mode][t.mode](...n);return Th(i,t.mode,"int",t.type)}class Ye{static black(){return new Ye([0,0,0],"rgb")}constructor(e,t){this.type="int",this.mode=t,this.comps_=Af(e,t,this.type)}getComponents(e){return ro(Sf(Ur(this.comps_),{mode:this.mode,type:this.type},{mode:e??this.mode,type:this.type}),this.comps_[3])}toRgbaObject(){const e=this.getComponents("rgb");return{r:e[0],g:e[1],b:e[2],a:e[3]}}}const Cn=Qe("colp");class oE{constructor(e,t){this.alphaViews_=null,this.element=e.createElement("div"),this.element.classList.add(Cn()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("div");n.classList.add(Cn("hsv"));const i=e.createElement("div");i.classList.add(Cn("sv")),this.svPaletteView_=t.svPaletteView,i.appendChild(this.svPaletteView_.element),n.appendChild(i);const s=e.createElement("div");s.classList.add(Cn("h")),this.hPaletteView_=t.hPaletteView,s.appendChild(this.hPaletteView_.element),n.appendChild(s),this.element.appendChild(n);const o=e.createElement("div");if(o.classList.add(Cn("rgb")),this.textsView_=t.textsView,o.appendChild(this.textsView_.element),this.element.appendChild(o),t.alphaViews){this.alphaViews_={palette:t.alphaViews.palette,text:t.alphaViews.text};const l=e.createElement("div");l.classList.add(Cn("a"));const y=e.createElement("div");y.classList.add(Cn("ap")),y.appendChild(this.alphaViews_.palette.element),l.appendChild(y);const x=e.createElement("div");x.classList.add(Cn("at")),x.appendChild(this.alphaViews_.text.element),l.appendChild(x),this.element.appendChild(l)}}get allFocusableElements(){const e=[this.svPaletteView_.element,this.hPaletteView_.element,this.textsView_.modeSelectElement,...this.textsView_.inputViews.map(t=>t.inputElement)];return this.alphaViews_&&e.push(this.alphaViews_.palette.element,this.alphaViews_.text.inputElement),e}}function lE(r){return r==="int"?"int":r==="float"?"float":void 0}function Lu(r){return Xt(r,e=>({color:e.optional.object({alpha:e.optional.boolean,type:e.optional.custom(lE)}),expanded:e.optional.boolean,picker:e.optional.custom(Ef),readonly:e.optional.constant(!1)}))}function ni(r){return r?.1:1}function Tf(r){var e;return(e=r.color)===null||e===void 0?void 0:e.type}class Vu{constructor(e,t){this.type="float",this.mode=t,this.comps_=Af(e,t,this.type)}getComponents(e){return ro(Sf(Ur(this.comps_),{mode:this.mode,type:this.type},{mode:e??this.mode,type:this.type}),this.comps_[3])}toRgbaObject(){const e=this.getComponents("rgb");return{r:e[0],g:e[1],b:e[2],a:e[3]}}}const uE={int:(r,e)=>new Ye(r,e),float:(r,e)=>new Vu(r,e)};function Ou(r,e,t){return uE[t](r,e)}function cE(r){return r.type==="float"}function dE(r){return r.type==="int"}function hE(r){const e=r.getComponents(),t=Mi(r.mode,"int");return new Ye([Math.round(tt(e[0],0,1,0,t[0])),Math.round(tt(e[1],0,1,0,t[1])),Math.round(tt(e[2],0,1,0,t[2])),e[3]],r.mode)}function pE(r){const e=r.getComponents(),t=Mi(r.mode,"int");return new Vu([tt(e[0],0,t[0],0,1),tt(e[1],0,t[1],0,1),tt(e[2],0,t[2],0,1),e[3]],r.mode)}function Zt(r,e){if(r.type===e)return r;if(dE(r)&&e==="float")return pE(r);if(cE(r)&&e==="int")return hE(r);throw pr.shouldNeverHappen()}function fE(r,e){return r.alpha===e.alpha&&r.mode===e.mode&&r.notation===e.notation&&r.type===e.type}function Pr(r,e){const t=r.match(/^(.+)%$/);return Math.min(t?parseFloat(t[1])*.01*e:parseFloat(r),e)}const mE={deg:r=>r,grad:r=>r*360/400,rad:r=>r*360/(2*Math.PI),turn:r=>r*360};function kf(r){const e=r.match(/^([0-9.]+?)(deg|grad|rad|turn)$/);if(!e)return parseFloat(r);const t=parseFloat(e[1]),n=e[2];return mE[n](t)}function Lf(r){const e=r.match(/^rgb\(\s*([0-9A-Fa-f.]+%?)\s*,\s*([0-9A-Fa-f.]+%?)\s*,\s*([0-9A-Fa-f.]+%?)\s*\)$/);if(!e)return null;const t=[Pr(e[1],255),Pr(e[2],255),Pr(e[3],255)];return isNaN(t[0])||isNaN(t[1])||isNaN(t[2])?null:t}function vE(r){const e=Lf(r);return e?new Ye(e,"rgb"):null}function Vf(r){const e=r.match(/^rgba\(\s*([0-9A-Fa-f.]+%?)\s*,\s*([0-9A-Fa-f.]+%?)\s*,\s*([0-9A-Fa-f.]+%?)\s*,\s*([0-9A-Fa-f.]+%?)\s*\)$/);if(!e)return null;const t=[Pr(e[1],255),Pr(e[2],255),Pr(e[3],255),Pr(e[4],1)];return isNaN(t[0])||isNaN(t[1])||isNaN(t[2])||isNaN(t[3])?null:t}function bE(r){const e=Vf(r);return e?new Ye(e,"rgb"):null}function Of(r){const e=r.match(/^hsl\(\s*([0-9A-Fa-f.]+(?:deg|grad|rad|turn)?)\s*,\s*([0-9A-Fa-f.]+%?)\s*,\s*([0-9A-Fa-f.]+%?)\s*\)$/);if(!e)return null;const t=[kf(e[1]),Pr(e[2],100),Pr(e[3],100)];return isNaN(t[0])||isNaN(t[1])||isNaN(t[2])?null:t}function _E(r){const e=Of(r);return e?new Ye(e,"hsl"):null}function Rf(r){const e=r.match(/^hsla\(\s*([0-9A-Fa-f.]+(?:deg|grad|rad|turn)?)\s*,\s*([0-9A-Fa-f.]+%?)\s*,\s*([0-9A-Fa-f.]+%?)\s*,\s*([0-9A-Fa-f.]+%?)\s*\)$/);if(!e)return null;const t=[kf(e[1]),Pr(e[2],100),Pr(e[3],100),Pr(e[4],1)];return isNaN(t[0])||isNaN(t[1])||isNaN(t[2])||isNaN(t[3])?null:t}function wE(r){const e=Rf(r);return e?new Ye(e,"hsl"):null}function Df(r){const e=r.match(/^#([0-9A-Fa-f])([0-9A-Fa-f])([0-9A-Fa-f])$/);if(e)return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16)];const t=r.match(/^(?:#|0x)([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})$/);return t?[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)]:null}function gE(r){const e=Df(r);return e?new Ye(e,"rgb"):null}function Mf(r){const e=r.match(/^#([0-9A-Fa-f])([0-9A-Fa-f])([0-9A-Fa-f])([0-9A-Fa-f])$/);if(e)return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16),tt(parseInt(e[4]+e[4],16),0,255,0,1)];const t=r.match(/^(?:#|0x)?([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})$/);return t?[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16),tt(parseInt(t[4],16),0,255,0,1)]:null}function yE(r){const e=Mf(r);return e?new Ye(e,"rgb"):null}function If(r){const e=r.match(/^\{\s*r\s*:\s*([0-9A-Fa-f.]+%?)\s*,\s*g\s*:\s*([0-9A-Fa-f.]+%?)\s*,\s*b\s*:\s*([0-9A-Fa-f.]+%?)\s*\}$/);if(!e)return null;const t=[parseFloat(e[1]),parseFloat(e[2]),parseFloat(e[3])];return isNaN(t[0])||isNaN(t[1])||isNaN(t[2])?null:t}function xE(r){return e=>{const t=If(e);return t?Ou(t,"rgb",r):null}}function Ff(r){const e=r.match(/^\{\s*r\s*:\s*([0-9A-Fa-f.]+%?)\s*,\s*g\s*:\s*([0-9A-Fa-f.]+%?)\s*,\s*b\s*:\s*([0-9A-Fa-f.]+%?)\s*,\s*a\s*:\s*([0-9A-Fa-f.]+%?)\s*\}$/);if(!e)return null;const t=[parseFloat(e[1]),parseFloat(e[2]),parseFloat(e[3]),parseFloat(e[4])];return isNaN(t[0])||isNaN(t[1])||isNaN(t[2])||isNaN(t[3])?null:t}function CE(r){return e=>{const t=Ff(e);return t?Ou(t,"rgb",r):null}}const EE=[{parser:Df,result:{alpha:!1,mode:"rgb",notation:"hex"}},{parser:Mf,result:{alpha:!0,mode:"rgb",notation:"hex"}},{parser:Lf,result:{alpha:!1,mode:"rgb",notation:"func"}},{parser:Vf,result:{alpha:!0,mode:"rgb",notation:"func"}},{parser:Of,result:{alpha:!1,mode:"hsl",notation:"func"}},{parser:Rf,result:{alpha:!0,mode:"hsl",notation:"func"}},{parser:If,result:{alpha:!1,mode:"rgb",notation:"object"}},{parser:Ff,result:{alpha:!0,mode:"rgb",notation:"object"}}];function PE(r){return EE.reduce((e,{parser:t,result:n})=>e||(t(r)?n:null),null)}function AE(r,e="int"){const t=PE(r);return t?t.notation==="hex"&&e!=="float"?Object.assign(Object.assign({},t),{type:"int"}):t.notation==="func"?Object.assign(Object.assign({},t),{type:e}):null:null}function js(r){const e=[gE,yE,vE,bE,_E,wE];e.push(xE("int"),CE("int"));const t=GC(e);return n=>{const i=t(n);return i?Zt(i,r):null}}function SE(r){const e=js("int");if(typeof r!="string")return Ye.black();const t=e(r);return t??Ye.black()}function $f(r){const e=Dt(Math.floor(r),0,255).toString(16);return e.length===1?`0${e}`:e}function Ru(r,e="#"){const t=Ur(r.getComponents("rgb")).map($f).join("");return`${e}${t}`}function Du(r,e="#"){const t=r.getComponents("rgb"),n=[t[0],t[1],t[2],t[3]*255].map($f).join("");return`${e}${n}`}function Bf(r){const e=ur(0),t=Zt(r,"int");return`rgb(${Ur(t.getComponents("rgb")).map(i=>e(i)).join(", ")})`}function Ra(r){const e=ur(2),t=ur(0);return`rgba(${Zt(r,"int").getComponents("rgb").map((s,o)=>(o===3?e:t)(s)).join(", ")})`}function TE(r){const e=[ur(0),Ua,Ua],t=Zt(r,"int");return`hsl(${Ur(t.getComponents("hsl")).map((i,s)=>e[s](i)).join(", ")})`}function kE(r){const e=[ur(0),Ua,Ua,ur(2)];return`hsla(${Zt(r,"int").getComponents("hsl").map((i,s)=>e[s](i)).join(", ")})`}function Nf(r,e){const t=ur(e==="float"?2:0),n=["r","g","b"],i=Zt(r,e);return`{${Ur(i.getComponents("rgb")).map((o,l)=>`${n[l]}: ${t(o)}`).join(", ")}}`}function LE(r){return e=>Nf(e,r)}function Gf(r,e){const t=ur(2),n=ur(e==="float"?2:0),i=["r","g","b","a"];return`{${Zt(r,e).getComponents("rgb").map((l,y)=>{const x=y===3?t:n;return`${i[y]}: ${x(l)}`}).join(", ")}}`}function VE(r){return e=>Gf(e,r)}const OE=[{format:{alpha:!1,mode:"rgb",notation:"hex",type:"int"},stringifier:Ru},{format:{alpha:!0,mode:"rgb",notation:"hex",type:"int"},stringifier:Du},{format:{alpha:!1,mode:"rgb",notation:"func",type:"int"},stringifier:Bf},{format:{alpha:!0,mode:"rgb",notation:"func",type:"int"},stringifier:Ra},{format:{alpha:!1,mode:"hsl",notation:"func",type:"int"},stringifier:TE},{format:{alpha:!0,mode:"hsl",notation:"func",type:"int"},stringifier:kE},...["int","float"].reduce((r,e)=>[...r,{format:{alpha:!1,mode:"rgb",notation:"object",type:e},stringifier:LE(e)},{format:{alpha:!0,mode:"rgb",notation:"object",type:e},stringifier:VE(e)}],[])];function jf(r){return OE.reduce((e,t)=>e||(fE(t.format,r)?t.stringifier:null),null)}const ps=Qe("apl");class RE{constructor(e,t){this.onValueChange_=this.onValueChange_.bind(this),this.value=t.value,this.value.emitter.on("change",this.onValueChange_),this.element=e.createElement("div"),this.element.classList.add(ps()),t.viewProps.bindClassModifiers(this.element),t.viewProps.bindTabIndex(this.element);const n=e.createElement("div");n.classList.add(ps("b")),this.element.appendChild(n);const i=e.createElement("div");i.classList.add(ps("c")),n.appendChild(i),this.colorElem_=i;const s=e.createElement("div");s.classList.add(ps("m")),this.element.appendChild(s),this.markerElem_=s;const o=e.createElement("div");o.classList.add(ps("p")),this.markerElem_.appendChild(o),this.previewElem_=o,this.update_()}update_(){const e=this.value.rawValue,t=e.getComponents("rgb"),n=new Ye([t[0],t[1],t[2],0],"rgb"),i=new Ye([t[0],t[1],t[2],255],"rgb"),s=["to right",Ra(n),Ra(i)];this.colorElem_.style.background=`linear-gradient(${s.join(",")})`,this.previewElem_.style.backgroundColor=Ra(e);const o=tt(t[3],0,1,0,100);this.markerElem_.style.left=`${o}%`}onValueChange_(){this.update_()}}class DE{constructor(e,t){this.onKeyDown_=this.onKeyDown_.bind(this),this.onKeyUp_=this.onKeyUp_.bind(this),this.onPointerDown_=this.onPointerDown_.bind(this),this.onPointerMove_=this.onPointerMove_.bind(this),this.onPointerUp_=this.onPointerUp_.bind(this),this.value=t.value,this.viewProps=t.viewProps,this.view=new RE(e,{value:this.value,viewProps:this.viewProps}),this.ptHandler_=new oi(this.view.element),this.ptHandler_.emitter.on("down",this.onPointerDown_),this.ptHandler_.emitter.on("move",this.onPointerMove_),this.ptHandler_.emitter.on("up",this.onPointerUp_),this.view.element.addEventListener("keydown",this.onKeyDown_),this.view.element.addEventListener("keyup",this.onKeyUp_)}handlePointerEvent_(e,t){if(!e.point)return;const n=e.point.x/e.bounds.width,i=this.value.rawValue,[s,o,l]=i.getComponents("hsv");this.value.setRawValue(new Ye([s,o,l,n],"hsv"),t)}onPointerDown_(e){this.handlePointerEvent_(e.data,{forceEmit:!1,last:!1})}onPointerMove_(e){this.handlePointerEvent_(e.data,{forceEmit:!1,last:!1})}onPointerUp_(e){this.handlePointerEvent_(e.data,{forceEmit:!0,last:!0})}onKeyDown_(e){const t=or(ni(!0),un(e));if(t===0)return;const n=this.value.rawValue,[i,s,o,l]=n.getComponents("hsv");this.value.setRawValue(new Ye([i,s,o,l+t],"hsv"),{forceEmit:!1,last:!1})}onKeyUp_(e){or(ni(!0),un(e))!==0&&this.value.setRawValue(this.value.rawValue,{forceEmit:!0,last:!0})}}const Ai=Qe("coltxt");function ME(r){const e=r.createElement("select"),t=[{text:"RGB",value:"rgb"},{text:"HSL",value:"hsl"},{text:"HSV",value:"hsv"},{text:"HEX",value:"hex"}];return e.appendChild(t.reduce((n,i)=>{const s=r.createElement("option");return s.textContent=i.text,s.value=i.value,n.appendChild(s),n},r.createDocumentFragment())),e}class IE{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(Ai()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("div");n.classList.add(Ai("m")),this.modeElem_=ME(e),this.modeElem_.classList.add(Ai("ms")),n.appendChild(this.modeSelectElement),t.viewProps.bindDisabled(this.modeElem_);const i=e.createElement("div");i.classList.add(Ai("mm")),i.appendChild(Ja(e,"dropdown")),n.appendChild(i),this.element.appendChild(n);const s=e.createElement("div");s.classList.add(Ai("w")),this.element.appendChild(s),this.inputsElem_=s,this.inputViews_=t.inputViews,this.applyInputViews_(),an(t.mode,o=>{this.modeElem_.value=o})}get modeSelectElement(){return this.modeElem_}get inputViews(){return this.inputViews_}set inputViews(e){this.inputViews_=e,this.applyInputViews_()}applyInputViews_(){pf(this.inputsElem_);const e=this.element.ownerDocument;this.inputViews_.forEach(t=>{const n=e.createElement("div");n.classList.add(Ai("c")),n.appendChild(t.element),this.inputsElem_.appendChild(n)})}}function FE(r){return ur(r==="float"?2:0)}function $E(r,e,t){const n=Mi(r,e)[t];return new Za({min:0,max:n})}function BE(r,e,t){return new Ns(r,{arrayPosition:t===0?"fst":t===2?"lst":"mid",parser:e.parser,props:Ze.fromObject({formatter:FE(e.colorType),keyScale:ni(!1),pointerScale:e.colorType==="float"?.01:1}),value:jt(0,{constraint:$E(e.colorMode,e.colorType,t)}),viewProps:e.viewProps})}function NE(r,e){const t={colorMode:e.colorMode,colorType:e.colorType,parser:On,viewProps:e.viewProps};return[0,1,2].map(n=>{const i=BE(r,t,n);return Gi({primary:e.value,secondary:i.value,forward(s){return Zt(s,e.colorType).getComponents(e.colorMode)[n]},backward(s,o){const l=e.colorMode,x=Zt(s,e.colorType).getComponents(l);x[n]=o;const B=Ou(ro(Ur(x),x[3]),l,e.colorType);return Zt(B,"int")}}),i})}function GE(r,e){const t=new ku(r,{parser:js("int"),props:Ze.fromObject({formatter:Ru}),value:jt(Ye.black()),viewProps:e.viewProps});return Gi({primary:e.value,secondary:t.value,forward:n=>new Ye(Ur(n.getComponents()),n.mode),backward:(n,i)=>new Ye(ro(Ur(i.getComponents(n.mode)),n.getComponents()[3]),n.mode)}),[t]}function jE(r){return r!=="hex"}class UE{constructor(e,t){this.onModeSelectChange_=this.onModeSelectChange_.bind(this),this.colorType_=t.colorType,this.value=t.value,this.viewProps=t.viewProps,this.colorMode=jt(this.value.rawValue.mode),this.ccs_=this.createComponentControllers_(e),this.view=new IE(e,{mode:this.colorMode,inputViews:[this.ccs_[0].view,this.ccs_[1].view,this.ccs_[2].view],viewProps:this.viewProps}),this.view.modeSelectElement.addEventListener("change",this.onModeSelectChange_)}createComponentControllers_(e){const t=this.colorMode.rawValue;return jE(t)?NE(e,{colorMode:t,colorType:this.colorType_,value:this.value,viewProps:this.viewProps}):GE(e,{value:this.value,viewProps:this.viewProps})}onModeSelectChange_(e){const t=e.currentTarget;this.colorMode.rawValue=t.value,this.ccs_=this.createComponentControllers_(this.view.element.ownerDocument),this.view.inputViews=this.ccs_.map(n=>n.view)}}const wl=Qe("hpl");class zE{constructor(e,t){this.onValueChange_=this.onValueChange_.bind(this),this.value=t.value,this.value.emitter.on("change",this.onValueChange_),this.element=e.createElement("div"),this.element.classList.add(wl()),t.viewProps.bindClassModifiers(this.element),t.viewProps.bindTabIndex(this.element);const n=e.createElement("div");n.classList.add(wl("c")),this.element.appendChild(n);const i=e.createElement("div");i.classList.add(wl("m")),this.element.appendChild(i),this.markerElem_=i,this.update_()}update_(){const e=this.value.rawValue,[t]=e.getComponents("hsv");this.markerElem_.style.backgroundColor=Bf(new Ye([t,100,100],"hsv"));const n=tt(t,0,360,0,100);this.markerElem_.style.left=`${n}%`}onValueChange_(){this.update_()}}class HE{constructor(e,t){this.onKeyDown_=this.onKeyDown_.bind(this),this.onKeyUp_=this.onKeyUp_.bind(this),this.onPointerDown_=this.onPointerDown_.bind(this),this.onPointerMove_=this.onPointerMove_.bind(this),this.onPointerUp_=this.onPointerUp_.bind(this),this.value=t.value,this.viewProps=t.viewProps,this.view=new zE(e,{value:this.value,viewProps:this.viewProps}),this.ptHandler_=new oi(this.view.element),this.ptHandler_.emitter.on("down",this.onPointerDown_),this.ptHandler_.emitter.on("move",this.onPointerMove_),this.ptHandler_.emitter.on("up",this.onPointerUp_),this.view.element.addEventListener("keydown",this.onKeyDown_),this.view.element.addEventListener("keyup",this.onKeyUp_)}handlePointerEvent_(e,t){if(!e.point)return;const n=tt(Dt(e.point.x,0,e.bounds.width),0,e.bounds.width,0,360),i=this.value.rawValue,[,s,o,l]=i.getComponents("hsv");this.value.setRawValue(new Ye([n,s,o,l],"hsv"),t)}onPointerDown_(e){this.handlePointerEvent_(e.data,{forceEmit:!1,last:!1})}onPointerMove_(e){this.handlePointerEvent_(e.data,{forceEmit:!1,last:!1})}onPointerUp_(e){this.handlePointerEvent_(e.data,{forceEmit:!0,last:!0})}onKeyDown_(e){const t=or(ni(!1),un(e));if(t===0)return;const n=this.value.rawValue,[i,s,o,l]=n.getComponents("hsv");this.value.setRawValue(new Ye([i+t,s,o,l],"hsv"),{forceEmit:!1,last:!1})}onKeyUp_(e){or(ni(!1),un(e))!==0&&this.value.setRawValue(this.value.rawValue,{forceEmit:!0,last:!0})}}const gl=Qe("svp"),kh=64;class KE{constructor(e,t){this.onValueChange_=this.onValueChange_.bind(this),this.value=t.value,this.value.emitter.on("change",this.onValueChange_),this.element=e.createElement("div"),this.element.classList.add(gl()),t.viewProps.bindClassModifiers(this.element),t.viewProps.bindTabIndex(this.element);const n=e.createElement("canvas");n.height=kh,n.width=kh,n.classList.add(gl("c")),this.element.appendChild(n),this.canvasElement=n;const i=e.createElement("div");i.classList.add(gl("m")),this.element.appendChild(i),this.markerElem_=i,this.update_()}update_(){const e=rC(this.canvasElement);if(!e)return;const n=this.value.rawValue.getComponents("hsv"),i=this.canvasElement.width,s=this.canvasElement.height,o=e.getImageData(0,0,i,s),l=o.data;for(let B=0;Bn.getComponents()[3],backward:(n,i)=>{const s=n.getComponents();return s[3]=i,new Ye(s,n.mode)}}),this.textsC_=new UE(e,{colorType:t.colorType,value:this.value,viewProps:this.viewProps}),this.view=new oE(e,{alphaViews:this.alphaIcs_?{palette:this.alphaIcs_.palette.view,text:this.alphaIcs_.text.view}:null,hPaletteView:this.hPaletteC_.view,supportsAlpha:t.supportsAlpha,svPaletteView:this.svPaletteC_.view,textsView:this.textsC_.view,viewProps:this.viewProps})}get textsController(){return this.textsC_}}const yl=Qe("colsw");class YE{constructor(e,t){this.onValueChange_=this.onValueChange_.bind(this),t.value.emitter.on("change",this.onValueChange_),this.value=t.value,this.element=e.createElement("div"),this.element.classList.add(yl()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("div");n.classList.add(yl("sw")),this.element.appendChild(n),this.swatchElem_=n;const i=e.createElement("button");i.classList.add(yl("b")),t.viewProps.bindDisabled(i),this.element.appendChild(i),this.buttonElement=i,this.update_()}update_(){const e=this.value.rawValue;this.swatchElem_.style.backgroundColor=Du(e)}onValueChange_(){this.update_()}}class WE{constructor(e,t){this.value=t.value,this.viewProps=t.viewProps,this.view=new YE(e,{value:this.value,viewProps:this.viewProps})}}class Mu{constructor(e,t){this.onButtonBlur_=this.onButtonBlur_.bind(this),this.onButtonClick_=this.onButtonClick_.bind(this),this.onPopupChildBlur_=this.onPopupChildBlur_.bind(this),this.onPopupChildKeydown_=this.onPopupChildKeydown_.bind(this),this.value=t.value,this.viewProps=t.viewProps,this.foldable_=Fs.create(t.expanded),this.swatchC_=new WE(e,{value:this.value,viewProps:this.viewProps});const n=this.swatchC_.view.buttonElement;n.addEventListener("blur",this.onButtonBlur_),n.addEventListener("click",this.onButtonClick_),this.textC_=new ku(e,{parser:t.parser,props:Ze.fromObject({formatter:t.formatter}),value:this.value,viewProps:this.viewProps}),this.view=new JC(e,{foldable:this.foldable_,pickerLayout:t.pickerLayout}),this.view.swatchElement.appendChild(this.swatchC_.view.element),this.view.textElement.appendChild(this.textC_.view.element),this.popC_=t.pickerLayout==="popup"?new wf(e,{viewProps:this.viewProps}):null;const i=new XE(e,{colorType:t.colorType,supportsAlpha:t.supportsAlpha,value:this.value,viewProps:this.viewProps});i.view.allFocusableElements.forEach(s=>{s.addEventListener("blur",this.onPopupChildBlur_),s.addEventListener("keydown",this.onPopupChildKeydown_)}),this.pickerC_=i,this.popC_?(this.view.element.appendChild(this.popC_.view.element),this.popC_.view.element.appendChild(i.view.element),Gi({primary:this.foldable_.value("expanded"),secondary:this.popC_.shows,forward:s=>s,backward:(s,o)=>o})):this.view.pickerElement&&(this.view.pickerElement.appendChild(this.pickerC_.view.element),Au(this.foldable_,this.view.pickerElement))}get textController(){return this.textC_}onButtonBlur_(e){if(!this.popC_)return;const t=this.view.element,n=e.relatedTarget;(!n||!t.contains(n))&&(this.popC_.shows.rawValue=!1)}onButtonClick_(){this.foldable_.set("expanded",!this.foldable_.get("expanded")),this.foldable_.get("expanded")&&this.pickerC_.view.allFocusableElements[0].focus()}onPopupChildBlur_(e){if(!this.popC_)return;const t=this.popC_.view.element,n=ff(e);n&&t.contains(n)||n&&n===this.swatchC_.view.buttonElement&&!gu(t.ownerDocument)||(this.popC_.shows.rawValue=!1)}onPopupChildKeydown_(e){this.popC_?e.key==="Escape"&&(this.popC_.shows.rawValue=!1):this.view.pickerElement&&e.key==="Escape"&&this.swatchC_.view.buttonElement.focus()}}function ZE(r){return Ur(r.getComponents("rgb")).reduce((e,t)=>e<<8|Math.floor(t)&255,0)}function QE(r){return r.getComponents("rgb").reduce((e,t,n)=>{const i=Math.floor(n===3?t*255:t)&255;return e<<8|i},0)>>>0}function JE(r){return new Ye([r>>16&255,r>>8&255,r&255],"rgb")}function e1(r){return new Ye([r>>24&255,r>>16&255,r>>8&255,tt(r&255,0,255,0,1)],"rgb")}function t1(r){return typeof r!="number"?Ye.black():JE(r)}function r1(r){return typeof r!="number"?Ye.black():e1(r)}function Da(r,e){return typeof r!="object"||vt(r)?!1:e in r&&typeof r[e]=="number"}function Uf(r){return Da(r,"r")&&Da(r,"g")&&Da(r,"b")}function zf(r){return Uf(r)&&Da(r,"a")}function Hf(r){return Uf(r)}function Iu(r,e){if(r.mode!==e.mode||r.type!==e.type)return!1;const t=r.getComponents(),n=e.getComponents();for(let i=0;i{Gs(t,e(n))}:null}function i1(r){const e=r?QE:ZE;return(t,n)=>{Gs(t,e(n))}}function s1(r,e,t){const i=Zt(e,t).toRgbaObject();r.writeProperty("r",i.r),r.writeProperty("g",i.g),r.writeProperty("b",i.b),r.writeProperty("a",i.a)}function a1(r,e,t){const i=Zt(e,t).toRgbaObject();r.writeProperty("r",i.r),r.writeProperty("g",i.g),r.writeProperty("b",i.b)}function o1(r,e){return(t,n)=>{r?s1(t,n,e):a1(t,n,e)}}function l1(r){var e;return!!(!((e=r?.color)===null||e===void 0)&&e.alpha)}function u1(r){return r?e=>Du(e,"0x"):e=>Ru(e,"0x")}function c1(r){return"color"in r||r.view==="color"}Jt({id:"input-color-number",type:"input",accept:(r,e)=>{if(typeof r!="number"||!c1(e))return null;const t=Lu(e);return t?{initialValue:r,params:Object.assign(Object.assign({},t),{supportsAlpha:l1(e)})}:null},binding:{reader:r=>r.params.supportsAlpha?r1:t1,equals:Iu,writer:r=>i1(r.params.supportsAlpha)},controller:r=>{var e,t;return new Mu(r.document,{colorType:"int",expanded:(e=r.params.expanded)!==null&&e!==void 0?e:!1,formatter:u1(r.params.supportsAlpha),parser:js("int"),pickerLayout:(t=r.params.picker)!==null&&t!==void 0?t:"popup",supportsAlpha:r.params.supportsAlpha,value:r.value,viewProps:r.viewProps})}});function d1(r,e){if(!Hf(r))return Zt(Ye.black(),e);if(e==="int"){const t=Lh(r);return new Ye(t,"rgb")}if(e==="float"){const t=Lh(r);return new Vu(t,"rgb")}return Zt(Ye.black(),"int")}function h1(r){return zf(r)}function p1(r){return e=>{const t=d1(e,r);return Zt(t,"int")}}function f1(r,e){return t=>r?Gf(t,e):Nf(t,e)}Jt({id:"input-color-object",type:"input",accept:(r,e)=>{var t;if(!Hf(r))return null;const n=Lu(e);return n?{initialValue:r,params:Object.assign(Object.assign({},n),{colorType:(t=Tf(e))!==null&&t!==void 0?t:"int"})}:null},binding:{reader:r=>p1(r.params.colorType),equals:Iu,writer:r=>o1(h1(r.initialValue),r.params.colorType)},controller:r=>{var e,t;const n=zf(r.initialValue);return new Mu(r.document,{colorType:r.params.colorType,expanded:(e=r.params.expanded)!==null&&e!==void 0?e:!1,formatter:f1(n,r.params.colorType),parser:js("int"),pickerLayout:(t=r.params.picker)!==null&&t!==void 0?t:"popup",supportsAlpha:n,value:r.value,viewProps:r.viewProps})}});Jt({id:"input-color-string",type:"input",accept:(r,e)=>{if(typeof r!="string"||e.view==="text")return null;const t=AE(r,Tf(e));if(!t)return null;const n=jf(t);if(!n)return null;const i=Lu(e);return i?{initialValue:r,params:Object.assign(Object.assign({},i),{format:t,stringifier:n})}:null},binding:{reader:()=>SE,equals:Iu,writer:r=>{const e=n1(r.params.format);if(!e)throw pr.notBindable();return e}},controller:r=>{var e,t;return new Mu(r.document,{colorType:r.params.format.type,expanded:(e=r.params.expanded)!==null&&e!==void 0?e:!1,formatter:r.params.stringifier,parser:js("int"),pickerLayout:(t=r.params.picker)!==null&&t!==void 0?t:"popup",supportsAlpha:r.params.format.alpha,value:r.value,viewProps:r.viewProps})}});class Fu{constructor(e){this.components=e.components,this.asm_=e.assembly}constrain(e){const t=this.asm_.toComponents(e).map((n,i)=>{var s,o;return(o=(s=this.components[i])===null||s===void 0?void 0:s.constrain(n))!==null&&o!==void 0?o:n});return this.asm_.fromComponents(t)}}const Vh=Qe("pndtxt");class m1{constructor(e,t){this.textViews=t.textViews,this.element=e.createElement("div"),this.element.classList.add(Vh()),this.textViews.forEach(n=>{const i=e.createElement("div");i.classList.add(Vh("a")),i.appendChild(n.element),this.element.appendChild(i)})}}function v1(r,e,t){return new Ns(r,{arrayPosition:t===0?"fst":t===e.axes.length-1?"lst":"mid",parser:e.parser,props:e.axes[t].textProps,value:jt(0,{constraint:e.axes[t].constraint}),viewProps:e.viewProps})}class $u{constructor(e,t){this.value=t.value,this.viewProps=t.viewProps,this.acs_=t.axes.map((n,i)=>v1(e,t,i)),this.acs_.forEach((n,i)=>{Gi({primary:this.value,secondary:n.value,forward:s=>t.assembly.toComponents(s)[i],backward:(s,o)=>{const l=t.assembly.toComponents(s);return l[i]=o,t.assembly.fromComponents(l)}})}),this.view=new m1(e,{textViews:this.acs_.map(n=>n.view)})}get textControllers(){return this.acs_}}class b1 extends wu{get max(){return this.controller.valueController.sliderController.props.get("max")}set max(e){this.controller.valueController.sliderController.props.set("max",e)}get min(){return this.controller.valueController.sliderController.props.get("min")}set min(e){this.controller.valueController.sliderController.props.set("min",e)}}function _1(r,e){const t=[],n=of(r,e);n&&t.push(n);const i=lf(r);i&&t.push(i);const s=Tu(r.options);return s&&t.push(s),new Bs(t)}Jt({id:"input-number",type:"input",accept:(r,e)=>{if(typeof r!="number")return null;const t=Xt(e,n=>Object.assign(Object.assign({},cf(n)),{options:n.optional.custom(to),readonly:n.optional.constant(!1)}));return t?{initialValue:r,params:t}:null},binding:{reader:r=>nf,constraint:r=>_1(r.params,r.initialValue),writer:r=>Gs},controller:r=>{const e=r.value,t=r.constraint,n=t&&ja(t,eo);if(n)return new Di(r.document,{props:new Ze({options:n.values.value("options")}),value:e,viewProps:r.viewProps});const i=uf(r.params,e.rawValue),s=t&&ja(t,Za);return s?new Sh(r.document,Object.assign(Object.assign({},XC(Object.assign(Object.assign({},i),{keyScale:jt(i.keyScale),max:s.values.value("max"),min:s.values.value("min")}))),{parser:On,value:e,viewProps:r.viewProps})):new Ns(r.document,{parser:On,props:Ze.fromObject(i),value:e,viewProps:r.viewProps})},api(r){return typeof r.controller.value.rawValue!="number"?null:r.controller.valueController instanceof Sh?new b1(r.controller):r.controller.valueController instanceof Di?new Su(r.controller):null}});class Ln{constructor(e=0,t=0){this.x=e,this.y=t}getComponents(){return[this.x,this.y]}static isObject(e){if(vt(e))return!1;const t=e.x,n=e.y;return!(typeof t!="number"||typeof n!="number")}static equals(e,t){return e.x===t.x&&e.y===t.y}toObject(){return{x:this.x,y:this.y}}}const Kf={toComponents:r=>r.getComponents(),fromComponents:r=>new Ln(...r)},Si=Qe("p2d");class w1{constructor(e,t){this.element=e.createElement("div"),this.element.classList.add(Si()),t.viewProps.bindClassModifiers(this.element),an(t.expanded,Ni(this.element,Si(void 0,"expanded")));const n=e.createElement("div");n.classList.add(Si("h")),this.element.appendChild(n);const i=e.createElement("button");i.classList.add(Si("b")),i.appendChild(Ja(e,"p2dpad")),t.viewProps.bindDisabled(i),n.appendChild(i),this.buttonElement=i;const s=e.createElement("div");if(s.classList.add(Si("t")),n.appendChild(s),this.textElement=s,t.pickerLayout==="inline"){const o=e.createElement("div");o.classList.add(Si("p")),this.element.appendChild(o),this.pickerElement=o}else this.pickerElement=null}}const En=Qe("p2dp");class g1{constructor(e,t){this.onFoldableChange_=this.onFoldableChange_.bind(this),this.onPropsChange_=this.onPropsChange_.bind(this),this.onValueChange_=this.onValueChange_.bind(this),this.props_=t.props,this.props_.emitter.on("change",this.onPropsChange_),this.element=e.createElement("div"),this.element.classList.add(En()),t.layout==="popup"&&this.element.classList.add(En(void 0,"p")),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("div");n.classList.add(En("p")),t.viewProps.bindTabIndex(n),this.element.appendChild(n),this.padElement=n;const i=e.createElementNS(Br,"svg");i.classList.add(En("g")),this.padElement.appendChild(i),this.svgElem_=i;const s=e.createElementNS(Br,"line");s.classList.add(En("ax")),s.setAttributeNS(null,"x1","0"),s.setAttributeNS(null,"y1","50%"),s.setAttributeNS(null,"x2","100%"),s.setAttributeNS(null,"y2","50%"),this.svgElem_.appendChild(s);const o=e.createElementNS(Br,"line");o.classList.add(En("ax")),o.setAttributeNS(null,"x1","50%"),o.setAttributeNS(null,"y1","0"),o.setAttributeNS(null,"x2","50%"),o.setAttributeNS(null,"y2","100%"),this.svgElem_.appendChild(o);const l=e.createElementNS(Br,"line");l.classList.add(En("l")),l.setAttributeNS(null,"x1","50%"),l.setAttributeNS(null,"y1","50%"),this.svgElem_.appendChild(l),this.lineElem_=l;const y=e.createElement("div");y.classList.add(En("m")),this.padElement.appendChild(y),this.markerElem_=y,t.value.emitter.on("change",this.onValueChange_),this.value=t.value,this.update_()}get allFocusableElements(){return[this.padElement]}update_(){const[e,t]=this.value.rawValue.getComponents(),n=this.props_.get("max"),i=tt(e,-n,+n,0,100),s=tt(t,-n,+n,0,100),o=this.props_.get("invertsY")?100-s:s;this.lineElem_.setAttributeNS(null,"x2",`${i}%`),this.lineElem_.setAttributeNS(null,"y2",`${o}%`),this.markerElem_.style.left=`${i}%`,this.markerElem_.style.top=`${o}%`}onValueChange_(){this.update_()}onPropsChange_(){this.update_()}onFoldableChange_(){this.update_()}}function Oh(r,e,t){return[or(e[0],un(r)),or(e[1],As(r))*(t?1:-1)]}class y1{constructor(e,t){this.onPadKeyDown_=this.onPadKeyDown_.bind(this),this.onPadKeyUp_=this.onPadKeyUp_.bind(this),this.onPointerDown_=this.onPointerDown_.bind(this),this.onPointerMove_=this.onPointerMove_.bind(this),this.onPointerUp_=this.onPointerUp_.bind(this),this.props=t.props,this.value=t.value,this.viewProps=t.viewProps,this.view=new g1(e,{layout:t.layout,props:this.props,value:this.value,viewProps:this.viewProps}),this.ptHandler_=new oi(this.view.padElement),this.ptHandler_.emitter.on("down",this.onPointerDown_),this.ptHandler_.emitter.on("move",this.onPointerMove_),this.ptHandler_.emitter.on("up",this.onPointerUp_),this.view.padElement.addEventListener("keydown",this.onPadKeyDown_),this.view.padElement.addEventListener("keyup",this.onPadKeyUp_)}handlePointerEvent_(e,t){if(!e.point)return;const n=this.props.get("max"),i=tt(e.point.x,0,e.bounds.width,-n,+n),s=tt(this.props.get("invertsY")?e.bounds.height-e.point.y:e.point.y,0,e.bounds.height,-n,+n);this.value.setRawValue(new Ln(i,s),t)}onPointerDown_(e){this.handlePointerEvent_(e.data,{forceEmit:!1,last:!1})}onPointerMove_(e){this.handlePointerEvent_(e.data,{forceEmit:!1,last:!1})}onPointerUp_(e){this.handlePointerEvent_(e.data,{forceEmit:!0,last:!0})}onPadKeyDown_(e){xf(e.key)&&e.preventDefault();const[t,n]=Oh(e,[this.props.get("xKeyScale"),this.props.get("yKeyScale")],this.props.get("invertsY"));t===0&&n===0||this.value.setRawValue(new Ln(this.value.rawValue.x+t,this.value.rawValue.y+n),{forceEmit:!1,last:!1})}onPadKeyUp_(e){const[t,n]=Oh(e,[this.props.get("xKeyScale"),this.props.get("yKeyScale")],this.props.get("invertsY"));t===0&&n===0||this.value.setRawValue(this.value.rawValue,{forceEmit:!0,last:!0})}}class x1{constructor(e,t){var n,i;this.onPopupChildBlur_=this.onPopupChildBlur_.bind(this),this.onPopupChildKeydown_=this.onPopupChildKeydown_.bind(this),this.onPadButtonBlur_=this.onPadButtonBlur_.bind(this),this.onPadButtonClick_=this.onPadButtonClick_.bind(this),this.value=t.value,this.viewProps=t.viewProps,this.foldable_=Fs.create(t.expanded),this.popC_=t.pickerLayout==="popup"?new wf(e,{viewProps:this.viewProps}):null;const s=new y1(e,{layout:t.pickerLayout,props:new Ze({invertsY:jt(t.invertsY),max:jt(t.max),xKeyScale:t.axes[0].textProps.value("keyScale"),yKeyScale:t.axes[1].textProps.value("keyScale")}),value:this.value,viewProps:this.viewProps});s.view.allFocusableElements.forEach(o=>{o.addEventListener("blur",this.onPopupChildBlur_),o.addEventListener("keydown",this.onPopupChildKeydown_)}),this.pickerC_=s,this.textC_=new $u(e,{assembly:Kf,axes:t.axes,parser:t.parser,value:this.value,viewProps:this.viewProps}),this.view=new w1(e,{expanded:this.foldable_.value("expanded"),pickerLayout:t.pickerLayout,viewProps:this.viewProps}),this.view.textElement.appendChild(this.textC_.view.element),(n=this.view.buttonElement)===null||n===void 0||n.addEventListener("blur",this.onPadButtonBlur_),(i=this.view.buttonElement)===null||i===void 0||i.addEventListener("click",this.onPadButtonClick_),this.popC_?(this.view.element.appendChild(this.popC_.view.element),this.popC_.view.element.appendChild(this.pickerC_.view.element),Gi({primary:this.foldable_.value("expanded"),secondary:this.popC_.shows,forward:o=>o,backward:(o,l)=>l})):this.view.pickerElement&&(this.view.pickerElement.appendChild(this.pickerC_.view.element),Au(this.foldable_,this.view.pickerElement))}get textController(){return this.textC_}onPadButtonBlur_(e){if(!this.popC_)return;const t=this.view.element,n=e.relatedTarget;(!n||!t.contains(n))&&(this.popC_.shows.rawValue=!1)}onPadButtonClick_(){this.foldable_.set("expanded",!this.foldable_.get("expanded")),this.foldable_.get("expanded")&&this.pickerC_.view.allFocusableElements[0].focus()}onPopupChildBlur_(e){if(!this.popC_)return;const t=this.popC_.view.element,n=ff(e);n&&t.contains(n)||n&&n===this.view.buttonElement&&!gu(t.ownerDocument)||(this.popC_.shows.rawValue=!1)}onPopupChildKeydown_(e){this.popC_?e.key==="Escape"&&(this.popC_.shows.rawValue=!1):this.view.pickerElement&&e.key==="Escape"&&this.view.buttonElement.focus()}}function C1(r){return Ln.isObject(r)?new Ln(r.x,r.y):new Ln}function E1(r,e){r.writeProperty("x",e.x),r.writeProperty("y",e.y)}function P1(r,e){return new Fu({assembly:Kf,components:[nn(Object.assign(Object.assign({},r),r.x),e.x),nn(Object.assign(Object.assign({},r),r.y),e.y)]})}function Rh(r,e){var t,n;if(!vt(r.min)||!vt(r.max))return Math.max(Math.abs((t=r.min)!==null&&t!==void 0?t:0),Math.abs((n=r.max)!==null&&n!==void 0?n:0));const i=af(r);return Math.max(Math.abs(i)*10,Math.abs(e)*10)}function A1(r,e){var t,n;const i=Rh(ri(r,(t=r.x)!==null&&t!==void 0?t:{}),e.x),s=Rh(ri(r,(n=r.y)!==null&&n!==void 0?n:{}),e.y);return Math.max(i,s)}function S1(r){if(!("y"in r))return!1;const e=r.y;return e&&"inverted"in e?!!e.inverted:!1}Jt({id:"input-point2d",type:"input",accept:(r,e)=>{if(!Ln.isObject(r))return null;const t=Xt(e,n=>Object.assign(Object.assign({},Ss(n)),{expanded:n.optional.boolean,picker:n.optional.custom(Ef),readonly:n.optional.constant(!1),x:n.optional.custom(Tn),y:n.optional.object(Object.assign(Object.assign({},Ss(n)),{inverted:n.optional.boolean}))}));return t?{initialValue:r,params:t}:null},binding:{reader:()=>C1,constraint:r=>P1(r.params,r.initialValue),equals:Ln.equals,writer:()=>E1},controller:r=>{var e,t;const n=r.document,i=r.value,s=r.constraint,o=[r.params.x,r.params.y];return new x1(n,{axes:i.rawValue.getComponents().map((l,y)=>{var x;return bu({constraint:s.components[y],initialValue:l,params:ri(r.params,(x=o[y])!==null&&x!==void 0?x:{})})}),expanded:(e=r.params.expanded)!==null&&e!==void 0?e:!1,invertsY:S1(r.params),max:A1(r.params,i.rawValue),parser:On,pickerLayout:(t=r.params.picker)!==null&&t!==void 0?t:"popup",value:i,viewProps:r.viewProps})}});class Vi{constructor(e=0,t=0,n=0){this.x=e,this.y=t,this.z=n}getComponents(){return[this.x,this.y,this.z]}static isObject(e){if(vt(e))return!1;const t=e.x,n=e.y,i=e.z;return!(typeof t!="number"||typeof n!="number"||typeof i!="number")}static equals(e,t){return e.x===t.x&&e.y===t.y&&e.z===t.z}toObject(){return{x:this.x,y:this.y,z:this.z}}}const qf={toComponents:r=>r.getComponents(),fromComponents:r=>new Vi(...r)};function T1(r){return Vi.isObject(r)?new Vi(r.x,r.y,r.z):new Vi}function k1(r,e){r.writeProperty("x",e.x),r.writeProperty("y",e.y),r.writeProperty("z",e.z)}function L1(r,e){return new Fu({assembly:qf,components:[nn(Object.assign(Object.assign({},r),r.x),e.x),nn(Object.assign(Object.assign({},r),r.y),e.y),nn(Object.assign(Object.assign({},r),r.z),e.z)]})}Jt({id:"input-point3d",type:"input",accept:(r,e)=>{if(!Vi.isObject(r))return null;const t=Xt(e,n=>Object.assign(Object.assign({},Ss(n)),{readonly:n.optional.constant(!1),x:n.optional.custom(Tn),y:n.optional.custom(Tn),z:n.optional.custom(Tn)}));return t?{initialValue:r,params:t}:null},binding:{reader:r=>T1,constraint:r=>L1(r.params,r.initialValue),equals:Vi.equals,writer:r=>k1},controller:r=>{const e=r.value,t=r.constraint,n=[r.params.x,r.params.y,r.params.z];return new $u(r.document,{assembly:qf,axes:e.rawValue.getComponents().map((i,s)=>{var o;return bu({constraint:t.components[s],initialValue:i,params:ri(r.params,(o=n[s])!==null&&o!==void 0?o:{})})}),parser:On,value:e,viewProps:r.viewProps})}});class Oi{constructor(e=0,t=0,n=0,i=0){this.x=e,this.y=t,this.z=n,this.w=i}getComponents(){return[this.x,this.y,this.z,this.w]}static isObject(e){if(vt(e))return!1;const t=e.x,n=e.y,i=e.z,s=e.w;return!(typeof t!="number"||typeof n!="number"||typeof i!="number"||typeof s!="number")}static equals(e,t){return e.x===t.x&&e.y===t.y&&e.z===t.z&&e.w===t.w}toObject(){return{x:this.x,y:this.y,z:this.z,w:this.w}}}const Xf={toComponents:r=>r.getComponents(),fromComponents:r=>new Oi(...r)};function V1(r){return Oi.isObject(r)?new Oi(r.x,r.y,r.z,r.w):new Oi}function O1(r,e){r.writeProperty("x",e.x),r.writeProperty("y",e.y),r.writeProperty("z",e.z),r.writeProperty("w",e.w)}function R1(r,e){return new Fu({assembly:Xf,components:[nn(Object.assign(Object.assign({},r),r.x),e.x),nn(Object.assign(Object.assign({},r),r.y),e.y),nn(Object.assign(Object.assign({},r),r.z),e.z),nn(Object.assign(Object.assign({},r),r.w),e.w)]})}Jt({id:"input-point4d",type:"input",accept:(r,e)=>{if(!Oi.isObject(r))return null;const t=Xt(e,n=>Object.assign(Object.assign({},Ss(n)),{readonly:n.optional.constant(!1),w:n.optional.custom(Tn),x:n.optional.custom(Tn),y:n.optional.custom(Tn),z:n.optional.custom(Tn)}));return t?{initialValue:r,params:t}:null},binding:{reader:r=>V1,constraint:r=>R1(r.params,r.initialValue),equals:Oi.equals,writer:r=>O1},controller:r=>{const e=r.value,t=r.constraint,n=[r.params.x,r.params.y,r.params.z,r.params.w];return new $u(r.document,{assembly:Xf,axes:e.rawValue.getComponents().map((i,s)=>{var o;return bu({constraint:t.components[s],initialValue:i,params:ri(r.params,(o=n[s])!==null&&o!==void 0?o:{})})}),parser:On,value:e,viewProps:r.viewProps})}});function D1(r){const e=[],t=Tu(r.options);return t&&e.push(t),new Bs(e)}Jt({id:"input-string",type:"input",accept:(r,e)=>{if(typeof r!="string")return null;const t=Xt(e,n=>({readonly:n.optional.constant(!1),options:n.optional.custom(to)}));return t?{initialValue:r,params:t}:null},binding:{reader:r=>yf,constraint:r=>D1(r.params),writer:r=>Gs},controller:r=>{const e=r.document,t=r.value,n=r.constraint,i=n&&ja(n,eo);return i?new Di(e,{props:new Ze({options:i.values.value("options")}),value:t,viewProps:r.viewProps}):new ku(e,{parser:s=>s,props:Ze.fromObject({formatter:Il}),value:t,viewProps:r.viewProps})},api(r){return typeof r.controller.value.rawValue!="string"?null:r.controller.valueController instanceof Di?new Su(r.controller):null}});const no={monitor:{defaultRows:3}},Dh=Qe("mll");class M1{constructor(e,t){this.onValueUpdate_=this.onValueUpdate_.bind(this),this.formatter_=t.formatter,this.element=e.createElement("div"),this.element.classList.add(Dh()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("textarea");n.classList.add(Dh("i")),n.style.height=`calc(var(${Cf("containerUnitSize")}) * ${t.rows})`,n.readOnly=!0,t.viewProps.bindDisabled(n),this.element.appendChild(n),this.textareaElem_=n,t.value.emitter.on("change",this.onValueUpdate_),this.value=t.value,this.update_()}update_(){const e=this.textareaElem_,t=e.scrollTop===e.scrollHeight-e.clientHeight,n=[];this.value.rawValue.forEach(i=>{i!==void 0&&n.push(this.formatter_(i))}),e.textContent=n.join(` +`),t&&(e.scrollTop=e.scrollHeight)}onValueUpdate_(){this.update_()}}class Bu{constructor(e,t){this.value=t.value,this.viewProps=t.viewProps,this.view=new M1(e,{formatter:t.formatter,rows:t.rows,value:this.value,viewProps:this.viewProps})}}const Mh=Qe("sgl");class I1{constructor(e,t){this.onValueUpdate_=this.onValueUpdate_.bind(this),this.formatter_=t.formatter,this.element=e.createElement("div"),this.element.classList.add(Mh()),t.viewProps.bindClassModifiers(this.element);const n=e.createElement("input");n.classList.add(Mh("i")),n.readOnly=!0,n.type="text",t.viewProps.bindDisabled(n),this.element.appendChild(n),this.inputElement=n,t.value.emitter.on("change",this.onValueUpdate_),this.value=t.value,this.update_()}update_(){const e=this.value.rawValue,t=e[e.length-1];this.inputElement.value=t!==void 0?this.formatter_(t):""}onValueUpdate_(){this.update_()}}class Nu{constructor(e,t){this.value=t.value,this.viewProps=t.viewProps,this.view=new I1(e,{formatter:t.formatter,value:this.value,viewProps:this.viewProps})}}Jt({id:"monitor-bool",type:"monitor",accept:(r,e)=>{if(typeof r!="boolean")return null;const t=Xt(e,n=>({readonly:n.required.constant(!0),rows:n.optional.number}));return t?{initialValue:r,params:t}:null},binding:{reader:r=>gf},controller:r=>{var e;return r.value.rawValue.length===1?new Nu(r.document,{formatter:Ah,value:r.value,viewProps:r.viewProps}):new Bu(r.document,{formatter:Ah,rows:(e=r.params.rows)!==null&&e!==void 0?e:no.monitor.defaultRows,value:r.value,viewProps:r.viewProps})}});class F1 extends wu{get max(){return this.controller.valueController.props.get("max")}set max(e){this.controller.valueController.props.set("max",e)}get min(){return this.controller.valueController.props.get("min")}set min(e){this.controller.valueController.props.set("min",e)}}const Pn=Qe("grl");class $1{constructor(e,t){this.onCursorChange_=this.onCursorChange_.bind(this),this.onValueUpdate_=this.onValueUpdate_.bind(this),this.element=e.createElement("div"),this.element.classList.add(Pn()),t.viewProps.bindClassModifiers(this.element),this.formatter_=t.formatter,this.props_=t.props,this.cursor_=t.cursor,this.cursor_.emitter.on("change",this.onCursorChange_);const n=e.createElementNS(Br,"svg");n.classList.add(Pn("g")),n.style.height=`calc(var(${Cf("containerUnitSize")}) * ${t.rows})`,this.element.appendChild(n),this.svgElem_=n;const i=e.createElementNS(Br,"polyline");this.svgElem_.appendChild(i),this.lineElem_=i;const s=e.createElement("div");s.classList.add(Pn("t"),Qe("tt")()),this.element.appendChild(s),this.tooltipElem_=s,t.value.emitter.on("change",this.onValueUpdate_),this.value=t.value,this.update_()}get graphElement(){return this.svgElem_}update_(){const{clientWidth:e,clientHeight:t}=this.element,n=this.value.rawValue.length-1,i=this.props_.get("min"),s=this.props_.get("max"),o=[];this.value.rawValue.forEach((U,de)=>{if(U===void 0)return;const Se=tt(de,0,n,0,e),Ce=tt(U,i,s,t,0);o.push([Se,Ce].join(","))}),this.lineElem_.setAttributeNS(null,"points",o.join(" "));const l=this.tooltipElem_,y=this.value.rawValue[this.cursor_.rawValue];if(y===void 0){l.classList.remove(Pn("t","a"));return}const x=tt(this.cursor_.rawValue,0,n,0,e),B=tt(y,i,s,t,0);l.style.left=`${x}px`,l.style.top=`${B}px`,l.textContent=`${this.formatter_(y)}`,l.classList.contains(Pn("t","a"))||(l.classList.add(Pn("t","a"),Pn("t","in")),Ga(l),l.classList.remove(Pn("t","in")))}onValueUpdate_(){this.update_()}onCursorChange_(){this.update_()}}class Yf{constructor(e,t){if(this.onGraphMouseMove_=this.onGraphMouseMove_.bind(this),this.onGraphMouseLeave_=this.onGraphMouseLeave_.bind(this),this.onGraphPointerDown_=this.onGraphPointerDown_.bind(this),this.onGraphPointerMove_=this.onGraphPointerMove_.bind(this),this.onGraphPointerUp_=this.onGraphPointerUp_.bind(this),this.props=t.props,this.value=t.value,this.viewProps=t.viewProps,this.cursor_=jt(-1),this.view=new $1(e,{cursor:this.cursor_,formatter:t.formatter,rows:t.rows,props:this.props,value:this.value,viewProps:this.viewProps}),!gu(e))this.view.element.addEventListener("mousemove",this.onGraphMouseMove_),this.view.element.addEventListener("mouseleave",this.onGraphMouseLeave_);else{const n=new oi(this.view.element);n.emitter.on("down",this.onGraphPointerDown_),n.emitter.on("move",this.onGraphPointerMove_),n.emitter.on("up",this.onGraphPointerUp_)}}importProps(e){return zr(e,null,t=>({max:t.required.number,min:t.required.number}),t=>(this.props.set("max",t.max),this.props.set("min",t.min),!0))}exportProps(){return Hr(null,{max:this.props.get("max"),min:this.props.get("min")})}onGraphMouseLeave_(){this.cursor_.rawValue=-1}onGraphMouseMove_(e){const{clientWidth:t}=this.view.element;this.cursor_.rawValue=Math.floor(tt(e.offsetX,0,t,0,this.value.rawValue.length))}onGraphPointerDown_(e){this.onGraphPointerMove_(e)}onGraphPointerMove_(e){if(!e.data.point){this.cursor_.rawValue=-1;return}this.cursor_.rawValue=Math.floor(tt(e.data.point.x,0,e.data.bounds.width,0,this.value.rawValue.length))}onGraphPointerUp_(){this.cursor_.rawValue=-1}}function Fl(r){return vt(r.format)?ur(2):r.format}function B1(r){var e;return r.value.rawValue.length===1?new Nu(r.document,{formatter:Fl(r.params),value:r.value,viewProps:r.viewProps}):new Bu(r.document,{formatter:Fl(r.params),rows:(e=r.params.rows)!==null&&e!==void 0?e:no.monitor.defaultRows,value:r.value,viewProps:r.viewProps})}function N1(r){var e,t,n;return new Yf(r.document,{formatter:Fl(r.params),rows:(e=r.params.rows)!==null&&e!==void 0?e:no.monitor.defaultRows,props:Ze.fromObject({max:(t=r.params.max)!==null&&t!==void 0?t:100,min:(n=r.params.min)!==null&&n!==void 0?n:0}),value:r.value,viewProps:r.viewProps})}function Ih(r){return r.view==="graph"}Jt({id:"monitor-number",type:"monitor",accept:(r,e)=>{if(typeof r!="number")return null;const t=Xt(e,n=>({format:n.optional.function,max:n.optional.number,min:n.optional.number,readonly:n.required.constant(!0),rows:n.optional.number,view:n.optional.string}));return t?{initialValue:r,params:t}:null},binding:{defaultBufferSize:r=>Ih(r)?64:1,reader:r=>nf},controller:r=>Ih(r.params)?N1(r):B1(r),api:r=>r.controller.valueController instanceof Yf?new F1(r.controller):null});Jt({id:"monitor-string",type:"monitor",accept:(r,e)=>{if(typeof r!="string")return null;const t=Xt(e,n=>({multiline:n.optional.boolean,readonly:n.required.constant(!0),rows:n.optional.number}));return t?{initialValue:r,params:t}:null},binding:{reader:r=>yf},controller:r=>{var e;const t=r.value;return t.rawValue.length>1||r.params.multiline?new Bu(r.document,{formatter:Il,rows:(e=r.params.rows)!==null&&e!==void 0?e:no.monitor.defaultRows,value:t,viewProps:r.viewProps}):new Nu(r.document,{formatter:Il,value:t,viewProps:r.viewProps})}});function eS(r,e,t,n){function i(s){return s instanceof t?s:new t(function(o){o(s)})}return new(t||(t=Promise))(function(s,o){function l(B){try{x(n.next(B))}catch(U){o(U)}}function y(B){try{x(n.throw(B))}catch(U){o(U)}}function x(B){B.done?s(B.value):i(B.value).then(l,y)}x((n=n.apply(r,e||[])).next())})}function Fh(r){var e=typeof Symbol=="function"&&Symbol.iterator,t=e&&r[e],n=0;if(t)return t.call(r);if(r&&typeof r.length=="number")return{next:function(){return r&&n>=r.length&&(r=void 0),{value:r&&r[n++],done:!r}}};throw new TypeError(e?"Object is not iterable.":"Symbol.iterator is not defined.")}function za(r){return this instanceof za?(this.v=r,this):new za(r)}function tS(r,e,t){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var n=t.apply(r,e||[]),i,s=[];return i={},o("next"),o("throw"),o("return"),i[Symbol.asyncIterator]=function(){return this},i;function o(de){n[de]&&(i[de]=function(Se){return new Promise(function(Ce,Ie){s.push([de,Se,Ce,Ie])>1||l(de,Se)})})}function l(de,Se){try{y(n[de](Se))}catch(Ce){U(s[0][3],Ce)}}function y(de){de.value instanceof za?Promise.resolve(de.value.v).then(x,B):U(s[0][2],de)}function x(de){l("next",de)}function B(de){l("throw",de)}function U(de,Se){de(Se),s.shift(),s.length&&l(s[0][0],s[0][1])}}function rS(r){var e,t;return e={},n("next"),n("throw",function(i){throw i}),n("return"),e[Symbol.iterator]=function(){return this},e;function n(i,s){e[i]=r[i]?function(o){return(t=!t)?{value:za(r[i](o)),done:!1}:s?s(o):o}:s}}function nS(r){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var e=r[Symbol.asyncIterator],t;return e?e.call(r):(r=typeof Fh=="function"?Fh(r):r[Symbol.iterator](),t={},n("next"),n("throw"),n("return"),t[Symbol.asyncIterator]=function(){return this},t);function n(s){t[s]=r[s]&&function(o){return new Promise(function(l,y){o=r[s](o),i(l,y,o.done,o.value)})}}function i(s,o,l,y){Promise.resolve(y).then(function(x){s({value:x,done:l})},o)}}const xl=2,Fr=4,tn=4,G1=4,An=new Int32Array(2),$h=new Float32Array(An.buffer),Bh=new Float64Array(An.buffer),Ta=new Uint16Array(new Uint8Array([1,0]).buffer)[0]===1;var $l;(function(r){r[r.UTF8_BYTES=1]="UTF8_BYTES",r[r.UTF16_STRING=2]="UTF16_STRING"})($l||($l={}));class Ha{constructor(e){this.bytes_=e,this.position_=0,this.text_decoder_=new TextDecoder}static allocate(e){return new Ha(new Uint8Array(e))}clear(){this.position_=0}bytes(){return this.bytes_}position(){return this.position_}setPosition(e){this.position_=e}capacity(){return this.bytes_.length}readInt8(e){return this.readUint8(e)<<24>>24}readUint8(e){return this.bytes_[e]}readInt16(e){return this.readUint16(e)<<16>>16}readUint16(e){return this.bytes_[e]|this.bytes_[e+1]<<8}readInt32(e){return this.bytes_[e]|this.bytes_[e+1]<<8|this.bytes_[e+2]<<16|this.bytes_[e+3]<<24}readUint32(e){return this.readInt32(e)>>>0}readInt64(e){return BigInt.asIntN(64,BigInt(this.readUint32(e))+(BigInt(this.readUint32(e+4))<>8}writeUint16(e,t){this.bytes_[e]=t,this.bytes_[e+1]=t>>8}writeInt32(e,t){this.bytes_[e]=t,this.bytes_[e+1]=t>>8,this.bytes_[e+2]=t>>16,this.bytes_[e+3]=t>>24}writeUint32(e,t){this.bytes_[e]=t,this.bytes_[e+1]=t>>8,this.bytes_[e+2]=t>>16,this.bytes_[e+3]=t>>24}writeInt64(e,t){this.writeInt32(e,Number(BigInt.asIntN(32,t))),this.writeInt32(e+4,Number(BigInt.asIntN(32,t>>BigInt(32))))}writeUint64(e,t){this.writeUint32(e,Number(BigInt.asUintN(32,t))),this.writeUint32(e+4,Number(BigInt.asUintN(32,t>>BigInt(32))))}writeFloat32(e,t){$h[0]=t,this.writeInt32(e,An[0])}writeFloat64(e,t){Bh[0]=t,this.writeInt32(e,An[Ta?0:1]),this.writeInt32(e+4,An[Ta?1:0])}getBufferIdentifier(){if(this.bytes_.lengththis.minalign&&(this.minalign=e);const n=~(this.bb.capacity()-this.space+t)+1&e-1;for(;this.space=0&&this.vtable[t]==0;t--);const n=t+1;for(;t>=0;t--)this.addInt16(this.vtable[t]!=0?e-this.vtable[t]:0);const i=2;this.addInt16(e-this.object_start);const s=(n+i)*xl;this.addInt16(s);let o=0;const l=this.space;e:for(t=0;t=0;o--)this.writeInt8(s.charCodeAt(o))}this.prep(this.minalign,Fr+i),this.addOffset(e),i&&this.addInt32(this.bb.capacity()-this.space),this.bb.setPosition(this.space)}finishSizePrefixed(e,t){this.finish(e,t,!0)}requiredField(e,t){const n=this.bb.capacity()-e,i=n-this.bb.readInt32(n);if(!(t + + + + + + Regl Scatterplot + + + + + + + + + + + + + + +

Regl Scatterplot

+ +
+
+ +
+
+
+
+
+
+
+
+ + diff --git a/biome.json b/biome.json deleted file mode 100644 index a32ea705..00000000 --- a/biome.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "$schema": "https://biomejs.dev/schemas/2.3.11/schema.json", - "assist": { "actions": { "source": { "organizeImports": "on" } } }, - "formatter": { - "indentStyle": "space", - "indentWidth": 2, - "lineWidth": 80 - }, - "javascript": { - "formatter": { - "quoteStyle": "single" - } - }, - "linter": { - "enabled": true, - "rules": { - "complexity": { - "noExcessiveCognitiveComplexity": "off" - }, - "style": { - "noDefaultExport": "off" - }, - "suspicious": { - "noConsole": "error" - }, - "recommended": true - } - }, - "files": { - "includes": ["**/src/**", "!**/src/kdbush-class.js"] - } -} diff --git a/codemeta.json b/codemeta.json deleted file mode 100644 index 22909329..00000000 --- a/codemeta.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "@context": "https://raw.githubusercontent.com/codemeta/codemeta/master/codemeta.jsonld", - "@type": "Code", - "author": [ - { - "@id": "http://orcid.org/0000-0001-8432-4835", - "@type": "Person", - "name": "Fritz Lekschas", - "affiliation": "Independent Researcher, USA" - } - ], - "identifier": "", - "codeRepository": "https://github.com/flekschas/regl-scatterplot", - "datePublished": "2023-02-12", - "dateModified": "2023-02-12", - "dateCreated": "2023-02-12", - "description": "A Scalable Interactive JavaScript-based Scatter Plot", - "keywords": "scatter plot, 2D scatter, interactive data visualization, JavaScript, embedding plot, WebGL", - "license": "MIT", - "title": "regl-scatterplot", - "version": "v1.5.1" -} diff --git a/connected-points-by-segments.html b/connected-points-by-segments.html new file mode 100644 index 00000000..706d962e --- /dev/null +++ b/connected-points-by-segments.html @@ -0,0 +1,444 @@ + + + + + + + Regl Scatterplot + + + + + + + + + + + + + +

Regl Scatterplot

+ +
+
+ +
+
+
+
+
+
+
+
+ + diff --git a/connected-points.html b/connected-points.html new file mode 100644 index 00000000..484bb52c --- /dev/null +++ b/connected-points.html @@ -0,0 +1,444 @@ + + + + + + + Regl Scatterplot + + + + + + + + + + + + + +

Regl Scatterplot

+ +
+
+ +
+
+
+
+
+
+
+
+ + diff --git a/dynamic-opacity.html b/dynamic-opacity.html new file mode 100644 index 00000000..9512b6bb --- /dev/null +++ b/dynamic-opacity.html @@ -0,0 +1,444 @@ + + + + + + + Regl Scatterplot + + + + + + + + + + + + + +

Regl Scatterplot

+ +
+
+ +
+
+
+
+
+
+
+
+ + diff --git a/embedded.html b/embedded.html new file mode 100644 index 00000000..9278fb0d --- /dev/null +++ b/embedded.html @@ -0,0 +1,444 @@ + + + + + + + Regl Scatterplot + + + + + + + + + + + + + +

Regl Scatterplot

+ +
+
+ +
+
+
+
+
+
+
+
+ + diff --git a/example/annotations.js b/example/annotations.js deleted file mode 100644 index 7bdaafb0..00000000 --- a/example/annotations.js +++ /dev/null @@ -1,165 +0,0 @@ -import createScatterplot from '../src'; -import createMenu from './menu'; -import { checkSupport } from './utils'; - -const canvas = document.querySelector('#canvas'); - -let points = { x: [], y: [], z: [], w: [] }; -let numPoints = 100000; -let pointSize = 2; -let opacity = 0.33; -let selection = []; - -const lassoMinDelay = 10; -const lassoMinDist = 2; -const showReticle = true; -const reticleColor = [1, 1, 0.878431373, 0.33]; - -const gaussianRandom = (mean = 0, stdev = 1) => { - const u = 1 - Math.random(); - const v = Math.random(); - const z = Math.sqrt(-2.0 * Math.log(u)) * Math.cos(2.0 * Math.PI * v); - // Transform to the desired mean and standard deviation: - return z * stdev + mean; -}; - -const selectHandler = ({ points: selectedPoints }) => { - selection = selectedPoints; - if (selection.length === 1) { - const x = points.x[selection[0]]; - const y = points.y[selection[0]]; - const category = points.z[selection[0]]; - const value = points.w[selection[0]]; - console.log( - `Selected: ${selectedPoints}`, - `X: ${x}\nY: ${y}\nCategory: ${category}\nValue: ${value}` - ); - } -}; - -const deselectHandler = () => { - selection = []; -}; - -const scatterplot = createScatterplot({ - canvas, - lassoMinDelay, - lassoMinDist, - pointSize, - opacity, - showReticle, - reticleColor, - lassoOnLongPress: true, -}); - -checkSupport(scatterplot); - -console.log(`Scatterplot v${scatterplot.get('version')}`); - -scatterplot.subscribe('select', selectHandler); -scatterplot.subscribe('deselect', deselectHandler); - -const generatePoints = (l) => { - const s = (Math.log10(l) / Math.log10(100000)) ** 2; - const clusters = [ - { - length: l * (7 / 16), - cx: -0.48, - cy: 0.46, - stdx: 0.05 * s, - stdy: 0.1 * s, - }, - { - length: l * (5 / 16), - cx: 0.49, - cy: 0.5, - stdx: 0.07 * s, - stdy: 0.066 * s, - }, - { - length: l * (3 / 16), - cx: 0.48, - cy: -0.51, - stdx: 0.12 * s, - stdy: 0.05 * s, - }, - { - length: l * (1 / 16), - cx: -0.49, - cy: -0.51, - stdx: 0.033 * s, - stdy: 0.033 * s, - }, - ]; - - let x = []; - let y = []; - let z = []; - let w = []; - - clusters.forEach(({ length, cx, cy, stdx, stdy }, i) => { - x = x.concat(Array.from({ length }, () => gaussianRandom(cx, stdx))); - y = y.concat(Array.from({ length }, () => gaussianRandom(cy, stdy))); - z = z.concat(Array.from({ length }, () => i)); - w = w.concat(Array.from({ length }, () => Math.random())); - }); - - return { x, y, z, w }; -}; - -const setNumPoints = (newNumPoints) => { - points = generatePoints(newNumPoints); - scatterplot.draw(points); -}; - -createMenu({ scatterplot, setNumPoints }); - -const colorsCat = ['#3a78aa', '#aa3a99']; -scatterplot.set({ colorBy: 'category', pointColor: colorsCat }); - -const colorsScale = ['#009E73', '#CC79A7', '#56B4E9', '#F0E442']; -scatterplot.set({ colorBy: 'z', pointColor: colorsScale }); - -setNumPoints(numPoints); - -scatterplot.drawAnnotations([ - { x: 0, lineColor: [1, 1, 1, 0.1], lineWidth: 1 }, - { y: 0, lineColor: [1, 1, 1, 0.1], lineWidth: 1 }, - { y: 0.5, x1: -0.9, x2: 0.9, lineColor: [1, 1, 1, 1], lineWidth: 1 }, - { - x1: -1, - y1: -1, - x2: 1, - y2: 1, - lineColor: [1, 1, 1, 0.25], - lineWidth: 1, - }, - { - x1: -0.5, - y1: -0.5, - x2: 0.5, - y2: 0.5, - lineColor: [1, 1, 1, 0.25], - lineWidth: 1, - }, - { - x1: -0.25, - y1: -0.25, - x2: 0.25, - y2: 0.25, - lineColor: [1, 1, 1, 0.25], - lineWidth: 1, - }, - { - vertices: [ - [-0.66, -0.5], - [-0.5, -0.33], - [-0.33, -0.45], - [-0.33, -0.6], - [-0.5, -0.7], - [-0.66, -0.5], - ], - lineColor: '#D55E00', - lineWidth: 1, - }, -]); diff --git a/example/axes.js b/example/axes.js deleted file mode 100644 index 5971cdfd..00000000 --- a/example/axes.js +++ /dev/null @@ -1,138 +0,0 @@ -import { axisBottom, axisRight } from 'd3-axis'; -import { scaleLinear } from 'd3-scale'; -import { select } from 'd3-selection'; - -import createScatterplot from '../src'; -import createMenu from './menu'; -import { checkSupport } from './utils'; - -const parentWrapper = document.querySelector('#parent-wrapper'); -const canvasWrapper = document.querySelector('#canvas-wrapper'); -const canvas = document.querySelector('#canvas'); - -const xDomain = [0, 42]; -const yDomain = [0, 4.2]; -const xScale = scaleLinear().domain(xDomain); -const yScale = scaleLinear().domain(yDomain); -const xAxis = axisBottom(xScale); -const yAxis = axisRight(yScale); -const axisContainer = select(parentWrapper).append('svg'); -const xAxisContainer = axisContainer.append('g'); -const yAxisContainer = axisContainer.append('g'); -const xAxisPadding = 20; -const yAxisPadding = 40; - -axisContainer.node().style.position = 'absolute'; -axisContainer.node().style.top = 0; -axisContainer.node().style.left = 0; -axisContainer.node().style.width = '100%'; -axisContainer.node().style.height = '100%'; -axisContainer.node().style.pointerEvents = 'none'; - -canvasWrapper.style.right = `${yAxisPadding}px`; -canvasWrapper.style.bottom = `${xAxisPadding}px`; - -let { width, height } = canvasWrapper.getBoundingClientRect(); - -xAxisContainer.attr('transform', `translate(0, ${height})`).call(xAxis); -yAxisContainer.attr('transform', `translate(${width}, 0)`).call(yAxis); - -// Render grid -xAxis.tickSizeInner(-height); -yAxis.tickSizeInner(-width); - -let points = []; -let numPoints = 100000; -let pointSize = 2; -let opacity = 0.5; -let selection = []; - -const selectHandler = ({ points: selectedPoints }) => { - console.log('Selected:', selectedPoints); - selection = selectedPoints; - if (selection.length === 1) { - const point = points[selection[0]]; - console.log( - `X: ${point[0]}\nY: ${point[1]}\nCategory: ${point[2]}\nValue: ${point[3]}` - ); - } -}; - -const deselectHandler = () => { - console.log('Deselected:', selection); - selection = []; -}; - -const scatterplot = createScatterplot({ - canvas, - pointSize, - opacity, - xScale, - yScale, - showReticle: true, - lassoInitiator: true, -}); - -checkSupport(scatterplot); - -console.log(`Scatterplot v${scatterplot.get('version')}`); - -scatterplot.subscribe('select', selectHandler); -scatterplot.subscribe('deselect', deselectHandler); -scatterplot.subscribe('view', (event) => { - xAxisContainer.call(xAxis.scale(event.xScale)); - yAxisContainer.call(yAxis.scale(event.yScale)); -}); - -scatterplot.subscribe( - 'init', - () => { - xAxisContainer.call(xAxis.scale(scatterplot.get('xScale'))); - yAxisContainer.call(yAxis.scale(scatterplot.get('yScale'))); - }, - 1 -); - -const resizeHandler = () => { - ({ width, height } = canvasWrapper.getBoundingClientRect()); - - xAxisContainer.attr('transform', `translate(0, ${height})`).call(xAxis); - yAxisContainer.attr('transform', `translate(${width}, 0)`).call(yAxis); - - // Render grid - xAxis.tickSizeInner(-height); - yAxis.tickSizeInner(-width); -}; - -window.addEventListener('resize', resizeHandler); -window.addEventListener('orientationchange', resizeHandler); - -const generatePoints = (num) => - new Array(num).fill().map(() => [ - -1 + Math.random() * 2, // x - -1 + Math.random() * 2, // y - Math.round(Math.random() * 9), // category - Math.random(), // value - ]); - -const setNumPoints = (newNumPoints) => { - points = generatePoints(newNumPoints); - scatterplot.draw(points); -}; - -createMenu({ scatterplot, setNumPoints }); - -scatterplot.set({ - colorBy: 'category', - pointColor: [ - '#d192b7', - '#6fb2e4', - '#eecb62', - '#56bf92', - '#dca237', - '#3a84cc', - '#c76526', - ], -}); - -setNumPoints(numPoints); diff --git a/example/connected-points-by-segments.js b/example/connected-points-by-segments.js deleted file mode 100644 index 5124b011..00000000 --- a/example/connected-points-by-segments.js +++ /dev/null @@ -1,123 +0,0 @@ -import createScatterplot from '../src'; -import createMenu from './menu'; -import { checkSupport } from './utils'; - -const canvas = document.querySelector('#canvas'); - -let points = []; -let numPoints = 9000; -let pointSize = 1; -let opacity = 0.33; -let selection = []; - -const pointSizeMax = 10; -const lassoMinDelay = 10; -const lassoMinDist = 2; -const showReticle = true; -const reticleColor = [1, 1, 0.878431373, 0.33]; -const showPointConnections = true; -const pointConnectionColor = [1, 1, 1, 0.15]; -const pointConnectionSize = 2; - -const selectHandler = ({ points: selectedPoints }) => { - console.log('Selected:', selectedPoints); - selection = selectedPoints; - if (selection.length === 1) { - const point = points[selection[0]]; - console.log( - `X: ${point[0]}\nY: ${point[1]}\nCategory: ${point[2]}\nValue: ${point[3]}` - ); - } -}; - -const deselectHandler = () => { - console.log('Deselected:', selection); - selection = []; -}; - -const scatterplot = createScatterplot({ - canvas, - lassoMinDelay, - lassoMinDist, - pointSize, - opacity, - showReticle, - reticleColor, - showPointConnections, - pointConnectionColor, - pointConnectionSize, - lassoInitiator: true, -}); - -checkSupport(scatterplot); - -console.log(`Scatterplot v${scatterplot.get('version')}`); - -scatterplot.subscribe('select', selectHandler); -scatterplot.subscribe('deselect', deselectHandler); - -const generatePoints = (num) => { - const numPointsPerGroup = Math.round(num / 3); // 9.000 / 3 => 3000 - const numPointsPerStep = Math.round(numPointsPerGroup / 5); // 3000 / 5 => 600 - // 600 * 3 => 1800 (lines) - - const outPoints = []; - - for (let g = 0; g < 3; g++) { - for (let i = 0; i < numPointsPerStep; i++) { - for (let s = 0; s < 5; s++) { - outPoints.push([ - -0.6 + g * 0.6 + (Math.random() * 0.3 - 0.15), // x - -0.9 + s * 0.45, // y - g, // category - Math.random(), // value - g * numPointsPerStep + i, // to identify connected points - ]); - } - } - } - - return outPoints; -}; - -const setNumPoints = (newNumPoints) => { - points = generatePoints(newNumPoints); - scatterplot.draw(points); -}; - -const getPointSizeRange = (basePointSize) => - Array.from( - { length: 100 }, - (_, i) => 1 + (i / 99) * (basePointSize * pointSizeMax - 1) - ); - -const setPointSize = (newPointSize) => { - scatterplot.set({ pointSize: getPointSizeRange(newPointSize) }); -}; - -createMenu({ scatterplot, setNumPoints, setPointSize }); - -scatterplot.set({ - colorBy: 'valueZ', - sizeBy: 'valueW', - pointColor: [ - [255, 128, 203, 128], - [87, 199, 255, 128], - [238, 228, 98, 128], - ], - pointConnectionColorBy: 'segment', - pointConnectionColor: Array(200) - .fill() - .map((v, i) => [i + 55, i + 55, i + 55, 10]), - pointConnectionSizeBy: 'segment', - pointConnectionSize: Array(20) - .fill() - .map((v, i) => 1 + i / 4), - pointConnectionOpacityBy: 'segment', - pointConnectionOpacity: Array(64) - .fill() - .map((v, i) => (i + 8) / 256), -}); - -setPointSize(pointSize) -setNumPoints(numPoints); diff --git a/example/connected-points.js b/example/connected-points.js deleted file mode 100644 index 2b12a3b7..00000000 --- a/example/connected-points.js +++ /dev/null @@ -1,136 +0,0 @@ -import createScatterplot from '../src'; -import createMenu from './menu'; -import { checkSupport } from './utils'; - -const canvas = document.querySelector('#canvas'); - -let points = []; -let numPoints = 9000; -let pointSize = 1; -let opacity = 0.33; -let selection = []; - -const pointSizeMax = 10; -const lassoMinDelay = 10; -const lassoMinDist = 2; -const showReticle = true; -const reticleColor = [1, 1, 0.878431373, 0.33]; -const showPointConnections = true; -const pointConnectionColor = [1, 1, 1, 0.15]; -const pointConnectionSize = 2; - -const selectHandler = ({ points: selectedPoints }) => { - console.log('Selected:', selectedPoints); - selection = selectedPoints; - if (selection.length === 1) { - const point = points[selection[0]]; - console.log( - `X: ${point[0]}\nY: ${point[1]}\nCategory: ${point[2]}\nValue: ${point[3]}` - ); - } -}; - -const deselectHandler = () => { - console.log('Deselected:', selection); - selection = []; -}; - -const scatterplot = createScatterplot({ - canvas, - lassoMinDelay, - lassoMinDist, - pointSize, - opacity, - showReticle, - reticleColor, - showPointConnections, - pointConnectionColor, - pointConnectionSize, - lassoInitiator: true, -}); - -checkSupport(scatterplot); - -console.log(`Scatterplot v${scatterplot.get('version')}`); - -scatterplot.subscribe('select', selectHandler); -scatterplot.subscribe('deselect', deselectHandler); - -const generatePoints = (num) => { - const numPointsPerGroup = Math.round(num / 3); // 9.000 / 3 => 3000 - const numPointsPerStep = Math.round(numPointsPerGroup / 5); // 3000 / 5 => 600 - // 600 * 3 => 1800 (lines) - - const outPoints = []; - - for (let g = 0; g < 3; g++) { - for (let i = 0; i < numPointsPerStep; i++) { - for (let s = 0; s < 5; s++) { - outPoints.push([ - -0.6 + g * 0.6 + (Math.random() * 0.3 - 0.15), // x - -0.9 + s * 0.45, // y - g, // category - Math.random(), // value - g * numPointsPerStep + i, // to identify connected points - // (s + 2) % 5, // specifies the order of the connected points - ]); - } - } - } - - return outPoints; -}; - -const setNumPoints = (newNumPoints) => { - points = generatePoints(newNumPoints); - scatterplot.draw(points); -}; - -const getPointSizeRange = (basePointSize) => - Array.from( - { length: 100 }, - (_, i) => 1 + (i / 99) * (basePointSize * pointSizeMax - 1) - ); - -const setPointSize = (newPointSize) => { - scatterplot.set({ pointSize: getPointSizeRange(newPointSize) }); -}; - -createMenu({ scatterplot, setNumPoints, setPointSize }); - -scatterplot.set({ - colorBy: 'valueZ', - sizeBy: 'valueW', - pointColor: [ - [255, 128, 203, 128], - [87, 199, 255, 128], - [238, 228, 98, 128], - ], - pointConnectionColorBy: 'valueZ', - pointConnectionColor: [ - [255, 128, 203, 6], - [87, 199, 255, 6], - [238, 228, 98, 6], - ], - pointConnectionColorActive: [ - [255, 128, 203, 128], - [87, 199, 255, 128], - [238, 228, 98, 128], - ], - pointConnectionColorHover: [ - [255, 128, 203, 99], - [87, 199, 255, 99], - [238, 228, 98, 99], - ], - pointConnectionOpacityBy: 'valueW', - pointConnectionOpacity: Array(10) - .fill() - .map((v, i) => (i + 1) / 100), - pointConnectionSizeBy: 'valueW', - pointConnectionSize: Array(18) - .fill() - .map((v, i) => (i + 1) / 2), -}); - -setPointSize(pointSize); -setNumPoints(numPoints); diff --git a/example/dynamic-opacity.js b/example/dynamic-opacity.js deleted file mode 100644 index 2e5a212a..00000000 --- a/example/dynamic-opacity.js +++ /dev/null @@ -1,122 +0,0 @@ -import createScatterplot from '../src'; -import createMenu from './menu'; -import { checkSupport } from './utils'; - -const canvas = document.querySelector('#canvas'); - -let points = []; -let numPoints = 1000000; -let pointSize = 2; -let opacityByDensityFill = 0.15; -let selection = []; - -const lassoMinDelay = 10; -const lassoMinDist = 2; -const showReticle = true; -const reticleColor = [1, 1, 0.878431373, 0.33]; - -const selectHandler = ({ points: selectedPoints }) => { - console.log('Selected:', selectedPoints); - selection = selectedPoints; - if (selection.length === 1) { - const point = points[selection[0]]; - console.log( - `X: ${point[0]}\nY: ${point[1]}\nCategory: ${point[2]}\nValue: ${point[3]}` - ); - } -}; - -const deselectHandler = () => { - console.log('Deselected:', selection); - selection = []; -}; - -const scatterplot = createScatterplot({ - canvas, - lassoMinDelay, - lassoMinDist, - pointSize, - pointColor: '#fff', - opacityBy: 'density', - showReticle, - reticleColor, - lassoInitiator: true, -}); - -checkSupport(scatterplot); - -console.log(`Scatterplot v${scatterplot.get('version')}`); - -scatterplot.subscribe('select', selectHandler); -scatterplot.subscribe('deselect', deselectHandler); - -const generatePoints = (num) => { - const newPoints = []; - - let xn = 2.644838333129883; - let yn = 4.060488700866699; - let zn = 2.8982460498809814; - let xn1; - let yn1; - let zn1; - const a = 0.2; - const b = 0.2; - const c = 5.7; - const dt = 0.006; - - let minX = Infinity; - let maxX = -Infinity; - let minY = Infinity; - let maxY = -Infinity; - for (let i = 0; i <= num; i++) { - let dx = -yn - zn; - let dy = xn + a * yn; - let dz = b + zn * (xn - c); - - const xh = xn + 0.5 * dt * dx; - const yh = yn + 0.5 * dt * dy; - const zh = zn + 0.5 * dt * dz; - - dx = -yh - zh; - dy = xh + a * yh; - dz = b + zh * (xh - c); - - xn1 = xn + dt * dx; - yn1 = yn + dt * dy; - zn1 = zn + dt * dz; - - newPoints.push([xn1, yn1, 0, 0]); - - minX = xn1 < minX ? xn1 : minX; - maxX = xn1 > maxX ? xn1 : maxX; - minY = yn1 < minY ? yn1 : minY; - maxY = yn1 > maxY ? yn1 : maxY; - - xn = xn1; - yn = yn1; - zn = zn1; - } - - const dX = maxX - minX; - const dY = maxY - minY; - - for (let i = 0; i <= num; i++) { - newPoints[i][0] -= minX; - newPoints[i][0] /= dX / 2; - newPoints[i][0] -= 1; - newPoints[i][1] -= minY; - newPoints[i][1] /= dY / 2; - newPoints[i][1] -= 1; - } - - return newPoints; -}; - -const setNumPoints = (newNumPoints) => { - points = generatePoints(newNumPoints); - scatterplot.draw(points); -}; - -createMenu({ scatterplot, setNumPoints }); - -setNumPoints(numPoints); diff --git a/example/embedded.js b/example/embedded.js deleted file mode 100644 index 16864eeb..00000000 --- a/example/embedded.js +++ /dev/null @@ -1,136 +0,0 @@ -import createScatterplot from '../src'; -import createMenu from './menu'; -import { saveAsPng, checkSupport } from './utils'; - -const canvas = document.querySelector('#canvas'); -const numPointsEl = document.querySelector('#num-points'); -const numPointsValEl = document.querySelector('#num-points-value'); -const pointSizeEl = document.querySelector('#point-size'); -const pointSizeValEl = document.querySelector('#point-size-value'); -const opacityEl = document.querySelector('#opacity'); -const opacityValEl = document.querySelector('#opacity-value'); -const clickLassoInitiatorEl = document.querySelector('#click-lasso-initiator'); -const resetEl = document.querySelector('#reset'); -const exportEl = document.querySelector('#export'); -const exampleEl = document.querySelector('#example-basic'); - -const canvasWrapper = canvas.parentNode; -canvasWrapper.style.padding = '15rem 0'; -canvasWrapper.style.height = '100vh'; -canvasWrapper.parentNode.style.overflow = 'auto'; - -exampleEl.setAttribute('class', 'active'); -exampleEl.removeAttribute('href'); - -let points = []; -let numPoints = 100000; -let pointSize = 4; -let opacity = 0.33; -let selection = []; - -const reticleColor = [1, 1, 0.878431373, 0.33]; - -const selectHandler = ({ points: selectedPoints }) => { - selection = selectedPoints; - if (selection.length === 1) { - const point = points[selection[0]]; - console.log( - `Selected: ${selectedPoints}`, - `X: ${point[0]}\nY: ${point[1]}\nCategory: ${point[2]}\nValue: ${point[3]}` - ); - } -}; - -const deselectHandler = () => { - selection = []; -}; - -const scatterplot = createScatterplot({ - canvas, - pointSize, - showReticle: true, - reticleColor, - lassoInitiator: true, -}); - -checkSupport(scatterplot); - -exportEl.addEventListener('click', () => saveAsPng(scatterplot)); - -console.log(`Scatterplot v${scatterplot.get('version')}`); - -scatterplot.subscribe('select', selectHandler); -scatterplot.subscribe('deselect', deselectHandler); - -const generatePoints = (num) => - new Array(num).fill().map(() => [ - -0.8 + Math.random() * 1.6, // x - -0.8 + Math.random() * 1.6, // y - Math.round(Math.random()), // category - Math.random(), // value - ]); - -const setNumPoints = (newNumPoints) => { - numPoints = newNumPoints; - numPointsEl.value = numPoints; - numPointsValEl.innerHTML = numPoints; - points = generatePoints(numPoints); - scatterplot.draw(points); -}; - -createMenu({ scatterplot, setNumPoints }); - -const numPointsInputHandler = (event) => { - numPointsValEl.innerHTML = `${+event.target - .value} release to redraw`; -}; - -numPointsEl.addEventListener('input', numPointsInputHandler); - -const numPointsChangeHandler = (event) => setNumPoints(+event.target.value); - -numPointsEl.addEventListener('change', numPointsChangeHandler); - -const setPointSize = (newPointSize) => { - pointSize = newPointSize; - pointSizeEl.value = pointSize; - pointSizeValEl.innerHTML = pointSize; - scatterplot.set({ pointSize }); -}; - -const pointSizeInputHandler = (event) => setPointSize(+event.target.value); - -pointSizeEl.addEventListener('input', pointSizeInputHandler); - -const setOpacity = (newOpacity) => { - opacity = newOpacity; - opacityEl.value = opacity; - opacityValEl.innerHTML = opacity; - scatterplot.set({ opacity }); -}; - -const opacityInputHandler = (event) => setOpacity(+event.target.value); - -opacityEl.addEventListener('input', opacityInputHandler); - -const clickLassoInitiatorChangeHandler = (event) => { - scatterplot.set({ - lassoInitiator: event.target.checked, - }); -}; - -clickLassoInitiatorEl.addEventListener( - 'change', - clickLassoInitiatorChangeHandler -); -clickLassoInitiatorEl.checked = scatterplot.get('lassoInitiator'); - -const resetClickHandler = () => { - scatterplot.reset(); -}; - -resetEl.addEventListener('click', resetClickHandler); - -setPointSize(pointSize); -setOpacity(opacity); -setNumPoints(numPoints); diff --git a/example/index.js b/example/index.js deleted file mode 100644 index c012fa4f..00000000 --- a/example/index.js +++ /dev/null @@ -1,121 +0,0 @@ -import createScatterplot from '../src'; -import createMenu from './menu'; -import { checkSupport } from './utils'; - -const canvas = document.querySelector('#canvas'); - -let points = { x: [], y: [], z: [], w: [] }; -let numPoints = 100000; -let pointSize = 2; -let opacity = 0.33; -let selection = []; - -const lassoMinDelay = 10; -const lassoMinDist = 2; -const showReticle = true; -const reticleColor = [1, 1, 0.878431373, 0.33]; - -const pointoverHandler = (pointId) => { - const x = points.x[pointId]; - const y = points.y[pointId]; - const category = points.z[pointId]; - const value = points.w[pointId]; - console.log( - `Out point: ${pointId}`, - `X: ${x}\nY: ${y}\nCategory: ${category}\nValue: ${value}` - ); -}; - -const pointoutHandler = (pointId) => { - const x = points.x[pointId]; - const y = points.y[pointId]; - const category = points.z[pointId]; - const value = points.w[pointId]; - console.log( - `Out point: ${pointId}`, - `X: ${x}\nY: ${y}\nCategory: ${category}\nValue: ${value}` - ); -}; - -const selectHandler = ({ points: selectedPoints }) => { - selection = selectedPoints; - if (selection.length === 1) { - const x = points.x[selection[0]]; - const y = points.y[selection[0]]; - const category = points.z[selection[0]]; - const value = points.w[selection[0]]; - console.log( - `Selected: ${selectedPoints}`, - `X: ${x}\nY: ${y}\nCategory: ${category}\nValue: ${value}` - ); - } -}; - -const deselectHandler = () => { - console.log('Deselected:', selection); - selection = []; -}; - -const scatterplot = createScatterplot({ - canvas, - lassoMinDelay, - lassoMinDist, - pointSize, - showReticle, - reticleColor, - opacity, - lassoOnLongPress: true, - lassoType: 'brush' -}); - -checkSupport(scatterplot); - -console.log(`Scatterplot v${scatterplot.get('version')}`); - -scatterplot.subscribe('pointover', pointoverHandler); -scatterplot.subscribe('pointout', pointoutHandler); -scatterplot.subscribe('select', selectHandler); -scatterplot.subscribe('deselect', deselectHandler); - -const generatePoints = (length) => ({ - x: Array.from({ length }, () => -1 + Math.random() * 2), - y: Array.from({ length }, () => -1 + Math.random() * 2), - z: Array.from({ length }, () => Math.round(Math.random())), // category - w: Array.from({ length }, () => Math.random()), // value -}); - -const setNumPoints = (newNumPoints) => { - points = generatePoints(numPoints); - scatterplot.draw(points); -}; - -createMenu({ scatterplot, setNumPoints }); - -const colorsCat = ['#3a78aa', '#aa3a99']; -scatterplot.set({ colorBy: 'category', pointColor: colorsCat }); - -const colorsScale = [ - '#002072', // dark blue - '#162b79', - '#233680', - '#2e4186', - '#394d8d', - '#425894', - '#4b649a', - '#5570a1', - '#5e7ca7', - '#6789ae', - '#7195b4', - '#7ba2ba', - '#85aec0', - '#90bbc6', - '#9cc7cc', - '#a9d4d2', - '#b8e0d7', - '#c8ecdc', - '#ddf7df', - '#ffffe0', // bright yellow -]; -scatterplot.set({ colorBy: 'value', pointColor: colorsScale }); - -setNumPoints(numPoints); diff --git a/example/menu.js b/example/menu.js deleted file mode 100644 index 8224f4f4..00000000 --- a/example/menu.js +++ /dev/null @@ -1,313 +0,0 @@ -import { Pane } from 'tweakpane'; - -import { LinkPlugin } from './tweakpane-link-plugin'; -import { saveAsPng } from './utils'; - -const DEFAULT_PARAMS = { - numPoints: 100000, - pointSize: 2, - opacity: 0.33, - opacityByDensity: false, - lassoInit: 'longPress', - lassoType: 'freeform', - lassoBrushSize: 24, -}; - -const set = (scatterplot, keyValuePairs) => { - if (Array.isArray(scatterplot)) { - for (const s of scatterplot) { - s.set(keyValuePairs); - } - } else { - scatterplot.set(keyValuePairs); - } -} - -export function createMenu({ - scatterplot, - setNumPoints, - setPointSize, - setOpacity, - opacityChangesDisabled, -}) { - let init = false; - - const refScatterplot = Array.isArray(scatterplot) - ? scatterplot[0] - : scatterplot; - - const params = { - ...DEFAULT_PARAMS, - numPoints: 0, - pointSize: Array.isArray(refScatterplot.get('pointSize')) - ? refScatterplot.get('pointSize')[0] - : refScatterplot.get('pointSize'), - opacity: refScatterplot.get('opacity'), - opacityByDensity: refScatterplot.get('opacityBy') === 'density', - lassoType: refScatterplot.get('lassoType'), - lassoBrushSize: refScatterplot.get('lassoBrushSize'), - }; - const initialParams = { ...params }; - - const pane = new Pane({ - title: 'Details', - container: document.getElementById('controls'), - }); - pane.registerPlugin({ id: 'link', plugins: [LinkPlugin] }); - - const settings = pane.addFolder({ title: 'Settings' }); - - const numPoints = settings.addBinding( - params, - 'numPoints', - { label: 'Num Points', min: 1000, step: 1000, max: 2000000 } - ); - numPoints.disabled = true; - if (setNumPoints) { - numPoints.on('change', ({ last, value }) => { - if (init && last) setNumPoints(value); - }); - } - - const pointSize = settings.addBinding( - params, 'pointSize', { label: 'Point Size', min: 1, max: 32, step: 1 } - ); - pointSize.disabled = Array.isArray(refScatterplot.get('pointSize')); - pointSize.on('change', ({ value }) => { - if (setPointSize) { - setPointSize(value); - } else { - set(scatterplot, { pointSize: value }); - } - }); - - const opacity = settings.addBinding( - params, - 'opacity', - { label: 'Opacity', min: 0.01, max: 1, step: 0.01 } - ); - opacity.disabled = params.opacityByDensity || Boolean(opacityChangesDisabled); - opacity.on('change', ({ value }) => { - if (setOpacity) { - setOpacity(value); - } else { - set(scatterplot, { opacity: value }); - } - }); - - const opacityByDensity = settings.addBinding( - params, - 'opacityByDensity', - { label: 'Dynamic Opacity' } - ); - opacityByDensity.disabled = Boolean(opacityChangesDisabled); - opacityByDensity.on('change', ({ value }) => { - set(scatterplot, { opacityBy: value ? 'density' : null }); - opacity.disabled = value; - }); - - const lassoInit = settings.addBinding( - params, - 'lassoInit', - { - label: 'Lasso Init', - options: { - 'On Long Press': 'longPress', - 'Via Click Initiator': 'clickInitiator' - } - } - ); - lassoInit.on('change', ({ value }) => { - switch (value) { - case 'longPress': { - set(scatterplot, { - lassoInitiator: false, - lassoOnLongPress: true, - }); - break; - } - case 'clickInitiator': { - set(scatterplot, { - lassoInitiator: true, - lassoOnLongPress: false, - }); - break; - } - } - }); - - const lassoType = settings.addBinding( - params, - 'lassoType', - { - label: 'Lasso Type', - options: { - 'Freeform': 'freeform', - 'Brush': 'brush', - 'Rectangle': 'rectangle', - } - } - ); - lassoType.on('change', ({ value }) => { - switch (value) { - case 'freeform': { - set(scatterplot, { lassoType: 'freeform' }); - break; - } - case 'brush': { - set(scatterplot, { lassoType: 'brush' }); - break; - } - case 'rectangle': { - set(scatterplot, { lassoType: 'rectangle' }); - break; - } - } - lassoBrushSize.hidden = value !== 'brush'; - }); - - const lassoBrushSize = settings.addBinding( - params, - 'lassoBrushSize', - { label: 'Brush Size', min: 1, max: 256, step: 1 } - ); - lassoBrushSize.hidden = params.lassoType !== 'brush'; - lassoBrushSize.on('change', ({ value }) => { - set(scatterplot, { lassoBrushSize: value }); - }); - - const reset = settings.addButton({ title: 'Reset' }); - reset.on('click', () => { - for (const [key, value] of Object.entries(initialParams)) { - params[key] = value; - } - pane.refresh(); - }) - - const examples = pane.addFolder({ title: 'Examples' }); - - const pathname = window.location.pathname.slice(1); - - examples.addBlade({ - view: 'link', - label: 'Color Encoding', - link: 'index.html', - active: pathname === '' || pathname === 'index.html', - }); - - examples.addBlade({ - view: 'link', - label: 'Size & Opacity Encoding', - link: 'size-encoding.html', - active: pathname === 'size-encoding.html', - }); - - examples.addBlade({ - view: 'link', - label: 'Dynamic Opacity', - link: 'dynamic-opacity.html', - active: pathname === 'dynamic-opacity.html', - }); - - examples.addBlade({ - view: 'link', - label: 'Axes', - link: 'axes.html', - active: pathname === 'axes.html', - }); - - examples.addBlade({ - view: 'link', - label: 'Text Labels', - link: 'text-labels.html', - active: pathname === 'text-labels.html', - }); - - examples.addBlade({ - view: 'link', - label: 'Annotations', - link: 'annotations.html', - active: pathname === 'annotations.html', - }); - - examples.addBlade({ - view: 'link', - label: 'Programmatic Lasso', - link: 'programmatic-lasso.html', - active: pathname === 'programmatic-lasso.html', - }); - - examples.addBlade({ - view: 'link', - label: 'Multiple Instances', - link: 'multiple-instances.html', - active: pathname === 'multiple-instances.html', - }); - - examples.addBlade({ - view: 'link', - label: 'Transition', - link: 'transition.html', - active: pathname === 'transition.html', - }); - - examples.addBlade({ - view: 'link', - label: 'Point Connections', - link: 'connected-points.html', - active: pathname === 'connected-points.html', - }); - - examples.addBlade({ - view: 'link', - label: 'Point Connections by Line Segments', - link: 'connected-points-by-segments.html', - active: pathname === 'connected-points-by-segments.html', - }); - - examples.addBlade({ - view: 'link', - label: 'Background Image', - link: 'texture-background.html', - active: pathname === 'texture-background.html', - }); - - examples.addBlade({ - view: 'link', - label: 'Performance Mode (20M Points)', - link: 'performance-mode.html', - active: pathname === 'performance-mode.html', - }); - - const info = pane.addFolder({ title: 'Info', expanded: false }); - - info.addBlade({ - view: 'text', - label: 'version', - parse: (v) => String(v), - value: refScatterplot.get('version'), - disabled: true, - }); - - const download = pane.addButton({ title: 'Download as PNG' }); - download.on('click', () => { - saveAsPng(scatterplot); - }); - - const sourceCode = pane.addButton({ title: 'Source Code' }); - sourceCode.on('click', () => { - window.open( - 'https://github.com/flekschas/regl-scatterplot', '_blank' - ).focus(); - }); - - refScatterplot.subscribe('draw', () => { - params.numPoints = refScatterplot.get('points').length; - initialParams.numPoints = params.numPoints; - if (setNumPoints) numPoints.disabled = false; - pane.refresh(); - init = true; - }, 1); -} - -export default createMenu; diff --git a/example/multiple-instances.js b/example/multiple-instances.js deleted file mode 100644 index 0faeae47..00000000 --- a/example/multiple-instances.js +++ /dev/null @@ -1,245 +0,0 @@ -/* eslint no-console: 0 */ -import { tableFromIPC } from 'apache-arrow'; -import createScatterplot, { createRenderer } from '../src'; -import createMenu from './menu'; -import { showModal, closeModal } from './utils'; - -/** - * General configuration - */ -const NUM_COLUMNS = 2; -const NUM_ROWS = 2; -const POINT_SIZE = 3; -const OPACITY = 0.66; -const FASHION_MNIST_CLASS_LABELS = [ - 'T-shirt/top', - 'Trouser', - 'Pullover', - 'Dress', - 'Coat', - 'Sandal', - 'Shirt', - 'Sneaker', - 'Bag', - 'Ankle boot', -]; -const CLASS_COLORS = [ - '#FFFF00', - '#1CE6FF', - '#FF34FF', - '#FF4A46', - '#008941', - '#006FA6', - '#A30059', - '#FFDBE5', - '#7A4900', - '#0000A6', -]; - -/** - * Load Embedding Example - */ -const whenData = fetch( - 'https://storage.googleapis.com/flekschas/regl-scatterplot/fashion-mnist-embeddings.arrow' -); - -/** - * Modal - */ -showModal('Loading...'); - -/** - * Add info to footer - */ -const footer = document.querySelector('#footer'); -footer.classList.remove('hidden'); -const infoContent = document.querySelector('#info-content'); -infoContent.innerHTML = ` -

Fashion MNIST embedding using four different techniques: PCA, t-SNE, UMAP, and a convolutional autoencoder.

-

Select a point so see the corresponding image.

-`; - -/** - * Note - */ -const parentWrapper = document.querySelector('#parent-wrapper'); -const noteEl = document.createElement('div'); -noteEl.id = 'note'; -noteEl.style.opacity = 0; -parentWrapper.appendChild(noteEl); - -const showNote = (text, color) => { - noteEl.style.opacity = 1; - noteEl.style.background = color; - noteEl.textContent = text; -}; - -const hideNote = () => { - noteEl.style.opacity = 0; -}; - -/** - * Image - */ -const centerNoteEl = document.createElement('div'); -centerNoteEl.id = 'center-note'; -centerNoteEl.style.opacity = 0; -const imgEl = document.createElement('div'); -imgEl.style.width = '56px'; -imgEl.style.height = '56px'; -imgEl.style.backgroundColor = 'black'; -imgEl.style.backgroundSize = 'cover'; -imgEl.style.backgroundRepeat = 'no-repeat'; -centerNoteEl.appendChild(imgEl); -parentWrapper.appendChild(centerNoteEl); - -const zeroPad = (num, places) => String(num).padStart(places, '0'); - -const showImg = (pointId, classId) => { - const img = new Image(); - const imgId = zeroPad(pointId, 5); - const src = `https://storage.googleapis.com/flekschas/regl-scatterplot/fashion-mnist-images/${imgId}.png`; - img.onload = () => { - centerNoteEl.style.opacity = 1; - centerNoteEl.style.transform = 'translate(-50%, -50%) scale(1)'; - imgEl.style.backgroundImage = `url("${src}")`; - centerNoteEl.style.background = CLASS_COLORS[classId]; - }; - img.src = src; -}; - -const hideImg = () => { - centerNoteEl.style.opacity = 0; - centerNoteEl.style.transform = 'translate(-50%, -50%) scale(0)'; -}; - -/** - * Set up the HTML template - */ -parentWrapper.style.display = 'grid'; -parentWrapper.style.gridTemplateColumns = `repeat(${NUM_COLUMNS}, minmax(0, 1fr))`; -parentWrapper.style.gridTemplateRows = `repeat(2, minmax(0, 1fr))`; -parentWrapper.style.gap = '1rem'; - -const baseCanvas = document.querySelector('#canvas'); -const baseCanvasWrapper = document.querySelector('#canvas-wrapper'); -baseCanvasWrapper.style.position = 'relative'; - -const canvases = [baseCanvas]; - -for (let i = 0; i < NUM_COLUMNS * NUM_ROWS - 1; i++) { - const newCanvas = baseCanvas.cloneNode(); - const newCanvasWrapper = baseCanvasWrapper.cloneNode(); - newCanvasWrapper.appendChild(newCanvas); - parentWrapper.appendChild(newCanvasWrapper); - canvases.push(newCanvas); -} - -/** - * Create a reusable renderer - */ -const renderer = createRenderer(); - -if (!renderer.isSupported) { - showModal( - 'Unfortunately, your browser does not support all WebGL extensions required by regl-scatterplot', - true - ); -} - -/** - * Create a scatter plot instances - */ - -const scatterplots = canvases.map((canvas) => - createScatterplot({ - renderer, - canvas, - pointSize: POINT_SIZE, - opacity: OPACITY, - lassoOnLongPress: true, - }) -); - -console.log(`Scatterplot v${scatterplots[0].get('version')}`); - -createMenu({ scatterplot: scatterplots }); - -/** - * Link scatter plots - */ -const syncSelection = (source, selectedPoints, classIds) => { - scatterplots - .filter((sp) => sp !== source) - .forEach((sp) => { - sp.select(selectedPoints, { preventEvent: true }); - }); - - scatterplots.forEach((sp) => { - sp.zoomToPoints(selectedPoints, { - padding: 0.2, - transition: true, - transitionDuration: 1500, - }); - }); - - const pointId = - selectedPoints[Math.floor(Math.random() * (selectedPoints.length - 1))]; - showImg(pointId, classIds[pointId]); -}; - -const syncDeselection = (source) => { - scatterplots - .filter((sp) => sp !== source) - .forEach((sp) => { - sp.deselect({ preventEvent: true }); - }); - - scatterplots.forEach((sp) => { - sp.zoomToOrigin({ - transition: true, - transitionDuration: 1500, - }); - }); - - hideImg(); -}; - -/** - * Finally, draw points 🎉 - */ - -whenData - .then((data) => tableFromIPC(data)) - .then((table) => { - closeModal(); - const columnValues = table.data[0].children.map((data) => data.values); - const classIds = columnValues[columnValues.length - 1]; - - scatterplots.forEach((sp, i) => { - sp.draw({ - x: columnValues[i * 2], - y: columnValues[i * 2 + 1], - z: classIds, - }); - sp.set({ - colorBy: 'z', - pointColor: CLASS_COLORS, - }); - sp.subscribe('pointover', (pointId) => { - showNote( - FASHION_MNIST_CLASS_LABELS[classIds[pointId]], - CLASS_COLORS[classIds[pointId]] - ); - }); - sp.subscribe('pointout', hideNote); - sp.subscribe('select', ({ points }) => - syncSelection(sp, points, classIds) - ); - sp.subscribe('deselect', () => syncDeselection(sp)); - }); - }) - .catch((error) => { - showModal('Could not load embedding... Damn...', true); - console.error(error); - }); diff --git a/example/performance-mode-point-worker.js b/example/performance-mode-point-worker.js deleted file mode 100644 index 25d495dc..00000000 --- a/example/performance-mode-point-worker.js +++ /dev/null @@ -1,41 +0,0 @@ -/* eslint-env worker */ -/* eslint no-restricted-globals: 1 */ - -const worker = function worker() { - self.onmessage = function onmessage(event) { - const num = event.data; - const bins = 10; - - try { - let points = []; - - const range = 2 / bins; - const numPerBin = num / bins ** 2; - - for (let i = 0; i < bins; i++) { - for (let j = 0; j < bins; j++) { - const xStart = -1 + j * range; - const yStart = -1 + i * range; - const tmp = []; - for (let k = 0; k < numPerBin; k++) { - tmp.push([ - xStart + Math.random() * range, // x - yStart + Math.random() * range, // y - Math.round(Math.random()), // category - Math.random(), // value - ]); - } - points = points.concat( - tmp.sort((a, b) => a[0] - b[0] || a[1] - b[1]) - ); - } - } - - self.postMessage({ points }); - } catch (error) { - self.postMessage({ error }); - } - }; -}; - -export default worker; diff --git a/example/performance-mode.js b/example/performance-mode.js deleted file mode 100644 index 44da2269..00000000 --- a/example/performance-mode.js +++ /dev/null @@ -1,186 +0,0 @@ -import { createWorker } from '@flekschas/utils'; -import { saveAsPng, checkSupport } from './utils'; - -import createScatterplot from '../src'; -import createMenu from './menu'; -import pointWorkerFn from './performance-mode-point-worker'; - -const modal = document.querySelector('#modal'); -const modalText = document.querySelector('#modal span'); -const canvas = document.querySelector('#canvas'); -const numPointsEl = document.querySelector('#num-points'); -const numPointsValEl = document.querySelector('#num-points-value'); -const pointSizeEl = document.querySelector('#point-size'); -const pointSizeValEl = document.querySelector('#point-size-value'); -const opacityEl = document.querySelector('#opacity'); -const opacityValEl = document.querySelector('#opacity-value'); -const clickLassoInitiatorEl = document.querySelector('#click-lasso-initiator'); -const resetEl = document.querySelector('#reset'); -const exportEl = document.querySelector('#export'); -const exampleEl = document.querySelector('#example-performance-mode'); - -exampleEl.setAttribute('class', 'active'); -exampleEl.removeAttribute('href'); - -let points = []; -let numPoints = 20000000; -let pointSize = 0.25; -let opacity = 0.33; -let selection = []; - -const lassoMinDelay = 10; -const lassoMinDist = 2; - -const pointWorker = createWorker(pointWorkerFn); - -const generatePoints = (num) => - new Promise((resolve, reject) => { - pointWorker.onmessage = (e) => { - if (e.data.error) reject(e.data.error); - else resolve(e.data.points); - }; - pointWorker.postMessage(num); - }); - -const showModal = (text) => { - modal.style.display = 'flex'; - modalText.textContent = text; -}; - -const closeModal = () => { - modal.style.display = 'none'; - modalText.textContent = ''; -}; - -const selectHandler = ({ points: selectedPoints }) => { - console.log('Selected:', selectedPoints); - selection = selectedPoints; - if (selection.length === 1) { - const point = points[selection[0]]; - console.log( - `X: ${point[0]}\nY: ${point[1]}\nCategory: ${point[2]}\nValue: ${point[3]}` - ); - } -}; - -const deselectHandler = () => { - console.log('Deselected:', selection); - selection = []; -}; - -const scatterplot = createScatterplot({ - canvas, - lassoMinDelay, - lassoMinDist, - pointSize, - showReticle: true, - performanceMode: true, - lassoInitiator: true, -}); - -checkSupport(scatterplot); - -exportEl.addEventListener('click', () => saveAsPng(scatterplot)); - -console.log(`Scatterplot v${scatterplot.get('version')}`); - -scatterplot.subscribe('select', selectHandler); -scatterplot.subscribe('deselect', deselectHandler); - -const setNumPoints = (newNumPoints) => { - showModal( - `Hang tight. Generating ${(numPoints / 1000000).toFixed( - 1 - )} million points...` - ); - numPoints = newNumPoints; - numPointsEl.value = numPoints; - numPointsValEl.innerHTML = numPoints; - - generatePoints(numPoints).then((newPoints) => { - points = newPoints; - scatterplot.draw(points); - closeModal(); - }); -}; - -createMenu({ scatterplot, setNumPoints }); - -const numPointsInputHandler = (event) => { - numPointsValEl.innerHTML = `${+event.target - .value} release to redraw`; -}; - -numPointsEl.addEventListener('input', numPointsInputHandler); - -const numPointsChangeHandler = (event) => setNumPoints(+event.target.value); - -numPointsEl.addEventListener('change', numPointsChangeHandler); - -const setPointSize = (newPointSize) => { - pointSize = newPointSize; - pointSizeEl.value = pointSize; - pointSizeValEl.innerHTML = pointSize; - scatterplot.set({ pointSize }); -}; - -const pointSizeInputHandler = (event) => setPointSize(+event.target.value); - -pointSizeEl.addEventListener('input', pointSizeInputHandler); - -const setOpacity = (newOpacity) => { - opacity = newOpacity; - opacityEl.value = opacity; - opacityValEl.innerHTML = opacity; - scatterplot.set({ opacity }); -}; - -const opacityInputHandler = (event) => setOpacity(+event.target.value); - -opacityEl.addEventListener('input', opacityInputHandler); - -const clickLassoInitiatorChangeHandler = (event) => { - scatterplot.set({ - lassoInitiator: event.target.checked, - }); -}; - -clickLassoInitiatorEl.addEventListener( - 'change', - clickLassoInitiatorChangeHandler -); -clickLassoInitiatorEl.checked = scatterplot.get('lassoInitiator'); - -const resetClickHandler = () => { - scatterplot.reset(); -}; - -resetEl.addEventListener('click', resetClickHandler); - -const colorsScale = [ - '#002072', // dark blue - '#162b79', - '#233680', - '#2e4186', - '#394d8d', - '#425894', - '#4b649a', - '#5570a1', - '#5e7ca7', - '#6789ae', - '#7195b4', - '#7ba2ba', - '#85aec0', - '#90bbc6', - '#9cc7cc', - '#a9d4d2', - '#b8e0d7', - '#c8ecdc', - '#ddf7df', - '#ffffe0', // bright yellow -]; -scatterplot.set({ colorBy: 'value', pointColor: colorsScale }); - -setPointSize(pointSize); -setOpacity(opacity); -setNumPoints(numPoints); diff --git a/example/programmatic-lasso.js b/example/programmatic-lasso.js deleted file mode 100644 index a4a24e82..00000000 --- a/example/programmatic-lasso.js +++ /dev/null @@ -1,293 +0,0 @@ -import { axisBottom, axisRight } from 'd3-axis'; -import { scaleLinear } from 'd3-scale'; -import { select } from 'd3-selection'; - -import createScatterplot from '../src'; -import createMenu from './menu'; -import { checkSupport } from './utils'; - -const parentWrapper = document.querySelector('#parent-wrapper'); -const canvasWrapper = document.querySelector('#canvas-wrapper'); -const canvas = document.querySelector('#canvas'); - -// Create button container with grid layout -const buttonContainer = document.createElement('div'); -buttonContainer.style.cssText = ` - position: absolute; - top: 10px; - left: 10px; - display: grid; - grid-template-columns: 1fr 1fr; - gap: 6px; - max-width: 400px; - max-height: calc(100vh - 20px); - overflow-y: auto; - z-index: 1000; -`; -parentWrapper.appendChild(buttonContainer); - -const xDomain = [0, 100]; -const yDomain = [0, 100]; -const xScale = scaleLinear().domain(xDomain); -const yScale = scaleLinear().domain(yDomain); -const xAxis = axisBottom(xScale); -const yAxis = axisRight(yScale); -const axisContainer = select(parentWrapper).append('svg'); -const xAxisContainer = axisContainer.append('g'); -const yAxisContainer = axisContainer.append('g'); -const xAxisPadding = 20; -const yAxisPadding = 40; - -axisContainer.node().style.position = 'absolute'; -axisContainer.node().style.top = 0; -axisContainer.node().style.left = 0; -axisContainer.node().style.width = '100%'; -axisContainer.node().style.height = '100%'; -axisContainer.node().style.pointerEvents = 'none'; - -canvasWrapper.style.right = `${yAxisPadding}px`; -canvasWrapper.style.bottom = `${xAxisPadding}px`; - -let { width, height } = canvasWrapper.getBoundingClientRect(); - -xAxisContainer.attr('transform', `translate(0, ${height})`).call(xAxis); -yAxisContainer.attr('transform', `translate(${width}, 0)`).call(yAxis); - -// Render grid -xAxis.tickSizeInner(-height); -yAxis.tickSizeInner(-width); - -let points = []; -let numPoints = 5000; -let pointSize = 4; -let opacity = 0.66; -let selection = []; - -const selectHandler = ({ points: selectedPoints }) => { - console.log('Selected:', selectedPoints.length, 'points'); - selection = selectedPoints; -}; - -const deselectHandler = () => { - console.log('Deselected'); - selection = []; -}; - -const scatterplot = createScatterplot({ - canvas, - pointSize, - opacity, - xScale, - yScale, - showReticle: true, - lassoInitiator: true, - pointColor: [0.33, 0.5, 1, 1], - pointColorActive: [1, 0.5, 0, 1], -}); - -checkSupport(scatterplot); - -console.log(`Scatterplot v${scatterplot.get('version')}`); - -scatterplot.subscribe('select', selectHandler); -scatterplot.subscribe('deselect', deselectHandler); -scatterplot.subscribe('view', (event) => { - xAxisContainer.call(xAxis.scale(event.xScale)); - yAxisContainer.call(yAxis.scale(event.yScale)); -}); - -scatterplot.subscribe( - 'init', - () => { - xAxisContainer.call(xAxis.scale(scatterplot.get('xScale'))); - yAxisContainer.call(yAxis.scale(scatterplot.get('yScale'))); - }, - 1 -); - -const resizeHandler = () => { - ({ width, height } = canvasWrapper.getBoundingClientRect()); - - xAxisContainer.attr('transform', `translate(0, ${height})`).call(xAxis); - yAxisContainer.attr('transform', `translate(${width}, 0)`).call(yAxis); - - // Render grid - xAxis.tickSizeInner(-height); - yAxis.tickSizeInner(-width); -}; - -window.addEventListener('resize', resizeHandler); -window.addEventListener('orientationchange', resizeHandler); - -// Generate points in DATA SPACE (not NDC) -const generatePoints = (num) => { - const pts = []; - for (let i = 0; i < num; i++) { - const x = Math.random() * 100; // 0 to 100 (data space) - const y = Math.random() * 100; // 0 to 100 (data space) - - // Convert to NDC for scatterplot - const xNdc = (x / 100) * 2 - 1; - const yNdc = (y / 100) * 2 - 1; - - pts.push([ - xNdc, - yNdc, - Math.round(Math.random() * 4), // category - Math.random(), // value - x, // store original x for reference - y, // store original y for reference - ]); - } - return pts; -}; - -const setNumPoints = (newNumPoints) => { - points = generatePoints(newNumPoints); - scatterplot.draw(points); -}; - -createMenu({ scatterplot, setNumPoints }); - -scatterplot.set({ - colorBy: 'category', - pointColor: [ - '#3a84cc', - '#56bf92', - '#eecb62', - '#c76526', - '#d192b7', - ], -}); - -// Helper function to create a button -const createButton = (label, onClick, wide = false) => { - const btn = document.createElement('button'); - btn.textContent = label; - btn.style.cssText = ` - padding: 6px 10px; - background: #3a84cc; - color: white; - border: none; - border-radius: 3px; - cursor: pointer; - font-size: 11px; - white-space: nowrap; - text-align: center; - ${wide ? 'grid-column: 1 / -1;' : ''} - `; - btn.addEventListener('mouseenter', () => { - btn.style.background = '#2a6cb0'; - }); - btn.addEventListener('mouseleave', () => { - btn.style.background = '#3a84cc'; - }); - btn.addEventListener('click', onClick); - return btn; -}; - -// Button 1: Select bottom-left triangle -buttonContainer.appendChild( - createButton('△ Bottom-Left', () => { - scatterplot.lassoSelect([ - [10, 10], - [40, 10], - [10, 40], - ]); - }) -); - -// Button 2: Select top-right circle (approximated by polygon) -buttonContainer.appendChild( - createButton('○ Top-Right', () => { - const cx = 75; - const cy = 75; - const radius = 20; - const sides = 16; - const polygon = []; - - for (let i = 0; i < sides; i++) { - const angle = (i / sides) * Math.PI * 2; - polygon.push([ - cx + Math.cos(angle) * radius, - cy + Math.sin(angle) * radius, - ]); - } - - scatterplot.lassoSelect(polygon); - }) -); - -// Button 3: Select center rectangle -buttonContainer.appendChild( - createButton('▭ Center', () => { - scatterplot.lassoSelect([ - [30, 30], - [70, 30], - [70, 70], - [30, 70], - ]); - }) -); - -// Button 4: Add diagonal stripe (merge) -buttonContainer.appendChild( - createButton('+ Diagonal (Merge)', () => { - scatterplot.lassoSelect( - [ - [0, 40], - [60, 100], - [70, 100], - [10, 40], - ], - { merge: true } - ); - }) -); - -// Button 5: Remove center square -buttonContainer.appendChild( - createButton('− Center (Remove)', () => { - scatterplot.lassoSelect( - [ - [40, 40], - [60, 40], - [60, 60], - [40, 60], - ], - { remove: true } - ); - }) -); - -// Button 6: Star shape -buttonContainer.appendChild( - createButton('★ Star', () => { - const cx = 50; - const cy = 50; - const outerRadius = 30; - const innerRadius = 15; - const points = 5; - const polygon = []; - - for (let i = 0; i < points * 2; i++) { - const angle = (i / (points * 2)) * Math.PI * 2 - Math.PI / 2; - const radius = i % 2 === 0 ? outerRadius : innerRadius; - polygon.push([ - cx + Math.cos(angle) * radius, - cy + Math.sin(angle) * radius, - ]); - } - - scatterplot.lassoSelect(polygon); - }) -); - -// Button 7: Deselect all (wide button) -buttonContainer.appendChild( - createButton('✕ Deselect All', () => { - scatterplot.deselect(); - }, true) -); - -setNumPoints(numPoints); diff --git a/example/size-encoding.js b/example/size-encoding.js deleted file mode 100644 index 480c2987..00000000 --- a/example/size-encoding.js +++ /dev/null @@ -1,133 +0,0 @@ -import { scaleLog } from 'd3-scale'; -import { randomExponential } from 'd3-random'; - -import createScatterplot from '../src'; -import createMenu from './menu'; -import { checkSupport } from './utils'; - -const canvas = document.querySelector('#canvas'); - -let points = []; -let numPoints = 100000; -let pointSize = 2; -let opacity = 1.0; -let selection = []; - -const lassoMinDelay = 10; -const lassoMinDist = 2; -const showReticle = true; -const reticleColor = [1, 1, 0.878431373, 0.33]; - -const selectHandler = ({ points: selectedPoints }) => { - console.log('Selected:', selectedPoints); - selection = selectedPoints; - if (selection.length === 1) { - const point = points[selection[0]]; - console.log( - `X: ${point[0]}\nY: ${point[1]}\nCategory: ${point[2]}\nValue: ${point[3]}` - ); - } -}; - -const deselectHandler = () => { - console.log('Deselected:', selection); - selection = []; -}; - -const scatterplot = createScatterplot({ - canvas, - lassoMinDelay, - lassoMinDist, - pointSize, - opacity, - showReticle, - reticleColor, - lassoInitiator: true, - opacityInactiveScale: 0.66, -}); - -checkSupport(scatterplot); - -console.log(`Scatterplot v${scatterplot.get('version')}`); - -scatterplot.subscribe('select', selectHandler); -scatterplot.subscribe('deselect', deselectHandler); - -const rndA = randomExponential(2); -const rndB = randomExponential(4); -const rndC = randomExponential(5); - -const generatePoints = (num) => { - const newPoints = [ - ...new Array(Math.round((num * 2) / 12)).fill().map(() => [ - -1 + (Math.random() * 2 * 1) / 3, // x - -1 + Math.random() * 2, // y - 0, // category - rndA(), // value - ]), - ...new Array(Math.round((num * 4) / 12)).fill().map(() => [ - -1 + 2 / 3 + (Math.random() * 2 * 1) / 3, // x - -1 + Math.random() * 2, // y - 1, // category - rndB(), // value - ]), - ...new Array(Math.round((num * 6) / 12)).fill().map(() => [ - -1 + 4 / 3 + (Math.random() * 2 * 1) / 3, // x - -1 + Math.random() * 2, // y - 2, // category - rndC(), // value - ]), - ]; - - const [minVal, maxVal] = newPoints.reduce( - ([min, max], point) => [Math.min(min, point[3]), Math.max(max, point[3])], - [Infinity, -Infinity] - ); - - const valRange = maxVal - minVal; - - newPoints.forEach((point) => { - point[3] = (point[3] - minVal) / valRange; - }); - - return newPoints; -}; - -const setNumPoints = (newNumPoints) => { - points = generatePoints(newNumPoints); - scatterplot.draw(points); -}; - -const getPointSizeRange = (basePointSize) => { - const pointSizeScale = scaleLog() - .domain([1, 10]) - .range([basePointSize, basePointSize * 10]); - - return Array.from( - { length: 100 }, (_, i) => pointSizeScale(1 + (i / 99) * 9) - ); -}; - -const setPointSize = (newPointSize) => { - scatterplot.set({ pointSize: getPointSizeRange(newPointSize) }); -}; - -const getOpacityRange = (baseOpacity) => - Array.from({ length: 10 }, (_, i) => ((i + 1) / 10) * baseOpacity); - -const setOpacity = (newOpacity) => { - scatterplot.set({ opacity: getOpacityRange(newOpacity) }); -}; - -createMenu({ scatterplot, setNumPoints, setPointSize, setOpacity }); - -scatterplot.set({ - colorBy: 'category', - pointColor: ['#ff80cb', '#57c7ff', '#eee462'], - sizeBy: 'w', - opacityBy: 'w', -}); - -setPointSize(pointSize); -setOpacity(opacity); -setNumPoints(numPoints); diff --git a/example/text-labels.js b/example/text-labels.js deleted file mode 100644 index 7d133fb1..00000000 --- a/example/text-labels.js +++ /dev/null @@ -1,155 +0,0 @@ -import { scaleLinear, scaleLog } from 'd3-scale'; - -import createScatterplot from '../src'; -import createMenu from './menu'; -import { checkSupport } from './utils'; - -const canvas = document.querySelector('#canvas'); -const canvasWrapper = document.querySelector('#canvas-wrapper'); - -const noteEl = document.createElement('div'); -noteEl.id = 'note'; -noteEl.textContent = 'Zoom in to see labels!'; -canvasWrapper.appendChild(noteEl); - -const textOverlayEl = document.createElement('canvas'); -textOverlayEl.id = '#text-overlay'; -textOverlayEl.style.position = 'absolute'; -textOverlayEl.style.top = 0; -textOverlayEl.style.right = 0; -textOverlayEl.style.bottom = 0; -textOverlayEl.style.left = 0; -textOverlayEl.style.pointerEvents = 'none'; - -canvasWrapper.appendChild(textOverlayEl); - -const resizeTextOverlay = () => { - const { width, height } = canvasWrapper.getBoundingClientRect(); - textOverlayEl.width = width * window.devicePixelRatio; - textOverlayEl.height = height * window.devicePixelRatio; - textOverlayEl.style.width = `${width}px`; - textOverlayEl.style.height = `${height}px`; -}; -resizeTextOverlay(); - -window.addEventListener('resize', resizeTextOverlay); - -const overlayFontSize = 12; -const textOverlayCtx = textOverlayEl.getContext('2d'); -textOverlayCtx.font = `${ - overlayFontSize * window.devicePixelRatio -}px sans-serif`; -textOverlayCtx.textAlign = 'center'; - -let points = []; -let numPoints = 10000; -let pointSize = 4; -let opacity = 1.0; -let selection = []; - -const maxPointLabels = 200; -const lassoMinDelay = 10; -const lassoMinDist = 2; -const showReticle = true; -const reticleColor = [1, 1, 0.878431373, 0.33]; - -const scatterplot = createScatterplot({ - canvas, - lassoMinDelay, - lassoMinDist, - pointSize, - opacity, - showReticle, - reticleColor, - xScale: scaleLinear().domain([-1, 1]), - yScale: scaleLinear().domain([-1, 1]), - pointColor: '#fff', - opacityBy: 'density', - lassoInitiator: true, -}); - -checkSupport(scatterplot); - -console.log(`Scatterplot v${scatterplot.get('version')}`); - -scatterplot.subscribe('select', ({ points: selectedPoints }) => { - console.log('Selected:', selectedPoints); - selection = selectedPoints; - if (selection.length === 1) { - const point = points[selection[0]]; - console.log( - `X: ${point[0]}\nY: ${point[1]}\nCategory: ${point[2]}\nValue: ${point[3]}` - ); - } -}); - -scatterplot.subscribe('deselect', () => { - selection = []; -}); - -const showPointLabels = (pointsInView, xScale, yScale) => { - textOverlayCtx.clearRect(0, 0, textOverlayEl.width, textOverlayEl.height); - textOverlayCtx.fillStyle = 'rgb(255, 255, 255)'; - - const dpr = window.devicePixelRatio; - - for (let i = 0; i < pointsInView.length; i++) { - const [x, y] = points[pointsInView[i]]; - textOverlayCtx.fillText( - pointsInView[i], - xScale(x) * dpr, - yScale(y) * dpr - overlayFontSize * 1.2 * dpr - ); - } -}; - -const hidePointLabels = () => { - textOverlayCtx.clearRect(0, 0, canvas.width, canvas.height); -}; - -scatterplot.subscribe('drawing', ({ xScale, yScale }) => { - const pointsInView = scatterplot.get('pointsInView'); - if (pointsInView.length <= maxPointLabels) { - showPointLabels(pointsInView, xScale, yScale); - } else { - hidePointLabels(); - } -}); - -const generatePoints = (num) => - Array.from({ length: num }, () => [ - -1 + Math.random() * 2, - -1 + Math.random() * 2, - ]); - -const setNumPoints = (newNumPoints) => { - points = generatePoints(newNumPoints); - scatterplot.draw(points); -}; - -const getPointSizeRange = (basePointSize) => { - const pointSizeScale = scaleLog() - .domain([1, 10]) - .range([basePointSize, basePointSize * 10]); - - return Array.from( - { length: 100 }, (_, i) => pointSizeScale(1 + (i / 99) * 9) - ); -}; - -const setPointSize = (newPointSize) => { - scatterplot.set({ pointSize: getPointSizeRange(newPointSize) }); -}; - -const getOpacityRange = (baseOpacity) => - Array.from({ length: 10 }, (_, i) => ((i + 1) / 10) * baseOpacity); - -const setOpacity = (newOpacity) => { - scatterplot.set({ opacity: getOpacityRange(newOpacity) }); -}; - -createMenu({ scatterplot, setNumPoints, setPointSize }); - -setPointSize(pointSize); -setOpacity(opacity); -setNumPoints(numPoints); diff --git a/example/texture-background.js b/example/texture-background.js deleted file mode 100644 index c21675bf..00000000 --- a/example/texture-background.js +++ /dev/null @@ -1,67 +0,0 @@ -import createScatterplot from '../src'; -import createMenu from './menu'; -import { checkSupport } from './utils'; - -const canvas = document.querySelector('#canvas'); - -const { width, height } = canvas.getBoundingClientRect(); - -let points = []; -let numPoints = 100000; -let pointSize = 3; -let opacity = 1; -let selection = []; - -const selectHandler = ({ points: selectedPoints }) => { - console.log('Selected:', selectedPoints); - selection = selectedPoints; - if (selection.length === 1) { - const point = points[selection[0]]; - console.log( - `X: ${point[0]}\nY: ${point[1]}\nCategory: ${point[2]}\nValue: ${point[3]}` - ); - } -}; - -const deselectHandler = () => { - console.log('Deselected:', selection); - selection = []; -}; - -const scatterplot = createScatterplot({ - canvas, - pointSize, - opacity, - showReticle: true, - backgroundImage: `https://picsum.photos/${Math.min(640, width)}/${Math.min( - 640, - height - )}/?random`, - lassoInitiator: true, -}); - -checkSupport(scatterplot); - -console.log(`Scatterplot v${scatterplot.get('version')}`); - -scatterplot.subscribe('select', selectHandler); -scatterplot.subscribe('deselect', deselectHandler); - -const generatePoints = (num) => - new Array(num).fill().map(() => [ - -1 + Math.random() * 2, // x - -1 + Math.random() * 2, // y - Math.round(Math.random()), // category - Math.random(), // value - ]); - -const setNumPoints = (newNumPoints) => { - points = generatePoints(newNumPoints); - scatterplot.draw(points); -}; - -createMenu({ scatterplot, setNumPoints }); - -scatterplot.set({ colorBy: 'category', pointColor: ['#3a78aa', '#aa3a99'] }); - -setNumPoints(numPoints); diff --git a/example/transition-old.js b/example/transition-old.js deleted file mode 100644 index f087b872..00000000 --- a/example/transition-old.js +++ /dev/null @@ -1,184 +0,0 @@ -/* eslint no-console: 0 */ - -import createScatterplot from '../src'; -import { saveAsPng, checkSupport } from './utils'; - -const canvas = document.querySelector('#canvas'); -const numPointsEl = document.querySelector('#num-points'); -const numPointsValEl = document.querySelector('#num-points-value'); -const pointSizeEl = document.querySelector('#point-size'); -const pointSizeValEl = document.querySelector('#point-size-value'); -const opacityEl = document.querySelector('#opacity'); -const opacityValEl = document.querySelector('#opacity-value'); -const clickLassoInitiatorEl = document.querySelector('#click-lasso-initiator'); -const resetEl = document.querySelector('#reset'); -const exportEl = document.querySelector('#export'); -const exampleEl = document.querySelector('#example-transition'); - -exampleEl.setAttribute('class', 'active'); -exampleEl.removeAttribute('href'); - -let points = []; -let pointStates = []; -let numPoints = 100000; -let pointSize = 2; -let opacity = 0.33; -let selection = []; - -const lassoMinDelay = 10; -const lassoMinDist = 2; -const showReticle = true; -const reticleColor = [1, 1, 0.878431373, 0.33]; - -const selectHandler = ({ points: selectedPoints }) => { - console.log('Selected:', selectedPoints); - selection = selectedPoints; - if (selection.length === 1) { - const point = points[selection[0]]; - console.log( - `X: ${point[0]}\nY: ${point[1]}\nCategory: ${point[2]}\nValue: ${point[3]}` - ); - } -}; - -const deselectHandler = () => { - console.log('Deselected:', selection); - selection = []; -}; - -const scatterplot = createScatterplot({ - canvas, - lassoMinDelay, - lassoMinDist, - pointSize, - showReticle, - reticleColor, - lassoInitiator: true, -}); - -checkSupport(scatterplot); - -exportEl.addEventListener('click', () => saveAsPng(scatterplot)); - -console.log(`Scatterplot v${scatterplot.get('version')}`); - -scatterplot.subscribe('select', selectHandler); -scatterplot.subscribe('deselect', deselectHandler); - -const generatePoints = (num) => [ - ...new Array(Math.round(num / 2)).fill().map(() => [ - -1 + Math.random(), // x - -1 + (Math.random() * 2) / 3, // y - 0, // category - Math.random() * 0.33, // value - ]), - ...new Array(Math.round(num / 2)).fill().map(() => [ - Math.random(), // x - -1 + Math.random() * 2, // y - 1, // category - 0.66 + Math.random() * 0.33, // value - ]), -]; - -const setNumPoint = (newNumPoints) => { - numPoints = newNumPoints; - numPointsEl.value = numPoints; - numPointsValEl.innerHTML = numPoints; - points = generatePoints(numPoints); - pointStates = [ - points, - points.map(([x, y, c, v], j) => - j < points.length / 2 - ? [x, (y + 1) * 3 - 1, c, v + 0.66] - : [x, (y + 1) / 3 - 1, c, v - 0.66] - ), - ]; - scatterplot.draw(points); -}; - -const numPointsInputHandler = (event) => { - numPointsValEl.innerHTML = `${+event.target - .value} release to redraw`; -}; - -numPointsEl.addEventListener('input', numPointsInputHandler); - -const numPointsChangeHandler = (event) => setNumPoint(+event.target.value); - -numPointsEl.addEventListener('change', numPointsChangeHandler); - -const setPointSize = (newPointSize) => { - pointSize = newPointSize; - pointSizeEl.value = pointSize; - pointSizeValEl.innerHTML = pointSize; - scatterplot.set({ pointSize }); -}; - -const pointSizeInputHandler = (event) => setPointSize(+event.target.value); - -pointSizeEl.addEventListener('input', pointSizeInputHandler); - -const setOpacity = (newOpacity) => { - opacity = newOpacity; - opacityEl.value = opacity; - opacityValEl.innerHTML = opacity; - scatterplot.set({ opacity }); -}; - -const opacityInputHandler = (event) => setOpacity(+event.target.value); - -opacityEl.addEventListener('input', opacityInputHandler); - -const clickLassoInitiatorChangeHandler = (event) => { - scatterplot.set({ - lassoInitiator: event.target.checked, - }); -}; - -clickLassoInitiatorEl.addEventListener( - 'change', - clickLassoInitiatorChangeHandler -); -clickLassoInitiatorEl.checked = scatterplot.get('lassoInitiator'); - -const resetClickHandler = () => { - scatterplot.reset(); -}; - -resetEl.addEventListener('click', resetClickHandler); - -const colorsCat = ['#3a78aa', '#aa3a99']; -scatterplot.set({ colorBy: 'category', pointColor: colorsCat }); - -const colorsScale = [ - '#ff80cb', // bright pink - '#df80b8', - '#bf80a5', - '#9f8092', - '#808080', - '#75919f', - '#6ba3bf', - '#61b5df', - '#57c7ff', // bright blue -]; -scatterplot.set({ colorBy: 'value', pointColor: colorsScale }); - -setPointSize(pointSize); -setOpacity(opacity); -setNumPoint(numPoints); - -let i = 0; -const transitionPoints = () => { - i++; - scatterplot - .draw(pointStates[i % pointStates.length], { - transition: true, - transitionDuration: 1000 - ((i - 1) % 5) * 150, - transitionEasing: 'quadInOut', - }) - .then(() => { - setTimeout(transitionPoints, +!(i % 5) * 3000); - }); -}; - -transitionPoints(); diff --git a/example/transition.js b/example/transition.js deleted file mode 100644 index 107aed76..00000000 --- a/example/transition.js +++ /dev/null @@ -1,111 +0,0 @@ -import { tableFromIPC } from 'apache-arrow'; - -import createScatterplot from '../src'; -import createMenu from './menu'; -import { checkSupport, showModal, closeModal } from './utils'; - -const CLASS_COLORS = [ - '#FFFF00', // bright yellow - '#1CFFD9', // turrtoise - '#FF34FF', // pink/purple - '#FF4A46', // pale red - '#008941', // forrest green - '#1966FF', // dark blue - '#C00069', // violette - '#FFDBE5', // almost white - '#FF9900', // yellow - '#8148D5', // grass green -]; - -/** - * Load Embedding Example - */ -const whenData = fetch( - 'https://storage.googleapis.com/flekschas/regl-scatterplot/cities.arrow' -); - -/** - * Modal - */ -showModal('Loading...'); - -/** - * Add info to footer - */ -const footer = document.querySelector('#footer'); -footer.classList.remove('hidden'); -const infoContent = document.querySelector('#info-content'); -infoContent.innerHTML = ` -

GeoNames – Cities Dataset visualized in three: by the cities' geographic location, by the total population across contintents, and by the citie's latitude distribution.

-`; - -const canvas = document.querySelector('#canvas'); - -let pointSize = 1.5; - -const scatterplot = createScatterplot({ - canvas, - pointSize, - lassoOnLongPress: true, -}); - -checkSupport(scatterplot); - -console.log(`Scatterplot v${scatterplot.get('version')}`); - -createMenu({ scatterplot, opacityChangesDisabled: true }); - -whenData - .then((data) => tableFromIPC(data)) - .then((table) => { - closeModal(); - const columnValues = table.data[0].children.map((data) => data.values); - - const population = columnValues[columnValues.length - 2]; - const continents = columnValues[columnValues.length - 1]; - - const staticOpacity = new Float32Array(population.length); - for (let i = 0; i < population.length; i++) { - staticOpacity[i] = 1; - } - - scatterplot.draw({ - x: columnValues[0], - y: columnValues[1], - z: continents, - w: population, - }); - scatterplot.set({ - colorBy: 'z', - pointColor: CLASS_COLORS, - opacityBy: 'w', - opacity: Array.from({ length: 10 }, (_, i) => 0.33 + (i / 9) * 0.33), - }); - - let i = 0; - const transitionPoints = () => { - i++; - - const startCol = (i % 3) * 2; - - scatterplot - .draw( - { - x: columnValues[startCol], - y: columnValues[startCol + 1], - z: continents, - w: [population, staticOpacity, staticOpacity][i % 3], - }, - { - transition: true, - transitionDuration: 750, - transitionEasing: 'quadInOut', - } - ) - .then(() => { - setTimeout(transitionPoints, 2500); - }); - }; - - setTimeout(transitionPoints, 2500); - }); diff --git a/example/tweakpane-link-plugin.js b/example/tweakpane-link-plugin.js deleted file mode 100644 index b82db44a..00000000 --- a/example/tweakpane-link-plugin.js +++ /dev/null @@ -1,136 +0,0 @@ -import { - bindValue, - createPlugin, - parseRecord, - BladeApi, - BladeController, - ValueMap -} from '@tweakpane/core'; - -class LinkController extends BladeController { - constructor(doc, config) { - super({ - ...config, - view: new LinkView(doc, { - props: config.props, - viewProps: config.viewProps, - }), - }); - } -} - -class LinkView { - constructor(doc, { props, viewProps }) { - // Create view elements - this.element = doc.createElement('div'); - this.element.classList.add('tp-link'); - viewProps.bindClassModifiers(this.element); - - // Create an `a` element for user interaction - const linkElement = doc.createElement('a'); - viewProps.bindDisabled(linkElement); - - function setLink(link) { - linkElement.href = link ?? ''; - } - - function setLabel(label) { - linkElement.textContent = label ?? ''; - } - - function setActive(active) { - if (active) { - linkElement.classList.add('active'); - linkElement.removeAttribute('href'); - linkElement.removeAttribute('target'); - } else { - linkElement.classList.remove('active'); - setLink(props.get('link')); - setNewPage(props.get('newPage')); - } - } - - function setNewPage(newPage) { - if (newPage) { - linkElement.target = '_blank'; - } else { - linkElement.removeAttribute('target'); - } - } - - bindValue(props.value('link'), setLink); - bindValue(props.value('label'), setLabel); - bindValue(props.value('active'), setActive); - bindValue(props.value('newPage'), setNewPage); - - this.element.appendChild(linkElement); - this.linkElement = linkElement; - } -} - -class LinkApi extends BladeApi { - get label() { - return this.controller.props.get('label') ?? ''; - } - - set label(label) { - this.controller.props.set('label', label); - } - - get link() { - return this.controller.props.get('link'); - } - - set link(link) { - this.controller.props.set('link', link); - } - - get active() { - return this.controller.props.get('active'); - } - - set active(active) { - this.controller.props.set('active', Boolean(active)); - } - - get newPage() { - return this.controller.props.get('newPage'); - } - - set newPage(newPage) { - this.controller.props.set('newPage', Boolean(newPage)); - } -} - -export const LinkPlugin = createPlugin({ - id: 'link', - type: 'blade', - accept(params) { - const result = parseRecord(params, (p) => ({ - view: p.required.constant('link'), - link: p.required.string, - label: p.required.string, - active: p.optional.boolean, - newPage: p.optional.boolean, - })); - return result ? { params: result } : null; - }, - controller(args) { - return new LinkController(args.document, { - blade: args.blade, - props: ValueMap.fromObject({ - label: args.params.label, - link: args.params.link, - active: args.params.active, - newPage: args.params.newPage, - }), - viewProps: args.viewProps, - }); - }, - api(args) { - if (!(args.controller instanceof LinkController)) { - return null; - } - return new LinkApi(args.controller); - }, -}); diff --git a/example/utils.js b/example/utils.js deleted file mode 100644 index 14fdaef6..00000000 --- a/example/utils.js +++ /dev/null @@ -1,62 +0,0 @@ -export function downloadBlob(blob, name = 'file.txt') { - const link = document.createElement('a'); - link.href = URL.createObjectURL(blob); - link.download = name; - - document.body.appendChild(link); - - link.dispatchEvent( - new MouseEvent('click', { - bubbles: true, - cancelable: true, - view: window, - }) - ); - - document.body.removeChild(link); -} - -export function saveAsPng(scatterplot) { - const imageObject = new Image(); - imageObject.onload = () => { - scatterplot.get('canvas').toBlob((blob) => { - downloadBlob(blob, 'regl-scatterplot.png'); - }); - }; - imageObject.src = scatterplot.get('canvas').toDataURL(); -} - -export function closeModal() { - const modal = document.querySelector('#modal'); - const modalText = document.querySelector('#modal-text'); - modal.style.display = 'none'; - modalText.textContent = ''; -} - -export function showModal(text, isError, isClosable) { - const modal = document.querySelector('#modal'); - modal.style.display = 'flex'; - - const modalText = document.querySelector('#modal-text'); - modalText.style.color = isError ? '#cc79A7' : '#bbb'; - modalText.textContent = text; - - const modalClose = document.querySelector('#modal-close'); - if (isClosable) { - modalClose.style.display = 'block'; - modalClose.style.background = isError ? '#cc79A7' : '#bbb'; - modalClose.addEventListener('click', closeModal, { once: true }); - } else { - modalClose.style.display = 'none'; - } -} - -export function checkSupport(scatterplot) { - if (!scatterplot.isSupported) { - showModal( - 'Your browser does not support all necessary WebGL features. The scatter plot might not render properly.', - true, - true - ); - } -} diff --git a/public/favicon.png b/favicon.png similarity index 100% rename from public/favicon.png rename to favicon.png diff --git a/public/index.html b/index.html similarity index 96% rename from public/index.html rename to index.html index dccce48a..5fe658d6 100644 --- a/public/index.html +++ b/index.html @@ -11,7 +11,7 @@ /> - + + + + @@ -437,5 +440,5 @@

Regl Scatterplot

- + diff --git a/multiple-instances.html b/multiple-instances.html new file mode 100644 index 00000000..8eb683e5 --- /dev/null +++ b/multiple-instances.html @@ -0,0 +1,445 @@ + + + + + + + Regl Scatterplot + + + + + + + + + + + + + + +

Regl Scatterplot

+ +
+
+ +
+
+
+
+
+
+
+
+ + diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index cd0ffbe7..00000000 --- a/package-lock.json +++ /dev/null @@ -1,8723 +0,0 @@ -{ - "name": "regl-scatterplot", - "version": "1.16.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "regl-scatterplot", - "version": "1.16.0", - "license": "MIT", - "dependencies": { - "@flekschas/utils": "^0.33.0", - "dom-2d-camera": "^2.2.6", - "earcut": "^3.0.2", - "gl-matrix": "~3.4.4", - "pub-sub-es": "~3.0.0", - "regl": "~2.1.1", - "regl-line": "~1.1.1" - }, - "devDependencies": { - "@babel/core": "^7.28.6", - "@babel/plugin-transform-regenerator": "^7.28.6", - "@babel/polyfill": "^7.12.1", - "@babel/preset-env": "^7.28.6", - "@biomejs/biome": "^2.3.11", - "@rollup/plugin-babel": "^6.1.0", - "@rollup/plugin-commonjs": "^29.0.0", - "@rollup/plugin-json": "^6.0.0", - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@tweakpane/core": "^2.0.5", - "@types/d3-scale": "^4.0.9", - "@types/node": "^25.0.8", - "@vitest/browser": "^4.0.17", - "@vitest/browser-playwright": "^4.0.17", - "@vitest/coverage-v8": "^4.0.17", - "apache-arrow": "^21.1.0", - "d3-axis": "^3.0.0", - "d3-random": "^3.0.1", - "d3-scale": "^4.0.2", - "d3-selection": "^3.0.0", - "esm": "^3.2.25", - "gh-pages": "^6.3.0", - "merge": "^2.1.1", - "playwright": "^1.57.0", - "rollup": "^4.55.1", - "rollup-plugin-filesize": "^10.0.0", - "tweakpane": "^4.0.5", - "typescript": "~5.9.3", - "vite": "^8.1.5", - "vite-plugin-virtual-html-template": "^1.1.0", - "vitest": "^4.0.17" - }, - "engines": { - "node": ">=20.0.0", - "npm": ">=7.0.0" - }, - "peerDependencies": { - "pub-sub-es": "~3.0.0", - "regl": "~2.1.1" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.6.tgz", - "integrity": "sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.6.tgz", - "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/generator": "^7.28.6", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6", - "@jridgewell/remapping": "^2.3.5", - "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/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.27.3", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", - "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.27.3" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.6.tgz", - "integrity": "sha512-dTOdvsjnG3xNT9Y0AUg1wAl38y+4Rl4sf9caSQZOXdNqVn+H+HbbJ4IyyHaIqNR6SW9oJpA/RuRjsjCw2IdIow==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/traverse": "^7.28.6", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", - "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "regexpu-core": "^6.3.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", - "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-plugin-utils": "^7.27.1", - "debug": "^4.4.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.22.10" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", - "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", - "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", - "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.1", - "@babel/helper-wrap-function": "^7.27.1", - "@babel/traverse": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz", - "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.28.5", - "@babel/helper-optimise-call-expression": "^7.27.1", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", - "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz", - "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.29.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", - "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.29.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", - "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", - "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", - "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", - "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", - "@babel/plugin-transform-optional-chaining": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.13.0" - } - }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz", - "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz", - "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz", - "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-unicode-sets-regex": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", - "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", - "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.6.tgz", - "integrity": "sha512-9knsChgsMzBV5Yh3kkhrZNxH3oCYAfMBkNNaVN4cP2RVlFPe8wYdwwcnOsAbkdDoV9UjFtOXWrWB52M8W4jNeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz", - "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-remap-async-to-generator": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", - "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz", - "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz", - "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz", - "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" - } - }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz", - "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-globals": "^7.28.0", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-replace-supers": "^7.28.6", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz", - "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/template": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", - "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz", - "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", - "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.28.6.tgz", - "integrity": "sha512-5suVoXjC14lUN6ZL9OLKIHCNVWCrqGqlmEp/ixdXjvgnEl/kauLvvMO/Xw9NyMc95Joj1AeLVPVMvibBgSoFlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", - "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-explicit-resource-management": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz", - "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz", - "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", - "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", - "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", - "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/traverse": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz", - "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", - "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz", - "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", - "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", - "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz", - "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.29.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.4.tgz", - "integrity": "sha512-N7QmZ0xRZfjHOfZeQLJjwgX2zS9pdGHSVl/cjSGlo4dXMqvurfxXDMKY4RqEKzPozV78VMcd0lxyG13mlbKc4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.29.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", - "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", - "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", - "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz", - "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz", - "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz", - "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", - "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1", - "@babel/helper-replace-supers": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz", - "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz", - "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.27.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", - "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz", - "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz", - "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.27.3", - "@babel/helper-create-class-features-plugin": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", - "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.6.tgz", - "integrity": "sha512-eZhoEZHYQLL5uc1gS5e9/oTknS0sSSAtd5TkKMUp3J+S/CaUjagc0kOUPsEbDmMeva0nC3WWl4SxVY6+OBuxfw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz", - "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", - "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", - "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz", - "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", - "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", - "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", - "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", - "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz", - "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", - "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.27.1", - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz", - "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.28.5", - "@babel/helper-plugin-utils": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/polyfill": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/polyfill/-/polyfill-7.12.1.tgz", - "integrity": "sha512-X0pi0V6gxLi6lFZpGmeNa4zxtwEmCs42isWLNjZZDE0Y8yVfgu0T2OAHlzBbdYlqbW/YXVvoBHpATEM+goCj8g==", - "deprecated": "🚨 This package has been deprecated in favor of separate inclusion of a polyfill and regenerator-runtime (when needed). See the @babel/polyfill docs (https://babeljs.io/docs/en/babel-polyfill) for more information.", - "dev": true, - "license": "MIT", - "dependencies": { - "core-js": "^2.6.5", - "regenerator-runtime": "^0.13.4" - } - }, - "node_modules/@babel/preset-env": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.6.tgz", - "integrity": "sha512-GaTI4nXDrs7l0qaJ6Rg06dtOXTBCG6TMDB44zbqofCIC4PqC7SEvmFFtpxzCDw9W5aJ7RKVshgXTLvLdBFV/qw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-plugin-utils": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.28.6", - "@babel/plugin-syntax-import-attributes": "^7.28.6", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.27.1", - "@babel/plugin-transform-async-generator-functions": "^7.28.6", - "@babel/plugin-transform-async-to-generator": "^7.28.6", - "@babel/plugin-transform-block-scoped-functions": "^7.27.1", - "@babel/plugin-transform-block-scoping": "^7.28.6", - "@babel/plugin-transform-class-properties": "^7.28.6", - "@babel/plugin-transform-class-static-block": "^7.28.6", - "@babel/plugin-transform-classes": "^7.28.6", - "@babel/plugin-transform-computed-properties": "^7.28.6", - "@babel/plugin-transform-destructuring": "^7.28.5", - "@babel/plugin-transform-dotall-regex": "^7.28.6", - "@babel/plugin-transform-duplicate-keys": "^7.27.1", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.28.6", - "@babel/plugin-transform-dynamic-import": "^7.27.1", - "@babel/plugin-transform-explicit-resource-management": "^7.28.6", - "@babel/plugin-transform-exponentiation-operator": "^7.28.6", - "@babel/plugin-transform-export-namespace-from": "^7.27.1", - "@babel/plugin-transform-for-of": "^7.27.1", - "@babel/plugin-transform-function-name": "^7.27.1", - "@babel/plugin-transform-json-strings": "^7.28.6", - "@babel/plugin-transform-literals": "^7.27.1", - "@babel/plugin-transform-logical-assignment-operators": "^7.28.6", - "@babel/plugin-transform-member-expression-literals": "^7.27.1", - "@babel/plugin-transform-modules-amd": "^7.27.1", - "@babel/plugin-transform-modules-commonjs": "^7.28.6", - "@babel/plugin-transform-modules-systemjs": "^7.28.5", - "@babel/plugin-transform-modules-umd": "^7.27.1", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", - "@babel/plugin-transform-new-target": "^7.27.1", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6", - "@babel/plugin-transform-numeric-separator": "^7.28.6", - "@babel/plugin-transform-object-rest-spread": "^7.28.6", - "@babel/plugin-transform-object-super": "^7.27.1", - "@babel/plugin-transform-optional-catch-binding": "^7.28.6", - "@babel/plugin-transform-optional-chaining": "^7.28.6", - "@babel/plugin-transform-parameters": "^7.27.7", - "@babel/plugin-transform-private-methods": "^7.28.6", - "@babel/plugin-transform-private-property-in-object": "^7.28.6", - "@babel/plugin-transform-property-literals": "^7.27.1", - "@babel/plugin-transform-regenerator": "^7.28.6", - "@babel/plugin-transform-regexp-modifiers": "^7.28.6", - "@babel/plugin-transform-reserved-words": "^7.27.1", - "@babel/plugin-transform-shorthand-properties": "^7.27.1", - "@babel/plugin-transform-spread": "^7.28.6", - "@babel/plugin-transform-sticky-regex": "^7.27.1", - "@babel/plugin-transform-template-literals": "^7.27.1", - "@babel/plugin-transform-typeof-symbol": "^7.27.1", - "@babel/plugin-transform-unicode-escapes": "^7.27.1", - "@babel/plugin-transform-unicode-property-regex": "^7.28.6", - "@babel/plugin-transform-unicode-regex": "^7.27.1", - "@babel/plugin-transform-unicode-sets-regex": "^7.28.6", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.14", - "babel-plugin-polyfill-corejs3": "^0.13.0", - "babel-plugin-polyfill-regenerator": "^0.6.5", - "core-js-compat": "^3.43.0", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-modules": { - "version": "0.1.6-no-external-plugins", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", - "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", - "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@bcoe/v8-coverage": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz", - "integrity": "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@biomejs/biome": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.3.11.tgz", - "integrity": "sha512-/zt+6qazBWguPG6+eWmiELqO+9jRsMZ/DBU3lfuU2ngtIQYzymocHhKiZRyrbra4aCOoyTg/BmY+6WH5mv9xmQ==", - "dev": true, - "license": "MIT OR Apache-2.0", - "bin": { - "biome": "bin/biome" - }, - "engines": { - "node": ">=14.21.3" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/biome" - }, - "optionalDependencies": { - "@biomejs/cli-darwin-arm64": "2.3.11", - "@biomejs/cli-darwin-x64": "2.3.11", - "@biomejs/cli-linux-arm64": "2.3.11", - "@biomejs/cli-linux-arm64-musl": "2.3.11", - "@biomejs/cli-linux-x64": "2.3.11", - "@biomejs/cli-linux-x64-musl": "2.3.11", - "@biomejs/cli-win32-arm64": "2.3.11", - "@biomejs/cli-win32-x64": "2.3.11" - } - }, - "node_modules/@biomejs/cli-darwin-arm64": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.3.11.tgz", - "integrity": "sha512-/uXXkBcPKVQY7rc9Ys2CrlirBJYbpESEDme7RKiBD6MmqR2w3j0+ZZXRIL2xiaNPsIMMNhP1YnA+jRRxoOAFrA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-darwin-x64": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.3.11.tgz", - "integrity": "sha512-fh7nnvbweDPm2xEmFjfmq7zSUiox88plgdHF9OIW4i99WnXrAC3o2P3ag9judoUMv8FCSUnlwJCM1B64nO5Fbg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-linux-arm64": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.3.11.tgz", - "integrity": "sha512-l4xkGa9E7Uc0/05qU2lMYfN1H+fzzkHgaJoy98wO+b/7Gl78srbCRRgwYSW+BTLixTBrM6Ede5NSBwt7rd/i6g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-linux-arm64-musl": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.3.11.tgz", - "integrity": "sha512-XPSQ+XIPZMLaZ6zveQdwNjbX+QdROEd1zPgMwD47zvHV+tCGB88VH+aynyGxAHdzL+Tm/+DtKST5SECs4iwCLg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-linux-x64": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.3.11.tgz", - "integrity": "sha512-/1s9V/H3cSe0r0Mv/Z8JryF5x9ywRxywomqZVLHAoa/uN0eY7F8gEngWKNS5vbbN/BsfpCG5yeBT5ENh50Frxg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-linux-x64-musl": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.3.11.tgz", - "integrity": "sha512-vU7a8wLs5C9yJ4CB8a44r12aXYb8yYgBn+WeyzbMjaCMklzCv1oXr8x+VEyWodgJt9bDmhiaW/I0RHbn7rsNmw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-win32-arm64": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.3.11.tgz", - "integrity": "sha512-PZQ6ElCOnkYapSsysiTy0+fYX+agXPlWugh6+eQ6uPKI3vKAqNp6TnMhoM3oY2NltSB89hz59o8xIfOdyhi9Iw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@biomejs/cli-win32-x64": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.3.11.tgz", - "integrity": "sha512-43VrG813EW+b5+YbDbz31uUsheX+qFKCpXeY9kfdAx+ww3naKxeVkTD9zLIWxUPfJquANMHrmW3wbe/037G0Qg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT OR Apache-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=14.21.3" - } - }, - "node_modules/@blazediff/core": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@blazediff/core/-/core-1.9.1.tgz", - "integrity": "sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@emnapi/core": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", - "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.2", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", - "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", - "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@flekschas/utils": { - "version": "0.33.0", - "resolved": "https://registry.npmjs.org/@flekschas/utils/-/utils-0.33.0.tgz", - "integrity": "sha512-THnZZqtQ5me5kgF9xzI0oYJ8D+524kKXKCUJErAmlT8pfw2iTwiyPDS8f3SqrY9Y7M8zNY2dGME+JBUpKypEqg==", - "license": "MIT" - }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true, - "license": "MIT" - }, - "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==", - "dev": true, - "license": "ISC", - "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-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/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==", - "dev": true, - "license": "MIT" - }, - "node_modules/@isaacs/cliui/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==", - "dev": true, - "license": "MIT", - "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/@isaacs/cliui/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==", - "dev": true, - "license": "MIT", - "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/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz", - "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@tybys/wasm-util": "^0.10.3" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" - } - }, - "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==", - "dev": true, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/fs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-3.1.1.tgz", - "integrity": "sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==", - "dev": true, - "license": "ISC", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/fs/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/git": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/git/-/git-4.1.0.tgz", - "integrity": "sha512-9hwoB3gStVfa0N31ymBmrX+GuDGdVA/QWShZVqE0HK2Af+7QGGrCTbZia/SW0ImUTjTne7SP91qxDmtXvDHRPQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/promise-spawn": "^6.0.0", - "lru-cache": "^7.4.4", - "npm-pick-manifest": "^8.0.0", - "proc-log": "^3.0.0", - "promise-inflight": "^1.0.1", - "promise-retry": "^2.0.1", - "semver": "^7.3.5", - "which": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/git/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/@npmcli/git/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@npmcli/installed-package-contents": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@npmcli/installed-package-contents/-/installed-package-contents-2.1.0.tgz", - "integrity": "sha512-c8UuGLeZpm69BryRykLuKRyKFZYJsZSCT4aVY5ds4omyZqJ172ApzgfKJ5eV/r3HgLdUYgFVe54KSFVjKoe27w==", - "dev": true, - "license": "ISC", - "dependencies": { - "npm-bundled": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "bin": { - "installed-package-contents": "bin/index.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "dev": true, - "license": "MIT", - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@npmcli/node-gyp": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@npmcli/node-gyp/-/node-gyp-3.0.0.tgz", - "integrity": "sha512-gp8pRXC2oOxu0DUE1/M3bYtb1b3/DbJ5aM113+XJBgfXdussRAsX0YOrOhdd8WvnAR6auDBvJomGAkLKA5ydxA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/promise-spawn": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/promise-spawn/-/promise-spawn-6.0.2.tgz", - "integrity": "sha512-gGq0NJkIGSwdbUt4yhdF8ZrmkGKVz9vAdVzpOfnom+V8PLSmSOVhZwbNvZZS1EYcJN5hzzKBxmmVVAInM6HQLg==", - "dev": true, - "license": "ISC", - "dependencies": { - "which": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@npmcli/run-script": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-6.0.2.tgz", - "integrity": "sha512-NCcr1uQo1k5U+SYlnIrbAh3cxy+OQT1VtqiAbxdymSlptbzBb62AjH2xXgjNCoP073hoa1CfCAcwoZ8k96C4nA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/node-gyp": "^3.0.0", - "@npmcli/promise-spawn": "^6.0.0", - "node-gyp": "^9.0.0", - "read-package-json-fast": "^3.0.0", - "which": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@oxc-project/types": { - "version": "0.139.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz", - "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/Boshen" - } - }, - "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==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@polka/url": { - "version": "1.0.0-next.29", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", - "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rolldown/binding-android-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz", - "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz", - "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz", - "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz", - "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz", - "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz", - "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz", - "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz", - "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz", - "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==", - "cpu": [ - "s390x" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz", - "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz", - "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz", - "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz", - "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "1.11.1", - "@emnapi/runtime": "1.11.1", - "@napi-rs/wasm-runtime": "^1.1.6" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz", - "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz", - "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", - "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/plugin-babel": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-6.1.0.tgz", - "integrity": "sha512-dFZNuFD2YRcoomP4oYf+DvQNSUA9ih+A3vUqopQx5EdtPGo3WBnQcI/S8pwpz91UsGfL0HsMSOlaMld8HrbubA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.18.6", - "@rollup/pluginutils": "^5.0.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0", - "@types/babel__core": "^7.1.9", - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "@types/babel__core": { - "optional": true - }, - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-commonjs": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-29.0.0.tgz", - "integrity": "sha512-U2YHaxR2cU/yAiwKJtJRhnyLk7cifnQw0zUpISsocBDoHDJn+HTV74ABqnwr5bEgWUwFZC9oFL6wLe21lHu5eQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "commondir": "^1.0.1", - "estree-walker": "^2.0.2", - "fdir": "^6.2.0", - "is-reference": "1.2.1", - "magic-string": "^0.30.3", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=16.0.0 || 14 >= 14.17" - }, - "peerDependencies": { - "rollup": "^2.68.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-json": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", - "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.1.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-node-resolve": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-16.0.3.tgz", - "integrity": "sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@rollup/pluginutils": "^5.0.1", - "@types/resolve": "1.20.2", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.22.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^2.78.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/plugin-terser": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-1.0.0.tgz", - "integrity": "sha512-FnCxhTBx6bMOYQrar6C8h3scPt8/JwIzw3+AJ2K++6guogH5fYaIFia+zZuhqv0eo1RN7W1Pz630SyvLbDjhtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "serialize-javascript": "^7.0.3", - "smob": "^1.0.0", - "terser": "^5.17.4" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "rollup": "^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/pluginutils": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", - "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", - "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", - "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", - "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", - "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", - "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", - "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", - "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", - "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", - "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", - "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", - "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", - "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", - "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", - "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", - "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", - "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", - "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", - "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", - "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", - "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", - "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", - "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", - "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", - "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", - "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@sigstore/bundle": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz", - "integrity": "sha512-PFutXEy0SmQxYI4texPw3dd2KewuNqv7OuK1ZFtY2fM754yhvG2KdgwIhRnoEE2uHdtdGNQ8s0lb94dW9sELog==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.2.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@sigstore/protobuf-specs": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@sigstore/protobuf-specs/-/protobuf-specs-0.2.1.tgz", - "integrity": "sha512-XTWVxnWJu+c1oCshMLwnKvz8ZQJJDVOlciMfgpJBQbThVjKTCG8dwyhgLngBD2KN0ap9F/gOV8rFDEx8uh7R2A==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@sigstore/sign": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@sigstore/sign/-/sign-1.0.0.tgz", - "integrity": "sha512-INxFVNQteLtcfGmcoldzV6Je0sbbfh9I16DM4yJPw3j5+TFP8X6uIiA18mvpEa9yyeycAKgPmOA3X9hVdVTPUA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^1.1.0", - "@sigstore/protobuf-specs": "^0.2.0", - "make-fetch-happen": "^11.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@sigstore/sign/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/@sigstore/sign/node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "license": "ISC", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@sigstore/sign/node_modules/minipass-fetch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", - "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/@sigstore/sign/node_modules/minipass-fetch/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/@sigstore/tuf": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@sigstore/tuf/-/tuf-1.0.3.tgz", - "integrity": "sha512-2bRovzs0nJZFlCN3rXirE4gwxCn97JNjMmwpecqlbgV9WcxX7WRuIrgzx/X7Ib7MYRbyUTpBYE0s2x6AmZXnlg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/protobuf-specs": "^0.2.0", - "tuf-js": "^1.1.7" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@standard-schema/spec": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", - "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@swc/helpers": { - "version": "0.5.18", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.18.tgz", - "integrity": "sha512-TXTnIcNJQEKwThMMqBXsZ4VGAza6bvN4pa41Rkqoio6QBKMvo+5lexeTMScGCIxtzgQJzElcvIltani+adC5PQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.8.0" - } - }, - "node_modules/@tootallnate/once": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz", - "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/@tufjs/canonical-json": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@tufjs/canonical-json/-/canonical-json-1.0.0.tgz", - "integrity": "sha512-QTnf++uxunWvG2z3UFNzAoQPHxnSXOwtaI3iJ+AohhV+5vONuArPjJE7aPXPVXfXJsqrVbZBu9b81AJoSd09IQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@tufjs/models": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tufjs/models/-/models-1.0.4.tgz", - "integrity": "sha512-qaGV9ltJP0EO25YfFUPhxRVK0evXFIAGicsVXuRim4Ed9cjPxYhNnNJ49SFmbeLgtxpslIkX317IgpfcHPVj/A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tufjs/canonical-json": "1.0.0", - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/@tweakpane/core": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@tweakpane/core/-/core-2.0.5.tgz", - "integrity": "sha512-punBgD5rKCF5vcNo6BsSOXiDR/NSs9VM7SG65QSLJIxfRaGgj54ree9zQW6bO3pNFf3AogiGgaNODUVQRk9YqQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", - "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@types/chai": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", - "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/deep-eql": "*", - "assertion-error": "^2.0.1" - } - }, - "node_modules/@types/command-line-args": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.2.3.tgz", - "integrity": "sha512-uv0aG6R0Y8WHZLTamZwtfsDLVRnOa+n+n5rEvFWL5Na5gZ8V2Teab/duDPFzIIIhs9qizDpcavCusCLJZu62Kw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/command-line-usage": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@types/command-line-usage/-/command-line-usage-5.0.4.tgz", - "integrity": "sha512-BwR5KP3Es/CSht0xqBcUXS3qCAUVXwpRKsV2+arxeb65atasuXG9LykC9Ab10Cw3s2raH92ZqOeILaQbsB2ACg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/d3-scale": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", - "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/d3-time": "*" - } - }, - "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==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/deep-eql": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", - "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/node": { - "version": "25.0.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.8.tgz", - "integrity": "sha512-powIePYMmC3ibL0UJ2i2s0WIbq6cg6UyVFQxSCpaPxxzAaziRfimGivjdF943sSGV6RADVbk0Nvlm5P/FB44Zg==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/@types/resolve": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", - "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vitest/browser": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-4.1.10.tgz", - "integrity": "sha512-UDwuWGwXj646CBx/bQHOaJSX7np0I8JL/UKQYa1e4QrVHH8VdWtx8eaOuf8sy0ShwDgR6NjJAsp5eF6vjF6qng==", - "dev": true, - "license": "MIT", - "dependencies": { - "@blazediff/core": "1.9.1", - "@vitest/mocker": "4.1.10", - "@vitest/utils": "4.1.10", - "magic-string": "^0.30.21", - "pngjs": "^7.0.0", - "sirv": "^3.0.2", - "tinyrainbow": "^3.1.0", - "ws": "^8.19.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "vitest": "4.1.10" - } - }, - "node_modules/@vitest/browser-playwright": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/browser-playwright/-/browser-playwright-4.1.10.tgz", - "integrity": "sha512-nMoXGEiRpT7m3W7NsbvrM2aKNwiNHZf+zEpUCvMteGjZFvfT96Q9fh7QyB98dvDWXiKvrLxA7bJ1mCOOv+JQPw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/browser": "4.1.10", - "@vitest/mocker": "4.1.10", - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "playwright": "*", - "vitest": "4.1.10" - }, - "peerDependenciesMeta": { - "playwright": { - "optional": false - } - } - }, - "node_modules/@vitest/coverage-v8": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.10.tgz", - "integrity": "sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@bcoe/v8-coverage": "^1.0.2", - "@vitest/utils": "4.1.10", - "ast-v8-to-istanbul": "^1.0.0", - "istanbul-lib-coverage": "^3.2.2", - "istanbul-lib-report": "^3.0.1", - "istanbul-reports": "^3.2.0", - "magicast": "^0.5.2", - "obug": "^2.1.1", - "std-env": "^4.0.0-rc.1", - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@vitest/browser": "4.1.10", - "vitest": "4.1.10" - }, - "peerDependenciesMeta": { - "@vitest/browser": { - "optional": true - } - } - }, - "node_modules/@vitest/expect": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.10.tgz", - "integrity": "sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@standard-schema/spec": "^1.1.0", - "@types/chai": "^5.2.2", - "@vitest/spy": "4.1.10", - "@vitest/utils": "4.1.10", - "chai": "^6.2.2", - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/mocker": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.10.tgz", - "integrity": "sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "4.1.10", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.21" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/@vitest/mocker/node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/@vitest/pretty-format": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.10.tgz", - "integrity": "sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.10.tgz", - "integrity": "sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "4.1.10", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.10.tgz", - "integrity": "sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.1.10", - "@vitest/utils": "4.1.10", - "magic-string": "^0.30.21", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.10.tgz", - "integrity": "sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.10.tgz", - "integrity": "sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "4.1.10", - "convert-source-map": "^2.0.0", - "tinyrainbow": "^3.1.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true, - "license": "ISC" - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agentkeepalive": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/apache-arrow": { - "version": "21.1.0", - "resolved": "https://registry.npmjs.org/apache-arrow/-/apache-arrow-21.1.0.tgz", - "integrity": "sha512-kQrYLxhC+NTVVZ4CCzGF6L/uPVOzJmD1T3XgbiUnP7oTeVFOFgEUu6IKNwCDkpFoBVqDKQivlX4RUFqqnWFlEA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@swc/helpers": "^0.5.11", - "@types/command-line-args": "^5.2.3", - "@types/command-line-usage": "^5.0.4", - "@types/node": "^24.0.3", - "command-line-args": "^6.0.1", - "command-line-usage": "^7.0.1", - "flatbuffers": "^25.1.24", - "json-bignum": "^0.0.3", - "tslib": "^2.6.2" - }, - "bin": { - "arrow2csv": "bin/arrow2csv.js" - } - }, - "node_modules/apache-arrow/node_modules/@types/node": { - "version": "24.10.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.8.tgz", - "integrity": "sha512-r0bBaXu5Swb05doFYO2kTWHMovJnNVbCsII0fhesM8bNRlLhXIuckley4a2DaD+vOdmm5G+zGkQZAPZsF80+YQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/aproba": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz", - "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==", - "dev": true, - "license": "ISC" - }, - "node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/array-back": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", - "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.17" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/ast-v8-to-istanbul": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.5.tgz", - "integrity": "sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.31", - "estree-walker": "^3.0.3", - "js-tokens": "^10.0.0" - } - }, - "node_modules/ast-v8-to-istanbul/node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/ast-v8-to-istanbul/node_modules/js-tokens": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-10.0.0.tgz", - "integrity": "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true, - "license": "MIT" - }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", - "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.27.7", - "@babel/helper-define-polyfill-provider": "^0.6.5", - "semver": "^6.3.1" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", - "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5", - "core-js-compat": "^3.43.0" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", - "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.5" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, - "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==", - "dev": true, - "license": "MIT" - }, - "node_modules/baseline-browser-mapping": { - "version": "2.9.14", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.14.tgz", - "integrity": "sha512-B0xUquLkiGLgHhpPBqvl7GWegWBUNuujQ6kXd/r1U38ElPT6Ok8KZ8e+FpUGEc2ZoRQUzq/aUnaKFc/svWUGSg==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brotli-size": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/brotli-size/-/brotli-size-4.0.0.tgz", - "integrity": "sha512-uA9fOtlTRC0iqKfzff1W34DXUA3GyVqbUaeo3Rw3d4gd1eavKVCETXrn3NzO74W+UVkG3UHu8WxUi+XvKI/huA==", - "dev": true, - "license": "MIT", - "dependencies": { - "duplexer": "0.1.1" - }, - "engines": { - "node": ">= 10.16.0" - } - }, - "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", - "dev": true, - "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" - } - ], - "license": "MIT", - "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cacache": { - "version": "17.1.4", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-17.1.4.tgz", - "integrity": "sha512-/aJwG2l3ZMJ1xNAnqbMpA40of9dj/pIH3QfiuQSqjfPJF747VR0J/bHn+/KdNnHKc6XQcWt/AfRSBft82W1d2A==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^3.1.0", - "fs-minipass": "^3.0.0", - "glob": "^10.2.2", - "lru-cache": "^7.7.1", - "minipass": "^7.0.3", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "p-map": "^4.0.0", - "ssri": "^10.0.0", - "tar": "^6.1.11", - "unique-filename": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/cacache/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/camera-2d-simple": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camera-2d-simple/-/camera-2d-simple-3.0.0.tgz", - "integrity": "sha512-hBeuUeerQ2Repi/61PGyFkuJ9jt6IKAny7pjQo2w8/8uZh+RKvNLZQy4xbQeDH8FrlnFxAJDjyM4/yuLdOV5vQ==", - "license": "MIT", - "dependencies": { - "gl-matrix": "~3.3.0" - }, - "peerDependencies": { - "gl-matrix": "~3.3.0" - } - }, - "node_modules/camera-2d-simple/node_modules/gl-matrix": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.3.0.tgz", - "integrity": "sha512-COb7LDz+SXaHtl/h4LeaFcNdJdAQSDeVqjiIihSXNrkWObZLhDI4hIkZC11Aeqp7bcE72clzB0BnDXr2SmslRA==", - "license": "MIT" - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001764", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001764.tgz", - "integrity": "sha512-9JGuzl2M+vPL+pz70gtMF9sHdMFbY9FJaQBi186cHKH3pSzDvzoUJUPV6fqiKIMyXbud9ZLg4F3Yza1vJ1+93g==", - "dev": true, - "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" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chai": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", - "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "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, - "license": "MIT", - "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/chalk-template": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", - "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/chalk-template?sponsor=1" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "dev": true, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT" - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "license": "ISC", - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/colors": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", - "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/command-line-args": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-6.0.1.tgz", - "integrity": "sha512-Jr3eByUjqyK0qd8W0SGFW1nZwqCaNCtbXjRo2cRJC1OYxWl3MZ5t1US3jq+cO4sPavqgw4l9BMGX0CBe+trepg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-back": "^6.2.2", - "find-replace": "^5.0.2", - "lodash.camelcase": "^4.3.0", - "typical": "^7.2.0" - }, - "engines": { - "node": ">=12.20" - }, - "peerDependencies": { - "@75lb/nature": "latest" - }, - "peerDependenciesMeta": { - "@75lb/nature": { - "optional": true - } - } - }, - "node_modules/command-line-usage": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-7.0.3.tgz", - "integrity": "sha512-PqMLy5+YGwhMh1wS04mVG44oqDsgyLRSKJBdOo1bnYhMKBW65gZF1dRp2OZRhiTjgUHljy99qkO7bsctLaw35Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-back": "^6.2.2", - "chalk-template": "^0.4.0", - "table-layout": "^4.1.0", - "typical": "^7.1.1" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/commander": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", - "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "MIT" - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true, - "license": "ISC" - }, - "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, - "license": "MIT" - }, - "node_modules/core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "dev": true, - "hasInstallScript": true, - "license": "MIT" - }, - "node_modules/core-js-compat": { - "version": "3.47.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz", - "integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "browserslist": "^4.28.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-spawn/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "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==", - "dev": true, - "license": "ISC", - "dependencies": { - "internmap": "1 - 2" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-axis": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-3.0.0.tgz", - "integrity": "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "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==", - "dev": true, - "license": "ISC", - "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==", - "dev": true, - "license": "ISC", - "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==", - "dev": true, - "license": "ISC", - "dependencies": { - "d3-color": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/d3-random": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-3.0.1.tgz", - "integrity": "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==", - "dev": true, - "license": "ISC", - "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==", - "dev": true, - "license": "ISC", - "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-selection": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", - "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", - "dev": true, - "license": "ISC", - "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==", - "dev": true, - "license": "ISC", - "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==", - "dev": true, - "license": "ISC", - "dependencies": { - "d3-time": "1 - 3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "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, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dom-2d-camera": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/dom-2d-camera/-/dom-2d-camera-2.2.6.tgz", - "integrity": "sha512-HWfV26qjCfpOHa6X0PI1ZyZDhowk6skEs5f7aOwgewuJSP6IgPcK694ImYIOMGnDYK4vC4/Etsi26WpbJtS2vQ==", - "license": "MIT", - "dependencies": { - "camera-2d-simple": "^3.0.0", - "gl-matrix": "^3.3.0" - }, - "peerDependencies": { - "gl-matrix": "^3.3.0" - } - }, - "node_modules/duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha512-sxNZ+ljy+RA1maXoUReeqBBpBC6RLKmg5ewzV+x+mSETmWNoKdZN6vcQjpFROemza23hGFskJtFNoUWUaQ+R4Q==", - "dev": true - }, - "node_modules/earcut": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.2.tgz", - "integrity": "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==", - "license": "ISC" - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.267", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", - "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", - "dev": true, - "license": "ISC" - }, - "node_modules/email-addresses": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", - "integrity": "sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==", - "dev": true, - "license": "MIT" - }, - "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==", - "dev": true, - "license": "MIT" - }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true, - "license": "MIT" - }, - "node_modules/es-module-lexer": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.1.tgz", - "integrity": "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==", - "dev": true, - "license": "MIT" - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/esm": { - "version": "3.2.25", - "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", - "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expect-type": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", - "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/exponential-backoff": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", - "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "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.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", - "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/filename-reserved-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/filenamify": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-4.3.0.tgz", - "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "filename-reserved-regex": "^2.0.0", - "strip-outer": "^1.0.1", - "trim-repeated": "^1.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/filesize": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/filesize/-/filesize-6.4.0.tgz", - "integrity": "sha512-mjFIpOHC4jbfcTfoh4rkWpI31mF7viw9ikj/JyLoKzqlwG/YsefKfvYlYhdYdg/9mtK2z1AzgN/0LvVQ3zdlSQ==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 0.4.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==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-cache-dir": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", - "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", - "dev": true, - "license": "MIT", - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, - "node_modules/find-replace": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-5.0.2.tgz", - "integrity": "sha512-Y45BAiE3mz2QsrN2fb5QEtO4qb44NcS7en/0y9PEVsg351HsLeVclP8QPMH79Le9sH3rs5RSwJu99W0WPZO43Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "@75lb/nature": "latest" - }, - "peerDependenciesMeta": { - "@75lb/nature": { - "optional": true - } - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flatbuffers": { - "version": "25.9.23", - "resolved": "https://registry.npmjs.org/flatbuffers/-/flatbuffers-25.9.23.tgz", - "integrity": "sha512-MI1qs7Lo4Syw0EOzUl0xjs2lsoeqFku44KpngfIduHBYvzm8h2+7K8YMQh1JtVVVrUvhLpNwqVi4DERegUJhPQ==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fs-extra": { - "version": "11.3.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", - "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/fs-minipass": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-3.0.3.tgz", - "integrity": "sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "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, - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/gauge/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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/gauge/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/gh-pages": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/gh-pages/-/gh-pages-6.3.0.tgz", - "integrity": "sha512-Ot5lU6jK0Eb+sszG8pciXdjMXdBJ5wODvgjR+imihTqsUWF2K6dJ9HST55lgqcs8wWcw6o6wAsUzfcYRhJPXbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "async": "^3.2.4", - "commander": "^13.0.0", - "email-addresses": "^5.0.0", - "filenamify": "^4.3.0", - "find-cache-dir": "^3.3.1", - "fs-extra": "^11.1.1", - "globby": "^11.1.0" - }, - "bin": { - "gh-pages": "bin/gh-pages.js", - "gh-pages-clean": "bin/gh-pages-clean.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gl-matrix": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.4.tgz", - "integrity": "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==", - "license": "MIT" - }, - "node_modules/glob": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", - "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", - "dev": true, - "license": "ISC", - "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/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "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/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/gzip-size": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz", - "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "duplexer": "^0.1.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gzip-size/node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hosted-git-info": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.3.tgz", - "integrity": "sha512-HVJyzUrLIL1c0QmviVh5E8VGyUS7xCFPS6yydaVd1UegW+ibV/CohqTH9MkOLDp5o+rb82DMo77PTuc9F/8GKw==", - "dev": true, - "license": "ISC", - "dependencies": { - "lru-cache": "^7.5.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/hosted-git-info/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true, - "license": "MIT" - }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.0.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-walk": { - "version": "6.0.5", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-6.0.5.tgz", - "integrity": "sha512-VuuG0wCnjhnylG1ABXT3dAuIpTNDs/G8jlpmwXY03fXoXy/8ZK8/T+hMzt8L4WnrLCJgdybqgPagnF/f97cg3A==", - "dev": true, - "license": "ISC", - "dependencies": { - "minimatch": "^9.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true, - "license": "ISC" - }, - "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, - "license": "ISC", - "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, - "license": "ISC" - }, - "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==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/ip-address": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", - "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", - "dev": true, - "license": "MIT" - }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-lib-report/node_modules/make-dir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", - "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.5.3" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/istanbul-lib-report/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", - "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "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==", - "dev": true, - "license": "MIT" - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-bignum": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/json-bignum/-/json-bignum-0.0.3.tgz", - "integrity": "sha512-2WHyXj3OfHSgNyuzDbSxI1w2jgw5gkWSWhS7Qg4bWXx1nLk3jnbwfUeS0PSba3IzpTUWdHxBieELUzXRjQB2zg==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-3.0.2.tgz", - "integrity": "sha512-fi0NG4bPjCHunUJffmLd0gxssIgkNmArMvis4iNah6Owg1MCJjWhEcDLmsK6iGkJq3tHwbDkTlce70/tmXN4cQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "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, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonparse": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", - "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", - "dev": true, - "engines": [ - "node >= 0.2.0" - ], - "license": "MIT" - }, - "node_modules/lightningcss": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", - "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "detect-libc": "^2.0.3" - }, - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - }, - "optionalDependencies": { - "lightningcss-android-arm64": "1.33.0", - "lightningcss-darwin-arm64": "1.33.0", - "lightningcss-darwin-x64": "1.33.0", - "lightningcss-freebsd-x64": "1.33.0", - "lightningcss-linux-arm-gnueabihf": "1.33.0", - "lightningcss-linux-arm64-gnu": "1.33.0", - "lightningcss-linux-arm64-musl": "1.33.0", - "lightningcss-linux-x64-gnu": "1.33.0", - "lightningcss-linux-x64-musl": "1.33.0", - "lightningcss-win32-arm64-msvc": "1.33.0", - "lightningcss-win32-x64-msvc": "1.33.0" - } - }, - "node_modules/lightningcss-android-arm64": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", - "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-arm64": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", - "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-darwin-x64": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", - "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-freebsd-x64": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", - "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", - "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", - "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", - "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", - "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "glibc" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-linux-x64-musl": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", - "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", - "cpu": [ - "x64" - ], - "dev": true, - "libc": [ - "musl" - ], - "license": "MPL-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", - "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.33.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", - "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MPL-2.0", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 12.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/parcel" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", - "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true, - "license": "MIT" - }, - "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, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/magicast": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.3.tgz", - "integrity": "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.29.3", - "@babel/types": "^7.29.0", - "source-map-js": "^1.2.1" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "license": "ISC", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/make-fetch-happen/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/make-fetch-happen/node_modules/minimatch": { - "version": "5.1.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", - "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-fetch-happen/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/make-fetch-happen/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-fetch-happen/node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dev": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/merge": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", - "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", - "dev": true, - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.2" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-collect/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/minipass-fetch/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-fetch/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-flush/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-flush/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minipass-json-stream": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/minipass-json-stream/-/minipass-json-stream-1.0.2.tgz", - "integrity": "sha512-myxeeTm57lYs8pH2nxPzmEEg8DGIgW+9mv6D4JZD2pa81I/OBjeU7PtICXV6c9eRGTA5JMDsuIPUZRCyBMYNhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "jsonparse": "^1.3.1", - "minipass": "^3.0.0" - } - }, - "node_modules/minipass-json-stream/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-json-stream/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-pipeline/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mrmime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", - "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "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==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.16", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", - "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/node-gyp": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-9.4.1.tgz", - "integrity": "sha512-OQkWKbjQKbGkMf/xqI1jjy3oCTgMKJac58G2+bjZb3fza6gW2YrCSdMQYaoTb70crvE//Gngr4f0AgVHmqHvBQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^7.1.4", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.0.3", - "nopt": "^6.0.0", - "npmlog": "^6.0.0", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "tar": "^6.1.2", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": "^12.13 || ^14.13 || >=16" - } - }, - "node_modules/node-gyp/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/node-gyp/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, - "license": "ISC", - "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/node-gyp/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/node-gyp/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-gyp/node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "license": "ISC", - "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/normalize-package-data": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-5.0.0.tgz", - "integrity": "sha512-h9iPVIfrVZ9wVYQnxFgtw1ugSvGEMOlyPWWtm8BMJhnwyEL/FLbYbTY3V3PpjI/BUK67n9PEWDu6eHzu1fB15Q==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^6.0.0", - "is-core-module": "^2.8.1", - "semver": "^7.3.5", - "validate-npm-package-license": "^3.0.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm-bundled": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-3.0.1.tgz", - "integrity": "sha512-+AvaheE/ww1JEwRHOrn4WHNzOxGtVp+adrg2AeZS/7KuxGUYFuBta98wYpfHBbJp6Tg6j1NKSEVHNcfZzJHQwQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-install-checks": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/npm-install-checks/-/npm-install-checks-6.3.0.tgz", - "integrity": "sha512-W29RiK/xtpCGqn6f3ixfRYGk+zRyr+Ew9F2E20BfXxT5/euLdA/Nm7fO7OeTGuAmTs30cpgInyJ0cYe708YTZw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "semver": "^7.1.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-install-checks/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm-normalize-package-bin": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-3.0.1.tgz", - "integrity": "sha512-dMxCf+zZ+3zeQZXKxmyuCKlIDPGuv8EF940xbkC4kQVDTtqoh6rJFO+JTKSA6/Rwi0getWmtuy4Itup0AMcaDQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-package-arg": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/npm-package-arg/-/npm-package-arg-10.1.0.tgz", - "integrity": "sha512-uFyyCEmgBfZTtrKk/5xDfHp6+MdrqGotX/VoOyEEl3mBwiEE5FlBaePanazJSVMPT7vKepcjYBY2ztg9A3yPIA==", - "dev": true, - "license": "ISC", - "dependencies": { - "hosted-git-info": "^6.0.0", - "proc-log": "^3.0.0", - "semver": "^7.3.5", - "validate-npm-package-name": "^5.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-package-arg/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm-packlist": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-7.0.4.tgz", - "integrity": "sha512-d6RGEuRrNS5/N84iglPivjaJPxhDbZmlbTwTDX2IbcRHG5bZCdtysYMhwiPvcF4GisXHGn7xsxv+GQ7T/02M5Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "ignore-walk": "^6.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-pick-manifest": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/npm-pick-manifest/-/npm-pick-manifest-8.0.2.tgz", - "integrity": "sha512-1dKY+86/AIiq1tkKVD3l0WI+Gd3vkknVGAggsFeBkTvbhMQ1OND/LKkYv4JtXPKUJ8bOTCyLiqEg2P6QNdK+Gg==", - "dev": true, - "license": "ISC", - "dependencies": { - "npm-install-checks": "^6.0.0", - "npm-normalize-package-bin": "^3.0.0", - "npm-package-arg": "^10.0.0", - "semver": "^7.3.5" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-pick-manifest/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/npm-registry-fetch": { - "version": "14.0.5", - "resolved": "https://registry.npmjs.org/npm-registry-fetch/-/npm-registry-fetch-14.0.5.tgz", - "integrity": "sha512-kIDMIo4aBm6xg7jOttupWZamsZRkAqMqwqqbVXnUqstY5+tapvv6bkH/qMR76jdgV+YljEUCyWx3hRYMrJiAgA==", - "dev": true, - "license": "ISC", - "dependencies": { - "make-fetch-happen": "^11.0.0", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-json-stream": "^1.0.1", - "minizlib": "^2.1.2", - "npm-package-arg": "^10.0.0", - "proc-log": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-registry-fetch/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/npm-registry-fetch/node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "license": "ISC", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/npm-registry-fetch/node_modules/minipass-fetch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", - "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/npm-registry-fetch/node_modules/minipass-fetch/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "deprecated": "This package is no longer supported.", - "dev": true, - "license": "ISC", - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/obug": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", - "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", - "dev": true, - "funding": [ - "https://github.com/sponsors/sxzz", - "https://opencollective.com/debug" - ], - "license": "MIT" - }, - "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==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "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==", - "dev": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/pacote": { - "version": "15.2.0", - "resolved": "https://registry.npmjs.org/pacote/-/pacote-15.2.0.tgz", - "integrity": "sha512-rJVZeIwHTUta23sIZgEIM62WYwbmGbThdbnkt81ravBplQv+HjyroqnLRNH2+sLJHcGZmLRmhPwACqhfTcOmnA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/git": "^4.0.0", - "@npmcli/installed-package-contents": "^2.0.1", - "@npmcli/promise-spawn": "^6.0.1", - "@npmcli/run-script": "^6.0.0", - "cacache": "^17.0.0", - "fs-minipass": "^3.0.0", - "minipass": "^5.0.0", - "npm-package-arg": "^10.0.0", - "npm-packlist": "^7.0.0", - "npm-pick-manifest": "^8.0.0", - "npm-registry-fetch": "^14.0.0", - "proc-log": "^3.0.0", - "promise-retry": "^2.0.1", - "read-package-json": "^6.0.0", - "read-package-json-fast": "^3.0.0", - "sigstore": "^1.3.0", - "ssri": "^10.0.0", - "tar": "^6.1.11" - }, - "bin": { - "pacote": "lib/bin.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "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, - "license": "MIT", - "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, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT" - }, - "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==", - "dev": true, - "license": "BlueOak-1.0.0", - "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==", - "dev": true, - "license": "ISC" - }, - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", - "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/playwright": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.57.0.tgz", - "integrity": "sha512-ilYQj1s8sr2ppEJ2YVadYBN0Mb3mdo9J0wQ+UuDhzYqURwSoW4n1Xs5vs7ORwgDGmyEh33tRMeS8KhdkMoLXQw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "playwright-core": "1.57.0" - }, - "bin": { - "playwright": "cli.js" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "fsevents": "2.3.2" - } - }, - "node_modules/playwright-core": { - "version": "1.57.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.57.0.tgz", - "integrity": "sha512-agTcKlMw/mjBWOnD6kFZttAAGHgi/Nw0CZ2o6JqWSbMlI219lAFLZZCyqByTsvVAJq5XA5H8cA6PrvBRpBWEuQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "playwright-core": "cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/pngjs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz", - "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.19.0" - } - }, - "node_modules/postcss": { - "version": "8.5.22", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.22.tgz", - "integrity": "sha512-KBDEIpLrvpv16pp3K0Fw+UCoZfopFjjgeB+0tA/aaThfEE74kKDLrgg603YvOWJyg3+WYtyq3xYsQWsIyZlPqQ==", - "dev": true, - "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" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.16", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/proc-log": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-3.0.0.tgz", - "integrity": "sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/pub-sub-es": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pub-sub-es/-/pub-sub-es-3.0.0.tgz", - "integrity": "sha512-pf+6yCPsOfvDMru2LnsqdKSN8XQyF5HZzmEoKBvjMk4TILMUQiq1vxI6rC92T9ErY06sLXBmC1p7JGNFVB1pUQ==", - "license": "MIT" - }, - "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==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/read-package-json": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-6.0.4.tgz", - "integrity": "sha512-AEtWXYfopBj2z5N5PbkAOeNHRPUg5q+Nen7QLxV8M2zJq1ym6/lCz3fYNTCXe19puu2d06jfHhrP7v/S2PtMMw==", - "deprecated": "This package is no longer supported. Please use @npmcli/package-json instead.", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^10.2.2", - "json-parse-even-better-errors": "^3.0.0", - "normalize-package-data": "^5.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/read-package-json-fast": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-3.0.2.tgz", - "integrity": "sha512-0J+Msgym3vrLOUB3hzQCuZHII0xkNGCtz/HJH9xZshwv9DbDwkw1KaE3gx/e2J5rpEY5rtOy6cyhKOPrkP7FZw==", - "dev": true, - "license": "ISC", - "dependencies": { - "json-parse-even-better-errors": "^3.0.0", - "npm-normalize-package-bin": "^3.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true, - "license": "MIT" - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", - "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", - "dev": true, - "license": "MIT" - }, - "node_modules/regexpu-core": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", - "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.2.2", - "regjsgen": "^0.8.0", - "regjsparser": "^0.13.0", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.2.1" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/regjsparser": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", - "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "jsesc": "~3.1.0" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, - "node_modules/regl": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/regl/-/regl-2.1.1.tgz", - "integrity": "sha512-+IOGrxl3FZ8ZM9ixCWQZzFRiRn7Rzn9bu3iFHwg/yz4tlOUQgbO4PHLgG+1ZT60zcIV8tief6Qrmyl8qcoJP0g==", - "license": "MIT" - }, - "node_modules/regl-line": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/regl-line/-/regl-line-1.1.1.tgz", - "integrity": "sha512-IKcyiZq+nQg7x3mEmxf9kImM9CzmEyZDhCCfas2xVpsoiDJFEyILsuocD1G4dSXA/nC39za9OBw4FzYEgWNiUg==", - "license": "MIT", - "dependencies": { - "gl-matrix": "^3.3.0", - "regl": "^2.1.0" - }, - "peerDependencies": { - "regl": "^2.1.0" - } - }, - "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "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, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rimraf/node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/rimraf/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, - "license": "ISC", - "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/rimraf/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/rolldown": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz", - "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@oxc-project/types": "=0.139.0", - "@rolldown/pluginutils": "^1.0.0" - }, - "bin": { - "rolldown": "bin/cli.mjs" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.1.5", - "@rolldown/binding-darwin-arm64": "1.1.5", - "@rolldown/binding-darwin-x64": "1.1.5", - "@rolldown/binding-freebsd-x64": "1.1.5", - "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", - "@rolldown/binding-linux-arm64-gnu": "1.1.5", - "@rolldown/binding-linux-arm64-musl": "1.1.5", - "@rolldown/binding-linux-ppc64-gnu": "1.1.5", - "@rolldown/binding-linux-s390x-gnu": "1.1.5", - "@rolldown/binding-linux-x64-gnu": "1.1.5", - "@rolldown/binding-linux-x64-musl": "1.1.5", - "@rolldown/binding-openharmony-arm64": "1.1.5", - "@rolldown/binding-wasm32-wasi": "1.1.5", - "@rolldown/binding-win32-arm64-msvc": "1.1.5", - "@rolldown/binding-win32-x64-msvc": "1.1.5" - } - }, - "node_modules/rollup": { - "version": "4.59.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", - "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.59.0", - "@rollup/rollup-android-arm64": "4.59.0", - "@rollup/rollup-darwin-arm64": "4.59.0", - "@rollup/rollup-darwin-x64": "4.59.0", - "@rollup/rollup-freebsd-arm64": "4.59.0", - "@rollup/rollup-freebsd-x64": "4.59.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", - "@rollup/rollup-linux-arm-musleabihf": "4.59.0", - "@rollup/rollup-linux-arm64-gnu": "4.59.0", - "@rollup/rollup-linux-arm64-musl": "4.59.0", - "@rollup/rollup-linux-loong64-gnu": "4.59.0", - "@rollup/rollup-linux-loong64-musl": "4.59.0", - "@rollup/rollup-linux-ppc64-gnu": "4.59.0", - "@rollup/rollup-linux-ppc64-musl": "4.59.0", - "@rollup/rollup-linux-riscv64-gnu": "4.59.0", - "@rollup/rollup-linux-riscv64-musl": "4.59.0", - "@rollup/rollup-linux-s390x-gnu": "4.59.0", - "@rollup/rollup-linux-x64-gnu": "4.59.0", - "@rollup/rollup-linux-x64-musl": "4.59.0", - "@rollup/rollup-openbsd-x64": "4.59.0", - "@rollup/rollup-openharmony-arm64": "4.59.0", - "@rollup/rollup-win32-arm64-msvc": "4.59.0", - "@rollup/rollup-win32-ia32-msvc": "4.59.0", - "@rollup/rollup-win32-x64-gnu": "4.59.0", - "@rollup/rollup-win32-x64-msvc": "4.59.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/rollup-plugin-filesize": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-filesize/-/rollup-plugin-filesize-10.0.0.tgz", - "integrity": "sha512-JAYYhzCcmGjmCzo3LEHSDE3RAPHKIeBdpqRhiyZSv5o/3wFhktUOzYAWg/uUKyEu5dEaVaql6UOmaqHx1qKrZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.13.8", - "boxen": "^5.0.0", - "brotli-size": "4.0.0", - "colors": "1.4.0", - "filesize": "^6.1.0", - "gzip-size": "^6.0.0", - "pacote": "^15.1.1", - "terser": "^5.6.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "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==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "license": "MIT", - "optional": true - }, - "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, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/serialize-javascript": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-7.0.5.tgz", - "integrity": "sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true, - "license": "ISC" - }, - "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==", - "dev": true, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true, - "license": "ISC" - }, - "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==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sigstore": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/sigstore/-/sigstore-1.9.0.tgz", - "integrity": "sha512-0Zjz0oe37d08VeOtBIuB6cRriqXse2e8w+7yIy2XSXjshRKxbc2KkhXjL229jXSxEm7UbcjS76wcJDGQddVI9A==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@sigstore/bundle": "^1.1.0", - "@sigstore/protobuf-specs": "^0.2.0", - "@sigstore/sign": "^1.0.0", - "@sigstore/tuf": "^1.0.3", - "make-fetch-happen": "^11.0.1" - }, - "bin": { - "sigstore": "bin/sigstore.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/sigstore/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/sigstore/node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "license": "ISC", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/sigstore/node_modules/minipass-fetch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", - "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/sigstore/node_modules/minipass-fetch/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/sirv": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", - "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@polka/url": "^1.0.0-next.24", - "mrmime": "^2.0.0", - "totalist": "^3.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/smob": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", - "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==", - "dev": true, - "license": "MIT" - }, - "node_modules/socks": { - "version": "2.8.7", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", - "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ip-address": "^10.0.1", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "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==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.22", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", - "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/ssri": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/ssri/-/ssri-10.0.6.tgz", - "integrity": "sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^7.0.3" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/ssri/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/std-env": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", - "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", - "dev": true, - "license": "MIT" - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "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==", - "dev": true, - "license": "MIT", - "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": { - "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==", - "dev": true, - "license": "MIT", - "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/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs/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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-outer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "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, - "license": "MIT", - "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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/table-layout": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-4.1.1.tgz", - "integrity": "sha512-iK5/YhZxq5GO5z8wb0bY1317uDF3Zjpha0QFFLA8/trAoiLbQD0HUbMesEaxyzUgDxi2QlcbM8IvqOlEjgoXBA==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-back": "^6.2.2", - "wordwrapjs": "^5.1.0" - }, - "engines": { - "node": ">=12.17" - } - }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/tar/node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/terser": { - "version": "5.44.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", - "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", - "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.17", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", - "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.4" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyrainbow": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz", - "integrity": "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/totalist": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", - "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/trim-repeated": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD" - }, - "node_modules/tuf-js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/tuf-js/-/tuf-js-1.1.7.tgz", - "integrity": "sha512-i3P9Kgw3ytjELUfpuKVDNBJvk4u5bXL6gskv572mcevPbSKCV3zt3djhmlEQ65yERjIbOSncy7U4cQJaB1CBCg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tufjs/models": "1.0.4", - "debug": "^4.3.4", - "make-fetch-happen": "^11.1.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/tuf-js/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/tuf-js/node_modules/make-fetch-happen": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-11.1.1.tgz", - "integrity": "sha512-rLWS7GCSTcEujjVBs2YqG7Y4643u8ucvCJeSRqiLYhesrDuzeuFIk37xREzAsfQaqzl8b9rNCE4m6J8tvX4Q8w==", - "dev": true, - "license": "ISC", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^17.0.0", - "http-cache-semantics": "^4.1.1", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^5.0.0", - "minipass-fetch": "^3.0.0", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^10.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/tuf-js/node_modules/minipass-fetch": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-3.0.5.tgz", - "integrity": "sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^7.0.3", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/tuf-js/node_modules/minipass-fetch/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/tweakpane": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/tweakpane/-/tweakpane-4.0.5.tgz", - "integrity": "sha512-rxEXdSI+ArlG1RyO6FghC4ZUX8JkEfz8F3v1JuteXSV0pEtHJzyo07fcDG+NsJfN5L39kSbCYbB9cBGHyuI/tQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/cocopon" - } - }, - "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, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typical": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-7.3.0.tgz", - "integrity": "sha512-ya4mg/30vm+DOWfBg4YK3j2WD6TWtRkCbasOJr40CseYENzCUby/7rIvXA99JGsQHeNxLbnXdyLLxKSv3tauFw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.17" - } - }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, - "license": "MIT" - }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", - "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", - "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", - "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/unique-filename": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-3.0.0.tgz", - "integrity": "sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==", - "dev": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^4.0.0" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/unique-slug": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-4.0.0.tgz", - "integrity": "sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "dev": true, - "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" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "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==", - "dev": true, - "license": "MIT" - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/validate-npm-package-name": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-name/-/validate-npm-package-name-5.0.1.tgz", - "integrity": "sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/vite": { - "version": "8.1.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.5.tgz", - "integrity": "sha512-7ULLwsCdYx/nRyrpiEwvqb5TFHrMVZyBt+rg/OAXT7rgj/z+DtTDyKFeLAdDkubDVDKD8jOsndmy7m55XcfUsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "lightningcss": "^1.32.0", - "picomatch": "^4.0.5", - "postcss": "^8.5.17", - "rolldown": "~1.1.5", - "tinyglobby": "^0.2.17" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.3.0", - "esbuild": "^0.27.0 || ^0.28.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "@vitejs/devtools": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite-plugin-virtual-html-template": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vite-plugin-virtual-html-template/-/vite-plugin-virtual-html-template-1.1.0.tgz", - "integrity": "sha512-/60jZyMrodtf1oev6iBbJaQgadr96sseYioo3rhu0vs69xlCdWK8EWGNTuFDc6aqyIoFauSf6mYOAqA45OxMNA==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash": "^4.17.21" - } - }, - "node_modules/vite/node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/vitest": { - "version": "4.1.10", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.10.tgz", - "integrity": "sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "4.1.10", - "@vitest/mocker": "4.1.10", - "@vitest/pretty-format": "4.1.10", - "@vitest/runner": "4.1.10", - "@vitest/snapshot": "4.1.10", - "@vitest/spy": "4.1.10", - "@vitest/utils": "4.1.10", - "es-module-lexer": "^2.0.0", - "expect-type": "^1.3.0", - "magic-string": "^0.30.21", - "obug": "^2.1.1", - "pathe": "^2.0.3", - "picomatch": "^4.0.3", - "std-env": "^4.0.0-rc.1", - "tinybench": "^2.9.0", - "tinyexec": "^1.0.2", - "tinyglobby": "^0.2.15", - "tinyrainbow": "^3.1.0", - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || >=24.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@opentelemetry/api": "^1.9.0", - "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", - "@vitest/browser-playwright": "4.1.10", - "@vitest/browser-preview": "4.1.10", - "@vitest/browser-webdriverio": "4.1.10", - "@vitest/coverage-istanbul": "4.1.10", - "@vitest/coverage-v8": "4.1.10", - "@vitest/ui": "4.1.10", - "happy-dom": "*", - "jsdom": "*", - "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@opentelemetry/api": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser-playwright": { - "optional": true - }, - "@vitest/browser-preview": { - "optional": true - }, - "@vitest/browser-webdriverio": { - "optional": true - }, - "@vitest/coverage-istanbul": { - "optional": true - }, - "@vitest/coverage-v8": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - }, - "vite": { - "optional": false - } - } - }, - "node_modules/which": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/which/-/which-3.0.1.tgz", - "integrity": "sha512-XA1b62dzQzLfaEOSQFTCOd5KFf/1VSzZo7/7TUjnya6u0vGGKzU96UQBZTAThCb2j4/xjBAyii1OhRLJEivHvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/which.js" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "dev": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wordwrapjs": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-5.1.1.tgz", - "integrity": "sha512-0yweIbkINJodk27gX9LBGMzyQdBDan3s/dEAiwBOj+Mf0PPyWL6/rikalkv8EeD0E8jm4o5RXEOrFTP3NXbhJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.17" - } - }, - "node_modules/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==", - "dev": true, - "license": "MIT", - "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": { - "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==", - "dev": true, - "license": "MIT", - "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/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/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==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "dev": true, - "license": "ISC" - }, - "node_modules/ws": { - "version": "8.21.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz", - "integrity": "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index 03232e67..00000000 --- a/package.json +++ /dev/null @@ -1,97 +0,0 @@ -{ - "name": "regl-scatterplot", - "version": "1.16.0", - "description": "A WebGL-Powered Scalable Interactive Scatter Plot Library", - "author": "Fritz Lekschas", - "keywords": [ - "scatterplot", - "2d scatter", - "interactive data visualization", - "regl", - "WebGL", - "embedding plot" - ], - "license": "MIT", - "type": "module", - "main": "dist/regl-scatterplot.js", - "module": "dist/regl-scatterplot.esm.js", - "types": "dist/regl-scatterplot.esm.d.ts", - "files": [ - "src/*", - "dist/*" - ], - "scripts": { - "build": "npm run build-library; npm run build-demo", - "build-library": "rm -rf dist/*; rollup -c; cp src/types.d.ts dist/; sed -i 's/\\.\\/renderer/\\.\\/regl-scatterplot.esm/g' dist/types.d.ts; tsc dist/*.esm.js --allowJs --declaration --emitDeclarationOnly", - "build-demo": "vite build", - "deploy": "npm run build-demo; touch docs/.nojekyll; gh-pages -d docs -t --git git", - "lint": "biome check --write .", - "precommit": "npm run test", - "prepublishOnly": "npm run test; rm -rf dist/*; npm run build;", - "prerelease": "rm -rf dist/*; npm run build; zip -r dist.zip dist", - "pretest": "npm run lint", - "prestart": "cp scripts/pre-commit .git/hooks/ && chmod +x .git/hooks/pre-commit && echo 'pre-commit hook copied'", - "start": "vite --port=3000", - "test": "vitest run", - "coverage": "vitest run --coverage" - }, - "dependencies": { - "@flekschas/utils": "^0.33.0", - "dom-2d-camera": "^2.2.6", - "earcut": "^3.0.2", - "gl-matrix": "~3.4.4", - "pub-sub-es": "~3.0.0", - "regl": "~2.1.1", - "regl-line": "~1.1.1" - }, - "peerDependencies": { - "pub-sub-es": "~3.0.0", - "regl": "~2.1.1" - }, - "devDependencies": { - "@babel/core": "^7.28.6", - "@babel/plugin-transform-regenerator": "^7.28.6", - "@babel/polyfill": "^7.12.1", - "@babel/preset-env": "^7.28.6", - "@biomejs/biome": "^2.3.11", - "@rollup/plugin-babel": "^6.1.0", - "@rollup/plugin-commonjs": "^29.0.0", - "@rollup/plugin-json": "^6.0.0", - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^1.0.0", - "@tweakpane/core": "^2.0.5", - "@types/d3-scale": "^4.0.9", - "@types/node": "^25.0.8", - "@vitest/browser": "^4.0.17", - "@vitest/browser-playwright": "^4.0.17", - "@vitest/coverage-v8": "^4.0.17", - "apache-arrow": "^21.1.0", - "d3-axis": "^3.0.0", - "d3-random": "^3.0.1", - "d3-scale": "^4.0.2", - "d3-selection": "^3.0.0", - "esm": "^3.2.25", - "gh-pages": "^6.3.0", - "merge": "^2.1.1", - "playwright": "^1.57.0", - "rollup": "^4.55.1", - "rollup-plugin-filesize": "^10.0.0", - "tweakpane": "^4.0.5", - "typescript": "~5.9.3", - "vite": "^8.1.5", - "vite-plugin-virtual-html-template": "^1.1.0", - "vitest": "^4.0.17" - }, - "engines": { - "npm": ">=7.0.0", - "node": ">=20.0.0" - }, - "homepage": "https://github.com/flekschas/regl-scatterplot", - "repository": { - "type": "git", - "url": "git://github.com/flekschas/regl-scatterplot.git" - }, - "bugs": { - "url": "https://github.com/flekschas/regl-scatterplot/issues" - } -} diff --git a/paper.md b/paper.md deleted file mode 100644 index 3fceff93..00000000 --- a/paper.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: - 'Regl-Scatterplot: A Scalable Interactive JavaScript-based Scatter Plot - Library' -tags: - - scatter plot - - 2D scatter - - interactive data visualization - - JavaScript - - embedding plot - - WebGL -authors: - - name: Fritz Lekschas - orcid: 0000-0001-8432-4835 - affiliation: 1 -affiliations: - - name: Independent Researcher, USA - index: 1 -date: 14 February 2023 -bibliography: paper/refs.bib ---- - -# Summary - -Scatter plots are one of the most popular visualization methods to surface -correlations (like trends or clusters) in bivariate data. They are used across -all scientific domains. With datasets ever increasing in size, it can become -challenging to effectively render and explore scatter plots. Hence, there is a -need for scalable and interactive scatter plot libraries. - -![Examples of `regl-scatterplot`. The top row visualizes the Rössler attractor -and demonstrates the dynamic point opacity. As one zooms in (see the white -bounding box) and number of points in the view decreases, the point opacity -increases. The bottom row shows four embeddings of the Fashion MNIST dataset -[@xiao2017fashion] created with PCA [@pearson1901], t-SNE -[@vandermaaten2008visualizing], UMAP [@leland2018umap], and a variational -autoencoder [@kingma2013auto]. The embeddings are visualized using four -`regl-scatterplot` instances that synchronize and zoom to the selected points. -For instance, upon selecting the sky blue cluster of points in the top-right -instance (see the white bounding box), the same points are selected in the other -instances. Also, all four instances zoom to the selected points (right side of -the second row).\label{fig:teaser}](paper/teaser.jpg) - -`regl-scatterplot` is a general-purpose data visualization library written in -JavaScript for rendering large-scale scatter plots on the web -(\autoref{fig:teaser}). Every aspect of the library focuses on performance. -Thanks to its WebGL-based renderer, which is written with `regl` [@regl], the -library can draw up to twenty million points while offering smooth pan and zoom. -To interact with the data points, `regl-scatterplot` implements fast lasso -selections using a spatial index [@kdbush]. - -Beyond the rendering and interaction performance, visualizing large datasets as -scatter plots also poses perceptual challenges [@micallef2017towards]. In -particular, the right level of opacity is critical to faithfully represent the -data distribution while ensuring that outliers are perceivable. To simplify this -aspect of the scatter plot design, `regl-scatterplot` implements a density-based -point opacity that extends an approach by @reusser2022selecting. In addition to -the original approach, the opacity dynamically adjusts to the points within the -field of view as the user pans and zooms. Finally, `regl-scatterplot` supports -drawing spline-interpolated point connections and animated transitions of the -point location and color encoding when drawing a new dataset with point -correspondences (\autoref{fig:additional}). - -![Additional features of `regl-scatterplot`. On the left side, we show an -example of point connections rendered as spline-interpolated lines. Note that -connections of selected points are highlighted as well. On the right side, we -show nine key frames of an animated transition of the point locations from a -geographical to a bar chart representation. The points visualize cities across -the globe [@geonames]. The animation example was inspired by -@beshai2017beautiful. -\label{fig:additional}](paper/additional.jpg) - -# Statement of Need - -`regl-scatterplot` was designed for visualization researchers and practitioners. -It has already been cited in a number of scientific publications -[@lekschas2020peax; @santala2020fast; @narechania2022vitality; -@bauerle2022symphony; @warchol2023visinity], it formed the software foundation -for a computer science master thesis [@hindersson2021scatterplot], and it is -actively used in scientific software tools [@peax; @histocat; @eodash; -@gotreescape; @jscatter; @warchol2023visinity; @cabrera23zeno]. The focus on -scalable rendering and interactions in combinations with a wide variety of -design customizations in `regl-scatterplot` enables visualization researchers -and practitioners to build, study, and test new visualization tools and -applications for scalable exploration of the ever-increasing number of -large-scale datasets. - -# Related & Future Work - -There are several related JavaScript packages for rendering scatter plots on the -web. General-purpose visualization libraries like `d3` [@bostock2011d3] or -`vega-lite` [@satyanarayan2016vegalite] are broadly useful, but are not well -suited to render datasets with millions of data points due to the reliance on a -Document Object Model (in the case of `d3`) and limited support for GPU-based -rendering. Like `regl-scatterplot`, `CandyGraph` [@candygraph] overcomes this -limitation by using WebGL for the rendering. However, being a general-purpose -plotting library means that `CandyGraph` does not offer critical features for -exploring scatter plots interactively like pan-and-zoom, lasso selections, etc. -The visualization charting library `plotly.js` [@plotlyjs] has support for WebGL -rendering and offers interactive pan-or-zoom and lasso selection, but is lacking -other features like animated transitions, dynamic point opacity, or -synchronization of multiple scatter plot instances. Similarly, the bespoke -`regl-scatter2d` [@reglscatter2d] library offers scalable WebGL-based rendering -of scatter plots and allows customizing the point shape. However, it does not -support data-driven visual encodings or interactive point selections. Finally, -`deepscatter` [@deepscatter] is another scalable scatter plot library that -offers data-driven visual encodings. Its reliance on tile-based data enables -even greater scalability compared to `regl-scatterplot` but at the expense of -having to preprocess data. Also, as of today, the library is lacking support for -lasso selections or the ability to synchronize multiple scatter plot instances. - -In the future, we plan to add built-in support for streaming tiled Apache Arrow -files in `regl-scatterplot` to further improve the performance. We also plan to -move as much or ideally all of `regl-scatterplot`'s code to web workers, which -would help to avoid any performance impact on the main thread. - -# Acknowledgements - -We acknowledge contributions from Jeremy A. Prescott, Trevor Manz, and Emlyn -Clay, and Dušan Josipović. - -# References diff --git a/paper/additional.jpg b/paper/additional.jpg deleted file mode 100644 index 6fa133a5..00000000 Binary files a/paper/additional.jpg and /dev/null differ diff --git a/paper/refs.bib b/paper/refs.bib deleted file mode 100644 index 4ab345bd..00000000 --- a/paper/refs.bib +++ /dev/null @@ -1,274 +0,0 @@ -@article{lekschas2020peax, - author = {Fritz Lekschas and Brant Peterson and Daniel Haehn and Eric Ma and Nils Gehlenborg and Hanspeter Pfister}, - title = {Peax: Interactive Visual Pattern Search in Sequential Data Using Unsupervised Deep Representation Learning}, - journal = {Computer Graphics Forum}, - volume = {39}, - number = {3}, - pages = {167-179}, - series = {EuroVis ’20}, - publisher = {The Eurographics Association and John Wiley & Sons Ltd.}, - year = {2020}, - month = {7}, - day = {18}, - doi = {10.1111/cgf.13971}, - url = {https://vcg.seas.harvard.edu/publications/peax-interactive-visual-pattern-search-in-sequential-data-using-unsupervised-deep-representation-learning} -} - -@inproceedings{santala2020fast, - author = {Santala, Simo}, - title = {Fast Interactive Design of Scatterplots for Large Data Set Visualisation}, - year = {2020}, - publisher = {Association for Computing Machinery}, - address = {New York, NY, USA}, - url = {https://doi.org/10.1145/3334480.3381443}, - doi = {10.1145/3334480.3381443}, - pages = {1–6}, - numpages = {6}, - location = {Honolulu, HI, USA}, - series = {CHI EA '20} -} - -@article{narechania2022vitality, - title = {VITALITY: Promoting Serendipitous Discovery of Academic Literature with Transformers \& Visual Analytics}, - author = {Narechania, Arpit and Karduni, Alireza and Wesslen, Ryan and Wall, Emily}, - journal = {IEEE Transactions on Visualization and Computer Graphics}, - year = {2022}, - volume = {28}, - number = {01}, - issn = {1941-0506}, - pages = {486-496}, - doi = {10.1109/TVCG.2021.3114820}, - publisher = {IEEE Computer Society}, - address = {Los Alamitos, CA, USA} -} - -@inproceedings{bauerle2022symphony, - author = {B\"{a}uerle, Alex and Cabrera, \'{A}ngel Alexander and Hohman, Fred and Maher, Megan and Koski, David and Suau, Xavier and Barik, Titus and Moritz, Dominik}, - title = {Symphony: Composing Interactive Interfaces for Machine Learning}, - year = {2022}, - publisher = {Association for Computing Machinery}, - address = {New York, NY, USA}, - url = {https://doi.org/10.1145/3491102.3502102}, - doi = {10.1145/3491102.3502102}, - numpages = {14}, - location = {New Orleans, LA, USA}, - series = {CHI '22} -} - -@article{warchol2023visinity, - title = {Visinity: Visual Spatial Neighborhood Analysis for Multiplexed Tissue Imaging Data}, - author = {Warchol, Simon and Krueger, Robert and Nirmal, Ajit Johnson and Gaglia, Giorgio and Jessup, Jared and Ritch, Cecily C. and Hoffer, John and Muhlich, Jeremy and Burger, Megan L. and Jacks, Tyler and Santagata, Sandro and Sorger, Peter K. and Pfister, Hanspeter}, - journal = {IEEE Transactions on Visualization and Computer Graphics}, - year = {2023}, - volume = {29}, - number = {1}, - pages = {106-116}, - doi = {10.1109/TVCG.2022.3209378}, - publisher = {IEEE Computer Society}, - address = {Los Alamitos, CA, USA}, -} - -@article{micallef2017towards, - author = {Micallef, Luana and Palmas, Gregorio and Oulasvirta, Antti and Weinkauf, Tino}, - journal = {IEEE Transactions on Visualization and Computer Graphics}, - title = {Towards Perceptual Optimization of the Visual Design of Scatterplots}, - year = {2017}, - volume = {23}, - number = {6}, - pages = {1588-1599}, - doi = {10.1109/TVCG.2017.2674978} -} - -@mastersthesis{hindersson2021scatterplot, - title = {Scatterplot Patterns: Using animation to enhance scatterplots}, - author = {Hindersson, Tobias}, - year = {2021}, - school = {KTH, School of Electrical Engineering and Computer Science}, - url = {http://urn.kb.se/resolve?urn=urn:nbn:se:kth:diva-305905}, -} - -@misc{peax, - author = {Lekschas, Fritz}, - title = {Peax: A Visual Pattern Explorer For Epigenomic Data Using Unsupervised Deep Representation Learning}, - year = {2020}, - url = {https://github.com/Novartis/peax}, -} - -@misc{histocat, - author = {Rau, Anton}, - title = {histoCAT Web: Histology Topography Cytometry Analysis Toolbox}, - year = {2021}, - url = {https://github.com/BodenmillerGroup/histocat-web}, -} - -@misc{eodash, - author = {Euro Data Cube}, - title = {EODash: Software behind the RACE dashboard by ESA and the {E}uropean {C}ommission as well as the {E}arth {O}bserving {D}ashboard by NASA, ESA, and JAXA}, - year = {2022}, - url = {https://github.com/eurodatacube/eodash}, -} - -@misc{gotreescape, - author = {Li, Guozheng}, - title = {GoTreeScape Prototype System}, - year = {2022}, - url = {https://github.com/bitvis2021/GoTreeScape}, -} - -@misc{jscatter, - author = {Lekschas, Fritz}, - title = {Jupyter-{S}catter: An interactive scatter plot widget for {J}upyter {N}otebook, {L}ab, and {G}oogle {C}olab}, - year = {2022}, - url = {https://github.com/flekschas/jupyter-scatter}, -} - -@inproceedings{cabrera23zeno, - author = {Cabrera, Ángel Alexander and Fu, Erica and Bertucci, Donald and Holstein, Kenneth and Talwalkar, Ameet and Hong, Jason I. and Perer, Adam}, - title = {Zeno: An Interactive Framework for Behavioral Evaluation of Machine Learning}, - year = {2023}, - publisher = {Association for Computing Machinery}, - address = {New York, NY, USA}, - url = {https://doi.org/10.1145/3544548.3581268}, - doi = {10.1145/3544548.3581268}, - booktitle = {CHI Conference on Human Factors in Computing Systems}, - location = {Hamburg, Germany}, - series = {CHI '23} -} - -@misc{regl, - author = {Lysenko, Mikola}, - title = {Regl: Functional WebGL}, - year = {2016}, - url = {https://github.com/regl-project/regl}, -}f - -@misc{kdbush, - author = {Agafonkin, Volodymyr}, - title = {Regl: Functional WebGL}, - year = {2016}, - url = {https://github.com/mourner/kdbush}, -} - -@misc{reusser2022selecting, - author = {Reusser, Ricky}, - title = {Selecting the Right Opacity for 2D Point Clouds}, - year = {2022}, - url = {https://observablehq.com/@rreusser/selecting-the-right-opacity-for-2d-point-clouds}, -} - -@misc{plotlyjs, - author = {{Plotly, Inc}}, - title = {Plotly.js: Open-source JavaScript charting library behind {P}lotly and {D}ash}, - year = {2023}, - url = {https://github.com/plotly/plotly.js}, -} - -@misc{reglscatter2d, - author = {Ivanov, Dmitry}, - title = {Regl-Scatter2d: Fast and precise scatter plot}, - year = {2023}, - url = {https://github.com/gl-vis/regl-scatter2d}, -} - -@misc{deepscatter, - author = {Schmidt, Benjamin}, - title = {Deepscatter: Zoomable, animated scatterplots in the browser that scales over a billion points}, - year = {2023}, - url = {https://github.com/nomic-ai/deepscatter}, -} - -@misc{candygraph, - author = {Terrell, Rye}, - title = {CandyGraph: A flexible and fast-by-default 2D plotting library tuned for rendering huge datasets on the GPU at interactive speeds}, - year = {2023}, - url = {https://github.com/wwwtyro/candygraph}, -} - -@misc{geonames, - author = {{GeoNames}}, - title = {{GeoNames}}, - year = {2023}, - url = {https://www.geonames.org}, -} - -@article{bostock2011d3, - title = {D$^3$ data-driven documents}, - author = {Bostock, Michael and Ogievetsky, Vadim and Heer, Jeffrey}, - journal = {IEEE transactions on visualization and computer graphics}, - volume = {17}, - number = {12}, - pages = {2301--2309}, - year = {2011}, - publisher = {IEEE}, - doi = {10.1109/TVCG.2011.185}, -} - -@article{satyanarayan2016vegalite, - title = {Vega-lite: A grammar of interactive graphics}, - author = {Satyanarayan, Arvind and Moritz, Dominik and Wongsuphasawat, Kanit and Heer, Jeffrey}, - journal = {IEEE transactions on visualization and computer graphics}, - volume = {23}, - number = {1}, - pages = {341--350}, - year = {2016}, - publisher = {IEEE}, - doi = {10.1109/TVCG.2016.2599030}, -} - -@misc{xiao2017fashion, - author = {Xiao, Han and Rasul, Kashif and Vollgraf, Roland}, - title = {Fashion-MNIST: a Novel Image Dataset for Benchmarking Machine Learning Algorithms}, - publisher = {arXiv}, - year = {2017}, - doi = {10.48550/ARXIV.1708.07747}, - url = {https://arxiv.org/abs/1708.07747}, -} - -@misc{leland2018umap, - author = {McInnes, Leland and Healy, John and Melville, James}, - title = {UMAP: Uniform Manifold Approximation and Projection for Dimension Reduction}, - publisher = {arXiv}, - year = {2018}, - doi = {10.48550/ARXIV.1802.03426}, - url = {https://arxiv.org/abs/1802.03426}, -} - -@article{vandermaaten2008visualizing, - author = {van der Maaten, Laurens and Hinton, Geoffrey}, - title = {Visualizing Data using t-SNE}, - journal = {Journal of Machine Learning Research}, - year = {2008}, - volume = {9}, - number = {86}, - pages = {2579--2605}, - url = {http://jmlr.org/papers/v9/vandermaaten08a.html} -} - -@misc{kingma2013auto, - author = {Kingma, Diederik P and Welling, Max}, - title = {Auto-Encoding Variational {B}ayes}, - publisher = {arXiv}, - year = {2013}, - doi = {10.48550/ARXIV.1312.6114}, - url = {https://arxiv.org/abs/1312.6114}, -} - -@article{pearson1901, - author = {Pearson, Karl}, - title = {On Lines and Planes of Closest Fit to Systems of Points is Space}, - journal = {The London, Edinburgh, and Dublin Philosophical Magazine and Journal of Science}, - volume = {2}, - number = {11}, - pages = {559-572}, - year = {1901}, - publisher = {Taylor & Francis}, - doi = {10.1080/14786440109462720}, -} - -@misc{beshai2017beautiful, - author = {Beshai, Peter}, - title = {Beautifully Animate Points with WebGL and regl}, - year = {2017}, - url = {https://peterbeshai.com/blog/2017-05-26-beautifully-animate-points-with-webgl-and-regl/}, -} - diff --git a/paper/teaser.jpg b/paper/teaser.jpg deleted file mode 100644 index c3beb866..00000000 Binary files a/paper/teaser.jpg and /dev/null differ diff --git a/performance-mode.html b/performance-mode.html new file mode 100644 index 00000000..9d660272 --- /dev/null +++ b/performance-mode.html @@ -0,0 +1,444 @@ + + + + + + + Regl Scatterplot + + + + + + + + + + + + + +

Regl Scatterplot

+ +
+
+ +
+
+
+
+
+
+
+
+ + diff --git a/programmatic-lasso.html b/programmatic-lasso.html new file mode 100644 index 00000000..b30b464e --- /dev/null +++ b/programmatic-lasso.html @@ -0,0 +1,445 @@ + + + + + + + Regl Scatterplot + + + + + + + + + + + + + + +

Regl Scatterplot

+ +
+
+ +
+
+
+
+
+
+
+
+ + diff --git a/rollup.config.mjs b/rollup.config.mjs deleted file mode 100644 index 20f6e713..00000000 --- a/rollup.config.mjs +++ /dev/null @@ -1,50 +0,0 @@ -import babel from '@rollup/plugin-babel'; -import json from '@rollup/plugin-json'; -import resolve from '@rollup/plugin-node-resolve'; -import terser from '@rollup/plugin-terser'; -import filesize from 'rollup-plugin-filesize'; - -const basePlugins = () => [ - json(), - resolve({ - dedupe: ['gl-matrix'], - mainFields: ['module', 'main'], - }), -]; - -const configurator = (file, format, plugins = []) => ({ - input: 'src/index.js', - output: { - name: 'createScatterplot', - exports: 'named', - format, - file, - globals: { - 'pub-sub-es': 'createPubSub', - regl: 'createREGL', - }, - interop: 'compat', - }, - plugins: [...basePlugins(), ...plugins], - external: ['pub-sub-es', 'regl'], - onwarn: (warning, warn) => { - if (warning.code === 'CIRCULAR_DEPENDENCY') return; - warn(warning); - }, -}); - -const devConfig = configurator('dist/regl-scatterplot.js', 'umd', [ - babel({ babelHelpers: 'bundled' }), - filesize(), -]); - -const prodConfig = configurator('dist/regl-scatterplot.min.js', 'umd', [ - babel({ babelHelpers: 'bundled' }), - terser(), -]); - -const esmConfig = configurator('dist/regl-scatterplot.esm.js', 'esm', [ - filesize(), -]); - -export default [devConfig, prodConfig, esmConfig]; diff --git a/rollup.test.config.mjs b/rollup.test.config.mjs deleted file mode 100644 index 60c86f85..00000000 --- a/rollup.test.config.mjs +++ /dev/null @@ -1,18 +0,0 @@ -import babel from '@rollup/plugin-babel'; -import commonjs from '@rollup/plugin-commonjs'; -import json from '@rollup/plugin-json'; -import resolve from '@rollup/plugin-node-resolve'; - -export default { - input: './tests/index.js', - output: { - name: 'test', - format: 'iife', - sourcemap: 'inline', - }, - plugins: [resolve(), commonjs(), babel({ babelHelpers: 'bundled' }), json()], - onwarn: (warning, warn) => { - if (warning.code === 'CIRCULAR_DEPENDENCY') return; - warn(warning); - }, -}; diff --git a/scripts/pre-commit b/scripts/pre-commit deleted file mode 100644 index 9cbeabf9..00000000 --- a/scripts/pre-commit +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -echo "** Running unit tests **" - -stash_commit="$(git stash create)" -git reset —-hard - -npm test - -status=$? - -if [[ -n "${stash_commit}" ]] -then git stash apply "${stash_commit}" -fi - -exit $status diff --git a/size-encoding.html b/size-encoding.html new file mode 100644 index 00000000..fc9a9f83 --- /dev/null +++ b/size-encoding.html @@ -0,0 +1,445 @@ + + + + + + + Regl Scatterplot + + + + + + + + + + + + + + +

Regl Scatterplot

+ +
+
+ +
+
+
+
+
+
+
+
+ + diff --git a/src/bg.fs b/src/bg.fs deleted file mode 100644 index baad0f75..00000000 --- a/src/bg.fs +++ /dev/null @@ -1,13 +0,0 @@ -const FRAGMENT_SHADER = ` -precision mediump float; - -uniform sampler2D texture; - -varying vec2 uv; - -void main () { - gl_FragColor = texture2D(texture, uv); -} -`; - -export default FRAGMENT_SHADER; diff --git a/src/bg.vs b/src/bg.vs deleted file mode 100644 index c214ab8d..00000000 --- a/src/bg.vs +++ /dev/null @@ -1,16 +0,0 @@ -const VERTEX_SHADER = ` -precision mediump float; - -uniform mat4 modelViewProjection; - -attribute vec2 position; - -varying vec2 uv; - -void main () { - uv = position; - gl_Position = modelViewProjection * vec4(-1.0 + 2.0 * uv.x, 1.0 - 2.0 * uv.y, 0, 1); -} -`; - -export default VERTEX_SHADER; diff --git a/src/constants.js b/src/constants.js deleted file mode 100644 index 32122e9e..00000000 --- a/src/constants.js +++ /dev/null @@ -1,187 +0,0 @@ -import { - cubicIn, - cubicInOut, - cubicOut, - linear, - quadIn, - quadInOut, - quadOut, -} from '@flekschas/utils'; - -export const AUTO = 'auto'; - -export const COLOR_NORMAL_IDX = 0; -export const COLOR_ACTIVE_IDX = 1; -export const COLOR_HOVER_IDX = 2; -export const COLOR_BG_IDX = 3; -export const COLOR_NUM_STATES = 4; -export const FLOAT_BYTES = Float32Array.BYTES_PER_ELEMENT; -export const GL_EXTENSIONS = [ - 'OES_texture_float', - 'OES_element_index_uint', - 'WEBGL_color_buffer_float', - 'EXT_float_blend', -]; -export const CLEAR_OPTIONS = { - color: [0, 0, 0, 0], // Transparent background color - depth: 1, -}; - -export const MOUSE_MODE_PANZOOM = 'panZoom'; -export const MOUSE_MODE_LASSO = 'lasso'; -export const MOUSE_MODE_ROTATE = 'rotate'; -export const MOUSE_MODES = [ - MOUSE_MODE_PANZOOM, - MOUSE_MODE_LASSO, - MOUSE_MODE_ROTATE, -]; -export const DEFAULT_MOUSE_MODE = MOUSE_MODE_PANZOOM; - -// Easing -export const EASING_FNS = { - cubicIn, - cubicInOut, - cubicOut, - linear, - quadIn, - quadInOut, - quadOut, -}; -export const DEFAULT_EASING = cubicInOut; - -export const CONTINUOUS = 'continuous'; -export const CATEGORICAL = 'categorical'; -export const VALUE_ZW_DATA_TYPES = [CONTINUOUS, CATEGORICAL]; - -// Default lasso -export const LASSO_CLEAR_ON_DESELECT = 'deselect'; -export const LASSO_CLEAR_ON_END = 'lassoEnd'; -export const LASSO_CLEAR_EVENTS = [LASSO_CLEAR_ON_DESELECT, LASSO_CLEAR_ON_END]; -export const LASSO_BRUSH_MIN_MIN_DIST = 3; -export const DEFAULT_LASSO_COLOR = [0, 0.666666667, 1, 1]; -export const DEFAULT_LASSO_LINE_WIDTH = 2; -export const DEFAULT_LASSO_INITIATOR = false; -export const DEFAULT_LASSO_INITIATOR_BACKGROUND = 'rgba(255, 255, 255, 0.1)'; -export const DEFAULT_LASSO_MIN_DELAY = 10; -export const DEFAULT_LASSO_MIN_DIST = 3; -export const DEFAULT_LASSO_CLEAR_EVENT = LASSO_CLEAR_ON_END; -export const DEFAULT_LASSO_ON_LONG_PRESS = false; -export const DEFAULT_LASSO_LONG_PRESS_TIME = 750; -export const DEFAULT_LASSO_LONG_PRESS_AFTER_EFFECT_TIME = 500; -export const DEFAULT_LASSO_LONG_PRESS_EFFECT_DELAY = 100; -export const DEFAULT_LASSO_LONG_PRESS_REVERT_EFFECT_TIME = 250; -export const DEFAULT_LASSO_BRUSH_SIZE = 24; - -// Key mapping -export const KEY_ACTION_LASSO = 'lasso'; -export const KEY_ACTION_ROTATE = 'rotate'; -export const KEY_ACTION_MERGE = 'merge'; -export const KEY_ACTION_REMOVE = 'remove'; -export const KEY_ACTIONS = [ - KEY_ACTION_LASSO, - KEY_ACTION_ROTATE, - KEY_ACTION_MERGE, - KEY_ACTION_REMOVE, -]; -export const KEY_ALT = 'alt'; -export const KEY_CMD = 'cmd'; -export const KEY_CTRL = 'ctrl'; -export const KEY_META = 'meta'; -export const KEY_SHIFT = 'shift'; -export const KEYS = [KEY_ALT, KEY_CMD, KEY_CTRL, KEY_META, KEY_SHIFT]; -export const DEFAULT_ACTION_KEY_MAP = { - [KEY_ACTION_REMOVE]: KEY_ALT, - [KEY_ACTION_ROTATE]: KEY_ALT, - [KEY_ACTION_LASSO]: KEY_SHIFT, - [KEY_ACTION_MERGE]: KEY_CMD, -}; - -// Default attribute -export const DEFAULT_DATA_ASPECT_RATIO = 1; -export const DEFAULT_WIDTH = AUTO; -export const DEFAULT_HEIGHT = AUTO; -export const DEFAULT_GAMMA = 1; - -// Default styles -export const MIN_POINT_SIZE = 1; -export const DEFAULT_POINT_SCALE_MODE = 'asinh'; -export const DEFAULT_POINT_SIZE = 6; -export const DEFAULT_POINT_SIZE_SELECTED = 2; -export const DEFAULT_POINT_OUTLINE_WIDTH = 2; -export const DEFAULT_SIZE_BY = null; -export const DEFAULT_POINT_ORDER = null; -export const DEFAULT_POINT_CONNECTION_SIZE = 2; -export const DEFAULT_POINT_CONNECTION_SIZE_ACTIVE = 2; -export const DEFAULT_POINT_CONNECTION_SIZE_BY = null; -export const DEFAULT_POINT_CONNECTION_OPACITY = null; -export const DEFAULT_POINT_CONNECTION_OPACITY_BY = null; -export const DEFAULT_POINT_CONNECTION_OPACITY_ACTIVE = 0.66; -export const DEFAULT_OPACITY = 1; -export const DEFAULT_OPACITY_BY = null; -export const DEFAULT_OPACITY_BY_DENSITY_FILL = 0.15; -export const DEFAULT_OPACITY_BY_DENSITY_DEBOUNCE_TIME = 25; -export const DEFAULT_OPACITY_INACTIVE_MAX = 1; -export const DEFAULT_OPACITY_INACTIVE_SCALE = 1; - -// Default colors -export const DEFAULT_COLORMAP = []; -export const DEFAULT_COLOR_BY = null; -export const DEFAULT_COLOR_NORMAL = [0.66, 0.66, 0.66, DEFAULT_OPACITY]; -export const DEFAULT_COLOR_ACTIVE = [0, 0.55, 1, 1]; -export const DEFAULT_COLOR_HOVER = [1, 1, 1, 1]; -export const DEFAULT_COLOR_BG = [0, 0, 0, 1]; -export const DEFAULT_POINT_CONNECTION_COLOR_BY = null; -export const DEFAULT_POINT_CONNECTION_COLOR_NORMAL = [0.66, 0.66, 0.66, 0.2]; -export const DEFAULT_POINT_CONNECTION_COLOR_ACTIVE = [0, 0.55, 1, 1]; -export const DEFAULT_POINT_CONNECTION_COLOR_HOVER = [1, 1, 1, 1]; - -// Annotations -export const DEFAULT_ANNOTATION_LINE_COLOR = [1, 1, 1, 0.5]; -export const DEFAULT_ANNOTATION_LINE_WIDTH = 1; -export const DEFAULT_ANNOTATION_HVLINE_LIMIT = 1000; - -// Default view -export const DEFAULT_TARGET = [0, 0]; -export const DEFAULT_DISTANCE = 1; -export const DEFAULT_ROTATION = 0; -// biome-ignore format: the array should not be formatted -export const DEFAULT_VIEW = new Float32Array([ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1, -]); - -// Error codes -export const IMAGE_LOAD_ERROR = 'IMAGE_LOAD_ERROR'; - -// Default misc -export const DEFAULT_BACKGROUND_IMAGE = null; -export const DEFAULT_SHOW_RETICLE = false; -export const DEFAULT_RETICLE_COLOR = [1, 1, 1, 0.5]; -export const DEFAULT_DESELECT_ON_DBL_CLICK = true; -export const DEFAULT_DESELECT_ON_ESCAPE = true; -export const DEFAULT_SHOW_POINT_CONNECTIONS = false; -export const DEFAULT_POINT_CONNECTION_MAX_INT_POINTS_PER_SEGMENT = 100; -export const DEFAULT_POINT_CONNECTION_INT_POINTS_TOLERANCE = 1 / 500; -export const DEFAULT_POINT_SIZE_MOUSE_DETECTION = 'auto'; -export const DEFAULT_PERFORMANCE_MODE = false; -export const SINGLE_CLICK_DELAY = 200; -export const LONG_CLICK_TIME = 500; -export const Z_NAMES = new Set(['z', 'valueZ', 'valueA', 'value1', 'category']); -export const W_NAMES = new Set(['w', 'valueW', 'valueB', 'value2', 'value']); -export const DEFAULT_IMAGE_LOAD_TIMEOUT = 15000; -export const DEFAULT_SPATIAL_INDEX_USE_WORKER = undefined; -export const DEFAULT_CAMERA_IS_FIXED = false; -export const DEFAULT_ANTI_ALIASING = 0.5; -export const DEFAULT_PIXEL_ALIGNED = false; -export const DEFAULT_LASSO_TYPE = 'lasso'; -export const SKIP_DEPRECATION_VALUE_TRANSLATION = Symbol( - 'SKIP_DEPRECATION_VALUE_TRANSLATION', -); - -// Error messages -export const ERROR_POINTS_NOT_DRAWN = 'Points have not been drawn'; -export const ERROR_INSTANCE_IS_DESTROYED = 'The instance was already destroyed'; -export const ERROR_IS_DRAWING = - 'Ignoring draw call as the previous draw call has not yet finished. To avoid this warning `await` the draw call.'; diff --git a/src/index.js b/src/index.js deleted file mode 100644 index d0c07e0b..00000000 --- a/src/index.js +++ /dev/null @@ -1,4787 +0,0 @@ -import { - hasSameElements, - identity, - max as maxArray, - rangeMap, - throttleAndDebounce, - unionIntegers, -} from '@flekschas/utils'; -import createDom2dCamera from 'dom-2d-camera'; -import earcut from 'earcut'; -import { mat4, vec4 } from 'gl-matrix'; -import createPubSub from 'pub-sub-es'; -import createLine from 'regl-line'; -import { version } from '../package.json'; -import BG_FS from './bg.fs'; -import BG_VS from './bg.vs'; -import { - AUTO, - CATEGORICAL, - COLOR_ACTIVE_IDX, - COLOR_BG_IDX, - COLOR_HOVER_IDX, - COLOR_NORMAL_IDX, - COLOR_NUM_STATES, - CONTINUOUS, - DEFAULT_ACTION_KEY_MAP, - DEFAULT_ANNOTATION_HVLINE_LIMIT, - DEFAULT_ANNOTATION_LINE_COLOR, - DEFAULT_ANNOTATION_LINE_WIDTH, - DEFAULT_ANTI_ALIASING, - DEFAULT_BACKGROUND_IMAGE, - DEFAULT_CAMERA_IS_FIXED, - DEFAULT_COLOR_ACTIVE, - DEFAULT_COLOR_BG, - DEFAULT_COLOR_BY, - DEFAULT_COLOR_HOVER, - DEFAULT_COLOR_NORMAL, - DEFAULT_DATA_ASPECT_RATIO, - DEFAULT_DESELECT_ON_DBL_CLICK, - DEFAULT_DESELECT_ON_ESCAPE, - DEFAULT_DISTANCE, - DEFAULT_EASING, - DEFAULT_HEIGHT, - DEFAULT_IMAGE_LOAD_TIMEOUT, - DEFAULT_LASSO_BRUSH_SIZE, - DEFAULT_LASSO_CLEAR_EVENT, - DEFAULT_LASSO_COLOR, - DEFAULT_LASSO_INITIATOR, - DEFAULT_LASSO_LINE_WIDTH, - DEFAULT_LASSO_LONG_PRESS_AFTER_EFFECT_TIME, - DEFAULT_LASSO_LONG_PRESS_EFFECT_DELAY, - DEFAULT_LASSO_LONG_PRESS_REVERT_EFFECT_TIME, - DEFAULT_LASSO_LONG_PRESS_TIME, - DEFAULT_LASSO_MIN_DELAY, - DEFAULT_LASSO_MIN_DIST, - DEFAULT_LASSO_ON_LONG_PRESS, - DEFAULT_LASSO_TYPE, - DEFAULT_MOUSE_MODE, - DEFAULT_OPACITY_BY, - DEFAULT_OPACITY_BY_DENSITY_DEBOUNCE_TIME, - DEFAULT_OPACITY_BY_DENSITY_FILL, - DEFAULT_OPACITY_INACTIVE_MAX, - DEFAULT_OPACITY_INACTIVE_SCALE, - DEFAULT_PERFORMANCE_MODE, - DEFAULT_PIXEL_ALIGNED, - DEFAULT_POINT_CONNECTION_COLOR_ACTIVE, - DEFAULT_POINT_CONNECTION_COLOR_BY, - DEFAULT_POINT_CONNECTION_COLOR_HOVER, - DEFAULT_POINT_CONNECTION_COLOR_NORMAL, - DEFAULT_POINT_CONNECTION_INT_POINTS_TOLERANCE, - DEFAULT_POINT_CONNECTION_MAX_INT_POINTS_PER_SEGMENT, - DEFAULT_POINT_CONNECTION_OPACITY, - DEFAULT_POINT_CONNECTION_OPACITY_ACTIVE, - DEFAULT_POINT_CONNECTION_OPACITY_BY, - DEFAULT_POINT_CONNECTION_SIZE, - DEFAULT_POINT_CONNECTION_SIZE_ACTIVE, - DEFAULT_POINT_CONNECTION_SIZE_BY, - DEFAULT_POINT_ORDER, - DEFAULT_POINT_OUTLINE_WIDTH, - DEFAULT_POINT_SCALE_MODE, - DEFAULT_POINT_SIZE, - DEFAULT_POINT_SIZE_MOUSE_DETECTION, - DEFAULT_POINT_SIZE_SELECTED, - DEFAULT_RETICLE_COLOR, - DEFAULT_ROTATION, - DEFAULT_SHOW_POINT_CONNECTIONS, - DEFAULT_SHOW_RETICLE, - DEFAULT_SIZE_BY, - DEFAULT_SPATIAL_INDEX_USE_WORKER, - DEFAULT_TARGET, - DEFAULT_VIEW, - DEFAULT_WIDTH, - EASING_FNS, - ERROR_INSTANCE_IS_DESTROYED, - ERROR_IS_DRAWING, - ERROR_POINTS_NOT_DRAWN, - FLOAT_BYTES, - KEY_ACTION_LASSO, - KEY_ACTION_MERGE, - KEY_ACTION_REMOVE, - KEY_ACTION_ROTATE, - KEY_ACTIONS, - KEY_ALT, - KEY_CMD, - KEY_CTRL, - KEY_META, - KEY_SHIFT, - KEYS, - LASSO_BRUSH_MIN_MIN_DIST, - LASSO_CLEAR_EVENTS, - LASSO_CLEAR_ON_DESELECT, - LASSO_CLEAR_ON_END, - LONG_CLICK_TIME, - MIN_POINT_SIZE, - MOUSE_MODE_LASSO, - MOUSE_MODE_PANZOOM, - MOUSE_MODE_ROTATE, - MOUSE_MODES, - SINGLE_CLICK_DELAY, - SKIP_DEPRECATION_VALUE_TRANSLATION, - VALUE_ZW_DATA_TYPES, - W_NAMES, - Z_NAMES, -} from './constants.js'; -import createKdbush from './kdbush.js'; -import createLassoManager from './lasso-manager/index.js'; -import POINT_FS from './point.fs'; -import createVertexShader from './point.vs'; -import POINT_SIMPLE_FS from './point-simple.fs'; -import POINT_UPDATE_FS from './point-update.fs'; -import POINT_UPDATE_VS from './point-update.vs'; -import createRenderer from './renderer.js'; -import createSplineCurve from './spline-curve.js'; -import { - checkReglExtensions as checkSupport, - clip, - createRegl, - createTextureFromUrl, - dist, - flipObj, - getBBox, - insertionSort, - isConditionalArray, - isDomRect, - isHorizontalLine, - isMultipleColors, - isPointInPolygon, - isPolygonAnnotation, - isPositiveNumber, - isRect, - isSameRgbas, - isStrictlyPositiveNumber, - isString, - isValidBBox, - isVerticalLine, - isVertices, - limit, - max, - min, - rgbBrightness, - toArrayOrientedPoints, - toRgba, - verticesToPolygon, -} from './utils.js'; - -const deprecations = { - showRecticle: { - replacement: 'showReticle', - removalVersion: '2', - translation: identity, - }, - recticleColor: { - replacement: 'reticleColor', - removalVersion: '2', - translation: identity, - }, - keyMap: { - replacement: 'actionKeyMap', - removalVersion: '2', - translation: flipObj, - }, -}; - -const checkDeprecations = (properties) => { - const deprecatedProps = Object.keys(properties).filter( - (prop) => deprecations[prop], - ); - - for (const prop of deprecatedProps) { - const { replacement, removalVersion, translation } = deprecations[prop]; - // biome-ignore lint/suspicious/noConsole: This is a legitimately useful warning - console.warn( - `regl-scatterplot: the "${prop}" property is deprecated and will be removed in v${removalVersion}. Please use "${replacement}" instead.`, - ); - properties[deprecations[prop].replacement] = - properties[prop] !== SKIP_DEPRECATION_VALUE_TRANSLATION - ? translation(properties[prop]) - : properties[prop]; - delete properties[prop]; - } - - return properties; -}; - -const getEncodingType = ( - type, - defaultValue, - { allowSegment = false, allowDensity = false, allowInherit = false } = {}, -) => { - // Z refers to the 3rd component of the RGBA value - if (Z_NAMES.has(type)) { - return 'valueZ'; - } - - // W refers to the 4th component of the RGBA value - if (W_NAMES.has(type)) { - return 'valueW'; - } - - if (type === 'segment') { - return allowSegment ? 'segment' : defaultValue; - } - - if (type === 'density') { - return allowDensity ? 'density' : defaultValue; - } - - if (type === 'inherit') { - return allowInherit ? 'inherit' : defaultValue; - } - - return defaultValue; -}; - -const getEncodingIdx = (type) => { - switch (type) { - case 'valueZ': - return 2; - - case 'valueW': - return 3; - - default: - return null; - } -}; - -const createScatterplot = ( - /** @type {Partial} */ initialProperties = {}, -) => { - /** @type {import('pub-sub-es').PubSub} */ - const pubSub = createPubSub({ - async: !initialProperties.syncEvents, - caseInsensitive: true, - }); - const scratch = new Float32Array(16); - const pvm = new Float32Array(16); - const mousePosition = [0, 0]; - - checkDeprecations(initialProperties); - - let { - renderer, - antiAliasing = DEFAULT_ANTI_ALIASING, - pixelAligned = DEFAULT_PIXEL_ALIGNED, - backgroundColor = DEFAULT_COLOR_BG, - backgroundImage = DEFAULT_BACKGROUND_IMAGE, - canvas = document.createElement('canvas'), - colorBy = DEFAULT_COLOR_BY, - deselectOnDblClick = DEFAULT_DESELECT_ON_DBL_CLICK, - deselectOnEscape = DEFAULT_DESELECT_ON_ESCAPE, - lassoColor = DEFAULT_LASSO_COLOR, - lassoLineWidth = DEFAULT_LASSO_LINE_WIDTH, - lassoMinDelay = DEFAULT_LASSO_MIN_DELAY, - lassoMinDist = DEFAULT_LASSO_MIN_DIST, - lassoClearEvent = DEFAULT_LASSO_CLEAR_EVENT, - lassoInitiator = DEFAULT_LASSO_INITIATOR, - lassoInitiatorParentElement = document.body, - lassoLongPressIndicatorParentElement = document.body, - lassoOnLongPress = DEFAULT_LASSO_ON_LONG_PRESS, - lassoLongPressTime = DEFAULT_LASSO_LONG_PRESS_TIME, - lassoLongPressAfterEffectTime = DEFAULT_LASSO_LONG_PRESS_AFTER_EFFECT_TIME, - lassoLongPressEffectDelay = DEFAULT_LASSO_LONG_PRESS_EFFECT_DELAY, - lassoLongPressRevertEffectTime = DEFAULT_LASSO_LONG_PRESS_REVERT_EFFECT_TIME, - lassoType = DEFAULT_LASSO_TYPE, - lassoBrushSize = DEFAULT_LASSO_BRUSH_SIZE, - actionKeyMap = DEFAULT_ACTION_KEY_MAP, - mouseMode = DEFAULT_MOUSE_MODE, - showReticle = DEFAULT_SHOW_RETICLE, - reticleColor = DEFAULT_RETICLE_COLOR, - pointColor = DEFAULT_COLOR_NORMAL, - pointColorActive = DEFAULT_COLOR_ACTIVE, - pointColorHover = DEFAULT_COLOR_HOVER, - showPointConnections = DEFAULT_SHOW_POINT_CONNECTIONS, - pointConnectionColor = DEFAULT_POINT_CONNECTION_COLOR_NORMAL, - pointConnectionColorActive = DEFAULT_POINT_CONNECTION_COLOR_ACTIVE, - pointConnectionColorHover = DEFAULT_POINT_CONNECTION_COLOR_HOVER, - pointConnectionColorBy = DEFAULT_POINT_CONNECTION_COLOR_BY, - pointConnectionOpacity = DEFAULT_POINT_CONNECTION_OPACITY, - pointConnectionOpacityBy = DEFAULT_POINT_CONNECTION_OPACITY_BY, - pointConnectionOpacityActive = DEFAULT_POINT_CONNECTION_OPACITY_ACTIVE, - pointConnectionSize = DEFAULT_POINT_CONNECTION_SIZE, - pointConnectionSizeActive = DEFAULT_POINT_CONNECTION_SIZE_ACTIVE, - pointConnectionSizeBy = DEFAULT_POINT_CONNECTION_SIZE_BY, - pointConnectionMaxIntPointsPerSegment = DEFAULT_POINT_CONNECTION_MAX_INT_POINTS_PER_SEGMENT, - pointConnectionTolerance = DEFAULT_POINT_CONNECTION_INT_POINTS_TOLERANCE, - pointSize = DEFAULT_POINT_SIZE, - pointSizeSelected = DEFAULT_POINT_SIZE_SELECTED, - pointSizeMouseDetection = DEFAULT_POINT_SIZE_MOUSE_DETECTION, - pointOutlineWidth = DEFAULT_POINT_OUTLINE_WIDTH, - opacity = AUTO, - opacityBy = DEFAULT_OPACITY_BY, - opacityByDensityFill = DEFAULT_OPACITY_BY_DENSITY_FILL, - opacityInactiveMax = DEFAULT_OPACITY_INACTIVE_MAX, - opacityInactiveScale = DEFAULT_OPACITY_INACTIVE_SCALE, - sizeBy = DEFAULT_SIZE_BY, - pointOrder = DEFAULT_POINT_ORDER, - pointScaleMode = DEFAULT_POINT_SCALE_MODE, - height = DEFAULT_HEIGHT, - width = DEFAULT_WIDTH, - annotationLineColor = DEFAULT_ANNOTATION_LINE_COLOR, - annotationLineWidth = DEFAULT_ANNOTATION_LINE_WIDTH, - annotationHVLineLimit = DEFAULT_ANNOTATION_HVLINE_LIMIT, - cameraIsFixed = DEFAULT_CAMERA_IS_FIXED, - } = initialProperties; - - let currentWidth = width === AUTO ? 1 : width; - let currentHeight = height === AUTO ? 1 : height; - - // The following properties cannot be changed after the initialization - const { - performanceMode = DEFAULT_PERFORMANCE_MODE, - opacityByDensityDebounceTime = DEFAULT_OPACITY_BY_DENSITY_DEBOUNCE_TIME, - spatialIndexUseWorker = DEFAULT_SPATIAL_INDEX_USE_WORKER, - } = initialProperties; - - const renderPointsAsSquares = Boolean( - initialProperties.renderPointsAsSquares || performanceMode, - ); - const disableAlphaBlending = Boolean( - initialProperties.disableAlphaBlending || performanceMode, - ); - - mouseMode = limit(MOUSE_MODES, MOUSE_MODE_PANZOOM)(mouseMode); - - if (!renderer) { - renderer = createRenderer({ - regl: initialProperties.regl, - gamma: initialProperties.gamma, - }); - } - - backgroundColor = toRgba(backgroundColor, true); - lassoColor = toRgba(lassoColor, true); - reticleColor = toRgba(reticleColor, true); - - let isDrawing = false; - let isDestroyed = false; - let backgroundColorBrightness = rgbBrightness(backgroundColor); - let camera; - /** @type {ReturnType} */ - let lasso; - /** @type {ReturnType} */ - let annotations; - let mouseDown = false; - let mouseDownTime = null; - let mouseDownPosition = [0, 0]; - let mouseDownTimeout = -1; - /** @type{number[]} */ - let selectedPoints = []; - /** @type{Set} */ - const selectedPointsSet = new Set(); - /** @type{Set} */ - const selectedPointsConnectionSet = new Set(); - let isPointsFiltered = false; - /** @type{Set} */ - const filteredPointsSet = new Set(); - let points = []; - let numPoints = 0; - let numPointsInView = 0; - let lassoActive = false; - let lassoPointsCurr = []; - let spatialIndex; - let viewAspectRatio; - let dataAspectRatio = - initialProperties.aspectRatio || DEFAULT_DATA_ASPECT_RATIO; - let projectionLocal; - let projection; - let model; - let pointConnections; - let pointConnectionMap; - let computingPointConnectionCurves; - let reticleHLine; - let reticleVLine; - let computedPointSizeMouseDetection; - let lassoInitiatorTimeout; - let topRightNdc; - let bottomLeftNdc; - let preventEventView = false; - let draw = true; - let drawReticleOnce = false; - let canvasObserver; - - pointColor = isMultipleColors(pointColor) ? [...pointColor] : [pointColor]; - pointColorActive = isMultipleColors(pointColorActive) - ? [...pointColorActive] - : [pointColorActive]; - pointColorHover = isMultipleColors(pointColorHover) - ? [...pointColorHover] - : [pointColorHover]; - - pointColor = pointColor.map((color) => toRgba(color, true)); - pointColorActive = pointColorActive.map((color) => toRgba(color, true)); - pointColorHover = pointColorHover.map((color) => toRgba(color, true)); - - opacity = - !Array.isArray(opacity) && Number.isNaN(+opacity) - ? pointColor[0][3] - : opacity; - opacity = isConditionalArray(opacity, isPositiveNumber, { - minLength: 1, - }) - ? [...opacity] - : [opacity]; - - pointSize = isConditionalArray(pointSize, isPositiveNumber, { - minLength: 1, - }) - ? [...pointSize] - : [pointSize]; - - let minPointScale = MIN_POINT_SIZE / pointSize[0]; - - if (pointConnectionColor === 'inherit') { - pointConnectionColor = [...pointColor]; - } else { - pointConnectionColor = isMultipleColors(pointConnectionColor) - ? [...pointConnectionColor] - : [pointConnectionColor]; - pointConnectionColor = pointConnectionColor.map((color) => - toRgba(color, true), - ); - } - - if (pointConnectionColorActive === 'inherit') { - pointConnectionColorActive = [...pointColorActive]; - } else { - pointConnectionColorActive = isMultipleColors(pointConnectionColorActive) - ? [...pointConnectionColorActive] - : [pointConnectionColorActive]; - pointConnectionColorActive = pointConnectionColorActive.map((color) => - toRgba(color, true), - ); - } - - if (pointConnectionColorHover === 'inherit') { - pointConnectionColorHover = [...pointColorHover]; - } else { - pointConnectionColorHover = isMultipleColors(pointConnectionColorHover) - ? [...pointConnectionColorHover] - : [pointConnectionColorHover]; - pointConnectionColorHover = pointConnectionColorHover.map((color) => - toRgba(color, true), - ); - } - - if (pointConnectionOpacity === 'inherit') { - pointConnectionOpacity = [...opacity]; - } else { - pointConnectionOpacity = isConditionalArray( - pointConnectionOpacity, - isPositiveNumber, - { - minLength: 1, - }, - ) - ? [...pointConnectionOpacity] - : [pointConnectionOpacity]; - } - - if (pointConnectionSize === 'inherit') { - pointConnectionSize = [...pointSize]; - } else { - pointConnectionSize = isConditionalArray( - pointConnectionSize, - isPositiveNumber, - { - minLength: 1, - }, - ) - ? [...pointConnectionSize] - : [pointConnectionSize]; - } - - colorBy = getEncodingType(colorBy, DEFAULT_COLOR_BY); - opacityBy = getEncodingType(opacityBy, DEFAULT_OPACITY_BY, { - allowDensity: true, - }); - sizeBy = getEncodingType(sizeBy, DEFAULT_SIZE_BY); - - pointConnectionColorBy = getEncodingType( - pointConnectionColorBy, - DEFAULT_POINT_CONNECTION_COLOR_BY, - { allowSegment: true, allowInherit: true }, - ); - pointConnectionOpacityBy = getEncodingType( - pointConnectionOpacityBy, - DEFAULT_POINT_CONNECTION_OPACITY_BY, - { allowSegment: true }, - ); - pointConnectionSizeBy = getEncodingType( - pointConnectionSizeBy, - DEFAULT_POINT_CONNECTION_SIZE_BY, - { allowSegment: true }, - ); - - let stateTex; // Stores the point texture holding x, y, category, and value - let prevStateTex; // Stores the previous point texture. Used for transitions - let tmpStateTex; // Stores a temporary point texture. Used for transitions - let tmpStateBuffer; // Temporary frame buffer - let stateTexRes = 0; // Width and height of the texture - let stateTexEps = 0; // Half a texel - let normalPointsIndexBuffer; // Buffer holding the indices pointing to the correct texel - let selectedPointsIndexBuffer; // Used for pointing to the selected texels - let hoveredPointIndexBuffer; // Used for pointing to the hovered texels - let pointOrderIndices = null; // Validated ordered point indices (Int32Array or null) - let pointOrderIndex = null; // Float32Array of tex coords in pointOrder sequence - - let cameraZoomTargetStart; // Stores the start (i.e., current) camera target for zooming - let cameraZoomTargetEnd; // Stores the end camera target for zooming - let cameraZoomDistanceStart; // Stores the start camera distance for zooming - let cameraZoomDistanceEnd; // Stores the end camera distance for zooming - - let isTransitioning = false; - let transitionStartTime = null; - let transitionDuration; - let transitionEasing; - let preTransitionShowReticle = showReticle; - - let colorTex; // Stores the point color texture - let colorTexRes = 0; // Width and height of the texture - let encodingTex; // Stores the point sizes and opacity values - let encodingTexRes = 0; // Width and height of the texture - - let isViewChanged = false; - let isPointsDrawn = false; - let isAnnotationsDrawn = false; - let isMouseOverCanvasChecked = false; - - let valueZDataType = CATEGORICAL; - let valueWDataType = CATEGORICAL; - - /** @type{number|undefined} */ - let hoveredPoint; - let isMouseInCanvas = false; - - let xScale = initialProperties.xScale || null; - let yScale = initialProperties.yScale || null; - let xDomainStart = 0; - let xDomainSize = 0; - let yDomainStart = 0; - let yDomainSize = 0; - if (xScale) { - xDomainStart = xScale.domain()[0]; - xDomainSize = xScale.domain()[1] - xScale.domain()[0]; - xScale.range([0, currentWidth]); - } - if (yScale) { - yDomainStart = yScale.domain()[0]; - yDomainSize = yScale.domain()[1] - yScale.domain()[0]; - yScale.range([currentHeight, 0]); - } - - const getNdcX = (x) => -1 + (x / currentWidth) * 2; - const getNdcY = (y) => 1 + (y / currentHeight) * -2; - - // Get relative WebGL position - const getMouseGlPos = () => [ - getNdcX(mousePosition[0]), - getNdcY(mousePosition[1]), - ]; - - const getScatterGlPos = (xGl, yGl) => { - // Homogeneous vector - const v = [xGl, yGl, 1, 1]; - - // projection^-1 * view^-1 * model^-1 is the same as - // model * view^-1 * projection - const mvp = mat4.invert( - scratch, - mat4.multiply( - scratch, - projectionLocal, - mat4.multiply(scratch, camera.view, model), - ), - ); - - // Translate vector - vec4.transformMat4(v, v, mvp); - - return v.slice(0, 2); - }; - - const getPointSizeNdc = (pointSizeIncrease = 0) => { - const pointScale = getPointScale(); - - // The height of the view in normalized device coordinates - const heightNdc = topRightNdc[1] - bottomLeftNdc[1]; - // The size of a pixel in the current view in normalized device coordinates - const pxNdc = heightNdc / canvas.height; - // The scaled point size in normalized device coordinates - return ( - (computedPointSizeMouseDetection * pointScale + pointSizeIncrease) * pxNdc - ); - }; - - const getPoints = () => { - if (isPointsFiltered) { - return points.filter((_, i) => filteredPointsSet.has(i)); - } - return points; - }; - - const getPointsInBBox = (x0, y0, x1, y1) => { - const pointsInBBox = spatialIndex.range(x0, y0, x1, y1); - if (isPointsFiltered) { - return pointsInBBox.filter((i) => filteredPointsSet.has(i)); - } - return pointsInBBox; - }; - - const raycast = () => { - const [xGl, yGl] = getMouseGlPos(); - const [xNdc, yNdc] = getScatterGlPos(xGl, yGl); - - const pointSizeNdc = getPointSizeNdc(4); - - // Get all points within a close range - const pointsInBBox = getPointsInBBox( - xNdc - pointSizeNdc, - yNdc - pointSizeNdc, - xNdc + pointSizeNdc, - yNdc + pointSizeNdc, - ); - - // Find the closest point - let minDist = pointSizeNdc; - let clostestPointIdx = -1; - for (const pointIdx of pointsInBBox) { - const [ptX, ptY] = points[pointIdx]; - const d = dist(ptX, ptY, xNdc, yNdc); - if (d < minDist) { - minDist = d; - clostestPointIdx = pointIdx; - } - } - - return clostestPointIdx; - }; - - const lassoExtend = (lassoPoints, lassoPointsFlat) => { - lassoPointsCurr = lassoPoints; - lasso.setPoints(lassoPointsFlat); - pubSub.publish('lassoExtend', { coordinates: lassoPoints }); - }; - - const findPointsInLasso = (lassoPolygon) => { - // get the bounding box of the lasso selection... - const bBox = getBBox(lassoPolygon); - - if (!isValidBBox(bBox)) { - return []; - } - - // ...to efficiently preselect potentially selected points - const pointsInBBox = getPointsInBBox(...bBox); - // next we test each point in the bounding box if it is in the polygon too - const pointsInPolygon = []; - for (const pointIdx of pointsInBBox) { - if (isPointInPolygon(lassoPolygon, points[pointIdx])) { - pointsInPolygon.push(pointIdx); - } - } - - return pointsInPolygon; - }; - - const lassoClear = () => { - lassoPointsCurr = []; - if (lasso) { - lasso.clear(); - } - }; - - const hasPointConnections = (point) => point && point.length > 4; - - const setPointConnectionColorState = (pointIdxs, stateIndex) => { - if ( - computingPointConnectionCurves || - !showPointConnections || - !hasPointConnections(points[pointIdxs[0]]) - ) { - return; - } - - const isNormal = stateIndex === 0; - const lineIdCacher = - stateIndex === 1 - ? (lineId) => selectedPointsConnectionSet.add(lineId) - : identity; - - // Get line IDs - const lineIds = Object.keys( - pointIdxs.reduce((ids, pointIdx) => { - const point = points[pointIdx]; - const isStruct = Array.isArray(point[4]); - const lineId = isStruct ? point[4][0] : point[4]; - - ids[lineId] = true; - - return ids; - }, {}), - ); - - const buffer = pointConnections.getData().opacities; - - const unselectedLineIds = lineIds.filter( - (lineId) => !selectedPointsConnectionSet.has(+lineId), - ); - - for (const lineId of unselectedLineIds) { - const index = pointConnectionMap[lineId][0]; - const numPointPerLine = pointConnectionMap[lineId][2]; - const pointOffset = pointConnectionMap[lineId][3]; - - const bufferStart = index * 4 + pointOffset * 2; - const bufferEnd = bufferStart + numPointPerLine * 2 + 4; - - if (buffer.__original__ === undefined) { - buffer.__original__ = buffer.slice(); - } - - for (let i = bufferStart; i < bufferEnd; i++) { - // buffer[i] = Math.floor(buffer[i] / 4) * 4 + stateIndex; - buffer[i] = isNormal - ? buffer.__original__[i] - : pointConnectionOpacityActive; - } - - lineIdCacher(lineId); - } - - pointConnections.getBuffer().opacities.subdata(buffer, 0); - }; - - const indexToStateTexCoord = (index) => [ - (index % stateTexRes) / stateTexRes + stateTexEps, - Math.floor(index / stateTexRes) / stateTexRes + stateTexEps, - ]; - - const isPointsFilteredOut = (pointIdx) => - isPointsFiltered && !filteredPointsSet.has(pointIdx); - - const deselect = ({ preventEvent = false } = {}) => { - if (lassoClearEvent === LASSO_CLEAR_ON_DESELECT) { - lassoClear(); - } - if (selectedPoints.length > 0) { - if (!preventEvent) { - pubSub.publish('deselect'); - } - selectedPointsConnectionSet.clear(); - setPointConnectionColorState(selectedPoints, 0); - selectedPoints = []; - selectedPointsSet.clear(); - draw = true; - } - }; - - /** - * Convert vertices from data space to GL space - * @param {Array<[number, number]>} vertices - Vertices in data space - * @returns {number[] | null} Flat array of GL coordinates or null if scales not defined - */ - const verticesFromDataToGl = (vertices) => { - // Check if xScale/yScale are defined - if (!(xScale && yScale)) { - // biome-ignore lint/suspicious/noConsole: User warning for missing configuration - console.warn( - 'xScale and yScale must be defined for programmatic lasso selection', - ); - return null; - } - - const verticesGl = []; - for (const [x, y] of vertices) { - // Step 1: Data space → normalized [0, 1] - const xNorm = (x - xDomainStart) / xDomainSize; - const yNorm = (y - yDomainStart) / yDomainSize; - - // Step 2: Normalized [0, 1] → NDC [-1, 1] - const xNdc = xNorm * 2 - 1; - const yNdc = yNorm * 2 - 1; - - // Step 3: NDC → GL space (camera transform) - const [xGl, yGl] = getScatterGlPos(xNdc, yNdc); - - verticesGl.push(xGl, yGl); - } - - return verticesGl; - }; - - /** - * Select and highlight a set of points - * @param {number | number[]} pointIdxs - * @param {import('./types').ScatterplotMethodOptions['select']} - */ - const select = ( - pointIdxs, - { merge = false, remove = false, preventEvent = false } = {}, - ) => { - const newSelectedPoints = Array.isArray(pointIdxs) - ? pointIdxs - : [pointIdxs]; - const currSelectedPoints = [...selectedPoints]; - - if (merge) { - selectedPoints = unionIntegers(selectedPoints, newSelectedPoints); - if (currSelectedPoints.length === selectedPoints.length) { - draw = true; - return; - } - } else if (remove) { - const newSelectedPointsSet = new Set(newSelectedPoints); - selectedPoints = selectedPoints.filter( - (point) => !newSelectedPointsSet.has(point), - ); - if (currSelectedPoints.length === selectedPoints.length) { - draw = true; - return; - } - } else { - // Unset previously highlight point connections - if (selectedPoints?.length > 0) { - setPointConnectionColorState(selectedPoints, 0); - } - if (currSelectedPoints.length > 0 && newSelectedPoints.length === 0) { - deselect({ preventEvent }); - return; - } - selectedPoints = newSelectedPoints; - } - - if (hasSameElements(currSelectedPoints, selectedPoints)) { - draw = true; - return; - } - - const selectedPointsBuffer = []; - - selectedPointsSet.clear(); - selectedPointsConnectionSet.clear(); - - for (let i = selectedPoints.length - 1; i >= 0; i--) { - const pointIdx = selectedPoints[i]; - - if ( - pointIdx < 0 || - pointIdx >= numPoints || - isPointsFilteredOut(pointIdx) - ) { - // Remove invalid selected points - selectedPoints.splice(i, 1); - continue; - } - - selectedPointsSet.add(pointIdx); - selectedPointsBuffer.push.apply( - selectedPointsBuffer, - indexToStateTexCoord(pointIdx), - ); - } - - selectedPointsIndexBuffer({ - usage: 'dynamic', - type: 'float', - data: selectedPointsBuffer, - }); - - setPointConnectionColorState(selectedPoints, 1); - - if (!preventEvent) { - pubSub.publish('select', { points: selectedPoints }); - } - - draw = true; - }; - - /** - * Lasso a certain area and select contained points - * @param {[number, number][]} vertices - Lasso vertices in either data space (default) or GL space - * @param {import('./types').ScatterplotMethodOptions['lasso']} - */ - const lassoSelect = ( - vertices, - { merge = false, remove = false, isGl = false } = {}, - ) => { - if (!isVertices(vertices)) { - throw new Error( - 'Lasso selection requires at least 3 vertices as [x, y] coordinate pairs', - ); - } - - const closedPolygon = verticesToPolygon(vertices); - - let polygonGl; - let polygonGlFlat; - - if (isGl) { - polygonGl = closedPolygon; - polygonGlFlat = closedPolygon.flat(); - } else { - polygonGlFlat = verticesFromDataToGl(closedPolygon); - - if (!polygonGlFlat) { - throw new Error( - 'xScale and yScale must be defined to convert lasso vertices from data space to GL space', - ); - } - - polygonGl = []; - for (let i = 0; i < polygonGlFlat.length; i += 2) { - polygonGl.push([polygonGlFlat[i], polygonGlFlat[i + 1]]); - } - } - - lassoEnd(polygonGl, polygonGlFlat, { merge, remove }); - }; - - /** - * @param {number} point - * @param {import('./types').ScatterplotMethodOptions['hover']} options - */ - const hover = ( - point, - { showReticleOnce = false, preventEvent = false } = {}, - ) => { - let needsRedraw = false; - - const isFilteredOut = isPointsFiltered && !filteredPointsSet.has(point); - - if (!isFilteredOut && point >= 0 && point < numPoints) { - needsRedraw = true; - const oldHoveredPoint = hoveredPoint; - const newHoveredPoint = point !== hoveredPoint; - if ( - +oldHoveredPoint >= 0 && - newHoveredPoint && - !selectedPointsSet.has(oldHoveredPoint) - ) { - setPointConnectionColorState([oldHoveredPoint], 0); - } - hoveredPoint = point; - hoveredPointIndexBuffer.subdata(indexToStateTexCoord(point)); - if (!selectedPointsSet.has(point)) { - setPointConnectionColorState([point], 2); - } - if (newHoveredPoint && !preventEvent) { - pubSub.publish('pointover', hoveredPoint); - } - } else { - needsRedraw = +hoveredPoint >= 0; - if (needsRedraw) { - if (!selectedPointsSet.has(hoveredPoint)) { - setPointConnectionColorState([hoveredPoint], 0); - } - if (!preventEvent) { - pubSub.publish('pointout', hoveredPoint); - } - } - hoveredPoint = undefined; - } - - if (needsRedraw) { - draw = true; - drawReticleOnce = showReticleOnce; - } - }; - - const getRelativeMousePosition = (event) => { - const rect = canvas.getBoundingClientRect(); - - mousePosition[0] = event.clientX - rect.left; - mousePosition[1] = event.clientY - rect.top; - - return [...mousePosition]; - }; - - const lassoStart = () => { - // Fix camera for the lasso selection - camera.config({ isFixed: true }); - mouseDown = true; - lassoActive = true; - lassoClear(); - if (mouseDownTimeout >= 0) { - clearTimeout(mouseDownTimeout); - mouseDownTimeout = -1; - } - pubSub.publish('lassoStart'); - }; - - const lassoEnd = ( - lassoPoints, - lassoPointsFlat, - { merge = false, remove = false } = {}, - ) => { - camera.config({ isFixed: cameraIsFixed }); - lassoPointsCurr = [...lassoPoints]; - const pointsInLasso = findPointsInLasso(lassoPointsFlat); - select(pointsInLasso, { merge, remove }); - - pubSub.publish('lassoEnd', { - coordinates: lassoPointsCurr, - }); - if (lassoClearEvent === LASSO_CLEAR_ON_END) { - lassoClear(); - } - }; - - const lassoManager = createLassoManager(canvas, { - onStart: lassoStart, - onDraw: lassoExtend, - onEnd: lassoEnd, - enableInitiator: lassoInitiator, - initiatorParentElement: lassoInitiatorParentElement, - longPressIndicatorParentElement: lassoLongPressIndicatorParentElement, - pointNorm: ([x, y]) => getScatterGlPos(getNdcX(x), getNdcY(y)), - minDelay: lassoMinDelay, - minDist: - lassoType === 'brush' - ? Math.max(LASSO_BRUSH_MIN_MIN_DIST, lassoMinDist) - : lassoMinDist, - type: lassoType, - }); - - const checkLassoMode = () => mouseMode === MOUSE_MODE_LASSO; - - const checkModKey = (event, action) => { - switch (actionKeyMap[action]) { - case KEY_ALT: - return event.altKey; - - case KEY_CMD: - return event.metaKey; - - case KEY_CTRL: - return event.ctrlKey; - - case KEY_META: - return event.metaKey; - - case KEY_SHIFT: - return event.shiftKey; - - default: - return false; - } - }; - - const checkIfMouseIsOverCanvas = (event) => - document - .elementsFromPoint(event.clientX, event.clientY) - .some((element) => element === canvas); - - const mouseDownHandler = (event) => { - if (!isPointsDrawn || event.buttons !== 1) { - return; - } - - mouseDown = true; - mouseDownTime = performance.now(); - - mouseDownPosition = getRelativeMousePosition(event); - lassoActive = checkLassoMode() || checkModKey(event, KEY_ACTION_LASSO); - - if (!lassoActive && lassoOnLongPress) { - lassoManager.showLongPressIndicator(event.clientX, event.clientY, { - time: lassoLongPressTime, - extraTime: lassoLongPressAfterEffectTime, - delay: lassoLongPressEffectDelay, - }); - mouseDownTimeout = setTimeout(() => { - mouseDownTimeout = -1; - lassoActive = true; - }, lassoLongPressTime); - } - }; - - const mouseUpHandler = (event) => { - if (!isPointsDrawn) { - return; - } - - mouseDown = false; - if (mouseDownTimeout >= 0) { - clearTimeout(mouseDownTimeout); - mouseDownTimeout = -1; - } - - if (lassoActive) { - event.preventDefault(); - lassoActive = false; - lassoManager.end({ - merge: checkModKey(event, KEY_ACTION_MERGE), - remove: checkModKey(event, KEY_ACTION_REMOVE), - }); - } - - if (lassoOnLongPress) { - lassoManager.hideLongPressIndicator({ - time: lassoLongPressRevertEffectTime, - }); - } - }; - - const mouseClickHandler = (event) => { - if (!isPointsDrawn) { - return; - } - - event.preventDefault(); - - const currentMousePosition = getRelativeMousePosition(event); - - if (dist(...currentMousePosition, ...mouseDownPosition) >= lassoMinDist) { - return; - } - - const clickTime = performance.now() - mouseDownTime; - - if (!lassoInitiator || clickTime < LONG_CLICK_TIME) { - // If the user clicked normally (i.e., fast) we'll only show the lasso - // initiator if the use click into the void - const clostestPoint = raycast(); - if (clostestPoint >= 0) { - if ( - selectedPoints.length > 0 && - lassoClearEvent === LASSO_CLEAR_ON_DESELECT - ) { - // Special case where we silently "deselect" the previous points by - // overriding the selected points. Hence, we need to clear the lasso. - lassoClear(); - } - select([clostestPoint], { - merge: checkModKey(event, KEY_ACTION_MERGE), - remove: checkModKey(event, KEY_ACTION_REMOVE), - }); - } else if (!lassoInitiatorTimeout) { - // We'll also wait to make sure the user didn't double click - lassoInitiatorTimeout = setTimeout(() => { - lassoInitiatorTimeout = null; - lassoManager.showInitiator(event); - }, SINGLE_CLICK_DELAY); - } - } - }; - - const mouseDblClickHandler = (event) => { - lassoManager.hideInitiator(); - if (lassoInitiatorTimeout) { - clearTimeout(lassoInitiatorTimeout); - lassoInitiatorTimeout = null; - } - if (deselectOnDblClick) { - event.preventDefault(); - deselect(); - } - }; - - const mouseMoveHandler = (event) => { - if (!isMouseOverCanvasChecked) { - isMouseInCanvas = checkIfMouseIsOverCanvas(event); - isMouseOverCanvasChecked = true; - } - if (!(isPointsDrawn && (isMouseInCanvas || mouseDown))) { - return; - } - - const currentMousePosition = getRelativeMousePosition(event); - const mouseMoveDist = dist(...currentMousePosition, ...mouseDownPosition); - const mouseMovedMin = mouseMoveDist >= lassoMinDist; - - // Only ray cast if the mouse cursor is inside - if (isMouseInCanvas && !lassoActive) { - hover(raycast()); // eslint-disable-line no-use-before-define - } - - if (lassoActive) { - event.preventDefault(); - lassoManager.extend(event, true); - } else if (mouseDown && lassoOnLongPress && mouseMovedMin) { - lassoManager.hideLongPressIndicator({ - time: lassoLongPressRevertEffectTime, - }); - } - - if (mouseDownTimeout >= 0 && mouseMovedMin) { - clearTimeout(mouseDownTimeout); - mouseDownTimeout = -1; - } - - // Always redraw when mousedown as the user might have panned or lassoed - if (mouseDown) { - draw = true; - } - }; - - const blurHandler = () => { - hoveredPoint = undefined; - isMouseInCanvas = false; - isMouseOverCanvasChecked = false; - - if (!isPointsDrawn) { - return; - } - - if (+hoveredPoint >= 0 && !selectedPointsSet.has(hoveredPoint)) { - setPointConnectionColorState([hoveredPoint], 0); - } - mouseUpHandler(); - draw = true; - }; - - const createEncodingTexture = () => { - const maxEncoding = Math.max(pointSize.length, opacity.length); - - encodingTexRes = Math.max(2, Math.ceil(Math.sqrt(maxEncoding))); - const rgba = new Float32Array(encodingTexRes ** 2 * 4); - - for (let i = 0; i < maxEncoding; i++) { - rgba[i * 4] = pointSize[i] || 0; - rgba[i * 4 + 1] = Math.min(1, opacity[i] || 0); - - const activeOpacity = Number( - (pointColorActive[i] || pointColorActive[0])[3], - ); - rgba[i * 4 + 2] = Math.min( - 1, - Number.isNaN(activeOpacity) ? 1 : activeOpacity, - ); - - const hoverOpacity = Number( - (pointColorHover[i] || pointColorHover[0])[3], - ); - rgba[i * 4 + 3] = Math.min( - 1, - Number.isNaN(hoverOpacity) ? 1 : hoverOpacity, - ); - } - - return renderer.regl.texture({ - data: rgba, - shape: [encodingTexRes, encodingTexRes, 4], - type: 'float', - }); - }; - - const getColors = ( - baseColor = pointColor, - activeColor = pointColorActive, - hoverColor = pointColorHover, - ) => { - const n = baseColor.length; - const n2 = activeColor.length; - const n3 = hoverColor.length; - const colors = []; - if (n === n2 && n2 === n3) { - for (let i = 0; i < n; i++) { - colors.push( - baseColor[i], - activeColor[i], - hoverColor[i], - backgroundColor, - ); - } - } else { - for (let i = 0; i < n; i++) { - const rgbaOpaque = [ - baseColor[i][0], - baseColor[i][1], - baseColor[i][2], - 1, - ]; - const colorActive = - colorBy === DEFAULT_COLOR_BY ? activeColor[0] : rgbaOpaque; - const colorHover = - colorBy === DEFAULT_COLOR_BY ? hoverColor[0] : rgbaOpaque; - colors.push(baseColor[i], colorActive, colorHover, backgroundColor); - } - } - return colors; - }; - - const createColorTexture = () => { - const colors = getColors(); - const numColors = colors.length; - colorTexRes = Math.max(2, Math.ceil(Math.sqrt(numColors))); - const rgba = new Float32Array(colorTexRes ** 2 * 4); - colors.forEach((color, i) => { - rgba[i * 4] = color[0]; // r - rgba[i * 4 + 1] = color[1]; // g - rgba[i * 4 + 2] = color[2]; // b - rgba[i * 4 + 3] = color[3]; // a - }); - - return renderer.regl.texture({ - data: rgba, - shape: [colorTexRes, colorTexRes, 4], - type: 'float', - }); - }; - - /** - * Since we're using an external renderer whose canvas' width and height - * might differ from this instance's width and height, we have to adjust the - * projection of camera spaces into clip space accordingly. - * - * The `widthRatio` is rendererCanvas.width / thisCanvas.width - * The `heightRatio` is rendererCanvas.height / thisCanvas.height - */ - const updateProjectionMatrix = (widthRatio, heightRatio) => { - projection[0] = widthRatio / viewAspectRatio; - projection[5] = heightRatio; - }; - - const updateViewAspectRatio = () => { - viewAspectRatio = currentWidth / currentHeight; - projectionLocal = mat4.fromScaling([], [1 / viewAspectRatio, 1, 1]); - projection = mat4.fromScaling([], [1 / viewAspectRatio, 1, 1]); - model = mat4.fromScaling([], [dataAspectRatio, 1, 1]); - }; - - const setDataAspectRatio = (newDataAspectRatio) => { - if (+newDataAspectRatio <= 0) { - return; - } - dataAspectRatio = newDataAspectRatio; - }; - - const setColors = (getter, setter) => (newColors) => { - if (!newColors || newColors.length === 0) { - return; - } - - const colors = getter(); - const prevColors = [...colors]; - - let tmpColors = isMultipleColors(newColors) ? newColors : [newColors]; - tmpColors = tmpColors.map((color) => toRgba(color, true)); - - if (isSameRgbas(prevColors, tmpColors)) { - // We don't need to update the color texture so we return early - return; - } - - if (colorTex) { - colorTex.destroy(); - } - - try { - setter(tmpColors); - colorTex = createColorTexture(); - } catch (_error) { - // biome-ignore lint/suspicious/noConsole: This is a legitimately useful warning - console.error('Invalid colors. Switching back to default colors.'); - setter(prevColors); - colorTex = createColorTexture(); - } - }; - - const setPointColor = setColors( - () => pointColor, - (colors) => { - pointColor = colors; - }, - ); - const setPointColorActive = setColors( - () => pointColorActive, - (colors) => { - pointColorActive = colors; - }, - ); - const setPointColorHover = setColors( - () => pointColorHover, - (colors) => { - pointColorHover = colors; - }, - ); - - const computeDomainView = () => { - const xyStartPt = getScatterGlPos(-1, -1); - const xyEndPt = getScatterGlPos(1, 1); - - const xStart = (xyStartPt[0] + 1) / 2; - const xEnd = (xyEndPt[0] + 1) / 2; - const yStart = (xyStartPt[1] + 1) / 2; - const yEnd = (xyEndPt[1] + 1) / 2; - - const xDomainView = [ - xDomainStart + xStart * xDomainSize, - xDomainStart + xEnd * xDomainSize, - ]; - const yDomainView = [ - yDomainStart + yStart * yDomainSize, - yDomainStart + yEnd * yDomainSize, - ]; - - return [xDomainView, yDomainView]; - }; - - const updateScales = () => { - if (!(xScale || yScale)) { - return; - } - - const [xDomainView, yDomainView] = computeDomainView(); - - if (xScale) { - xScale.domain(xDomainView); - } - - if (yScale) { - yScale.domain(yDomainView); - } - }; - - const setCurrentHeight = (newCurrentHeight, skipScaleUpdates) => { - currentHeight = Math.max(1, newCurrentHeight); - canvas.height = Math.floor(currentHeight * window.devicePixelRatio); - if (yScale) { - yScale.range([currentHeight, 0]); - if (!skipScaleUpdates) { - updateScales(); - } - } - }; - - const setHeight = (newHeight) => { - if (newHeight === AUTO) { - height = newHeight; - canvas.style.height = '100%'; - window.requestAnimationFrame(() => { - if (canvas) { - setCurrentHeight(canvas.getBoundingClientRect().height); - } - }); - return; - } - - if (!+newHeight || +newHeight <= 0) { - return; - } - - height = +newHeight; - setCurrentHeight(height); - canvas.style.height = `${height}px`; - }; - - const computePointSizeMouseDetection = () => { - computedPointSizeMouseDetection = pointSizeMouseDetection; - - if (pointSizeMouseDetection === AUTO) { - computedPointSizeMouseDetection = Array.isArray(pointSize) - ? maxArray(pointSize) - : pointSize; - } - }; - - const setPointSize = (newPointSize) => { - const oldPointSize = Array.isArray(pointSize) ? [...pointSize] : pointSize; - - if (isConditionalArray(newPointSize, isPositiveNumber, { minLength: 1 })) { - pointSize = [...newPointSize]; - } else if (isStrictlyPositiveNumber(+newPointSize)) { - pointSize = [+newPointSize]; - } - - if ( - oldPointSize === pointSize || - hasSameElements(oldPointSize, pointSize) - ) { - // We don't need to update the encoding texture so we return early - return; - } - - if (encodingTex) { - encodingTex.destroy(); - } - - minPointScale = MIN_POINT_SIZE / pointSize[0]; - encodingTex = createEncodingTexture(); - computePointSizeMouseDetection(); - }; - - const setPointSizeSelected = (newPointSizeSelected) => { - if (!+newPointSizeSelected || +newPointSizeSelected < 0) { - return; - } - pointSizeSelected = +newPointSizeSelected; - }; - - const setPointOutlineWidth = (newPointOutlineWidth) => { - if (!+newPointOutlineWidth || +newPointOutlineWidth < 0) { - return; - } - pointOutlineWidth = +newPointOutlineWidth; - }; - - const setCurrentWidth = (newCurrentWidth, skipScaleUpdates) => { - currentWidth = Math.max(1, newCurrentWidth); - canvas.width = Math.floor(currentWidth * window.devicePixelRatio); - if (xScale) { - xScale.range([0, currentWidth]); - if (!skipScaleUpdates) { - updateScales(); - } - } - }; - - const setWidth = (newWidth) => { - if (newWidth === AUTO) { - width = newWidth; - canvas.style.width = '100%'; - window.requestAnimationFrame(() => { - if (canvas) { - setCurrentWidth(canvas.getBoundingClientRect().width); - } - }); - return; - } - - if (!+newWidth || +newWidth <= 0) { - return; - } - - width = +newWidth; - setCurrentWidth(width); - canvas.style.width = `${currentWidth}px`; - }; - - const setOpacity = (newOpacity) => { - const oldOpacity = Array.isArray(opacity) ? [...opacity] : opacity; - - if (isConditionalArray(newOpacity, isPositiveNumber, { minLength: 1 })) { - opacity = [...newOpacity]; - } else if (isStrictlyPositiveNumber(+newOpacity)) { - opacity = [+newOpacity]; - } - - if (oldOpacity === opacity || hasSameElements(oldOpacity, opacity)) { - // We don't need to update the encoding texture so we return early - return; - } - - if (encodingTex) { - encodingTex.destroy(); - } - - encodingTex = createEncodingTexture(); - }; - - const getEncodingDataType = (type) => { - switch (type) { - case 'valueZ': - return valueZDataType; - - case 'valueW': - return valueWDataType; - - default: - return null; - } - }; - - const getEncodingValueToIdx = (type, rangeValues) => { - switch (type) { - case CONTINUOUS: - return (value) => Math.round(value * (rangeValues.length - 1)); - - default: - return identity; - } - }; - - const setColorBy = (type) => { - colorBy = getEncodingType(type, DEFAULT_COLOR_BY); - }; - const setOpacityBy = (type) => { - opacityBy = getEncodingType(type, DEFAULT_OPACITY_BY, { - allowDensity: true, - }); - }; - const setSizeBy = (type) => { - sizeBy = getEncodingType(type, DEFAULT_SIZE_BY); - }; - const setPointOrder = (newPointOrder) => { - if (newPointOrder === null || newPointOrder === undefined) { - pointOrder = null; - } else if (Array.isArray(newPointOrder)) { - pointOrder = newPointOrder; - } else { - return; - } - - if (isPointsDrawn) { - computePointOrderIndex(); - if (isPointsFiltered) { - // Re-apply filter respecting the new point order - const filteredPointsBuffer = []; - if (pointOrderIndices !== null) { - for (let i = 0; i < pointOrderIndices.length; i++) { - if (filteredPointsSet.has(pointOrderIndices[i])) { - filteredPointsBuffer.push.apply( - filteredPointsBuffer, - indexToStateTexCoord(pointOrderIndices[i]), - ); - } - } - } else { - const sortedFiltered = insertionSort([...filteredPointsSet]); - for (const idx of sortedFiltered) { - filteredPointsBuffer.push.apply( - filteredPointsBuffer, - indexToStateTexCoord(idx), - ); - } - } - normalPointsIndexBuffer.subdata(filteredPointsBuffer); - } else { - normalPointsIndexBuffer.subdata(getEffectivePointIndex(numPoints)); - } - } - }; - const setPointConnectionColorBy = (type) => { - pointConnectionColorBy = getEncodingType( - type, - DEFAULT_POINT_CONNECTION_COLOR_BY, - { allowSegment: true, allowInherit: true }, - ); - }; - const setPointConnectionOpacityBy = (type) => { - pointConnectionOpacityBy = getEncodingType( - type, - DEFAULT_POINT_CONNECTION_OPACITY_BY, - { allowSegment: true }, - ); - }; - const setPointConnectionSizeBy = (type) => { - pointConnectionSizeBy = getEncodingType( - type, - DEFAULT_POINT_CONNECTION_SIZE_BY, - { allowSegment: true }, - ); - }; - - const getAntiAliasing = () => antiAliasing; - const getResolution = () => [canvas.width, canvas.height]; - const getBackgroundImage = () => backgroundImage; - const getColorTex = () => colorTex; - const getColorTexRes = () => colorTexRes; - const getColorTexEps = () => 0.5 / colorTexRes; - const getDevicePixelRatio = () => window.devicePixelRatio; - const getNormalPointsIndexBuffer = () => normalPointsIndexBuffer; - const getSelectedPointsIndexBuffer = () => selectedPointsIndexBuffer; - const getEncodingTex = () => encodingTex; - const getEncodingTexRes = () => encodingTexRes; - const getEncodingTexEps = () => 0.5 / encodingTexRes; - const getNormalPointSizeExtra = () => 0; - const getStateTex = () => tmpStateTex || stateTex; - const getStateTexRes = () => stateTexRes; - const getStateTexEps = () => 0.5 / stateTexRes; - const getProjection = () => projection; - const getView = () => camera.view; - const getModel = () => model; - const getModelViewProjection = () => - mat4.multiply(pvm, projection, mat4.multiply(pvm, camera.view, model)); - const getConstantPointScale = () => { - return window.devicePixelRatio; - }; - const getLinearPointScale = () => { - return max(minPointScale, camera.scaling[0]) * window.devicePixelRatio; - }; - const getAsinhPointScale = () => { - if (camera.scaling[0] > 1) { - return ( - (Math.asinh(max(1.0, camera.scaling[0])) / Math.asinh(1)) * - window.devicePixelRatio - ); - } - return max(minPointScale, camera.scaling[0]) * window.devicePixelRatio; - }; - let getPointScale = getAsinhPointScale; - if (pointScaleMode === 'linear') { - getPointScale = getLinearPointScale; - } else if (pointScaleMode === 'constant') { - getPointScale = getConstantPointScale; - } - const getNormalNumPoints = () => - isPointsFiltered ? filteredPointsSet.size : numPoints; - const getSelectedNumPoints = () => selectedPoints.length; - const getPointOpacityMaxBase = () => - getSelectedNumPoints() > 0 ? opacityInactiveMax : 1; - const getPointOpacityScaleBase = () => - getSelectedNumPoints() > 0 ? opacityInactiveScale : 1; - const getIsColoredByZ = () => +(colorBy === 'valueZ'); - const getIsColoredByW = () => +(colorBy === 'valueW'); - const getIsOpacityByZ = () => +(opacityBy === 'valueZ'); - const getIsOpacityByW = () => +(opacityBy === 'valueW'); - const getIsOpacityByDensity = () => +(opacityBy === 'density'); - const getIsSizedByZ = () => +(sizeBy === 'valueZ'); - const getIsSizedByW = () => +(sizeBy === 'valueW'); - const getIsPixelAligned = () => +pixelAligned; - const getColorMultiplicator = () => { - if (colorBy === 'valueZ') { - return valueZDataType === CONTINUOUS ? pointColor.length - 1 : 1; - } - return valueWDataType === CONTINUOUS ? pointColor.length - 1 : 1; - }; - const getOpacityMultiplicator = () => { - if (opacityBy === 'valueZ') { - return valueZDataType === CONTINUOUS ? opacity.length - 1 : 1; - } - return valueWDataType === CONTINUOUS ? opacity.length - 1 : 1; - }; - const getSizeMultiplicator = () => { - if (sizeBy === 'valueZ') { - return valueZDataType === CONTINUOUS ? pointSize.length - 1 : 1; - } - return valueWDataType === CONTINUOUS ? pointSize.length - 1 : 1; - }; - const getOpacityDensity = (context) => { - if (opacityBy !== 'density') { - return 1; - } - - // Adopted from the fabulous Ricky Reusser: - // https://observablehq.com/@rreusser/selecting-the-right-opacity-for-2d-point-clouds - // Extended with a point-density based approach - const pointScale = getPointScale(); - const p = pointSize[0] * pointScale; - - // Compute the plot's x and y range from the view matrix, though these could come from any source - const s = (2 / (2 / camera.view[0])) * (2 / (2 / camera.view[5])); - - // Viewport size, in device pixels - const H = context.viewportHeight; - const W = context.viewportWidth; - - // Adaptation: Instead of using the global number of points, I am using a - // density-based approach that takes the points in the view into context - // when zooming in. This ensure that in sparse areas, points are opaque and - // in dense areas points are more translucent. - let alpha = - ((opacityByDensityFill * W * H) / (numPointsInView * p * p)) * min(1, s); - - // Unless `renderPointsAsSquares` is true, we use circles, which only take - // up (pi r^2) of the unit square - alpha *= renderPointsAsSquares ? 1 : 1 / (0.25 * Math.PI); - - // If the pixels shrink below the minimum permitted size, then we adjust the opacity instead - // and apply clamping of the point size in the vertex shader. Note that we add 0.5 since we - // slightly inrease the size of points during rendering to accommodate SDF-style antialiasing. - const clampedPointDeviceSize = max(MIN_POINT_SIZE, p) + 0.5; - - // We square this since we're concerned with the ratio of *areas*. - alpha *= (p / clampedPointDeviceSize) ** 2; - - // And finally, we clamp to the range [0, 1]. We should really clamp this to 1 / precision - // on the low end, depending on the data type of the destination so that we never render *nothing*. - return min(1, max(0, alpha)); - }; - - const updatePoints = renderer.regl({ - framebuffer: () => tmpStateBuffer, - - vert: POINT_UPDATE_VS, - frag: POINT_UPDATE_FS, - - attributes: { - position: [-4, 0, 4, 4, 4, -4], - }, - - uniforms: { - startStateTex: () => prevStateTex, - endStateTex: () => stateTex, - t: (_ctx, props) => props.t, - }, - - count: 3, - }); - - const drawPoints = ( - getPointSizeExtra, - getNumPoints, - getStateIndexBuffer, - globalState = COLOR_NORMAL_IDX, - getPointOpacityMax = getPointOpacityMaxBase, - getPointOpacityScale = getPointOpacityScaleBase, - ) => - renderer.regl({ - frag: renderPointsAsSquares ? POINT_SIMPLE_FS : POINT_FS, - vert: createVertexShader(globalState), - - blend: { - enable: !disableAlphaBlending, - func: { - srcRGB: 'src alpha', - srcAlpha: 'one', - dstRGB: 'one minus src alpha', - dstAlpha: 'one minus src alpha', - }, - }, - - depth: { enable: false }, - - attributes: { - stateIndex: { - buffer: getStateIndexBuffer, - size: 2, - }, - }, - - uniforms: { - antiAliasing: getAntiAliasing, - resolution: getResolution, - modelViewProjection: getModelViewProjection, - devicePixelRatio: getDevicePixelRatio, - pointScale: () => getPointScale(), - encodingTex: getEncodingTex, - encodingTexRes: getEncodingTexRes, - encodingTexEps: getEncodingTexEps, - pointOpacityMax: getPointOpacityMax, - pointOpacityScale: getPointOpacityScale, - pointSizeExtra: getPointSizeExtra, - globalState, - colorTex: getColorTex, - colorTexRes: getColorTexRes, - colorTexEps: getColorTexEps, - stateTex: getStateTex, - stateTexRes: getStateTexRes, - stateTexEps: getStateTexEps, - isColoredByZ: getIsColoredByZ, - isColoredByW: getIsColoredByW, - isOpacityByZ: getIsOpacityByZ, - isOpacityByW: getIsOpacityByW, - isOpacityByDensity: getIsOpacityByDensity, - isSizedByZ: getIsSizedByZ, - isSizedByW: getIsSizedByW, - isPixelAligned: getIsPixelAligned, - colorMultiplicator: getColorMultiplicator, - opacityMultiplicator: getOpacityMultiplicator, - opacityDensity: getOpacityDensity, - sizeMultiplicator: getSizeMultiplicator, - numColorStates: COLOR_NUM_STATES, - drawingBufferWidth: (context) => context.drawingBufferWidth, - drawingBufferHeight: (context) => context.drawingBufferHeight, - }, - - count: getNumPoints, - - primitive: 'points', - }); - - const drawPointBodies = drawPoints( - getNormalPointSizeExtra, - getNormalNumPoints, - getNormalPointsIndexBuffer, - ); - - const drawHoveredPoint = drawPoints( - getNormalPointSizeExtra, - () => 1, - () => hoveredPointIndexBuffer, - COLOR_HOVER_IDX, - () => 1, - () => 1, - ); - - const drawSelectedPointOutlines = drawPoints( - () => (pointSizeSelected + pointOutlineWidth * 2) * window.devicePixelRatio, - getSelectedNumPoints, - getSelectedPointsIndexBuffer, - COLOR_ACTIVE_IDX, - () => 1, - () => 1, - ); - - const drawSelectedPointInnerBorder = drawPoints( - () => (pointSizeSelected + pointOutlineWidth) * window.devicePixelRatio, - getSelectedNumPoints, - getSelectedPointsIndexBuffer, - COLOR_BG_IDX, - () => 1, - () => 1, - ); - - const drawSelectedPointBodies = drawPoints( - () => pointSizeSelected * window.devicePixelRatio, - getSelectedNumPoints, - getSelectedPointsIndexBuffer, - COLOR_ACTIVE_IDX, - () => 1, - () => 1, - ); - - const drawSelectedPoints = () => { - drawSelectedPointOutlines(); - drawSelectedPointInnerBorder(); - drawSelectedPointBodies(); - }; - - const drawBackgroundImage = renderer.regl({ - frag: BG_FS, - vert: BG_VS, - - attributes: { - position: [0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0], - }, - - uniforms: { - modelViewProjection: getModelViewProjection, - texture: getBackgroundImage, - }, - - count: 6, - }); - - const drawLassoPolygon = renderer.regl({ - vert: ` - precision mediump float; - uniform mat4 modelViewProjection; - attribute vec2 position; - void main () { - gl_Position = modelViewProjection * vec4(position, 0, 1); - }`, - - frag: ` - precision mediump float; - uniform vec4 color; - void main () { - gl_FragColor = vec4(color.rgb, 0.2); - }`, - - depth: { enable: false }, - - blend: { - enable: true, - func: { - srcRGB: 'src alpha', - srcAlpha: 'one', - dstRGB: 'one minus src alpha', - dstAlpha: 'one minus src alpha', - }, - }, - - attributes: { - position: () => lassoPointsCurr, - }, - - uniforms: { - modelViewProjection: getModelViewProjection, - color: () => lassoColor, - }, - - elements: () => earcut(lasso.getPoints()), - }); - - const drawReticle = () => { - if (!(hoveredPoint >= 0)) { - return; - } - - const [x, y] = points[hoveredPoint].slice(0, 2); - - // Homogeneous coordinates of the point - const v = [x, y, 0, 1]; - - // We have to calculate the model-view-projection matrix outside of the - // shader as we actually don't want the model, view, or projection of the - // line view space to change such that the reticle is visualized across the - // entire view container and not within the view of the scatterplot - mat4.multiply( - scratch, - projection, - mat4.multiply(scratch, camera.view, model), - ); - - vec4.transformMat4(v, v, scratch); - - reticleHLine.setPoints([-1, v[1], 1, v[1]]); - reticleVLine.setPoints([v[0], 1, v[0], -1]); - - reticleHLine.draw(); - reticleVLine.draw(); - - // Draw outer outline - drawPoints( - () => - (pointSizeSelected + pointOutlineWidth * 2) * window.devicePixelRatio, - () => 1, - hoveredPointIndexBuffer, - COLOR_ACTIVE_IDX, - )(); - - // Draw inner outline - drawPoints( - () => (pointSizeSelected + pointOutlineWidth) * window.devicePixelRatio, - () => 1, - hoveredPointIndexBuffer, - COLOR_BG_IDX, - )(); - }; - - const createPointIndex = (numNewPoints) => { - const index = new Float32Array(numNewPoints * 2); - - let j = 0; - for (let i = 0; i < numNewPoints; ++i) { - const texCoord = indexToStateTexCoord(i); - index[j] = texCoord[0]; // x - index[j + 1] = texCoord[1]; // y - j += 2; - } - - return index; - }; - - const computePointOrderIndex = () => { - if (pointOrder === null) { - pointOrderIndices = null; - pointOrderIndex = null; - return; - } - - const includedSet = new Set(); - const orderedIndices = []; - - for (let i = 0; i < pointOrder.length; i++) { - const idx = pointOrder[i]; - if ( - Number.isFinite(idx) && - idx >= 0 && - idx < numPoints && - !includedSet.has(idx) - ) { - orderedIndices.push(idx); - includedSet.add(idx); - } - } - - // Append any missing indices in sequential order - for (let i = 0; i < numPoints; i++) { - if (!includedSet.has(i)) { - orderedIndices.push(i); - } - } - - pointOrderIndices = orderedIndices; - - pointOrderIndex = new Float32Array(orderedIndices.length * 2); - let j = 0; - for (let i = 0; i < orderedIndices.length; i++) { - const texCoord = indexToStateTexCoord(orderedIndices[i]); - pointOrderIndex[j] = texCoord[0]; - pointOrderIndex[j + 1] = texCoord[1]; - j += 2; - } - }; - - const getEffectivePointIndex = (count) => - pointOrderIndex !== null ? pointOrderIndex : createPointIndex(count); - - const createStateTexture = (newPoints, dataTypes = {}) => { - const numNewPoints = newPoints.length; - stateTexRes = Math.max(2, Math.ceil(Math.sqrt(numNewPoints))); - stateTexEps = 0.5 / stateTexRes; - const data = new Float32Array(stateTexRes ** 2 * 4); - - let zIsInts = true; - let wIsInts = true; - - let k = 0; - let z = 0; - let w = 0; - for (let i = 0; i < numNewPoints; ++i) { - k = i * 4; - - data[k] = newPoints[i][0]; // x - data[k + 1] = newPoints[i][1]; // y - - z = newPoints[i][2] || 0; - w = newPoints[i][3] || 0; - - data[k + 2] = z; // z: value 1 - data[k + 3] = w; // w: value 2 - zIsInts &&= Number.isInteger(z); - wIsInts &&= Number.isInteger(w); - } - - if (dataTypes.z && VALUE_ZW_DATA_TYPES.includes(dataTypes.z)) { - valueZDataType = dataTypes.z; - } else { - valueZDataType = zIsInts ? CATEGORICAL : CONTINUOUS; - } - - if (dataTypes.w && VALUE_ZW_DATA_TYPES.includes(dataTypes.w)) { - valueWDataType = dataTypes.w; - } else { - valueWDataType = wIsInts ? CATEGORICAL : CONTINUOUS; - } - - return renderer.regl.texture({ - data, - shape: [stateTexRes, stateTexRes, 4], - type: 'float', - }); - }; - - const cachePoints = (newPoints, dataTypes = {}) => { - if (!stateTex) { - return false; - } - - if (isTransitioning) { - const tmp = prevStateTex; - prevStateTex = tmpStateTex; - tmp.destroy(); - } else { - prevStateTex = stateTex; - } - - tmpStateTex = createStateTexture(newPoints, dataTypes); - tmpStateBuffer = renderer.regl.framebuffer({ - color: tmpStateTex, - depth: false, - stencil: false, - }); - stateTex = undefined; - - return true; - }; - - const hasCachedPoints = () => Boolean(prevStateTex && tmpStateTex); - - const clearCachedPoints = () => { - if (prevStateTex) { - prevStateTex.destroy(); - prevStateTex = undefined; - } - - if (tmpStateTex) { - tmpStateTex.destroy(); - tmpStateTex = undefined; - } - }; - - const setPoints = (newPoints, options = {}) => - new Promise((resolve) => { - isPointsDrawn = false; - - const preventFilterReset = - options?.preventFilterReset && newPoints.length === numPoints; - - const prevNumPoints = numPoints; - numPoints = newPoints.length; - numPointsInView = numPoints; - - // Reset pointOrder when re-drawing with different-length data - // (ordering becomes meaningless). Skip on first draw (prevNumPoints === 0). - if (prevNumPoints > 0 && numPoints !== prevNumPoints) { - pointOrder = null; - pointOrderIndices = null; - pointOrderIndex = null; - } - - if (stateTex) { - stateTex.destroy(); - } - stateTex = createStateTexture(newPoints, { - z: options.zDataType, - w: options.wDataType, - }); - - if (!preventFilterReset) { - computePointOrderIndex(); - normalPointsIndexBuffer({ - usage: 'static', - type: 'float', - data: getEffectivePointIndex(numPoints), - }); - } - - createKdbush(options.spatialIndex || newPoints, { - useWorker: spatialIndexUseWorker, - }) - .then((newSearchIndex) => { - spatialIndex = newSearchIndex; - points = newPoints; - - isPointsDrawn = true; - }) - .then(resolve); - }); - - const cacheCamera = (newTarget, newDistance) => { - cameraZoomTargetStart = camera.target; - cameraZoomTargetEnd = newTarget; - cameraZoomDistanceStart = camera.distance[0]; - cameraZoomDistanceEnd = newDistance; - }; - - const hasCachedCamera = () => - Boolean( - cameraZoomTargetStart !== undefined && - cameraZoomTargetEnd !== undefined && - cameraZoomDistanceStart !== undefined && - cameraZoomDistanceEnd !== undefined, - ); - - const clearCachedCamera = () => { - cameraZoomTargetStart = undefined; - cameraZoomTargetEnd = undefined; - cameraZoomDistanceStart = undefined; - cameraZoomDistanceEnd = undefined; - }; - - const getPointConnectionColorIndices = (curvePoints) => { - const colorEncoding = - pointConnectionColorBy === 'inherit' ? colorBy : pointConnectionColorBy; - - if (colorEncoding === 'segment') { - const maxColorIdx = pointConnectionColor.length - 1; - if (maxColorIdx < 1) { - return []; - } - return curvePoints.reduce((colorIndices, curve, index) => { - let totalLength = 0; - const segLengths = []; - // Compute the total length of the line - for (let i = 2; i < curve.length; i += 2) { - const segLength = Math.sqrt( - (curve[i - 2] - curve[i]) ** 2 + (curve[i - 1] - curve[i + 1]) ** 2, - ); - segLengths.push(segLength); - totalLength += segLength; - } - colorIndices[index] = [0]; - let cumLength = 0; - // Assign the color index based on the cumulative length - for (let i = 0; i < curve.length / 2 - 1; i++) { - cumLength += segLengths[i]; - // The `4` comes from the fact that we have 4 color states: - // normal, active, hover, and background - colorIndices[index].push( - Math.floor((cumLength / totalLength) * maxColorIdx) * 4, - ); - } - // The `4` comes from the fact that we have 4 color states: - // normal, active, hover, and background - // colorIndices[index] = rangeMap( - // curve.length, - // (i) => Math.floor((i / (curve.length - 1)) * maxColorIdx) * 4 - // ); - return colorIndices; - }, []); - } - - if (colorEncoding) { - const encodingIdx = getEncodingIdx(colorEncoding); - const encodingValueToIdx = getEncodingValueToIdx( - getEncodingDataType(colorEncoding), - pointConnectionColorBy === 'inherit' - ? pointColor - : pointConnectionColor, - ); - return pointConnectionMap.reduce( - (colorIndices, [index, referencePoint]) => { - // The `4` comes from the fact that we have 4 color states: - // normal, active, hover, and background - colorIndices[index] = - encodingValueToIdx(referencePoint[encodingIdx]) * 4; - return colorIndices; - }, - [], - ); - } - - return new Array(pointConnectionMap.length).fill(0); - }; - - const getPointConnectionOpacities = () => { - const opacityEncoding = - pointConnectionOpacityBy === 'inherit' - ? opacityBy - : pointConnectionOpacityBy; - - if (opacityEncoding === 'segment') { - const maxOpacityIdx = pointConnectionOpacity.length - 1; - if (maxOpacityIdx < 1) { - return []; - } - return pointConnectionMap.reduce( - (opacities, [index, _referencePoint, length]) => { - opacities[index] = rangeMap( - length, - (i) => - pointConnectionOpacity[ - Math.floor((i / (length - 1)) * maxOpacityIdx) - ], - ); - return opacities; - }, - [], - ); - } - - if (opacityEncoding) { - const encodingIdx = getEncodingIdx(opacityEncoding); - const encodingRangeMap = - pointConnectionOpacityBy === 'inherit' - ? opacity - : pointConnectionOpacity; - const encodingValueToIdx = getEncodingValueToIdx( - getEncodingDataType(opacityEncoding), - encodingRangeMap, - ); - return pointConnectionMap.reduce((opacities, [index, referencePoint]) => { - opacities[index] = - encodingRangeMap[encodingValueToIdx(referencePoint[encodingIdx])]; - return opacities; - }, []); - } - - return undefined; - }; - - const getPointConnectionWidths = () => { - const sizeEncoding = - pointConnectionSizeBy === 'inherit' ? sizeBy : pointConnectionSizeBy; - - if (sizeEncoding === 'segment') { - const maxSizeIdx = pointConnectionSize.length - 1; - if (maxSizeIdx < 1) { - return []; - } - return pointConnectionMap.reduce( - (widths, [index, _referencePoint, length]) => { - widths[index] = rangeMap( - length, - (i) => - pointConnectionSize[Math.floor((i / (length - 1)) * maxSizeIdx)], - ); - return widths; - }, - [], - ); - } - - if (sizeEncoding) { - const encodingIdx = getEncodingIdx(sizeEncoding); - const encodingRangeMap = - pointConnectionSizeBy === 'inherit' ? pointSize : pointConnectionSize; - const encodingValueToIdx = getEncodingValueToIdx( - getEncodingDataType(sizeEncoding), - encodingRangeMap, - ); - return pointConnectionMap.reduce((widths, [index, referencePoint]) => { - widths[index] = - encodingRangeMap[encodingValueToIdx(referencePoint[encodingIdx])]; - return widths; - }, []); - } - - return undefined; - }; - - const setPointConnectionMap = (curvePoints) => { - pointConnectionMap = []; - - let cumLinePoints = 0; - Object.keys(curvePoints).forEach((id, index) => { - pointConnectionMap[id] = [ - index, - curvePoints[id].reference, - curvePoints[id].length / 2, - // Used for offsetting in the buffer manipulations on - // hovering and selecting - cumLinePoints, - ]; - cumLinePoints += curvePoints[id].length / 2; - }); - }; - - const setPointConnections = (newPoints) => - new Promise((resolve) => { - pointConnections.setPoints([]); - if (newPoints?.length > 0) { - computingPointConnectionCurves = true; - createSplineCurve(newPoints, { - maxIntPointsPerSegment: pointConnectionMaxIntPointsPerSegment, - tolerance: pointConnectionTolerance, - }).then((curvePoints) => { - setPointConnectionMap(curvePoints); - const curvePointValues = Object.values(curvePoints); - pointConnections.setPoints( - curvePointValues.length === 1 - ? curvePointValues[0] - : curvePointValues, - { - colorIndices: getPointConnectionColorIndices(curvePointValues), - opacities: getPointConnectionOpacities(curvePointValues), - widths: getPointConnectionWidths(curvePointValues), - }, - ); - computingPointConnectionCurves = false; - resolve(); - }); - } else { - resolve(); - } - }); - - /** - * Reset the point filter - * @param {import('./types').ScatterplotMethodOptions['filter']} - */ - const unfilter = ({ preventEvent = false } = {}) => { - isPointsFiltered = false; - filteredPointsSet.clear(); - normalPointsIndexBuffer.subdata(getEffectivePointIndex(numPoints)); - - return new Promise((resolve) => { - const finish = () => { - pubSub.subscribe( - 'draw', - () => { - if (!preventEvent) { - pubSub.publish('unfilter'); - } - resolve(); - }, - 1, - ); - draw = true; - }; - - // Update point connections - if (showPointConnections || hasPointConnections(points[0])) { - setPointConnections(getPoints()).then(() => { - if (!preventEvent) { - pubSub.publish('pointConnectionsDraw'); - } - finish(); - }); - } else { - finish(); - } - }); - }; - - /** - * Filter down to a set of points - * @param {number | number[]} pointIdxs - * @param {import('./types').ScatterplotMethodOptions['filter']} - */ - const filter = (pointIdxs, { preventEvent = false } = {}) => { - isPointsFiltered = true; - filteredPointsSet.clear(); - - const pointIdxsArray = Array.isArray(pointIdxs) ? pointIdxs : [pointIdxs]; - const filteredPoints = []; - const filteredPointsBuffer = []; - const filteredSelectedPoints = []; - - for (const pointIdx of pointIdxsArray) { - if (!Number.isFinite(pointIdx) || pointIdx < 0 || pointIdx >= numPoints) { - // Skip invalid filtered points - continue; - } - - filteredPoints.push(pointIdx); - filteredPointsSet.add(pointIdx); - - if (selectedPointsSet.has(pointIdx)) { - filteredSelectedPoints.push(pointIdx); - } - } - - let orderedFilteredPoints; - if (pointOrderIndices !== null) { - // Maintain the custom point order within the filtered set - orderedFilteredPoints = []; - for (let i = 0; i < pointOrderIndices.length; i++) { - if (filteredPointsSet.has(pointOrderIndices[i])) { - orderedFilteredPoints.push(pointOrderIndices[i]); - } - } - } else { - orderedFilteredPoints = insertionSort([...filteredPoints]); - } - - for (const pointIdx of orderedFilteredPoints) { - filteredPointsBuffer.push.apply( - filteredPointsBuffer, - indexToStateTexCoord(pointIdx), - ); - } - - // Update the normal points index buffers - normalPointsIndexBuffer.subdata(filteredPointsBuffer); - - // Update selection - select(filteredSelectedPoints, { preventEvent }); - - // Unset any potentially hovered point - if (!filteredPointsSet.has(hoveredPoint)) { - hover(-1, { preventEvent }); - } - - return new Promise((resolve) => { - const finish = () => { - pubSub.subscribe( - 'draw', - () => { - if (!preventEvent) { - pubSub.publish('filter', { points: filteredPoints }); - } - resolve(); - }, - 1, - ); - draw = true; - }; - - // Update point connections - if (showPointConnections || hasPointConnections(points[0])) { - setPointConnections(getPoints()).then(() => { - if (!preventEvent) { - pubSub.publish('pointConnectionsDraw'); - } - // We have to re-apply the selection because the connections might - // have changed - select(filteredSelectedPoints, { preventEvent }); - finish(); - }); - } else { - finish(); - } - }); - }; - - const getPointsInView = () => - getPointsInBBox( - bottomLeftNdc[0], - bottomLeftNdc[1], - topRightNdc[0], - topRightNdc[1], - ); - - const getNumPointsInView = () => { - numPointsInView = getPointsInView().length; - }; - - const getNumPointsInViewDb = throttleAndDebounce( - getNumPointsInView, - opacityByDensityDebounceTime, - ); - - const tweenCamera = (t) => { - const [xStart, yStart] = cameraZoomTargetStart; - const [xEnd, yEnd] = cameraZoomTargetEnd; - - const ti = 1.0 - t; - - const targetX = xStart * ti + xEnd * t; - const targetY = yStart * ti + yEnd * t; - const distance = cameraZoomDistanceStart * ti + cameraZoomDistanceEnd * t; - - camera.lookAt([targetX, targetY], distance); - }; - - const isTransitioningPoints = () => hasCachedPoints(); - - const isTransitioningCamera = () => hasCachedCamera(); - - const tween = (duration, easing) => { - if (!transitionStartTime) { - transitionStartTime = performance.now(); - } - - const dt = performance.now() - transitionStartTime; - const t = clip(easing(dt / duration), 0, 1); - - if (isTransitioningPoints()) { - updatePoints({ t }); - } - - if (isTransitioningCamera()) { - tweenCamera(t); - } - - return dt < duration; - }; - - const endTransition = () => { - isTransitioning = false; - transitionStartTime = null; - transitionDuration = undefined; - transitionEasing = undefined; - showReticle = preTransitionShowReticle; - - clearCachedPoints(); - clearCachedCamera(); - - pubSub.publish('transitionEnd'); - }; - - const startTransition = ({ duration = 500, easing = DEFAULT_EASING }) => { - if (isTransitioning) { - pubSub.publish('transitionEnd'); - } - - isTransitioning = true; - transitionStartTime = null; - transitionDuration = duration; - transitionEasing = isString(easing) - ? EASING_FNS[easing] || DEFAULT_EASING - : easing; - preTransitionShowReticle = showReticle; - showReticle = false; - - pubSub.publish('transitionStart'); - }; - - /** - * @param {import('./types').Points} newPoints - * @param {import('./types').ScatterplotMethodOptions['draw']} options - * @returns {Promise} - */ - const publicDraw = (newPoints, options = {}) => { - if (isDestroyed) { - return Promise.reject(new Error(ERROR_INSTANCE_IS_DESTROYED)); - } - if (isDrawing) { - return Promise.reject(new Error(ERROR_IS_DRAWING)); - } - isDrawing = true; - return toArrayOrientedPoints(newPoints).then((newPointsArray) => - new Promise((resolve) => { - if (isDestroyed) { - // In the special case where the instance was destroyed after - // scatterplot.draw() was called but before toArrayOrientedPoints() - // resolved, we will _not_ reject the promise as this would be - // confusing. Instead we will immediately resolve and return. - resolve(); - return; - } - - let pointsCached = false; - - if ( - !options.preventFilterReset || - newPointsArray?.length !== numPoints - ) { - isPointsFiltered = false; - filteredPointsSet.clear(); - } - - const drawPointConnections = - newPointsArray && - hasPointConnections(newPointsArray[0]) && - (showPointConnections || options.showPointConnectionsOnce); - - const { zDataType, wDataType } = options; - - new Promise((resolveDraw) => { - if (newPointsArray) { - if (options.transition) { - if (newPointsArray.length === numPoints) { - pointsCached = cachePoints(newPointsArray, { - z: zDataType, - w: wDataType, - }); - } else { - // biome-ignore lint/suspicious/noConsole: This is a legitimately useful warning - console.warn( - 'Cannot transition! The number of points between the previous and current draw call must be identical.', - ); - } - } - - setPoints(newPointsArray, { - zDataType, - wDataType, - preventFilterReset: options.preventFilterReset, - spatialIndex: options.spatialIndex, - }).then(() => { - if (options.hover !== undefined) { - hover(options.hover, { preventEvent: true }); - } - - if (options.select !== undefined) { - select(options.select, { preventEvent: true }); - } - - if (options.filter !== undefined) { - filter(options.filter, { preventEvent: true }); - } - - if (drawPointConnections) { - setPointConnections(newPointsArray) - .then(() => { - pubSub.publish('pointConnectionsDraw'); - draw = true; - drawReticleOnce = options.showReticleOnce; - }) - .then(() => resolve()); - } else { - resolveDraw(); - } - }); - } else { - resolveDraw(); - } - }).then(() => { - if (options.transition && pointsCached) { - if (drawPointConnections) { - Promise.all([ - new Promise((resolveTransition) => { - pubSub.subscribe( - 'transitionEnd', - () => { - // Point connects cannot be transitioned yet so we hide them during - // the transition. Hence, we need to make sure we call `draw()` once - // the transition has ended. - draw = true; - drawReticleOnce = options.showReticleOnce; - resolveTransition(); - }, - 1, - ); - }), - new Promise((resolveDraw) => { - pubSub.subscribe('pointConnectionsDraw', resolveDraw, 1); - }), - ]).then(() => resolve()); - } else { - pubSub.subscribe( - 'transitionEnd', - () => { - // Point connects cannot be transitioned yet so we hide them during - // the transition. Hence, we need to make sure we call `draw()` once - // the transition has ended. - draw = true; - drawReticleOnce = options.showReticleOnce; - resolve(); - }, - 1, - ); - } - startTransition({ - duration: options.transitionDuration, - easing: options.transitionEasing, - }); - } else { - if (drawPointConnections) { - Promise.all([ - new Promise((resolveDraw) => { - pubSub.subscribe('draw', resolveDraw, 1); - }), - new Promise((resolveDraw) => { - pubSub.subscribe('pointConnectionsDraw', resolveDraw, 1); - }), - ]).then(() => resolve()); - } else { - pubSub.subscribe('draw', () => resolve(), 1); - } - draw = true; - drawReticleOnce = options.showReticleOnce; - } - }); - }).finally(() => { - isDrawing = false; - }), - ); - }; - - /** - * Draw line-based annotations. - * @param {import('./types').Annotation[]} newAnnotations - * @returns {Promise} - */ - const drawAnnotations = (newAnnotations) => { - if (isDestroyed) { - return Promise.reject(new ERROR_INSTANCE_IS_DESTROYED()); - } - - isAnnotationsDrawn = false; - - if (newAnnotations.length === 0) { - return new Promise((resolve) => { - annotations.clear(); - pubSub.subscribe('draw', resolve, 1); - isAnnotationsDrawn = true; - draw = true; - }); - } - - return new Promise((resolve) => { - const newPoints = []; - const newColors = new Map(); - const newColorIndices = []; - const newWidths = []; - - let maxNewColorIdx = -1; - - const addColorAndWidth = (annotation) => { - newWidths.push(annotation.lineWidth || annotationLineWidth); - - const color = toRgba(annotation.lineColor || annotationLineColor, true); - const colorId = `[${color.join(',')}]`; - if (newColors.has(colorId)) { - const { idx } = newColors.get(colorId); - newColorIndices.push(idx); - } else { - const idx = ++maxNewColorIdx; - newColors.set(colorId, { idx, color }); - newColorIndices.push(idx); - } - }; - - for (const annotation of newAnnotations) { - if (isHorizontalLine(annotation)) { - newPoints.push([ - annotation.x1 ?? -annotationHVLineLimit, - annotation.y, - annotation.x2 ?? annotationHVLineLimit, - annotation.y, - ]); - addColorAndWidth(annotation); - continue; - } - - if (isVerticalLine(annotation)) { - newPoints.push([ - annotation.x, - annotation.y1 ?? -annotationHVLineLimit, - annotation.x, - annotation.y2 ?? annotationHVLineLimit, - ]); - addColorAndWidth(annotation); - continue; - } - - if (isRect(annotation)) { - newPoints.push([ - annotation.x1, - annotation.y1, - annotation.x2, - annotation.y1, - annotation.x2, - annotation.y2, - annotation.x1, - annotation.y2, - annotation.x1, - annotation.y1, - ]); - addColorAndWidth(annotation); - continue; - } - - if (isDomRect(annotation)) { - newPoints.push([ - annotation.x, - annotation.y, - annotation.x + annotation.width, - annotation.y, - annotation.x + annotation.width, - annotation.y + annotation.height, - annotation.x, - annotation.y + annotation.height, - annotation.x, - annotation.y, - ]); - addColorAndWidth(annotation); - continue; - } - - if (isPolygonAnnotation(annotation)) { - newPoints.push(annotation.vertices.flatMap(identity)); - addColorAndWidth(annotation); - } - } - - annotations.setStyle({ - color: Array.from(newColors.values()) - .sort((a, b) => (a.idx > b.idx ? 1 : -1)) - .map(({ color }) => color), - }); - annotations.setPoints( - newPoints.length === 1 ? newPoints.flat() : newPoints, - { - colorIndices: newColorIndices, - widths: newWidths, - }, - ); - - pubSub.subscribe('draw', resolve, 1); - isAnnotationsDrawn = true; - draw = true; - }); - }; - - /** @type {(f: F) => (...args: Parameters) => Promise>} */ - const withDraw = - (f) => - (...args) => { - const out = f(...args); - draw = true; - return new Promise((resolve) => { - pubSub.subscribe('draw', () => resolve(out), 1); - }); - }; - - /** - * Get the bounding box of a set of points. - * @param {number[]} pointIdxs - A list of point indices - * @returns {import('./types').Rect} The bounding box - */ - const getBBoxOfPoints = (pointIdxs) => { - let xMin = Number.POSITIVE_INFINITY; - let xMax = Number.NEGATIVE_INFINITY; - let yMin = Number.POSITIVE_INFINITY; - let yMax = Number.NEGATIVE_INFINITY; - - for (const pointIdx of pointIdxs) { - const [x, y] = points[pointIdx]; - xMin = Math.min(xMin, x); - xMax = Math.max(xMax, x); - yMin = Math.min(yMin, y); - yMax = Math.max(yMax, y); - } - - return { x: xMin, y: yMin, width: xMax - xMin, height: yMax - yMin }; - }; - - /** - * Zoom to an area specified as a rectangle - * @param {import('./types').Rect} rect - The rectangle to zoom to in normalized device coordinates - * @param {import('./types').ScatterplotMethodOptions['zoomToArea']} options - * @returns {Promise} - */ - const zoomToArea = (rect, options = {}) => - new Promise((resolve) => { - const target = vec4 - .transformMat4( - [], - [rect.x + rect.width / 2, rect.y + rect.height / 2, 0, 0], - model, - ) - .slice(0, 2); - - // Vertical field of view - // The Arc Tangent is based on the original camera position. Otherwise - // we would have to do `Math.atan(1 / camera.view[5])` - const vFOV = 2 * Math.atan(1); - - const aspectRatio = viewAspectRatio / dataAspectRatio; - - const distance = - rect.height * aspectRatio >= rect.width - ? // Distance is based on the height of the bounding box - rect.height / 2 / Math.tan(vFOV / 2) - : // Distance is based on the width of the bounding box - rect.width / 2 / Math.tan(vFOV / 2) / aspectRatio; - - if (options.transition) { - camera.config({ isFixed: true }); - cacheCamera(target, distance); - pubSub.subscribe( - 'transitionEnd', - () => { - resolve(); - camera.config({ isFixed: cameraIsFixed }); - }, - 1, - ); - startTransition({ - duration: options.transitionDuration, - easing: options.transitionEasing, - }); - } else { - camera.lookAt(target, distance); - pubSub.subscribe('draw', resolve, 1); - draw = true; - } - }); - - /** - * Zoom to a set of points - * @param {number[]} pointIdxs - A list of point indices - * @param {import('./types').ScatterplotMethodOptions['zoomToPoints']} options - * @returns {Promise} - */ - const zoomToPoints = (pointIdxs, options = {}) => { - if (!isPointsDrawn) { - return Promise.reject(new Error(ERROR_POINTS_NOT_DRAWN)); - } - const rect = getBBoxOfPoints(pointIdxs); - const cX = rect.x + rect.width / 2; - const cY = rect.y + rect.height / 2; - - const pointSizeNdc = getPointSizeNdc(); - const scale = 1 + (options.padding || 0); - - const w = Math.max(rect.width, pointSizeNdc) * scale; - const h = Math.max(rect.height, pointSizeNdc) * scale; - const x = cX - w / 2; - const y = cY - h / 2; - - return zoomToArea({ x, y, width: w, height: h }, options); - }; - - /** - * Zoom to a location specified in normalized devide coordinates. - * @param {number[]} target - The camera target given in normalized device coordinates - * @param {number} distance - The camera distance - * @param {import('./types').ScatterplotMethodOptions['zoomToLocation']} options - * @returns {Promise} - */ - const zoomToLocation = (target, distance, options = {}) => - new Promise((resolve) => { - if (options.transition) { - camera.config({ isFixed: true }); - cacheCamera(target, distance); - pubSub.subscribe( - 'transitionEnd', - () => { - resolve(); - camera.config({ isFixed: cameraIsFixed }); - }, - 1, - ); - startTransition({ - duration: options.transitionDuration, - easing: options.transitionEasing, - }); - } else { - camera.lookAt(target, distance); - pubSub.subscribe('draw', resolve, 1); - draw = true; - } - }); - - /** - * Zoom to the origin - * @param {import('./types').ScatterplotMethodOptions['zoomToLocation']} options - * @returns {Promise} - */ - const zoomToOrigin = (options = {}) => zoomToLocation([0, 0], 1, options); - - /** - * Get the screen position of a point - * @param {number} pointIdx - Point index - * @returns {[number, number] | undefined} - */ - const getScreenPosition = (pointIdx) => { - if (!isPointsDrawn) { - throw new Error(ERROR_POINTS_NOT_DRAWN); - } - - const point = points[pointIdx]; - - if (!point) { - return undefined; - } - - // Homogeneous coordinates of the point - const v = [point[0], point[1], 0, 1]; - - // Convert to clip space - mat4.multiply( - scratch, - projectionLocal, - mat4.multiply(scratch, camera.view, model), - ); - - vec4.transformMat4(v, v, scratch); - - // Finally, we convert to the screen space - const x = (currentWidth * (v[0] + 1)) / 2; - const y = currentHeight * (0.5 - v[1] / 2); - - return [x, y]; - }; - - const updatePointConnectionStyle = () => { - pointConnections.setStyle({ - color: getColors( - pointConnectionColor, - pointConnectionColorActive, - pointConnectionColorHover, - ), - opacity: - pointConnectionOpacity === null ? null : pointConnectionOpacity[0], - width: pointConnectionSize[0], - }); - }; - - const updateLassoInitiatorStyle = () => { - const v = Math.round(backgroundColorBrightness) > 0.5 ? 0 : 255; - lassoManager.initiator.style.border = `1px dashed rgba(${v}, ${v}, ${v}, 0.33)`; - lassoManager.initiator.style.background = `rgba(${v}, ${v}, ${v}, 0.1)`; - }; - - const updateLassoLongPressIndicatorStyle = () => { - const v = Math.round(backgroundColorBrightness) > 0.5 ? 0 : 255; - - lassoManager.longPressIndicator.style.color = `rgb(${v}, ${v}, ${v})`; - lassoManager.longPressIndicator.dataset.color = `rgb(${v}, ${v}, ${v})`; - - const rgb = lassoColor.map((c) => Math.round(c * 255)); - lassoManager.longPressIndicator.dataset.activeColor = `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`; - }; - - const setBackgroundColor = (newBackgroundColor) => { - if (!newBackgroundColor) { - return; - } - - backgroundColor = toRgba(newBackgroundColor, true); - backgroundColorBrightness = rgbBrightness(backgroundColor); - updateLassoInitiatorStyle(); - updateLassoLongPressIndicatorStyle(); - }; - - const setBackgroundImage = (newBackgroundImage) => { - if (!newBackgroundImage) { - backgroundImage = null; - } else if (isString(newBackgroundImage)) { - createTextureFromUrl(renderer.regl, newBackgroundImage) - .then((texture) => { - backgroundImage = texture; - draw = true; - pubSub.publish('backgroundImageReady'); - }) - .catch(() => { - // biome-ignore lint/suspicious/noConsole: This is a legitimately useful error log - console.error(`Count not create texture from ${newBackgroundImage}`); - backgroundImage = null; - }); - } else if (newBackgroundImage._reglType === 'texture2d') { - backgroundImage = newBackgroundImage; - } else { - backgroundImage = null; - } - }; - - const setCameraDistance = (distance) => { - if (distance > 0) { - camera.lookAt(camera.target, distance, camera.rotation); - } - }; - - const setCameraRotation = (rotation) => { - if (rotation !== null) { - camera.lookAt(camera.target, camera.distance[0], rotation); - } - }; - - const setCameraTarget = (target) => { - if (target) { - camera.lookAt(target, camera.distance[0], camera.rotation); - } - }; - - const setCameraView = (view) => { - if (view) { - camera.setView(view); - } - }; - - const setCameraIsFixed = (isFixed) => { - cameraIsFixed = Boolean(isFixed); - camera.config({ isFixed: cameraIsFixed }); - }; - - const setLassoColor = (newLassoColor) => { - if (!newLassoColor) { - return; - } - - lassoColor = toRgba(newLassoColor, true); - - lasso.setStyle({ color: lassoColor }); - - const rgb = lassoColor.map((c) => Math.round(c * 255)); - lassoManager.longPressIndicator.dataset.activeColor = `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`; - }; - - const setLassoLineWidth = (newLassoLineWidth) => { - if (Number.isNaN(+newLassoLineWidth) || +newLassoLineWidth < 1) { - return; - } - - lassoLineWidth = +newLassoLineWidth; - - lasso.setStyle({ width: lassoLineWidth }); - }; - - const setLassoMinDelay = (newLassoMinDelay) => { - if (!+newLassoMinDelay) { - return; - } - - lassoMinDelay = +newLassoMinDelay; - - lassoManager.set({ - minDelay: lassoMinDelay, - }); - }; - - const setLassoMinDist = (newLassoMinDist) => { - if (!+newLassoMinDist) { - return; - } - - lassoMinDist = +newLassoMinDist; - - lassoManager.set({ - minDist: lassoMinDist, - }); - }; - - const setLassoClearEvent = (newLassoClearEvent) => { - lassoClearEvent = limit( - LASSO_CLEAR_EVENTS, - lassoClearEvent, - )(newLassoClearEvent); - }; - - const setLassoInitiator = (newLassoInitiator) => { - lassoInitiator = Boolean(newLassoInitiator); - - lassoManager.set({ - enableInitiator: lassoInitiator, - }); - }; - - const setLassoInitiatorParentElement = (newLassoInitiatorParentElement) => { - lassoInitiatorParentElement = newLassoInitiatorParentElement; - - lassoManager.set({ - initiatorParentElement: lassoInitiatorParentElement, - }); - }; - - const setLassoLongPressIndicatorParentElement = (newParentElement) => { - lassoLongPressIndicatorParentElement = newParentElement; - - lassoManager.set({ - longPressIndicatorParentElement: lassoLongPressIndicatorParentElement, - }); - }; - - const setLassoOnLongPress = (newLassoOnLongPress) => { - lassoOnLongPress = Boolean(newLassoOnLongPress); - }; - - const setLassoLongPressTime = (newLassoOnLongPressTime) => { - lassoLongPressTime = Number(newLassoOnLongPressTime); - }; - - const setLassoLongPressAfterEffectTime = (newTime) => { - lassoLongPressAfterEffectTime = Number(newTime); - }; - - const setLassoLongPressEffectDelay = (newDelay) => { - lassoLongPressEffectDelay = Number(newDelay); - }; - - const setLassoLongPressRevertEffectTime = (newTime) => { - lassoLongPressRevertEffectTime = Number(newTime); - }; - - const setLassoType = (newType) => { - if (newType === 'brush') { - lassoManager.set({ - type: newType, - minDist: Math.max(LASSO_BRUSH_MIN_MIN_DIST, lassoMinDist), - }); - } else { - lassoManager.set({ - type: newType, - minDist: lassoMinDist, - }); - } - lassoType = lassoManager.get('type'); - }; - - const setLassoBrushSize = (newBrushSize) => { - lassoBrushSize = Number(newBrushSize) || lassoBrushSize; - lassoManager.set({ brushSize: lassoBrushSize }); - }; - - const updateActionKeyMapChange = () => { - if (actionKeyMap[KEY_ACTION_ROTATE]) { - camera.config({ - isRotate: true, - mouseDownMoveModKey: actionKeyMap[KEY_ACTION_ROTATE], - }); - } else { - camera.config({ - isRotate: false, - }); - } - }; - - const setActionKeyMap = (newActionKeyMap) => { - actionKeyMap = Object.entries(newActionKeyMap).reduce( - (map, [action, key]) => { - if (KEYS.includes(key) && KEY_ACTIONS.includes(action)) { - map[action] = key; - } - return map; - }, - {}, - ); - - updateActionKeyMapChange(); - }; - - const setMouseMode = (newMouseMode) => { - mouseMode = limit(MOUSE_MODES, MOUSE_MODE_PANZOOM)(newMouseMode); - - camera.config({ - defaultMouseDownMoveAction: - mouseMode === MOUSE_MODE_ROTATE ? 'rotate' : 'pan', - }); - }; - - const setShowReticle = (newShowReticle) => { - if (newShowReticle === null) { - return; - } - - showReticle = newShowReticle; - }; - - const setReticleColor = (newReticleColor) => { - if (!newReticleColor) { - return; - } - - reticleColor = toRgba(newReticleColor, true); - - reticleHLine.setStyle({ color: reticleColor }); - reticleVLine.setStyle({ color: reticleColor }); - }; - - const setXScale = (newXScale) => { - if (!newXScale) { - return; - } - - xScale = newXScale; - xDomainStart = newXScale.domain()[0]; - xDomainSize = newXScale ? newXScale.domain()[1] - newXScale.domain()[0] : 0; - xScale.range([0, currentWidth]); - updateScales(); - }; - - const setYScale = (newYScale) => { - if (!newYScale) { - return; - } - - yScale = newYScale; - yDomainStart = yScale.domain()[0]; - yDomainSize = yScale ? yScale.domain()[1] - yScale.domain()[0] : 0; - yScale.range([currentHeight, 0]); - updateScales(); - }; - - const setDeselectOnDblClick = (newDeselectOnDblClick) => { - deselectOnDblClick = !!newDeselectOnDblClick; - }; - - const setDeselectOnEscape = (newDeselectOnEscape) => { - deselectOnEscape = !!newDeselectOnEscape; - }; - - const setShowPointConnections = (newShowPointConnections) => { - showPointConnections = !!newShowPointConnections; - if (showPointConnections) { - if (isPointsDrawn && hasPointConnections(points[0])) { - setPointConnections(getPoints()).then(() => { - pubSub.publish('pointConnectionsDraw'); - draw = true; - }); - } - } else { - setPointConnections(); - } - }; - - const setPointConnectionColors = (setter, getInheritance) => (newColors) => { - if (newColors === 'inherit') { - setter([...getInheritance()]); - } else { - const tmpColors = isMultipleColors(newColors) ? newColors : [newColors]; - setter(tmpColors.map((color) => toRgba(color, true))); - } - updatePointConnectionStyle(); - }; - - const setPointConnectionColor = setPointConnectionColors( - (newColors) => { - pointConnectionColor = newColors; - }, - () => pointColor, - ); - - const setPointConnectionColorActive = setPointConnectionColors( - (newColors) => { - pointConnectionColorActive = newColors; - }, - () => pointColorActive, - ); - - const setPointConnectionColorHover = setPointConnectionColors( - (newColors) => { - pointConnectionColorHover = newColors; - }, - () => pointColorHover, - ); - - const setPointConnectionOpacity = (newOpacity) => { - if (isConditionalArray(newOpacity, isPositiveNumber, { minLength: 1 })) { - pointConnectionOpacity = [...newOpacity]; - } - - if (isStrictlyPositiveNumber(+newOpacity)) { - pointConnectionOpacity = [+newOpacity]; - } - - pointConnectionColor = pointConnectionColor.map((color) => { - color[3] = Number.isNaN(+pointConnectionOpacity[0]) - ? color[3] - : +pointConnectionOpacity[0]; - return color; - }); - - updatePointConnectionStyle(); - }; - - const setPointConnectionOpacityActive = (newOpacity) => { - if (!Number.isNaN(+newOpacity) && +newOpacity) { - pointConnectionOpacityActive = +newOpacity; - } - }; - - const setPointConnectionSize = (newPointConnectionSize) => { - if ( - isConditionalArray(newPointConnectionSize, isPositiveNumber, { - minLength: 1, - }) - ) { - pointConnectionSize = [...newPointConnectionSize]; - } - - if (isStrictlyPositiveNumber(+newPointConnectionSize)) { - pointConnectionSize = [+newPointConnectionSize]; - } - - updatePointConnectionStyle(); - }; - - const setPointConnectionSizeActive = (newPointConnectionSizeActive) => { - if ( - !Number.isNaN(+newPointConnectionSizeActive) && - +newPointConnectionSizeActive - ) { - pointConnectionSizeActive = Math.max(0, newPointConnectionSizeActive); - } - }; - - const setPointConnectionMaxIntPointsPerSegment = ( - newPointConnectionMaxIntPointsPerSegment, - ) => { - pointConnectionMaxIntPointsPerSegment = Math.max( - 0, - newPointConnectionMaxIntPointsPerSegment, - ); - }; - - const setPointConnectionTolerance = (newPointConnectionTolerance) => { - pointConnectionTolerance = Math.max(0, newPointConnectionTolerance); - }; - - const setPointSizeMouseDetection = (newPointSizeMouseDetection) => { - pointSizeMouseDetection = newPointSizeMouseDetection; - computePointSizeMouseDetection(); - }; - - const setPointScaleMode = (newPointScaleMode) => { - switch (newPointScaleMode) { - case 'linear': { - pointScaleMode = newPointScaleMode; - getPointScale = getLinearPointScale; - break; - } - case 'constant': { - pointScaleMode = newPointScaleMode; - getPointScale = getConstantPointScale; - break; - } - default: { - pointScaleMode = 'asinh'; - getPointScale = getAsinhPointScale; - break; - } - } - }; - - const setOpacityByDensityFill = (newOpacityByDensityFill) => { - opacityByDensityFill = +newOpacityByDensityFill; - }; - - const setOpacityInactiveMax = (newOpacityInactiveMax) => { - opacityInactiveMax = +newOpacityInactiveMax; - }; - - const setOpacityInactiveScale = (newOpacityInactiveScale) => { - opacityInactiveScale = +newOpacityInactiveScale; - }; - - const setAnnotationLineColor = (newAnnotationLineColor) => { - annotationLineColor = toRgba(newAnnotationLineColor); - }; - - const setAnnotationLineWidth = (newAnnotationLineWidth) => { - annotationLineWidth = +newAnnotationLineWidth; - }; - - const setAnnotationHVLineLimit = (newAnnotationHVLineLimit) => { - annotationHVLineLimit = +newAnnotationHVLineLimit; - }; - - const setGamma = (newGamma) => { - renderer.gamma = newGamma; - }; - - const setAntiAliasing = (newAntiAliasing) => { - antiAliasing = Number(newAntiAliasing) || 0.5; - }; - - const setPixelAligned = (newPixelAligned) => { - pixelAligned = Boolean(newPixelAligned); - }; - - /** @type {(property: Key) => import('./types').Properties[Key] } */ - const get = (prop) => { - const [property] = Object.keys( - checkDeprecations({ - [prop]: SKIP_DEPRECATION_VALUE_TRANSLATION, - }), - ); - - if (property === 'aspectRatio') { - return dataAspectRatio; - } - - if (property === 'background') { - return backgroundColor; - } - - if (property === 'backgroundColor') { - return backgroundColor; - } - - if (property === 'backgroundImage') { - return backgroundImage; - } - - if (property === 'camera') { - return camera; - } - - if (property === 'cameraTarget') { - return camera.target; - } - - if (property === 'cameraDistance') { - return camera.distance[0]; - } - - if (property === 'cameraRotation') { - return camera.rotation; - } - - if (property === 'cameraView') { - return camera.view; - } - - if (property === 'cameraIsFixed') { - return cameraIsFixed; - } - - if (property === 'canvas') { - return canvas; - } - - if (property === 'colorBy') { - return colorBy; - } - - if (property === 'sizeBy') { - return sizeBy; - } - - if (property === 'pointOrder') { - return pointOrder !== null ? [...pointOrder] : null; - } - - if (property === 'deselectOnDblClick') { - return deselectOnDblClick; - } - - if (property === 'deselectOnEscape') { - return deselectOnEscape; - } - - if (property === 'height') { - return height; - } - - if (property === 'lassoColor') { - return lassoColor; - } - - if (property === 'lassoLineWidth') { - return lassoLineWidth; - } - - if (property === 'lassoMinDelay') { - return lassoMinDelay; - } - - if (property === 'lassoMinDist') { - return lassoMinDist; - } - - if (property === 'lassoClearEvent') { - return lassoClearEvent; - } - - if (property === 'lassoInitiator') { - return lassoInitiator; - } - - if (property === 'lassoInitiatorElement') { - return lassoManager.initiator; - } - - if (property === 'lassoInitiatorParentElement') { - return lassoInitiatorParentElement; - } - - if (property === 'lassoLongPressIndicatorParentElement') { - return lassoLongPressIndicatorParentElement; - } - - if (property === 'lassoOnLongPress') { - return lassoOnLongPress; - } - - if (property === 'lassoType') { - return lassoType; - } - - if (property === 'lassoBrushSize') { - return lassoBrushSize; - } - - if (property === 'mouseMode') { - return mouseMode; - } - - if (property === 'opacity') { - return opacity.length === 1 ? opacity[0] : opacity; - } - - if (property === 'opacityBy') { - return opacityBy; - } - - if (property === 'opacityByDensityFill') { - return opacityByDensityFill; - } - - if (property === 'opacityByDensityDebounceTime') { - return opacityByDensityDebounceTime; - } - - if (property === 'opacityInactiveMax') { - return opacityInactiveMax; - } - - if (property === 'opacityInactiveScale') { - return opacityInactiveScale; - } - - if (property === 'points') { - return points; - } - - if (property === 'hoveredPoint') { - return hoveredPoint; - } - - if (property === 'selectedPoints') { - return [...selectedPoints]; - } - - if (property === 'filteredPoints') { - return isPointsFiltered - ? Array.from(filteredPointsSet) - : Array.from({ length: points.length }, (_, i) => i); - } - - if (property === 'pointsInView') { - return getPointsInView(); - } - - if (property === 'pointColor') { - return pointColor.length === 1 ? pointColor[0] : pointColor; - } - - if (property === 'pointColorActive') { - return pointColorActive.length === 1 - ? pointColorActive[0] - : pointColorActive; - } - - if (property === 'pointColorHover') { - return pointColorHover.length === 1 - ? pointColorHover[0] - : pointColorHover; - } - - if (property === 'pointOutlineWidth') { - return pointOutlineWidth; - } - - if (property === 'pointSize') { - return pointSize.length === 1 ? pointSize[0] : pointSize; - } - - if (property === 'pointSizeSelected') { - return pointSizeSelected; - } - - if (property === 'pointSizeMouseDetection') { - return pointSizeMouseDetection; - } - - if (property === 'showPointConnections') { - return showPointConnections; - } - - if (property === 'pointConnectionColor') { - return pointConnectionColor.length === 1 - ? pointConnectionColor[0] - : pointConnectionColor; - } - - if (property === 'pointConnectionColorActive') { - return pointConnectionColorActive.length === 1 - ? pointConnectionColorActive[0] - : pointConnectionColorActive; - } - - if (property === 'pointConnectionColorHover') { - return pointConnectionColorHover.length === 1 - ? pointConnectionColorHover[0] - : pointConnectionColorHover; - } - - if (property === 'pointConnectionColorBy') { - return pointConnectionColorBy; - } - - if (property === 'pointConnectionOpacity') { - return pointConnectionOpacity.length === 1 - ? pointConnectionOpacity[0] - : pointConnectionOpacity; - } - - if (property === 'pointConnectionOpacityBy') { - return pointConnectionOpacityBy; - } - - if (property === 'pointConnectionOpacityActive') { - return pointConnectionOpacityActive; - } - - if (property === 'pointConnectionSize') { - return pointConnectionSize.length === 1 - ? pointConnectionSize[0] - : pointConnectionSize; - } - - if (property === 'pointConnectionSizeActive') { - return pointConnectionSizeActive; - } - - if (property === 'pointConnectionSizeBy') { - return pointConnectionSizeBy; - } - - if (property === 'pointConnectionMaxIntPointsPerSegment') { - return pointConnectionMaxIntPointsPerSegment; - } - - if (property === 'pointConnectionTolerance') { - return pointConnectionTolerance; - } - - if (property === 'pointScaleMode') { - return pointScaleMode; - } - - if (property === 'reticleColor') { - return reticleColor; - } - - if (property === 'regl') { - return renderer.regl; - } - - if (property === 'showReticle') { - return showReticle; - } - - if (property === 'version') { - return version; - } - - if (property === 'width') { - return width; - } - - if (property === 'xScale') { - return xScale; - } - - if (property === 'yScale') { - return yScale; - } - - if (property === 'performanceMode') { - return performanceMode; - } - - if (property === 'renderPointsAsSquares') { - return renderPointsAsSquares; - } - - if (property === 'disableAlphaBlending') { - return disableAlphaBlending; - } - - if (property === 'gamma') { - return renderer.gamma; - } - - if (property === 'renderer') { - return renderer; - } - - if (property === 'isDestroyed') { - return isDestroyed; - } - - if (property === 'isDrawing') { - return isDrawing; - } - - if (property === 'isPointsDrawn') { - return isPointsDrawn; - } - - if (property === 'isPointsFiltered') { - return isPointsFiltered; - } - - if (property === 'isAnnotationsDrawn') { - return isAnnotationsDrawn; - } - - if (property === 'zDataType') { - return valueZDataType; - } - - if (property === 'wDataType') { - return valueWDataType; - } - - if (property === 'spatialIndex') { - return spatialIndex?.data; - } - - if (property === 'annotationLineColor') { - return annotationLineColor; - } - - if (property === 'annotationLineWidth') { - return annotationLineWidth; - } - - if (property === 'annotationHVLineLimit') { - return annotationHVLineLimit; - } - - if (property === 'antiAliasing') { - return antiAliasing; - } - - if (property === 'pixelAligned') { - return pixelAligned; - } - - if (property === 'actionKeyMap') { - return { ...actionKeyMap }; - } - - return undefined; - }; - - /** @type {(properties: Partial) => Promise} */ - const set = (properties = {}) => { - if (isDestroyed) { - return Promise.reject(new Error(ERROR_INSTANCE_IS_DESTROYED)); - } - - checkDeprecations(properties); - - if ( - properties.backgroundColor !== undefined || - properties.background !== undefined - ) { - setBackgroundColor(properties.backgroundColor || properties.background); - } - - if (properties.backgroundImage !== undefined) { - setBackgroundImage(properties.backgroundImage); - } - - if (properties.cameraTarget !== undefined) { - setCameraTarget(properties.cameraTarget); - } - - if (properties.cameraDistance !== undefined) { - setCameraDistance(properties.cameraDistance); - } - - if (properties.cameraRotation !== undefined) { - setCameraRotation(properties.cameraRotation); - } - - if (properties.cameraView !== undefined) { - setCameraView(properties.cameraView); - } - - if (properties.cameraIsFixed !== undefined) { - setCameraIsFixed(properties.cameraIsFixed); - } - - if (properties.colorBy !== undefined) { - setColorBy(properties.colorBy); - } - - if (properties.pointColor !== undefined) { - setPointColor(properties.pointColor); - } - - if (properties.pointColorActive !== undefined) { - setPointColorActive(properties.pointColorActive); - } - - if (properties.pointColorHover !== undefined) { - setPointColorHover(properties.pointColorHover); - } - - if (properties.pointSize !== undefined) { - setPointSize(properties.pointSize); - } - - if (properties.pointSizeSelected !== undefined) { - setPointSizeSelected(properties.pointSizeSelected); - } - - if (properties.pointSizeMouseDetection !== undefined) { - setPointSizeMouseDetection(properties.pointSizeMouseDetection); - } - - if (properties.sizeBy !== undefined) { - setSizeBy(properties.sizeBy); - } - - if (properties.pointOrder !== undefined) { - setPointOrder(properties.pointOrder); - } - - if (properties.opacity !== undefined) { - setOpacity(properties.opacity); - } - - if (properties.showPointConnections !== undefined) { - setShowPointConnections(properties.showPointConnections); - } - - if (properties.pointConnectionColor !== undefined) { - setPointConnectionColor(properties.pointConnectionColor); - } - - if (properties.pointConnectionColorActive !== undefined) { - setPointConnectionColorActive(properties.pointConnectionColorActive); - } - - if (properties.pointConnectionColorHover !== undefined) { - setPointConnectionColorHover(properties.pointConnectionColorHover); - } - - if (properties.pointConnectionColorBy !== undefined) { - setPointConnectionColorBy(properties.pointConnectionColorBy); - } - - if (properties.pointConnectionOpacityBy !== undefined) { - setPointConnectionOpacityBy(properties.pointConnectionOpacityBy); - } - - if (properties.pointConnectionOpacity !== undefined) { - setPointConnectionOpacity(properties.pointConnectionOpacity); - } - - if (properties.pointConnectionOpacityActive !== undefined) { - setPointConnectionOpacityActive(properties.pointConnectionOpacityActive); - } - - if (properties.pointConnectionSize !== undefined) { - setPointConnectionSize(properties.pointConnectionSize); - } - - if (properties.pointConnectionSizeActive !== undefined) { - setPointConnectionSizeActive(properties.pointConnectionSizeActive); - } - - if (properties.pointConnectionSizeBy !== undefined) { - setPointConnectionSizeBy(properties.pointConnectionSizeBy); - } - - if (properties.pointConnectionMaxIntPointsPerSegment !== undefined) { - setPointConnectionMaxIntPointsPerSegment( - properties.pointConnectionMaxIntPointsPerSegment, - ); - } - - if (properties.pointConnectionTolerance !== undefined) { - setPointConnectionTolerance(properties.pointConnectionTolerance); - } - - if (properties.pointScaleMode !== undefined) { - setPointScaleMode(properties.pointScaleMode); - } - - if (properties.opacityBy !== undefined) { - setOpacityBy(properties.opacityBy); - } - - if (properties.lassoColor !== undefined) { - setLassoColor(properties.lassoColor); - } - - if (properties.lassoLineWidth !== undefined) { - setLassoLineWidth(properties.lassoLineWidth); - } - - if (properties.lassoMinDelay !== undefined) { - setLassoMinDelay(properties.lassoMinDelay); - } - - if (properties.lassoMinDist !== undefined) { - setLassoMinDist(properties.lassoMinDist); - } - - if (properties.lassoClearEvent !== undefined) { - setLassoClearEvent(properties.lassoClearEvent); - } - - if (properties.lassoInitiator !== undefined) { - setLassoInitiator(properties.lassoInitiator); - } - - if (properties.lassoInitiatorParentElement !== undefined) { - setLassoInitiatorParentElement(properties.lassoInitiatorParentElement); - } - - if (properties.lassoLongPressIndicatorParentElement !== undefined) { - setLassoLongPressIndicatorParentElement( - properties.lassoLongPressIndicatorParentElement, - ); - } - - if (properties.lassoOnLongPress !== undefined) { - setLassoOnLongPress(properties.lassoOnLongPress); - } - - if (properties.lassoLongPressTime !== undefined) { - setLassoLongPressTime(properties.lassoLongPressTime); - } - - if (properties.lassoLongPressAfterEffectTime !== undefined) { - setLassoLongPressAfterEffectTime( - properties.lassoLongPressAfterEffectTime, - ); - } - - if (properties.lassoLongPressEffectDelay !== undefined) { - setLassoLongPressEffectDelay(properties.lassoLongPressEffectDelay); - } - - if (properties.lassoLongPressRevertEffectTime !== undefined) { - setLassoLongPressRevertEffectTime( - properties.lassoLongPressRevertEffectTime, - ); - } - - if (properties.lassoType !== undefined) { - setLassoType(properties.lassoType); - } - - if (properties.lassoBrushSize !== undefined) { - setLassoBrushSize(properties.lassoBrushSize); - } - - if (properties.actionKeyMap !== undefined) { - setActionKeyMap(properties.actionKeyMap); - } - - if (properties.mouseMode !== undefined) { - setMouseMode(properties.mouseMode); - } - - if (properties.showReticle !== undefined) { - setShowReticle(properties.showReticle); - } - - if (properties.reticleColor !== undefined) { - setReticleColor(properties.reticleColor); - } - - if (properties.pointOutlineWidth !== undefined) { - setPointOutlineWidth(properties.pointOutlineWidth); - } - - if (properties.height !== undefined) { - setHeight(properties.height); - } - - if (properties.width !== undefined) { - setWidth(properties.width); - } - - if (properties.aspectRatio !== undefined) { - setDataAspectRatio(properties.aspectRatio); - } - - if (properties.xScale !== undefined) { - setXScale(properties.xScale); - } - - if (properties.yScale !== undefined) { - setYScale(properties.yScale); - } - - if (properties.deselectOnDblClick !== undefined) { - setDeselectOnDblClick(properties.deselectOnDblClick); - } - - if (properties.deselectOnEscape !== undefined) { - setDeselectOnEscape(properties.deselectOnEscape); - } - - if (properties.opacityByDensityFill !== undefined) { - setOpacityByDensityFill(properties.opacityByDensityFill); - } - - if (properties.opacityInactiveMax !== undefined) { - setOpacityInactiveMax(properties.opacityInactiveMax); - } - - if (properties.opacityInactiveScale !== undefined) { - setOpacityInactiveScale(properties.opacityInactiveScale); - } - - if (properties.gamma !== undefined) { - setGamma(properties.gamma); - } - - if (properties.annotationLineColor !== undefined) { - setAnnotationLineColor(properties.annotationLineColor); - } - - if (properties.annotationLineWidth !== undefined) { - setAnnotationLineWidth(properties.annotationLineWidth); - } - - if (properties.annotationHVLineLimit !== undefined) { - setAnnotationHVLineLimit(properties.annotationHVLineLimit); - } - - if (properties.antiAliasing !== undefined) { - setAntiAliasing(properties.antiAliasing); - } - - if (properties.pixelAligned !== undefined) { - setPixelAligned(properties.pixelAligned); - } - - // setWidth and setHeight can be async when width or height are set to - // 'auto'. And since draw() would have anyway been async we can just make - // all calls async. - return new Promise((resolve) => { - window.requestAnimationFrame(() => { - if (isDestroyed || !canvas) { - // Instance was destroyed in between - return; - } - updateViewAspectRatio(); - camera.refresh(); - renderer.refresh(); - redraw(); - resolve(); - }); - }); - }; - - /** - * @param {number[]} cameraView - * @param {import('./types').ScatterplotMethodOptions['preventEvent']} options - */ - const view = (cameraView, { preventEvent = false } = {}) => { - setCameraView(cameraView); - draw = true; - preventEventView = preventEvent; - }; - - const initCamera = () => { - if (!camera) { - camera = createDom2dCamera(canvas, { - isFixed: cameraIsFixed, - isPanInverted: [false, true], - defaultMouseDownMoveAction: - mouseMode === MOUSE_MODE_ROTATE ? 'rotate' : 'pan', - }); - } - - if (initialProperties.cameraView) { - camera.setView(mat4.clone(initialProperties.cameraView)); - } else if ( - initialProperties.cameraTarget || - initialProperties.cameraDistance || - initialProperties.cameraRotation - ) { - camera.lookAt( - [...(initialProperties.cameraTarget || DEFAULT_TARGET)], - initialProperties.cameraDistance || DEFAULT_DISTANCE, - initialProperties.cameraRotation || DEFAULT_ROTATION, - ); - } else { - camera.setView(mat4.clone(DEFAULT_VIEW)); - } - - topRightNdc = getScatterGlPos(1, 1); - bottomLeftNdc = getScatterGlPos(-1, -1); - }; - - /** - * @param {import('./types').ScatterplotMethodOptions['preventEvent']} options - */ - const reset = ({ preventEvent = false } = {}) => { - initCamera(); - updateScales(); - - if (preventEvent) { - return; - } - - pubSub.publish('view', { - view: camera.view, - camera, - xScale, - yScale, - }); - }; - - const keyUpHandler = ({ key }) => { - switch (key) { - case 'Escape': { - if (deselectOnEscape) { - deselect(); - } - break; - } - default: - // Nothing - } - }; - - const mouseEnterCanvasHandler = () => { - isMouseInCanvas = true; - isMouseOverCanvasChecked = true; - }; - - const mouseLeaveCanvasHandler = () => { - hover(); - isMouseInCanvas = false; - isMouseOverCanvasChecked = true; - draw = true; - }; - - const wheelHandler = () => { - draw = true; - }; - - /** @type {() => void} */ - const clearPoints = () => { - setPoints([]); - pointConnections.clear(); - }; - - /** @type {() => void} */ - const clearPointConnections = () => { - pointConnections.clear(); - }; - - /** @type {() => void} */ - const clearAnnotations = () => { - drawAnnotations([]); - }; - - /** @type {() => void} */ - const clear = () => { - clearPoints(); - clearAnnotations(); - }; - - const resizeHandler = () => { - const autoWidth = width === AUTO; - const autoHeight = height === AUTO; - if (autoWidth || autoHeight) { - const { width: newWidth, height: newHeight } = - canvas.getBoundingClientRect(); - - if (autoWidth) { - setCurrentWidth(newWidth, true); - } - - if (autoHeight) { - setCurrentHeight(newHeight, true); - } - - updateViewAspectRatio(); - updateScales(); - draw = true; - } - camera.refresh(); - }; - - /** - * Export view as `ImageData` using custom render settings - * @param {import('./types').ScatterplotMethodOptions['export']} options - * @returns {Promise} - */ - const exportFnAdvanced = async (options) => { - canvas.style.userSelect = 'none'; - - const dpr = window.devicePixelRatio; - - const currPointSize = pointSize; - const currWidth = width; - const currHeight = height; - const currRendererWidth = renderer.canvas.width / dpr; - const currRendererHeight = renderer.canvas.height / dpr; - const currPixelAligned = pixelAligned; - const currAntiAliasing = antiAliasing; - - const scale = options?.scale || 1; - const newPointSize = Array.isArray(pointSize) - ? pointSize.map((s) => s * scale) - : pointSize * scale; - const newWidth = currentWidth * scale; - const newHeight = currentHeight * scale; - - setPointSize(newPointSize); - setWidth(newWidth); - setHeight(newHeight); - setPixelAligned(options?.pixelAligned || pixelAligned); - setAntiAliasing(options?.antiAliasing || antiAliasing); - - renderer.resize(width, height); - renderer.refresh(); - - await new Promise((resolve) => { - pubSub.subscribe('draw', resolve, 1); - redraw(); - }); - - const imageData = canvas - .getContext('2d') - .getImageData(0, 0, canvas.width, canvas.height); - - renderer.resize(currRendererWidth, currRendererHeight); - renderer.refresh(); - - setPointSize(currPointSize); - setWidth(currWidth); - setHeight(currHeight); - setPixelAligned(currPixelAligned); - setAntiAliasing(currAntiAliasing); - - await new Promise((resolve) => { - pubSub.subscribe('draw', resolve, 1); - redraw(); - }); - - canvas.style.userSelect = null; - - return imageData; - }; - - /** - * Export view as `ImageData` using the current render settings - * @overload - * @param {undefined} options - * @return {ImageData} - */ - /** - * Export view as `ImageData` using custom render settings - * @overload - * @param {import('./types').ScatterplotMethodOptions['export']} options - * @return {Promise} - */ - /** - * Export view - * @param {import('./types').ScatterplotMethodOptions['export']} [options] - * @returns {Promise} - */ - const exportFn = (options) => { - if (options === undefined) { - return canvas - .getContext('2d') - .getImageData(0, 0, canvas.width, canvas.height); - } - - return exportFnAdvanced(options); - }; - - const init = () => { - updateViewAspectRatio(); - initCamera(); - updateScales(); - - lasso = createLine(renderer.regl, { - color: lassoColor, - width: lassoLineWidth, - is2d: true, - }); - pointConnections = createLine(renderer.regl, { - color: getColors( - pointConnectionColor, - pointConnectionColorActive, - pointConnectionColorHover, - ), - opacity: - pointConnectionOpacity === null ? null : pointConnectionOpacity[0], - width: pointConnectionSize[0], - widthActive: pointConnectionSizeActive, - is2d: true, - }); - reticleHLine = createLine(renderer.regl, { - color: reticleColor, - width: 1, - is2d: true, - }); - reticleVLine = createLine(renderer.regl, { - color: reticleColor, - width: 1, - is2d: true, - }); - annotations = createLine(renderer.regl, { - color: annotationLineColor, - width: annotationLineWidth, - is2d: true, - }); - computePointSizeMouseDetection(); - - // Event listeners - canvas.addEventListener('wheel', wheelHandler); - - // Buffers - normalPointsIndexBuffer = renderer.regl.buffer(); - selectedPointsIndexBuffer = renderer.regl.buffer(); - hoveredPointIndexBuffer = renderer.regl.buffer({ - usage: 'dynamic', - type: 'float', - length: FLOAT_BYTES * 2, // This buffer is fixed to exactly 1 point consisting of 2 coordinates - }); - - colorTex = createColorTexture(); - encodingTex = createEncodingTexture(); - - // Set dimensions - const whenSet = set({ - backgroundImage, - width, - height, - actionKeyMap, - }); - updateLassoInitiatorStyle(); - updateLassoLongPressIndicatorStyle(); - - // Setup event handler - window.addEventListener('keyup', keyUpHandler, false); - window.addEventListener('blur', blurHandler, false); - window.addEventListener('mouseup', mouseUpHandler, false); - window.addEventListener('mousemove', mouseMoveHandler, false); - canvas.addEventListener('mousedown', mouseDownHandler, false); - canvas.addEventListener('mouseenter', mouseEnterCanvasHandler, false); - canvas.addEventListener('mouseleave', mouseLeaveCanvasHandler, false); - canvas.addEventListener('click', mouseClickHandler, false); - canvas.addEventListener('dblclick', mouseDblClickHandler, false); - - if ('ResizeObserver' in window) { - canvasObserver = new ResizeObserver(resizeHandler); - canvasObserver.observe(canvas); - } else { - window.addEventListener('resize', resizeHandler); - window.addEventListener('orientationchange', resizeHandler); - } - - whenSet.then(() => { - pubSub.publish('init'); - }); - }; - - const cancelFrameListener = renderer.onFrame(() => { - // Update camera: this needs to happen on every frame - isViewChanged = camera.tick(); - - if (!((isPointsDrawn || isAnnotationsDrawn) && (draw || isTransitioning))) { - return; - } - - if (isTransitioning && !tween(transitionDuration, transitionEasing)) { - endTransition(); - } - - if (isViewChanged) { - topRightNdc = getScatterGlPos(1, 1); - bottomLeftNdc = getScatterGlPos(-1, -1); - if (opacityBy === 'density') { - getNumPointsInViewDb(); - } - } - - renderer.render(() => { - const widthRatio = canvas.width / renderer.canvas.width; - const heightRatio = canvas.height / renderer.canvas.height; - - updateProjectionMatrix(widthRatio, heightRatio); - - if (backgroundImage?._reglType) { - drawBackgroundImage(); - } - - if (lassoPointsCurr.length > 2) { - drawLassoPolygon(); - } - - // The draw order of the following calls is important! - if (!isTransitioning) { - pointConnections.draw({ - projection: getProjection(), - model: getModel(), - view: getView(), - }); - } - - const numPoints = getNormalNumPoints(); - if (isPointsDrawn && numPoints > 0) { - drawPointBodies(); - } - - if (!mouseDown && (showReticle || drawReticleOnce)) { - drawReticle(); - } - - if (hoveredPoint >= 0) { - drawHoveredPoint(); - } - - if (selectedPoints.length > 0) { - drawSelectedPoints(); - } - - annotations.draw({ - projection: getProjection(), - model: getModel(), - view: getView(), - }); - - lasso.draw({ - projection: getProjection(), - model: getModel(), - view: getView(), - }); - }, canvas); - - const renderView = { - view: camera.view, - isViewChanged, - camera, - xScale, - yScale, - }; - - // Publish camera change - if (isViewChanged) { - updateScales(); - - if (preventEventView) { - preventEventView = false; - } else { - pubSub.publish('view', renderView); - } - } - - draw = false; - drawReticleOnce = false; - - pubSub.publish('drawing', renderView, { async: false }); - pubSub.publish('draw', renderView); - }); - - const redraw = () => { - draw = true; - }; - - const destroy = () => { - isPointsDrawn = false; - isAnnotationsDrawn = false; - isDestroyed = true; - cancelFrameListener(); - window.removeEventListener('keyup', keyUpHandler, false); - window.removeEventListener('blur', blurHandler, false); - window.removeEventListener('mouseup', mouseUpHandler, false); - window.removeEventListener('mousemove', mouseMoveHandler, false); - canvas.removeEventListener('mousedown', mouseDownHandler, false); - canvas.removeEventListener('mouseenter', mouseEnterCanvasHandler, false); - canvas.removeEventListener('mouseleave', mouseLeaveCanvasHandler, false); - canvas.removeEventListener('click', mouseClickHandler, false); - canvas.removeEventListener('dblclick', mouseDblClickHandler, false); - canvas.removeEventListener('wheel', wheelHandler, false); - if (canvasObserver) { - canvasObserver.disconnect(); - } else { - window.removeEventListener('resize', resizeHandler); - window.removeEventListener('orientationchange', resizeHandler); - } - canvas = undefined; - camera.dispose(); - camera = undefined; - lasso.destroy(); - lassoManager.destroy(); - pointConnections.destroy(); - reticleHLine.destroy(); - reticleVLine.destroy(); - if (colorTex) { - colorTex.destroy(); - } - if (encodingTex) { - encodingTex.destroy(); - } - if (!(initialProperties.renderer || renderer.isDestroyed)) { - // Since the user did not pass in an externally created renderer we can - // assume that the renderer is only used by this scatter plot instance. - // Therefore it's save to destroy it when this scatter plot instance is - // destroyed. - renderer.destroy(); - } - pubSub.publish('destroy'); - pubSub.clear(); - }; - - init(); - - return { - /** - * Get whether the browser supports all necessary WebGL features - * @return {boolean} If `true` the browser supports all necessary WebGL features - */ - get isSupported() { - return renderer.isSupported; - }, - clear: withDraw(clear), - clearPoints: withDraw(clearPoints), - clearPointConnections: withDraw(clearPointConnections), - clearAnnotations: withDraw(clearAnnotations), - createTextureFromUrl: ( - /** @type {string} */ url, - /** @type {number} */ timeout = DEFAULT_IMAGE_LOAD_TIMEOUT, - ) => createTextureFromUrl(renderer.regl, url, timeout), - deselect, - destroy, - draw: publicDraw, - drawAnnotations, - filter, - get, - getScreenPosition, - hover, - lassoSelect, - redraw, - refresh: renderer.refresh, - reset: withDraw(reset), - select, - set, - export: exportFn, - subscribe: pubSub.subscribe, - unfilter, - unsubscribe: pubSub.unsubscribe, - view, - zoomToLocation, - zoomToArea, - zoomToPoints, - zoomToOrigin, - }; -}; - -export default createScatterplot; - -/** - * Create spatial index from points. - * - * @description - * The spatial index can be used with `scatterplot.draw(points, { spatialIndex })` - * to drastically speed up the draw call. - * - * @param {import('./types').Points} points - The points for which to create the spatial index. - * @param {boolean=} useWorker - Whether to create the spatial index in a worker thread or not. If `undefined`, the spatial index will be created in a worker if `points` contains more than one million entries. - * @return {Promise} Spatial index - */ -const createSpatialIndex = (points, useWorker) => - toArrayOrientedPoints(points) - .then((arrayPoints) => createKdbush(arrayPoints, { useWorker })) - .then((index) => index.data); - -export { - createRegl, - createRenderer, - createSpatialIndex, - createTextureFromUrl, - checkSupport, -}; diff --git a/src/kdbush-class.js b/src/kdbush-class.js deleted file mode 100644 index ebcdfdab..00000000 --- a/src/kdbush-class.js +++ /dev/null @@ -1,369 +0,0 @@ -/** - * KDBush - A fast static index for 2D points - * @license ISC License - * @copyright Vladimir Agafonkin 2018 - * @version 4.0.2 - * @see https://github.com/mourner/kdbush/ - */ -export default () => { - const ARRAY_TYPES = [ - Int8Array, - Uint8Array, - Uint8ClampedArray, - Int16Array, - Uint16Array, - Int32Array, - Uint32Array, - Float32Array, - Float64Array, - ]; - - /** @typedef {Int8ArrayConstructor | Uint8ArrayConstructor | Uint8ClampedArrayConstructor | Int16ArrayConstructor | Uint16ArrayConstructor | Int32ArrayConstructor | Uint32ArrayConstructor | Float32ArrayConstructor | Float64ArrayConstructor} TypedArrayConstructor */ - - const VERSION = 1; // serialized format version - const HEADER_SIZE = 8; - - class KDBush { - /** - * Creates an index from raw `ArrayBuffer` data. - * @param {ArrayBuffer} data - */ - static from(data) { - if (!(data instanceof ArrayBuffer)) { - throw new Error('Data must be an instance of ArrayBuffer.'); - } - const [magic, versionAndType] = new Uint8Array(data, 0, 2); - if (magic !== 0xdb) { - throw new Error('Data does not appear to be in a KDBush format.'); - } - const version = versionAndType >> 4; - if (version !== VERSION) { - throw new Error(`Got v${version} data when expected v${VERSION}.`); - } - const ArrayType = ARRAY_TYPES[versionAndType & 0x0f]; - if (!ArrayType) { - throw new Error('Unrecognized array type.'); - } - const [nodeSize] = new Uint16Array(data, 2, 1); - const [numItems] = new Uint32Array(data, 4, 1); - - return new KDBush(numItems, nodeSize, ArrayType, data); - } - - /** - * Creates an index that will hold a given number of items. - * @param {number} numItems - * @param {number} [nodeSize=64] Size of the KD-tree node (64 by default). - * @param {TypedArrayConstructor} [ArrayType=Float64Array] The array type used for coordinates storage (`Float64Array` by default). - * @param {ArrayBuffer} [data] (For internal use only) - */ - constructor(numItems, nodeSize = 64, ArrayType = Float64Array, data) { - if (isNaN(numItems) || numItems < 0) - throw new Error(`Unexpected numItems value: ${numItems}.`); - - this.numItems = +numItems; - this.nodeSize = Math.min(Math.max(+nodeSize, 2), 65535); - this.ArrayType = ArrayType; - this.IndexArrayType = numItems < 65536 ? Uint16Array : Uint32Array; - - const arrayTypeIndex = ARRAY_TYPES.indexOf(this.ArrayType); - const coordsByteSize = numItems * 2 * this.ArrayType.BYTES_PER_ELEMENT; - const idsByteSize = numItems * this.IndexArrayType.BYTES_PER_ELEMENT; - const padCoords = (8 - (idsByteSize % 8)) % 8; - - if (arrayTypeIndex < 0) { - throw new Error(`Unexpected typed array class: ${ArrayType}.`); - } - - if (data && data instanceof ArrayBuffer) { - // reconstruct an index from a buffer - this.data = data; - this.ids = new this.IndexArrayType(this.data, HEADER_SIZE, numItems); - this.coords = new this.ArrayType( - this.data, - HEADER_SIZE + idsByteSize + padCoords, - numItems * 2 - ); - this._pos = numItems * 2; - this._finished = true; - } else { - // initialize a new index - this.data = new ArrayBuffer( - HEADER_SIZE + coordsByteSize + idsByteSize + padCoords - ); - this.ids = new this.IndexArrayType(this.data, HEADER_SIZE, numItems); - this.coords = new this.ArrayType( - this.data, - HEADER_SIZE + idsByteSize + padCoords, - numItems * 2 - ); - this._pos = 0; - this._finished = false; - - // set header - new Uint8Array(this.data, 0, 2).set([ - 0xdb, - (VERSION << 4) + arrayTypeIndex, - ]); - new Uint16Array(this.data, 2, 1)[0] = nodeSize; - new Uint32Array(this.data, 4, 1)[0] = numItems; - } - } - - /** - * Add a point to the index. - * @param {number} x - * @param {number} y - * @returns {number} An incremental index associated with the added item (starting from `0`). - */ - add(x, y) { - const index = this._pos >> 1; - this.ids[index] = index; - this.coords[this._pos++] = x; - this.coords[this._pos++] = y; - return index; - } - - /** - * Perform indexing of the added points. - */ - finish() { - const numAdded = this._pos >> 1; - if (numAdded !== this.numItems) { - throw new Error( - `Added ${numAdded} items when expected ${this.numItems}.` - ); - } - // kd-sort both arrays for efficient search - sort(this.ids, this.coords, this.nodeSize, 0, this.numItems - 1, 0); - - this._finished = true; - return this; - } - - /** - * Search the index for items within a given bounding box. - * @param {number} minX - * @param {number} minY - * @param {number} maxX - * @param {number} maxY - * @returns {number[]} An array of indices correponding to the found items. - */ - range(minX, minY, maxX, maxY) { - if (!this._finished) - throw new Error('Data not yet indexed - call index.finish().'); - - const { ids, coords, nodeSize } = this; - const stack = [0, ids.length - 1, 0]; - const result = []; - - // recursively search for items in range in the kd-sorted arrays - while (stack.length) { - const axis = stack.pop() || 0; - const right = stack.pop() || 0; - const left = stack.pop() || 0; - - // if we reached "tree node", search linearly - if (right - left <= nodeSize) { - for (let i = left; i <= right; i++) { - const x = coords[2 * i]; - const y = coords[2 * i + 1]; - if (x >= minX && x <= maxX && y >= minY && y <= maxY) - result.push(ids[i]); - } - continue; - } - - // otherwise find the middle index - const m = (left + right) >> 1; - - // include the middle item if it's in range - const x = coords[2 * m]; - const y = coords[2 * m + 1]; - if (x >= minX && x <= maxX && y >= minY && y <= maxY) - result.push(ids[m]); - - // queue search in halves that intersect the query - if (axis === 0 ? minX <= x : minY <= y) { - stack.push(left); - stack.push(m - 1); - stack.push(1 - axis); - } - if (axis === 0 ? maxX >= x : maxY >= y) { - stack.push(m + 1); - stack.push(right); - stack.push(1 - axis); - } - } - - return result; - } - - /** - * Search the index for items within a given radius. - * @param {number} qx - * @param {number} qy - * @param {number} r Query radius. - * @returns {number[]} An array of indices correponding to the found items. - */ - within(qx, qy, r) { - if (!this._finished) - throw new Error('Data not yet indexed - call index.finish().'); - - const { ids, coords, nodeSize } = this; - const stack = [0, ids.length - 1, 0]; - const result = []; - const r2 = r * r; - - // recursively search for items within radius in the kd-sorted arrays - while (stack.length) { - const axis = stack.pop() || 0; - const right = stack.pop() || 0; - const left = stack.pop() || 0; - - // if we reached "tree node", search linearly - if (right - left <= nodeSize) { - for (let i = left; i <= right; i++) { - if (sqDist(coords[2 * i], coords[2 * i + 1], qx, qy) <= r2) - result.push(ids[i]); - } - continue; - } - - // otherwise find the middle index - const m = (left + right) >> 1; - - // include the middle item if it's in range - const x = coords[2 * m]; - const y = coords[2 * m + 1]; - if (sqDist(x, y, qx, qy) <= r2) result.push(ids[m]); - - // queue search in halves that intersect the query - if (axis === 0 ? qx - r <= x : qy - r <= y) { - stack.push(left); - stack.push(m - 1); - stack.push(1 - axis); - } - if (axis === 0 ? qx + r >= x : qy + r >= y) { - stack.push(m + 1); - stack.push(right); - stack.push(1 - axis); - } - } - - return result; - } - } - - /** - * @param {Uint16Array | Uint32Array} ids - * @param {InstanceType} coords - * @param {number} nodeSize - * @param {number} left - * @param {number} right - * @param {number} axis - */ - function sort(ids, coords, nodeSize, left, right, axis) { - if (right - left <= nodeSize) return; - - const m = (left + right) >> 1; // middle index - - // sort ids and coords around the middle index so that the halves lie - // either left/right or top/bottom correspondingly (taking turns) - select(ids, coords, m, left, right, axis); - - // recursively kd-sort first half and second half on the opposite axis - sort(ids, coords, nodeSize, left, m - 1, 1 - axis); - sort(ids, coords, nodeSize, m + 1, right, 1 - axis); - } - - /** - * Custom Floyd-Rivest selection algorithm: sort ids and coords so that - * [left..k-1] items are smaller than k-th item (on either x or y axis) - * @param {Uint16Array | Uint32Array} ids - * @param {InstanceType} coords - * @param {number} k - * @param {number} left - * @param {number} right - * @param {number} axis - */ - function select(ids, coords, k, left, right, axis) { - while (right > left) { - if (right - left > 600) { - const n = right - left + 1; - const m = k - left + 1; - const z = Math.log(n); - const s = 0.5 * Math.exp((2 * z) / 3); - const sd = - 0.5 * Math.sqrt((z * s * (n - s)) / n) * (m - n / 2 < 0 ? -1 : 1); - const newLeft = Math.max(left, Math.floor(k - (m * s) / n + sd)); - const newRight = Math.min( - right, - Math.floor(k + ((n - m) * s) / n + sd) - ); - select(ids, coords, k, newLeft, newRight, axis); - } - - const t = coords[2 * k + axis]; - let i = left; - let j = right; - - swapItem(ids, coords, left, k); - if (coords[2 * right + axis] > t) swapItem(ids, coords, left, right); - - while (i < j) { - swapItem(ids, coords, i, j); - i++; - j--; - while (coords[2 * i + axis] < t) i++; - while (coords[2 * j + axis] > t) j--; - } - - if (coords[2 * left + axis] === t) swapItem(ids, coords, left, j); - else { - j++; - swapItem(ids, coords, j, right); - } - - if (j <= k) left = j + 1; - if (k <= j) right = j - 1; - } - } - - /** - * @param {Uint16Array | Uint32Array} ids - * @param {InstanceType} coords - * @param {number} i - * @param {number} j - */ - function swapItem(ids, coords, i, j) { - swap(ids, i, j); - swap(coords, 2 * i, 2 * j); - swap(coords, 2 * i + 1, 2 * j + 1); - } - - /** - * @param {InstanceType} arr - * @param {number} i - * @param {number} j - */ - function swap(arr, i, j) { - const tmp = arr[i]; - arr[i] = arr[j]; - arr[j] = tmp; - } - - /** - * @param {number} ax - * @param {number} ay - * @param {number} bx - * @param {number} by - */ - function sqDist(ax, ay, bx, by) { - const dx = ax - bx; - const dy = ay - by; - return dx * dx + dy * dy; - } - - return KDBush; -}; diff --git a/src/kdbush-worker.js b/src/kdbush-worker.js deleted file mode 100644 index 55ce14a8..00000000 --- a/src/kdbush-worker.js +++ /dev/null @@ -1,19 +0,0 @@ -export default () => { - addEventListener('message', (event) => { - const points = event.data.points; - - if (points.length === 0) { - self.postMessage({ error: new Error('Invalid point data') }); - } - - const index = new KDBush(points.length, event.data.nodeSize); - - for (const [x, y] of points) { - index.add(x, y); - } - - index.finish(); - - postMessage(index.data, [index.data]); - }); -}; diff --git a/src/kdbush.js b/src/kdbush.js deleted file mode 100644 index fe4ff01d..00000000 --- a/src/kdbush.js +++ /dev/null @@ -1,66 +0,0 @@ -import createKDBushClass from './kdbush-class.js'; -import workerFn from './kdbush-worker.js'; - -const KDBush = createKDBushClass(); -const WORKER_THRESHOLD = 1000000; - -const createWorker = (fn) => { - const kdbushStr = createKDBushClass.toString(); - const fnStr = fn.toString(); - const workerStr = - `const createKDBushClass = ${kdbushStr};` + - 'KDBush = createKDBushClass();' + - `const createWorker = ${fnStr};` + - 'createWorker();'; - - const blob = new Blob([workerStr], { type: 'text/javascript' }); - const workerUrl = URL.createObjectURL(blob); - const worker = new Worker(workerUrl, { name: 'KDBush' }); - - // Clean up URL - URL.revokeObjectURL(workerUrl); - - return worker; -}; - -/** - * Create KDBush from an either point data or an existing spatial index - * @param {import('./types').Points | ArrayBuffer} pointsOrIndex - Points or KDBush index - * @param {Partial} options - Options for configuring the index and its creation - * @return {Promise} KDBush instance - */ -const createKdbush = ( - pointsOrIndex, - options = { nodeSize: 16, useWorker: undefined }, -) => - new Promise((resolve, reject) => { - if (pointsOrIndex instanceof ArrayBuffer) { - resolve(KDBush.from(pointsOrIndex)); - } else if ( - (pointsOrIndex.length < WORKER_THRESHOLD || - options.useWorker === false) && - options.useWorker !== true - ) { - const index = new KDBush(pointsOrIndex.length, options.nodeSize); - for (const pointOrIndex of pointsOrIndex) { - index.add(pointOrIndex[0], pointOrIndex[1]); - } - index.finish(); - resolve(index); - } else { - const worker = createWorker(workerFn); - - worker.onmessage = (e) => { - if (e.data.error) { - reject(e.data.error); - } else { - resolve(KDBush.from(e.data)); - } - worker.terminate(); - }; - - worker.postMessage({ points: pointsOrIndex, nodeSize: options.nodeSize }); - } - }); - -export default createKdbush; diff --git a/src/lasso-manager/constants.js b/src/lasso-manager/constants.js deleted file mode 100644 index 80c2c252..00000000 --- a/src/lasso-manager/constants.js +++ /dev/null @@ -1,7 +0,0 @@ -export const DEFAULT_LASSO_START_INITIATOR_SHOW = true; -export const DEFAULT_LASSO_MIN_DELAY = 8; -export const DEFAULT_LASSO_MIN_DIST = 2; -export const DEFAULT_LASSO_TYPE = 'freeform'; -export const DEFAULT_BRUSH_SIZE = 24; -export const LASSO_SHOW_START_INITIATOR_TIME = 2500; -export const LASSO_HIDE_START_INITIATOR_TIME = 250; diff --git a/src/lasso-manager/create-long-press-animations.js b/src/lasso-manager/create-long-press-animations.js deleted file mode 100644 index 7a9862cd..00000000 --- a/src/lasso-manager/create-long-press-animations.js +++ /dev/null @@ -1,257 +0,0 @@ -import { - DEFAULT_LASSO_LONG_PRESS_AFTER_EFFECT_TIME, - DEFAULT_LASSO_LONG_PRESS_EFFECT_DELAY, - DEFAULT_LASSO_LONG_PRESS_REVERT_EFFECT_TIME, - DEFAULT_LASSO_LONG_PRESS_TIME, -} from '../constants.js'; - -const getInTime = (p, time, extraTime) => (1 - p) * time + extraTime; - -const getMainInAnimation = (t, d) => - `${t}ms ease-out mainIn ${d}ms 1 normal forwards`; - -const getEffectInAnimation = (t, d) => - `${t}ms ease-out effectIn ${d}ms 1 normal forwards`; - -const getCircleLeftInAnimation = (t, d) => - `${t}ms linear leftSpinIn ${d}ms 1 normal forwards`; - -const getCircleRightInAnimation = (t, d) => - `${t}ms linear rightSpinIn ${d}ms 1 normal forwards`; - -const getCircleInAnimation = (t, d) => - `${t}ms linear circleIn ${d}ms 1 normal forwards`; - -const getMainIn = (mainEffectPercent, currentColor, targetColor) => ` - @keyframes mainIn { - 0% { - color: ${currentColor}; - opacity: 0; - } - 0%, ${mainEffectPercent}% { - color: ${currentColor}; - opacity: 1; - } - 100% { - color: ${targetColor}; - opacity: 0.8; - } - } -`; - -const getEffectIn = (mainEffectPercent, afterEffectPercent, opacity, scale) => ` - @keyframes effectIn { - 0%, ${mainEffectPercent}% { - opacity: ${opacity}; - transform: scale(${scale}); - } - ${afterEffectPercent}% { - opacity: 0.66; - transform: scale(1.5); - } - 99% { - opacity: 0; - transform: scale(2); - } - 100% { - opacity: 0; - transform: scale(0); - } - } -`; - -const getCircleIn = (halfMainEffectPercent, clipPath, opacity) => ` - @keyframes circleIn { - 0% { - clip-path: ${clipPath}; - opacity: ${opacity}; - } - ${halfMainEffectPercent}% { - clip-path: ${clipPath}; - opacity: 1; - } - ${halfMainEffectPercent + 0.01}%, 100% { - clip-path: inset(0); - opacity: 1; - } - } -`; - -const getCircleLeftIn = (mainEffectPercent, angle) => ` - @keyframes leftSpinIn { - 0% { - transform: rotate(${angle}deg); - } - ${mainEffectPercent}%, 100% { - transform: rotate(360deg); - } - } -`; - -const getCircleRightIn = (halfMainEffectPercent, angle) => ` - @keyframes rightSpinIn { - 0% { - transform: rotate(${angle}deg); - } - ${halfMainEffectPercent}%, 100% { - transform: rotate(180deg); - } - } -`; - -export const createLongPressInAnimations = ({ - time = DEFAULT_LASSO_LONG_PRESS_TIME, - extraTime = DEFAULT_LASSO_LONG_PRESS_AFTER_EFFECT_TIME, - delay = DEFAULT_LASSO_LONG_PRESS_EFFECT_DELAY, - currentColor, - targetColor, - effectOpacity, - effectScale, - circleLeftRotation, - circleRightRotation, - circleClipPath, - circleOpacity, -}) => { - const p = circleLeftRotation / 360; - const actualTime = getInTime(p, time, extraTime); - const longPressPercent = Math.round((((1 - p) * time) / actualTime) * 100); - const halfLongPressPercent = Math.round(longPressPercent / 2); - const afterEffectPercent = longPressPercent + (100 - longPressPercent) / 4; - - return { - rules: { - main: getMainIn(longPressPercent, currentColor, targetColor), - effect: getEffectIn( - longPressPercent, - afterEffectPercent, - effectOpacity, - effectScale, - ), - circleRight: getCircleRightIn(halfLongPressPercent, circleRightRotation), - circleLeft: getCircleLeftIn(longPressPercent, circleLeftRotation), - circle: getCircleIn(halfLongPressPercent, circleClipPath, circleOpacity), - }, - names: { - main: getMainInAnimation(actualTime, delay), - effect: getEffectInAnimation(actualTime, delay), - circleLeft: getCircleLeftInAnimation(actualTime, delay), - circleRight: getCircleRightInAnimation(actualTime, delay), - circle: getCircleInAnimation(actualTime, delay), - }, - }; -}; - -const getMainOutAnimation = (t) => `${t}ms linear mainOut 0s 1 normal forwards`; - -const getEffectOutAnimation = (t) => - `${t}ms linear effectOut 0s 1 normal forwards`; - -const getCircleLeftOutAnimation = (t) => - `${t}ms linear leftSpinOut 0s 1 normal forwards`; - -const getCircleRightOutAnimation = (t) => - `${t}ms linear rightSpinOut 0s 1 normal forwards`; - -const getCircleOutAnimation = (t) => - `${t}ms linear circleOut 0s 1 normal forwards`; - -const getMainOut = (currentColor, targetColor) => ` - @keyframes mainOut { - 0% { - color: ${currentColor}; - } - 100% { - color: ${targetColor}; - } - } -`; - -const getEffectOut = (opacity, scale) => ` - @keyframes effectOut { - 0% { - opacity: ${opacity}; - transform: scale(${scale}); - } - 99% { - opacity: 0; - transform: scale(${scale + 0.5}); - } - 100% { - opacity: 0; - transform: scale(0); - } - } -`; - -const getCircleRightOut = (halfEffectPercent, angle) => ` - @keyframes rightSpinOut { - 0%, ${halfEffectPercent}% { - transform: rotate(${angle}deg); - } - 100% { - transform: rotate(0deg); - } -`; - -const getCircleLeftOut = (angle) => ` - @keyframes leftSpinOut { - 0% { - transform: rotate(${angle}deg); - } - 100% { - transform: rotate(0deg); - } - } -`; - -const getCircleOut = (halfEffectPercent, clipPath, opacity) => ` - @keyframes circleOut { - 0%, ${halfEffectPercent}% { - clip-path: ${clipPath}; - opacity: ${opacity}; - } - ${halfEffectPercent + 0.01}% { - clip-path: inset(0 0 0 50%); - opacity: ${opacity}; - } - 100% { - clip-path: inset(0 0 0 50%); - opacity: 0; - } - } -`; - -export const createLongPressOutAnimations = ({ - time = DEFAULT_LASSO_LONG_PRESS_REVERT_EFFECT_TIME, - currentColor, - targetColor, - effectOpacity, - effectScale, - circleLeftRotation, - circleRightRotation, - circleClipPath, - circleOpacity, -}) => { - const p = circleLeftRotation / 360; - const actualTime = p * time; - const rotatedPercent = Math.min(100, p * 100); - const halfPercent = - rotatedPercent > 50 ? Math.round((1 - 50 / rotatedPercent) * 100) : 0; - - return { - rules: { - main: getMainOut(currentColor, targetColor), - effect: getEffectOut(effectOpacity, effectScale), - circleRight: getCircleRightOut(halfPercent, circleRightRotation), - circleLeft: getCircleLeftOut(circleLeftRotation), - circle: getCircleOut(halfPercent, circleClipPath, circleOpacity), - }, - names: { - main: getMainOutAnimation(actualTime), - effect: getEffectOutAnimation(actualTime), - circleRight: getCircleLeftOutAnimation(actualTime), - circleLeft: getCircleRightOutAnimation(actualTime), - circle: getCircleOutAnimation(actualTime), - }, - }; -}; diff --git a/src/lasso-manager/create-long-press-elements.js b/src/lasso-manager/create-long-press-elements.js deleted file mode 100644 index d14d1bf9..00000000 --- a/src/lasso-manager/create-long-press-elements.js +++ /dev/null @@ -1,68 +0,0 @@ -export const createLongPressElements = () => { - const longPress = document.createElement('div'); - const longPressId = - Math.random().toString(36).substring(2, 5) + - Math.random().toString(36).substring(2, 5); - longPress.id = `lasso-long-press-${longPressId}`; - longPress.style.position = 'fixed'; - longPress.style.width = '1.25rem'; - longPress.style.height = '1.25rem'; - longPress.style.pointerEvents = 'none'; - longPress.style.transform = 'translate(-50%,-50%)'; - - const longPressCircle = document.createElement('div'); - longPressCircle.style.position = 'absolute'; - longPressCircle.style.top = 0; - longPressCircle.style.left = 0; - longPressCircle.style.width = '1.25rem'; - longPressCircle.style.height = '1.25rem'; - longPressCircle.style.clipPath = 'inset(0px 0px 0px 50%)'; - longPressCircle.style.opacity = 0; - longPress.appendChild(longPressCircle); - - const longPressCircleLeft = document.createElement('div'); - longPressCircleLeft.style.position = 'absolute'; - longPressCircleLeft.style.top = 0; - longPressCircleLeft.style.left = 0; - longPressCircleLeft.style.width = '0.8rem'; - longPressCircleLeft.style.height = '0.8rem'; - longPressCircleLeft.style.border = '0.2rem solid currentcolor'; - longPressCircleLeft.style.borderRadius = '0.8rem'; - longPressCircleLeft.style.clipPath = 'inset(0px 50% 0px 0px)'; - longPressCircleLeft.style.transform = 'rotate(0deg)'; - longPressCircle.appendChild(longPressCircleLeft); - - const longPressCircleRight = document.createElement('div'); - longPressCircleRight.style.position = 'absolute'; - longPressCircleRight.style.top = 0; - longPressCircleRight.style.left = 0; - longPressCircleRight.style.width = '0.8rem'; - longPressCircleRight.style.height = '0.8rem'; - longPressCircleRight.style.border = '0.2rem solid currentcolor'; - longPressCircleRight.style.borderRadius = '0.8rem'; - longPressCircleRight.style.clipPath = 'inset(0px 50% 0px 0px)'; - longPressCircleRight.style.transform = 'rotate(0deg)'; - longPressCircle.appendChild(longPressCircleRight); - - const longPressEffect = document.createElement('div'); - longPressEffect.style.position = 'absolute'; - longPressEffect.style.top = 0; - longPressEffect.style.left = 0; - longPressEffect.style.width = '1.25rem'; - longPressEffect.style.height = '1.25rem'; - longPressEffect.style.borderRadius = '1.25rem'; - longPressEffect.style.background = 'currentcolor'; - longPressEffect.style.transform = 'scale(0)'; - longPressEffect.style.opacity = 0; - longPress.appendChild(longPressEffect); - - return { - longPress, - longPressCircle, - longPressCircleLeft, - longPressCircleRight, - longPressEffect, - }; -}; - -export default createLongPressElements; diff --git a/src/lasso-manager/index.js b/src/lasso-manager/index.js deleted file mode 100644 index 0e88be34..00000000 --- a/src/lasso-manager/index.js +++ /dev/null @@ -1,779 +0,0 @@ -import { - assign, - identity, - l2Norm, - l2PointDist, - nextAnimationFrame, - pipe, - throttleAndDebounce, - withConstructor, - withStaticProperty, -} from '@flekschas/utils'; -import { - DEFAULT_LASSO_LONG_PRESS_AFTER_EFFECT_TIME, - DEFAULT_LASSO_LONG_PRESS_EFFECT_DELAY, - DEFAULT_LASSO_LONG_PRESS_REVERT_EFFECT_TIME, - DEFAULT_LASSO_LONG_PRESS_TIME, -} from '../constants.js'; -import { - DEFAULT_BRUSH_SIZE, - DEFAULT_LASSO_MIN_DELAY, - DEFAULT_LASSO_MIN_DIST, - DEFAULT_LASSO_START_INITIATOR_SHOW, - DEFAULT_LASSO_TYPE, - LASSO_HIDE_START_INITIATOR_TIME, - LASSO_SHOW_START_INITIATOR_TIME, -} from './constants.js'; - -import { - createLongPressInAnimations, - createLongPressOutAnimations, -} from './create-long-press-animations.js'; -import createLongPressElements from './create-long-press-elements.js'; -import { exponentialMovingAverage } from './utils.js'; - -const ifNotNull = (v, alternative = null) => (v === null ? alternative : v); - -let cachedLassoStylesheets; - -const getLassoStylesheets = () => { - if (!cachedLassoStylesheets) { - const lassoStyleEl = document.createElement('style'); - document.head.appendChild(lassoStyleEl); - cachedLassoStylesheets = lassoStyleEl.sheet; - } - return cachedLassoStylesheets; -}; - -const addRule = (rule) => { - const lassoStylesheets = getLassoStylesheets(); - const currentNumRules = lassoStylesheets.rules.length; - lassoStylesheets.insertRule(rule, currentNumRules); - return currentNumRules; -}; - -const removeRule = (index) => { - getLassoStylesheets().deleteRule(index); -}; - -const inAnimation = `${LASSO_SHOW_START_INITIATOR_TIME}ms ease scaleInFadeOut 0s 1 normal backwards`; - -const createInAnimationRule = (opacity, scale, rotate) => ` -@keyframes scaleInFadeOut { - 0% { - opacity: ${opacity}; - transform: translate(-50%,-50%) scale(${scale}) rotate(${rotate}deg); - } - 10% { - opacity: 1; - transform: translate(-50%,-50%) scale(1) rotate(${rotate + 20}deg); - } - 100% { - opacity: 0; - transform: translate(-50%,-50%) scale(0.9) rotate(${rotate + 60}deg); - } -} -`; -let inAnimationRuleIndex = null; - -const outAnimation = `${LASSO_HIDE_START_INITIATOR_TIME}ms ease fadeScaleOut 0s 1 normal backwards`; - -const createOutAnimationRule = (opacity, scale, rotate) => ` -@keyframes fadeScaleOut { - 0% { - opacity: ${opacity}; - transform: translate(-50%,-50%) scale(${scale}) rotate(${rotate}deg); - } - 100% { - opacity: 0; - transform: translate(-50%,-50%) scale(0) rotate(${rotate}deg); - } -} -`; -let outAnimationRuleIndex = null; - -export const createLasso = ( - element, - { - onDraw: initialOnDraw = identity, - onStart: initialOnStart = identity, - onEnd: initialOnEnd = identity, - enableInitiator: - initialenableInitiator = DEFAULT_LASSO_START_INITIATOR_SHOW, - initiatorParentElement: initialInitiatorParentElement = document.body, - longPressIndicatorParentElement: - initialLongPressIndicatorParentElement = document.body, - minDelay: initialMinDelay = DEFAULT_LASSO_MIN_DELAY, - minDist: initialMinDist = DEFAULT_LASSO_MIN_DIST, - pointNorm: initialPointNorm = identity, - type: initialType = DEFAULT_LASSO_TYPE, - brushSize: initialBrushSize = DEFAULT_BRUSH_SIZE, - } = {}, -) => { - let enableInitiator = initialenableInitiator; - let initiatorParentElement = initialInitiatorParentElement; - let longPressIndicatorParentElement = initialLongPressIndicatorParentElement; - - let onDraw = initialOnDraw; - let onStart = initialOnStart; - let onEnd = initialOnEnd; - - let minDelay = initialMinDelay; - let minDist = initialMinDist; - - let pointNorm = initialPointNorm; - - let type = initialType; - let brushSize = initialBrushSize; - - const initiator = document.createElement('div'); - const initiatorId = - Math.random().toString(36).substring(2, 5) + - Math.random().toString(36).substring(2, 5); - initiator.id = `lasso-initiator-${initiatorId}`; - initiator.style.position = 'fixed'; - initiator.style.display = 'flex'; - initiator.style.justifyContent = 'center'; - initiator.style.alignItems = 'center'; - initiator.style.zIndex = 99; - initiator.style.width = '4rem'; - initiator.style.height = '4rem'; - initiator.style.borderRadius = '4rem'; - initiator.style.opacity = 0.5; - initiator.style.transform = 'translate(-50%,-50%) scale(0) rotate(0deg)'; - - const { - longPress, - longPressCircle, - longPressCircleLeft, - longPressCircleRight, - longPressEffect, - } = createLongPressElements(); - - let isMouseDown = false; - let isLasso = false; - let lassoPos = []; - let lassoPosFlat = []; - let lassoBrushCenterPos = []; - let lassoBrushNormals = []; - let prevMousePos; - let longPressIsStarting = false; - - let longPressMainInAnimationRuleIndex = null; - let longPressEffectInAnimationRuleIndex = null; - let longPressCircleLeftInAnimationRuleIndex = null; - let longPressCircleRightInAnimationRuleIndex = null; - let longPressCircleInAnimationRuleIndex = null; - let longPressMainOutAnimationRuleIndex = null; - let longPressEffectOutAnimationRuleIndex = null; - let longPressCircleLeftOutAnimationRuleIndex = null; - let longPressCircleRightOutAnimationRuleIndex = null; - let longPressCircleOutAnimationRuleIndex = null; - - const mouseUpHandler = () => { - isMouseDown = false; - }; - - const getMousePosition = (event) => { - const { left, top } = element.getBoundingClientRect(); - - return [event.clientX - left, event.clientY - top]; - }; - - window.addEventListener('mouseup', mouseUpHandler); - - const resetInitiatorStyle = () => { - initiator.style.opacity = 0.5; - initiator.style.transform = 'translate(-50%,-50%) scale(0) rotate(0deg)'; - }; - - const getCurrentTransformStyle = (node, hasRotated) => { - const computedStyle = getComputedStyle(node); - const opacity = +computedStyle.opacity; - // The css rule `transform: translate(-1, -1) scale(0.5);` is represented as - // `matrix(0.5, 0, 0, 0.5, -1, -1)` - const m = computedStyle.transform.match(/([0-9.-]+)+/g); - - const a = +m[0]; - const b = +m[1]; - - const scale = Math.sqrt(a * a + b * b); - let rotate = Math.atan2(b, a) * (180 / Math.PI); - - rotate = hasRotated && rotate <= 0 ? 360 + rotate : rotate; - - return { opacity, scale, rotate }; - }; - - const showInitiator = (event) => { - if (!enableInitiator || isMouseDown) { - return; - } - - const x = event.clientX; - const y = event.clientY; - initiator.style.top = `${y}px`; - initiator.style.left = `${x}px`; - - const style = getCurrentTransformStyle(initiator); - const opacity = style.opacity; - const scale = style.scale; - const rotate = style.rotate; - initiator.style.opacity = opacity; - initiator.style.transform = `translate(-50%,-50%) scale(${scale}) rotate(${rotate}deg)`; - - initiator.style.animation = 'none'; - - // See https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Animations/Tips - // why we need to wait for two animation frames - nextAnimationFrame().then(() => { - if (inAnimationRuleIndex !== null) { - removeRule(inAnimationRuleIndex); - } - - inAnimationRuleIndex = addRule( - createInAnimationRule(opacity, scale, rotate), - ); - - initiator.style.animation = inAnimation; - - nextAnimationFrame().then(() => { - resetInitiatorStyle(); - }); - }); - }; - - const hideInitiator = () => { - const { opacity, scale, rotate } = getCurrentTransformStyle(initiator); - initiator.style.opacity = opacity; - initiator.style.transform = `translate(-50%,-50%) scale(${scale}) rotate(${rotate}deg)`; - - initiator.style.animation = 'none'; - - nextAnimationFrame(2).then(() => { - if (outAnimationRuleIndex !== null) { - removeRule(outAnimationRuleIndex); - } - - outAnimationRuleIndex = addRule( - createOutAnimationRule(opacity, scale, rotate), - ); - - initiator.style.animation = outAnimation; - - nextAnimationFrame().then(() => { - resetInitiatorStyle(); - }); - }); - }; - - const showLongPressIndicator = ( - x, - y, - { - time = DEFAULT_LASSO_LONG_PRESS_TIME, - extraTime = DEFAULT_LASSO_LONG_PRESS_AFTER_EFFECT_TIME, - delay = DEFAULT_LASSO_LONG_PRESS_EFFECT_DELAY, - } = { - time: DEFAULT_LASSO_LONG_PRESS_TIME, - extraTime: DEFAULT_LASSO_LONG_PRESS_AFTER_EFFECT_TIME, - delay: DEFAULT_LASSO_LONG_PRESS_EFFECT_DELAY, - }, - ) => { - longPressIsStarting = true; - - const mainStyle = getComputedStyle(longPress); - longPress.style.color = mainStyle.color; - longPress.style.top = `${y}px`; - longPress.style.left = `${x}px`; - longPress.style.animation = 'none'; - - const circleStyle = getComputedStyle(longPressCircle); - longPressCircle.style.clipPath = circleStyle.clipPath; - longPressCircle.style.opacity = circleStyle.opacity; - longPressCircle.style.animation = 'none'; - - const effectStyle = getCurrentTransformStyle(longPressEffect); - longPressEffect.style.opacity = effectStyle.opacity; - longPressEffect.style.transform = `scale(${effectStyle.scale})`; - longPressEffect.style.animation = 'none'; - - const circleLeftStyle = getCurrentTransformStyle(longPressCircleLeft); - longPressCircleLeft.style.transform = `rotate(${circleLeftStyle.rotate}deg)`; - longPressCircleLeft.style.animation = 'none'; - - const circleRightStyle = getCurrentTransformStyle(longPressCircleRight); - longPressCircleRight.style.transform = `rotate(${circleRightStyle.rotate}deg)`; - longPressCircleRight.style.animation = 'none'; - - nextAnimationFrame().then(() => { - if (!longPressIsStarting) { - return; - } - - if (longPressCircleInAnimationRuleIndex !== null) { - removeRule(longPressCircleInAnimationRuleIndex); - } - if (longPressCircleRightInAnimationRuleIndex !== null) { - removeRule(longPressCircleRightInAnimationRuleIndex); - } - if (longPressCircleLeftInAnimationRuleIndex !== null) { - removeRule(longPressCircleLeftInAnimationRuleIndex); - } - if (longPressEffectInAnimationRuleIndex !== null) { - removeRule(longPressEffectInAnimationRuleIndex); - } - if (longPressMainInAnimationRuleIndex !== null) { - removeRule(longPressMainInAnimationRuleIndex); - } - - const { rules, names } = createLongPressInAnimations({ - time, - extraTime, - delay, - currentColor: mainStyle.color || 'currentcolor', - targetColor: longPress.dataset.activeColor, - effectOpacity: effectStyle.opacity || 0, - effectScale: effectStyle.scale || 0, - circleLeftRotation: circleLeftStyle.rotate || 0, - circleRightRotation: circleRightStyle.rotate || 0, - circleClipPath: circleStyle.clipPath || 'inset(0 0 0 50%)', - circleOpacity: circleStyle.opacity || 0, - }); - - longPressMainInAnimationRuleIndex = addRule(rules.main); - longPressEffectInAnimationRuleIndex = addRule(rules.effect); - longPressCircleLeftInAnimationRuleIndex = addRule(rules.circleLeft); - longPressCircleRightInAnimationRuleIndex = addRule(rules.circleRight); - longPressCircleInAnimationRuleIndex = addRule(rules.circle); - - longPress.style.animation = names.main; - longPressEffect.style.animation = names.effect; - longPressCircleLeft.style.animation = names.circleLeft; - longPressCircleRight.style.animation = names.circleRight; - longPressCircle.style.animation = names.circle; - }); - }; - - const hideLongPressIndicator = ( - { time = DEFAULT_LASSO_LONG_PRESS_REVERT_EFFECT_TIME } = { - time: DEFAULT_LASSO_LONG_PRESS_REVERT_EFFECT_TIME, - }, - ) => { - if (!longPressIsStarting) { - return; - } - - longPressIsStarting = false; - - const mainStyle = getComputedStyle(longPress); - longPress.style.color = mainStyle.color; - longPress.style.animation = 'none'; - - const circleStyle = getComputedStyle(longPressCircle); - longPressCircle.style.clipPath = circleStyle.clipPath; - longPressCircle.style.opacity = circleStyle.opacity; - longPressCircle.style.animation = 'none'; - - const effectStyle = getCurrentTransformStyle(longPressEffect); - longPressEffect.style.opacity = effectStyle.opacity; - longPressEffect.style.transform = `scale(${effectStyle.scale})`; - longPressEffect.style.animation = 'none'; - - // The first half of the circle animation, the clip-path is set to `inset(0px 0px 0px 50%)`. - // In the second half it's set to `inset(0px)`. Hence we can look at the second to last - // character to determine if the animatation has progressed passed half time. - const isAnimatedMoreThan50Percent = - circleStyle.clipPath.slice(-2, -1) === 'x'; - - const circleLeftStyle = getCurrentTransformStyle( - longPressCircleLeft, - isAnimatedMoreThan50Percent, - ); - longPressCircleLeft.style.transform = `rotate(${circleLeftStyle.rotate}deg)`; - longPressCircleLeft.style.animation = 'none'; - - const circleRightStyle = getCurrentTransformStyle(longPressCircleRight); - longPressCircleRight.style.transform = `rotate(${circleRightStyle.rotate}deg)`; - longPressCircleRight.style.animation = 'none'; - - nextAnimationFrame().then(() => { - if (longPressCircleOutAnimationRuleIndex !== null) { - removeRule(longPressCircleOutAnimationRuleIndex); - } - if (longPressCircleRightOutAnimationRuleIndex !== null) { - removeRule(longPressCircleRightOutAnimationRuleIndex); - } - if (longPressCircleLeftOutAnimationRuleIndex !== null) { - removeRule(longPressCircleLeftOutAnimationRuleIndex); - } - if (longPressEffectOutAnimationRuleIndex !== null) { - removeRule(longPressEffectOutAnimationRuleIndex); - } - if (longPressMainOutAnimationRuleIndex !== null) { - removeRule(longPressMainOutAnimationRuleIndex); - } - - const { rules, names } = createLongPressOutAnimations({ - time, - currentColor: mainStyle.color || 'currentcolor', - targetColor: longPress.dataset.color, - effectOpacity: effectStyle.opacity || 0, - effectScale: effectStyle.scale || 0, - circleLeftRotation: circleLeftStyle.rotate || 0, - circleRightRotation: circleRightStyle.rotate || 0, - circleClipPath: circleStyle.clipPath || 'inset(0px)', - circleOpacity: circleStyle.opacity || 1, - }); - - longPressMainOutAnimationRuleIndex = addRule(rules.main); - longPressEffectOutAnimationRuleIndex = addRule(rules.effect); - longPressCircleLeftOutAnimationRuleIndex = addRule(rules.circleLeft); - longPressCircleRightOutAnimationRuleIndex = addRule(rules.circleRight); - longPressCircleOutAnimationRuleIndex = addRule(rules.circle); - - longPress.style.animation = names.main; - longPressEffect.style.animation = names.effect; - longPressCircleLeft.style.animation = names.circleLeft; - longPressCircleRight.style.animation = names.circleRight; - longPressCircle.style.animation = names.circle; - }); - }; - - const draw = () => { - onDraw(lassoPos, lassoPosFlat); - }; - - const extendFreeform = (point) => { - lassoPos.push(point); - lassoPosFlat.push(point[0], point[1]); - }; - - const extendRectangle = (point) => { - const [x, y] = point; - const [startX, startY] = lassoPos[0]; - - lassoPos[1] = [x, startY]; - lassoPos[2] = [x, y]; - lassoPos[3] = [startX, y]; - lassoPos[4] = [startX, startY]; - - lassoPosFlat[2] = x; - lassoPosFlat[3] = startY; - lassoPosFlat[4] = x; - lassoPosFlat[5] = y; - lassoPosFlat[6] = startX; - lassoPosFlat[7] = y; - lassoPosFlat[8] = startX; - lassoPosFlat[9] = startY; - }; - - const startBrush = (point) => { - lassoBrushCenterPos.push(point); - }; - - const getNormalizedBrushSize = () => - Math.abs(pointNorm([0, 0])[0] - pointNorm([brushSize / 2, 0])[0]); - - const getBrushNormal = (point1, point2, w) => { - const [x1, y1] = point1; - const [x2, y2] = point2; - - const dx = x1 - x2; - const dy = y1 - y2; - const dn = l2Norm([dx, dy]); - - return [(+dy / dn) * w, (-dx / dn) * w]; - }; - - const extendBrush = (point) => { - const prevPoint = lassoBrushCenterPos.at(-1); - - const width = getNormalizedBrushSize(); - let [nx, ny] = getBrushNormal(point, prevPoint, width); - - const N = lassoBrushCenterPos.length; - - if (N === 1) { - // In this special case, we have to add the initial two points and normal - // because when the first brush point was set the direction is undefined. - const pl = [prevPoint[0] + nx, prevPoint[1] + ny]; - const pr = [prevPoint[0] - nx, prevPoint[1] - ny]; - - lassoPos.push(pl, pr); - lassoPosFlat.push(pl[0], pl[1], pr[0], pr[1]); - lassoBrushNormals.push([nx, ny]); - } else { - // In this case, we have to adjust the previous normal to create a proper - // line join by taking the middle between the current and previous normal. - // const prevPrevPoint = lassoBrushCenterPos.at(-2); - [nx, ny] = getBrushNormal(point, prevPoint, width); - - const nextRawBrushNormals = [...lassoBrushNormals, [nx, ny]]; - - // However, to avoid jittery lines we're smoothing the normal - [nx, ny] = exponentialMovingAverage(nextRawBrushNormals, 1, 10); - - const [pnx, pny] = lassoBrushNormals.at(-1); - - const pnx2 = (nx + pnx) / 2; - const pny2 = (ny + pny) / 2; - - const pl = [prevPoint[0] + pnx2, prevPoint[1] + pny2]; - const pr = [prevPoint[0] - pnx2, prevPoint[1] - pny2]; - - // We're going to replace the previous left and right points - lassoPos.splice(N - 1, 2, pl, pr); - lassoPosFlat.splice(2 * (N - 1), 4, pl[0], pl[1], pr[0], pr[1]); - lassoBrushNormals.splice(N, 1, [pnx2, pny2]); - } - - const pl = [point[0] + nx, point[1] + ny]; - const pr = [point[0] - nx, point[1] - ny]; - - lassoPos.splice(N, 0, pl, pr); - lassoPosFlat.splice(2 * N, 0, pl[0], pl[1], pr[0], pr[1]); - - lassoBrushCenterPos.push(point); - lassoBrushNormals.push([nx, ny]); - }; - - let extendLasso = extendFreeform; - let startLasso = extendFreeform; - - const extend = (currMousePos) => { - if (prevMousePos) { - const d = l2PointDist( - currMousePos[0], - currMousePos[1], - prevMousePos[0], - prevMousePos[1], - ); - - if (d > minDist) { - prevMousePos = currMousePos; - - extendLasso(pointNorm(currMousePos)); - - if (lassoPos.length > 1) { - draw(); - } - } - } else { - if (!isLasso) { - isLasso = true; - onStart(); - } - prevMousePos = currMousePos; - const point = pointNorm(currMousePos); - startLasso(point); - } - }; - - const extendDb = throttleAndDebounce(extend, minDelay, minDelay); - - const extendPublic = (event, debounced) => { - const mousePosition = getMousePosition(event); - if (debounced) { - return extendDb(mousePosition); - } - return extend(mousePosition); - }; - - const clear = () => { - lassoPos = []; - lassoPosFlat = []; - lassoBrushCenterPos = []; - lassoBrushNormals = []; - prevMousePos = undefined; - draw(); - }; - - const initiatorClickHandler = (event) => { - showInitiator(event); - }; - - const initiatorMouseDownHandler = () => { - isMouseDown = true; - isLasso = true; - clear(); - onStart(); - }; - - const initiatorMouseLeaveHandler = () => { - hideInitiator(); - }; - - const end = ({ merge = false, remove = false } = {}) => { - isLasso = false; - - const currLassoPos = [...lassoPos]; - const currLassoPosFlat = [...lassoPosFlat]; - - extendDb.cancel(); - - clear(); - - // When `currLassoPos` is empty the user didn't actually lasso - if (currLassoPos.length > 0) { - onEnd(currLassoPos, currLassoPosFlat, { merge, remove }); - } - - return currLassoPos; - }; - - const setExtendLasso = (newType) => { - switch (newType) { - case 'rectangle': { - type = newType; - extendLasso = extendRectangle; - // This is on purpose. The start of a rectangle & freeform are the same - startLasso = extendFreeform; - break; - } - - case 'brush': { - type = newType; - extendLasso = extendBrush; - startLasso = startBrush; - break; - } - - default: { - type = 'freeform'; - extendLasso = extendFreeform; - startLasso = extendFreeform; - break; - } - } - }; - - const get = (property) => { - if (property === 'onDraw') { - return onDraw; - } - if (property === 'onStart') { - return onStart; - } - if (property === 'onEnd') { - return onEnd; - } - if (property === 'enableInitiator') { - return enableInitiator; - } - if (property === 'minDelay') { - return minDelay; - } - if (property === 'minDist') { - return minDist; - } - if (property === 'pointNorm') { - return pointNorm; - } - if (property === 'type') { - return type; - } - if (property === 'brushSize') { - return brushSize; - } - }; - - const set = ({ - onDraw: newOnDraw = null, - onStart: newOnStart = null, - onEnd: newOnEnd = null, - enableInitiator: newEnableInitiator = null, - initiatorParentElement: newInitiatorParentElement = null, - longPressIndicatorParentElement: newLongPressIndicatorParentElement = null, - minDelay: newMinDelay = null, - minDist: newMinDist = null, - pointNorm: newPointNorm = null, - type: newType = null, - brushSize: newBrushSize = null, - } = {}) => { - onDraw = ifNotNull(newOnDraw, onDraw); - onStart = ifNotNull(newOnStart, onStart); - onEnd = ifNotNull(newOnEnd, onEnd); - enableInitiator = ifNotNull(newEnableInitiator, enableInitiator); - minDelay = ifNotNull(newMinDelay, minDelay); - minDist = ifNotNull(newMinDist, minDist); - pointNorm = ifNotNull(newPointNorm, pointNorm); - brushSize = ifNotNull(newBrushSize, brushSize); - - if ( - newInitiatorParentElement !== null && - newInitiatorParentElement !== initiatorParentElement - ) { - initiatorParentElement.removeChild(initiator); - newInitiatorParentElement.appendChild(initiator); - initiatorParentElement = newInitiatorParentElement; - } - - if ( - newLongPressIndicatorParentElement !== null && - newLongPressIndicatorParentElement !== longPressIndicatorParentElement - ) { - longPressIndicatorParentElement.removeChild(longPress); - newLongPressIndicatorParentElement.appendChild(longPress); - longPressIndicatorParentElement = newLongPressIndicatorParentElement; - } - - if (enableInitiator) { - initiator.addEventListener('click', initiatorClickHandler); - initiator.addEventListener('mousedown', initiatorMouseDownHandler); - initiator.addEventListener('mouseleave', initiatorMouseLeaveHandler); - } else { - initiator.removeEventListener('mousedown', initiatorMouseDownHandler); - initiator.removeEventListener('mouseleave', initiatorMouseLeaveHandler); - } - - if (newType !== null) { - setExtendLasso(newType); - } - }; - - const destroy = () => { - initiatorParentElement.removeChild(initiator); - longPressIndicatorParentElement.removeChild(longPress); - window.removeEventListener('mouseup', mouseUpHandler); - initiator.removeEventListener('click', initiatorClickHandler); - initiator.removeEventListener('mousedown', initiatorMouseDownHandler); - initiator.removeEventListener('mouseleave', initiatorMouseLeaveHandler); - }; - - const withPublicMethods = () => (self) => - assign(self, { - clear, - destroy, - end, - extend: extendPublic, - get, - set, - showInitiator, - hideInitiator, - showLongPressIndicator, - hideLongPressIndicator, - }); - - initiatorParentElement.appendChild(initiator); - longPressIndicatorParentElement.appendChild(longPress); - - set({ - onDraw, - onStart, - onEnd, - enableInitiator, - initiatorParentElement, - type, - brushSize, - }); - - return pipe( - withStaticProperty('initiator', initiator), - withStaticProperty('longPressIndicator', longPress), - withPublicMethods(), - withConstructor(createLasso), - )({}); -}; - -export default createLasso; diff --git a/src/lasso-manager/utils.js b/src/lasso-manager/utils.js deleted file mode 100644 index 689ffc46..00000000 --- a/src/lasso-manager/utils.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Calculates exponential moving average of 2D points - * @param {[number, number][]} values - Array of numbers to average - * @param {number} halfLife - Number of steps after which weight becomes half - * @param {number} windowSize - Maximum number of previous values to consider - * @returns {number} The exponential moving average - */ -export const exponentialMovingAverage = (values, halfLife, windowSize) => { - if (values.length === 0) { - return 0; - } - - if (values.length === 1) { - return values[0]; - } - - // Calculate decay factor from `halfLife` such that weight = 0.5 when the - // step is `halfLife` - const decayBase = 2 ** (-1 / halfLife); - - // Limit to window size - const startIdx = Math.max(0, values.length - windowSize); - const relevantValues = values.slice(startIdx); - - let weightedSumX = 0; - let weightedSumY = 0; - let weightSum = 0; - - // Calculate weighted sum starting from most recent value - for (let i = relevantValues.length - 1; i >= 0; i--) { - const steps = relevantValues.length - 1 - i; - const weight = decayBase ** steps; - - weightedSumX += relevantValues[i][0] * weight; - weightedSumY += relevantValues[i][1] * weight; - weightSum += weight; - } - - return [weightedSumX / weightSum, weightedSumY / weightSum]; -}; diff --git a/src/point-simple.fs b/src/point-simple.fs deleted file mode 100644 index f3261243..00000000 --- a/src/point-simple.fs +++ /dev/null @@ -1,10 +0,0 @@ -const FRAGMENT_SHADER = `precision highp float; - -varying vec4 color; - -void main() { - gl_FragColor = color; -} -`; - -export default FRAGMENT_SHADER; diff --git a/src/point-update.fs b/src/point-update.fs deleted file mode 100644 index 8350e77d..00000000 --- a/src/point-update.fs +++ /dev/null @@ -1,21 +0,0 @@ -const SHADER = `precision highp float; - -uniform sampler2D startStateTex; -uniform sampler2D endStateTex; -uniform float t; - -varying vec2 particleTextureIndex; - -void main() { - // Interpolate x, y, and value - vec3 start = texture2D(startStateTex, particleTextureIndex).xyw; - vec3 end = texture2D(endStateTex, particleTextureIndex).xyw; - vec3 curr = start * (1.0 - t) + end * t; - - // The category cannot be interpolated - float endCategory = texture2D(endStateTex, particleTextureIndex).z; - - gl_FragColor = vec4(curr.xy, endCategory, curr.z); -}`; - -export default SHADER; diff --git a/src/point-update.vs b/src/point-update.vs deleted file mode 100644 index c9c66b6e..00000000 --- a/src/point-update.vs +++ /dev/null @@ -1,13 +0,0 @@ -const SHADER = `precision highp float; - -attribute vec2 position; -varying vec2 particleTextureIndex; - -void main() { - // map normalized device coords to texture coords - particleTextureIndex = 0.5 * (1.0 + position); - - gl_Position = vec4(position, 0, 1); -}`; - -export default SHADER; diff --git a/src/point.fs b/src/point.fs deleted file mode 100644 index 4b6cfecc..00000000 --- a/src/point.fs +++ /dev/null @@ -1,22 +0,0 @@ -const FRAGMENT_SHADER = ` -precision highp float; - -uniform float antiAliasing; - -varying vec4 color; -varying float finalPointSize; - -float linearstep(float edge0, float edge1, float x) { - return clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0); -} - -void main() { - vec2 c = gl_PointCoord * 2.0 - 1.0; - float sdf = length(c) * finalPointSize; - float alpha = linearstep(finalPointSize + antiAliasing, finalPointSize - antiAliasing, sdf); - - gl_FragColor = vec4(color.rgb, alpha * color.a); -} -`; - -export default FRAGMENT_SHADER; diff --git a/src/point.vs b/src/point.vs deleted file mode 100644 index c4cb35cc..00000000 --- a/src/point.vs +++ /dev/null @@ -1,124 +0,0 @@ -const createVertexShader = (globalState) => ` -precision highp float; - -uniform sampler2D colorTex; -uniform float colorTexRes; -uniform float colorTexEps; -uniform sampler2D stateTex; -uniform float stateTexRes; -uniform float stateTexEps; -uniform float devicePixelRatio; -uniform sampler2D encodingTex; -uniform float encodingTexRes; -uniform float encodingTexEps; -uniform float pointSizeExtra; -uniform float pointOpacityMax; -uniform float pointOpacityScale; -uniform float numPoints; -uniform float globalState; -uniform float isColoredByZ; -uniform float isColoredByW; -uniform float isOpacityByZ; -uniform float isOpacityByW; -uniform float isOpacityByDensity; -uniform float isSizedByZ; -uniform float isSizedByW; -uniform float isPixelAligned; -uniform float colorMultiplicator; -uniform float opacityMultiplicator; -uniform float opacityDensity; -uniform float sizeMultiplicator; -uniform float numColorStates; -uniform float pointScale; -uniform float drawingBufferWidth; -uniform float drawingBufferHeight; -uniform mat4 modelViewProjection; - -attribute vec2 stateIndex; - -varying vec4 color; -varying float finalPointSize; - -void main() { - vec4 state = texture2D(stateTex, stateIndex); - - if (isPixelAligned < 0.5) { - gl_Position = modelViewProjection * vec4(state.x, state.y, 0.0, 1.0); - } else { - vec4 clipSpacePosition = modelViewProjection * vec4(state.x, state.y, 0.0, 1.0); - vec2 ndcPosition = clipSpacePosition.xy / clipSpacePosition.w; - vec2 pixelPos = 0.5 * (ndcPosition + 1.0) * vec2(drawingBufferWidth, drawingBufferHeight); - pixelPos = floor(pixelPos + 0.5); // Snap to nearest pixel - vec2 snappedPosition = (pixelPos / vec2(drawingBufferWidth, drawingBufferHeight)) * 2.0 - 1.0; - gl_Position = vec4(snappedPosition, 0.0, 1.0); - } - - - // Determine color index - float colorIndexZ = isColoredByZ * floor(state.z * colorMultiplicator); - float colorIndexW = isColoredByW * floor(state.w * colorMultiplicator); - - // Multiply by the number of color states per color - // I.e., normal, active, hover, background, etc. - float colorIndex = (colorIndexZ + colorIndexW) * numColorStates; - - // Half a "pixel" or "texel" in texture coordinates - float colorLinearIndex = colorIndex + globalState; - - // Need to add cEps here to avoid floating point issue that can lead to - // dramatic changes in which color is loaded as floor(3/2.9999) = 1 but - // floor(3/3.0001) = 0! - float colorRowIndex = floor((colorLinearIndex + colorTexEps) / colorTexRes); - - vec2 colorTexIndex = vec2( - (colorLinearIndex / colorTexRes) - colorRowIndex + colorTexEps, - colorRowIndex / colorTexRes + colorTexEps - ); - - color = texture2D(colorTex, colorTexIndex); - - // Retrieve point size - float pointSizeIndexZ = isSizedByZ * floor(state.z * sizeMultiplicator); - float pointSizeIndexW = isSizedByW * floor(state.w * sizeMultiplicator); - float pointSizeIndex = pointSizeIndexZ + pointSizeIndexW; - - float pointSizeRowIndex = floor((pointSizeIndex + encodingTexEps) / encodingTexRes); - vec2 pointSizeTexIndex = vec2( - (pointSizeIndex / encodingTexRes) - pointSizeRowIndex + encodingTexEps, - pointSizeRowIndex / encodingTexRes + encodingTexEps - ); - float pointSize = texture2D(encodingTex, pointSizeTexIndex).x; - - // Retrieve opacity - ${ - (() => { - // Drawing the inner border of selected points - if (globalState === 3) return ''; - - // Draw points with opacity encoding or dynamic opacity - return ` - if (isOpacityByDensity < 0.5) { - float opacityIndexZ = isOpacityByZ * floor(state.z * opacityMultiplicator); - float opacityIndexW = isOpacityByW * floor(state.w * opacityMultiplicator); - float opacityIndex = opacityIndexZ + opacityIndexW; - - float opacityRowIndex = floor((opacityIndex + encodingTexEps) / encodingTexRes); - vec2 opacityTexIndex = vec2( - (opacityIndex / encodingTexRes) - opacityRowIndex + encodingTexEps, - opacityRowIndex / encodingTexRes + encodingTexEps - ); - color.a = texture2D(encodingTex, opacityTexIndex)[${1 + globalState}]; - } else { - color.a = min(1.0, opacityDensity + globalState); - } - `; - })() - } - - color.a = min(pointOpacityMax, color.a) * pointOpacityScale; - finalPointSize = (pointSize * pointScale) + pointSizeExtra; - gl_PointSize = finalPointSize; -} -`; - -export default createVertexShader; diff --git a/src/renderer.js b/src/renderer.js deleted file mode 100644 index 09a227af..00000000 --- a/src/renderer.js +++ /dev/null @@ -1,250 +0,0 @@ -import { CLEAR_OPTIONS, DEFAULT_GAMMA } from './constants.js'; -import { checkReglExtensions, createRegl } from './utils.js'; - -export const createRenderer = ( - /** @type {Partial} */ options = {}, -) => { - let { - regl, - canvas = document.createElement('canvas'), - gamma = DEFAULT_GAMMA, - } = options; - - let isDestroyed = false; - - if (!regl) { - regl = createRegl(canvas); - } - - const isSupportingAllGlExtensions = checkReglExtensions(regl); - - const fboRes = [canvas.width, canvas.height]; - const fbo = regl.framebuffer({ - width: fboRes[0], - height: fboRes[1], - colorFormat: 'rgba', - colorType: 'float', - }); - - /** - * Render the float32 framebuffer to the internal canvas - * - * From https://observablehq.com/@rreusser/selecting-the-right-opacity-for-2d-point-clouds - */ - const renderToCanvas = regl({ - vert: ` - precision highp float; - attribute vec2 xy; - void main () { - gl_Position = vec4(xy, 0, 1); - }`, - frag: ` - precision highp float; - uniform vec2 srcRes; - uniform sampler2D src; - uniform float gamma; - - vec3 approxLinearToSRGB (vec3 rgb, float gamma) { - return pow(clamp(rgb, vec3(0), vec3(1)), vec3(1.0 / gamma)); - } - - void main () { - vec4 color = texture2D(src, gl_FragCoord.xy / srcRes); - gl_FragColor = vec4(approxLinearToSRGB(color.rgb, gamma), color.a); - }`, - attributes: { - xy: [-4, -4, 4, -4, 0, 4], - }, - uniforms: { - src: () => fbo, - srcRes: () => fboRes, - gamma: () => gamma, - }, - count: 3, - depth: { enable: false }, - blend: { - enable: true, - func: { - srcRGB: 'one', - srcAlpha: 'one', - dstRGB: 'one minus src alpha', - dstAlpha: 'one minus src alpha', - }, - }, - }); - - /** - * Copy the pixels from the internal canvas onto the target canvas - */ - const copyTo = (targetCanvas) => { - const ctx = targetCanvas.getContext('2d'); - ctx.clearRect(0, 0, targetCanvas.width, targetCanvas.height); - ctx.drawImage( - canvas, - (canvas.width - targetCanvas.width) / 2, - (canvas.height - targetCanvas.height) / 2, - targetCanvas.width, - targetCanvas.height, - 0, - 0, - targetCanvas.width, - targetCanvas.height, - ); - }; - - /** - * The render function - */ - const render = ( - /** @type {(): void} */ draw, - /** @type {HTMLCanvasElement} */ targetCanvas, - ) => { - // Clear internal canvas - regl.clear(CLEAR_OPTIONS); - fbo.use(() => { - // Clear framebuffer - regl.clear(CLEAR_OPTIONS); - draw(); - }); - renderToCanvas(); - copyTo(targetCanvas); - }; - - /** - * Update Regl's viewport, drawingBufferWidth, and drawingBufferHeight - * - * @description Call this method after the viewport has changed, e.g., width - * or height have been altered - */ - const refresh = () => { - regl.poll(); - }; - - const drawFns = new Set(); - - /** - * Register an draw function that is going to be invoked on every animation - * frame. - */ - const onFrame = (/** @type {(): void} */ draw) => { - drawFns.add(draw); - return () => { - drawFns.delete(draw); - }; - }; - - const frame = regl.frame(() => { - const iterator = drawFns.values(); - let result = iterator.next(); - while (!result.done) { - result.value(); // The draw function - result = iterator.next(); - } - }); - - const resize = ( - /** @type {number} */ customWidth, - /** @type {number} */ customHeight, - ) => { - // We need to limit the width and height by the screen size to prevent - // a bug in VSCode where the window height is said to be taller than the - // screen height. The problem with too large dimensions is that at some - // point WebGL will break down because there's an upper limit on how large - // any buffer and texture can be. It also harms the performance quite a bit. - // - // By restricting the widht/height to the screen size we should have a safe - // upper limit for the canvas size. - // - // @see - // https://github.com/microsoft/vscode/issues/225808 - // https://github.com/flekschas/jupyter-scatter/issues/37 - const width = - customWidth === undefined - ? Math.min(window.innerWidth, window.screen.availWidth) - : customWidth; - const height = - customHeight === undefined - ? Math.min(window.innerHeight, window.screen.availHeight) - : customHeight; - canvas.width = width * window.devicePixelRatio; - canvas.height = height * window.devicePixelRatio; - fboRes[0] = canvas.width; - fboRes[1] = canvas.height; - fbo.resize(...fboRes); - }; - - const resizeHandler = () => { - resize(); - }; - - if (!options.canvas) { - window.addEventListener('resize', resizeHandler); - window.addEventListener('orientationchange', resizeHandler); - resize(); - } - - /** - * Destroy the renderer to free resources and cancel animation frames - */ - const destroy = () => { - isDestroyed = true; - window.removeEventListener('resize', resizeHandler); - window.removeEventListener('orientationchange', resizeHandler); - frame.cancel(); - canvas = undefined; - regl.destroy(); - regl = undefined; - }; - - return { - /** - * Get the associated canvas element - * @return {HTMLCanvasElement} The associated canvas element - */ - get canvas() { - return canvas; - }, - /** - * Get the associated Regl instance - * @return {import('regl').Regl} The associated Regl instance - */ - get regl() { - return regl; - }, - /** - * Get the gamma value - * @return {number} The gamma value - */ - get gamma() { - return gamma; - }, - /** - * Set gamma to a new value - * @param {number} newGamma - The new gamma value - */ - set gamma(newGamma) { - gamma = +newGamma; - }, - /** - * Get whether the browser supports all necessary WebGL features - * @return {boolean} If `true` the browser supports all necessary WebGL features - */ - get isSupported() { - return isSupportingAllGlExtensions; - }, - /** - * Get whether the renderer (and its Regl instance) is destroyed - * @return {boolean} If `true` the renderer is destroyed - */ - get isDestroyed() { - return isDestroyed; - }, - render, - resize, - onFrame, - refresh, - destroy, - }; -}; - -export default createRenderer; diff --git a/src/spline-curve-worker.js b/src/spline-curve-worker.js deleted file mode 100644 index 616acf65..00000000 --- a/src/spline-curve-worker.js +++ /dev/null @@ -1,268 +0,0 @@ -/* eslint-env worker */ -/* eslint no-restricted-globals: 1 */ - -const worker = function worker() { - const state = {}; - - /** - * Catmull-Rom interpolation - * @param {number} t - Progress value - * @param {array} p0 - First point - * @param {array} p1 - Second point - * @param {array} p2 - Third point - * @param {array} p3 - Forth point - * @return {number} Interpolated value - */ - const catmullRom = (t, p0, p1, p2, p3) => { - const v0 = (p2 - p0) * 0.5; - const v1 = (p3 - p1) * 0.5; - return ( - (2 * p1 - 2 * p2 + v0 + v1) * t * t * t + - (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t * t + - v0 * t + - p1 - ); - }; - - /** - * Interpolate a point with Catmull-Rom - * @param {number} t - Progress value - * @param {array} points - Key points - * @param {number} maxPointIdx - Highest point index. Same as array.length - 1 - * @return {array} Interpolated point - */ - const interpolatePoint = (t, points, maxPointIdx) => { - const p = maxPointIdx * t; - - const intPoint = Math.floor(p); - const weight = p - intPoint; - - const p0 = points[Math.max(0, intPoint - 1)]; - const p1 = points[intPoint]; - const p2 = points[Math.min(maxPointIdx, intPoint + 1)]; - const p3 = points[Math.min(maxPointIdx, intPoint + 2)]; - - return [ - catmullRom(weight, p0[0], p1[0], p2[0], p3[0]), - catmullRom(weight, p0[1], p1[1], p2[1], p3[1]), - ]; - }; - - /** - * Square distance - * @param {number} x1 - First x coordinate - * @param {number} y1 - First y coordinate - * @param {number} x2 - Second x coordinate - * @param {number} y2 - Second y coordinate - * @return {number} Distance - */ - const sqDist = (x1, y1, x2, y2) => (x1 - x2) ** 2 + (y1 - y2) ** 2; - - /** - * Douglas Peucker square segment distance - * Implementation from https://github.com/mourner/simplify-js - * @author Vladimir Agafonkin - * @copyright Vladimir Agafonkin 2013 - * @license BSD - * @param {array} p - Point - * @param {array} p1 - First boundary point - * @param {array} p2 - Second boundary point - * @return {number} Distance - */ - const sqSegDist = (p, p1, p2) => { - let x = p1[0]; - let y = p1[1]; - let dx = p2[0] - x; - let dy = p2[1] - y; - - if (dx !== 0 || dy !== 0) { - const t = ((p[0] - x) * dx + (p[1] - y) * dy) / (dx * dx + dy * dy); - - if (t > 1) { - x = p2[0]; - y = p2[1]; - } else if (t > 0) { - x += dx * t; - y += dy * t; - } - } - - dx = p[0] - x; - dy = p[1] - y; - - return dx * dx + dy * dy; - }; - - /** - * Douglas Peucker step function - * Implementation from https://github.com/mourner/simplify-js - * @author Vladimir Agafonkin - * @copyright Vladimir Agafonkin 2013 - * @license BSD - * @param {[type]} points [description] - * @param {[type]} first [description] - * @param {[type]} last [description] - * @param {[type]} tolerance [description] - * @param {[type]} simplified [description] - * @return {[type]} [description] - */ - const simplifyDPStep = (points, first, last, tolerance, simplified) => { - let maxDist = tolerance; - let index; - - for (let i = first + 1; i < last; i++) { - const dist = sqSegDist(points[i], points[first], points[last]); - - if (dist > maxDist) { - index = i; - maxDist = dist; - } - } - - if (maxDist > tolerance) { - if (index - first > 1) { - simplifyDPStep(points, first, index, tolerance, simplified); - } - simplified.push(points[index]); - if (last - index > 1) { - simplifyDPStep(points, index, last, tolerance, simplified); - } - } - }; - - /** - * Douglas Peucker. Implementation from https://github.com/mourner/simplify-js - * @author Vladimir Agafonkin - * @copyright Vladimir Agafonkin 2013 - * @license BSD - * @param {array} points - List of points to be simplified - * @param {number} tolerance - Tolerance level. Points below this distance level will be ignored - * @return {array} Simplified point list - */ - const simplifyDouglasPeucker = (points, tolerance) => { - const last = points.length - 1; - const simplified = [points[0]]; - - simplifyDPStep(points, 0, last, tolerance, simplified); - simplified.push(points[last]); - - return simplified; - }; - - /** - * Interpolate intermediate points between key points - * @param {array} points - Fixed key points - * @param {number} options.maxIntPointsPerSegment - Maximum number of points between two key points - * @param {number} options.tolerance - Simplification tolerance - * @return {array} Interpolated points including key points - */ - const interpolatePoints = ( - points, - { maxIntPointsPerSegment = 100, tolerance = 0.002 } = {}, - ) => { - const numPoints = points.length; - const maxPointIdx = numPoints - 1; - - const maxOutPoints = maxPointIdx * maxIntPointsPerSegment + 1; - const sqTolerance = tolerance ** 2; - - let outPoints = []; - let prevPoint; - - // Generate interpolated points where the squared-distance between points - // is larger than sqTolerance - for (let i = 0; i < numPoints - 1; i++) { - let segmentPoints = [points[i].slice(0, 2)]; - prevPoint = points[i]; - - for (let j = 1; j < maxIntPointsPerSegment; j++) { - const t = (i * maxIntPointsPerSegment + j) / maxOutPoints; - const intPoint = interpolatePoint(t, points, maxPointIdx); - - // Check squared distance simplification - if ( - sqDist(prevPoint[0], prevPoint[1], intPoint[0], intPoint[1]) > - sqTolerance - ) { - segmentPoints.push(intPoint); - prevPoint = intPoint; - } - } - - // Add next key point. Needed for the simplification algorithm - segmentPoints.push(points[i + 1]); - // Simplify interpolated points using the douglas-peuckner algorithm - segmentPoints = simplifyDouglasPeucker(segmentPoints, sqTolerance); - // Add simplified points without the last key point, which is added - // anyway in the next segment - outPoints = outPoints.concat( - segmentPoints.slice(0, segmentPoints.length - 1), - ); - } - outPoints.push(points[points.length - 1].slice(0, 2)); - - return outPoints.flat(); - }; - - /** - * Group points by line assignment (the fifth component of a point) - * @param {array} points - Flat list of points - * @return {array} List of lists of ordered points by line - */ - const groupPoints = (points) => { - const groupedPoints = {}; - - const isOrdered = !Number.isNaN(+points[0][5]); - points.forEach((point) => { - const segId = point[4]; - - if (!groupedPoints[segId]) { - groupedPoints[segId] = []; - } - - if (isOrdered) { - groupedPoints[segId][point[5]] = point; - } else { - groupedPoints[segId].push(point); - } - }); - - // The filtering ensures that non-existing array entries are removed - Object.entries(groupedPoints).forEach((idPoints) => { - groupedPoints[idPoints[0]] = idPoints[1].filter((v) => v); - // Store the first point as the reference - groupedPoints[idPoints[0]].reference = idPoints[1][0]; - }); - - return groupedPoints; - }; - - self.onmessage = function onmessage(event) { - const numPoints = event.data.points ? +event.data.points.length : 0; - - if (!numPoints) { - self.postMessage({ error: new Error('No points provided') }); - } - - state.points = event.data.points; - - const groupedPoints = groupPoints(event.data.points); - - self.postMessage({ - points: Object.entries(groupedPoints).reduce( - (curvePoints, idAndPoints) => { - curvePoints[idAndPoints[0]] = interpolatePoints( - idAndPoints[1], - event.data.options, - ); - // Make sure the reference is passed on - curvePoints[idAndPoints[0]].reference = idAndPoints[1].reference; - return curvePoints; - }, - {}, - ), - }); - }; -}; - -export default worker; diff --git a/src/spline-curve.js b/src/spline-curve.js deleted file mode 100644 index de541aac..00000000 --- a/src/spline-curve.js +++ /dev/null @@ -1,23 +0,0 @@ -import { createWorker } from '@flekschas/utils'; -import workerFn from './spline-curve-worker.js'; - -const createSplineCurve = ( - points, - options = { tolerance: 0.002, maxIntPointsPerSegment: 100 }, -) => - new Promise((resolve, reject) => { - const worker = createWorker(workerFn); - - worker.onmessage = (e) => { - if (e.data.error) { - reject(e.data.error); - } else { - resolve(e.data.points); - } - worker.terminate(); - }; - - worker.postMessage({ points, options }); - }); - -export default createSplineCurve; diff --git a/src/types.d.ts b/src/types.d.ts deleted file mode 100644 index 87b04d5a..00000000 --- a/src/types.d.ts +++ /dev/null @@ -1,300 +0,0 @@ -type Hex = string; -type Rgb = [number, number, number]; -type Rgba = [number, number, number, number]; - -type Color = Hex | Rgb | Rgba; -type ColorMap = Color | Color[]; - -type Category = 'category' | 'value1' | 'valueA' | 'valueZ' | 'z'; -type Value = 'value' | 'value2' | 'valueB' | 'valueW' | 'w'; -type DataEncoding = Category | Value; -type PointDataEncoding = DataEncoding | 'inherit' | 'segment'; - -type KeyAction = 'lasso' | 'rotate' | 'merge'; -type KeyMap = Record<'alt' | 'cmd' | 'ctrl' | 'meta' | 'shift', KeyAction>; - -type MouseMode = 'panZoom' | 'lasso' | 'rotate'; - -type PointScaleMode = 'constant' | 'asinh' | 'linear'; - -type ZWDataType = 'continuous' | 'categorical'; - -// biome-ignore lint/suspicious/noExplicitAny: Untyped external library -type Camera2D = any; // Needs to be typed at some point -type Scale = import('d3-scale').ScaleContinuousNumeric; - -type PointsObject = { - x: ArrayLike; - y: ArrayLike; - line?: ArrayLike; - lineOrder?: ArrayLike; -} & { - [Key in Category | Value]?: ArrayLike; -}; - -export type Points = number[][] | PointsObject; - -type PointOptions = { - color: ColorMap; - colorActive: Color; - colorHover: Color; - outlineWidth: number; - size: number | number[]; - sizeSelected: number; -}; - -type PointConnectionOptions = { - color: ColorMap; - colorActive: Color; - colorHover: Color; - opacity: number | number[]; - opacityActive: number; - size: number | number[]; - sizeActive: number; - maxIntPointsPerSegment: number; - tolerance: number; - // Nullifiable - colorBy: null | PointDataEncoding; - opacityBy: null | PointDataEncoding; - sizeBy: null | PointDataEncoding; -}; - -type LassoOptions = { - color: Color; - lineWidth: number; - minDelay: number; - minDist: number; - clearEvent: 'lassoEnd' | 'deselect'; - initiator: boolean; - initiatorParentElement: HTMLElement; - onLongPress: boolean; - longPressTime: number; - longPressAfterEffectTime: number; - longPressEffectDelay: number; - longPressRevertEffectTime: number; -}; - -type CameraOptions = { - target: [number, number]; - distance: number; - rotation: number; - view: Float32Array; -}; - -// biome-ignore lint/correctness/noUnusedVariables: Imported from ./index.js -type Rect = { - x: number; - y: number; - width: number; - height: number; -}; - -interface BaseAnnotation { - lineColor?: Color; - lineWidth?: number; -} - -interface AnnotationHLine extends BaseAnnotation { - y: number; - x1?: number; - x2?: number; -} - -interface AnnotationVLine extends BaseAnnotation { - x: number; - y1?: number; - y2?: number; -} - -interface AnnotationDomRect extends BaseAnnotation { - x: number; - y: number; - width: number; - height: number; -} - -interface AnnotationRect extends BaseAnnotation { - x1: number; - y1: number; - x2: number; - y2: number; -} - -interface AnnotationPolygon extends BaseAnnotation { - vertices: [number, number][]; -} - -// biome-ignore lint/correctness/noUnusedVariables: Imported from ./index.js -type Annotation = - | AnnotationHLine - | AnnotationVLine - | AnnotationDomRect - | AnnotationRect - | AnnotationPolygon; - -interface BaseOptions { - backgroundColor: Color; - deselectOnDblClick: boolean; - deselectOnEscape: boolean; - keyMap: KeyMap; - mouseMode: MouseMode; - showPointConnections: boolean; - showReticle: boolean; - reticleColor: Color; - opacity: number | number[]; - opacityByDensityFill: number; - opacityInactiveMax: number; - opacityInactiveScale: number; - height: 'auto' | number; - width: 'auto' | number; - gamma: number; - aspectRatio: number; - annotationLineColor: Color; - annotationLineWidth: number; - annotationHVLineLimit: number; - // Nullifiable - backgroundImage: null | import('regl').Texture2D | string; - colorBy: null | DataEncoding; - sizeBy: null | DataEncoding; - opacityBy: null | DataEncoding; - pointOrder: null | number[]; - xScale: null | Scale; - yScale: null | Scale; - pointScaleMode: PointScaleMode; - cameraIsFixed: boolean; - antiAliasing: number; - pixelAligned: boolean; -} - -export interface CreateKDBushOptions { - node: number; - useWorker: boolean; -} - -/** - * Helper type. Adds a prefix to keys of Options. - * - * type A = { a: number; b: string }; - * WithPrefix<'myPrefix', A> === { myPrefixA: number, myPrefixB: string }; - */ -type WithPrefix< - Name extends string, - Options extends Record, -> = { - [Key in keyof Options as `${Name}${Capitalize}`]: Options[Key]; -}; - -export type Settable = BaseOptions & - WithPrefix<'point', PointOptions> & - WithPrefix<'pointConnection', PointConnectionOptions> & - WithPrefix<'lasso', LassoOptions> & - WithPrefix<'camera', CameraOptions>; - -export type RendererOptions = { - regl: import('regl').Regl; - canvas: HTMLCanvasElement; - gamma: number; -}; - -export type Properties = { - renderer: ReturnType; - canvas: HTMLCanvasElement; - regl: import('regl').Regl; - syncEvents: boolean; - version: string; - lassoInitiatorElement: HTMLElement; - lassoLongPressIndicatorParentElement: HTMLElement; - camera: Camera2D; - performanceMode: boolean; - renderPointsAsSquares: boolean; - disableAlphaBlending: boolean; - opacityByDensityDebounceTime: number; - spatialIndex: ArrayBuffer; - spatialIndexUseWorker: undefined | boolean; - points: [number, number][]; - pointsInView: number[]; - isDestroyed: boolean; - isPointsDrawn: boolean; - isPointsFiltered: boolean; - hoveredPoint: number; - filteredPoints: number[]; - selectedPoints: number[]; -} & Settable; - -// Options for plot.{draw, select, hover} -export interface ScatterplotMethodOptions { - draw: Partial<{ - transition: boolean; - transitionDuration: number; - transitionEasing: (t: number) => number; - preventFilterReset: boolean; - hover: number; - select: number | number[]; - filter: number | number[]; - zDataType: ZWDataType; - wDataType: ZWDataType; - spatialIndex: ArrayBuffer; - }>; - hover: Partial<{ - showReticleOnce: boolean; - preventEvent: boolean; - }>; - select: Partial<{ - merge: boolean; - remove: boolean; - preventEvent: boolean; - }>; - filter: Partial<{ - preventEvent: boolean; - }>; - preventEvent: Partial<{ - preventEvent: boolean; - }>; - zoomToPoints: Partial<{ - padding: number; - transition: boolean; - transitionDuration: number; - transitionEasing: (t: number) => number; - }>; - zoomToArea: Partial<{ - transition: boolean; - transitionDuration: number; - transitionEasing: (t: number) => number; - }>; - zoomToLocation: Partial<{ - transition: boolean; - transitionDuration: number; - transitionEasing: (t: number) => number; - }>; - export: Partial<{ - scale: number; - antiAliasing: number; - pixelAligned: boolean; - }>; -} - -export type Events = import('pub-sub-es').Event< - | 'init' - | 'destroy' - | 'backgroundImageReady' - | 'deselect' - | 'unfilter' - | 'lassoStart' - | 'transitionStart' - | 'pointConnectionsDraw', - undefined -> & - import('pub-sub-es').Event< - 'lassoEnd' | 'lassoExtend', - { coordinates: number[] } - > & - import('pub-sub-es').Event<'pointOver' | 'pointOut', number> & - import('pub-sub-es').Event<'select' | 'focus', { points: number[] }> & - import('pub-sub-es').Event<'points', { points: number[][] }> & - import('pub-sub-es').Event<'transitionEnd', import('regl').Regl> & - import('pub-sub-es').Event< - 'view' | 'draw' | 'drawing', - Pick & { - view: Properties['cameraView']; - } - >; diff --git a/src/utils.js b/src/utils.js deleted file mode 100644 index e671a8cf..00000000 --- a/src/utils.js +++ /dev/null @@ -1,634 +0,0 @@ -import createOriginalRegl from 'regl'; - -import { - DEFAULT_IMAGE_LOAD_TIMEOUT, - GL_EXTENSIONS, - IMAGE_LOAD_ERROR, - W_NAMES, - Z_NAMES, -} from './constants.js'; - -/** - * Get the max value of an array. helper method to be used with `Array.reduce()`. - * @param {number} max Accumulator holding the max value. - * @param {number} x Current value. - * @return {number} Max value. - */ -export const arrayMax = (max, x) => (max > x ? max : x); - -/** - * Check if all GL extensions are supported and enabled and warn otherwise - * @param {import('regl').Regl} regl Regl instance to be tested - * @param {boolean} silent If `true` the function will not print `console.warn` statements - * @return {boolean} If `true` all required GL extensions are supported - */ -export const checkReglExtensions = (regl, silent) => { - if (!regl) { - return false; - } - return GL_EXTENSIONS.reduce((every, extension) => { - if (!regl.hasExtension(extension)) { - if (!silent) { - // biome-ignore lint/suspicious/noConsole: This is a legitimately useful warning - console.warn( - `WebGL: ${extension} extension not supported. Scatterplot might not render properly`, - ); - } - return false; - } - return every; - }, true); -}; - -/** - * Create a new Regl instance with `GL_EXTENSIONS` enables - * @param {HTMLCanvasElement} canvas Canvas element to be rendered on - * @return {import('regl').Regl} New Regl instance - */ -export const createRegl = (canvas) => { - const gl = canvas.getContext('webgl', { - antialias: true, - preserveDrawingBuffer: true, - }); - const extensions = []; - - // Needed to run the tests properly as the headless-gl doesn't support all - // extensions, which is fine for the functional tests. - for (const extension of GL_EXTENSIONS) { - if (gl.getExtension(extension)) { - extensions.push(extension); - } else { - // biome-ignore lint/suspicious/noConsole: This is a legitimately useful warning - console.warn( - `WebGL: ${extension} extension not supported. Scatterplot might not render properly`, - ); - } - } - - return createOriginalRegl({ gl, extensions }); -}; - -/** - * L2 distance between a pair of 2D points - * @param {number} x1 X coordinate of the first point - * @param {number} y1 Y coordinate of the first point - * @param {number} x2 X coordinate of the second point - * @param {number} y2 Y coordinate of the first point - * @return {number} L2 distance - */ -export const dist = (x1, y1, x2, y2) => - Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2); - -/** - * Get the bounding box of a set of 2D positions - * @param {array} positions2d 2D positions to be checked - * @return {array} Quadruple of form `[xMin, yMin, xMax, yMax]` defining the - * bounding box - */ -export const getBBox = (positions2d) => { - let xMin = Number.POSITIVE_INFINITY; - let xMax = Number.NEGATIVE_INFINITY; - let yMin = Number.POSITIVE_INFINITY; - let yMax = Number.NEGATIVE_INFINITY; - - for (let i = 0; i < positions2d.length; i += 2) { - xMin = positions2d[i] < xMin ? positions2d[i] : xMin; - xMax = positions2d[i] > xMax ? positions2d[i] : xMax; - yMin = positions2d[i + 1] < yMin ? positions2d[i + 1] : yMin; - yMax = positions2d[i + 1] > yMax ? positions2d[i + 1] : yMax; - } - - return [xMin, yMin, xMax, yMax]; -}; - -/** - * Test whether a bounding box is actually specifying an area - * @param {array} bBox The bounding box to be checked - * @return {array} `true` if the bounding box is valid - */ -export const isValidBBox = ([xMin, yMin, xMax, yMax]) => - Number.isFinite(xMin) && - Number.isFinite(yMin) && - Number.isFinite(xMax) && - Number.isFinite(yMax) && - xMax - xMin > 0 && - yMax - yMin > 0; - -const REGEX_HEX_TO_RGB = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; - -/** - * Convert a HEX-encoded color to an RGB-encoded color - * @param {string} hex HEX-encoded color string. - * @param {boolean} isNormalize If `true` the returned RGB values will be - * normalized to `[0,1]`. - * @return {array} Triple holding the RGB values. - */ -export const hexToRgb = (hex, isNormalize = false) => - hex - .replace(REGEX_HEX_TO_RGB, (_m, r, g, b) => `#${r}${r}${g}${g}${b}${b}`) - .substring(1) - .match(/.{2}/g) - .map((x) => Number.parseInt(x, 16) / 255 ** isNormalize); - -export const isConditionalArray = (a, condition, { minLength = 0 } = {}) => - Array.isArray(a) && a.length >= minLength && a.every(condition); - -export const isPositiveNumber = (x) => !Number.isNaN(+x) && +x >= 0; - -export const isStrictlyPositiveNumber = (x) => !Number.isNaN(+x) && +x > 0; - -/** - * Create a function to limit choices to a predefined list - * @param {array} choices Array of acceptable choices - * @param {*} defaultOption Default choice - * @return {function} Function limiting the choices - */ -export const limit = (choices, defaultChoice) => (choice) => - choices.indexOf(choice) >= 0 ? choice : defaultChoice; - -/** - * Promised-based image loading - * @param {string} src Remote image source, i.e., a URL - * @param {boolean} isCrossOrigin If `true` allow loading image from a source of another origin. - * @return {Promise} Promise resolving to the image once its loaded - */ -export const loadImage = ( - src, - isCrossOrigin = false, - timeout = DEFAULT_IMAGE_LOAD_TIMEOUT, -) => - new Promise((resolve, reject) => { - const image = new Image(); - if (isCrossOrigin) { - image.crossOrigin = 'anonymous'; - } - image.src = src; - image.onload = () => { - resolve(image); - }; - const rejectPromise = () => { - reject(new Error(IMAGE_LOAD_ERROR)); - }; - image.onerror = rejectPromise; - setTimeout(rejectPromise, timeout); - }); - -/** - * @deprecated Please use `scatterplot.createTextureFromUrl(url)` - * - * Create a Regl texture from an URL. - * @param {import('regl').Regl} regl Regl instance used for creating the texture. - * @param {string} url Source URL of the image. - * @return {Promise} Promise resolving to the texture object. - */ -export const createTextureFromUrl = ( - regl, - url, - timeout = DEFAULT_IMAGE_LOAD_TIMEOUT, -) => - new Promise((resolve, reject) => { - loadImage( - url, - url.indexOf(window.location.origin) !== 0 && url.indexOf('base64') === -1, - timeout, - ) - .then((image) => { - resolve(regl.texture(image)); - }) - .catch((error) => { - reject(error); - }); - }); - -/** - * Convert a HEX-encoded color to an RGBA-encoded color - * @param {string} hex HEX-encoded color string. - * @param {boolean} isNormalize If `true` the returned RGBA values will be - * normalized to `[0,1]`. - * @return {array} Triple holding the RGBA values. - */ -export const hexToRgba = (hex, isNormalize = false) => [ - ...hexToRgb(hex, isNormalize), - 255 ** !isNormalize, -]; - -const REGEX_IS_HEX = /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i; - -/** - * Tests if a string is a valid HEX color encoding - * @param {string} hex HEX-encoded color string. - * @return {boolean} If `true` the string is a valid HEX color encoding. - */ -export const isHex = (hex) => REGEX_IS_HEX.test(hex); - -/** - * Tests if a number is in `[0,1]`. - * @param {number} x Number to be tested. - * @return {boolean} If `true` the number is in `[0,1]`. - */ -export const isNormFloat = (x) => x >= 0 && x <= 1; - -/** - * Tests if an array consist of normalized numbers that are in `[0,1]` only. - * @param {array} a Array to be tested - * @return {boolean} If `true` the array contains only numbers in `[0,1]`. - */ -export const isNormFloatArray = (a) => Array.isArray(a) && a.every(isNormFloat); - -/** - * Computes the cross product to determine the orientation of three points - * @param {number} x1 X-coordinate of first point - * @param {number} y1 Y-coordinate of first point - * @param {number} x2 X-coordinate of second point - * @param {number} y2 Y-coordinate of second point - * @param {number} px X-coordinate of test point - * @param {number} py Y-coordinate of test point - * @return {number} Positive if counterclockwise, negative if clockwise - */ -function crossProduct(x1, y1, x2, y2, px, py) { - return (x2 - x1) * (py - y1) - (px - x1) * (y2 - y1); -} - -/** - * Determines if a point lies within a polygon using the non-zero winding rule. - * This handles self-intersecting polygons and overlapping areas correctly. - * @param {Array} polygon 1D list of vertices defining the polygon [x1,y1,x2,y2,...] - * @param {Array} point Tuple of the form [x,y] to be tested - * @return {boolean} True if point lies within the polygon - */ -export const isPointInPolygon = (polygon, [px, py] = []) => { - let winding = 0; - - for (let i = 0, j = polygon.length - 2; i < polygon.length; i += 2) { - const x1 = polygon[i]; - const y1 = polygon[i + 1]; - const x2 = polygon[j]; - const y2 = polygon[j + 1]; - - if (y1 <= py) { - if (y2 > py) { - const orientation = crossProduct(x1, y1, x2, y2, px, py); - if (orientation > 0) { - winding++; - } - } - } else if (y2 <= py) { - const orientation = crossProduct(x1, y1, x2, y2, px, py); - if (orientation < 0) { - winding--; - } - } - - j = i; - } - - return winding !== 0; -}; - -/** - * Tests if a variable is a string - * @param {*} s Variable to be tested - * @return {boolean} If `true` variable is a string - */ -export const isString = (s) => typeof s === 'string' || s instanceof String; - -/** - * Tests if a number is an interger and in `[0,255]`. - * @param {number} x Number to be tested. - * @return {boolean} If `true` the number is an interger and in `[0,255]`. - */ -export const isUint8 = (x) => Number.isInteger(x) && x >= 0 && x <= 255; - -/** - * Tests if an array consist of Uint8 numbers only. - * @param {array} a Array to be tested. - * @return {boolean} If `true` the array contains only Uint8 numbers. - */ -export const isUint8Array = (a) => Array.isArray(a) && a.every(isUint8); - -/** - * Tests if an array is encoding an RGB color. - * @param {array} rgb Array to be tested - * @return {boolean} If `true` the array hold a triple of Uint8 numbers or - * a triple of normalized floats. - */ -export const isRgb = (rgb) => - rgb.length === 3 && (isNormFloatArray(rgb) || isUint8Array(rgb)); - -/** - * Tests if an array is encoding an RGBA color. - * @param {array} rgb Array to be tested - * @return {boolean} If `true` the array hold a quadruple of Uint8 numbers or - * a quadruple of normalized floats. - */ -export const isRgba = (rgba) => - rgba.length === 4 && (isNormFloatArray(rgba) || isUint8Array(rgba)); - -/** - * Test if a color is multiple colors - * @param {*} color To be tested - * @return {boolean} If `true`, `color` is an array of colors. - */ -export const isMultipleColors = (color) => - Array.isArray(color) && - color.length > 0 && - (Array.isArray(color[0]) || isString(color[0])); - -/** - * Test if two arrays contain the same primitive values - */ -export const isSameElements = (a, b) => - Array.isArray(a) && Array.isArray(b) && a.every((value, i) => value === b[i]); - -/** - * Test if two arrays contain the same RGBA quadruples - */ -export const isSameRgbas = (a, b) => { - if (!(Array.isArray(a) && Array.isArray(b)) || a.length !== b.length) { - return false; - } - - if (a.length === 0) { - return true; - } - - // We need to test whether a and b are arrays of RGBA quadruples - if (!(Array.isArray(a[0]) && Array.isArray(b[0]))) { - return false; - } - - return a.every(([r1, g1, b1, a1], i) => { - const [r2, g2, b2, a2] = b[i]; - return r1 === r2 && g1 === g2 && b1 === b2 && a1 === a2; - }); -}; - -/** - * Fast version of `Math.max`. Based on - * https://jsperf.com/math-min-max-vs-ternary-vs-if/24 `Math.max` is not - * very fast - * @param {number} a Value A - * @param {number} b Value B - * @return {boolean} If `true` A is greater than B. - */ -export const max = (a, b) => (a > b ? a : b); - -/** - * Fast version of `Math.min`. Based on - * https://jsperf.com/math-min-max-vs-ternary-vs-if/24 `Math.max` is not - * very fast - * @param {number} a Value A - * @param {number} b Value B - * @return {boolean} If `true` A is smaller than B. - */ -export const min = (a, b) => (a < b ? a : b); - -/** - * Normalize an array - * @param {array} a Array to be normalized. - * @return {array} Normalized array. - */ -export const normNumArray = (a) => - a.map((x) => x / a.reduce(arrayMax, Number.NEGATIVE_INFINITY)); - -/** - * Convert a color to an RGBA color - * @param {*} color Color to be converted. Currently supports: - * HEX, RGB, or RGBA. - * @param {boolean} isNormalize If `true` the returned RGBA values will be - * normalized to `[0,1]`. - * @return {array} Quadruple defining an RGBA color. - */ -export const toRgba = (color, shouldNormalize) => { - if (isRgba(color)) { - const isNormalized = isNormFloatArray(color); - if ( - (shouldNormalize && isNormalized) || - !(shouldNormalize || isNormalized) - ) { - return color; - } - if (shouldNormalize && !isNormalized) { - return color.map((x) => x / 255); - } - return color.map((x) => x * 255); - } - - if (isRgb(color)) { - const base = 255 ** !shouldNormalize; - const isNormalized = isNormFloatArray(color); - - if ( - (shouldNormalize && isNormalized) || - !(shouldNormalize || isNormalized) - ) { - return [...color, base]; - } - if (shouldNormalize && !isNormalized) { - return [...color.map((x) => x / 255), base]; - } - return [...color.map((x) => x * 255), base]; - } - - if (isHex(color)) { - return hexToRgba(color, shouldNormalize); - } - - // biome-ignore lint/suspicious/noConsole: This is a legitimately useful warning - console.warn( - 'Only HEX, RGB, and RGBA are handled by this function. Returning white instead.', - ); - return shouldNormalize ? [1, 1, 1, 1] : [255, 255, 255, 255]; -}; - -/** - * Flip the key-value pairs of an object - * @param {object} obj - Object to be flipped - * @return {object} Flipped object - */ -export const flipObj = (obj) => - Object.entries(obj).reduce((out, [key, value]) => { - if (out[value]) { - out[value] = [...out[value], key]; - } else { - out[value] = key; - } - return out; - }, {}); - -export const rgbBrightness = (rgb) => - 0.21 * rgb[0] + 0.72 * rgb[1] + 0.07 * rgb[2]; - -/** - * Clip a number between min and max - * @param {number} value - The value to be clipped - * @param {number} minValue - The minimum value - * @param {number} maxValue - The maximum value - * @return {number} The clipped value - */ -export const clip = (value, minValue, maxValue) => - Math.min(maxValue, Math.max(minValue, value)); - -/** - * Convert object- or array-oriented points to array-oriented points - * @param {import('./types').Points} points - The point data - * @return {number[][]} Array-oriented points - */ -export const toArrayOrientedPoints = (points) => - new Promise((resolve, reject) => { - if (!points || Array.isArray(points)) { - resolve(points); - } else { - const length = - Array.isArray(points.x) || ArrayBuffer.isView(points.x) - ? points.x.length - : 0; - - const getX = - (Array.isArray(points.x) || ArrayBuffer.isView(points.x)) && - ((i) => points.x[i]); - const getY = - (Array.isArray(points.y) || ArrayBuffer.isView(points.y)) && - ((i) => points.y[i]); - const getL = - (Array.isArray(points.line) || ArrayBuffer.isView(points.line)) && - ((i) => points.line[i]); - - const getLO = - (Array.isArray(points.lineOrder) || - ArrayBuffer.isView(points.lineOrder)) && - ((i) => points.lineOrder[i]); - - const components = Object.keys(points); - const getZ = (() => { - const z = components.find((c) => Z_NAMES.has(c)); - return ( - z && - (Array.isArray(points[z]) || ArrayBuffer.isView(points[z])) && - ((i) => points[z][i]) - ); - })(); - const getW = (() => { - const w = components.find((c) => W_NAMES.has(c)); - return ( - w && - (Array.isArray(points[w]) || ArrayBuffer.isView(points[w])) && - ((i) => points[w][i]) - ); - })(); - - if (getX && getY && getZ && getW && getL && getLO) { - resolve( - points.x.map((x, i) => [ - x, - getY(i), - getZ(i), - getW(i), - getL(i), - getLO(i), - ]), - ); - } else if (getX && getY && getZ && getW && getL) { - resolve( - Array.from({ length }, (_, i) => [ - getX(i), - getY(i), - getZ(i), - getW(i), - getL(i), - ]), - ); - } else if (getX && getY && getZ && getW) { - resolve( - Array.from({ length }, (_, i) => [ - getX(i), - getY(i), - getZ(i), - getW(i), - ]), - ); - } else if (getX && getY && getZ) { - resolve(Array.from({ length }, (_, i) => [getX(i), getY(i), getZ(i)])); - } else if (getX && getY) { - resolve(Array.from({ length }, (_, i) => [getX(i), getY(i)])); - } else { - reject(new Error('You need to specify at least x and y')); - } - } - }); - -export const isHorizontalLine = (annotation) => - Number.isFinite(annotation.y) && !('x' in annotation); - -export const isVerticalLine = (annotation) => - Number.isFinite(annotation.x) && !('y' in annotation); - -export const isDomRect = (annotation) => - Number.isFinite(annotation.x) && - Number.isFinite(annotation.y) && - Number.isFinite(annotation.width) && - Number.isFinite(annotation.height); - -export const isRect = (annotation) => - Number.isFinite(annotation.x1) && - Number.isFinite(annotation.y1) && - Number.isFinite(annotation.x2) && - Number.isFinite(annotation.x2); - -export const isPolygonAnnotation = (annotation) => - 'vertices' in annotation && annotation.vertices.length > 1; - -/** - * Check if an array is a valid list of 2D vertices - * @param {any} arg - The argument to check - * @returns {boolean} True if argument is an array of [x, y] coordinate pairs - */ -export const isVertices = (arg) => { - if (!Array.isArray(arg) || arg.length < 3) { - return false; - } - - for (const vertex of arg) { - if ( - !Array.isArray(vertex) || - vertex.length !== 2 || - typeof vertex[0] !== 'number' || - typeof vertex[1] !== 'number' - ) { - return false; - } - } - - return true; -}; - -/** - * Ensure a list of vertices forms a closed polygon - * @param {Array<[number, number]>} vertices - Array of [x, y] coordinates - * @returns {Array<[number, number]>} Closed polygon (first vertex repeated at end if needed) - */ -export const verticesToPolygon = (vertices) => { - const polygon = [...vertices]; - const firstVertex = vertices.at(0); - const lastVertex = vertices.at(-1); - if (firstVertex[0] !== lastVertex[0] || firstVertex[1] !== lastVertex[1]) { - polygon.push(firstVertex); - } - return polygon; -}; - -export const insertionSort = (array) => { - const end = array.length; - for (let i = 1; i < end; i++) { - // Choosing the first element in our unsorted subarray - const current = array[i]; - // The last element of our sorted subarray - let j = i - 1; - while (j > -1 && current < array[j]) { - array[j + 1] = array[j]; - j--; - } - array[j + 1] = current; - } - return array; -}; diff --git a/tests/assets/image.jpg b/tests/assets/image.jpg deleted file mode 100644 index bc304e8e..00000000 Binary files a/tests/assets/image.jpg and /dev/null differ diff --git a/tests/constructor.test.js b/tests/constructor.test.js deleted file mode 100644 index eddfcc41..00000000 --- a/tests/constructor.test.js +++ /dev/null @@ -1,201 +0,0 @@ -import '@babel/polyfill'; -import { assert, expect, test } from 'vitest'; -import { isFunction } from '@flekschas/utils'; - -import createScatterplot, { - createRegl, - createRenderer, - createSpatialIndex, - createTextureFromUrl, -} from '../src'; - -import { - DEFAULT_CAMERA_IS_FIXED, - DEFAULT_COLOR_ACTIVE, - DEFAULT_COLOR_BG, - DEFAULT_COLOR_HOVER, - DEFAULT_COLOR_NORMAL, - DEFAULT_GAMMA, - DEFAULT_HEIGHT, - DEFAULT_LASSO_BRUSH_SIZE, - DEFAULT_LASSO_TYPE, - DEFAULT_OPACITY, - DEFAULT_OPACITY_INACTIVE_MAX, - DEFAULT_OPACITY_INACTIVE_SCALE, - DEFAULT_POINT_OUTLINE_WIDTH, - DEFAULT_POINT_SIZE, - DEFAULT_POINT_SIZE_SELECTED, - DEFAULT_WIDTH, - IMAGE_LOAD_ERROR, -} from '../src/constants'; - -import { - createCanvas, - flatArrayEqual, -} from './utils'; - -import imageUrl from './assets/image.jpg'; - -const EPS = 1e-7; - -const floatEqual = (a, b) => Math.abs(a - b) <= EPS; - -test('createRegl()', () => { - const dim = 200; - const canvas = createCanvas(dim, dim); - const gl = canvas.getContext('webgl'); - - expect(gl.drawingBufferWidth).toBe(dim); - expect(gl.drawingBufferHeight).toBe(dim); - - const regl = createRegl(canvas); - - expect(regl).toBeDefined(); - - regl.destroy(); -}); - -test('createScatterplot()', () => { - const canvas = createCanvas(null, null); - const scatterplot = createScatterplot({ canvas }); - - expect(scatterplot.get('canvas')).toBe(canvas); - expect(scatterplot.get('backgroundColor')).toBe(DEFAULT_COLOR_BG); - expect(scatterplot.get('pointColor')).toBe(DEFAULT_COLOR_NORMAL); - expect(scatterplot.get('pointColorActive')).toBe(DEFAULT_COLOR_ACTIVE); - expect(scatterplot.get('pointColorHover')).toBe(DEFAULT_COLOR_HOVER); - expect(scatterplot.get('pointSize')).toBe(DEFAULT_POINT_SIZE); - expect(scatterplot.get('pointSizeSelected')).toBe(DEFAULT_POINT_SIZE_SELECTED); - expect(scatterplot.get('pointOutlineWidth')).toBe(DEFAULT_POINT_OUTLINE_WIDTH); - expect(scatterplot.get('opacity')).toBe(DEFAULT_OPACITY); - expect(scatterplot.get('opacityInactiveMax')).toBe(DEFAULT_OPACITY_INACTIVE_MAX); - expect(scatterplot.get('opacityInactiveScale')).toBe(DEFAULT_OPACITY_INACTIVE_SCALE); - expect(scatterplot.get('width')).toBe(DEFAULT_WIDTH); - expect(scatterplot.get('height')).toBe(DEFAULT_HEIGHT); - expect(scatterplot.get('opacityInactiveMax')).toBe(DEFAULT_OPACITY_INACTIVE_MAX); - expect(scatterplot.get('opacityInactiveScale')).toBe(DEFAULT_OPACITY_INACTIVE_SCALE); - expect(scatterplot.get('width')).toBe(DEFAULT_WIDTH); - expect(scatterplot.get('height')).toBe(DEFAULT_HEIGHT); - expect(scatterplot.get('cameraIsFixed')).toBe(DEFAULT_CAMERA_IS_FIXED); - expect(scatterplot.get('lassoType')).toBe(DEFAULT_LASSO_TYPE); - expect(scatterplot.get('lassoBrushSize')).toBe(DEFAULT_LASSO_BRUSH_SIZE); - - scatterplot.destroy(); -}); - -test('createScatterplot({ cameraTarget, cameraDistance, cameraRotation, cameraView })', () => { - const cameraTarget = [1, 1]; - const cameraDistance = 2; - const cameraRotation = Math.PI / 4; - const scatterplot = createScatterplot({ - cameraTarget, - cameraDistance, - cameraRotation, - }); - - expect(flatArrayEqual([1, 1], scatterplot.get('cameraTarget'), floatEqual)).toBe(true); - expect(floatEqual(cameraDistance, scatterplot.get('cameraDistance'))).toBe(true); - expect(floatEqual(cameraRotation, scatterplot.get('cameraRotation'))).toBe(true); - - // biome-ignore format: the array should not be formatted - const cameraView = new Float32Array([ - 0.5, 0, 0, 0.5, - 0, 0.5, 0, 0.5, - 0, 0, 0.5, 0, - 0, 0, 0, 1, - ]); - const scatterplot2 = createScatterplot({ cameraView }); - - expect(cameraView).toEqual(scatterplot2.get('cameraView')); - - scatterplot.destroy(); - scatterplot2.destroy(); -}); - -test('createTextureFromUrl()', async ({ skip }) => { - const regl = createRegl(createCanvas()); - - try { - const texture = await createTextureFromUrl(regl, imageUrl); - - expect(texture._reglType).toBe('texture2d'); - } catch (e) { - if (e.message === IMAGE_LOAD_ERROR) { - skip('Skipping because image loading timed out'); - } else { - assert.fail('Failed to load image from URL'); - } - } - - regl.destroy(); -}); - -test('createRenderer()', () => { - const canvas = createCanvas(); - const regl = createRegl(canvas); - const renderer = createRenderer({ canvas, regl }); - - expect(!!renderer).toBe(true); - expect(renderer.canvas).toBe(canvas); - expect(renderer.regl).toBe(regl); - expect(renderer.gamma).toBe(DEFAULT_GAMMA); - expect(isFunction(renderer.render)).toBe(true); - expect(isFunction(renderer.onFrame)).toBe(true); - expect(isFunction(renderer.refresh)).toBe(true); - expect(isFunction(renderer.destroy)).toBe(true); - - const sp1 = createScatterplot({ renderer }); - const sp2 = createScatterplot({ renderer }); - - expect(sp1.get('renderer')).toBe(renderer); - expect(sp2.get('renderer')).toBe(renderer); - - sp1.destroy(); - sp2.destroy(); - - // Renderer should have not been destroyed - expect(renderer.canvas).toBe(canvas); - expect(renderer.regl).toBe(regl); - - const sp3 = createScatterplot({ renderer }); - expect(sp3.get('renderer')).toBe(renderer); - - renderer.gamma = 10; - expect(renderer.gamma).toBe(10); - - sp3.destroy(); - renderer.destroy(); - - // Now the renderer should have been destroyed - expect(renderer.canvas).toBeUndefined(); - expect(renderer.regl).toBeUndefined(); -}); - -test('createSpatialIndex', async () => { - const points = { - x: [-1, 1, 0, -1, 1], - y: [1, 1, 0, -1, -1], - z: [0.2, 0.4, 0.6, 0.8, 1], - }; - - const spatialIndex1 = await createSpatialIndex(points); - const spatialIndex2 = await createSpatialIndex(points, { - useWorker: true, - }); - - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - await scatterplot.draw(points, { spatialIndex: spatialIndex1 }); - - await scatterplot.zoomToArea({ x: 0, y: 0, width: 1, height: 1 }); - - expect(scatterplot.get('pointsInView')).toEqual([1, 2]); - - await scatterplot.draw(points, { spatialIndex: spatialIndex2 }); - - await scatterplot.zoomToArea({ x: -1, y: -1, width: 1, height: 1 }); - - expect(scatterplot.get('pointsInView')).toEqual([2, 3]); - - scatterplot.destroy(); -}); diff --git a/tests/events.test.js b/tests/events.test.js deleted file mode 100644 index d77436c2..00000000 --- a/tests/events.test.js +++ /dev/null @@ -1,964 +0,0 @@ -import '@babel/polyfill'; -import { assert, expect, test } from 'vitest'; -import { scaleLinear } from 'd3-scale'; -import { mat4 } from 'gl-matrix'; -import { nextAnimationFrame } from '@flekschas/utils'; - -import createScatterplot from '../src'; - -import { - DEFAULT_LASSO_MIN_DELAY, - DEFAULT_LASSO_MIN_DIST, - KEY_ACTION_LASSO, - KEY_ACTION_ROTATE, - SINGLE_CLICK_DELAY, - CONTINUOUS, - CATEGORICAL, -} from '../src/constants'; - -import { - asyncForEach, - createCanvas, - createMouseEvent, - createKeyboardEvent, - wait, - capitalize, -} from './utils'; - -test('init and destroy events', async () => { - const canvas = createCanvas(200, 200); - const scatterplot = createScatterplot({ - canvas, - width: 200, - height: 200, - }); - - const whenInit = new Promise((resolve) => { - scatterplot.subscribe('init', () => resolve(true), 1); - }); - const whenDestroy = new Promise((resolve) => { - scatterplot.subscribe('destroy', () => resolve(true), 1); - }); - - await expect(whenInit).resolves.toBe(true); - - scatterplot.destroy(); - - await expect(whenDestroy).resolves.toBe(true); -}); - -test('throw an error when calling draw() after destroy()', async () => { - const canvas = createCanvas(200, 200); - const scatterplot = createScatterplot({ - canvas, - width: 200, - height: 200, - }); - - await scatterplot.draw([[0, 0]]); - - scatterplot.destroy(); - - try { - await scatterplot.draw([[0, 0]]); - assert.fail( - 'should have thrown an error because the scatterplot instance is destroyed' - ); - } catch (e) { - expect(e.message).toBe('The instance was already destroyed'); - } -}); - -test('test that `isPointsDrawn` is set correctly', async () => { - const canvas = createCanvas(200, 200); - const scatterplot = createScatterplot({ - canvas, - width: 200, - height: 200, - }); - - expect(scatterplot.get('isPointsDrawn')).toBe(false); - expect(scatterplot.get('isDestroyed')).toBe(false); - - await scatterplot.draw([[0, 0]]); - - expect(scatterplot.get('isPointsDrawn')).toBe(true); - - scatterplot.destroy(); - - expect(scatterplot.get('isDestroyed')).toBe(true); - expect(scatterplot.get('isPointsDrawn')).toBe(false); -}); - -test('do _not_ throw an error when calling draw() _before_ destroy()', async () => { - const canvas = createCanvas(200, 200); - const scatterplot = createScatterplot({ - canvas, - width: 200, - height: 200, - }); - - let numDraws = 0; - scatterplot.subscribe('draw', () => ++numDraws); - - scatterplot.draw([[0, 0]]); - scatterplot.destroy(); - - // draw call should have been canceled due to the destroy call - expect(numDraws).toBe(0); -}); - -test('test that draw() recognized the correct data type of z and w', async () => { - const canvas = createCanvas(200, 200); - const scatterplot = createScatterplot({ - canvas, - width: 200, - height: 200, - }); - - await scatterplot.draw([[0, 0]]); - - expect(scatterplot.get('zDataType')).toBe(CATEGORICAL); - expect(scatterplot.get('wDataType')).toBe(CATEGORICAL); - - await scatterplot.draw([[0, 0, 1, 1]]); - - expect(scatterplot.get('zDataType')).toBe(CATEGORICAL); - expect(scatterplot.get('wDataType')).toBe(CATEGORICAL); - - await scatterplot.draw([ - [0, 0, 0, 0], - [0, 0, 1, 1], - ]); - - expect(scatterplot.get('zDataType')).toBe(CATEGORICAL); - expect(scatterplot.get('wDataType')).toBe(CATEGORICAL); - - await scatterplot.draw([ - [0, 0, 0, 0], - [0, 0, 1, 1], - [0, 0, 10, 10], - ]); - - expect(scatterplot.get('zDataType')).toBe(CATEGORICAL); - expect(scatterplot.get('wDataType')).toBe(CATEGORICAL); - - await scatterplot.draw([[0, 0, 0.5, 0.5]]); - - expect(scatterplot.get('zDataType')).toBe(CONTINUOUS); - expect(scatterplot.get('wDataType')).toBe(CONTINUOUS); - - await scatterplot.draw([ - [0, 0, 0, 0], - [0, 0, 0.5, 0.5], - [0, 0, 1, 1], - ]); - - expect(scatterplot.get('zDataType')).toBe(CONTINUOUS); - expect(scatterplot.get('wDataType')).toBe(CONTINUOUS); - - await scatterplot.draw( - [ - [0, 0, 0, 0], - [0, 0, 1, 1], - ], - { zDataType: CONTINUOUS, wDataType: CONTINUOUS } - ); - - expect(scatterplot.get('zDataType')).toBe(CONTINUOUS); - expect(scatterplot.get('wDataType')).toBe(CONTINUOUS); - - await scatterplot.draw([[0, 0, 0.5, 1]]); - - expect(scatterplot.get('zDataType')).toBe(CONTINUOUS); - expect(scatterplot.get('wDataType')).toBe(CATEGORICAL); - - await scatterplot.draw([[0, 0, 1, 0.5]]); - - expect(scatterplot.get('zDataType')).toBe(CATEGORICAL); - expect(scatterplot.get('wDataType')).toBe(CONTINUOUS); - - scatterplot.destroy(); -}); - -test('test drawing point connections via `showLineConnections`', async () => { - const scatterplot = createScatterplot({ - canvas: createCanvas(200, 200), - width: 200, - height: 200, - showPointConnections: true, - }); - - let numConnectionsDraws = 0; - scatterplot.subscribe('pointConnectionsDraw', () => { - ++numConnectionsDraws; - }); - - await scatterplot.draw( - new Array(10) - .fill() - .map((_, i) => [ - -1 + (i / 6) * 2, // x - -1 + Math.random() * 2, // y - i, // category - 1, // group - 0, // line group - ]) - ); - await wait(0); - - expect(numConnectionsDraws).toBe(1); - - await scatterplot.draw( - new Array(10) - .fill() - .map((e, i) => [ - -1 + (i / 6) * 2, - -1 + Math.random() * 2, - i, - 1, - i % 5, - ]) - ); - await wait(0); - - expect(numConnectionsDraws).toBe(2); - - scatterplot.destroy(); -}); - -test('draw(), clear(), publish("select")', async () => { - const dim = 200; - const hdim = dim / 2; - const canvas = createCanvas(dim, dim); - const scatterplot = createScatterplot({ - canvas, - width: dim, - height: dim, - }); - - const points = [ - [0, 0], - [1, 1], - [1, -1], - [-1, -1], - [-1, 1], - ]; - await scatterplot.draw(points); - // The second draw call should not block the drawing of the points! - // This test is related to a previous issue caused by `drawRaf` as `withRaf` - // overwrites previous arguments. While that is normally expected, this - // should not overwrite the points from above - await scatterplot.draw(); - - let selectedPoints = []; - const selectHandler = ({ points: newSelectedPoints }) => { - selectedPoints = [...newSelectedPoints]; - }; - const deselectHandler = () => { - selectedPoints = []; - }; - // Event names should be case insensitive. Let's test it - scatterplot.subscribe('sElEcT', selectHandler); - scatterplot.subscribe('deselect', deselectHandler); - - // Test single selection via mouse clicks - canvas.dispatchEvent( - createMouseEvent('mousedown', hdim, hdim, { buttons: 1 }) - ); - canvas.dispatchEvent(createMouseEvent('click', hdim, hdim)); - - await wait(0); - - expect(selectedPoints.length).toBe(1); - expect(selectedPoints[0]).toBe(0); - - // Test deselection - canvas.dispatchEvent(createMouseEvent('dblclick', hdim, hdim)); - - await wait(0); - - expect(selectedPoints.length).toBe(0); - - // Test that mousedown + mousemove + click is not interpreted as a click when - // the cursor moved more than `DEFAULT_LASSO_MIN_DIST` in between mousedown and - // mouseup - canvas.dispatchEvent( - createMouseEvent('mousedown', hdim - DEFAULT_LASSO_MIN_DIST, hdim, { - buttons: 1, - }) - ); - canvas.dispatchEvent(createMouseEvent('click', hdim, hdim)); - - await wait(0); - - expect(selectedPoints.length).toBe(0); - - // Test that clearing the points works. The selection that worked previously - // should not work anymore - scatterplot.clear(); - window.dispatchEvent( - createMouseEvent('mousedown', hdim, hdim, { buttons: 1 }) - ); - canvas.dispatchEvent(createMouseEvent('click', hdim, hdim)); - - await wait(0); - - expect(selectedPoints.length).toBe(0); - - scatterplot.destroy(); -}); - -test( - 'lasso selection (with events: select, lassoStart, lassoExtend, and lassoEnd)', - async () => { - const dim = 200; - const hdim = dim / 2; - const canvas = createCanvas(dim, dim); - const scatterplot = createScatterplot({ - canvas, - width: dim, - height: dim, - }); - - const points = [ - [0, 0], - [1, 1], - [1, -1], - [-1, -1], - [-1, 1], - ]; - await scatterplot.draw(points); - - let selectedPoints = []; - const selectHandler = ({ points: newSelectedPoints }) => { - selectedPoints = [...newSelectedPoints]; - }; - const deselectHandler = () => { - selectedPoints = []; - }; - scatterplot.subscribe('select', selectHandler); - scatterplot.subscribe('deselect', deselectHandler); - - let lassoStartCount = 0; - let lassoExtendCount = 0; - let lassoEndCount = 0; - let lassoEndCoordinates = []; - scatterplot.subscribe('lassoStart', () => ++lassoStartCount); - scatterplot.subscribe('lassoExtend', () => ++lassoExtendCount); - scatterplot.subscribe('lassoEnd', ({ coordinates }) => { - ++lassoEndCount; - lassoEndCoordinates = coordinates; - }); - - const [_, lassoKey] = Object.entries(scatterplot.get('keyMap')).find( - ([action]) => action === KEY_ACTION_LASSO - ); - - // Test multi selections via mousedown + mousemove - canvas.dispatchEvent( - createMouseEvent('mousedown', dim * 1.125, hdim, { - [`${lassoKey}Key`]: true, - buttons: 1, - }) - ); - - // Needed to first digest the mousedown event - await wait(0); - - const mousePositions = [ - [dim * 1.125, hdim], - [hdim, -dim * 0.125], - [-dim * 0.125, -dim * 0.125], - [-dim * 0.125, dim * 0.125], - [0, dim * 0.9], - [dim * 0.1, dim * 0.9], - [dim * 0.1, dim * 1.125], - [dim * 1.125, dim * 1.125], - ]; - - await asyncForEach(mousePositions, async (mousePosition) => { - window.dispatchEvent(createMouseEvent('mousemove', ...mousePosition)); - await wait(DEFAULT_LASSO_MIN_DELAY + 5); - }); - - window.dispatchEvent(createMouseEvent('mouseup')); - - await wait(0); - - expect(selectedPoints.length).toBe(3); - expect(selectedPoints).toEqual([0, 2, 4]); - - expect(lassoStartCount).toBe(1); - expect(lassoExtendCount).toBe(mousePositions.length); - expect(lassoEndCoordinates.length).toBe(mousePositions.length); - expect(lassoEndCount).toBe(1); - - scatterplot.destroy(); - } -); - -test('disable lasso selection', async () => { - const dim = 200; - const hdim = dim / 2; - const canvas = createCanvas(dim, dim); - const scatterplot = createScatterplot({ - canvas, - width: dim, - height: dim, - keyMap: {}, - }); - - await scatterplot.draw([[0, 0]]); - - let selectedPoints = []; - scatterplot.subscribe('select', ({ points: newSelectedPoints }) => { - selectedPoints = [...newSelectedPoints]; - }); - - let lassoStartCount = 0; - scatterplot.subscribe('lassoStart', () => ++lassoStartCount); - - expect(Object.entries(scatterplot.get('actionKeyMap')).length).toBe(0); - - // Test multi selections via mousedown + mousemove - canvas.dispatchEvent( - createMouseEvent('mousedown', dim * 1.125, hdim, { - buttons: 1, - altKey: true, - ctrlKey: true, - metaKey: true, - shiftKey: true, - }) - ); - - // Needed to first digest the mousedown event - await wait(0); - - const mousePositions = [ - [dim * 1.125, hdim], - [hdim, -dim * 0.125], - [-dim * 0.125, -dim * 0.125], - [-dim * 0.125, dim * 0.125], - [0, dim * 0.9], - [dim * 0.1, dim * 0.9], - [dim * 0.1, dim * 1.125], - [dim * 1.125, dim * 1.125], - ]; - - await asyncForEach(mousePositions, async (mousePosition) => { - window.dispatchEvent(createMouseEvent('mousemove', ...mousePosition)); - await wait(DEFAULT_LASSO_MIN_DELAY + 5); - }); - - window.dispatchEvent(createMouseEvent('mouseup')); - - await wait(0); - - expect(lassoStartCount).toBe(0); - expect(selectedPoints.length).toBe(0); - - scatterplot.destroy(); -}); - -test('test lasso selection via the initiator', async () => { - const dim = 200; - const hdim = dim / 2; - const canvas = createCanvas(dim, dim); - const scatterplot = createScatterplot({ - canvas, - width: dim, - height: dim, - lassoInitiator: false, - }); - - await scatterplot.draw([ - [0, 0], - [1, 1], - [1, -1], - [-1, -1], - [-1, 1], - ]); - - let selectedPoints = []; - scatterplot.subscribe('select', ({ points: newSelectedPoints }) => { - selectedPoints = [...newSelectedPoints]; - }); - - const lassoIniatorElement = scatterplot.get('lassoInitiatorElement'); - - expect(scatterplot.get('lassoInitiator')).toBe(false); - expect(lassoIniatorElement.id.startsWith('lasso-initiator')).toBe(true); - expect(scatterplot.get('lassoInitiatorParentElement')).toBe(document.body); - - canvas.dispatchEvent(createMouseEvent('click', dim * 1.125, hdim)); - - // We need to wait for the click delay and some extra milliseconds for - // the circle to appear - await wait(SINGLE_CLICK_DELAY + 50); - - lassoIniatorElement.dispatchEvent( - createMouseEvent('mousedown', dim * 1.125, hdim, { buttons: 1 }) - ); - await wait(0); - - const mousePositions = [ - [dim * 1.125, hdim], - [hdim, -dim * 0.125], - [-dim * 0.125, -dim * 0.125], - [-dim * 0.125, dim * 0.125], - [0, dim * 0.9], - [dim * 0.1, dim * 0.9], - [dim * 0.1, dim * 1.125], - [dim * 1.125, dim * 1.125], - ]; - - await asyncForEach(mousePositions, async (mousePosition) => { - window.dispatchEvent(createMouseEvent('mousemove', ...mousePosition)); - await wait(DEFAULT_LASSO_MIN_DELAY + 5); - }); - - window.dispatchEvent(createMouseEvent('mouseup')); - - await wait(0); - - expect(selectedPoints.length).toBe(0); - - scatterplot.set({ lassoInitiator: true }); - - await wait(0); - - expect(scatterplot.get('lassoInitiator')).toBe(true); - - canvas.dispatchEvent( - createMouseEvent('mousedown', dim * 1.125, hdim, { buttons: 1 }) - ); - await wait(0); - canvas.dispatchEvent(createMouseEvent('click', dim * 1.125, hdim)); - - // We need to wait for the click delay and some extra milliseconds for - // the circle to appear - await wait(SINGLE_CLICK_DELAY + 50); - - lassoIniatorElement.dispatchEvent( - createMouseEvent('mousedown', dim * 1.125, hdim, { buttons: 1 }) - ); - await wait(0); - - await asyncForEach(mousePositions, async (mousePosition) => { - window.dispatchEvent(createMouseEvent('mousemove', ...mousePosition)); - await wait(DEFAULT_LASSO_MIN_DELAY + 5); - }); - - window.dispatchEvent(createMouseEvent('mouseup')); - - await wait(0); - - expect(selectedPoints).toEqual([0, 2, 4]); - - scatterplot.destroy(); -}); - -test('test brush lasso selection', async () => { - const dim = 200; - const hdim = dim / 2; - const qdim = dim / 4; - const canvas = createCanvas(dim, dim); - const scatterplot = createScatterplot({ - canvas, - width: dim, - height: dim, - lassoInitiator: true, - lassoType: 'brush', - }); - - await scatterplot.draw([ - [0, 0], - [1, 1], - [1, -1], - [-1, -1], - [-1, 1], - [0, 0.5], - [0.5, 0], - [0, -0.5], - [-0.5, 0], - ]); - - const lassoIniatorElement = scatterplot.get('lassoInitiatorElement'); - - let selectedPoints = []; - scatterplot.subscribe('select', ({ points: newSelectedPoints }) => { - selectedPoints = [...newSelectedPoints]; - }); - - canvas.dispatchEvent(createMouseEvent('click', qdim, qdim)); - - // We need to wait for the click delay and some extra milliseconds for - // the circle to appear - await wait(SINGLE_CLICK_DELAY + 50); - - lassoIniatorElement.dispatchEvent( - createMouseEvent('mousedown', qdim, qdim, { buttons: 1 }) - ); - await wait(0); - - const mousePositions = [ - [qdim, qdim], - [hdim + qdim, qdim], - [hdim + qdim, hdim + qdim], - [qdim, hdim + qdim], - [qdim, qdim], - ]; - - for (const mousePosition of mousePositions) { - window.dispatchEvent(createMouseEvent('mousemove', ...mousePosition)); - await wait(DEFAULT_LASSO_MIN_DELAY + 5); - } - - window.dispatchEvent(createMouseEvent('mouseup')); - - await wait(0); - - expect(selectedPoints).toEqual([5, 6, 7, 8]); - - scatterplot.destroy(); -}); - -test('test rectangle lasso selection', async () => { - const dim = 200; - const hdim = dim / 2; - const canvas = createCanvas(dim, dim); - const scatterplot = createScatterplot({ - canvas, - width: dim, - height: dim, - lassoInitiator: true, - lassoType: 'rectangle', - }); - - await scatterplot.draw([ - [0, 0], - [1, 1], - [1, -1], - [0, -1], - [-1, -1], - [-1, 1], - ]); - - const lassoIniatorElement = scatterplot.get('lassoInitiatorElement'); - - let selectedPoints = []; - scatterplot.subscribe('select', ({ points: newSelectedPoints }) => { - selectedPoints = [...newSelectedPoints]; - }); - - canvas.dispatchEvent(createMouseEvent('click', hdim - 10, hdim - 10)); - - // We need to wait for the click delay and some extra milliseconds for - // the circle to appear - await wait(SINGLE_CLICK_DELAY + 50); - - lassoIniatorElement.dispatchEvent( - createMouseEvent('mousedown', hdim - 10, hdim - 10, { buttons: 1 }) - ); - await wait(0); - - const mousePositions = [ - [hdim - 10, hdim - 10], - [dim + 10, dim + 10], - ]; - - for (const mousePosition of mousePositions) { - window.dispatchEvent(createMouseEvent('mousemove', ...mousePosition)); - await wait(DEFAULT_LASSO_MIN_DELAY + 5); - } - - window.dispatchEvent(createMouseEvent('mouseup')); - - await wait(0); - - expect(selectedPoints).toEqual([0, 2, 3]); - - scatterplot.destroy(); -}); - -test('test rotation', async () => { - const dim = 200; - const hdim = dim / 2; - const canvas = createCanvas(dim, dim); - const scatterplot = createScatterplot({ - canvas, - width: dim, - height: dim, - // keyMap: { alt: 'rotate', shift: 'lasso', cmd: 'merge' } - }); - - await scatterplot.draw([[0, 0]]); - - const initialRotation = scatterplot.get('cameraRotation'); - expect(initialRotation).toBe(0); - - let rotation; - const viewHandler = ({ camera }) => { - rotation = camera.rotation; - }; - scatterplot.subscribe('view', viewHandler); - - let [_, rotateKey] = Object.entries(scatterplot.get('actionKeyMap')).find( - ([action]) => action === KEY_ACTION_ROTATE - ); - - // Test rotation via keydown + mousedown + mousemove + keydown - window.dispatchEvent(createMouseEvent('mousemove', dim * 0.75, hdim)); - await nextAnimationFrame(); - await wait(0); - - window.dispatchEvent( - createKeyboardEvent('keydown', capitalize(rotateKey), { - [`${rotateKey}Key`]: true, - }) - ); - await wait(0); - - canvas.dispatchEvent( - createMouseEvent('mousedown', dim * 0.75, hdim, { - [`${rotateKey}Key`]: true, - buttons: 1, - }) - ); - - await wait(0); - - const mousePositions = [ - [dim * 0.75, hdim], - [dim * 0.75, hdim * 0.5], - ]; - - let whenDrawn = new Promise((resolve) => { - scatterplot.subscribe('draw', resolve, 1); - }); - - await asyncForEach(mousePositions, async (mousePosition) => { - window.dispatchEvent(createMouseEvent('mousemove', ...mousePosition)); - await wait(DEFAULT_LASSO_MIN_DELAY + 5); - }); - - // We need to ensure that the camera's tick() function was called before - // we release the mouse via the mouseup event - await nextAnimationFrame(); - await wait(0); - - window.dispatchEvent(createMouseEvent('mouseup')); - window.dispatchEvent( - createKeyboardEvent('keyup', capitalize(rotateKey), { - [`${rotateKey}Key`]: true, - }) - ); - - await whenDrawn; - await wait(10); - - expect(initialRotation !== rotation && Number.isFinite(rotation)).toBe(true); - - const lastRotation = rotation; - const oldRotateKey = rotateKey; - - rotateKey = 'shift'; - scatterplot.set({ keyMap: { [rotateKey]: 'rotate' } }); - - // Needed to first digest the keyMap change - await wait(10); - - // Test rotation via mousedown + mousemove + keydown - window.dispatchEvent(createMouseEvent('mousemove', dim * 0.75, hdim)); - await nextAnimationFrame(); - await wait(0); - - window.dispatchEvent( - createKeyboardEvent('keydown', capitalize(oldRotateKey), { - [`${oldRotateKey}Key`]: true, - }) - ); - await wait(0); - - canvas.dispatchEvent( - createMouseEvent('mousedown', dim * 0.75, hdim, { - [`${oldRotateKey}Key`]: true, - buttons: 1, - }) - ); - - // Needed to first digest the mousedown event - await wait(10); - - whenDrawn = new Promise((resolve) => { - scatterplot.subscribe('draw', resolve, 1); - }); - - await asyncForEach(mousePositions, async (mousePosition) => { - window.dispatchEvent(createMouseEvent('mousemove', ...mousePosition)); - await wait(DEFAULT_LASSO_MIN_DELAY + 5); - }); - - // We need to ensure that the camera's tick() function was called before - // we release the mouse via the mouseup event - await nextAnimationFrame(); - await wait(0); - - window.dispatchEvent(createMouseEvent('mouseup')); - window.dispatchEvent( - createKeyboardEvent('keyup', capitalize(oldRotateKey), { - [`${oldRotateKey}Key`]: true, - }) - ); - - await whenDrawn; - await wait(10); - - expect(lastRotation).toBe(rotation); - - // Test rotation via mousedown + mousemove + keydown - window.dispatchEvent(createMouseEvent('mousemove', dim * 0.75, hdim)); - await nextAnimationFrame(); - await wait(0); - - window.dispatchEvent( - createKeyboardEvent('keydown', capitalize(rotateKey), { - [`${rotateKey}Key`]: true, - }) - ); - await wait(0); - - canvas.dispatchEvent( - createMouseEvent('mousedown', dim * 0.75, hdim, { - [`${rotateKey}Key`]: true, - buttons: 1, - }) - ); - - // Needed to first digest the mousedown event - await wait(10); - - whenDrawn = new Promise((resolve) => { - scatterplot.subscribe('draw', resolve, 1); - }); - - await asyncForEach(mousePositions, async (mousePosition) => { - window.dispatchEvent(createMouseEvent('mousemove', ...mousePosition)); - await wait(DEFAULT_LASSO_MIN_DELAY + 5); - }); - - // We need to ensure that the camera's tick() function was called before - // we release the mouse via the mouseup event - await nextAnimationFrame(); - await wait(0); - - window.dispatchEvent(createMouseEvent('mouseup')); - window.dispatchEvent( - createKeyboardEvent('keyup', capitalize(rotateKey), { - [`${rotateKey}Key`]: true, - }) - ); - - await whenDrawn; - await wait(10); - - expect(lastRotation !== rotation).toBe(true); - - scatterplot.destroy(); -}); - -test('point hover with publish("pointover") and publish("pointout")', async () => { - const dim = 200; - const hdim = dim / 2; - const canvas = createCanvas(dim, dim); - const scatterplot = createScatterplot({ - canvas, - width: dim, - height: dim, - }); - - const points = [ - [0, 0], - [1, 1], - [1, -1], - [-1, -1], - [-1, 1], - ]; - await scatterplot.draw(points); - - let hoveredPoint = null; - const pointoverHandler = (point) => { - hoveredPoint = point; - }; - const pointoutHandler = () => { - hoveredPoint = null; - }; - scatterplot.subscribe('pointover', pointoverHandler); - scatterplot.subscribe('pointout', pointoutHandler); - - // Test single selection via mouse clicks - canvas.dispatchEvent(createMouseEvent('mouseenter', hdim, hdim)); - await wait(250); - window.dispatchEvent(createMouseEvent('mousemove', hdim, hdim)); - await wait(250); - - expect(hoveredPoint).toBe(0); - - // Test deselection - window.dispatchEvent(createMouseEvent('mousemove', hdim / 2, hdim)); - - await wait(0); - - expect(hoveredPoint).toBe(null); - - scatterplot.destroy(); -}); - -test('publish("view")', async () => { - const dim = 200; - const hdim = dim / 2; - const canvas = createCanvas(dim, dim); - const xScale = scaleLinear().domain([-5, 5]); - const yScale = scaleLinear().domain([0, 0.5]); - - const scatterplot = createScatterplot({ - canvas, - width: dim, - height: dim, - xScale, - yScale, - }); - await scatterplot.draw([[0, 0]]); - - const predictedView = mat4.fromTranslation([], [-1, 0, 0]); - - let currentView; - let currentCamera; - const viewHandler = ({ camera, view }) => { - currentCamera = camera; - currentView = view; - }; - scatterplot.subscribe('view', viewHandler); - - window.dispatchEvent(createMouseEvent('mouseup', hdim, hdim)); - window.dispatchEvent(createMouseEvent('mousemove', hdim, hdim)); - await nextAnimationFrame(); - await wait(50); - - canvas.dispatchEvent( - createMouseEvent('mousedown', hdim, hdim, { buttons: 1 }) - ); - await nextAnimationFrame(); - await wait(50); - window.dispatchEvent(createMouseEvent('mousemove', 0, hdim)); - await nextAnimationFrame(); - await wait(50); - - expect(Array.from(currentView)).toEqual(predictedView); - expect(currentCamera).toBeDefined(); - expect(xScale.domain()).toEqual([0, 10]); - expect(yScale.domain()).toEqual([0, 0.5]); - - scatterplot.destroy(); -}); diff --git a/tests/get-set.test.js b/tests/get-set.test.js deleted file mode 100644 index 8cf8589a..00000000 --- a/tests/get-set.test.js +++ /dev/null @@ -1,863 +0,0 @@ -import '@babel/polyfill'; -import { nextAnimationFrame } from '@flekschas/utils'; -import { assert, expect, test } from 'vitest'; - -import { version } from '../package.json'; - -import createScatterplot, { - createRegl, - createRenderer, - createTextureFromUrl, -} from '../src'; - -import { - DEFAULT_LASSO_COLOR, - DEFAULT_SHOW_RETICLE, - DEFAULT_RETICLE_COLOR, - DEFAULT_LASSO_MIN_DELAY, - DEFAULT_LASSO_MIN_DIST, - DEFAULT_LASSO_CLEAR_EVENT, - DEFAULT_POINT_CONNECTION_OPACITY, - DEFAULT_POINT_CONNECTION_OPACITY_ACTIVE, - DEFAULT_POINT_CONNECTION_SIZE, - DEFAULT_POINT_CONNECTION_SIZE_ACTIVE, - DEFAULT_IMAGE_LOAD_TIMEOUT, - ERROR_INSTANCE_IS_DESTROYED, - IMAGE_LOAD_ERROR, -} from '../src/constants'; - -import { - createCanvas, - flatArrayEqual, -} from './utils'; - -import imageUrl from './assets/image.jpg'; - -const EPS = 1e-7; - -const floatEqual = (a, b) => Math.abs(a - b) <= EPS; - -const valueVariants = { - valueZ: ['category', 'value1', 'valueA', 'valueZ', 'z'], - valueW: ['value', 'value2', 'valueB', 'valueW', 'w'], -}; - -test('get("canvas"), get("regl"), and get("version")', () => { - const canvas = createCanvas(); - const regl = createRegl(canvas); - const renderer = createRenderer({ regl }); - const scatterplot = createScatterplot({ canvas, renderer }); - - expect(scatterplot.get('canvas')).toBe(canvas); - expect(scatterplot.get('regl')).toBe(regl); - expect(scatterplot.get('version')).toBe(version); - - scatterplot.destroy(); -}); - -test('set({ width, height })', () => { - const w1 = 200; - const h1 = 200; - - const canvas = createCanvas(w1, h1); - const gl = canvas.getContext('webgl'); - const scatterplot = createScatterplot({ canvas, width: w1, height: h1 }); - - expect(gl.drawingBufferWidth).toBe(w1 * window.devicePixelRatio); - expect(gl.drawingBufferHeight).toBe(h1 * window.devicePixelRatio); - - const w2 = 400; - const h2 = 300; - - scatterplot.set({ width: w2, height: h2 }); - - expect(scatterplot.get('width')).toBe(w2); - expect(scatterplot.get('height')).toBe(h2); - - expect(gl.drawingBufferWidth).toBe(w2 * window.devicePixelRatio); - expect(gl.drawingBufferHeight).toBe(h2 * window.devicePixelRatio); - - scatterplot.destroy(); -}); - -test('set({ aspectRatio })', (t) => { - const canvas = createCanvas(400, 200); - const scatterplot = createScatterplot({ - canvas, - width: 400, - height: 200, - }); - - const aspectRatio = 2; - scatterplot.set({ aspectRatio }); - - expect(scatterplot.get('aspectRatio')).toBe(aspectRatio); - - scatterplot.destroy(); -}); - -test('set({ backgroundColor })', () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - const backgroundHex = '#ff0000'; - const backgroundNrgba = [1, 0, 0, 1]; - scatterplot.set({ backgroundColor: backgroundHex }); - - expect( - scatterplot - .get('backgroundColor') - .every((v, i) => v === backgroundNrgba[i]) - ).toBe(true); - - scatterplot.destroy(); -}); - -test('set({ backgroundImage })', async ({ skip }) => { - const canvas = createCanvas(); - const regl = createRegl(canvas); - const scatterplot = createScatterplot({ canvas, regl }); - - try { - const backgroundImage = await createTextureFromUrl(regl, imageUrl); - - scatterplot.set({ backgroundImage }); - - expect(scatterplot.get('backgroundImage')).toBe(backgroundImage); - } catch (e) { - if (e.message === IMAGE_LOAD_ERROR) { - skip(`Failed to load image from URL: ${e.message}`); - } else { - assert.fail('Could not create background image from URL'); - } - } - - try { - const backgroundImage = await scatterplot.createTextureFromUrl( - 'https://picsum.photos/300/200/' - ); - - scatterplot.set({ backgroundImage }); - - expect(scatterplot.get('backgroundImage')).toBe(backgroundImage); - - scatterplot.set({ backgroundImage: null }); - - expect(scatterplot.get('backgroundImage')).toBe(null); - } catch (e) { - if (e.message === IMAGE_LOAD_ERROR) { - skip(`Failed to load image from URL: ${e.message}`); - } else { - assert.fail('Could not create background image from URL'); - } - } - - try { - await new Promise((resolve, reject) => { - scatterplot.subscribe('backgroundImageReady', resolve, 1); - scatterplot.set({ - backgroundImage: 'https://picsum.photos/300/200/', - }); - setTimeout(() => { - reject(new Error(IMAGE_LOAD_ERROR)); - }, DEFAULT_IMAGE_LOAD_TIMEOUT); - }); - - expect(scatterplot.get('backgroundImage').width).toBe(300); - } catch (e) { - if (e.message === IMAGE_LOAD_ERROR) { - skip(`Failed to load image from URL: ${e.message}`); - } else { - assert.fail('Could not create background image from URL'); - } - } - - // Base64 image - scatterplot.set({ - backgroundImage: - 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4QDeRXhpZgAASUkqAAgAAAAGABIBAwABAAAAAQAAABoBBQABAAAAVgAAABsBBQABAAAAXgAAACgBAwABAAAAAgAAABMCAwABAAAAAQAAAGmHBAABAAAAZgAAAAAAAAA4YwAA6AMAADhjAADoAwAABwAAkAcABAAAADAyMTABkQcABAAAAAECAwCGkgcAFQAAAMAAAAAAoAcABAAAADAxMDABoAMAAQAAAP//AAACoAQAAQAAABAAAAADoAQAAQAAABAAAAAAAAAAQVNDSUkAAABQaWNzdW0gSUQ6IDM1AP/bAEMACAYGBwYFCAcHBwkJCAoMFA0MCwsMGRITDxQdGh8eHRocHCAkLicgIiwjHBwoNyksMDE0NDQfJzk9ODI8LjM0Mv/bAEMBCQkJDAsMGA0NGDIhHCEyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMv/CABEIABAAEAMBIgACEQEDEQH/xAAVAAEBAAAAAAAAAAAAAAAAAAAEBf/EABQBAQAAAAAAAAAAAAAAAAAAAAT/2gAMAwEAAhADEAAAAXqhhMj/xAAZEAADAAMAAAAAAAAAAAAAAAABAgMFERP/2gAIAQEAAQUClkNit1EkQol3PT//xAAYEQACAwAAAAAAAAAAAAAAAAABAwACIf/aAAgBAwEBPwFa6jTP/8QAGBEAAgMAAAAAAAAAAAAAAAAAAAIBAyH/2gAIAQIBAT8Be12yD//EABsQAAIDAAMAAAAAAAAAAAAAAAABAhExIzKR/9oACAEBAAY/AuSHhJraOo1Wo//EABkQAAMBAQEAAAAAAAAAAAAAAAABESFBUf/aAAgBAQABPyHK09GZVWkzrMZfGL//2gAMAwEAAgADAAAAEG//xAAVEQEBAAAAAAAAAAAAAAAAAAAAAf/aAAgBAwEBPxCsP//EABURAQEAAAAAAAAAAAAAAAAAAABR/9oACAECAQE/EJG//8QAGxABAAMAAwEAAAAAAAAAAAAAAQARITFBcZH/2gAIAQEAAT8QLFXq/H7McnD32o87LUuUMEBVpM48n//Z', - }); - - await new Promise((resolve) => { - scatterplot.subscribe('backgroundImageReady', resolve, 1); - }); - - expect(scatterplot.get('backgroundImage').width).toBe(16); - - scatterplot.destroy(); -}); - -test('set({ cameraTarget, cameraDistance, cameraRotation, cameraView })', (t) => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - const settings = { - cameraTarget: [1.337, 1.337], - cameraDistance: 1.337, - cameraRotation: Math.PI / 1.337, - }; - - const comparators = { - cameraTarget: (a, b) => flatArrayEqual(a, b, floatEqual), - cameraDistance: (a, b) => floatEqual(a, b), - cameraRotation: (a, b) => floatEqual(a, b), - }; - - Object.entries(settings).forEach(([setting, value]) => { - scatterplot.set({ [setting]: value }); - - expect( - comparators[setting](value, scatterplot.get(setting)) - ).toBe(true); - - scatterplot.set({ [setting]: null }); - - expect( - comparators[setting](value, scatterplot.get(setting)) - ).toBe(true); - }); - - scatterplot.destroy(); -}); - -test('set({ mouseMode })', () => { - const canvas = createCanvas(); - - let scatterplot = createScatterplot({ canvas }); - expect(scatterplot.get('mouseMode')).toBe('panZoom'); - scatterplot.destroy(); - - scatterplot = createScatterplot({ canvas, mouseMode: 'panZoom' }); - expect(scatterplot.get('mouseMode')).toBe('panZoom'); - scatterplot.destroy(); - - scatterplot = createScatterplot({ canvas, mouseMode: 'lasso' }); - expect(scatterplot.get('mouseMode')).toBe('lasso'); - scatterplot.destroy(); - - scatterplot = createScatterplot({ canvas, mouseMode: 'rotate' }); - expect(scatterplot.get('mouseMode')).toBe('rotate'); - scatterplot.destroy(); - - scatterplot = createScatterplot({ canvas, mouseMode: 'invalid' }); - expect(scatterplot.get('mouseMode')).toBe('panZoom'); - - scatterplot.set({ mouseMode: 'lasso' }); - expect(scatterplot.get('mouseMode')).toBe('lasso'); - - scatterplot.set({ mouseMode: 'panZoom' }); - expect(scatterplot.get('mouseMode')).toBe('panZoom'); - - scatterplot.set({ mouseMode: 'rotate' }); - expect(scatterplot.get('mouseMode')).toBe('rotate'); - - scatterplot.set({ mouseMode: 'invalid' }); - expect(scatterplot.get('mouseMode')).toBe('panZoom'); - - scatterplot.destroy(); -}); - -test( - 'set({ colorBy, opacityBy, sizeBy, pointConnectionColorBy, pointConnectionOpacityBy, pointConnectionSizeBy })', - () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - [ - 'colorBy', - 'opacityBy', - 'sizeBy', - 'pointConnectionColorBy', - 'pointConnectionOpacityBy', - 'pointConnectionSizeBy', - ].forEach((property) => { - Object.entries(valueVariants).forEach(([value, variants]) => { - variants.forEach((variant) => { - scatterplot.set({ [property]: variant }); - - expect(scatterplot.get(property)).toBe(value); - }); - }); - - scatterplot.set({ [property]: null }); - - expect(scatterplot.get(property)).toBe(null); - }); - - scatterplot.destroy(); - } -); - -test( - 'set({ pointColor, pointColorActive, pointColorHover, pointConnectionColor, pointConnectionColorActive, pointConnectionColorHover }) single color', - () => { - const canvas = createCanvas(); - const scatterplot = createScatterplot({ canvas }); - - const rgbaPointColor = [ - 0.22745098039215686, 0.47058823529411764, 0.6666666666666666, 1, - ]; - const rgbaPointColorActive = [0, 0.5529411764705883, 1, 1]; - const rgbaPointColorHover = [0, 0.5529411764705883, 1, 1]; - - // Set a single color - scatterplot.set({ - pointColor: '#3a78aa', - pointColorActive: '#008dff', - pointColorHover: '#008dff', - pointConnectionColor: 'inherit', - pointConnectionColorActive: 'inherit', - pointConnectionColorHover: 'inherit', - }); - - expect(scatterplot.get('pointColor')).toEqual(rgbaPointColor); - expect(scatterplot.get('pointColorActive')).toEqual(rgbaPointColorActive); - expect(scatterplot.get('pointColorHover')).toEqual(rgbaPointColorHover); - expect(scatterplot.get('pointConnectionColor')).toEqual(rgbaPointColor); - expect(scatterplot.get('pointConnectionColorActive')).toEqual(rgbaPointColorActive); - expect(scatterplot.get('pointConnectionColorHover')).toEqual(rgbaPointColorHover); - - // Set custom point connection color - scatterplot.set({ - pointConnectionColor: '#ff0000', - pointConnectionColorActive: '#00ff00', - pointConnectionColorHover: '#0000ff', - }); - - expect(scatterplot.get('pointConnectionColor')).toEqual([1, 0, 0, 1]); - expect(scatterplot.get('pointConnectionColorActive')).toEqual([0, 1, 0, 1]); - expect(scatterplot.get('pointConnectionColorHover')).toEqual([0, 0, 1, 1]); - - // Set an invalid color, which should default to white - scatterplot.set({ - pointColor: 'shouldnotwork', - }); - - expect( - scatterplot.get('pointColor').every((component) => component === 1) - ).toBe(true); - - scatterplot.destroy(); - } -); - -test( - 'set({ pointColor, pointColorActive, pointColorHover }) multiple colors', - () => { - const canvas = createCanvas(); - const scatterplot = createScatterplot({ canvas }); - - const pointColor = [ - [0, 0.5, 1, 0.5], - [1, 0.5, 0, 0.5], - ]; - const pointColorActive = [ - [0.5, 0, 1, 0.5], - [1, 0, 0.5, 0.5], - ]; - const pointColorHover = [ - [1, 0.5, 0, 0.5], - [0, 0.5, 1, 0.5], - ]; - - // Set a single color - scatterplot.set({ - pointColor, - pointColorActive, - pointColorHover, - pointConnectionColor: 'inherit', - pointConnectionColorActive: 'inherit', - pointConnectionColorHover: 'inherit', - }); - - expect( - scatterplot - .get('pointColor') - .every((color, i) => color.every((c, j) => c === pointColor[i][j])) - ).toBe(true); - - expect( - scatterplot - .get('pointColorActive') - .every((color, i) => - color.every((c, j) => c === pointColorActive[i][j]) - ) - ).toBe(true); - - expect( - scatterplot - .get('pointColorHover') - .every((color, i) => - color.every((c, j) => c === pointColorHover[i][j]) - ) - ).toBe(true); - - expect( - scatterplot - .get('pointConnectionColor') - .every((color, i) => color.every((c, j) => c === pointColor[i][j])) - ).toBe(true); - - expect( - scatterplot - .get('pointConnectionColorActive') - .every((color, i) => - color.every((c, j) => c === pointColorActive[i][j]) - ) - ).toBe(true); - - expect( - scatterplot - .get('pointConnectionColorHover') - .every((color, i) => - color.every((c, j) => c === pointColorHover[i][j]) - ) - ).toBe(true); - - // Add another point color to the existing point colors - const newPointColors = [...pointColor, [1, 0, 1, 1]]; - scatterplot.set({ - pointColor: newPointColors, - }); - - expect( - scatterplot - .get('pointColor') - .every((color, i) => color.every((c, j) => c === newPointColors[i][j])) - ).toBe(true); - - scatterplot.set({ - pointConnectionColor: ['#ff0000', '#ff00ff'], - pointConnectionColorActive: ['#ffff00', '#0000ff'], - pointConnectionColorHover: ['#000000', '#ffffff'], - }); - - expect(scatterplot.get('pointConnectionColor')).toEqual([ - [1, 0, 0, 1], - [1, 0, 1, 1], - ], - ); - - expect(scatterplot.get('pointConnectionColorActive')).toEqual([ - [1, 1, 0, 1], - [0, 0, 1, 1], - ]); - - expect(scatterplot.get('pointConnectionColorHover')).toEqual([ - [0, 0, 0, 1], - [1, 1, 1, 1], - ]); - - scatterplot.destroy(); - } -); - -test( - 'set({ opacity, pointConnectionOpacity, pointConnectionOpacityActive })', - () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - let opacity = 0.5; - - scatterplot.set({ opacity }); - - expect(scatterplot.get('opacity')).toBe(opacity); - - expect(scatterplot.get('pointConnectionOpacity')).toBe( - DEFAULT_POINT_CONNECTION_OPACITY - ); - - expect(scatterplot.get('pointConnectionOpacityActive')).toBe( - DEFAULT_POINT_CONNECTION_OPACITY_ACTIVE, - ); - - scatterplot.set({ - opacity: 0, - pointConnectionOpacity: opacity, - pointConnectionOpacityActive: opacity, - }); - - expect(scatterplot.get('opacity')).toBe(opacity); - expect(scatterplot.get('pointConnectionOpacity')).toBe(opacity); - expect(scatterplot.get('pointConnectionOpacityActive')).toBe(opacity); - - opacity = [0.5, 0.75, 1]; - - scatterplot.set({ - opacity, - pointConnectionOpacity: opacity, - pointConnectionOpacityActive: opacity, - }); - - expect(scatterplot.get('opacity')).toEqual(opacity); - expect(scatterplot.get('pointConnectionOpacity')).toEqual(opacity); - expect(scatterplot.get('pointConnectionOpacityActive')).toEqual(0.5); - - scatterplot.destroy(); - } -); - -test( - 'set({ lassoColor, lassoMinDist, lassoMinDelay, lassoClearEvent })', - () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - // Check default lasso color, min distance, and min delay - expect(scatterplot.get('lassoColor')).toEqual(DEFAULT_LASSO_COLOR); - expect(scatterplot.get('lassoMinDist')).toEqual(DEFAULT_LASSO_MIN_DIST); - expect(scatterplot.get('lassoMinDelay')).toEqual(DEFAULT_LASSO_MIN_DELAY); - expect(scatterplot.get('lassoClearEvent')).toEqual(DEFAULT_LASSO_CLEAR_EVENT); - - const lassoColor = [1, 0, 0, 1]; - const lassoMinDist = 10; - const lassoMinDelay = 150; - const lassoClearEvent = 'deselect'; - - scatterplot.set({ - lassoColor, - lassoMinDist, - lassoMinDelay, - lassoClearEvent, - }); - - expect(scatterplot.get('lassoColor')).toEqual(lassoColor); - expect(scatterplot.get('lassoMinDist')).toEqual(lassoMinDist); - expect(scatterplot.get('lassoMinDelay')).toEqual(lassoMinDelay); - expect(scatterplot.get('lassoClearEvent')).toEqual(lassoClearEvent); - - scatterplot.set({ - lassoColor: null, - lassoMinDist: null, - lassoMinDelay: null, - lassoClearEvent: null, - }); - - expect(scatterplot.get('lassoColor')).toEqual(lassoColor); - expect(scatterplot.get('lassoMinDist')).toEqual(lassoMinDist); - expect(scatterplot.get('lassoMinDelay')).toEqual(lassoMinDelay); - expect(scatterplot.get('lassoClearEvent')).toEqual(lassoClearEvent); - - scatterplot.destroy(); - } -); - -test( - 'set({ pointOutlineWidth })', - () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - const pointOutlineWidth = 42; - - scatterplot.set({ pointOutlineWidth }); - - expect(scatterplot.get('pointOutlineWidth')).toEqual(pointOutlineWidth); - - scatterplot.set({ pointOutlineWidth: 0 }); - - expect(scatterplot.get('pointOutlineWidth')).toEqual(pointOutlineWidth); - - scatterplot.destroy(); - } -); - -test( - 'set({ pointSize, pointConnectionSize, pointConnectionSizeActive })', - () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - const pointSize = 42; - - scatterplot.set({ pointSize }); - - expect(scatterplot.get('pointSize')).toEqual(pointSize); - expect(scatterplot.get('pointConnectionSize')).toEqual( - DEFAULT_POINT_CONNECTION_SIZE - ); - expect(scatterplot.get('pointConnectionSizeActive')).toEqual( - DEFAULT_POINT_CONNECTION_SIZE_ACTIVE - ); - - scatterplot.set({ - pointSize: 0, - pointConnectionSize: pointSize, - pointConnectionSizeActive: pointSize, - }); - - expect(scatterplot.get('pointSize')).toEqual(pointSize); - expect(scatterplot.get('pointConnectionSize')).toEqual(pointSize); - expect(scatterplot.get('pointConnectionSizeActive')).toEqual(pointSize); - - scatterplot.set({ - pointSize: [2, 4, 6], - pointConnectionSize: [2, 4, 6], - pointConnectionSizeActive: [2, 4, 6], - }); - - expect(scatterplot.get('pointSize')).toEqual([2, 4, 6]); - expect(scatterplot.get('pointConnectionSize')).toEqual([2, 4, 6]); - expect(scatterplot.get('pointConnectionSizeActive')).toBe(pointSize); - - scatterplot.destroy(); - } -); - -test( - 'set({ pointSizeSelected })', - () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - const pointSizeSelected = 42; - - scatterplot.set({ pointSizeSelected }); - - expect(scatterplot.get('pointSizeSelected')).toEqual(pointSizeSelected); - - scatterplot.set({ pointSizeSelected: 0 }); - - expect(scatterplot.get('pointSizeSelected')).toEqual(pointSizeSelected); - - scatterplot.destroy(); - } -); - -test( - 'set({ showReticle, reticleColor })', - () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - expect(scatterplot.get('showReticle')).toEqual(DEFAULT_SHOW_RETICLE); - expect(scatterplot.get('reticleColor')).toEqual(DEFAULT_RETICLE_COLOR); - - const showReticle = !DEFAULT_SHOW_RETICLE; - const reticleColor = [1, 0, 0, 0.5]; - - scatterplot.set({ showReticle, reticleColor }); - - expect(scatterplot.get('showReticle')).toEqual(showReticle); - expect(scatterplot.get('reticleColor')).toEqual(reticleColor); - - scatterplot.set({ showReticle: null }); - - expect(scatterplot.get('showReticle')).toEqual(showReticle); - - scatterplot.set({ reticleColor: null }); - - expect(scatterplot.get('reticleColor')).toEqual(reticleColor); - - scatterplot.destroy(); - } -); - -test('set({ cameraIsFixed })', async () => { - const canvas = createCanvas(); - const scatterplot = createScatterplot({ canvas }); - - await scatterplot.draw([ - [-1, 1], - [1, 1], - [0, 0], - [-1, -1], - [1, -1], - ]); - - canvas.dispatchEvent(new WheelEvent('wheel', { deltaY: -100 })); - - await nextAnimationFrame(); - - // We expect the distance to be less than one because we zoomed into the plot - // via wheeling - expect(scatterplot.get('camera').distance[0]).toBeLessThan(1); - - await scatterplot.zoomToOrigin(); - - expect(scatterplot.get('camera').distance[0]).toBe(1); - - scatterplot.set({ cameraIsFixed: true }); - expect(scatterplot.get('cameraIsFixed')).toBe(true); - - // Adding this here to triple check that the programmatic zoom does not unset - // the camera fixed state - await scatterplot.zoomToOrigin(); - - canvas.dispatchEvent(new WheelEvent('wheel', { deltaY: -100 })); - - await nextAnimationFrame(); - - // We expect the distance to be one because we fixed the camera - expect(scatterplot.get('camera').distance[0]).toBe(1); - - scatterplot.set({ cameraIsFixed: false }); - expect(scatterplot.get('cameraIsFixed')).toBe(false); - - canvas.dispatchEvent(new WheelEvent('wheel', { deltaY: -100 })); - - await nextAnimationFrame(); - - // We expect the distance to be less than one because we unfixed the camera - expect(scatterplot.get('camera').distance[0]).toBeLessThan(1); - - await scatterplot.zoomToOrigin(); - expect(scatterplot.get('camera').distance[0]).toBe(1); - - scatterplot.set({ cameraIsFixed: true }); - await scatterplot.zoomToPoints([2]); - - // Even though the camera is fixed, programmatic zooming still works. Only - // mouse wheel interactions are prevented - expect(scatterplot.get('cameraIsFixed')).toBe(true); - expect(scatterplot.get('camera').distance[0]).toBeLessThan(1); - - scatterplot.destroy(); -}); - -test('get("isDestroyed")', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - expect(scatterplot.get('isDestroyed')).toBe(false); - - scatterplot.destroy(); - - expect(scatterplot.get('isDestroyed')).toBe(true); -}); - -test('get("isDrawing")', async () => { - const canvas = createCanvas(); - const scatterplot = createScatterplot({ canvas }); - - expect(scatterplot.get('isDrawing')).toBe(false); - - const whenDrawn = scatterplot.draw([ - [-1, 1], - [1, 1], - [0, 0], - [-1, -1], - [1, -1], - ]); - - expect(scatterplot.get('isDrawing')).toBe(true); - - await expect(whenDrawn).resolves.toBe(undefined); - - expect(scatterplot.get('isDrawing')).toBe(false); - - scatterplot.destroy(); -}); - -test('set() after destroy', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - scatterplot.destroy(); - - const whenSet = scatterplot.set({ mouseMode: 'lasso' }); - - await expect(whenSet).rejects.toThrow(ERROR_INSTANCE_IS_DESTROYED); -}); - -test('get() and set() performance properties', async () => { - const scatterplotA = createScatterplot({ canvas: createCanvas() }); - - expect(scatterplotA.get('performanceMode')).toBe(false); - expect(scatterplotA.get('renderPointsAsSquares')).toBe(false); - expect(scatterplotA.get('disableAlphaBlending')).toBe(false); - - scatterplotA.set({ - 'performanceMode': true, - 'renderPointsAsSquares': true, - 'disableAlphaBlending': true, - }); - - expect(scatterplotA.get('performanceMode')).toBe(false); - expect(scatterplotA.get('renderPointsAsSquares')).toBe(false); - expect(scatterplotA.get('disableAlphaBlending')).toBe(false); - - scatterplotA.destroy(); - - const scatterplotB = createScatterplot({ - canvas: createCanvas(), - performanceMode: true, - }); - - expect(scatterplotB.get('performanceMode')).toBe(true); - expect(scatterplotB.get('renderPointsAsSquares')).toBe(true); - expect(scatterplotB.get('disableAlphaBlending')).toBe(true); - - scatterplotB.destroy(); - - const scatterplotC = createScatterplot({ - canvas: createCanvas(), - renderPointsAsSquares: true, - }); - - expect(scatterplotC.get('performanceMode')).toBe(false); - expect(scatterplotC.get('renderPointsAsSquares')).toBe(true); - expect(scatterplotC.get('disableAlphaBlending')).toBe(false); - - scatterplotC.destroy(); - - const scatterplotD = createScatterplot({ - canvas: createCanvas(), - disableAlphaBlending: true, - }); - - expect(scatterplotD.get('performanceMode')).toBe(false); - expect(scatterplotD.get('renderPointsAsSquares')).toBe(false); - expect(scatterplotD.get('disableAlphaBlending')).toBe(true); - - scatterplotD.destroy(); -}); - -test('get() and set() lasso types', async () => { - const scatterplot = createScatterplot({ - canvas: createCanvas(), - lassoType: 'rectangle', - lassoBrushSize: 32, - }); - - expect(scatterplot.get('lassoType')).toBe('rectangle'); - expect(scatterplot.get('lassoBrushSize')).toBe(32); - - scatterplot.set({ lassoType: 'brush', lassoBrushSize: 18 }); - - expect(scatterplot.get('lassoType')).toBe('brush'); - expect(scatterplot.get('lassoBrushSize')).toBe(18); - - scatterplot.set({ lassoType: 'freeform' }); - - expect(scatterplot.get('lassoType')).toBe('freeform'); - - scatterplot.set({ lassoType: 'rectangle' }); - - expect(scatterplot.get('lassoType')).toBe('rectangle'); - - scatterplot.set({ lassoType: 'invalid' }); - - expect(scatterplot.get('lassoType')).toBe('freeform'); -}); - -test('set({ pointOrder }) and get("pointOrder")', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - expect(scatterplot.get('pointOrder')).toBe(null); - - await scatterplot.draw([ - [0, 0], - [1, 1], - [2, 2], - [3, 3], - ]); - - scatterplot.set({ pointOrder: [3, 1, 0, 2] }); - expect(scatterplot.get('pointOrder')).toEqual([3, 1, 0, 2]); - - // Returns a copy, not a reference - const order = scatterplot.get('pointOrder'); - order[0] = 999; - expect(scatterplot.get('pointOrder')).toEqual([3, 1, 0, 2]); - - // Reset to null - scatterplot.set({ pointOrder: null }); - expect(scatterplot.get('pointOrder')).toBe(null); - - // Invalid values are ignored - scatterplot.set({ pointOrder: 'invalid' }); - expect(scatterplot.get('pointOrder')).toBe(null); - - scatterplot.destroy(); -}); diff --git a/tests/methods.test.js b/tests/methods.test.js deleted file mode 100644 index 2351cbfe..00000000 --- a/tests/methods.test.js +++ /dev/null @@ -1,1418 +0,0 @@ -import '@babel/polyfill'; -import { assert, expect, test } from 'vitest'; -import { nextAnimationFrame, hasSameElements } from '@flekschas/utils'; - -import createScatterplot from '../src'; - -import { - DEFAULT_POINT_SCALE_MODE, - ERROR_INSTANCE_IS_DESTROYED, - ERROR_IS_DRAWING, - ERROR_POINTS_NOT_DRAWN, -} from '../src/constants'; - -import { createCanvas, wait, getPixelSum } from './utils'; - -const EPS = 1e-7; - -test('draw() with transition', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - let numDrawCalls = 0; - let numTransitionStartCalls = 0; - let numTransitionEndCalls = 0; - - scatterplot.subscribe('draw', () => numDrawCalls++); - scatterplot.subscribe('transitionStart', () => numTransitionStartCalls++); - scatterplot.subscribe('transitionEnd', () => numTransitionEndCalls++); - - await scatterplot.draw([[0, 0]]); - - expect(numDrawCalls).toBe(1); - - const t0 = performance.now(); - const transitionDuration = 250; - - await scatterplot.draw([[1, 1]], { - transition: true, - transitionDuration, - }); - - expect(numTransitionStartCalls).toBe(1); - expect(numTransitionEndCalls).toBe(1); - expect(performance.now() - t0 >= transitionDuration).toBe(true); - - scatterplot.destroy(); -}); - -test('draw() with preventFilterReset', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - const filteredPoints = [0, 1, 2]; - - const points = [ - [0, 0], - [0.9, 0.9], - [0.9, -0.9], - [-0.9, -0.9], - [-0.9, 0.9], - ]; - - await scatterplot.draw(points); - - await scatterplot.filter(filteredPoints); - await wait(0); - - expect( - hasSameElements(scatterplot.get('filteredPoints'), filteredPoints) - ).toBe(true); - - let img = scatterplot.export(); - - // The left side of the image should be empty as points #3 and #4 are filtered out - expect( - getPixelSum(img, 0, Math.ceil(img.width / 3), 0, img.height) - ).toBe(0); - - // The right side of the image should *not* be empty as points #0 to #2 are filtered in - expect( - getPixelSum(img, Math.ceil(img.width / 3), img.width, 0, img.height) > 0 - ).toBe(true); - - await scatterplot.draw([...points], { preventFilterReset: true }); - - // `isPointsFiltered` should be `true` as draw has been invoked with preventFilterReset - expect(scatterplot.get('isPointsFiltered')).toBe(true); - - // the filtered points should be the same as before - expect( - hasSameElements(scatterplot.get('filteredPoints'), filteredPoints) - ).toBe(true); - - img = scatterplot.export(); - - // The left side of the image should be empty as points #3 and #4 are filtered out - expect( - getPixelSum(img, 0, Math.ceil(img.width / 3), 0, img.height) - ).toBe(0); - - // The right side of the image should *not* be empty as points #0 to #2 are filtered in - expect( - getPixelSum(img, Math.ceil(img.width / 3), img.width, 0, img.height) > 0 - ).toBe(true); - - await scatterplot.draw([...points, [0.5, 0.5]], { - preventFilterReset: true, - }); - - // `isPointsFiltered` should be `false` as draw has been invoked with different number of points - expect(scatterplot.get('isPointsFiltered')).toBe(false); - - // the filtered points should be reset as draw has been invoked with different number of points - expect(scatterplot.get('filteredPoints').length).toBe(points.length + 1); - - img = scatterplot.export(); - - // The left side of the image should *not* be empty as the filter was reset - expect( - getPixelSum(img, 0, Math.ceil(img.width / 3), 0, img.height) > 0 - ).toBe(true); - - scatterplot.destroy(); -}); - -test('draw() prematurely', async () => { - const canvas = createCanvas(); - const scatterplot = createScatterplot({ canvas }); - - const whenDrawn1 = scatterplot.draw([[-1, 1], [0, 0], [1, -1]]); - const whenDrawn2 = scatterplot.draw([[-1, 1], [0, 0], [1, -1]]); - await expect(whenDrawn2).rejects.toThrow(ERROR_IS_DRAWING); - - await expect(whenDrawn1).resolves.toBe(undefined); - - const whenDrawn3 = scatterplot.draw([[-1, 1], [0, 0], [1, -1]]); - - await expect(whenDrawn3).resolves.toBe(undefined); - - scatterplot.destroy(); -}); - -test('draw() after destroy', async () => { - const canvas = createCanvas(); - const scatterplot = createScatterplot({ canvas }); - - scatterplot.destroy(); - - const whenDrawn = scatterplot.draw([[-1, 1], [0, 0], [1, -1]]); - - await expect(whenDrawn).rejects.toThrow(ERROR_INSTANCE_IS_DESTROYED); -}); - -test('select()', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - const points = [ - [0, 0], - [1, 1], - [1, -1], - [-1, -1], - [-1, 1], - ]; - - await scatterplot.draw(points); - - let selectedPoints = []; - const selectHandler = ({ points: newSelectedPoints }) => { - selectedPoints = [...newSelectedPoints]; - }; - const deselectHandler = () => { - selectedPoints = []; - }; - scatterplot.subscribe('select', selectHandler); - scatterplot.subscribe('deselect', deselectHandler); - - scatterplot.select([0, 2, 4]); - - await wait(0); - - expect(selectedPoints).toEqual([0, 2, 4]); - expect(scatterplot.get('selectedPoints')).toEqual([0, 2, 4]); - - scatterplot.deselect(); - - await wait(0); - - expect(selectedPoints.length).toBe(0); - - scatterplot.select([0, 2, 4]); - - await wait(0); - - expect(scatterplot.get('selectedPoints')).toEqual([0, 2, 4]); - - scatterplot.select([]); - - await wait(0); - - expect(selectedPoints.length).toBe(0); - - scatterplot.select([0, 2, 4], { preventEvent: true }); - - await wait(0); - - expect(selectedPoints.length + scatterplot.get('selectedPoints').length).toBe(3); - - scatterplot.deselect(); - scatterplot.select([0, 2, 4]); - scatterplot.deselect({ preventEvent: true }); - - await wait(0); - - expect(selectedPoints).toEqual([0, 2, 4]); - - scatterplot.select(2); - - await wait(0); - - expect(selectedPoints).toEqual([2]); - - scatterplot.select(-1); - - await wait(0); - - expect(selectedPoints).toEqual([]); - - scatterplot.select([0, -1, 2, 4, 6]); - - await wait(0); - - expect(selectedPoints).toEqual([0, 2, 4]); - - scatterplot.destroy(); -}); - -test('lassoSelect() with data space coordinates', async () => { - const { scaleLinear } = await import('d3-scale'); - - const scatterplot = createScatterplot({ - canvas: createCanvas(), - xScale: scaleLinear().domain([0, 100]), - yScale: scaleLinear().domain([0, 100]), - }); - - // Draw 5 points in data space coordinates - // Points at: [10,10], [90,90], [90,10], [10,90], [50,50] - const points = [ - [-0.8, -0.8], // 10,10 - [0.8, 0.8], // 90,90 - [0.8, -0.8], // 90,10 - [-0.8, 0.8], // 10,90 - [0, 0], // 50,50 - ]; - - await scatterplot.draw(points); - - let selectedPoints = []; - const selectHandler = ({ points: newSelectedPoints }) => { - selectedPoints = [...newSelectedPoints]; - }; - scatterplot.subscribe('select', selectHandler); - - // Select bottom-left quadrant in data space coordinates - // Should select point 0 (10,10) and point 4 (50,50) - scatterplot.lassoSelect([ - [0, 0], - [60, 0], - [60, 60], - [0, 60], - ]); - - await wait(0); - - expect(selectedPoints.sort()).toEqual([0, 4]); - - scatterplot.destroy(); -}); - -test('lassoSelect() with GL space coordinates', async () => { - const { scaleLinear } = await import('d3-scale'); - - const scatterplot = createScatterplot({ - canvas: createCanvas(), - xScale: scaleLinear().domain([0, 100]), - yScale: scaleLinear().domain([0, 100]), - }); - - const points = [ - [-0.8, -0.8], // bottom-left - [0.8, 0.8], // top-right - [0.8, -0.8], // bottom-right - [-0.8, 0.8], // top-left - [0, 0], // center - ]; - - await scatterplot.draw(points); - - let selectedPoints = []; - const selectHandler = ({ points: newSelectedPoints }) => { - selectedPoints = [...newSelectedPoints]; - }; - scatterplot.subscribe('select', selectHandler); - - // Select using GL space coordinates (NDC space since no camera transform) - // Select left side: points 0, 3, 4 - scatterplot.lassoSelect( - [ - [-1, -1], - [0.1, -1], - [0.1, 1], - [-1, 1], - ], - { isGl: true } - ); - - await wait(0); - - expect(selectedPoints.sort()).toEqual([0, 3, 4]); - - scatterplot.destroy(); -}); - -test('lassoSelect() with open polygon (auto-closes)', async () => { - const { scaleLinear } = await import('d3-scale'); - - const scatterplot = createScatterplot({ - canvas: createCanvas(), - xScale: scaleLinear().domain([0, 100]), - yScale: scaleLinear().domain([0, 100]), - }); - - const points = [ - [-0.5, -0.5], - [0.5, 0.5], - [0.5, -0.5], - ]; - - await scatterplot.draw(points); - - let selectedPoints = []; - const selectHandler = ({ points: newSelectedPoints }) => { - selectedPoints = [...newSelectedPoints]; - }; - scatterplot.subscribe('select', selectHandler); - - // Pass open polygon (first and last vertices different) - // Should auto-close and still work - scatterplot.lassoSelect([ - [0, 0], - [100, 0], - [100, 100], - [0, 100], - // Note: NOT closing back to [0, 0] - ]); - - await wait(0); - - // All points should be selected - expect(selectedPoints.sort()).toEqual([0, 1, 2]); - - scatterplot.destroy(); -}); - -test('lassoSelect() with merge and remove options', async () => { - const { scaleLinear } = await import('d3-scale'); - - const scatterplot = createScatterplot({ - canvas: createCanvas(), - xScale: scaleLinear().domain([0, 100]), - yScale: scaleLinear().domain([0, 100]), - }); - - const points = [ - [-0.8, -0.8], // 10,10 - [0.8, 0.8], // 90,90 - [0.8, -0.8], // 90,10 - [-0.8, 0.8], // 10,90 - [0, 0], // 50,50 - ]; - - await scatterplot.draw(points); - - let selectedPoints = []; - const selectHandler = ({ points: newSelectedPoints }) => { - selectedPoints = [...newSelectedPoints]; - }; - scatterplot.subscribe('select', selectHandler); - - // Select bottom-left quadrant (points 0, 4) - scatterplot.lassoSelect([ - [0, 0], - [60, 0], - [60, 60], - [0, 60], - ]); - - await wait(0); - expect(selectedPoints.sort()).toEqual([0, 4]); - - // Merge with top-left quadrant (should add point 3) - scatterplot.lassoSelect( - [ - [0, 40], - [60, 40], - [60, 100], - [0, 100], - ], - { merge: true } - ); - - await wait(0); - expect(selectedPoints.sort()).toEqual([0, 3, 4]); - - // Remove center region (should remove point 4) - scatterplot.lassoSelect( - [ - [25, 25], - [75, 25], - [75, 75], - [25, 75], - ], - { remove: true } - ); - - await wait(0); - expect(selectedPoints.sort()).toEqual([0, 3]); - - scatterplot.destroy(); -}); - -test('lassoSelect() error: less than 3 vertices', async () => { - const { scaleLinear } = await import('d3-scale'); - - const scatterplot = createScatterplot({ - canvas: createCanvas(), - xScale: scaleLinear().domain([0, 100]), - yScale: scaleLinear().domain([0, 100]), - }); - - await scatterplot.draw([[0, 0]]); - - // Should throw error with less than 3 vertices - expect(() => { - scatterplot.lassoSelect([ - [10, 10], - [50, 50], - // Only 2 points - invalid - ]); - }).toThrow('Lasso selection requires at least 3 vertices'); - - scatterplot.destroy(); -}); - -test('lassoSelect() error: invalid vertices format', async () => { - const { scaleLinear } = await import('d3-scale'); - - const scatterplot = createScatterplot({ - canvas: createCanvas(), - xScale: scaleLinear().domain([0, 100]), - yScale: scaleLinear().domain([0, 100]), - }); - - await scatterplot.draw([[0, 0]]); - - // Should throw error with invalid format - expect(() => { - scatterplot.lassoSelect([ - [10, 10], - [50], // Invalid: missing y coordinate - [90, 90], - ]); - }).toThrow('Lasso selection requires at least 3 vertices'); - - scatterplot.destroy(); -}); - -test('lassoSelect() error: no scales defined', async () => { - const scatterplot = createScatterplot({ - canvas: createCanvas(), - // No xScale/yScale defined - }); - - await scatterplot.draw([[0, 0]]); - - // Should throw error when trying to use data space without scales - expect(() => { - scatterplot.lassoSelect([ - [10, 10], - [50, 50], - [90, 90], - ]); - }).toThrow('xScale and yScale must be defined'); - - scatterplot.destroy(); -}); - -test('lassoSelect() works without scales when using isGl: true', async () => { - const scatterplot = createScatterplot({ - canvas: createCanvas(), - // No xScale/yScale defined - }); - - const points = [ - [-0.5, -0.5], - [0.5, 0.5], - [0.5, -0.5], - ]; - - await scatterplot.draw(points); - - let selectedPoints = []; - const selectHandler = ({ points: newSelectedPoints }) => { - selectedPoints = [...newSelectedPoints]; - }; - scatterplot.subscribe('select', selectHandler); - - // Should work with GL coordinates even without scales - scatterplot.lassoSelect( - [ - [-1, -1], - [1, -1], - [1, 1], - [-1, 1], - ], - { isGl: true } - ); - - await wait(0); - - // All points should be selected - expect(selectedPoints.sort()).toEqual([0, 1, 2]); - - scatterplot.destroy(); -}); - -test('hover() with columnar data', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - const data = { - x: [0, 1, 1, -1, -1], - y: [0, 1, -1, -1, 1], - }; - - await scatterplot.draw(data); - - let hovering; - const pointoverHandler = (newHovering) => { - hovering = newHovering; - }; - const pointoutHandler = () => { - hovering = undefined; - }; - scatterplot.subscribe('pointover', pointoverHandler); - scatterplot.subscribe('pointout', pointoutHandler); - - scatterplot.hover(0); - - await wait(0); - - expect(hovering).toBe(0); - - scatterplot.hover(); - - await wait(0); - - expect(hovering).toBe(undefined); - - scatterplot.hover(2, { preventEvent: true }); - - await wait(0); - - // should be silently hovering point 2 - expect(hovering).toBe(undefined); - - scatterplot.hover(4); - scatterplot.hover(undefined, { preventEvent: true }); - - await wait(0); - - // should have silently stopped hovering point 4 - expect(hovering).toBe(4); - - scatterplot.hover(-1); - - await wait(0); - - // Point 4 should still be registered as being hovered because -1 is invalid - expect(hovering).toBe(4); - - scatterplot.hover(6); - - await wait(0); - - // Point 4 should still be registered as being hovered because 6 is invalid - expect(hovering).toBe(4); - - scatterplot.destroy(); -}); - -test('filter()', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - const points = [ - [0, 0], - [1, 1], - [1, -1], - [-1, -1], - [-1, 1], - ]; - - await scatterplot.draw(points); - - expect(scatterplot.get('isPointsFiltered')).toBe(false); - - expect( - hasSameElements(scatterplot.get('filteredPoints'), [0, 1, 2, 3, 4]) - ).toBe(true); - - let filteredPoints = []; - const filterHandler = ({ points: newFilteredPoints }) => { - filteredPoints = [...newFilteredPoints]; - }; - const unfilterHandler = () => { - filteredPoints = scatterplot.get('filteredPoints'); - }; - scatterplot.subscribe('filter', filterHandler); - scatterplot.subscribe('unfilter', unfilterHandler); - - let hoveredPoint; - const pointOverHandler = (pointIdx) => { - hoveredPoint = pointIdx; - }; - const pointOutHandler = () => { - hoveredPoint = undefined; - }; - scatterplot.subscribe('pointover', pointOverHandler); - scatterplot.subscribe('pointout', pointOutHandler); - - await scatterplot.filter([1, 3]); - await wait(0); - - expect( - hasSameElements(filteredPoints, [1, 3]) - ).toBe(true); - - expect(scatterplot.get('isPointsFiltered')).toBe(true); - - expect( - hasSameElements(scatterplot.get('pointsInView'), [1, 3]) - ).toBe(true); - - expect( - hasSameElements(scatterplot.get('filteredPoints'), [1, 3]) - ).toBe(true); - - scatterplot.hover(1); - await wait(0); - - expect(hoveredPoint).toBe(1); - - scatterplot.hover(2); - await wait(0); - - // should not be able to hover a point that is filtered out - expect(hoveredPoint).toBe(undefined); - - let selectedPoints = []; - const selectHandler = ({ points: newSelectedPoints }) => { - selectedPoints = [...newSelectedPoints]; - }; - const deselectHandler = () => { - selectedPoints = []; - }; - scatterplot.subscribe('select', selectHandler); - scatterplot.subscribe('deselect', deselectHandler); - - scatterplot.select([0, 2, 4]); - - await wait(0); - - // should not have selected points 0, 2, and 4 because they are filtered out - expect(selectedPoints.length).toBe(0); - - await scatterplot.filter([]); - - await wait(0); - - expect(filteredPoints.length).toBe(0); - expect(scatterplot.get('filteredPoints').length).toBe(0); - - scatterplot.select([0, 1, 2, 3, 4]); - - await wait(0); - - // should not be able to selected any points because all are filtered out - expect(selectedPoints.length).toBe(0); - - await scatterplot.unfilter(); - await wait(0); - - // should have unfiltered the points - expect( - hasSameElements(filteredPoints, [0, 1, 2, 3, 4]) - ).toBe(true); - - expect( - hasSameElements(scatterplot.get('filteredPoints'), [0, 1, 2, 3, 4]) - ).toBe(true); - - expect( - scatterplot.get('isPointsFiltered'), - ).toBe(false); - - scatterplot.select([0, 2, 4]); - - await wait(0); - - expect(selectedPoints).toEqual([0, 2, 4]); - - await scatterplot.filter([1, 3], { preventEvent: true }); - await wait(0); - - // should have silently filtered down to two points. I.e., the filter - // argument should not have been altered - expect(filteredPoints.length).toBe(5); - expect(scatterplot.get('pointsInView').length).toBe(2); - - await scatterplot.filter([0, 1, 3]); - await scatterplot.unfilter({ preventEvent: true }); - await wait(0); - - // should have silently unfiltered points. I.e., the unfilter argument - // should not have been altered - expect(filteredPoints.length).toBe(3); - expect(scatterplot.get('pointsInView').length).toBe(5); - - await scatterplot.filter(2); - await wait(0); - - expect(filteredPoints.length).toBe(1); - expect(filteredPoints[0]).toBe(2); - expect(scatterplot.get('pointsInView').length).toBe(1); - - await scatterplot.filter(-1); - await wait(0); - - // should have not filtered down to any point because -1 is an invalid point index - expect(filteredPoints.length).toBe(0); - - const pointsToBeFiltered = [0, -1, 2, 4, 6]; - - await scatterplot.filter(pointsToBeFiltered); - await wait(0); - - // should have filtered down to valid points (0, 2, and 4) only - expect( - hasSameElements(filteredPoints, [0, 2, 4]) - ).toBe(true); - - // We're testing this due to the following bug where we accidentically - // spliced of from the input argument, which we should never do. - // @see https://github.com/flekschas/regl-scatterplot/issues/197 - expect(pointsToBeFiltered.length).toBe(5); - - scatterplot.destroy(); -}); - -test('`filter() point order consistency`', async () => { - const scatterplot = createScatterplot({ - canvas: createCanvas(50, 50), - width: 50, - height: 50, - pointColor: ['#FF0000', '#00FF00', '#0000FF'], - pointSize: 50, - opacity: 1, - colorBy: "valueA" - }); - - const dpr = window.devicePixelRatio; - const middlePixel = (50 * dpr * 25 * dpr + 25 * dpr) * 4; - - await scatterplot.draw({ - x: [0, 0, 0], - y: [0, 0, 0], - valueA: [0, 1, 2] - }); - - await wait(25); - - let image = scatterplot.export(); - - // the center pixel should be blue - expect( - Array.from(image.data.slice(middlePixel, middlePixel + 4)) - ).toEqual([0, 0, 255, 255]); - - await scatterplot.filter([1, 0]); - - await wait(25); - - image = scatterplot.export(); - - // the center pixel should be green - expect( - Array.from(image.data.slice(middlePixel, middlePixel + 4)) - ).toEqual([0, 255, 0, 255]); - - await scatterplot.unfilter(); - await scatterplot.filter([0, 1]); - - await wait(25); - - image = scatterplot.export(); - - // the center pixel should still be green - expect( - Array.from(image.data.slice(middlePixel, middlePixel + 4)) - ).toEqual([0, 255, 0, 255]); -}); - -test('test hover, select, and filter options of `draw()`', async () => { - const scatterplot = createScatterplot({ - canvas: createCanvas(200, 200), - width: 200, - height: 200, - }); - - const points = [ - [0, 0], - [1, 1], - [1, -1], - [-1, -1], - [-1, 1], - ]; - - await scatterplot.draw(points, { - hover: 0, - select: [1, 2], - filter: [0, 2, 3], - }); - - await wait(50); - - expect(scatterplot.get('hoveredPoint')).toBe(0); - expect(scatterplot.get('selectedPoints')).toEqual([2]); - expect( - hasSameElements(scatterplot.get('filteredPoints'), [0, 2, 3]) - ).toBe(true); - - scatterplot.destroy(); -}); - -test('zooming with transition', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - const camera = scatterplot.get('camera'); - - let numDrawCalls = 0; - let numTransitionStartCalls = 0; - let numTransitionEndCalls = 0; - - scatterplot.subscribe('draw', () => numDrawCalls++); - scatterplot.subscribe('transitionStart', () => numTransitionStartCalls++); - scatterplot.subscribe('transitionEnd', () => numTransitionEndCalls++); - - await scatterplot.draw([ - [-1, 1], - [1, 1], - [0, 0], - [-1, -1], - [1, -1], - ]); - - expect(numDrawCalls).toBe(1); - - const t0 = performance.now(); - const transitionDuration = 50; - - await scatterplot.zoomToPoints([1, 2], { - transition: true, - transitionDuration, - }); - - expect(numTransitionStartCalls).toBe(1); - expect(numTransitionEndCalls).toBe(1); - expect(performance.now() - t0).toBeGreaterThanOrEqual(transitionDuration); - expect(camera.target[0] - 0.5).toBeLessThanOrEqual(1e-8); - expect(camera.target[1] - 0.5).toBeLessThanOrEqual(1e-8); - - await scatterplot.zoomToOrigin({ transition: true, transitionDuration }); - - expect(numTransitionStartCalls).toBe(2); - expect(numTransitionEndCalls).toBe(2); - expect(camera.target[0]).toBeLessThanOrEqual(1e-8); - expect(camera.target[1]).toBeLessThanOrEqual(1e-8); - - await scatterplot.zoomToLocation([-0.5, -0.5], 0.1, { - transition: true, - transitionDuration, - }); - - expect(numTransitionStartCalls).toBe(3); - expect(numTransitionEndCalls).toBe(3); - expect(camera.target[0] + 0.1).toBeLessThanOrEqual(1e-8); - expect(camera.target[1] + 0.1).toBeLessThanOrEqual(1e-8); - expect(camera.distance[0] - 0.1).toBeLessThanOrEqual(1e-8); - - await scatterplot.zoomToArea( - { x: 0, y: -1, width: 1, height: 1 }, - { transition: true, transitionDuration } - ); - - expect(numTransitionStartCalls).toBe(4); - expect(numTransitionEndCalls).toBe(4); - expect(camera.target[0] - 0.5).toBeLessThanOrEqual(1e-8); - expect(camera.target[1] + 0.5).toBeLessThanOrEqual(1e-8); - - scatterplot.destroy(); -}); - -test('zoomToPoints() before point were drawn should fail', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - try { - await scatterplot.zoomToPoints([1, 2]); - assert.fail('zoomToPoints() should have thrown an error'); - } catch (e) { - expect(e.message).toBe(ERROR_POINTS_NOT_DRAWN); - } - scatterplot.destroy(); -}); - -test('zoomToArea() with non-standard aspect ratio', async () => { - const dims = [ - [200, 200], - [200, 100], - [100, 200], - [333, 123], - ]; - const aspectRatios = [1, 2, 0.3, 5 / 3]; - - const xStart = -8 / 6; - const xWidth = 5 + 8 / 6; - const yStart = -1 / 3; - const yWidth = 2 / 3; - - const points = { - x: Array.from({ length: 500 }, (_, i) => xStart + (i / 499) * xWidth), - y: Array.from({ length: 500 }, (_, i) => yStart + (i / 499) * yWidth), - }; - - const rect = { - x: xStart - EPS, - width: xWidth + EPS * 2, - y: yStart - EPS, - height: yWidth + EPS * 2, - }; - - for (const [width, height] of dims) { - for (const aspectRatio of aspectRatios) { - const scatterplot = createScatterplot({ - canvas: createCanvas(width, height), - aspectRatio, - }); - - // eslint-disable-next-line no-await-in-loop - await scatterplot.draw(points); - // eslint-disable-next-line no-await-in-loop - await scatterplot.zoomToArea(rect); - - expect( - scatterplot.get('pointsInView').length - ).toBe(500); - expect(Math.abs(scatterplot.getScreenPosition(0)[0])).toBeLessThan(0.01); - expect( - Math.abs(scatterplot.getScreenPosition(499)[0] - width) - ).toBeLessThan(0.01); - - scatterplot.destroy(); - } - } -}); - -test('getScreenPosition()', async () => { - const scatterplot = createScatterplot({ - canvas: createCanvas(100, 100), - width: 100, - height: 100, - }); - - try { - scatterplot.getScreenPosition(0); - assert.fail('getScreenPosition() should have thrown an error'); - } catch (e) { - expect(e.message).toBe(ERROR_POINTS_NOT_DRAWN); - } - - await scatterplot.draw([ - [-1, -1], - [0, 0], - [1, 1], - ]); - - expect(scatterplot.getScreenPosition(0)).toEqual([0, 100]); - expect(scatterplot.getScreenPosition(1)).toEqual([50, 50]); - expect(scatterplot.getScreenPosition(2)).toEqual([100, 0]); - - // A forth point does not exist as we only drew three - expect(scatterplot.getScreenPosition(3)).toBeUndefined(); - - await scatterplot.zoomToPoints([0]); - expect(scatterplot.getScreenPosition(0)).toEqual([50, 50]); - - scatterplot.destroy(); -}); - -test('isSupported', () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - const renderer = scatterplot.get('renderer'); - - expect( - Object.prototype.hasOwnProperty.call(scatterplot, 'isSupported') - ).toBe(true); - - expect( - Object.prototype.hasOwnProperty.call(renderer, 'isSupported') - ).toBe(true); - - expect( - scatterplot.isSupported === true || scatterplot.isSupported === false - ).toBe(true); - - expect( - renderer.isSupported === true || renderer.isSupported === false - ).toBe(true); - - scatterplot.destroy(); -}); - -test('test "drawing" event', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - let numDrawCalls = 0; - let numDrawingCalls = 0; - - scatterplot.subscribe('draw', () => ++numDrawCalls); - scatterplot.subscribe('drawing', () => ++numDrawingCalls); - - await new Promise((resolve) => { - scatterplot.subscribe('init', resolve); - }); - - const isDrawn = scatterplot.draw([[-1, 1]]); - await nextAnimationFrame(); - - expect(numDrawCalls).toBe(0); - expect(numDrawingCalls).toBe(1); - - await isDrawn; - - expect(numDrawCalls).toBe(1); - - scatterplot.destroy(); -}); - -test('spatial index', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - const x = [-1, 1, 0, -1, 1]; - const y = [1, 1, 0, -1, -1]; - const z1 = [0.2, 0.4, 0.6, 0.8, 1]; - const z2 = [1, 0.8, 0.6, 0.4, 0.2]; - - await scatterplot.draw({ x, y, z: z1 }); - - await scatterplot.zoomToArea( - { - x: -EPS, - y: -EPS, - width: 1 + 2 * EPS, - height: 1 + 2 * EPS, - }, - { log: true } - ); - - expect(scatterplot.get('pointsInView')).toEqual([1, 2]); - - const spatialIndex = scatterplot.get('spatialIndex'); - - // Because `x` and `y` remain unchanged, we can reuse the spatial index - // from the previous draw call. - await scatterplot.draw({ x, y, z: z2 }, { spatialIndex }); - - await scatterplot.zoomToArea({ - x: -1 - EPS, - y: -1 - EPS, - width: 1 + 2 * EPS, - height: 1 + 2 * EPS, - }); - - // The reused spatial index should work as before - expect(scatterplot.get('pointsInView')).toEqual([2, 3]); - - scatterplot.destroy(); -}); - -test('drawAnnotations()', async () => { - const scatterplot = createScatterplot({ - canvas: createCanvas(100, 100), - width: 100, - height: 100, - }); - - await scatterplot.drawAnnotations([ - { x: 0.9, lineColor: [1, 1, 1, 0.1], lineWidth: 1 }, - { y: 0.9, lineColor: [1, 1, 1, 0.1], lineWidth: 1 }, - { - x1: -0.8, - y1: -0.8, - x2: -0.6, - y2: -0.6, - lineColor: [1, 1, 1, 0.25], - lineWidth: 1, - }, - { - x: -0.8, - y: 0.6, - width: 0.2, - height: 0.2, - lineColor: [1, 1, 1, 0.25], - lineWidth: 1, - }, - { - vertices: [ - [0.6, 0.8], - [0.8, 0.8], - [0.8, 0.6], - [0.6, 0.6], - [0.6, 0.8], - ], - lineColor: '#D55E00', - lineWidth: 2, - }, - ]); - - let img = scatterplot.export(); - let w = img.width; - let h = img.height; - const wp = w * 0.1; - const hp = w * 0.1; - - expect(getPixelSum(img, 0, w, 0, hp)).toBeGreaterThan(0); - expect(getPixelSum(img, w - wp, w, 0, h)).toBeGreaterThan(0); - expect(getPixelSum(img, wp, 2 * wp, h - hp * 2, h - hp)).toBeGreaterThan(0); - expect(getPixelSum(img, wp, 2 * wp, hp, 2 * hp)).toBeGreaterThan(0); - expect(getPixelSum(img, wp - 2 * wp, w - wp, hp, 2 * hp)).toBeGreaterThan(0); - - await scatterplot.clearAnnotations(); - - img = scatterplot.export(); - w = img.width; - h = img.height; - expect(getPixelSum(img, 0, w, 0, h)).toBe(0); - - scatterplot.destroy(); -}); - -test('pointScaleMode', async () => { - const dim = 100; - const scatterplot = createScatterplot({ - canvas: createCanvas(dim, dim), - width: dim, - height: dim, - pointSize: 10, - }); - - expect(scatterplot.get('pointScaleMode')).toBe(DEFAULT_POINT_SCALE_MODE); - - await scatterplot.draw([[0, 0]]); - - const initialImage = scatterplot.export(); - const initialPixelSum = getPixelSum(initialImage, 0, dim, 0, dim); - - expect(initialPixelSum).toBeGreaterThan(0); - - // Zoom in a bit - await scatterplot.zoomToLocation([0, 0], 0.5); - - const asinhImage = scatterplot.export(); - const asinhPixelSum = getPixelSum(asinhImage, 0, dim, 0, dim); - - expect(asinhPixelSum).toBeGreaterThan(initialPixelSum); - - // Zoom back to the origin - await scatterplot.zoomToLocation([0, 0], 1); - - scatterplot.set({ pointScaleMode: 'constant' }); - expect(scatterplot.get('pointScaleMode')).toBe('constant'); - - // Zoom in a bit - await scatterplot.zoomToLocation([0, 0], 0.5); - - const constantImage = scatterplot.export(); - const constantPixelSum = getPixelSum(constantImage, 0, dim, 0, dim); - - expect(constantPixelSum).toBe(initialPixelSum); - - // Zoom back to the origin - await scatterplot.zoomToLocation([0, 0], 1); - - scatterplot.set({ pointScaleMode: 'linear' }); - expect(scatterplot.get('pointScaleMode')).toBe('linear'); - - // Zoom in a bit - await scatterplot.zoomToLocation([0, 0], 0.5); - - const linearImage = scatterplot.export(); - const linearPixelSum = getPixelSum(linearImage, 0, dim, 0, dim); - - expect(linearPixelSum).toBeGreaterThan(asinhPixelSum); - - scatterplot.set({ pointScaleMode: 'nonsense' }); - expect(scatterplot.get('pointScaleMode')).toBe('asinh'); - - scatterplot.destroy(); -}); - -test('pointOrder controls draw order', async () => { - const dim = 64; - const scatterplot = createScatterplot({ - canvas: createCanvas(dim, dim), - width: dim, - height: dim, - pointSize: dim, - opacity: 1, - pointColor: ['#ff0000', '#0000ff'], - colorBy: 'valueA', - }); - - // Two overlapping points at center: point 0 = red, point 1 = blue - await scatterplot.draw([ - [0, 0, 0], - [0, 0, 1], - ]); - await nextAnimationFrame(); - - // Default order: point 1 (blue) drawn last, so it is on top - let image = scatterplot.export(); - const cx = Math.floor(dim / 2); - const cy = Math.floor(dim / 2); - let pixelIdx = (cy * dim + cx) * 4; - let r = image.data[pixelIdx]; - let b = image.data[pixelIdx + 2]; - expect(b).toBeGreaterThan(r); // Blue on top - - // Reverse order: point 0 (red) drawn last, so it is on top - await scatterplot.set({ pointOrder: [1, 0] }); - await nextAnimationFrame(); - - image = scatterplot.export(); - pixelIdx = (cy * dim + cx) * 4; - r = image.data[pixelIdx]; - b = image.data[pixelIdx + 2]; - expect(r).toBeGreaterThan(b); // Red on top - - scatterplot.destroy(); -}); - -test('pointOrder with filter preserves order within filtered set', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - const points = [ - [0, 0], - [1, 1], - [2, 2], - [3, 3], - [4, 4], - ]; - - await scatterplot.draw(points); - - // Set a custom order - scatterplot.set({ pointOrder: [4, 2, 0, 1, 3] }); - - // Filter to a subset - await scatterplot.filter([0, 2, 4]); - await wait(0); - - expect(scatterplot.get('isPointsFiltered')).toBe(true); - expect( - hasSameElements(scatterplot.get('filteredPoints'), [0, 2, 4]) - ).toBe(true); - - // Unfilter restores full set - await scatterplot.unfilter(); - await wait(0); - - expect(scatterplot.get('isPointsFiltered')).toBe(false); - expect(scatterplot.get('filteredPoints').length).toBe(5); - - scatterplot.destroy(); -}); - -test('pointOrder resets when draw() is called with different-length data', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - await scatterplot.draw([ - [0, 0], - [1, 1], - [2, 2], - ]); - - scatterplot.set({ pointOrder: [2, 0, 1] }); - expect(scatterplot.get('pointOrder')).toEqual([2, 0, 1]); - - // Draw with different number of points - await scatterplot.draw([ - [0, 0], - [1, 1], - ]); - - expect(scatterplot.get('pointOrder')).toBe(null); - - scatterplot.destroy(); -}); - -test('pointOrder is preserved when draw() is called with same-length data', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - await scatterplot.draw([ - [0, 0], - [1, 1], - [2, 2], - ]); - - scatterplot.set({ pointOrder: [2, 0, 1] }); - expect(scatterplot.get('pointOrder')).toEqual([2, 0, 1]); - - // Draw with same number of points - await scatterplot.draw([ - [3, 3], - [4, 4], - [5, 5], - ]); - - expect(scatterplot.get('pointOrder')).toEqual([2, 0, 1]); - - scatterplot.destroy(); -}); - -test('pointOrder via constructor', async () => { - const scatterplot = createScatterplot({ - canvas: createCanvas(), - pointOrder: [2, 0, 1], - }); - - expect(scatterplot.get('pointOrder')).toEqual([2, 0, 1]); - - await scatterplot.draw([ - [0, 0], - [1, 1], - [2, 2], - ]); - - // pointOrder should still be set after draw - expect(scatterplot.get('pointOrder')).toEqual([2, 0, 1]); - - scatterplot.destroy(); -}); - -test('pointOrder with partial array appends missing indices', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - await scatterplot.draw([ - [0, 0], - [1, 1], - [2, 2], - [3, 3], - ]); - - // Only specify 2 of 4 points - scatterplot.set({ pointOrder: [3, 1] }); - expect(scatterplot.get('pointOrder')).toEqual([3, 1]); - - // All 4 points should still be drawn (missing indices appended) - expect(scatterplot.get('filteredPoints').length).toBe(4); - - scatterplot.destroy(); -}); - -test('export()', async () => { - const dim = 10; - const scatterplot = createScatterplot({ - canvas: createCanvas(dim, dim), - width: dim, - height: dim, - pointSize: 4, - }); - - await scatterplot.draw([[0.01, 0.01]]); - - const initialImage = scatterplot.export(); - const initialPixelSum = getPixelSum(initialImage, 0, dim, 0, dim); - - expect(initialPixelSum).toBeGreaterThan(0); - - // Export at two scale - const upscaledImage = await scatterplot.export({ scale: 2 }); - const upscaledPixelSum = getPixelSum(upscaledImage, 0, dim * 2, 0, dim * 2); - expect(upscaledPixelSum).toBeGreaterThan(initialPixelSum); - - // Align point with pixel grid - const pixelAlignedImage = await scatterplot.export({ pixelAligned: true }); - expect(pixelAlignedImage.data).not.toEqual(initialImage.data); - - // Increase anti aliasing - const antiAliasingImage = await scatterplot.export({ antiAliasing: 2 }); - const antiAliasingPixelSum = getPixelSum(antiAliasingImage, 0, dim, 0, dim); - - expect(antiAliasingPixelSum).toBeLessThan(initialPixelSum); -}); diff --git a/tests/spatial-index.test.js b/tests/spatial-index.test.js deleted file mode 100644 index 3296eadd..00000000 --- a/tests/spatial-index.test.js +++ /dev/null @@ -1,62 +0,0 @@ -import '@babel/polyfill'; - -import { expect, test } from 'vitest'; - -import createScatterplot, { createSpatialIndex } from '../src'; - -import { createCanvas } from './utils'; - -test('spatial index', async () => { - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - const x = [-1, 1, 0, -1, 1]; - const y = [1, 1, 0, -1, -1]; - const z1 = [0.2, 0.4, 0.6, 0.8, 1]; - const z2 = [1, 0.8, 0.6, 0.4, 0.2]; - - await scatterplot.draw({ x, y, z: z1 }); - - await scatterplot.zoomToArea({ x: 0, y: 0, width: 1, height: 1 }); - - expect(scatterplot.get('pointsInView')).toEqual([1, 2]); - - const spatialIndex = scatterplot.get('spatialIndex'); - - // Because `x` and `y` remain unchanged, we can reuse the spatial index - // from the previous draw call. - await scatterplot.draw({ x, y, z: z2 }, { spatialIndex }); - - await scatterplot.zoomToArea({ x: -1, y: -1, width: 1, height: 1 }); - - // The reused spatial index should work as before - expect(scatterplot.get('pointsInView')).toEqual([2, 3]); - - scatterplot.destroy(); -}); - -test('create spatial index', async () => { - const points = { - x: [-1, 1, 0, -1, 1], - y: [1, 1, 0, -1, -1], - z: [0.2, 0.4, 0.6, 0.8, 1], - }; - - const spatialIndex1 = await createSpatialIndex(points); - const spatialIndex2 = await createSpatialIndex(points, { useWorker: true }); - - const scatterplot = createScatterplot({ canvas: createCanvas() }); - - await scatterplot.draw(points, { spatialIndex: spatialIndex1 }); - - await scatterplot.zoomToArea({ x: 0, y: 0, width: 1, height: 1 }); - - expect(scatterplot.get('pointsInView')).toEqual([1, 2]); - - await scatterplot.draw(points, { spatialIndex: spatialIndex2 }); - - await scatterplot.zoomToArea({ x: -1, y: -1, width: 1, height: 1 }); - - expect(scatterplot.get('pointsInView')).toEqual([2, 3]); - - scatterplot.destroy(); -}); diff --git a/tests/utils.js b/tests/utils.js deleted file mode 100644 index ea9c8ed6..00000000 --- a/tests/utils.js +++ /dev/null @@ -1,73 +0,0 @@ -export const asyncForEach = async (array, callback) => { - for (let index = 0; index < array.length; index++) { - await callback(array[index], index, array); - } -}; - -export const createCanvas = (width = 200, height = 200) => { - const canvas = document.createElement('canvas'); - canvas.width = width; - canvas.height = height; - - // Hacky but necessary - canvas.getBoundingClientRect = () => ({ - width, - height, - top: 0, - right: width, - bottom: height, - left: 0, - x: 0, - y: 0, - }); - - return canvas; -}; - -export const createMouseEvent = (type, x, y, args = {}) => - new MouseEvent(type, { - view: window, - bubbles: true, - cancelable: true, - screenX: x, - screenY: y, - clientX: x, - clientY: y, - ...args, - }); - -export const createKeyboardEvent = (type, key, args = {}) => - new KeyboardEvent(type, { - view: window, - bubbles: true, - cancelable: true, - key, - ...args, - }); - -export const flatArrayEqual = (a, b, comparator = (x, y) => x === y) => - a.length === b.length && a.every((x, i) => comparator(x, b[i])); - -export const wait = (milliSeconds) => - new Promise((resolve) => { - setTimeout(() => { - resolve(); - }, milliSeconds); - }); - -export const capitalize = (s) => `${s[0].toUpperCase}${s.slice(1)}`; - -export const getPixelSum = (img, xStart, xEnd, yStart, yEnd) => { - let pixelSum = 0; - for (let i = yStart; i < yEnd; i++) { - for (let j = xStart; j < xEnd; j++) { - const idx = (i * img.width + j) * 4; - pixelSum += - img.data[idx] + - img.data[idx + 1] + - img.data[idx + 2] + - img.data[idx + 3]; - } - } - return pixelSum; -}; diff --git a/tests/utils.test.js b/tests/utils.test.js deleted file mode 100644 index f507cf80..00000000 --- a/tests/utils.test.js +++ /dev/null @@ -1,68 +0,0 @@ -/* eslint no-console: 1, no-undef: 1, no-unused-vars: 1 */ - -import '@babel/polyfill'; -import { expect, test } from 'vitest'; - -import { checkSupport } from '../src'; - -import { - toRgba, - isNormFloatArray, - isValidBBox, - isSameRgbas, -} from '../src/utils'; - -const EPS = 1e-7; - -test('isValidBBox()', () => { - expect(isValidBBox([1, 2, 3, 4])).toBe(true); - // x range is zero - expect(isValidBBox([1, 2, 1, 4])).toBe(false); - // y range is zero - expect(isValidBBox([1, 2, 3, 2])).toBe(false); - // infinity - expect(isValidBBox([1, Infinity, 3, 2])).toBe(false); - // -infinity - expect(isValidBBox([1, -Infinity, 3, 2])).toBe(false); - // NaN - expect(isValidBBox([1, Number.NaN, 3, 2])).toBe(false); -}); - -test('isNormFloatArray()', () => { - expect(isNormFloatArray([255, 0, 0, 255])).toBe(false); - expect(isNormFloatArray([1, 2, 3, 4])).toBe(false); - expect(isNormFloatArray([0, 0, 0, 0.5])).toBe(true); - expect(isNormFloatArray([0.5, 1, 0.005, 1])).toBe(true); - - // Inconclusive - // [0, 0, 0, 1] could be [0, 0, 0, 1] or [0, 0, 0, 1/255] - expect(isNormFloatArray([0, 0, 0, 1])).toBe(true); - // [1, 1, 1, 1] could be [1, 1, 1, 1] or [1/255, 1/255, 1/255, 1/255] - expect(isNormFloatArray([1, 1, 1, 1])).toBe(true); -}); - -test('toRgba()', () => { - expect(toRgba('#ff0000')).toEqual([255, 0, 0, 255]); - expect(toRgba('#ff0000', true)).toEqual([1, 0, 0, 1]); - expect(toRgba([255, 0, 0])).toEqual([255, 0, 0, 255]); - expect(toRgba([1, 0, 0], true)).toEqual([1, 0, 0, 1]); - expect(toRgba([255, 0, 0, 153])).toEqual([255, 0, 0, 153]); - expect(toRgba([153, 0, 0, 153], true)).toEqual([0.6, 0, 0, 0.6]); - expect(toRgba([1, 0, 0, 0.6])).toEqual([255, 0, 0, 153]); - expect(toRgba([0, 0, 0, 0.1], true)).toEqual([0, 0, 0, 0.1]); - expect(toRgba([1, 0, 0, 0.6])).toEqual([255, 0, 0, 153]); -}); - -test('checkSupport()', () => { - expect(checkSupport() === true || checkSupport() === false).toBe(true); -}); - -test('isSameRgbas()', () => { - expect(isSameRgbas('#ff0000', [[0, 1, 1, 1]])).toBe(false); - expect(isSameRgbas([[0, 1, 1, 1]], '#ff0000')).toBe(false); - expect(isSameRgbas([0, 1, 1, 1], [0, 1, 1, 1])).toBe(false); - expect(isSameRgbas([[0, 1, 1, 1], [1, 1, 0, 0]], [[0, 1, 1, 1]])).toBe(false); - expect(isSameRgbas([[0, 1, 1, 1]], [[0, 1, 1, 1], [1, 1, 0, 0]])).toBe(false); - expect(isSameRgbas([[0, 1, 1, 1]], [[1, 1, 1, 1]])).toBe(false); - expect(isSameRgbas([[0, 1, 1, 1]], [[0, 1, 1, 1]])).toBe(true); -}); diff --git a/text-labels.html b/text-labels.html new file mode 100644 index 00000000..ee18ad97 --- /dev/null +++ b/text-labels.html @@ -0,0 +1,445 @@ + + + + + + + Regl Scatterplot + + + + + + + + + + + + + + +

Regl Scatterplot

+ +
+
+ +
+
+
+
+
+
+
+
+ + diff --git a/texture-background.html b/texture-background.html new file mode 100644 index 00000000..66584059 --- /dev/null +++ b/texture-background.html @@ -0,0 +1,444 @@ + + + + + + + Regl Scatterplot + + + + + + + + + + + + + +

Regl Scatterplot

+ +
+
+ +
+
+
+
+
+
+
+
+ + diff --git a/transition.html b/transition.html new file mode 100644 index 00000000..6e35c1ac --- /dev/null +++ b/transition.html @@ -0,0 +1,445 @@ + + + + + + + Regl Scatterplot + + + + + + + + + + + + + + +

Regl Scatterplot

+ +
+
+ +
+
+ + + diff --git a/version.js b/version.js deleted file mode 100644 index 3aa2163b..00000000 --- a/version.js +++ /dev/null @@ -1,3 +0,0 @@ -const packageJson = require('./package.json'); - -module.exports = JSON.stringify(packageJson.version); diff --git a/vite.config.mjs b/vite.config.mjs deleted file mode 100644 index 16508571..00000000 --- a/vite.config.mjs +++ /dev/null @@ -1,56 +0,0 @@ -import { defineConfig } from 'vite'; -import virtualHtmlTemplate from 'vite-plugin-virtual-html-template'; - -const chunks = [ - 'index', - 'axes', - 'text-labels', - 'connected-points-by-segments', - 'connected-points', - 'dynamic-opacity', - 'embedded', - 'performance-mode', - 'size-encoding', - 'texture-background', - 'transition', - 'multiple-instances', - 'annotations', - 'programmatic-lasso', -]; - -const pages = Object.fromEntries( - chunks.map((chunk) => [ - chunk, - { template: 'public/index.html', entry: `example/${chunk}.js` }, - ]) -); - -const manualChunks = (id) => { - if (id.includes('node_modules')) { - if (id.includes('apache-arrow')) { - return 'apache-arrow'; - } - if (id.includes('d3')) { - return 'd3'; - } - return 'vendor'; - } - return undefined; -}; - -export default defineConfig({ - base: './', - plugins: [virtualHtmlTemplate({ pages })], - build: { - outDir: 'docs', - rollupOptions: { - input: Object.fromEntries( - chunks.map((chunk) => [chunk, `${chunk}.html`]) - ), - output: { manualChunks }, - }, - }, - optimizeDeps: { - exclude: ['regl-line'], - }, -}); diff --git a/vitest.config.mjs b/vitest.config.mjs deleted file mode 100644 index 2bcd2eae..00000000 --- a/vitest.config.mjs +++ /dev/null @@ -1,20 +0,0 @@ -import { defineConfig } from 'vitest/config' -import { playwright } from '@vitest/browser-playwright' - -export default defineConfig({ - test: { - browser: { - provider: playwright(), - enabled: true, - instances: [ - { browser: 'chromium' }, - ], - headless: true, - screenshot: 'off', - }, - coverage: { - include: ['src'], - reporter: ['text', 'json-summary', 'json'], - }, - }, -})