diff --git a/GEMstack/onboard/visualization/sr_viz/README.md b/GEMstack/onboard/visualization/sr_viz/README.md new file mode 100644 index 000000000..251d8b027 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/README.md @@ -0,0 +1,141 @@ +# SR Visualization Dashboard + +## How to Use + +### 1. Start Backend Server + +Navigate to the backend directory: + +``` +cd ./log_dashboard +``` + +Install Python dependencies: + +``` +pip install -r requirements.txt +``` + +Start the backend server: + +``` +python app.py +``` + +The backend server will be running at: [http://localhost:5000](http://localhost:5000) + +--- + +### 2. Start Frontend (Development or Production) + +#### Prerequisites + +- Node.js (v18.17+) and npm. If you already have a different version of Node.js installed, you can manage multiple versions using [nvm](https://github.com/nvm-sh/nvm) (for Unix-based systems) or [nvm-windows](https://github.com/coreybutler/nvm-windows) (for Windows). + +Navigate to the frontend directory: + +``` +cd ./GEMstack/onboard/visualization/sr_viz/threeD +``` + +Install frontend dependencies: + +``` +npm install +``` + +Run development server: + +``` +npm run dev +``` + +Or run production build: + +``` +npm run build && npm run start +``` + +The frontend visualizer will be available at: [http://localhost:3000](http://localhost:3000) + +--- + +### 3. Open the Dashboard + +Visit: [http://localhost:5000](http://localhost:5000) + +If a valid `behavior.json` file is loaded, the **"3D Visualization"** button will appear at the top-right corner. + +Clicking it redirects you to the 3D visualizer at: [http://localhost:3000](http://localhost:3000) + +--- + +## Format of Objects in `behavior.json` + +### Other Vehicles + +```json +{ + "other_vehicles": { + "": { + "type": "OtherVehicleState", + "data": { + "pose": { + "frame": , + "t": , + "x": , + "y": , + "z": , + "yaw": , + "pitch": , + "roll": + }, + "dimensions": [, , ], + "outline": , + "type": , + "activity": , + "velocity": [, , ], + "yaw_rate": + } + } + }, + "time": +} +``` + +### Traffic Lights + +```json +{ + "traffic_lights": { + "": { + "type": "TrafficLightState", + "data": { + "pose": { + "frame": , + "t": , + "x": , + "y": , + "z": , + "yaw": , + "pitch": , + "roll": + }, + "state": + } + } + }, + "time": +} +``` + +# SR Rosbag Viewer +## How to Use +In the bottom-right corner of the 3D Visualizer, there's a redirect button. Clicking it will take you to the Rosbag Viewer. Currently, it supports viewing uncompressed images and point clouds by topic. + +To view both images and point clouds simultaneously: + 1. After uploading the rosbag file and confirming that the upload is complete (as indicated by the loading status in the scrubber), click the menu in the top-right corner. + + 2. Choose to split the current panel vertically or horizontally. + + 3. In one of the panels, select `Switch to PointCloud Panel`. \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/data/__init__.py b/GEMstack/onboard/visualization/sr_viz/data/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.gitignore b/GEMstack/onboard/visualization/sr_viz/threeD/.gitignore new file mode 100644 index 000000000..5ef6a5207 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/app.config.mjs b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/app.config.mjs new file mode 100644 index 000000000..fc95a313e --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/app.config.mjs @@ -0,0 +1,18 @@ + +import { _replaceAppConfig } from '#app/config' +import { defuFn } from 'defu' + +const inlineConfig = { + "nuxt": {} +} + +// Vite - webpack is handled directly in #app/config +if (import.meta.hot) { + import.meta.hot.accept((newModule) => { + _replaceAppConfig(newModule.default) + }) +} + + + +export default /*@__PURE__*/ defuFn(inlineConfig) diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/components.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/components.d.ts new file mode 100644 index 000000000..728c161ba --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/components.d.ts @@ -0,0 +1,138 @@ + +import type { DefineComponent, SlotsType } from 'vue' +type IslandComponent = T & DefineComponent<{}, {refresh: () => Promise}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, SlotsType<{ fallback: { error: unknown } }>> +type HydrationStrategies = { + hydrateOnVisible?: IntersectionObserverInit | true + hydrateOnIdle?: number | true + hydrateOnInteraction?: keyof HTMLElementEventMap | Array | true + hydrateOnMediaQuery?: string + hydrateAfter?: number + hydrateWhen?: boolean + hydrateNever?: true +} +type LazyComponent = (T & DefineComponent void }>) +interface _GlobalComponents { + 'AxesReference': typeof import("../components/AxesReference.vue")['default'] + 'Car': typeof import("../components/Car")['default'] + 'Human': typeof import("../components/Human")['default'] + 'RoadVehicleViz': typeof import("../components/RoadVehicleViz.vue")['default'] + 'TrafficLight': typeof import("../components/TrafficLight")['default'] + 'UnoIcon': typeof import("../node_modules/@unocss/nuxt/runtime/UnoIcon.vue")['default'] + 'NuxtWelcome': typeof import("../node_modules/nuxt/dist/app/components/welcome.vue")['default'] + 'NuxtLayout': typeof import("../node_modules/nuxt/dist/app/components/nuxt-layout")['default'] + 'NuxtErrorBoundary': typeof import("../node_modules/nuxt/dist/app/components/nuxt-error-boundary")['default'] + 'ClientOnly': typeof import("../node_modules/nuxt/dist/app/components/client-only")['default'] + 'DevOnly': typeof import("../node_modules/nuxt/dist/app/components/dev-only")['default'] + 'ServerPlaceholder': typeof import("../node_modules/nuxt/dist/app/components/server-placeholder")['default'] + 'NuxtLink': typeof import("../node_modules/nuxt/dist/app/components/nuxt-link")['default'] + 'NuxtLoadingIndicator': typeof import("../node_modules/nuxt/dist/app/components/nuxt-loading-indicator")['default'] + 'NuxtRouteAnnouncer': typeof import("../node_modules/nuxt/dist/app/components/nuxt-route-announcer")['default'] + 'NuxtImg': typeof import("../node_modules/nuxt/dist/app/components/nuxt-stubs")['NuxtImg'] + 'NuxtPicture': typeof import("../node_modules/nuxt/dist/app/components/nuxt-stubs")['NuxtPicture'] + 'NuxtPage': typeof import("../node_modules/nuxt/dist/pages/runtime/page")['default'] + 'NoScript': typeof import("../node_modules/nuxt/dist/head/runtime/components")['NoScript'] + 'Link': typeof import("../node_modules/nuxt/dist/head/runtime/components")['Link'] + 'Base': typeof import("../node_modules/nuxt/dist/head/runtime/components")['Base'] + 'Title': typeof import("../node_modules/nuxt/dist/head/runtime/components")['Title'] + 'Meta': typeof import("../node_modules/nuxt/dist/head/runtime/components")['Meta'] + 'Style': typeof import("../node_modules/nuxt/dist/head/runtime/components")['Style'] + 'Head': typeof import("../node_modules/nuxt/dist/head/runtime/components")['Head'] + 'Html': typeof import("../node_modules/nuxt/dist/head/runtime/components")['Html'] + 'Body': typeof import("../node_modules/nuxt/dist/head/runtime/components")['Body'] + 'NuxtIsland': typeof import("../node_modules/nuxt/dist/app/components/nuxt-island")['default'] + 'NuxtRouteAnnouncer': IslandComponent + 'LazyAxesReference': LazyComponent + 'LazyCar': LazyComponent + 'LazyHuman': LazyComponent + 'LazyRoadVehicleViz': LazyComponent + 'LazyTrafficLight': LazyComponent + 'LazyUnoIcon': LazyComponent + 'LazyNuxtWelcome': LazyComponent + 'LazyNuxtLayout': LazyComponent + 'LazyNuxtErrorBoundary': LazyComponent + 'LazyClientOnly': LazyComponent + 'LazyDevOnly': LazyComponent + 'LazyServerPlaceholder': LazyComponent + 'LazyNuxtLink': LazyComponent + 'LazyNuxtLoadingIndicator': LazyComponent + 'LazyNuxtRouteAnnouncer': LazyComponent + 'LazyNuxtImg': LazyComponent + 'LazyNuxtPicture': LazyComponent + 'LazyNuxtPage': LazyComponent + 'LazyNoScript': LazyComponent + 'LazyLink': LazyComponent + 'LazyBase': LazyComponent + 'LazyTitle': LazyComponent + 'LazyMeta': LazyComponent + 'LazyStyle': LazyComponent + 'LazyHead': LazyComponent + 'LazyHtml': LazyComponent + 'LazyBody': LazyComponent + 'LazyNuxtIsland': LazyComponent + 'LazyNuxtRouteAnnouncer': LazyComponent> +} + +declare module 'vue' { + export interface GlobalComponents extends _GlobalComponents { } +} + +export const AxesReference: typeof import("../components/AxesReference.vue")['default'] +export const Car: typeof import("../components/Car")['default'] +export const Human: typeof import("../components/Human")['default'] +export const RoadVehicleViz: typeof import("../components/RoadVehicleViz.vue")['default'] +export const TrafficLight: typeof import("../components/TrafficLight")['default'] +export const UnoIcon: typeof import("../node_modules/@unocss/nuxt/runtime/UnoIcon.vue")['default'] +export const NuxtWelcome: typeof import("../node_modules/nuxt/dist/app/components/welcome.vue")['default'] +export const NuxtLayout: typeof import("../node_modules/nuxt/dist/app/components/nuxt-layout")['default'] +export const NuxtErrorBoundary: typeof import("../node_modules/nuxt/dist/app/components/nuxt-error-boundary")['default'] +export const ClientOnly: typeof import("../node_modules/nuxt/dist/app/components/client-only")['default'] +export const DevOnly: typeof import("../node_modules/nuxt/dist/app/components/dev-only")['default'] +export const ServerPlaceholder: typeof import("../node_modules/nuxt/dist/app/components/server-placeholder")['default'] +export const NuxtLink: typeof import("../node_modules/nuxt/dist/app/components/nuxt-link")['default'] +export const NuxtLoadingIndicator: typeof import("../node_modules/nuxt/dist/app/components/nuxt-loading-indicator")['default'] +export const NuxtRouteAnnouncer: typeof import("../node_modules/nuxt/dist/app/components/nuxt-route-announcer")['default'] +export const NuxtImg: typeof import("../node_modules/nuxt/dist/app/components/nuxt-stubs")['NuxtImg'] +export const NuxtPicture: typeof import("../node_modules/nuxt/dist/app/components/nuxt-stubs")['NuxtPicture'] +export const NuxtPage: typeof import("../node_modules/nuxt/dist/pages/runtime/page")['default'] +export const NoScript: typeof import("../node_modules/nuxt/dist/head/runtime/components")['NoScript'] +export const Link: typeof import("../node_modules/nuxt/dist/head/runtime/components")['Link'] +export const Base: typeof import("../node_modules/nuxt/dist/head/runtime/components")['Base'] +export const Title: typeof import("../node_modules/nuxt/dist/head/runtime/components")['Title'] +export const Meta: typeof import("../node_modules/nuxt/dist/head/runtime/components")['Meta'] +export const Style: typeof import("../node_modules/nuxt/dist/head/runtime/components")['Style'] +export const Head: typeof import("../node_modules/nuxt/dist/head/runtime/components")['Head'] +export const Html: typeof import("../node_modules/nuxt/dist/head/runtime/components")['Html'] +export const Body: typeof import("../node_modules/nuxt/dist/head/runtime/components")['Body'] +export const NuxtIsland: typeof import("../node_modules/nuxt/dist/app/components/nuxt-island")['default'] +export const NuxtRouteAnnouncer: IslandComponent +export const LazyAxesReference: LazyComponent +export const LazyCar: LazyComponent +export const LazyHuman: LazyComponent +export const LazyRoadVehicleViz: LazyComponent +export const LazyTrafficLight: LazyComponent +export const LazyUnoIcon: LazyComponent +export const LazyNuxtWelcome: LazyComponent +export const LazyNuxtLayout: LazyComponent +export const LazyNuxtErrorBoundary: LazyComponent +export const LazyClientOnly: LazyComponent +export const LazyDevOnly: LazyComponent +export const LazyServerPlaceholder: LazyComponent +export const LazyNuxtLink: LazyComponent +export const LazyNuxtLoadingIndicator: LazyComponent +export const LazyNuxtRouteAnnouncer: LazyComponent +export const LazyNuxtImg: LazyComponent +export const LazyNuxtPicture: LazyComponent +export const LazyNuxtPage: LazyComponent +export const LazyNoScript: LazyComponent +export const LazyLink: LazyComponent +export const LazyBase: LazyComponent +export const LazyTitle: LazyComponent +export const LazyMeta: LazyComponent +export const LazyStyle: LazyComponent +export const LazyHead: LazyComponent +export const LazyHtml: LazyComponent +export const LazyBody: LazyComponent +export const LazyNuxtIsland: LazyComponent +export const LazyNuxtRouteAnnouncer: LazyComponent> + +export const componentNames: string[] diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/imports.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/imports.d.ts new file mode 100644 index 000000000..94d8219ea --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/imports.d.ts @@ -0,0 +1,32 @@ +export { useScriptTriggerConsent, useScriptEventPage, useScriptTriggerElement, useScript, useScriptGoogleAnalytics, useScriptPlausibleAnalytics, useScriptCrisp, useScriptClarity, useScriptCloudflareWebAnalytics, useScriptFathomAnalytics, useScriptMatomoAnalytics, useScriptGoogleTagManager, useScriptGoogleAdsense, useScriptSegment, useScriptMetaPixel, useScriptXPixel, useScriptIntercom, useScriptHotjar, useScriptStripe, useScriptLemonSqueezy, useScriptVimeoPlayer, useScriptYouTubePlayer, useScriptGoogleMaps, useScriptNpm, useScriptUmamiAnalytics, useScriptSnapchatPixel } from '#app/composables/script-stubs'; +export { isVue2, isVue3 } from 'vue-demi'; +export { defineNuxtLink } from '#app/components/nuxt-link'; +export { useNuxtApp, tryUseNuxtApp, defineNuxtPlugin, definePayloadPlugin, useRuntimeConfig, defineAppConfig } from '#app/nuxt'; +export { useAppConfig, updateAppConfig } from '#app/config'; +export { defineNuxtComponent } from '#app/composables/component'; +export { useAsyncData, useLazyAsyncData, useNuxtData, refreshNuxtData, clearNuxtData } from '#app/composables/asyncData'; +export { useHydration } from '#app/composables/hydrate'; +export { callOnce } from '#app/composables/once'; +export { useState, clearNuxtState } from '#app/composables/state'; +export { clearError, createError, isNuxtError, showError, useError } from '#app/composables/error'; +export { useFetch, useLazyFetch } from '#app/composables/fetch'; +export { useCookie, refreshCookie } from '#app/composables/cookie'; +export { onPrehydrate, prerenderRoutes, useRequestHeader, useRequestHeaders, useResponseHeader, useRequestEvent, useRequestFetch, setResponseStatus } from '#app/composables/ssr'; +export { onNuxtReady } from '#app/composables/ready'; +export { preloadComponents, prefetchComponents, preloadRouteComponents } from '#app/composables/preload'; +export { abortNavigation, addRouteMiddleware, defineNuxtRouteMiddleware, setPageLayout, navigateTo, useRoute, useRouter } from '#app/composables/router'; +export { isPrerendered, loadPayload, preloadPayload, definePayloadReducer, definePayloadReviver } from '#app/composables/payload'; +export { useLoadingIndicator } from '#app/composables/loading-indicator'; +export { getAppManifest, getRouteRules } from '#app/composables/manifest'; +export { reloadNuxtApp } from '#app/composables/chunk'; +export { useRequestURL } from '#app/composables/url'; +export { usePreviewMode } from '#app/composables/preview'; +export { useRouteAnnouncer } from '#app/composables/route-announcer'; +export { useRuntimeHook } from '#app/composables/runtime-hook'; +export { useHead, useHeadSafe, useServerHeadSafe, useServerHead, useSeoMeta, useServerSeoMeta, injectHead } from '#app/composables/head'; +export { onBeforeRouteLeave, onBeforeRouteUpdate, useLink } from 'vue-router'; +export { withCtx, withDirectives, withKeys, withMemo, withModifiers, withScopeId, onActivated, onBeforeMount, onBeforeUnmount, onBeforeUpdate, onDeactivated, onErrorCaptured, onMounted, onRenderTracked, onRenderTriggered, onServerPrefetch, onUnmounted, onUpdated, computed, customRef, isProxy, isReactive, isReadonly, isRef, markRaw, proxyRefs, reactive, readonly, ref, shallowReactive, shallowReadonly, shallowRef, toRaw, toRef, toRefs, triggerRef, unref, watch, watchEffect, watchPostEffect, watchSyncEffect, isShallow, effect, effectScope, getCurrentScope, onScopeDispose, defineComponent, defineAsyncComponent, resolveComponent, getCurrentInstance, h, inject, hasInjectionContext, nextTick, provide, mergeModels, toValue, useModel, useAttrs, useCssModule, useCssVars, useSlots, useTransitionState, useId, useTemplateRef, useShadowRoot, Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue'; +export { requestIdleCallback, cancelIdleCallback } from '#app/compat/idle-callback'; +export { setInterval } from '#app/compat/interval'; +export { HUMAN_BODY_RATIOS, HUMAN_TO_CAR_HEIGHT_RATIO } from '../utils/constants'; +export { definePageMeta } from '../node_modules/nuxt/dist/pages/runtime/composables'; \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/nuxt.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/nuxt.d.ts new file mode 100644 index 000000000..7ed344d33 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/nuxt.d.ts @@ -0,0 +1,22 @@ +// Generated by nuxi +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// + +export {} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/nuxt.json b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/nuxt.json new file mode 100644 index 000000000..e0cddd4b5 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/nuxt.json @@ -0,0 +1,9 @@ +{ + "_hash": "ZSSPpUqkABKhlhHw1INEi3K-kN_AvMblsSfoalBhuyw", + "project": { + "rootDir": "/Users/qhk/Library/CloudStorage/GoogleDrive-hangkai2@illinois.edu/My Drive/Academics/Graduate3/588/GEMstack/GEMstack/onboard/visualization/sr_viz/threeD" + }, + "versions": { + "nuxt": "3.16.1" + } +} \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/schema/nuxt.schema.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/schema/nuxt.schema.d.ts new file mode 100644 index 000000000..d9d266ce5 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/schema/nuxt.schema.d.ts @@ -0,0 +1,17 @@ +export interface NuxtCustomSchema { + +} +export type CustomAppConfig = Exclude +type _CustomAppConfig = CustomAppConfig + +declare module '@nuxt/schema' { + interface NuxtConfig extends Omit {} + interface NuxtOptions extends Omit {} + interface CustomAppConfig extends _CustomAppConfig {} +} + +declare module 'nuxt/schema' { + interface NuxtConfig extends Omit {} + interface NuxtOptions extends Omit {} + interface CustomAppConfig extends _CustomAppConfig {} +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/schema/nuxt.schema.json b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/schema/nuxt.schema.json new file mode 100644 index 000000000..034ff697e --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/schema/nuxt.schema.json @@ -0,0 +1,3 @@ +{ + "id": "#" +} \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/tsconfig.json b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/tsconfig.json new file mode 100644 index 000000000..1205b7bde --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/tsconfig.json @@ -0,0 +1,173 @@ +// Generated by nuxi +{ + "compilerOptions": { + "paths": { + "nitropack/types": [ + "../node_modules/nitropack/types" + ], + "nitropack/runtime": [ + "../node_modules/nitropack/runtime" + ], + "nitropack": [ + "../node_modules/nitropack" + ], + "defu": [ + "../node_modules/defu" + ], + "h3": [ + "../node_modules/h3" + ], + "consola": [ + "../node_modules/consola" + ], + "ofetch": [ + "../node_modules/ofetch" + ], + "@unhead/vue": [ + "../node_modules/@unhead/vue" + ], + "@nuxt/devtools": [ + "../node_modules/@nuxt/devtools" + ], + "@vue/runtime-core": [ + "../node_modules/@vue/runtime-core" + ], + "@vue/compiler-sfc": [ + "../node_modules/@vue/compiler-sfc" + ], + "unplugin-vue-router/client": [ + "../node_modules/unplugin-vue-router/client" + ], + "@nuxt/schema": [ + "../node_modules/@nuxt/schema" + ], + "nuxt": [ + "../node_modules/nuxt" + ], + "vite/client": [ + "../node_modules/vite/client" + ], + "~": [ + ".." + ], + "~/*": [ + "../*" + ], + "@": [ + ".." + ], + "@/*": [ + "../*" + ], + "~~": [ + ".." + ], + "~~/*": [ + "../*" + ], + "@@": [ + ".." + ], + "@@/*": [ + "../*" + ], + "#shared": [ + "../shared" + ], + "assets": [ + "../assets" + ], + "public": [ + "../public" + ], + "public/*": [ + "../public/*" + ], + "#app": [ + "../node_modules/nuxt/dist/app" + ], + "#app/*": [ + "../node_modules/nuxt/dist/app/*" + ], + "vue-demi": [ + "../node_modules/nuxt/dist/app/compat/vue-demi" + ], + "#vue-router": [ + "../node_modules/vue-router" + ], + "#unhead/composables": [ + "../node_modules/nuxt/dist/head/runtime/composables/v3" + ], + "#imports": [ + "./imports" + ], + "#app-manifest": [ + "./manifest/meta/b2c428c1-7be1-4c1c-b492-5128fccb89d9" + ], + "#components": [ + "./components" + ], + "#build": [ + "." + ], + "#build/*": [ + "./*" + ] + }, + "esModuleInterop": true, + "skipLibCheck": true, + "target": "ESNext", + "allowJs": true, + "resolveJsonModule": true, + "moduleDetection": "force", + "isolatedModules": true, + "verbatimModuleSyntax": true, + "strict": true, + "noUncheckedIndexedAccess": false, + "forceConsistentCasingInFileNames": true, + "noImplicitOverride": true, + "module": "preserve", + "noEmit": true, + "lib": [ + "ESNext", + "dom", + "dom.iterable", + "webworker" + ], + "jsx": "preserve", + "jsxImportSource": "vue", + "types": [], + "moduleResolution": "Bundler", + "useDefineForClassFields": true, + "noImplicitThis": true, + "allowSyntheticDefaultImports": true + }, + "include": [ + "./nuxt.d.ts", + "../.config/nuxt.*", + "../**/*", + "../node_modules/@unocss/nuxt/runtime", + "../node_modules/@unocss/nuxt/dist/runtime", + "../node_modules/@nuxt/devtools/runtime", + "../node_modules/@nuxt/devtools/dist/runtime", + "../node_modules/@nuxt/telemetry/runtime", + "../node_modules/@nuxt/telemetry/dist/runtime", + ".." + ], + "exclude": [ + "../dist", + "../node_modules", + "../../../../../../node_modules", + "../node_modules/nuxt/node_modules", + "../node_modules/@unocss/nuxt/node_modules", + "../node_modules/@nuxt/devtools/node_modules", + "../node_modules/@nuxt/telemetry/node_modules", + "../node_modules/@unocss/nuxt/runtime/server", + "../node_modules/@unocss/nuxt/dist/runtime/server", + "../node_modules/@nuxt/devtools/runtime/server", + "../node_modules/@nuxt/devtools/dist/runtime/server", + "../node_modules/@nuxt/telemetry/runtime/server", + "../node_modules/@nuxt/telemetry/dist/runtime/server", + "../.output" + ] +} \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/tsconfig.server.json b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/tsconfig.server.json new file mode 100644 index 000000000..dc195cab9 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/tsconfig.server.json @@ -0,0 +1,122 @@ +{ + "compilerOptions": { + "forceConsistentCasingInFileNames": true, + "strict": true, + "noEmit": true, + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "Bundler", + "allowJs": true, + "resolveJsonModule": true, + "jsx": "preserve", + "allowSyntheticDefaultImports": true, + "jsxFactory": "h", + "jsxFragmentFactory": "Fragment", + "paths": { + "#imports": [ + "./types/nitro-imports" + ], + "~/*": [ + "../*" + ], + "@/*": [ + "../*" + ], + "~~/*": [ + "../*" + ], + "@@/*": [ + "../*" + ], + "nitropack/types": [ + "../node_modules/nitropack/types" + ], + "nitropack/runtime": [ + "../node_modules/nitropack/runtime" + ], + "nitropack": [ + "../node_modules/nitropack" + ], + "defu": [ + "../node_modules/defu" + ], + "h3": [ + "../node_modules/h3" + ], + "consola": [ + "../node_modules/consola" + ], + "ofetch": [ + "../node_modules/ofetch" + ], + "@unhead/vue": [ + "../node_modules/@unhead/vue" + ], + "@nuxt/devtools": [ + "../node_modules/@nuxt/devtools" + ], + "@vue/runtime-core": [ + "../node_modules/@vue/runtime-core" + ], + "@vue/compiler-sfc": [ + "../node_modules/@vue/compiler-sfc" + ], + "unplugin-vue-router/client": [ + "../node_modules/unplugin-vue-router/client" + ], + "@nuxt/schema": [ + "../node_modules/@nuxt/schema" + ], + "nuxt": [ + "../node_modules/nuxt" + ], + "vite/client": [ + "../node_modules/vite/client" + ], + "#shared": [ + "../shared" + ], + "assets": [ + "../assets" + ], + "public": [ + "../public" + ], + "public/*": [ + "../public/*" + ], + "#build": [ + "./" + ], + "#internal/nuxt/paths": [ + "../node_modules/nuxt/dist/core/runtime/nitro/utils/paths" + ], + "#unhead/composables": [ + "../node_modules/nuxt/dist/head/runtime/composables/v3" + ] + }, + "lib": [ + "esnext", + "webworker", + "dom.iterable" + ] + }, + "include": [ + "./types/nitro-nuxt.d.ts", + "../node_modules/@unocss/nuxt/runtime/server", + "../node_modules/@nuxt/devtools/runtime/server", + "../node_modules/@nuxt/telemetry/runtime/server", + "./types/nitro.d.ts", + "../**/*", + "../server/**/*" + ], + "exclude": [ + "../node_modules", + "../../../../../../node_modules", + "../node_modules/nuxt/node_modules", + "../node_modules/@unocss/nuxt/node_modules", + "../node_modules/@nuxt/devtools/node_modules", + "../node_modules/@nuxt/telemetry/node_modules", + "../dist" + ] +} \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/app-defaults.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/app-defaults.d.ts new file mode 100644 index 000000000..7a36d008d --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/app-defaults.d.ts @@ -0,0 +1,7 @@ + +declare module 'nuxt/app/defaults' { + type DefaultAsyncDataErrorValue = null + type DefaultAsyncDataValue = null + type DefaultErrorValue = null + type DedupeOption = boolean | 'cancel' | 'defer' +} \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/app.config.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/app.config.d.ts new file mode 100644 index 000000000..23d972d1d --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/app.config.d.ts @@ -0,0 +1,31 @@ + +import type { CustomAppConfig } from 'nuxt/schema' +import type { Defu } from 'defu' + + +declare const inlineConfig = { + "nuxt": {} +} +type ResolvedAppConfig = Defu +type IsAny = 0 extends 1 & T ? true : false + +type MergedAppConfig, Custom extends Record> = { + [K in keyof (Resolved & Custom)]: K extends keyof Custom + ? unknown extends Custom[K] + ? Resolved[K] + : IsAny extends true + ? Resolved[K] + : Custom[K] extends Record + ? Resolved[K] extends Record + ? MergedAppConfig + : Exclude + : Exclude + : Resolved[K] +} + +declare module 'nuxt/schema' { + interface AppConfig extends MergedAppConfig { } +} +declare module '@nuxt/schema' { + interface AppConfig extends MergedAppConfig { } +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/build.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/build.d.ts new file mode 100644 index 000000000..42040d97b --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/build.d.ts @@ -0,0 +1,22 @@ +declare module "#build/app-component.mjs"; +declare module "#build/nitro.client.mjs"; +declare module "#build/plugins.client.mjs"; +declare module "#build/css.mjs"; +declare module "#build/fetch.mjs"; +declare module "#build/error-component.mjs"; +declare module "#build/layouts.mjs"; +declare module "#build/middleware.mjs"; +declare module "#build/nuxt.config.mjs"; +declare module "#build/paths.mjs"; +declare module "#build/root-component.mjs"; +declare module "#build/plugins.server.mjs"; +declare module "#build/test-component-wrapper.mjs"; +declare module "#build/unocss.mjs"; +declare module "#build/routes.mjs"; +declare module "#build/pages.mjs"; +declare module "#build/router.options.mjs"; +declare module "#build/unhead-options.mjs"; +declare module "#build/unhead.config.mjs"; +declare module "#build/components.plugin.mjs"; +declare module "#build/component-names.mjs"; +declare module "#build/components.islands.mjs"; diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/builder-env.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/builder-env.d.ts new file mode 100644 index 000000000..0eb132902 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/builder-env.d.ts @@ -0,0 +1 @@ +import "vite/client"; \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/imports.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/imports.d.ts new file mode 100644 index 000000000..585706af9 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/imports.d.ts @@ -0,0 +1,356 @@ +// Generated by auto imports +export {} +declare global { + const HUMAN_BODY_RATIOS: typeof import('../../utils/constants')['HUMAN_BODY_RATIOS'] + const HUMAN_TO_CAR_HEIGHT_RATIO: typeof import('../../utils/constants')['HUMAN_TO_CAR_HEIGHT_RATIO'] + const abortNavigation: typeof import('../../node_modules/nuxt/dist/app/composables/router')['abortNavigation'] + const addRouteMiddleware: typeof import('../../node_modules/nuxt/dist/app/composables/router')['addRouteMiddleware'] + const callOnce: typeof import('../../node_modules/nuxt/dist/app/composables/once')['callOnce'] + const cancelIdleCallback: typeof import('../../node_modules/nuxt/dist/app/compat/idle-callback')['cancelIdleCallback'] + const clearError: typeof import('../../node_modules/nuxt/dist/app/composables/error')['clearError'] + const clearNuxtData: typeof import('../../node_modules/nuxt/dist/app/composables/asyncData')['clearNuxtData'] + const clearNuxtState: typeof import('../../node_modules/nuxt/dist/app/composables/state')['clearNuxtState'] + const computed: typeof import('vue')['computed'] + const createError: typeof import('../../node_modules/nuxt/dist/app/composables/error')['createError'] + const customRef: typeof import('vue')['customRef'] + const defineAppConfig: typeof import('../../node_modules/nuxt/dist/app/nuxt')['defineAppConfig'] + const defineAsyncComponent: typeof import('vue')['defineAsyncComponent'] + const defineComponent: typeof import('vue')['defineComponent'] + const defineNuxtComponent: typeof import('../../node_modules/nuxt/dist/app/composables/component')['defineNuxtComponent'] + const defineNuxtLink: typeof import('../../node_modules/nuxt/dist/app/components/nuxt-link')['defineNuxtLink'] + const defineNuxtPlugin: typeof import('../../node_modules/nuxt/dist/app/nuxt')['defineNuxtPlugin'] + const defineNuxtRouteMiddleware: typeof import('../../node_modules/nuxt/dist/app/composables/router')['defineNuxtRouteMiddleware'] + const definePageMeta: typeof import('../../node_modules/nuxt/dist/pages/runtime/composables')['definePageMeta'] + const definePayloadPlugin: typeof import('../../node_modules/nuxt/dist/app/nuxt')['definePayloadPlugin'] + const definePayloadReducer: typeof import('../../node_modules/nuxt/dist/app/composables/payload')['definePayloadReducer'] + const definePayloadReviver: typeof import('../../node_modules/nuxt/dist/app/composables/payload')['definePayloadReviver'] + const effect: typeof import('vue')['effect'] + const effectScope: typeof import('vue')['effectScope'] + const getAppManifest: typeof import('../../node_modules/nuxt/dist/app/composables/manifest')['getAppManifest'] + const getCurrentInstance: typeof import('vue')['getCurrentInstance'] + const getCurrentScope: typeof import('vue')['getCurrentScope'] + const getRouteRules: typeof import('../../node_modules/nuxt/dist/app/composables/manifest')['getRouteRules'] + const h: typeof import('vue')['h'] + const hasInjectionContext: typeof import('vue')['hasInjectionContext'] + const inject: typeof import('vue')['inject'] + const injectHead: typeof import('../../node_modules/nuxt/dist/app/composables/head')['injectHead'] + const isNuxtError: typeof import('../../node_modules/nuxt/dist/app/composables/error')['isNuxtError'] + const isPrerendered: typeof import('../../node_modules/nuxt/dist/app/composables/payload')['isPrerendered'] + const isProxy: typeof import('vue')['isProxy'] + const isReactive: typeof import('vue')['isReactive'] + const isReadonly: typeof import('vue')['isReadonly'] + const isRef: typeof import('vue')['isRef'] + const isShallow: typeof import('vue')['isShallow'] + const isVue2: typeof import('../../node_modules/nuxt/dist/app/compat/vue-demi')['isVue2'] + const isVue3: typeof import('../../node_modules/nuxt/dist/app/compat/vue-demi')['isVue3'] + const loadPayload: typeof import('../../node_modules/nuxt/dist/app/composables/payload')['loadPayload'] + const markRaw: typeof import('vue')['markRaw'] + const mergeModels: typeof import('vue')['mergeModels'] + const navigateTo: typeof import('../../node_modules/nuxt/dist/app/composables/router')['navigateTo'] + const nextTick: typeof import('vue')['nextTick'] + const onActivated: typeof import('vue')['onActivated'] + const onBeforeMount: typeof import('vue')['onBeforeMount'] + const onBeforeRouteLeave: typeof import('vue-router')['onBeforeRouteLeave'] + const onBeforeRouteUpdate: typeof import('vue-router')['onBeforeRouteUpdate'] + const onBeforeUnmount: typeof import('vue')['onBeforeUnmount'] + const onBeforeUpdate: typeof import('vue')['onBeforeUpdate'] + const onDeactivated: typeof import('vue')['onDeactivated'] + const onErrorCaptured: typeof import('vue')['onErrorCaptured'] + const onMounted: typeof import('vue')['onMounted'] + const onNuxtReady: typeof import('../../node_modules/nuxt/dist/app/composables/ready')['onNuxtReady'] + const onPrehydrate: typeof import('../../node_modules/nuxt/dist/app/composables/ssr')['onPrehydrate'] + const onRenderTracked: typeof import('vue')['onRenderTracked'] + const onRenderTriggered: typeof import('vue')['onRenderTriggered'] + const onScopeDispose: typeof import('vue')['onScopeDispose'] + const onServerPrefetch: typeof import('vue')['onServerPrefetch'] + const onUnmounted: typeof import('vue')['onUnmounted'] + const onUpdated: typeof import('vue')['onUpdated'] + const prefetchComponents: typeof import('../../node_modules/nuxt/dist/app/composables/preload')['prefetchComponents'] + const preloadComponents: typeof import('../../node_modules/nuxt/dist/app/composables/preload')['preloadComponents'] + const preloadPayload: typeof import('../../node_modules/nuxt/dist/app/composables/payload')['preloadPayload'] + const preloadRouteComponents: typeof import('../../node_modules/nuxt/dist/app/composables/preload')['preloadRouteComponents'] + const prerenderRoutes: typeof import('../../node_modules/nuxt/dist/app/composables/ssr')['prerenderRoutes'] + const provide: typeof import('vue')['provide'] + const proxyRefs: typeof import('vue')['proxyRefs'] + const reactive: typeof import('vue')['reactive'] + const readonly: typeof import('vue')['readonly'] + const ref: typeof import('vue')['ref'] + const refreshCookie: typeof import('../../node_modules/nuxt/dist/app/composables/cookie')['refreshCookie'] + const refreshNuxtData: typeof import('../../node_modules/nuxt/dist/app/composables/asyncData')['refreshNuxtData'] + const reloadNuxtApp: typeof import('../../node_modules/nuxt/dist/app/composables/chunk')['reloadNuxtApp'] + const requestIdleCallback: typeof import('../../node_modules/nuxt/dist/app/compat/idle-callback')['requestIdleCallback'] + const resolveComponent: typeof import('vue')['resolveComponent'] + const setInterval: typeof import('../../node_modules/nuxt/dist/app/compat/interval')['setInterval'] + const setPageLayout: typeof import('../../node_modules/nuxt/dist/app/composables/router')['setPageLayout'] + const setResponseStatus: typeof import('../../node_modules/nuxt/dist/app/composables/ssr')['setResponseStatus'] + const shallowReactive: typeof import('vue')['shallowReactive'] + const shallowReadonly: typeof import('vue')['shallowReadonly'] + const shallowRef: typeof import('vue')['shallowRef'] + const showError: typeof import('../../node_modules/nuxt/dist/app/composables/error')['showError'] + const toRaw: typeof import('vue')['toRaw'] + const toRef: typeof import('vue')['toRef'] + const toRefs: typeof import('vue')['toRefs'] + const toValue: typeof import('vue')['toValue'] + const triggerRef: typeof import('vue')['triggerRef'] + const tryUseNuxtApp: typeof import('../../node_modules/nuxt/dist/app/nuxt')['tryUseNuxtApp'] + const unref: typeof import('vue')['unref'] + const updateAppConfig: typeof import('../../node_modules/nuxt/dist/app/config')['updateAppConfig'] + const useAppConfig: typeof import('../../node_modules/nuxt/dist/app/config')['useAppConfig'] + const useAsyncData: typeof import('../../node_modules/nuxt/dist/app/composables/asyncData')['useAsyncData'] + const useAttrs: typeof import('vue')['useAttrs'] + const useCookie: typeof import('../../node_modules/nuxt/dist/app/composables/cookie')['useCookie'] + const useCssModule: typeof import('vue')['useCssModule'] + const useCssVars: typeof import('vue')['useCssVars'] + const useError: typeof import('../../node_modules/nuxt/dist/app/composables/error')['useError'] + const useFetch: typeof import('../../node_modules/nuxt/dist/app/composables/fetch')['useFetch'] + const useHead: typeof import('../../node_modules/nuxt/dist/app/composables/head')['useHead'] + const useHeadSafe: typeof import('../../node_modules/nuxt/dist/app/composables/head')['useHeadSafe'] + const useHydration: typeof import('../../node_modules/nuxt/dist/app/composables/hydrate')['useHydration'] + const useId: typeof import('vue')['useId'] + const useLazyAsyncData: typeof import('../../node_modules/nuxt/dist/app/composables/asyncData')['useLazyAsyncData'] + const useLazyFetch: typeof import('../../node_modules/nuxt/dist/app/composables/fetch')['useLazyFetch'] + const useLink: typeof import('vue-router')['useLink'] + const useLoadingIndicator: typeof import('../../node_modules/nuxt/dist/app/composables/loading-indicator')['useLoadingIndicator'] + const useModel: typeof import('vue')['useModel'] + const useNuxtApp: typeof import('../../node_modules/nuxt/dist/app/nuxt')['useNuxtApp'] + const useNuxtData: typeof import('../../node_modules/nuxt/dist/app/composables/asyncData')['useNuxtData'] + const usePreviewMode: typeof import('../../node_modules/nuxt/dist/app/composables/preview')['usePreviewMode'] + const useRequestEvent: typeof import('../../node_modules/nuxt/dist/app/composables/ssr')['useRequestEvent'] + const useRequestFetch: typeof import('../../node_modules/nuxt/dist/app/composables/ssr')['useRequestFetch'] + const useRequestHeader: typeof import('../../node_modules/nuxt/dist/app/composables/ssr')['useRequestHeader'] + const useRequestHeaders: typeof import('../../node_modules/nuxt/dist/app/composables/ssr')['useRequestHeaders'] + const useRequestURL: typeof import('../../node_modules/nuxt/dist/app/composables/url')['useRequestURL'] + const useResponseHeader: typeof import('../../node_modules/nuxt/dist/app/composables/ssr')['useResponseHeader'] + const useRoute: typeof import('../../node_modules/nuxt/dist/app/composables/router')['useRoute'] + const useRouteAnnouncer: typeof import('../../node_modules/nuxt/dist/app/composables/route-announcer')['useRouteAnnouncer'] + const useRouter: typeof import('../../node_modules/nuxt/dist/app/composables/router')['useRouter'] + const useRuntimeConfig: typeof import('../../node_modules/nuxt/dist/app/nuxt')['useRuntimeConfig'] + const useRuntimeHook: typeof import('../../node_modules/nuxt/dist/app/composables/runtime-hook')['useRuntimeHook'] + const useScript: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScript'] + const useScriptClarity: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptClarity'] + const useScriptCloudflareWebAnalytics: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptCloudflareWebAnalytics'] + const useScriptCrisp: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptCrisp'] + const useScriptEventPage: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptEventPage'] + const useScriptFathomAnalytics: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptFathomAnalytics'] + const useScriptGoogleAdsense: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptGoogleAdsense'] + const useScriptGoogleAnalytics: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptGoogleAnalytics'] + const useScriptGoogleMaps: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptGoogleMaps'] + const useScriptGoogleTagManager: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptGoogleTagManager'] + const useScriptHotjar: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptHotjar'] + const useScriptIntercom: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptIntercom'] + const useScriptLemonSqueezy: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptLemonSqueezy'] + const useScriptMatomoAnalytics: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptMatomoAnalytics'] + const useScriptMetaPixel: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptMetaPixel'] + const useScriptNpm: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptNpm'] + const useScriptPlausibleAnalytics: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptPlausibleAnalytics'] + const useScriptSegment: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptSegment'] + const useScriptSnapchatPixel: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptSnapchatPixel'] + const useScriptStripe: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptStripe'] + const useScriptTriggerConsent: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptTriggerConsent'] + const useScriptTriggerElement: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptTriggerElement'] + const useScriptUmamiAnalytics: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptUmamiAnalytics'] + const useScriptVimeoPlayer: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptVimeoPlayer'] + const useScriptXPixel: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptXPixel'] + const useScriptYouTubePlayer: typeof import('../../node_modules/nuxt/dist/app/composables/script-stubs')['useScriptYouTubePlayer'] + const useSeoMeta: typeof import('../../node_modules/nuxt/dist/app/composables/head')['useSeoMeta'] + const useServerHead: typeof import('../../node_modules/nuxt/dist/app/composables/head')['useServerHead'] + const useServerHeadSafe: typeof import('../../node_modules/nuxt/dist/app/composables/head')['useServerHeadSafe'] + const useServerSeoMeta: typeof import('../../node_modules/nuxt/dist/app/composables/head')['useServerSeoMeta'] + const useShadowRoot: typeof import('vue')['useShadowRoot'] + const useSlots: typeof import('vue')['useSlots'] + const useState: typeof import('../../node_modules/nuxt/dist/app/composables/state')['useState'] + const useTemplateRef: typeof import('vue')['useTemplateRef'] + const useTransitionState: typeof import('vue')['useTransitionState'] + const watch: typeof import('vue')['watch'] + const watchEffect: typeof import('vue')['watchEffect'] + const watchPostEffect: typeof import('vue')['watchPostEffect'] + const watchSyncEffect: typeof import('vue')['watchSyncEffect'] + const withCtx: typeof import('vue')['withCtx'] + const withDirectives: typeof import('vue')['withDirectives'] + const withKeys: typeof import('vue')['withKeys'] + const withMemo: typeof import('vue')['withMemo'] + const withModifiers: typeof import('vue')['withModifiers'] + const withScopeId: typeof import('vue')['withScopeId'] +} +// for type re-export +declare global { + // @ts-ignore + export type { Component, ComponentPublicInstance, ComputedRef, DirectiveBinding, ExtractDefaultPropTypes, ExtractPropTypes, ExtractPublicPropTypes, InjectionKey, PropType, Ref, MaybeRef, MaybeRefOrGetter, VNode, WritableComputedRef } from 'vue' + import('vue') +} +// for vue template auto import +import { UnwrapRef } from 'vue' +declare module 'vue' { + interface ComponentCustomProperties { + readonly HUMAN_BODY_RATIOS: UnwrapRef + readonly HUMAN_TO_CAR_HEIGHT_RATIO: UnwrapRef + readonly abortNavigation: UnwrapRef + readonly addRouteMiddleware: UnwrapRef + readonly callOnce: UnwrapRef + readonly cancelIdleCallback: UnwrapRef + readonly clearError: UnwrapRef + readonly clearNuxtData: UnwrapRef + readonly clearNuxtState: UnwrapRef + readonly computed: UnwrapRef + readonly createError: UnwrapRef + readonly customRef: UnwrapRef + readonly defineAppConfig: UnwrapRef + readonly defineAsyncComponent: UnwrapRef + readonly defineComponent: UnwrapRef + readonly defineNuxtComponent: UnwrapRef + readonly defineNuxtLink: UnwrapRef + readonly defineNuxtPlugin: UnwrapRef + readonly defineNuxtRouteMiddleware: UnwrapRef + readonly definePageMeta: UnwrapRef + readonly definePayloadPlugin: UnwrapRef + readonly definePayloadReducer: UnwrapRef + readonly definePayloadReviver: UnwrapRef + readonly effect: UnwrapRef + readonly effectScope: UnwrapRef + readonly getAppManifest: UnwrapRef + readonly getCurrentInstance: UnwrapRef + readonly getCurrentScope: UnwrapRef + readonly getRouteRules: UnwrapRef + readonly h: UnwrapRef + readonly hasInjectionContext: UnwrapRef + readonly inject: UnwrapRef + readonly injectHead: UnwrapRef + readonly isNuxtError: UnwrapRef + readonly isPrerendered: UnwrapRef + readonly isProxy: UnwrapRef + readonly isReactive: UnwrapRef + readonly isReadonly: UnwrapRef + readonly isRef: UnwrapRef + readonly isShallow: UnwrapRef + readonly isVue2: UnwrapRef + readonly isVue3: UnwrapRef + readonly loadPayload: UnwrapRef + readonly markRaw: UnwrapRef + readonly mergeModels: UnwrapRef + readonly navigateTo: UnwrapRef + readonly nextTick: UnwrapRef + readonly onActivated: UnwrapRef + readonly onBeforeMount: UnwrapRef + readonly onBeforeRouteLeave: UnwrapRef + readonly onBeforeRouteUpdate: UnwrapRef + readonly onBeforeUnmount: UnwrapRef + readonly onBeforeUpdate: UnwrapRef + readonly onDeactivated: UnwrapRef + readonly onErrorCaptured: UnwrapRef + readonly onMounted: UnwrapRef + readonly onNuxtReady: UnwrapRef + readonly onPrehydrate: UnwrapRef + readonly onRenderTracked: UnwrapRef + readonly onRenderTriggered: UnwrapRef + readonly onScopeDispose: UnwrapRef + readonly onServerPrefetch: UnwrapRef + readonly onUnmounted: UnwrapRef + readonly onUpdated: UnwrapRef + readonly prefetchComponents: UnwrapRef + readonly preloadComponents: UnwrapRef + readonly preloadPayload: UnwrapRef + readonly preloadRouteComponents: UnwrapRef + readonly prerenderRoutes: UnwrapRef + readonly provide: UnwrapRef + readonly proxyRefs: UnwrapRef + readonly reactive: UnwrapRef + readonly readonly: UnwrapRef + readonly ref: UnwrapRef + readonly refreshCookie: UnwrapRef + readonly refreshNuxtData: UnwrapRef + readonly reloadNuxtApp: UnwrapRef + readonly requestIdleCallback: UnwrapRef + readonly resolveComponent: UnwrapRef + readonly setInterval: UnwrapRef + readonly setPageLayout: UnwrapRef + readonly setResponseStatus: UnwrapRef + readonly shallowReactive: UnwrapRef + readonly shallowReadonly: UnwrapRef + readonly shallowRef: UnwrapRef + readonly showError: UnwrapRef + readonly toRaw: UnwrapRef + readonly toRef: UnwrapRef + readonly toRefs: UnwrapRef + readonly toValue: UnwrapRef + readonly triggerRef: UnwrapRef + readonly tryUseNuxtApp: UnwrapRef + readonly unref: UnwrapRef + readonly updateAppConfig: UnwrapRef + readonly useAppConfig: UnwrapRef + readonly useAsyncData: UnwrapRef + readonly useAttrs: UnwrapRef + readonly useCookie: UnwrapRef + readonly useCssModule: UnwrapRef + readonly useCssVars: UnwrapRef + readonly useError: UnwrapRef + readonly useFetch: UnwrapRef + readonly useHead: UnwrapRef + readonly useHeadSafe: UnwrapRef + readonly useHydration: UnwrapRef + readonly useId: UnwrapRef + readonly useLazyAsyncData: UnwrapRef + readonly useLazyFetch: UnwrapRef + readonly useLink: UnwrapRef + readonly useLoadingIndicator: UnwrapRef + readonly useModel: UnwrapRef + readonly useNuxtApp: UnwrapRef + readonly useNuxtData: UnwrapRef + readonly usePreviewMode: UnwrapRef + readonly useRequestEvent: UnwrapRef + readonly useRequestFetch: UnwrapRef + readonly useRequestHeader: UnwrapRef + readonly useRequestHeaders: UnwrapRef + readonly useRequestURL: UnwrapRef + readonly useResponseHeader: UnwrapRef + readonly useRoute: UnwrapRef + readonly useRouteAnnouncer: UnwrapRef + readonly useRouter: UnwrapRef + readonly useRuntimeConfig: UnwrapRef + readonly useRuntimeHook: UnwrapRef + readonly useScript: UnwrapRef + readonly useScriptClarity: UnwrapRef + readonly useScriptCloudflareWebAnalytics: UnwrapRef + readonly useScriptCrisp: UnwrapRef + readonly useScriptEventPage: UnwrapRef + readonly useScriptFathomAnalytics: UnwrapRef + readonly useScriptGoogleAdsense: UnwrapRef + readonly useScriptGoogleAnalytics: UnwrapRef + readonly useScriptGoogleMaps: UnwrapRef + readonly useScriptGoogleTagManager: UnwrapRef + readonly useScriptHotjar: UnwrapRef + readonly useScriptIntercom: UnwrapRef + readonly useScriptLemonSqueezy: UnwrapRef + readonly useScriptMatomoAnalytics: UnwrapRef + readonly useScriptMetaPixel: UnwrapRef + readonly useScriptNpm: UnwrapRef + readonly useScriptPlausibleAnalytics: UnwrapRef + readonly useScriptSegment: UnwrapRef + readonly useScriptSnapchatPixel: UnwrapRef + readonly useScriptStripe: UnwrapRef + readonly useScriptTriggerConsent: UnwrapRef + readonly useScriptTriggerElement: UnwrapRef + readonly useScriptUmamiAnalytics: UnwrapRef + readonly useScriptVimeoPlayer: UnwrapRef + readonly useScriptXPixel: UnwrapRef + readonly useScriptYouTubePlayer: UnwrapRef + readonly useSeoMeta: UnwrapRef + readonly useServerHead: UnwrapRef + readonly useServerHeadSafe: UnwrapRef + readonly useServerSeoMeta: UnwrapRef + readonly useShadowRoot: UnwrapRef + readonly useSlots: UnwrapRef + readonly useState: UnwrapRef + readonly useTemplateRef: UnwrapRef + readonly useTransitionState: UnwrapRef + readonly watch: UnwrapRef + readonly watchEffect: UnwrapRef + readonly watchPostEffect: UnwrapRef + readonly watchSyncEffect: UnwrapRef + readonly withCtx: UnwrapRef + readonly withDirectives: UnwrapRef + readonly withKeys: UnwrapRef + readonly withMemo: UnwrapRef + readonly withModifiers: UnwrapRef + readonly withScopeId: UnwrapRef + } +} \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/layouts.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/layouts.d.ts new file mode 100644 index 000000000..5a6f1868d --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/layouts.d.ts @@ -0,0 +1,7 @@ +import type { ComputedRef, MaybeRef } from 'vue' +export type LayoutKey = string +declare module "../../node_modules/nuxt/dist/pages/runtime/composables" { + interface PageMeta { + layout?: MaybeRef | ComputedRef + } +} \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/middleware.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/middleware.d.ts new file mode 100644 index 000000000..c018923cf --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/middleware.d.ts @@ -0,0 +1,7 @@ +import type { NavigationGuard } from 'vue-router' +export type MiddlewareKey = never +declare module "../../node_modules/nuxt/dist/pages/runtime/composables" { + interface PageMeta { + middleware?: MiddlewareKey | NavigationGuard | Array + } +} \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro-config.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro-config.d.ts new file mode 100644 index 000000000..94df18ab1 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro-config.d.ts @@ -0,0 +1,14 @@ +// Generated by nitro + +// App Config +import type { Defu } from 'defu' + + + +type UserAppConfig = Defu<{}, []> + +declare module "nitropack/types" { + interface AppConfig extends UserAppConfig {} + +} +export {} \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro-imports.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro-imports.d.ts new file mode 100644 index 000000000..d8f55d612 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro-imports.d.ts @@ -0,0 +1,141 @@ +declare global { + const __buildAssetsURL: typeof import('../../node_modules/nuxt/dist/core/runtime/nitro/utils/paths')['buildAssetsURL'] + const __publicAssetsURL: typeof import('../../node_modules/nuxt/dist/core/runtime/nitro/utils/paths')['publicAssetsURL'] + const appendCorsHeaders: typeof import('../../node_modules/h3')['appendCorsHeaders'] + const appendCorsPreflightHeaders: typeof import('../../node_modules/h3')['appendCorsPreflightHeaders'] + const appendHeader: typeof import('../../node_modules/h3')['appendHeader'] + const appendHeaders: typeof import('../../node_modules/h3')['appendHeaders'] + const appendResponseHeader: typeof import('../../node_modules/h3')['appendResponseHeader'] + const appendResponseHeaders: typeof import('../../node_modules/h3')['appendResponseHeaders'] + const assertMethod: typeof import('../../node_modules/h3')['assertMethod'] + const cachedEventHandler: typeof import('../../node_modules/nitropack/dist/runtime/internal/cache')['cachedEventHandler'] + const cachedFunction: typeof import('../../node_modules/nitropack/dist/runtime/internal/cache')['cachedFunction'] + const callNodeListener: typeof import('../../node_modules/h3')['callNodeListener'] + const clearResponseHeaders: typeof import('../../node_modules/h3')['clearResponseHeaders'] + const clearSession: typeof import('../../node_modules/h3')['clearSession'] + const createApp: typeof import('../../node_modules/h3')['createApp'] + const createAppEventHandler: typeof import('../../node_modules/h3')['createAppEventHandler'] + const createError: typeof import('../../node_modules/h3')['createError'] + const createEvent: typeof import('../../node_modules/h3')['createEvent'] + const createEventStream: typeof import('../../node_modules/h3')['createEventStream'] + const createRouter: typeof import('../../node_modules/h3')['createRouter'] + const defaultContentType: typeof import('../../node_modules/h3')['defaultContentType'] + const defineAppConfig: typeof import('../../node_modules/nuxt/dist/core/runtime/nitro/utils/config')['defineAppConfig'] + const defineCachedEventHandler: typeof import('../../node_modules/nitropack/dist/runtime/internal/cache')['defineCachedEventHandler'] + const defineCachedFunction: typeof import('../../node_modules/nitropack/dist/runtime/internal/cache')['defineCachedFunction'] + const defineEventHandler: typeof import('../../node_modules/h3')['defineEventHandler'] + const defineLazyEventHandler: typeof import('../../node_modules/h3')['defineLazyEventHandler'] + const defineNitroErrorHandler: typeof import('../../node_modules/nitropack/dist/runtime/internal/error/utils')['defineNitroErrorHandler'] + const defineNitroPlugin: typeof import('../../node_modules/nitropack/dist/runtime/internal/plugin')['defineNitroPlugin'] + const defineNodeListener: typeof import('../../node_modules/h3')['defineNodeListener'] + const defineNodeMiddleware: typeof import('../../node_modules/h3')['defineNodeMiddleware'] + const defineRenderHandler: typeof import('../../node_modules/nitropack/dist/runtime/internal/renderer')['defineRenderHandler'] + const defineRequestMiddleware: typeof import('../../node_modules/h3')['defineRequestMiddleware'] + const defineResponseMiddleware: typeof import('../../node_modules/h3')['defineResponseMiddleware'] + const defineRouteMeta: typeof import('../../node_modules/nitropack/dist/runtime/internal/meta')['defineRouteMeta'] + const defineTask: typeof import('../../node_modules/nitropack/dist/runtime/internal/task')['defineTask'] + const defineWebSocket: typeof import('../../node_modules/h3')['defineWebSocket'] + const defineWebSocketHandler: typeof import('../../node_modules/h3')['defineWebSocketHandler'] + const deleteCookie: typeof import('../../node_modules/h3')['deleteCookie'] + const dynamicEventHandler: typeof import('../../node_modules/h3')['dynamicEventHandler'] + const eventHandler: typeof import('../../node_modules/h3')['eventHandler'] + const fetchWithEvent: typeof import('../../node_modules/h3')['fetchWithEvent'] + const fromNodeMiddleware: typeof import('../../node_modules/h3')['fromNodeMiddleware'] + const fromPlainHandler: typeof import('../../node_modules/h3')['fromPlainHandler'] + const fromWebHandler: typeof import('../../node_modules/h3')['fromWebHandler'] + const getCookie: typeof import('../../node_modules/h3')['getCookie'] + const getHeader: typeof import('../../node_modules/h3')['getHeader'] + const getHeaders: typeof import('../../node_modules/h3')['getHeaders'] + const getMethod: typeof import('../../node_modules/h3')['getMethod'] + const getProxyRequestHeaders: typeof import('../../node_modules/h3')['getProxyRequestHeaders'] + const getQuery: typeof import('../../node_modules/h3')['getQuery'] + const getRequestFingerprint: typeof import('../../node_modules/h3')['getRequestFingerprint'] + const getRequestHeader: typeof import('../../node_modules/h3')['getRequestHeader'] + const getRequestHeaders: typeof import('../../node_modules/h3')['getRequestHeaders'] + const getRequestHost: typeof import('../../node_modules/h3')['getRequestHost'] + const getRequestIP: typeof import('../../node_modules/h3')['getRequestIP'] + const getRequestPath: typeof import('../../node_modules/h3')['getRequestPath'] + const getRequestProtocol: typeof import('../../node_modules/h3')['getRequestProtocol'] + const getRequestURL: typeof import('../../node_modules/h3')['getRequestURL'] + const getRequestWebStream: typeof import('../../node_modules/h3')['getRequestWebStream'] + const getResponseHeader: typeof import('../../node_modules/h3')['getResponseHeader'] + const getResponseHeaders: typeof import('../../node_modules/h3')['getResponseHeaders'] + const getResponseStatus: typeof import('../../node_modules/h3')['getResponseStatus'] + const getResponseStatusText: typeof import('../../node_modules/h3')['getResponseStatusText'] + const getRouteRules: typeof import('../../node_modules/nitropack/dist/runtime/internal/route-rules')['getRouteRules'] + const getRouterParam: typeof import('../../node_modules/h3')['getRouterParam'] + const getRouterParams: typeof import('../../node_modules/h3')['getRouterParams'] + const getSession: typeof import('../../node_modules/h3')['getSession'] + const getValidatedQuery: typeof import('../../node_modules/h3')['getValidatedQuery'] + const getValidatedRouterParams: typeof import('../../node_modules/h3')['getValidatedRouterParams'] + const handleCacheHeaders: typeof import('../../node_modules/h3')['handleCacheHeaders'] + const handleCors: typeof import('../../node_modules/h3')['handleCors'] + const isCorsOriginAllowed: typeof import('../../node_modules/h3')['isCorsOriginAllowed'] + const isError: typeof import('../../node_modules/h3')['isError'] + const isEvent: typeof import('../../node_modules/h3')['isEvent'] + const isEventHandler: typeof import('../../node_modules/h3')['isEventHandler'] + const isMethod: typeof import('../../node_modules/h3')['isMethod'] + const isPreflightRequest: typeof import('../../node_modules/h3')['isPreflightRequest'] + const isStream: typeof import('../../node_modules/h3')['isStream'] + const isWebResponse: typeof import('../../node_modules/h3')['isWebResponse'] + const lazyEventHandler: typeof import('../../node_modules/h3')['lazyEventHandler'] + const nitroPlugin: typeof import('../../node_modules/nitropack/dist/runtime/internal/plugin')['nitroPlugin'] + const parseCookies: typeof import('../../node_modules/h3')['parseCookies'] + const promisifyNodeListener: typeof import('../../node_modules/h3')['promisifyNodeListener'] + const proxyRequest: typeof import('../../node_modules/h3')['proxyRequest'] + const readBody: typeof import('../../node_modules/h3')['readBody'] + const readFormData: typeof import('../../node_modules/h3')['readFormData'] + const readMultipartFormData: typeof import('../../node_modules/h3')['readMultipartFormData'] + const readRawBody: typeof import('../../node_modules/h3')['readRawBody'] + const readValidatedBody: typeof import('../../node_modules/h3')['readValidatedBody'] + const removeResponseHeader: typeof import('../../node_modules/h3')['removeResponseHeader'] + const runTask: typeof import('../../node_modules/nitropack/dist/runtime/internal/task')['runTask'] + const sanitizeStatusCode: typeof import('../../node_modules/h3')['sanitizeStatusCode'] + const sanitizeStatusMessage: typeof import('../../node_modules/h3')['sanitizeStatusMessage'] + const sealSession: typeof import('../../node_modules/h3')['sealSession'] + const send: typeof import('../../node_modules/h3')['send'] + const sendError: typeof import('../../node_modules/h3')['sendError'] + const sendIterable: typeof import('../../node_modules/h3')['sendIterable'] + const sendNoContent: typeof import('../../node_modules/h3')['sendNoContent'] + const sendProxy: typeof import('../../node_modules/h3')['sendProxy'] + const sendRedirect: typeof import('../../node_modules/h3')['sendRedirect'] + const sendStream: typeof import('../../node_modules/h3')['sendStream'] + const sendWebResponse: typeof import('../../node_modules/h3')['sendWebResponse'] + const serveStatic: typeof import('../../node_modules/h3')['serveStatic'] + const setCookie: typeof import('../../node_modules/h3')['setCookie'] + const setHeader: typeof import('../../node_modules/h3')['setHeader'] + const setHeaders: typeof import('../../node_modules/h3')['setHeaders'] + const setResponseHeader: typeof import('../../node_modules/h3')['setResponseHeader'] + const setResponseHeaders: typeof import('../../node_modules/h3')['setResponseHeaders'] + const setResponseStatus: typeof import('../../node_modules/h3')['setResponseStatus'] + const splitCookiesString: typeof import('../../node_modules/h3')['splitCookiesString'] + const toEventHandler: typeof import('../../node_modules/h3')['toEventHandler'] + const toNodeListener: typeof import('../../node_modules/h3')['toNodeListener'] + const toPlainHandler: typeof import('../../node_modules/h3')['toPlainHandler'] + const toWebHandler: typeof import('../../node_modules/h3')['toWebHandler'] + const toWebRequest: typeof import('../../node_modules/h3')['toWebRequest'] + const unsealSession: typeof import('../../node_modules/h3')['unsealSession'] + const updateSession: typeof import('../../node_modules/h3')['updateSession'] + const useAppConfig: typeof import('../../node_modules/nitropack/dist/runtime/internal/config')['useAppConfig'] + const useBase: typeof import('../../node_modules/h3')['useBase'] + const useEvent: typeof import('../../node_modules/nitropack/dist/runtime/internal/context')['useEvent'] + const useNitroApp: typeof import('../../node_modules/nitropack/dist/runtime/internal/app')['useNitroApp'] + const useRuntimeConfig: typeof import('../../node_modules/nitropack/dist/runtime/internal/config')['useRuntimeConfig'] + const useSession: typeof import('../../node_modules/h3')['useSession'] + const useStorage: typeof import('../../node_modules/nitropack/dist/runtime/internal/storage')['useStorage'] + const writeEarlyHints: typeof import('../../node_modules/h3')['writeEarlyHints'] +} +export { useNitroApp } from 'nitropack/runtime/internal/app'; +export { useRuntimeConfig, useAppConfig } from 'nitropack/runtime/internal/config'; +export { defineNitroPlugin, nitroPlugin } from 'nitropack/runtime/internal/plugin'; +export { defineCachedFunction, defineCachedEventHandler, cachedFunction, cachedEventHandler } from 'nitropack/runtime/internal/cache'; +export { useStorage } from 'nitropack/runtime/internal/storage'; +export { defineRenderHandler } from 'nitropack/runtime/internal/renderer'; +export { defineRouteMeta } from 'nitropack/runtime/internal/meta'; +export { getRouteRules } from 'nitropack/runtime/internal/route-rules'; +export { useEvent } from 'nitropack/runtime/internal/context'; +export { defineTask, runTask } from 'nitropack/runtime/internal/task'; +export { defineNitroErrorHandler } from 'nitropack/runtime/internal/error/utils'; +export { appendCorsHeaders, appendCorsPreflightHeaders, appendHeader, appendHeaders, appendResponseHeader, appendResponseHeaders, assertMethod, callNodeListener, clearResponseHeaders, clearSession, createApp, createAppEventHandler, createError, createEvent, createEventStream, createRouter, defaultContentType, defineEventHandler, defineLazyEventHandler, defineNodeListener, defineNodeMiddleware, defineRequestMiddleware, defineResponseMiddleware, defineWebSocket, defineWebSocketHandler, deleteCookie, dynamicEventHandler, eventHandler, fetchWithEvent, fromNodeMiddleware, fromPlainHandler, fromWebHandler, getCookie, getHeader, getHeaders, getMethod, getProxyRequestHeaders, getQuery, getRequestFingerprint, getRequestHeader, getRequestHeaders, getRequestHost, getRequestIP, getRequestPath, getRequestProtocol, getRequestURL, getRequestWebStream, getResponseHeader, getResponseHeaders, getResponseStatus, getResponseStatusText, getRouterParam, getRouterParams, getSession, getValidatedQuery, getValidatedRouterParams, handleCacheHeaders, handleCors, isCorsOriginAllowed, isError, isEvent, isEventHandler, isMethod, isPreflightRequest, isStream, isWebResponse, lazyEventHandler, parseCookies, promisifyNodeListener, proxyRequest, readBody, readFormData, readMultipartFormData, readRawBody, readValidatedBody, removeResponseHeader, sanitizeStatusCode, sanitizeStatusMessage, sealSession, send, sendError, sendIterable, sendNoContent, sendProxy, sendRedirect, sendStream, sendWebResponse, serveStatic, setCookie, setHeader, setHeaders, setResponseHeader, setResponseHeaders, setResponseStatus, splitCookiesString, toEventHandler, toNodeListener, toPlainHandler, toWebHandler, toWebRequest, unsealSession, updateSession, useBase, useSession, writeEarlyHints } from 'h3'; +export { buildAssetsURL as __buildAssetsURL, publicAssetsURL as __publicAssetsURL } from '/Users/qhk/Library/CloudStorage/GoogleDrive-hangkai2@illinois.edu/My Drive/Academics/Graduate3/588/GEMstack/GEMstack/onboard/visualization/sr_viz/threeD/node_modules/nuxt/dist/core/runtime/nitro/utils/paths'; +export { defineAppConfig } from '/Users/qhk/Library/CloudStorage/GoogleDrive-hangkai2@illinois.edu/My Drive/Academics/Graduate3/588/GEMstack/GEMstack/onboard/visualization/sr_viz/threeD/node_modules/nuxt/dist/core/runtime/nitro/utils/config'; \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro-middleware.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro-middleware.d.ts new file mode 100644 index 000000000..3b02e2b95 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro-middleware.d.ts @@ -0,0 +1,6 @@ +export type MiddlewareKey = never +declare module 'nitropack' { + interface NitroRouteConfig { + appMiddleware?: MiddlewareKey | MiddlewareKey[] | Record + } +} \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro-nuxt.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro-nuxt.d.ts new file mode 100644 index 000000000..000340901 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro-nuxt.d.ts @@ -0,0 +1,34 @@ + +/// +/// + +import type { RuntimeConfig } from 'nuxt/schema' +import type { H3Event } from 'h3' +import type { LogObject } from 'consola' +import type { NuxtIslandContext, NuxtIslandResponse, NuxtRenderHTMLContext } from 'nuxt/app' + +declare module 'nitropack' { + interface NitroRuntimeConfigApp { + buildAssetsDir: string + cdnURL: string + } + interface NitroRuntimeConfig extends RuntimeConfig {} + interface NitroRouteConfig { + ssr?: boolean + noScripts?: boolean + /** @deprecated Use `noScripts` instead */ + experimentalNoScripts?: boolean + } + interface NitroRouteRules { + ssr?: boolean + noScripts?: boolean + /** @deprecated Use `noScripts` instead */ + experimentalNoScripts?: boolean + appMiddleware?: Record + } + interface NitroRuntimeHooks { + 'dev:ssr-logs': (ctx: { logs: LogObject[], path: string }) => void | Promise + 'render:html': (htmlContext: NuxtRenderHTMLContext, context: { event: H3Event }) => void | Promise + 'render:island': (islandResponse: NuxtIslandResponse, context: { event: H3Event, islandContext: NuxtIslandContext }) => void | Promise + } +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro-routes.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro-routes.d.ts new file mode 100644 index 000000000..e6ba37e3a --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro-routes.d.ts @@ -0,0 +1,11 @@ +// Generated by nitro +import type { Serialize, Simplify } from "nitropack/types"; +declare module "nitropack/types" { + type Awaited = T extends PromiseLike ? Awaited : T + interface InternalApi { + '/__nuxt_error': { + 'default': Simplify>>> + } + } +} +export {} \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro.d.ts new file mode 100644 index 000000000..bf09bd4d3 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/nitro.d.ts @@ -0,0 +1,3 @@ +/// +/// +/// \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/plugins.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/plugins.d.ts new file mode 100644 index 000000000..5e10cfd6a --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/plugins.d.ts @@ -0,0 +1,31 @@ +// Generated by Nuxt' +import type { Plugin } from '#app' + +type Decorate> = { [K in keyof T as K extends string ? `$${K}` : never]: T[K] } + +type InjectionType = A extends {default: Plugin} ? Decorate : unknown + +type NuxtAppInjections = + InjectionType & + InjectionType & + InjectionType & + InjectionType & + InjectionType & + InjectionType & + InjectionType & + InjectionType & + InjectionType + +declare module '#app' { + interface NuxtApp extends NuxtAppInjections { } + + interface NuxtAppLiterals { + pluginName: 'nuxt:revive-payload:client' | 'nuxt:head' | 'nuxt:router' | 'nuxt:payload' | 'nuxt:revive-payload:server' | 'nuxt:chunk-reload' | 'nuxt:global-components' | 'nuxt:prefetch' + } +} + +declare module 'vue' { + interface ComponentCustomProperties extends NuxtAppInjections { } +} + +export { } diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/schema.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/schema.d.ts new file mode 100644 index 000000000..f97dda2a5 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/schema.d.ts @@ -0,0 +1,92 @@ +import { NuxtModule, RuntimeConfig } from '@nuxt/schema' +declare module '@nuxt/schema' { + interface NuxtOptions { + /** + * Configuration for `@unocss/nuxt` + */ + ["unocss"]: typeof import("@unocss/nuxt").default extends NuxtModule ? O : Record + /** + * Configuration for `@nuxt/devtools` + */ + ["devtools"]: typeof import("@nuxt/devtools").default extends NuxtModule ? O : Record + /** + * Configuration for `@nuxt/telemetry` + */ + ["telemetry"]: typeof import("@nuxt/telemetry").default extends NuxtModule ? O : Record + } + interface NuxtConfig { + /** + * Configuration for `@unocss/nuxt` + */ + ["unocss"]?: typeof import("@unocss/nuxt").default extends NuxtModule ? Partial : Record + /** + * Configuration for `@nuxt/devtools` + */ + ["devtools"]?: typeof import("@nuxt/devtools").default extends NuxtModule ? Partial : Record + /** + * Configuration for `@nuxt/telemetry` + */ + ["telemetry"]?: typeof import("@nuxt/telemetry").default extends NuxtModule ? Partial : Record + modules?: (undefined | null | false | NuxtModule | string | [NuxtModule | string, Record] | ["@unocss/nuxt", Exclude] | ["@nuxt/devtools", Exclude] | ["@nuxt/telemetry", Exclude])[], + } +} +declare module 'nuxt/schema' { + interface NuxtOptions { + /** + * Configuration for `@unocss/nuxt` + * @see https://www.npmjs.com/package/@unocss/nuxt + */ + ["unocss"]: typeof import("@unocss/nuxt").default extends NuxtModule ? O : Record + /** + * Configuration for `@nuxt/devtools` + * @see https://www.npmjs.com/package/@nuxt/devtools + */ + ["devtools"]: typeof import("@nuxt/devtools").default extends NuxtModule ? O : Record + /** + * Configuration for `@nuxt/telemetry` + * @see https://www.npmjs.com/package/@nuxt/telemetry + */ + ["telemetry"]: typeof import("@nuxt/telemetry").default extends NuxtModule ? O : Record + } + interface NuxtConfig { + /** + * Configuration for `@unocss/nuxt` + * @see https://www.npmjs.com/package/@unocss/nuxt + */ + ["unocss"]?: typeof import("@unocss/nuxt").default extends NuxtModule ? Partial : Record + /** + * Configuration for `@nuxt/devtools` + * @see https://www.npmjs.com/package/@nuxt/devtools + */ + ["devtools"]?: typeof import("@nuxt/devtools").default extends NuxtModule ? Partial : Record + /** + * Configuration for `@nuxt/telemetry` + * @see https://www.npmjs.com/package/@nuxt/telemetry + */ + ["telemetry"]?: typeof import("@nuxt/telemetry").default extends NuxtModule ? Partial : Record + modules?: (undefined | null | false | NuxtModule | string | [NuxtModule | string, Record] | ["@unocss/nuxt", Exclude] | ["@nuxt/devtools", Exclude] | ["@nuxt/telemetry", Exclude])[], + } + interface RuntimeConfig { + app: { + buildId: string, + + baseURL: string, + + buildAssetsDir: string, + + cdnURL: string, + }, + + nitro: { + envPrefix: string, + }, + } + interface PublicRuntimeConfig { + + } +} +declare module 'vue' { + interface ComponentCustomProperties { + $config: RuntimeConfig + } + } \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/vue-shim.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/.nuxt/types/vue-shim.d.ts new file mode 100644 index 000000000..e69de29bb diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/README.md b/GEMstack/onboard/visualization/sr_viz/threeD/README.md new file mode 100644 index 000000000..e215bc4cc --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/eslint.config.mjs b/GEMstack/onboard/visualization/sr_viz/threeD/eslint.config.mjs new file mode 100644 index 000000000..c85fb67c4 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/eslint.config.mjs @@ -0,0 +1,16 @@ +import { dirname } from "path"; +import { fileURLToPath } from "url"; +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const compat = new FlatCompat({ + baseDirectory: __dirname, +}); + +const eslintConfig = [ + ...compat.extends("next/core-web-vitals", "next/typescript"), +]; + +export default eslintConfig; diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/next-env.d.ts b/GEMstack/onboard/visualization/sr_viz/threeD/next-env.d.ts new file mode 100644 index 000000000..1b3be0840 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/next.config.ts b/GEMstack/onboard/visualization/sr_viz/threeD/next.config.ts new file mode 100644 index 000000000..5ca340c47 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/next.config.ts @@ -0,0 +1,13 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + /* config options here */ + eslint: { + ignoreDuringBuilds: true, + }, + typescript: { + ignoreBuildErrors: true, + }, +}; + +export default nextConfig; diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/package-lock.json b/GEMstack/onboard/visualization/sr_viz/threeD/package-lock.json new file mode 100644 index 000000000..2ae9e1513 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/package-lock.json @@ -0,0 +1,6865 @@ +{ + "name": "cs588_vis", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "cs588_vis", + "version": "0.1.0", + "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.0", + "@foxglove/rosbag": "^0.4.1", + "@mui/icons-material": "^7.0.2", + "@mui/material": "^7.0.2", + "@react-three/drei": "^10.0.6", + "@react-three/fiber": "^9.1.2", + "cs588_vis": "file:", + "next": "15.3.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-icons": "^5.5.0", + "react-resizable-panels": "^3.0.1", + "three": "^0.175.0", + "three-stdlib": "^2.36.0", + "urdf-loader": "^0.12.4" + }, + "devDependencies": { + "@eslint/eslintrc": "^3", + "@tailwindcss/postcss": "^4", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "15.3.0", + "tailwindcss": "^4", + "typescript": "^5" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", + "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", + "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", + "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.0.tgz", + "integrity": "sha512-H+N/FqT07NmLmt6OFFtDfwe8PNygprzBikrEMyQfgqSmT0vzE515Pz7R8izwB9q/zsH/MA64AKoul3sA6/CzVg==", + "dev": true, + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.0.tgz", + "integrity": "sha512-64WYIf4UYcdLnbKn/umDlNjQDSS8AgZrI/R9+x5ilkUVFxXcA1Ebl+gQLc/6mERA4407Xof0R7wEyEuj091CVw==", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.1.tgz", + "integrity": "sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==", + "dev": true, + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emotion/babel-plugin": { + "version": "11.13.5", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", + "integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/runtime": "^7.18.3", + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/serialize": "^1.3.3", + "babel-plugin-macros": "^3.1.0", + "convert-source-map": "^1.5.0", + "escape-string-regexp": "^4.0.0", + "find-root": "^1.1.0", + "source-map": "^0.5.7", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/cache": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0", + "@emotion/sheet": "^1.4.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "stylis": "4.2.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/is-prop-valid": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz", + "integrity": "sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==", + "license": "MIT", + "dependencies": { + "@emotion/memoize": "^0.9.0" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz", + "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==", + "license": "MIT" + }, + "node_modules/@emotion/react": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz", + "integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/cache": "^11.14.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2", + "@emotion/weak-memoize": "^0.4.0", + "hoist-non-react-statics": "^3.3.1" + }, + "peerDependencies": { + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/serialize": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "license": "MIT", + "dependencies": { + "@emotion/hash": "^0.9.2", + "@emotion/memoize": "^0.9.0", + "@emotion/unitless": "^0.10.0", + "@emotion/utils": "^1.4.2", + "csstype": "^3.0.2" + } + }, + "node_modules/@emotion/sheet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz", + "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==", + "license": "MIT" + }, + "node_modules/@emotion/styled": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.0.tgz", + "integrity": "sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@emotion/babel-plugin": "^11.13.5", + "@emotion/is-prop-valid": "^1.3.0", + "@emotion/serialize": "^1.3.3", + "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", + "@emotion/utils": "^1.4.2" + }, + "peerDependencies": { + "@emotion/react": "^11.0.0-rc.0", + "react": ">=16.8.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@emotion/unitless": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz", + "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==", + "license": "MIT" + }, + "node_modules/@emotion/use-insertion-effect-with-fallbacks": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz", + "integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@emotion/utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" + }, + "node_modules/@emotion/weak-memoize": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz", + "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==", + "license": "MIT" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz", + "integrity": "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.0.tgz", + "integrity": "sha512-fxlS1kkIjx8+vy2SjuCB94q3htSNrufYTXubwiBFeaQHbH6Ipi43gFJq2zCMt6PHhImH3Xmr0NksKDvchWlpQQ==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.1.tgz", + "integrity": "sha512-RI17tsD2frtDu/3dmI7QRrD4bedNKPM08ziRYaC5AhkGrzIAJelm9kJU1TznK+apx6V+cqRz8tfpEeG3oIyjxw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz", + "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.24.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz", + "integrity": "sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz", + "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==", + "dev": true, + "dependencies": { + "@eslint/core": "^0.13.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz", + "integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@foxglove/message-definition": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@foxglove/message-definition/-/message-definition-0.2.0.tgz", + "integrity": "sha512-IQHIGCvBZR8GIua9nEpS+hsMF3gm1bfbrrnjG0rgtcFBWiNuKbzx4vIP8OIwDC+8wtwcFdfJhf4Vp5TPFiUUcQ==" + }, + "node_modules/@foxglove/rosbag": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@foxglove/rosbag/-/rosbag-0.4.1.tgz", + "integrity": "sha512-Tbt1SUz+xnKOX+bvhbHiVjNMpTM28hl3zAku8fJ7+8qTZjJPrW95p3W4Aiz6YVWO+NMhCns5wQqOv8rvBpCotg==", + "dependencies": { + "@foxglove/rosmsg": "^4.0.0", + "@foxglove/rosmsg-serialization": "^2.0.0", + "@foxglove/rostime": "^1.1.2", + "heap": "^0.2.7" + } + }, + "node_modules/@foxglove/rosmsg": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@foxglove/rosmsg/-/rosmsg-4.2.2.tgz", + "integrity": "sha512-bAY7+b/3AJnR6pIkUWbDdFCRGwCc/WaI9V/51nkj0iNP16ZMJ6s5xPDwKYMpaNIlFSyJG1QE69AmRPRYzP6oEQ==", + "dependencies": { + "@foxglove/message-definition": "^0.2.0", + "md5-typescript": "^1.0.5" + }, + "bin": { + "gendeps2": "bin/gendeps2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@foxglove/rosmsg-serialization": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@foxglove/rosmsg-serialization/-/rosmsg-serialization-2.0.3.tgz", + "integrity": "sha512-IN/VREnP+3eGNBQJUXQxKfX1ZG/rc0/kkRdZMhqkuFhCywGHwOGNo8KNVEuEO6EfYygREArPoRB1V9L0MUjZ2Q==", + "dependencies": { + "@foxglove/message-definition": "^0.2.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@foxglove/rostime": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@foxglove/rostime/-/rostime-1.1.2.tgz", + "integrity": "sha512-vWuTJCuGv0xvgwOlrZ1y2MevmNMVxWcUU/HwlmYXi/jUq/kRaACStU18uyuZ3LzdNKaffkti0rTcXWESaQjwQw==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", + "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.1.tgz", + "integrity": "sha512-pn44xgBtgpEbZsu+lWf2KNb6OAf70X68k+yk69Ic2Xz11zHR/w24/U49XT7AeRwJ0Px+mhALhU5LPci1Aymk7A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.1.0" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.1.tgz", + "integrity": "sha512-VfuYgG2r8BpYiOUN+BfYeFo69nP/MIwAtSJ7/Zpxc5QF3KS22z8Pvg3FkrSFJBPNQ7mmcUcYQFBmEQp7eu1F8Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.1.0" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.1.0.tgz", + "integrity": "sha512-HZ/JUmPwrJSoM4DIQPv/BfNh9yrOA8tlBbqbLz4JZ5uew2+o22Ik+tHQJcih7QJuSa0zo5coHTfD5J8inqj9DA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.1.0.tgz", + "integrity": "sha512-Xzc2ToEmHN+hfvsl9wja0RlnXEgpKNmftriQp6XzY/RaSfwD9th+MSh0WQKzUreLKKINb3afirxW7A0fz2YWuQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.1.0.tgz", + "integrity": "sha512-s8BAd0lwUIvYCJyRdFqvsj+BJIpDBSxs6ivrOPm/R7piTs5UIwY5OjXrP2bqXC9/moGsyRa37eYWYCOGVXxVrA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.1.0.tgz", + "integrity": "sha512-IVfGJa7gjChDET1dK9SekxFFdflarnUB8PwW8aGwEoF3oAsSDuNUTYS+SKDOyOJxQyDC1aPFMuRYLoDInyV9Ew==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.1.0.tgz", + "integrity": "sha512-tiXxFZFbhnkWE2LA8oQj7KYR+bWBkiV2nilRldT7bqoEZ4HiDOcePr9wVDAZPi/Id5fT1oY9iGnDq20cwUz8lQ==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.1.0.tgz", + "integrity": "sha512-xukSwvhguw7COyzvmjydRb3x/09+21HykyapcZchiCUkTThEQEOMtBj9UhkaBRLuBrgLFzQ2wbxdeCCJW/jgJA==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.1.0.tgz", + "integrity": "sha512-yRj2+reB8iMg9W5sULM3S74jVS7zqSzHG3Ol/twnAAkAhnGQnpjj6e4ayUz7V+FpKypwgs82xbRdYtchTTUB+Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.1.0.tgz", + "integrity": "sha512-jYZdG+whg0MDK+q2COKbYidaqW/WTz0cc1E+tMAusiDygrM4ypmSCjOJPmFTvHHJ8j/6cAGyeDWZOsK06tP33w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.1.0.tgz", + "integrity": "sha512-wK7SBdwrAiycjXdkPnGCPLjYb9lD4l6Ze2gSdAGVZrEL05AOUJESWU2lhlC+Ffn5/G+VKuSm6zzbQSzFX/P65A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.1.tgz", + "integrity": "sha512-anKiszvACti2sGy9CirTlNyk7BjjZPiML1jt2ZkTdcvpLU1YH6CXwRAZCA2UmRXnhiIftXQ7+Oh62Ji25W72jA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.1.0" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.1.tgz", + "integrity": "sha512-kX2c+vbvaXC6vly1RDf/IWNXxrlxLNpBVWkdpRq5Ka7OOKj6nr66etKy2IENf6FtOgklkg9ZdGpEu9kwdlcwOQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.1.0" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.1.tgz", + "integrity": "sha512-7s0KX2tI9mZI2buRipKIw2X1ufdTeaRgwmRabt5bi9chYfhur+/C1OXg3TKg/eag1W+6CCWLVmSauV1owmRPxA==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.1.0" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.1.tgz", + "integrity": "sha512-wExv7SH9nmoBW3Wr2gvQopX1k8q2g5V5Iag8Zk6AVENsjwd+3adjwxtp3Dcu2QhOXr8W9NusBU6XcQUohBZ5MA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.1.0" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.1.tgz", + "integrity": "sha512-DfvyxzHxw4WGdPiTF0SOHnm11Xv4aQexvqhRDAoD00MzHekAj9a/jADXeXYCDFH/DzYruwHbXU7uz+H+nWmSOQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.1.0" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.1.tgz", + "integrity": "sha512-pax/kTR407vNb9qaSIiWVnQplPcGU8LRIJpDT5o8PdAx5aAA7AS3X9PS8Isw1/WfqgQorPotjrZL3Pqh6C5EBg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.1.0" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.1.tgz", + "integrity": "sha512-YDybQnYrLQfEpzGOQe7OKcyLUCML4YOXl428gOOzBgN6Gw0rv8dpsJ7PqTHxBnXnwXr8S1mYFSLSa727tpz0xg==", + "cpu": [ + "wasm32" + ], + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.4.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.1.tgz", + "integrity": "sha512-WKf/NAZITnonBf3U1LfdjoMgNO5JYRSlhovhRhMxXVdvWYveM4kM3L8m35onYIdh75cOMCo1BexgVQcCDzyoWw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.1.tgz", + "integrity": "sha512-hw1iIAHpNE8q3uMIRCgGOeDoz9KtFNarFLQclLxr/LK1VBkj8nby18RjFvr6aP7USRYAjTZW6yisnBWMX571Tw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@mediapipe/tasks-vision": { + "version": "0.10.17", + "resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.17.tgz", + "integrity": "sha512-CZWV/q6TTe8ta61cZXjfnnHsfWIdFhms03M9T7Cnd5y2mdpylJM0rF1qRq+wsQVRMLz1OYPVEBU9ph2Bx8cxrg==" + }, + "node_modules/@monogrid/gainmap-js": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@monogrid/gainmap-js/-/gainmap-js-3.1.0.tgz", + "integrity": "sha512-Obb0/gEd/HReTlg8ttaYk+0m62gQJmCblMOjHSMHRrBP2zdfKMHLCRbh/6ex9fSUJMKdjjIEiohwkbGD3wj2Nw==", + "dependencies": { + "promise-worker-transferable": "^1.0.4" + }, + "peerDependencies": { + "three": ">= 0.159.0" + } + }, + "node_modules/@mui/core-downloads-tracker": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.0.2.tgz", + "integrity": "sha512-TfeFU9TgN1N06hyb/pV/63FfO34nijZRMqgHk0TJ3gkl4Fbd+wZ73+ZtOd7jag6hMmzO9HSrBc6Vdn591nhkAg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + } + }, + "node_modules/@mui/icons-material": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@mui/icons-material/-/icons-material-7.0.2.tgz", + "integrity": "sha512-Bo57PFLOqXOqPNrXjd8AhzH5s6TCsNUQbvnQ0VKZ8D+lIlteqKnrk/O1luMJUc/BXONK7BfIdTdc7qOnXYbMdw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@mui/material": "^7.0.2", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-7.0.2.tgz", + "integrity": "sha512-rjJlJ13+3LdLfobRplkXbjIFEIkn6LgpetgU/Cs3Xd8qINCCQK9qXQIjjQ6P0FXFTPFzEVMj0VgBR1mN+FhOcA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.0", + "@mui/core-downloads-tracker": "^7.0.2", + "@mui/system": "^7.0.2", + "@mui/types": "^7.4.1", + "@mui/utils": "^7.0.2", + "@popperjs/core": "^2.11.8", + "@types/react-transition-group": "^4.4.12", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1", + "react-is": "^19.1.0", + "react-transition-group": "^4.4.5" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@mui/material-pigment-css": "^7.0.2", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@mui/material-pigment-css": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/material/node_modules/react-is": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz", + "integrity": "sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==", + "license": "MIT" + }, + "node_modules/@mui/private-theming": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.0.2.tgz", + "integrity": "sha512-6lt8heDC9wN8YaRqEdhqnm0cFCv08AMf4IlttFvOVn7ZdKd81PNpD/rEtPGLLwQAFyyKSxBG4/2XCgpbcdNKiA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.0", + "@mui/utils": "^7.0.2", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/styled-engine": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.0.2.tgz", + "integrity": "sha512-11Bt4YdHGlh7sB8P75S9mRCUxTlgv7HGbr0UKz6m6Z9KLeiw1Bm9y/t3iqLLVMvSHYB6zL8X8X+LmfTE++gyBw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.0", + "@emotion/cache": "^11.13.5", + "@emotion/serialize": "^1.3.3", + "@emotion/sheet": "^1.4.0", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.4.1", + "@emotion/styled": "^11.3.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + } + } + }, + "node_modules/@mui/system": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-7.0.2.tgz", + "integrity": "sha512-yFUraAWYWuKIISPPEVPSQ1NLeqmTT4qiQ+ktmyS8LO/KwHxB+NNVOacEZaIofh5x1NxY8rzphvU5X2heRZ/RDA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.0", + "@mui/private-theming": "^7.0.2", + "@mui/styled-engine": "^7.0.2", + "@mui/types": "^7.4.1", + "@mui/utils": "^7.0.2", + "clsx": "^2.1.1", + "csstype": "^3.1.3", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@emotion/react": "^11.5.0", + "@emotion/styled": "^11.3.0", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/react": { + "optional": true + }, + "@emotion/styled": { + "optional": true + }, + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/types": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.1.tgz", + "integrity": "sha512-gUL8IIAI52CRXP/MixT1tJKt3SI6tVv4U/9soFsTtAsHzaJQptZ42ffdHZV3niX1ei0aUgMvOxBBN0KYqdG39g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.0" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.0.2.tgz", + "integrity": "sha512-72gcuQjPzhj/MLmPHLCgZjy2VjOH4KniR/4qRtXTTXIEwbkgcN+Y5W/rC90rWtMmZbjt9svZev/z+QHUI4j74w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.0", + "@mui/types": "^7.4.1", + "@types/prop-types": "^15.7.14", + "clsx": "^2.1.1", + "prop-types": "^15.8.1", + "react-is": "^19.1.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mui-org" + }, + "peerDependencies": { + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@mui/utils/node_modules/react-is": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.0.tgz", + "integrity": "sha512-Oe56aUPnkHyyDxxkvqtd7KkdQP5uIUfHxd5XTb3wE9d/kRnZLmKbDB0GWk919tdQ+mxxPtG6EAs6RMT6i1qtHg==", + "license": "MIT" + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.8.tgz", + "integrity": "sha512-OBlgKdX7gin7OIq4fadsjpg+cp2ZphvAIKucHsNfTdJiqdOmOEwQd/bHi0VwNrcw5xpBJyUw6cK/QilCqy1BSg==", + "dev": true, + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.0", + "@emnapi/runtime": "^1.4.0", + "@tybys/wasm-util": "^0.9.0" + } + }, + "node_modules/@next/env": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.3.0.tgz", + "integrity": "sha512-6mDmHX24nWlHOlbwUiAOmMyY7KELimmi+ed8qWcJYjqXeC+G6JzPZ3QosOAfjNwgMIzwhXBiRiCgdh8axTTdTA==" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.3.0.tgz", + "integrity": "sha512-511UUcpWw5GWTyKfzW58U2F/bYJyjLE9e3SlnGK/zSXq7RqLlqFO8B9bitJjumLpj317fycC96KZ2RZsjGNfBw==", + "dev": true, + "dependencies": { + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.3.0.tgz", + "integrity": "sha512-PDQcByT0ZfF2q7QR9d+PNj3wlNN4K6Q8JoHMwFyk252gWo4gKt7BF8Y2+KBgDjTFBETXZ/TkBEUY7NIIY7A/Kw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.3.0.tgz", + "integrity": "sha512-m+eO21yg80En8HJ5c49AOQpFDq+nP51nu88ZOMCorvw3g//8g1JSUsEiPSiFpJo1KCTQ+jm9H0hwXK49H/RmXg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.3.0.tgz", + "integrity": "sha512-H0Kk04ZNzb6Aq/G6e0un4B3HekPnyy6D+eUBYPJv9Abx8KDYgNMWzKt4Qhj57HXV3sTTjsfc1Trc1SxuhQB+Tg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.3.0.tgz", + "integrity": "sha512-k8GVkdMrh/+J9uIv/GpnHakzgDQhrprJ/FbGQvwWmstaeFG06nnAoZCJV+wO/bb603iKV1BXt4gHG+s2buJqZA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.3.0.tgz", + "integrity": "sha512-ZMQ9yzDEts/vkpFLRAqfYO1wSpIJGlQNK9gZ09PgyjBJUmg8F/bb8fw2EXKgEaHbCc4gmqMpDfh+T07qUphp9A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.3.0.tgz", + "integrity": "sha512-RFwq5VKYTw9TMr4T3e5HRP6T4RiAzfDJ6XsxH8j/ZeYq2aLsBqCkFzwMI0FmnSsLaUbOb46Uov0VvN3UciHX5A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.3.0.tgz", + "integrity": "sha512-a7kUbqa/k09xPjfCl0RSVAvEjAkYBYxUzSVAzk2ptXiNEL+4bDBo9wNC43G/osLA/EOGzG4CuNRFnQyIHfkRgQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.3.0.tgz", + "integrity": "sha512-vHUQS4YVGJPmpjn7r5lEZuMhK5UQBNBRSB+iGDvJjaNk649pTIcRluDWNb9siunyLLiu/LDPHfvxBtNamyuLTw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@react-three/drei": { + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@react-three/drei/-/drei-10.0.6.tgz", + "integrity": "sha512-QtiAv/a1BaP+ZYfp8BphV8BMSO0O1BNhIPye3Zqm5iDqgX6JeiknPR6f2UmzUdBfPLwjZEaqjfULgJFvTUWgkg==", + "dependencies": { + "@babel/runtime": "^7.26.0", + "@mediapipe/tasks-vision": "0.10.17", + "@monogrid/gainmap-js": "^3.0.6", + "@use-gesture/react": "^10.3.1", + "camera-controls": "^2.9.0", + "cross-env": "^7.0.3", + "detect-gpu": "^5.0.56", + "glsl-noise": "^0.0.0", + "hls.js": "^1.5.17", + "maath": "^0.10.8", + "meshline": "^3.3.1", + "stats-gl": "^2.2.8", + "stats.js": "^0.17.0", + "suspend-react": "^0.1.3", + "three-mesh-bvh": "^0.8.3", + "three-stdlib": "^2.35.6", + "troika-three-text": "^0.52.0", + "tunnel-rat": "^0.1.2", + "use-sync-external-store": "^1.4.0", + "utility-types": "^3.11.0", + "zustand": "^5.0.1" + }, + "peerDependencies": { + "@react-three/fiber": "^9.0.0", + "react": "^19", + "react-dom": "^19", + "three": ">=0.159" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/@react-three/fiber": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-9.1.2.tgz", + "integrity": "sha512-k8FR9yVHV9kIF3iuOD0ds5hVymXYXfgdKklqziBVod9ZEJ8uk05Zjw29J/omU3IKeUfLNAIHfxneN3TUYM4I2w==", + "dependencies": { + "@babel/runtime": "^7.17.8", + "@types/react-reconciler": "^0.28.9", + "@types/webxr": "*", + "base64-js": "^1.5.1", + "buffer": "^6.0.3", + "its-fine": "^2.0.0", + "react-reconciler": "^0.31.0", + "react-use-measure": "^2.1.7", + "scheduler": "^0.25.0", + "suspend-react": "^0.1.3", + "use-sync-external-store": "^1.4.0", + "zustand": "^5.0.3" + }, + "peerDependencies": { + "expo": ">=43.0", + "expo-asset": ">=8.4", + "expo-file-system": ">=11.0", + "expo-gl": ">=11.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-native": ">=0.78", + "three": ">=0.156" + }, + "peerDependenciesMeta": { + "expo": { + "optional": true + }, + "expo-asset": { + "optional": true + }, + "expo-file-system": { + "optional": true + }, + "expo-gl": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/@react-three/fiber/node_modules/scheduler": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", + "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==" + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.11.0.tgz", + "integrity": "sha512-zxnHvoMQVqewTJr/W4pKjF0bMGiKJv1WX7bSrkl46Hg0QjESbzBROWK0Wg4RphzSOS5Jiy7eFimmM3UgMrMZbQ==", + "dev": true + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.3.tgz", + "integrity": "sha512-H/6r6IPFJkCfBJZ2dKZiPJ7Ueb2wbL592+9bQEl2r73qbX6yGnmQVIfiUvDRB2YI0a3PWDrzUwkvQx1XW1bNkA==", + "dev": true, + "dependencies": { + "enhanced-resolve": "^5.18.1", + "jiti": "^2.4.2", + "lightningcss": "1.29.2", + "tailwindcss": "4.1.3" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.3.tgz", + "integrity": "sha512-t16lpHCU7LBxDe/8dCj9ntyNpXaSTAgxWm1u2XQP5NiIu4KGSyrDJJRlK9hJ4U9yJxx0UKCVI67MJWFNll5mOQ==", + "dev": true, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.3", + "@tailwindcss/oxide-darwin-arm64": "4.1.3", + "@tailwindcss/oxide-darwin-x64": "4.1.3", + "@tailwindcss/oxide-freebsd-x64": "4.1.3", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.3", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.3", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.3", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.3", + "@tailwindcss/oxide-linux-x64-musl": "4.1.3", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.3", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.3" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.3.tgz", + "integrity": "sha512-cxklKjtNLwFl3mDYw4XpEfBY+G8ssSg9ADL4Wm6//5woi3XGqlxFsnV5Zb6v07dxw1NvEX2uoqsxO/zWQsgR+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.3.tgz", + "integrity": "sha512-mqkf2tLR5VCrjBvuRDwzKNShRu99gCAVMkVsaEOFvv6cCjlEKXRecPu9DEnxp6STk5z+Vlbh1M5zY3nQCXMXhw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.3.tgz", + "integrity": "sha512-7sGraGaWzXvCLyxrc7d+CCpUN3fYnkkcso3rCzwUmo/LteAl2ZGCDlGvDD8Y/1D3ngxT8KgDj1DSwOnNewKhmg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.3.tgz", + "integrity": "sha512-E2+PbcbzIReaAYZe997wb9rId246yDkCwAakllAWSGqe6VTg9hHle67hfH6ExjpV2LSK/siRzBUs5wVff3RW9w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.3.tgz", + "integrity": "sha512-GvfbJ8wjSSjbLFFE3UYz4Eh8i4L6GiEYqCtA8j2Zd2oXriPuom/Ah/64pg/szWycQpzRnbDiJozoxFU2oJZyfg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.3.tgz", + "integrity": "sha512-35UkuCWQTeG9BHcBQXndDOrpsnt3Pj9NVIB4CgNiKmpG8GnCNXeMczkUpOoqcOhO6Cc/mM2W7kaQ/MTEENDDXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.3.tgz", + "integrity": "sha512-dm18aQiML5QCj9DQo7wMbt1Z2tl3Giht54uVR87a84X8qRtuXxUqnKQkRDK5B4bCOmcZ580lF9YcoMkbDYTXHQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.3.tgz", + "integrity": "sha512-LMdTmGe/NPtGOaOfV2HuO7w07jI3cflPrVq5CXl+2O93DCewADK0uW1ORNAcfu2YxDUS035eY2W38TxrsqngxA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.3.tgz", + "integrity": "sha512-aalNWwIi54bbFEizwl1/XpmdDrOaCjRFQRgtbv9slWjmNPuJJTIKPHf5/XXDARc9CneW9FkSTqTbyvNecYAEGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.3.tgz", + "integrity": "sha512-PEj7XR4OGTGoboTIAdXicKuWl4EQIjKHKuR+bFy9oYN7CFZo0eu74+70O4XuERX4yjqVZGAkCdglBODlgqcCXg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.3.tgz", + "integrity": "sha512-T8gfxECWDBENotpw3HR9SmNiHC9AOJdxs+woasRZ8Q/J4VHN0OMs7F+4yVNZ9EVN26Wv6mZbK0jv7eHYuLJLwA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.3.tgz", + "integrity": "sha512-6s5nJODm98F++QT49qn8xJKHQRamhYHfMi3X7/ltxiSQ9dyRsaFSfFkfaMsanWzf+TMYQtbk8mt5f6cCVXJwfg==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.1.3", + "@tailwindcss/oxide": "4.1.3", + "postcss": "^8.4.41", + "tailwindcss": "4.1.3" + } + }, + "node_modules/@tweenjs/tween.js": { + "version": "23.1.3", + "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz", + "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "dev": true, + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/draco3d": { + "version": "1.4.10", + "resolved": "https://registry.npmjs.org/@types/draco3d/-/draco3d-1.4.10.tgz", + "integrity": "sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw==" + }, + "node_modules/@types/estree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", + "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.17.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.30.tgz", + "integrity": "sha512-7zf4YyHA+jvBNfVrk2Gtvs6x7E8V+YDW05bNfG2XkWDJfYRXrTiP/DsB2zSYTaHX0bGIujTBQdMVAhb+j7mwpg==", + "dev": true, + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/offscreencanvas": { + "version": "2019.7.3", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz", + "integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A==" + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.0.tgz", + "integrity": "sha512-UaicktuQI+9UKyA4njtDOGBD/67t8YEBt2xdfqu8+gP9hqPUPsiXlNPcpS2gVdjmis5GKPG3fCxbQLVgxsQZ8w==", + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.1.2", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.1.2.tgz", + "integrity": "sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw==", + "dev": true, + "peerDependencies": { + "@types/react": "^19.0.0" + } + }, + "node_modules/@types/react-reconciler": { + "version": "0.28.9", + "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.9.tgz", + "integrity": "sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg==", + "peerDependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-transition-group": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/stats.js": { + "version": "0.17.3", + "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.3.tgz", + "integrity": "sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ==" + }, + "node_modules/@types/three": { + "version": "0.175.0", + "resolved": "https://registry.npmjs.org/@types/three/-/three-0.175.0.tgz", + "integrity": "sha512-ldMSBgtZOZ3g9kJ3kOZSEtZIEITmJOzu8eKVpkhf036GuNkM4mt0NXecrjCn5tMm1OblOF7dZehlaDypBfNokw==", + "dependencies": { + "@tweenjs/tween.js": "~23.1.3", + "@types/stats.js": "*", + "@types/webxr": "*", + "@webgpu/types": "*", + "fflate": "~0.8.2", + "meshoptimizer": "~0.18.1" + } + }, + "node_modules/@types/webxr": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.21.tgz", + "integrity": "sha512-geZIAtLzjGmgY2JUi6VxXdCrTb99A7yP49lxLr2Nm/uIK0PkkxcEi4OGhoGDO4pxCf3JwGz2GiJL2Ej4K2bKaA==" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.29.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.29.1.tgz", + "integrity": "sha512-ba0rr4Wfvg23vERs3eB+P3lfj2E+2g3lhWcCVukUuhtcdUx5lSIFZlGFEBHKr+3zizDa/TvZTptdNHVZWAkSBg==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.29.1", + "@typescript-eslint/type-utils": "8.29.1", + "@typescript-eslint/utils": "8.29.1", + "@typescript-eslint/visitor-keys": "8.29.1", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.29.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.29.1.tgz", + "integrity": "sha512-zczrHVEqEaTwh12gWBIJWj8nx+ayDcCJs06yoNMY0kwjMWDM6+kppljY+BxWI06d2Ja+h4+WdufDcwMnnMEWmg==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.29.1", + "@typescript-eslint/types": "8.29.1", + "@typescript-eslint/typescript-estree": "8.29.1", + "@typescript-eslint/visitor-keys": "8.29.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.29.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.29.1.tgz", + "integrity": "sha512-2nggXGX5F3YrsGN08pw4XpMLO1Rgtnn4AzTegC2MDesv6q3QaTU5yU7IbS1tf1IwCR0Hv/1EFygLn9ms6LIpDA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.29.1", + "@typescript-eslint/visitor-keys": "8.29.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.29.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.29.1.tgz", + "integrity": "sha512-DkDUSDwZVCYN71xA4wzySqqcZsHKic53A4BLqmrWFFpOpNSoxX233lwGu/2135ymTCR04PoKiEEEvN1gFYg4Tw==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "8.29.1", + "@typescript-eslint/utils": "8.29.1", + "debug": "^4.3.4", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.29.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.29.1.tgz", + "integrity": "sha512-VT7T1PuJF1hpYC3AGm2rCgJBjHL3nc+A/bhOp9sGMKfi5v0WufsX/sHCFBfNTx2F+zA6qBc/PD0/kLRLjdt8mQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.29.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.29.1.tgz", + "integrity": "sha512-l1enRoSaUkQxOQnbi0KPUtqeZkSiFlqrx9/3ns2rEDhGKfTa+88RmXqedC1zmVTOWrLc2e6DEJrTA51C9iLH5g==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.29.1", + "@typescript-eslint/visitor-keys": "8.29.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.0.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.29.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.29.1.tgz", + "integrity": "sha512-QAkFEbytSaB8wnmB+DflhUPz6CLbFWE2SnSCrRMEa+KnXIzDYbpsn++1HGvnfAsUY44doDXmvRkO5shlM/3UfA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.29.1", + "@typescript-eslint/types": "8.29.1", + "@typescript-eslint/typescript-estree": "8.29.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.9.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.29.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.29.1.tgz", + "integrity": "sha512-RGLh5CRaUEf02viP5c1Vh1cMGffQscyHe7HPAzGpfmfflFg1wUz2rYxd+OZqwpeypYvZ8UxSxuIpF++fmOzEcg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.29.1", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.4.1.tgz", + "integrity": "sha512-8Tv+Bsd0BjGwfEedIyor4inw8atppRxM5BdUnIt+3mAm/QXUm7Dw74CHnXpfZKXkp07EXJGiA8hStqCINAWhdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.4.1.tgz", + "integrity": "sha512-X8c3PhWziEMKAzZz+YAYWfwawi5AEgzy/hmfizAB4C70gMHLKmInJcp1270yYAOs7z07YVFI220pp50z24Jk3A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.4.1.tgz", + "integrity": "sha512-UUr/nREy1UdtxXQnmLaaTXFGOcGxPwNIzeJdb3KXai3TKtC1UgNOB9s8KOA4TaxOUBR/qVgL5BvBwmUjD5yuVA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.4.1.tgz", + "integrity": "sha512-e3pII53dEeS8inkX6A1ad2UXE0nuoWCqik4kOxaDnls0uJUq0ntdj5d9IYd+bv5TDwf9DSge/xPOvCmRYH+Tsw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.4.1.tgz", + "integrity": "sha512-e/AKKd9gR+HNmVyDEPI/PIz2t0DrA3cyonHNhHVjrkxe8pMCiYiqhtn1+h+yIpHUtUlM6Y1FNIdivFa+r7wrEQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.4.1.tgz", + "integrity": "sha512-vtIu34luF1jRktlHtiwm2mjuE8oJCsFiFr8hT5+tFQdqFKjPhbJXn83LswKsOhy0GxAEevpXDI4xxEwkjuXIPA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.4.1.tgz", + "integrity": "sha512-H3PaOuGyhFXiyJd+09uPhGl4gocmhyi1BRzvsP8Lv5AQO3p3/ZY7WjV4t2NkBksm9tMjf3YbOVHyPWi2eWsNYw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.4.1.tgz", + "integrity": "sha512-4+GmJcaaFntCi1S01YByqp8wLMjV/FyQyHVGm0vedIhL1Vfx7uHkz/sZmKsidRwokBGuxi92GFmSzqT2O8KcNA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.4.1.tgz", + "integrity": "sha512-6RDQVCmtFYTlhy89D5ixTqo9bTQqFhvNN0Ey1wJs5r+01Dq15gPHRXv2jF2bQATtMrOfYwv+R2ZR9ew1N1N3YQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.4.1.tgz", + "integrity": "sha512-XpU9uzIkD86+19NjCXxlVPISMUrVXsXo5htxtuG+uJ59p5JauSRZsIxQxzzfKzkxEjdvANPM/lS1HFoX6A6QeA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.4.1.tgz", + "integrity": "sha512-3CDjG/spbTKCSHl66QP2ekHSD+H34i7utuDIM5gzoNBcZ1gTO0Op09Wx5cikXnhORRf9+HyDWzm37vU1PLSM1A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.4.1.tgz", + "integrity": "sha512-50tYhvbCTnuzMn7vmP8IV2UKF7ITo1oihygEYq9wW2DUb/Y+QMqBHJUSCABRngATjZ4shOK6f2+s0gQX6ElENQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.8" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.4.1.tgz", + "integrity": "sha512-KyJiIne/AqV4IW0wyQO34wSMuJwy3VxVQOfIXIPyQ/Up6y/zi2P/WwXb78gHsLiGRUqCA9LOoCX+6dQZde0g1g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.4.1.tgz", + "integrity": "sha512-y2NUD7pygrBolN2NoXUrwVqBpKPhF8DiSNE5oB5/iFO49r2DpoYqdj5HPb3F42fPBH5qNqj6Zg63+xCEzAD2hw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.4.1.tgz", + "integrity": "sha512-hVXaObGI2lGFmrtT77KSbPQ3I+zk9IU500wobjk0+oX59vg/0VqAzABNtt3YSQYgXTC2a/LYxekLfND/wlt0yQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@use-gesture/core": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.3.1.tgz", + "integrity": "sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw==" + }, + "node_modules/@use-gesture/react": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/@use-gesture/react/-/react-10.3.1.tgz", + "integrity": "sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==", + "dependencies": { + "@use-gesture/core": "10.3.1" + }, + "peerDependencies": { + "react": ">= 16.8.0" + } + }, + "node_modules/@webgpu/types": { + "version": "0.1.60", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.60.tgz", + "integrity": "sha512-8B/tdfRFKdrnejqmvq95ogp8tf52oZ51p3f4QD5m5Paey/qlX4Rhhy5Y8tgFMi7Ms70HzcMMw3EQjH/jdhTwlA==" + }, + "node_modules/acorn": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.10.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.3.tgz", + "integrity": "sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/babel-plugin-macros": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", + "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "cosmiconfig": "^7.0.0", + "resolve": "^1.19.0" + }, + "engines": { + "node": ">=10", + "npm": ">=6" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bidi-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", + "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", + "dependencies": { + "require-from-string": "^2.0.2" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/camera-controls": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/camera-controls/-/camera-controls-2.10.1.tgz", + "integrity": "sha512-KnaKdcvkBJ1Irbrzl8XD6WtZltkRjp869Jx8c0ujs9K+9WD+1D7ryBsCiVqJYUqt6i/HR5FxT7RLASieUD+Q5w==", + "peerDependencies": { + "three": ">=0.126.1" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001713", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001713.tgz", + "integrity": "sha512-wCIWIg+A4Xr7NfhTuHdX+/FKh3+Op3LBbSp2N5Pfx6T/LhdQy3GTyoTg48BReaW/MyMNZAkTadsBtai3ldWK0Q==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "devOptional": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "devOptional": true + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "optional": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cs588_vis": { + "resolved": "", + "link": true + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/detect-gpu": { + "version": "5.0.70", + "resolved": "https://registry.npmjs.org/detect-gpu/-/detect-gpu-5.0.70.tgz", + "integrity": "sha512-bqerEP1Ese6nt3rFkwPnGbsUF9a4q+gMmpTVVOEzoCyeCc+y7/RvJnQZJx1JwhgQI5Ntg0Kgat8Uu7XpBqnz1w==", + "dependencies": { + "webgl-constants": "^1.1.1" + } + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "devOptional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, + "node_modules/draco3d": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.7.tgz", + "integrity": "sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ==" + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/enhanced-resolve": { + "version": "5.18.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz", + "integrity": "sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-ex/node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "license": "MIT" + }, + "node_modules/es-abstract": { + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-regex": "^1.2.1", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.0", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.18" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", + "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.6", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.4", + "safe-array-concat": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.24.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.24.0.tgz", + "integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.20.0", + "@eslint/config-helpers": "^0.2.0", + "@eslint/core": "^0.12.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.24.0", + "@eslint/plugin-kit": "^0.2.7", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.3.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-next": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.3.0.tgz", + "integrity": "sha512-+Z3M1W9MnJjX3W4vI9CHfKlEyhTWOUHvc5dB89FyRnzPsUkJlLWZOi8+1pInuVcSztSM4MwBFB0hIHf4Rbwu4g==", + "dev": true, + "dependencies": { + "@next/eslint-plugin-next": "15.3.0", + "@rushstack/eslint-patch": "^1.10.3", + "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^5.0.0" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.0.tgz", + "integrity": "sha512-aV3/dVsT0/H9BtpNwbaqvl+0xGMRGzncLyhm793NFGvbwGGvzyAykqWZ8oZlZuGwuHkwJjhWJkG1cM3ynvd2pQ==", + "dev": true, + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.12", + "unrs-resolver": "^1.3.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "dev": true, + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.3.0.tgz", + "integrity": "sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", + "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==", + "dev": true, + "dependencies": { + "acorn": "^8.14.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==" + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", + "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glsl-noise": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/glsl-noise/-/glsl-noise-0.0.0.tgz", + "integrity": "sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w==" + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/heap": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", + "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==" + }, + "node_modules/hls.js": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/hls.js/-/hls.js-1.6.2.tgz", + "integrity": "sha512-rx+pETSCJEDThm/JCm8CuadcAC410cVjb1XVXFNDKFuylaayHk1+tFxhkjvnMDAfqsJHxZXDAJ3Uc2d5xQyWlQ==" + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", + "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "optional": true + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "dependencies": { + "semver": "^7.7.1" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/its-fine": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/its-fine/-/its-fine-2.0.0.tgz", + "integrity": "sha512-KLViCmWx94zOvpLwSlsx6yOCeMhZYaxrJV87Po5k/FoZzcPSahvK5qJ7fYhS61sZi5ikmh2S3Hz55A2l3U69ng==", + "dependencies": { + "@types/react-reconciler": "^0.28.9" + }, + "peerDependencies": { + "react": "^19.0.0" + } + }, + "node_modules/jiti": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.4.2.tgz", + "integrity": "sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==", + "dev": true, + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lie": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", + "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lightningcss": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.29.2.tgz", + "integrity": "sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==", + "dev": true, + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.29.2", + "lightningcss-darwin-x64": "1.29.2", + "lightningcss-freebsd-x64": "1.29.2", + "lightningcss-linux-arm-gnueabihf": "1.29.2", + "lightningcss-linux-arm64-gnu": "1.29.2", + "lightningcss-linux-arm64-musl": "1.29.2", + "lightningcss-linux-x64-gnu": "1.29.2", + "lightningcss-linux-x64-musl": "1.29.2", + "lightningcss-win32-arm64-msvc": "1.29.2", + "lightningcss-win32-x64-msvc": "1.29.2" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.29.2.tgz", + "integrity": "sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.29.2.tgz", + "integrity": "sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.29.2.tgz", + "integrity": "sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.29.2.tgz", + "integrity": "sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.29.2.tgz", + "integrity": "sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.29.2.tgz", + "integrity": "sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.29.2.tgz", + "integrity": "sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.29.2.tgz", + "integrity": "sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.29.2.tgz", + "integrity": "sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.29.2", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.29.2.tgz", + "integrity": "sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/maath": { + "version": "0.10.8", + "resolved": "https://registry.npmjs.org/maath/-/maath-0.10.8.tgz", + "integrity": "sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g==", + "peerDependencies": { + "@types/three": ">=0.134.0", + "three": ">=0.134.0" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/md5-typescript": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/md5-typescript/-/md5-typescript-1.0.5.tgz", + "integrity": "sha512-ovAc4EtiNt2dY8JPhPr/wkC9h4U5k/nuClNVcG0Ga3V1rMlYpAY24ZaaymFXJlz+ccJ6UMPo3FSaVKe7czBsXw==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/meshline": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/meshline/-/meshline-3.3.1.tgz", + "integrity": "sha512-/TQj+JdZkeSUOl5Mk2J7eLcYTLiQm2IDzmlSvYm7ov15anEcDJ92GHqqazxTSreeNgfnYu24kiEvvv0WlbCdFQ==", + "peerDependencies": { + "three": ">=0.137" + } + }, + "node_modules/meshoptimizer": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.18.1.tgz", + "integrity": "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==" + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/next": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/next/-/next-15.3.0.tgz", + "integrity": "sha512-k0MgP6BsK8cZ73wRjMazl2y2UcXj49ZXLDEgx6BikWuby/CN+nh81qFFI16edgd7xYpe/jj2OZEIwCoqnzz0bQ==", + "dependencies": { + "@next/env": "15.3.0", + "@swc/counter": "0.1.3", + "@swc/helpers": "0.5.15", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "15.3.0", + "@next/swc-darwin-x64": "15.3.0", + "@next/swc-linux-arm64-gnu": "15.3.0", + "@next/swc-linux-arm64-musl": "15.3.0", + "@next/swc-linux-x64-gnu": "15.3.0", + "@next/swc-linux-x64-musl": "15.3.0", + "@next/swc-win32-arm64-msvc": "15.3.0", + "@next/swc-win32-x64-msvc": "15.3.0", + "sharp": "^0.34.1" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", + "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.8", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/potpack": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz", + "integrity": "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/promise-worker-transferable": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/promise-worker-transferable/-/promise-worker-transferable-1.0.4.tgz", + "integrity": "sha512-bN+0ehEnrXfxV2ZQvU2PetO0n4gqBD4ulq3MI1WOPLgr7/Mg9yRQkX5+0v1vagr74ZTsl7XtzlaYDo2EuCeYJw==", + "dependencies": { + "is-promise": "^2.1.0", + "lie": "^3.0.2" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", + "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz", + "integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==", + "dependencies": { + "scheduler": "^0.26.0" + }, + "peerDependencies": { + "react": "^19.1.0" + } + }, + "node_modules/react-icons": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.5.0.tgz", + "integrity": "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==", + "peerDependencies": { + "react": "*" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, + "node_modules/react-reconciler": { + "version": "0.31.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.31.0.tgz", + "integrity": "sha512-7Ob7Z+URmesIsIVRjnLoDGwBEG/tVitidU0nMsqX/eeJaLY89RISO/10ERe0MqmzuKUUB1rmY+h1itMbUHg9BQ==", + "dependencies": { + "scheduler": "^0.25.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "^19.0.0" + } + }, + "node_modules/react-reconciler/node_modules/scheduler": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", + "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==" + }, + "node_modules/react-resizable-panels": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-3.0.1.tgz", + "integrity": "sha512-6ruCEyw0iqXRcXEktPQn1HL553DNhrdLisCyEdSpzhkmo9bPqZxskJZ+aGeFqJ1qPvIWxuAiag82kvLSb2JZTQ==", + "peerDependencies": { + "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, + "node_modules/react-use-measure": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.7.tgz", + "integrity": "sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg==", + "peerDependencies": { + "react": ">=16.13", + "react-dom": ">=16.13" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.26.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz", + "integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==" + }, + "node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "devOptional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "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" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sharp": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.1.tgz", + "integrity": "sha512-1j0w61+eVxu7DawFJtnfYcvSv6qPFvfTaqzTQ2BLknVhHTwGS8sc63ZBF4rzkWMBVKybo4S5OBtDdZahh2A1xg==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.7.1" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.1", + "@img/sharp-darwin-x64": "0.34.1", + "@img/sharp-libvips-darwin-arm64": "1.1.0", + "@img/sharp-libvips-darwin-x64": "1.1.0", + "@img/sharp-libvips-linux-arm": "1.1.0", + "@img/sharp-libvips-linux-arm64": "1.1.0", + "@img/sharp-libvips-linux-ppc64": "1.1.0", + "@img/sharp-libvips-linux-s390x": "1.1.0", + "@img/sharp-libvips-linux-x64": "1.1.0", + "@img/sharp-libvips-linuxmusl-arm64": "1.1.0", + "@img/sharp-libvips-linuxmusl-x64": "1.1.0", + "@img/sharp-linux-arm": "0.34.1", + "@img/sharp-linux-arm64": "0.34.1", + "@img/sharp-linux-s390x": "0.34.1", + "@img/sharp-linux-x64": "0.34.1", + "@img/sharp-linuxmusl-arm64": "0.34.1", + "@img/sharp-linuxmusl-x64": "0.34.1", + "@img/sharp-wasm32": "0.34.1", + "@img/sharp-win32-ia32": "0.34.1", + "@img/sharp-win32-x64": "0.34.1" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "optional": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true + }, + "node_modules/stats-gl": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/stats-gl/-/stats-gl-2.4.2.tgz", + "integrity": "sha512-g5O9B0hm9CvnM36+v7SFl39T7hmAlv541tU81ME8YeSb3i1CIP5/QdDeSB3A0la0bKNHpxpwxOVRo2wFTYEosQ==", + "dependencies": { + "@types/three": "*", + "three": "^0.170.0" + }, + "peerDependencies": { + "@types/three": "*", + "three": "*" + } + }, + "node_modules/stats-gl/node_modules/three": { + "version": "0.170.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.170.0.tgz", + "integrity": "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ==" + }, + "node_modules/stats.js": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/stats.js/-/stats.js-0.17.0.tgz", + "integrity": "sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw==" + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/stylis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/suspend-react": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/suspend-react/-/suspend-react-0.1.3.tgz", + "integrity": "sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ==", + "peerDependencies": { + "react": ">=17.0" + } + }, + "node_modules/tailwindcss": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.3.tgz", + "integrity": "sha512-2Q+rw9vy1WFXu5cIxlvsabCwhU2qUwodGq03ODhLJ0jW4ek5BUtoCsnLB0qG+m8AHgEsSJcJGDSDe06FXlP74g==", + "dev": true + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/three": { + "version": "0.175.0", + "resolved": "https://registry.npmjs.org/three/-/three-0.175.0.tgz", + "integrity": "sha512-nNE3pnTHxXN/Phw768u0Grr7W4+rumGg/H6PgeseNJojkJtmeHJfZWi41Gp2mpXl1pg1pf1zjwR4McM1jTqkpg==" + }, + "node_modules/three-mesh-bvh": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.8.3.tgz", + "integrity": "sha512-4G5lBaF+g2auKX3P0yqx+MJC6oVt6sB5k+CchS6Ob0qvH0YIhuUk1eYr7ktsIpY+albCqE80/FVQGV190PmiAg==", + "peerDependencies": { + "three": ">= 0.159.0" + } + }, + "node_modules/three-stdlib": { + "version": "2.36.0", + "resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.36.0.tgz", + "integrity": "sha512-kv0Byb++AXztEGsULgMAs8U2jgUdz6HPpAB/wDJnLiLlaWQX2APHhiTJIN7rqW+Of0eRgcp7jn05U1BsCP3xBA==", + "dependencies": { + "@types/draco3d": "^1.4.0", + "@types/offscreencanvas": "^2019.6.4", + "@types/webxr": "^0.5.2", + "draco3d": "^1.4.1", + "fflate": "^0.6.9", + "potpack": "^1.0.1" + }, + "peerDependencies": { + "three": ">=0.128.0" + } + }, + "node_modules/three-stdlib/node_modules/fflate": { + "version": "0.6.10", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.6.10.tgz", + "integrity": "sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==" + }, + "node_modules/tinyglobby": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", + "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", + "dev": true, + "dependencies": { + "fdir": "^6.4.3", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", + "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", + "dev": true, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/troika-three-text": { + "version": "0.52.4", + "resolved": "https://registry.npmjs.org/troika-three-text/-/troika-three-text-0.52.4.tgz", + "integrity": "sha512-V50EwcYGruV5rUZ9F4aNsrytGdKcXKALjEtQXIOBfhVoZU9VAqZNIoGQ3TMiooVqFAbR1w15T+f+8gkzoFzawg==", + "dependencies": { + "bidi-js": "^1.0.2", + "troika-three-utils": "^0.52.4", + "troika-worker-utils": "^0.52.0", + "webgl-sdf-generator": "1.1.1" + }, + "peerDependencies": { + "three": ">=0.125.0" + } + }, + "node_modules/troika-three-utils": { + "version": "0.52.4", + "resolved": "https://registry.npmjs.org/troika-three-utils/-/troika-three-utils-0.52.4.tgz", + "integrity": "sha512-NORAStSVa/BDiG52Mfudk4j1FG4jC4ILutB3foPnfGbOeIs9+G5vZLa0pnmnaftZUGm4UwSoqEpWdqvC7zms3A==", + "peerDependencies": { + "three": ">=0.125.0" + } + }, + "node_modules/troika-worker-utils": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/troika-worker-utils/-/troika-worker-utils-0.52.0.tgz", + "integrity": "sha512-W1CpvTHykaPH5brv5VHLfQo9D1OYuo0cSBEUQFFT/nBUzM8iD6Lq2/tgG/f1OelbAS1WtaTPQzE5uM49egnngw==" + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/tunnel-rat": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/tunnel-rat/-/tunnel-rat-0.1.2.tgz", + "integrity": "sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ==", + "dependencies": { + "zustand": "^4.3.2" + } + }, + "node_modules/tunnel-rat/node_modules/zustand": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.6.tgz", + "integrity": "sha512-ibr/n1hBzLLj5Y+yUcU7dYw8p6WnIVzdJbnX+1YpaScvZVF2ziugqHs+LAmHw4lWO9c/zRj+K1ncgWDQuthEdQ==", + "dependencies": { + "use-sync-external-store": "^1.2.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true + }, + "node_modules/unrs-resolver": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.4.1.tgz", + "integrity": "sha512-MhPB3wBI5BR8TGieTb08XuYlE8oFVEXdSAgat3psdlRyejl8ojQ8iqPcjh094qCZ1r+TnkxzP6BeCd/umfHckQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/JounQin" + }, + "optionalDependencies": { + "@unrs/resolver-binding-darwin-arm64": "1.4.1", + "@unrs/resolver-binding-darwin-x64": "1.4.1", + "@unrs/resolver-binding-freebsd-x64": "1.4.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.4.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.4.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.4.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.4.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.4.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.4.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.4.1", + "@unrs/resolver-binding-linux-x64-musl": "1.4.1", + "@unrs/resolver-binding-wasm32-wasi": "1.4.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.4.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.4.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.4.1" + } + }, + "node_modules/urdf-loader": { + "version": "0.12.4", + "resolved": "https://registry.npmjs.org/urdf-loader/-/urdf-loader-0.12.4.tgz", + "integrity": "sha512-CmBVJmsGDQpWLN3cg9lYkgMGlpbdKqaXDhvG4XXkpADRcYMDWGxHsu0U/1FQcvMq5oke7C65WJoSG2/MyX7HrA==", + "license": "Apache-2.0", + "peerDependencies": { + "three": ">=0.152.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/utility-types": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz", + "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/webgl-constants": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/webgl-constants/-/webgl-constants-1.1.1.tgz", + "integrity": "sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg==" + }, + "node_modules/webgl-sdf-generator": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/webgl-sdf-generator/-/webgl-sdf-generator-1.1.1.tgz", + "integrity": "sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA==" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zustand": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.3.tgz", + "integrity": "sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + } + } +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/package.json b/GEMstack/onboard/visualization/sr_viz/threeD/package.json new file mode 100644 index 000000000..73f65fb57 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/package.json @@ -0,0 +1,40 @@ +{ + "name": "cs588_vis", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev --turbopack", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.0", + "@foxglove/rosbag": "^0.4.1", + "@mui/icons-material": "^7.0.2", + "@mui/material": "^7.0.2", + "@react-three/drei": "^10.0.6", + "@react-three/fiber": "^9.1.2", + "cs588_vis": "file:", + "next": "15.3.0", + "react": "^19.0.0", + "react-dom": "^19.0.0", + "react-icons": "^5.5.0", + "react-resizable-panels": "^3.0.1", + "three": "^0.175.0", + "three-stdlib": "^2.36.0", + "urdf-loader": "^0.12.4" + }, + "devDependencies": { + "@eslint/eslintrc": "^3", + "@tailwindcss/postcss": "^4", + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "15.3.0", + "tailwindcss": "^4", + "typescript": "^5" + } +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/postcss.config.mjs b/GEMstack/onboard/visualization/sr_viz/threeD/postcss.config.mjs new file mode 100644 index 000000000..c7bcb4b1e --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/postcss.config.mjs @@ -0,0 +1,5 @@ +const config = { + plugins: ["@tailwindcss/postcss"], +}; + +export default config; diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/gem_e2.urdf b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/gem_e2.urdf new file mode 100644 index 000000000..1989feab6 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/gem_e2.urdf @@ -0,0 +1,1473 @@ + + + + + + + + Gazebo/Red + + + Gazebo/Red + + + 10000 + 100000000 + 1000000 + 1e8 + 0.001 + 100.0 + Gazebo/Blue + + + 10000 + 100000000 + 1000000 + 1e8 + 0.001 + 100.0 + Gazebo/Blue + + + 0.9 + 1000000 + 0.005 + 1e8 + Gazebo/Black + + + 0.9 + 1000000 + 0.005 + 1e8 + Gazebo/Black + + + 0.9 + 1000000 + 0.005 + 1e8 + Gazebo/Black + + + 0.9 + 1000000 + 0.005 + 1e8 + Gazebo/Black + + + + + Gazebo/White + + + Gazebo/Grey + + + Gazebo/White + + + + Gazebo/Black + + + Gazebo/Black + + + Gazebo/Black + + + Gazebo/Red + + + Gazebo/Red + + + Gazebo/Red + + + Gazebo/Red + + + Gazebo/Red + + + Gazebo/Red + + + Gazebo/Red + + + Gazebo/White + + + Gazebo/White + + + Gazebo/Orange + + + Gazebo/Orange + + + Gazebo/Orange + + + Gazebo/Orange + + + Gazebo/Blue + + + Gazebo/Blue + + + Gazebo/Grey + + + Gazebo/Grey + + + Gazebo/Red + + + Gazebo/Red + + + Gazebo/Red + + + Gazebo/Red + + + Gazebo/Orange + + + Gazebo/Orange + + + Gazebo/Red + + + + true + gazebo_ros_control/DefaultRobotHWSim + + + + + + 30.0 + + + 1.5707963 + + 640 + 480 + + R8G8B8 + + + 0.02 + 300 + + + gaussian + 0.0 + 0.007 + + + + true + 0.0 + front_single_camera + image_raw + camera_info + front_single_camera_link + 0.07 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + + + + + + + true + IMU_link + IMU_link + imu + imu_service + 0.0 + 50.0 + + + + + + 20.0 + GPS_link + GPS_link + /gps/fix + /gps/fix_velocity + 40.09302494 + -88.23575484 + 90 + 220 + 0 0 0 + 0.001 0.001 0.001 + 0.05 0.05 0.05 + 0.001 0.001 0.001 + 0.5 0.5 0.5 + + + + + + + + + + true + 20 + 0 0 0 0 0 0 + false + + + + 2 + 1 + -28 + 28 + + + 2 + 1 + -28 + 28 + + + + 0.3 + 5 + 0.01 + + + + 0.005 + /front_sonar_distance + front_sonar_link + + + + + + + true + 20 + 0 0 0 0 0 0 + false + + + + 2 + 1 + -28 + 28 + + + 2 + 1 + -28 + 28 + + + + 0.3 + 5 + 0.01 + + + + 0.005 + /rear_sonar_distance + rear_sonar_link + + + + + + + 30.0 + + 1.5707963 + + 800 + 600 + R8G8B8 + + + 0.02 + 300 + + + gaussian + 0.0 + 0.007 + + + + 0 -0.07 0 0 0 0 + 1.5707963 + + 800 + 600 + R8G8B8 + + + 0.02 + 300 + + + gaussian + 0.0 + 0.007 + + + + true + 0.0 + stereo/camera + image_raw + camera_info + stereo_camera_link + + + 0.5 + 0.0 + 0.0 + 0.0 + 0.0 + 0.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + transmission_interface/SimpleTransmission + + hardware_interface/EffortJointInterface + + + hardware_interface/EffortJointInterface + 1 + + + + transmission_interface/SimpleTransmission + + hardware_interface/EffortJointInterface + + + hardware_interface/EffortJointInterface + 1 + + + + transmission_interface/SimpleTransmission + + hardware_interface/EffortJointInterface + + + hardware_interface/EffortJointInterface + 1 + + + + transmission_interface/SimpleTransmission + + hardware_interface/EffortJointInterface + + + hardware_interface/EffortJointInterface + 1 + + + + transmission_interface/SimpleTransmission + + hardware_interface/EffortJointInterface + + + hardware_interface/EffortJointInterface + 1 + + + + transmission_interface/SimpleTransmission + + hardware_interface/EffortJointInterface + + + hardware_interface/EffortJointInterface + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/gem_e4.urdf b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/gem_e4.urdf new file mode 100644 index 000000000..5ddb5a0eb --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/gem_e4.urdf @@ -0,0 +1,919 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/base_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/base_link.STL new file mode 100755 index 000000000..9c17ee417 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/base_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/chair_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/chair_link.STL new file mode 100755 index 000000000..0c6765cf2 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/chair_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/door_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/door_link.STL new file mode 100755 index 000000000..c747ca9af Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/door_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/base_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/base_link.STL new file mode 100644 index 000000000..952b788ef Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/base_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/front_camera_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/front_camera_link.STL new file mode 100644 index 000000000..d658e5cdb Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/front_camera_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/front_lidar_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/front_lidar_link.STL new file mode 100644 index 000000000..d49aea2e7 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/front_lidar_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/front_rack_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/front_rack_link.STL new file mode 100755 index 000000000..6484d4245 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/front_rack_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/front_radar_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/front_radar_link.STL new file mode 100644 index 000000000..fa7839417 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/front_radar_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/gps_antenna_aux_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/gps_antenna_aux_link.STL new file mode 100755 index 000000000..9a0c069b0 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/gps_antenna_aux_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/gps_antenna_main_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/gps_antenna_main_link.STL new file mode 100755 index 000000000..32c0d6565 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/gps_antenna_main_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/headlight_fl_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/headlight_fl_link.STL new file mode 100755 index 000000000..bc49454cd Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/headlight_fl_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/headlight_fr_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/headlight_fr_link.STL new file mode 100755 index 000000000..bc49454cd Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/headlight_fr_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/i_logo_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/i_logo_link.STL new file mode 100755 index 000000000..e0769efe7 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/i_logo_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/imu_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/imu_link.STL new file mode 100644 index 000000000..97d552e72 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/imu_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/lightbar_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/lightbar_link.STL new file mode 100755 index 000000000..04a9d2f1e Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/lightbar_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/rear_rack_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/rear_rack_link.STL new file mode 100755 index 000000000..1ab3f1a54 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/rear_rack_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/stoplight_rl_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/stoplight_rl_link.STL new file mode 100755 index 000000000..9e30a0a21 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/stoplight_rl_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/stoplight_rr_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/stoplight_rr_link.STL new file mode 100755 index 000000000..9e30a0a21 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/stoplight_rr_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/taillight_rl_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/taillight_rl_link.STL new file mode 100755 index 000000000..b24d6ae97 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/taillight_rl_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/taillight_rr_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/taillight_rr_link.STL new file mode 100755 index 000000000..afc66745f Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/taillight_rr_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/top_lidar_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/top_lidar_link.STL new file mode 100644 index 000000000..b52b8f475 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/top_lidar_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/top_rack_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/top_rack_link.STL new file mode 100644 index 000000000..a55bd5397 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/top_rack_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/turnlight_fl_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/turnlight_fl_link.STL new file mode 100755 index 000000000..50888317f Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/turnlight_fl_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/turnlight_fr_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/turnlight_fr_link.STL new file mode 100755 index 000000000..a4488df1f Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/turnlight_fr_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/wheel_link_fl.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/wheel_link_fl.STL new file mode 100644 index 000000000..06fb9b87e Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/wheel_link_fl.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/wheel_link_fr.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/wheel_link_fr.STL new file mode 100644 index 000000000..85975cc77 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/wheel_link_fr.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/wheel_link_rl.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/wheel_link_rl.STL new file mode 100644 index 000000000..049fec865 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/wheel_link_rl.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/wheel_link_rr.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/wheel_link_rr.STL new file mode 100644 index 000000000..0d0940a96 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/e4/wheel_link_rr.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_camera_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_camera_link.STL new file mode 100755 index 000000000..5074cba3e Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_camera_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_left_emergency_button_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_left_emergency_button_link.STL new file mode 100755 index 000000000..eb6fcfd4e Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_left_emergency_button_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_left_head_light_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_left_head_light_link.STL new file mode 100755 index 000000000..bc49454cd Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_left_head_light_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_left_turn_light_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_left_turn_light_link.STL new file mode 100755 index 000000000..50888317f Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_left_turn_light_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_left_wheel_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_left_wheel_link.STL new file mode 100755 index 000000000..06fb9b87e Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_left_wheel_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_rack_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_rack_link.STL new file mode 100755 index 000000000..6484d4245 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_rack_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_right_emergency_button_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_right_emergency_button_link.STL new file mode 100755 index 000000000..4180556f8 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_right_emergency_button_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_right_head_light_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_right_head_light_link.STL new file mode 100755 index 000000000..bc49454cd Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_right_head_light_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_right_turn_light_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_right_turn_light_link.STL new file mode 100755 index 000000000..a4488df1f Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_right_turn_light_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_right_wheel_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_right_wheel_link.STL new file mode 100755 index 000000000..85975cc77 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/front_right_wheel_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/left_I_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/left_I_link.STL new file mode 100755 index 000000000..e0769efe7 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/left_I_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/left_antenna_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/left_antenna_link.STL new file mode 100755 index 000000000..32c0d6565 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/left_antenna_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/left_blue_outer_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/left_blue_outer_link.STL new file mode 100755 index 000000000..717f1c931 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/left_blue_outer_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/left_fixed_hinge_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/left_fixed_hinge_link.STL new file mode 100755 index 000000000..2c8e0610a Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/left_fixed_hinge_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/left_steering_hinge_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/left_steering_hinge_link.STL new file mode 100755 index 000000000..43f7ecc63 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/left_steering_hinge_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_left_emergency_button_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_left_emergency_button_link.STL new file mode 100755 index 000000000..033a25319 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_left_emergency_button_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_left_light_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_left_light_link.STL new file mode 100755 index 000000000..b24d6ae97 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_left_light_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_left_stop_light_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_left_stop_light_link.STL new file mode 100755 index 000000000..9e30a0a21 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_left_stop_light_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_left_wheel_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_left_wheel_link.STL new file mode 100755 index 000000000..049fec865 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_left_wheel_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_light_bar_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_light_bar_link.STL new file mode 100755 index 000000000..04a9d2f1e Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_light_bar_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_rack_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_rack_link.STL new file mode 100755 index 000000000..1ab3f1a54 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_rack_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_right_emergency_button_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_right_emergency_button_link.STL new file mode 100755 index 000000000..4bb494cd5 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_right_emergency_button_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_right_light_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_right_light_link.STL new file mode 100755 index 000000000..afc66745f Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_right_light_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_right_stop_light_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_right_stop_light_link.STL new file mode 100755 index 000000000..9e30a0a21 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_right_stop_light_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_right_wheel_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_right_wheel_link.STL new file mode 100755 index 000000000..0d0940a96 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/rear_right_wheel_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/right_I_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/right_I_link.STL new file mode 100755 index 000000000..e0769efe7 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/right_I_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/right_antenna_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/right_antenna_link.STL new file mode 100755 index 000000000..9a0c069b0 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/right_antenna_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/right_blue_outer_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/right_blue_outer_link.STL new file mode 100755 index 000000000..717f1c931 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/right_blue_outer_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/right_fixed_hinge_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/right_fixed_hinge_link.STL new file mode 100755 index 000000000..0307a31e6 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/right_fixed_hinge_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/right_steering_hinge_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/right_steering_hinge_link.STL new file mode 100755 index 000000000..01cb60e1b Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/right_steering_hinge_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/top_rack_link.STL b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/top_rack_link.STL new file mode 100755 index 000000000..33cbd12b1 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/meshes/top_rack_link.STL differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/plane.off b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/plane.off new file mode 100644 index 000000000..5ce7162d9 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/model/plane.off @@ -0,0 +1,8 @@ +OFF +4 2 0 +-5.000000 -5.000000 0.000000 +-5.000000 5.000000 0.000000 +5.000000 -5.000000 0.000000 +5.000000 5.000000 0.000000 +3 0 2 1 +3 1 2 3 diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/pedestrian.glb b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/pedestrian.glb new file mode 100644 index 000000000..5b0b0d826 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/pedestrian.glb differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/traffic_cone.glb b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/traffic_cone.glb new file mode 100644 index 000000000..cf0096550 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/traffic_cone.glb differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/public/models/traffic_light.glb b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/traffic_light.glb new file mode 100644 index 000000000..d7f8826cb Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/public/models/traffic_light.glb differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/app/favicon.ico b/GEMstack/onboard/visualization/sr_viz/threeD/src/app/favicon.ico new file mode 100644 index 000000000..718d6fea4 Binary files /dev/null and b/GEMstack/onboard/visualization/sr_viz/threeD/src/app/favicon.ico differ diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/app/globals.css b/GEMstack/onboard/visualization/sr_viz/threeD/src/app/globals.css new file mode 100644 index 000000000..a2dc41ece --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/app/globals.css @@ -0,0 +1,26 @@ +@import "tailwindcss"; + +:root { + --background: #ffffff; + --foreground: #171717; +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --font-sans: var(--font-geist-sans); + --font-mono: var(--font-geist-mono); +} + +@media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } +} + +body { + background: var(--background); + color: var(--foreground); + font-family: Arial, Helvetica, sans-serif; +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/app/layout.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/app/layout.tsx new file mode 100644 index 000000000..5ec74caf3 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/app/layout.tsx @@ -0,0 +1,32 @@ +import type { Metadata } from "next"; +import { Geist, Geist_Mono } from "next/font/google"; +import "./globals.css"; + +const geistSans = Geist({ + variable: "--font-geist-sans", + subsets: ["latin"], +}); + +const geistMono = Geist_Mono({ + variable: "--font-geist-mono", + subsets: ["latin"], +}); + +export const metadata: Metadata = { + title: "CS588 Visualizer", + description: "CS588 3D driving UI in Three.js", +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + + {children} + + + ); +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/app/page.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/app/page.tsx new file mode 100644 index 000000000..70c3cd55e --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/app/page.tsx @@ -0,0 +1,85 @@ +"use client"; + +import { useEffect, useState } from "react"; +import ControlPanel from "@/components/ControlPanel"; +import CanvasWrapper from "@/components/CanvasWrapper"; +import Scrubber from "@/components/Scrubber"; +import { VehicleInfoPanel } from "@/components/VehicleInfoPanel"; +import { usePlaybackTime } from "@/hooks/usePlaybackTime"; +import { useRouter } from "next/navigation"; +import Button from "@mui/material/Button"; +import PageviewIcon from "@mui/icons-material/Pageview"; + +export default function HomePage() { + const router = useRouter(); + const { + time, + reset, + restart, + play, + setPlay, + togglePlay, + speed, + setPlaybackSpeed, + moveToTime, + duration, + setDuration, + } = usePlaybackTime(); + + const [searchParams, setSearchParams] = useState<{ + folder?: string; + file?: string; + }>({}); + + useEffect(() => { + if (typeof window !== "undefined") { + const params = new URLSearchParams(window.location.search); + const folder = params.get("folder") || undefined; + const file = params.get("file") || undefined; + setSearchParams({ folder, file }); + } + }, []); + + const handleRedirect = () => { + setPlay(false); + router.replace("/rosbagViewer"); + }; + + return ( +
+
+
+ +
+
+ + + + +
+ ); +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/app/rosbagViewer/page.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/app/rosbagViewer/page.tsx new file mode 100644 index 000000000..411ea3acd --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/app/rosbagViewer/page.tsx @@ -0,0 +1,37 @@ +"use client"; + +import React from "react"; +import RosbagViewer from "@/components/RosbagViewer"; +import { useRouter } from "next/navigation"; +import Button from "@mui/material/Button"; +import HomeIcon from "@mui/icons-material/Home"; + +export default function RosbagViewerPage() { + const router = useRouter(); + const handleRedirect = () => { + router.replace("/"); + }; + return ( +
+
+
+ +
+
+ +
+ ); +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/components/CanvasWrapper.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/CanvasWrapper.tsx new file mode 100644 index 000000000..e9477cad5 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/CanvasWrapper.tsx @@ -0,0 +1,70 @@ +"use client"; + +import { Canvas } from "@react-three/fiber"; +import React, { useEffect } from "react"; +import { Environment } from "@react-three/drei"; +import { useTimelineStore } from "@/hooks/useTimelineStore"; +import Vehicle from "./Vehicle"; +import Pedestrian from "./Pedestrian"; +import TrafficLight from "./TrafficLight"; +import OtherVehicle from "./OtherVehicle"; +import Ground from "./Ground"; +import TrafficCone from "./TrafficCone"; + +export default function CanvasWrapper({ + time, + setDuration, +}: { + time: number; + setDuration: (duration: number) => void; +}) { + const { vehicle, pedestrians, trafficLights, trafficCones, otherVehicles } = + useTimelineStore(); + + useEffect(() => { + if (vehicle.length > 0) { + setDuration(vehicle[vehicle.length - 1].time - vehicle[0].time); + } + }, [vehicle]); + + const startTime = vehicle.length > 0 ? vehicle[0].time : 0; + const syncedTime = startTime + time; + + return ( + + + + + + + {Object.entries(pedestrians).map(([id, timeline]) => ( + + ))} + + {Object.entries(trafficLights).map(([id, timeline]) => ( + + ))} + + {Object.entries(trafficCones).map(([id, timeline]) => ( + + ))} + + {Object.entries(otherVehicles).map(([id, timeline]) => ( + + ))} + + + + ); +} \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/components/ControlPanel.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/ControlPanel.tsx new file mode 100644 index 000000000..474019e36 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/ControlPanel.tsx @@ -0,0 +1,112 @@ +"use client"; + +import React, { useRef, useState, useEffect } from "react"; +import { TiUpload } from "react-icons/ti"; +import { RxCross2 } from "react-icons/rx"; +import { buildTimeline } from "@/utils/buildTimeline"; +import { parseLogFile } from "@/utils/parseLogFile"; +import { useTimelineStore } from "@/hooks/useTimelineStore"; +import { TimelineData } from "@/types/TimelineData"; + +export default function ControlPanel({ + reset, + folder, + file, +}: { + reset: () => void; + folder?: string; + file?: string; +}) { + const [isOpen, setIsOpen] = useState(false); + const [fileName, setFileName] = useState(null); + const fileInputRef = useRef(null); + const prevKeyRef = useRef(null); + const setTimeline = useTimelineStore((state) => state.setTimeline); + + const handleFileUpload = async ( + event: React.ChangeEvent + ) => { + const uploaded = event.target.files?.[0]; + if (!uploaded) return; + setFileName(uploaded.name); + const entries = await parseLogFile(uploaded); + const timeline: TimelineData = buildTimeline(entries); + setTimeline(timeline); + reset(); + fileInputRef.current!.value = ""; + }; + + useEffect(() => { + if (!folder || !file) return; + const key = `${folder}/${file}`; + if (prevKeyRef.current === key) return; + prevKeyRef.current = key; + (async () => { + const url = `http://localhost:5000/raw_logs/${encodeURIComponent( + folder + )}/${encodeURIComponent(file)}`; + const res = await fetch(url); + const text = await res.text(); + const fakeFile = new File([text], file, { type: "text/plain" }); + const entries = await parseLogFile(fakeFile); + const timeline = buildTimeline(entries); + setTimeline(timeline); + reset(); + setFileName(file); + })(); + }, [folder, file, reset, setTimeline]); + + return ( + <> +
{ + e.preventDefault(); + setIsOpen((o) => !o); + }} + > + {isOpen && ( + <> +
+

+ Control Panel +

+ +
+
+ +

+ {fileName ?? "No file loaded"} +

+
+ + )} +
+ {!isOpen && ( + + )} + + ); +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/components/Ground.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/Ground.tsx new file mode 100644 index 000000000..010a80a8e --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/Ground.tsx @@ -0,0 +1,24 @@ +"use client"; + +import React from "react"; +import { groundConfig } from "@/config/groundConfig"; +import { Grid } from "@react-three/drei"; + +export default function Ground() { + return ( + + ); +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/components/OtherVehicle.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/OtherVehicle.tsx new file mode 100644 index 000000000..f0224111f --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/OtherVehicle.tsx @@ -0,0 +1,69 @@ +"use client"; + +import React, { useRef, useEffect, useMemo, useState } from "react"; +import { useFrame } from "@react-three/fiber"; +import * as THREE from "three"; +import { FrameData } from "@/types/FrameData"; +import { currentOtherVehicle } from "@/config/otherVehicleConfig"; +import URDFLoader from "urdf-loader"; +import { getInterpolatedFrame } from "@/utils/getInterpolatedFrame"; + +interface OtherVehicleProps { + id: string; + timeline: FrameData[]; + time: number; +} + +export default function OtherVehicle({ id, timeline, time }: OtherVehicleProps) { + const ref = useRef(null); + const vehicleGroup = useRef(new THREE.Group()); + const [isLoaded, setIsLoaded] = useState(false); + + const targetPosition = useMemo(() => new THREE.Vector3(), []); + const targetQuaternion = useMemo(() => new THREE.Quaternion(), []); + + const { modelPath, scale, rotation, offset, bodyColor } = currentOtherVehicle; + + useEffect(() => { + const loader = new URDFLoader(); + loader.load( + modelPath, + (robot) => { + robot.scale.set(scale[0], scale[1], scale[2]); + robot.rotation.set(rotation[0], rotation[1], rotation[2]); + robot.position.set(offset[0], offset[1], offset[2]); + robot.traverse((child) => { + if ( + child instanceof THREE.Mesh && + child.material instanceof THREE.MeshStandardMaterial + ) { + child.material = child.material.clone(); + child.material.color.set(bodyColor); + } + }); + vehicleGroup.current.add(robot); + setIsLoaded(true); + }, + undefined, + (error) => { + console.error("URDF loading failed:", error); + } + ); + }, [modelPath, scale, rotation, offset, bodyColor]); + + useFrame(() => { + if (!ref.current || timeline.length === 0) return; + const frame = getInterpolatedFrame(timeline, time); + if (!frame) return; + targetPosition.set(frame.x, 0, frame.y); + ref.current.position.lerp(targetPosition, 0.2); + targetQuaternion.setFromEuler(new THREE.Euler(0, -frame.yaw, 0)); + ref.current.quaternion.slerp(targetQuaternion, 0.2); + }); + + return ( + + + + ); +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/components/PanelManager.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/PanelManager.tsx new file mode 100644 index 000000000..2cfc438dd --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/PanelManager.tsx @@ -0,0 +1,274 @@ +"use client"; + +import React, { useState } from "react"; +import { VideoPanel } from "./VideoPanel"; +import { PointCloudPanel } from "./PointCloudPanel"; +import { + Button, + Menu, + MenuItem, + ListItemIcon, + ListItemText, +} from "@mui/material"; +import MenuIcon from "@mui/icons-material/Menu"; +import { PanelGroup, Panel, PanelResizeHandle } from "react-resizable-panels"; +import HorizontalSplitIcon from "@mui/icons-material/HorizontalSplit"; +import VerticalSplitIcon from "@mui/icons-material/VerticalSplit"; +import ImageIcon from "@mui/icons-material/Image"; +import HubIcon from "@mui/icons-material/Hub"; +import CloseIcon from "@mui/icons-material/Close"; + +type PanelNode = + | { + id: number; + type: "video" | "pointcloud" | "text"; + } + | { + id: number; + split: "horizontal" | "vertical"; + children: PanelNode[]; + }; + +let panelIdCounter = 2; + +function createPanel(type: "video" | "pointcloud" | "text"): PanelNode { + return { id: panelIdCounter++, type }; +} + +export const PanelManager = ({ + messageMap, +}: { + messageMap: Record | any[]>; +}) => { + const [rootPanel, setRootPanel] = useState(createPanel("video")); + + const renderPanelNode = (node: PanelNode) => { + if ("split" in node) { + return ( + + + {node.children.map((child, idx) => ( + + {renderPanelNode(child)} + {idx < node.children.length - 1 && ( + + )} + + ))} + + + ); + } + + return ( + + { + const newSplit: PanelNode = { + id: panelIdCounter++, + split: direction, + children: [node, createPanel("video")], + }; + replacePanel( + rootPanel, + node.id, + newSplit, + setRootPanel + ); + }} + onClose={() => closePanel(rootPanel, node.id, setRootPanel)} + onChangeType={(newType) => + changePanelType( + rootPanel, + node.id, + newType, + setRootPanel + ) + } + rootPanel={rootPanel} + /> + {node.type === "video" && ( + } initialTopic={Object.keys(messageMap["video"])[0]} /> + )} + {node.type === "pointcloud" && ( + } + tfMessages={messageMap["tf"] as any[]} + initialTopic={Object.keys(messageMap["pointcloud"])[0]} + /> + )} + + ); + }; + + return ( +
+ + {renderPanelNode(rootPanel)} + +
+ ); +}; + +function replacePanel( + root: PanelNode, + targetId: number, + replacement: PanelNode, + setRoot: (r: PanelNode) => void +) { + function helper(node: PanelNode): PanelNode { + if (node.id === targetId) return replacement; + if ("split" in node) { + return { + ...node, + children: node.children.map(helper), + }; + } + return node; + } + const newRoot = helper(root); + setRoot(newRoot); +} + +function closePanel( + root: PanelNode, + targetId: number, + setRoot: (r: PanelNode) => void +) { + function helper(node: PanelNode): PanelNode | null { + if (node.id === targetId) return null; + if ("split" in node) { + const newChildren = node.children + .map(helper) + .filter((child) => child !== null) as PanelNode[]; + return { ...node, children: newChildren }; + } + return node; + } + const newRoot = helper(root); + if (newRoot) setRoot(newRoot); +} + +function changePanelType( + root: PanelNode, + targetId: number, + newType: "video" | "pointcloud" | "text", + setRoot: (r: PanelNode) => void +) { + function helper(node: PanelNode): PanelNode { + if (node.id === targetId) { + return { ...node, type: newType }; + } + if ("split" in node) { + return { + ...node, + children: node.children.map(helper), + }; + } + return node; + } + const newRoot = helper(root); + setRoot(newRoot); +} + +function getNumLeaves(node: PanelNode): number { + if ("split" in node) { + return node.children.reduce( + (sum, child) => sum + getNumLeaves(child), + 0 + ); + } + return 1; +} + +const PanelMenu = ({ + onSplit, + onClose, + onChangeType, + rootPanel, +}: { + onSplit: (dir: "horizontal" | "vertical") => void; + onClose: () => void; + onChangeType: (newType: "video" | "pointcloud") => void; + rootPanel: PanelNode; +}) => { + const [anchorEl, setAnchorEl] = useState(null); + const open = Boolean(anchorEl); + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + const handleClose = () => setAnchorEl(null); + + return ( +
+ + + { + onSplit("horizontal"); + handleClose(); + }} + > + + + + Split Horizontally + + { + onSplit("vertical"); + handleClose(); + }} + > + + + + Split Vertically + + { + onChangeType("video"); + handleClose(); + }} + > + + + + Switch to Video Panel + + { + onChangeType("pointcloud"); + handleClose(); + }} + > + + + + Switch to PointCloud Panel + + {getNumLeaves(rootPanel) > 1 && ( + { + onClose(); + handleClose(); + }} + > + + + + Close Panel + + )} + +
+ ); +}; diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/components/Pedestrian.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/Pedestrian.tsx new file mode 100644 index 000000000..13b3331ad --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/Pedestrian.tsx @@ -0,0 +1,70 @@ +"use client"; + +import React, { useRef, useMemo, useEffect, useState } from "react"; +import { useFrame } from "@react-three/fiber"; +import { + Mesh, + Object3D, + MeshStandardMaterial, + Vector3, + Quaternion, + Euler, +} from "three"; +import { useGLTF } from "@react-three/drei"; +import { FrameData } from "@/types/FrameData"; +import { currentPedestrian } from "@/config/pedestrianConfig"; +import { getInterpolatedFrame } from "@/utils/getInterpolatedFrame"; + +interface PedestrianProps { + id: string; + timeline: FrameData[]; + time: number; +} + +export default function Pedestrian({ id, timeline, time }: PedestrianProps) { + const [mounted, setMounted] = useState(false); + const ref = useRef(null); + + const { modelPath, scale, rotation, offset, bodyColor } = currentPedestrian; + const { scene } = useGLTF(modelPath); + const clonedScene = useMemo(() => scene.clone(true), [scene]); + + const targetPosition = useMemo(() => new Vector3(), []); + const targetQuaternion = useMemo(() => new Quaternion(), []); + + useEffect(() => { + setMounted(true); + }, []); + + useEffect(() => { + clonedScene.traverse((child) => { + if ( + child instanceof Mesh && + child.material instanceof MeshStandardMaterial + ) { + child.material = child.material.clone(); + child.material.color.set(bodyColor); + } + }); + }, [clonedScene, bodyColor]); + + useFrame(() => { + if (!ref.current || timeline.length === 0) return; + const frame = getInterpolatedFrame(timeline, time); + if (!frame) return; + targetPosition.set(frame.x, 0, frame.y); + ref.current.position.lerp(targetPosition, 0.2); + targetQuaternion.setFromEuler(new Euler(0, -frame.yaw, 0)); + ref.current.quaternion.slerp(targetQuaternion, 0.2); + }); + + return ( + } + object={clonedScene} + scale={scale} + rotation={rotation} + position={offset} + /> + ); +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/components/PointCloudPanel.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/PointCloudPanel.tsx new file mode 100644 index 000000000..69e6063b7 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/PointCloudPanel.tsx @@ -0,0 +1,256 @@ +"use client"; + +import React, { useEffect, useRef, useState } from "react"; +import { useScrubber } from "./ScrubberContext"; +import * as THREE from "three"; +import { OrbitControls } from "three-stdlib"; +import { Select, SelectChangeEvent, MenuItem } from "@mui/material"; + +function parsePointCloud2(msg: any): THREE.Points { + const { data, point_step, fields } = msg; + const positions: number[] = []; + const colors: number[] = []; + + const fieldMap = Object.fromEntries( + fields.map((f: any) => [f.name, f.offset]) + ); + const dv = new DataView(data.buffer, data.byteOffset, data.byteLength); + + for (let i = 0; i < data.length; i += point_step) { + const x = dv.getFloat32(i + fieldMap["x"], true); + const y = dv.getFloat32(i + fieldMap["y"], true); + const z = dv.getFloat32(i + fieldMap["z"], true); + + if (!Number.isFinite(x) || !Number.isFinite(y) || !Number.isFinite(z)) + continue; + + positions.push(x, y, z); + + if ("rgba" in fieldMap) { + const rgba = dv.getUint32(i + fieldMap["rgba"], true); + const r = (rgba >> 24) & 0xff; + const g = (rgba >> 16) & 0xff; + const b = (rgba >> 8) & 0xff; + colors.push(r / 255, g / 255, b / 255); + } else if ("rgb" in fieldMap) { + const rgb = dv.getUint32(i + fieldMap["rgb"], true); + const r = (rgb >> 16) & 0xff; + const g = (rgb >> 8) & 0xff; + const b = rgb & 0xff; + colors.push(r / 255, g / 255, b / 255); + } else { + colors.push(1, 1, 1); + } + } + + const geometry = new THREE.BufferGeometry(); + geometry.setAttribute( + "position", + new THREE.Float32BufferAttribute(positions, 3) + ); + geometry.setAttribute("color", new THREE.Float32BufferAttribute(colors, 3)); + const material = new THREE.PointsMaterial({ + size: 0.05, + vertexColors: true, + }); + + return new THREE.Points(geometry, material); +} + +function buildTransformLookup(tfMessages: any[], time: number) { + const latestTransforms = new Map(); + + for (const msg of tfMessages) { + const transforms = msg.data.transforms || []; + for (const t of transforms) { + if (t.header.stamp.sec + t.header.stamp.nsec * 1e-9 < time) + continue; + const key = `${t.header.frame_id}->${t.child_frame_id}`; + if (!latestTransforms.has(key)) { + latestTransforms.set(key, t); + } + } + } + + return latestTransforms; +} + +function getTransformMatrix( + lookup: Map, + from: string, + to: string +): THREE.Matrix4 | null { + const key = `${from}->${to}`; + const tf = lookup.get(key); + if (!tf) return null; + + const { translation, rotation } = tf.transform; + const position = new THREE.Vector3( + translation.x, + translation.y, + translation.z + ); + const quaternion = new THREE.Quaternion( + rotation.x, + rotation.y, + rotation.z, + rotation.w + ); + + const matrix = new THREE.Matrix4(); + matrix.makeRotationFromQuaternion(quaternion); + matrix.setPosition(position); + + return matrix; +} + +export const PointCloudPanel = ({ + messages, + tfMessages, + initialTopic, +}: { + messages: Record; + tfMessages: any[]; + initialTopic?: string; +}) => { + const mountRef = useRef(null); + const { startTime, currentTime } = useScrubber(); + const rendererRef = useRef(null); + const cameraRef = useRef(null); + const sceneRef = useRef(null); + const controlsRef = useRef(null); + const pointCloudRef = useRef(null); + const [selectedTopic, setSelectedTopic] = useState( + initialTopic || Object.keys(messages)[0] || "" + ); + + useEffect(() => { + if (initialTopic && messages[initialTopic]) { + setSelectedTopic(initialTopic); + } + }, [initialTopic]); + + useEffect(() => { + if (!selectedTopic || !messages[selectedTopic]) return; + if (!mountRef.current) return; + + const scene = new THREE.Scene(); + const camera = new THREE.PerspectiveCamera( + 75, + mountRef.current.clientWidth / mountRef.current.clientHeight, + 0.1, + 1000 + ); + camera.position.z = 5; + + const renderer = new THREE.WebGLRenderer({ antialias: true }); + renderer.setSize( + mountRef.current.clientWidth, + mountRef.current.clientHeight + ); + mountRef.current.appendChild(renderer.domElement); + + const controls = new OrbitControls(camera, renderer.domElement); + controls.enableDamping = true; + + sceneRef.current = scene; + cameraRef.current = camera; + rendererRef.current = renderer; + controlsRef.current = controls; + + const animate = () => { + requestAnimationFrame(animate); + controls.update(); + renderer.render(scene, camera); + }; + animate(); + + return () => { + if (rendererRef.current) { + rendererRef.current.dispose(); + const canvas = rendererRef.current.domElement; + canvas.remove(); + } + }; + }, []); + + useEffect(() => { + const scene = sceneRef.current; + if (!scene) return; + + const msg = messages[selectedTopic].find( + (m) => m.timestamp >= startTime + currentTime + ); + if (!msg) return; + + if (pointCloudRef.current) { + scene.remove(pointCloudRef.current); + pointCloudRef.current.geometry.dispose(); + (pointCloudRef.current.material as THREE.Material).dispose(); + } + + const newCloud = parsePointCloud2(msg.data); + pointCloudRef.current = newCloud; + + const transforms = buildTransformLookup( + tfMessages, + currentTime + startTime + ); + const cloudFrame = msg.data.header.frame_id; + const targetFrame = "base_link"; + + const matrix = getTransformMatrix(transforms, cloudFrame, targetFrame); + + if (matrix) { + newCloud.applyMatrix4(matrix); + } + scene.add(newCloud); + }, [startTime, currentTime, messages, tfMessages]); + + useEffect(() => { + if (!mountRef.current || !rendererRef.current || !cameraRef.current) + return; + + const observer = new ResizeObserver(() => { + const width = mountRef.current!.clientWidth; + const height = mountRef.current!.clientHeight; + + rendererRef.current!.setSize(width, height); + cameraRef.current!.aspect = width / height; + cameraRef.current!.updateProjectionMatrix(); + }); + + observer.observe(mountRef.current); + + return () => observer.disconnect(); + }, []); + + return ( +
+
+ +
+
+ ); +}; diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/components/RosbagViewer.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/RosbagViewer.tsx new file mode 100644 index 000000000..a42dd2191 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/RosbagViewer.tsx @@ -0,0 +1,184 @@ +"use client"; + +import React, { useState } from "react"; +import { Bag } from "@foxglove/rosbag"; +import Button from "@mui/material/Button"; +import CloudUploadIcon from "@mui/icons-material/CloudUpload"; +import { styled } from "@mui/material/styles"; +import { ScrubberProvider } from "./ScrubberContext"; +import { Scrubber2 } from "@/components/Scrubber2"; +import { PanelManager } from "./PanelManager"; + +const VisuallyHiddenInput = styled("input")({ + clip: "rect(0 0 0 0)", + clipPath: "inset(50%)", + height: 1, + overflow: "hidden", + position: "absolute", + bottom: 0, + left: 0, + whiteSpace: "nowrap", + width: 1, +}); + +function fileToReader(file: File) { + return { + size: () => file.size, + read: async (offset: number, length: number) => { + const blob = file.slice(offset, offset + length); + const arrayBuffer = await blob.arrayBuffer(); + return new Uint8Array(arrayBuffer); + }, + }; +} + +export default function RosbagViewer() { + const [topics, setTopics] = useState([]); + const [types, setTypes] = useState([]); + const [loading, setLoading] = useState(false); + const [messageMap, setMessageMap] = useState<{ + video: Record; + pointcloud: Record; + tf: any[]; + }>({ + video: {}, + pointcloud: {}, + tf: [], + }); + + const [duration, setDuration] = useState(0); + const [startTime, setStartTime] = useState(0); + + const handleFileUpload = async ( + event: React.ChangeEvent + ) => { + const file = event.target.files?.[0]; + if (!file) return; + + setMessageMap({ + video: {}, + pointcloud: {}, + tf: [], + }); + setLoading(true); + const reader = fileToReader(file); + const bag = new Bag(reader); + await bag.open(); + // console.log("Bag opened:", bag); + const topicNames = Array.from(bag.connections.values()).map( + (conn) => conn.topic + ); + const topicTypes = Array.from(bag.connections.values()).map( + (conn) => conn.type + ); + setTopics(topicNames); + setTypes(topicTypes as string[]); + // console.log("Topics:", topicNames, topicTypes); + + const videoMessages: Record = {}; + const pointcloudMessages: Record = {}; + const tfMessages: any[] = []; + for await (const msg of bag.messageIterator()) { + const entry = { + timestamp: msg.timestamp.sec + msg.timestamp.nsec * 1e-9, + topic: msg.topic, + data: msg.message, + }; + const type = topicTypes[topicNames.indexOf(msg.topic)] as string; + if (type.includes("Image")) { + if (!videoMessages[msg.topic]) videoMessages[msg.topic] = []; + videoMessages[msg.topic].push(entry); + } + if (type.includes("PointCloud2")) { + if (!pointcloudMessages[msg.topic]) + pointcloudMessages[msg.topic] = []; + pointcloudMessages[msg.topic].push(entry); + } + if (type.includes("TFMessage")) tfMessages.push(entry); + } + setLoading(false); + // console.log( + // "Messages parsed:", + // videoMessages, + // pointcloudMessages, + // tfMessages + // ); + setMessageMap({ + video: videoMessages, + pointcloud: pointcloudMessages, + tf: tfMessages, + }); + const getDuration = ( + messagesByTopic: Record + ): number => { + const durations = Object.values(messagesByTopic) + .filter((msgs) => msgs.length > 1) + .map( + (msgs) => + msgs[msgs.length - 1].timestamp - msgs[0].timestamp + ); + return durations.length > 0 ? Math.max(...durations) : 0; + }; + + const getStart = (messagesByTopic: Record): number => { + const starts = Object.values(messagesByTopic) + .filter((msgs) => msgs.length > 0) + .map((msgs) => msgs[0].timestamp); + return starts.length > 0 ? Math.min(...starts) : 0; + }; + + setDuration( + Math.max( + getDuration(videoMessages), + getDuration(pointcloudMessages), + 0 + ) + ); + const videoStart = getStart(videoMessages); + const pointcloudStart = getStart(pointcloudMessages); + setStartTime( + videoStart > 0 && pointcloudStart > 0 + ? Math.min(videoStart, pointcloudStart) + : Math.max(videoStart, pointcloudStart) + ); + }; + + return ( +
+
+
+ +
+
+ + + + + +
+ ); +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/components/Scrubber.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/Scrubber.tsx new file mode 100644 index 000000000..5729d6312 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/Scrubber.tsx @@ -0,0 +1,131 @@ +"use client"; + +import React, { useState } from "react"; +import { IconButton, Slider, Menu, MenuItem } from "@mui/material"; +import PlayArrowIcon from "@mui/icons-material/PlayArrow"; +import PauseIcon from "@mui/icons-material/Pause"; +import SpeedIcon from "@mui/icons-material/Speed"; +import RefreshIcon from "@mui/icons-material/Refresh"; + +export default function Scrubber({ + time, + play, + togglePlay, + restart, + setPlaybackSpeed, + moveToTime, + duration, +}: { + time: number; + play: boolean; + togglePlay: () => void; + restart: () => void; + setPlaybackSpeed: (speed: number) => void; + moveToTime: (time: number) => void; + duration: number; +}) { + const [anchorEl, setAnchorEl] = useState(null); + const [selectedSpeed, setSelectedSpeed] = useState(1); + const [isDragging, setIsDragging] = useState(false); + const speedOptions = [0.5, 1, 1.5, 2, 3]; + const open = Boolean(anchorEl); + + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + const handleClose = () => { + setAnchorEl(null); + }; + const handleMenuItemClick = (speed: number) => { + setSelectedSpeed(speed); + setPlaybackSpeed(speed); + handleClose(); + }; + const handleSliderChange = (_: Event, newValue: number) => { + moveToTime(newValue); + }; + const handleSliderChangeCommitted = () => { + setIsDragging(false); + }; + const formatDuration = (time: number) => { + const minutes = Math.floor(time / 60); + const seconds = Math.floor(time % 60); + return `${minutes < 10 ? "0" : ""}${minutes}:${ + seconds < 10 ? "0" : "" + }${seconds}`; + }; + const handleContextMenu = (event: React.MouseEvent) => { + event.preventDefault(); + }; + + return ( +
+ + {play ? ( + + ) : ( + + )} + + +
+ + {formatDuration(Math.min(time, duration))} + + setIsDragging(true)} + onChangeCommitted={handleSliderChangeCommitted} + /> + + {formatDuration(duration)} + +
+ +
+ + + + + {speedOptions.map((speed) => ( + handleMenuItemClick(speed)} + > + {speed}x + + ))} + + + + + +
+
+ ); +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/components/Scrubber2.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/Scrubber2.tsx new file mode 100644 index 000000000..b26f3ac26 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/Scrubber2.tsx @@ -0,0 +1,170 @@ +"use client"; + +import React, { useEffect, useState } from "react"; +import { useScrubber } from "./ScrubberContext"; +import { IconButton, Slider, Menu, MenuItem } from "@mui/material"; +import PlayArrowIcon from "@mui/icons-material/PlayArrow"; +import PauseIcon from "@mui/icons-material/Pause"; +import SpeedIcon from "@mui/icons-material/Speed"; +import RefreshIcon from "@mui/icons-material/Refresh"; + +export const Scrubber2 = ({ + duration, + startTime, + loading, +}: { + duration: number; + startTime: number; + loading: boolean; +}) => { + const { + setStartTime, + currentTime, + setCurrentTime, + isPlaying, + setIsPlaying, + } = useScrubber(); + const frameRate = 30; + const [anchorEl, setAnchorEl] = useState(null); + const [selectedSpeed, setSelectedSpeed] = useState(1); + const speedOptions = [0.5, 1, 1.5, 2, 3]; + const open = Boolean(anchorEl); + const [isDragging, setIsDragging] = useState(false); + + const handleClick = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + const handleClose = () => { + setAnchorEl(null); + }; + const handleMenuItemClick = (speed: number) => { + setSelectedSpeed(speed); + handleClose(); + }; + const handleSliderChange = (_: Event, newValue: number) => { + setCurrentTime(newValue); + }; + const handleSliderChangeCommitted = () => { + setIsDragging(false); + }; + const togglePlay = () => { + setIsPlaying((prev: boolean) => !prev); + }; + const restart = () => { + setCurrentTime(0); + }; + const formatDuration = (time: number) => { + const minutes = Math.floor(time / 60); + const seconds = Math.floor(time % 60); + return `${minutes < 10 ? "0" : ""}${minutes}:${ + seconds < 10 ? "0" : "" + }${seconds}`; + }; + const handleContextMenu = (event: React.MouseEvent) => { + event.preventDefault(); + }; + useEffect(() => { + if (!isPlaying) return; + const interval = setInterval(() => { + setCurrentTime((prev: number) => + Math.min(prev + (selectedSpeed * frameRate) / 1000, duration) + ); + }, 1000 / frameRate); + return () => clearInterval(interval); + }, [isPlaying, duration, selectedSpeed]); + + useEffect(() => { + setStartTime(startTime); + setCurrentTime(0); + }, [startTime]); + + useEffect(() => { + if (currentTime >= duration) { + setIsPlaying(false); + } + }, [currentTime, duration]); + + useEffect(() => { + if (loading) { + setIsPlaying(false); + } + }, [loading]); + + return ( +
+ + {isPlaying ? ( + + ) : ( + + )} + +
+ + {currentTime < duration + ? formatDuration(currentTime) + : formatDuration(duration)} + + setIsDragging(true)} + onChangeCommitted={handleSliderChangeCommitted} + value={currentTime} + /> + {formatDuration(duration)} +
+
+ + + + + {speedOptions.map((speed) => ( + handleMenuItemClick(speed)} + > + {speed}x + + ))} + + + + +
+
+ ); +}; diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/components/ScrubberContext.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/ScrubberContext.tsx new file mode 100644 index 000000000..180c79356 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/ScrubberContext.tsx @@ -0,0 +1,32 @@ +"use client"; + +import React, { createContext, useContext, useState } from "react"; + +const ScrubberContext = createContext(null); + +export const ScrubberProvider = ({ + children, +}: { + children: React.ReactNode; +}) => { + const [startTime, setStartTime] = useState(0); + const [currentTime, setCurrentTime] = useState(0); + const [isPlaying, setIsPlaying] = useState(false); + + return ( + + {children} + + ); +}; + +export const useScrubber = () => useContext(ScrubberContext); diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/components/TrafficCone.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/TrafficCone.tsx new file mode 100644 index 000000000..e9991414f --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/TrafficCone.tsx @@ -0,0 +1,69 @@ +"use client"; + +import React, { useRef, useMemo, useEffect, useState } from "react"; +import { useFrame } from "@react-three/fiber"; +import { + Mesh, + Object3D, + MeshStandardMaterial, + Vector3, + Quaternion, + Euler, +} from "three"; +import { useGLTF } from "@react-three/drei"; +import { FrameData } from "@/types/FrameData"; +import { currentTrafficCone } from "@/config/trafficConeConfig"; +import { getInterpolatedFrame } from "@/utils/getInterpolatedFrame"; + +interface TrafficConeProps { + id: string; + timeline: FrameData[]; + time: number; +} + +export default function TrafficCone({ id, timeline, time }: TrafficConeProps) { + const [mounted, setMounted] = useState(false); + const ref = useRef(null); + const { modelPath, scale, rotation, offset, bodyColor } = currentTrafficCone; + const { scene } = useGLTF(modelPath); + const clonedScene = useMemo(() => scene.clone(true), [scene]); + + const targetPosition = useMemo(() => new Vector3(), []); + const targetQuaternion = useMemo(() => new Quaternion(), []); + + useEffect(() => { + setMounted(true); + }, []); + + useEffect(() => { + clonedScene.traverse((child) => { + if ( + child instanceof Mesh && + child.material instanceof MeshStandardMaterial + ) { + child.material = child.material.clone(); + child.material.color.set(bodyColor); + } + }); + }, [clonedScene, bodyColor]); + + useFrame(() => { + if (!ref.current || timeline.length === 0) return; + const frame = getInterpolatedFrame(timeline, time); + if (!frame) return; + targetPosition.set(frame.x, frame.z, frame.y); + ref.current.position.lerp(targetPosition, 0.2); + targetQuaternion.setFromEuler(new Euler(0, -frame.yaw, 0)); + ref.current.quaternion.slerp(targetQuaternion, 0.2); + }); + + return ( + } + object={clonedScene} + scale={scale} + rotation={rotation} + position={offset} + /> + ); +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/components/TrafficLight.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/TrafficLight.tsx new file mode 100644 index 000000000..59039ab13 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/TrafficLight.tsx @@ -0,0 +1,73 @@ +"use client"; + +import React, { useRef, useMemo, useEffect, useState } from "react"; +import { useFrame } from "@react-three/fiber"; +import { + Mesh, + Object3D, + MeshStandardMaterial, + Vector3, + Quaternion, + Euler, +} from "three"; +import { useGLTF } from "@react-three/drei"; +import { FrameData } from "@/types/FrameData"; +import { currentTrafficLight } from "@/config/trafficLightConfig"; +import { getInterpolatedFrame } from "@/utils/getInterpolatedFrame"; + +interface TrafficLightProps { + id: string; + timeline: FrameData[]; + time: number; +} + +export default function TrafficLight({ + id, + timeline, + time, +}: TrafficLightProps) { + const [mounted, setMounted] = useState(false); + const ref = useRef(null); + const { modelPath, scale, rotation, offset, bodyColor } = currentTrafficLight; + const { scene } = useGLTF(modelPath); + const clonedScene = useMemo(() => scene.clone(true), [scene]); + + const targetPosition = useMemo(() => new Vector3(), []); + const targetQuaternion = useMemo(() => new Quaternion(), []); + + useEffect(() => { + setMounted(true); + }, []); + + useEffect(() => { + clonedScene.traverse((child) => { + if ( + child instanceof Mesh && + child.material instanceof MeshStandardMaterial + ) { + child.material = child.material.clone(); + child.material.color.set(bodyColor); + } + }); + }, [clonedScene, bodyColor]); + + useFrame(() => { + if (!ref.current || timeline.length === 0) return; + const frame = getInterpolatedFrame(timeline, time); + if (!frame) return; + targetPosition.set(frame.x, frame.z, frame.y); + ref.current.position.lerp(targetPosition, 0.2); + targetQuaternion.setFromEuler(new Euler(0, -frame.yaw, 0)); + ref.current.quaternion.slerp(targetQuaternion, 0.2); + }); + + return ( + } + object={clonedScene} + scale={scale} + rotation={rotation} + position={offset} + /> + ); +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/components/Vehicle.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/Vehicle.tsx new file mode 100644 index 000000000..eb4a24527 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/Vehicle.tsx @@ -0,0 +1,75 @@ +import React, { useRef, useMemo, useEffect } from "react"; +import * as THREE from "three"; +import { useFrame } from "@react-three/fiber"; +import { useCameraController } from "@/hooks/useCameraController"; +import { currentVehicle } from "@/config/vehicleConfig"; +import { FrameData } from "@/types/FrameData"; +import { OrbitControls } from "@react-three/drei"; +import URDFLoader from "urdf-loader"; +import { getInterpolatedFrame } from "@/utils/getInterpolatedFrame"; + +interface VehicleProps { + timeline: FrameData[]; + time: number; +} + +export default function Vehicle({ timeline, time }: VehicleProps) { + const ref = useRef(null); + const vehicleGroup = useRef(new THREE.Group()); + const mode = useCameraController(ref); + + const targetPosition = useMemo(() => new THREE.Vector3(), []); + const targetQuaternion = useMemo(() => new THREE.Quaternion(), []); + + const { modelPath, scale, rotation, offset, bodyColor } = currentVehicle; + + useEffect(() => { + const loader = new URDFLoader(); + + loader.load( + modelPath, + (robot) => { + robot.scale.set(scale[0], scale[1], scale[2]); + robot.rotation.set(rotation[0], rotation[1], rotation[2]); + robot.position.set(offset[0], offset[1], offset[2]); + + robot.traverse((child) => { + if ( + child instanceof THREE.Mesh && + child.material instanceof THREE.MeshStandardMaterial + ) { + child.material = child.material.clone(); + child.material.color.set(bodyColor); + } + }); + + if (vehicleGroup.current) { + vehicleGroup.current.add(robot); + } + }, + undefined, + (error) => { + console.error("URDF loading failed", error); + } + ); + }, [modelPath, scale, rotation, offset, bodyColor]); + + useFrame(() => { + if (!ref.current || timeline.length === 0) return; + const interp = getInterpolatedFrame(timeline, time); + if (!interp) return; + targetPosition.set(interp.x, 0, interp.y); + ref.current.position.lerp(targetPosition, 0.2); + targetQuaternion.setFromEuler(new THREE.Euler(0, -interp.yaw, 0)); + ref.current.quaternion.slerp(targetQuaternion, 0.2); + }); + + return ( + <> + + + + {mode === "free" && } + + ); +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/components/VehicleInfoPanel.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/VehicleInfoPanel.tsx new file mode 100644 index 000000000..72ab56221 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/VehicleInfoPanel.tsx @@ -0,0 +1,95 @@ +"use client"; + +import React, { useState } from "react"; +import { useTimelineStore } from "@/hooks/useTimelineStore"; +import { RxCross2 } from "react-icons/rx"; + +export function VehicleInfoPanel({ time }: { time: number }) { + const [isOpen, setIsOpen] = useState(true); + const frames = useTimelineStore((s) => s.vehicle); + + const toggleOpen = (e?: React.MouseEvent) => { + if (e) e.preventDefault(); + setIsOpen((open) => !open); + }; + + if (frames.length === 0) return null; + + const startTimestamp = frames[0].time; + const currentTimestamp = startTimestamp + time; + const current = frames.filter((f) => f.time <= currentTimestamp).pop(); + + return ( + <> +
+
+

Vehicle State

+ +
+ + {/* Scrollable content */} +
+ {current ? ( +
    + {[ + ["Timestamp", current.time], + ["X", current.x], + ["Y", current.y], + ["Z", current.z], + ["Yaw", current.yaw], + ["Pitch", current.pitch], + ["Roll", current.roll], + ].map(([label, value]) => ( +
  • + {label}: + {value} +
  • + ))} + + {current.metadata && + Object.entries(current.metadata).map(([key, value]) => { + if (typeof value === "object") return null; + return ( +
  • + + {key.replace(/_/g, " ")}: + + + {String(value)} + +
  • + ); + })} +
+ ) : ( +

+ No vehicle data at this time +

+ )} +
+
+ + {!isOpen && ( + + )} + + ); +} \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/components/VideoPanel.tsx b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/VideoPanel.tsx new file mode 100644 index 000000000..69f39f3e4 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/components/VideoPanel.tsx @@ -0,0 +1,354 @@ +"use client"; + +import React, { useEffect, useRef, useState } from "react"; +import { useScrubber } from "./ScrubberContext"; +import { + Switch, + FormControlLabel, + Select, + SelectChangeEvent, + MenuItem, +} from "@mui/material"; + +export function decodeImage(msg: { + encoding: string; + data: Uint8Array; + height: number; + width: number; + step: number; +}): ImageData { + const { encoding, data, height, width, step } = msg; + const rgba = new Uint8ClampedArray(width * height * 4); + + if (encoding === "bgr8") { + for (let i = 0; i < height; i++) { + for (let j = 0; j < width; j++) { + const srcIdx = i * step + j * 3; + const dstIdx = (i * width + j) * 4; + rgba[dstIdx] = data[srcIdx + 2]; + rgba[dstIdx + 1] = data[srcIdx + 1]; + rgba[dstIdx + 2] = data[srcIdx]; + rgba[dstIdx + 3] = 255; + } + } + } else if (encoding === "rgb8") { + for (let i = 0; i < height; i++) { + for (let j = 0; j < width; j++) { + const srcIdx = i * step + j * 3; + const dstIdx = (i * width + j) * 4; + rgba[dstIdx] = data[srcIdx]; + rgba[dstIdx + 1] = data[srcIdx + 1]; + rgba[dstIdx + 2] = data[srcIdx + 2]; + rgba[dstIdx + 3] = 255; + } + } + } else if (encoding === "mono8") { + for (let i = 0; i < height; i++) { + for (let j = 0; j < width; j++) { + const gray = data[i * step + j]; + const dstIdx = (i * width + j) * 4; + rgba[dstIdx] = gray; + rgba[dstIdx + 1] = gray; + rgba[dstIdx + 2] = gray; + rgba[dstIdx + 3] = 255; + } + } + } else if (encoding === "bayer_grbg8") { + const get = (x: number, y: number): number => + x >= 0 && y >= 0 && x < width && y < height + ? data[y * width + x] + : 0; + + for (let y = 0; y < height; y++) { + for (let x = 0; x < width; x++) { + let r = 0, + g = 0, + b = 0; + + const val = get(x, y); + + if (y % 2 === 0) { + if (x % 2 === 0) { + g = val; + r = (get(x - 1, y) + get(x + 1, y)) / 2; + b = (get(x, y - 1) + get(x, y + 1)) / 2; + } else { + r = val; + g = + (get(x - 1, y) + + get(x + 1, y) + + get(x, y - 1) + + get(x, y + 1)) / + 4; + b = + (get(x - 1, y - 1) + + get(x + 1, y - 1) + + get(x - 1, y + 1) + + get(x + 1, y + 1)) / + 4; + } + } else { + if (x % 2 === 0) { + b = val; + g = + (get(x - 1, y) + + get(x + 1, y) + + get(x, y - 1) + + get(x, y + 1)) / + 4; + r = + (get(x - 1, y - 1) + + get(x + 1, y - 1) + + get(x - 1, y + 1) + + get(x + 1, y + 1)) / + 4; + } else { + g = val; + r = (get(x, y - 1) + get(x, y + 1)) / 2; + b = (get(x - 1, y) + get(x + 1, y)) / 2; + } + } + + const i = (y * width + x) * 4; + rgba[i] = r; + rgba[i + 1] = g; + rgba[i + 2] = b; + rgba[i + 3] = 255; + } + } + } else { + throw new Error(`Unsupported encoding: ${encoding}`); + } + + return new ImageData(rgba, width, height); +} + +type VideoPanelProps = { + messages: Record; + initialTopic?: string; +}; + +export const VideoPanel: React.FC = ({ + messages, + initialTopic, +}) => { + const { startTime, currentTime } = useScrubber(); + const canvasRef = useRef(null); + const containerRef = useRef(null); + const imageRef = useRef(null); + + const [enableInteraction, setEnableInteraction] = useState(false); + const [zoom, setZoom] = useState(1); + const [offset, setOffset] = useState({ x: 0, y: 0 }); + const [isDragging, setIsDragging] = useState(false); + const lastMouse = useRef({ x: 0, y: 0 }); + const [selectedTopic, setSelectedTopic] = useState( + initialTopic || Object.keys(messages)[0] || "" + ); + + useEffect(() => { + if (initialTopic && messages[initialTopic]) { + setSelectedTopic(initialTopic); + } + }, [initialTopic]); + + useEffect(() => { + if (!selectedTopic || !messages[selectedTopic]) return; + const msg = messages[selectedTopic].find( + (m) => m.timestamp >= startTime + currentTime + ); + if (!msg || !msg.data) return; + + const canvas = canvasRef.current; + const ctx = canvas?.getContext("2d"); + + try { + const imageData = decodeImage(msg.data); + imageRef.current = imageData; + + if (!enableInteraction) { + if (canvas && ctx) { + canvas.width = imageData.width; + canvas.height = imageData.height; + ctx.putImageData(imageData, 0, 0); + } + } else { + drawImage(); + } + } catch (e) { + console.error("Failed to decode image:", e); + } + }, [messages, currentTime, enableInteraction]); + + const drawImage = () => { + requestAnimationFrame(() => { + const canvas = canvasRef.current; + const ctx = canvas?.getContext("2d"); + const imageData = imageRef.current; + if (!canvas || !ctx || !imageData) return; + + const { width: cw, height: ch } = canvas; + ctx.clearRect(0, 0, cw, ch); + + const imgAspect = imageData.width / imageData.height; + const canvasAspect = cw / ch; + + let drawW = imageData.width * zoom; + let drawH = imageData.height * zoom; + + if (imgAspect > canvasAspect) { + drawW = cw * zoom; + drawH = drawW / imgAspect; + } else { + drawH = ch * zoom; + drawW = drawH * imgAspect; + } + + const drawX = (cw - drawW) / 2 + offset.x; + const drawY = (ch - drawH) / 2 + offset.y; + + const offscreen = document.createElement("canvas"); + offscreen.width = imageData.width; + offscreen.height = imageData.height; + offscreen.getContext("2d")?.putImageData(imageData, 0, 0); + + ctx.drawImage(offscreen, drawX, drawY, drawW, drawH); + }); + }; + + useEffect(() => { + if (!enableInteraction) return; + + const container = containerRef.current; + if (!container) return; + + const handleWheel = (e: WheelEvent) => { + e.preventDefault(); + const zoomDelta = -e.deltaY * 0.001; + setZoom((z) => Math.min(Math.max(z + zoomDelta, 0.1), 10)); + }; + + container.addEventListener("wheel", handleWheel, { passive: false }); + return () => container.removeEventListener("wheel", handleWheel); + }, [enableInteraction]); + + useEffect(() => { + if (!enableInteraction) return; + drawImage(); + }, [zoom, offset, enableInteraction]); + + useEffect(() => { + const handleResize = () => { + const container = containerRef.current; + const canvas = canvasRef.current; + if (container && canvas) { + canvas.width = container.clientWidth; + canvas.height = container.clientHeight; + if (enableInteraction) drawImage(); + } + }; + + window.addEventListener("resize", handleResize); + handleResize(); + return () => window.removeEventListener("resize", handleResize); + }, [enableInteraction]); + + useEffect(() => { + if (!enableInteraction) { + setZoom(1); + setOffset({ x: 0, y: 0 }); + } + }, [enableInteraction]); + + const handleMouseDown = (e: React.MouseEvent) => { + if (!enableInteraction) return; + setIsDragging(true); + lastMouse.current = { x: e.clientX, y: e.clientY }; + }; + + const handleMouseMove = (e: React.MouseEvent) => { + if (!enableInteraction || !isDragging) return; + const dx = e.clientX - lastMouse.current.x; + const dy = e.clientY - lastMouse.current.y; + lastMouse.current = { x: e.clientX, y: e.clientY }; + setOffset((prev) => ({ x: prev.x + dx, y: prev.y + dy })); + }; + + const handleMouseUp = () => { + if (!enableInteraction) return; + setIsDragging(false); + }; + + return ( +
+
+ +
+
+ + setEnableInteraction(e.target.checked) + } + /> + } + sx={{ + backgroundColor: "white", + opacity: 0.25, + borderRadius: "9999px", + paddingRight: "10px", + "&:hover": { + opacity: 0.5, + }, + }} + /> +
+ + +
+ ); +}; diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/config/cameraConfig.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/config/cameraConfig.ts new file mode 100644 index 000000000..ae017432c --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/config/cameraConfig.ts @@ -0,0 +1,35 @@ +type CameraConfig = { + position: [number, number, number]; + lookAt: [number, number, number]; + damping?: number; +}; + +type CameraConfigMap = { + [key in 'first' | 'chase' | 'top' | 'side' | 'free']: Partial; +}; + +const cameraConfig: CameraConfigMap = { + first: { + position: [0, 1.5, 0], + lookAt: [10, 2, 0], + damping: 0.1, + }, + chase: { + position: [-6, 3, 0], + lookAt: [0, 0, 0], + damping: 0.1, + }, + top: { + position: [0, 10, 0], + lookAt: [0, 0, 0], + damping: 0.1, + }, + side: { + position: [0, 2, 5], + lookAt: [0, 0, -10], + damping: 0.1, + }, + free: {}, +}; + +export { cameraConfig }; diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/config/groundConfig.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/config/groundConfig.ts new file mode 100644 index 000000000..914fc6362 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/config/groundConfig.ts @@ -0,0 +1,32 @@ +export interface GroundConfig { + size: [number, number]; + position: [number, number, number]; + rotation: [number, number, number]; + cellSize: number; + cellThickness: number; + cellColor: string; + sectionSize: number; + sectionThickness: number; + sectionColor: string; + fadeDistance: number; + fadeStrength: number; + infiniteGrid: boolean; +} + +const groundConfig: GroundConfig = { + size: [1000, 1000], + position: [0, 0, 0], + rotation: [0, 0, 0], + cellSize: 2, + cellThickness: 0.5, + cellColor: "#222222", + sectionSize: 10, + sectionThickness: 1, + sectionColor: "#444444", + fadeDistance: 1500, + fadeStrength: 0, + infiniteGrid: false, +}; + + +export { groundConfig }; \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/config/otherVehicleConfig.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/config/otherVehicleConfig.ts new file mode 100644 index 000000000..2296e26d0 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/config/otherVehicleConfig.ts @@ -0,0 +1,14 @@ +const otherVehicleConfig = { + car: { + name: "Car", + modelPath: "/models/model/gem_e2.urdf", + scale: [1, 1, 1], + rotation: [-Math.PI / 2, 0, 0], + offset: [0, 0, 0], + bodyColor: "#808080", + }, +}; + +const currentOtherVehicle = otherVehicleConfig.car; + +export { otherVehicleConfig, currentOtherVehicle }; diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/config/pedestrianConfig.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/config/pedestrianConfig.ts new file mode 100644 index 000000000..57030e97d --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/config/pedestrianConfig.ts @@ -0,0 +1,14 @@ +const pedestrianConfig = { + pedestrian: { + name: "Pedestrian", + modelPath: "/models/pedestrian.glb", + scale: [0.2, 0.2, 0.2], + rotation: [0, Math.PI, 0], + offset: [0, 0, 0], + bodyColor: "#808080", + } +}; + +const currentPedestrian = pedestrianConfig.pedestrian; + +export { pedestrianConfig, currentPedestrian }; \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/config/trafficConeConfig.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/config/trafficConeConfig.ts new file mode 100644 index 000000000..76a1e6479 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/config/trafficConeConfig.ts @@ -0,0 +1,14 @@ +const trafficConeConfig = { + trafficCone: { + name: "Traffic Cone", + modelPath: "/models/traffic_cone.glb", + scale: [0.03, 0.03, 0.03], + rotation: [0, 0, 0], + offset: [0, 0, 0], + bodyColor: "#FFFFFF", + }, +}; + +const currentTrafficCone = trafficConeConfig.trafficCone; + +export { trafficConeConfig, currentTrafficCone }; diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/config/trafficLightConfig.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/config/trafficLightConfig.ts new file mode 100644 index 000000000..ef86a63ee --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/config/trafficLightConfig.ts @@ -0,0 +1,14 @@ +const trafficLightConfig = { + trafficLight: { + name: "Traffic Light", + modelPath: "/models/traffic_light.glb", + scale: [0.03, 0.03, 0.03], + rotation: [0, 0, 0], + offset: [0, 0, 0], + bodyColor: "#FFD700", + }, +}; + +const currentTrafficLight = trafficLightConfig.trafficLight; + +export { trafficLightConfig, currentTrafficLight }; diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/config/vehicleConfig.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/config/vehicleConfig.ts new file mode 100644 index 000000000..a23435ad0 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/config/vehicleConfig.ts @@ -0,0 +1,14 @@ +const vehicles = { + gemE4: { + name: "Gem E4", + modelPath: "/models/model/gem_e4.urdf", + scale: [1, 1, 1], + rotation: [-Math.PI / 2, 0, 0], + offset: [0, 0, 0], + bodyColor: "#808080", + } +}; + +const currentVehicle = vehicles.gemE4; + +export { vehicles, currentVehicle }; diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/hooks/useCameraController.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/hooks/useCameraController.ts new file mode 100644 index 000000000..326cef297 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/hooks/useCameraController.ts @@ -0,0 +1,86 @@ +"use client"; + +import { useEffect, useState, useRef } from "react"; +import { useThree, useFrame } from "@react-three/fiber"; +import * as THREE from "three"; +import { cameraConfig } from "@/config/cameraConfig"; + +type CameraModeKey = "chase" | "top" | "side" | "free" | "first"; + +export function useCameraController( + carRef: React.RefObject +): CameraModeKey { + const { camera, gl } = useThree(); + const [mode, setMode] = useState("chase"); + const lastMode = useRef("chase"); + const modeRef = useRef("chase"); + + const smoothedPos = useRef(new THREE.Vector3()); + const smoothedLookAt = useRef(new THREE.Vector3()); + + useEffect(() => { modeRef.current = mode; }, [mode]); + + useEffect(() => { + const handleKey = (e: KeyboardEvent) => { + switch (e.key) { + case "1": setMode("first"); break; + case "2": setMode("chase"); break; + case "3": setMode("top"); break; + case "4": setMode("side"); break; + case "5": lastMode.current = modeRef.current; setMode("free"); break; + case "0": if (lastMode.current !== "free") setMode(lastMode.current); break; + } + }; + window.addEventListener("keydown", handleKey); + return () => window.removeEventListener("keydown", handleKey); + }, []); + + useEffect(() => { + const dom = gl.domElement; + const activateFree = () => { + if (modeRef.current !== "free") { + lastMode.current = modeRef.current; + setMode("free"); + } + }; + const onMouseDown = (e: MouseEvent) => { if (e.button === 0) activateFree(); }; + const onWheel = () => activateFree(); + + dom.addEventListener("mousedown", onMouseDown); + dom.addEventListener("wheel", onWheel); + return () => { + dom.removeEventListener("mousedown", onMouseDown); + dom.removeEventListener("wheel", onWheel); + }; + }, [gl.domElement]); + + useFrame((_, delta) => { + if (modeRef.current === "free" || !carRef.current) return; + + const config = cameraConfig[modeRef.current]; + if (!config) return; + + const alpha = 1 - Math.exp(-10.0 * delta); + + const carPos = new THREE.Vector3(); + carRef.current.getWorldPosition(carPos); + const carQuat = new THREE.Quaternion(); + carRef.current.getWorldQuaternion(carQuat); + + const [px, py, pz] = config.position ?? [0, 0, 0]; + const camTargetPos = carPos.clone().add( + new THREE.Vector3(px, py, pz).applyQuaternion(carQuat) + ); + smoothedPos.current.lerp(camTargetPos, alpha); + camera.position.copy(smoothedPos.current); + + const [lx, ly, lz] = config.lookAt ?? [0, 0, 0]; + const camLookAt = carPos.clone().add( + new THREE.Vector3(lx, ly, lz).applyQuaternion(carQuat) + ); + smoothedLookAt.current.lerp(camLookAt, alpha); + camera.lookAt(smoothedLookAt.current); + }); + + return mode; +} \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/hooks/usePlaybackTime.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/hooks/usePlaybackTime.ts new file mode 100644 index 000000000..95843bb0f --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/hooks/usePlaybackTime.ts @@ -0,0 +1,61 @@ +import { useEffect, useRef, useState } from "react"; + +export function usePlaybackTime() { + const [time, setTime] = useState(0); + const [play, setPlay] = useState(true); + const [speed, setSpeed] = useState(1); + const [duration, setDuration] = useState(0); + + const lastFrame = useRef(performance.now()); + + const reset = () => { + lastFrame.current = performance.now(); + setTime(0); + setDuration(0); + setPlay(true); + }; + + const restart = () => { + lastFrame.current = performance.now(); + setTime(0); + setPlay(true); + } + + const togglePlay = () => { + setPlay((prev) => { + if (!prev) lastFrame.current = performance.now(); + return !prev; + }); + }; + + const setPlaybackSpeed = (newSpeed: number) => { + if (newSpeed <= 0) return; + setSpeed(newSpeed); + }; + + const moveToTime = (targetTime: number) => { + setTime(targetTime); + lastFrame.current = performance.now(); + } + + useEffect(() => { + let rafId: number; + + const loop = () => { + rafId = requestAnimationFrame(loop); + + if (!play) return; + + const now = performance.now(); + const delta = (now - lastFrame.current) / 1000; + lastFrame.current = now; + + setTime((t) => t + delta * speed); + }; + + rafId = requestAnimationFrame(loop); + return () => cancelAnimationFrame(rafId); + }, [play, speed]); + + return { time, reset, restart, play, setPlay, togglePlay, speed, setPlaybackSpeed, moveToTime, duration, setDuration }; +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/hooks/useTimelineStore.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/hooks/useTimelineStore.ts new file mode 100644 index 000000000..ba371de9e --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/hooks/useTimelineStore.ts @@ -0,0 +1,11 @@ +import { TimelineStore } from '@/types/TimelineStore'; +import { create } from 'zustand'; + +export const useTimelineStore = create((set) => ({ + vehicle: [], + pedestrians: {}, + trafficLights: {}, + trafficCones: {}, + otherVehicles: {}, + setTimeline: (timeline) => set(timeline), +})); diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/hooks/useVehicleControls.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/hooks/useVehicleControls.ts new file mode 100644 index 000000000..27eccfc5f --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/hooks/useVehicleControls.ts @@ -0,0 +1,67 @@ +import { useEffect, useState, useRef } from 'react'; +import { Group, Vector3, Euler } from 'three'; +import { useFrame } from '@react-three/fiber'; + +export function useVehicleControls( + groupRef: React.RefObject, + getSpeed: () => number = () => 1 +) { + const [keys, setKeys] = useState<{ [key: string]: boolean }>({}); + const targetPosition = useRef(new Vector3()); + const targetRotation = useRef(new Euler()); + + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => + setKeys((k) => ({ ...k, [e.key.toLowerCase()]: true })); + const handleKeyUp = (e: KeyboardEvent) => + setKeys((k) => ({ ...k, [e.key.toLowerCase()]: false })); + + window.addEventListener('keydown', handleKeyDown); + window.addEventListener('keyup', handleKeyUp); + return () => { + window.removeEventListener('keydown', handleKeyDown); + window.removeEventListener('keyup', handleKeyUp); + }; + }, []); + + const state = { moving: false, direction: 0 }; + + useFrame((_, delta) => { + if (!groupRef.current) return; + + const group = groupRef.current; + const speed = getSpeed(); + const moveDir = new Vector3(); + const currentRotation = group.rotation.clone(); + + state.moving = false; + + const forward = new Vector3(1, 0, 0).applyEuler(currentRotation); + + if (keys['w']) { + moveDir.add(forward); + state.moving = true; + state.direction = 1; + } + if (keys['s']) { + moveDir.sub(forward); + state.moving = true; + state.direction = -1; + } + + moveDir.normalize().multiplyScalar(speed * delta); + targetPosition.current.add(moveDir); + + const steerAmount = 1.5 * delta * (keys['s'] ? -1 : 1); + if (keys['a']) targetRotation.current.y += steerAmount; + if (keys['d']) targetRotation.current.y -= steerAmount; + + // Smooth rotation + group.rotation.y += (targetRotation.current.y - group.rotation.y) * 0.2; + + // Smooth position + group.position.lerp(targetPosition.current, 0.2); + }); + + return state; +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/types/FrameData.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/types/FrameData.ts new file mode 100644 index 000000000..8e9442962 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/types/FrameData.ts @@ -0,0 +1,10 @@ +export interface FrameData { + time: number; + x: number; + y: number; + z: number; + yaw: number; + pitch: number; + roll: number; + metadata?: Record; +} \ No newline at end of file diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/types/LogEntry.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/types/LogEntry.ts new file mode 100644 index 000000000..15b88b363 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/types/LogEntry.ts @@ -0,0 +1,7 @@ +export interface LogEntry { + key: string; // Top-level key (e.g., "vehicle", "agents", etc.) + type: string; // Inner type (e.g., "VehicleState") + time: number; // Timestamp of the event + data: T; // Full data object (includes pose, velocity, etc.) +} + diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/types/TimelineData.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/types/TimelineData.ts new file mode 100644 index 000000000..8db52b621 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/types/TimelineData.ts @@ -0,0 +1,9 @@ +import { FrameData } from './FrameData'; + +export interface TimelineData { + vehicle: FrameData[]; + pedestrians: Record; + trafficLights: Record; + trafficCones: Record; + otherVehicles: Record; +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/types/TimelineStore.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/types/TimelineStore.ts new file mode 100644 index 000000000..ed2341de9 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/types/TimelineStore.ts @@ -0,0 +1,5 @@ +import { TimelineData } from './TimelineData'; + +export interface TimelineStore extends TimelineData { + setTimeline: (timeline: TimelineData) => void; +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/utils/buildTimeline.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/utils/buildTimeline.ts new file mode 100644 index 000000000..536c6e896 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/utils/buildTimeline.ts @@ -0,0 +1,49 @@ +import { LogEntry } from "@/types/LogEntry"; +import { FrameData } from "@/types/FrameData"; +import { TimelineData } from "@/types/TimelineData"; + +export function buildTimeline(entries: LogEntry[]): TimelineData { + const vehicle: FrameData[] = []; + const pedestrians: Record = {}; + const trafficLights: Record = {}; + const trafficCones: Record = {}; + const otherVehicles: Record = {}; + + for (const entry of entries) { + const pose = entry.data?.pose; + if (!pose || typeof pose.x !== "number" || typeof pose.y !== "number") continue; + + const frame: FrameData = { + time: entry.time, + x: pose.x ?? 0, + y: pose.y ?? 0, + z: pose.z ?? 0, + yaw: pose.yaw ?? 0, + pitch: pose.pitch ?? 0, + roll: pose.roll ?? 0, + metadata: entry.type === "VehicleState" ? { ...entry.data } : undefined, + }; + + if (entry.type === "VehicleState") { + vehicle.push(frame); + } else if (entry.type === "PedestrianState") { + const key = entry.key.trim(); + if (!pedestrians[key]) pedestrians[key] = []; + pedestrians[key].push(frame); + } else if (entry.type === "TrafficLightState") { + const key = entry.key.trim(); + if (!trafficLights[key]) trafficLights[key] = []; + trafficLights[key].push(frame); + } else if (entry.type === "TrafficConeState") { + const key = entry.key.trim(); + if (!trafficCones[key]) trafficCones[key] = []; + trafficCones[key].push(frame); + } else if (entry.type === "OtherVehicleState") { + const key = entry.key.trim(); + if (!otherVehicles[key]) otherVehicles[key] = []; + otherVehicles[key].push(frame); + } + } + + return { vehicle, pedestrians, trafficLights, trafficCones, otherVehicles }; +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/utils/getInterpolatedFrame.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/utils/getInterpolatedFrame.ts new file mode 100644 index 000000000..cc38d019e --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/utils/getInterpolatedFrame.ts @@ -0,0 +1,30 @@ +import { FrameData } from "@/types/FrameData"; + +export function getInterpolatedFrame(frames: FrameData[], t: number): FrameData | null { + if (frames.length === 0) return null; + // If before first or after last, clamp + if (t <= frames[0].time) return frames[0]; + if (t >= frames[frames.length - 1].time) return frames[frames.length - 1]; + + // binary search for the first frame with time > t + let lo = 0, hi = frames.length - 1; + while (lo < hi) { + const mid = Math.floor((lo + hi) / 2); + if (frames[mid].time > t) hi = mid; + else lo = mid + 1; + } + const b = frames[lo]; + const a = frames[lo - 1]; + + const α = (t - a.time) / (b.time - a.time); + return { + time: t, + x: a.x * (1 - α) + b.x * α, + y: a.y * (1 - α) + b.y * α, + z: a.z * (1 - α) + b.z * α, + yaw: a.yaw * (1 - α) + b.yaw * α, + pitch: a.pitch * (1 - α) + b.pitch * α, + roll: a.roll * (1 - α) + b.roll * α, + metadata: a.metadata, // or merge if needed + }; +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/utils/parseLogFile.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/utils/parseLogFile.ts new file mode 100644 index 000000000..cd7887aec --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/utils/parseLogFile.ts @@ -0,0 +1,66 @@ +import { LogEntry } from '../types/LogEntry'; +import { streamLogLines } from './streamLogLines'; + +export async function parseLogFile(file: File): Promise { + const entries: LogEntry[] = []; + + for await (const line of streamLogLines(file)) { + try { + const parsed = JSON.parse(line); + const time = parsed.time; + + for (const [key, value] of Object.entries(parsed)) { + if (key === 'time' || typeof value !== 'object' || value === null) continue; + + // Main vehicle (frame 2) + if ( + key === 'vehicle' && + 'type' in value && + 'data' in value && + (value as any).type === "VehicleState" + ) { + entries.push({ + key, + type: (value as any).type, + time, + data: (value as any).data, + }); + continue; + } + + // Unified agents (pedestrians, lights, cones, others) — frame 0 only + if (key === 'agents') { + for (const [agentId, agentValue] of Object.entries(value)) { + if ( + typeof agentValue === 'object' && + agentValue !== null && + 'data' in agentValue && + (agentValue as any).type === 'AgentState' + ) { + const inferredType = getTypeFromKey(agentId); + entries.push({ + key: agentId, + type: inferredType, + time, + data: (agentValue as any).data, + }); + } + } + } + } + } catch (err) { + console.warn('Failed to parse log line:', err); + } + } + + return entries; +} + +function getTypeFromKey(key: string): string { + const lowerKey = key.toLowerCase(); + if (lowerKey.startsWith('pedestrian')) return 'PedestrianState'; + if (lowerKey.startsWith('vehicle')) return 'OtherVehicleState'; + if (lowerKey.startsWith('light')) return 'TrafficLightState'; + if (lowerKey.startsWith('cone')) return 'TrafficConeState'; + return 'UnknownState'; +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/src/utils/streamLogLines.ts b/GEMstack/onboard/visualization/sr_viz/threeD/src/utils/streamLogLines.ts new file mode 100644 index 000000000..d4c0c5ba8 --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/src/utils/streamLogLines.ts @@ -0,0 +1,20 @@ +export async function* streamLogLines(file: File): AsyncGenerator { + const reader = file.stream().getReader(); + const decoder = new TextDecoder('utf-8'); + let partial = ''; + + while (true) { + const { value, done } = await reader.read(); + if (done) break; + + partial += decoder.decode(value, { stream: true }); + const lines = partial.split('\n'); + partial = lines.pop() || ''; + + for (const line of lines) { + if (line.trim()) yield line; + } + } + + if (partial.trim()) yield partial; +} diff --git a/GEMstack/onboard/visualization/sr_viz/threeD/tsconfig.json b/GEMstack/onboard/visualization/sr_viz/threeD/tsconfig.json new file mode 100644 index 000000000..c1334095f --- /dev/null +++ b/GEMstack/onboard/visualization/sr_viz/threeD/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/log_dashboard/app.py b/log_dashboard/app.py index 3258d9cbd..7e2178b06 100644 --- a/log_dashboard/app.py +++ b/log_dashboard/app.py @@ -9,179 +9,228 @@ import numpy as np import platform import matplotlib +from flask import Response, stream_with_context +from flask_cors import CORS + # Use the 'Agg' backend which is thread-safe and doesn't require a GUI -matplotlib.use('Agg') +matplotlib.use("Agg") import matplotlib.pyplot as plt + app = Flask(__name__) +CORS(app) +CORS(app, origins=["http://localhost:3000"]) + # Configure cache cache = SimpleCache(threshold=500, default_timeout=300) # 5 minutes cache timeout -LOG_DIR = '../logs' +LOG_DIR = "../logs" + def generate_behavior_plots(log_folder, behavior_file, target_frame=3): """ Generate a comprehensive visualization plot for vehicle, agents, and trajectory - + Args: log_folder (str): Name of the log folder behavior_file (str): Path to the behavior.json file target_frame (int, optional): Specific frame to filter data. Defaults to None. - + Returns: dict: Paths to generated plot files """ target_frame = 3 # Define output plot directory - plot_dir = os.path.join('./plots', log_folder, 'viz') + plot_dir = os.path.join("./plots", log_folder, "viz") os.makedirs(plot_dir, exist_ok=True) - + # Create cache file to track previous plot generation - cache_file = os.path.join(plot_dir, f'plot_cache_frame_{target_frame}.json') - + cache_file = os.path.join(plot_dir, f"plot_cache_frame_{target_frame}.json") + # Check if plots have been previously generated if os.path.exists(cache_file): - with open(cache_file, 'r') as f: + with open(cache_file, "r") as f: return json.load(f) - + + # Initialize data collections vehicle_data = [] agent_data = {} trajectory_data = [] - + # Parse behavior file - with open(behavior_file, 'r') as f: + with open(behavior_file, "r") as f: for line in f: try: entry = json.loads(line.strip()) - + # Vehicle state - if 'vehicle' in entry and 'data' in entry['vehicle']: - vehicle_state = entry['vehicle']['data']['pose'] + if "vehicle" in entry and "data" in entry["vehicle"]: + vehicle_state = entry["vehicle"]["data"]["pose"] # Check frame filter if specified - if target_frame is None or vehicle_state.get('frame') == target_frame: - vehicle_data.append({ - 'time': entry['time'], - 'x': vehicle_state.get('x', 0), - 'y': vehicle_state.get('y', 0), - 'frame': vehicle_state.get('frame') - }) - + if ( + target_frame is None + or vehicle_state.get("frame") == target_frame + ): + vehicle_data.append( + { + "time": entry["time"], + "x": vehicle_state.get("x", 0), + "y": vehicle_state.get("y", 0), + "frame": vehicle_state.get("frame"), + } + ) + # Agent states - if 'agents' in entry: - for agent_name, agent_info in entry['agents'].items(): - agent_state = agent_info['data']['pose'] + if "agents" in entry: + for agent_name, agent_info in entry["agents"].items(): + agent_state = agent_info["data"]["pose"] # Check frame filter if specified - if target_frame is None or agent_state.get('frame') == target_frame: + if ( + target_frame is None + or agent_state.get("frame") == target_frame + ): if agent_name not in agent_data: agent_data[agent_name] = [] - - agent_data[agent_name].append({ - 'time': entry['time'], - 'x': agent_state.get('x', 0), - 'y': agent_state.get('y', 0), - 'frame': agent_state.get('frame') - }) - + + agent_data[agent_name].append( + { + "time": entry["time"], + "x": agent_state.get("x", 0), + "y": agent_state.get("y", 0), + "frame": agent_state.get("frame"), + } + ) + # Trajectory - if 'trajectory' in entry and 'data' in entry['trajectory']: - traj_points = entry['trajectory']['data']['points'] - traj_times = entry['trajectory']['data']['times'] - traj_frames = entry['trajectory']['data'].get('frames', [None] * len(traj_points)) - + if "trajectory" in entry and "data" in entry["trajectory"]: + traj_points = entry["trajectory"]["data"]["points"] + traj_times = entry["trajectory"]["data"]["times"] + traj_frames = entry["trajectory"]["data"].get( + "frames", [None] * len(traj_points) + ) + trajectory_data = [ - {'x': point[0], 'y': point[1], 'time': time, 'frame': frame} - for point, time, frame in zip(traj_points, traj_times, traj_frames) + {"x": point[0], "y": point[1], "time": time, "frame": frame} + for point, time, frame in zip( + traj_points, traj_times, traj_frames + ) if target_frame is None or frame == target_frame ] - + except json.JSONDecodeError: continue - + # Comprehensive Plot plt.figure(figsize=(12, 8)) - + # Plot vehicle trajectory if vehicle_data: - vehicle_xs = [v['x'] for v in vehicle_data] - vehicle_ys = [v['y'] for v in vehicle_data] - plt.plot(vehicle_xs, vehicle_ys, label='Vehicle Path', color='red', linewidth=3, marker='o', markersize=5) - + vehicle_xs = [v["x"] for v in vehicle_data] + vehicle_ys = [v["y"] for v in vehicle_data] + plt.plot( + vehicle_xs, + vehicle_ys, + label="Vehicle Path", + color="red", + linewidth=3, + marker="o", + markersize=5, + ) + # Plot agent trajectories for agent_name, positions in agent_data.items(): - agent_xs = [a['x'] for a in positions] - agent_ys = [a['y'] for a in positions] - plt.plot(agent_xs, agent_ys, label=agent_name, marker='x') - + agent_xs = [a["x"] for a in positions] + agent_ys = [a["y"] for a in positions] + plt.plot(agent_xs, agent_ys, label=agent_name, marker="x") + # Plot planned trajectory if trajectory_data: - traj_xs = [t['x'] for t in trajectory_data] - traj_ys = [t['y'] for t in trajectory_data] - plt.plot(traj_xs, traj_ys, label='Planned Trajectory', color='green', linestyle='--', linewidth=2) - - plt.title(f'Comprehensive Movement Visualization (Frame {target_frame})') - plt.xlabel('X Position') - plt.ylabel('Y Position') + traj_xs = [t["x"] for t in trajectory_data] + traj_ys = [t["y"] for t in trajectory_data] + plt.plot( + traj_xs, + traj_ys, + label="Planned Trajectory", + color="green", + linestyle="--", + linewidth=2, + ) + + plt.title(f"Comprehensive Movement Visualization (Frame {target_frame})") + plt.xlabel("X Position") + plt.ylabel("Y Position") plt.legend() - plt.grid(True, linestyle='--', alpha=0.7) - + plt.grid(True, linestyle="--", alpha=0.7) + # Save the plot - plot_path = os.path.join(plot_dir, f'comprehensive_trajectory_frame_{target_frame}.png') - plt.savefig(plot_path, dpi=300, bbox_inches='tight') + plot_path = os.path.join( + plot_dir, f"comprehensive_trajectory_frame_{target_frame}.png" + ) + plt.savefig(plot_path, dpi=300, bbox_inches="tight") plt.close() - + # Cache plot file paths - plot_files = {'comprehensive': plot_path} - with open(cache_file, 'w') as f: + plot_files = {"comprehensive": plot_path} + with open(cache_file, "w") as f: json.dump(plot_files, f) - + return plot_files -@app.route('/view_log//render') + +@app.route("/view_log//render") + def render_vis_html(log_folder): print(f"Rendering visualization HTML for log folder: {log_folder}") return render_template("render.html", log_folder=log_folder) -@app.route('/view_log//get_render') + +@app.route("/view_log//get_render") def render_behavior_visualization(log_folder): """ Render behavior visualization for a specific log folder - + + Returns: JSON response with plot file paths """ log_folder_path = os.path.join(LOG_DIR, log_folder) - + # Find behavior.json file - behavior_files = [f for f in os.listdir(log_folder_path) if f == 'behavior.json'] - + behavior_files = [f for f in os.listdir(log_folder_path) if f == "behavior.json"] + if not behavior_files: - return jsonify({'error': 'No behavior.json file found'}), 404 - + return jsonify({"error": "No behavior.json file found"}), 404 + behavior_file_path = os.path.join(log_folder_path, behavior_files[0]) - + # Get frame from query parameter, default to None if not specified - target_frame = request.args.get('frame', type=int) - + target_frame = request.args.get("frame", type=int) + try: # Generate behavior plots - plot_files = generate_behavior_plots(log_folder, behavior_file_path, target_frame) + plot_files = generate_behavior_plots( + log_folder, behavior_file_path, target_frame + ) print(plot_files) # return jsonify(plot_files) # return render_template("render.html", image_path=plot_files) - return send_file(plot_files['comprehensive'], mimetype='image/png') - + return send_file(plot_files["comprehensive"], mimetype="image/png") + except Exception as e: - return jsonify({'error': str(e)}), 500 + return jsonify({"error": str(e)}), 500 + # Add a route to serve plot files -@app.route('/plots//viz/') +@app.route("/plots//viz/") + def serve_plot(log_folder, filename): """ Serve plot files from the plots directory """ - plot_dir = os.path.join('./plots', log_folder, 'viz') + plot_dir = os.path.join("./plots", log_folder, "viz") + return send_file(os.path.join(plot_dir, filename)) @@ -189,10 +238,12 @@ def get_cache_key(prefix, *args): """Generate a cache key with a prefix and arguments""" return f"{prefix}_{hash(str(args))}" + def parse_behavior_data(file_path): """ Parse behavior.json file and extract vehicle and agent positions - + + Returns: { 'vehicle': [{'time': float, 'x': float, 'y': float}, ...], @@ -204,86 +255,96 @@ def parse_behavior_data(file_path): } """ try: - with open(file_path, 'r') as f: + with open(file_path, "r") as f: # Read file line by line to handle large files - positions = { - 'vehicle': [], - 'agents': {} - } - + positions = {"vehicle": [], "agents": {}} + for line in f: try: entry = json.loads(line.strip()) - + # Process Vehicle State - if 'vehicle' in entry: - vehicle_data = entry['vehicle']['data']['pose'] - positions['vehicle'].append({ - 'time': entry['time'], - 'x': vehicle_data.get('x', 0), - 'y': vehicle_data.get('y', 0) - }) - + if "vehicle" in entry: + vehicle_data = entry["vehicle"]["data"]["pose"] + positions["vehicle"].append( + { + "time": entry["time"], + "x": vehicle_data.get("x", 0), + "y": vehicle_data.get("y", 0), + } + ) + # Process Agent States - if 'agents' in entry: - for agent_name, agent_data in entry['agents'].items(): - if agent_name not in positions['agents']: - positions['agents'][agent_name] = [] - - agent_pose = agent_data['data']['pose'] - positions['agents'][agent_name].append({ - 'time': entry['time'], - 'x': agent_pose.get('x', 0), - 'y': agent_pose.get('y', 0) - }) - + if "agents" in entry: + for agent_name, agent_data in entry["agents"].items(): + if agent_name not in positions["agents"]: + positions["agents"][agent_name] = [] + + agent_pose = agent_data["data"]["pose"] + positions["agents"][agent_name].append( + { + "time": entry["time"], + "x": agent_pose.get("x", 0), + "y": agent_pose.get("y", 0), + } + ) + except json.JSONDecodeError: # Skip invalid JSON lines continue - + + return positions except Exception as e: print(f"Error parsing behavior data: {e}") return None + @functools.lru_cache(maxsize=100) def load_log_data(): """Load all log data with caching""" - cache_key = 'all_logs' + cache_key = "all_logs" cached_logs = cache.get(cache_key) - + if cached_logs is not None: return cached_logs - + start_time = time.time() logs = [] - + + for log_folder in sorted(os.listdir(LOG_DIR), reverse=True): log_path = os.path.join(LOG_DIR, log_folder) if not os.path.isdir(log_path): continue - meta_path = os.path.join(log_path, 'meta.yaml') - settings_path = os.path.join(log_path, 'settings.yaml') + meta_path = os.path.join(log_path, "meta.yaml") + settings_path = os.path.join(log_path, "settings.yaml") try: - with open(meta_path, 'r') as meta_file: + with open(meta_path, "r") as meta_file: meta_data = yaml.safe_load(meta_file) - with open(settings_path, 'r') as settings_file: - settings_data = yaml.safe_load(settings_file).get('run', {}) + with open(settings_path, "r") as settings_file: + settings_data = yaml.safe_load(settings_file).get("run", {}) + except Exception as e: print(f"Error loading log data: {e}") continue - logs.append({ - 'date': log_folder, - 'run_duration': meta_data.get('run_duration', 'Unknown'), - 'exit_reason': meta_data.get('exit_reason', 'Unknown'), - 'mode': settings_data.get('mode', 'Unknown'), - 'launch_command': settings_data.get('log', {}).get('launch_command', 'Unknown'), - 'folder': log_path - }) - + logs.append( + { + "date": log_folder, + "run_duration": meta_data.get("run_duration", "Unknown"), + "exit_reason": meta_data.get("exit_reason", "Unknown"), + "mode": settings_data.get("mode", "Unknown"), + "launch_command": settings_data.get("log", {}).get( + "launch_command", "Unknown" + ), + "folder": log_path, + } + ) + + # Store results in cache cache.set(cache_key, logs) end_time = time.time() @@ -291,14 +352,16 @@ def load_log_data(): print(logs) return logs + def filter_logs_by_date(logs, start_date=None, end_date=None): """Filter logs by date range""" - cache_key = get_cache_key('filtered_logs', start_date, end_date) + cache_key = get_cache_key("filtered_logs", start_date, end_date) cached_result = cache.get(cache_key) - + if cached_result is not None: return cached_result - + + if start_date: start_date = datetime.datetime.strptime(start_date, "%Y-%m-%d") if end_date: @@ -307,72 +370,84 @@ def filter_logs_by_date(logs, start_date=None, end_date=None): filtered_logs = [] for log in logs: try: - log_date = datetime.datetime.strptime(log['date'][:10], "%Y-%m-%d") - if (not start_date or log_date >= start_date) and (not end_date or log_date <= end_date): + log_date = datetime.datetime.strptime(log["date"][:10], "%Y-%m-%d") + if (not start_date or log_date >= start_date) and ( + not end_date or log_date <= end_date + ): + filtered_logs.append(log) except ValueError: # Skip logs with invalid date format continue - + # Cache the filtered results cache.set(cache_key, filtered_logs) return filtered_logs + @functools.lru_cache(maxsize=50) def get_log_metadata(log_folder_path): """Get metadata for a specific log with caching""" cache_key = f"metadata_{log_folder_path}" cached_metadata = cache.get(cache_key) - + if cached_metadata is not None: return cached_metadata - - metadata = {'folder': log_folder_path} - + + metadata = {"folder": log_folder_path} + # Read metadata from files - meta_path = os.path.join(log_folder_path, 'meta.yaml') - settings_path = os.path.join(log_folder_path, 'settings.yaml') + meta_path = os.path.join(log_folder_path, "meta.yaml") + settings_path = os.path.join(log_folder_path, "settings.yaml") try: if os.path.exists(meta_path): - with open(meta_path, 'r') as meta_file: + with open(meta_path, "r") as meta_file: metadata.update(yaml.safe_load(meta_file)) if os.path.exists(settings_path): - with open(settings_path, 'r') as settings_file: - log_settings = yaml.safe_load(settings_file).get('run', {}) - - - metadata.update({ - 'mode': log_settings.get('mode', 'Unknown'), - 'launch_command': log_settings.get('log', {}).get('launch_command', 'Unknown'), - }) + with open(settings_path, "r") as settings_file: + log_settings = yaml.safe_load(settings_file).get("run", {}) + + metadata.update( + { + "mode": log_settings.get("mode", "Unknown"), + "launch_command": log_settings.get("log", {}).get( + "launch_command", "Unknown" + ), + } + ) except Exception as e: print(f"Error loading metadata: {e}") - + # Cache the results cache.set(cache_key, metadata) return metadata -@app.route('/') + +@app.route("/") def index(): logs = load_log_data() - return render_template('index.html', logs=logs) + return render_template("index.html", logs=logs) + + +@app.route("/filter_logs", methods=["POST"]) -@app.route('/filter_logs', methods=['POST']) def filter_logs(): start_time = time.time() logs = load_log_data() data = request.json - start_date = data.get('start_date') - end_date = data.get('end_date') + start_date = data.get("start_date") + end_date = data.get("end_date") filtered_logs = filter_logs_by_date(logs, start_date, end_date) - + end_time = time.time() print(f"Filtered logs in {end_time - start_time:.2f} seconds") return jsonify(filtered_logs) -@app.route('/view_log/') + +@app.route("/view_log/") + def view_log(log_folder): log_folder_path = os.path.join(LOG_DIR, log_folder) if not os.path.exists(log_folder_path): @@ -380,106 +455,144 @@ def view_log(log_folder): # Get metadata with caching metadata = get_log_metadata(log_folder_path) - + # Get directory structure files = sorted(os.listdir(log_folder_path)) - return render_template('view_log.html', log_folder=log_folder, metadata=metadata, files=files) + return render_template( + "view_log.html", log_folder=log_folder, metadata=metadata, files=files + ) + -@app.route('/open_folder/') +@app.route("/open_folder/") def open_folder(folder): - # Determine the platform and try to open the folder - if platform.system() == 'Linux': - result = os.system(f'xdg-open "{folder}"') - elif platform.system() == 'Windows': - result = os.system(f'explorer "{folder}"') - elif platform.system() == 'Darwin': # macOS - result = os.system(f'open "{folder}"') - else: - return 'Unsupported platform', 400 - - # Check the result of the command - if result != 0: - return 'Failed to open folder', 500 - - return '', 204 - -@app.route('/view_file//') + import os, platform + + full_path = os.path.abspath(os.path.join(LOG_DIR, folder)) + if not full_path.startswith(os.path.abspath(LOG_DIR)): + return "Invalid path", 400 + if not os.path.isdir(full_path): + return f"Folder does not exist: {folder}", 404 + + try: + if platform.system() == "Windows": + os.system(f'explorer "{full_path}"') + elif platform.system() == "Linux": + os.system(f'xdg-open "{full_path}"') + elif platform.system() == "Darwin": + os.system(f'open "{full_path}"') + else: + return "Unsupported platform", 400 + except Exception as e: + return f"Failed to open folder: {e}", 500 + + # if result != 0: + # return 'Failed to open folder', 500 + + return "Folder opened successfully.", 204 + + +@app.route("/view_file//") def view_file(log_folder, filename): file_path = os.path.join(LOG_DIR, log_folder, filename) if not os.path.exists(file_path): - return jsonify({'error': 'File not found!'}), 404 + return jsonify({"error": "File not found!"}), 404 # Check file size first file_size = os.path.getsize(file_path) - + # Define chunk size for pagination (50,000 lines or ~1MB) CHUNK_SIZE = 1000 - + # Get page number from query parameter (default to 1) - page = request.args.get('page', 1, type=int) - + page = request.args.get("page", 1, type=int) + try: - with open(file_path, 'r') as f: + with open(file_path, "r") as f: # Skip lines for previous pages for _ in range((page - 1) * CHUNK_SIZE): f.readline() - + + # Read next chunk of lines lines = [f.readline() for _ in range(CHUNK_SIZE)] # Check if there are more lines has_more = bool(f.readline()) - + # Prepare response - return jsonify({ - 'filename': filename, - 'content': ''.join(lines), - 'total_size': file_size, - 'page': page, - 'has_more': has_more - }) + return jsonify( + { + "filename": filename, + "content": "".join(lines), + "total_size": file_size, + "page": page, + "has_more": has_more, + } + ) except UnicodeDecodeError: - return jsonify({ - 'filename': filename, - 'content': "This file contains binary data and cannot be displayed in the browser.", - 'total_size': file_size, - 'page': page, - 'has_more': False - }) - -@app.route('/parse_behavior//') + return jsonify( + { + "filename": filename, + "content": "This file contains binary data and cannot be displayed in the browser.", + "total_size": file_size, + "page": page, + "has_more": False, + } + ) + + +@app.route("/raw_logs//") +def stream_raw_log(log_folder, filename): + file_path = os.path.join(LOG_DIR, log_folder, filename) + if not os.path.isfile(file_path): + return "File not found!", 404 + + def generate(): + with open(file_path, "r", encoding="utf-8") as f: + for line in f: + yield line + + return Response(stream_with_context(generate()), mimetype="text/plain") + + +@app.route("/parse_behavior//") + def parse_behavior(log_folder, filename): """ Parse behavior.json and return structured position data """ file_path = os.path.join(LOG_DIR, log_folder, filename) - + if not os.path.exists(file_path): - return jsonify({'error': 'File not found!'}), 404 - + return jsonify({"error": "File not found!"}), 404 + # Parse behavior data behavior_data = parse_behavior_data(file_path) - + if behavior_data is None: - return jsonify({'error': 'Could not parse behavior data'}), 500 - + return jsonify({"error": "Could not parse behavior data"}), 500 + return jsonify(behavior_data) + + # Clear cache after certain time period @app.after_request def add_header(response): # Invalidate cache for certain requests - if request.path == '/': + if request.path == "/": # Clear cache periodically for main page current_time = int(time.time()) - last_cleared = cache.get('last_cache_clear') or 0 - + last_cleared = cache.get("last_cache_clear") or 0 + if current_time - last_cleared > 300: # 5 minutes # Reset log data cache load_log_data.cache_clear() - cache.set('last_cache_clear', current_time) - + cache.set("last_cache_clear", current_time) + return response -if __name__ == '__main__': - app.run(debug=True) \ No newline at end of file + +if __name__ == "__main__": + app.run(debug=True) + diff --git a/log_dashboard/requirements.txt b/log_dashboard/requirements.txt index cb006a29b..485786a9f 100644 --- a/log_dashboard/requirements.txt +++ b/log_dashboard/requirements.txt @@ -2,4 +2,5 @@ flask pyyaml cachelib numpy -matplotlib \ No newline at end of file +matplotlib +flask-cors diff --git a/log_dashboard/templates/index.html b/log_dashboard/templates/index.html index d82dd2137..d48791218 100644 --- a/log_dashboard/templates/index.html +++ b/log_dashboard/templates/index.html @@ -37,8 +37,11 @@

GEMstack Log Dashboard

{{ log.launch_command }}
- View Details - + View + Details + +
@@ -49,21 +52,21 @@

GEMstack Log Dashboard

+ + \ No newline at end of file diff --git a/log_dashboard/templates/view_log.html b/log_dashboard/templates/view_log.html index 1a59b119d..9fb7c8c25 100644 --- a/log_dashboard/templates/view_log.html +++ b/log_dashboard/templates/view_log.html @@ -1,5 +1,6 @@ + View Log - {{ log_folder }} @@ -9,15 +10,17 @@ + -
-
-

Log Details for {{ log_folder }}

-
- Back to Dashboard - -
-
- -
-
-
-

Run Duration: {{ metadata.run_duration }}

-

Exit Reason: {{ metadata.exit_reason }}

-
-
-

Mode: {{ metadata.mode }}

-

Launch Command: {{ metadata.launch_command }}

+
+
+

Log Details for {{ log_folder }}

+
+ Back to Dashboard +
-
-
-
-

Files

-
- {% for file in files %} -
- {% if file.endswith('.yaml') or file.endswith('.yml') %} - 📄 {{ file }} - {% elif file.endswith('.txt') or file.endswith('.log') %} - 📝 {{ file }} - {% elif file.endswith('.csv') %} - 📊 {{ file }} - {% else %} - 📄 {{ file }} - {% endif %} +
+
+
+

Run Duration: {{ metadata.run_duration }}

+

Exit Reason: {{ metadata.exit_reason }}

+
+
+

Mode: {{ metadata.mode }}

+

Launch Command: {{ metadata.launch_command }}

- {% endfor %}
-
-
-

Select a file to view

-
-
-
+ +
+
+

Files

+
+ {% for file in files %} +
+ {% if file.endswith('.yaml') or file.endswith('.yml') %} + 📄 {{ file }} + {% elif file.endswith('.txt') or file.endswith('.log') %} + 📝 {{ file }} + {% elif file.endswith('.csv') %} + 📊 {{ file }} + {% else %} + 📄 {{ file }} + {% endif %} +
+ {% endfor %} +
-
- +
+
+

Select a file to view

+
+
+
+
+
+ +
-
- - - - + function loadMoreContent() { + if (hasMorePages) { + currentPage++; + loadFileContent(currentLogFolder, currentFilename, currentPage); + } + } + + function toggleLoadMoreButton() { + if (hasMorePages) { + $('#load-more-btn').show(); + } else { + $('#load-more-btn').hide(); + } + } + + function formatLogFile(content, element) { + // Replace the content with formatted HTML + let formattedContent = content + // Format timestamps (like 22:29:43.349:) + .replace(/(\d{2}:\d{2}:\d{2}\.\d{3}):/g, '$1:') + // Format error words + .replace(/\b(Error|ERROR|error|Exception|EXCEPTION|exception|Warning|WARNING|warning)\b/g, '$1') + // Format numeric values with units + .replace(/(\d+(\.\d+)?\s*(m\/s(\^2)?|degrees))/g, '$1'); + + element.innerHTML = formattedContent; + } + + function formatCsvFile(content, element) { + // Check if it's actually CSV content + if (content.includes(',')) { + let rows = content.trim().split('\n'); + let table = ''; + + // Process header row + let headers = rows[0].split(','); + table += ''; + headers.forEach(header => { + table += ``; + }); + table += ''; + // Process data rows + for (let i = 1; i < rows.length; i++) { + let cells = rows[i].split(','); + table += ''; + cells.forEach(cell => { + table += ``; + }); + table += ''; + } + + table += '
${header.trim()}
${cell.trim()}
'; + element.innerHTML = table; + } else { + // If not properly formatted as CSV, display as plain text + element.textContent = content; + } + } + + document.addEventListener('DOMContentLoaded', function () { + document.getElementById('openFolderBtn').addEventListener('click', function () { + openFolder('{{ log_folder }}'); + }); + }); + + function openFolder(folderName) { + window.location.href = `/open_folder/${encodeURIComponent(folderName)}`; + } + + + +