From c1e12a41fb9c7605a35180bac688afc25304b673 Mon Sep 17 00:00:00 2001 From: Source Open Date: Wed, 1 Apr 2026 17:33:42 -0700 Subject: [PATCH] feat(ui): add shared seeded paper gradients (#1288) * feat(ui): add shared seeded paper gradients Centralize the Paper mesh and grain wrappers so React and Solid apps can reuse the same deterministic seed-based visuals without repeating shader config. Add a standalone demo surface and update existing consumers so the shared package is easier to validate and evolve. * fix(ui): resolve shared package from source Point the shared UI package exports at source files so Next builds do not depend on a prebuilt dist directory. Add Next transpilation for @openwork/ui in Landing and Den Web so monorepo and Vercel builds resolve the package consistently. --------- Co-authored-by: src-opn --- apps/app/package.json | 4 + apps/share/package.json | 1 - apps/ui-demo/index.html | 12 + apps/ui-demo/package.json | 24 + apps/ui-demo/src/app.tsx | 216 +++++ apps/ui-demo/src/main.tsx | 10 + apps/ui-demo/src/styles.css | 343 +++++++ apps/ui-demo/tsconfig.json | 17 + apps/ui-demo/vite.config.ts | 19 + .../app/(den)/_components/auth-screen.tsx | 5 +- .../_components/background-agents-screen.tsx | 5 +- .../custom-llm-providers-screen.tsx | 5 +- ee/apps/den-web/next.config.js | 1 + ee/apps/den-web/package.json | 4 +- .../landing/components/responsive-grain.tsx | 50 +- ee/apps/landing/next.config.js | 1 + ee/apps/landing/package.json | 3 +- package.json | 1 + packages/ui/README.md | 39 + packages/ui/package.json | 38 + packages/ui/src/common/paper.ts | 416 +++++++++ packages/ui/src/react/index.ts | 17 + .../ui/src/react/paper/grain-gradient.tsx | 101 ++ packages/ui/src/react/paper/mesh-gradient.tsx | 61 ++ packages/ui/src/solid/index.ts | 17 + .../ui/src/solid/paper/grain-gradient.tsx | 125 +++ packages/ui/src/solid/paper/mesh-gradient.tsx | 104 +++ packages/ui/src/solid/paper/shader-mount.tsx | 115 +++ packages/ui/tsconfig.react.json | 19 + packages/ui/tsconfig.solid.json | 20 + packages/ui/tsup.config.ts | 46 + pnpm-lock.yaml | 872 ++++++------------ 32 files changed, 2059 insertions(+), 652 deletions(-) create mode 100644 apps/ui-demo/index.html create mode 100644 apps/ui-demo/package.json create mode 100644 apps/ui-demo/src/app.tsx create mode 100644 apps/ui-demo/src/main.tsx create mode 100644 apps/ui-demo/src/styles.css create mode 100644 apps/ui-demo/tsconfig.json create mode 100644 apps/ui-demo/vite.config.ts create mode 100644 packages/ui/README.md create mode 100644 packages/ui/package.json create mode 100644 packages/ui/src/common/paper.ts create mode 100644 packages/ui/src/react/index.ts create mode 100644 packages/ui/src/react/paper/grain-gradient.tsx create mode 100644 packages/ui/src/react/paper/mesh-gradient.tsx create mode 100644 packages/ui/src/solid/index.ts create mode 100644 packages/ui/src/solid/paper/grain-gradient.tsx create mode 100644 packages/ui/src/solid/paper/mesh-gradient.tsx create mode 100644 packages/ui/src/solid/paper/shader-mount.tsx create mode 100644 packages/ui/tsconfig.react.json create mode 100644 packages/ui/tsconfig.solid.json create mode 100644 packages/ui/tsup.config.ts diff --git a/apps/app/package.json b/apps/app/package.json index 3fe3a46b..3341a3ea 100644 --- a/apps/app/package.json +++ b/apps/app/package.json @@ -6,10 +6,13 @@ "scripts": { "dev": "OPENWORK_DEV_MODE=1 vite", "dev:windows": "vite", + "prebuild": "pnpm --dir ../../packages/ui build", "build": "vite build", "dev:web": "OPENWORK_DEV_MODE=1 vite", + "prebuild:web": "pnpm --dir ../../packages/ui build", "build:web": "vite build", "preview": "vite preview", + "pretypecheck": "pnpm --dir ../../packages/ui build", "typecheck": "tsc -p tsconfig.json --noEmit", "test:health": "node scripts/health.mjs", "test:mention-send": "node scripts/mention-send.mjs", @@ -32,6 +35,7 @@ "bump:set": "node scripts/bump-version.mjs --set" }, "dependencies": { + "@openwork/ui": "workspace:*", "@codemirror/commands": "^6.8.0", "@codemirror/lang-markdown": "^6.3.3", "@codemirror/language": "^6.11.0", diff --git a/apps/share/package.json b/apps/share/package.json index 79a26f4e..1d7083eb 100644 --- a/apps/share/package.json +++ b/apps/share/package.json @@ -11,7 +11,6 @@ "test:e2e": "playwright test" }, "dependencies": { - "@paper-design/shaders-react": "0.0.71", "@vercel/blob": "^0.27.0", "botid": "^1.5.11", "jsonc-parser": "^3.3.1", diff --git a/apps/ui-demo/index.html b/apps/ui-demo/index.html new file mode 100644 index 00000000..66f28a9a --- /dev/null +++ b/apps/ui-demo/index.html @@ -0,0 +1,12 @@ + + + + + + OpenWork UI Demo + + +
+ + + diff --git a/apps/ui-demo/package.json b/apps/ui-demo/package.json new file mode 100644 index 00000000..2cb9bde6 --- /dev/null +++ b/apps/ui-demo/package.json @@ -0,0 +1,24 @@ +{ + "name": "@openwork/ui-demo", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "pnpm --dir ../../packages/ui build && vite --host 0.0.0.0 --port 3333 --strictPort", + "build": "pnpm --dir ../../packages/ui build && vite build", + "preview": "vite preview --host 0.0.0.0 --port 3333 --strictPort", + "typecheck": "pnpm --dir ../../packages/ui build && tsc -p tsconfig.json --noEmit" + }, + "dependencies": { + "@openwork/ui": "workspace:*", + "react": "19.2.4", + "react-dom": "19.2.4" + }, + "devDependencies": { + "@types/react": "19.2.14", + "@types/react-dom": "19.2.3", + "@vitejs/plugin-react": "^5.0.4", + "typescript": "^5.9.3", + "vite": "^7.1.12" + } +} diff --git a/apps/ui-demo/src/app.tsx b/apps/ui-demo/src/app.tsx new file mode 100644 index 00000000..76a3ff72 --- /dev/null +++ b/apps/ui-demo/src/app.tsx @@ -0,0 +1,216 @@ +import { + PaperGrainGradient, + PaperMeshGradient, + getSeededPaperGrainGradientConfig, + getSeededPaperMeshGradientConfig, +} from "@openwork/ui/react" +import { useMemo, useState } from "react" + +const sampleIds = [ + "om_01kmhbscaze02vp04ykqa4tcsb", + "om_01kmhbscazf4cjf1bssx6v9q9", + "ow_01kmj2wc68r1zk4n8v7j6v1n2k", +] + +export function App() { + const [seed, setSeed] = useState(sampleIds[0]) + const normalizedSeed = seed.trim() || sampleIds[0] + const parsedSeed = parseTypeId(normalizedSeed) + const meshConfig = useMemo(() => getSeededPaperMeshGradientConfig(normalizedSeed), [normalizedSeed]) + const grainConfig = useMemo(() => getSeededPaperGrainGradientConfig(normalizedSeed), [normalizedSeed]) + + return ( +
+
+
+ +
+
+ OpenWork UI demo +

Seeded Paper gradients on their own dev surface

+

+ Type a TypeID-like string, inspect the deterministic values derived from it, and preview + the gradients that `@openwork/ui/react` will render anywhere else in the repo. +

+
+ +
+ Deterministic + Same seed, same result. +

Useful for stable identity-driven art direction across apps.

+
+
+ +
+
+ + setSeed(event.target.value)} + spellCheck={false} + /> + +
+ {sampleIds.map((sampleId) => ( + + ))} +
+
+ +
+ + + + +
+
+ +
+ } + /> + + } + /> +
+ +
+
+ Determinism check +
+ + + + + + +
+

+ These two cards use the same seed and should always match. +

+
+ +
+ Import paths +
+ @openwork/ui/react + @openwork/ui/solid +
+
{`import { PaperMeshGradient, PaperGrainGradient } from "@openwork/ui/react"
+
+
+`}
+
+
+
+ ) +} + +function GradientCard({ + title, + subtitle, + colors, + config, + surface, +}: { + title: string + subtitle: string + colors: string[] + config: Record + surface: React.ReactNode +}) { + return ( +
+
+ {surface} +
+
+ @openwork/ui/react +

{title}

+

{subtitle}

+
+
+ +
+
+ Colors +
+ {colors.map((color) => ( +
+ + {color} +
+ ))} +
+
+ +
+ Calculated values +
{JSON.stringify(config, null, 2)}
+
+
+
+ ) +} + +function MiniPreview({ title, children }: { title: string; children: React.ReactNode }) { + return ( +
+ {title} +
{children}
+
+ ) +} + +function SeedMeta({ label, value }: { label: string; value: string }) { + return ( +
+ {label} + {value} +
+ ) +} + +function parseTypeId(value: string) { + const separatorIndex = value.indexOf("_") + + if (separatorIndex === -1) { + return { + prefix: null, + suffix: value, + suffixAnchor: value.slice(0, 5) || null, + suffixTail: value.slice(5) || null, + } + } + + const prefix = value.slice(0, separatorIndex) || null + const suffix = value.slice(separatorIndex + 1) || null + + return { + prefix, + suffix, + suffixAnchor: suffix?.slice(0, 5) || null, + suffixTail: suffix?.slice(5) || null, + } +} diff --git a/apps/ui-demo/src/main.tsx b/apps/ui-demo/src/main.tsx new file mode 100644 index 00000000..8624da88 --- /dev/null +++ b/apps/ui-demo/src/main.tsx @@ -0,0 +1,10 @@ +import React from "react" +import ReactDOM from "react-dom/client" +import { App } from "./app" +import "./styles.css" + +ReactDOM.createRoot(document.getElementById("root")!).render( + + + , +) diff --git a/apps/ui-demo/src/styles.css b/apps/ui-demo/src/styles.css new file mode 100644 index 00000000..69007a89 --- /dev/null +++ b/apps/ui-demo/src/styles.css @@ -0,0 +1,343 @@ +:root { + color-scheme: light; + font-family: "IBM Plex Sans", "Inter", system-ui, sans-serif; + background: + radial-gradient(circle at top left, rgba(57, 181, 74, 0.16), transparent 28%), + radial-gradient(circle at top right, rgba(39, 98, 255, 0.14), transparent 30%), + linear-gradient(180deg, #f6f1e8 0%, #efe7d7 100%); + color: #1f2c2b; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + min-width: 320px; +} + +button, +input, +textarea, +select { + font: inherit; +} + +code, +pre, +.sample-chip, +.seed-input { + font-family: "IBM Plex Mono", "SFMono-Regular", ui-monospace, monospace; +} + +.app-shell { + position: relative; + min-height: 100vh; + padding: 32px; + overflow: hidden; +} + +.ambient { + position: fixed; + pointer-events: none; + border-radius: 999px; + filter: blur(70px); + opacity: 0.45; +} + +.ambient-a { + top: -120px; + left: -80px; + width: 320px; + height: 320px; + background: rgba(76, 175, 80, 0.22); +} + +.ambient-b { + right: -80px; + bottom: 80px; + width: 280px; + height: 280px; + background: rgba(59, 130, 246, 0.2); +} + +.panel { + position: relative; + border: 1px solid rgba(24, 30, 28, 0.08); + background: rgba(255, 251, 245, 0.82); + backdrop-filter: blur(18px); + border-radius: 28px; + box-shadow: 0 24px 80px -48px rgba(29, 24, 17, 0.45); +} + +.hero-card { + display: grid; + gap: 24px; + grid-template-columns: minmax(0, 1.5fr) minmax(260px, 0.8fr); + padding: 32px; +} + +.hero-copy h1 { + margin: 10px 0 0; + font-size: clamp(2.4rem, 6vw, 4.5rem); + line-height: 0.92; + letter-spacing: -0.08em; +} + +.hero-copy p, +.rule-card p, +.support-copy, +.surface-copy p { + margin: 0; + color: #516160; + line-height: 1.7; +} + +.hero-copy p { + margin-top: 18px; + max-width: 62ch; +} + +.rule-card { + align-self: end; + padding: 20px; + border-radius: 24px; + background: #16201f; + color: #f0f7f3; +} + +.rule-card p { + margin-top: 8px; + color: rgba(240, 247, 243, 0.74); +} + +.eyebrow { + display: inline-block; + font-size: 0.72rem; + font-weight: 700; + letter-spacing: 0.18em; + text-transform: uppercase; +} + +.muted { + color: #6d7a79; +} + +.on-dark { + color: rgba(255, 255, 255, 0.68); +} + +.controls-grid, +.footer-grid { + display: grid; + gap: 24px; + grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.95fr); + margin-top: 24px; +} + +.input-panel, +.seed-meta-grid, +.code-panel { + padding: 24px; +} + +.seed-input { + width: 100%; + margin-top: 10px; + padding: 15px 16px; + border-radius: 20px; + border: 1px solid rgba(22, 32, 31, 0.12); + background: rgba(255, 255, 255, 0.92); + color: #182321; + font-size: 0.92rem; + outline: none; + transition: border-color 120ms ease, box-shadow 120ms ease; +} + +.seed-input:focus { + border-color: #287d75; + box-shadow: 0 0 0 5px rgba(40, 125, 117, 0.12); +} + +.sample-list { + display: flex; + flex-wrap: wrap; + gap: 10px; + margin-top: 16px; +} + +.sample-chip { + border: 1px solid rgba(22, 32, 31, 0.1); + background: rgba(255, 255, 255, 0.75); + color: #425251; + border-radius: 999px; + padding: 9px 14px; + cursor: pointer; +} + +.sample-chip.active { + background: #1f6978; + color: white; + border-color: #1f6978; +} + +.seed-meta-grid { + display: grid; + gap: 12px; + grid-template-columns: repeat(2, minmax(0, 1fr)); + background: #16201f; +} + +.seed-meta-card { + padding: 18px; + border-radius: 20px; + border: 1px solid rgba(255, 255, 255, 0.08); + background: rgba(255, 255, 255, 0.04); +} + +.seed-meta-card code { + display: block; + margin-top: 8px; + color: #f4fbf7; + word-break: break-all; + line-height: 1.6; +} + +.preview-grid { + display: grid; + gap: 24px; + grid-template-columns: repeat(2, minmax(0, 1fr)); + margin-top: 24px; +} + +.preview-card { + overflow: hidden; +} + +.gradient-surface { + position: relative; + min-height: 340px; + background: #101818; +} + +.gradient-fill { + position: absolute; + inset: 0; +} + +.surface-overlay { + position: absolute; + inset: 0; + background: linear-gradient(180deg, rgba(10, 18, 18, 0.08), rgba(10, 18, 18, 0.34)); +} + +.surface-copy { + position: absolute; + inset-inline: 0; + bottom: 0; + padding: 24px; + color: white; +} + +.surface-copy h2 { + margin: 10px 0 0; + font-size: 2rem; + letter-spacing: -0.05em; +} + +.surface-copy p { + margin-top: 10px; + color: rgba(255, 255, 255, 0.78); +} + +.details-stack { + display: grid; + gap: 20px; + padding: 24px; +} + +.swatch-list, +.pill-stack { + display: flex; + flex-wrap: wrap; + gap: 10px; + margin-top: 14px; +} + +.swatch-pill, +.import-pill { + display: inline-flex; + align-items: center; + gap: 10px; + border-radius: 999px; + border: 1px solid rgba(22, 32, 31, 0.08); + background: rgba(248, 243, 235, 0.9); + padding: 10px 14px; +} + +.swatch-dot { + width: 14px; + height: 14px; + border-radius: 999px; + border: 1px solid rgba(0, 0, 0, 0.12); +} + +pre { + overflow-x: auto; + margin: 14px 0 0; + border-radius: 22px; + background: #16201f; + color: #dcebe4; + padding: 18px; + font-size: 0.8rem; + line-height: 1.7; +} + +.mini-grid { + display: grid; + gap: 16px; + grid-template-columns: repeat(2, minmax(0, 1fr)); + margin-top: 16px; +} + +.mini-surface { + position: relative; + min-height: 180px; + margin-top: 8px; + overflow: hidden; + border-radius: 22px; + background: #111918; +} + +.support-copy { + margin-top: 16px; +} + +@media (max-width: 980px) { + .hero-card, + .controls-grid, + .preview-grid, + .footer-grid { + grid-template-columns: 1fr; + } +} + +@media (max-width: 640px) { + .app-shell { + padding: 18px; + } + + .hero-card, + .input-panel, + .seed-meta-grid, + .code-panel, + .details-stack { + padding: 18px; + } + + .seed-meta-grid, + .mini-grid { + grid-template-columns: 1fr; + } +} diff --git a/apps/ui-demo/tsconfig.json b/apps/ui-demo/tsconfig.json new file mode 100644 index 00000000..2957d0df --- /dev/null +++ b/apps/ui-demo/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": true, + "module": "ESNext", + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "jsx": "react-jsx", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "strict": true, + "skipLibCheck": true, + "types": ["vite/client"] + }, + "include": ["src", "vite.config.ts"] +} diff --git a/apps/ui-demo/vite.config.ts b/apps/ui-demo/vite.config.ts new file mode 100644 index 00000000..4f3f02a3 --- /dev/null +++ b/apps/ui-demo/vite.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from "vite" +import react from "@vitejs/plugin-react" + +export default defineConfig({ + plugins: [react()], + server: { + host: "0.0.0.0", + port: 3333, + strictPort: true, + }, + preview: { + host: "0.0.0.0", + port: 3333, + strictPort: true, + }, + build: { + target: "es2022", + }, +}) diff --git a/ee/apps/den-web/app/(den)/_components/auth-screen.tsx b/ee/apps/den-web/app/(den)/_components/auth-screen.tsx index 60de4d31..b4667e8d 100644 --- a/ee/apps/den-web/app/(den)/_components/auth-screen.tsx +++ b/ee/apps/den-web/app/(den)/_components/auth-screen.tsx @@ -1,6 +1,7 @@ "use client"; -import { Dithering, MeshGradient } from "@paper-design/shaders-react"; +import { PaperMeshGradient } from "@openwork/ui/react"; +import { Dithering } from "@paper-design/shaders-react"; import { ArrowRight, CheckCircle2 } from "lucide-react"; import { usePathname, useRouter } from "next/navigation"; import { useEffect, useRef, useState } from "react"; @@ -184,7 +185,7 @@ export function AuthScreen() { colorFront="#FEFEFE" style={{ backgroundColor: "#142033", width: "100%", height: "100%" }} > - - - (null); - const [dimensions, setDimensions] = useState({ width: 0, height: 0 }); - - useEffect(() => { - if (!containerRef.current) return; - - const observer = new ResizeObserver((entries) => { - for (const entry of entries) { - setDimensions({ - width: entry.contentRect.width, - height: entry.contentRect.height - }); - } - }); - - observer.observe(containerRef.current); - return () => observer.disconnect(); - }, []); - return ( -
- {dimensions.width > 0 && dimensions.height > 0 ? ( - - ) : null} -
+ seed={props.seed} + colors={props.colors} + colorBack={props.colorBack} + softness={props.softness} + intensity={props.intensity} + noise={props.noise} + shape={props.shape} + speed={props.speed} + /> ); } diff --git a/ee/apps/landing/next.config.js b/ee/apps/landing/next.config.js index f0c4686b..3bd3d638 100644 --- a/ee/apps/landing/next.config.js +++ b/ee/apps/landing/next.config.js @@ -5,6 +5,7 @@ const mintlifyOrigin = "https://differentai.mintlify.dev"; const nextConfig = { reactStrictMode: true, + transpilePackages: ["@openwork/ui"], async rewrites() { return [ { diff --git a/ee/apps/landing/package.json b/ee/apps/landing/package.json index b15973bc..c7ef5350 100644 --- a/ee/apps/landing/package.json +++ b/ee/apps/landing/package.json @@ -4,12 +4,13 @@ "version": "0.0.0", "scripts": { "dev": "OPENWORK_DEV_MODE=1 next dev --hostname 0.0.0.0", + "prebuild": "pnpm --dir ../../../packages/ui build", "build": "next build", "start": "next start --hostname 0.0.0.0", "lint": "next lint" }, "dependencies": { - "@paper-design/shaders-react": "0.0.71", + "@openwork/ui": "workspace:*", "botid": "^1.5.11", "framer-motion": "^12.35.1", "lucide-react": "^0.577.0", diff --git a/package.json b/package.json index 9da01728..d14d067f 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "dev:windows": ".\\scripts\\dev-windows.cmd", "dev:windows:x64": ".\\scripts\\dev-windows.cmd x64", "dev:ui": "OPENWORK_DEV_MODE=1 pnpm --filter @openwork/app dev", + "dev:ui-demo": "pnpm --filter @openwork/ui-demo dev", "dev:story": "OPENWORK_DEV_MODE=1 pnpm --filter @openwork/story-book dev", "dev:web": "OPENWORK_DEV_MODE=1 pnpm --filter @openwork-ee/den-web dev", "dev:web-local": "pnpm dev:den-local", diff --git a/packages/ui/README.md b/packages/ui/README.md new file mode 100644 index 00000000..4c21a033 --- /dev/null +++ b/packages/ui/README.md @@ -0,0 +1,39 @@ +# @openwork/ui + +Shared UI primitives for OpenWork apps. + +This package intentionally ships two framework-specific entrypoints: + +- `@openwork/ui/react` for React apps like `ee/apps/den-web` +- `@openwork/ui/solid` for Solid apps like `apps/app` + +The public API should stay aligned across both entrypoints. If you add a new component, add both implementations in the same task unless there is a documented blocker. + +## Paper components + +The first shared components live under the `paper` namespace and wrap Paper Design shaders with OpenWork-specific defaults and deterministic seed support. + +Current components: + +- `PaperMeshGradient` +- `PaperGrainGradient` + +Both accept a `seed` prop. Pass a TypeID-like string such as `om_01kmhbscaze02vp04ykqa4tcsb` and the component will deterministically derive colors and shader params from it. The same seed always produces the same result. + +Explicit props still work and override the seeded values, so the merge order is: + +1. OpenWork defaults +2. Seed-derived values from `seed` +3. Explicit props passed by the caller + +## Layout convention + +These components default to `fill={true}`, which means they render at `width: 100%` and `height: 100%`. Put them inside a sized container and they will fill it without needing manual width or height props. + +## Agent notes + +- Shared seed logic lives in `src/common/paper.ts` +- React wrappers live in `src/react/paper/*` +- Solid wrappers live in `src/solid/paper/*` +- Keep the framework prop names aligned unless there is a hard runtime mismatch +- Prefer extending the existing seed helpers instead of inventing per-app one-off shader configs diff --git a/packages/ui/package.json b/packages/ui/package.json new file mode 100644 index 00000000..efedcd9c --- /dev/null +++ b/packages/ui/package.json @@ -0,0 +1,38 @@ +{ + "name": "@openwork/ui", + "private": true, + "type": "module", + "exports": { + "./react": { + "types": "./src/react/index.ts", + "development": "./src/react/index.ts", + "default": "./src/react/index.ts" + }, + "./solid": { + "types": "./src/solid/index.ts", + "development": "./src/solid/index.ts", + "default": "./src/solid/index.ts" + } + }, + "files": [ + "dist", + "src", + "README.md" + ], + "scripts": { + "build": "tsup" + }, + "dependencies": { + "@paper-design/shaders": "0.0.72", + "@paper-design/shaders-react": "0.0.72" + }, + "peerDependencies": { + "react": "^18 || ^19", + "solid-js": "^1.9.0" + }, + "devDependencies": { + "@types/react": "^19.2.14", + "tsup": "^8.5.0", + "typescript": "^5.6.3" + } +} diff --git a/packages/ui/src/common/paper.ts b/packages/ui/src/common/paper.ts new file mode 100644 index 00000000..37469a00 --- /dev/null +++ b/packages/ui/src/common/paper.ts @@ -0,0 +1,416 @@ +import type { + GrainGradientParams, + GrainGradientShape, + MeshGradientParams, +} from "@paper-design/shaders" + +export type PaperMeshGradientConfig = Required< + Pick< + MeshGradientParams, + "colors" | "distortion" | "swirl" | "grainMixer" | "grainOverlay" | "speed" | "frame" + > +> + +export type PaperGrainGradientConfig = Required< + Pick< + GrainGradientParams, + "colorBack" | "colors" | "softness" | "intensity" | "noise" | "shape" | "speed" | "frame" + > +> + +export type SeededPaperOption = { + seed?: string +} + +export const paperMeshGradientDefaults: PaperMeshGradientConfig = { + colors: ["#e0eaff", "#241d9a", "#f75092", "#9f50d3"], + distortion: 0.8, + swirl: 0.1, + grainMixer: 0, + grainOverlay: 0, + speed: 0.1, + frame: 0, +} + +export const paperGrainGradientDefaults: PaperGrainGradientConfig = { + colors: ["#7300ff", "#eba8ff", "#00bfff", "#2b00ff"], + colorBack: "#000000", + softness: 0.5, + intensity: 0.5, + noise: 0.25, + shape: "ripple", + speed: 0.4, + frame: 0, +} + +const grainShapes: GrainGradientShape[] = [ + "corners", + "wave", + "dots", + "truchet", + "ripple", + "blob", + "sphere", +] + +const meshPaletteFamilies = [ + ["#e0eaff", "#241d9a", "#f75092", "#9f50d3"], + ["#ddfff5", "#006c67", "#35d8c0", "#8cff7a"], + ["#ffe5c2", "#8a2500", "#ff7b39", "#ffd166"], + ["#f5f7ff", "#0d1b52", "#3f8cff", "#00c2ff"], + ["#fff2f2", "#6f1237", "#ff4d6d", "#ffb703"], + ["#f0ffe1", "#254d00", "#8cc63f", "#00a76f"], + ["#f5edff", "#44206b", "#b5179e", "#7209b7"], + ["#f4f1ea", "#3a2f1f", "#927c55", "#d0c2a8"], +] + +const grainPaletteFamilies = [ + ["#7300ff", "#eba8ff", "#00bfff", "#2b00ff"], + ["#0df2c1", "#0b7cff", "#74efff", "#1a2cff"], + ["#ff7a18", "#ffd166", "#ff4d6d", "#5f0f40"], + ["#8dff6a", "#1f7a1f", "#d7ff70", "#00c48c"], + ["#f6a6ff", "#7027c9", "#ff66c4", "#20115b"], + ["#b9ecff", "#006494", "#00a6a6", "#072ac8"], + ["#f7f0d6", "#8c5e34", "#d68c45", "#4e342e"], + ["#ffd9f5", "#ff006e", "#8338ec", "#3a0ca3"], +] + +const paletteModes = [ + { + hueOffsets: [0, 22, 182, 238], + saturations: [0.92, 0.7, 0.84, 0.74], + lightnesses: [0.82, 0.28, 0.6, 0.5], + }, + { + hueOffsets: [0, 118, 242, 304], + saturations: [0.88, 0.76, 0.82, 0.7], + lightnesses: [0.8, 0.42, 0.58, 0.48], + }, + { + hueOffsets: [0, 44, 156, 214], + saturations: [0.94, 0.78, 0.86, 0.72], + lightnesses: [0.78, 0.4, 0.6, 0.46], + }, + { + hueOffsets: [0, 76, 184, 326], + saturations: [0.86, 0.8, 0.78, 0.76], + lightnesses: [0.82, 0.52, 0.42, 0.58], + }, + { + hueOffsets: [0, 140, 196, 224], + saturations: [0.84, 0.7, 0.76, 0.88], + lightnesses: [0.86, 0.46, 0.36, 0.54], + }, + { + hueOffsets: [0, 162, 212, 342], + saturations: [0.9, 0.72, 0.8, 0.82], + lightnesses: [0.8, 0.38, 0.52, 0.56], + }, +] + +type MeshGradientOverrides = SeededPaperOption & Partial +type GrainGradientOverrides = SeededPaperOption & Partial + +export function getSeededPaperMeshGradientConfig(seed: string): PaperMeshGradientConfig { + const random = createRandom(seed, "mesh") + + return { + colors: createSeededPalette(paperMeshGradientDefaults.colors, seed, "mesh-colors", { + families: meshPaletteFamilies, + hueShift: 42, + saturationShift: 0.18, + lightnessShift: 0.14, + baseBlend: [0.08, 0.2], + }), + distortion: roundTo(clamp(0.58 + random() * 0.32, 0, 1), 3), + swirl: roundTo(clamp(0.03 + random() * 0.28, 0, 1), 3), + grainMixer: roundTo(clamp(random() * 0.18, 0, 1), 3), + grainOverlay: roundTo(clamp(random() * 0.12, 0, 1), 3), + speed: roundTo(0.05 + random() * 0.11, 3), + frame: Math.round(random() * 240000), + } +} + +export function getSeededPaperGrainGradientConfig(seed: string): PaperGrainGradientConfig { + const random = createRandom(seed, "grain") + const colors = createSeededPalette(paperGrainGradientDefaults.colors, seed, "grain-colors", { + families: grainPaletteFamilies, + hueShift: 58, + saturationShift: 0.22, + lightnessShift: 0.18, + baseBlend: [0.04, 0.14], + }) + const anchorColor = colors[Math.floor(random() * colors.length)] ?? colors[0] + + return { + colors, + colorBack: createSeededBackground(anchorColor, seed, "grain-background"), + softness: roundTo(clamp(0.22 + random() * 0.56, 0, 1), 3), + intensity: roundTo(clamp(0.2 + random() * 0.6, 0, 1), 3), + noise: roundTo(clamp(0.12 + random() * 0.34, 0, 1), 3), + shape: grainShapes[Math.floor(random() * grainShapes.length)] ?? paperGrainGradientDefaults.shape, + speed: roundTo(0.2 + random() * 0.6, 3), + frame: Math.round(random() * 320000), + } +} + +export function resolvePaperMeshGradientConfig( + options: MeshGradientOverrides = {}, +): PaperMeshGradientConfig { + const seeded = options.seed ? getSeededPaperMeshGradientConfig(options.seed) : paperMeshGradientDefaults + + return { + colors: options.colors ?? seeded.colors, + distortion: options.distortion ?? seeded.distortion, + swirl: options.swirl ?? seeded.swirl, + grainMixer: options.grainMixer ?? seeded.grainMixer, + grainOverlay: options.grainOverlay ?? seeded.grainOverlay, + speed: options.speed ?? seeded.speed, + frame: options.frame ?? seeded.frame, + } +} + +export function resolvePaperGrainGradientConfig( + options: GrainGradientOverrides = {}, +): PaperGrainGradientConfig { + const seeded = options.seed ? getSeededPaperGrainGradientConfig(options.seed) : paperGrainGradientDefaults + + return { + colors: options.colors ?? seeded.colors, + colorBack: options.colorBack ?? seeded.colorBack, + softness: options.softness ?? seeded.softness, + intensity: options.intensity ?? seeded.intensity, + noise: options.noise ?? seeded.noise, + shape: options.shape ?? seeded.shape, + speed: options.speed ?? seeded.speed, + frame: options.frame ?? seeded.frame, + } +} + +function buildSeedSource(seed: string) { + const trimmedSeed = seed.trim() + const separatorIndex = trimmedSeed.indexOf("_") + + if (separatorIndex === -1) { + return trimmedSeed + } + + const prefix = trimmedSeed.slice(0, separatorIndex) + const suffix = trimmedSeed.slice(separatorIndex + 1) + const suffixTail = suffix.slice(5) || suffix + + return `${trimmedSeed}|${prefix}|${suffix}|${suffixTail}` +} + +function createSeededPalette( + baseColors: string[], + seed: string, + namespace: string, + options: { + families: string[][] + hueShift: number + saturationShift: number + lightnessShift: number + baseBlend: [number, number] + }, +) { + const familyRandom = createRandom(seed, `${namespace}:family`) + const primaryIndex = Math.floor(familyRandom() * options.families.length) + const secondaryOffset = 1 + Math.floor(familyRandom() * (options.families.length - 1)) + const secondaryIndex = (primaryIndex + secondaryOffset) % options.families.length + const primary = options.families[primaryIndex] ?? baseColors + const secondary = options.families[secondaryIndex] ?? [...baseColors].reverse() + const primaryShift = Math.floor(familyRandom() * primary.length) + const secondaryShift = Math.floor(familyRandom() * secondary.length) + const paletteMode = paletteModes[Math.floor(familyRandom() * paletteModes.length)] ?? paletteModes[0] + const baseHue = familyRandom() * 360 + + return baseColors.map((color, index) => { + const random = createRandom(seed, `${namespace}:${index}`) + const primaryColor = primary[(index + primaryShift) % primary.length] ?? color + const secondaryColor = secondary[(index + secondaryShift) % secondary.length] ?? primaryColor + const proceduralColor = hslToHex( + (baseHue + paletteMode.hueOffsets[index % paletteMode.hueOffsets.length] + (random() * 2 - 1) * 18 + 360) % 360, + clamp(paletteMode.saturations[index % paletteMode.saturations.length] + (random() * 2 - 1) * 0.08, 0, 1), + clamp(paletteMode.lightnesses[index % paletteMode.lightnesses.length] + (random() * 2 - 1) * 0.08, 0, 1), + ) + const mixedFamilyColor = mixHexColors(primaryColor, secondaryColor, 0.18 + random() * 0.64) + const remixedFamilyColor = mixHexColors( + mixedFamilyColor, + primary[(index + secondaryShift + 1) % primary.length] ?? mixedFamilyColor, + random() * 0.32, + ) + const proceduralFamilyColor = mixHexColors(proceduralColor, remixedFamilyColor, 0.22 + random() * 0.34) + const [minBaseBlend, maxBaseBlend] = options.baseBlend + const blendedBaseColor = mixHexColors( + proceduralFamilyColor, + color, + minBaseBlend + random() * (maxBaseBlend - minBaseBlend), + ) + + return adjustHexColor(blendedBaseColor, { + hueShift: (random() * 2 - 1) * options.hueShift + (random() * 2 - 1) * 14, + saturationShift: (random() * 2 - 1) * options.saturationShift + 0.06, + lightnessShift: (random() * 2 - 1) * options.lightnessShift, + }) + }) +} + +function createSeededBackground(baseColor: string, seed: string, namespace: string) { + const [red, green, blue] = hexToRgb(baseColor) + const [hue] = rgbToHsl(red, green, blue) + const random = createRandom(seed, namespace) + + return hslToHex( + hue, + clamp(0.18 + random() * 0.18, 0, 1), + clamp(0.03 + random() * 0.09, 0, 1), + ) +} + +function adjustHexColor( + hex: string, + adjustments: { hueShift: number; saturationShift: number; lightnessShift: number }, +) { + const [red, green, blue] = hexToRgb(hex) + const [hue, saturation, lightness] = rgbToHsl(red, green, blue) + + return hslToHex( + (hue + adjustments.hueShift + 360) % 360, + clamp(saturation + adjustments.saturationShift, 0, 1), + clamp(lightness + adjustments.lightnessShift, 0, 1), + ) +} + +function mixHexColors(colorA: string, colorB: string, amount: number) { + const [redA, greenA, blueA] = hexToRgb(colorA) + const [redB, greenB, blueB] = hexToRgb(colorB) + const mixAmount = clamp(amount, 0, 1) + + return rgbToHex( + Math.round(redA + (redB - redA) * mixAmount), + Math.round(greenA + (greenB - greenA) * mixAmount), + Math.round(blueA + (blueB - blueA) * mixAmount), + ) +} + +function createRandom(seed: string, namespace: string) { + return mulberry32(hashString(`${buildSeedSource(seed)}::${namespace}`)) +} + +function hashString(input: string) { + let hash = 2166136261 + + for (let index = 0; index < input.length; index += 1) { + hash ^= input.charCodeAt(index) + hash = Math.imul(hash, 16777619) + } + + return hash >>> 0 +} + +function mulberry32(seed: number) { + return function nextRandom() { + let value = seed += 0x6d2b79f5 + value = Math.imul(value ^ (value >>> 15), value | 1) + value ^= value + Math.imul(value ^ (value >>> 7), value | 61) + return ((value ^ (value >>> 14)) >>> 0) / 4294967296 + } +} + +function clamp(value: number, min: number, max: number) { + return Math.min(max, Math.max(min, value)) +} + +function roundTo(value: number, precision: number) { + const power = 10 ** precision + return Math.round(value * power) / power +} + +function hexToRgb(hex: string): [number, number, number] { + const normalized = hex.replace(/^#/, "") + const expanded = normalized.length === 3 + ? normalized.split("").map((part) => `${part}${part}`).join("") + : normalized + + if (expanded.length !== 6) { + throw new Error(`Unsupported hex color: ${hex}`) + } + + const value = Number.parseInt(expanded, 16) + + return [ + (value >> 16) & 255, + (value >> 8) & 255, + value & 255, + ] +} + +function rgbToHsl(red: number, green: number, blue: number): [number, number, number] { + const normalizedRed = red / 255 + const normalizedGreen = green / 255 + const normalizedBlue = blue / 255 + const max = Math.max(normalizedRed, normalizedGreen, normalizedBlue) + const min = Math.min(normalizedRed, normalizedGreen, normalizedBlue) + const lightness = (max + min) / 2 + + if (max === min) { + return [0, 0, lightness] + } + + const delta = max - min + const saturation = lightness > 0.5 + ? delta / (2 - max - min) + : delta / (max + min) + + let hue = 0 + + switch (max) { + case normalizedRed: + hue = (normalizedGreen - normalizedBlue) / delta + (normalizedGreen < normalizedBlue ? 6 : 0) + break + case normalizedGreen: + hue = (normalizedBlue - normalizedRed) / delta + 2 + break + default: + hue = (normalizedRed - normalizedGreen) / delta + 4 + break + } + + return [hue * 60, saturation, lightness] +} + +function hslToHex(hue: number, saturation: number, lightness: number) { + if (saturation === 0) { + const value = Math.round(lightness * 255) + return rgbToHex(value, value, value) + } + + const hueToRgb = (p: number, q: number, t: number) => { + let normalizedT = t + + if (normalizedT < 0) normalizedT += 1 + if (normalizedT > 1) normalizedT -= 1 + if (normalizedT < 1 / 6) return p + (q - p) * 6 * normalizedT + if (normalizedT < 1 / 2) return q + if (normalizedT < 2 / 3) return p + (q - p) * (2 / 3 - normalizedT) * 6 + return p + } + + const normalizedHue = hue / 360 + const q = lightness < 0.5 + ? lightness * (1 + saturation) + : lightness + saturation - lightness * saturation + const p = 2 * lightness - q + const red = hueToRgb(p, q, normalizedHue + 1 / 3) + const green = hueToRgb(p, q, normalizedHue) + const blue = hueToRgb(p, q, normalizedHue - 1 / 3) + + return rgbToHex(Math.round(red * 255), Math.round(green * 255), Math.round(blue * 255)) +} + +function rgbToHex(red: number, green: number, blue: number) { + return `#${[red, green, blue] + .map((value) => value.toString(16).padStart(2, "0")) + .join("")}` +} diff --git a/packages/ui/src/react/index.ts b/packages/ui/src/react/index.ts new file mode 100644 index 00000000..5945ca55 --- /dev/null +++ b/packages/ui/src/react/index.ts @@ -0,0 +1,17 @@ +export { + getSeededPaperGrainGradientConfig, + getSeededPaperMeshGradientConfig, + paperGrainGradientDefaults, + paperMeshGradientDefaults, + resolvePaperGrainGradientConfig, + resolvePaperMeshGradientConfig, +} from "../common/paper" +export type { + PaperGrainGradientConfig, + PaperMeshGradientConfig, + SeededPaperOption, +} from "../common/paper" +export { PaperGrainGradient } from "./paper/grain-gradient" +export type { PaperGrainGradientProps } from "./paper/grain-gradient" +export { PaperMeshGradient } from "./paper/mesh-gradient" +export type { PaperMeshGradientProps } from "./paper/mesh-gradient" diff --git a/packages/ui/src/react/paper/grain-gradient.tsx b/packages/ui/src/react/paper/grain-gradient.tsx new file mode 100644 index 00000000..a247eecd --- /dev/null +++ b/packages/ui/src/react/paper/grain-gradient.tsx @@ -0,0 +1,101 @@ +"use client" + +import { + defaultObjectSizing, + defaultPatternSizing, + type GrainGradientShape, +} from "@paper-design/shaders" +import { GrainGradient, type GrainGradientProps } from "@paper-design/shaders-react" +import { resolvePaperGrainGradientConfig } from "../../common/paper" + +export interface PaperGrainGradientProps + extends Omit< + GrainGradientProps, + "colorBack" | "colors" | "softness" | "intensity" | "noise" | "shape" | "speed" | "frame" + > { + seed?: string + fill?: boolean + colorBack?: string + colors?: string[] + softness?: number + intensity?: number + noise?: number + shape?: GrainGradientProps["shape"] + speed?: number + frame?: number +} + +export function PaperGrainGradient({ + seed, + fill = true, + colorBack, + colors, + softness, + intensity, + noise, + shape, + speed, + frame, + fit, + rotation, + scale, + originX, + originY, + offsetX, + offsetY, + worldWidth, + worldHeight, + width, + height, + ...props +}: PaperGrainGradientProps) { + const resolved = resolvePaperGrainGradientConfig({ + seed, + colorBack, + colors, + softness, + intensity, + noise, + shape, + speed, + frame, + }) + + const sizingDefaults = getSizingDefaults(resolved.shape) + + return ( + + ) +} + +function getSizingDefaults(shape: GrainGradientShape) { + switch (shape) { + case "wave": + case "dots": + case "truchet": + return defaultPatternSizing + default: + return defaultObjectSizing + } +} diff --git a/packages/ui/src/react/paper/mesh-gradient.tsx b/packages/ui/src/react/paper/mesh-gradient.tsx new file mode 100644 index 00000000..da9fe68a --- /dev/null +++ b/packages/ui/src/react/paper/mesh-gradient.tsx @@ -0,0 +1,61 @@ +"use client" + +import { MeshGradient, type MeshGradientProps } from "@paper-design/shaders-react" +import { resolvePaperMeshGradientConfig } from "../../common/paper" + +export interface PaperMeshGradientProps + extends Omit< + MeshGradientProps, + "colors" | "distortion" | "swirl" | "grainMixer" | "grainOverlay" | "speed" | "frame" + > { + seed?: string + fill?: boolean + colors?: string[] + distortion?: number + swirl?: number + grainMixer?: number + grainOverlay?: number + speed?: number + frame?: number +} + +export function PaperMeshGradient({ + seed, + fill = true, + colors, + distortion, + swirl, + grainMixer, + grainOverlay, + speed, + frame, + width, + height, + ...props +}: PaperMeshGradientProps) { + const resolved = resolvePaperMeshGradientConfig({ + seed, + colors, + distortion, + swirl, + grainMixer, + grainOverlay, + speed, + frame, + }) + + return ( + + ) +} diff --git a/packages/ui/src/solid/index.ts b/packages/ui/src/solid/index.ts new file mode 100644 index 00000000..5945ca55 --- /dev/null +++ b/packages/ui/src/solid/index.ts @@ -0,0 +1,17 @@ +export { + getSeededPaperGrainGradientConfig, + getSeededPaperMeshGradientConfig, + paperGrainGradientDefaults, + paperMeshGradientDefaults, + resolvePaperGrainGradientConfig, + resolvePaperMeshGradientConfig, +} from "../common/paper" +export type { + PaperGrainGradientConfig, + PaperMeshGradientConfig, + SeededPaperOption, +} from "../common/paper" +export { PaperGrainGradient } from "./paper/grain-gradient" +export type { PaperGrainGradientProps } from "./paper/grain-gradient" +export { PaperMeshGradient } from "./paper/mesh-gradient" +export type { PaperMeshGradientProps } from "./paper/mesh-gradient" diff --git a/packages/ui/src/solid/paper/grain-gradient.tsx b/packages/ui/src/solid/paper/grain-gradient.tsx new file mode 100644 index 00000000..81c057a2 --- /dev/null +++ b/packages/ui/src/solid/paper/grain-gradient.tsx @@ -0,0 +1,125 @@ +import { + defaultObjectSizing, + defaultPatternSizing, + getShaderColorFromString, + getShaderNoiseTexture, + grainGradientFragmentShader, + GrainGradientShapes, + ShaderFitOptions, + type GrainGradientParams, +} from "@paper-design/shaders" +import type { JSX } from "solid-js" +import { resolvePaperGrainGradientConfig } from "../../common/paper" +import { SolidShaderMount } from "./shader-mount" + +type SharedGrainProps = Pick< + GrainGradientParams, + "fit" | "rotation" | "scale" | "originX" | "originY" | "offsetX" | "offsetY" | "worldWidth" | "worldHeight" +> + +export interface PaperGrainGradientProps + extends Omit, "ref">, + Partial { + ref?: (element: HTMLDivElement) => void + seed?: string + fill?: boolean + colorBack?: string + colors?: string[] + softness?: number + intensity?: number + noise?: number + shape?: GrainGradientParams["shape"] + speed?: number + frame?: number + minPixelRatio?: number + maxPixelCount?: number + webGlContextAttributes?: WebGLContextAttributes + width?: string | number + height?: string | number +} + +export function PaperGrainGradient({ + seed, + fill = true, + colorBack, + colors, + softness, + intensity, + noise, + shape, + speed, + frame, + fit, + rotation, + scale, + originX, + originY, + offsetX, + offsetY, + worldWidth, + worldHeight, + minPixelRatio, + maxPixelCount, + webGlContextAttributes, + width, + height, + ...props +}: PaperGrainGradientProps) { + const resolved = resolvePaperGrainGradientConfig({ + seed, + colorBack, + colors, + softness, + intensity, + noise, + shape, + speed, + frame, + }) + + const sizingDefaults = getSizingDefaults(resolved.shape) + + return ( + + ) +} + +function getSizingDefaults(shape: NonNullable) { + switch (shape) { + case "wave": + case "dots": + case "truchet": + return defaultPatternSizing + default: + return defaultObjectSizing + } +} diff --git a/packages/ui/src/solid/paper/mesh-gradient.tsx b/packages/ui/src/solid/paper/mesh-gradient.tsx new file mode 100644 index 00000000..234c6f42 --- /dev/null +++ b/packages/ui/src/solid/paper/mesh-gradient.tsx @@ -0,0 +1,104 @@ +import { + defaultObjectSizing, + getShaderColorFromString, + meshGradientFragmentShader, + ShaderFitOptions, + type MeshGradientParams, +} from "@paper-design/shaders" +import type { JSX } from "solid-js" +import { resolvePaperMeshGradientConfig } from "../../common/paper" +import { SolidShaderMount } from "./shader-mount" + +type SharedMeshProps = Pick< + MeshGradientParams, + "fit" | "rotation" | "scale" | "originX" | "originY" | "offsetX" | "offsetY" | "worldWidth" | "worldHeight" +> + +export interface PaperMeshGradientProps + extends Omit, "ref">, + Partial { + ref?: (element: HTMLDivElement) => void + seed?: string + fill?: boolean + colors?: string[] + distortion?: number + swirl?: number + grainMixer?: number + grainOverlay?: number + speed?: number + frame?: number + minPixelRatio?: number + maxPixelCount?: number + webGlContextAttributes?: WebGLContextAttributes + width?: string | number + height?: string | number +} + +export function PaperMeshGradient({ + seed, + fill = true, + colors, + distortion, + swirl, + grainMixer, + grainOverlay, + speed, + frame, + fit = defaultObjectSizing.fit, + rotation = defaultObjectSizing.rotation, + scale = defaultObjectSizing.scale, + originX = defaultObjectSizing.originX, + originY = defaultObjectSizing.originY, + offsetX = defaultObjectSizing.offsetX, + offsetY = defaultObjectSizing.offsetY, + worldWidth = defaultObjectSizing.worldWidth, + worldHeight = defaultObjectSizing.worldHeight, + minPixelRatio, + maxPixelCount, + webGlContextAttributes, + width, + height, + ...props +}: PaperMeshGradientProps) { + const resolved = resolvePaperMeshGradientConfig({ + seed, + colors, + distortion, + swirl, + grainMixer, + grainOverlay, + speed, + frame, + }) + + return ( + + ) +} diff --git a/packages/ui/src/solid/paper/shader-mount.tsx b/packages/ui/src/solid/paper/shader-mount.tsx new file mode 100644 index 00000000..c8c0d4fe --- /dev/null +++ b/packages/ui/src/solid/paper/shader-mount.tsx @@ -0,0 +1,115 @@ +import { ShaderMount, type ShaderMountUniforms } from "@paper-design/shaders" +import { createEffect, onCleanup, onMount, splitProps, type JSX } from "solid-js" + +type SolidShaderMountProps = Omit, "ref"> & { + ref?: (element: HTMLDivElement) => void + fragmentShader: string + uniforms: ShaderMountUniforms + speed?: number + frame?: number + minPixelRatio?: number + maxPixelCount?: number + webGlContextAttributes?: WebGLContextAttributes + width?: string | number + height?: string | number +} + +export function SolidShaderMount(props: SolidShaderMountProps) { + const [local, rest] = splitProps(props, [ + "ref", + "fragmentShader", + "uniforms", + "speed", + "frame", + "minPixelRatio", + "maxPixelCount", + "webGlContextAttributes", + "width", + "height", + "style", + ]) + + let element: HTMLDivElement | undefined + let shaderMount: ShaderMount | undefined + + onMount(() => { + if (!element) { + return + } + + shaderMount = new ShaderMount( + element, + local.fragmentShader, + local.uniforms, + local.webGlContextAttributes, + local.speed, + local.frame, + local.minPixelRatio, + local.maxPixelCount, + ) + + onCleanup(() => { + shaderMount?.dispose() + shaderMount = undefined + }) + }) + + createEffect(() => { + shaderMount?.setUniforms(local.uniforms) + }) + + createEffect(() => { + shaderMount?.setSpeed(local.speed) + }) + + createEffect(() => { + if (local.frame !== undefined) { + shaderMount?.setFrame(local.frame) + } + }) + + createEffect(() => { + shaderMount?.setMinPixelRatio(local.minPixelRatio) + }) + + createEffect(() => { + shaderMount?.setMaxPixelCount(local.maxPixelCount) + }) + + return ( +
{ + element = node + local.ref?.(node) + }} + style={mergeStyle(local.style, local.width, local.height)} + /> + ) +} + +function mergeStyle( + style: JSX.CSSProperties | string | undefined, + width: string | number | undefined, + height: string | number | undefined, +) { + if (typeof style === "string") { + return [ + width !== undefined ? `width:${toCssSize(width)}` : "", + height !== undefined ? `height:${toCssSize(height)}` : "", + style, + ] + .filter(Boolean) + .join(";") + } + + return { + ...(style ?? {}), + ...(width !== undefined ? { width: toCssSize(width) } : {}), + ...(height !== undefined ? { height: toCssSize(height) } : {}), + } +} + +function toCssSize(value: string | number) { + return typeof value === "number" ? `${value}px` : value +} diff --git a/packages/ui/tsconfig.react.json b/packages/ui/tsconfig.react.json new file mode 100644 index 00000000..5c868816 --- /dev/null +++ b/packages/ui/tsconfig.react.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "rootDir": "src", + "outDir": "dist", + "declaration": true, + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "jsx": "react-jsx" + }, + "include": [ + "src/common/**/*", + "src/react/**/*" + ] +} diff --git a/packages/ui/tsconfig.solid.json b/packages/ui/tsconfig.solid.json new file mode 100644 index 00000000..de511d1b --- /dev/null +++ b/packages/ui/tsconfig.solid.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "Bundler", + "rootDir": "src", + "outDir": "dist", + "declaration": true, + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "resolveJsonModule": true, + "jsx": "preserve", + "jsxImportSource": "solid-js/h" + }, + "include": [ + "src/common/**/*", + "src/solid/**/*" + ] +} diff --git a/packages/ui/tsup.config.ts b/packages/ui/tsup.config.ts new file mode 100644 index 00000000..88fe7467 --- /dev/null +++ b/packages/ui/tsup.config.ts @@ -0,0 +1,46 @@ +import { defineConfig } from "tsup" + +export default defineConfig([ + { + entry: { + "react/index": "src/react/index.ts", + }, + tsconfig: "./tsconfig.react.json", + format: ["esm"], + dts: { + tsconfig: "./tsconfig.react.json", + }, + clean: true, + target: "es2022", + platform: "browser", + sourcemap: false, + splitting: false, + treeshake: true, + external: ["react", "react/jsx-runtime"], + esbuildOptions(options) { + options.jsx = "automatic" + options.jsxImportSource = "react" + }, + }, + { + entry: { + "solid/index": "src/solid/index.ts", + }, + tsconfig: "./tsconfig.solid.json", + format: ["esm"], + dts: { + tsconfig: "./tsconfig.solid.json", + }, + clean: false, + target: "es2022", + platform: "browser", + sourcemap: false, + splitting: false, + treeshake: true, + external: ["solid-js", "solid-js/jsx-runtime"], + esbuildOptions(options) { + options.jsx = "automatic" + options.jsxImportSource = "solid-js/h" + }, + }, +]) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 35b9f67c..38943a65 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -37,6 +37,9 @@ importers: '@opencode-ai/sdk': specifier: ^1.1.31 version: 1.1.39 + '@openwork/ui': + specifier: workspace:* + version: link:../../packages/ui '@radix-ui/colors': specifier: ^3.0.0 version: 3.0.0 @@ -218,9 +221,6 @@ importers: apps/share: dependencies: - '@paper-design/shaders-react': - specifier: 0.0.71 - version: 0.0.71(@types/react@18.2.79)(react@19.2.4) '@vercel/blob': specifier: ^0.27.0 version: 0.27.3 @@ -353,6 +353,34 @@ importers: specifier: ^2.11.0 version: 2.11.10(solid-js@1.9.9)(vite@6.4.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + apps/ui-demo: + dependencies: + '@openwork/ui': + specifier: workspace:* + version: link:../../packages/ui + react: + specifier: 19.2.4 + version: 19.2.4 + react-dom: + specifier: 19.2.4 + version: 19.2.4(react@19.2.4) + devDependencies: + '@types/react': + specifier: 19.2.14 + version: 19.2.14 + '@types/react-dom': + specifier: 19.2.3 + version: 19.2.3(@types/react@19.2.14) + '@vitejs/plugin-react': + specifier: ^5.0.4 + version: 5.2.0(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.1.12 + version: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + ee/apps/den-api: dependencies: '@daytonaio/sdk': @@ -396,60 +424,14 @@ importers: specifier: ^5.5.4 version: 5.9.3 - ee/apps/den-controller: - dependencies: - '@daytonaio/sdk': - specifier: ^0.150.0 - version: 0.150.0(ws@8.19.0) - '@openwork-ee/den-db': - specifier: workspace:* - version: link:../../packages/den-db - '@openwork-ee/utils': - specifier: workspace:* - version: link:../../packages/utils - better-auth: - specifier: ^1.4.18 - version: 1.4.18(drizzle-kit@0.31.9)(drizzle-orm@0.45.1(@opentelemetry/api@1.9.0)(@planetscale/database@1.19.0)(bun-types@1.3.6)(kysely@0.28.11)(mysql2@3.17.4))(mysql2@3.17.4)(next@16.2.1(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(solid-js@1.9.10) - better-call: - specifier: ^1.1.8 - version: 1.1.8(zod@4.3.6) - cors: - specifier: ^2.8.5 - version: 2.8.6 - dotenv: - specifier: ^16.4.5 - version: 16.6.1 - express: - specifier: ^4.19.2 - version: 4.22.1 - mysql2: - specifier: ^3.11.3 - version: 3.17.4 - zod: - specifier: ^4.3.6 - version: 4.3.6 - devDependencies: - '@types/cors': - specifier: ^2.8.17 - version: 2.8.19 - '@types/express': - specifier: ^4.17.21 - version: 4.17.25 - '@types/node': - specifier: ^20.11.30 - version: 20.12.12 - tsx: - specifier: ^4.15.7 - version: 4.21.0 - typescript: - specifier: ^5.5.4 - version: 5.9.3 - ee/apps/den-web: dependencies: + '@openwork/ui': + specifier: workspace:* + version: link:../../../packages/ui '@paper-design/shaders-react': - specifier: 0.0.71 - version: 0.0.71(@types/react@19.2.14)(react@19.2.4) + specifier: 0.0.72 + version: 0.0.72(@types/react@19.2.14)(react@19.2.4) lucide-react: specifier: ^0.577.0 version: 0.577.0(react@19.2.4) @@ -521,9 +503,9 @@ importers: ee/apps/landing: dependencies: - '@paper-design/shaders-react': - specifier: 0.0.71 - version: 0.0.71(@types/react@18.2.79)(react@18.2.0) + '@openwork/ui': + specifier: workspace:* + version: link:../../../packages/ui botid: specifier: ^1.5.11 version: 1.5.11(next@14.2.5(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0) @@ -612,6 +594,31 @@ importers: specifier: ^5.5.4 version: 5.9.3 + packages/ui: + dependencies: + '@paper-design/shaders': + specifier: 0.0.72 + version: 0.0.72 + '@paper-design/shaders-react': + specifier: 0.0.72 + version: 0.0.72(@types/react@19.2.14)(react@19.2.4) + react: + specifier: ^18 || ^19 + version: 19.2.4 + solid-js: + specifier: ^1.9.0 + version: 1.9.9 + devDependencies: + '@types/react': + specifier: ^19.2.14 + version: 19.2.14 + tsup: + specifier: ^8.5.0 + version: 8.5.1(jiti@2.6.1)(postcss@8.5.6)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2) + typescript: + specifier: ^5.6.3 + version: 5.9.3 + packages: '@alloc/quick-lru@5.2.0': @@ -791,6 +798,10 @@ packages: resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==} engines: {node: '>=6.9.0'} + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} + engines: {node: '>=6.9.0'} + '@babel/compat-data@7.28.6': resolution: {integrity: sha512-2lfu57JtzctfIrcGMz992hyLlByuzgIk58+hhGCxjKZ3rWI82NnVLjXcaTqkI2NvlcvOskZaiZ5kjUALo3Lpxg==} engines: {node: '>=6.9.0'} @@ -803,10 +814,18 @@ packages: resolution: {integrity: sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==} engines: {node: '>=6.9.0'} + '@babel/core@7.29.0': + resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} + engines: {node: '>=6.9.0'} + '@babel/generator@7.28.6': resolution: {integrity: sha512-lOoVRwADj8hjf7al89tvQ2a1lf53Z+7tiXMgpZJL3maQPDxh0DgLMN62B2MKUOFcoodBHLMbDM6WAbKgNy5Suw==} engines: {node: '>=6.9.0'} + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} + engines: {node: '>=6.9.0'} + '@babel/helper-annotate-as-pure@7.27.3': resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} engines: {node: '>=6.9.0'} @@ -882,6 +901,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.29.2': + resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-syntax-jsx@7.28.6': resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} engines: {node: '>=6.9.0'} @@ -900,6 +924,18 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-react-jsx-self@7.27.1': + resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.27.1': + resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-typescript@7.28.6': resolution: {integrity: sha512-0YWL2RFxOqEm9Efk5PvreamxPME8OyY0wM5wh5lHjF+VtVhdneCWGzZeSqzOfiobVqQaNCd2z0tQvnI9DaPWPw==} engines: {node: '>=6.9.0'} @@ -920,10 +956,18 @@ packages: resolution: {integrity: sha512-fgWX62k02qtjqdSNTAGxmKYY/7FSL9WAS1o2Hu5+I5m9T0yxZzr4cnrfXQ/MX0rIifthCSs6FKTlzYbJcPtMNg==} engines: {node: '>=6.9.0'} + '@babel/traverse@7.29.0': + resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} + engines: {node: '>=6.9.0'} + '@babel/types@7.28.6': resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==} engines: {node: '>=6.9.0'} + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + '@better-auth/core@1.4.18': resolution: {integrity: sha512-q+awYgC7nkLEBdx2sW0iJjkzgSHlIxGnOpsN1r/O1+a4m7osJNHtfK2mKJSL1I+GfNyIlxJF8WvD/NLuYMpmcg==} peerDependencies: @@ -2188,8 +2232,8 @@ packages: peerDependencies: solid-js: 1.9.9 - '@paper-design/shaders-react@0.0.71': - resolution: {integrity: sha512-kTqjIlyZcpkwqJie+3ldEDscTtx1oOi8eRBD5QgWKI21GaNn/SSg26092M5zzqr3e8dVANv0ktS2ICSjbMFKbw==} + '@paper-design/shaders-react@0.0.72': + resolution: {integrity: sha512-q6KwquL93ZVNcuSM7pqzW0z/VLjnDVb/NSpYyGJBxf7MEHHCXx37E+zw/Px6RZLt3SGCUerIDDCGCMT385oW0w==} peerDependencies: '@types/react': ^18 || ^19 react: ^18 || ^19 @@ -2197,8 +2241,8 @@ packages: '@types/react': optional: true - '@paper-design/shaders@0.0.71': - resolution: {integrity: sha512-brCt05YxxyjBrhnE3l1wJJHcFXsM8aE4lmpd9TMQp+p0dMU3F+OWkJZL9m/RC1Tt7om5xr0Wg7d0HYm+b9NYZA==} + '@paper-design/shaders@0.0.72': + resolution: {integrity: sha512-rk2BFuV5ood2DaivbxJC2jQMzaB434isDUzdUQ85Cy0OWnUMuxl8kyGMR74TDPyjo3EvcHIyreNLkJdRG+GfSA==} '@pinojs/redact@0.4.0': resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} @@ -2245,6 +2289,9 @@ packages: '@radix-ui/colors@3.0.0': resolution: {integrity: sha512-FUOsGBkHrYJwCSEtWRCIfQbZG7q1e6DgxCIOe1SUQzDe/7rXXeA47s8yCn6fuTNQAj1Zq4oTFi9Yjp3wzElcxg==} + '@rolldown/pluginutils@1.0.0-rc.3': + resolution: {integrity: sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==} + '@rollup/rollup-android-arm-eabi@4.55.1': resolution: {integrity: sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==} cpu: [arm] @@ -2876,30 +2923,9 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} - '@types/body-parser@1.19.6': - resolution: {integrity: sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==} - - '@types/connect@3.4.38': - resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} - - '@types/cors@2.8.19': - resolution: {integrity: sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==} - '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - '@types/express-serve-static-core@4.19.8': - resolution: {integrity: sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==} - - '@types/express@4.17.25': - resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==} - - '@types/http-errors@2.0.5': - resolution: {integrity: sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==} - - '@types/mime@1.3.5': - resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} - '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} @@ -2918,12 +2944,6 @@ packages: '@types/prop-types@15.7.15': resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} - '@types/qs@6.14.0': - resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} - - '@types/range-parser@1.2.7': - resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} - '@types/react-dom@18.2.25': resolution: {integrity: sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA==} @@ -2941,15 +2961,6 @@ packages: '@types/retry@0.12.0': resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} - '@types/send@0.17.6': - resolution: {integrity: sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==} - - '@types/send@1.2.1': - resolution: {integrity: sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==} - - '@types/serve-static@1.15.10': - resolution: {integrity: sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==} - '@types/ws@8.18.1': resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} @@ -2957,6 +2968,12 @@ packages: resolution: {integrity: sha512-WizeAxzOTmv0JL7wOaxvLIU/KdBcrclM1ZUOdSlIZAxsTTTe1jsyBthStLby0Ueh7FnmKYAjLz26qRJTk5SDkQ==} engines: {node: '>=16.14'} + '@vitejs/plugin-react@5.2.0': + resolution: {integrity: sha512-YmKkfhOAi3wsB1PhJq5Scj3GXMn3WvtQ/JC0xoopuHoXSdmtdStOpFrYaT1kie2YgFBcIe64ROzMYRjCrYOdYw==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 + '@webgpu/types@0.1.69': resolution: {integrity: sha512-RPmm6kgRbI8e98zSD3RVACvnuktIja5+yLgDAkTmxLr90BEwdTXRQWNLF3ETTTyH/8mKhznZuN5AveXYFEsMGQ==} @@ -2964,10 +2981,6 @@ packages: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} - accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} - acorn-import-attributes@1.9.5: resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} peerDependencies: @@ -2999,9 +3012,6 @@ packages: arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} - array-flatten@1.1.1: - resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} - async-retry@1.3.3: resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==} @@ -3139,10 +3149,6 @@ packages: bmp-ts@1.0.9: resolution: {integrity: sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==} - body-parser@1.20.4: - resolution: {integrity: sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - botid@1.5.11: resolution: {integrity: sha512-KOO1A3+/vFVJk5aFoG3sNwiogKFPVR+x4aw4gQ1b2e0XoE+i5xp48/EZn+WqR07jRHeDGwHWQUOtV5WVm7xiww==} peerDependencies: @@ -3219,10 +3225,6 @@ packages: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} - bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -3231,10 +3233,6 @@ packages: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} - call-bound@1.0.4: - resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} - engines: {node: '>= 0.4'} - camelcase-css@2.0.1: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} @@ -3290,28 +3288,9 @@ packages: resolution: {integrity: sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==} engines: {node: ^14.18.0 || >=16.10.0} - content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} - - content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} - convert-source-map@2.0.0: resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - cookie-signature@1.0.7: - resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} - - cookie@0.7.2: - resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} - engines: {node: '>= 0.6'} - - cors@2.8.6: - resolution: {integrity: sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw==} - engines: {node: '>= 0.10'} - crelt@1.0.6: resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} @@ -3323,14 +3302,6 @@ packages: csstype@3.2.3: resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} - debug@2.6.9: - resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -3351,14 +3322,6 @@ packages: resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} engines: {node: '>=0.10'} - depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - - destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -3481,19 +3444,12 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} - ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.267: resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - encodeurl@2.0.0: - resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} - engines: {node: '>= 0.8'} - enhanced-resolve@5.18.4: resolution: {integrity: sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==} engines: {node: '>=10.13.0'} @@ -3542,13 +3498,6 @@ packages: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} - escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - - etag@1.8.1: - resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} - engines: {node: '>= 0.6'} - event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} @@ -3570,10 +3519,6 @@ packages: resolution: {integrity: sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==} engines: {node: '>=0.10.0'} - express@4.22.1: - resolution: {integrity: sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==} - engines: {node: '>= 0.10.0'} - fast-glob@3.3.3: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} @@ -3605,10 +3550,6 @@ packages: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} - finalhandler@1.3.2: - resolution: {integrity: sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==} - engines: {node: '>= 0.8'} - find-babel-config@2.1.2: resolution: {integrity: sha512-ZfZp1rQyp4gyuxqt1ZqjFGVeVBvmpURMqdIWXbPRfB97Bf6BzdK/xSIbylEINzQ0kB5tlDQfn9HkNXXWsqTqLg==} @@ -3635,10 +3576,6 @@ packages: forwarded-parse@2.1.2: resolution: {integrity: sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==} - forwarded@0.2.0: - resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} - engines: {node: '>= 0.6'} - fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} @@ -3656,10 +3593,6 @@ packages: react-dom: optional: true - fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -3751,14 +3684,6 @@ packages: html-entities@2.3.3: resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==} - http-errors@2.0.1: - resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} - engines: {node: '>= 0.8'} - - iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - iconv-lite@0.7.2: resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} engines: {node: '>=0.10.0'} @@ -3775,10 +3700,6 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - ipaddr.js@1.9.1: - resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} - engines: {node: '>= 0.10'} - is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -4002,25 +3923,14 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} - media-typer@0.3.0: - resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} - engines: {node: '>= 0.6'} - merge-anything@5.1.7: resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==} engines: {node: '>=12.13'} - merge-descriptors@1.0.3: - resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} - merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - methods@1.1.2: - resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} - engines: {node: '>= 0.6'} - micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} @@ -4033,11 +3943,6 @@ packages: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} - mime@1.6.0: - resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} - engines: {node: '>=4'} - hasBin: true - mime@3.0.0: resolution: {integrity: sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==} engines: {node: '>=10.0.0'} @@ -4075,9 +3980,6 @@ packages: motion-utils@12.29.2: resolution: {integrity: sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A==} - ms@2.0.0: - resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} - ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -4101,10 +4003,6 @@ packages: resolution: {integrity: sha512-yJBmDJr18xy47dbNVlHcgdPrulSn1nhSE6Ns9vTG+Nx9VPT6iV1MD6aQFp/t52zpf82FhLLTXAXr30NuCnxvwA==} engines: {node: ^20.0.0 || >=22.0.0} - negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - next@14.2.5: resolution: {integrity: sha512-0f8aRfBVL+mpzfBjYfQuLWh2WyAwtJXCRfkPF4UJ5qd2YwrHczsrSzXU4tRMV0OAxR8ZJZWPFn6uhSC56UTsLA==} engines: {node: '>=18.17.0'} @@ -4194,10 +4092,6 @@ packages: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} - object-inspect@1.13.4: - resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} - engines: {node: '>= 0.4'} - omggif@1.0.10: resolution: {integrity: sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==} @@ -4205,10 +4099,6 @@ packages: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} - on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - p-finally@1.0.0: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} engines: {node: '>=4'} @@ -4256,10 +4146,6 @@ packages: parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} - parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - path-exists@3.0.0: resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} engines: {node: '>=4'} @@ -4275,9 +4161,6 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} - path-to-regexp@0.1.12: - resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} - pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} @@ -4427,31 +4310,15 @@ packages: resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==} engines: {node: '>=12.0.0'} - proxy-addr@2.0.7: - resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} - engines: {node: '>= 0.10'} - proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - qs@6.14.2: - resolution: {integrity: sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==} - engines: {node: '>=0.6'} - queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} - range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - - raw-body@2.5.3: - resolution: {integrity: sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==} - engines: {node: '>= 0.8'} - react-dom@18.2.0: resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} peerDependencies: @@ -4462,6 +4329,10 @@ packages: peerDependencies: react: ^19.2.4 + react-refresh@0.18.0: + resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} + engines: {node: '>=0.10.0'} + react@18.2.0: resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} engines: {node: '>=0.10.0'} @@ -4571,10 +4442,6 @@ packages: engines: {node: '>=10'} hasBin: true - send@0.19.2: - resolution: {integrity: sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==} - engines: {node: '>= 0.8.0'} - seroval-plugins@1.3.3: resolution: {integrity: sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w==} engines: {node: '>=10'} @@ -4585,16 +4452,9 @@ packages: resolution: {integrity: sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==} engines: {node: '>=10'} - serve-static@1.16.3: - resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==} - engines: {node: '>= 0.8.0'} - set-cookie-parser@2.7.2: resolution: {integrity: sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==} - setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - sharp@0.34.5: resolution: {integrity: sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -4603,22 +4463,6 @@ packages: resolution: {integrity: sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==} engines: {node: '>= 0.4'} - side-channel-list@1.0.0: - resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} - engines: {node: '>= 0.4'} - - side-channel-map@1.0.1: - resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} - engines: {node: '>= 0.4'} - - side-channel-weakmap@1.0.2: - resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} - engines: {node: '>= 0.4'} - - side-channel@1.1.0: - resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} - engines: {node: '>= 0.4'} - simple-xml-to-json@1.2.3: resolution: {integrity: sha512-kWJDCr9EWtZ+/EYYM5MareWj2cRnZGF93YDNpH4jQiHB+hBIZnfPFSQiVMzZOdk+zXWqTZ/9fTeQNu2DqeiudA==} engines: {node: '>=20.12.2'} @@ -4664,10 +4508,6 @@ packages: resolution: {integrity: sha512-AzlMO+t51v6cFvKZ+Oe9DJnL1OXEH5s9bEy6di5aOrUpcP7PCzI/wIeXF0u3zg0L89gwnceoKxrLId0ZpYnNXw==} engines: {node: '>=18.0'} - statuses@2.0.2: - resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} - engines: {node: '>= 0.8'} - stream-browserify@3.0.0: resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} @@ -4778,10 +4618,6 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - token-types@4.2.1: resolution: {integrity: sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==} engines: {node: '>=10'} @@ -4827,10 +4663,6 @@ packages: resolution: {integrity: sha512-Rb4qk5YT8RUwwdXtkLpkVhNEe/lor6+WV7S5tTlLpxSz6MjV5Qi8jGNn4gS6NAvrYGA/rNrE6YUQM85sCZUDbQ==} hasBin: true - type-is@1.6.18: - resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} - engines: {node: '>= 0.6'} - typeid-js@1.2.0: resolution: {integrity: sha512-t76ZucAnvGC60ea/HjVsB0TSoB0cw9yjnfurUgtInXQWUI/VcrlZGpO23KN3iSe8yOGUgb1zr7W7uEzJ3hSljA==} @@ -4864,10 +4696,6 @@ packages: resolution: {integrity: sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==} engines: {node: '>=14.0'} - unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - update-browserslist-db@1.2.3: resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true @@ -4880,18 +4708,10 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - utils-merge@1.0.1: - resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} - engines: {node: '>= 0.4.0'} - uuid@10.0.0: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} hasBin: true - vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - vite-plugin-solid@2.11.10: resolution: {integrity: sha512-Yr1dQybmtDtDAHkii6hXuc1oVH9CPcS/Zb2jN/P36qqcrkNnVPsMTzQ06jyzFPFjj3U1IYKMVt/9ZqcwGCEbjw==} peerDependencies: @@ -4942,6 +4762,46 @@ packages: yaml: optional: true + vite@7.3.1: + resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + vitefu@1.1.1: resolution: {integrity: sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==} peerDependencies: @@ -5497,6 +5357,12 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/code-frame@7.29.0': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + '@babel/compat-data@7.28.6': {} '@babel/core@7.28.0': @@ -5539,6 +5405,26 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/core@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helpers': 7.28.6 + '@babel/parser': 7.29.2 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + '@babel/generator@7.28.6': dependencies: '@babel/parser': 7.28.6 @@ -5547,6 +5433,14 @@ snapshots: '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 + '@babel/generator@7.29.1': + dependencies: + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + '@babel/helper-annotate-as-pure@7.27.3': dependencies: '@babel/types': 7.28.6 @@ -5610,6 +5504,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.6 + transitivePeerDependencies: + - supports-color + '@babel/helper-optimise-call-expression@7.27.1': dependencies: '@babel/types': 7.28.6 @@ -5647,6 +5550,10 @@ snapshots: dependencies: '@babel/types': 7.28.6 + '@babel/parser@7.29.2': + dependencies: + '@babel/types': 7.29.0 + '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.28.0)': dependencies: '@babel/core': 7.28.0 @@ -5670,6 +5577,16 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + '@babel/plugin-transform-typescript@7.28.6(@babel/core@7.28.0)': dependencies: '@babel/core': 7.28.0 @@ -5710,11 +5627,28 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/traverse@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.29.2 + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + '@babel/types@7.28.6': dependencies: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@better-auth/core@1.4.18(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.21)(better-call@1.1.8(zod@4.3.6))(jose@6.1.3)(kysely@0.28.11)(nanostores@1.1.0)': dependencies: '@better-auth/utils': 0.3.0 @@ -6884,28 +6818,14 @@ snapshots: - typescript - web-tree-sitter - '@paper-design/shaders-react@0.0.71(@types/react@18.2.79)(react@18.2.0)': + '@paper-design/shaders-react@0.0.72(@types/react@19.2.14)(react@19.2.4)': dependencies: - '@paper-design/shaders': 0.0.71 - react: 18.2.0 - optionalDependencies: - '@types/react': 18.2.79 - - '@paper-design/shaders-react@0.0.71(@types/react@18.2.79)(react@19.2.4)': - dependencies: - '@paper-design/shaders': 0.0.71 - react: 19.2.4 - optionalDependencies: - '@types/react': 18.2.79 - - '@paper-design/shaders-react@0.0.71(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@paper-design/shaders': 0.0.71 + '@paper-design/shaders': 0.0.72 react: 19.2.4 optionalDependencies: '@types/react': 19.2.14 - '@paper-design/shaders@0.0.71': {} + '@paper-design/shaders@0.0.72': {} '@pinojs/redact@0.4.0': {} @@ -6940,6 +6860,8 @@ snapshots: '@radix-ui/colors@3.0.0': {} + '@rolldown/pluginutils@1.0.0-rc.3': {} + '@rollup/rollup-android-arm-eabi@4.55.1': optional: true @@ -7610,39 +7532,8 @@ snapshots: dependencies: '@babel/types': 7.28.6 - '@types/body-parser@1.19.6': - dependencies: - '@types/connect': 3.4.38 - '@types/node': 20.12.12 - - '@types/connect@3.4.38': - dependencies: - '@types/node': 20.12.12 - - '@types/cors@2.8.19': - dependencies: - '@types/node': 20.12.12 - '@types/estree@1.0.8': {} - '@types/express-serve-static-core@4.19.8': - dependencies: - '@types/node': 20.12.12 - '@types/qs': 6.14.0 - '@types/range-parser': 1.2.7 - '@types/send': 1.2.1 - - '@types/express@4.17.25': - dependencies: - '@types/body-parser': 1.19.6 - '@types/express-serve-static-core': 4.19.8 - '@types/qs': 6.14.0 - '@types/serve-static': 1.15.10 - - '@types/http-errors@2.0.5': {} - - '@types/mime@1.3.5': {} - '@types/minimatch@5.1.2': {} '@types/node@16.9.1': {} @@ -7661,10 +7552,6 @@ snapshots: '@types/prop-types@15.7.15': {} - '@types/qs@6.14.0': {} - - '@types/range-parser@1.2.7': {} - '@types/react-dom@18.2.25': dependencies: '@types/react': 18.2.79 @@ -7684,21 +7571,6 @@ snapshots: '@types/retry@0.12.0': {} - '@types/send@0.17.6': - dependencies: - '@types/mime': 1.3.5 - '@types/node': 20.12.12 - - '@types/send@1.2.1': - dependencies: - '@types/node': 20.12.12 - - '@types/serve-static@1.15.10': - dependencies: - '@types/http-errors': 2.0.5 - '@types/node': 20.12.12 - '@types/send': 0.17.6 - '@types/ws@8.18.1': dependencies: '@types/node': 20.12.12 @@ -7711,6 +7583,18 @@ snapshots: throttleit: 2.1.0 undici: 5.29.0 + '@vitejs/plugin-react@5.2.0(vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) + '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) + '@rolldown/pluginutils': 1.0.0-rc.3 + '@types/babel__core': 7.20.5 + react-refresh: 0.18.0 + vite: 7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + transitivePeerDependencies: + - supports-color + '@webgpu/types@0.1.69': optional: true @@ -7718,11 +7602,6 @@ snapshots: dependencies: event-target-shim: 5.0.1 - accepts@1.3.8: - dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - acorn-import-attributes@1.9.5(acorn@8.16.0): dependencies: acorn: 8.16.0 @@ -7746,8 +7625,6 @@ snapshots: arg@5.0.2: {} - array-flatten@1.1.1: {} - async-retry@1.3.3: dependencies: retry: 0.13.1 @@ -7862,23 +7739,6 @@ snapshots: bmp-ts@1.0.9: {} - body-parser@1.20.4: - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.1 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.14.2 - raw-body: 2.5.3 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - botid@1.5.11(next@14.2.5(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0))(react@18.2.0): optionalDependencies: next: 14.2.5(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -7958,8 +7818,6 @@ snapshots: dependencies: streamsearch: 1.1.0 - bytes@3.1.2: {} - cac@6.7.14: {} call-bind-apply-helpers@1.0.2: @@ -7967,11 +7825,6 @@ snapshots: es-errors: 1.3.0 function-bind: 1.1.2 - call-bound@1.0.4: - dependencies: - call-bind-apply-helpers: 1.0.2 - get-intrinsic: 1.3.0 - camelcase-css@2.0.1: {} caniuse-lite@1.0.30001764: {} @@ -8022,33 +7875,14 @@ snapshots: consola@3.4.2: {} - content-disposition@0.5.4: - dependencies: - safe-buffer: 5.2.1 - - content-type@1.0.5: {} - convert-source-map@2.0.0: {} - cookie-signature@1.0.7: {} - - cookie@0.7.2: {} - - cors@2.8.6: - dependencies: - object-assign: 4.1.1 - vary: 1.1.2 - crelt@1.0.6: {} cssesc@3.0.0: {} csstype@3.2.3: {} - debug@2.6.9: - dependencies: - ms: 2.0.0 - debug@4.4.3: dependencies: ms: 2.1.3 @@ -8059,10 +7893,6 @@ snapshots: denque@2.1.0: {} - depd@2.0.0: {} - - destroy@1.2.0: {} - detect-libc@2.1.2: {} didyoumean@1.2.2: {} @@ -8098,14 +7928,10 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 - ee-first@1.1.1: {} - electron-to-chromium@1.5.267: {} emoji-regex@8.0.0: {} - encodeurl@2.0.0: {} - enhanced-resolve@5.18.4: dependencies: graceful-fs: 4.2.11 @@ -8220,10 +8046,6 @@ snapshots: escalade@3.2.0: {} - escape-html@1.0.3: {} - - etag@1.8.1: {} - event-target-shim@5.0.1: {} eventemitter3@4.0.7: {} @@ -8238,42 +8060,6 @@ snapshots: dependencies: homedir-polyfill: 1.0.3 - express@4.22.1: - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.4 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.7.2 - cookie-signature: 1.0.7 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.3.2 - fresh: 0.5.2 - http-errors: 2.0.1 - merge-descriptors: 1.0.3 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.12 - proxy-addr: 2.0.7 - qs: 6.14.2 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.19.2 - serve-static: 1.16.3 - setprototypeof: 1.2.0 - statuses: 2.0.2 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - fast-glob@3.3.3: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -8309,18 +8095,6 @@ snapshots: dependencies: to-regex-range: 5.0.1 - finalhandler@1.3.2: - dependencies: - debug: 2.6.9 - encodeurl: 2.0.0 - escape-html: 1.0.3 - on-finished: 2.4.1 - parseurl: 1.3.3 - statuses: 2.0.2 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - find-babel-config@2.1.2: dependencies: json5: 2.2.3 @@ -8347,8 +8121,6 @@ snapshots: forwarded-parse@2.1.2: {} - forwarded@0.2.0: {} - fraction.js@4.3.7: {} framer-motion@12.35.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0): @@ -8360,8 +8132,6 @@ snapshots: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - fresh@0.5.2: {} - fs.realpath@1.0.0: {} fsevents@2.3.2: @@ -8456,18 +8226,6 @@ snapshots: html-entities@2.3.3: {} - http-errors@2.0.1: - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.2 - toidentifier: 1.0.1 - - iconv-lite@0.4.24: - dependencies: - safer-buffer: 2.1.2 - iconv-lite@0.7.2: dependencies: safer-buffer: 2.1.2 @@ -8487,8 +8245,6 @@ snapshots: inherits@2.0.4: {} - ipaddr.js@1.9.1: {} - is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 @@ -8671,18 +8427,12 @@ snapshots: math-intrinsics@1.1.0: {} - media-typer@0.3.0: {} - merge-anything@5.1.7: dependencies: is-what: 4.1.16 - merge-descriptors@1.0.3: {} - merge2@1.4.1: {} - methods@1.1.2: {} - micromatch@4.0.8: dependencies: braces: 3.0.3 @@ -8694,8 +8444,6 @@ snapshots: dependencies: mime-db: 1.52.0 - mime@1.6.0: {} - mime@3.0.0: {} minimatch@10.1.1: @@ -8729,8 +8477,6 @@ snapshots: motion-utils@12.29.2: {} - ms@2.0.0: {} - ms@2.1.3: {} mysql2@3.17.4: @@ -8758,8 +8504,6 @@ snapshots: nanostores@1.1.0: {} - negotiator@0.6.3: {} - next@14.2.5(@opentelemetry/api@1.9.0)(@playwright/test@1.58.2)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): dependencies: '@next/env': 14.2.5 @@ -8853,16 +8597,10 @@ snapshots: object-hash@3.0.0: {} - object-inspect@1.13.4: {} - omggif@1.0.10: {} on-exit-leak-free@2.1.2: {} - on-finished@2.4.1: - dependencies: - ee-first: 1.1.1 - p-finally@1.0.0: {} p-limit@2.3.0: @@ -8906,8 +8644,6 @@ snapshots: dependencies: entities: 6.0.1 - parseurl@1.3.3: {} - path-exists@3.0.0: {} path-expression-matcher@1.1.3: {} @@ -8919,8 +8655,6 @@ snapshots: lru-cache: 10.4.3 minipass: 7.1.2 - path-to-regexp@0.1.12: {} - pathe@2.0.3: {} peek-readable@4.1.0: {} @@ -9063,30 +8797,12 @@ snapshots: '@types/node': 20.12.12 long: 5.3.2 - proxy-addr@2.0.7: - dependencies: - forwarded: 0.2.0 - ipaddr.js: 1.9.1 - proxy-from-env@1.1.0: {} - qs@6.14.2: - dependencies: - side-channel: 1.1.0 - queue-microtask@1.2.3: {} quick-format-unescaped@4.0.4: {} - range-parser@1.2.1: {} - - raw-body@2.5.3: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.1 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - react-dom@18.2.0(react@18.2.0): dependencies: loose-envify: 1.4.0 @@ -9098,6 +8814,8 @@ snapshots: react: 19.2.4 scheduler: 0.27.0 + react-refresh@0.18.0: {} + react@18.2.0: dependencies: loose-envify: 1.4.0 @@ -9216,43 +8934,14 @@ snapshots: semver@7.7.4: {} - send@0.19.2: - dependencies: - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 2.0.0 - escape-html: 1.0.3 - etag: 1.8.1 - fresh: 0.5.2 - http-errors: 2.0.1 - mime: 1.6.0 - ms: 2.1.3 - on-finished: 2.4.1 - range-parser: 1.2.1 - statuses: 2.0.2 - transitivePeerDependencies: - - supports-color - seroval-plugins@1.3.3(seroval@1.3.2): dependencies: seroval: 1.3.2 seroval@1.3.2: {} - serve-static@1.16.3: - dependencies: - encodeurl: 2.0.0 - escape-html: 1.0.3 - parseurl: 1.3.3 - send: 0.19.2 - transitivePeerDependencies: - - supports-color - set-cookie-parser@2.7.2: {} - setprototypeof@1.2.0: {} - sharp@0.34.5: dependencies: '@img/colour': 1.1.0 @@ -9286,34 +8975,6 @@ snapshots: shell-quote@1.8.3: {} - side-channel-list@1.0.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - - side-channel-map@1.0.1: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - - side-channel-weakmap@1.0.2: - dependencies: - call-bound: 1.0.4 - es-errors: 1.3.0 - get-intrinsic: 1.3.0 - object-inspect: 1.13.4 - side-channel-map: 1.0.1 - - side-channel@1.1.0: - dependencies: - es-errors: 1.3.0 - object-inspect: 1.13.4 - side-channel-list: 1.0.0 - side-channel-map: 1.0.1 - side-channel-weakmap: 1.0.2 - simple-xml-to-json@1.2.3: {} solid-js@1.9.10: @@ -9360,8 +9021,6 @@ snapshots: stage-js@1.0.0-alpha.17: optional: true - statuses@2.0.2: {} - stream-browserify@3.0.0: dependencies: inherits: 2.0.4 @@ -9483,8 +9142,6 @@ snapshots: dependencies: is-number: 7.0.0 - toidentifier@1.0.1: {} - token-types@4.2.1: dependencies: '@tokenizer/token': 0.3.0 @@ -9542,11 +9199,6 @@ snapshots: '@turbo/windows-64': 2.8.20 '@turbo/windows-arm64': 2.8.20 - type-is@1.6.18: - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - typeid-js@1.2.0: dependencies: uuid: 10.0.0 @@ -9569,8 +9221,6 @@ snapshots: dependencies: '@fastify/busboy': 2.1.1 - unpipe@1.0.0: {} - update-browserslist-db@1.2.3(browserslist@4.28.1): dependencies: browserslist: 4.28.1 @@ -9583,12 +9233,8 @@ snapshots: util-deprecate@1.0.2: {} - utils-merge@1.0.1: {} - uuid@10.0.0: {} - vary@1.1.2: {} - vite-plugin-solid@2.11.10(solid-js@1.9.9)(vite@6.4.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)): dependencies: '@babel/core': 7.28.6 @@ -9618,6 +9264,22 @@ snapshots: tsx: 4.21.0 yaml: 2.8.2 + vite@7.3.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2): + dependencies: + esbuild: 0.27.2 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.55.1 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 25.4.0 + fsevents: 2.3.3 + jiti: 2.6.1 + lightningcss: 1.30.2 + tsx: 4.21.0 + yaml: 2.8.2 + vitefu@1.1.1(vite@6.4.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)): optionalDependencies: vite: 6.4.1(@types/node@25.4.0)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)