diff --git a/.prettierrc b/.prettierrc index 11573d8..23a11b9 100644 --- a/.prettierrc +++ b/.prettierrc @@ -7,6 +7,5 @@ "useTabs": false, "arrowParens": "avoid", "bracketSpacing": true, - "endOfLine": "lf", - "plugins": ["prettier-plugin-tailwindcss"] + "endOfLine": "lf" } \ No newline at end of file diff --git a/DOCS.md b/DOCS.md new file mode 100644 index 0000000..a6c53bf --- /dev/null +++ b/DOCS.md @@ -0,0 +1,211 @@ + +# Solid-Three: Integrative 3D Rendering with Solid.js + +**Solid-Three** is a Solid.js library that enables seamless integration of Three.js, facilitating the creation and manipulation of 3D graphics within a Solid.js framework. This library is a port of the popular React library react-three-fiber, designed to bring its powerful declarative 3D capabilities to the reactive and efficient Solid.js ecosystem. + +## Table of Contents + +1. Introduction +2. Features +3. Differences from React-Three-Fiber +4. Installation +5. Basic Usage +6. Components + - Canvas + - Primitive Components (``) +7. Hooks + - useThree + - useFrame + - useLoader +8. Event Handling +9. Advanced Examples + - Using `` with `useLoader` +10. Contributing +11. License + +## Introduction + +Solid-Three merges the expressive and detailed world of Three.js with the declarative power of Solid.js. It allows developers to construct complex 3D scenes and animations using a straightforward JSX syntax, bridging the gap between 3D graphics programming and modern web development frameworks. + +## Features + +- **Declarative Three.js Components**: Utilize Three.js objects as JSX components. +- **Reactive Prop Updates**: Properties of 3D objects update reactively, promoting efficient re-renders. +- **Integrated Animation Loop**: `useFrame` hook allows for easy animations. +- **Comprehensive Event System**: Enhanced event handling with support for Three.js pointer and mouse events. +- **Extensible and Customizable**: Easily extendable with additional Three.js entities or custom behaviors. +- **Optimized for Solid.js**: Leverages Solid.js' fine-grained reactivity for optimal performance. + +## Differences from React-Three-Fiber + +While Solid-Three is inspired by react-three-fiber, there are several key differences tailored to fit the Solid.js environment: + +- **No `performance` Prop**: The `Canvas` component does not support a `performance` prop as optimization is handled differently in Solid.js. +- **No Pointer Capture**: Pointer events do not support pointer capture management. +- **No `onPointerMissed` Event**: This event is not available in Solid-Three. +- **Simplified Event Objects**: The event object provided to event handlers is more minimalistic. +- **Minimal `useThree` Hook**: Returns a more concise context object, focusing on essential properties. + +## Installation + +\`\`\` +npm install solid-three three +\`\`\` + +Ensure that `solid-js` is installed in your environment, as it is a peer dependency of Solid-Three. + +## Basic Usage + +Here's a simple example to get you started: + +\`\`\` +import { Component } from "solid-js"; +import { Canvas, T } from "solid-three"; +import { Box } from "./components/Box"; // A custom Box component + +const App: Component = () => { + return ( + + + + + + ); +}; +\`\`\` + +## Components + +### Canvas + +The `Canvas` component initializes the Three.js rendering context and acts as the root for your 3D scene. + +**Props:** +- **camera**: Configures the camera used in the scene. +- **gl**: Defines options for the WebGLRenderer. +- **scene**: Provides custom settings for the Scene instance. +- **raycaster**: Configures the Raycaster for mouse and pointer events. +- **shadows**: Enables and configures shadows in the scene. +- **orthographic**: Toggles between Orthographic and Perspective camera. +- **style**: Custom CSS styles for the canvas container. +- **frameloop**: Controls the rendering loop's operation mode. + +### Primitive Components (``) + +`` components are wrappers around Three.js objects, allowing you to insert these objects into your scene declaratively. + +Example: +\`\`\` + + + + +\`\`\` + +## Hooks + +### useThree + +Provides access to the Three.js context, including the renderer, scene, camera, and raycaster. Ideal for accessing these elements to manage scene properties or integrate other libraries. + +\`\`\` +const CameraInfo = () => { + const { camera } = useThree(); + useEffect(() => { + console.log(`Camera position: ${camera.position.toArray().join(", ")}`); + }, []); + + return null; +}; +\`\`\` + +### useFrame + +Registers a callback that will be called before every frame is rendered, useful for animations and updates. + +\`\`\` +const RotatingMesh = () => { + useFrame(({ delta }) => { + const { scene } = useThree(); + scene.children[0].rotation.y += delta * Math.PI; + }); + + return ( + + + + + ); +}; +\`\`\` + +### useLoader + +Manages asynchronous resource loading, such as textures or models, and integrates with Solid.js' reactivity system. This hook can be used with Solid's `` to handle loading states. + +\`\`\` +import { Suspense } from 'solid-js'; +import { Canvas, T, useLoader } from 'solid-three'; +import { TextureLoader } from 'three'; + +const TexturedSphere = () => { + const texture = useLoader(TextureLoader, "path/to/texture.jpg"); + + return ( + + + + + ); +}; + +export const App = () => { + return ( + + Loading...}> + + + + ); +}; +\`\`\` + +## Event Handling + +Solid-Three enhances Three.js event handling capabilities, integrating them smoothly with Solid.js' reactivity. Events like `onClick`, `onPointerOver`, and others are supported directly on `` components. + +## Advanced Examples + +### Using `` with `useLoader` + +Here is an advanced example demonstrating how to use the `useLoader` hook with `` for graceful loading state management: + +\`\`\` +import { Suspense } from 'solid-js'; +import { Canvas, T, useLoader } from 'solid-three'; +import { TextureLoader } from 'three'; + +const MultipleTextures = () => { + const textures = useLoader(TextureLoader, [ + "/textures/wood.jpg", + "/textures/metal.jpg" + ]); + + return textures().map(texture => ( + + + + + )); +}; + +export const App = () => { + return ( + + Loading Textures...}> + + + + ); +}; +\`\`\` diff --git a/package.json b/package.json index 5140975..49e50e0 100644 --- a/package.json +++ b/package.json @@ -1,64 +1,106 @@ -{ - "name": "solid-three", - "version": "0.2.0", - "description": "SolidJS bindings for ThreeJS", - "repository": { - "type": "git", - "url": "git+https://github.com/solidjs-community/solid-three.git" - }, - "module": "./dist/index.mjs", - "main": "./dist/index.js", - "types": "./types/index.d.ts", - "sideEffects": false, - "license": "MIT", - "files": [ - "dist/**", - "types/**", - "README.md" - ], - "scripts": { - "test": "vitest", - "build:lib": "BUILD_MODE=lib vite build", - "build": "vite build", - "types": "tsc --emitDeclarationOnly --declarationDir types", - "dev": "vite", - "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist" - }, - "exports": { - ".": { - "import": "./dist/index.mjs", - "require": "./dist/index.cjs.js" - } - }, - "devDependencies": { - "@types/node": "^18.11.18", - "@types/three": "0.149.0", - "@vinxi/tsconfig": "0.0.3", - "esbuild": "^0.16.16", - "esbuild-register": "^3.4.2", - "remark-gfm": "^3.0.1", - "rollup": "^3.9.1", - "rollup-plugin-dts": "^5.1.1", - "solid-app-router": "^0.1.14", - "solid-js": "^1.7.0", - "three": "0.149.0", - "tsm": "^2.3.0", - "tsup": "^6.5.0", - "typescript": "^4.9.4", - "vite": "4.1.1", - "vite-plugin-inspect": "0.7.14", - "vite-plugin-solid": "2.5.0" - }, - "peerDependencies": { - "solid-js": "*", - "three": "*" - }, - "jest": { - "preset": "scripts/jest/node" - }, - "dependencies": { - "@types/three": "0.149.0", - "zustand": "^3.7.2" - }, - "packageManager": "pnpm@7.26.0" -} \ No newline at end of file +{ + "name": "solid-three", + "version": "0.3.0", + "description": "SolidJS bindings for ThreeJS", + "repository": { + "type": "git", + "url": "git+https://github.com/solidjs-community/solid-three.git" + }, + "module": "./dist/core/index.js", + "main": "./dist/core/index.js", + "types": "./dist/core/index.d.ts", + "sideEffects": false, + "license": "MIT", + "files": [ + "dist/**", + "types/**", + "README.md" + ], + "scripts": { + "build": "tsup", + "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist", + "dev": "vite", + "start": "vite", + "test": "vitest", + "types": "tsc --emitDeclarationOnly --declarationDir types" + }, + "exports": { + "./core": { + "development": { + "import": { + "types": "./dist/core/index.d.ts", + "default": "./dist/core/dev.js" + } + }, + "import": { + "types": "./dist/core/index.d.ts", + "default": "./dist/core/index.js" + } + }, + "./testing": { + "solid": { + "development": "./dist/testing/dev.jsx", + "import": "./dist/testing/index.jsx" + }, + "development": { + "import": { + "types": "./dist/testing/index.d.ts", + "default": "./dist/testing/dev.js" + } + }, + "import": { + "types": "./dist/testing/index.d.ts", + "default": "./dist/testing/index.js" + } + } + }, + "devDependencies": { + "@jest/types": "^29.6.3", + "@solidjs/testing-library": "^0.8.7", + "@types/node": "^18.11.18", + "@types/three": "^0.164.0", + "@vinxi/tsconfig": "0.0.3", + "esbuild": "^0.16.16", + "esbuild-register": "^3.4.2", + "jest": "^29.7.0", + "jsdom": "^24.0.0", + "remark-gfm": "^3.0.1", + "rollup": "^3.9.1", + "rollup-plugin-dts": "^5.1.1", + "solid-app-router": "^0.1.14", + "solid-js": "^1.8.0", + "three": "^0.164.0", + "three-stdlib": "^2.29.6", + "tsm": "^2.3.0", + "tsup": "^8.0.0", + "tsup-preset-solid": "^2.2.0", + "typescript": "^4.9.4", + "vite": "4.1.1", + "vite-plugin-inspect": "0.7.14", + "vite-plugin-solid": "2.5.0", + "vitest": "^1.5.0" + }, + "peerDependencies": { + "solid-js": "*", + "three": "*", + "@types/three": "*" + }, + "jest": { + "preset": "scripts/jest/node" + }, + "dependencies": { + "@solid-primitives/resize-observer": "^2.0.25" + }, + "browser": {}, + "typesVersions": { + "*": { + "core": [ + "./dist/core/index.d.ts" + ], + "testing": [ + "./dist/testing/index.d.ts" + ] + } + }, + "type": "module" +} diff --git a/playground/App.tsx b/playground/App.tsx index d419666..f084c7f 100644 --- a/playground/App.tsx +++ b/playground/App.tsx @@ -1,20 +1,19 @@ -import { Canvas } from "../src"; +import { Component } from "solid-js"; +import * as THREE from "three"; +import { Vector3 } from "three"; +import { Canvas, T, extend } from "../src"; import { Box } from "./Box"; +import "./index.css"; -export function App() { +extend(THREE); + +export const App: Component = () => { + // return "hallo"; return ( - + + + - - ); -} +}; diff --git a/playground/Box.tsx b/playground/Box.tsx index efbd002..ea1e22a 100644 --- a/playground/Box.tsx +++ b/playground/Box.tsx @@ -1,5 +1,6 @@ +import { createSignal } from "solid-js"; import { Mesh } from "three"; -import { createSignal, useFrame } from "../src"; +import { T, useFrame } from "../src"; export function Box() { let mesh: Mesh | undefined; @@ -8,13 +9,15 @@ export function Box() { useFrame(() => (mesh!.rotation.y += 0.01)); return ( - setHovered(true)} - onPointerLeave={e => setHovered(false)} - > - - - + <> + setHovered(true)} + onPointerLeave={e => setHovered(false)} + > + + + + ); } diff --git a/playground/index.css b/playground/index.css new file mode 100644 index 0000000..d392ed7 --- /dev/null +++ b/playground/index.css @@ -0,0 +1,4 @@ +body { + padding: 0px; + margin: 0px; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e48e400..5b2ddbf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,62 +1,89 @@ lockfileVersion: '6.0' -dependencies: - '@types/three': - specifier: 0.149.0 - version: 0.149.0 - zustand: - specifier: ^3.7.2 - version: 3.7.2 - -devDependencies: - '@types/node': - specifier: ^18.11.18 - version: 18.11.18 - '@vinxi/tsconfig': - specifier: 0.0.3 - version: 0.0.3 - esbuild: - specifier: ^0.16.16 - version: 0.16.16 - esbuild-register: - specifier: ^3.4.2 - version: 3.4.2(esbuild@0.16.16) - remark-gfm: - specifier: ^3.0.1 - version: 3.0.1 - rollup: - specifier: ^3.9.1 - version: 3.9.1 - rollup-plugin-dts: - specifier: ^5.1.1 - version: 5.1.1(rollup@3.9.1)(typescript@4.9.4) - solid-app-router: - specifier: ^0.1.14 - version: 0.1.14(solid-js@1.7.0) - solid-js: - specifier: ^1.7.0 - version: 1.7.0 - three: - specifier: 0.149.0 - version: 0.149.0 - tsm: - specifier: ^2.3.0 - version: 2.3.0 - tsup: - specifier: ^6.5.0 - version: 6.5.0(typescript@4.9.4) - typescript: - specifier: ^4.9.4 - version: 4.9.4 - vite: - specifier: 4.1.1 - version: 4.1.1(@types/node@18.11.18) - vite-plugin-inspect: - specifier: 0.7.14 - version: 0.7.14(rollup@3.9.1)(vite@4.1.1) - vite-plugin-solid: - specifier: 2.5.0 - version: 2.5.0(solid-js@1.7.0)(vite@4.1.1) +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@solid-primitives/resize-observer': + specifier: ^2.0.25 + version: 2.0.25(solid-js@1.8.17) + devDependencies: + '@jest/types': + specifier: ^29.6.3 + version: 29.6.3 + '@solidjs/testing-library': + specifier: ^0.8.7 + version: 0.8.7(solid-js@1.8.17) + '@types/node': + specifier: ^18.11.18 + version: 18.11.18 + '@types/three': + specifier: ^0.164.0 + version: 0.164.0 + '@vinxi/tsconfig': + specifier: 0.0.3 + version: 0.0.3 + esbuild: + specifier: ^0.16.16 + version: 0.16.16 + esbuild-register: + specifier: ^3.4.2 + version: 3.4.2(esbuild@0.16.16) + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@18.11.18) + jsdom: + specifier: ^24.0.0 + version: 24.0.0 + remark-gfm: + specifier: ^3.0.1 + version: 3.0.1 + rollup: + specifier: ^3.9.1 + version: 3.9.1 + rollup-plugin-dts: + specifier: ^5.1.1 + version: 5.1.1(rollup@3.9.1)(typescript@4.9.4) + solid-app-router: + specifier: ^0.1.14 + version: 0.1.14(solid-js@1.8.17) + solid-js: + specifier: ^1.8.0 + version: 1.8.17 + three: + specifier: ^0.164.0 + version: 0.164.1 + three-stdlib: + specifier: ^2.29.6 + version: 2.29.6(three@0.164.1) + tsm: + specifier: ^2.3.0 + version: 2.3.0 + tsup: + specifier: ^8.0.0 + version: 8.0.2(typescript@4.9.4) + tsup-preset-solid: + specifier: ^2.2.0 + version: 2.2.0(esbuild@0.16.16)(solid-js@1.8.17)(tsup@8.0.2) + typescript: + specifier: ^4.9.4 + version: 4.9.4 + vite: + specifier: 4.1.1 + version: 4.1.1(@types/node@18.11.18) + vite-plugin-inspect: + specifier: 0.7.14 + version: 0.7.14(rollup@3.9.1)(vite@4.1.1) + vite-plugin-solid: + specifier: 2.5.0 + version: 2.5.0(solid-js@1.8.17)(vite@4.1.1) + vitest: + specifier: ^1.5.0 + version: 1.5.0(@types/node@18.11.18)(jsdom@24.0.0) packages: @@ -79,11 +106,24 @@ packages: '@babel/highlight': 7.18.6 dev: true + /@babel/code-frame@7.24.2: + resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.24.2 + picocolors: 1.0.0 + dev: true + /@babel/compat-data@7.21.7: resolution: {integrity: sha512-KYMqFYTaenzMK4yUtf4EW9wc4N9ef80FsbMtkwool5zpwl4YrT1SdWYSTRcT94KO4hannogdS+LxY7L+arP3gA==} engines: {node: '>=6.9.0'} dev: true + /@babel/compat-data@7.24.4: + resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==} + engines: {node: '>=6.9.0'} + dev: true + /@babel/core@7.21.5: resolution: {integrity: sha512-9M398B/QH5DlfCOTKDZT1ozXr0x8uBEeFd+dJraGUZGiaNpGCDVGCc14hZexsMblw3XxltJ+6kSvogp9J+5a9g==} engines: {node: '>=6.9.0'} @@ -107,6 +147,29 @@ packages: - supports-color dev: true + /@babel/core@7.24.4: + resolution: {integrity: sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.24.2 + '@babel/generator': 7.24.4 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.4) + '@babel/helpers': 7.24.4 + '@babel/parser': 7.24.4 + '@babel/template': 7.24.0 + '@babel/traverse': 7.24.1 + '@babel/types': 7.24.0 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/generator@7.21.5: resolution: {integrity: sha512-SrKK/sRv8GesIW1bDagf9cCG38IOMYZusoe1dfg0D8aiUe3Amvoj1QtjTPAWcfrZFvIwlleLb0gxzQidL9w14w==} engines: {node: '>=6.9.0'} @@ -117,6 +180,16 @@ packages: jsesc: 2.5.2 dev: true + /@babel/generator@7.24.4: + resolution: {integrity: sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 2.5.2 + dev: true + /@babel/helper-annotate-as-pure@7.18.6: resolution: {integrity: sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==} engines: {node: '>=6.9.0'} @@ -138,6 +211,17 @@ packages: semver: 6.3.0 dev: true + /@babel/helper-compilation-targets@7.23.6: + resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.24.4 + '@babel/helper-validator-option': 7.23.5 + browserslist: 4.23.0 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: true + /@babel/helper-create-class-features-plugin@7.21.5(@babel/core@7.21.5): resolution: {integrity: sha512-yNSEck9SuDvPTEUYm4BSXl6ZVC7yO5ZLEMAhG3v3zi7RDxyL/nQDemWWZmw4L0stPWwhpnznRRyJHPRcbXR2jw==} engines: {node: '>=6.9.0'} @@ -158,11 +242,36 @@ packages: - supports-color dev: true + /@babel/helper-create-class-features-plugin@7.21.5(@babel/core@7.24.4): + resolution: {integrity: sha512-yNSEck9SuDvPTEUYm4BSXl6ZVC7yO5ZLEMAhG3v3zi7RDxyL/nQDemWWZmw4L0stPWwhpnznRRyJHPRcbXR2jw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-environment-visitor': 7.21.5 + '@babel/helper-function-name': 7.21.0 + '@babel/helper-member-expression-to-functions': 7.21.5 + '@babel/helper-optimise-call-expression': 7.18.6 + '@babel/helper-replace-supers': 7.21.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.20.0 + '@babel/helper-split-export-declaration': 7.18.6 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/helper-environment-visitor@7.21.5: resolution: {integrity: sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ==} engines: {node: '>=6.9.0'} dev: true + /@babel/helper-environment-visitor@7.22.20: + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + engines: {node: '>=6.9.0'} + dev: true + /@babel/helper-function-name@7.21.0: resolution: {integrity: sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==} engines: {node: '>=6.9.0'} @@ -171,6 +280,14 @@ packages: '@babel/types': 7.21.5 dev: true + /@babel/helper-function-name@7.23.0: + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.24.0 + '@babel/types': 7.24.0 + dev: true + /@babel/helper-hoist-variables@7.18.6: resolution: {integrity: sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==} engines: {node: '>=6.9.0'} @@ -178,6 +295,13 @@ packages: '@babel/types': 7.21.5 dev: true + /@babel/helper-hoist-variables@7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + dev: true + /@babel/helper-member-expression-to-functions@7.21.5: resolution: {integrity: sha512-nIcGfgwpH2u4n9GG1HpStW5Ogx7x7ekiFHbjjFRKXbn5zUvqO9ZgotCO4x1aNbKn/x/xOUaXEhyNHCwtFCpxWg==} engines: {node: '>=6.9.0'} @@ -206,6 +330,13 @@ packages: '@babel/types': 7.21.5 dev: true + /@babel/helper-module-imports@7.24.3: + resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + dev: true + /@babel/helper-module-transforms@7.21.5: resolution: {integrity: sha512-bI2Z9zBGY2q5yMHoBvJ2a9iX3ZOAzJPm7Q8Yz6YeoUjU/Cvhmi2G4QyTNyPBqqXSgTjUxRg3L0xV45HvkNWWBw==} engines: {node: '>=6.9.0'} @@ -222,6 +353,20 @@ packages: - supports-color dev: true + /@babel/helper-module-transforms@7.23.3(@babel/core@7.24.4): + resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.24.3 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 + dev: true + /@babel/helper-optimise-call-expression@7.18.6: resolution: {integrity: sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==} engines: {node: '>=6.9.0'} @@ -255,6 +400,13 @@ packages: '@babel/types': 7.21.5 dev: true + /@babel/helper-simple-access@7.22.5: + resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + dev: true + /@babel/helper-skip-transparent-expression-wrappers@7.20.0: resolution: {integrity: sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg==} engines: {node: '>=6.9.0'} @@ -269,21 +421,43 @@ packages: '@babel/types': 7.21.5 dev: true + /@babel/helper-split-export-declaration@7.22.6: + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.24.0 + dev: true + /@babel/helper-string-parser@7.21.5: resolution: {integrity: sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==} engines: {node: '>=6.9.0'} dev: true + /@babel/helper-string-parser@7.24.1: + resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} + engines: {node: '>=6.9.0'} + dev: true + /@babel/helper-validator-identifier@7.19.1: resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} engines: {node: '>=6.9.0'} dev: true + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + dev: true + /@babel/helper-validator-option@7.21.0: resolution: {integrity: sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==} engines: {node: '>=6.9.0'} dev: true + /@babel/helper-validator-option@7.23.5: + resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} + engines: {node: '>=6.9.0'} + dev: true + /@babel/helpers@7.21.5: resolution: {integrity: sha512-BSY+JSlHxOmGsPTydUkPf1MdMQ3M81x5xGCOVgWM3G8XH77sJ292Y2oqcp0CbbgxhqBuI46iUz1tT7hqP7EfgA==} engines: {node: '>=6.9.0'} @@ -295,6 +469,17 @@ packages: - supports-color dev: true + /@babel/helpers@7.24.4: + resolution: {integrity: sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.24.0 + '@babel/traverse': 7.24.1 + '@babel/types': 7.24.0 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/highlight@7.18.6: resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} engines: {node: '>=6.9.0'} @@ -304,6 +489,17 @@ packages: js-tokens: 4.0.0 dev: true + /@babel/highlight@7.24.2: + resolution: {integrity: sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==} + engines: {node: '>=6.9.0'} + requiresBuild: true + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.0.0 + dev: true + /@babel/parser@7.21.5: resolution: {integrity: sha512-J+IxH2IsxV4HbnTrSWgMAQj0UEo61hDA4Ny8h8PCX0MLXiibqHbqIOVneqdocemSBc22VpBKxt4J6FQzy9HarQ==} engines: {node: '>=6.0.0'} @@ -312,6 +508,59 @@ packages: '@babel/types': 7.21.5 dev: true + /@babel/parser@7.24.4: + resolution: {integrity: sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.21.5 + dev: true + + /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.21.5): + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.5 + '@babel/helper-plugin-utils': 7.21.5 + dev: true + + /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.21.5): + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.5 + '@babel/helper-plugin-utils': 7.21.5 + dev: true + + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.21.5): + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.5 + '@babel/helper-plugin-utils': 7.21.5 + dev: true + + /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.21.5): + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.5 + '@babel/helper-plugin-utils': 7.21.5 + dev: true + + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.21.5): + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.5 + '@babel/helper-plugin-utils': 7.21.5 + dev: true + /@babel/plugin-syntax-jsx@7.21.4(@babel/core@7.21.5): resolution: {integrity: sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==} engines: {node: '>=6.9.0'} @@ -322,6 +571,80 @@ packages: '@babel/helper-plugin-utils': 7.21.5 dev: true + /@babel/plugin-syntax-jsx@7.21.4(@babel/core@7.24.4): + resolution: {integrity: sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.21.5 + dev: true + + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.21.5): + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.5 + '@babel/helper-plugin-utils': 7.21.5 + dev: true + + /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.21.5): + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.5 + '@babel/helper-plugin-utils': 7.21.5 + dev: true + + /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.21.5): + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.5 + '@babel/helper-plugin-utils': 7.21.5 + dev: true + + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.21.5): + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.5 + '@babel/helper-plugin-utils': 7.21.5 + dev: true + + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.21.5): + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.5 + '@babel/helper-plugin-utils': 7.21.5 + dev: true + + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.21.5): + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.5 + '@babel/helper-plugin-utils': 7.21.5 + dev: true + + /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.21.5): + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.21.5 + '@babel/helper-plugin-utils': 7.21.5 + dev: true + /@babel/plugin-syntax-typescript@7.21.4(@babel/core@7.21.5): resolution: {integrity: sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==} engines: {node: '>=6.9.0'} @@ -332,6 +655,16 @@ packages: '@babel/helper-plugin-utils': 7.21.5 dev: true + /@babel/plugin-syntax-typescript@7.21.4(@babel/core@7.24.4): + resolution: {integrity: sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.21.5 + dev: true + /@babel/plugin-transform-modules-commonjs@7.21.5(@babel/core@7.21.5): resolution: {integrity: sha512-OVryBEgKUbtqMoB7eG2rs6UFexJi6Zj6FDXx+esBLPTCxCNxAY9o+8Di7IsUGJ+AVhp5ncK0fxWUBd0/1gPhrQ==} engines: {node: '>=6.9.0'} @@ -346,6 +679,20 @@ packages: - supports-color dev: true + /@babel/plugin-transform-modules-commonjs@7.21.5(@babel/core@7.24.4): + resolution: {integrity: sha512-OVryBEgKUbtqMoB7eG2rs6UFexJi6Zj6FDXx+esBLPTCxCNxAY9o+8Di7IsUGJ+AVhp5ncK0fxWUBd0/1gPhrQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-module-transforms': 7.21.5 + '@babel/helper-plugin-utils': 7.21.5 + '@babel/helper-simple-access': 7.21.5 + transitivePeerDependencies: + - supports-color + dev: true + /@babel/plugin-transform-typescript@7.21.3(@babel/core@7.21.5): resolution: {integrity: sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==} engines: {node: '>=6.9.0'} @@ -361,6 +708,21 @@ packages: - supports-color dev: true + /@babel/plugin-transform-typescript@7.21.3(@babel/core@7.24.4): + resolution: {integrity: sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-annotate-as-pure': 7.18.6 + '@babel/helper-create-class-features-plugin': 7.21.5(@babel/core@7.24.4) + '@babel/helper-plugin-utils': 7.21.5 + '@babel/plugin-syntax-typescript': 7.21.4(@babel/core@7.24.4) + transitivePeerDependencies: + - supports-color + dev: true + /@babel/preset-typescript@7.21.5(@babel/core@7.21.5): resolution: {integrity: sha512-iqe3sETat5EOrORXiQ6rWfoOg2y68Cs75B9wNxdPW4kixJxh7aXQE1KPdWLDniC24T/6dSnguF33W9j/ZZQcmA==} engines: {node: '>=6.9.0'} @@ -377,6 +739,29 @@ packages: - supports-color dev: true + /@babel/preset-typescript@7.21.5(@babel/core@7.24.4): + resolution: {integrity: sha512-iqe3sETat5EOrORXiQ6rWfoOg2y68Cs75B9wNxdPW4kixJxh7aXQE1KPdWLDniC24T/6dSnguF33W9j/ZZQcmA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-plugin-utils': 7.21.5 + '@babel/helper-validator-option': 7.21.0 + '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.24.4) + '@babel/plugin-transform-modules-commonjs': 7.21.5(@babel/core@7.24.4) + '@babel/plugin-transform-typescript': 7.21.3(@babel/core@7.24.4) + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/runtime@7.24.4: + resolution: {integrity: sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 + dev: true + /@babel/template@7.20.7: resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==} engines: {node: '>=6.9.0'} @@ -386,6 +771,15 @@ packages: '@babel/types': 7.21.5 dev: true + /@babel/template@7.24.0: + resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.24.2 + '@babel/parser': 7.24.4 + '@babel/types': 7.24.0 + dev: true + /@babel/traverse@7.21.5: resolution: {integrity: sha512-AhQoI3YjWi6u/y/ntv7k48mcrCXmus0t79J9qPNlk/lAsFlCiJ047RmbfMOawySTHtywXhbXgpx/8nXMYd+oFw==} engines: {node: '>=6.9.0'} @@ -404,14 +798,63 @@ packages: - supports-color dev: true - /@babel/types@7.21.5: - resolution: {integrity: sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==} + /@babel/traverse@7.24.1: + resolution: {integrity: sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-string-parser': 7.21.5 - '@babel/helper-validator-identifier': 7.19.1 - to-fast-properties: 2.0.0 + '@babel/code-frame': 7.24.2 + '@babel/generator': 7.24.4 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.24.4 + '@babel/types': 7.24.0 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types@7.21.5: + resolution: {integrity: sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.21.5 + '@babel/helper-validator-identifier': 7.19.1 + to-fast-properties: 2.0.0 + dev: true + + /@babel/types@7.24.0: + resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.24.1 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + dev: true + + /@bcoe/v8-coverage@0.2.3: + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true + + /@esbuild/aix-ppc64@0.19.12: + resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true + dev: true + optional: true + + /@esbuild/aix-ppc64@0.20.2: + resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [aix] + requiresBuild: true dev: true + optional: true /@esbuild/android-arm64@0.16.16: resolution: {integrity: sha512-hFHVAzUKp9Tf8psGq+bDVv+6hTy1bAOoV/jJMUWwhUnIHsh6WbFMhw0ZTkqDuh7TdpffFoHOiIOIxmHc7oYRBQ==} @@ -422,6 +865,24 @@ packages: dev: true optional: true + /@esbuild/android-arm64@0.19.12: + resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm64@0.20.2: + resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-arm@0.15.18: resolution: {integrity: sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==} engines: {node: '>=12'} @@ -440,6 +901,24 @@ packages: dev: true optional: true + /@esbuild/android-arm@0.19.12: + resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.20.2: + resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/android-x64@0.16.16: resolution: {integrity: sha512-9WhxJpeb6XumlfivldxqmkJepEcELekmSw3NkGrs+Edq6sS5KRxtUBQuKYDD7KqP59dDkxVbaoPIQFKWQG0KLg==} engines: {node: '>=12'} @@ -449,6 +928,24 @@ packages: dev: true optional: true + /@esbuild/android-x64@0.19.12: + resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.20.2: + resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-arm64@0.16.16: resolution: {integrity: sha512-8Z+wld+vr/prHPi2O0X7o1zQOfMbXWGAw9hT0jEyU/l/Yrg+0Z3FO9pjPho72dVkZs4ewZk0bDOFLdZHm8jEfw==} engines: {node: '>=12'} @@ -458,6 +955,24 @@ packages: dev: true optional: true + /@esbuild/darwin-arm64@0.19.12: + resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.20.2: + resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/darwin-x64@0.16.16: resolution: {integrity: sha512-CYkxVvkZzGCqFrt7EgjFxQKhlUPyDkuR9P0Y5wEcmJqVI8ncerOIY5Kej52MhZyzOBXkYrJgZeVZC9xXXoEg9A==} engines: {node: '>=12'} @@ -467,6 +982,24 @@ packages: dev: true optional: true + /@esbuild/darwin-x64@0.19.12: + resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.20.2: + resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-arm64@0.16.16: resolution: {integrity: sha512-fxrw4BYqQ39z/3Ja9xj/a1gMsVq0xEjhSyI4a9MjfvDDD8fUV8IYliac96i7tzZc3+VytyXX+XNsnpEk5sw5Wg==} engines: {node: '>=12'} @@ -476,6 +1009,24 @@ packages: dev: true optional: true + /@esbuild/freebsd-arm64@0.19.12: + resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.20.2: + resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/freebsd-x64@0.16.16: resolution: {integrity: sha512-8p3v1D+du2jiDvSoNVimHhj7leSfST9YlKsAEO7etBfuqjaBMndo0fmjNLp0JCMld+XIx9L80tooOkyUv1a1PQ==} engines: {node: '>=12'} @@ -485,6 +1036,24 @@ packages: dev: true optional: true + /@esbuild/freebsd-x64@0.19.12: + resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.20.2: + resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm64@0.16.16: resolution: {integrity: sha512-N3u6BBbCVY3xeP2D8Db7QY8I+nZ+2AgOopUIqk+5yCoLnsWkcVxD2ay5E9iIdvApFi1Vg1lZiiwaVp8bOpAc4A==} engines: {node: '>=12'} @@ -494,6 +1063,24 @@ packages: dev: true optional: true + /@esbuild/linux-arm64@0.19.12: + resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.20.2: + resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-arm@0.16.16: resolution: {integrity: sha512-bYaocE1/PTMRmkgSckZ0D0Xn2nox8v2qlk+MVVqm+VECNKDdZvghVZtH41dNtBbwADSvA6qkCHGYeWm9LrNCBw==} engines: {node: '>=12'} @@ -503,6 +1090,24 @@ packages: dev: true optional: true + /@esbuild/linux-arm@0.19.12: + resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.20.2: + resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ia32@0.16.16: resolution: {integrity: sha512-dxjqLKUW8GqGemoRT9v8IgHk+T4tRm1rn1gUcArsp26W9EkK/27VSjBVUXhEG5NInHZ92JaQ3SSMdTwv/r9a2A==} engines: {node: '>=12'} @@ -512,6 +1117,24 @@ packages: dev: true optional: true + /@esbuild/linux-ia32@0.19.12: + resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.20.2: + resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-loong64@0.15.18: resolution: {integrity: sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==} engines: {node: '>=12'} @@ -530,6 +1153,24 @@ packages: dev: true optional: true + /@esbuild/linux-loong64@0.19.12: + resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.20.2: + resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-mips64el@0.16.16: resolution: {integrity: sha512-CO3YmO7jYMlGqGoeFeKzdwx/bx8Vtq/SZaMAi+ZLDUnDUdfC7GmGwXzIwDJ70Sg+P9pAemjJyJ1icKJ9R3q/Fg==} engines: {node: '>=12'} @@ -539,6 +1180,24 @@ packages: dev: true optional: true + /@esbuild/linux-mips64el@0.19.12: + resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.20.2: + resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + /@esbuild/linux-ppc64@0.16.16: resolution: {integrity: sha512-DSl5Czh5hCy/7azX0Wl9IdzPHX2H8clC6G87tBnZnzUpNgRxPFhfmArbaHoAysu4JfqCqbB/33u/GL9dUgCBAw==} engines: {node: '>=12'} @@ -548,898 +1207,3070 @@ packages: dev: true optional: true - /@esbuild/linux-riscv64@0.16.16: - resolution: {integrity: sha512-sSVVMEXsqf1fQu0j7kkhXMViroixU5XoaJXl1u/u+jbXvvhhCt9YvA/B6VM3aM/77HuRQ94neS5bcisijGnKFQ==} + /@esbuild/linux-ppc64@0.19.12: + resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} engines: {node: '>=12'} - cpu: [riscv64] + cpu: [ppc64] os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/linux-s390x@0.16.16: - resolution: {integrity: sha512-jRqBCre9gZGoCdCN/UWCCMwCMsOg65IpY9Pyj56mKCF5zXy9d60kkNRdDN6YXGjr3rzcC4DXnS/kQVCGcC4yPQ==} + /@esbuild/linux-ppc64@0.20.2: + resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} engines: {node: '>=12'} - cpu: [s390x] + cpu: [ppc64] os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/linux-x64@0.16.16: - resolution: {integrity: sha512-G1+09TopOzo59/55lk5Q0UokghYLyHTKKzD5lXsAOOlGDbieGEFJpJBr3BLDbf7cz89KX04sBeExAR/pL/26sA==} + /@esbuild/linux-riscv64@0.16.16: + resolution: {integrity: sha512-sSVVMEXsqf1fQu0j7kkhXMViroixU5XoaJXl1u/u+jbXvvhhCt9YvA/B6VM3aM/77HuRQ94neS5bcisijGnKFQ==} engines: {node: '>=12'} - cpu: [x64] + cpu: [riscv64] os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/netbsd-x64@0.16.16: - resolution: {integrity: sha512-xwjGJB5wwDEujLaJIrSMRqWkbigALpBNcsF9SqszoNKc+wY4kPTdKrSxiY5ik3IatojePP+WV108MvF6q6np4w==} + /@esbuild/linux-riscv64@0.19.12: + resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] + cpu: [riscv64] + os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/openbsd-x64@0.16.16: - resolution: {integrity: sha512-yeERkoxG2nR2oxO5n+Ms7MsCeNk23zrby2GXCqnfCpPp7KNc0vxaaacIxb21wPMfXXRhGBrNP4YLIupUBrWdlg==} + /@esbuild/linux-riscv64@0.20.2: + resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] + cpu: [riscv64] + os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/sunos-x64@0.16.16: - resolution: {integrity: sha512-nHfbEym0IObXPhtX6Va3H5GaKBty2kdhlAhKmyCj9u255ktAj0b1YACUs9j5H88NRn9cJCthD1Ik/k9wn8YKVg==} + /@esbuild/linux-s390x@0.16.16: + resolution: {integrity: sha512-jRqBCre9gZGoCdCN/UWCCMwCMsOg65IpY9Pyj56mKCF5zXy9d60kkNRdDN6YXGjr3rzcC4DXnS/kQVCGcC4yPQ==} engines: {node: '>=12'} - cpu: [x64] - os: [sunos] + cpu: [s390x] + os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/win32-arm64@0.16.16: - resolution: {integrity: sha512-pdD+M1ZOFy4hE15ZyPX09fd5g4DqbbL1wXGY90YmleVS6Y5YlraW4BvHjim/X/4yuCpTsAFvsT4Nca2lbyDH/A==} + /@esbuild/linux-s390x@0.19.12: + resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} engines: {node: '>=12'} - cpu: [arm64] - os: [win32] + cpu: [s390x] + os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/win32-ia32@0.16.16: - resolution: {integrity: sha512-IPEMfU9p0c3Vb8PqxaPX6BM9rYwlTZGYOf9u+kMdhoILZkVKEjq6PKZO0lB+isojWwAnAqh4ZxshD96njTXajg==} + /@esbuild/linux-s390x@0.20.2: + resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} engines: {node: '>=12'} - cpu: [ia32] - os: [win32] + cpu: [s390x] + os: [linux] requiresBuild: true dev: true optional: true - /@esbuild/win32-x64@0.16.16: - resolution: {integrity: sha512-1YYpoJ39WV/2bnShPwgdzJklc+XS0bysN6Tpnt1cWPdeoKOG4RMEY1g7i534QxXX/rPvNx/NLJQTTCeORYzipg==} + /@esbuild/linux-x64@0.16.16: + resolution: {integrity: sha512-G1+09TopOzo59/55lk5Q0UokghYLyHTKKzD5lXsAOOlGDbieGEFJpJBr3BLDbf7cz89KX04sBeExAR/pL/26sA==} engines: {node: '>=12'} cpu: [x64] - os: [win32] + os: [linux] requiresBuild: true dev: true optional: true - /@jridgewell/gen-mapping@0.3.3: - resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.18 - dev: true - - /@jridgewell/resolve-uri@3.1.0: - resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} - engines: {node: '>=6.0.0'} + /@esbuild/linux-x64@0.19.12: + resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true dev: true + optional: true - /@jridgewell/set-array@1.1.2: - resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} - engines: {node: '>=6.0.0'} + /@esbuild/linux-x64@0.20.2: + resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true dev: true + optional: true - /@jridgewell/sourcemap-codec@1.4.14: - resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} + /@esbuild/netbsd-x64@0.16.16: + resolution: {integrity: sha512-xwjGJB5wwDEujLaJIrSMRqWkbigALpBNcsF9SqszoNKc+wY4kPTdKrSxiY5ik3IatojePP+WV108MvF6q6np4w==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true dev: true + optional: true - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + /@esbuild/netbsd-x64@0.19.12: + resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true dev: true + optional: true - /@jridgewell/trace-mapping@0.3.18: - resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} - dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.14 + /@esbuild/netbsd-x64@0.20.2: + resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true dev: true + optional: true - /@jridgewell/trace-mapping@0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.0 - '@jridgewell/sourcemap-codec': 1.4.15 + /@esbuild/openbsd-x64@0.16.16: + resolution: {integrity: sha512-yeERkoxG2nR2oxO5n+Ms7MsCeNk23zrby2GXCqnfCpPp7KNc0vxaaacIxb21wPMfXXRhGBrNP4YLIupUBrWdlg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true dev: true + optional: true - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 + /@esbuild/openbsd-x64@0.19.12: + resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true dev: true + optional: true - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} + /@esbuild/openbsd-x64@0.20.2: + resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true dev: true + optional: true - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.13.0 + /@esbuild/sunos-x64@0.16.16: + resolution: {integrity: sha512-nHfbEym0IObXPhtX6Va3H5GaKBty2kdhlAhKmyCj9u255ktAj0b1YACUs9j5H88NRn9cJCthD1Ik/k9wn8YKVg==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true dev: true + optional: true - /@polka/url@1.0.0-next.21: - resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} + /@esbuild/sunos-x64@0.19.12: + resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true dev: true + optional: true - /@rollup/pluginutils@5.0.2(rollup@3.9.1): - resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@types/estree': 1.0.1 - estree-walker: 2.0.2 - picomatch: 2.3.1 - rollup: 3.9.1 + /@esbuild/sunos-x64@0.20.2: + resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true dev: true + optional: true - /@types/debug@4.1.7: - resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==} - dependencies: - '@types/ms': 0.7.31 + /@esbuild/win32-arm64@0.16.16: + resolution: {integrity: sha512-pdD+M1ZOFy4hE15ZyPX09fd5g4DqbbL1wXGY90YmleVS6Y5YlraW4BvHjim/X/4yuCpTsAFvsT4Nca2lbyDH/A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true dev: true + optional: true - /@types/estree@1.0.1: - resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} + /@esbuild/win32-arm64@0.19.12: + resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true dev: true + optional: true - /@types/mdast@3.0.10: - resolution: {integrity: sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==} - dependencies: - '@types/unist': 2.0.6 + /@esbuild/win32-arm64@0.20.2: + resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true dev: true + optional: true - /@types/ms@0.7.31: - resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} + /@esbuild/win32-ia32@0.16.16: + resolution: {integrity: sha512-IPEMfU9p0c3Vb8PqxaPX6BM9rYwlTZGYOf9u+kMdhoILZkVKEjq6PKZO0lB+isojWwAnAqh4ZxshD96njTXajg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true dev: true + optional: true - /@types/node@18.11.18: - resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==} + /@esbuild/win32-ia32@0.19.12: + resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true dev: true + optional: true - /@types/three@0.149.0: - resolution: {integrity: sha512-fgNBm9LWc65ER/W0cvoXdC0iMy7Ke9e2CONmEr6Jt8sDSY3sw4DgOubZfmdZ747dkPhbQrgRQAWwDEr2S/7IEg==} - dependencies: - '@types/webxr': 0.5.1 - dev: false - - /@types/unist@2.0.6: - resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} + /@esbuild/win32-ia32@0.20.2: + resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true dev: true + optional: true - /@types/webxr@0.5.1: - resolution: {integrity: sha512-xlFXPfgJR5vIuDefhaHuUM9uUgvPaXB6GKdXy2gdEh8gBWQZ2ul24AJz3foUd8NNKlSTQuWYJpCb1/pL81m1KQ==} - dev: false - - /@vinxi/tsconfig@0.0.3: - resolution: {integrity: sha512-97jCGpffst+IXmzzm+R2MIRNDxo9mPjFESszx38Nkm7NAPgUN/yKFkg3WS+W/sySSjm5evVR8oA+qBTlbMUcww==} + /@esbuild/win32-x64@0.16.16: + resolution: {integrity: sha512-1YYpoJ39WV/2bnShPwgdzJklc+XS0bysN6Tpnt1cWPdeoKOG4RMEY1g7i534QxXX/rPvNx/NLJQTTCeORYzipg==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true dev: true + optional: true - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 + /@esbuild/win32-x64@0.19.12: + resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true dev: true + optional: true - /any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + /@esbuild/win32-x64@0.20.2: + resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true dev: true + optional: true - /anymatch@3.1.2: - resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} - engines: {node: '>= 8'} + /@istanbuljs/load-nyc-config@1.1.0: + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 dev: true - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + /@istanbuljs/schema@0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} dev: true - /babel-plugin-jsx-dom-expressions@0.36.10(@babel/core@7.21.5): - resolution: {integrity: sha512-QA2k/14WGw+RgcGGnEuLWwnu4em6CGhjeXtjvgOYyFHYS2a+CzPeaVQHDOlfuiBcjq/3hWMspHMIMnPEOIzdBg==} - peerDependencies: - '@babel/core': ^7.20.12 + /@jest/console@29.7.0: + resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@babel/core': 7.21.5 - '@babel/helper-module-imports': 7.18.6 - '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.21.5) - '@babel/types': 7.21.5 - html-entities: 2.3.3 - validate-html-nesting: 1.2.2 + '@jest/types': 29.6.3 + '@types/node': 18.11.18 + chalk: 4.1.2 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 dev: true - /babel-preset-solid@1.7.3(@babel/core@7.21.5): - resolution: {integrity: sha512-HOdyrij99zo+CBrmtDxSexBAl54vCBCfBoyueLBvcfVniaEXNd4ftKqSN6XQcLvFfCY28UFO+DHaigXzWKOfzg==} + /@jest/core@29.7.0: + resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: - '@babel/core': ^7.0.0 + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true dependencies: - '@babel/core': 7.21.5 - babel-plugin-jsx-dom-expressions: 0.36.10(@babel/core@7.21.5) + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 18.11.18 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@18.11.18) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.5 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node dev: true - /bail@2.0.2: - resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + /@jest/environment@29.7.0: + resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 18.11.18 + jest-mock: 29.7.0 dev: true - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + /@jest/expect-utils@29.7.0: + resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-get-type: 29.6.3 dev: true - /binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} - engines: {node: '>=8'} + /@jest/expect@29.7.0: + resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + expect: 29.7.0 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color dev: true - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + /@jest/fake-timers@29.7.0: + resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 18.11.18 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 dev: true - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} + /@jest/globals@29.7.0: + resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - fill-range: 7.0.1 + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/types': 29.6.3 + jest-mock: 29.7.0 + transitivePeerDependencies: + - supports-color dev: true - /browserslist@4.21.5: - resolution: {integrity: sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true + /@jest/reporters@29.7.0: + resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true dependencies: - caniuse-lite: 1.0.30001481 - electron-to-chromium: 1.4.377 - node-releases: 2.0.10 - update-browserslist-db: 1.0.11(browserslist@4.21.5) + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.18 + '@types/node': 18.11.18 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.1.6 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.7 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + jest-worker: 29.7.0 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.2.0 + transitivePeerDependencies: + - supports-color dev: true - /bundle-require@3.1.2(esbuild@0.15.18): - resolution: {integrity: sha512-Of6l6JBAxiyQ5axFxUM6dYeP/W7X2Sozeo/4EYB9sJhL+dqL7TKjg+shwxp6jlu/6ZSERfsYtIpSJ1/x3XkAEA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - peerDependencies: - esbuild: '>=0.13' + /@jest/schemas@29.6.3: + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - esbuild: 0.15.18 - load-tsconfig: 0.2.3 + '@sinclair/typebox': 0.27.8 dev: true - /cac@6.7.12: - resolution: {integrity: sha512-rM7E2ygtMkJqD9c7WnFU6fruFcN3xe4FM5yUmgxhZzIKJk4uHl9U/fhwdajGFQbQuv43FAUo1Fe8gX/oIKDeSA==} - engines: {node: '>=8'} + /@jest/source-map@29.6.3: + resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jridgewell/trace-mapping': 0.3.18 + callsites: 3.1.0 + graceful-fs: 4.2.11 dev: true - /caniuse-lite@1.0.30001481: - resolution: {integrity: sha512-KCqHwRnaa1InZBtqXzP98LPg0ajCVujMKjqKDhZEthIpAsJl/YEIa3YvXjGXPVqzZVguccuu7ga9KOE1J9rKPQ==} + /@jest/test-result@29.7.0: + resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/console': 29.7.0 + '@jest/types': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 dev: true - /ccount@2.0.1: - resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + /@jest/test-sequencer@29.7.0: + resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/test-result': 29.7.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + slash: 3.0.0 dev: true - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} + /@jest/transform@29.7.0: + resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 + '@babel/core': 7.21.5 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.18 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.5 + pirates: 4.0.5 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color dev: true - /character-entities@2.0.1: - resolution: {integrity: sha512-OzmutCf2Kmc+6DrFrrPS8/tDh2+DpnrfzdICHWhcVC9eOd0N1PXmQEE1a8iM4IziIAG+8tmTq3K+oo0ubH6RRQ==} + /@jest/types@29.6.3: + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 18.11.18 + '@types/yargs': 17.0.32 + chalk: 4.1.2 dev: true - /chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} + /@jridgewell/gen-mapping@0.3.3: + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + engines: {node: '>=6.0.0'} dependencies: - anymatch: 3.1.2 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.2 + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.18 dev: true - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + /@jridgewell/gen-mapping@0.3.5: + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} dependencies: - color-name: 1.1.3 + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.25 dev: true - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + /@jridgewell/resolve-uri@3.1.0: + resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} + engines: {node: '>=6.0.0'} dev: true - /commander@4.1.1: - resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} - engines: {node: '>= 6'} + /@jridgewell/set-array@1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} dev: true - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + /@jridgewell/set-array@1.2.1: + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} dev: true - /convert-source-map@1.8.0: - resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} - dependencies: - safe-buffer: 5.1.2 + /@jridgewell/sourcemap-codec@1.4.14: + resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} dev: true - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} dev: true - /csstype@3.1.2: - resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} + /@jridgewell/trace-mapping@0.3.18: + resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} + dependencies: + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.14 dev: true - /debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + /@jridgewell/trace-mapping@0.3.25: + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} dependencies: - ms: 2.1.2 + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.15 dev: true - /decode-named-character-reference@1.0.1: - resolution: {integrity: sha512-YV/0HQHreRwKb7uBopyIkLG17jG6Sv2qUchk9qSoVJ2f+flwRsPNBO0hAnjt6mTNYUT+vw9Gy2ihXg4sUWPi2w==} + /@jridgewell/trace-mapping@0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} dependencies: - character-entities: 2.0.1 + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.15 dev: true - /dequal@2.0.2: - resolution: {integrity: sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug==} - engines: {node: '>=6'} + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 dev: true - /diff@5.0.0: - resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} - engines: {node: '>=0.3.1'} + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} dev: true - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} dependencies: - path-type: 4.0.0 + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.13.0 dev: true - /electron-to-chromium@1.4.377: - resolution: {integrity: sha512-H3BYG6DW5Z+l0xcfXaicJGxrpA4kMlCxnN71+iNX+dBLkRMOdVJqFJiAmbNZZKA1zISpRg17JR03qGifXNsJtw==} + /@polka/url@1.0.0-next.21: + resolution: {integrity: sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g==} dev: true - /esbuild-android-64@0.15.18: - resolution: {integrity: sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - requiresBuild: true + /@rollup/pluginutils@5.0.2(rollup@3.9.1): + resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.1 + estree-walker: 2.0.2 + picomatch: 2.3.1 + rollup: 3.9.1 dev: true - optional: true - /esbuild-android-arm64@0.15.18: - resolution: {integrity: sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==} - engines: {node: '>=12'} - cpu: [arm64] + /@rollup/rollup-android-arm-eabi@4.14.3: + resolution: {integrity: sha512-X9alQ3XM6I9IlSlmC8ddAvMSyG1WuHk5oUnXGw+yUBs3BFoTizmG1La/Gr8fVJvDWAq+zlYTZ9DBgrlKRVY06g==} + cpu: [arm] os: [android] requiresBuild: true dev: true optional: true - /esbuild-darwin-64@0.15.18: - resolution: {integrity: sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] + /@rollup/rollup-android-arm64@4.14.3: + resolution: {integrity: sha512-eQK5JIi+POhFpzk+LnjKIy4Ks+pwJ+NXmPxOCSvOKSNRPONzKuUvWE+P9JxGZVxrtzm6BAYMaL50FFuPe0oWMQ==} + cpu: [arm64] + os: [android] requiresBuild: true dev: true optional: true - /esbuild-darwin-arm64@0.15.18: - resolution: {integrity: sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==} - engines: {node: '>=12'} + /@rollup/rollup-darwin-arm64@4.14.3: + resolution: {integrity: sha512-Od4vE6f6CTT53yM1jgcLqNfItTsLt5zE46fdPaEmeFHvPs5SjZYlLpHrSiHEKR1+HdRfxuzXHjDOIxQyC3ptBA==} cpu: [arm64] os: [darwin] requiresBuild: true dev: true optional: true - /esbuild-freebsd-64@0.15.18: - resolution: {integrity: sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==} - engines: {node: '>=12'} + /@rollup/rollup-darwin-x64@4.14.3: + resolution: {integrity: sha512-0IMAO21axJeNIrvS9lSe/PGthc8ZUS+zC53O0VhF5gMxfmcKAP4ESkKOCwEi6u2asUrt4mQv2rjY8QseIEb1aw==} cpu: [x64] - os: [freebsd] + os: [darwin] requiresBuild: true dev: true optional: true - /esbuild-freebsd-arm64@0.15.18: - resolution: {integrity: sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] + /@rollup/rollup-linux-arm-gnueabihf@4.14.3: + resolution: {integrity: sha512-ge2DC7tHRHa3caVEoSbPRJpq7azhG+xYsd6u2MEnJ6XzPSzQsTKyXvh6iWjXRf7Rt9ykIUWHtl0Uz3T6yXPpKw==} + cpu: [arm] + os: [linux] requiresBuild: true dev: true optional: true - /esbuild-linux-32@0.15.18: - resolution: {integrity: sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==} - engines: {node: '>=12'} - cpu: [ia32] + /@rollup/rollup-linux-arm-musleabihf@4.14.3: + resolution: {integrity: sha512-ljcuiDI4V3ySuc7eSk4lQ9wU8J8r8KrOUvB2U+TtK0TiW6OFDmJ+DdIjjwZHIw9CNxzbmXY39wwpzYuFDwNXuw==} + cpu: [arm] os: [linux] requiresBuild: true dev: true optional: true - /esbuild-linux-64@0.15.18: - resolution: {integrity: sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==} - engines: {node: '>=12'} - cpu: [x64] + /@rollup/rollup-linux-arm64-gnu@4.14.3: + resolution: {integrity: sha512-Eci2us9VTHm1eSyn5/eEpaC7eP/mp5n46gTRB3Aar3BgSvDQGJZuicyq6TsH4HngNBgVqC5sDYxOzTExSU+NjA==} + cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true - /esbuild-linux-arm64@0.15.18: - resolution: {integrity: sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==} - engines: {node: '>=12'} + /@rollup/rollup-linux-arm64-musl@4.14.3: + resolution: {integrity: sha512-UrBoMLCq4E92/LCqlh+blpqMz5h1tJttPIniwUgOFJyjWI1qrtrDhhpHPuFxULlUmjFHfloWdixtDhSxJt5iKw==} cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true - /esbuild-linux-arm@0.15.18: - resolution: {integrity: sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==} - engines: {node: '>=12'} - cpu: [arm] + /@rollup/rollup-linux-powerpc64le-gnu@4.14.3: + resolution: {integrity: sha512-5aRjvsS8q1nWN8AoRfrq5+9IflC3P1leMoy4r2WjXyFqf3qcqsxRCfxtZIV58tCxd+Yv7WELPcO9mY9aeQyAmw==} + cpu: [ppc64] os: [linux] requiresBuild: true dev: true optional: true - /esbuild-linux-mips64le@0.15.18: - resolution: {integrity: sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==} - engines: {node: '>=12'} - cpu: [mips64el] + /@rollup/rollup-linux-riscv64-gnu@4.14.3: + resolution: {integrity: sha512-sk/Qh1j2/RJSX7FhEpJn8n0ndxy/uf0kI/9Zc4b1ELhqULVdTfN6HL31CDaTChiBAOgLcsJ1sgVZjWv8XNEsAQ==} + cpu: [riscv64] os: [linux] requiresBuild: true dev: true optional: true - /esbuild-linux-ppc64le@0.15.18: - resolution: {integrity: sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==} - engines: {node: '>=12'} - cpu: [ppc64] + /@rollup/rollup-linux-s390x-gnu@4.14.3: + resolution: {integrity: sha512-jOO/PEaDitOmY9TgkxF/TQIjXySQe5KVYB57H/8LRP/ux0ZoO8cSHCX17asMSv3ruwslXW/TLBcxyaUzGRHcqg==} + cpu: [s390x] os: [linux] requiresBuild: true dev: true optional: true - /esbuild-linux-riscv64@0.15.18: - resolution: {integrity: sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==} - engines: {node: '>=12'} - cpu: [riscv64] + /@rollup/rollup-linux-x64-gnu@4.14.3: + resolution: {integrity: sha512-8ybV4Xjy59xLMyWo3GCfEGqtKV5M5gCSrZlxkPGvEPCGDLNla7v48S662HSGwRd6/2cSneMQWiv+QzcttLrrOA==} + cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true - /esbuild-linux-s390x@0.15.18: - resolution: {integrity: sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==} - engines: {node: '>=12'} - cpu: [s390x] + /@rollup/rollup-linux-x64-musl@4.14.3: + resolution: {integrity: sha512-s+xf1I46trOY10OqAtZ5Rm6lzHre/UiLA1J2uOhCFXWkbZrJRkYBPO6FhvGfHmdtQ3Bx793MNa7LvoWFAm93bg==} + cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true - /esbuild-netbsd-64@0.15.18: - resolution: {integrity: sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] + /@rollup/rollup-win32-arm64-msvc@4.14.3: + resolution: {integrity: sha512-+4h2WrGOYsOumDQ5S2sYNyhVfrue+9tc9XcLWLh+Kw3UOxAvrfOrSMFon60KspcDdytkNDh7K2Vs6eMaYImAZg==} + cpu: [arm64] + os: [win32] requiresBuild: true dev: true optional: true - /esbuild-openbsd-64@0.15.18: - resolution: {integrity: sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] + /@rollup/rollup-win32-ia32-msvc@4.14.3: + resolution: {integrity: sha512-T1l7y/bCeL/kUwh9OD4PQT4aM7Bq43vX05htPJJ46RTI4r5KNt6qJRzAfNfM+OYMNEVBWQzR2Gyk+FXLZfogGw==} + cpu: [ia32] + os: [win32] requiresBuild: true dev: true optional: true - /esbuild-register@3.4.2(esbuild@0.16.16): - resolution: {integrity: sha512-kG/XyTDyz6+YDuyfB9ZoSIOOmgyFCH+xPRtsCa8W85HLRV5Csp+o3jWVbOSHgSLfyLc5DmP+KFDNwty4mEjC+Q==} + /@rollup/rollup-win32-x64-msvc@4.14.3: + resolution: {integrity: sha512-/BypzV0H1y1HzgYpxqRaXGBRqfodgoBBCcsrujT6QRcakDQdfU+Lq9PENPh5jB4I44YWq+0C2eHsHya+nZY1sA==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@sinclair/typebox@0.27.8: + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + dev: true + + /@sinonjs/commons@3.0.1: + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + dependencies: + type-detect: 4.0.8 + dev: true + + /@sinonjs/fake-timers@10.3.0: + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + dependencies: + '@sinonjs/commons': 3.0.1 + dev: true + + /@solid-primitives/event-listener@2.3.3(solid-js@1.8.17): + resolution: {integrity: sha512-DAJbl+F0wrFW2xmcV8dKMBhk9QLVLuBSW+TR4JmIfTaObxd13PuL7nqaXnaYKDWOYa6otB00qcCUIGbuIhSUgQ==} peerDependencies: - esbuild: '>=0.12 <1' + solid-js: ^1.6.12 + dependencies: + '@solid-primitives/utils': 6.2.3(solid-js@1.8.17) + solid-js: 1.8.17 + dev: false + + /@solid-primitives/resize-observer@2.0.25(solid-js@1.8.17): + resolution: {integrity: sha512-jVDXkt2MiriYRaz4DYs62185d+6jQ+1DCsR+v7f6XMsIJJuf963qdBRFjtZtKXBaxdPNMyuPeDgf5XQe3EoDJg==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + '@solid-primitives/event-listener': 2.3.3(solid-js@1.8.17) + '@solid-primitives/rootless': 1.4.5(solid-js@1.8.17) + '@solid-primitives/static-store': 0.0.8(solid-js@1.8.17) + '@solid-primitives/utils': 6.2.3(solid-js@1.8.17) + solid-js: 1.8.17 + dev: false + + /@solid-primitives/rootless@1.4.5(solid-js@1.8.17): + resolution: {integrity: sha512-GFJE9GC3ojx0aUKqAUZmQPyU8fOVMtnVNrkdk2yS4kd17WqVSpXpoTmo9CnOwA+PG7FTzdIkogvfLQSLs4lrww==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + '@solid-primitives/utils': 6.2.3(solid-js@1.8.17) + solid-js: 1.8.17 + dev: false + + /@solid-primitives/static-store@0.0.8(solid-js@1.8.17): + resolution: {integrity: sha512-ZecE4BqY0oBk0YG00nzaAWO5Mjcny8Fc06CdbXadH9T9lzq/9GefqcSe/5AtdXqjvY/DtJ5C6CkcjPZO0o/eqg==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + '@solid-primitives/utils': 6.2.3(solid-js@1.8.17) + solid-js: 1.8.17 + dev: false + + /@solid-primitives/utils@6.2.3(solid-js@1.8.17): + resolution: {integrity: sha512-CqAwKb2T5Vi72+rhebSsqNZ9o67buYRdEJrIFzRXz3U59QqezuuxPsyzTSVCacwS5Pf109VRsgCJQoxKRoECZQ==} + peerDependencies: + solid-js: ^1.6.12 + dependencies: + solid-js: 1.8.17 + dev: false + + /@solidjs/testing-library@0.8.7(solid-js@1.8.17): + resolution: {integrity: sha512-1Wl6Ewk+JyxQVzfG95KHa3H7hmCrdNcLigRgm0ih8fEBhbnVZakGoU2uizAWi5/8biwGwV9OQqW+bJO+nnJZ1Q==} + engines: {node: '>= 14'} + peerDependencies: + '@solidjs/router': '>=0.9.0' + solid-js: '>=1.0.0' + peerDependenciesMeta: + '@solidjs/router': + optional: true + dependencies: + '@testing-library/dom': 9.3.4 + solid-js: 1.8.17 + dev: true + + /@testing-library/dom@9.3.4: + resolution: {integrity: sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==} + engines: {node: '>=14'} + dependencies: + '@babel/code-frame': 7.21.4 + '@babel/runtime': 7.24.4 + '@types/aria-query': 5.0.4 + aria-query: 5.1.3 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + dev: true + + /@tweenjs/tween.js@23.1.1: + resolution: {integrity: sha512-ZpboH7pCPPeyBWKf8c7TJswtCEQObFo3bOBYalm99NzZarATALYCo5OhbCa/n4RQyJyHfhkdx+hNrdL5ByFYDw==} + dev: true + + /@types/aria-query@5.0.4: + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + dev: true + + /@types/babel__core@7.20.5: + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + dependencies: + '@babel/parser': 7.21.5 + '@babel/types': 7.21.5 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.5 + dev: true + + /@types/babel__generator@7.6.8: + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + dependencies: + '@babel/types': 7.21.5 + dev: true + + /@types/babel__template@7.4.4: + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + dependencies: + '@babel/parser': 7.21.5 + '@babel/types': 7.21.5 + dev: true + + /@types/babel__traverse@7.20.5: + resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==} + dependencies: + '@babel/types': 7.21.5 + dev: true + + /@types/debug@4.1.7: + resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==} + dependencies: + '@types/ms': 0.7.31 + dev: true + + /@types/draco3d@1.4.9: + resolution: {integrity: sha512-4MMUjMQb4yA5fJ4osXx+QxGHt0/ZSy4spT6jL1HM7Tn8OJEC35siqdnpOo+HxPhYjqEFumKfGVF9hJfdyKBIBA==} + dev: true + + /@types/estree@1.0.1: + resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} + dev: true + + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: true + + /@types/graceful-fs@4.1.9: + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + dependencies: + '@types/node': 18.11.18 + dev: true + + /@types/istanbul-lib-coverage@2.0.6: + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + dev: true + + /@types/istanbul-lib-report@3.0.3: + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + dev: true + + /@types/istanbul-reports@3.0.4: + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + dependencies: + '@types/istanbul-lib-report': 3.0.3 + dev: true + + /@types/mdast@3.0.10: + resolution: {integrity: sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==} + dependencies: + '@types/unist': 2.0.6 + dev: true + + /@types/ms@0.7.31: + resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} + dev: true + + /@types/node@18.11.18: + resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==} + dev: true + + /@types/offscreencanvas@2019.7.3: + resolution: {integrity: sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==} + dev: true + + /@types/stack-utils@2.0.3: + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + dev: true + + /@types/stats.js@0.17.3: + resolution: {integrity: sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==} + dev: true + + /@types/three@0.164.0: + resolution: {integrity: sha512-SFDofn9dJVrE+1DKta7xj7lc4ru7B3S3yf10NsxOserW57aQlB6GxtAS1UK5To3LfEMN5HUHMu3n5v+M5rApgA==} + dependencies: + '@tweenjs/tween.js': 23.1.1 + '@types/stats.js': 0.17.3 + '@types/webxr': 0.5.15 + fflate: 0.8.2 + meshoptimizer: 0.18.1 + dev: true + + /@types/unist@2.0.6: + resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} + dev: true + + /@types/webxr@0.5.15: + resolution: {integrity: sha512-nC9116Gd4N+CqTxqo6gvCfhAMAzgRcfS8ZsciNodHq8uwW4JCVKwhagw8yN0XmC7mHrLnWqniJpoVEiR+72Drw==} + dev: true + + /@types/yargs-parser@21.0.3: + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + dev: true + + /@types/yargs@17.0.32: + resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} + dependencies: + '@types/yargs-parser': 21.0.3 + dev: true + + /@vinxi/tsconfig@0.0.3: + resolution: {integrity: sha512-97jCGpffst+IXmzzm+R2MIRNDxo9mPjFESszx38Nkm7NAPgUN/yKFkg3WS+W/sySSjm5evVR8oA+qBTlbMUcww==} + dev: true + + /@vitest/expect@1.5.0: + resolution: {integrity: sha512-0pzuCI6KYi2SIC3LQezmxujU9RK/vwC1U9R0rLuGlNGcOuDWxqWKu6nUdFsX9tH1WU0SXtAxToOsEjeUn1s3hA==} + dependencies: + '@vitest/spy': 1.5.0 + '@vitest/utils': 1.5.0 + chai: 4.4.1 + dev: true + + /@vitest/runner@1.5.0: + resolution: {integrity: sha512-7HWwdxXP5yDoe7DTpbif9l6ZmDwCzcSIK38kTSIt6CFEpMjX4EpCgT6wUmS0xTXqMI6E/ONmfgRKmaujpabjZQ==} + dependencies: + '@vitest/utils': 1.5.0 + p-limit: 5.0.0 + pathe: 1.1.2 + dev: true + + /@vitest/snapshot@1.5.0: + resolution: {integrity: sha512-qpv3fSEuNrhAO3FpH6YYRdaECnnRjg9VxbhdtPwPRnzSfHVXnNzzrpX4cJxqiwgRMo7uRMWDFBlsBq4Cr+rO3A==} + dependencies: + magic-string: 0.30.9 + pathe: 1.1.2 + pretty-format: 29.7.0 + dev: true + + /@vitest/spy@1.5.0: + resolution: {integrity: sha512-vu6vi6ew5N5MMHJjD5PoakMRKYdmIrNJmyfkhRpQt5d9Ewhw9nZ5Aqynbi3N61bvk9UvZ5UysMT6ayIrZ8GA9w==} + dependencies: + tinyspy: 2.2.1 + dev: true + + /@vitest/utils@1.5.0: + resolution: {integrity: sha512-BDU0GNL8MWkRkSRdNFvCUCAVOeHaUlVJ9Tx0TYBZyXaaOTmGtUFObzchCivIBrIwKzvZA7A9sCejVhXM2aY98A==} + dependencies: + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + dev: true + + /acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /agent-base@7.1.1: + resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} + engines: {node: '>= 14'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: true + + /any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + dev: true + + /anymatch@3.1.2: + resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + + /aria-query@5.1.3: + resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} + dependencies: + deep-equal: 2.2.3 + dev: true + + /array-buffer-byte-length@1.0.1: + resolution: {integrity: sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + is-array-buffer: 3.0.4 + dev: true + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + dev: true + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: true + + /available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + dependencies: + possible-typed-array-names: 1.0.0 + dev: true + + /babel-jest@29.7.0(@babel/core@7.21.5): + resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + dependencies: + '@babel/core': 7.21.5 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@7.21.5) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + dependencies: + '@babel/helper-plugin-utils': 7.21.5 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-jest-hoist@29.6.3: + resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/template': 7.20.7 + '@babel/types': 7.21.5 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.5 + dev: true + + /babel-plugin-jsx-dom-expressions@0.36.10(@babel/core@7.21.5): + resolution: {integrity: sha512-QA2k/14WGw+RgcGGnEuLWwnu4em6CGhjeXtjvgOYyFHYS2a+CzPeaVQHDOlfuiBcjq/3hWMspHMIMnPEOIzdBg==} + peerDependencies: + '@babel/core': ^7.20.12 + dependencies: + '@babel/core': 7.21.5 + '@babel/helper-module-imports': 7.18.6 + '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.21.5) + '@babel/types': 7.21.5 + html-entities: 2.3.3 + validate-html-nesting: 1.2.2 + dev: true + + /babel-plugin-jsx-dom-expressions@0.36.10(@babel/core@7.24.4): + resolution: {integrity: sha512-QA2k/14WGw+RgcGGnEuLWwnu4em6CGhjeXtjvgOYyFHYS2a+CzPeaVQHDOlfuiBcjq/3hWMspHMIMnPEOIzdBg==} + peerDependencies: + '@babel/core': ^7.20.12 + dependencies: + '@babel/core': 7.24.4 + '@babel/helper-module-imports': 7.18.6 + '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.24.4) + '@babel/types': 7.21.5 + html-entities: 2.3.3 + validate-html-nesting: 1.2.2 + dev: true + + /babel-preset-current-node-syntax@1.0.1(@babel/core@7.21.5): + resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.5 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.21.5) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.21.5) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.21.5) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.21.5) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.21.5) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.21.5) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.21.5) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.21.5) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.21.5) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.21.5) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.21.5) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.21.5) + dev: true + + /babel-preset-jest@29.6.3(@babel/core@7.21.5): + resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.5 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.21.5) + dev: true + + /babel-preset-solid@1.7.3(@babel/core@7.21.5): + resolution: {integrity: sha512-HOdyrij99zo+CBrmtDxSexBAl54vCBCfBoyueLBvcfVniaEXNd4ftKqSN6XQcLvFfCY28UFO+DHaigXzWKOfzg==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.21.5 + babel-plugin-jsx-dom-expressions: 0.36.10(@babel/core@7.21.5) + dev: true + + /babel-preset-solid@1.7.3(@babel/core@7.24.4): + resolution: {integrity: sha512-HOdyrij99zo+CBrmtDxSexBAl54vCBCfBoyueLBvcfVniaEXNd4ftKqSN6XQcLvFfCY28UFO+DHaigXzWKOfzg==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.24.4 + babel-plugin-jsx-dom-expressions: 0.36.10(@babel/core@7.24.4) + dev: true + + /bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /browserslist@4.21.5: + resolution: {integrity: sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001481 + electron-to-chromium: 1.4.377 + node-releases: 2.0.10 + update-browserslist-db: 1.0.11(browserslist@4.21.5) + dev: true + + /browserslist@4.23.0: + resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001610 + electron-to-chromium: 1.4.736 + node-releases: 2.0.14 + update-browserslist-db: 1.0.13(browserslist@4.23.0) + dev: true + + /bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + dependencies: + node-int64: 0.4.0 + dev: true + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + + /bundle-require@4.0.3(esbuild@0.19.12): + resolution: {integrity: sha512-2iscZ3fcthP2vka4Y7j277YJevwmsby/FpFDwjgw34Nl7dtCpt7zz/4TexmHMzY6KZEih7En9ImlbbgUNNQGtA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + esbuild: '>=0.17' + dependencies: + esbuild: 0.19.12 + load-tsconfig: 0.2.3 + dev: true + + /cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + dev: true + + /call-bind@1.0.7: + resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + set-function-length: 1.2.2 + dev: true + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + dev: true + + /caniuse-lite@1.0.30001481: + resolution: {integrity: sha512-KCqHwRnaa1InZBtqXzP98LPg0ajCVujMKjqKDhZEthIpAsJl/YEIa3YvXjGXPVqzZVguccuu7ga9KOE1J9rKPQ==} + dev: true + + /caniuse-lite@1.0.30001610: + resolution: {integrity: sha512-QFutAY4NgaelojVMjY63o6XlZyORPaLfyMnsl3HgnWdJUcX6K0oaJymHjH8PT5Gk7sTm8rvC/c5COUQKXqmOMA==} + dev: true + + /ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + dev: true + + /chai@4.4.1: + resolution: {integrity: sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==} + engines: {node: '>=4'} + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.3 + deep-eql: 4.1.3 + get-func-name: 2.0.2 + loupe: 2.3.7 + pathval: 1.1.1 + type-detect: 4.0.8 + dev: true + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + dev: true + + /character-entities@2.0.1: + resolution: {integrity: sha512-OzmutCf2Kmc+6DrFrrPS8/tDh2+DpnrfzdICHWhcVC9eOd0N1PXmQEE1a8iM4IziIAG+8tmTq3K+oo0ubH6RRQ==} + dev: true + + /check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + dependencies: + get-func-name: 2.0.2 + dev: true + + /chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.2 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + dev: true + + /cjs-module-lexer@1.2.3: + resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} + dev: true + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + dev: true + + /collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + dev: true + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: true + + /commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /convert-source-map@1.8.0: + resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} + dependencies: + safe-buffer: 5.1.2 + dev: true + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: true + + /create-jest@29.7.0(@types/node@18.11.18): + resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@18.11.18) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /cssstyle@4.0.1: + resolution: {integrity: sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==} + engines: {node: '>=18'} + dependencies: + rrweb-cssom: 0.6.0 + dev: true + + /csstype@3.1.2: + resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} + + /data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.0.0 + dev: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /decimal.js@10.4.3: + resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + dev: true + + /decode-named-character-reference@1.0.1: + resolution: {integrity: sha512-YV/0HQHreRwKb7uBopyIkLG17jG6Sv2qUchk9qSoVJ2f+flwRsPNBO0hAnjt6mTNYUT+vw9Gy2ihXg4sUWPi2w==} + dependencies: + character-entities: 2.0.1 + dev: true + + /dedent@1.5.3: + resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + dev: true + + /deep-eql@4.1.3: + resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} + engines: {node: '>=6'} + dependencies: + type-detect: 4.0.8 + dev: true + + /deep-equal@2.2.3: + resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.1 + call-bind: 1.0.7 + es-get-iterator: 1.1.3 + get-intrinsic: 1.2.4 + is-arguments: 1.1.1 + is-array-buffer: 3.0.4 + is-date-object: 1.0.5 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.3 + isarray: 2.0.5 + object-is: 1.1.6 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.2 + side-channel: 1.0.6 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.2 + which-typed-array: 1.1.15 + dev: true + + /deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + dev: true + + /define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + dependencies: + es-define-property: 1.0.0 + es-errors: 1.3.0 + gopd: 1.0.1 + dev: true + + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + dev: true + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: true + + /dequal@2.0.2: + resolution: {integrity: sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug==} + engines: {node: '>=6'} + dev: true + + /detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + dev: true + + /diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + + /diff@5.0.0: + resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} + engines: {node: '>=0.3.1'} + dev: true + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + dev: true + + /draco3d@1.5.7: + resolution: {integrity: sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ==} + dev: true + + /electron-to-chromium@1.4.377: + resolution: {integrity: sha512-H3BYG6DW5Z+l0xcfXaicJGxrpA4kMlCxnN71+iNX+dBLkRMOdVJqFJiAmbNZZKA1zISpRg17JR03qGifXNsJtw==} + dev: true + + /electron-to-chromium@1.4.736: + resolution: {integrity: sha512-Rer6wc3ynLelKNM4lOCg7/zPQj8tPOCB2hzD32PX9wd3hgRRi9MxEbmkFCokzcEhRVMiOVLjnL9ig9cefJ+6+Q==} + dev: true + + /emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + dev: true + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + dev: true + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /es-define-property@1.0.0: + resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.4 + dev: true + + /es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + dev: true + + /es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + has-symbols: 1.0.3 + is-arguments: 1.1.1 + is-map: 2.0.3 + is-set: 2.0.3 + is-string: 1.0.7 + isarray: 2.0.5 + stop-iteration-iterator: 1.0.0 + dev: true + + /esbuild-android-64@0.15.18: + resolution: {integrity: sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /esbuild-android-arm64@0.15.18: + resolution: {integrity: sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /esbuild-darwin-64@0.15.18: + resolution: {integrity: sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /esbuild-darwin-arm64@0.15.18: + resolution: {integrity: sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /esbuild-freebsd-64@0.15.18: + resolution: {integrity: sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /esbuild-freebsd-arm64@0.15.18: + resolution: {integrity: sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-32@0.15.18: + resolution: {integrity: sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-64@0.15.18: + resolution: {integrity: sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-arm64@0.15.18: + resolution: {integrity: sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-arm@0.15.18: + resolution: {integrity: sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-mips64le@0.15.18: + resolution: {integrity: sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-ppc64le@0.15.18: + resolution: {integrity: sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-riscv64@0.15.18: + resolution: {integrity: sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-linux-s390x@0.15.18: + resolution: {integrity: sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /esbuild-netbsd-64@0.15.18: + resolution: {integrity: sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /esbuild-openbsd-64@0.15.18: + resolution: {integrity: sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /esbuild-plugin-solid@0.5.0(esbuild@0.16.16)(solid-js@1.8.17): + resolution: {integrity: sha512-ITK6n+0ayGFeDVUZWNMxX+vLsasEN1ILrg4pISsNOQ+mq4ljlJJiuXotInd+HE0MzwTcA9wExT1yzDE2hsqPsg==} + peerDependencies: + esbuild: '>=0.12' + solid-js: '>= 1.0' + dependencies: + '@babel/core': 7.24.4 + '@babel/preset-typescript': 7.21.5(@babel/core@7.24.4) + babel-preset-solid: 1.7.3(@babel/core@7.24.4) + esbuild: 0.16.16 + solid-js: 1.8.17 + transitivePeerDependencies: + - supports-color + dev: true + + /esbuild-register@3.4.2(esbuild@0.16.16): + resolution: {integrity: sha512-kG/XyTDyz6+YDuyfB9ZoSIOOmgyFCH+xPRtsCa8W85HLRV5Csp+o3jWVbOSHgSLfyLc5DmP+KFDNwty4mEjC+Q==} + peerDependencies: + esbuild: '>=0.12 <1' + dependencies: + debug: 4.3.4 + esbuild: 0.16.16 + transitivePeerDependencies: + - supports-color + dev: true + + /esbuild-sunos-64@0.15.18: + resolution: {integrity: sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /esbuild-windows-32@0.15.18: + resolution: {integrity: sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /esbuild-windows-64@0.15.18: + resolution: {integrity: sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /esbuild-windows-arm64@0.15.18: + resolution: {integrity: sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /esbuild@0.15.18: + resolution: {integrity: sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.15.18 + '@esbuild/linux-loong64': 0.15.18 + esbuild-android-64: 0.15.18 + esbuild-android-arm64: 0.15.18 + esbuild-darwin-64: 0.15.18 + esbuild-darwin-arm64: 0.15.18 + esbuild-freebsd-64: 0.15.18 + esbuild-freebsd-arm64: 0.15.18 + esbuild-linux-32: 0.15.18 + esbuild-linux-64: 0.15.18 + esbuild-linux-arm: 0.15.18 + esbuild-linux-arm64: 0.15.18 + esbuild-linux-mips64le: 0.15.18 + esbuild-linux-ppc64le: 0.15.18 + esbuild-linux-riscv64: 0.15.18 + esbuild-linux-s390x: 0.15.18 + esbuild-netbsd-64: 0.15.18 + esbuild-openbsd-64: 0.15.18 + esbuild-sunos-64: 0.15.18 + esbuild-windows-32: 0.15.18 + esbuild-windows-64: 0.15.18 + esbuild-windows-arm64: 0.15.18 + dev: true + + /esbuild@0.16.16: + resolution: {integrity: sha512-24JyKq10KXM5EBIgPotYIJ2fInNWVVqflv3gicIyQqfmUqi4HvDW1VR790cBgLJHCl96Syy7lhoz7tLFcmuRmg==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.16.16 + '@esbuild/android-arm64': 0.16.16 + '@esbuild/android-x64': 0.16.16 + '@esbuild/darwin-arm64': 0.16.16 + '@esbuild/darwin-x64': 0.16.16 + '@esbuild/freebsd-arm64': 0.16.16 + '@esbuild/freebsd-x64': 0.16.16 + '@esbuild/linux-arm': 0.16.16 + '@esbuild/linux-arm64': 0.16.16 + '@esbuild/linux-ia32': 0.16.16 + '@esbuild/linux-loong64': 0.16.16 + '@esbuild/linux-mips64el': 0.16.16 + '@esbuild/linux-ppc64': 0.16.16 + '@esbuild/linux-riscv64': 0.16.16 + '@esbuild/linux-s390x': 0.16.16 + '@esbuild/linux-x64': 0.16.16 + '@esbuild/netbsd-x64': 0.16.16 + '@esbuild/openbsd-x64': 0.16.16 + '@esbuild/sunos-x64': 0.16.16 + '@esbuild/win32-arm64': 0.16.16 + '@esbuild/win32-ia32': 0.16.16 + '@esbuild/win32-x64': 0.16.16 + dev: true + + /esbuild@0.19.12: + resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.19.12 + '@esbuild/android-arm': 0.19.12 + '@esbuild/android-arm64': 0.19.12 + '@esbuild/android-x64': 0.19.12 + '@esbuild/darwin-arm64': 0.19.12 + '@esbuild/darwin-x64': 0.19.12 + '@esbuild/freebsd-arm64': 0.19.12 + '@esbuild/freebsd-x64': 0.19.12 + '@esbuild/linux-arm': 0.19.12 + '@esbuild/linux-arm64': 0.19.12 + '@esbuild/linux-ia32': 0.19.12 + '@esbuild/linux-loong64': 0.19.12 + '@esbuild/linux-mips64el': 0.19.12 + '@esbuild/linux-ppc64': 0.19.12 + '@esbuild/linux-riscv64': 0.19.12 + '@esbuild/linux-s390x': 0.19.12 + '@esbuild/linux-x64': 0.19.12 + '@esbuild/netbsd-x64': 0.19.12 + '@esbuild/openbsd-x64': 0.19.12 + '@esbuild/sunos-x64': 0.19.12 + '@esbuild/win32-arm64': 0.19.12 + '@esbuild/win32-ia32': 0.19.12 + '@esbuild/win32-x64': 0.19.12 + dev: true + + /esbuild@0.20.2: + resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/aix-ppc64': 0.20.2 + '@esbuild/android-arm': 0.20.2 + '@esbuild/android-arm64': 0.20.2 + '@esbuild/android-x64': 0.20.2 + '@esbuild/darwin-arm64': 0.20.2 + '@esbuild/darwin-x64': 0.20.2 + '@esbuild/freebsd-arm64': 0.20.2 + '@esbuild/freebsd-x64': 0.20.2 + '@esbuild/linux-arm': 0.20.2 + '@esbuild/linux-arm64': 0.20.2 + '@esbuild/linux-ia32': 0.20.2 + '@esbuild/linux-loong64': 0.20.2 + '@esbuild/linux-mips64el': 0.20.2 + '@esbuild/linux-ppc64': 0.20.2 + '@esbuild/linux-riscv64': 0.20.2 + '@esbuild/linux-s390x': 0.20.2 + '@esbuild/linux-x64': 0.20.2 + '@esbuild/netbsd-x64': 0.20.2 + '@esbuild/openbsd-x64': 0.20.2 + '@esbuild/sunos-x64': 0.20.2 + '@esbuild/win32-arm64': 0.20.2 + '@esbuild/win32-ia32': 0.20.2 + '@esbuild/win32-x64': 0.20.2 + dev: true + + /escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: true + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + dev: true + + /escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + dev: true + + /esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: true + + /estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + dependencies: + '@types/estree': 1.0.1 + dev: true + + /execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.3.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + dev: true + + /exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + dev: true + + /expect@29.7.0: + resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/expect-utils': 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + dev: true + + /extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + dev: true + + /fast-glob@3.2.11: + resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fastq@1.13.0: + resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} + dependencies: + reusify: 1.0.4 + dev: true + + /fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + dependencies: + bser: 2.1.1 + dev: true + + /fflate@0.6.10: + resolution: {integrity: sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==} + dev: true + + /fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: true + + /fs-extra@11.1.1: + resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.0 + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + dev: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + + /get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + dev: true + + /get-intrinsic@1.2.4: + resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + has-proto: 1.0.3 + has-symbols: 1.0.3 + hasown: 2.0.2 + dev: true + + /get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + dev: true + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + + /get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob@7.1.6: + resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.2.11 + ignore: 5.2.0 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.4 + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + dependencies: + es-define-property: 1.0.0 + dev: true + + /has-proto@1.0.3: + resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==} + engines: {node: '>= 0.4'} + dev: true + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: true + + /has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} dependencies: + has-symbols: 1.0.3 + dev: true + + /has@1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + dependencies: + function-bind: 1.1.1 + dev: true + + /hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: true + + /html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + dependencies: + whatwg-encoding: 3.1.1 + dev: true + + /html-entities@2.3.3: + resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} + dev: true + + /html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: true + + /http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.1 debug: 4.3.4 - esbuild: 0.16.16 transitivePeerDependencies: - supports-color dev: true - /esbuild-sunos-64@0.15.18: - resolution: {integrity: sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - requiresBuild: true + /https-proxy-agent@7.0.4: + resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.1 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color dev: true - optional: true - /esbuild-windows-32@0.15.18: - resolution: {integrity: sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - requiresBuild: true + /human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} dev: true - optional: true - /esbuild-windows-64@0.15.18: - resolution: {integrity: sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - requiresBuild: true + /human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} dev: true - optional: true - /esbuild-windows-arm64@0.15.18: - resolution: {integrity: sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - requiresBuild: true + /iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 dev: true - optional: true - /esbuild@0.15.18: - resolution: {integrity: sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==} - engines: {node: '>=12'} + /ignore@5.2.0: + resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} + engines: {node: '>= 4'} + dev: true + + /import-local@3.1.0: + resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + engines: {node: '>=8'} hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.15.18 - '@esbuild/linux-loong64': 0.15.18 - esbuild-android-64: 0.15.18 - esbuild-android-arm64: 0.15.18 - esbuild-darwin-64: 0.15.18 - esbuild-darwin-arm64: 0.15.18 - esbuild-freebsd-64: 0.15.18 - esbuild-freebsd-arm64: 0.15.18 - esbuild-linux-32: 0.15.18 - esbuild-linux-64: 0.15.18 - esbuild-linux-arm: 0.15.18 - esbuild-linux-arm64: 0.15.18 - esbuild-linux-mips64le: 0.15.18 - esbuild-linux-ppc64le: 0.15.18 - esbuild-linux-riscv64: 0.15.18 - esbuild-linux-s390x: 0.15.18 - esbuild-netbsd-64: 0.15.18 - esbuild-openbsd-64: 0.15.18 - esbuild-sunos-64: 0.15.18 - esbuild-windows-32: 0.15.18 - esbuild-windows-64: 0.15.18 - esbuild-windows-arm64: 0.15.18 + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 dev: true - /esbuild@0.16.16: - resolution: {integrity: sha512-24JyKq10KXM5EBIgPotYIJ2fInNWVVqflv3gicIyQqfmUqi4HvDW1VR790cBgLJHCl96Syy7lhoz7tLFcmuRmg==} + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /internal-slot@1.0.7: + resolution: {integrity: sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==} + engines: {node: '>= 0.4'} + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.0.6 + dev: true + + /is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: true + + /is-array-buffer@3.0.4: + resolution: {integrity: sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + get-intrinsic: 1.2.4 + dev: true + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: true + + /is-buffer@2.0.5: + resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} + engines: {node: '>=4'} + dev: true + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module@2.12.0: + resolution: {integrity: sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==} + dependencies: + has: 1.0.3 + dev: true + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-plain-obj@4.0.0: + resolution: {integrity: sha512-NXRbBtUdBioI73y/HmOhogw/U5msYPC9DAtGkJXeFcFWSFZw0mCUsPxk/snTuJHzNKA8kLBK4rH97RMB1BfCXw==} engines: {node: '>=12'} - hasBin: true - requiresBuild: true - optionalDependencies: - '@esbuild/android-arm': 0.16.16 - '@esbuild/android-arm64': 0.16.16 - '@esbuild/android-x64': 0.16.16 - '@esbuild/darwin-arm64': 0.16.16 - '@esbuild/darwin-x64': 0.16.16 - '@esbuild/freebsd-arm64': 0.16.16 - '@esbuild/freebsd-x64': 0.16.16 - '@esbuild/linux-arm': 0.16.16 - '@esbuild/linux-arm64': 0.16.16 - '@esbuild/linux-ia32': 0.16.16 - '@esbuild/linux-loong64': 0.16.16 - '@esbuild/linux-mips64el': 0.16.16 - '@esbuild/linux-ppc64': 0.16.16 - '@esbuild/linux-riscv64': 0.16.16 - '@esbuild/linux-s390x': 0.16.16 - '@esbuild/linux-x64': 0.16.16 - '@esbuild/netbsd-x64': 0.16.16 - '@esbuild/openbsd-x64': 0.16.16 - '@esbuild/sunos-x64': 0.16.16 - '@esbuild/win32-arm64': 0.16.16 - '@esbuild/win32-ia32': 0.16.16 - '@esbuild/win32-x64': 0.16.16 dev: true - /escalade@3.1.1: - resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} - engines: {node: '>=6'} + /is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + dev: true + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + has-tostringtag: 1.0.2 + dev: true + + /is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + dev: true + + /is-shared-array-buffer@1.0.3: + resolution: {integrity: sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + dev: true + + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} dev: true - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: true - /escape-string-regexp@5.0.0: - resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} - engines: {node: '>=12'} + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.2 dev: true - /estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 dev: true - /execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} + /is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + dev: true + + /is-weakset@2.0.3: + resolution: {integrity: sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==} + engines: {node: '>= 0.4'} dependencies: - cross-spawn: 7.0.3 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 + call-bind: 1.0.7 + get-intrinsic: 1.2.4 dev: true - /extend@3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + /is-what@4.1.8: + resolution: {integrity: sha512-yq8gMao5upkPoGEU9LsB2P+K3Kt8Q3fQFCGyNCWOAnJAMzEXVV9drYb0TXr42TTliLLhKIBvulgAXgtLLnwzGA==} + engines: {node: '>=12.13'} dev: true - /fast-glob@3.2.11: - resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==} - engines: {node: '>=8.6.0'} + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 + '@babel/core': 7.21.5 + '@babel/parser': 7.21.5 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.0 + transitivePeerDependencies: + - supports-color dev: true - /fastq@1.13.0: - resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} + /istanbul-lib-instrument@6.0.2: + resolution: {integrity: sha512-1WUsZ9R1lA0HtBSohTkm39WTPlNKSJ5iFk7UwqXkBLoHQT+hfqPsfsTDVuZdKGaBwn7din9bS7SsnoAr943hvw==} + engines: {node: '>=10'} dependencies: - reusify: 1.0.4 + '@babel/core': 7.24.4 + '@babel/parser': 7.24.4 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color dev: true - /fill-range@7.0.1: - resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} - engines: {node: '>=8'} + /istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} dependencies: - to-regex-range: 5.0.1 + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 dev: true - /fs-extra@11.1.1: - resolution: {integrity: sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==} - engines: {node: '>=14.14'} + /istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.0 + debug: 4.3.4 + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color dev: true - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + /istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 dev: true - /fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true + /jest-changed-files@29.7.0: + resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + execa: 5.1.1 + jest-util: 29.7.0 + p-limit: 3.1.0 dev: true - optional: true - /function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + /jest-circus@29.7.0: + resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 18.11.18 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.5.3 + is-generator-fn: 2.1.0 + jest-each: 29.7.0 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + p-limit: 3.1.0 + pretty-format: 29.7.0 + pure-rand: 6.1.0 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color dev: true - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} + /jest-cli@29.7.0(@types/node@18.11.18): + resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@18.11.18) + exit: 0.1.2 + import-local: 3.1.0 + jest-config: 29.7.0(@types/node@18.11.18) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node dev: true - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} + /jest-config@29.7.0(@types/node@18.11.18): + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.21.5 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 18.11.18 + babel-jest: 29.7.0(@babel/core@7.21.5) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.1.6 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color dev: true - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + /jest-diff@29.7.0: + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - is-glob: 4.0.3 + chalk: 4.1.2 + diff-sequences: 29.6.3 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 dev: true - /glob@7.1.6: - resolution: {integrity: sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==} + /jest-docblock@29.7.0: + resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 + detect-newline: 3.1.0 dev: true - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} + /jest-each@29.7.0: + resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + jest-get-type: 29.6.3 + jest-util: 29.7.0 + pretty-format: 29.7.0 dev: true - /globby@11.1.0: - resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} - engines: {node: '>=10'} + /jest-environment-node@29.7.0: + resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.2.11 - ignore: 5.2.0 - merge2: 1.4.1 - slash: 3.0.0 + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 18.11.18 + jest-mock: 29.7.0 + jest-util: 29.7.0 dev: true - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + /jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dev: true - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} + /jest-haste-map@29.7.0: + resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.9 + '@types/node': 18.11.18 + anymatch: 3.1.2 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.5 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 dev: true - /has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} + /jest-leak-detector@29.7.0: + resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - function-bind: 1.1.1 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 dev: true - /html-entities@2.3.3: - resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} + /jest-matcher-utils@29.7.0: + resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 dev: true - /human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} + /jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/code-frame': 7.21.4 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.5 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 dev: true - /ignore@5.2.0: - resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} - engines: {node: '>= 4'} + /jest-mock@29.7.0: + resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/node': 18.11.18 + jest-util: 29.7.0 dev: true - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + /jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true dependencies: - once: 1.4.0 - wrappy: 1.0.2 + jest-resolve: 29.7.0 dev: true - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + /jest-regex-util@29.6.3: + resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dev: true - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} + /jest-resolve-dependencies@29.7.0: + resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - binary-extensions: 2.2.0 + jest-regex-util: 29.6.3 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color dev: true - /is-buffer@2.0.5: - resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} - engines: {node: '>=4'} + /jest-resolve@29.7.0: + resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) + jest-util: 29.7.0 + jest-validate: 29.7.0 + resolve: 1.22.2 + resolve.exports: 2.0.2 + slash: 3.0.0 dev: true - /is-core-module@2.12.0: - resolution: {integrity: sha512-RECHCBCd/viahWmwj6enj19sKbHfJrddi/6cBDsNTKbNq0f7VeaUkBo60BqzvPqo/W54ChS62Z5qyun7cfOMqQ==} + /jest-runner@29.7.0: + resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - has: 1.0.3 + '@jest/console': 29.7.0 + '@jest/environment': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 18.11.18 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.11 + jest-docblock: 29.7.0 + jest-environment-node: 29.7.0 + jest-haste-map: 29.7.0 + jest-leak-detector: 29.7.0 + jest-message-util: 29.7.0 + jest-resolve: 29.7.0 + jest-runtime: 29.7.0 + jest-util: 29.7.0 + jest-watcher: 29.7.0 + jest-worker: 29.7.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color dev: true - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} + /jest-runtime@29.7.0: + resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/globals': 29.7.0 + '@jest/source-map': 29.6.3 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 18.11.18 + chalk: 4.1.2 + cjs-module-lexer: 1.2.3 + collect-v8-coverage: 1.0.2 + glob: 7.1.6 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color dev: true - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} + /jest-snapshot@29.7.0: + resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - is-extglob: 2.1.1 + '@babel/core': 7.21.5 + '@babel/generator': 7.21.5 + '@babel/plugin-syntax-jsx': 7.21.4(@babel/core@7.21.5) + '@babel/plugin-syntax-typescript': 7.21.4(@babel/core@7.21.5) + '@babel/types': 7.21.5 + '@jest/expect-utils': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.21.5) + chalk: 4.1.2 + expect: 29.7.0 + graceful-fs: 4.2.11 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + natural-compare: 1.4.0 + pretty-format: 29.7.0 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color dev: true - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} + /jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/node': 18.11.18 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 dev: true - /is-plain-obj@4.0.0: - resolution: {integrity: sha512-NXRbBtUdBioI73y/HmOhogw/U5msYPC9DAtGkJXeFcFWSFZw0mCUsPxk/snTuJHzNKA8kLBK4rH97RMB1BfCXw==} - engines: {node: '>=12'} + /jest-validate@29.7.0: + resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 dev: true - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} + /jest-watcher@29.7.0: + resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 18.11.18 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.7.0 + string-length: 4.0.2 dev: true - /is-what@4.1.8: - resolution: {integrity: sha512-yq8gMao5upkPoGEU9LsB2P+K3Kt8Q3fQFCGyNCWOAnJAMzEXVV9drYb0TXr42TTliLLhKIBvulgAXgtLLnwzGA==} - engines: {node: '>=12.13'} + /jest-worker@29.7.0: + resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@types/node': 18.11.18 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 dev: true - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + /jest@29.7.0(@types/node@18.11.18): + resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.7.0 + '@jest/types': 29.6.3 + import-local: 3.1.0 + jest-cli: 29.7.0(@types/node@18.11.18) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node dev: true /joycon@3.1.1: @@ -1451,18 +4282,74 @@ packages: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} dev: true + /js-tokens@9.0.0: + resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} + dev: true + + /js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + + /jsdom@24.0.0: + resolution: {integrity: sha512-UDS2NayCvmXSXVP6mpTj+73JnNQadZlr9N68189xib2tx5Mls7swlTNao26IoHv46BZJFvXygyRtyXd1feAk1A==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^2.11.2 + peerDependenciesMeta: + canvas: + optional: true + dependencies: + cssstyle: 4.0.1 + data-urls: 5.0.0 + decimal.js: 10.4.3 + form-data: 4.0.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.4 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.7 + parse5: 7.1.2 + rrweb-cssom: 0.6.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.3 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.0.0 + ws: 8.16.0 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + /jsesc@2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} hasBin: true dev: true + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + /json5@2.2.3: resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} engines: {node: '>=6'} hasBin: true dev: true + /jsonc-parser@3.2.1: + resolution: {integrity: sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==} + dev: true + /jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} dependencies: @@ -1471,6 +4358,11 @@ packages: graceful-fs: 4.2.11 dev: true + /kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + dev: true + /kleur@4.1.4: resolution: {integrity: sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==} engines: {node: '>=6'} @@ -1480,9 +4372,14 @@ packages: resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} dev: true - /lilconfig@2.0.5: - resolution: {integrity: sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==} - engines: {node: '>=10'} + /leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + dev: true + + /lilconfig@3.1.1: + resolution: {integrity: sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==} + engines: {node: '>=14'} dev: true /lines-and-columns@1.2.4: @@ -1494,6 +4391,21 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: true + /local-pkg@0.5.0: + resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} + engines: {node: '>=14'} + dependencies: + mlly: 1.6.1 + pkg-types: 1.0.3 + dev: true + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + /lodash.sortby@4.7.0: resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} dev: true @@ -1502,12 +4414,30 @@ packages: resolution: {integrity: sha512-cHlYSUpL2s7Fb3394mYxwTYj8niTaNHUCLr0qdiCXQfSjfuA7CKofpX2uSwEfFDQ0EB7JcnMnm+GjbqqoinYYg==} dev: true + /loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + dependencies: + get-func-name: 2.0.2 + dev: true + /lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} dependencies: yallist: 3.1.1 dev: true + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + dev: true + /magic-string@0.27.0: resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} engines: {node: '>=12'} @@ -1515,6 +4445,26 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true + /magic-string@0.30.9: + resolution: {integrity: sha512-S1+hd+dIrC8EZqKyT9DstTH/0Z+f76kmmvZnkfQVmOpDEF9iVgdYif3Q/pIWHmCoo59bQVGW0kVL3e2nl+9+Sw==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + dependencies: + semver: 7.6.0 + dev: true + + /makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + dependencies: + tmpl: 1.0.5 + dev: true + /markdown-table@3.0.2: resolution: {integrity: sha512-y8j3a5/DkJCmS5x4dMCQL+OR0+2EAq3DOtio1COSHsmW2BGXnNCK3v12hJt1LrUz5iZH5g0LmuYOjDdI+czghA==} dev: true @@ -1633,6 +4583,10 @@ packages: engines: {node: '>= 8'} dev: true + /meshoptimizer@0.18.1: + resolution: {integrity: sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==} + dev: true + /micromark-core-commonmark@1.0.6: resolution: {integrity: sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA==} dependencies: @@ -1890,17 +4844,43 @@ packages: picomatch: 2.3.1 dev: true + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: true + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: true + /mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} dev: true + /mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: true + /minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: brace-expansion: 1.1.11 dev: true + /mlly@1.6.1: + resolution: {integrity: sha512-vLgaHvaeunuOXHSmEbZ9izxPx3USsk8KCQ8iC+aTlp5sKRSoZvwhHh5L9VbKSaVC6sJDqbyohIS76E2VmHIPAA==} + dependencies: + acorn: 8.11.3 + pathe: 1.1.2 + pkg-types: 1.0.3 + ufo: 1.5.3 + dev: true + /mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -1929,10 +4909,28 @@ packages: hasBin: true dev: true + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + dev: true + /node-releases@2.0.10: resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==} dev: true + /node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + dev: true + /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -1945,11 +4943,49 @@ packages: path-key: 3.1.1 dev: true + /npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + path-key: 4.0.0 + dev: true + + /nwsapi@2.2.7: + resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} + dev: true + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} dev: true + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + dev: true + + /object-is@1.1.6: + resolution: {integrity: sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + dev: true + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: @@ -1963,6 +4999,67 @@ packages: mimic-fn: 2.1.0 dev: true + /onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + dev: true + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-limit@5.0.0: + resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} + engines: {node: '>=18'} + dependencies: + yocto-queue: 1.0.0 + dev: true + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.21.4 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + dependencies: + entities: 4.5.0 + dev: true + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} @@ -1973,6 +5070,11 @@ packages: engines: {node: '>=8'} dev: true + /path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + dev: true + /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} dev: true @@ -1982,6 +5084,14 @@ packages: engines: {node: '>=8'} dev: true + /pathe@1.1.2: + resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} + dev: true + + /pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + dev: true + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: true @@ -1996,9 +5106,29 @@ packages: engines: {node: '>= 6'} dev: true - /postcss-load-config@3.1.4: - resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} - engines: {node: '>= 10'} + /pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + dev: true + + /pkg-types@1.0.3: + resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} + dependencies: + jsonc-parser: 3.2.1 + mlly: 1.6.1 + pathe: 1.1.2 + dev: true + + /possible-typed-array-names@1.0.0: + resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} + engines: {node: '>= 0.4'} + dev: true + + /postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} peerDependencies: postcss: '>=8.0.9' ts-node: '>=9.0.0' @@ -2008,8 +5138,8 @@ packages: ts-node: optional: true dependencies: - lilconfig: 2.0.5 - yaml: 1.10.2 + lilconfig: 3.1.1 + yaml: 2.4.2 dev: true /postcss@8.4.23: @@ -2021,15 +5151,79 @@ packages: source-map-js: 1.0.2 dev: true + /postcss@8.4.38: + resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.2.0 + dev: true + + /potpack@1.0.2: + resolution: {integrity: sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==} + dev: true + + /pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + dev: true + + /pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.2.0 + dev: true + + /prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + dev: true + + /psl@1.9.0: + resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + dev: true + /punycode@2.3.0: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} dev: true + /punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + dev: true + + /pure-rand@6.1.0: + resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} + dev: true + + /querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + dev: true + /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} dev: true + /react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + dev: true + + /react-is@18.2.0: + resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + dev: true + /readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -2037,6 +5231,20 @@ packages: picomatch: 2.3.1 dev: true + /regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + dev: true + + /regexp.prototype.flags@1.5.2: + resolution: {integrity: sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + define-properties: 1.2.1 + es-errors: 1.3.0 + set-function-name: 2.0.2 + dev: true + /remark-gfm@3.0.1: resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==} dependencies: @@ -2048,11 +5256,32 @@ packages: - supports-color dev: true + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + dev: true + + /resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + dependencies: + resolve-from: 5.0.0 + dev: true + /resolve-from@5.0.0: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} dev: true + /resolve.exports@2.0.2: + resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} + engines: {node: '>=10'} + dev: true + /resolve@1.22.2: resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} hasBin: true @@ -2078,7 +5307,7 @@ packages: rollup: 3.9.1 typescript: 4.9.4 optionalDependencies: - '@babel/code-frame': 7.21.4 + '@babel/code-frame': 7.24.2 dev: true /rollup@3.21.2: @@ -2086,7 +5315,7 @@ packages: engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true optionalDependencies: - fsevents: 2.3.2 + fsevents: 2.3.3 dev: true /rollup@3.9.1: @@ -2094,7 +5323,37 @@ packages: engines: {node: '>=14.18.0', npm: '>=8.0.0'} hasBin: true optionalDependencies: - fsevents: 2.3.2 + fsevents: 2.3.3 + dev: true + + /rollup@4.14.3: + resolution: {integrity: sha512-ag5tTQKYsj1bhrFC9+OEWqb5O6VYgtQDO9hPDBMmIbePwhfSr+ExlcU741t8Dhw5DkPCQf6noz0jb36D6W9/hw==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + dependencies: + '@types/estree': 1.0.5 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.14.3 + '@rollup/rollup-android-arm64': 4.14.3 + '@rollup/rollup-darwin-arm64': 4.14.3 + '@rollup/rollup-darwin-x64': 4.14.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.14.3 + '@rollup/rollup-linux-arm-musleabihf': 4.14.3 + '@rollup/rollup-linux-arm64-gnu': 4.14.3 + '@rollup/rollup-linux-arm64-musl': 4.14.3 + '@rollup/rollup-linux-powerpc64le-gnu': 4.14.3 + '@rollup/rollup-linux-riscv64-gnu': 4.14.3 + '@rollup/rollup-linux-s390x-gnu': 4.14.3 + '@rollup/rollup-linux-x64-gnu': 4.14.3 + '@rollup/rollup-linux-x64-musl': 4.14.3 + '@rollup/rollup-win32-arm64-msvc': 4.14.3 + '@rollup/rollup-win32-ia32-msvc': 4.14.3 + '@rollup/rollup-win32-x64-msvc': 4.14.3 + fsevents: 2.3.3 + dev: true + + /rrweb-cssom@0.6.0: + resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} dev: true /run-parallel@1.2.0: @@ -2114,14 +5373,67 @@ packages: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} dev: true + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: true + + /saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + dependencies: + xmlchars: 2.2.0 + dev: true + /semver@6.3.0: resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} hasBin: true dev: true - /seroval@0.5.1: - resolution: {integrity: sha512-ZfhQVB59hmIauJG5Ydynupy8KHyr5imGNtdDhbZG68Ufh1Ynkv9KOYOAABf71oVbQxJ8VkWnMHAjEHE7fWkH5g==} + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: true + + /semver@7.6.0: + resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /seroval-plugins@1.0.5(seroval@1.0.5): + resolution: {integrity: sha512-8+pDC1vOedPXjKG7oz8o+iiHrtF2WswaMQJ7CKFpccvSYfrzmvKY9zOJWCg+881722wIHfwkdnRmiiDm9ym+zQ==} + engines: {node: '>=10'} + peerDependencies: + seroval: ^1.0 + dependencies: + seroval: 1.0.5 + + /seroval@1.0.5: + resolution: {integrity: sha512-TM+Z11tHHvQVQKeNlOUonOWnsNM+2IBwZ4vwoi4j3zKzIpc5IDw8WPwCfcc8F17wy6cBcJGbZbFOR0UCuTZHQA==} engines: {node: '>=10'} + + /set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.2.4 + gopd: 1.0.1 + has-property-descriptors: 1.0.2 + dev: true + + /set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 dev: true /shebang-command@2.0.0: @@ -2131,15 +5443,34 @@ packages: shebang-regex: 3.0.0 dev: true - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /side-channel@1.0.6: + resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.7 + es-errors: 1.3.0 + get-intrinsic: 1.2.4 + object-inspect: 1.13.1 + dev: true + + /siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} dev: true /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} dev: true + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: true + /sirv@2.0.2: resolution: {integrity: sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w==} engines: {node: '>= 10'} @@ -2149,27 +5480,31 @@ packages: totalist: 3.0.0 dev: true + /sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: true + /slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} dev: true - /solid-app-router@0.1.14(solid-js@1.7.0): + /solid-app-router@0.1.14(solid-js@1.8.17): resolution: {integrity: sha512-fnX+jCB5sDMbjq3od9qGtQNdlvHP2c6DG5STvMHVXyNuSEN+MdO7WJtZ58OpVpq6zWS4FYeYAh7NMEa7C2CcOA==} peerDependencies: solid-js: ^1.0.0 dependencies: - solid-js: 1.7.0 + solid-js: 1.8.17 dev: true - /solid-js@1.7.0: - resolution: {integrity: sha512-tLG68KWlVRgzYeAW003G3E70emZqTcqCKJR9QoGr0rcuiLIuKrlUoezT8jLME1YSl3Wfu35jzgeY10iLEY4YQQ==} + /solid-js@1.8.17: + resolution: {integrity: sha512-E0FkUgv9sG/gEBWkHr/2XkBluHb1fkrHywUgA6o6XolPDCJ4g1HaLmQufcBBhiF36ee40q+HpG/vCZu7fLpI3Q==} dependencies: csstype: 3.1.2 - seroval: 0.5.1 - dev: true + seroval: 1.0.5 + seroval-plugins: 1.0.5(seroval@1.0.5) - /solid-refresh@0.4.3(solid-js@1.7.0): + /solid-refresh@0.4.3(solid-js@1.8.17): resolution: {integrity: sha512-7+4/gYsVi0BlM4PzT1PU1TB5nW3Hv8FWuB+Kw/ofWui7KQkWBf+dVZOrReQYHEmLCzytHUa2JysUXgzVALJmSw==} peerDependencies: solid-js: ^1.3 @@ -2177,7 +5512,7 @@ packages: '@babel/generator': 7.21.5 '@babel/helper-module-imports': 7.16.7 '@babel/types': 7.21.5 - solid-js: 1.7.0 + solid-js: 1.8.17 dev: true /source-map-js@1.0.2: @@ -2185,6 +5520,23 @@ packages: engines: {node: '>=0.10.0'} dev: true + /source-map-js@1.2.0: + resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + /source-map@0.8.0-beta.0: resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} engines: {node: '>= 8'} @@ -2192,11 +5544,82 @@ packages: whatwg-url: 7.1.0 dev: true + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true + + /stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + dependencies: + escape-string-regexp: 2.0.0 + dev: true + + /stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + dev: true + + /std-env@3.7.0: + resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + dev: true + + /stop-iteration-iterator@1.0.0: + resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} + engines: {node: '>= 0.4'} + dependencies: + internal-slot: 1.0.7 + dev: true + + /string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + dev: true + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + dev: true + /strip-final-newline@2.0.0: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} dev: true + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /strip-literal@2.1.0: + resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==} + dependencies: + js-tokens: 9.0.0 + dev: true + /sucrase@3.21.0: resolution: {integrity: sha512-FjAhMJjDcifARI7bZej0Bi1yekjWQHoEvWIXhLPwDhC6O4iZ5PtGb86WV56riW87hzpgB13wwBKO9vKAiWu5VQ==} engines: {node: '>=8'} @@ -2217,11 +5640,38 @@ packages: has-flag: 3.0.0 dev: true + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: true + /supports-preserve-symlinks-flag@1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} dev: true + /symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + dev: true + + /test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.1.6 + minimatch: 3.1.2 + dev: true + /thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -2235,8 +5685,40 @@ packages: any-promise: 1.3.0 dev: true - /three@0.149.0: - resolution: {integrity: sha512-tohpUxPDht0qExRLDTM8sjRLc5d9STURNrdnK3w9A+V4pxaTBfKWWT/IqtiLfg23Vfc3Z+ImNfvRw1/0CtxrkQ==} + /three-stdlib@2.29.6(three@0.164.1): + resolution: {integrity: sha512-nj9bHkzhhwfmqQcM/keC2RDb0bHhbw6bRXTy81ehzi8F1rtp6pJ5eS0/vl1Eg5RMFqXOMyxJ6sDHPoLU+IrVZg==} + peerDependencies: + three: '>=0.128.0' + dependencies: + '@types/draco3d': 1.4.9 + '@types/offscreencanvas': 2019.7.3 + '@types/webxr': 0.5.15 + draco3d: 1.5.7 + fflate: 0.6.10 + potpack: 1.0.2 + three: 0.164.1 + dev: true + + /three@0.164.1: + resolution: {integrity: sha512-iC/hUBbl1vzFny7f5GtqzVXYjMJKaTPxiCxXfrvVdBi1Sf+jhd1CAkitiFwC7mIBFCo3MrDLJG97yisoaWig0w==} + dev: true + + /tinybench@2.7.0: + resolution: {integrity: sha512-Qgayeb106x2o4hNzNjsZEfFziw8IbKqtbXBjVh7VIZfBxfD5M4gWtpyx5+YTae2gJ6Y6Dz/KLepiv16RFeQWNA==} + dev: true + + /tinypool@0.8.4: + resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} + engines: {node: '>=14.0.0'} + dev: true + + /tinyspy@2.2.1: + resolution: {integrity: sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==} + engines: {node: '>=14.0.0'} + dev: true + + /tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} dev: true /to-fast-properties@2.0.0: @@ -2256,10 +5738,27 @@ packages: engines: {node: '>=6'} dev: true + /tough-cookie@4.1.3: + resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} + engines: {node: '>=6'} + dependencies: + psl: 1.9.0 + punycode: 2.3.0 + universalify: 0.2.0 + url-parse: 1.5.10 + dev: true + /tr46@1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} dependencies: - punycode: 2.3.0 + punycode: 2.3.1 + dev: true + + /tr46@5.0.0: + resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==} + engines: {node: '>=18'} + dependencies: + punycode: 2.3.1 dev: true /tree-kill@1.2.2: @@ -2283,15 +5782,31 @@ packages: esbuild: 0.15.18 dev: true - /tsup@6.5.0(typescript@4.9.4): - resolution: {integrity: sha512-36u82r7rYqRHFkD15R20Cd4ercPkbYmuvRkz3Q1LCm5BsiFNUgpo36zbjVhCOgvjyxNBWNKHsaD5Rl8SykfzNA==} - engines: {node: '>=14'} + /tsup-preset-solid@2.2.0(esbuild@0.16.16)(solid-js@1.8.17)(tsup@8.0.2): + resolution: {integrity: sha512-sPAzeArmYkVAZNRN+m4tkiojdd0GzW/lCwd4+TQDKMENe8wr2uAuro1s0Z59ASmdBbkXoxLgCiNcuQMyiidMZg==} + peerDependencies: + tsup: ^8.0.0 + dependencies: + esbuild-plugin-solid: 0.5.0(esbuild@0.16.16)(solid-js@1.8.17) + tsup: 8.0.2(typescript@4.9.4) + transitivePeerDependencies: + - esbuild + - solid-js + - supports-color + dev: true + + /tsup@8.0.2(typescript@4.9.4): + resolution: {integrity: sha512-NY8xtQXdH7hDUAZwcQdY/Vzlw9johQsaqf7iwZ6g1DOUlFYQ5/AtVAjTvihhEyeRlGo4dLRVHtrRaL35M1daqQ==} + engines: {node: '>=18'} hasBin: true peerDependencies: + '@microsoft/api-extractor': ^7.36.0 '@swc/core': ^1 postcss: ^8.4.12 - typescript: ^4.1.0 + typescript: '>=4.5.0' peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true '@swc/core': optional: true postcss: @@ -2299,17 +5814,17 @@ packages: typescript: optional: true dependencies: - bundle-require: 3.1.2(esbuild@0.15.18) - cac: 6.7.12 + bundle-require: 4.0.3(esbuild@0.19.12) + cac: 6.7.14 chokidar: 3.5.3 debug: 4.3.4 - esbuild: 0.15.18 + esbuild: 0.19.12 execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 - postcss-load-config: 3.1.4 + postcss-load-config: 4.0.2 resolve-from: 5.0.0 - rollup: 3.9.1 + rollup: 4.14.3 source-map: 0.8.0-beta.0 sucrase: 3.21.0 tree-kill: 1.2.2 @@ -2319,6 +5834,16 @@ packages: - ts-node dev: true + /type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + + /type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: true + /typescript@4.9.4: resolution: {integrity: sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==} engines: {node: '>=4.2.0'} @@ -2329,6 +5854,10 @@ packages: resolution: {integrity: sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg==} dev: true + /ufo@1.5.3: + resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} + dev: true + /unified@10.1.2: resolution: {integrity: sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==} dependencies: @@ -2373,6 +5902,11 @@ packages: unist-util-visit-parents: 5.1.0 dev: true + /universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + dev: true + /universalify@2.0.0: resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} engines: {node: '>= 10.0.0'} @@ -2389,6 +5923,24 @@ packages: picocolors: 1.0.0 dev: true + /update-browserslist-db@1.0.13(browserslist@4.23.0): + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.23.0 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: true + + /url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + dev: true + /uvu@0.5.3: resolution: {integrity: sha512-brFwqA3FXzilmtnIyJ+CxdkInkY/i4ErvP7uV0DnUVxQcQ55reuHphorpF+tZoVHK2MniZ/VJzI7zJQoc9T9Yw==} engines: {node: '>=8'} @@ -2400,6 +5952,15 @@ packages: sade: 1.8.1 dev: true + /v8-to-istanbul@9.2.0: + resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==} + engines: {node: '>=10.12.0'} + dependencies: + '@jridgewell/trace-mapping': 0.3.18 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + dev: true + /validate-html-nesting@1.2.2: resolution: {integrity: sha512-hGdgQozCsQJMyfK5urgFcWEqsSSrK63Awe0t/IMR0bZ0QMtnuaiHzThW81guu3qx9abLi99NEuiaN6P9gVYsNg==} dev: true @@ -2420,6 +5981,27 @@ packages: vfile-message: 3.1.2 dev: true + /vite-node@1.5.0(@types/node@18.11.18): + resolution: {integrity: sha512-tV8h6gMj6vPzVCa7l+VGq9lwoJjW8Y79vst8QZZGiuRAfijU+EEWuc0kFpmndQrWhMMhet1jdSF+40KSZUqIIw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.3.4 + pathe: 1.1.2 + picocolors: 1.0.0 + vite: 5.2.8(@types/node@18.11.18) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + /vite-plugin-inspect@0.7.14(rollup@3.9.1)(vite@4.1.1): resolution: {integrity: sha512-C9V93Yy2yUf941oVxIq93K6T1o0SZxoG8MdmyJsnoNDijOAGHT1rVSVjzF/uKFYvgnvLvaXioaoy6ica6aOS0g==} engines: {node: '>=14'} @@ -2439,7 +6021,7 @@ packages: - supports-color dev: true - /vite-plugin-solid@2.5.0(solid-js@1.7.0)(vite@4.1.1): + /vite-plugin-solid@2.5.0(solid-js@1.8.17)(vite@4.1.1): resolution: {integrity: sha512-VneGd3RyFJvwaiffsqgymeMaofn0IzQLPwDzafTV2f1agoWeeJlk5VrI5WqT9BTtLe69vNNbCJWqLhHr9fOdDw==} peerDependencies: solid-js: ^1.3.17 || ^1.4.0 || ^1.5.0 || ^1.6.0 @@ -2449,8 +6031,8 @@ packages: '@babel/preset-typescript': 7.21.5(@babel/core@7.21.5) babel-preset-solid: 1.7.3(@babel/core@7.21.5) merge-anything: 5.1.5 - solid-js: 1.7.0 - solid-refresh: 0.4.3(solid-js@1.7.0) + solid-js: 1.8.17 + solid-refresh: 0.4.3(solid-js@1.8.17) vite: 4.1.1(@types/node@18.11.18) vitefu: 0.2.4(vite@4.1.1) transitivePeerDependencies: @@ -2488,7 +6070,43 @@ packages: resolve: 1.22.2 rollup: 3.21.2 optionalDependencies: - fsevents: 2.3.2 + fsevents: 2.3.3 + dev: true + + /vite@5.2.8(@types/node@18.11.18): + resolution: {integrity: sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 18.11.18 + esbuild: 0.20.2 + postcss: 8.4.38 + rollup: 4.14.3 + optionalDependencies: + fsevents: 2.3.3 dev: true /vitefu@0.2.4(vite@4.1.1): @@ -2502,10 +6120,105 @@ packages: vite: 4.1.1(@types/node@18.11.18) dev: true + /vitest@1.5.0(@types/node@18.11.18)(jsdom@24.0.0): + resolution: {integrity: sha512-d8UKgR0m2kjdxDWX6911uwxout6GHS0XaGH1cksSIVVG8kRlE7G7aBw7myKQCvDI5dT4j7ZMa+l706BIORMDLw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 1.5.0 + '@vitest/ui': 1.5.0 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@types/node': 18.11.18 + '@vitest/expect': 1.5.0 + '@vitest/runner': 1.5.0 + '@vitest/snapshot': 1.5.0 + '@vitest/spy': 1.5.0 + '@vitest/utils': 1.5.0 + acorn-walk: 8.3.2 + chai: 4.4.1 + debug: 4.3.4 + execa: 8.0.1 + jsdom: 24.0.0 + local-pkg: 0.5.0 + magic-string: 0.30.9 + pathe: 1.1.2 + picocolors: 1.0.0 + std-env: 3.7.0 + strip-literal: 2.1.0 + tinybench: 2.7.0 + tinypool: 0.8.4 + vite: 5.2.8(@types/node@18.11.18) + vite-node: 1.5.0(@types/node@18.11.18) + why-is-node-running: 2.2.2 + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + + /w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + dependencies: + xml-name-validator: 5.0.0 + dev: true + + /walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + dependencies: + makeerror: 1.0.12 + dev: true + /webidl-conversions@4.0.2: resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} dev: true + /webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + dev: true + + /whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + dependencies: + iconv-lite: 0.6.3 + dev: true + + /whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + dev: true + + /whatwg-url@14.0.0: + resolution: {integrity: sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==} + engines: {node: '>=18'} + dependencies: + tr46: 5.0.0 + webidl-conversions: 7.0.0 + dev: true + /whatwg-url@7.1.0: resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} dependencies: @@ -2514,6 +6227,37 @@ packages: webidl-conversions: 4.0.2 dev: true + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.3 + dev: true + + /which-typed-array@1.1.15: + resolution: {integrity: sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.7 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.2 + dev: true + /which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -2522,28 +6266,104 @@ packages: isexe: 2.0.0 dev: true + /why-is-node-running@2.2.2: + resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} + engines: {node: '>=8'} + hasBin: true + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + dev: true + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} dev: true + /write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + dev: true + + /ws@8.16.0: + resolution: {integrity: sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==} + 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 + dev: true + + /xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + dev: true + + /xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + dev: true + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: true + /yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} dev: true - /yaml@1.10.2: - resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} - engines: {node: '>= 6'} + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: true - /zustand@3.7.2: - resolution: {integrity: sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==} - engines: {node: '>=12.7.0'} - peerDependencies: - react: '>=16.8' - peerDependenciesMeta: - react: - optional: true - dev: false + /yaml@2.4.2: + resolution: {integrity: sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==} + engines: {node: '>= 14'} + hasBin: true + dev: true + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: true + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true + + /yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + dev: true /zwitch@2.0.2: resolution: {integrity: sha512-JZxotl7SxAJH0j7dN4pxsTV6ZLXoLdGME+PsjkL/DaBrVryK9kTGq06GfKrwcSOqypP+fdXGoCHE36b99fWVoA==} diff --git a/src/augment.ts b/src/augment.ts new file mode 100644 index 0000000..ec93ba3 --- /dev/null +++ b/src/augment.ts @@ -0,0 +1,19 @@ +import { S3 } from "."; + +export const $S3C = Symbol("solid-three"); + +/** + * A utility to add metadata to a given instance. + * This data can be accessed behind the `S3C` symbol and is used internally in `solid-three`. + * + * @param instance - `three` instance + * @param augmentation - additional data: `{ props }` + * @returns the `three` instance with the additional data + */ +export const augment = (instance: T, augmentation = {}) => { + if (instance && typeof instance === "object" && $S3C in instance) { + return instance as S3.Instance; + } + instance[$S3C] = { children: new Set(), ...augmentation }; + return instance as S3.Instance; +}; diff --git a/src/canvas.tsx b/src/canvas.tsx new file mode 100644 index 0000000..841be74 --- /dev/null +++ b/src/canvas.tsx @@ -0,0 +1,131 @@ +import { ComponentProps, JSX, createRenderEffect, onCleanup, onMount, splitProps } from "solid-js"; +import { Camera, OrthographicCamera, Raycaster, Scene, WebGLRenderer } from "three"; +import { S3 } from "./"; +import { createThree } from "./create-three"; + +/** + * Props for the Canvas component, which initializes the Three.js rendering context and acts as the root for your 3D scene. + */ +export interface CanvasProps extends ComponentProps<"div"> { + /** + * Configuration for the camera used in the scene. + */ + camera?: Partial | S3.Props<"OrthographicCamera">> | Camera; + + /** + * Element to render while the main content is loading asynchronously. + */ + fallback?: JSX.Element; + + /** + * Options for the WebGLRenderer or a function returning a customized renderer. + */ + gl?: + | Partial> + | ((canvas: HTMLCanvasElement) => WebGLRenderer) + | WebGLRenderer; + + /** + * Toggles between Orthographic and Perspective camera. + */ + orthographic?: boolean; + + /** + * Configuration for the Raycaster used for mouse and pointer events. + */ + raycaster?: Partial> | Raycaster; + + /** + * Configuration for the Scene instance. + */ + scene?: Partial> | Scene; + + /** + * Custom CSS styles for the canvas container. + */ + style?: JSX.CSSProperties; + + /** + * Enables and configures shadows in the scene. + */ + shadows?: boolean | "basic" | "percentage" | "soft" | "variance" | WebGLRenderer["shadowMap"]; + + /** + * Toggles linear interpolation for texture filtering. + */ + linear?: boolean; + + /** + * Toggles flat interpolation for texture filtering. + */ + flat?: boolean; + + /** + * Controls the rendering loop's operation mode. + */ + frameloop?: "never" | "demand" | "always"; +} + +/** + * Serves as the root component for all 3D scenes created with `solid-three`. It initializes + * the Three.js rendering context, including a WebGL renderer, a scene, and a camera. + * All ``-components must be children of this Canvas. Hooks such as `useThree` and + * `useFrame` should only be used within this component to ensure proper context. + * + * @function Canvas + * @param props - Configuration options include camera settings, style, and children elements. + * @returns A div element containing the WebGL canvas configured to occupy the full available space. + */ +export function Canvas(_props: CanvasProps) { + const [props, canvasProps] = splitProps(_props, ["fallback", "camera", "children", "ref"]); + let canvas: HTMLCanvasElement; + let container: HTMLDivElement; + + onMount(() => { + const context = createThree(canvas, props); + + // Resize observer for the canvas to adjust camera and renderer on size change + function onResize() { + context.gl.setSize(window.innerWidth, window.innerHeight); + context.gl.setPixelRatio(window.devicePixelRatio); + + if (context.camera instanceof OrthographicCamera) { + context.camera.left = window.innerWidth / -2; + context.camera.right = window.innerWidth / 2; + context.camera.top = window.innerHeight / 2; + context.camera.bottom = window.innerHeight / -2; + } else { + context.camera.aspect = window.innerWidth / window.innerHeight; + } + context.camera.updateProjectionMatrix(); + context.render(performance.now()); + } + const observer = new ResizeObserver(onResize); + observer.observe(container); + onResize(); + onCleanup(() => observer.disconnect()); + + // Assign ref + createRenderEffect(() => { + if (props.ref instanceof Function) props.ref(container); + else props.ref = container; + }); + }); + + return ( +
+
+ +
+
+ ); +} diff --git a/src/components.tsx b/src/components.tsx new file mode 100644 index 0000000..adaf2b1 --- /dev/null +++ b/src/components.tsx @@ -0,0 +1,67 @@ +import { JSX, ParentProps, createMemo, createRenderEffect, mergeProps } from "solid-js"; +import { Object3D } from "three"; +import { S3 } from "./"; +import { augment } from "./augment"; +import { threeContext, useThree } from "./hooks"; +import { manageProps, manageSceneGraph } from "./props"; +import { InstanceFromConstructor } from "./type-utils"; +import { isAugmentedElement } from "./utils/is-augmented-element"; +import { withContext } from "./utils/with-context"; + +type PortalProps = ParentProps<{ + element?: InstanceFromConstructor | S3.Instance; +}>; +/** + * A component for placing its children outside the regular `solid-three` scene graph managed by Solid's reactive system. + * This is useful for bypassing the normal rendering flow and manually managing children, similar to Solid's Portal but specific to `solid-three`. + * + * @function Portal + * @param props - The component props containing `children` to be rendered and an optional Object3D `element` to be rendered into. + * @returns An empty JSX element. + */ +export const Portal = (props: PortalProps) => { + const context = useThree(); + const scene = createMemo(() => { + return props.element + ? isAugmentedElement(props.element) + ? (props.element as S3.Instance) + : augment(props.element, { props: {} }) + : context.scene; + }); + + createRenderEffect(() => { + manageSceneGraph(scene(), () => + withContext( + () => props.children as unknown as S3.Instance | S3.Instance[], + threeContext, + mergeProps(context, { + get scene() { + return scene(); + }, + }), + ), + ); + }); + + return null; +}; + +type PrimitiveProps = Omit, "object" | "children" | "ref" | "args"> & { + object: T; + children?: JSX.Element; + ref?: T | ((value: T) => void); +}; +/** + * Wraps a `ThreeElement` and allows it to be used as a JSX-component within a `solid-three` scene. + * + * @function Primitive + * @template T - Extends `S3.ThreeInstance` + * @param props - The properties for the Three.js object including the object instance's methods, + * optional children, and a ref that provides access to the object instance. + * @returns The Three.js object wrapped as a JSX element, allowing it to be used within Solid's component system. + */ +export function Primitive(props: PrimitiveProps) { + const memo = createMemo(() => augment(props.object, { props }) as S3.Instance); + manageProps(memo, props); + return memo as unknown as JSX.Element; +} diff --git a/src/core/events.ts b/src/core/events.ts deleted file mode 100644 index 9f48ec4..0000000 --- a/src/core/events.ts +++ /dev/null @@ -1,531 +0,0 @@ -import * as THREE from "three"; -// @ts-ignore -// import { -// ContinuousEventPriority, -// DiscreteEventPriority, -// DefaultEventPriority, -// } from "react-reconciler/constants"; -import type { StoreApi as UseStore } from "zustand/vanilla"; -import type { Instance } from "./renderer"; -import type { RootState } from "./store"; - -export interface Intersection extends THREE.Intersection { - eventObject: THREE.Object3D; -} - -export interface IntersectionEvent extends Intersection { - intersections: Intersection[]; - stopped: boolean; - unprojectedPoint: THREE.Vector3; - ray: THREE.Ray; - camera: Camera; - stopPropagation: () => void; - /** - * @deprecated in favour of nativeEvent. Please use that instead. - */ - sourceEvent: TSourceEvent; - nativeEvent: TSourceEvent; - delta: number; - spaceX: number; - spaceY: number; -} - -export type Camera = THREE.OrthographicCamera | THREE.PerspectiveCamera; -export type ThreeEvent = IntersectionEvent; -export type DomEvent = PointerEvent | MouseEvent | WheelEvent; - -export type Events = { - onClick: EventListener; - onContextMenu: EventListener; - onDoubleClick: EventListener; - onWheel: EventListener; - onPointerDown: EventListener; - onPointerUp: EventListener; - onPointerLeave: EventListener; - onPointerMove: EventListener; - onPointerCancel: EventListener; - onLostPointerCapture: EventListener; -}; - -export type EventHandlers = { - onClick?: (event: ThreeEvent) => void; - onContextMenu?: (event: ThreeEvent) => void; - onDoubleClick?: (event: ThreeEvent) => void; - onPointerUp?: (event: ThreeEvent) => void; - onPointerDown?: (event: ThreeEvent) => void; - onPointerOver?: (event: ThreeEvent) => void; - onPointerOut?: (event: ThreeEvent) => void; - onPointerEnter?: (event: ThreeEvent) => void; - onPointerLeave?: (event: ThreeEvent) => void; - onPointerMove?: (event: ThreeEvent) => void; - onPointerMissed?: (event: MouseEvent) => void; - onPointerCancel?: (event: ThreeEvent) => void; - onWheel?: (event: ThreeEvent) => void; -}; - -export interface EventManager { - connected: TTarget | boolean; - handlers?: Events; - connect?: (target: TTarget) => void; - disconnect?: () => void; -} - -export interface PointerCaptureTarget { - intersection: Intersection; - target: Element; -} - -function makeId(event: Intersection) { - return ( - (event.eventObject || event.object).uuid + - "/" + - event.index + - event.instanceId - ); -} - -// https://github.com/facebook/react/tree/main/packages/react-reconciler#getcurrenteventpriority -// Gives React a clue as to how import the current interaction is -// export function getEventPriority() { -// let name = window?.event?.type; -// switch (name) { -// case "click": -// case "contextmenu": -// case "dblclick": -// case "pointercancel": -// case "pointerdown": -// case "pointerup": -// return DiscreteEventPriority; -// case "pointermove": -// case "pointerout": -// case "pointerover": -// case "pointerenter": -// case "pointerleave": -// case "wheel": -// return ContinuousEventPriority; -// default: -// return DefaultEventPriority; -// } -// } - -/** - * Release pointer captures. - * This is called by releasePointerCapture in the API, and when an object is removed. - */ -function releaseInternalPointerCapture( - capturedMap: Map>, - obj: THREE.Object3D, - captures: Map, - pointerId: number -): void { - const captureData: PointerCaptureTarget | undefined = captures.get(obj); - if (captureData) { - captures.delete(obj); - // If this was the last capturing object for this pointer - if (captures.size === 0) { - capturedMap.delete(pointerId); - captureData.target.releasePointerCapture(pointerId); - } - } -} - -export function removeInteractivity( - store: UseStore, - object: THREE.Object3D -) { - const { internal } = store.getState(); - // Removes every trace of an object from the data store - internal.interaction = internal.interaction.filter((o) => o !== object); - internal.initialHits = internal.initialHits.filter((o) => o !== object); - internal.hovered.forEach((value, key) => { - if (value.eventObject === object || value.object === object) { - internal.hovered.delete(key); - } - }); - internal.capturedMap.forEach((captures, pointerId) => { - releaseInternalPointerCapture( - internal.capturedMap, - object, - captures, - pointerId - ); - }); -} - -export function createEvents(store: UseStore) { - const temp = new THREE.Vector3(); - - /** Sets up defaultRaycaster */ - function prepareRay(event: DomEvent) { - const state = store.getState(); - const { raycaster, mouse, camera, size } = state; - // https://github.com/pmndrs/react-three-fiber/pull/782 - // Events trigger outside of canvas when moved - const { offsetX, offsetY } = - raycaster.computeOffsets?.(event, state) ?? event; - const { width, height } = size; - mouse.set((offsetX / width) * 2 - 1, -(offsetY / height) * 2 + 1); - raycaster.setFromCamera(mouse, camera); - } - - /** Calculates delta */ - function calculateDistance(event: DomEvent) { - const { internal } = store.getState(); - const dx = event.offsetX - internal.initialClick[0]; - const dy = event.offsetY - internal.initialClick[1]; - return Math.round(Math.sqrt(dx * dx + dy * dy)); - } - - /** Returns true if an instance has a valid pointer-event registered, this excludes scroll, clicks etc */ - function filterPointerEvents(objects: THREE.Object3D[]) { - return objects.filter((obj) => - ["Move", "Over", "Enter", "Out", "Leave"].some( - (name) => - (obj as unknown as Instance).__r3f?.handlers[ - ("onPointer" + name) as keyof EventHandlers - ] - ) - ); - } - - function intersect(filter?: (objects: THREE.Object3D[]) => THREE.Object3D[]) { - const state = store.getState(); - const { raycaster, internal } = state; - // Skip event handling when noEvents is set - if (!raycaster.enabled) return []; - - const seen = new Set(); - const intersections: Intersection[] = []; - - // Allow callers to eliminate event objects - const eventsObjects = filter - ? filter(internal.interaction) - : internal.interaction; - - // Intersect known handler objects and filter against duplicates - let intersects = raycaster - .intersectObjects(eventsObjects, true) - .filter((item) => { - const id = makeId(item as Intersection); - if (seen.has(id)) return false; - seen.add(id); - return true; - }); - - // https://github.com/mrdoob/three.js/issues/16031 - // Allow custom userland intersect sort order - if (raycaster.filter) intersects = raycaster.filter(intersects, state); - - for (const intersect of intersects) { - let eventObject: THREE.Object3D | null = intersect.object; - // Bubble event up - while (eventObject) { - if ((eventObject as unknown as Instance).__r3f?.eventCount) - intersections.push({ ...intersect, eventObject }); - eventObject = eventObject.parent; - } - } - return intersections; - } - - /** Creates filtered intersects and returns an array of positive hits */ - function patchIntersects(intersections: Intersection[], event: DomEvent) { - const { internal } = store.getState(); - // If the interaction is captured, make all capturing targets part of the - // intersect. - if ("pointerId" in event && internal.capturedMap.has(event.pointerId)) { - for (let captureData of internal.capturedMap - .get(event.pointerId)! - .values()) { - intersections.push(captureData.intersection); - } - } - return intersections; - } - - /** Handles intersections by forwarding them to handlers */ - function handleIntersects( - intersections: Intersection[], - event: DomEvent, - delta: number, - callback: (event: ThreeEvent) => void - ) { - const { raycaster, mouse, camera, internal } = store.getState(); - // If anything has been found, forward it to the event listeners - if (intersections.length) { - const unprojectedPoint = temp.set(mouse.x, mouse.y, 0).unproject(camera); - - const localState = { stopped: false }; - - for (const hit of intersections) { - const hasPointerCapture = (id: number) => - internal.capturedMap.get(id)?.has(hit.eventObject) ?? false; - - const setPointerCapture = (id: number) => { - const captureData = { - intersection: hit, - target: event.target as Element, - }; - if (internal.capturedMap.has(id)) { - // if the pointerId was previously captured, we add the hit to the - // event capturedMap. - internal.capturedMap.get(id)!.set(hit.eventObject, captureData); - } else { - // if the pointerId was not previously captured, we create a map - // containing the hitObject, and the hit. hitObject is used for - // faster access. - internal.capturedMap.set( - id, - new Map([[hit.eventObject, captureData]]) - ); - } - // Call the original event now - (event.target as Element).setPointerCapture(id); - }; - - const releasePointerCapture = (id: number) => { - const captures = internal.capturedMap.get(id); - if (captures) { - releaseInternalPointerCapture( - internal.capturedMap, - hit.eventObject, - captures, - id - ); - } - }; - - // Add native event props - let extractEventProps: any = {}; - // This iterates over the event's properties including the inherited ones. Native PointerEvents have most of their props as getters which are inherited, but polyfilled PointerEvents have them all as their own properties (i.e. not inherited). We can't use Object.keys() or Object.entries() as they only return "own" properties; nor Object.getPrototypeOf(event) as that *doesn't* return "own" properties, only inherited ones. - for (let prop in event) { - let property = event[prop as keyof DomEvent]; - // Only copy over atomics, leave functions alone as these should be - // called as event.nativeEvent.fn() - if (typeof property !== "function") - extractEventProps[prop] = property; - } - - let raycastEvent: any = { - ...hit, - ...extractEventProps, - spaceX: mouse.x, - spaceY: mouse.y, - intersections, - stopped: localState.stopped, - delta, - unprojectedPoint, - ray: raycaster.ray, - camera: camera, - // Hijack stopPropagation, which just sets a flag - stopPropagation: () => { - // https://github.com/pmndrs/react-three-fiber/issues/596 - // Events are not allowed to stop propagation if the pointer has been captured - const capturesForPointer = - "pointerId" in event && internal.capturedMap.get(event.pointerId); - - // We only authorize stopPropagation... - if ( - // ...if this pointer hasn't been captured - !capturesForPointer || - // ... or if the hit object is capturing the pointer - capturesForPointer.has(hit.eventObject) - ) { - raycastEvent.stopped = localState.stopped = true; - // Propagation is stopped, remove all other hover records - // An event handler is only allowed to flush other handlers if it is hovered itself - if ( - internal.hovered.size && - Array.from(internal.hovered.values()).find( - (i) => i.eventObject === hit.eventObject - ) - ) { - // Objects cannot flush out higher up objects that have already caught the event - const higher = intersections.slice( - 0, - intersections.indexOf(hit) - ); - cancelPointer([...higher, hit]); - } - } - }, - // there should be a distinction between target and currentTarget - target: { - hasPointerCapture, - setPointerCapture, - releasePointerCapture, - }, - currentTarget: { - hasPointerCapture, - setPointerCapture, - releasePointerCapture, - }, - sourceEvent: event, // deprecated - nativeEvent: event, - }; - - // Call subscribers - callback(raycastEvent); - // Event bubbling may be interrupted by stopPropagation - if (localState.stopped === true) break; - } - } - return intersections; - } - - function cancelPointer(hits: Intersection[]) { - const { internal } = store.getState(); - Array.from(internal.hovered.values()).forEach((hoveredObj) => { - // When no objects were hit or the the hovered object wasn't found underneath the cursor - // we call onPointerOut and delete the object from the hovered-elements map - if ( - !hits.length || - !hits.find( - (hit) => - hit.object === hoveredObj.object && - hit.index === hoveredObj.index && - hit.instanceId === hoveredObj.instanceId - ) - ) { - const eventObject = hoveredObj.eventObject; - const instance = (eventObject as unknown as Instance).__r3f; - const handlers = instance?.handlers; - internal.hovered.delete(makeId(hoveredObj)); - if (instance?.eventCount) { - // Clear out intersects, they are outdated by now - const data = { ...hoveredObj, intersections: hits || [] }; - handlers.onPointerOut?.(data as ThreeEvent); - handlers.onPointerLeave?.(data as ThreeEvent); - } - } - }); - } - - const handlePointer = (name: string) => { - // Deal with cancelation - switch (name) { - case "onPointerLeave": - case "onPointerCancel": - return () => cancelPointer([]); - case "onLostPointerCapture": - return (event: DomEvent) => { - const { internal } = store.getState(); - if ( - "pointerId" in event && - !internal.capturedMap.has(event.pointerId) - ) { - // If the object event interface had onLostPointerCapture, we'd call it here on every - // object that's getting removed. - internal.capturedMap.delete(event.pointerId); - cancelPointer([]); - } - }; - } - - // Any other pointer goes here ... - return (event: DomEvent) => { - const { onPointerMissed, internal } = store.getState(); - - prepareRay(event); - internal.lastEvent.current = event; - - // Get fresh intersects - const isPointerMove = name === "onPointerMove"; - const isClickEvent = - name === "onClick" || - name === "onContextMenu" || - name === "onDoubleClick"; - const filter = isPointerMove ? filterPointerEvents : undefined; - const hits = patchIntersects(intersect(filter), event); - const delta = isClickEvent ? calculateDistance(event) : 0; - - // Save initial coordinates on pointer-down - if (name === "onPointerDown") { - internal.initialClick = [event.offsetX, event.offsetY]; - internal.initialHits = hits.map((hit) => hit.eventObject); - } - - // If a click yields no results, pass it back to the user as a miss - // Missed events have to come first in order to establish user-land side-effect clean up - if (isClickEvent && !hits.length) { - if (delta <= 2) { - pointerMissed(event, internal.interaction); - if (onPointerMissed) onPointerMissed(event); - } - } - // Take care of unhover - if (isPointerMove) cancelPointer(hits); - - handleIntersects(hits, event, delta, (data: ThreeEvent) => { - const eventObject = data.eventObject; - const instance = (eventObject as unknown as Instance).__r3f; - const handlers = instance?.handlers; - // Check presence of handlers - if (!instance?.eventCount) return; - - if (isPointerMove) { - // Move event ... - if ( - handlers.onPointerOver || - handlers.onPointerEnter || - handlers.onPointerOut || - handlers.onPointerLeave - ) { - // When enter or out is present take care of hover-state - const id = makeId(data); - const hoveredItem = internal.hovered.get(id); - if (!hoveredItem) { - // If the object wasn't previously hovered, book it and call its handler - internal.hovered.set(id, data); - handlers.onPointerOver?.(data as ThreeEvent); - handlers.onPointerEnter?.(data as ThreeEvent); - } else if (hoveredItem.stopped) { - // If the object was previously hovered and stopped, we shouldn't allow other items to proceed - data.stopPropagation(); - } - } - // Call mouse move - handlers.onPointerMove?.(data as ThreeEvent); - } else { - // All other events ... - const handler = handlers[name as keyof EventHandlers] as ( - event: ThreeEvent - ) => void; - if (handler) { - // Forward all events back to their respective handlers with the exception of click events, - // which must use the initial target - if (!isClickEvent || internal.initialHits.includes(eventObject)) { - // Missed events have to come first - pointerMissed( - event, - internal.interaction.filter( - (object) => !internal.initialHits.includes(object) - ) - ); - // Now call the handler - handler(data as ThreeEvent); - } - } else { - // Trigger onPointerMissed on all elements that have pointer over/out handlers, but not click and weren't hit - if (isClickEvent && internal.initialHits.includes(eventObject)) { - pointerMissed( - event, - internal.interaction.filter( - (object) => !internal.initialHits.includes(object) - ) - ); - } - } - } - }); - }; - }; - - function pointerMissed(event: MouseEvent, objects: THREE.Object3D[]) { - objects.forEach((object: THREE.Object3D) => - (object as unknown as Instance).__r3f?.handlers.onPointerMissed?.(event) - ); - } - - return { handlePointer }; -} diff --git a/src/core/index.tsx b/src/core/index.tsx deleted file mode 100644 index b8b6f0d..0000000 --- a/src/core/index.tsx +++ /dev/null @@ -1,193 +0,0 @@ -import * as THREE from "three"; -import { StoreApi as UseStore } from "zustand/vanilla"; -import { dispose, calculateDpr, applyProps } from "./utils"; -import { - Renderer, - createThreeStore, - StoreProps, - isRenderer, - ThreeContext, - RootState, - Size -} from "./store"; -import { extend, Root } from "./renderer"; -import { createLoop, addEffect, addAfterEffect, addTail } from "./loop"; -import { EventManager } from "./events"; -import { createEffect, PropsWithChildren } from "solid-js"; - -export type { IntersectionEvent, EventHandlers, Intersection, Camera } from "./events"; -export { attach, applyProp } from "./utils"; -export { catalogue } from "./renderer"; -export type { InternalState, Raycaster } from "./store"; -export type { DiffSet } from "./utils"; - -export const roots = new Map(); -const { invalidate, advance } = createLoop(roots); - -type Properties = Pick any ? never : K }[keyof T]>; - -type GLProps = - | Renderer - | ((canvas: HTMLCanvasElement) => Renderer) - | Partial | THREE.WebGLRendererParameters> - | undefined; - -export type RenderProps = Omit & { - gl?: GLProps; - events?: (store: UseStore) => EventManager; - size?: Size; - onCreated?: (state: RootState) => void; -}; - -const createRendererInstance = ( - gl: GLProps, - canvas: TElement -): THREE.WebGLRenderer => { - const customRenderer = ( - typeof gl === "function" ? gl(canvas as unknown as HTMLCanvasElement) : gl - ) as THREE.WebGLRenderer; - if (isRenderer(customRenderer)) return customRenderer; - - const renderer = new THREE.WebGLRenderer({ - powerPreference: "high-performance", - canvas: canvas as unknown as HTMLCanvasElement, - antialias: true, - alpha: true, - ...gl - }); - - // Set color management - renderer.outputEncoding = THREE.sRGBEncoding; - renderer.toneMapping = THREE.ACESFilmicToneMapping; - - // Set gl props - if (gl) applyProps(renderer as any, gl as any); - - return renderer; -}; - -function createThreeRoot( - canvas: TCanvas, - config?: RenderProps -) { - let { gl, size, events, onCreated, ...props } = config || {}; - // Allow size to take on container bounds initially - if (!size) { - size = canvas.parentElement?.getBoundingClientRect() ?? { - width: 0, - height: 0 - }; - } - - // if (fiber && state) { - // // When a root was found, see if any fundamental props must be changed or exchanged - - // // Check pixelratio - // if ( - // props.dpr !== undefined && - // state.viewport.dpr !== calculateDpr(props.dpr) - // ) - // state.setDpr(props.dpr); - // // Check size - // if ( - // state.size.width !== size.width || - // state.size.height !== size.height - // ) - // state.setSize(size.width, size.height); - // // Check frameloop - // if (state.frameloop !== props.frameloop) - // state.setFrameloop(props.frameloop); - - // // For some props we want to reset the entire root - - // // Changes to the color-space - // const linearChanged = props.linear !== state.internal.lastProps.linear; - // if (linearChanged) { - // unmountComponentAtNode(canvas); - // fiber = undefined; - // } - // } - - // Create gl - const glRenderer = createRendererInstance(gl, canvas); - - // Create store - const store = createThreeStore(applyProps, invalidate, advance, { - gl: glRenderer, - size, - ...props - }); - - const state = store.getState(); - - // Map it - roots.set(canvas, { store }); - // Store events internally - if (events) state.set({ events: events(store) }); - - createEffect(() => { - const state = store.getState(); - // Flag the canvas active, rendering will now begin - state.set(state => ({ internal: { ...state.internal, active: true } })); - // Connect events - state.events.connect?.(canvas); - // Notifiy that init is completed, the scene graph exists, but nothing has yet rendered - onCreated?.(state); - - state.invalidate(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }); - - return store; -} - -function unmountComponentAtNode( - canvas: TElement, - callback?: (canvas: TElement) => void -) { - const root = roots.get(canvas); - // const fiber = root?.fiber; - // if (fiber) { - // const state = root?.store.getState(); - // if (state) state.internal.active = false; - - // setTimeout(() => { - // try { - // state.events.disconnect?.(); - // state.gl?.renderLists?.dispose?.(); - // state.gl?.forceContextLoss?.(); - // if (state.gl?.xr) state.internal.xr.disconnect(); - // dispose(state); - // roots.delete(canvas); - // if (callback) callback(canvas); - // } catch (e) { - // /* ... */ - // } - // }, 500); - // } -} - -// function createPortal( -// children: React.ReactNode, -// container: THREE.Object3D -// ): React.ReactNode { -// return reconciler.createPortal(children, container, null, null); -// } - -export { - ThreeContext as context, - // render, - createThreeRoot, - unmountComponentAtNode, - // createPortal, - applyProps, - dispose, - invalidate, - advance, - extend, - addEffect, - addAfterEffect, - addTail, - // act, - roots as _roots -}; diff --git a/src/core/is.ts b/src/core/is.ts deleted file mode 100644 index 82dcf02..0000000 --- a/src/core/is.ts +++ /dev/null @@ -1,21 +0,0 @@ -export const is = { - obj: (a: any) => a === Object(a) && !is.arr(a) && typeof a !== 'function', - fun: (a: any): a is Function => typeof a === 'function', - str: (a: any): a is string => typeof a === 'string', - num: (a: any): a is number => typeof a === 'number', - und: (a: any) => a === void 0, - arr: (a: any) => Array.isArray(a), - equ(a: any, b: any) { - // Wrong type or one of the two undefined, doesn't match - if (typeof a !== typeof b || !!a !== !!b) return false - // Atomic, just compare a against b - if (is.str(a) || is.num(a) || is.obj(a)) return a === b - // Array, shallow compare first to see if it's a match - if (is.arr(a) && a == b) return true - // Last resort, go through keys - let i - for (i in a) if (!(i in b)) return false - for (i in b) if (a[i] !== b[i]) return false - return is.und(i) ? a === b : true - }, -} diff --git a/src/core/loop.ts b/src/core/loop.ts deleted file mode 100644 index e7fba0f..0000000 --- a/src/core/loop.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { Root } from "./renderer"; -import { RootState } from "./store"; - -type GlobalRenderCallback = (timeStamp: number) => void; - -function createSubs( - callback: GlobalRenderCallback, - subs: GlobalRenderCallback[] -): () => void { - const index = subs.length; - subs.push(callback); - return () => void subs.splice(index, 1); -} - -let i; -let globalEffects: GlobalRenderCallback[] = []; -let globalAfterEffects: GlobalRenderCallback[] = []; -let globalTailEffects: GlobalRenderCallback[] = []; -export const addEffect = (callback: GlobalRenderCallback) => - createSubs(callback, globalEffects); -export const addAfterEffect = (callback: GlobalRenderCallback) => - createSubs(callback, globalAfterEffects); -export const addTail = (callback: GlobalRenderCallback) => - createSubs(callback, globalTailEffects); - -function run(effects: GlobalRenderCallback[], timestamp: number) { - for (i = 0; i < effects.length; i++) effects[i](timestamp); -} - -function render(timestamp: number, state: RootState) { - // Run local effects - let delta = state.clock.getDelta(); - // In frameloop='never' mode, clock times are updated using the provided timestamp - if (state.frameloop === "never" && typeof timestamp === "number") { - delta = timestamp - state.clock.elapsedTime; - state.clock.oldTime = state.clock.elapsedTime; - state.clock.elapsedTime = timestamp; - } - // Call subscribers (useFrame) - for (i = 0; i < state.internal.subscribers.length; i++) - state.internal.subscribers[i].ref(state, delta); - // Render content - if (!state.internal.priority && state.gl.render) - state.gl.render(state.scene, state.camera); - // Decrease frame count - state.internal.frames = Math.max(0, state.internal.frames - 1); - return state.frameloop === "always" ? 1 : state.internal.frames; -} - -export function createLoop(roots: Map) { - let running = false; - let repeat: number; - function loop(timestamp: number) { - running = true; - repeat = 0; - - // Run effects - run(globalEffects, timestamp); - // Render all roots - roots.forEach((root) => { - const state = root.store.getState(); - // If the frameloop is invalidated, do not run another frame - if ( - state.internal.active && - (state.frameloop === "always" || state.internal.frames > 0) && - !state.gl.xr?.isPresenting - ) { - repeat += render(timestamp, state); - } - }); - // Run after-effects - run(globalAfterEffects, timestamp); - - // Keep on looping if anything invalidates the frameloop - if (repeat > 0) return requestAnimationFrame(loop); - // Tail call effects, they are called when rendering stops - else run(globalTailEffects, timestamp); - - // Flag end of operation - running = false; - } - - function invalidate(state?: RootState): void { - if (!state) - return roots.forEach((root) => invalidate(root.store.getState())); - if ( - state.gl.xr?.isPresenting || - !state.internal.active || - state.frameloop === "never" - ) - return; - // Increase frames, do not go higher than 60 - state.internal.frames = Math.min(60, state.internal.frames + 1); - // If the render-loop isn't active, start it - if (!running) { - running = true; - requestAnimationFrame(loop); - } - } - - function advance( - timestamp: number, - runGlobalEffects: boolean = true, - state?: RootState - ): void { - if (runGlobalEffects) run(globalEffects, timestamp); - if (!state) - roots.forEach((root) => render(timestamp, root.store.getState())); - else render(timestamp, state); - if (runGlobalEffects) run(globalAfterEffects, timestamp); - } - - return { loop, invalidate, advance }; -} diff --git a/src/core/renderer.ts b/src/core/renderer.ts deleted file mode 100644 index f87de96..0000000 --- a/src/core/renderer.ts +++ /dev/null @@ -1,322 +0,0 @@ -import * as THREE from "three"; -import { StoreApi as UseStore } from "zustand/vanilla"; -import { - is, - prepare, - diffProps, - DiffSet, - applyProps, - updateInstance, - invalidateInstance, - attach, - detach, - applyProp -} from "./utils"; -import { RootState } from "./store"; -import { EventHandlers, removeInteractivity } from "./events"; -import { log } from "../solid"; -import { dispose } from "."; - -export type Root = { store: UseStore }; - -export type LocalState = { - root: UseStore; - // objects and parent are used when children are added with `attach` instead of being added to the Object3D scene graph - objects: Instance[]; - parent: Instance | null; - primitive?: boolean; - eventCount: number; - handlers: Partial; - attach?: AttachType; - previousAttach?: any; - memoizedProps: { - [key: string]: any; - }; -}; - -export type AttachFnType = (parent: Instance, self: Instance) => void; -export type AttachType = string | [attach: string | AttachFnType, detach: string | AttachFnType]; - -// This type clamps down on a couple of assumptions that we can make regarding native types, which -// could anything from scene objects, THREE.Objects, JSM, user-defined classes and non-scene objects. -// What they all need to have in common is defined here ... -export type BaseInstance = Omit< - THREE.Object3D, - "children" | "attach" | "add" | "remove" | "raycast" -> & { - __r3f: LocalState; - children: Instance[]; - remove: (...object: Instance[]) => Instance; - add: (...object: Instance[]) => Instance; - raycast?: (raycaster: THREE.Raycaster, intersects: THREE.Intersection[]) => void; -}; -export type Instance = BaseInstance & { [key: string]: any }; - -export type InstanceProps = { - [key: string]: unknown; -} & { - args?: any[]; - object?: object; - visible?: boolean; - dispose?: null; - attach?: AttachType; -}; - -interface Catalogue { - [name: string]: { - new (...args: any): Instance; - }; -} - -// Type guard to tell a store from a portal -const isStore = (def: any): def is UseStore => - def && !!(def as UseStore).getState; -// const getContainer = ( -// container: UseStore | Instance, -// child: Instance -// ) => ({ -// // If the container is not a root-store then it must be a THREE.Object3D into which part of the -// // scene is portalled into. Now there can be two variants of this, either that object is part of -// // the regular jsx tree, in which case it already has __r3f with a valid root attached, or it lies -// // outside react, in which case we must take the root of the child that is about to be attached to it. -// root: isStore(container) -// ? container -// : container.__r3f?.root ?? child.__r3f.root, -// // The container is the eventual target into which objects are mounted, it has to be a THREE.Object3D -// container: isStore(container) -// ? (container.getState().scene as unknown as Instance) -// : container, -// }); - -export let catalogue: Catalogue = {}; -let extend = (objects: object): void => void (catalogue = { ...catalogue, ...objects }); - -function createThreeRenderer(roots: Map, getEventPriority?: () => any) { - function createInstance( - type: string, - { args = [], attach, ...props }: InstanceProps, - root: UseStore | Instance - ) { - let name = `${type[0].toUpperCase()}${type.slice(1)}`; - let instance: Instance; - - // https://github.com/facebook/react/issues/17147 - // Portals do not give us a root, they are themselves treated as a root by the reconciler - // In order to figure out the actual root we have to climb through fiber internals :( - // if (!isStore(root) && internalInstanceHandle) { - // const fn = (node: Reconciler.Fiber): UseStore => { - // if (!node.return) return node.stateNode && node.stateNode.containerInfo; - // else return fn(node.return); - // }; - // root = fn(internalInstanceHandle); - // } - // Assert that by now we have a valid root - if (!root || !isStore(root)) throw `No valid root for ${name}!`; - - // Auto-attach geometries and materials - if (attach === undefined) { - if (name.endsWith("Geometry")) attach = "geometry"; - else if (name.endsWith("Material")) attach = "material"; - } - - if (type === "primitive") { - if (props.object === undefined) throw `Primitives without 'object' are invalid!`; - const object = props.object as Instance; - instance = prepare(object, { - root, - attach, - primitive: true - }); - } else { - const target = catalogue[name]; - if (!target) { - throw `${name} is not part of the THREE namespace! Did you forget to extend? See: https://github.com/pmndrs/react-three-fiber/blob/master/markdown/api.md#using-3rd-party-objects-declaratively`; - } - - // Throw if an object or literal was passed for args - if (!Array.isArray(args)) throw "The args prop must be an array!"; - - // Instanciate new object, link it to the root - // Append memoized props with args so it's not forgotten - instance = prepare(new target(...args), { - root, - attach, - // TODO: Figure out what this is for - memoizedProps: { args: args.length === 0 ? null : args } - }); - } - - // It should NOT call onUpdate on object instanciation, because it hasn't been added to the - // view yet. If the callback relies on references for instance, they won't be ready yet, this is - // why it passes "true" here - applyProps(instance, props); - return instance; - } - - function appendChild(parentInstance: Instance, child: Instance) { - let added = false; - if (child) { - // The attach attribute implies that the object attaches itself on the parent - if (child.__r3f.attach) { - attach(parentInstance, child, child.__r3f.attach); - } else if (child.isObject3D && parentInstance.isObject3D) { - // add in the usual parent-child way - parentInstance.add(child); - added = true; - } - // This is for anything that used attach, and for non-Object3Ds that don't get attached to props; - // that is, anything that's a child in React but not a child in the scenegraph. - if (!added) parentInstance.__r3f.objects.push(child); - if (!child.__r3f) prepare(child, {}); - child.__r3f.parent = parentInstance; - updateInstance(child); - invalidateInstance(child); - } - } - - function insertBefore(parentInstance: Instance, child: Instance, beforeChild: Instance) { - let added = false; - if (child) { - if (child.__r3f.attach) { - attach(parentInstance, child, child.__r3f.attach); - } else if (child.isObject3D && parentInstance.isObject3D) { - child.parent = parentInstance as unknown as THREE.Object3D; - child.dispatchEvent({ type: "added" }); - const restSiblings = parentInstance.children.filter(sibling => sibling !== child); - const index = restSiblings.indexOf(beforeChild); - parentInstance.children = [ - ...restSiblings.slice(0, index), - child, - ...restSiblings.slice(index) - ]; - added = true; - } - - if (!added) parentInstance.__r3f.objects.push(child); - if (!child.__r3f) prepare(child, {}); - child.__r3f.parent = parentInstance; - updateInstance(child); - invalidateInstance(child); - } - } - - function removeRecursive(array: Instance[], parent: Instance, dispose: boolean = false) { - if (array) [...array].forEach(child => removeChild(parent, child, dispose)); - } - - function removeChild(parentInstance: Instance, child: Instance, canDispose?: boolean) { - if (child) { - // Clear the parent reference - if (child.__r3f) child.__r3f.parent = null; - // Remove child from the parents objects - if (parentInstance.__r3f?.objects) - parentInstance.__r3f.objects = parentInstance.__r3f.objects.filter(x => x !== child); - // Remove attachment - if (child.__r3f?.attach) { - detach(parentInstance, child, child.__r3f.attach); - } else if (child.isObject3D && parentInstance.isObject3D) { - log("three", "removeObject", parentInstance, child); - parentInstance.remove(child); - // Remove interactivity - if (child.__r3f?.root) { - removeInteractivity(child.__r3f.root, child as unknown as THREE.Object3D); - } - } - - // Allow objects to bail out of recursive dispose alltogether by passing dispose={null} - // Never dispose of primitives because their state may be kept outside of React! - // In order for an object to be able to dispose it has to have - // - a dispose method, - // - it cannot be a - // - it cannot be a THREE.Scene, because three has broken it's own api - // - // Since disposal is recursive, we can check the optional dispose arg, which will be undefined - // when the reconciler calls it, but then carry our own check recursively - const isPrimitive = child.__r3f?.primitive; - const shouldDispose = - canDispose === undefined ? child.dispose !== null && !isPrimitive : canDispose; - - // Remove nested child objects. Primitives should not have objects and children that are - // attached to them declaratively ... - if (!isPrimitive) { - removeRecursive(child.__r3f?.objects, child, shouldDispose); - removeRecursive(child.children, child, shouldDispose); - } - - // Remove references - if (child.__r3f) { - delete ((child as Partial).__r3f as Partial).root; - delete ((child as Partial).__r3f as Partial).objects; - delete ((child as Partial).__r3f as Partial).handlers; - delete ((child as Partial).__r3f as Partial).memoizedProps; - if (!isPrimitive) delete (child as Partial).__r3f; - } - - // Dispose item whenever the reconciler feels like it - if (shouldDispose && child.type !== "Scene") { - // scheduleCallback(idlePriority, () => { - try { - log("three", "dispose", child); - child.dispose?.(); - dispose(child); - } catch (e) { - /* ... */ - } - // }); - } - - invalidateInstance(parentInstance); - } - } - - function switchInstance(instance: Instance, type: string, newProps: InstanceProps) { - const parent = instance.__r3f?.parent; - if (!parent) return; - - const newInstance = createInstance(type, newProps, instance.__r3f.root); - - // https://github.com/pmndrs/react-three-fiber/issues/1348 - // When args change the instance has to be re-constructed, which then - // forces r3f to re-parent the children and non-scene objects - // This can not include primitives, which should not have declarative children - if (type !== "primitive" && instance.children) { - instance.children.forEach(child => appendChild(newInstance, child)); - instance.children = []; - } - - instance.__r3f.objects.forEach(child => appendChild(newInstance, child)); - instance.__r3f.objects = []; - - removeChild(parent, instance); - appendChild(parent, newInstance); - - // This evil hack switches the react-internal fiber node - // https://github.com/facebook/react/issues/14983 - // https://github.com/facebook/react/pull/15021 - // [fiber, fiber.alternate].forEach((fiber) => { - // if (fiber !== null) { - // fiber.stateNode = newInstance; - // if (fiber.ref) { - // if (typeof fiber.ref === "function") - // (fiber as unknown as any).ref(newInstance); - // else (fiber.ref as Reconciler.RefObject).current = newInstance; - // } - // } - // }); - } - - return { - applyProps, - applyProp, - appendChild, - createInstance, - switchInstance, - insertBefore, - removeChild, - removeRecursive, - attach - }; -} -export type ThreeRenderer = ReturnType; - -export { prepare, createThreeRenderer, extend }; diff --git a/src/core/store.ts b/src/core/store.ts deleted file mode 100644 index 12e0347..0000000 --- a/src/core/store.ts +++ /dev/null @@ -1,470 +0,0 @@ -import * as THREE from "three"; -import * as ReactThreeFiber from "../three-types"; -import create, { - GetState, - SetState, - StoreApi as UseStore, -} from "zustand/vanilla"; -import { prepare, Instance, InstanceProps } from "./renderer"; -import { - DomEvent, - EventManager, - PointerCaptureTarget, - ThreeEvent, -} from "./events"; -import { calculateDpr } from "./utils"; -import { createContext } from "solid-js"; -import { subscribeWithSelector } from "zustand/middleware"; - -export interface Intersection extends THREE.Intersection { - eventObject: THREE.Object3D; -} - -export type Subscription = { - ref: RenderCallback; - priority: number; -}; - -export type Dpr = number | [min: number, max: number]; -export type Size = { width: number; height: number }; -export type Viewport = Size & { - initialDpr: number; - dpr: number; - factor: number; - distance: number; - aspect: number; -}; - -export type Camera = THREE.OrthographicCamera | THREE.PerspectiveCamera; -export type Raycaster = THREE.Raycaster & { - enabled: boolean; - filter?: FilterFunction; - computeOffsets?: ComputeOffsetsFunction; -}; - -export type RenderCallback = (state: RootState, delta: number) => void; - -export type Performance = { - current: number; - min: number; - max: number; - debounce: number; - regress: () => void; -}; - -export type Renderer = { - render: (scene: THREE.Scene, camera: THREE.Camera) => any; -}; - -export const isRenderer = (def: Renderer) => !!def?.render; -export const isOrthographicCamera = ( - def: THREE.Camera -): def is THREE.OrthographicCamera => - def && (def as THREE.OrthographicCamera).isOrthographicCamera; - -export type InternalState = { - active: boolean; - priority: number; - frames: number; - lastProps: StoreProps; - lastEvent: { current: DomEvent | null }; - - interaction: THREE.Object3D[]; - hovered: Map>; - subscribers: Subscription[]; - capturedMap: Map>; - initialClick: [x: number, y: number]; - initialHits: THREE.Object3D[]; - - xr: { connect: () => void; disconnect: () => void }; - subscribe: (callback: RenderCallback, priority?: number) => () => void; -}; - -export type RootState = { - gl: THREE.WebGLRenderer; - scene: THREE.Scene; - camera: Camera & { manual?: boolean }; - controls: THREE.EventDispatcher | null; - raycaster: Raycaster; - mouse: THREE.Vector2; - clock: THREE.Clock; - - linear: boolean; - flat: boolean; - frameloop: "always" | "demand" | "never"; - performance: Performance; - - size: Size; - viewport: Viewport & { - getCurrentViewport: ( - camera?: Camera, - target?: THREE.Vector3, - size?: Size - ) => Omit; - }; - - set: SetState; - get: GetState; - invalidate: () => void; - advance: (timestamp: number, runGlobalEffects?: boolean) => void; - setSize: (width: number, height: number) => void; - setDpr: (dpr: Dpr) => void; - setFrameloop: (frameloop?: "always" | "demand" | "never") => void; - onPointerMissed?: (event: MouseEvent) => void; - - events: EventManager; - internal: InternalState; -}; - -export type FilterFunction = ( - items: THREE.Intersection[], - state: RootState -) => THREE.Intersection[]; -export type ComputeOffsetsFunction = ( - event: any, - state: RootState -) => { offsetX: number; offsetY: number }; - -export type StoreProps = { - gl: THREE.WebGLRenderer; - size: Size; - shadows?: boolean | Partial; - linear?: boolean; - flat?: boolean; - orthographic?: boolean; - frameloop?: "always" | "demand" | "never"; - performance?: Partial>; - dpr?: Dpr; - clock?: THREE.Clock; - raycaster?: Partial; - camera?: ( - | Camera - | Partial< - ReactThreeFiber.Object3DNode & - ReactThreeFiber.Object3DNode< - THREE.PerspectiveCamera, - typeof THREE.PerspectiveCamera - > & - ReactThreeFiber.Object3DNode< - THREE.OrthographicCamera, - typeof THREE.OrthographicCamera - > - > - ) & { manual?: boolean }; - onPointerMissed?: (event: MouseEvent) => void; -}; - -export type ApplyProps = (instance: Instance, newProps: InstanceProps) => void; - -const ThreeContext = createContext>(null!); - -const createThreeStore = ( - applyProps: ApplyProps, - invalidate: (state?: RootState) => void, - advance: ( - timestamp: number, - runGlobalEffects?: boolean, - state?: RootState - ) => void, - props: StoreProps -): UseStore => { - const { - gl, - size, - shadows = false, - linear = false, - flat = false, - orthographic = false, - frameloop = "always", - dpr = [1, 2], - performance, - clock = new THREE.Clock(), - raycaster: raycastOptions, - camera: cameraOptions, - onPointerMissed, - } = props; - - // Set shadowmap - if (shadows) { - gl.shadowMap.enabled = true; - if (typeof shadows === "object") Object.assign(gl.shadowMap, shadows); - else gl.shadowMap.type = THREE.PCFSoftShadowMap; - } - - // Set color preferences - if (linear) gl.outputEncoding = THREE.LinearEncoding; - if (flat) gl.toneMapping = THREE.NoToneMapping; - - // clock.elapsedTime is updated using advance(timestamp) - if (frameloop === "never") { - clock.stop(); - clock.elapsedTime = 0; - } - - const rootState = create( - subscribeWithSelector((set, get) => { - // Create custom raycaster - const raycaster = new THREE.Raycaster() as Raycaster; - const { params, ...options } = raycastOptions || {}; - applyProps(raycaster as any, { - enabled: true, - ...options, - params: { ...raycaster.params, ...params }, - }); - - // Create default camera - const isCamera = cameraOptions instanceof THREE.Camera; - const camera = isCamera - ? (cameraOptions as Camera) - : orthographic - ? new THREE.OrthographicCamera(0, 0, 0, 0, 0.1, 1000) - : new THREE.PerspectiveCamera(75, 0, 0.1, 1000); - if (!isCamera) { - camera.position.z = 5; - if (cameraOptions) applyProps(camera as any, cameraOptions as any); - // Always look at center by default - if (!cameraOptions?.rotation) camera.lookAt(0, 0, 0); - } - - const initialDpr = calculateDpr(dpr); - - const position = new THREE.Vector3(); - const defaultTarget = new THREE.Vector3(); - const tempTarget = new THREE.Vector3(); - function getCurrentViewport( - camera: Camera = get().camera, - target: - | THREE.Vector3 - | Parameters = defaultTarget, - size: Size = get().size - ) { - const { width, height } = size; - const aspect = width / height; - if (target instanceof THREE.Vector3) tempTarget.copy(target); - else tempTarget.set(...target); - const distance = camera - .getWorldPosition(position) - .distanceTo(tempTarget); - if (isOrthographicCamera(camera)) { - return { - width: width / camera.zoom, - height: height / camera.zoom, - factor: 1, - distance, - aspect, - }; - } else { - const fov = (camera.fov * Math.PI) / 180; // convert vertical fov to radians - const h = 2 * Math.tan(fov / 2) * distance; // visible height - const w = h * (width / height); - return { width: w, height: h, factor: width / w, distance, aspect }; - } - } - - let performanceTimeout: ReturnType | undefined = - undefined; - const setPerformanceCurrent = (current: number) => - set((state) => ({ performance: { ...state.performance, current } })); - - // Handle frame behavior in WebXR - const handleXRFrame = (timestamp: number) => { - const state = get(); - if (state.frameloop === "never") return; - - advance(timestamp, true); - }; - - // Toggle render switching on session - const handleSessionChange = () => { - gl.xr.enabled = gl.xr.isPresenting; - gl.setAnimationLoop(gl.xr.isPresenting ? handleXRFrame : null); - - // If exiting session, request frame - if (!gl.xr.isPresenting) invalidate(get()); - }; - - // WebXR session manager - const xr = { - connect() { - gl.xr.addEventListener("sessionstart", handleSessionChange); - gl.xr.addEventListener("sessionend", handleSessionChange); - }, - disconnect() { - gl.xr.removeEventListener("sessionstart", handleSessionChange); - gl.xr.removeEventListener("sessionend", handleSessionChange); - }, - }; - - // Subscribe to WebXR session events - if (gl.xr) xr.connect(); - - return { - gl, - - set, - get, - invalidate: () => invalidate(get()), - advance: (timestamp: number, runGlobalEffects?: boolean) => - advance(timestamp, runGlobalEffects, get()), - - linear, - flat, - scene: prepare(new THREE.Scene()), - camera, - controls: null, - raycaster, - clock, - mouse: new THREE.Vector2(), - - frameloop, - onPointerMissed, - - performance: { - current: 1, - min: 0.5, - max: 1, - debounce: 200, - ...performance, - regress: () => { - const state = get(); - // Clear timeout - if (performanceTimeout) clearTimeout(performanceTimeout); - // Set lower bound performance - if (state.performance.current !== state.performance.min) - setPerformanceCurrent(state.performance.min); - // Go back to upper bound performance after a while unless something regresses meanwhile - performanceTimeout = setTimeout( - () => setPerformanceCurrent(get().performance.max), - state.performance.debounce - ); - }, - }, - - size: { width: 800, height: 600 }, - viewport: { - initialDpr, - dpr: initialDpr, - width: 0, - height: 0, - aspect: 0, - distance: 0, - factor: 0, - getCurrentViewport, - }, - - setSize: (width: number, height: number) => { - const size = { width, height }; - set((state) => ({ - size, - viewport: { - ...state.viewport, - ...getCurrentViewport(camera, defaultTarget, size), - }, - })); - }, - setDpr: (dpr: Dpr) => - set((state) => ({ - viewport: { ...state.viewport, dpr: calculateDpr(dpr) }, - })), - - setFrameloop: (frameloop: "always" | "demand" | "never" = "always") => - set(() => ({ frameloop })), - - events: { connected: false }, - internal: { - active: false, - priority: 0, - frames: 0, - lastProps: props, - lastEvent: { current: null }, - - interaction: [], - hovered: new Map>(), - subscribers: [], - initialClick: [0, 0], - initialHits: [], - capturedMap: new Map(), - - xr, - subscribe: (ref: RenderCallback, priority = 0) => { - set(({ internal }) => ({ - internal: { - ...internal, - // If this subscription was given a priority, it takes rendering into its own hands - // For that reason we switch off automatic rendering and increase the manual flag - // As long as this flag is positive there can be no internal rendering at all - // because there could be multiple render subscriptions - priority: internal.priority + (priority > 0 ? 1 : 0), - // Register subscriber and sort layers from lowest to highest, meaning, - // highest priority renders last (on top of the other frames) - subscribers: [...internal.subscribers, { ref, priority }].sort( - (a, b) => a.priority - b.priority - ), - }, - })); - return () => { - set(({ internal }) => ({ - internal: { - ...internal, - // Decrease manual flag if this subscription had a priority - priority: internal.priority - (priority > 0 ? 1 : 0), - // Remove subscriber from list - subscribers: internal.subscribers.filter( - (s) => s.ref !== ref - ), - }, - })); - }; - }, - }, - }; - }) - ); - - const state = rootState.getState(); - - // Resize camera and renderer on changes to size and pixelratio - let oldSize = state.size; - let oldDpr = state.viewport.dpr; - rootState.subscribe(() => { - const { camera, size, viewport, internal } = rootState.getState(); - if (size !== oldSize || viewport.dpr !== oldDpr) { - // https://github.com/pmndrs/react-three-fiber/issues/92 - // Do not mess with the camera if it belongs to the user - if ( - !camera.manual && - !(internal.lastProps.camera instanceof THREE.Camera) - ) { - if (isOrthographicCamera(camera)) { - camera.left = size.width / -2; - camera.right = size.width / 2; - camera.top = size.height / 2; - camera.bottom = size.height / -2; - } else { - camera.aspect = size.width / size.height; - } - camera.updateProjectionMatrix(); - // https://github.com/pmndrs/react-three-fiber/issues/178 - // Update matrix world since the renderer is a frame late - camera.updateMatrixWorld(); - } - // Update renderer - gl.setPixelRatio(viewport.dpr); - gl.setSize(size.width, size.height); - - oldSize = size; - oldDpr = viewport.dpr; - } - }); - - // Update size - if (size) state.setSize(size.width, size.height); - - // Invalidate on any change - rootState.subscribe((state) => invalidate(state)); - - // Return root state - return rootState; -}; - -export { createThreeStore, ThreeContext }; diff --git a/src/core/utils.ts b/src/core/utils.ts deleted file mode 100644 index 06e652b..0000000 --- a/src/core/utils.ts +++ /dev/null @@ -1,379 +0,0 @@ -import * as THREE from "three"; -import { StoreApi as UseStore } from "zustand/vanilla"; -import { log } from "../solid"; -import { EventHandlers } from "./events"; -import { AttachType, Instance, InstanceProps, LocalState } from "./renderer"; -import { Dpr, RootState } from "./store"; - -export const DEFAULT = "__default"; - -export type DiffSet = { - changes: [key: string, value: unknown, isEvent: boolean, keys: string[]][]; -}; - -export const isDiffSet = (def: any): def is DiffSet => def && !!(def as DiffSet).changes; -export type ClassConstructor = { new (): void }; - -export type ObjectMap = { - nodes: { [name: string]: THREE.Object3D }; - materials: { [name: string]: THREE.Material }; -}; - -export function calculateDpr(dpr: Dpr) { - return Array.isArray(dpr) ? Math.min(Math.max(dpr[0], window.devicePixelRatio), dpr[1]) : dpr; -} - -/** - * Picks or omits keys from an object - * `omit` will filter out keys, and otherwise cherry-pick them. - */ -export function filterKeys< - TObj extends { [key: string]: any }, - TOmit extends boolean, - TKey extends keyof TObj ->( - obj: TObj, - omit: TOmit, - ...keys: TKey[] -): TOmit extends true ? Omit : Pick { - const keysToSelect = new Set(keys); - - return Object.entries(obj).reduce((acc, [key, value]) => { - const shouldInclude = !omit; - - if (keysToSelect.has(key as TKey) === shouldInclude) { - acc[key] = value; - } - - return acc; - }, {} as any); -} - -/** - * Clones an object and cherry-picks keys. - */ -export const pick = (obj: Partial, keys: Array) => - filterKeys, false, keyof TObj>(obj, false, ...keys); - -/** - * Clones an object and prunes or omits keys. - */ -export const omit = (obj: Partial, keys: Array) => - filterKeys, true, keyof TObj>(obj, true, ...keys); - -// A collection of compare functions -export const is = { - obj: (a: any) => a === Object(a) && !is.arr(a) && typeof a !== "function", - fun: (a: any): a is Function => typeof a === "function", - str: (a: any): a is string => typeof a === "string", - num: (a: any): a is number => typeof a === "number", - und: (a: any) => a === void 0, - arr: (a: any) => Array.isArray(a), - equ(a: any, b: any) { - // Wrong type or one of the two undefined, doesn't match - if (typeof a !== typeof b || !!a !== !!b) return false; - // Atomic, just compare a against b - if (is.str(a) || is.num(a) || is.obj(a)) return a === b; - // Array, shallow compare first to see if it's a match - if (is.arr(a) && a == b) return true; - // Last resort, go through keys - let i; - for (i in a) if (!(i in b)) return false; - for (i in b) if (a[i] !== b[i]) return false; - return is.und(i) ? a === b : true; - } -}; - -// Collects nodes and materials from a THREE.Object3D -export function buildGraph(object: THREE.Object3D) { - const data: ObjectMap = { nodes: {}, materials: {} }; - if (object) { - object.traverse((obj: any) => { - if (obj.name) data.nodes[obj.name] = obj; - if (obj.material && !data.materials[obj.material.name]) - data.materials[obj.material.name] = obj.material; - }); - } - return data; -} - -// Disposes an object and all its properties -export function dispose void; type?: string; [key: string]: any }>( - obj: TObj -) { - if (obj.dispose && obj.type !== "Scene") obj.dispose(); - for (const p in obj) { - (p as any).dispose?.(); - delete obj[p]; - } -} - -// Each object in the scene carries a small LocalState descriptor -export function prepare(object: T, state?: Partial) { - const instance = object as unknown as Instance; - if (state?.primitive || !instance.__r3f) { - instance.__r3f = { - root: null as unknown as UseStore, - memoizedProps: {}, - eventCount: 0, - handlers: {}, - objects: [], - parent: null, - ...state - }; - } - return object; -} - -function resolve(instance: Instance, key: string) { - let target = instance; - if (key.includes("-")) { - const entries = key.split("-"); - const last = entries.pop() as string; - target = entries.reduce((acc, key) => acc[key], instance); - return { target, key: last }; - } else return { target, key }; -} - -export function attach(parent: Instance, child: Instance, type: AttachType) { - log("three", "attach", parent, child, type); - if (is.str(type)) { - const { target, key } = resolve(parent, type); - parent.__r3f.previousAttach = target[key]; - - target[key] = child; - } else if (is.arr(type)) { - const [attach] = type; - if (is.str(attach)) parent[attach](child); - else if (is.fun(attach)) attach(parent, child); - } -} - -export function detach(parent: Instance, child: Instance, type: AttachType) { - log("three", "detach", parent, child, type); - if (is.str(type)) { - const { target, key } = resolve(parent, type); - if (child === parent.__r3f.previousAttach) { - return; - } - - target[key] = parent.__r3f.previousAttach; - } else if (is.arr(type)) { - const [, detach] = type; - if (is.str(detach)) parent[detach](child); - else if (is.fun(detach)) detach(parent, child); - } -} - -// Shallow check arrays, but check objects atomically -function checkShallow(a: any, b: any) { - if (is.arr(a) && is.equ(a, b)) return true; - if (a === b) return true; - return false; -} - -// This function prepares a set of changes to be applied to the instance -export function diffProps( - instance: Instance, - { children: cN, key: kN, ref: rN, ...props }: InstanceProps, - { children: cP, key: kP, ref: rP, ...previous }: InstanceProps = {}, - remove = false -): DiffSet { - const localState = (instance?.__r3f ?? {}) as LocalState; - const entries = Object.entries(props); - const changes: [key: string, value: unknown, isEvent: boolean, keys: string[]][] = []; - - // Catch removed props, prepend them so they can be reset or removed - if (remove) { - const previousKeys = Object.keys(previous); - for (let i = 0; i < previousKeys.length; i++) { - if (!props.hasOwnProperty(previousKeys[i])) - entries.unshift([previousKeys[i], DEFAULT + "remove"]); - } - } - - entries.forEach(([key, value]) => { - // Bail out on primitive object - if (instance.__r3f?.primitive && key === "object") return; - // When props match bail out - if (checkShallow(value, previous[key])) return; - // Collect handlers and bail out - if (/^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/.test(key)) - return changes.push([key, value, true, []]); - // Split dashed props - let entries: string[] = []; - if (key.includes("-")) entries = key.split("-"); - changes.push([key, value, false, entries]); - }); - - // const memoized: { [key: string]: any } = { ...props }; - // if (localState.memoizedProps && localState.memoizedProps.args) - // memoized.args = localState.memoizedProps.args; - // if (localState.memoizedProps && localState.memoizedProps.attach) - // memoized.attach = localState.memoizedProps.attach; - - return { changes }; -} - -// This function applies a set of changes to the instance -export function applyProps(instance: Instance, data: InstanceProps | DiffSet) { - // Filter equals, events and reserved props - const localState = (instance?.__r3f ?? {}) as LocalState; - const root = localState.root; - const rootState: RootState = root?.getState() ?? ({} as unknown as RootState); - const { changes } = isDiffSet(data) ? data : diffProps(instance, data); - const prevHandlers = localState.eventCount; - - // Prepare memoized props - // if (instance.__r3f) instance.__r3f.memoizedProps = memoized; - - changes.forEach(change => { - applyProp(instance, change, localState, rootState); - }); - - if ( - localState.parent && - rootState.internal && - instance.raycast && - prevHandlers !== localState.eventCount - ) { - // Pre-emptively remove the instance from the interaction manager - const index = rootState.internal.interaction.indexOf(instance as unknown as THREE.Object3D); - if (index > -1) rootState.internal.interaction.splice(index, 1); - // Add the instance to the interaction manager only when it has handlers - if (localState.eventCount) - rootState.internal.interaction.push(instance as unknown as THREE.Object3D); - } - - // Call the update lifecycle when it is being updated, but only when it is part of the scene - if (changes.length && instance.parent) updateInstance(instance); -} - -export function applyProp( - instance: Instance, - [key, value, isEvent, keys]: [key: string, value: unknown, isEvent: boolean, keys: string[]], - localState: LocalState = instance?.__r3f ?? ({} as unknown as LocalState), - rootState: RootState = localState.root?.getState() -) { - let currentInstance = instance; - let targetProp = currentInstance[key]; - - // Revolve dashed props - if (keys.length) { - targetProp = keys.reduce((acc, key) => acc[key], instance); - // If the target is atomic, it forces us to switch the root - if (!(targetProp && targetProp.set)) { - const [name, ...reverseEntries] = keys.reverse(); - currentInstance = reverseEntries.reverse().reduce((acc, key) => acc[key], instance); - key = name; - } - } - - // https://github.com/mrdoob/three.js/issues/21209 - // HMR/fast-refresh relies on the ability to cancel out props, but threejs - // has no means to do this. Hence we curate a small collection of value-classes - // with their respective constructor/set arguments - // For removed props, try to set default values, if possible - if (value === DEFAULT + "remove") { - if (targetProp && targetProp.constructor) { - // use the prop constructor to find the default it should be - value = new targetProp.constructor(); - } else if (currentInstance.constructor) { - // create a blank slate of the instance and copy the particular parameter. - // @ts-ignore - const defaultClassCall = new currentInstance.constructor( - currentInstance.__r3f.memoizedProps.args - ); - value = defaultClassCall[targetProp]; - // destory the instance - if (defaultClassCall.dispose) defaultClassCall.dispose(); - // instance does not have constructor, just set it to 0 - } else { - value = 0; - } - } - - // Deal with pointer events ... - if (isEvent) { - if (value) localState.handlers[key as keyof EventHandlers] = value as any; - else delete localState.handlers[key as keyof EventHandlers]; - localState.eventCount = Object.keys(localState.handlers).length; - } - - // Special treatment for objects with support for set/copy, and layers - else if ( - targetProp && - targetProp.set && - (targetProp.copy || targetProp instanceof THREE.Layers) - ) { - // If value is an array - if (Array.isArray(value)) { - if (targetProp.fromArray) targetProp.fromArray(value); - else targetProp.set(...value); - } - - // Test again target.copy(class) next ... - else if ( - targetProp.copy && - value && - (value as ClassConstructor).constructor && - targetProp.constructor.name === (value as ClassConstructor).constructor.name - ) { - targetProp.copy(value); - } - - // If nothing else fits, just set the single value, ignore undefined - // https://github.com/pmndrs/react-three-fiber/issues/274 - else if (value !== undefined) { - const isColor = targetProp instanceof THREE.Color; - // Allow setting array scalars - if (!isColor && targetProp.setScalar) targetProp.setScalar(value); - // Layers have no copy function, we must therefore copy the mask property - else if (targetProp instanceof THREE.Layers && value instanceof THREE.Layers) - targetProp.mask = value.mask; - // Otherwise just set ... - else targetProp.set(value); - // Auto-convert sRGB colors, for now ... - // https://github.com/pmndrs/react-three-fiber/issues/344 - if (!rootState.linear && isColor) targetProp.convertSRGBToLinear(); - } - // Else, just overwrite the value - } else { - currentInstance[key] = value; - // Auto-convert sRGB textures, for now ... - // https://github.com/pmndrs/react-three-fiber/issues/344 - if (!rootState.linear && currentInstance[key] instanceof THREE.Texture) { - currentInstance[key].encoding = THREE.sRGBEncoding; - } - } - - if ( - // localState.parent && - rootState.internal && - instance.raycast - // prevHandlers !== localState.eventCount - ) { - // Pre-emptively remove the instance from the interaction manager - const index = rootState.internal.interaction.indexOf(instance as unknown as THREE.Object3D); - if (index > -1) rootState.internal.interaction.splice(index, 1); - // Add the instance to the interaction manager only when it has handlers - if (localState.eventCount) - rootState.internal.interaction.push(instance as unknown as THREE.Object3D); - } - - invalidateInstance(instance); - return { __return: instance, key, value }; -} - -export function invalidateInstance(instance: Instance) { - const state = instance.__r3f?.root?.getState?.(); - if (state && state.internal.frames === 0) state.invalidate(); -} - -export function updateInstance(instance: Instance) { - instance.onUpdate?.(instance); -} - -export function toFirstUpper(string: string) { - return `${string.charAt(0).toUpperCase()}${string.slice(1)}`; -} diff --git a/src/create-events.ts b/src/create-events.ts new file mode 100644 index 0000000..a564cbf --- /dev/null +++ b/src/create-events.ts @@ -0,0 +1,228 @@ +import { onCleanup } from "solid-js"; +import { Intersection, Object3D } from "three"; +import { S3 } from "./"; +import { $S3C } from "./augment"; +import { isAugmentedElement } from "./utils/is-augmented-element"; +import { removeElementFromArray } from "./utils/remove-element-from-array"; + +/** + * Checks if a given string is a valid event type within the system. + * + * @param type - The type of the event to check. + * @returns `true` if the type is a recognized `EventType`, otherwise `false`. + */ +export const isEventType = (type: string): type is S3.EventName => + /^on(Pointer|Click|DoubleClick|ContextMenu|Wheel|Mouse)/.test(type); + +/** + * Initializes and manages event handling for `AugmentedElement`. + * + * @param context + * @returns An object containing `addEventListener`-function and `eventRegistry`-object. + */ +export const createEvents = (context: S3.Context) => { + /** + * An object keeping track of all the `AugmentedElement` that are listening to a specific event. + */ + const eventRegistry = { + onMouseMove: [] as S3.Instance[], + onMouseUp: [] as S3.Instance[], + onMouseDown: [] as S3.Instance[], + onPointerMove: [] as S3.Instance[], + onPointerUp: [] as S3.Instance[], + onPointerDown: [] as S3.Instance[], + onWheel: [] as S3.Instance[], + onClick: [] as S3.Instance[], + onDoubleClick: [] as S3.Instance[], + } as const; + + // Creates a `ThreeEvent` from the current `MouseEvent` | `WheelEvent`. + const createThreeEvent = ( + nativeEvent: TEvent, + ): S3.Event => { + const event = { + ...nativeEvent, + nativeEvent, + stopped: false, + stopPropagation: () => (event.stopped = true), + }; + return event; + }; + + // Performs a raycast from the camera through the mouse position to find intersecting 3D objects. + const raycast = ( + nativeEvent: TNativeEvent, + type: keyof typeof eventRegistry, + ): Intersection>[] => { + context.setPointer(pointer => { + pointer.x = (nativeEvent.offsetX / window.innerWidth) * 2 - 1; + pointer.y = -(nativeEvent.offsetY / window.innerHeight) * 2 + 1; + return pointer; + }); + + context.raycaster.setFromCamera(context.pointer, context.camera); + + const duplicates = new Set>(); + + // NOTE: we currently perform a recursive intersection-test just as r3f. + // this method performs a lot of duplicate intersection-tests. + const intersections: Intersection>[] = context.raycaster.intersectObjects( + eventRegistry[type], + true, + ); + + return ( + intersections + // sort by distance + .sort((a, b) => a.distance - b.distance) + // remove duplicates + .filter(({ object }) => { + if (duplicates.has(object)) return false; + duplicates.add(object); + return true; + }) + ); + }; + + // Propagates an event down through the ancestors of a given `Object3D` in a scene graph, + // calling the event handler for each ancestor as long as the event has not been marked as stopped. + const bubbleDown = < + TNativeEvent extends MouseEvent | WheelEvent, + TEvent extends S3.Event, + >( + element: S3.Instance, + type: S3.EventName, + event: TEvent, + ) => { + let node: Object3D | null = element.parent; + while (node) { + // If event has been stopped with event.stopPropagation() we break out. + if (event.stopped) break; + // If node is an AugmentedElement we call the type's event-handler if it is defined. + if (isAugmentedElement(node)) { + node[$S3C].props[type]?.(event); + } + // We bubble a layer down. + node = node.parent; + } + }; + + // A handler-factory for `on{Pointer|Mouse}Move` events. + // This handler manages also its derived events: + // - `on{Pointer|Mouse}Enter` + // - `on{Pointer|Mouse}Leave` + const createMoveHandler = (type: "Pointer" | "Mouse") => (nativeEvent: MouseEvent) => { + const moveEvent = createThreeEvent(nativeEvent); + const enterEvent = createThreeEvent(nativeEvent); + + let staleIntersects = new Set(priorIntersects[type]); + + for (const intersection of raycast(nativeEvent, `on${type}Move`)) { + const props = intersection.object[$S3C].props; + + if (!enterEvent.stopped && !priorIntersects[type].has(intersection.object)) { + props[`on${type}Enter`]?.(enterEvent); + bubbleDown(intersection.object, `on${type}Enter`, enterEvent); + } + + if (!moveEvent.stopped) { + props[`on${type}Move`]?.(moveEvent); + bubbleDown(intersection.object, `on${type}Move`, moveEvent); + } + + staleIntersects.delete(intersection.object); + priorIntersects[type].add(intersection.object); + + if (moveEvent.stopped && enterEvent.stopped) break; + } + + if (priorMoveEvents[type]) { + const leaveEvent = createThreeEvent(priorMoveEvents[type]!); + + for (const object of staleIntersects.values()) { + priorIntersects[type].delete(object); + + if (!leaveEvent.stopped) { + const props = object[$S3C].props; + props[`on${type}Leave`]?.(leaveEvent); + bubbleDown(object, `on${type}Leave`, leaveEvent); + } + } + } + + priorMoveEvents[type] = nativeEvent; + }; + const priorIntersects = { + Mouse: new Set>(), + Pointer: new Set>(), + }; + const priorMoveEvents = { + Mouse: undefined as undefined | MouseEvent, + Pointer: undefined as undefined | MouseEvent, + }; + + // Creates a generic event handler for events other than `move` and its derived events. + const createEventHandler = + (type: keyof typeof eventRegistry) => + (nativeEvent: TEvent) => { + const event = createThreeEvent(nativeEvent); + for (const { object } of raycast(nativeEvent, type)) { + object[$S3C].props?.[type]?.(event); + bubbleDown(object, type, event); + if (event.stopped) break; + } + }; + + // Register event handlers to the canvas + context.canvas.addEventListener("mousemove", createMoveHandler("Mouse")); + context.canvas.addEventListener("pointermove", createMoveHandler("Pointer")); + + context.canvas.addEventListener("mousedown", createEventHandler("onMouseDown")); + context.canvas.addEventListener("pointerdown", createEventHandler("onPointerDown")); + + context.canvas.addEventListener("mouseup", createEventHandler("onMouseUp")); + context.canvas.addEventListener("pointerup", createEventHandler("onPointerUp")); + + context.canvas.addEventListener("wheel", createEventHandler("onWheel"), { passive: true }); + context.canvas.addEventListener("click", createEventHandler("onClick")); + context.canvas.addEventListener("dblclick", createEventHandler("onDoubleClick")); + + /** + * Registers an `AugmentedElement` with the event handling system. + * + * @param object - The 3D object to register. + * @param type - The type of event the object should listen for. + */ + const addEventListener = (object: S3.Instance, type: S3.EventName) => { + const isDerivedEvent = type.includes("Enter") || type.includes("Leave"); + const isPointerEvent = type.includes("Pointer"); + + // Derived events are handled by `on{Pointer|Mouse}Move` + const derivedType = isDerivedEvent ? `on${isPointerEvent ? "Pointer" : "Mouse"}Move` : type; + + if (!eventRegistry[derivedType].find(value => value === object)) { + eventRegistry[derivedType].push(object); + } + + onCleanup(() => { + // NOTE: When a move/derived event-handler cleans up, it only removes the object from the registry + // if the object is currently not listening to another move/derived-event. + if (derivedType.includes("Move")) { + const props = object[$S3C].props; + if (isPointerEvent) { + if ("onPointerMove" in props || "onPointerEnter" in props || "onPointerLeave" in props) { + return; + } + } else { + if ("onMouseMove" in props || "onMouseEnter" in props || "onMouseLeave" in props) { + return; + } + } + } + + removeElementFromArray(eventRegistry[type], object); + }); + }; + + return { addEventListener, eventRegistry }; +}; diff --git a/src/create-three.tsx b/src/create-three.tsx new file mode 100644 index 0000000..5e104cc --- /dev/null +++ b/src/create-three.tsx @@ -0,0 +1,355 @@ +import { + children, + createEffect, + createMemo, + createRenderEffect, + createSignal, + mergeProps, + onCleanup, +} from "solid-js"; +import { + ACESFilmicToneMapping, + BasicShadowMap, + Camera, + NoToneMapping, + OrthographicCamera, + PCFShadowMap, + PCFSoftShadowMap, + PerspectiveCamera, + Raycaster, + Scene, + VSMShadowMap, + Vector2, + WebGLRenderer, +} from "three"; +import { S3 } from "./"; +import { augment } from "./augment"; +import { CanvasProps } from "./canvas"; +import { createEvents } from "./create-events"; +import { AugmentedStack } from "./data-structure/augmented-stack"; +import { frameContext, threeContext } from "./hooks"; +import { canvasPropsContext, eventContext } from "./internal-context"; +import { manageProps, manageSceneGraph } from "./props"; +import { Context } from "./types"; +import { defaultProps } from "./utils/default-props"; +import { removeElementFromArray } from "./utils/remove-element-from-array"; +import { withMultiContexts } from "./utils/with-context"; + +/** + * Creates and manages a `solid-three` scene. It initializes necessary objects like + * camera, renderer, raycaster, and scene, manages the scene graph, setups up an event system + * and rendering loop based on the provided properties. + * + * @param canvas - The HTML canvas element on which Three.js will render. + * @param props - Configuration properties. + * @returns - an `S3.Context` with additional properties including eventRegistry and addFrameListener. + */ +export function createThree(canvas: HTMLCanvasElement, props: CanvasProps) { + const canvasProps = defaultProps(props, { frameloop: "always" }); + + /**********************************************************************************/ + /* */ + /* Frame Listeners */ + /* */ + /**********************************************************************************/ + + type FrameListener = (context: S3.Context, delta: number, frame?: XRFrame) => void; + + const frameListeners: FrameListener[] = []; + // Adds a callback to be called on each frame + function addFrameListener(callback: FrameListener) { + frameListeners.push(callback); + const cleanup = () => removeElementFromArray(frameListeners, callback); + onCleanup(cleanup); + return cleanup; + } + + /**********************************************************************************/ + /* */ + /* XR */ + /* */ + /**********************************************************************************/ + + // Handle frame behavior in WebXR + const handleXRFrame: XRFrameRequestCallback = (timestamp: number, frame?: XRFrame) => { + if (canvasProps.frameloop === "never") return; + render(timestamp, frame); + }; + // Toggle render switching on session + function handleSessionChange() { + context.gl.xr.enabled = context.gl.xr.isPresenting; + context.gl.xr.setAnimationLoop(context.gl.xr.isPresenting ? handleXRFrame : null); + } + // WebXR session-manager + const xr = { + connect() { + context.gl.xr.addEventListener("sessionstart", handleSessionChange); + context.gl.xr.addEventListener("sessionend", handleSessionChange); + }, + disconnect() { + context.gl.xr.removeEventListener("sessionstart", handleSessionChange); + context.gl.xr.removeEventListener("sessionend", handleSessionChange); + }, + }; + + /**********************************************************************************/ + /* */ + /* Render */ + /* */ + /**********************************************************************************/ + + let isRenderPending = false; + function render(timestamp: number, frame?: XRFrame) { + isRenderPending = false; + context.gl.render(context.scene, context.camera); + frameListeners.forEach(listener => listener(context, timestamp, frame)); + } + function requestRender() { + if (isRenderPending) return; + isRenderPending = true; + requestAnimationFrame(render); + } + + /**********************************************************************************/ + /* */ + /* Three Context */ + /* */ + /**********************************************************************************/ + + const [pointer, setPointer] = createSignal(new Vector2(), { equals: false }); + const cameraStack = new AugmentedStack("camera"); + const sceneStack = new AugmentedStack("scene"); + const raycasterStack = new AugmentedStack("raycaster"); + const glStack = new AugmentedStack("gl"); + + const context: Context = { + canvas, + get pointer() { + return pointer(); + }, + setPointer, + render, + requestRender, + xr, + // elements + get camera() { + return cameraStack.peek()!; + }, + setCamera: cameraStack.push.bind(cameraStack), + get scene() { + return sceneStack.peek()!; + }, + setScene: sceneStack.push.bind(sceneStack), + get raycaster() { + return raycasterStack.peek()!; + }, + setRaycaster: raycasterStack.push.bind(raycasterStack), + get gl() { + return glStack.peek()!; + }, + setGl: glStack.push.bind(glStack), + }; + + initializeContext(context, canvasProps); + + /**********************************************************************************/ + /* */ + /* Events */ + /* */ + /**********************************************************************************/ + + // Initialize event-system + const { addEventListener, eventRegistry } = createEvents(context); + + /**********************************************************************************/ + /* */ + /* Scene Graph */ + /* */ + /**********************************************************************************/ + + manageSceneGraph( + context.scene, + children(() => + withMultiContexts( + () => canvasProps.children, + [ + // Dependency injection of all the contexts. + [threeContext, context], + [frameContext, addFrameListener], + [eventContext, addEventListener], + [canvasPropsContext, canvasProps], + ], + ), + ) as any, + ); + + /**********************************************************************************/ + /* */ + /* Render Loop */ + /* */ + /**********************************************************************************/ + + function loop(value: number) { + if (canvasProps.frameloop === "always") { + requestAnimationFrame(loop); + context.render(value); + } + } + createRenderEffect(() => { + if (canvasProps.frameloop === "always") { + requestAnimationFrame(loop); + } + }); + + // Return context merged with `eventRegistry` and `addFrameListeners`` + // This is used in `@solid-three/testing` + return mergeProps(context, { eventRegistry, addFrameListener }); +} + +function initializeContext(context: S3.Context, props: CanvasProps) { + withMultiContexts(() => { + const { camera, scene, gl, raycaster } = createDefaultElements(context, props); + // Set default elements to context + context.setGl(gl); + context.setCamera(camera); + context.setScene(scene); + context.setRaycaster(raycaster); + + // Manage camera + createRenderEffect(() => { + if (!props.camera || props.camera instanceof Camera) return; + manageProps(camera, props.camera); + // NOTE: Manually update camera's matrix with updateMatrixWorld is needed. + // Otherwise casting a ray immediately after start-up will cause the incorrect matrix to be used. + camera().updateMatrixWorld(true); + }); + + // Manage scene + createRenderEffect(() => { + if (!props.scene || props.scene instanceof Scene) return; + manageProps(scene, props.scene); + }); + + // Manage raycaster + createRenderEffect(() => { + if (!props.raycaster || props.raycaster instanceof Raycaster) return; + manageProps(raycaster, props.raycaster); + }); + + // Manage gl + createRenderEffect(() => { + // Set shadow-map + createRenderEffect(() => { + const _gl = gl(); + if (_gl.shadowMap) { + const oldEnabled = _gl.shadowMap.enabled; + const oldType = _gl.shadowMap.type; + _gl.shadowMap.enabled = !!props.shadows; + + if (typeof props.shadows === "boolean") { + _gl.shadowMap.type = PCFSoftShadowMap; + } else if (typeof props.shadows === "string") { + const types = { + basic: BasicShadowMap, + percentage: PCFShadowMap, + soft: PCFSoftShadowMap, + variance: VSMShadowMap, + }; + _gl.shadowMap.type = types[props.shadows] ?? PCFSoftShadowMap; + } else if (typeof props.shadows === "object") { + Object.assign(_gl.shadowMap, props.shadows); + } + + if (oldEnabled !== _gl.shadowMap.enabled || oldType !== _gl.shadowMap.type) + _gl.shadowMap.needsUpdate = true; + } + }); + + createEffect(() => { + const renderer = gl(); + // Connect to xr if property exists + if (renderer.xr) context.xr.connect(); + }); + + // Set color space and tonemapping preferences + const LinearEncoding = 3000; + const sRGBEncoding = 3001; + // Color management and tone-mapping + manageProps(gl, { + get outputEncoding() { + return props.linear ? LinearEncoding : sRGBEncoding; + }, + get toneMapping() { + return props.flat ? NoToneMapping : ACESFilmicToneMapping; + }, + }); + + // Manage props + if (props.gl && !(props.gl instanceof WebGLRenderer)) { + manageProps(gl, props.gl); + } + }); + }, [ + [threeContext, context], + [canvasPropsContext, props], + ]); +} + +/** + * Creates the default elements of the `solid-three` context. + * + * @param canvas - The HTML canvas element to be used for the WebGL renderer. + * @param props - Configuration properties that define specifics such as camera type, + * scene configuration, raycaster parameters, and renderer options. + * @returns - Returns objects providing reactive access to the camera, WebGL renderer, raycaster, + * and scene, allowing these elements to be integrated into the Solid.js reactive system. + */ +function createDefaultElements(context: S3.Context, props: CanvasProps) { + return { + camera: createMemo(() => + augment( + props.camera instanceof Camera + ? (props.camera as OrthographicCamera | PerspectiveCamera) + : props.orthographic + ? new OrthographicCamera() + : new PerspectiveCamera(), + { + get props() { + return props.camera || {}; + }, + }, + ), + ), + scene: createMemo(() => + augment(props.scene instanceof Scene ? props.scene : new Scene(), { + get props() { + return props.scene || {}; + }, + }), + ), + raycaster: createMemo(() => + augment(props.raycaster instanceof Raycaster ? props.raycaster : new Raycaster(), { + get props() { + return props.raycaster || {}; + }, + }), + ), + gl: createMemo(() => + augment( + props.gl instanceof WebGLRenderer + ? // props.gl can be a WebGLRenderer provided by the user + props.gl + : typeof props.gl === "function" + ? // or a callback that returns a Renderer + props.gl(context.canvas) + : // if props.gl is not defined we default to a WebGLRenderer + new WebGLRenderer({ canvas: context.canvas }), + { + get props() { + return props.gl || {}; + }, + }, + ), + ), + }; +} diff --git a/src/data-structure/augmented-stack.ts b/src/data-structure/augmented-stack.ts new file mode 100644 index 0000000..e02cfd3 --- /dev/null +++ b/src/data-structure/augmented-stack.ts @@ -0,0 +1,28 @@ +import { Accessor } from "solid-js"; +import { S3 } from ".."; +import { augment } from "../augment"; +import { Stack } from "./stack"; + +/** A generic stack data structure. It augments each value before pushing it onto the stack. */ +export class AugmentedStack { + #stack = new Stack>(null!); + constructor(public name: string) { + this.#stack.name = name; + } + all = this.#stack.all.bind(this.#stack); + peek = this.#stack.peek.bind(this.#stack); + /** + * Augments a value `T` or `Accessor` and adds it to the stack. + * Value is automatically removed from stack on cleanup. + * + * @param value - The value to add to the stack. + * @returns A cleanup function to manually remove the value from the stack. + */ + push(value: T | Accessor) { + const cleanup = + typeof value === "function" + ? this.#stack.push(() => augment((value as Accessor)())) + : this.#stack.push(augment(value)); + return cleanup; + } +} diff --git a/src/data-structure/stack.ts b/src/data-structure/stack.ts new file mode 100644 index 0000000..e93b985 --- /dev/null +++ b/src/data-structure/stack.ts @@ -0,0 +1,72 @@ +import { Accessor, Setter, createSignal, getOwner, onCleanup, untrack } from "solid-js"; + +/** Class representing a stack data structure. */ +export class Stack { + #array: Accessor<(T | Accessor)[]>; + #setArray: Setter<(T | Accessor)[]>; + constructor(public name: string) { + [this.#array, this.#setArray] = createSignal<(T | Accessor)[]>([], { equals: false }); + } + /** + * Returns the complete stack. + * @returns Returns the complete stack. + */ + all() { + return this.#array(); + } + /** + * Returns the top element of the stack without removing it. + * @returns The top element of the stack. + */ + peek(): T | undefined { + const array = this.#array(); + const top = array[array.length - 1]; + return typeof top === "function" ? (top as Accessor)() : top; + } + /** + * Adds a value `T` or `Accessor` to the stack. + * Value is automatically removed from stack on cleanup. + * @param value - The value to add to the stack. + * @returns A cleanup function to remove the value from the stack. + */ + push(value: T | Accessor) { + this.#setArray(array => { + const index = array.indexOf(value); + if (index !== -1) array.splice(index, 1); + array.push(value); + return array; + }); + if (import.meta.env?.MODE === "development") { + const array = untrack(this.#array.bind(this)); + if (array.length > 2) { + // TODO: write better warning message + console.warn( + `Stack ${this.name} has more then 2 entries:`, + array, + `This could lead to unexpected behavior: only the latest added value will be selected.`, + ); + } + if (getOwner() === null) { + console.warn( + `Value ${value} is added to stack ${this.name} outside a \`createRoot\` or \`render\`. +Remember to remove the element from the stack by calling the returned cleanup-function manually.`, + ); + } + } + onCleanup(() => this.remove(value)); + return () => this.remove(value); + } + /** + * Removes a value from the stack. + * @private + * @param value - The value to remove from the stack. + */ + remove(value: T | Accessor) { + this.#setArray(array => { + const index = array.indexOf(value); + if (index === -1) return array; + array.splice(index, 1); + return array; + }); + } +} diff --git a/src/hooks.ts b/src/hooks.ts index 372eeb7..ab7503e 100644 --- a/src/hooks.ts +++ b/src/hooks.ts @@ -1,161 +1,131 @@ -import * as THREE from "three"; -import { StateSelector, EqualityChecker } from "zustand/vanilla"; -import { ThreeContext, RootState, RenderCallback } from "./core/store"; -import { buildGraph, ObjectMap, is } from "./core/utils"; -import { - createComputed, - createEffect, - createMemo, - createSignal, - onCleanup, - untrack, - useContext, -} from "solid-js"; - -export interface Loader extends THREE.Loader { - load( - url: string, - onLoad?: (result: T) => void, - onProgress?: (event: ProgressEvent) => void, - onError?: (event: ErrorEvent) => void - ): unknown; -} - -export type Extensions = (loader: THREE.Loader) => void; -export type LoaderResult = T extends any[] ? Loader : Loader; -export type ConditionalType = Child extends Parent - ? Truthy - : Falsy; -export type BranchingReturn = ConditionalType< - T, - Parent, - Coerced, - T ->; - -export function useStore() { - const store = useContext(ThreeContext); - if (!store) throw `R3F hooks can only be used within the Canvas component!`; - return store; -} - -export function useThree( - selector: StateSelector = (state) => state as unknown as U, - equalityFn?: EqualityChecker -) { - let store = useStore(); - const [signal, setSignal] = createSignal(selector(store.getState())); - - createComputed(() => { - let cleanup = useStore().subscribe( - // @ts-expect-error - selector, - (v) => { - // @ts-expect-error - setSignal(() => v); - }, - equalityFn - ); - - onCleanup(cleanup); - }); - - return signal; -} - -/** - * Creates a signal that is updated when the given effect is run. - * - * @example - * ```ts - * const [count, setCount] = useSignal(0); - * useFrame(() => { - * setCount(count + 1); - * }); - * ``` - * - * @param callback - a function to run on every frame render - * @param renderPriority - priority of the callback decides its order in the frameloop, higher is earlier - */ -export function useFrame( - callback: RenderCallback, - renderPriority: number = 0 -): void { - const subscribe = useStore().getState().internal.subscribe; - let cleanup = subscribe( - (t, delta) => untrack(() => callback(t, delta)), - renderPriority - ); - - onCleanup(cleanup); -} - -export function useGraph(object: THREE.Object3D) { - return createMemo(() => buildGraph(object)); -} - -export function loadingFn( - extensions?: Extensions, - onProgress?: (event: ProgressEvent) => void -) { - return function (Proto: new () => LoaderResult, ...input: string[]) { - // Construct new loader and run extensions - const loader = new Proto(); - if (extensions) extensions(loader); - // Go through the urls and load them - return Promise.all( - input.map( - (input) => - new Promise((res, reject) => - loader.load( - input, - (data: any) => { - if (data.scene) Object.assign(data, buildGraph(data.scene)); - res(data); - }, - onProgress, - (error) => reject(`Could not load ${input}: ${error.message}`) - ) - ) - ) - ); - }; -} - -// export function useLoader( -// Proto: new () => LoaderResult, -// input: U, -// extensions?: Extensions, -// onProgress?: (event: ProgressEvent) => void -// ): U extends any[] -// ? BranchingReturn[] -// : BranchingReturn { -// // Use suspense to load async assets -// const keys = (Array.isArray(input) ? input : [input]) as string[]; -// const results = suspend( -// loadingFn(extensions, onProgress), -// [Proto, ...keys], -// { equal: is.equ } -// ); -// // Return the object/s -// return (Array.isArray(input) ? results : results[0]) as U extends any[] -// ? BranchingReturn[] -// : BranchingReturn; -// } - -// useLoader.preload = function ( -// Proto: new () => LoaderResult, -// input: U, -// extensions?: Extensions -// ) { -// const keys = (Array.isArray(input) ? input : [input]) as string[]; -// return preload(loadingFn(extensions), [Proto, ...keys]); -// }; - -// useLoader.clear = function ( -// Proto: new () => LoaderResult, -// input: U -// ) { -// const keys = (Array.isArray(input) ? input : [input]) as string[]; -// return clear([Proto, ...keys]); -// }; +import { Accessor, Resource, createContext, createResource, useContext } from "solid-js"; +import { S3 } from "./"; + +/**********************************************************************************/ +/* */ +/* Use Three */ +/* */ +/**********************************************************************************/ + +export const threeContext = createContext(null!); + +/** + * Custom hook to access all necessary Three.js objects needed to manage a 3D scene. + * This hook must be used within a component that is a descendant of the `` component. + * + * @template T The expected return type after applying the callback to the context. + * @param [callback] - Optional callback function that processes and returns a part of the context. + * @returns Returns `S3.Context` directly, or as a selector if a callback is provided. + * @throws Throws an error if used outside of the Canvas component context. + */ +export function useThree(): S3.Context; +export function useThree(callback: (value: S3.Context) => T): Accessor; +export function useThree(callback?: (value: S3.Context) => any) { + const store = useContext(threeContext); + if (!store) { + throw new Error("S3F: Hooks can only be used within the Canvas component!"); + } + if (callback) return () => callback(store); + return store; +} + +/**********************************************************************************/ +/* */ +/* Use Frame */ +/* */ +/**********************************************************************************/ + +type FrameContext = ( + callback: (context: S3.Context, delta: number, frame?: XRFrame) => void, +) => void; +export const frameContext = createContext(); + +/** + * Hook to register a callback that will be executed on each animation frame within the `` component. + * This hook must be used within a component that is a descendant of the `` component. + * + * @param callback - The callback function to be executed on each frame. + * @throws Throws an error if used outside of the Canvas component context. + */ +export const useFrame = ( + callback: (context: S3.Context, delta: number, frame?: XRFrame) => void, +) => { + const addFrameListener = useContext(frameContext); + if (!addFrameListener) { + throw new Error("S3F: Hooks can only be used within the Canvas component!"); + } + addFrameListener(callback); +}; + +/**********************************************************************************/ +/* */ +/* Use Loader */ +/* */ +/**********************************************************************************/ + +type Loader = { + load: ( + value: string, + onLoad: (value: TLoaderResult) => void, + onProgress: (() => void) | undefined, + onReject: ((error: ErrorEvent) => void) | undefined, + ) => void | null; +}; +type UseLoaderOverload = TArg extends readonly TLoaderArg[] + ? { [K in keyof TArg]: TLoaderResult } + : TLoaderResult; +type LoaderCache> = { loader: T; resources: {} }; + +const LOADER_CACHE = new Map(); + +/** + * Hook to create and manage a resource using a Three.js loader. It ensures that the loader is + * reused if it has been instantiated before, and manages the resource lifecycle automatically. + * + * @template TResult The type of the resolved data when the loader completes loading. + * @template TArg The argument type expected by the loader function. + * @param Constructor - The loader class constructor. + * @param args - The arguments to be passed to the loader function, wrapped in an accessor to enable reactivity. + * @returns An accessor containing the loaded resource, re-evaluating when inputs change. + */ +export const useLoader = ( + Constructor: new () => TLoader, + args: Accessor, + setup?: (loader: TLoader) => void, +) => { + let cache = LOADER_CACHE.get(Constructor) as LoaderCache; + if (!cache) { + cache = { + loader: new Constructor(), + resources: {}, + }; + LOADER_CACHE.set(Constructor, cache); + } + const { loader, resources } = cache; + setup?.(loader); + + const load = (arg: string) => { + if (resources[arg]) return resources[arg]; + return (resources[arg] = new Promise((resolve, reject) => + loader.load( + arg, + value => { + resources[arg] = value; + resolve(value); + }, + undefined, + reject, + ), + )); + }; + + const [resource] = createResource(args, args => + Array.isArray(args) + ? Promise.all((args as string[]).map(arg => load(arg))) + : load(args as string), + ); + + return resource as Resource< + UseLoaderOverload ? U : never, TArg> + >; +}; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..a9f2834 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,6 @@ +export { $S3C } from "./augment"; +export { Canvas } from "./canvas"; +export { useFrame, useLoader, useThree } from "./hooks"; +export { T, extend } from "./proxy"; +export * as S3 from "./types"; +export { buildGraph } from "./utils/build-graph"; diff --git a/src/index.tsx b/src/index.tsx deleted file mode 100644 index c7645ff..0000000 --- a/src/index.tsx +++ /dev/null @@ -1,22 +0,0 @@ -export * from "./renderer"; -export * from "./core/renderer"; -export * from "./three-types"; -import * as ThreeJSX from "./three-types"; -export { ThreeJSX }; -export type { - Intersection, - Subscription, - Dpr, - Size, - Viewport, - Camera, - RenderCallback, - Performance, - RootState -} from "./core/store"; -export type { ThreeEvent, Events, EventManager, IntersectionEvent } from "./core/events"; -export type { ObjectMap } from "./core/utils"; -export * from "./hooks"; -export * from "./web/Canvas"; -export { createPointerEvents as events } from "./web/events"; -export * from "./core"; diff --git a/src/internal-context.ts b/src/internal-context.ts new file mode 100644 index 0000000..17dc7ce --- /dev/null +++ b/src/internal-context.ts @@ -0,0 +1,54 @@ +import { JSX, createContext, useContext } from "solid-js"; +import { Object3D } from "three"; +import { S3 } from "./"; +import { CanvasProps } from "./canvas"; + +/** + * Registers an event listener for an `AugmentedElement` to the nearest Canvas component up the component tree. + * This function must be called within components that are descendants of the Canvas component. + * + * @param object - The Three.js object to attach the event listener to. + * @param type - The type of event to listen for (e.g., 'click', 'mouseenter'). + * @throws Throws an error if used outside of the Canvas component context. + */ +export const addToEventListeners = (object: S3.Instance, type: S3.EventName) => { + const addToEventListeners = useContext(eventContext); + if (!addToEventListeners) { + throw new Error("S3F: Hooks can only be used within the Canvas component!"); + } + addToEventListeners(object, type); +}; +export const eventContext = + createContext<(object: S3.Instance, type: S3.EventName) => void>(); + +/** + * This function facilitates the rendering of JSX elements outside the normal scene + * graph, and must be used within components that are descendants of the Canvas component. + * + * @param children - The child elements to be rendered through the portal. + * @throws Throws an error if used outside of the Canvas component context. + */ +export const addPortal = (children: JSX.Element | JSX.Element[]) => { + const addPortal = useContext(portalContext); + if (!addPortal) { + throw new Error("S3F: Hooks can only be used within the Canvas component!"); + } + addPortal(children); +}; +export const portalContext = createContext<(children: JSX.Element | JSX.Element[]) => void>(); + +/** + * Hook that provides access to the props of the nearest Canvas component up the component tree. + * This hook must be used within components that are descendants of the Canvas component. + * + * @returns The current properties of the Canvas component. + * @throws Throws an error if used outside of a Canvas component context. + */ +export const useCanvasProps = () => { + const canvasProps = useContext(canvasPropsContext); + if (!canvasProps) { + throw new Error("S3F: Hooks can only be used within the Canvas component!"); + } + return canvasProps; +}; +export const canvasPropsContext = createContext(); diff --git a/src/props.ts b/src/props.ts new file mode 100644 index 0000000..9a22199 --- /dev/null +++ b/src/props.ts @@ -0,0 +1,312 @@ +import { + Accessor, + children, + createRenderEffect, + mapArray, + onCleanup, + splitProps, + untrack, +} from "solid-js"; +import { + BufferGeometry, + Color, + Fog, + Layers, + Material, + Object3D, + RGBAFormat, + Texture, + UnsignedByteType, +} from "three"; +import { S3 } from "./"; +import { $S3C } from "./augment"; +import { isEventType } from "./create-events"; +import { useThree } from "./hooks"; +import { addToEventListeners, useCanvasProps } from "./internal-context"; +import { hasColorSpace } from "./utils/has-colorspace"; +import { resolve } from "./utils/resolve"; + +/**********************************************************************************/ +/* */ +/* Manage Props */ +/* */ +/**********************************************************************************/ + +/** + * Manages and applies `solid-three` props to its Three.js object. This function sets up reactive effects + * to ensure that properties are correctly applied and updated in response to changes. It also manages the + * attachment of children and the disposal of the object. + * + * @template T - The type of the augmented element. + * @param object - An accessor function that returns the target object to which properties will be applied. + * @param props - An object containing the props to apply. This includes both direct properties + * and special properties like `ref` and `children`. + */ +export function manageProps(object: Accessor>, props: any) { + const [local, instanceProps] = splitProps(props, ["ref", "args", "object", "attach", "children"]); + + // Assign ref + createRenderEffect(() => { + if (local.ref instanceof Function) local.ref(object()); + else local.ref = object(); + }); + + // Connect or attach children to THREE-instance + const childrenAccessor = children(() => props.children); + createRenderEffect(() => + manageSceneGraph(object(), childrenAccessor as unknown as Accessor), + ); + + // Apply the props to THREE-instance + createRenderEffect(() => { + const keys = Object.keys(instanceProps); + for (const key of keys) { + // An array of sub-property-keys: + // p.ex in position's subKeys will be ['position-x'] + const subKeys = keys.filter(_key => key !== _key && _key.includes(key)); + createRenderEffect(() => { + applyProp(object(), key, instanceProps[key]); + // If property updates, apply its sub-properties immediately after. + for (const subKey of subKeys) { + applyProp(object(), subKey, instanceProps[subKey]); + } + }); + } + // NOTE: see "onUpdate should not update itself"-test + untrack(() => props.onUpdate)?.(object()); + }); + + // Automatically dispose + onCleanup(() => object()?.dispose?.()); +} + +/**********************************************************************************/ +/* */ +/* Apply Prop */ +/* */ +/**********************************************************************************/ + +const NEEDS_UPDATE = [ + "map", + "envMap", + "bumpMap", + "normalMap", + "transparent", + "morphTargets", + "skinning", + "alphaTest", + "useVertexColors", + "flatShading", +]; + +/** + * Applies a specified property value to an `AugmentedElement`. This function handles nested properties, + * automatic updates of the `needsUpdate` flag, color space conversions, and event listener management. + * It efficiently manages property assignments with appropriate handling for different data types and structures. + * + * @param source - The target object for property application. + * @param type - The property name, which can include nested paths indicated by hyphens. + * @param value - The value to be assigned to the property; can be of any appropriate type. + */ +export const applyProp = (source: S3.Instance, type: string, value: any) => { + if (!source) { + console.error("error while applying prop", source, type, value); + return; + } + + // Ignore setting undefined props + if (value === undefined) return; + + /* If the key contains a hyphen, we're setting a sub property. */ + if (type.indexOf("-") > -1) { + const [property, ...rest] = type.split("-"); + applyProp(source[property], rest.join("-"), value); + return; + } + + if (NEEDS_UPDATE.includes(type) && ((!source[type] && value) || (source[type] && !value))) { + source.needsUpdate = true; + } + + // Alias (output)encoding => (output)colorSpace (since r152) + // https://github.com/pmndrs/react-three-fiber/pull/2829 + if (hasColorSpace(source)) { + const sRGBEncoding = 3001; + const SRGBColorSpace = "srgb"; + const LinearSRGBColorSpace = "srgb-linear"; + + if (type === "encoding") { + type = "colorSpace"; + value = value === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace; + } else if (type === "outputEncoding") { + type = "outputColorSpace"; + value = value === sRGBEncoding ? SRGBColorSpace : LinearSRGBColorSpace; + } + } + + if (isEventType(type)) { + if (source instanceof Object3D) { + addToEventListeners(source, type); + } else { + console.error( + "Event handlers can only be added to Three elements extending from Object3D. Ignored event-type:", + type, + "from element", + source, + ); + } + return; + } + + const target = source[type]; + const context = useThree(); + const canvasProps = useCanvasProps(); + + try { + // Copy if properties match signatures + if (target?.copy && target?.constructor === value?.constructor) { + target.copy(value); + } + // Layers have no copy function, we must therefore copy the mask property + else if (target instanceof Layers && value instanceof Layers) { + target.mask = value.mask; + } + // Set array types + else if (target?.set && Array.isArray(value)) { + if (target.fromArray) target.fromArray(value); + else target.set(...value); + } + // Set literal types, ignore undefined + // https://github.com/pmndrs/react-three-fiber/issues/274 + else if (target?.set && typeof value !== "object") { + const isColor = target instanceof Color; + // Allow setting array scalars + if (!isColor && target.setScalar && typeof value === "number") target.setScalar(value); + // Otherwise just set ... + else if (value !== undefined) target.set(value); + } + // Else, just overwrite the value + else { + source[type] = value; + + // Auto-convert sRGB textures, for now ... + // https://github.com/pmndrs/react-three-fiber/issues/344 + if ( + source[type] instanceof Texture && + // sRGB textures must be RGBA8 since r137 https://github.com/mrdoob/three.js/pull/23129 + source[type].format === RGBAFormat && + source[type].type === UnsignedByteType + ) { + createRenderEffect(() => { + // Subscribe manually to linear and flat-prop. + canvasProps.linear; + canvasProps.flat; + + const texture = source[type] as Texture; + if (hasColorSpace(texture) && hasColorSpace(context.gl)) { + texture.colorSpace = context.gl.outputColorSpace; + } else { + texture.encoding = context.gl.outputEncoding; + } + }); + } + } + } finally { + if (canvasProps.frameloop === "demand") { + context.requestRender(); + } + } +}; + +/**********************************************************************************/ +/* */ +/* Scene Graph */ +/* */ +/**********************************************************************************/ + +/** + * Dynamically attaches/connects child elements to a parent within a scene graph based on specified attachment properties. + * The function supports different attachment behaviors: + * - Direct assignment for standard properties like material, geometry, or fog. + * - Custom attachment logic through a callback function provided in the attach property of the child. + * - Default behavior for Three.js Object3D instances where children are added to the parent's children array if no specific attach property is provided. + * + * @template T The type parameter for the elements in the scene graph. + * @param parent - The parent element to which children will be attached. + * @param childAccessor - A function returning the child or children to be managed. + */ +export const manageSceneGraph = ( + parent: T, + childAccessor: Accessor, +) => { + createRenderEffect( + mapArray( + () => { + const result = resolve(childAccessor, true); + return Array.isArray(result) ? result : result ? [result] : []; + }, + child => + createRenderEffect(() => { + // NOTE: this happens currently more then I would expect. + if (!child) { + return; + } + + // Update parent's augmented children-property. + parent[$S3C].children.add(child); + onCleanup(() => parent[$S3C].children.delete(child)); + + // Attaching children first. If a child is attached it will not be added to the parent's children. + let attachProp = child[$S3C].props.attach; + + // Attach-prop can be a callback. It returns a cleanup-function. + if (typeof attachProp === "function") { + const cleanup = attachProp(parent, child); + onCleanup(cleanup); + return; + } + + // Defaults for Material, BufferGeometry and Fog. + if (!attachProp) { + if (child instanceof Material) attachProp = "material"; + else if (child instanceof BufferGeometry) attachProp = "geometry"; + else if (child instanceof Fog) attachProp = "fog"; + } + + // If an attachProp is defined, attach the child to the parent. + if (attachProp) { + let target = parent; + const path = attachProp.split("-"); + while (true) { + const property = path.shift()!; + if (path.length === 0) { + target[property] = child; + onCleanup(() => (parent[attachProp] = undefined)); + break; + } else { + target = parent[property]; + } + } + return; + } + + // If no attach-prop is defined, connect the child to the parent. + if ( + child instanceof Object3D && + parent instanceof Object3D && + !parent.children.includes(child) + ) { + parent.add(child); + onCleanup(() => parent.remove(child)); + return child; + } + + console.error( + "Error while connecting/attaching child: child does not have attach-props defined and is not an Object3D", + parent, + child, + ); + }), + ), + ); +}; diff --git a/src/proxy.tsx b/src/proxy.tsx new file mode 100644 index 0000000..b58d56a --- /dev/null +++ b/src/proxy.tsx @@ -0,0 +1,105 @@ +import { createMemo, JSX, mergeProps } from "solid-js"; +import type * as THREE from "three"; +import { S3 } from "."; +import { augment } from "./augment"; +import { Portal, Primitive } from "./components"; +import { manageProps } from "./props"; +import { Constructor } from "./type-utils"; + +/**********************************************************************************/ +/* */ +/* Catalogue */ +/* */ +/**********************************************************************************/ + +/** + * Global catalogue object storing mappings from names to constructor representations. + */ +const CATALOGUE = {}; + +/** + * Predefined components that can be used directly within the system. + */ +const COMPONENTS: SolidThree.Components = { + Primitive, + Portal, +}; + +/** + * Extends the global CATALOGUE with additional objects. + * + * @param objects - The objects to add to the catalogue. + */ +export const extend = ( + objects: Partial< + | { + [TKey in keyof SolidThree.Elements]: Constructor; + } + | typeof THREE + >, +): void => void Object.assign(CATALOGUE, objects); + +/**********************************************************************************/ +/* */ +/* T */ +/* */ +/**********************************************************************************/ + +/** + * Cache for storing initialized components. + */ +const T_CACHE = new Map>(Object.entries(COMPONENTS)); + +/** Map given type to `S3.Component` */ +type MapToS3Components = { + [K in keyof Source]: S3.Component; +}; + +/** + * A proxy that provides on-demand creation and caching of `solid-three` components. + * It represents a dynamic layer over the predefined components and any added through extend function. + */ +export const T = new Proxy< + MapToS3Components & SolidThree.Components +>({} as any, { + get: (_, name: string) => { + /* Create and memoize a wrapper component for the specified property. */ + if (!T_CACHE.has(name)) { + /* Try and find a constructor within the THREE namespace. */ + const constructor = CATALOGUE[name]; + + /* If no constructor is found, return undefined. */ + if (!constructor) return undefined; + + /* Otherwise, create and memoize a component for that constructor. */ + T_CACHE.set(name, createThreeComponent(constructor)); + } + + return T_CACHE.get(name); + }, +}); + +/** + * Creates a ThreeComponent instance for a given source constructor. + * + * @template TSource The source constructor type. + * @param source - The constructor from which the component will be created. + * @returns The created component. + */ +function createThreeComponent( + source: TSource, +): S3.Component { + return (props: any) => { + const merged = mergeProps({ args: [] }, props); + const memo = createMemo(() => { + try { + return augment(new (source as any)(...merged.args), { props }); + } catch (e) { + console.error(e); + throw new Error(""); + } + }); + manageProps(memo, props); + return memo as unknown as JSX.Element; + }; +} diff --git a/src/renderer.tsx b/src/renderer.tsx deleted file mode 100644 index 3af31d9..0000000 --- a/src/renderer.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { Accessor, Component, createMemo, JSX, splitProps, untrack } from "solid-js"; -import { createThreeRenderer } from "./core/renderer"; -import { roots } from "./core"; -import { createSolidRenderer } from "./solid"; - -export const threeReconciler = createThreeRenderer(roots); -export const threeRenderer = createSolidRenderer(threeReconciler); - -export const { - render, - effect, - memo, - createComponent, - createElement, - createTextNode, - insertNode, - insert, - spread, - setProp, - mergeProps, - use -} = threeRenderer; - -export * from "solid-js"; - -type DynamicProps = T & { - children?: any; - component?: Component | string | keyof JSX.IntrinsicElements; -}; - -/** - * renders an arbitrary custom or native component and passes the other props - * ```typescript - * - * ``` - * @description https://www.solidjs.com/docs/latest/api#%3Cdynamic%3E - */ -export function Dynamic(props: DynamicProps): Accessor { - const [p, others] = splitProps(props, ["component"]); - return createMemo(() => { - const component = p.component as Function | string; - switch (typeof component) { - case "function": - return untrack(() => component(others)); - - case "string": - // const isSvg = SVGElements.has(component); - // const el = sharedConfig.context - // ? getNextElement() - let el = createElement(component); - - spread(el, others, true); - return el; - - default: - break; - } - }); -} diff --git a/src/solid.ts b/src/solid.ts deleted file mode 100644 index 09c07f2..0000000 --- a/src/solid.ts +++ /dev/null @@ -1,104 +0,0 @@ -import { prepare, toFirstUpper } from "./core/utils"; -import { ThreeContext } from "./core/store"; -import { useContext } from "solid-js"; -import { Scene } from "three"; -import { ThreeRenderer, catalogue, Instance } from "./core/renderer"; -import { createRenderer } from "solid-js/universal"; - -export let DEBUG = window.location.search.indexOf("debug") > -1; - -export function log(renderer: string, action: any, ...options: any[]) { - DEBUG && - console.debug( - `%c${renderer} %s %c`, - "font-weight: bold", - action, - "font-weight: normal", - ...options - ); -} - -function checkCatalogue(element: string) { - return catalogue[toFirstUpper(element)] !== undefined || element === "primitive"; -} - -export function createSolidRenderer({ - createInstance, - applyProp, - appendChild, - insertBefore, - removeChild, - attach -}: ThreeRenderer) { - return createRenderer({ - // @ts-ignore - createElement(element: string, args) { - log("three", "createElement", element); - if (element === "scene") { - return prepare(new Scene() as unknown as Instance); - } - let root = useContext(ThreeContext); - return createInstance( - element, - { - args - }, - root - ); - }, - createTextNode(value: string) { - return prepare({ - text: value, - type: "text" - }) as any; - }, - replaceText(textNode: Instance, value: string) { - throw new Error("Cant replace text node in three"); - }, - setProperty(node: Instance, key: string, value: any) { - log("three", "setProperty", node, key, node[key], value); - if (/^on(Pointer|Click|DoubleClick|ContextMenu|Wheel)/.test(key)) - return applyProp(node, [key, value, true, []]); - // Split dashed props - let entries: string[] = []; - if (key.includes("-")) entries = key.split("-"); - applyProp(node, [key, value, false, entries]); - - if (key === "attach" && node.__r3f.parent) { - attach(node.__r3f.parent, node, value); - } - }, - insertNode(parent, node, anchor) { - log("three", "insertNode", parent, node, anchor); - if (node instanceof Text) { - return; - } - - if (anchor) { - insertBefore(parent, node, anchor); - } else { - appendChild(parent, node); - } - }, - isTextNode(node) { - return node.type === "text"; - }, - removeNode(parent, node) { - log("three", "removeNode", parent, node); - removeChild(parent, node, true); - }, - - getParentNode(node) { - log("three", "getParentNode", node); - return node.__r3f.parent as unknown as Instance; - }, - getFirstChild(node) { - log("three", "getFirstChild", node); - return node.__r3f.objects?.length ? node.__r3f.objects[0] : node.children[0]; - }, - getNextSibling(node) { - log("three", "getNextSibling", node); - return node.nextSibling; - } - }); -} diff --git a/src/testing/index.tsx b/src/testing/index.tsx new file mode 100644 index 0000000..2b9b772 --- /dev/null +++ b/src/testing/index.tsx @@ -0,0 +1,134 @@ +import { Accessor, JSX, createRenderEffect, createRoot, mergeProps } from "solid-js"; + +import { CanvasProps } from "../canvas"; +import { createThree } from "../create-three"; +import { WebGL2RenderingContext } from "./webgl2-rendering-context"; + +/** + * Initializes a testing enviromnent for `solid-three`. + * + * @param children - An accessor for the `AugmentedElement` to render. + * @param [props] - Optional properties to configure canvas. + * @returns `S3.Context` augmented with methods to unmount the scene and to wait for the next animation frame. + * + * @example + * const testScene = test(() => , { camera: position: [0,0,5] }); + * await testScene.waitTillNextFrame(); + * testScene.unmount(); + */ +export function test( + children: Accessor, + props?: Omit, +): TestApi { + const canvas = createTestCanvas(); + let context: ReturnType = null!; + let unmount: () => void = null!; + + createRoot(dispose => { + unmount = dispose; + context = createThree( + canvas, + mergeProps( + { + get children() { + return children(); + }, + camera: { + position: [0, 0, 5] as [number, number, number], + }, + }, + props, + ), + ); + }); + + const waitTillNextFrame = () => + new Promise(resolve => { + const cleanup = context.addFrameListener(() => (cleanup(), resolve())); + }); + + return mergeProps(context, { + unmount, + waitTillNextFrame, + }); +} +type TestApi = ReturnType & { + unmount: () => void; + waitTillNextFrame: () => Promise; +}; + +/** + * Canvas element tailored for testing. + * + * @param props + * @returns The canvas JSX element. + * + * @example + * render(); + */ +export function TestCanvas(props: CanvasProps) { + const canvas = createTestCanvas(); + const container = ( +
{canvas}
+ ) as HTMLDivElement; + + createRoot(() => createThree(canvas, props)); + /* Assign ref */ + createRenderEffect(() => { + if (props.ref instanceof Function) props.ref(container); + else props.ref = container; + }); + + return container; +} + +/** + * Creates a mock canvas element for testing purposes. This function dynamically generates a canvas, + * suitable for environments with or without a standard DOM. In non-DOM environments, it simulates + * essential canvas properties and methods, including WebGL contexts. + * + * @param [options] - Configuration options for the canvas. + * @returns A canvas element with specified dimensions and stubbed if necessary. + * + * @example + * // Create a test canvas of default size + * const canvas = createTestCanvas(); + * + * @example + * // Create a test canvas with custom dimensions + * const customCanvas = createTestCanvas({ width: 1024, height: 768 }); + */ +const createTestCanvas = ({ width = 1280, height = 800 } = {}) => { + let canvas: HTMLCanvasElement; + + if (typeof document !== "undefined" && typeof document.createElement === "function") { + canvas = document.createElement("canvas"); + } else { + canvas = { + style: {}, + addEventListener: (() => {}) as any, + removeEventListener: (() => {}) as any, + clientWidth: width, + clientHeight: height, + getContext: (() => new WebGL2RenderingContext(canvas)) as any, + } as HTMLCanvasElement; + } + canvas.width = width; + canvas.height = height; + + if (globalThis.HTMLCanvasElement) { + const getContext = HTMLCanvasElement.prototype.getContext; + HTMLCanvasElement.prototype.getContext = function (this: HTMLCanvasElement, id: string) { + if (id.startsWith("webgl")) return new WebGL2RenderingContext(this); + return getContext.apply(this, arguments as any); + } as any; + } + + class WebGLRenderingContext extends WebGL2RenderingContext {} + // @ts-expect-error + globalThis.WebGLRenderingContext ??= WebGLRenderingContext; + // @ts-expect-error + globalThis.WebGL2RenderingContext ??= WebGL2RenderingContext; + + return canvas; +}; diff --git a/src/testing/webgl2-rendering-context.ts b/src/testing/webgl2-rendering-context.ts new file mode 100644 index 0000000..00a27ce --- /dev/null +++ b/src/testing/webgl2-rendering-context.ts @@ -0,0 +1,760 @@ +const functions = [ + "activeTexture", + "attachShader", + "beginQuery", + "beginTransformFeedback", + "bindAttribLocation", + "bindBufferBase", + "bindBufferRange", + "bindRenderbuffer", + "bindSampler", + "bindTransformFeedback", + "bindVertexArray", + "blendColor", + "blendEquation", + "blendEquationSeparate", + "blendFunc", + "blendFuncSeparate", + "blitFramebuffer", + "bufferData", + "bufferSubData", + "checkFramebufferStatus", + "clientWaitSync", + "compileShader", + "compressedTexImage2D", + "compressedTexImage3D", + "compressedTexSubImage2D", + "compressedTexSubImage3D", + "copyBufferSubData", + "copyTexImage2D", + "copyTexSubImage2D", + "copyTexSubImage3D", + "createBuffer", + "createFramebuffer", + "createProgram", + "createQuery", + "createRenderbuffer", + "createSampler", + "createShader", + "createTexture", + "createTransformFeedback", + "createVertexArray", + "cullFace", + "deleteBuffer", + "deleteFramebuffer", + "deleteProgram", + "deleteQuery", + "deleteRenderbuffer", + "deleteSampler", + "deleteShader", + "deleteSync", + "deleteTexture", + "deleteTransformFeedback", + "deleteVertexArray", + "depthFunc", + "depthMask", + "depthRange", + "detachShader", + "disable", + "drawArraysInstanced", + "drawElementsInstanced", + "drawRangeElements", + "enable", + "endQuery", + "endTransformFeedback", + "fenceSync", + "finish", + "flush", + "framebufferRenderbuffer", + "framebufferTexture2D", + "framebufferTextureLayer", + "frontFace", + "generateMipmap", + "getActiveAttrib", + "getActiveUniform", + "getActiveUniformBlockName", + "getActiveUniformBlockParameter", + "getActiveUniforms", + "getAttachedShaders", + "getAttribLocation", + "getBufferParameter", + "getBufferSubData", + "getContextAttributes", + "getError", + "getExtension", + "getFragDataLocation", + "getFramebufferAttachmentParameter", + "getIndexedParameter", + "getInternalformatParameter", + "getParameter", + "getProgramInfoLog", + "getProgramParameter", + "getQuery", + "getQueryParameter", + "getRenderbufferParameter", + "getSamplerParameter", + "getShaderInfoLog", + "getShaderParameter", + "getShaderPrecisionFormat", + "getShaderSource", + "getSupportedExtensions", + "getSyncParameter", + "getTexParameter", + "getTransformFeedbackVarying", + "getUniform", + "getUniformBlockIndex", + "getUniformIndices", + "getUniformLocation", + "getVertexAttrib", + "getVertexAttribOffset", + "hint", + "invalidateFramebuffer", + "invalidateSubFramebuffer", + "isBuffer", + "isContextLost", + "isEnabled", + "isFramebuffer", + "isProgram", + "isQuery", + "isRenderbuffer", + "isSampler", + "isShader", + "isSync", + "isTexture", + "isTransformFeedback", + "isVertexArray", + "lineWidth", + "linkProgram", + "pauseTransformFeedback", + "pixelStorei", + "polygonOffset", + "readBuffer", + "readPixels", + "renderbufferStorage", + "renderbufferStorageMultisample", + "resumeTransformFeedback", + "sampleCoverage", + "samplerParameterf", + "samplerParameteri", + "shaderSource", + "stencilFunc", + "stencilFuncSeparate", + "stencilMask", + "stencilMaskSeparate", + "stencilOp", + "stencilOpSeparate", + "texImage2D", + "texImage3D", + "texParameterf", + "texParameteri", + "texStorage2D", + "texStorage3D", + "texSubImage2D", + "texSubImage3D", + "transformFeedbackVaryings", + "uniform1ui", + "uniform2ui", + "uniform3ui", + "uniform4ui", + "uniformBlockBinding", + "useProgram", + "validateProgram", + "vertexAttribDivisor", + "vertexAttribI4i", + "vertexAttribI4ui", + "vertexAttribIPointer", + "waitSync", + "bindBuffer", + "bindFramebuffer", + "bindTexture", + "clear", + "clearBufferfi", + "clearBufferfv", + "clearBufferiv", + "clearBufferuiv", + "clearColor", + "clearDepth", + "clearStencil", + "colorMask", + "disableVertexAttribArray", + "drawArrays", + "drawBuffers", + "drawElements", + "enableVertexAttribArray", + "scissor", + "uniform1f", + "uniform1fv", + "uniform1i", + "uniform1iv", + "uniform1uiv", + "uniform2f", + "uniform2fv", + "uniform2i", + "uniform2iv", + "uniform2uiv", + "uniform3f", + "uniform3fv", + "uniform3i", + "uniform3iv", + "uniform3uiv", + "uniform4f", + "uniform4fv", + "uniform4i", + "uniform4iv", + "uniform4uiv", + "uniformMatrix2fv", + "uniformMatrix2x3fv", + "uniformMatrix2x4fv", + "uniformMatrix3fv", + "uniformMatrix3x2fv", + "uniformMatrix3x4fv", + "uniformMatrix4fv", + "uniformMatrix4x2fv", + "uniformMatrix4x3fv", + "vertexAttrib1f", + "vertexAttrib1fv", + "vertexAttrib2f", + "vertexAttrib2fv", + "vertexAttrib3f", + "vertexAttrib3fv", + "vertexAttrib4f", + "vertexAttrib4fv", + "vertexAttribI4iv", + "vertexAttribI4uiv", + "vertexAttribPointer", + "viewport", + "makeXRCompatible", +]; + +const enums: Record = { + DEPTH_BUFFER_BIT: 256, + STENCIL_BUFFER_BIT: 1024, + COLOR_BUFFER_BIT: 16384, + POINTS: 0, + LINES: 1, + LINE_LOOP: 2, + LINE_STRIP: 3, + TRIANGLES: 4, + TRIANGLE_STRIP: 5, + TRIANGLE_FAN: 6, + ZERO: 0, + ONE: 1, + SRC_COLOR: 768, + ONE_MINUS_SRC_COLOR: 769, + SRC_ALPHA: 770, + ONE_MINUS_SRC_ALPHA: 771, + DST_ALPHA: 772, + ONE_MINUS_DST_ALPHA: 773, + DST_COLOR: 774, + ONE_MINUS_DST_COLOR: 775, + SRC_ALPHA_SATURATE: 776, + FUNC_ADD: 32774, + BLEND_EQUATION: 32777, + BLEND_EQUATION_RGB: 32777, + BLEND_EQUATION_ALPHA: 34877, + FUNC_SUBTRACT: 32778, + FUNC_REVERSE_SUBTRACT: 32779, + BLEND_DST_RGB: 32968, + BLEND_SRC_RGB: 32969, + BLEND_DST_ALPHA: 32970, + BLEND_SRC_ALPHA: 32971, + CONSTANT_COLOR: 32769, + ONE_MINUS_CONSTANT_COLOR: 32770, + CONSTANT_ALPHA: 32771, + ONE_MINUS_CONSTANT_ALPHA: 32772, + BLEND_COLOR: 32773, + ARRAY_BUFFER: 34962, + ELEMENT_ARRAY_BUFFER: 34963, + ARRAY_BUFFER_BINDING: 34964, + ELEMENT_ARRAY_BUFFER_BINDING: 34965, + STREAM_DRAW: 35040, + STATIC_DRAW: 35044, + DYNAMIC_DRAW: 35048, + BUFFER_SIZE: 34660, + BUFFER_USAGE: 34661, + CURRENT_VERTEX_ATTRIB: 34342, + FRONT: 1028, + BACK: 1029, + FRONT_AND_BACK: 1032, + TEXTURE_2D: 3553, + CULL_FACE: 2884, + BLEND: 3042, + DITHER: 3024, + STENCIL_TEST: 2960, + DEPTH_TEST: 2929, + SCISSOR_TEST: 3089, + POLYGON_OFFSET_FILL: 32823, + SAMPLE_ALPHA_TO_COVERAGE: 32926, + SAMPLE_COVERAGE: 32928, + NO_ERROR: 0, + INVALID_ENUM: 1280, + INVALID_VALUE: 1281, + INVALID_OPERATION: 1282, + OUT_OF_MEMORY: 1285, + CW: 2304, + CCW: 2305, + LINE_WIDTH: 2849, + ALIASED_POINT_SIZE_RANGE: 33901, + ALIASED_LINE_WIDTH_RANGE: 33902, + CULL_FACE_MODE: 2885, + FRONT_FACE: 2886, + DEPTH_RANGE: 2928, + DEPTH_WRITEMASK: 2930, + DEPTH_CLEAR_VALUE: 2931, + DEPTH_FUNC: 2932, + STENCIL_CLEAR_VALUE: 2961, + STENCIL_FUNC: 2962, + STENCIL_FAIL: 2964, + STENCIL_PASS_DEPTH_FAIL: 2965, + STENCIL_PASS_DEPTH_PASS: 2966, + STENCIL_REF: 2967, + STENCIL_VALUE_MASK: 2963, + STENCIL_WRITEMASK: 2968, + STENCIL_BACK_FUNC: 34816, + STENCIL_BACK_FAIL: 34817, + STENCIL_BACK_PASS_DEPTH_FAIL: 34818, + STENCIL_BACK_PASS_DEPTH_PASS: 34819, + STENCIL_BACK_REF: 36003, + STENCIL_BACK_VALUE_MASK: 36004, + STENCIL_BACK_WRITEMASK: 36005, + VIEWPORT: 2978, + SCISSOR_BOX: 3088, + COLOR_CLEAR_VALUE: 3106, + COLOR_WRITEMASK: 3107, + UNPACK_ALIGNMENT: 3317, + PACK_ALIGNMENT: 3333, + MAX_TEXTURE_SIZE: 3379, + MAX_VIEWPORT_DIMS: 3386, + SUBPIXEL_BITS: 3408, + RED_BITS: 3410, + GREEN_BITS: 3411, + BLUE_BITS: 3412, + ALPHA_BITS: 3413, + DEPTH_BITS: 3414, + STENCIL_BITS: 3415, + POLYGON_OFFSET_UNITS: 10752, + POLYGON_OFFSET_FACTOR: 32824, + TEXTURE_BINDING_2D: 32873, + SAMPLE_BUFFERS: 32936, + SAMPLES: 32937, + SAMPLE_COVERAGE_VALUE: 32938, + SAMPLE_COVERAGE_INVERT: 32939, + COMPRESSED_TEXTURE_FORMATS: 34467, + DONT_CARE: 4352, + FASTEST: 4353, + NICEST: 4354, + GENERATE_MIPMAP_HINT: 33170, + BYTE: 5120, + UNSIGNED_BYTE: 5121, + SHORT: 5122, + UNSIGNED_SHORT: 5123, + INT: 5124, + UNSIGNED_INT: 5125, + FLOAT: 5126, + DEPTH_COMPONENT: 6402, + ALPHA: 6406, + RGB: 6407, + RGBA: 6408, + LUMINANCE: 6409, + LUMINANCE_ALPHA: 6410, + UNSIGNED_SHORT_4_4_4_4: 32819, + UNSIGNED_SHORT_5_5_5_1: 32820, + UNSIGNED_SHORT_5_6_5: 33635, + FRAGMENT_SHADER: 35632, + VERTEX_SHADER: 35633, + MAX_VERTEX_ATTRIBS: 34921, + MAX_VERTEX_UNIFORM_VECTORS: 36347, + MAX_VARYING_VECTORS: 36348, + MAX_COMBINED_TEXTURE_IMAGE_UNITS: 35661, + MAX_VERTEX_TEXTURE_IMAGE_UNITS: 35660, + MAX_TEXTURE_IMAGE_UNITS: 34930, + MAX_FRAGMENT_UNIFORM_VECTORS: 36349, + SHADER_TYPE: 35663, + DELETE_STATUS: 35712, + LINK_STATUS: 35714, + VALIDATE_STATUS: 35715, + ATTACHED_SHADERS: 35717, + ACTIVE_UNIFORMS: 35718, + ACTIVE_ATTRIBUTES: 35721, + SHADING_LANGUAGE_VERSION: 35724, + CURRENT_PROGRAM: 35725, + NEVER: 512, + LESS: 513, + EQUAL: 514, + LEQUAL: 515, + GREATER: 516, + NOTEQUAL: 517, + GEQUAL: 518, + ALWAYS: 519, + KEEP: 7680, + REPLACE: 7681, + INCR: 7682, + DECR: 7683, + INVERT: 5386, + INCR_WRAP: 34055, + DECR_WRAP: 34056, + VENDOR: 7936, + RENDERER: 7937, + VERSION: 7938, + NEAREST: 9728, + LINEAR: 9729, + NEAREST_MIPMAP_NEAREST: 9984, + LINEAR_MIPMAP_NEAREST: 9985, + NEAREST_MIPMAP_LINEAR: 9986, + LINEAR_MIPMAP_LINEAR: 9987, + TEXTURE_MAG_FILTER: 10240, + TEXTURE_MIN_FILTER: 10241, + TEXTURE_WRAP_S: 10242, + TEXTURE_WRAP_T: 10243, + TEXTURE: 5890, + TEXTURE_CUBE_MAP: 34067, + TEXTURE_BINDING_CUBE_MAP: 34068, + TEXTURE_CUBE_MAP_POSITIVE_X: 34069, + TEXTURE_CUBE_MAP_NEGATIVE_X: 34070, + TEXTURE_CUBE_MAP_POSITIVE_Y: 34071, + TEXTURE_CUBE_MAP_NEGATIVE_Y: 34072, + TEXTURE_CUBE_MAP_POSITIVE_Z: 34073, + TEXTURE_CUBE_MAP_NEGATIVE_Z: 34074, + MAX_CUBE_MAP_TEXTURE_SIZE: 34076, + TEXTURE0: 33984, + TEXTURE1: 33985, + TEXTURE2: 33986, + TEXTURE3: 33987, + TEXTURE4: 33988, + TEXTURE5: 33989, + TEXTURE6: 33990, + TEXTURE7: 33991, + TEXTURE8: 33992, + TEXTURE9: 33993, + TEXTURE10: 33994, + TEXTURE11: 33995, + TEXTURE12: 33996, + TEXTURE13: 33997, + TEXTURE14: 33998, + TEXTURE15: 33999, + TEXTURE16: 34000, + TEXTURE17: 34001, + TEXTURE18: 34002, + TEXTURE19: 34003, + TEXTURE20: 34004, + TEXTURE21: 34005, + TEXTURE22: 34006, + TEXTURE23: 34007, + TEXTURE24: 34008, + TEXTURE25: 34009, + TEXTURE26: 34010, + TEXTURE27: 34011, + TEXTURE28: 34012, + TEXTURE29: 34013, + TEXTURE30: 34014, + TEXTURE31: 34015, + ACTIVE_TEXTURE: 34016, + REPEAT: 10497, + CLAMP_TO_EDGE: 33071, + MIRRORED_REPEAT: 33648, + FLOAT_VEC2: 35664, + FLOAT_VEC3: 35665, + FLOAT_VEC4: 35666, + INT_VEC2: 35667, + INT_VEC3: 35668, + INT_VEC4: 35669, + BOOL: 35670, + BOOL_VEC2: 35671, + BOOL_VEC3: 35672, + BOOL_VEC4: 35673, + FLOAT_MAT2: 35674, + FLOAT_MAT3: 35675, + FLOAT_MAT4: 35676, + SAMPLER_2D: 35678, + SAMPLER_CUBE: 35680, + VERTEX_ATTRIB_ARRAY_ENABLED: 34338, + VERTEX_ATTRIB_ARRAY_SIZE: 34339, + VERTEX_ATTRIB_ARRAY_STRIDE: 34340, + VERTEX_ATTRIB_ARRAY_TYPE: 34341, + VERTEX_ATTRIB_ARRAY_NORMALIZED: 34922, + VERTEX_ATTRIB_ARRAY_POINTER: 34373, + VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: 34975, + IMPLEMENTATION_COLOR_READ_TYPE: 35738, + IMPLEMENTATION_COLOR_READ_FORMAT: 35739, + COMPILE_STATUS: 35713, + LOW_FLOAT: 36336, + MEDIUM_FLOAT: 36337, + HIGH_FLOAT: 36338, + LOW_INT: 36339, + MEDIUM_INT: 36340, + HIGH_INT: 36341, + FRAMEBUFFER: 36160, + RENDERBUFFER: 36161, + RGBA4: 32854, + RGB5_A1: 32855, + RGB565: 36194, + DEPTH_COMPONENT16: 33189, + STENCIL_INDEX: 6401, + STENCIL_INDEX8: 36168, + DEPTH_STENCIL: 34041, + RENDERBUFFER_WIDTH: 36162, + RENDERBUFFER_HEIGHT: 36163, + RENDERBUFFER_INTERNAL_FORMAT: 36164, + RENDERBUFFER_RED_SIZE: 36176, + RENDERBUFFER_GREEN_SIZE: 36177, + RENDERBUFFER_BLUE_SIZE: 36178, + RENDERBUFFER_ALPHA_SIZE: 36179, + RENDERBUFFER_DEPTH_SIZE: 36180, + RENDERBUFFER_STENCIL_SIZE: 36181, + FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: 36048, + FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: 36049, + FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: 36050, + FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: 36051, + COLOR_ATTACHMENT0: 36064, + DEPTH_ATTACHMENT: 36096, + STENCIL_ATTACHMENT: 36128, + DEPTH_STENCIL_ATTACHMENT: 33306, + NONE: 0, + FRAMEBUFFER_COMPLETE: 36053, + FRAMEBUFFER_INCOMPLETE_ATTACHMENT: 36054, + FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: 36055, + FRAMEBUFFER_INCOMPLETE_DIMENSIONS: 36057, + FRAMEBUFFER_UNSUPPORTED: 36061, + FRAMEBUFFER_BINDING: 36006, + RENDERBUFFER_BINDING: 36007, + MAX_RENDERBUFFER_SIZE: 34024, + INVALID_FRAMEBUFFER_OPERATION: 1286, + UNPACK_FLIP_Y_WEBGL: 37440, + UNPACK_PREMULTIPLY_ALPHA_WEBGL: 37441, + CONTEXT_LOST_WEBGL: 37442, + UNPACK_COLORSPACE_CONVERSION_WEBGL: 37443, + BROWSER_DEFAULT_WEBGL: 37444, + READ_BUFFER: 3074, + UNPACK_ROW_LENGTH: 3314, + UNPACK_SKIP_ROWS: 3315, + UNPACK_SKIP_PIXELS: 3316, + PACK_ROW_LENGTH: 3330, + PACK_SKIP_ROWS: 3331, + PACK_SKIP_PIXELS: 3332, + COLOR: 6144, + DEPTH: 6145, + STENCIL: 6146, + RED: 6403, + UNPACK_SKIP_IMAGES: 32877, + UNPACK_IMAGE_HEIGHT: 32878, + TEXTURE_WRAP_R: 32882, + MAX_ELEMENTS_VERTICES: 33000, + MAX_ELEMENTS_INDICES: 33001, + TEXTURE_MIN_LOD: 33082, + TEXTURE_MAX_LOD: 33083, + TEXTURE_BASE_LEVEL: 33084, + TEXTURE_MAX_LEVEL: 33085, + MIN: 32775, + MAX: 32776, + MAX_TEXTURE_LOD_BIAS: 34045, + TEXTURE_COMPARE_MODE: 34892, + TEXTURE_COMPARE_FUNC: 34893, + CURRENT_QUERY: 34917, + QUERY_RESULT: 34918, + QUERY_RESULT_AVAILABLE: 34919, + STREAM_READ: 35041, + STREAM_COPY: 35042, + STATIC_READ: 35045, + STATIC_COPY: 35046, + DYNAMIC_READ: 35049, + DYNAMIC_COPY: 35050, + MAX_DRAW_BUFFERS: 34852, + MAX_FRAGMENT_UNIFORM_COMPONENTS: 35657, + MAX_VERTEX_UNIFORM_COMPONENTS: 35658, + FRAGMENT_SHADER_DERIVATIVE_HINT: 35723, + PIXEL_PACK_BUFFER: 35051, + PIXEL_UNPACK_BUFFER: 35052, + PIXEL_PACK_BUFFER_BINDING: 35053, + PIXEL_UNPACK_BUFFER_BINDING: 35055, + SRGB: 35904, + COMPARE_REF_TO_TEXTURE: 34894, + VERTEX_ATTRIB_ARRAY_INTEGER: 35069, + MAX_ARRAY_TEXTURE_LAYERS: 35071, + MIN_PROGRAM_TEXEL_OFFSET: 35076, + MAX_PROGRAM_TEXEL_OFFSET: 35077, + MAX_VARYING_COMPONENTS: 35659, + TRANSFORM_FEEDBACK_BUFFER_MODE: 35967, + MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: 35968, + TRANSFORM_FEEDBACK_VARYINGS: 35971, + TRANSFORM_FEEDBACK_BUFFER_START: 35972, + TRANSFORM_FEEDBACK_BUFFER_SIZE: 35973, + TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: 35976, + RASTERIZER_DISCARD: 35977, + MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: 35978, + MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: 35979, + INTERLEAVED_ATTRIBS: 35980, + SEPARATE_ATTRIBS: 35981, + TRANSFORM_FEEDBACK_BUFFER: 35982, + TRANSFORM_FEEDBACK_BUFFER_BINDING: 35983, + RED_INTEGER: 36244, + RGB_INTEGER: 36248, + RGBA_INTEGER: 36249, + SAMPLER_CUBE_SHADOW: 36293, + INT_SAMPLER_CUBE: 36300, + UNSIGNED_INT_SAMPLER_CUBE: 36308, + FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: 33296, + FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: 33297, + FRAMEBUFFER_ATTACHMENT_RED_SIZE: 33298, + FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: 33299, + FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: 33300, + FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: 33301, + FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: 33302, + FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: 33303, + FRAMEBUFFER_DEFAULT: 33304, + UNSIGNED_NORMALIZED: 35863, + DRAW_FRAMEBUFFER_BINDING: 36006, + READ_FRAMEBUFFER: 36008, + DRAW_FRAMEBUFFER: 36009, + READ_FRAMEBUFFER_BINDING: 36010, + RENDERBUFFER_SAMPLES: 36011, + FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: 36052, + MAX_COLOR_ATTACHMENTS: 36063, + FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: 36182, + MAX_SAMPLES: 36183, + HALF_FLOAT: 5131, + RG: 33319, + RG_INTEGER: 33320, + VERTEX_ARRAY_BINDING: 34229, + SIGNED_NORMALIZED: 36764, + COPY_READ_BUFFER: 36662, + COPY_WRITE_BUFFER: 36663, + COPY_READ_BUFFER_BINDING: 36662, + COPY_WRITE_BUFFER_BINDING: 36663, + UNIFORM_BUFFER: 35345, + UNIFORM_BUFFER_BINDING: 35368, + UNIFORM_BUFFER_START: 35369, + UNIFORM_BUFFER_SIZE: 35370, + MAX_VERTEX_UNIFORM_BLOCKS: 35371, + MAX_FRAGMENT_UNIFORM_BLOCKS: 35373, + MAX_COMBINED_UNIFORM_BLOCKS: 35374, + MAX_UNIFORM_BUFFER_BINDINGS: 35375, + MAX_UNIFORM_BLOCK_SIZE: 35376, + MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: 35377, + MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: 35379, + UNIFORM_BUFFER_OFFSET_ALIGNMENT: 35380, + ACTIVE_UNIFORM_BLOCKS: 35382, + UNIFORM_TYPE: 35383, + UNIFORM_SIZE: 35384, + UNIFORM_BLOCK_INDEX: 35386, + UNIFORM_OFFSET: 35387, + UNIFORM_ARRAY_STRIDE: 35388, + UNIFORM_MATRIX_STRIDE: 35389, + UNIFORM_IS_ROW_MAJOR: 35390, + UNIFORM_BLOCK_BINDING: 35391, + UNIFORM_BLOCK_DATA_SIZE: 35392, + UNIFORM_BLOCK_ACTIVE_UNIFORMS: 35394, + UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: 35395, + UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: 35396, + UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: 35398, + INVALID_INDEX: 4294967295, + MAX_VERTEX_OUTPUT_COMPONENTS: 37154, + MAX_FRAGMENT_INPUT_COMPONENTS: 37157, + MAX_SERVER_WAIT_TIMEOUT: 37137, + OBJECT_TYPE: 37138, + SYNC_CONDITION: 37139, + SYNC_STATUS: 37140, + SYNC_FLAGS: 37141, + SYNC_FENCE: 37142, + SYNC_GPU_COMMANDS_COMPLETE: 37143, + UNSIGNALED: 37144, + SIGNALED: 37145, + ALREADY_SIGNALED: 37146, + TIMEOUT_EXPIRED: 37147, + CONDITION_SATISFIED: 37148, + WAIT_FAILED: 37149, + SYNC_FLUSH_COMMANDS_BIT: 1, + VERTEX_ATTRIB_ARRAY_DIVISOR: 35070, + ANY_SAMPLES_PASSED: 35887, + ANY_SAMPLES_PASSED_CONSERVATIVE: 36202, + SAMPLER_BINDING: 35097, + TRANSFORM_FEEDBACK: 36386, + TRANSFORM_FEEDBACK_PAUSED: 36387, + TRANSFORM_FEEDBACK_ACTIVE: 36388, + TRANSFORM_FEEDBACK_BINDING: 36389, + TEXTURE_IMMUTABLE_FORMAT: 37167, + MAX_ELEMENT_INDEX: 36203, + TEXTURE_IMMUTABLE_LEVELS: 33503, + TIMEOUT_IGNORED: -1, + MAX_CLIENT_WAIT_TIMEOUT_WEBGL: 37447, +}; + +const extensions: { [key: string]: any } = { + // ratified + OES_texture_float: {}, + OES_texture_half_float: {}, + WEBGL_lose_context: { + loseContext: () => {}, + }, + OES_standard_derivatives: {}, + OES_vertex_array_object: { + createVertexArrayOES: () => {}, + bindVertexArrayOES: () => {}, + deleteVertexArrayOES: () => {}, + }, + WEBGL_debug_renderer_info: null, + WEBGL_debug_shaders: null, + WEBGL_compressed_texture_s3tc: null, + WEBGL_depth_texture: {}, + OES_element_index_uint: {}, + EXT_texture_filter_anisotropic: null, + EXT_frag_depth: {}, + WEBGL_draw_buffers: {}, + ANGLE_instanced_arrays: null, + OES_texture_float_linear: null, + OES_texture_half_float_linear: null, + EXT_blend_minmax: { MIN_EXT: 0, MAX_EXT: 0 }, + EXT_shader_texture_lod: null, + // community + WEBGL_compressed_texture_atc: null, + WEBGL_compressed_texture_pvrtc: null, + EXT_color_buffer_half_float: null, + WEBGL_color_buffer_float: null, + EXT_sRGB: null, + WEBGL_compressed_texture_etc1: null, +}; + +export class WebGL2RenderingContext { + [key: string]: any; + + constructor(canvas: HTMLCanvasElement) { + this.canvas = canvas; + this.drawingBufferWidth = canvas.width; + this.drawingBufferHeight = canvas.height; + + for (const method of functions) { + this[method] ??= () => {}; + } + + Object.assign(this, enums); + } + + getShaderPrecisionFormat = () => { + return { + rangeMin: 127, + rangeMax: 127, + precision: 23, + }; + }; + + private GL_VERSION = 7938; + private SCISSOR_BOX = 3088; + private VIEWPORT = 2978; + + getParameter(paramId: number) { + switch (paramId) { + case this.GL_VERSION: + return ["WebGL2"]; + case this.SCISSOR_BOX: + case this.VIEWPORT: + return [0, 0, 1, 1]; + } + } + + getExtension(ext: string) { + return extensions[ext]; + } + + getProgramInfoLog = () => ""; + + getShaderInfoLog = () => ""; +} diff --git a/src/three-types.ts b/src/three-types.ts deleted file mode 100644 index 1ba31a2..0000000 --- a/src/three-types.ts +++ /dev/null @@ -1,685 +0,0 @@ -import * as THREE from "three"; -import { EventHandlers } from "./core/events"; -import { AttachType } from "./core/renderer"; -import { JSX } from "solid-js"; -import { BufferGeometry, Material } from "three"; -export type NonFunctionKeys = { - [K in keyof T]: T[K] extends Function ? never : K; -}[keyof T]; -export type Overwrite = Omit> & O; - -/** - * If **T** contains a constructor, @see ConstructorParameters must be used, otherwise **T**. - */ -type Args = T extends new (...args: any) => any - ? ConstructorParameters - : T; - -export type Euler = THREE.Euler | Parameters; -export type Matrix4 = THREE.Matrix4 | Parameters; -export type Vector2 = - | THREE.Vector2 - | Parameters - | Parameters[0]; -export type Vector3 = - | THREE.Vector3 - | Parameters - | Parameters[0]; -export type Vector4 = - | THREE.Vector4 - | Parameters - | Parameters[0]; -export type Color = - | ConstructorParameters - | THREE.Color - | number - | string; // Parameters will not work here because of multiple function signatures in three.js types -export type ColorArray = typeof THREE.Color | Parameters; -export type Layers = THREE.Layers | Parameters[0]; -export type Quaternion = THREE.Quaternion | Parameters; - -export type AttachCallback = - | string - | ((child: any, parentInstance: any) => void); - -export interface NodeProps { - attach?: AttachType; - /** Constructor arguments */ - args?: Args

; - children?: any; - ref?: T | ((instance: T) => void); - // key?: React.Key; - onUpdate?: (self: T) => void; -} - -export type Node = Overwrite, NodeProps>; - -export type Object3DNode = Overwrite< - Node, - { - position?: Vector3; - up?: Vector3; - scale?: Vector3; - rotation?: Euler; - matrix?: Matrix4; - quaternion?: Quaternion; - layers?: Layers; - dispose?: (() => void) | null; - - geometry?: JSX.Element | BufferGeometry | null; - material?: JSX.Element | Material | null; - } -> & - EventHandlers; - -export type BufferGeometryNode = Overwrite< - Node, - {} ->; -export type MaterialNode = Overwrite< - Node, - { color?: Color } ->; -export type LightNode = Overwrite< - Object3DNode, - { color?: Color } ->; - -// export type AudioProps = Object3DNode -export type AudioListenerProps = Object3DNode< - THREE.AudioListener, - typeof THREE.AudioListener ->; -export type PositionalAudioProps = Object3DNode< - THREE.PositionalAudio, - typeof THREE.PositionalAudio ->; - -export type MeshProps = Object3DNode; -export type InstancedMeshProps = Object3DNode< - THREE.InstancedMesh, - typeof THREE.InstancedMesh ->; -export type SceneProps = Object3DNode; -export type SpriteProps = Object3DNode; -export type LODProps = Object3DNode; -export type SkinnedMeshProps = Object3DNode< - THREE.SkinnedMesh, - typeof THREE.SkinnedMesh ->; - -export type SkeletonProps = Object3DNode; -export type BoneProps = Object3DNode; -export type LineSegmentsProps = Object3DNode< - THREE.LineSegments, - typeof THREE.LineSegments ->; -export type LineLoopProps = Object3DNode; -// export type LineProps = Object3DNode -export type PointsProps = Object3DNode; -export type GroupProps = Object3DNode; - -export type CameraProps = Object3DNode; -export type PerspectiveCameraProps = Object3DNode< - THREE.PerspectiveCamera, - typeof THREE.PerspectiveCamera ->; -export type OrthographicCameraProps = Object3DNode< - THREE.OrthographicCamera, - typeof THREE.OrthographicCamera ->; -export type CubeCameraProps = Object3DNode< - THREE.CubeCamera, - typeof THREE.CubeCamera ->; -export type ArrayCameraProps = Object3DNode< - THREE.ArrayCamera, - typeof THREE.ArrayCamera ->; - -export type InstancedBufferGeometryProps = BufferGeometryNode< - THREE.InstancedBufferGeometry, - typeof THREE.InstancedBufferGeometry ->; -export type BufferGeometryProps = BufferGeometryNode< - THREE.BufferGeometry, - typeof THREE.BufferGeometry ->; -export type BoxBufferGeometryProps = BufferGeometryNode< - THREE.BoxBufferGeometry, - typeof THREE.BoxBufferGeometry ->; -export type CircleBufferGeometryProps = BufferGeometryNode< - THREE.CircleBufferGeometry, - typeof THREE.CircleBufferGeometry ->; -export type ConeBufferGeometryProps = BufferGeometryNode< - THREE.ConeBufferGeometry, - typeof THREE.ConeBufferGeometry ->; -export type CylinderBufferGeometryProps = BufferGeometryNode< - THREE.CylinderBufferGeometry, - typeof THREE.CylinderBufferGeometry ->; -export type DodecahedronBufferGeometryProps = BufferGeometryNode< - THREE.DodecahedronBufferGeometry, - typeof THREE.DodecahedronBufferGeometry ->; -export type ExtrudeBufferGeometryProps = BufferGeometryNode< - THREE.ExtrudeBufferGeometry, - typeof THREE.ExtrudeBufferGeometry ->; -export type IcosahedronBufferGeometryProps = BufferGeometryNode< - THREE.IcosahedronBufferGeometry, - typeof THREE.IcosahedronBufferGeometry ->; -export type LatheBufferGeometryProps = BufferGeometryNode< - THREE.LatheBufferGeometry, - typeof THREE.LatheBufferGeometry ->; -export type OctahedronBufferGeometryProps = BufferGeometryNode< - THREE.OctahedronBufferGeometry, - typeof THREE.OctahedronBufferGeometry ->; -export type PlaneBufferGeometryProps = BufferGeometryNode< - THREE.PlaneBufferGeometry, - typeof THREE.PlaneBufferGeometry ->; -export type PolyhedronBufferGeometryProps = BufferGeometryNode< - THREE.PolyhedronBufferGeometry, - typeof THREE.PolyhedronBufferGeometry ->; -export type RingBufferGeometryProps = BufferGeometryNode< - THREE.RingBufferGeometry, - typeof THREE.RingBufferGeometry ->; -export type ShapeBufferGeometryProps = BufferGeometryNode< - THREE.ShapeBufferGeometry, - typeof THREE.ShapeBufferGeometry ->; -export type SphereBufferGeometryProps = BufferGeometryNode< - THREE.SphereBufferGeometry, - typeof THREE.SphereBufferGeometry ->; -export type TetrahedronBufferGeometryProps = BufferGeometryNode< - THREE.TetrahedronBufferGeometry, - typeof THREE.TetrahedronBufferGeometry ->; -export type TorusBufferGeometryProps = BufferGeometryNode< - THREE.TorusBufferGeometry, - typeof THREE.TorusBufferGeometry ->; -export type TorusKnotBufferGeometryProps = BufferGeometryNode< - THREE.TorusKnotBufferGeometry, - typeof THREE.TorusKnotBufferGeometry ->; -export type TubeBufferGeometryProps = BufferGeometryNode< - THREE.TubeBufferGeometry, - typeof THREE.TubeBufferGeometry ->; -export type WireframeGeometryProps = BufferGeometryNode< - THREE.WireframeGeometry, - typeof THREE.WireframeGeometry ->; -export type TetrahedronGeometryProps = BufferGeometryNode< - THREE.TetrahedronGeometry, - typeof THREE.TetrahedronGeometry ->; -export type OctahedronGeometryProps = BufferGeometryNode< - THREE.OctahedronGeometry, - typeof THREE.OctahedronGeometry ->; -export type IcosahedronGeometryProps = BufferGeometryNode< - THREE.IcosahedronGeometry, - typeof THREE.IcosahedronGeometry ->; -export type DodecahedronGeometryProps = BufferGeometryNode< - THREE.DodecahedronGeometry, - typeof THREE.DodecahedronGeometry ->; -export type PolyhedronGeometryProps = BufferGeometryNode< - THREE.PolyhedronGeometry, - typeof THREE.PolyhedronGeometry ->; -export type TubeGeometryProps = BufferGeometryNode< - THREE.TubeGeometry, - typeof THREE.TubeGeometry ->; -export type TorusKnotGeometryProps = BufferGeometryNode< - THREE.TorusKnotGeometry, - typeof THREE.TorusKnotGeometry ->; -export type TorusGeometryProps = BufferGeometryNode< - THREE.TorusGeometry, - typeof THREE.TorusGeometry ->; -export type SphereGeometryProps = BufferGeometryNode< - THREE.SphereGeometry, - typeof THREE.SphereGeometry ->; -export type RingGeometryProps = BufferGeometryNode< - THREE.RingGeometry, - typeof THREE.RingGeometry ->; -export type PlaneGeometryProps = BufferGeometryNode< - THREE.PlaneGeometry, - typeof THREE.PlaneGeometry ->; -export type LatheGeometryProps = BufferGeometryNode< - THREE.LatheGeometry, - typeof THREE.LatheGeometry ->; -export type ShapeGeometryProps = BufferGeometryNode< - THREE.ShapeGeometry, - typeof THREE.ShapeGeometry ->; -export type ExtrudeGeometryProps = BufferGeometryNode< - THREE.ExtrudeGeometry, - typeof THREE.ExtrudeGeometry ->; -export type EdgesGeometryProps = BufferGeometryNode< - THREE.EdgesGeometry, - typeof THREE.EdgesGeometry ->; -export type ConeGeometryProps = BufferGeometryNode< - THREE.ConeGeometry, - typeof THREE.ConeGeometry ->; -export type CylinderGeometryProps = BufferGeometryNode< - THREE.CylinderGeometry, - typeof THREE.CylinderGeometry ->; -export type CircleGeometryProps = BufferGeometryNode< - THREE.CircleGeometry, - typeof THREE.CircleGeometry ->; -export type BoxGeometryProps = BufferGeometryNode< - THREE.BoxGeometry, - typeof THREE.BoxGeometry ->; - -export type MaterialProps = MaterialNode< - THREE.Material, - [THREE.MaterialParameters] ->; -export type ShadowMaterialProps = MaterialNode< - THREE.ShadowMaterial, - [THREE.ShaderMaterialParameters] ->; -export type SpriteMaterialProps = MaterialNode< - THREE.SpriteMaterial, - [THREE.SpriteMaterialParameters] ->; -export type RawShaderMaterialProps = MaterialNode< - THREE.RawShaderMaterial, - [THREE.ShaderMaterialParameters] ->; -export type ShaderMaterialProps = MaterialNode< - THREE.ShaderMaterial, - [THREE.ShaderMaterialParameters] ->; -export type PointsMaterialProps = MaterialNode< - THREE.PointsMaterial, - [THREE.PointsMaterialParameters] ->; -export type MeshPhysicalMaterialProps = MaterialNode< - THREE.MeshPhysicalMaterial, - [THREE.MeshPhysicalMaterialParameters] ->; -export type MeshStandardMaterialProps = MaterialNode< - THREE.MeshStandardMaterial, - [THREE.MeshStandardMaterialParameters] ->; -export type MeshPhongMaterialProps = MaterialNode< - THREE.MeshPhongMaterial, - [THREE.MeshPhongMaterialParameters] ->; -export type MeshToonMaterialProps = MaterialNode< - THREE.MeshToonMaterial, - [THREE.MeshToonMaterialParameters] ->; -export type MeshNormalMaterialProps = MaterialNode< - THREE.MeshNormalMaterial, - [THREE.MeshNormalMaterialParameters] ->; -export type MeshLambertMaterialProps = MaterialNode< - THREE.MeshLambertMaterial, - [THREE.MeshLambertMaterialParameters] ->; -export type MeshDepthMaterialProps = MaterialNode< - THREE.MeshDepthMaterial, - [THREE.MeshDepthMaterialParameters] ->; -export type MeshDistanceMaterialProps = MaterialNode< - THREE.MeshDistanceMaterial, - [THREE.MeshDistanceMaterialParameters] ->; -export type MeshBasicMaterialProps = MaterialNode< - THREE.MeshBasicMaterial, - [THREE.MeshBasicMaterialParameters] ->; -export type MeshMatcapMaterialProps = MaterialNode< - THREE.MeshMatcapMaterial, - [THREE.MeshMatcapMaterialParameters] ->; -export type LineDashedMaterialProps = MaterialNode< - THREE.LineDashedMaterial, - [THREE.LineDashedMaterialParameters] ->; -export type LineBasicMaterialProps = MaterialNode< - THREE.LineBasicMaterial, - [THREE.LineBasicMaterialParameters] ->; - -export type PrimitiveProps = { object: any } & { [properties: string]: any }; - -export type LightProps = LightNode; -export type SpotLightShadowProps = Node< - THREE.SpotLightShadow, - typeof THREE.SpotLightShadow ->; -export type SpotLightProps = LightNode; -export type PointLightProps = LightNode< - THREE.PointLight, - typeof THREE.PointLight ->; -export type RectAreaLightProps = LightNode< - THREE.RectAreaLight, - typeof THREE.RectAreaLight ->; -export type HemisphereLightProps = LightNode< - THREE.HemisphereLight, - typeof THREE.HemisphereLight ->; -export type DirectionalLightShadowProps = Node< - THREE.DirectionalLightShadow, - typeof THREE.DirectionalLightShadow ->; -export type DirectionalLightProps = LightNode< - THREE.DirectionalLight, - typeof THREE.DirectionalLight ->; -export type AmbientLightProps = LightNode< - THREE.AmbientLight, - typeof THREE.AmbientLight ->; -export type LightShadowProps = Node< - THREE.LightShadow, - typeof THREE.LightShadow ->; -export type AmbientLightProbeProps = LightNode< - THREE.AmbientLightProbe, - typeof THREE.AmbientLightProbe ->; -export type HemisphereLightProbeProps = LightNode< - THREE.HemisphereLightProbe, - typeof THREE.HemisphereLightProbe ->; -export type LightProbeProps = LightNode< - THREE.LightProbe, - typeof THREE.LightProbe ->; - -export type SpotLightHelperProps = Object3DNode< - THREE.SpotLightHelper, - typeof THREE.SpotLightHelper ->; -export type SkeletonHelperProps = Object3DNode< - THREE.SkeletonHelper, - typeof THREE.SkeletonHelper ->; -export type PointLightHelperProps = Object3DNode< - THREE.PointLightHelper, - typeof THREE.PointLightHelper ->; -export type HemisphereLightHelperProps = Object3DNode< - THREE.HemisphereLightHelper, - typeof THREE.HemisphereLightHelper ->; -export type GridHelperProps = Object3DNode< - THREE.GridHelper, - typeof THREE.GridHelper ->; -export type PolarGridHelperProps = Object3DNode< - THREE.PolarGridHelper, - typeof THREE.PolarGridHelper ->; -export type DirectionalLightHelperProps = Object3DNode< - THREE.DirectionalLightHelper, - typeof THREE.DirectionalLightHelper ->; -export type CameraHelperProps = Object3DNode< - THREE.CameraHelper, - typeof THREE.CameraHelper ->; -export type BoxHelperProps = Object3DNode< - THREE.BoxHelper, - typeof THREE.BoxHelper ->; -export type Box3HelperProps = Object3DNode< - THREE.Box3Helper, - typeof THREE.Box3Helper ->; -export type PlaneHelperProps = Object3DNode< - THREE.PlaneHelper, - typeof THREE.PlaneHelper ->; -export type ArrowHelperProps = Object3DNode< - THREE.ArrowHelper, - typeof THREE.ArrowHelper ->; -export type AxesHelperProps = Object3DNode< - THREE.AxesHelper, - typeof THREE.AxesHelper ->; - -export type TextureProps = Node; -export type VideoTextureProps = Node< - THREE.VideoTexture, - typeof THREE.VideoTexture ->; -export type DataTextureProps = Node< - THREE.DataTexture, - typeof THREE.DataTexture ->; -export type DataTexture3DProps = Node< - THREE.DataTexture3D, - typeof THREE.DataTexture3D ->; -export type CompressedTextureProps = Node< - THREE.CompressedTexture, - typeof THREE.CompressedTexture ->; -export type CubeTextureProps = Node< - THREE.CubeTexture, - typeof THREE.CubeTexture ->; -export type CanvasTextureProps = Node< - THREE.CanvasTexture, - typeof THREE.CanvasTexture ->; -export type DepthTextureProps = Node< - THREE.DepthTexture, - typeof THREE.DepthTexture ->; - -export type RaycasterProps = Node; -export type Vector2Props = Node; -export type Vector3Props = Node; -export type Vector4Props = Node; -export type EulerProps = Node; -export type Matrix3Props = Node; -export type Matrix4Props = Node; -export type QuaternionProps = Node; -export type BufferAttributeProps = Node< - THREE.BufferAttribute, - typeof THREE.BufferAttribute ->; -export type Float32BufferAttributeProps = Node< - THREE.Float32BufferAttribute, - typeof THREE.Float32BufferAttribute ->; -export type InstancedBufferAttributeProps = Node< - THREE.InstancedBufferAttribute, - typeof THREE.InstancedBufferAttribute ->; -export type ColorProps = Node; -export type FogProps = Node; -export type FogExp2Props = Node; -export type ShapeProps = Node; - -declare module "solid-js" { - // eslint-disable-next-line @typescript-eslint/no-namespace - namespace JSX { - interface IntrinsicElements { - // `audio` works but conflicts with @types/react. Try using Audio from react-three-fiber/components instead - // audio: AudioProps - audioListener: AudioListenerProps; - positionalAudio: PositionalAudioProps; - - mesh: MeshProps; - instancedMesh: InstancedMeshProps; - scene: SceneProps; - sprite: SpriteProps; - lOD: LODProps; - skinnedMesh: SkinnedMeshProps; - skeleton: SkeletonProps; - bone: BoneProps; - lineSegments: LineSegmentsProps; - lineLoop: LineLoopProps; - // see `audio` - // line: LineProps - points: PointsProps; - group: GroupProps; - - // cameras - camera: CameraProps; - perspectiveCamera: PerspectiveCameraProps; - orthographicCamera: OrthographicCameraProps; - cubeCamera: CubeCameraProps; - arrayCamera: ArrayCameraProps; - - // geometry - instancedBufferGeometry: InstancedBufferGeometryProps; - bufferGeometry: BufferGeometryProps; - boxBufferGeometry: BoxBufferGeometryProps; - circleBufferGeometry: CircleBufferGeometryProps; - coneBufferGeometry: ConeBufferGeometryProps; - cylinderBufferGeometry: CylinderBufferGeometryProps; - dodecahedronBufferGeometry: DodecahedronBufferGeometryProps; - extrudeBufferGeometry: ExtrudeBufferGeometryProps; - icosahedronBufferGeometry: IcosahedronBufferGeometryProps; - latheBufferGeometry: LatheBufferGeometryProps; - octahedronBufferGeometry: OctahedronBufferGeometryProps; - planeBufferGeometry: PlaneBufferGeometryProps; - polyhedronBufferGeometry: PolyhedronBufferGeometryProps; - ringBufferGeometry: RingBufferGeometryProps; - shapeBufferGeometry: ShapeBufferGeometryProps; - sphereBufferGeometry: SphereBufferGeometryProps; - tetrahedronBufferGeometry: TetrahedronBufferGeometryProps; - torusBufferGeometry: TorusBufferGeometryProps; - torusKnotBufferGeometry: TorusKnotBufferGeometryProps; - tubeBufferGeometry: TubeBufferGeometryProps; - wireframeGeometry: WireframeGeometryProps; - tetrahedronGeometry: TetrahedronGeometryProps; - octahedronGeometry: OctahedronGeometryProps; - icosahedronGeometry: IcosahedronGeometryProps; - dodecahedronGeometry: DodecahedronGeometryProps; - polyhedronGeometry: PolyhedronGeometryProps; - tubeGeometry: TubeGeometryProps; - torusKnotGeometry: TorusKnotGeometryProps; - torusGeometry: TorusGeometryProps; - sphereGeometry: SphereGeometryProps; - ringGeometry: RingGeometryProps; - planeGeometry: PlaneGeometryProps; - latheGeometry: LatheGeometryProps; - shapeGeometry: ShapeGeometryProps; - extrudeGeometry: ExtrudeGeometryProps; - edgesGeometry: EdgesGeometryProps; - coneGeometry: ConeGeometryProps; - cylinderGeometry: CylinderGeometryProps; - circleGeometry: CircleGeometryProps; - boxGeometry: BoxGeometryProps; - - // materials - material: MaterialProps; - shadowMaterial: ShadowMaterialProps; - spriteMaterial: SpriteMaterialProps; - rawShaderMaterial: RawShaderMaterialProps; - shaderMaterial: ShaderMaterialProps; - pointsMaterial: PointsMaterialProps; - meshPhysicalMaterial: MeshPhysicalMaterialProps; - meshStandardMaterial: MeshStandardMaterialProps; - meshPhongMaterial: MeshPhongMaterialProps; - meshToonMaterial: MeshToonMaterialProps; - meshNormalMaterial: MeshNormalMaterialProps; - meshLambertMaterial: MeshLambertMaterialProps; - meshDepthMaterial: MeshDepthMaterialProps; - meshDistanceMaterial: MeshDistanceMaterialProps; - meshBasicMaterial: MeshBasicMaterialProps; - meshMatcapMaterial: MeshMatcapMaterialProps; - lineDashedMaterial: LineDashedMaterialProps; - lineBasicMaterial: LineBasicMaterialProps; - - // primitive - primitive: PrimitiveProps; - - // lights and other - light: LightProps; - spotLightShadow: SpotLightShadowProps; - spotLight: SpotLightProps; - pointLight: PointLightProps; - rectAreaLight: RectAreaLightProps; - hemisphereLight: HemisphereLightProps; - directionalLightShadow: DirectionalLightShadowProps; - directionalLight: DirectionalLightProps; - ambientLight: AmbientLightProps; - lightShadow: LightShadowProps; - ambientLightProbe: AmbientLightProbeProps; - hemisphereLightProbe: HemisphereLightProbeProps; - lightProbe: LightProbeProps; - - // helpers - spotLightHelper: SpotLightHelperProps; - skeletonHelper: SkeletonHelperProps; - pointLightHelper: PointLightHelperProps; - hemisphereLightHelper: HemisphereLightHelperProps; - gridHelper: GridHelperProps; - polarGridHelper: PolarGridHelperProps; - directionalLightHelper: DirectionalLightHelperProps; - cameraHelper: CameraHelperProps; - boxHelper: BoxHelperProps; - box3Helper: Box3HelperProps; - planeHelper: PlaneHelperProps; - arrowHelper: ArrowHelperProps; - axesHelper: AxesHelperProps; - - // textures - texture: TextureProps; - videoTexture: VideoTextureProps; - dataTexture: DataTextureProps; - dataTexture3D: DataTexture3DProps; - compressedTexture: CompressedTextureProps; - cubeTexture: CubeTextureProps; - canvasTexture: CanvasTextureProps; - depthTexture: DepthTextureProps; - - // misc - raycaster: RaycasterProps; - vector2: Vector2Props; - vector3: Vector3Props; - vector4: Vector4Props; - euler: EulerProps; - matrix3: Matrix3Props; - matrix4: Matrix4Props; - quaternion: QuaternionProps; - bufferAttribute: BufferAttributeProps; - float32BufferAttribute: Float32BufferAttributeProps; - instancedBufferAttribute: InstancedBufferAttributeProps; - color: ColorProps; - fog: FogProps; - fogExp2: FogExp2Props; - shape: ShapeProps; - } - } -} diff --git a/src/type-utils.ts b/src/type-utils.ts new file mode 100644 index 0000000..413e8c0 --- /dev/null +++ b/src/type-utils.ts @@ -0,0 +1,81 @@ +/** Generic constructor. Returns instance of given type. Defaults to any. */ +export type Constructor = new (...args: any[]) => T; + +/** Extracts the instance from a constructor. */ +export type InstanceFromConstructor = TConstructor extends Constructor + ? TObject + : TConstructor; + +/** Omit function-properties from given type. */ +type OmitFunctionProperties = { [K in keyof T]: T[K] extends Function ? never : K }[keyof T]; +/** Overwrites the properties in `T` with the properties from `O`. */ +export type Overwrite = Omit> & O; + +type ExcludeUnknown = T extends Array ? ({} extends I & {} ? never : T) : T; +/** + * Extracts the parameters of all possible overloads of a given constructor. + * + * @example + * class Example { + * constructor(a: string); + * constructor(a: number, b: boolean); + * constructor(a: any, b?: any) { + * // Implementation + * } + * } + * + * type ExampleParameters = ConstructorOverloadParameters; + * // ExampleParameters will be equivalent to: [string] | [number, boolean] + */ +export type ConstructorOverloadParameters = ExcludeUnknown< + T extends { + new (...o: infer U): void; + new (...o: infer U2): void; + new (...o: infer U3): void; + new (...o: infer U4): void; + new (...o: infer U5): void; + new (...o: infer U6): void; + new (...o: infer U7): void; + } + ? U | U2 | U3 | U4 | U5 | U6 | U7 + : T extends { + new (...o: infer U): void; + new (...o: infer U2): void; + new (...o: infer U3): void; + new (...o: infer U4): void; + new (...o: infer U5): void; + new (...o: infer U6): void; + } + ? U | U2 | U3 | U4 | U5 | U6 + : T extends { + new (...o: infer U): void; + new (...o: infer U2): void; + new (...o: infer U3): void; + new (...o: infer U4): void; + new (...o: infer U5): void; + } + ? U | U2 | U3 | U4 | U5 + : T extends { + new (...o: infer U): void; + new (...o: infer U2): void; + new (...o: infer U3): void; + new (...o: infer U4): void; + } + ? U | U2 | U3 | U4 + : T extends { + new (...o: infer U): void; + new (...o: infer U2): void; + new (...o: infer U3): void; + } + ? U | U2 | U3 + : T extends { + new (...o: infer U): void; + new (...o: infer U2): void; + } + ? U | U2 + : T extends { + new (...o: infer U): void; + } + ? U + : never +>; diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..8cc94b4 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,173 @@ +import { Accessor, JSX, Setter, Component as SolidComponent } from "solid-js"; +import type * as THREE from "three"; +import { S3 } from "."; +import { $S3C } from "./augment"; +import { Portal, Primitive } from "./components"; +import { + Constructor, + ConstructorOverloadParameters, + InstanceFromConstructor, + Overwrite, +} from "./type-utils"; + +declare global { + namespace SolidThree { + interface Components { + Primitive: typeof Primitive; + Portal: typeof Portal; + } + interface Elements {} + } +} + +/** `solid-three` context. Accessible via `useThree`. */ +export type Context = ContextElements & { + canvas: HTMLCanvasElement; + render: (delta: number) => void; + requestRender: () => void; + pointer: THREE.Vector2; + setPointer: Setter; + xr: { + connect: () => void; + disconnect: () => void; + }; +}; + +type ContextElements = { + camera: Instance; + setCamera: (camera: S3.CameraType | Accessor) => () => void; + gl: Instance; + setGl: (gl: THREE.WebGLRenderer | Accessor) => () => void; + raycaster: Instance; + setRaycaster: (raycaster: THREE.Raycaster | Accessor) => () => void; + scene: Instance | Instance; + setScene: (scene: THREE.Scene | Accessor) => () => void; +}; + +/** Possible camera types. */ +export type CameraType = THREE.PerspectiveCamera | THREE.OrthographicCamera; + +/**********************************************************************************/ +/* */ +/* Event */ +/* */ +/**********************************************************************************/ + +/** Generic `solid-three` event. */ +export type Event = { + nativeEvent: TEvent; + stopped: boolean; + stopPropagation: () => void; +}; + +/** Event handlers for various `solid-three` events. */ +export type EventHandlers = { + onClick: (event: Event) => void; + onDoubleClick: (event: Event) => void; + onContextMenu: (event: Event) => void; + onMouseDown: (event: Event) => void; + onMouseEnter: (event: Event) => void; + onMouseLeave: (event: Event) => void; + onMouseMove: (event: Event) => void; + onMouseUp: (event: Event) => void; + onPointerUp: (event: Event) => void; + onPointerDown: (event: Event) => void; + onPointerMove: (event: Event) => void; + onPointerEnter: (event: Event) => void; + onPointerLeave: (event: Event) => void; + onPointerMissed: (event: Event) => void; + onWheel: (event: Event) => void; +}; + +/** The names of all `SolidThreeEventHandlers` */ +export type EventName = keyof EventHandlers; + +/**********************************************************************************/ +/* */ +/* Solid Three Representation */ +/* */ +/**********************************************************************************/ + +interface ThreeMathRepresentation { + set(...args: number[]): any; +} +interface ThreeVectorRepresentation extends ThreeMathRepresentation { + setScalar(s: number): any; +} + +/** Map given type to `solid-three` representation. */ +type Representation = T extends THREE.Color + ? ConstructorParameters | THREE.ColorRepresentation + : T extends ThreeVectorRepresentation | THREE.Layers | THREE.Euler + ? T | Parameters | number + : T extends ThreeMathRepresentation + ? T | Parameters + : T; + +export type Vector2 = Representation; +export type Vector3 = Representation; +export type Vector4 = Representation; +export type Color = Representation; +export type Layers = Representation; +export type Quaternion = Representation; +export type Euler = Representation; +export type Matrix3 = Representation; +export type Matrix4 = Representation; + +/**********************************************************************************/ +/* */ +/* Three To JSX */ +/* */ +/**********************************************************************************/ + +type ExtractConstructors = T extends Constructor ? T : never; +/** All constructors within the `THREE` namespace */ +type ThreeConstructors = ExtractConstructors<(typeof THREE)[keyof typeof THREE]>; + +/** Generic instance of a given `Constructor`. */ +export type ThreeInstance = InstanceFromConstructor; + +/** Instance of a given constructor augmented with `S3Metadata`. Defaults to `ThreeConstructor`*/ +export type Instance = InstanceFromConstructor & { + [$S3C]: Metadata; +}; + +/** Metadata of a `solid-three` instance. */ +export type Metadata = { + props?: ClassProps>; + children: Set; +}; + +/** Generic `solid-three` component. */ +export type Component = SolidComponent>; + +/** Maps properties of given type to their `solid-three` representations. */ +type MapToRepresentation = { + [TKey in keyof T]: Representation; +}; + +/** Generic `solid-three` props of a given class. */ +export type ClassProps = Partial< + Overwrite< + MapToRepresentation>, + { + args: T extends Constructor ? ConstructorOverloadParameters : unknown; + attach: + | string + | (( + parent: Instance, + self: Instance>, + ) => () => void); + children?: JSX.Element; + onUpdate: (self: Instance>) => void; + } & EventHandlers + > +>; + +/** Generic `solid-three` props of a given type. */ +export type Props = + T extends keyof typeof THREE + ? ClassProps<(typeof THREE)[T]> + : T extends keyof SolidThree.Elements + ? ClassProps + : never; diff --git a/src/utils/build-graph.ts b/src/utils/build-graph.ts new file mode 100644 index 0000000..972cde4 --- /dev/null +++ b/src/utils/build-graph.ts @@ -0,0 +1,18 @@ +import { Material, Object3D } from "three"; + +export interface ObjectMap { + nodes: { [name: string]: Object3D }; + materials: { [name: string]: Material }; +} +// Collects nodes and materials from a THREE.Object3D +export function buildGraph(object: Object3D): ObjectMap { + const data: ObjectMap = { nodes: {}, materials: {} }; + if (object) { + object.traverse((obj: any) => { + if (obj.name) data.nodes[obj.name] = obj; + if (obj.material && !data.materials[obj.material.name]) + data.materials[obj.material.name] = obj.material; + }); + } + return data; +} diff --git a/src/utils/default-props.ts b/src/utils/default-props.ts new file mode 100644 index 0000000..b3962ea --- /dev/null +++ b/src/utils/default-props.ts @@ -0,0 +1,13 @@ +import { MergeProps, mergeProps } from "solid-js"; + +/** Extracts the keys of the optional properties in T. */ +type KeyOfOptionals = keyof { + [K in keyof T as T extends Record ? never : K]: T[K]; +}; + +export function defaultProps>( + props: T, + defaults: Required>, +): MergeProps<[Required>, T]> { + return mergeProps(defaults, props); +} diff --git a/src/utils/has-colorspace.ts b/src/utils/has-colorspace.ts new file mode 100644 index 0000000..921b954 --- /dev/null +++ b/src/utils/has-colorspace.ts @@ -0,0 +1,11 @@ +import { Renderer } from "three"; + +/** + * Returns `true` with correct TS type inference if an object has a configurable color space (since r152). + */ +export const hasColorSpace = < + T extends Renderer | THREE.Texture | object, + P = T extends Renderer ? { outputColorSpace: string } : { colorSpace: string }, +>( + object: T, +): object is T & P => "colorSpace" in object || "outputColorSpace" in object; diff --git a/src/utils/is-augmented-element.ts b/src/utils/is-augmented-element.ts new file mode 100644 index 0000000..c7cacd9 --- /dev/null +++ b/src/utils/is-augmented-element.ts @@ -0,0 +1,5 @@ +import { S3 } from "../"; +import { $S3C } from "../augment"; + +export const isAugmentedElement = (element: any): element is S3.Instance => + typeof element === "object" && $S3C in element; diff --git a/src/utils/remove-element-from-array.ts b/src/utils/remove-element-from-array.ts new file mode 100644 index 0000000..45db4d1 --- /dev/null +++ b/src/utils/remove-element-from-array.ts @@ -0,0 +1,5 @@ +export const removeElementFromArray = (array: any[], value: any) => { + const index = array.indexOf(value); + if (index !== -1) array.splice(index, 1); + return array; +}; diff --git a/src/utils/resolve.ts b/src/utils/resolve.ts new file mode 100644 index 0000000..306aca6 --- /dev/null +++ b/src/utils/resolve.ts @@ -0,0 +1,9 @@ +import { Accessor } from "solid-js"; + +export function resolve(child: Accessor | T, recursive = false): T { + return typeof child !== "function" + ? child + : recursive + ? resolve((child as Accessor)()) + : (child as Accessor)(); +} diff --git a/src/utils/with-context.ts b/src/utils/with-context.ts new file mode 100644 index 0000000..243a062 --- /dev/null +++ b/src/utils/with-context.ts @@ -0,0 +1,92 @@ +import { Accessor, Context, JSX } from "solid-js"; + +export type ContextProviderProps = { + children?: JSX.Element; +} & Record; +export type ContextProvider = ( + props: { children: JSX.Element } & T, +) => JSX.Element; +/** + * A utility-function to provide context to components. + * + * @param children Accessor of Children + * @param context Context + * @param value T + * + * @example + * ```tsx + * const NumberContext = createContext + * + * const children = withContext( + * () => props.children, + * NumberContext, + * 1 + * ) + * ``` + */ + +export function withContext( + children: Accessor, + context: Context, + value: T, +) { + let result: TResult; + + context.Provider({ + value, + children: (() => { + result = children(); + return ""; + }) as any as JSX.Element, + }); + + return result!; +} + +/* + +Type validation of the `values` array thanks to the amazing @otonashixav (https://github.com/otonashixav) + +*/ + +/** + * A utility-function to provide multiple context to components. + * + * @param children Accessor of Children + * @param values Array of tuples of `[Context, value T]`. + * + * @example + * ```tsx + * const NumberContext = createContext + * const StringContext = createContext + * const children = withContext( + * () => props.children, + * [ + * [NumberContext, 1], + * [StringContext, "string"] + * ] + * ) + * ``` + */ + +export function withMultiContexts( + children: () => TResult, + values: { + [K in keyof T]: readonly [Context, [T[K]][T extends unknown ? 0 : never]]; + }, +) { + let result: TResult; + + (values as [Context, any]).reduce((acc, [context, value], index) => { + return () => + context.Provider({ + value, + children: () => { + if (index === 0) result = acc(); + else acc(); + }, + }); + }, children)(); + + return result!; +} diff --git a/src/web/Canvas.tsx b/src/web/Canvas.tsx deleted file mode 100644 index 1fcac3f..0000000 --- a/src/web/Canvas.tsx +++ /dev/null @@ -1,109 +0,0 @@ -import * as THREE from "three"; -import { extend, createThreeRoot, RenderProps } from "../core"; -import { createPointerEvents } from "./events"; -import { RootState, ThreeContext } from "../core/store"; -import { Accessor, createEffect, onCleanup, JSX, mergeProps } from "solid-js"; -import { insert } from "../renderer"; -import { Instance } from "../core/renderer"; -import { StoreApi } from "zustand/vanilla"; -import { EventManager } from "../core/events"; -import { log } from "../solid"; -import { threeReconciler } from ".."; - -extend(THREE); - -export interface Props extends Omit, "size" | "events"> { - // , - // HTMLAttributes - children: JSX.Element; - fallback?: JSX.Element; - // resize?: ResizeOptions - events?: (store: StoreApi) => EventManager; - id?: string; - class?: string; - height?: string; - width?: string; - tabIndex?: number; - // style?: CSSProperties; -} - -// type SetBlock = false | Promise | null; - -// const CANVAS_PROPS: Array = [ -// "gl", -// "events", -// "shadows", -// "linear", -// "flat", -// "orthographic", -// "frameloop", -// "dpr", -// "performance", -// "clock", -// "raycaster", -// "camera", -// "onPointerMissed", -// "onCreated", -// ]; - -export function Canvas(props: Props) { - props = mergeProps( - { - height: "100vh", - width: "100vw" - }, - props - ); - - let canvas: HTMLCanvasElement = () as any; - let containerRef: HTMLDivElement = ( -

- {canvas} -
- ) as any; - - const root = createThreeRoot(canvas, { - events: createPointerEvents, - size: containerRef.getBoundingClientRect(), - camera: props.camera, - shadows: props.shadows, - onPointerMissed: props.onPointerMissed - // TODO: add the rest of the canvas props! - }); - - new ResizeObserver(entries => { - if (entries[0]?.target !== containerRef) return; - root.getState().setSize(entries[0].contentRect.width, entries[0].contentRect.height); - }).observe(containerRef); - - insert( - root.getState().scene as unknown as Instance, - ( - ( - {props.children} - ) as unknown as Accessor - )() - ); - - onCleanup(() => { - log("three", "cleanup"); - threeReconciler.removeRecursive( - root.getState().scene.children as any, - root.getState().scene as any, - true - ); - root.getState().scene.clear(); - }); - - return containerRef; -} diff --git a/src/web/events.ts b/src/web/events.ts deleted file mode 100644 index 7a81976..0000000 --- a/src/web/events.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { StoreApi as UseStore } from "zustand/vanilla"; -import { RootState } from "../core/store"; -import { EventManager, Events, createEvents } from "../core/events"; - -const DOM_EVENTS = { - onClick: ["click", false], - onContextMenu: ["contextmenu", false], - onDoubleClick: ["dblclick", false], - onWheel: ["wheel", true], - onPointerDown: ["pointerdown", true], - onPointerUp: ["pointerup", true], - onPointerLeave: ["pointerleave", true], - onPointerMove: ["pointermove", true], - onPointerCancel: ["pointercancel", true], - onLostPointerCapture: ["lostpointercapture", true], -} as const; - -export function createPointerEvents( - store: UseStore -): EventManager { - const { handlePointer } = createEvents(store); - - return { - connected: false, - handlers: Object.keys(DOM_EVENTS).reduce( - (acc, key) => ({ ...acc, [key]: handlePointer(key) }), - {} - ) as unknown as Events, - connect: (target: HTMLElement) => { - const { set, events } = store.getState(); - events.disconnect?.(); - set((state) => ({ events: { ...state.events, connected: target } })); - Object.entries(events?.handlers ?? []).forEach(([name, event]) => { - const [eventName, passive] = - DOM_EVENTS[name as keyof typeof DOM_EVENTS]; - target.addEventListener(eventName, event, { passive }); - }); - }, - disconnect: () => { - const { set, events } = store.getState(); - if (events.connected) { - Object.entries(events.handlers ?? []).forEach(([name, event]) => { - if (events && events.connected instanceof HTMLElement) { - const [eventName] = DOM_EVENTS[name as keyof typeof DOM_EVENTS]; - events.connected.removeEventListener(eventName, event); - } - }); - set((state) => ({ events: { ...state.events, connected: false } })); - } - }, - }; -} diff --git a/tests/core/events.test.tsx b/tests/core/events.test.tsx new file mode 100644 index 0000000..e2b5453 --- /dev/null +++ b/tests/core/events.test.tsx @@ -0,0 +1,370 @@ +import { fireEvent } from "@solidjs/testing-library"; +import { describe, expect, it, vi } from "vitest"; + +import { Show, createSignal } from "solid-js"; +import { T } from "../../src"; +import { test } from "../../src/testing"; + +describe("events", () => { + it("can handle onPointerDown", async () => { + const handlePointerDown = vi.fn(); + + const { canvas, waitTillNextFrame } = test(() => ( + + + + + )); + + const evt = new Event("mousedown"); + Object.defineProperty(evt, "offsetX", { get: () => 640 }); + Object.defineProperty(evt, "offsetY", { get: () => 400 }); + + fireEvent(canvas, evt); + + expect(handlePointerDown).toHaveBeenCalled(); + }); + + // TODO: implement onPointerMissed-api + // NOTE: unsure if/how we should implement onPointerMissed + // the heuristics are unclear imo + + it("can handle onPointerMissed", async () => { + const handleClick = vi.fn(); + const handleMissed = vi.fn(); + + const { canvas } = test(() => ( + + + + + )); + + const evt = new MouseEvent("click"); + Object.defineProperty(evt, "offsetX", { get: () => 0 }); + Object.defineProperty(evt, "offsetY", { get: () => 0 }); + + fireEvent(canvas, evt); + + expect(handleClick).not.toHaveBeenCalled(); + expect(handleMissed).toHaveBeenCalledWith(evt); + }); + + // TODO: implement onPointerMissed-api + + // it("should not fire onPointerMissed when same element is clicked", async () => { + // const handleClick = vi.fn(); + // const handleMissed = vi.fn(); + + // const { canvas } = test(() => ( + // + // + // + // + // )); + + // const down = new Event("pointerdown"); + // Object.defineProperty(down, "offsetX", { get: () => 577 }); + // Object.defineProperty(down, "offsetY", { get: () => 480 }); + + // fireEvent(canvas, down); + + // const up = new Event("pointerup"); + // Object.defineProperty(up, "offsetX", { get: () => 577 }); + // Object.defineProperty(up, "offsetY", { get: () => 480 }); + + // const evt = new MouseEvent("click"); + // Object.defineProperty(evt, "offsetX", { get: () => 577 }); + // Object.defineProperty(evt, "offsetY", { get: () => 480 }); + + // fireEvent(canvas, evt); + + // expect(handleClick).toHaveBeenCalled(); + // expect(handleMissed).not.toHaveBeenCalled(); + // }); + + // TODO: implement onPointerMissed-api + + // it("should not fire onPointerMissed on parent when child element is clicked", async () => { + // const handleClick = vi.fn(); + // const handleMissed = vi.fn(); + + // const { canvas } = test(() => ( + // + // + // + // + // + // + // )); + + // const down = new Event("pointerdown"); + // Object.defineProperty(down, "offsetX", { get: () => 577 }); + // Object.defineProperty(down, "offsetY", { get: () => 480 }); + + // fireEvent(canvas, down); + + // const up = new Event("pointerup"); + // Object.defineProperty(up, "offsetX", { get: () => 577 }); + // Object.defineProperty(up, "offsetY", { get: () => 480 }); + + // const evt = new MouseEvent("click"); + // Object.defineProperty(evt, "offsetX", { get: () => 577 }); + // Object.defineProperty(evt, "offsetY", { get: () => 480 }); + + // fireEvent(canvas, evt); + + // expect(handleClick).toHaveBeenCalled(); + // expect(handleMissed).not.toHaveBeenCalled(); + // }); + + // TODO: implement onPointerMissed-api + + // it("can handle onPointerMissed on Canvas", async () => { + // const handleMissed = vi.fn(); + + // const { canvas } = test(() => ( + // + // + // + // + // )); + + // const evt = new MouseEvent("click"); + // Object.defineProperty(evt, "offsetX", { get: () => 0 }); + // Object.defineProperty(evt, "offsetY", { get: () => 0 }); + + // fireEvent(canvas, evt); + // expect(handleMissed).toHaveBeenCalledWith(evt); + // }); + + it("can handle onPointerMove", async () => { + const handlePointerMove = vi.fn(); + const handlePointerEnter = vi.fn(); + const handlePointerOut = vi.fn(); + + const { canvas } = test(() => ( + + + + + )); + + const evt1 = new Event("pointermove"); + Object.defineProperty(evt1, "offsetX", { get: () => 577 }); + Object.defineProperty(evt1, "offsetY", { get: () => 480 }); + + fireEvent(canvas, evt1); + + expect(handlePointerMove).toHaveBeenCalled(); + expect(handlePointerEnter).toHaveBeenCalled(); + + const evt2 = new Event("pointermove"); + Object.defineProperty(evt2, "offsetX", { get: () => 0 }); + Object.defineProperty(evt2, "offsetY", { get: () => 0 }); + + fireEvent(canvas, evt2); + + expect(handlePointerOut).toHaveBeenCalled(); + }); + + it("should handle stopPropogation", async () => { + const handlePointerEnter = vi.fn().mockImplementation(e => { + expect(() => e.stopPropagation()).not.toThrow(); + }); + const handlePointerLeave = vi.fn(); + + const { canvas } = test(() => ( + <> + + + + + + + + + + )); + + const evt1 = new Event("pointermove"); + Object.defineProperty(evt1, "offsetX", { get: () => 577 }); + Object.defineProperty(evt1, "offsetY", { get: () => 480 }); + + fireEvent(canvas, evt1); + + expect(handlePointerEnter).toHaveBeenCalled(); + + const evt2 = new Event("pointermove"); + Object.defineProperty(evt2, "offsetX", { get: () => 0 }); + Object.defineProperty(evt2, "offsetY", { get: () => 0 }); + + fireEvent(canvas, evt2); + + expect(handlePointerLeave).toHaveBeenCalled(); + }); + + it("should handle stopPropagation on click events", async () => { + const handleClickFront = vi.fn(e => e.stopPropagation()); + const handleClickRear = vi.fn(); + + const { canvas } = test(() => ( + <> + + + + + + + + + + )); + + const down = new Event("pointerdown"); + Object.defineProperty(down, "offsetX", { get: () => 577 }); + Object.defineProperty(down, "offsetY", { get: () => 480 }); + + fireEvent(canvas, down); + + const up = new Event("pointerup"); + Object.defineProperty(up, "offsetX", { get: () => 577 }); + Object.defineProperty(up, "offsetY", { get: () => 480 }); + + fireEvent(canvas, up); + + const event = new Event("click"); + Object.defineProperty(event, "offsetX", { get: () => 577 }); + Object.defineProperty(event, "offsetY", { get: () => 480 }); + + fireEvent(canvas, event); + + expect(handleClickFront).toHaveBeenCalled(); + expect(handleClickRear).not.toHaveBeenCalled(); + }); + + // TODO: implement pointer capture + + describe("web pointer capture", () => { + const handlePointerMove = vi.fn(); + const handlePointerDown = vi.fn(ev => { + (ev.nativeEvent.target as any).setPointerCapture(ev.pointerId); + }); + const handlePointerUp = vi.fn(ev => + (ev.nativeEvent.target as any).releasePointerCapture(ev.pointerId), + ); + const handlePointerEnter = vi.fn(); + const handlePointerLeave = vi.fn(); + + /* This component lets us unmount the event-handling object */ + function PointerCaptureTest(props: { hasMesh: boolean; manualRelease?: boolean }) { + return ( + + + + + + + ); + } + + const pointerId = 1234; + + it("should release when the capture target is unmounted", async () => { + const [hasMesh, setHasMesh] = createSignal(true); + + // s3f: we do not have a replacement for rerender + const { canvas } = test(() => ); + + canvas.setPointerCapture = vi.fn(); + canvas.releasePointerCapture = vi.fn(); + + const down = new Event("pointerdown", { pointerId }); + Object.defineProperty(down, "offsetX", { get: () => 577 }); + Object.defineProperty(down, "offsetY", { get: () => 480 }); + + /* testing-utils/react's fireEvent wraps the event like React does, so it doesn't match how our event handlers are called in production, so we call dispatchEvent directly. */ + canvas.dispatchEvent(down); + + /* This should have captured the DOM pointer */ + expect(handlePointerDown).toHaveBeenCalledTimes(1); + expect(canvas.setPointerCapture).toHaveBeenCalledWith(pointerId); + expect(canvas.releasePointerCapture).not.toHaveBeenCalled(); + + /* Now remove the T.Mesh */ + setHasMesh(false); + + expect(canvas.releasePointerCapture).toHaveBeenCalledWith(pointerId); + + const move = new Event("pointerdown", { pointerId }); + Object.defineProperty(move, "offsetX", { get: () => 577 }); + Object.defineProperty(move, "offsetY", { get: () => 480 }); + + canvas.dispatchEvent(move); + + /* There should now be no pointer capture */ + expect(handlePointerMove).not.toHaveBeenCalled(); + }); + + it("should not leave when captured", async () => { + const { canvas } = test(() => ); + + canvas.setPointerCapture = vi.fn(); + canvas.releasePointerCapture = vi.fn(); + + const moveIn = new Event("pointermove", { pointerId }); + Object.defineProperty(moveIn, "offsetX", { get: () => 577 }); + Object.defineProperty(moveIn, "offsetY", { get: () => 480 }); + + const moveOut = new Event("pointermove", { pointerId }); + Object.defineProperty(moveOut, "offsetX", { get: () => -10000 }); + Object.defineProperty(moveOut, "offsetY", { get: () => -10000 }); + + /* testing-utils/react's fireEvent wraps the event like React does, so it doesn't match how our event handlers are called in production, so we call dispatchEvent directly. */ + canvas.dispatchEvent(moveIn); + expect(handlePointerEnter).toHaveBeenCalledTimes(1); + expect(handlePointerMove).toHaveBeenCalledTimes(1); + + const down = new Event("pointerdown", { pointerId }); + Object.defineProperty(down, "offsetX", { get: () => 577 }); + Object.defineProperty(down, "offsetY", { get: () => 480 }); + + canvas.dispatchEvent(down); + + // If we move the pointer now, when it is captured, it should raise the onPointerMove event even though the pointer is not over the element, + // and NOT raise the onPointerLeave event. + canvas.dispatchEvent(moveOut); + expect(handlePointerMove).toHaveBeenCalledTimes(2); + expect(handlePointerLeave).not.toHaveBeenCalled(); + + canvas.dispatchEvent(moveIn); + expect(handlePointerMove).toHaveBeenCalledTimes(3); + + const up = new Event("pointerup", { pointerId }); + Object.defineProperty(up, "offsetX", { get: () => 577 }); + Object.defineProperty(up, "offsetY", { get: () => 480 }); + const lostpointercapture = new Event("lostpointercapture", { pointerId }); + + canvas.dispatchEvent(up); + canvas.dispatchEvent(lostpointercapture); + + // The pointer is still over the element, so onPointerLeave should not have been called. + expect(handlePointerLeave).not.toHaveBeenCalled(); + + // The element pointer should no longer be captured, so moving it away should call onPointerLeave. + canvas.dispatchEvent(moveOut); + expect(handlePointerEnter).toHaveBeenCalledTimes(1); + expect(handlePointerLeave).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/tests/core/hooks.test.tsx b/tests/core/hooks.test.tsx new file mode 100644 index 0000000..ee4a862 --- /dev/null +++ b/tests/core/hooks.test.tsx @@ -0,0 +1,205 @@ +import { Show, Suspense } from "solid-js"; +import * as THREE from "three"; +import { GLTFLoader } from "three-stdlib"; +import { describe, expect, it, vi } from "vitest"; +import { S3, T, buildGraph, useFrame, useLoader, useThree } from "../../src"; +import { test } from "../../src/testing"; +import { asyncUtils } from "../utils/async-utils"; + +const resolvers: (() => void)[] = []; +const { waitFor } = asyncUtils(resolver => resolvers.push(resolver)); + +describe("hooks", () => { + it("can handle useThree hook", async () => { + let result: S3.Context = null!; + + const Component = () => { + result = useThree(); + return ; + }; + + test(() => ); + + expect(result.camera instanceof THREE.Camera).toBeTruthy(); + expect(result.scene instanceof THREE.Scene).toBeTruthy(); + expect(result.raycaster instanceof THREE.Raycaster).toBeTruthy(); + // expect(result.size).toEqual({ height: 0, width: 0, top: 0, left: 0, updateStyle: false }); + }); + + it("can handle useFrame hook", async () => { + const frameCalls: number[] = []; + + const Component = () => { + let ref: THREE.Mesh = null!; + + useFrame((_, delta) => { + frameCalls.push(delta); + ref.position.x = 1; + }); + + return ( + + + + + ); + }; + + const { scene, waitTillNextFrame, requestRender } = test(() => , { + frameloop: "never", + }); + requestRender(); + await waitTillNextFrame(); + + expect(scene.children[0].position.x).toEqual(1); + expect(frameCalls.length).toBeGreaterThan(0); + }); + + it("can handle useLoader hook", async () => { + const MockMesh = new THREE.Mesh(); + const mockLoad = vi.fn().mockImplementation((_url, onLoad) => onLoad(MockMesh)); + class mockGLTFLoader extends GLTFLoader { + constructor() { + super(); + } + load = mockLoad; + } + + const Component = () => { + const model = useLoader(mockGLTFLoader, () => "/suzanne.glb"); + return {model => }; + }; + + const scene = test(() => ( + + + + )).scene; + + await waitFor(() => expect(scene.children[0]).toBeDefined()); + + expect(scene.children[0]).toBe(MockMesh); + }); + + it("can handle useLoader hook with an array of strings", async () => { + const MockMesh = new THREE.Mesh(); + + const MockGroup = new THREE.Group(); + const mat1 = new THREE.MeshBasicMaterial(); + mat1.name = "Mat 1"; + const mesh1 = new THREE.Mesh(new THREE.BoxGeometry(2, 2), mat1); + mesh1.name = "Mesh 1"; + const mat2 = new THREE.MeshBasicMaterial(); + mat2.name = "Mat 2"; + const mesh2 = new THREE.Mesh(new THREE.BoxGeometry(2, 2), mat2); + mesh2.name = "Mesh 2"; + MockGroup.add(mesh1, mesh2); + + class mockGLTFLoader extends GLTFLoader { + constructor() { + super(); + } + load = vi + .fn() + .mockImplementationOnce((_url, onLoad) => { + onLoad(MockMesh); + }) + .mockImplementationOnce((_url, onLoad) => { + onLoad({ scene: MockGroup }); + }); + } + + const Component = () => { + const resource = useLoader( + mockGLTFLoader, + () => ["/suzanne.glb", "/myModels.glb"], + loader => { + loader.setPath("/public/models"); + }, + ); + + return ( + + {([mockMesh, mockScene]) => ( + <> + + + + )} + + ); + }; + + let scene = test(() => ( + + + + )).scene; + + await waitFor(() => expect(scene.children[0]).toBeDefined()); + + expect(scene.children[0]).toBe(MockMesh); + }); + + it("can handle useLoader with a loader extension", async () => { + class Loader extends THREE.Loader { + load = (_url: string) => null; + } + + let proto!: Loader; + + function Test() { + useLoader( + Loader, + () => "", + loader => (proto = loader), + ); + return <>; + } + + test(() => ); + + expect(proto).toBeInstanceOf(Loader); + }); + + it("can handle buildGraph utility", async () => { + const group = new THREE.Group(); + const mat1 = new THREE.MeshBasicMaterial(); + mat1.name = "Mat 1"; + const mesh1 = new THREE.Mesh(new THREE.BoxGeometry(2, 2), mat1); + mesh1.name = "Mesh 1"; + const mat2 = new THREE.MeshBasicMaterial(); + mat2.name = "Mat 2"; + const mesh2 = new THREE.Mesh(new THREE.BoxGeometry(2, 2), mat2); + mesh2.name = "Mesh 2"; + const subGroup = new THREE.Group(); + const mat3 = new THREE.MeshBasicMaterial(); + mat3.name = "Mat 3"; + const mesh3 = new THREE.Mesh(new THREE.BoxGeometry(2, 2), mat3); + mesh3.name = "Mesh 3"; + const mat4 = new THREE.MeshBasicMaterial(); + mat4.name = "Mat 4"; + const mesh4 = new THREE.Mesh(new THREE.BoxGeometry(2, 2), mat4); + mesh4.name = "Mesh 4"; + + subGroup.add(mesh3, mesh4); + group.add(mesh1, mesh2, subGroup); + + const result = buildGraph(group); + + expect(result).toEqual({ + nodes: { + [mesh1.name]: mesh1, + [mesh2.name]: mesh2, + [mesh3.name]: mesh3, + [mesh4.name]: mesh4, + }, + materials: { + [mat1.name]: mat1, + [mat2.name]: mat2, + [mat3.name]: mat3, + [mat4.name]: mat4, + }, + }); + }); +}); diff --git a/tests/core/renderer.test.tsx b/tests/core/renderer.test.tsx new file mode 100644 index 0000000..d3ea2a6 --- /dev/null +++ b/tests/core/renderer.test.tsx @@ -0,0 +1,863 @@ +import * as THREE from "three"; + +import { + ComponentProps, + For, + Show, + createRenderEffect, + createSignal, + onCleanup, + onMount, +} from "solid-js"; +import { beforeAll, describe, expect, it, vi } from "vitest"; +import { S3, T, extend, useFrame, useThree } from "../../src/index"; +import { test } from "../../src/testing"; + +type ComponentMesh = THREE.Mesh; + +interface ObjectWithBackground extends THREE.Object3D { + background: THREE.Color; +} + +/* This class is used for one of the tests */ +class HasObject3dMember extends THREE.Object3D { + public attachment?: THREE.Object3D = undefined; +} + +/* This class is used for one of the tests */ +class HasObject3dMethods extends THREE.Object3D { + attachedObj3d?: THREE.Object3D; + detachedObj3d?: THREE.Object3D; + + customAttach(obj3d: THREE.Object3D) { + this.attachedObj3d = obj3d; + } + + detach(obj3d: THREE.Object3D) { + this.detachedObj3d = obj3d; + } +} + +class MyColor extends THREE.Color { + constructor(col: number) { + super(col); + } +} + +declare global { + module SolidThree { + interface Elements { + HasObject3dMember: HasObject3dMember; + HasObject3dMethods: HasObject3dMethods; + MyColor: MyColor; + } + } +} + +extend({ HasObject3dMember, HasObject3dMethods }); + +beforeAll(() => { + Object.defineProperty(window, "devicePixelRatio", { + configurable: true, + value: 2, + }); +}); + +describe("renderer", () => { + it("renders a simple component", async () => { + const Mesh = () => ( + + + + + ); + const scene = test(() => ).scene; + + expect(scene.children[0].type).toEqual("Mesh"); + expect((scene.children[0] as ComponentMesh).geometry.type).toEqual("BoxGeometry"); + expect((scene.children[0] as ComponentMesh).material.type).toEqual("MeshBasicMaterial"); + expect( + (scene.children[0] as THREE.Mesh).material + .type, + ).toEqual("MeshBasicMaterial"); + }); + + it("renders an empty scene", async () => { + const Empty = () => null; + const scene = test(() => ).scene; + + expect(scene.type).toEqual("Scene"); + expect(scene.children).toEqual([]); + }); + + it("can render a composite component", async () => { + const Parent = () => { + return ( + + + + + ); + }; + + const Child = () => { + return ( + + + + + ); + }; + + const scene = test(() => ).scene; + + expect(scene.children[0].type).toEqual("Group"); + expect((scene.children[0] as ObjectWithBackground).background.getStyle()).toEqual("rgb(0,0,0)"); + expect(scene.children[0].children[0].type).toEqual("Mesh"); + expect((scene.children[0].children[0] as ComponentMesh).geometry.type).toEqual("BoxGeometry"); + expect((scene.children[0].children[0] as ComponentMesh).material.type).toEqual( + "MeshBasicMaterial", + ); + expect( + (scene.children[0].children[0] as THREE.Mesh) + .material.type, + ).toEqual("MeshBasicMaterial"); + }); + + it("renders some basics with an update", async () => { + let renders = 0; + + const Component = () => { + const [state, setState] = createSignal(3); + + setState(7); + + renders++; + + return ( + + + + + ); + }; + + const Child = () => { + renders++; + return ; + }; + + const Null = () => { + renders++; + return null; + }; + + const scene = test(() => ).scene; + + expect(scene.children[0].position.x).toEqual(7); + expect(renders).toBe(3); + }); + + it("updates types & names", async () => { + const [type, setType] = createSignal<"MeshBasicMaterial" | "MeshStandardMaterial">( + "MeshBasicMaterial", + ); + + const scene = test(() => ( + + {type() === "MeshBasicMaterial" ? ( + + + + ) : ( + + + + )} + + )).scene; + + expect( + (scene.children[0] as THREE.Mesh).material.type, + ).toEqual("MeshBasicMaterial"); + expect( + (scene.children[0] as THREE.Mesh).material.name, + ).toEqual("basicMat"); + + setType("MeshStandardMaterial"); + + expect( + (scene.children[0] as THREE.Mesh).material + .type, + ).toEqual("MeshStandardMaterial"); + expect( + (scene.children[0] as THREE.Mesh).material + .name, + ).toEqual("standardMat"); + }); + + it("should forward ref three object", async () => { + // Note: Passing directly should be less strict, and assigning current should be more strict + let immutableRef!: THREE.Mesh; + let mutableRef!: THREE.Mesh; + let mutableRefSpecific!: THREE.Mesh; + + const RefTest = () => { + return ( + <> + + + (mutableRefSpecific = r)} /> + + ); + }; + + test(() => ); + + expect(immutableRef).toBeTruthy(); + expect(mutableRef).toBeTruthy(); + expect(mutableRefSpecific).toBeTruthy(); + }); + + it("attaches Object3D children that use attach", async () => { + const scene = test(() => ( + + + + )).scene; + + const attachedMesh = (scene.children[0] as HasObject3dMember).attachment; + expect(attachedMesh).toBeDefined(); + expect(attachedMesh?.type).toBe("Mesh"); + // attaching is *instead of* being a regular child + expect(scene.children[0].children.length).toBe(0); + }); + + it("can attach a Scene", async () => { + const scene = test(() => ( + + + + )).scene; + + const attachedScene = (scene.children[0] as HasObject3dMember).attachment; + expect(attachedScene).toBeDefined(); + expect(attachedScene?.type).toBe("Scene"); + // attaching is *instead of* being a regular child + expect(scene.children[0].children.length).toBe(0); + }); + + describe("attaches Object3D children that use attachFns", () => { + it("attachFns with cleanup", async () => { + const [visible, setVisible] = createSignal(true); + + const scene = test(() => ( + + + ( + (parent as any).customAttach(self), () => (parent as any).detach(self) + )} + /> + + + )).scene; + + const attachedMesh = (scene.children[0] as HasObject3dMethods).attachedObj3d; + + expect(attachedMesh).toBeDefined(); + expect(attachedMesh?.type).toBe("Mesh"); + // attaching is *instead of* being a regular child + expect(scene.children[0].children.length).toBe(0); + + // and now detach .. + expect((scene.children[0] as HasObject3dMethods).detachedObj3d).toBeUndefined(); + + setVisible(false); + + const detachedMesh = (scene.children[0] as HasObject3dMethods).detachedObj3d; + expect(detachedMesh).toBe(attachedMesh); + }); + + it("attachFns as functions", async () => { + let attachedMesh: THREE.Object3D = null!; + let detachedMesh: THREE.Object3D = null!; + + const [visible, setVisible] = createSignal(true); + + const scene = test(() => ( + + + ((attachedMesh = parent), () => (detachedMesh = parent))} /> + + + )).scene; + + expect(attachedMesh).toBeDefined(); + expect(attachedMesh?.type).toBe("Object3D"); + // attaching is *instead of* being a regular child + expect(scene.children[0].children.length).toBe(0); + + setVisible(false); + + expect(detachedMesh).toBe(attachedMesh); + }); + }); + + it("does the full lifecycle", async () => { + const log: string[] = []; + const Log = props => { + onMount(() => log.push("mount " + props.name)); + onCleanup(() => log.push("unmount " + props.name)); + log.push("render " + props.name); + return ; + }; + + const { unmount: dispose } = test(() => ); + + dispose(); + + expect(log).toEqual(["render Foo", "mount Foo", "unmount Foo"]); + }); + + it("will mount/unmount event handlers correctly", async () => { + let [mounted, setMounted] = createSignal(false); + let [attachEvents, setAttachEvents] = createSignal(false); + + // NOTE: this test fails when using ternary operators + const EventfulComponent = () => ( + + {} : undefined} /> + + ); + + const { eventRegistry, waitTillNextFrame } = test(() => ); + + // Test initial mount without events + setMounted(true); + expect(eventRegistry.onClick.length).toBe(0); + + // Test initial mount with events + setAttachEvents(true); + + expect(eventRegistry.onClick.length).not.toBe(0); + + // Test events update + setAttachEvents(false); + + expect(eventRegistry.onClick.length).toBe(0); + + setAttachEvents(true); + expect(eventRegistry.onClick.length).not.toBe(0); + + // Test unmount with events + setMounted(false); + expect(eventRegistry.onClick.length).toBe(0); + }); + + it("will create an identical instance when reconstructing", async () => { + const [first, setFirst] = createSignal(true); + + const instances: { uuid: string; parentUUID?: string; childUUID?: string }[] = []; + + const object1 = new THREE.Group(); + const object2 = new THREE.Group(); + + const Test = (props: { first?: boolean }) => ( + null}> + + + ); + + const state = test(() => ); + + instances.push({ + uuid: state.scene.children[0].uuid, + parentUUID: state.scene.children[0].parent?.uuid, + childUUID: state.scene.children[0].children[0]?.uuid, + }); + expect(state.scene.children[0]).toBe(object1); + expect(state.scene.children[0].children[0]).toBeDefined(); + + setFirst(false); + + instances.push({ + uuid: state.scene.children[0].uuid, + parentUUID: state.scene.children[0].parent?.uuid, + childUUID: state.scene.children[0].children[0]?.uuid, + }); + + const [oldInstance, newInstance] = instances; + + // Swapped to new instance + expect(state.scene.children[0]).toBe(object2); + + // Preserves scene hierarchy + expect(oldInstance.parentUUID).toBe(newInstance.parentUUID); + expect(oldInstance.childUUID).toBe(newInstance.childUUID); + + // Rebinds events + expect(state.eventRegistry.onPointerMove.length).not.toBe(0); + }); + + it("can swap primitives", async () => { + const [n, setN] = createSignal(1); + const o1 = new THREE.Group(); + o1.add(new THREE.Group()); + const o2 = new THREE.Group(); + + const Test = (props: { n: number }) => ( + + + + ); + + const state = test(() => ); + + // Initial object is added with children and attachments + expect(state.scene.children[0]).toBe(o1); + expect(state.scene.children[0].children.length).toBe(1); + expect((state.scene.children[0] as any).test).toBeInstanceOf(THREE.Group); + + setN(2); + + // Swapped to object 2, does not copy old children, copies attachments + expect(state.scene.children[0]).toBe(o2); + expect(state.scene.children[0].children.length).toBe(0); + expect((state.scene.children[0] as any).test).toBeInstanceOf(THREE.Group); + }); + + it("can swap 4 array primitives", async () => { + const a = new THREE.Group(); + const b = new THREE.Group(); + const c = new THREE.Group(); + const d = new THREE.Group(); + const [array, setArray] = createSignal([a, b, c, d]); + + const Test = (props: { array: THREE.Group[] }) => ( + <> + {group => } + + ); + + const state = test(() => ); + + expect(state.scene.children[0]).toBe(a); + expect(state.scene.children[1]).toBe(b); + expect(state.scene.children[2]).toBe(c); + expect(state.scene.children[3]).toBe(d); + + const reversedArray = [...array().reverse()]; + + setArray(reversedArray); + + expect(state.scene.children[0]).toBe(d); + expect(state.scene.children[1]).toBe(c); + expect(state.scene.children[2]).toBe(b); + expect(state.scene.children[3]).toBe(a); + + const mixedArray = [b, a, d, c]; + + setArray(mixedArray); + + expect(state.scene.children[0]).toBe(b); + expect(state.scene.children[1]).toBe(a); + expect(state.scene.children[2]).toBe(d); + expect(state.scene.children[3]).toBe(c); + }); + + it("will make an Orthographic Camera & set the position", async () => { + let camera: THREE.Camera = null!; + + camera = test(() => , { + orthographic: true, + camera: { position: [0, 0, 5] }, + }).camera; + + expect(camera.type).toEqual("OrthographicCamera"); + expect(camera.position.z).toEqual(5); + }); + + // TODO: implement performance configuration + + // it("should handle an performance changing functions", async () => { + // let state = test(() => , { dpr: [1, 2], performance: { min: 0.2 } }); + + // expect(state.viewport.initialDpr).toEqual(2); + // expect(state.performance.min).toEqual(0.2); + // expect(state.performance.current).toEqual(1); + + // state.setDpr(0.1); + + // expect(state.viewport.dpr).toEqual(0.1); + + // vi.useFakeTimers(); + + // state.performance.regress(); + // vi.advanceTimersByTime(100); + + // expect(state.performance.current).toEqual(0.2); + + // vi.advanceTimersByTime(200); + + // expect(state.performance.current).toEqual(1); + + // vi.useRealTimers(); + // }); + + it("should set PCFSoftShadowMap as the default shadow map", async () => { + let state = test(() => , { shadows: true }); + expect(state.gl.shadowMap.type).toBe(THREE.PCFSoftShadowMap); + }); + + it("should set tonemapping to ACESFilmicToneMapping and outputEncoding to sRGBEncoding if linear is false", async () => { + let state = test(() => , { linear: false }); + + expect(state.gl.toneMapping).toBe(THREE.ACESFilmicToneMapping); + expect(state.gl.outputEncoding).toBe(THREE.sRGBEncoding); + }); + + it("should toggle render mode in xr", async () => { + const state = test(() => ); + + state.gl.xr.isPresenting = true; + state.gl.xr.dispatchEvent({ type: "sessionstart" }); + + expect(state.gl.xr.enabled).toEqual(true); + + state.gl.xr.isPresenting = false; + state.gl.xr.dispatchEvent({ type: "sessionend" }); + + expect(state.gl.xr.enabled).toEqual(false); + }); + + it('should respect frameloop="never" in xr', async () => { + let respected = true; + + const TestGroup = () => { + useFrame(() => { + respected = false; + }); + return ; + }; + const state = test(() => , { frameloop: "never" }); + state.gl.xr.isPresenting = true; + state.gl.xr.dispatchEvent({ type: "sessionstart" }); + + await new Promise(resolve => requestAnimationFrame(resolve)); + + expect(respected).toEqual(true); + }); + + it("will render components that are extended", async () => { + const testExtend = async () => { + extend({ MyColor }); + + test(() => ); + }; + + expect(() => testExtend()).not.toThrow(); + }); + + it("should set renderer props via gl prop", async () => { + const gl = test(() => , { gl: { physicallyCorrectLights: true } }).gl; + expect(gl.physicallyCorrectLights).toBe(true); + }); + + it("should update scene via scene prop", async () => { + const scene = test(() => , { scene: { name: "test" } }).scene; + + expect(scene.name).toBe("test"); + }); + + it("should set a custom scene via scene prop", async () => { + const prop = new THREE.Scene(); + + const scene = test(() => , { scene: prop }).scene; + + expect(prop).toBe(scene); + }); + + it("should set a renderer via gl callback", async () => { + class Renderer extends THREE.WebGLRenderer {} + + const gl = test(() => , { gl: canvas => new Renderer({ canvas }) }).gl; + + expect(gl instanceof Renderer).toBe(true); + }); + + it("should respect color management preferences via gl", async () => { + const texture = new THREE.Texture() as THREE.Texture & { colorSpace?: string }; + function Test() { + return ; + } + + const LinearEncoding = 3000; + const sRGBEncoding = 3001; + + const [linear, setLinear] = createSignal(false); + const [flat, setFlat] = createSignal(false); + + const gl = test(() => , { + get linear() { + return linear(); + }, + get flat() { + return flat(); + }, + }).gl as unknown as THREE.WebGLRenderer & { outputColorSpace: string }; + + expect(gl.outputEncoding).toBe(sRGBEncoding); + expect(gl.toneMapping).toBe(THREE.ACESFilmicToneMapping); + expect(texture.encoding).toBe(sRGBEncoding); + + setLinear(true); + setFlat(true); + + expect(gl.outputEncoding).toBe(LinearEncoding); + expect(gl.toneMapping).toBe(THREE.NoToneMapping); + expect(texture.encoding).toBe(LinearEncoding); + + // Sets outputColorSpace since r152 + const SRGBColorSpace = "srgb"; + const LinearSRGBColorSpace = "srgb-linear"; + + gl.outputColorSpace = "test"; + texture.colorSpace = ""; + + setLinear(false); + expect(gl.outputColorSpace).toBe(SRGBColorSpace); + expect(texture.colorSpace).toBe(SRGBColorSpace); + + setLinear(true); + expect(gl.outputColorSpace).toBe(LinearSRGBColorSpace); + expect(texture.colorSpace).toBe(LinearSRGBColorSpace); + }); + + // NOTE: Maybe we can keep legacy mode out of solid-three + + // it("should respect legacy prop", async () => { + // // <= r138 internal fallback + // const material = React.createRef(); + // extend({ ColorManagement: null }); + // render(() => ); + // expect((THREE as any).ColorManagement.legacyMode).toBe(false); + // expect(material.current!.color.toArray()).toStrictEqual( + // new THREE.Color("#111111").convertSRGBToLinear().toArray(), + // ); + // extend({ ColorManagement: (THREE as any).ColorManagement }); + + // // r139 legacyMode + // root.configure({ legacy: true }).render(); + // expect((THREE as any).ColorManagement.legacyMode).toBe(true); + + // root.configure({ legacy: false }).render(); + // expect((THREE as any).ColorManagement.legacyMode).toBe(false); + + // // r150 !enabled + // (THREE as any).ColorManagement.enabled = true; + + // root.configure({ legacy: true }).render(); + // expect((THREE as any).ColorManagement.enabled).toBe(false); + + // root.configure({ legacy: false }).render(); + // expect((THREE as any).ColorManagement.enabled).toBe(true); + // }); + + it("can handle createPortal", async () => { + const scene = new THREE.Scene(); + + let state: S3.Context = null!; + let portalState: S3.Context = null!; + + const Normal = () => { + const three = useThree(); + state = three; + + return ; + }; + + const Portal = () => { + const three = useThree(); + portalState = three; + + return ; + }; + + test(() => ( + <> + + + + + + )); + + // Renders into portal target + expect(scene.children.length).not.toBe(0); + + // Creates an isolated state enclave + expect(state.scene).not.toBe(scene); + expect(portalState.scene).toBe(scene); + }); + + it("can handle createPortal on unmounted container", async () => { + const [group, setGroup] = createSignal | null>(null); + const [key, setKey] = createSignal(1); + + function Test(props: any) { + return ( + + + {group => { + return ( + + + + ); + }} + + + ); + } + + test(() => (key() ? : undefined)); + + expect(group()).toBeDefined(); + const prevUUID = group()!.uuid; + + setKey(key => key + 1); + + expect(group()).toBeDefined(); + expect(prevUUID).not.toBe(group()!.uuid); + }); + + it("invalidates pierced props when root is changed", async () => { + const [signal, setSignal] = createSignal(1); + let material: THREE.MeshBasicMaterial; + const texture1 = { needsUpdate: false, name: "" } as THREE.Texture; + const texture2 = { needsUpdate: false, name: "" } as THREE.Texture; + + test(() => ( + + )); + + expect(material!.map).toBe(texture1); + expect(texture1.needsUpdate).toBe(true); + expect(texture1.name).toBe("test"); + + setSignal(2); + + expect(material!.map).toBe(texture2); + expect(texture2.needsUpdate).toBe(true); + expect(texture2.name).toBe("test"); + }); + + // https://github.com/mrdoob/three.js/issues/21209 + it("can handle HMR default where three.js isn't reliable", async () => { + let ref: THREE.Mesh; + + function Test() { + const [scale, setScale] = createSignal(true); + createRenderEffect(() => void setScale(false), []); + return ; + } + + test(() => ); + + expect(ref!.scale.toArray()).toStrictEqual(new THREE.Object3D().scale.toArray()); + }); + + it("onUpdate shouldn't update itself", async () => { + const one = vi.fn(); + const two = vi.fn(); + + const Test = (props: ComponentProps) => ; + + const [updateType, setUpdateType] = createSignal<"one" | "two">("one"); + + test(() => ); + + setUpdateType("two"); + + expect(one).toBeCalledTimes(1); + expect(two).toBeCalledTimes(0); + }); + + // TODO: Unsure if we should implement this. + // I was thinking of doing the opposite: useThree is readonly and if you want to take control you use props. + + // it("camera props shouldn't overwrite state", async () => { + // const camera = new THREE.OrthographicCamera(); + + // function Test() { + // // const set = useThree(state => state.set); + // // React.useMemo(() => set({ camera }), [set]); + // return null; + // } + + // const [cameraName, setCameraName] = createSignal(undefined); + + // const store = test(() => , { + // camera: { + // get name() { + // return cameraName(); + // }, + // }, + // }); + // expect(store.camera).toBe(camera); + + // setCameraName("test"); + + // expect(store.camera).toBe(camera); + // expect(camera.name).not.toBe("test"); + // }); + + it("should safely handle updates to the object prop", async () => { + let ref: THREE.Object3D = null!; + let child: THREE.Object3D = null!; + let attachedChild: THREE.Object3D = null!; + + const Test = (props: ComponentProps) => ( + + + + + ); + + const object1 = new THREE.Object3D(); + const child1 = new THREE.Object3D(); + object1.add(child1); + + const object2 = new THREE.Object3D(); + const child2 = new THREE.Object3D(); + object2.add(child2); + + const [object, setObject] = createSignal(object1); + + // Initial + test(() => ); + + expect(ref).toBe(object1); + + expect(ref!.children).toStrictEqual([child1, child]); + expect(ref!.userData.attach).toBe(attachedChild); + + // Update + setObject(object2); + expect(ref).toBe(object2); + expect(ref!.children).toStrictEqual([child2, child]); + expect(ref!.userData.attach).toBe(attachedChild); + + // Revert + setObject(object1); + expect(ref).toBe(object1); + expect(ref!.children).toStrictEqual([child1, child]); + expect(ref!.userData.attach).toBe(attachedChild); + }); +}); diff --git a/tests/setup.ts b/tests/setup.ts new file mode 100644 index 0000000..86fd7d9 --- /dev/null +++ b/tests/setup.ts @@ -0,0 +1,5 @@ +import * as THREE from "three"; +import { extend } from "../src"; + +// Extend catalogue for render API in tests +extend(THREE); diff --git a/tests/utils/async-utils.ts b/tests/utils/async-utils.ts new file mode 100644 index 0000000..da723b5 --- /dev/null +++ b/tests/utils/async-utils.ts @@ -0,0 +1,103 @@ +// helpers + +class TimeoutError extends Error { + constructor(util: Function, timeout: number) { + super(`Timed out in ${util.name} after ${timeout}ms.`); + } +} + +const resolveAfter = (ms: number): Promise => { + return new Promise(resolve => setTimeout(resolve, ms)); +}; + +const callAfter = async (callback: () => void, ms: number): Promise => { + await resolveAfter(ms); + callback(); +}; + +const DEFAULT_INTERVAL = 50; +const DEFAULT_TIMEOUT = 5000; + +// types + +type WaitOptions = { + interval?: number | false; + timeout?: number | false; +}; + +type AsyncUtils = { + waitFor: (callback: () => boolean | void, options?: WaitOptions) => Promise; + waitTick: (cb: () => T) => Promise; +}; + +// the utils + +export const asyncUtils = (addResolver: (callback: () => void) => void): AsyncUtils => { + const wait = async (callback: () => boolean | void, { interval, timeout }: WaitOptions) => { + const checkResult = () => { + const callbackResult = callback(); + return callbackResult ?? callbackResult === undefined; + }; + + const waitForResult = async () => { + while (true) { + await Promise.race( + [ + new Promise(resolve => addResolver(resolve)), + interval && resolveAfter(interval), + ].filter(Boolean), + ); + + if (checkResult()) { + return; + } + } + }; + + let timedOut = false; + + if (!checkResult()) { + if (timeout) { + const timeoutPromise = () => + callAfter(() => { + timedOut = true; + }, timeout); + + await Promise.race([waitForResult(), timeoutPromise()]); + } else { + await waitForResult(); + } + } + + return !timedOut; + }; + + const waitFor = async ( + callback: () => boolean | void, + { interval = DEFAULT_INTERVAL, timeout = DEFAULT_TIMEOUT }: WaitOptions = {}, + ) => { + const safeCallback = () => { + try { + return callback(); + } catch (error: unknown) { + return false; + } + }; + + const result = await wait(safeCallback, { interval, timeout }); + if (!result && timeout) { + throw new TimeoutError(waitFor, timeout); + } + }; + + const waitTick = async (cb: () => T) => + new Promise(resolve => { + const result = cb(); + queueMicrotask(() => resolve(result)); + }); + + return { + waitFor, + waitTick, + }; +}; diff --git a/tests/web/__snapshots__/canvas.test.tsx.snap b/tests/web/__snapshots__/canvas.test.tsx.snap new file mode 100644 index 0000000..3589ae2 --- /dev/null +++ b/tests/web/__snapshots__/canvas.test.tsx.snap @@ -0,0 +1,15 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`web Canvas > should correctly mount 1`] = ` +
+
+ +
+
+`; diff --git a/tests/web/canvas.test.tsx b/tests/web/canvas.test.tsx new file mode 100644 index 0000000..5e14d72 --- /dev/null +++ b/tests/web/canvas.test.tsx @@ -0,0 +1,54 @@ +// use default export for jest.spyOn +import { render } from "@solidjs/testing-library"; + +import { describe, expect, it } from "vitest"; +import { T } from "../../src"; +import { TestCanvas } from "../../src/testing"; + +describe("web Canvas", () => { + it("should correctly mount", async () => { + let renderer = render(() => ( + + + + )); + + expect(renderer.container).toMatchSnapshot(); + }); + + it("should forward ref", async () => { + let ref: HTMLDivElement; + + render(() => ( + + + + )); + + expect(ref!).toBeDefined(); + }); + + it("should correctly unmount", async () => { + let renderer = render(() => ( + + + + )); + + expect(() => renderer.unmount()).not.toThrow(); + }); + + // it("plays nice with react SSR", async () => { + // const useLayoutEffect = jest.spyOn(React, "useLayoutEffect"); + + // await act(async () => { + // render( + // + // + // , + // ); + // }); + + // expect(useLayoutEffect).not.toHaveBeenCalled(); + // }); +}); diff --git a/tsconfig.json b/tsconfig.json index 8baa855..e3e44a4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,9 +1,9 @@ { "extends": "@vinxi/tsconfig/solid-library.json", - "include": ["./src"], + "include": ["./src", "./tests"], "compilerOptions": { "outDir": "./types", - "rootDir": "./src", + "rootDir": "./", "target": "esnext", "lib": ["dom", "esnext"] }, diff --git a/tsup.config.ts b/tsup.config.ts new file mode 100644 index 0000000..e812fbc --- /dev/null +++ b/tsup.config.ts @@ -0,0 +1,42 @@ +import { defineConfig } from "tsup"; +import * as preset from "tsup-preset-solid"; + +const CI = + process.env["CI"] === "true" || + process.env["GITHUB_ACTIONS"] === "true" || + process.env["CI"] === '"1"' || + process.env["GITHUB_ACTIONS"] === '"1"'; + +export default defineConfig(config => { + const watching = !!config.watch; + + const parsed_options = preset.parsePresetOptions( + { + entries: [ + { + name: "core", + entry: "src/index.ts", + dev_entry: true, + }, + { + entry: "src/testing/index.tsx", + name: "testing", + dev_entry: true, + }, + ], + drop_console: true, + }, + watching, + ); + + if (!watching && !CI) { + const package_fields = preset.generatePackageExports(parsed_options); + + console.info(`package.json: \n\n${JSON.stringify(package_fields, null, 2)}\n\n`); + + // will update ./package.json with the correct export fields + preset.writePackageJson(package_fields); + } + + return preset.generateTsupOptions(parsed_options); +}); diff --git a/vite.config.ts b/vite.config.ts index 9993379..d1287ab 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,60 +1,9 @@ import { defineConfig } from "vite"; -import solidPlugin from "vite-plugin-solid"; import inspect from "vite-plugin-inspect"; -import { DOMElements, SVGElements } from "solid-js/web/dist/dev.cjs"; -export default defineConfig(async (mode) => ({ - build: - process.env.BUILD_MODE === "lib" - ? { - lib: { - entry: "./src/index.tsx", - formats: ["es", "cjs", "umd"], - fileName: "index", - name: "SolidThree", - }, - minify: false, - rollupOptions: { - external: [ - "solid-js", - "solid-js/web", - "solid-js/store", - "three", - "zustand", - "zustand/vanilla", - ], - }, - polyfillDynamicImport: false, - } - : {}, - plugins: [ - // mdx({ - // transformMDX: (code) => { - // return code.replace(/<\!--[a-zA-Z\.\s]+-->/g, ` `); - // }, - // xdm: { - // remarkPlugins: [(await import("remark-gfm")).default], - // }, - // }), - // for the playground, we need to be able to use the renderer from the src itself - solidPlugin({ - solid: { - moduleName: "solid-js/web", - // @ts-ignore - generate: "dynamic", - renderers: [ - { - name: "dom", - moduleName: "solid-js/web", - elements: [...DOMElements.values(), ...SVGElements.values()], - }, - { - name: "universal", - moduleName: "/src/renderer.tsx", - elements: [], - }, - ], - }, - }), - inspect(), - ], -})); +import solidPlugin from "vite-plugin-solid"; +export default defineConfig({ + test: { + setupFiles: ["./tests/setup.ts"], + }, + plugins: [solidPlugin(), inspect()], +});