From 48914920728d30a0951818fe3ac6249536d0e86d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Qu=C3=A9freen=20Almeida?= Date: Tue, 22 Sep 2026 07:23:38 +0200 Subject: [PATCH] Replace /web with a device-driven web-session export Devices (iPhone 17 Pro, iPad Pro clones) driven by existing 2D/3D motion templates, screen content per device clone, exported as a standalone interactive HTML+glb. Replaces the old paste-HTML/animate/export-CSS- keyframes flow; DesktopEditor now bails out for nav==='web' and the new page (app/(editor)/web/page.tsx) owns the whole screen. Old flow's components/lib are left in place, unrouted. Co-Authored-By: Claude Sonnet 5 --- app/(editor)/web/page.tsx | 357 ++++- components/DesktopEditor.tsx | 8 + lib/webMvpExport.ts | 526 +++++++ next-env.d.ts | 4 +- package-lock.json | 1968 +++++++++++++++++++++++-- package.json | 1 + public/3d/web-devices/ipadpro.glb | Bin 0 -> 2277948 bytes public/3d/web-devices/iphone17pro.glb | Bin 0 -> 1658824 bytes scripts/optimize-web-devices.cjs | 52 + three3d/screenImage.ts | 143 ++ three3d/webDevices.ts | 36 + three3d/webMvpViewer.ts | 119 ++ three3d/webTemplateScene.ts | 290 ++++ 13 files changed, 3407 insertions(+), 97 deletions(-) create mode 100644 lib/webMvpExport.ts create mode 100644 public/3d/web-devices/ipadpro.glb create mode 100644 public/3d/web-devices/iphone17pro.glb create mode 100644 scripts/optimize-web-devices.cjs create mode 100644 three3d/screenImage.ts create mode 100644 three3d/webDevices.ts create mode 100644 three3d/webMvpViewer.ts create mode 100644 three3d/webTemplateScene.ts diff --git a/app/(editor)/web/page.tsx b/app/(editor)/web/page.tsx index 3a3ff76..df255b4 100644 --- a/app/(editor)/web/page.tsx +++ b/app/(editor)/web/page.tsx @@ -1,10 +1,355 @@ -import type { Metadata } from 'next'; +'use client'; -export const metadata: Metadata = { - title: 'Web', - description: 'The experimental web-source stage.', -}; +// ── /web: devices → real 3D export ─────────────────────────────────────── +// Replaces the old paste-HTML/component → animate → export-CSS-keyframes +// flow. Pick a device, drive it with an existing motion template, put an +// image on its screen, export a standalone interactive HTML+glb. +// +// Rendered as EditorShell's `children` (app/(editor)/layout.tsx), not +// through DesktopEditor — DesktopEditor bails out early when nav === 'web' +// (see components/DesktopEditor.tsx) so this page owns the whole screen, +// including its own IconRail, rather than sitting inside the shared +// rail/panels/stage grid the other sections use. +// +// Styled with the app's own panel classes (globals.css: .rail, .card, .tpl- +// list/.tpl-item, .ctl-row via ControlRow, .stage-col/.stage-wrap/.stage- +// canvas, .btn). + +import { useEffect, useRef, useState } from 'react'; +import IconRail from '@/components/IconRail'; +import { ControlRow } from '@/components/Controls'; +import { WEB_DEVICES } from '@/three3d/webDevices'; +import { initWebMvpViewer } from '@/three3d/webMvpViewer'; +import { initWebTemplateScene } from '@/three3d/webTemplateScene'; +import { DEFAULT_SCREEN_TRANSFORM, type ScreenTransform } from '@/three3d/screenImage'; +import { getTemplate, defaultsFor } from '@/templates'; +import { dimsFor } from '@/store/useSceneStore'; +import { downloadWebMvpZip, downloadWebMvpTemplateZip } from '@/lib/webMvpExport'; +import { demoSourceForSlot } from '@/lib/demoAssets'; +import type { ControlDef } from '@/lib/types'; + +const zoomDef: ControlDef = { key: 'zoom', label: 'Zoom', type: 'slider', min: 0.2, max: 3, step: 0.01, default: 1 }; +const posXDef: ControlDef = { key: 'px', label: 'Position X', type: 'slider', min: 0, max: 100, step: 1, default: 50 }; +const posYDef: ControlDef = { key: 'py', label: 'Position Y', type: 'slider', min: 0, max: 100, step: 1, default: 50 }; + +const FITS: { id: ScreenTransform['fit']; label: string }[] = [ + { id: 'cover', label: 'Cover' }, + { id: 'width', label: 'Fit width' }, + { id: 'contain', label: 'Contain' }, +]; + +// Device clones are full GLB instances with their own 1024² screen texture — +// not cheap 2D cards. Motion presets default to 10-70 layers, way past what a +// device grid can carry, so instancing is hard-capped at 12 (see three3d/ +// webTemplateScene.ts's own MAX_INSTANCES and lib/webMvpExport.ts's bake +// step — this page's UI just mirrors the same number). +const MAX_INSTANCES = 12; + +interface ScreenSlot { url: string; name: string } +function clampTemplateValues(v: Record): Record { + if (!('count' in v)) return v; + return { ...v, count: Math.min(Number(v.count), MAX_INSTANCES) }; +} + +// The session canvas — fixed, not responsive-fill: a web session is authored +// at one size (like a hero/banner slot) and exported at that size, the same +// way the 2D canvas has a fixed aspect rather than filling whatever window +// it's previewed in. +const SESSION_W = 1300; +const SESSION_H = 720; + +// Free orbit uses the plain device viewer (three3d/webMvpViewer.ts) and has no +// controls of its own. The others drive the device with an EXISTING 2D/3D +// motion template instead of a bespoke animation — see three3d/ +// webTemplateScene.ts. `canvasSize` is the reference frame each preset's +// px-space values (planeSize, orbitRadius…) were authored against, independent +// of the session canvas's own on-screen size above. +const WEB_MOTIONS = [ + { key: 'free', label: 'Free orbit', templateId: null as string | null, canvasSize: dimsFor('3:4') }, + // Gap 20% (the control's own max): the template's 10% default packs device + // clones edge-to-edge, which reads as one smeared shape at this scale — + // devices need more breathing room than flat 2D cards do. Backward reads + // better than the default forward for a device flythrough. Defaults to the + // iPad — its 16:9-ish screen reads better than the phone's tall sliver at + // this canvas's landscape framing. + { key: 'tunnel-01', label: 'Card Tunnel', templateId: 'tunnel-01', canvasSize: dimsFor('16:9'), valuesOverride: { gap: 20, direction: 'backward' }, defaultDeviceKey: 'ipadpro' }, + { key: 'ring-r01', label: 'Ring 01', templateId: 'ring-r01', canvasSize: dimsFor('4:5') }, + { key: 'orbit-3d-01', label: 'Orbit 3D 01', templateId: 'orbit-3d-01', canvasSize: dimsFor('4:5') }, + { key: 'carousel3d-01', label: 'Carousel 3D 01', templateId: 'carousel3d-01', canvasSize: dimsFor('3:4') }, + { key: 'deck-r01', label: 'Deck 04', templateId: 'deck-r01', canvasSize: dimsFor('3:4') }, + { key: 'spinner-01', label: 'Spinner 01', templateId: 'spinner-01', canvasSize: dimsFor('1:1') }, + { key: 'globe-r01', label: 'Sphere 01', templateId: 'globe-r01', canvasSize: dimsFor('3:4') }, +]; export default function WebPage() { - return null; + const [deviceKey, setDeviceKey] = useState(WEB_DEVICES[0].key); + const device = WEB_DEVICES.find((d) => d.key === deviceKey) ?? WEB_DEVICES[0]; + const [motionKey, setMotionKey] = useState(WEB_MOTIONS[0].key); + const motion = WEB_MOTIONS.find((m) => m.key === motionKey) ?? WEB_MOTIONS[0]; + + // Picking a motion with its own preferred device (Card Tunnel → iPad, its + // screen reads better than the phone's sliver at this canvas's landscape + // framing) switches to it once, on the switch itself — a device picked + // afterward sticks, same as every other control here. + useEffect(() => { + if (motion.defaultDeviceKey) setDeviceKey(motion.defaultDeviceKey); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [motionKey]); + + // The active template's own control values — same "full reset on switch" + // contract the editor uses (store/useSceneStore's setTemplate). Read live by + // the render loop via valuesRef, so a slider drag never re-inits the scene. + const [values, setValues] = useState>(() => (motion.templateId ? clampTemplateValues({ ...defaultsFor(motion.templateId), ...motion.valuesOverride }) : {})); + const valuesRef = useRef(values); + valuesRef.current = values; + useEffect(() => { + setValues(motion.templateId ? clampTemplateValues({ ...defaultsFor(motion.templateId), ...motion.valuesOverride }) : {}); + }, [motion.templateId]); + + // One slot per possible device clone (index i's image goes on clone i, + // cycled — see three3d/webTemplateScene.ts). Free orbit only ever shows + // one device, so it just reads slot 0. + // Seeded from the same bundled demo set the Library/Assets panel opens + // with (lib/demoAssets.ts) — a fresh session shows real imagery on every + // device screen instead of blank black glass. Replace or remove like any + // upload; nothing here is fetched or persisted beyond this page's state. + const [screenSlots, setScreenSlots] = useState<(ScreenSlot | null)[]>(() => + Array.from({ length: MAX_INSTANCES }, (_, i) => { + const demo = demoSourceForSlot(i); + return { url: demo.url, name: demo.name }; + })); + const fileInputRef = useRef(null); + const uploadTargetRef = useRef(0); + // Object URL lifecycle lives in a ref, not inside the setState updater: + // React (Strict Mode especially) may invoke a functional updater more than + // once to check it's pure, and createObjectURL/revokeObjectURL are real + // side effects — called twice, the second pass revokes the blob the first + // pass just handed to , and the load fails. + const slotUrlsRef = useRef<(string | null)[]>(Array(MAX_INSTANCES).fill(null)); + const onSlotFile = (i: number, f: File | undefined) => { + if (!f) return; + const prev = slotUrlsRef.current[i]; + if (prev) URL.revokeObjectURL(prev); + const next = URL.createObjectURL(f); + slotUrlsRef.current[i] = next; + setScreenSlots((s) => { const copy = s.slice(); copy[i] = { url: next, name: f.name }; return copy; }); + }; + const clearSlot = (i: number) => { + const prev = slotUrlsRef.current[i]; + if (prev) { URL.revokeObjectURL(prev); slotUrlsRef.current[i] = null; } + setScreenSlots((s) => { const copy = s.slice(); copy[i] = null; return copy; }); + }; + const visibleSlots = motion.templateId ? MAX_INSTANCES : 1; + const screenImageUrls = screenSlots.slice(0, visibleSlots).map((s) => s?.url ?? null); + const hasAnyScreenImage = screenImageUrls.some(Boolean); + // Stable primitive key — the array above is a fresh object every render, + // so the scene-init effect below keys off this instead to avoid + // re-loading the model on every unrelated re-render. + const screenImageUrlsKey = screenImageUrls.join('|'); + + // Same isolation principle as store/use3DStore.ts's per-effect state: this + // is local to this page, not use3DStore's global screenFit/screenZoom + // (that's Mockup-only state) — components/ScreenContent.tsx's UI pattern is + // reused, its store binding is not. + const [screenTransform, setScreenTransform] = useState(DEFAULT_SCREEN_TRANSFORM); + const screenTransformRef = useRef(screenTransform); + screenTransformRef.current = screenTransform; + const patchScreenTransform = (patch: Partial) => setScreenTransform((s) => ({ ...s, ...patch })); + + const stageRef = useRef(null); + const canvasRef = useRef(null); + const [exporting, setExporting] = useState(false); + const [exportError, setExportError] = useState(null); + + useEffect(() => { + const stage = stageRef.current; + const canvas = canvasRef.current; + if (!stage || !canvas) return; + const dispose = motion.templateId + ? initWebTemplateScene(stage, canvas, { + device, templateId: motion.templateId, canvasSize: motion.canvasSize, + getValues: () => valuesRef.current, screenImageUrls, + getScreenTransform: () => screenTransformRef.current, + }) + : initWebMvpViewer(stage, canvas, device, screenImageUrls[0] ?? null, () => screenTransformRef.current); + return dispose; + // valuesRef is read live — not a dependency. Changing device/motion/screen + // is the only thing that should re-load the model. screenImageUrlsKey + // stands in for screenImageUrls (a fresh array reference every render). + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [device, motion.templateId, motion.canvasSize, screenImageUrlsKey]); + + const onExport = async () => { + setExporting(true); + setExportError(null); + try { + if (motion.templateId) { + await downloadWebMvpTemplateZip(device.key, device, device.label, motion.templateId, motion.canvasSize, values, screenImageUrls, screenTransform); + } else { + await downloadWebMvpZip(device.key, device, device.label, screenImageUrls[0] ?? null, screenTransform); + } + } catch (err) { + setExportError(err instanceof Error ? err.message : 'Export failed'); + } finally { + setExporting(false); + } + }; + + const template = motion.templateId ? getTemplate(motion.templateId) : null; + + return ( +
+ + + {/* LEFT — pick what's on stage: device + motion. */} + + +
+
+
+ +
+
+
+ + {/* RIGHT — manipulate what's on stage: screen content + the active + motion template's own controls, plus export. */} + +
+ ); } diff --git a/components/DesktopEditor.tsx b/components/DesktopEditor.tsx index a44a031..95552e6 100644 --- a/components/DesktopEditor.tsx +++ b/components/DesktopEditor.tsx @@ -60,6 +60,14 @@ export default function DesktopEditor() { else if (is3D && s.effectId === 'mockup') s.setEffect('cartoon'); }, [isMockup, is3D]); + // /web is now the device-sessions flow (see app/(editor)/web/page.tsx, + // formerly the standalone /web-mvp route) — it renders its own full shell + // (rail, stage, panels) as EditorShell's `children`, not through this + // component. The old paste-HTML/animate/export flow's wiring below + // (WebStage, WebSourceBar, WebSelectionPanel, WebScenePanel, WebCodeModal) + // is left in place but unreachable now that isWeb bails out here first. + if (isWeb) return null; + return (
diff --git a/lib/webMvpExport.ts b/lib/webMvpExport.ts new file mode 100644 index 0000000..c13bb28 --- /dev/null +++ b/lib/webMvpExport.ts @@ -0,0 +1,526 @@ +import JSZip from 'jszip'; +import { asset } from './paths'; +import { getTemplate, defaultsFor } from '@/templates'; +import type { TransformCtx } from '@/lib/types'; +import type { DeviceDef } from '@/three3d/devices'; +import type { ScreenTransform } from '@/three3d/screenImage'; + +const DEFAULT_SCREEN_TRANSFORM: ScreenTransform = { fit: 'cover', zoom: 1, offsetX: 50, offsetY: 50 }; + +// ── Web MVP export ──────────────────────────────────────────────────────── +// Ships a real interactive 3D viewer, not a baked video: an index.html that +// loads three.js from a CDN via an import map, plus the device's own .glb +// (and, if one was set, a screen image) sitting next to it. No build step — +// the person receiving it just opens index.html. +// +// The rig here is a plain-JS re-statement of three3d/webMvpViewer.ts and +// three3d/webTemplateScene.ts. It has to be re-derived rather than imported: +// the exported page runs standalone, months or years after this app built +// it, against whatever three.js version the pinned CDN URL resolves to — it +// can't import this repo's own modules. + +const THREE_VERSION = '0.185.1'; // matches package.json's three — keep in step + +// Screen compositing — trimmed re-statement of three3d/screenImage.ts for the +// exported page: find the mesh named "Screen", fit the bundled image onto a +// canvas texture, clip to the device's own corner radius. `screenFileNames` +// is indexed by instance (cycled: files[i % files.length]) so a multi-device +// scene can show different screen content per clone from a handful of images. +function screenJsBlock(device: DeviceDef, screenFileNames: string[], transform: ScreenTransform): string { + return ` +function partKeyOf(mesh) { + const mn = mesh.material && !Array.isArray(mesh.material) ? mesh.material.name : ''; + if (mn) return mn; + return (mesh.name || 'mesh').replace(/[._-\\s]?\\d+$/, '') || mesh.name; +} +function findScreenMesh(root) { + let found = null; + root.traverse((o) => { if (!found && o.isMesh && partKeyOf(o) === 'Screen') found = o; }); + return found; +} +function ensureUVs(mesh) { + const geo = mesh.geometry; + if (geo.getAttribute('uv')) return; + const pos = geo.getAttribute('position'); + if (!pos) return; + geo.computeBoundingBox(); + const bb = geo.boundingBox, size = bb.getSize(new THREE.Vector3()); + const flat = size.x <= size.y && size.x <= size.z ? 'x' : size.y <= size.z ? 'y' : 'z'; + const axes = ['x', 'y', 'z'].filter((a) => a !== flat); + const ua = axes[0], va = axes[1]; + const get = { x: 'getX', y: 'getY', z: 'getZ' }; + const uSpan = Math.max(1e-6, size[ua]), vSpan = Math.max(1e-6, size[va]); + const uv = new Float32Array(pos.count * 2); + for (let i = 0; i < pos.count; i++) { + uv[i * 2] = (pos[get[ua]](i) - bb.min[ua]) / uSpan; + uv[i * 2 + 1] = (pos[get[va]](i) - bb.min[va]) / vSpan; + } + geo.setAttribute('uv', new THREE.BufferAttribute(uv, 2)); +} +const SCREEN_FILES = ${JSON.stringify(screenFileNames)}; +function applyScreenImage(instance, i) { + if (!SCREEN_FILES.length) return; + const screenFileName = SCREEN_FILES[i % SCREEN_FILES.length]; + const mesh = findScreenMesh(instance); + if (!mesh) return; + ensureUVs(mesh); + const transpose = ${JSON.stringify(device.screenTextureTranspose ?? null)}; + const aspect = transpose ? 1 / ${device.screenAspect} : ${device.screenAspect}; + const canvas = document.createElement('canvas'); + canvas.width = 1024; + canvas.height = Math.max(1, Math.round(1024 / aspect)); + const ctx = canvas.getContext('2d'); + const tex = new THREE.CanvasTexture(canvas); + tex.colorSpace = THREE.SRGBColorSpace; + tex.flipY = ${device.screenTextureFlipY ?? true}; + const mat = new THREE.MeshBasicMaterial({ map: tex, toneMapped: false, transparent: true, alphaTest: 0.001 }); + mat.polygonOffset = true; mat.polygonOffsetFactor = 0; mat.polygonOffsetUnits = -2; + mesh.material = mat; + mesh.renderOrder = 1000; + const FIT = ${JSON.stringify(transform.fit)}; + const ZOOM = ${JSON.stringify(transform.zoom)}; + const OFFSET_X = ${JSON.stringify(transform.offsetX)}; + const OFFSET_Y = ${JSON.stringify(transform.offsetY)}; + const img = new Image(); + img.onload = () => { + const W = canvas.width, H = canvas.height; + const r = Math.min(W, H) * ${Math.max(0, device.screenCornerFrac)}; + ctx.clearRect(0, 0, W, H); + ctx.save(); + if (r > 0.5) { ctx.beginPath(); ctx.roundRect(0, 0, W, H, r); ctx.clip(); } + const srcW = img.naturalWidth, srcH = img.naturalHeight; + const byW = W / srcW, byH = H / srcH; + const base = FIT === 'width' ? byW : FIT === 'contain' ? Math.min(byW, byH) : Math.max(byW, byH); + const scale = base * Math.max(0.05, ZOOM); + const dw = srcW * scale, dh = srcH * scale; + const dx = (W - dw) * (OFFSET_X / 100); + const dy = (H - dh) * (OFFSET_Y / 100); + ctx.drawImage(img, dx, dy, dw, dh); + ctx.restore(); + tex.needsUpdate = true; + }; + img.src = './' + screenFileName; +} +`; +} + +function viewerHtml(deviceLabel: string, glbFileName: string, device: DeviceDef, screenFileName: string | null, screenTransform: ScreenTransform): string { + return ` + + + +${deviceLabel} — 3D viewer + + + + + + + + + +`; +} + +/** Fetches `url` (may be a blob: URL) and returns its bytes + a short extension. */ +async function fetchBytes(url: string): Promise<{ buf: ArrayBuffer; ext: string }> { + const res = await fetch(url); + if (!res.ok) throw new Error(`Failed to fetch ${url}: ${res.status}`); + const blob = await res.blob(); + const ext = blob.type.split('/')[1]?.split('+')[0] || 'jpg'; + return { buf: await blob.arrayBuffer(), ext }; +} + +/** Build the export zip (index.html + the device's .glb [+ screen image]) as a Blob. */ +export async function buildWebMvpZip(device: DeviceDef, deviceLabel: string, screenImageUrl?: string | null, screenTransform: ScreenTransform = DEFAULT_SCREEN_TRANSFORM): Promise { + const glbRes = await fetch(asset(device.modelUrl)); + if (!glbRes.ok) throw new Error(`Failed to fetch model: ${glbRes.status}`); + const glbBuf = await glbRes.arrayBuffer(); + + const glbFileName = 'model.glb'; + const zip = new JSZip(); + let screenFileName: string | null = null; + if (screenImageUrl) { + const { buf, ext } = await fetchBytes(screenImageUrl); + screenFileName = `screen.${ext}`; + zip.file(screenFileName, buf); + } + zip.file('index.html', viewerHtml(deviceLabel, glbFileName, device, screenFileName, screenTransform)); + zip.file(glbFileName, glbBuf); + return zip.generateAsync({ type: 'blob' }); +} + +/** Build the zip and trigger a download. */ +export async function downloadWebMvpZip(deviceKey: string, device: DeviceDef, deviceLabel: string, screenImageUrl?: string | null, screenTransform?: ScreenTransform): Promise { + const blob = await buildWebMvpZip(device, deviceLabel, screenImageUrl, screenTransform); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `${deviceKey}-3d-viewer.zip`; + document.body.appendChild(a); + a.click(); + a.remove(); + setTimeout(() => URL.revokeObjectURL(url), 1000); +} + +// ── Template-driven export ─────────────────────────────────────────────── +// The motion catalogue's transform3d()/transform()/camera() are pure functions +// of (frame, index, count, values, ctx) — see templates/*.ts's own ground +// rules ("transforms stay pure and deterministic"). Rather than re-bundling a +// template's TS source (and its own imports) into a dependency-free exported +// page, this BAKES one full loop's worth of poses by calling those same +// functions here, once, and ships the resulting table as a small embedded +// JSON array. The exported page just indexes into it every frame — same +// numbers the live app produces, no reimplementation to drift out of sync. + +const r3 = (n: number) => Math.round(n * 1000) / 1000; // trim JSON size, negligible visually + +// Same cap as three3d/webTemplateScene.ts's MAX_INSTANCES — keeps the exported +// page's instance count identical to what was previewed live. +const MAX_INSTANCES = 12; + +interface BakedInstance { x: number; y: number; z: number; rx: number; ry: number; rz: number; s: number; a: number; } +interface BakedCamPose { fov: number; x: number; y: number; z: number; tx: number; ty: number; tz: number; near: number; far: number; } +interface BakedFrame { inst: BakedInstance[]; cam: BakedCamPose; } + +function bakeTemplateFrames( + templateId: string, + canvasSize: { width: number; height: number }, + durationSec: number, + fps: number, + valuesOverride?: Record, +): { frames: BakedFrame[]; count: number } { + const template = getTemplate(templateId); + const values = { ...defaultsFor(templateId), ...valuesOverride }; + const totalFrames = Math.max(1, Math.round(durationSec * fps)); + const linear = (t: number) => t; + const ctx: TransformCtx = { + fps, width: canvasSize.width, height: canvasSize.height, + duration: durationSec, totalFrames, + ease: linear, + easedPhase: (p) => { const b = Math.floor(p); return b + linear(p - b); }, + cardAspect: template.meta.cardAspect === 'canvas' ? canvasSize.width / canvasSize.height : (typeof template.meta.cardAspect === 'number' ? template.meta.cardAspect : undefined), + }; + // Reads count off the same merged `values` the live preview resizes with + // (three3d/webTemplateScene.ts's syncInstanceCount) — the export matches + // whatever instance count was on screen when Export was clicked. + const rawCount = Math.max(1, Math.round(template.layerCount?.(values, ctx) ?? Number(values.count ?? 1))); + const count = Math.min(MAX_INSTANCES, rawCount); + + const frames: BakedFrame[] = []; + for (let f = 0; f < totalFrames; f++) { + const inst: BakedInstance[] = []; + for (let i = 0; i < count; i++) { + if (template.transform3d) { + const t = template.transform3d(f, i, count, values, ctx); + inst.push({ x: r3(t.x), y: r3(t.y), z: r3(t.z), rx: r3(t.rotationX ?? 0), ry: r3(t.rotationY ?? 0), rz: r3(t.rotationZ ?? 0), s: r3(t.scale), a: r3(t.alpha) }); + } else { + const t = template.transform(f, i, count, values, ctx); + inst.push({ x: r3(t.x), y: r3(t.y), z: r3(t.depth), rx: 0, ry: 0, rz: r3(-t.rotation), s: r3(t.scale), a: r3(t.alpha) }); + } + } + const pose = template.camera?.(values, ctx); + const fov = pose?.fov ?? 50; + const D = (ctx.height / 2) / Math.tan((fov * Math.PI) / 360); + const position = pose?.position ?? { x: 0, y: 0, z: D * (pose?.distance ?? 1) }; + const target = pose?.target ?? { x: 0, y: 0, z: 0 }; + frames.push({ + inst, + cam: { + fov: r3(fov), x: r3(position.x), y: r3(position.y), z: r3(position.z), + tx: r3(target.x), ty: r3(target.y), tz: r3(target.z), + near: r3(pose?.near ?? 0.1), far: r3(pose?.far ?? Math.max(D * 8, Math.abs(position.z) * 8)), + }, + }); + } + return { frames, count }; +} + +function templateViewerHtml( + deviceLabel: string, glbFileName: string, framesJson: string, count: number, fps: number, + device: DeviceDef, screenFileNames: string[], screenTransform: ScreenTransform, +): string { + return ` + + + +${deviceLabel} — 3D scene + + + + + + + + + +`; +} + +/** Build the export zip (index.html + baked motion table + the device's .glb [+ screen image]) as a Blob. */ +export async function buildWebMvpTemplateZip( + device: DeviceDef, + deviceLabel: string, + templateId: string, + canvasSize: { width: number; height: number }, + valuesOverride?: Record, + screenImageUrls?: (string | null | undefined)[], + durationSec = 8, + fps = 30, + screenTransform: ScreenTransform = DEFAULT_SCREEN_TRANSFORM, +): Promise { + const glbRes = await fetch(asset(device.modelUrl)); + if (!glbRes.ok) throw new Error(`Failed to fetch model: ${glbRes.status}`); + const glbBuf = await glbRes.arrayBuffer(); + + const { frames, count } = bakeTemplateFrames(templateId, canvasSize, durationSec, fps, valuesOverride); + const glbFileName = 'model.glb'; + const zip = new JSZip(); + // One zipped file per distinct image, indexed in the same order the + // exported page cycles them (screenFileNames[i % length]) — a gap in the + // source array is dropped, not zipped as an empty slot. + const screenFileNames: string[] = []; + const urls = (screenImageUrls ?? []).filter((u): u is string => !!u); + for (let i = 0; i < urls.length; i++) { + const { buf, ext } = await fetchBytes(urls[i]); + const name = `screen-${i}.${ext}`; + zip.file(name, buf); + screenFileNames.push(name); + } + zip.file('index.html', templateViewerHtml(deviceLabel, glbFileName, JSON.stringify(frames), count, fps, device, screenFileNames, screenTransform)); + zip.file(glbFileName, glbBuf); + return zip.generateAsync({ type: 'blob' }); +} + +/** Build the template-driven zip and trigger a download. */ +export async function downloadWebMvpTemplateZip( + deviceKey: string, + device: DeviceDef, + deviceLabel: string, + templateId: string, + canvasSize: { width: number; height: number }, + valuesOverride?: Record, + screenImageUrls?: (string | null | undefined)[], + screenTransform?: ScreenTransform, +): Promise { + const blob = await buildWebMvpTemplateZip(device, deviceLabel, templateId, canvasSize, valuesOverride, screenImageUrls, undefined, undefined, screenTransform); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `${deviceKey}-${templateId}-3d-scene.zip`; + document.body.appendChild(a); + a.click(); + a.remove(); + setTimeout(() => URL.revokeObjectURL(url), 1000); +} diff --git a/next-env.d.ts b/next-env.d.ts index ce4e94a..a419cbe 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -1,7 +1,7 @@ /// /// -import "./.next/types/routes.d.ts"; -import "./.next/types/root-params.d.ts"; +import "./.next/dev/types/routes.d.ts"; +import "./.next/dev/types/root-params.d.ts"; // NOTE: This file should not be edited // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/package-lock.json b/package-lock.json index 34fd7a6..245efd4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "zustand": "^5.0.14" }, "devDependencies": { + "@gltf-transform/cli": "^4.5.0", "@types/node": "^26.1.1", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", @@ -49,6 +50,28 @@ "node": ">=6.9.0" } }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.9.tgz", + "integrity": "sha512-R6siwR65Hm+3yfgP7o8DKhNvputQAwfoz9zTc3kyDudnomj2/BcLmD+uGQQPICjuFUp8ounPBU+jmKsocwVVAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@so-ric/colorspace": "^1.1.6", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, "node_modules/@dimforge/rapier3d-compat": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz", @@ -109,10 +132,84 @@ "react": ">=16.8.0" } }, + "node_modules/@donmccurdy/caporal": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/@donmccurdy/caporal/-/caporal-0.0.10.tgz", + "integrity": "sha512-VdaJjOqYFYcDTM5We2x8cL+B+U9UFQvq0iW2ypqEGX31SDf2oYFjEg7INEJorBwJJnFNXV8jXoYGzJyLeYl1EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/glob": "^8.1.0", + "@types/lodash": "^4.14.197", + "@types/node": "20.5.6", + "@types/table": "5.0.0", + "@types/wrap-ansi": "^8.0.1", + "chalk": "3.0.0", + "glob": "^10.3.3", + "lodash": "^4.17.21", + "table": "5.4.6", + "winston": "3.10.0", + "wrap-ansi": "^8.1.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@donmccurdy/caporal/node_modules/@types/node": { + "version": "20.5.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.6.tgz", + "integrity": "sha512-Gi5wRGPbbyOTX+4Y2iULQ27oUPrefaB0PxGQJnfyWN3kvEDGM3mIB5M/gQLmitZf7A9FmLeaqxD3L1CXpm3VKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@donmccurdy/caporal/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@donmccurdy/caporal/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@donmccurdy/caporal/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@emnapi/runtime": { "version": "1.11.3", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -561,12 +658,103 @@ "node": ">=18" } }, + "node_modules/@gltf-transform/cli": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@gltf-transform/cli/-/cli-4.5.0.tgz", + "integrity": "sha512-0i/qco9bR1tva3wI7iksrdcQoZmgFn4WFMJnKOWqXWdX/a2T+mrNomfGUEfFqMSI26JPSZXqasXyHiytiEpodQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@donmccurdy/caporal": "~0.0.10", + "@gltf-transform/core": "^4.5.0", + "@gltf-transform/extensions": "^4.5.0", + "@gltf-transform/functions": "^4.5.0", + "@types/micromatch": "~4.0.10", + "@types/prompts": "^2.4.9", + "@types/tmp": "~0.2.6", + "cli-table3": "~0.6.5", + "csv-stringify": "~6.8.3", + "draco3dgltf": "~1.5.7", + "gltf-validator": "~2.0.0-dev.3.10", + "keyframe-resample": "~0.1.0", + "ktx-parse": "^1.1.0", + "listr2": "~8.3.3", + "meshoptimizer": "~1.2.0", + "micromatch": "~4.0.8", + "mikktspace": "~1.1.1", + "prompts": "^2.4.2", + "sharp": "~0.35.3", + "tmp": "~0.2.7", + "watlas": "^1.0.1" + }, + "bin": { + "gltf-transform": "bin/cli.js" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/donmccurdy" + } + }, + "node_modules/@gltf-transform/cli/node_modules/meshoptimizer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-1.2.0.tgz", + "integrity": "sha512-davRZeIJbxJrE24cwQle7ZDsxjdk/OphNOV83oX+efQinyoHY9Jcyz3MHbaoG0qySZajldGztNZ1RN/T19PZsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@gltf-transform/core": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@gltf-transform/core/-/core-4.5.0.tgz", + "integrity": "sha512-JlvShvnB4AtfGZqjnESS/wfPJbpVnyHhTwJBbWN4qXqkB3C5HIoxxpu/orwGBge6Pc0zObeWj70lVf+4gbuu0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "property-graph": "^4.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/donmccurdy" + } + }, + "node_modules/@gltf-transform/extensions": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@gltf-transform/extensions/-/extensions-4.5.0.tgz", + "integrity": "sha512-J4cKzrmEr75YkrtdI4cKosBg2vDC4rT56aq/QoijW7GT1Y9gSEMJbqyFO9xcFO3FNpZaZiDrHWUqE5Okrl5nOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@gltf-transform/core": "^4.5.0", + "ktx-parse": "^1.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/donmccurdy" + } + }, + "node_modules/@gltf-transform/functions": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@gltf-transform/functions/-/functions-4.5.0.tgz", + "integrity": "sha512-7sMOuEfksMyF+/NTwUnEOgh7djohJ5XfeYg8rzXDG+9JIdbGVUpvJUY3XVBJCUJJ04dusDvcTHloOi1wfM8lnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@gltf-transform/core": "^4.5.0", + "@gltf-transform/extensions": "^4.5.0", + "ktx-parse": "^1.1.0", + "ndarray": "^1.0.19", + "ndarray-lanczos": "^0.3.0", + "ndarray-pixels": "^5.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/donmccurdy" + } + }, "node_modules/@img/colour": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "devOptional": true, "license": "MIT", - "optional": true, "engines": { "node": ">=18" } @@ -578,6 +766,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -600,6 +789,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -619,6 +809,7 @@ "version": "0.35.4", "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.4.tgz", "integrity": "sha512-lIsKw/BU+kjB4eZjxrYrZmwOJYi3Ajrv66iAlBmUPyKc3HpnloevB1g3wxGD9P/5BbQ1brBGl65VRRrCvQDEqA==", + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -641,6 +832,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -657,6 +849,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -673,9 +866,7 @@ "cpu": [ "arm" ], - "libc": [ - "glibc" - ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -692,9 +883,7 @@ "cpu": [ "arm64" ], - "libc": [ - "glibc" - ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -711,9 +900,7 @@ "cpu": [ "ppc64" ], - "libc": [ - "glibc" - ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -730,9 +917,7 @@ "cpu": [ "riscv64" ], - "libc": [ - "glibc" - ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -749,9 +934,7 @@ "cpu": [ "s390x" ], - "libc": [ - "glibc" - ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -768,9 +951,7 @@ "cpu": [ "x64" ], - "libc": [ - "glibc" - ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -787,9 +968,7 @@ "cpu": [ "arm64" ], - "libc": [ - "musl" - ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -806,9 +985,7 @@ "cpu": [ "x64" ], - "libc": [ - "musl" - ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -825,9 +1002,7 @@ "cpu": [ "arm" ], - "libc": [ - "glibc" - ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -850,9 +1025,7 @@ "cpu": [ "arm64" ], - "libc": [ - "glibc" - ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -875,9 +1048,7 @@ "cpu": [ "ppc64" ], - "libc": [ - "glibc" - ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -900,9 +1071,7 @@ "cpu": [ "riscv64" ], - "libc": [ - "glibc" - ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -925,9 +1094,7 @@ "cpu": [ "s390x" ], - "libc": [ - "glibc" - ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -950,9 +1117,7 @@ "cpu": [ "x64" ], - "libc": [ - "glibc" - ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -975,9 +1140,7 @@ "cpu": [ "arm64" ], - "libc": [ - "musl" - ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1000,9 +1163,7 @@ "cpu": [ "x64" ], - "libc": [ - "musl" - ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1022,6 +1183,7 @@ "version": "0.35.4", "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.4.tgz", "integrity": "sha512-zQnl4Kwp7Q6NHsENtU2T/00Zi+w3AQNwz3+UaTyVBy2FpXrzXzGjndpK61onhZjRtRpQXxCTeqw19bVyXOh7jA==", + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { @@ -1041,6 +1203,7 @@ "cpu": [ "wasm32" ], + "dev": true, "license": "Apache-2.0", "optional": true, "dependencies": { @@ -1060,6 +1223,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ @@ -1079,6 +1243,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ @@ -1098,6 +1263,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ @@ -1110,6 +1276,67 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -1190,9 +1417,6 @@ "cpu": [ "arm64" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1209,9 +1433,6 @@ "cpu": [ "arm64" ], - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -1228,9 +1449,6 @@ "cpu": [ "x64" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1247,9 +1465,6 @@ "cpu": [ "x64" ], - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -1297,6 +1512,17 @@ "integrity": "sha512-nezytU2pw587fQstUu1AsJZDVEynjskwOL+kibwcdxsMBFqPsFFNA7xl0ii/gXuDi6M0xj3mfRJj8pBSc2jCfA==", "license": "MIT" }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@puppeteer/browsers": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/@puppeteer/browsers/-/browsers-3.0.6.tgz", @@ -1381,6 +1607,17 @@ "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", "license": "MIT" }, + "node_modules/@so-ric/colorspace": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@so-ric/colorspace/-/colorspace-1.1.6.tgz", + "integrity": "sha512-/KiKkpHNOBgkFJwu9sh48LkHSMYGyuTcSFK/qMBdnOAlrRJzRSXAOFB5qwzaVQuDl8wAvHVMkaASQDReTahxuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "color": "^5.0.2", + "text-hex": "1.0.x" + } + }, "node_modules/@swc/helpers": { "version": "0.5.23", "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", @@ -1403,6 +1640,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/braces": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/braces/-/braces-3.0.5.tgz", + "integrity": "sha512-SQFof9H+LXeWNz8wDe7oN5zu7ket0qwMu5vZubW4GCJ8Kkeh6nBWUz87+KTz/G3Kqsrp0j/W253XJb3KMEeg3w==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/dom-mediacapture-transform": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/@types/dom-mediacapture-transform/-/dom-mediacapture-transform-0.1.12.tgz", @@ -1424,6 +1668,48 @@ "integrity": "sha512-k/9fOUGO39yd2sCjrbAJvGDEQvRwRnQIZlBz43roGwUZo5SHAmyVvSFyaVVZkicRVCaDXPKlbxrUcBuJoSWunQ==", "license": "MIT" }, + "node_modules/@types/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimatch": "^5.1.2", + "@types/node": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.17.25", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.25.tgz", + "integrity": "sha512-+K1NIO8I+F9/wNulfVvu23QYd0Pe9/OCqRrim4NoYIf1VoEDL90Ve4ClzpyqBLc7NpGGWRvYNCKZ1BE/Jpf8dQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/micromatch": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/@types/micromatch/-/micromatch-4.0.10.tgz", + "integrity": "sha512-5jOhFDElqr4DKTrTEbnW8DZ4Hz5LRUEmyrGpCMrD/NphYv3nUnaF08xmSLx1rGGnyEs/kFnhiw6dCgcDqMr5PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/braces": "*" + } + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ndarray": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@types/ndarray/-/ndarray-1.1.0.tgz", + "integrity": "sha512-go+C6vHBUuO9jH6Tj6qEZ63JEGoMSxFdmd+6QAtthGD6xumBfIz3RbNDDs2aoRVLf9naH8lk5jnWy2UHHKgYQQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "26.1.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-26.1.1.tgz", @@ -1434,6 +1720,17 @@ "undici-types": "~8.3.0" } }, + "node_modules/@types/prompts": { + "version": "2.4.9", + "resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.4.9.tgz", + "integrity": "sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "kleur": "^3.0.3" + } + }, "node_modules/@types/react": { "version": "19.2.17", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", @@ -1469,6 +1766,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/table": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/table/-/table-5.0.0.tgz", + "integrity": "sha512-fQLtGLZXor264zUPWI95WNDsZ3QV43/c0lJpR/h1hhLJumXRmHNsrvBfEzW2YMhb0EWCsn4U6h82IgwsajAuTA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/three": { "version": "0.185.1", "resolved": "https://registry.npmjs.org/@types/three/-/three-0.185.1.tgz", @@ -1484,6 +1788,20 @@ "meshoptimizer": "~1.1.1" } }, + "node_modules/@types/tmp": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.6.tgz", + "integrity": "sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/webxr": { "version": "0.5.24", "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.24.tgz", @@ -1496,6 +1814,13 @@ "integrity": "sha512-ggMz8nOygG7d/stpH40WVaNvBwuyYLnrg5Mbyf6bmsj/8+gb6Ei4ZZ9/4PNpcPNTT8th9Q8sM8wYmWGjMWLX/A==", "license": "MIT" }, + "node_modules/@types/wrap-ansi": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@types/wrap-ansi/-/wrap-ansi-8.0.2.tgz", + "integrity": "sha512-mdaFibQzYYqJF8Sc9By84eBLtDQD9Hnko0yXuezHBU5f5KdtQk+j5hPRQc1j4ayzdqGddKON6PjeuzxD5U1hPg==", + "dev": true, + "license": "MIT" + }, "node_modules/@vercel/analytics": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-2.0.1.tgz", @@ -1591,6 +1916,39 @@ "node": ">=10.0.0" } }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "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-escapes": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", + "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", @@ -1623,6 +1981,30 @@ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", "license": "MIT" }, + "node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -1655,14 +2037,37 @@ "node": ">=6.0.0" } }, - "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" + "node_modules/brace-expansion": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz", + "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/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", @@ -1699,6 +2104,56 @@ ], "license": "CC-BY-4.0" }, + "node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/chalk/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/chalk/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, "node_modules/chromium-bidi": { "version": "16.0.1", "resolved": "https://registry.npmjs.org/chromium-bidi/-/chromium-bidi-16.0.1.tgz", @@ -1716,6 +2171,110 @@ "devtools-protocol": "*" } }, + "node_modules/cli-cursor": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-table3/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-table3/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-table3/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-table3/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-table3/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-truncate": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -1737,6 +2296,63 @@ "node": ">=20" } }, + "node_modules/color": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/color/-/color-5.0.3.tgz", + "integrity": "sha512-ezmVcLR3xAVp8kYOm4GS45ZLLgIE6SPAFoduLr6hTDajwb3KZ2F46gulK3XpcwRFb5KKGCSezCBAY4Dw4HsyXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^3.1.3", + "color-string": "^2.1.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/color-convert": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.3.tgz", + "integrity": "sha512-fasDH2ont2GqF5HpyO4w0+BcewlhHEZOFn9c1ckZdHpJ56Qb7MHhH/IcJZbBGgvdtwdwNbLvxiBEdg336iA9Sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=14.6" + } + }, + "node_modules/color-name": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-2.1.1.tgz", + "integrity": "sha512-p2FdgwVx1a9yWBHP2wI0VgShkDpgN4kZISkxdNipGBJWpa5G6b04OINlVWCyJj0JmfvcPrgqt95E9k8yvaOJFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/color-string": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-2.1.4.tgz", + "integrity": "sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -1752,18 +2368,50 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "license": "MIT" }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "license": "MIT" }, + "node_modules/csv-stringify": { + "version": "6.8.3", + "resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-6.8.3.tgz", + "integrity": "sha512-gIeSCvq5F4VtXV3naV3VAewLhBkiZBz+PPhTOA8H3Y8h/ELa+R1ml0GZck/4/Nzo9ep2lvOluilJ6MJlbZsKMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/cwise-compiler": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/cwise-compiler/-/cwise-compiler-1.1.3.tgz", + "integrity": "sha512-WXlK/m+Di8DMMcCjcWr4i+XzcQra9eCdXIJrgh4TUgh0pIS/yJduLxS9JgefsHJ/YVLdgPtXm9r62W92MvanEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "uniq": "^1.0.0" + } + }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "devOptional": true, "license": "Apache-2.0", - "optional": true, "engines": { "node": ">=8" } @@ -1775,12 +2423,26 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/draco3dgltf": { + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/draco3dgltf/-/draco3dgltf-1.5.7.tgz", + "integrity": "sha512-LeqcpmoHIyYUi0z70/H3tMkGj8QhqVxq6FJGPjlzR24BNkQ6jyMheMvFKJBI0dzGZrEOUyQEmZ8axM1xRrbRiw==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/earcut": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.2.3.tgz", "integrity": "sha512-vnS4AVwp1KHAF13i1vp1/2D5evWy3k5u/iW/B81QVsUZtV8cv2tU0b2VNFlqvh4kYwrFMDdjPCfAmfyJW9y14Q==", "license": "ISC" }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, "node_modules/emoji-regex": { "version": "10.6.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", @@ -1788,6 +2450,26 @@ "dev": true, "license": "MIT" }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/environment": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", + "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/esbuild": { "version": "0.28.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", @@ -1846,6 +2528,20 @@ "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", "license": "MIT" }, + "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, + "license": "MIT" + }, + "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, + "license": "MIT" + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -1863,6 +2559,13 @@ } } }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==", + "dev": true, + "license": "MIT" + }, "node_modules/fflate": { "version": "0.8.3", "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.3.tgz", @@ -1870,6 +2573,43 @@ "dev": true, "license": "MIT" }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -1908,6 +2648,45 @@ "js-binary-schema-parser": "^2.0.3" } }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/gltf-validator": { + "version": "2.0.0-dev.3.10", + "resolved": "https://registry.npmjs.org/gltf-validator/-/gltf-validator-2.0.0-dev.3.10.tgz", + "integrity": "sha512-odJ4k0tRkGXiDGn78yDBg+fBbAIvBnXxh3RwAta0emSxGtyagFE8B4xELB1oYe3S5RD8Ci3uZAsZaascH2LAEQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -1940,36 +2719,116 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, - "node_modules/isarray": { + "node_modules/iota-array": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "resolved": "https://registry.npmjs.org/iota-array/-/iota-array-1.0.0.tgz", + "integrity": "sha512-pZ2xT+LOHckCatGQ3DcG/a+QuEqvoxqkiL7tvE8nn3uuu+f6i1TtpB5/FtWFbxUuVr5PZCx8KskuGatbJDXOWA==", + "dev": true, "license": "MIT" }, - "node_modules/ismobilejs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-1.1.1.tgz", - "integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw==", + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, "license": "MIT" }, - "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==", + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, "license": "MIT", - "dependencies": { - "@types/react-reconciler": "^0.28.9" + "engines": { + "node": ">=12" }, - "peerDependencies": { - "react": "^19.0.0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/js-binary-schema-parser": { + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/ismobilejs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-1.1.1.tgz", + "integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw==", + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "@types/react-reconciler": "^0.28.9" + }, + "peerDependencies": { + "react": "^19.0.0" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-binary-schema-parser": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/js-binary-schema-parser/-/js-binary-schema-parser-2.0.3.tgz", "integrity": "sha512-xezGJmOb4lk/M1ZZLTR/jaBHQ4gG/lqQnJqdIv4721DMggsa1bDVlHXNeHYogaIEHD9vCRv0fcL4hMA+Coarkg==", "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, + "license": "MIT" + }, "node_modules/jszip": { "version": "3.10.1", "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", @@ -1982,6 +2841,37 @@ "setimmediate": "^1.0.5" } }, + "node_modules/keyframe-resample": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/keyframe-resample/-/keyframe-resample-0.1.0.tgz", + "integrity": "sha512-z1au6Q6qCWP734q44t/5SyGwNydC7MvOWo2ZETAz7ZqAgtcyb5EGO7jwgk3DEH7CaDtb0DkGec9iwVpeDWX5dA==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ktx-parse": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ktx-parse/-/ktx-parse-1.1.0.tgz", + "integrity": "sha512-mKp3y+FaYgR7mXWAbyyzpa/r1zDWeaunH+INJO4fou3hb45XuNSwar+7llrRyvpMWafxSIi99RNFJ05MHedaJQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==", + "dev": true, + "license": "MIT" + }, "node_modules/lie": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", @@ -1997,6 +2887,119 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, + "node_modules/listr2": { + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", + "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^4.0.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^6.1.0", + "rfdc": "^1.4.1", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", + "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "cli-cursor": "^5.0.0", + "slice-ansi": "^7.1.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", + "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-east-asian-width": "^1.3.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", + "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "is-fullwidth-code-point": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/logform": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.7.0.tgz", + "integrity": "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/logform/node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/mediabunny": { "version": "1.54.0", "resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.54.0.tgz", @@ -2028,6 +3031,79 @@ "dev": true, "license": "MIT" }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mikktspace": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/mikktspace/-/mikktspace-1.1.1.tgz", + "integrity": "sha512-w+n5O2YLFsv/aRi3QUF0jxR+mEsl2J08ZkRItJHE08MWqiDIy8amyZN9vetBfbLhlWGMb8G3mzSPwtKHvBF7hQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", @@ -2056,6 +3132,13 @@ "@types/wicg-file-system-access": "^2020.9.5" } }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, "node_modules/mz": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", @@ -2085,6 +3168,51 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/ndarray": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ndarray/-/ndarray-1.1.1.tgz", + "integrity": "sha512-AsE8w/M2MS+0pD3nP5qbRRtJFeJJJaJ+qXZaZr0XjVGXhy6LIj2TERTlkpdK2AI3WufoOP+pwPk3q2ilAJcZ9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "iota-array": "^1.0.0", + "is-buffer": "^1.0.2" + } + }, + "node_modules/ndarray-lanczos": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ndarray-lanczos/-/ndarray-lanczos-0.3.0.tgz", + "integrity": "sha512-5kBmmG3Zvyj77qxIAC4QFLKuYdDIBJwCG+DukT6jQHNa1Ft74/hPH1z5mbQXeHBt8yvGPBGVrr3wEOdJPYYZYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ndarray": "^1.0.11", + "ndarray": "^1.0.19" + } + }, + "node_modules/ndarray-ops": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ndarray-ops/-/ndarray-ops-1.2.2.tgz", + "integrity": "sha512-BppWAFRjMYF7N/r6Ie51q6D4fs0iiGmeXIACKY66fLpnwIui3Wc3CXiD/30mgLbDjPpSLrsqcp3Z62+IcHZsDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cwise-compiler": "^1.0.0" + } + }, + "node_modules/ndarray-pixels": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ndarray-pixels/-/ndarray-pixels-5.2.0.tgz", + "integrity": "sha512-lTh4tFKziAatVTa9crIsidUyn+lqujVOQpzfdBWvdFu2wo9Uo6z261lVX7SgMyP89xGmj3TMTPbbxl9YDnV4SA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ndarray": "^1.0.14", + "ndarray": "^1.0.19", + "ndarray-ops": "^1.2.2", + "sharp": "^0.35.0" + } + }, "node_modules/next": { "version": "16.3.4", "resolved": "https://registry.npmjs.org/next/-/next-16.3.4.tgz", @@ -2147,6 +3275,39 @@ "node": ">=0.10.0" } }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fn.name": "1.x.x" + } + }, + "node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/pako": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", @@ -2159,6 +3320,33 @@ "integrity": "sha512-Tf7FFIrguPKQwzD4pWnYkR2VOv3raoHeKED80Bm+BYHI3KxC8KsgsGC5+fSMzAGDA6UEk4bHvmi+RsjmL3khpg==", "license": "MIT" }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -2259,6 +3447,37 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "license": "MIT" }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/property-graph": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/property-graph/-/property-graph-4.1.0.tgz", + "integrity": "sha512-AvPcP7XECNWy4LGmFQ77k7un4lSKM4eS29PTvW4ck95uYeLxXPWJM7hLuBqK91FaHqCcgJvIUCuNJjjxKE7VKQ==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/puppeteer-core": { "version": "25.3.0", "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-25.3.0.tgz", @@ -2349,12 +3568,46 @@ "util-deprecate": "~1.0.1" } }, - "node_modules/safe-buffer": { + "node_modules/restore-cursor": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, + "node_modules/safe-stable-stringify": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz", + "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/scheduler": { "version": "0.27.0", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", @@ -2365,8 +3618,8 @@ "version": "7.8.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "devOptional": true, "license": "ISC", - "optional": true, "bin": { "semver": "bin/semver.js" }, @@ -2384,8 +3637,8 @@ "version": "0.35.4", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.4.tgz", "integrity": "sha512-n++8XWcj+jCOr2IOl7h8LbKnGBDY4aPbmprMONBNFdn0ImXqpGVv5zliDs0V9HbmbCQLpbuo2ej9rAoOQTvMDA==", + "devOptional": true, "license": "Apache-2.0", - "optional": true, "dependencies": { "@img/colour": "^1.1.0", "detect-libc": "^2.1.2", @@ -2430,6 +3683,66 @@ } } }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -2439,6 +3752,16 @@ "node": ">=0.10.0" } }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -2466,6 +3789,62 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-ansi": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", @@ -2482,6 +3861,30 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/styled-jsx": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", @@ -2527,6 +3930,19 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/suspend-react": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/suspend-react/-/suspend-react-0.1.3.tgz", @@ -2536,6 +3952,129 @@ "react": ">=17.0" } }, + "node_modules/table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/table/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/table/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/table/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/table/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/table/node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true, + "license": "MIT" + }, + "node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/table/node_modules/slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/table/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/table/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==", + "dev": true, + "license": "MIT" + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", @@ -2588,6 +4127,39 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/tmp": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -2628,6 +4200,23 @@ "dev": true, "license": "MIT" }, + "node_modules/uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "BSD-2-Clause", + "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", @@ -2643,6 +4232,13 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, + "node_modules/watlas": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/watlas/-/watlas-1.0.1.tgz", + "integrity": "sha512-TmB++BFqEQY19cPNby5iszACZd8t6uauB7YdObkqhWarhed79OMPS8wufoDSo0p85A/8QW/aqZwEJf+nD4emSw==", + "dev": true, + "license": "MIT" + }, "node_modules/webdriver-bidi-protocol": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/webdriver-bidi-protocol/-/webdriver-bidi-protocol-0.4.2.tgz", @@ -2650,6 +4246,90 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/winston": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.10.0.tgz", + "integrity": "sha512-nT6SIDaE9B7ZRO0u3UvdrimG0HkB7dSTAgInQnNR2SOPJ4bvq5q79+pXLftKmP52lJGW15+H5MCK0nM9D3KB/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@colors/colors": "1.5.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.4.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.9.0.tgz", + "integrity": "sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "logform": "^2.7.0", + "readable-stream": "^3.6.2", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/winston/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/wrap-ansi": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", @@ -2668,6 +4348,116 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ws": { "version": "8.21.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.1.tgz", diff --git a/package.json b/package.json index 428cc32..9e64b4d 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "zustand": "^5.0.14" }, "devDependencies": { + "@gltf-transform/cli": "^4.5.0", "@types/node": "^26.1.1", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", diff --git a/public/3d/web-devices/ipadpro.glb b/public/3d/web-devices/ipadpro.glb new file mode 100644 index 0000000000000000000000000000000000000000..3c1584916244a65fe4908f68ba6d7075a17213c4 GIT binary patch literal 2277948 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