diff --git a/dash/package.json b/dash/package.json
index eb07336a..32a7932f 100644
--- a/dash/package.json
+++ b/dash/package.json
@@ -12,6 +12,10 @@
"dependencies": {
"@fireworks-js/react": "^2.10.8",
"@headlessui/react": "2.2.0",
+ "@react-three/drei": "^10.0.5",
+ "@react-three/fiber": "^9.1.0",
+ "@react-three/uikit": "^0.8.14",
+ "@types/three": "^0.174.0",
"clsx": "2.1.1",
"framer-motion": "11.11.17",
"geist": "1.3.1",
@@ -21,6 +25,7 @@
"react": "18.3.1",
"react-dom": "18.3.1",
"sharp": "0.33.5",
+ "three": "^0.174.0",
"zod": "3.23.8",
"zustand": "5.0.1"
},
diff --git a/dash/src/app/(nav)/settings/page.tsx b/dash/src/app/(nav)/settings/page.tsx
index 36908358..56544d36 100644
--- a/dash/src/app/(nav)/settings/page.tsx
+++ b/dash/src/app/(nav)/settings/page.tsx
@@ -1,22 +1,22 @@
"use client";
-import { useEffect, useState } from "react";
import { motion } from "framer-motion";
import Image from "next/image";
+import { useEffect, useState } from "react";
import xIcon from "public/icons/xmark.svg";
import type { Driver } from "@/types/state.type";
-import SegmentedControls from "@/components/SegmentedControls";
-import SelectMultiple from "@/components/SelectMultiple";
-import DriverTag from "@/components/driver/DriverTag";
-import DelayInput from "@/components/DelayInput";
import Button from "@/components/Button";
-import Toggle from "@/components/Toggle";
+import DelayInput from "@/components/DelayInput";
import Footer from "@/components/Footer";
-import Slider from "@/components/Slider";
import Input from "@/components/Input";
+import SegmentedControls from "@/components/SegmentedControls";
+import SelectMultiple from "@/components/SelectMultiple";
+import Slider from "@/components/Slider";
+import Toggle from "@/components/Toggle";
+import DriverTag from "@/components/driver/DriverTag";
import { useSettingsStore } from "@/stores/useSettingsStore";
@@ -78,6 +78,11 @@ export default function SettingsPage() {
)}
+
+
settings.setUse3DMap(v)} />
+ (Experimental) Use 3D Map
+
+
Favorite Drivers
Select your favorite drivers to highlight them on the dashboard.
diff --git a/dash/src/app/dashboard/page.tsx b/dash/src/app/dashboard/page.tsx
index 57a003c9..9772226a 100644
--- a/dash/src/app/dashboard/page.tsx
+++ b/dash/src/app/dashboard/page.tsx
@@ -1,27 +1,29 @@
"use client";
-import { useEffect, useRef } from "react";
import clsx from "clsx";
+import { useEffect, useRef } from "react";
import Fireworks, { FireworksHandlers } from "@fireworks-js/react";
import { useDataStore } from "@/stores/useDataStore";
-import SessionInfo from "@/components/SessionInfo";
-import WeatherInfo from "@/components/WeatherInfo";
-import TrackInfo from "@/components/TrackInfo";
+import Footer from "@/components/Footer";
+import LapCount from "@/components/LapCount";
import LeaderBoard from "@/components/LeaderBoard";
+import Map from "@/components/map/Map";
+import Map3D from "@/components/map/Map3D";
import Qualifying from "@/components/Qualifying";
import RaceControl from "@/components/RaceControl";
+import SessionInfo from "@/components/SessionInfo";
import TeamRadios from "@/components/TeamRadios";
-import Footer from "@/components/Footer";
-import Map from "@/components/Map";
-import LapCount from "@/components/LapCount";
+import TrackInfo from "@/components/TrackInfo";
+import WeatherInfo from "@/components/WeatherInfo";
+import { useSettingsStore } from "@/stores/useSettingsStore";
export default function Page() {
const fireworksRef = useRef(null);
const fireworksPlayed = useRef(false);
-
+ const settings = useSettingsStore();
const sessionType = useDataStore((state) => state.sessionInfo?.type);
const raceControlMessages = useDataStore((state) => state.raceControlMessages?.messages);
@@ -83,9 +85,7 @@ export default function Page() {
)}
-
-
-
+ {settings.use3DMap ? : }
state.lapCount);
const track = useDataStore((state) => state.trackStatus);
- const currentTrackStatus = getTrackStatusMessage(track?.status ? parseInt(track?.status) : undefined);
+ const currentTrackStatus = useMemo(
+ () => getTrackStatusMessage(track?.status ? parseInt(track?.status) : undefined),
+ [track],
+ );
+ const computedTrackStyle = useMemo(
+ () => (currentTrackStatus ? getComputedFlagStyle(currentTrackStatus.flagType) : null),
+ [currentTrackStatus],
+ );
return (
@@ -22,9 +30,9 @@ export default function TrackInfo() {
{!!currentTrackStatus ? (
{currentTrackStatus.message}
diff --git a/dash/src/components/map/CornerNumber3D.tsx b/dash/src/components/map/CornerNumber3D.tsx
new file mode 100644
index 00000000..f3d632c1
--- /dev/null
+++ b/dash/src/components/map/CornerNumber3D.tsx
@@ -0,0 +1,35 @@
+import { useLookAt } from "@/hooks/useLookAt";
+import { theme } from "@/styles/tailwindTheme";
+import { Text as Text3D } from "@react-three/drei";
+import { useThree } from "@react-three/fiber";
+import { useRef } from "react";
+
+import { Mesh } from "three";
+
+type CornerNumberProps = {
+ number: number;
+ x: number;
+ y: number;
+};
+
+export default function CornerNumber({ number, x, y }: CornerNumberProps) {
+ const { camera } = useThree();
+
+ const mesh = useRef
();
+
+ useLookAt({ object: mesh.current, target: camera.position });
+
+ return (
+
+ {number}
+
+ );
+}
diff --git a/dash/src/components/map/DriverIndicator.tsx b/dash/src/components/map/DriverIndicator.tsx
new file mode 100644
index 00000000..e0a35d64
--- /dev/null
+++ b/dash/src/components/map/DriverIndicator.tsx
@@ -0,0 +1,218 @@
+import { rotate } from "@/lib/map";
+import { toVector3 } from "@/lib/r3f";
+import { theme } from "@/styles/tailwindTheme";
+import { PositionCar } from "@/types/state.type";
+import { Billboard, Line, Sphere } from "@react-three/drei";
+import { useFrame } from "@react-three/fiber";
+import { Container, Root, Text as TextUI } from "@react-three/uikit";
+import { useCallback, useEffect, useMemo, useRef, useState } from "react";
+import { Color, MeshBasicMaterial, Vector3 } from "three";
+
+function calculateAverageUpdateTime(history: number[]) {
+ if (history.length < 2) return 0;
+
+ let totalAmount = 0;
+ for (let i = 0; i < history.length; ++i) {
+ const current = history[i];
+ const previous = history[i - 1];
+ const delta = current - previous;
+ totalAmount += delta;
+ }
+
+ return totalAmount / (history.length - 1);
+}
+
+type DriverIndicatorProps = {
+ name: string;
+ color: string | undefined;
+ racingNumber: string;
+ favoriteDriver: boolean;
+
+ pit: boolean;
+ hidden: boolean;
+
+ pos: PositionCar;
+ rotation: number;
+
+ centerX: number;
+ centerY: number;
+};
+
+export function DriverIndicator({
+ pos,
+ name,
+ color,
+ racingNumber,
+ favoriteDriver,
+ pit,
+ hidden,
+ rotation,
+ centerX,
+ centerY,
+}: DriverIndicatorProps) {
+ const rotatedPos = rotate(pos.X, pos.Y, rotation, centerX, centerY);
+
+ const opacity = useMemo(() => {
+ if (pit) return 0.3;
+ return hidden ? 0 : 1;
+ }, [pit, hidden]);
+
+ const material = useMemo(() => {
+ const m = new MeshBasicMaterial();
+ m.transparent = true;
+ m.opacity = opacity;
+ m.color = new Color(`#${color}`);
+ return m;
+ }, [color, opacity]);
+
+ const styles = useMemo(
+ () => ({
+ renderPriority: favoriteDriver ? 40 : 20,
+ billboardHeight: favoriteDriver ? 800 : 400,
+ billboardSize: {
+ x: favoriteDriver ? 1050 * 1.5 : 1050,
+ y: favoriteDriver ? 350 * 1.5 : 350,
+ },
+ fontSize: favoriteDriver ? 24000 * 1.5 : 24000,
+ fontWeight: favoriteDriver ? 600 : 500,
+ dotSize: favoriteDriver ? 180 : 120,
+ }),
+ [favoriteDriver],
+ );
+
+ if (hidden) {
+ return null;
+ }
+
+ return (
+
+
+
+
+
+
+
+ {racingNumber}
+
+
+
+
+ {name}
+
+
+
+
+
+
+
+ );
+}
+
+type InterpolatedDriverIndicatorProps = DriverIndicatorProps & {
+ interpolationLength?: number;
+};
+
+export function InterpolatedDriverIndicator({
+ pos,
+ interpolationLength = 8,
+ ...props
+}: InterpolatedDriverIndicatorProps) {
+ const incomingPosition = useMemo(() => new Vector3(pos.X, 0, pos.Y), [pos]);
+ const [currentPosition, setCurrentPosition] = useState(new Vector3());
+ const [previousPosition, setPreviousPosition] = useState(new Vector3());
+ const [interpolatedPosition, setInterpolatedPosition] = useState(new Vector3());
+ const [interpolationFactor, setInterpolationFactor] = useState(0);
+ const [shouldUpdatePosition, setShouldUpdatePosition] = useState(false);
+ const updatesHistoryRef = useRef([]);
+
+ useEffect(() => {
+ // Delegate update to the next frame
+ setShouldUpdatePosition(true);
+ }, [incomingPosition]);
+
+ const updatePosition = useCallback(() => {
+ const { current: updatesHistory } = updatesHistoryRef;
+
+ // Only set previous position if current position is valid
+ if (currentPosition.length() > 0) {
+ setPreviousPosition(currentPosition.clone());
+ }
+ setCurrentPosition(incomingPosition.clone());
+ setInterpolationFactor(0);
+
+ // Record timestamp in history
+ const timestamp = performance.now();
+ updatesHistory.push(timestamp);
+ if (updatesHistory.length > interpolationLength) {
+ updatesHistory.shift();
+ }
+
+ // Clear position update flag
+ setShouldUpdatePosition(false);
+ }, [currentPosition, incomingPosition, updatesHistoryRef]);
+
+ useFrame((_, delta) => {
+ shouldUpdatePosition && updatePosition();
+
+ const { current: updatesHistory } = updatesHistoryRef;
+
+ const averageTimeBetweenUpdatesInMillis = calculateAverageUpdateTime(updatesHistory) / 1000;
+ const interpolationRate = 1 / averageTimeBetweenUpdatesInMillis;
+ const interpolationSpeed = averageTimeBetweenUpdatesInMillis > 0 ? interpolationRate : 1;
+
+ if (interpolationFactor < 1) {
+ // Interpolate position
+ const newInterpolatedPosition = new Vector3().lerpVectors(previousPosition, currentPosition, interpolationFactor);
+ setInterpolatedPosition(newInterpolatedPosition);
+ setInterpolationFactor((prev) => Math.min(1, prev + delta * interpolationSpeed));
+ } else {
+ // Clamp to last known position
+ setInterpolatedPosition(currentPosition);
+ }
+ });
+
+ return (
+
+ );
+}
diff --git a/dash/src/components/Map.tsx b/dash/src/components/map/Map.tsx
similarity index 89%
rename from dash/src/components/Map.tsx
rename to dash/src/components/map/Map.tsx
index 46a20a42..570ee441 100644
--- a/dash/src/components/Map.tsx
+++ b/dash/src/components/map/Map.tsx
@@ -1,14 +1,12 @@
-import { useEffect, useMemo, useState } from "react";
import clsx from "clsx";
+import { useEffect, useMemo, useState } from "react";
+import type { TrackPosition } from "@/types/map.type";
import type { PositionCar } from "@/types/state.type";
-import type { Map, TrackPosition } from "@/types/map.type";
-import { fetchMap } from "@/lib/fetchMap";
import { objectEntries } from "@/lib/driverHelper";
-import { useDataStore, usePositionStore } from "@/stores/useDataStore";
-import { useSettingsStore } from "@/stores/useSettingsStore";
-import { getTrackStatusMessage } from "@/lib/getTrackStatusMessage";
+import { fetchMap } from "@/lib/fetchMap";
+import { getComputedFlagStyle, getTrackStatusMessage } from "@/lib/getTrackStatusMessage";
import {
createSectors,
findYellowSectors,
@@ -18,6 +16,9 @@ import {
rad,
rotate,
} from "@/lib/map";
+import { useDataStore, usePositionStore } from "@/stores/useDataStore";
+import { useSettingsStore } from "@/stores/useSettingsStore";
+import MapLoader from "./MapLoader";
// This is basically fearlessly copied from
// https://github.com/tdjsnelling/monaco
@@ -45,7 +46,7 @@ export default function Map() {
const [[minX, minY, widthX, widthY], setBounds] = useState<(null | number)[]>([null, null, null, null]);
const [[centerX, centerY], setCenter] = useState<(null | number)[]>([null, null]);
- const [points, setPoints] = useState(null);
+ const [points, setPoints] = useState(null);
const [sectors, setSectors] = useState([]);
const [corners, setCorners] = useState([]);
const [rotation, setRotation] = useState(0);
@@ -105,24 +106,21 @@ export default function Map() {
return sectors
.map((sector) => {
- const color = getSectorColor(sector, status?.bySector, status?.trackColor, yellowSectors);
+ const flagType = getSectorColor(sector, status?.bySector, status?.flagType, yellowSectors);
+ const { stroke } = getComputedFlagStyle(flagType);
return {
- color,
+ color: stroke,
pulse: status?.pulse,
number: sector.number,
- strokeWidth: color === "stroke-white" ? 60 : 120,
- d: `M${sector.points[0].x},${sector.points[0].y} ${sector.points.map((point) => `L${point.x},${point.y}`).join(" ")}`,
+ strokeWidth: flagType === "GREEN" ? 60 : 120,
+ d: generateDrawnSVGPath(sector.points),
};
})
.sort(prioritizeColoredSectors);
}, [trackStatus, sectors]);
if (!points || !minX || !minY || !widthX || !widthY) {
- return (
-
- );
+ return ;
}
return (
@@ -136,7 +134,7 @@ export default function Map() {
strokeWidth={300}
strokeLinejoin="round"
fill="transparent"
- d={`M${points[0].x},${points[0].y} ${points.map((point) => `L${point.x},${point.y}`).join(" ")}`}
+ d={generateDrawnSVGPath(points)}
/>
{renderedSectors.map((sector) => {
@@ -269,3 +267,10 @@ const CarDot = ({ pos, name, color, favoriteDriver, pit, hidden, rotation, cente
);
};
+
+function generateDrawnSVGPath(points: TrackPosition[]) {
+ const formattedCoords = points.map((point) => `${point.x},${point.y}`);
+ const origin = `M${formattedCoords[0]}`;
+ const spline = formattedCoords.map((coord) => `L${coord}`);
+ return `${origin} ${spline.join(" ")}`;
+}
diff --git a/dash/src/components/map/Map3D.tsx b/dash/src/components/map/Map3D.tsx
new file mode 100644
index 00000000..a6d21d8f
--- /dev/null
+++ b/dash/src/components/map/Map3D.tsx
@@ -0,0 +1,252 @@
+import { useEffect, useMemo, useRef, useState } from "react";
+
+import type { FlagType, TrackPosition } from "@/types/map.type";
+
+import { objectEntries } from "@/lib/driverHelper";
+import { fetchMap } from "@/lib/fetchMap";
+import { getComputedFlagStyle, getTrackStatusMessage } from "@/lib/getTrackStatusMessage";
+import { createSectors, findYellowSectors, getSectorColor, MapSector, rad, rotate } from "@/lib/map";
+import { toVector3 } from "@/lib/r3f";
+import { useDataStore, usePositionStore } from "@/stores/useDataStore";
+import { useSettingsStore } from "@/stores/useSettingsStore";
+import { theme } from "@/styles/tailwindTheme";
+import { Line, OrbitControls } from "@react-three/drei";
+import { Canvas } from "@react-three/fiber";
+import { Vector3 } from "three";
+import CornerNumber from "./CornerNumber3D";
+import { InterpolatedDriverIndicator } from "./DriverIndicator";
+import MapLoader from "./MapLoader";
+
+const SPACE = 1000;
+const ROTATION_FIX = 90;
+const CAMERA_FOV = 35;
+
+type Corner = {
+ number: number;
+ pos: TrackPosition;
+ labelPos: TrackPosition;
+};
+
+type RenderedSector3D = {
+ number: number;
+ points: TrackPosition[];
+ flagType: FlagType;
+ hex: string;
+ strokeWidth: number;
+ pulse?: number;
+};
+
+function prioritizeColoredSectors3D(a: RenderedSector3D, b: RenderedSector3D) {
+ if (a.flagType === "GREEN" && b.flagType !== "GREEN") {
+ return -1;
+ }
+ if (a.flagType !== "GREEN" && b.flagType === "GREEN") {
+ return 1;
+ }
+ return a.number - b.number;
+}
+
+function getCenter(xPoints: number[], yPoints: number[]) {
+ const maxBounds = {
+ x: Math.max(...xPoints),
+ y: Math.max(...yPoints),
+ };
+
+ const minBounds = {
+ x: Math.min(...xPoints),
+ y: Math.min(...yPoints),
+ };
+
+ return {
+ x: (maxBounds.x - minBounds.x) * 0.5 + minBounds.x,
+ y: (maxBounds.y - minBounds.y) * 0.5 + minBounds.y,
+ };
+}
+
+export default function Map3D() {
+ const showCornerNumbers = useSettingsStore((state) => state.showCornerNumbers);
+ const favoriteDrivers = useSettingsStore((state) => state.favoriteDrivers);
+
+ const positions = usePositionStore((state) => state.positions);
+ const drivers = useDataStore((state) => state?.driverList);
+ const trackStatus = useDataStore((state) => state?.trackStatus);
+ const timingDrivers = useDataStore((state) => state?.timingData);
+ const raceControlMessages = useDataStore((state) => state?.raceControlMessages?.messages);
+ const circuitKey = useDataStore((state) => state?.sessionInfo?.meeting.circuit.key);
+
+ const [[minX, minY, widthX, widthY], setBounds] = useState<(null | number)[]>([null, null, null, null]);
+ const [[centerX, centerY], setCenter] = useState([0, 0]);
+
+ const [points, setPoints] = useState(null);
+ const [sectors, setSectors] = useState([]);
+ const [corners, setCorners] = useState([]);
+ const [rotation, setRotation] = useState(0);
+
+ // FIXME: This is garbage but I am struggling finding the proper type
+ const controlsRef = useRef(null);
+
+ const defaultCameraDistance = useMemo(() => Math.max(widthX ?? 0, widthY ?? 0), [widthX, widthY]);
+ const defaultCameraPosition = useMemo(
+ () => [centerX, defaultCameraDistance, centerY + defaultCameraDistance] as const,
+ [centerX, centerY, defaultCameraDistance],
+ );
+ const yellowSectors = useMemo(() => findYellowSectors(raceControlMessages), [raceControlMessages]);
+ const renderedSectors = useMemo(() => {
+ const status = getTrackStatusMessage(trackStatus?.status ? parseInt(trackStatus.status) : undefined);
+ return sectors
+ .map((sector) => {
+ const flagType = getSectorColor(sector, status?.bySector, status?.flagType, yellowSectors);
+ const { trackHex } = getComputedFlagStyle(flagType);
+ return {
+ hex: trackHex,
+ flagType: flagType,
+ pulse: status?.pulse,
+ number: sector.number,
+ strokeWidth: flagType === "GREEN" ? 2 : 5,
+ points: sector.points,
+ };
+ })
+ .sort(prioritizeColoredSectors3D);
+ }, [trackStatus, sectors]);
+
+ useEffect(() => {
+ const loadMap = async () => {
+ if (!circuitKey) return;
+ const mapJson = await fetchMap(circuitKey);
+
+ const { x: mapCenterX, y: mapCenterY } = getCenter(mapJson.x, mapJson.y);
+
+ const fixedRotation = mapJson.rotation + ROTATION_FIX;
+
+ const sectors = createSectors(mapJson).map((s) => ({
+ ...s,
+ start: rotate(s.start.x, s.start.y, fixedRotation, mapCenterX, mapCenterY),
+ end: rotate(s.end.x, s.end.y, fixedRotation, mapCenterX, mapCenterY),
+ points: s.points.map((p) => rotate(p.x, p.y, fixedRotation, mapCenterX, mapCenterY)),
+ }));
+
+ const cornerPositions = mapJson.corners.map((corner) => ({
+ number: corner.number,
+ pos: rotate(corner.trackPosition.x, corner.trackPosition.y, fixedRotation, mapCenterX, mapCenterY),
+ labelPos: rotate(
+ corner.trackPosition.x + 540 * Math.cos(rad(corner.angle)),
+ corner.trackPosition.y + 540 * Math.sin(rad(corner.angle)),
+ fixedRotation,
+ mapCenterX,
+ mapCenterY,
+ ),
+ }));
+
+ const rotatedPoints = mapJson.x.map((x, index) =>
+ rotate(x, mapJson.y[index], fixedRotation, mapCenterX, mapCenterY),
+ );
+
+ const pointsX = rotatedPoints.map((item) => item.x);
+ const pointsY = rotatedPoints.map((item) => item.y);
+
+ const cMinX = Math.min(...pointsX) - SPACE;
+ const cMinY = Math.min(...pointsY) - SPACE;
+ const cWidthX = Math.max(...pointsX) - cMinX + SPACE * 2;
+ const cWidthY = Math.max(...pointsY) - cMinY + SPACE * 2;
+
+ setCenter([mapCenterX, mapCenterY]);
+ setBounds([cMinX, cMinY, cWidthX, cWidthY]);
+ setSectors(sectors);
+ setPoints(rotatedPoints);
+ setRotation(fixedRotation);
+ setCorners(cornerPositions);
+ };
+
+ loadMap();
+ }, [circuitKey]);
+
+ if (!points || !minX || !minY || !widthX || !widthY) {
+ return ;
+ }
+
+ return (
+
+
+
+
+
+
+
+ );
+}
diff --git a/dash/src/components/map/MapLoader.tsx b/dash/src/components/map/MapLoader.tsx
new file mode 100644
index 00000000..d7a98410
--- /dev/null
+++ b/dash/src/components/map/MapLoader.tsx
@@ -0,0 +1,7 @@
+export default function MapLoader() {
+ return (
+
+ );
+}
diff --git a/dash/src/hooks/useLookAt.ts b/dash/src/hooks/useLookAt.ts
new file mode 100644
index 00000000..c795de13
--- /dev/null
+++ b/dash/src/hooks/useLookAt.ts
@@ -0,0 +1,14 @@
+import { useFrame } from "@react-three/fiber";
+import { Object3D, Vector3 } from "three";
+
+type LookAtProps = {
+ object: Object3D | undefined | null;
+ target: Vector3;
+};
+
+/**
+ * Make a THREE object look at target.
+ */
+export function useLookAt({ object, target }: LookAtProps) {
+ useFrame(() => object?.lookAt(target));
+}
diff --git a/dash/src/lib/getTrackStatusMessage.ts b/dash/src/lib/getTrackStatusMessage.ts
index cfafb182..7243ce83 100644
--- a/dash/src/lib/getTrackStatusMessage.ts
+++ b/dash/src/lib/getTrackStatusMessage.ts
@@ -1,32 +1,51 @@
+import { FlagType } from "@/types/map.type";
+
type StatusMessage = {
message: string;
- color: string;
- trackColor: string;
- bySector?: boolean;
+ flagType: FlagType;
+ bySector: boolean;
pulse?: number;
- hex: string;
};
-type MessageMap = {
- [key: string]: StatusMessage;
+type MessageMap = Record;
+
+type FlagStyle = {
+ bg: string;
+ stroke: string;
+ trackHex: string;
+ flagHex: string;
};
-export const getTrackStatusMessage = (statusCode: number | undefined): StatusMessage | null => {
- const messageMap: MessageMap = {
- 1: { message: "Track Clear", color: "bg-emerald-500", trackColor: "stroke-white", hex: "#34b981" },
- 2: {
- message: "Yellow Flag",
- color: "bg-yellow-500",
- trackColor: "stroke-yellow-500",
- bySector: true,
- hex: "#f59e0c",
- },
- 3: { message: "Flag", color: "bg-yellow-500", trackColor: "stroke-yellow-500", bySector: true, hex: "#f59e0c" },
- 4: { message: "Safety Car", color: "bg-yellow-500", trackColor: "stroke-yellow-500", hex: "#f59e0c" },
- 5: { message: "Red Flag", color: "bg-red-500", trackColor: "stroke-red-500", hex: "#ef4444" },
- 6: { message: "VSC Deployed", color: "bg-yellow-500", trackColor: "stroke-yellow-500", hex: "#f59e0c" },
- 7: { message: "VSC Ending", color: "bg-yellow-500", trackColor: "stroke-yellow-500", hex: "#f59e0c" },
- };
+type ComputedFlagStyle = FlagStyle & { flag: FlagType };
+
+const STYLE_BY_FLAG_TYPE: Record = {
+ GREEN: { stroke: "stroke-white", bg: "bg-emerald-500", flagHex: "#34b981", trackHex: "#fafafa" },
+ YELLOW: { stroke: "stroke-yellow-500", bg: "bg-yellow-500", flagHex: "#f59e0c", trackHex: "#f59e0c" },
+ RED: { stroke: "stroke-red-500", bg: "bg-red-500", flagHex: "#ef4444", trackHex: "#ef4444" },
+};
- return statusCode ? (messageMap[statusCode] ?? messageMap[0]) : null;
+const MESSAGE_MAP: MessageMap = {
+ 1: { message: "Track Clear", flagType: "GREEN", bySector: false },
+ 2: {
+ message: "Yellow Flag",
+ flagType: "YELLOW",
+ bySector: true,
+ },
+ 3: { message: "Flag", flagType: "YELLOW", bySector: true },
+ 4: { message: "Safety Car", flagType: "YELLOW", bySector: false },
+ 5: { message: "Red Flag", flagType: "RED", bySector: false },
+ 6: { message: "VSC Deployed", flagType: "YELLOW", bySector: false },
+ 7: { message: "VSC Ending", flagType: "YELLOW", bySector: false },
};
+
+export const getTrackStatusMessage = (statusCode: number | undefined): StatusMessage | null => {
+ if (!statusCode) return null;
+ return MESSAGE_MAP[statusCode] ?? MESSAGE_MAP[0];
+};
+
+export function getComputedFlagStyle(flag: FlagType): ComputedFlagStyle {
+ return {
+ ...STYLE_BY_FLAG_TYPE[flag],
+ flag,
+ };
+}
diff --git a/dash/src/lib/map.ts b/dash/src/lib/map.ts
index 1df61867..212314c6 100644
--- a/dash/src/lib/map.ts
+++ b/dash/src/lib/map.ts
@@ -1,4 +1,4 @@
-import type { Map, TrackPosition } from "@/types/map.type";
+import type { FlagType, Map, TrackPosition } from "@/types/map.type";
import type { Message } from "@/types/state.type";
import { sortUtc } from "@/lib/sorting";
@@ -125,6 +125,9 @@ export const prioritizeColoredSectors = (a: RenderedSector, b: RenderedSector) =
export const getSectorColor = (
sector: MapSector,
bySector: boolean | undefined,
- trackColor: string | undefined = "stroke-white",
+ flagType: FlagType | undefined = "GREEN",
yellowSectors: Set,
-) => (bySector ? (yellowSectors.has(sector.number) ? trackColor : "stroke-white") : trackColor);
+): FlagType => {
+ if (!bySector) return flagType;
+ return yellowSectors.has(sector.number) ? flagType : "GREEN";
+};
diff --git a/dash/src/lib/r3f.tsx b/dash/src/lib/r3f.tsx
new file mode 100644
index 00000000..6f1eb58a
--- /dev/null
+++ b/dash/src/lib/r3f.tsx
@@ -0,0 +1,6 @@
+import { TrackPosition } from "@/types/map.type";
+import { Vector3 } from "three";
+
+export function toVector3(point: TrackPosition) {
+ return new Vector3(point.x, 0, point.y);
+}
diff --git a/dash/src/stores/useSettingsStore.ts b/dash/src/stores/useSettingsStore.ts
index b0902181..1b37724a 100644
--- a/dash/src/stores/useSettingsStore.ts
+++ b/dash/src/stores/useSettingsStore.ts
@@ -1,5 +1,5 @@
-import { persist, createJSONStorage, subscribeWithSelector } from "zustand/middleware";
import { create } from "zustand";
+import { createJSONStorage, persist, subscribeWithSelector } from "zustand/middleware";
type SpeedUnit = "metric" | "imperial";
@@ -34,6 +34,9 @@ type SettingsStore = {
raceControlChimeVolume: number;
setRaceControlChimeVolume: (raceControlChimeVolume: number) => void;
+
+ use3DMap: boolean;
+ setUse3DMap: (use3DMap: boolean) => void;
};
export const useSettingsStore = create(
@@ -71,6 +74,9 @@ export const useSettingsStore = create(
raceControlChimeVolume: 50,
setRaceControlChimeVolume: (raceControlChimeVolume: number) => set({ raceControlChimeVolume }),
+
+ use3DMap: false,
+ setUse3DMap: (use3DMap: boolean) => set({ use3DMap }),
}),
{
name: "settings-storage",
diff --git a/dash/src/styles/tailwindTheme.tsx b/dash/src/styles/tailwindTheme.tsx
new file mode 100644
index 00000000..1528f9bd
--- /dev/null
+++ b/dash/src/styles/tailwindTheme.tsx
@@ -0,0 +1,5 @@
+import tailwindConfig from "tailwind.config";
+import resolveConfig from "tailwindcss/resolveConfig";
+
+const fullTailwindConfig = resolveConfig(tailwindConfig);
+export const { theme } = fullTailwindConfig;
diff --git a/dash/src/types/map.type.ts b/dash/src/types/map.type.ts
index ed409acd..8f454706 100644
--- a/dash/src/types/map.type.ts
+++ b/dash/src/types/map.type.ts
@@ -42,3 +42,5 @@ export type TrackPosition = {
x: number;
y: number;
};
+
+export type FlagType = "GREEN" | "YELLOW" | "RED";
\ No newline at end of file
diff --git a/dash/yarn.lock b/dash/yarn.lock
index 19aa075b..1362772b 100644
--- a/dash/yarn.lock
+++ b/dash/yarn.lock
@@ -12,6 +12,15 @@ __metadata:
languageName: node
linkType: hard
+"@babel/runtime@npm:^7.17.8, @babel/runtime@npm:^7.26.0":
+ version: 7.26.10
+ resolution: "@babel/runtime@npm:7.26.10"
+ dependencies:
+ regenerator-runtime: "npm:^0.14.0"
+ checksum: 10c0/6dc6d88c7908f505c4f7770fb4677dfa61f68f659b943c2be1f2a99cb6680343462867abf2d49822adc435932919b36c77ac60125793e719ea8745f2073d3745
+ languageName: node
+ linkType: hard
+
"@emnapi/runtime@npm:^1.2.0":
version: 1.3.1
resolution: "@emnapi/runtime@npm:1.3.1"
@@ -331,6 +340,24 @@ __metadata:
languageName: node
linkType: hard
+"@mediapipe/tasks-vision@npm:0.10.17":
+ version: 0.10.17
+ resolution: "@mediapipe/tasks-vision@npm:0.10.17"
+ checksum: 10c0/f2f5dd9ca39d562b902a6d964f8b786f17a143f42776d0d26b8c79632b10cf210e28d98ec92de757b7bb2e6595ed4f9bbf5e49f1709b09dc08709bd276ced442
+ languageName: node
+ linkType: hard
+
+"@monogrid/gainmap-js@npm:^3.0.6":
+ version: 3.1.0
+ resolution: "@monogrid/gainmap-js@npm:3.1.0"
+ dependencies:
+ promise-worker-transferable: "npm:^1.0.4"
+ peerDependencies:
+ three: ">= 0.159.0"
+ checksum: 10c0/0afae39fdca31456a57803d5751c0e5b742d8dfac53aa95b21b43fbf02ad250cd80f5ae0368071128729754b89ff1be6317e1e23be86706c0d3e227bb5f82db2
+ languageName: node
+ linkType: hard
+
"@next/env@npm:15.0.3":
version: 15.0.3
resolution: "@next/env@npm:15.0.3"
@@ -450,6 +477,36 @@ __metadata:
languageName: node
linkType: hard
+"@pmndrs/msdfonts@npm:^0.8.14":
+ version: 0.8.14
+ resolution: "@pmndrs/msdfonts@npm:0.8.14"
+ checksum: 10c0/3760f206afa667f9e9b79a6792290975449bb5ad32146c4b0b6391253acecec733ad987527ab9b3b13017cd0f71b549337289283e0e1e8aadc65656089c5fb4b
+ languageName: node
+ linkType: hard
+
+"@pmndrs/uikit@npm:^0.8.14":
+ version: 0.8.14
+ resolution: "@pmndrs/uikit@npm:0.8.14"
+ dependencies:
+ "@pmndrs/msdfonts": "npm:^0.8.14"
+ "@preact/signals-core": "npm:^1.5.1"
+ inline-style-parser: "npm:^0.2.3"
+ node-html-parser: "npm:^6.1.13"
+ tw-to-css: "npm:^0.0.12"
+ yoga-layout: "npm:^3.2.1"
+ peerDependencies:
+ three: ">=0.160"
+ checksum: 10c0/1c2dbd259f07c5fa1c7ff67b9e0fd27ecac3617702a1077eb024f2d774ca13e0445af6b2994ecdd933ffdb27cb330599581f8a5fcde715f4994bed72a4a220e1
+ languageName: node
+ linkType: hard
+
+"@preact/signals-core@npm:^1.5.1":
+ version: 1.8.0
+ resolution: "@preact/signals-core@npm:1.8.0"
+ checksum: 10c0/fa773157621d881e7aefddb8dbded805d8203600211040cc4b5907726e288a163fa58558c1d36bc7085d75e6488af0a806322bbbed005d08be76a76f40244246
+ languageName: node
+ linkType: hard
+
"@react-aria/focus@npm:^3.17.1":
version: 3.18.4
resolution: "@react-aria/focus@npm:3.18.4"
@@ -516,6 +573,107 @@ __metadata:
languageName: node
linkType: hard
+"@react-three/drei@npm:^10.0.5":
+ version: 10.0.5
+ resolution: "@react-three/drei@npm:10.0.5"
+ dependencies:
+ "@babel/runtime": "npm:^7.26.0"
+ "@mediapipe/tasks-vision": "npm:0.10.17"
+ "@monogrid/gainmap-js": "npm:^3.0.6"
+ "@use-gesture/react": "npm:^10.3.1"
+ camera-controls: "npm:^2.9.0"
+ cross-env: "npm:^7.0.3"
+ detect-gpu: "npm:^5.0.56"
+ glsl-noise: "npm:^0.0.0"
+ hls.js: "npm:^1.5.17"
+ maath: "npm:^0.10.8"
+ meshline: "npm:^3.3.1"
+ stats-gl: "npm:^2.2.8"
+ stats.js: "npm:^0.17.0"
+ suspend-react: "npm:^0.1.3"
+ three-mesh-bvh: "npm:^0.8.3"
+ three-stdlib: "npm:^2.35.6"
+ troika-three-text: "npm:^0.52.0"
+ tunnel-rat: "npm:^0.1.2"
+ use-sync-external-store: "npm:^1.4.0"
+ utility-types: "npm:^3.11.0"
+ zustand: "npm:^5.0.1"
+ peerDependencies:
+ "@react-three/fiber": ^9.0.0
+ react: ^19
+ react-dom: ^19
+ three: ">=0.159"
+ peerDependenciesMeta:
+ react-dom:
+ optional: true
+ checksum: 10c0/9cddb291a5032563a382cfa31b66fd226158e0f98642c4a0f31d29a702a8c31e09857cc11542a201ff0fb86b7d5504ddfeae4bd83574258b3aebb7ea655e93e4
+ languageName: node
+ linkType: hard
+
+"@react-three/fiber@npm:^9.1.0":
+ version: 9.1.0
+ resolution: "@react-three/fiber@npm:9.1.0"
+ dependencies:
+ "@babel/runtime": "npm:^7.17.8"
+ "@types/react-reconciler": "npm:^0.28.9"
+ "@types/webxr": "npm:*"
+ base64-js: "npm:^1.5.1"
+ buffer: "npm:^6.0.3"
+ its-fine: "npm:^2.0.0"
+ react-reconciler: "npm:^0.31.0"
+ react-use-measure: "npm:^2.1.7"
+ scheduler: "npm:^0.25.0"
+ suspend-react: "npm:^0.1.3"
+ use-sync-external-store: "npm:^1.4.0"
+ zustand: "npm:^5.0.3"
+ peerDependencies:
+ expo: ">=43.0"
+ expo-asset: ">=8.4"
+ expo-file-system: ">=11.0"
+ expo-gl: ">=11.0"
+ react: ^19.0.0
+ react-dom: ^19.0.0
+ react-native: ">=0.78"
+ three: ">=0.156"
+ peerDependenciesMeta:
+ expo:
+ optional: true
+ expo-asset:
+ optional: true
+ expo-file-system:
+ optional: true
+ expo-gl:
+ optional: true
+ react-dom:
+ optional: true
+ react-native:
+ optional: true
+ checksum: 10c0/418103e098d929fcee8b7f05e14f976d01b453958e23f79b00f2d477c9309092e0696de88182155106c6a039f1248112890dcfcbbafb8f2dc79830a101a164fb
+ languageName: node
+ linkType: hard
+
+"@react-three/uikit@npm:^0.8.14":
+ version: 0.8.14
+ resolution: "@react-three/uikit@npm:0.8.14"
+ dependencies:
+ "@pmndrs/uikit": "npm:^0.8.14"
+ "@preact/signals-core": "npm:^1.5.1"
+ chalk: "npm:^5.3.0"
+ commander: "npm:^12.0.0"
+ ora: "npm:^8.0.1"
+ prettier: "npm:^3.2.5"
+ prompts: "npm:^2.4.2"
+ zod: "npm:^3.22.4"
+ zustand: "npm:^4.5.2"
+ peerDependencies:
+ "@react-three/fiber": ">=8"
+ react: ">=18"
+ bin:
+ uikit: dist/cli/index.js
+ checksum: 10c0/6d0c44a709e94c6c54631cda306314057343244d60dcec4e7c5e44177a1e20023df357ff9c4bd591199b90e7088a5ecf9b0296dc39a71b5b96ea9135e99ebf4b
+ languageName: node
+ linkType: hard
+
"@react-types/shared@npm:^3.25.0":
version: 3.25.0
resolution: "@react-types/shared@npm:3.25.0"
@@ -569,6 +727,20 @@ __metadata:
languageName: node
linkType: hard
+"@tweenjs/tween.js@npm:~23.1.3":
+ version: 23.1.3
+ resolution: "@tweenjs/tween.js@npm:23.1.3"
+ checksum: 10c0/811b30f5f0e7409fb41833401c501c2d6f600eb5f43039dd9067a7f70aff6dad5f5ce1233848e13f0b33a269a160d9c133f344d986cbff4f1f6b72ddecd06c89
+ languageName: node
+ linkType: hard
+
+"@types/draco3d@npm:^1.4.0":
+ version: 1.4.10
+ resolution: "@types/draco3d@npm:1.4.10"
+ checksum: 10c0/431e333b2fd67e2b081e8697e71dfb82a125fc04b2cbfa0205e4d521719d3749c964b2bf82bb7944ba0a12e5bc3d9afe387a58e68b195d838fcdbc65c8572a35
+ languageName: node
+ linkType: hard
+
"@types/lodash@npm:4.17.13":
version: 4.17.13
resolution: "@types/lodash@npm:4.17.13"
@@ -585,6 +757,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/offscreencanvas@npm:^2019.6.4":
+ version: 2019.7.3
+ resolution: "@types/offscreencanvas@npm:2019.7.3"
+ checksum: 10c0/6d1dfae721d321cd2b5435f347a0e53b09f33b2f9e9333396480f592823bc323847b8169f7d251d2285cb93dbc1ba2e30741ac5cf4b1c003d660fd4c24526963
+ languageName: node
+ linkType: hard
+
"@types/pako@npm:2.0.3":
version: 2.0.3
resolution: "@types/pako@npm:2.0.3"
@@ -608,6 +787,15 @@ __metadata:
languageName: node
linkType: hard
+"@types/react-reconciler@npm:^0.28.9":
+ version: 0.28.9
+ resolution: "@types/react-reconciler@npm:0.28.9"
+ peerDependencies:
+ "@types/react": "*"
+ checksum: 10c0/9fe71fa856aab2cd4742fe0416bdd4f5c82ecc05ef6451ee7fcb65a5efdf5fa588f5820fbe2a665b15371b0da3bfc4097f28bb6d450b9a834af2d0fc00f403bd
+ languageName: node
+ linkType: hard
+
"@types/react@npm:*, @types/react@npm:18.3.12":
version: 18.3.12
resolution: "@types/react@npm:18.3.12"
@@ -618,6 +806,59 @@ __metadata:
languageName: node
linkType: hard
+"@types/stats.js@npm:*":
+ version: 0.17.3
+ resolution: "@types/stats.js@npm:0.17.3"
+ checksum: 10c0/ccccc992c6dfe08fb85049aa3ce44ca7e428db8da4a3edd20298f1c8b72768021fa8bacdfbe8e9735a7552ee5d57f667c6f557050ad2d9a87b699b3566a6177a
+ languageName: node
+ linkType: hard
+
+"@types/three@npm:*, @types/three@npm:^0.174.0":
+ version: 0.174.0
+ resolution: "@types/three@npm:0.174.0"
+ dependencies:
+ "@tweenjs/tween.js": "npm:~23.1.3"
+ "@types/stats.js": "npm:*"
+ "@types/webxr": "npm:*"
+ "@webgpu/types": "npm:*"
+ fflate: "npm:~0.8.2"
+ meshoptimizer: "npm:~0.18.1"
+ checksum: 10c0/338e9d8d01d373014ee3c3b686a0d633c1a29603fe199c7c5340fc1a35c17e6eea0d0a7bba5ff9a33b8e462e5b471c0829c2aaa34ab2300e8d6e7e3f885e45b5
+ languageName: node
+ linkType: hard
+
+"@types/webxr@npm:*, @types/webxr@npm:^0.5.2":
+ version: 0.5.21
+ resolution: "@types/webxr@npm:0.5.21"
+ checksum: 10c0/7b6a7001f8592a0c8f1bff46352a451a5bcc24d016d10985a4d7bff9b778c4530fb82e48db1a7e1da67ff4f75bff49384fdac5e56fa103455f8281c3c0f403a6
+ languageName: node
+ linkType: hard
+
+"@use-gesture/core@npm:10.3.1":
+ version: 10.3.1
+ resolution: "@use-gesture/core@npm:10.3.1"
+ checksum: 10c0/2e3b5c0f7fe26cdb47be3a9c2a58a6a9edafc5b2895b07d2898eda9ab5a2b29fb0098b15597baa0856907b593075cd44cc69bba4785c9cfb7b6fabaa3b52cd3e
+ languageName: node
+ linkType: hard
+
+"@use-gesture/react@npm:^10.3.1":
+ version: 10.3.1
+ resolution: "@use-gesture/react@npm:10.3.1"
+ dependencies:
+ "@use-gesture/core": "npm:10.3.1"
+ peerDependencies:
+ react: ">= 16.8.0"
+ checksum: 10c0/978da66e4e7c424866ad52eba8fdf0ce93a4c8fc44f8837c7043e68c6a6107cd67e817fffb27f7db2ae871ef2f6addb0c8ddf1586f24c67b7e6aef1646c668cf
+ languageName: node
+ linkType: hard
+
+"@webgpu/types@npm:*":
+ version: 0.1.58
+ resolution: "@webgpu/types@npm:0.1.58"
+ checksum: 10c0/6a2f5acfc7aa9e2c47f843897c3df31d79b099cdbc0779ddac9bf7bd126675d5344329a6824daf3a88cac90a8e058c342aa2813efe781040aba7b4fb356d7f4d
+ languageName: node
+ linkType: hard
+
"abbrev@npm:^2.0.0":
version: 2.0.0
resolution: "abbrev@npm:2.0.0"
@@ -723,6 +964,22 @@ __metadata:
languageName: node
linkType: hard
+"base64-js@npm:^1.3.1, base64-js@npm:^1.5.1":
+ version: 1.5.1
+ resolution: "base64-js@npm:1.5.1"
+ checksum: 10c0/f23823513b63173a001030fae4f2dabe283b99a9d324ade3ad3d148e218134676f1ee8568c877cd79ec1c53158dcf2d2ba527a97c606618928ba99dd930102bf
+ languageName: node
+ linkType: hard
+
+"bidi-js@npm:^1.0.2":
+ version: 1.0.3
+ resolution: "bidi-js@npm:1.0.3"
+ dependencies:
+ require-from-string: "npm:^2.0.2"
+ checksum: 10c0/fdddea4aa4120a34285486f2267526cd9298b6e8b773ad25e765d4f104b6d7437ab4ba542e6939e3ac834a7570bcf121ee2cf6d3ae7cd7082c4b5bedc8f271e1
+ languageName: node
+ linkType: hard
+
"binary-extensions@npm:^2.0.0":
version: 2.3.0
resolution: "binary-extensions@npm:2.3.0"
@@ -730,6 +987,13 @@ __metadata:
languageName: node
linkType: hard
+"boolbase@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "boolbase@npm:1.0.0"
+ checksum: 10c0/e4b53deb4f2b85c52be0e21a273f2045c7b6a6ea002b0e139c744cb6f95e9ec044439a52883b0d74dedd1ff3da55ed140cfdddfed7fb0cccbed373de5dce1bcf
+ languageName: node
+ linkType: hard
+
"brace-expansion@npm:^2.0.1":
version: 2.0.1
resolution: "brace-expansion@npm:2.0.1"
@@ -762,6 +1026,16 @@ __metadata:
languageName: node
linkType: hard
+"buffer@npm:^6.0.3":
+ version: 6.0.3
+ resolution: "buffer@npm:6.0.3"
+ dependencies:
+ base64-js: "npm:^1.3.1"
+ ieee754: "npm:^1.2.1"
+ checksum: 10c0/2a905fbbcde73cc5d8bd18d1caa23715d5f83a5935867c2329f0ac06104204ba7947be098fe1317fbd8830e26090ff8e764f08cd14fefc977bb248c3487bcbd0
+ languageName: node
+ linkType: hard
+
"busboy@npm:1.6.0":
version: 1.6.0
resolution: "busboy@npm:1.6.0"
@@ -798,6 +1072,15 @@ __metadata:
languageName: node
linkType: hard
+"camera-controls@npm:^2.9.0":
+ version: 2.10.0
+ resolution: "camera-controls@npm:2.10.0"
+ peerDependencies:
+ three: ">=0.126.1"
+ checksum: 10c0/c4289f632f536771cf0fc8b28c3208f6c11e6bcaec2b85319e176a2d85c7e4f83a369d2b131306bd4a79df986bedb1f5e3d50a198803e91dc0e4e9ed81c59d0c
+ languageName: node
+ linkType: hard
+
"caniuse-lite@npm:^1.0.30001579, caniuse-lite@npm:^1.0.30001646, caniuse-lite@npm:^1.0.30001669":
version: 1.0.30001680
resolution: "caniuse-lite@npm:1.0.30001680"
@@ -805,7 +1088,14 @@ __metadata:
languageName: node
linkType: hard
-"chokidar@npm:^3.6.0":
+"chalk@npm:^5.3.0":
+ version: 5.4.1
+ resolution: "chalk@npm:5.4.1"
+ checksum: 10c0/b23e88132c702f4855ca6d25cb5538b1114343e41472d5263ee8a37cccfccd9c4216d111e1097c6a27830407a1dc81fecdf2a56f2c63033d4dbbd88c10b0dcef
+ languageName: node
+ linkType: hard
+
+"chokidar@npm:^3.5.3, chokidar@npm:^3.6.0":
version: 3.6.0
resolution: "chokidar@npm:3.6.0"
dependencies:
@@ -838,6 +1128,22 @@ __metadata:
languageName: node
linkType: hard
+"cli-cursor@npm:^5.0.0":
+ version: 5.0.0
+ resolution: "cli-cursor@npm:5.0.0"
+ dependencies:
+ restore-cursor: "npm:^5.0.0"
+ checksum: 10c0/7ec62f69b79f6734ab209a3e4dbdc8af7422d44d360a7cb1efa8a0887bbe466a6e625650c466fe4359aee44dbe2dc0b6994b583d40a05d0808a5cb193641d220
+ languageName: node
+ linkType: hard
+
+"cli-spinners@npm:^2.9.2":
+ version: 2.9.2
+ resolution: "cli-spinners@npm:2.9.2"
+ checksum: 10c0/907a1c227ddf0d7a101e7ab8b300affc742ead4b4ebe920a5bf1bc6d45dce2958fcd195eb28fa25275062fe6fa9b109b93b63bc8033396ed3bcb50297008b3a3
+ languageName: node
+ linkType: hard
+
"client-only@npm:0.0.1":
version: 0.0.1
resolution: "client-only@npm:0.0.1"
@@ -888,6 +1194,13 @@ __metadata:
languageName: node
linkType: hard
+"commander@npm:^12.0.0":
+ version: 12.1.0
+ resolution: "commander@npm:12.1.0"
+ checksum: 10c0/6e1996680c083b3b897bfc1cfe1c58dfbcd9842fd43e1aaf8a795fbc237f65efcc860a3ef457b318e73f29a4f4a28f6403c3d653d021d960e4632dd45bde54a9
+ languageName: node
+ linkType: hard
+
"commander@npm:^4.0.0":
version: 4.1.1
resolution: "commander@npm:4.1.1"
@@ -895,6 +1208,18 @@ __metadata:
languageName: node
linkType: hard
+"cross-env@npm:^7.0.3":
+ version: 7.0.3
+ resolution: "cross-env@npm:7.0.3"
+ dependencies:
+ cross-spawn: "npm:^7.0.1"
+ bin:
+ cross-env: src/bin/cross-env.js
+ cross-env-shell: src/bin/cross-env-shell.js
+ checksum: 10c0/f3765c25746c69fcca369655c442c6c886e54ccf3ab8c16847d5ad0e91e2f337d36eedc6599c1227904bf2a228d721e690324446876115bc8e7b32a866735ecf
+ languageName: node
+ linkType: hard
+
"cross-spawn@npm:^7.0.0":
version: 7.0.5
resolution: "cross-spawn@npm:7.0.5"
@@ -906,6 +1231,37 @@ __metadata:
languageName: node
linkType: hard
+"cross-spawn@npm:^7.0.1":
+ version: 7.0.6
+ resolution: "cross-spawn@npm:7.0.6"
+ dependencies:
+ path-key: "npm:^3.1.0"
+ shebang-command: "npm:^2.0.0"
+ which: "npm:^2.0.1"
+ checksum: 10c0/053ea8b2135caff68a9e81470e845613e374e7309a47731e81639de3eaeb90c3d01af0e0b44d2ab9d50b43467223b88567dfeb3262db942dc063b9976718ffc1
+ languageName: node
+ linkType: hard
+
+"css-select@npm:^5.1.0":
+ version: 5.1.0
+ resolution: "css-select@npm:5.1.0"
+ dependencies:
+ boolbase: "npm:^1.0.0"
+ css-what: "npm:^6.1.0"
+ domhandler: "npm:^5.0.2"
+ domutils: "npm:^3.0.1"
+ nth-check: "npm:^2.0.1"
+ checksum: 10c0/551c60dba5b54054741032c1793b5734f6ba45e23ae9e82761a3c0ed1acbb8cfedfa443aaba3a3c1a54cac12b456d2012a09d2cd5f0e82e430454c1b9d84d500
+ languageName: node
+ linkType: hard
+
+"css-what@npm:^6.1.0":
+ version: 6.1.0
+ resolution: "css-what@npm:6.1.0"
+ checksum: 10c0/a09f5a6b14ba8dcf57ae9a59474722e80f20406c53a61e9aedb0eedc693b135113ffe2983f4efc4b5065ae639442e9ae88df24941ef159c218b231011d733746
+ languageName: node
+ linkType: hard
+
"cssesc@npm:^3.0.0":
version: 3.0.0
resolution: "cssesc@npm:3.0.0"
@@ -934,6 +1290,15 @@ __metadata:
languageName: node
linkType: hard
+"detect-gpu@npm:^5.0.56":
+ version: 5.0.70
+ resolution: "detect-gpu@npm:5.0.70"
+ dependencies:
+ webgl-constants: "npm:^1.1.1"
+ checksum: 10c0/5a2053d4779edb3490821599b316b5362c8b55c30b82806c64bcfd21f40c67e2debfd677937899080aea2b27765471552bafeeae9c9f1cf63bdd07461a7e2163
+ languageName: node
+ linkType: hard
+
"detect-libc@npm:^2.0.3":
version: 2.0.3
resolution: "detect-libc@npm:2.0.3"
@@ -955,6 +1320,51 @@ __metadata:
languageName: node
linkType: hard
+"dom-serializer@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "dom-serializer@npm:2.0.0"
+ dependencies:
+ domelementtype: "npm:^2.3.0"
+ domhandler: "npm:^5.0.2"
+ entities: "npm:^4.2.0"
+ checksum: 10c0/d5ae2b7110ca3746b3643d3ef60ef823f5f078667baf530cec096433f1627ec4b6fa8c072f09d079d7cda915fd2c7bc1b7b935681e9b09e591e1e15f4040b8e2
+ languageName: node
+ linkType: hard
+
+"domelementtype@npm:^2.3.0":
+ version: 2.3.0
+ resolution: "domelementtype@npm:2.3.0"
+ checksum: 10c0/686f5a9ef0fff078c1412c05db73a0dce096190036f33e400a07e2a4518e9f56b1e324f5c576a0a747ef0e75b5d985c040b0d51945ce780c0dd3c625a18cd8c9
+ languageName: node
+ linkType: hard
+
+"domhandler@npm:^5.0.2, domhandler@npm:^5.0.3":
+ version: 5.0.3
+ resolution: "domhandler@npm:5.0.3"
+ dependencies:
+ domelementtype: "npm:^2.3.0"
+ checksum: 10c0/bba1e5932b3e196ad6862286d76adc89a0dbf0c773e5ced1eb01f9af930c50093a084eff14b8de5ea60b895c56a04d5de8bbc4930c5543d029091916770b2d2a
+ languageName: node
+ linkType: hard
+
+"domutils@npm:^3.0.1":
+ version: 3.2.2
+ resolution: "domutils@npm:3.2.2"
+ dependencies:
+ dom-serializer: "npm:^2.0.0"
+ domelementtype: "npm:^2.3.0"
+ domhandler: "npm:^5.0.3"
+ checksum: 10c0/47938f473b987ea71cd59e59626eb8666d3aa8feba5266e45527f3b636c7883cca7e582d901531961f742c519d7514636b7973353b648762b2e3bedbf235fada
+ languageName: node
+ linkType: hard
+
+"draco3d@npm:^1.4.1":
+ version: 1.5.7
+ resolution: "draco3d@npm:1.5.7"
+ checksum: 10c0/4419509bb93c31560a22a1a54e1c394a5b5017cab39941120c75151d941c11dec05925abf31f597ac2694c570b78c04f82aa3d69e5311f8f8e71fc8b9d92d12f
+ languageName: node
+ linkType: hard
+
"eastasianwidth@npm:^0.2.0":
version: 0.2.0
resolution: "eastasianwidth@npm:0.2.0"
@@ -969,6 +1379,13 @@ __metadata:
languageName: node
linkType: hard
+"emoji-regex@npm:^10.3.0":
+ version: 10.4.0
+ resolution: "emoji-regex@npm:10.4.0"
+ checksum: 10c0/a3fcedfc58bfcce21a05a5f36a529d81e88d602100145fcca3dc6f795e3c8acc4fc18fe773fbf9b6d6e9371205edb3afa2668ec3473fa2aa7fd47d2a9d46482d
+ languageName: node
+ linkType: hard
+
"emoji-regex@npm:^8.0.0":
version: 8.0.0
resolution: "emoji-regex@npm:8.0.0"
@@ -992,6 +1409,13 @@ __metadata:
languageName: node
linkType: hard
+"entities@npm:^4.2.0":
+ version: 4.5.0
+ resolution: "entities@npm:4.5.0"
+ checksum: 10c0/5b039739f7621f5d1ad996715e53d964035f75ad3b9a4d38c6b3804bb226e282ffeae2443624d8fdd9c47d8e926ae9ac009c54671243f0c3294c26af7cc85250
+ languageName: node
+ linkType: hard
+
"env-paths@npm:^2.2.0":
version: 2.2.1
resolution: "env-paths@npm:2.2.1"
@@ -1013,6 +1437,13 @@ __metadata:
languageName: node
linkType: hard
+"escape-string-regexp@npm:^1.0.3":
+ version: 1.0.5
+ resolution: "escape-string-regexp@npm:1.0.5"
+ checksum: 10c0/a968ad453dd0c2724e14a4f20e177aaf32bb384ab41b674a8454afe9a41c5e6fe8903323e0a1052f56289d04bd600f81278edf140b0fcc02f5cac98d0f5b5371
+ languageName: node
+ linkType: hard
+
"exponential-backoff@npm:^3.1.1":
version: 3.1.1
resolution: "exponential-backoff@npm:3.1.1"
@@ -1020,17 +1451,28 @@ __metadata:
languageName: node
linkType: hard
+"extend@npm:^3.0.1":
+ version: 3.0.2
+ resolution: "extend@npm:3.0.2"
+ checksum: 10c0/73bf6e27406e80aa3e85b0d1c4fd987261e628064e170ca781125c0b635a3dabad5e05adbf07595ea0cf1e6c5396cacb214af933da7cbaf24fe75ff14818e8f9
+ languageName: node
+ linkType: hard
+
"f1-dash@workspace:.":
version: 0.0.0-use.local
resolution: "f1-dash@workspace:."
dependencies:
"@fireworks-js/react": "npm:^2.10.8"
"@headlessui/react": "npm:2.2.0"
+ "@react-three/drei": "npm:^10.0.5"
+ "@react-three/fiber": "npm:^9.1.0"
+ "@react-three/uikit": "npm:^0.8.14"
"@types/lodash": "npm:4.17.13"
"@types/node": "npm:20.11.10"
"@types/pako": "npm:2.0.3"
"@types/react": "npm:18.3.12"
"@types/react-dom": "npm:18.3.1"
+ "@types/three": "npm:^0.174.0"
autoprefixer: "npm:10.4.20"
clsx: "npm:2.1.1"
framer-motion: "npm:11.11.17"
@@ -1045,12 +1487,26 @@ __metadata:
react-dom: "npm:18.3.1"
sharp: "npm:0.33.5"
tailwindcss: "npm:3.4.15"
+ three: "npm:^0.174.0"
typescript: "npm:5.6.3"
zod: "npm:3.23.8"
zustand: "npm:5.0.1"
languageName: unknown
linkType: soft
+"fast-glob@npm:^3.2.12":
+ version: 3.3.3
+ resolution: "fast-glob@npm:3.3.3"
+ dependencies:
+ "@nodelib/fs.stat": "npm:^2.0.2"
+ "@nodelib/fs.walk": "npm:^1.2.3"
+ glob-parent: "npm:^5.1.2"
+ merge2: "npm:^1.3.0"
+ micromatch: "npm:^4.0.8"
+ checksum: 10c0/f6aaa141d0d3384cf73cbcdfc52f475ed293f6d5b65bfc5def368b09163a9f7e5ec2b3014d80f733c405f58e470ee0cc451c2937685045cddcdeaa24199c43fe
+ languageName: node
+ linkType: hard
+
"fast-glob@npm:^3.3.2":
version: 3.3.2
resolution: "fast-glob@npm:3.3.2"
@@ -1073,6 +1529,20 @@ __metadata:
languageName: node
linkType: hard
+"fflate@npm:^0.6.9":
+ version: 0.6.10
+ resolution: "fflate@npm:0.6.10"
+ checksum: 10c0/c452f720e4cb404b300fceb8ef0bdf345f18fbfd3f57f7d0974dce5f5e2ac0e8dd4b6ff4bb7061ae74fd919b9c707172f9dbd44d91149b1137199b8c705768f1
+ languageName: node
+ linkType: hard
+
+"fflate@npm:~0.8.2":
+ version: 0.8.2
+ resolution: "fflate@npm:0.8.2"
+ checksum: 10c0/03448d630c0a583abea594835a9fdb2aaf7d67787055a761515bf4ed862913cfd693b4c4ffd5c3f3b355a70cf1e19033e9ae5aedcca103188aaff91b8bd6e293
+ languageName: node
+ linkType: hard
+
"fill-range@npm:^7.1.1":
version: 7.1.1
resolution: "fill-range@npm:7.1.1"
@@ -1179,6 +1649,13 @@ __metadata:
languageName: node
linkType: hard
+"get-east-asian-width@npm:^1.0.0":
+ version: 1.3.0
+ resolution: "get-east-asian-width@npm:1.3.0"
+ checksum: 10c0/1a049ba697e0f9a4d5514c4623781c5246982bdb61082da6b5ae6c33d838e52ce6726407df285cdbb27ec1908b333cf2820989bd3e986e37bb20979437fdf34b
+ languageName: node
+ linkType: hard
+
"glob-parent@npm:^5.1.2, glob-parent@npm:~5.1.2":
version: 5.1.2
resolution: "glob-parent@npm:5.1.2"
@@ -1213,6 +1690,13 @@ __metadata:
languageName: node
linkType: hard
+"glsl-noise@npm:^0.0.0":
+ version: 0.0.0
+ resolution: "glsl-noise@npm:0.0.0"
+ checksum: 10c0/442630e86ed109079f4ed92f3b59d24d0b9da60c03cb8ac9313a056996bf4b5d696b4c6121ee29952e8a19c5cf174a999cfe672464959db36fc75334c3134677
+ languageName: node
+ linkType: hard
+
"graceful-fs@npm:^4.2.6":
version: 4.2.11
resolution: "graceful-fs@npm:4.2.11"
@@ -1229,6 +1713,22 @@ __metadata:
languageName: node
linkType: hard
+"he@npm:1.2.0":
+ version: 1.2.0
+ resolution: "he@npm:1.2.0"
+ bin:
+ he: bin/he
+ checksum: 10c0/a27d478befe3c8192f006cdd0639a66798979dfa6e2125c6ac582a19a5ebfec62ad83e8382e6036170d873f46e4536a7e795bf8b95bf7c247f4cc0825ccc8c17
+ languageName: node
+ linkType: hard
+
+"hls.js@npm:^1.5.17":
+ version: 1.5.20
+ resolution: "hls.js@npm:1.5.20"
+ checksum: 10c0/1d0357e381f6fa81a6b2737aab7fcf88b79b8f9b23c66665e0405eea6c2cfb58df00ba7fc72ee71990c6898d67f092732f8e7046914098ebba2c33323dc627f4
+ languageName: node
+ linkType: hard
+
"http-cache-semantics@npm:^4.1.1":
version: 4.1.1
resolution: "http-cache-semantics@npm:4.1.1"
@@ -1265,6 +1765,20 @@ __metadata:
languageName: node
linkType: hard
+"ieee754@npm:^1.2.1":
+ version: 1.2.1
+ resolution: "ieee754@npm:1.2.1"
+ checksum: 10c0/b0782ef5e0935b9f12883a2e2aa37baa75da6e66ce6515c168697b42160807d9330de9a32ec1ed73149aea02e0d822e572bca6f1e22bdcbd2149e13b050b17bb
+ languageName: node
+ linkType: hard
+
+"immediate@npm:~3.0.5":
+ version: 3.0.6
+ resolution: "immediate@npm:3.0.6"
+ checksum: 10c0/f8ba7ede69bee9260241ad078d2d535848745ff5f6995c7c7cb41cfdc9ccc213f66e10fa5afb881f90298b24a3f7344b637b592beb4f54e582770cdce3f1f039
+ languageName: node
+ linkType: hard
+
"imurmurhash@npm:^0.1.4":
version: 0.1.4
resolution: "imurmurhash@npm:0.1.4"
@@ -1279,6 +1793,13 @@ __metadata:
languageName: node
linkType: hard
+"inline-style-parser@npm:^0.2.3":
+ version: 0.2.4
+ resolution: "inline-style-parser@npm:0.2.4"
+ checksum: 10c0/ddc0b210eaa03e0f98d677b9836242c583c7c6051e84ce0e704ae4626e7871c5b78f8e30853480218b446355745775df318d4f82d33087ff7e393245efa9a881
+ languageName: node
+ linkType: hard
+
"ip-address@npm:^9.0.5":
version: 9.0.5
resolution: "ip-address@npm:9.0.5"
@@ -1314,6 +1835,15 @@ __metadata:
languageName: node
linkType: hard
+"is-core-module@npm:^2.16.0":
+ version: 2.16.1
+ resolution: "is-core-module@npm:2.16.1"
+ dependencies:
+ hasown: "npm:^2.0.2"
+ checksum: 10c0/898443c14780a577e807618aaae2b6f745c8538eca5c7bc11388a3f2dc6de82b9902bcc7eb74f07be672b11bbe82dd6a6edded44a00cb3d8f933d0459905eedd
+ languageName: node
+ linkType: hard
+
"is-extglob@npm:^2.1.1":
version: 2.1.1
resolution: "is-extglob@npm:2.1.1"
@@ -1337,6 +1867,13 @@ __metadata:
languageName: node
linkType: hard
+"is-interactive@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "is-interactive@npm:2.0.0"
+ checksum: 10c0/801c8f6064f85199dc6bf99b5dd98db3282e930c3bc197b32f2c5b89313bb578a07d1b8a01365c4348c2927229234f3681eb861b9c2c92bee72ff397390fa600
+ languageName: node
+ linkType: hard
+
"is-lambda@npm:^1.0.1":
version: 1.0.1
resolution: "is-lambda@npm:1.0.1"
@@ -1351,6 +1888,27 @@ __metadata:
languageName: node
linkType: hard
+"is-promise@npm:^2.1.0":
+ version: 2.2.2
+ resolution: "is-promise@npm:2.2.2"
+ checksum: 10c0/2dba959812380e45b3df0fb12e7cb4d4528c989c7abb03ececb1d1fd6ab1cbfee956ca9daa587b9db1d8ac3c1e5738cf217bdb3dfd99df8c691be4c00ae09069
+ languageName: node
+ linkType: hard
+
+"is-unicode-supported@npm:^1.3.0":
+ version: 1.3.0
+ resolution: "is-unicode-supported@npm:1.3.0"
+ checksum: 10c0/b8674ea95d869f6faabddc6a484767207058b91aea0250803cbf1221345cb0c56f466d4ecea375dc77f6633d248d33c47bd296fb8f4cdba0b4edba8917e83d8a
+ languageName: node
+ linkType: hard
+
+"is-unicode-supported@npm:^2.0.0":
+ version: 2.1.0
+ resolution: "is-unicode-supported@npm:2.1.0"
+ checksum: 10c0/a0f53e9a7c1fdbcf2d2ef6e40d4736fdffff1c9f8944c75e15425118ff3610172c87bf7bc6c34d3903b04be59790bb2212ddbe21ee65b5a97030fc50370545a5
+ languageName: node
+ linkType: hard
+
"isexe@npm:^2.0.0":
version: 2.0.0
resolution: "isexe@npm:2.0.0"
@@ -1365,6 +1923,17 @@ __metadata:
languageName: node
linkType: hard
+"its-fine@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "its-fine@npm:2.0.0"
+ dependencies:
+ "@types/react-reconciler": "npm:^0.28.9"
+ peerDependencies:
+ react: ^19.0.0
+ checksum: 10c0/1ff1ff3257c0c7eb115c9c26cf0506eb84162edc1a63d3136780d146f7c7833298b240d0fcb46888909773f1a7d16539e0c03f2482cff1a5a502d6436686fe21
+ languageName: node
+ linkType: hard
+
"jackspeak@npm:^3.1.2":
version: 3.4.3
resolution: "jackspeak@npm:3.4.3"
@@ -1378,6 +1947,15 @@ __metadata:
languageName: node
linkType: hard
+"jiti@npm:^1.18.2":
+ version: 1.21.7
+ resolution: "jiti@npm:1.21.7"
+ bin:
+ jiti: bin/jiti.js
+ checksum: 10c0/77b61989c758ff32407cdae8ddc77f85e18e1a13fc4977110dbd2e05fc761842f5f71bce684d9a01316e1c4263971315a111385759951080bbfe17cbb5de8f7a
+ languageName: node
+ linkType: hard
+
"jiti@npm:^1.21.6":
version: 1.21.6
resolution: "jiti@npm:1.21.6"
@@ -1401,6 +1979,22 @@ __metadata:
languageName: node
linkType: hard
+"kleur@npm:^3.0.3":
+ version: 3.0.3
+ resolution: "kleur@npm:3.0.3"
+ checksum: 10c0/cd3a0b8878e7d6d3799e54340efe3591ca787d9f95f109f28129bdd2915e37807bf8918bb295ab86afb8c82196beec5a1adcaf29042ce3f2bd932b038fe3aa4b
+ languageName: node
+ linkType: hard
+
+"lie@npm:^3.0.2":
+ version: 3.3.0
+ resolution: "lie@npm:3.3.0"
+ dependencies:
+ immediate: "npm:~3.0.5"
+ checksum: 10c0/56dd113091978f82f9dc5081769c6f3b947852ecf9feccaf83e14a123bc630c2301439ce6182521e5fbafbde88e88ac38314327a4e0493a1bea7e0699a7af808
+ languageName: node
+ linkType: hard
+
"lilconfig@npm:^2.1.0":
version: 2.1.0
resolution: "lilconfig@npm:2.1.0"
@@ -1422,6 +2016,16 @@ __metadata:
languageName: node
linkType: hard
+"log-symbols@npm:^6.0.0":
+ version: 6.0.0
+ resolution: "log-symbols@npm:6.0.0"
+ dependencies:
+ chalk: "npm:^5.3.0"
+ is-unicode-supported: "npm:^1.3.0"
+ checksum: 10c0/36636cacedba8f067d2deb4aad44e91a89d9efb3ead27e1846e7b82c9a10ea2e3a7bd6ce28a7ca616bebc60954ff25c67b0f92d20a6a746bb3cc52c3701891f6
+ languageName: node
+ linkType: hard
+
"loose-envify@npm:^1.1.0":
version: 1.4.0
resolution: "loose-envify@npm:1.4.0"
@@ -1440,6 +2044,16 @@ __metadata:
languageName: node
linkType: hard
+"maath@npm:^0.10.8":
+ version: 0.10.8
+ resolution: "maath@npm:0.10.8"
+ peerDependencies:
+ "@types/three": ">=0.134.0"
+ three: ">=0.134.0"
+ checksum: 10c0/fb61faac89567595f7e25f261f8a9750d0ced674fd16c77c6e486a0c4a00c572fa37969d613d017380f8ea4e8ff357d481dcd94240a104a7969bc7e95b9fe99e
+ languageName: node
+ linkType: hard
+
"make-fetch-happen@npm:^13.0.0":
version: 13.0.1
resolution: "make-fetch-happen@npm:13.0.1"
@@ -1467,7 +2081,23 @@ __metadata:
languageName: node
linkType: hard
-"micromatch@npm:^4.0.4, micromatch@npm:^4.0.8":
+"meshline@npm:^3.3.1":
+ version: 3.3.1
+ resolution: "meshline@npm:3.3.1"
+ peerDependencies:
+ three: ">=0.137"
+ checksum: 10c0/95d5c7c90aca350530f37f9ea5c5e333a66ea0c50416fa6372c24a23321837a4c70d92d6a9a5942ee124484855a2d3fc8ca0656305feb8d8f86aa10513e324e4
+ languageName: node
+ linkType: hard
+
+"meshoptimizer@npm:~0.18.1":
+ version: 0.18.1
+ resolution: "meshoptimizer@npm:0.18.1"
+ checksum: 10c0/8a825c58b20b65585e8d00788843929b60c66ba4297e89afaa49f7c51ab9a0f7b9130f90cc9ad1b9b48b3d1bee3beb1bc93608acba0d73e78995c3e6e5ca436b
+ languageName: node
+ linkType: hard
+
+"micromatch@npm:^4.0.4, micromatch@npm:^4.0.5, micromatch@npm:^4.0.8":
version: 4.0.8
resolution: "micromatch@npm:4.0.8"
dependencies:
@@ -1477,6 +2107,13 @@ __metadata:
languageName: node
linkType: hard
+"mimic-function@npm:^5.0.0":
+ version: 5.0.1
+ resolution: "mimic-function@npm:5.0.1"
+ checksum: 10c0/f3d9464dd1816ecf6bdf2aec6ba32c0728022039d992f178237d8e289b48764fee4131319e72eedd4f7f094e22ded0af836c3187a7edc4595d28dd74368fd81d
+ languageName: node
+ linkType: hard
+
"minimatch@npm:^9.0.4":
version: 9.0.5
resolution: "minimatch@npm:9.0.5"
@@ -1613,6 +2250,15 @@ __metadata:
languageName: node
linkType: hard
+"nanoid@npm:^3.3.8":
+ version: 3.3.11
+ resolution: "nanoid@npm:3.3.11"
+ bin:
+ nanoid: bin/nanoid.cjs
+ checksum: 10c0/40e7f70b3d15f725ca072dfc4f74e81fcf1fbb02e491cf58ac0c79093adc9b0a73b152bcde57df4b79cd097e13023d7504acb38404a4da7bc1cd8e887b82fe0b
+ languageName: node
+ linkType: hard
+
"negotiator@npm:^0.6.3":
version: 0.6.4
resolution: "negotiator@npm:0.6.4"
@@ -1701,6 +2347,16 @@ __metadata:
languageName: node
linkType: hard
+"node-html-parser@npm:^6.1.13":
+ version: 6.1.13
+ resolution: "node-html-parser@npm:6.1.13"
+ dependencies:
+ css-select: "npm:^5.1.0"
+ he: "npm:1.2.0"
+ checksum: 10c0/ca36290507da8ec0fa131a0fd67ba62e300365c3950b5a6058b0e32b71b520ff43a5661b19e98a5c9797dbe3428b08db788b602f1f8aa62f2db5bb66e1d80782
+ languageName: node
+ linkType: hard
+
"node-releases@npm:^2.0.18":
version: 2.0.18
resolution: "node-releases@npm:2.0.18"
@@ -1733,6 +2389,15 @@ __metadata:
languageName: node
linkType: hard
+"nth-check@npm:^2.0.1":
+ version: 2.1.1
+ resolution: "nth-check@npm:2.1.1"
+ dependencies:
+ boolbase: "npm:^1.0.0"
+ checksum: 10c0/5fee7ff309727763689cfad844d979aedd2204a817fbaaf0e1603794a7c20db28548d7b024692f953557df6ce4a0ee4ae46cd8ebd9b36cfb300b9226b567c479
+ languageName: node
+ linkType: hard
+
"object-assign@npm:^4.0.1":
version: 4.1.1
resolution: "object-assign@npm:4.1.1"
@@ -1747,6 +2412,32 @@ __metadata:
languageName: node
linkType: hard
+"onetime@npm:^7.0.0":
+ version: 7.0.0
+ resolution: "onetime@npm:7.0.0"
+ dependencies:
+ mimic-function: "npm:^5.0.0"
+ checksum: 10c0/5cb9179d74b63f52a196a2e7037ba2b9a893245a5532d3f44360012005c9cadb60851d56716ebff18a6f47129dab7168022445df47c2aff3b276d92585ed1221
+ languageName: node
+ linkType: hard
+
+"ora@npm:^8.0.1":
+ version: 8.2.0
+ resolution: "ora@npm:8.2.0"
+ dependencies:
+ chalk: "npm:^5.3.0"
+ cli-cursor: "npm:^5.0.0"
+ cli-spinners: "npm:^2.9.2"
+ is-interactive: "npm:^2.0.0"
+ is-unicode-supported: "npm:^2.0.0"
+ log-symbols: "npm:^6.0.0"
+ stdin-discarder: "npm:^0.2.2"
+ string-width: "npm:^7.2.0"
+ strip-ansi: "npm:^7.1.0"
+ checksum: 10c0/7d9291255db22e293ea164f520b6042a3e906576ab06c9cf408bf9ef5664ba0a9f3bd258baa4ada058cfcc2163ef9b6696d51237a866682ce33295349ba02c3a
+ languageName: node
+ linkType: hard
+
"p-map@npm:^4.0.0":
version: 4.0.0
resolution: "p-map@npm:4.0.0"
@@ -1822,6 +2513,19 @@ __metadata:
languageName: node
linkType: hard
+"postcss-css-variables@npm:0.18.0":
+ version: 0.18.0
+ resolution: "postcss-css-variables@npm:0.18.0"
+ dependencies:
+ balanced-match: "npm:^1.0.0"
+ escape-string-regexp: "npm:^1.0.3"
+ extend: "npm:^3.0.1"
+ peerDependencies:
+ postcss: ^8.2.6
+ checksum: 10c0/be3e6a752b852c20fdf7e76beb46b943da79b3c647a08df2b58e946ec1e52e229ac58646611e6cc746028dc949ca02ecb0772f5755743af5dfb5917c59cf7380
+ languageName: node
+ linkType: hard
+
"postcss-import@npm:^15.1.0":
version: 15.1.0
resolution: "postcss-import@npm:15.1.0"
@@ -1846,7 +2550,7 @@ __metadata:
languageName: node
linkType: hard
-"postcss-load-config@npm:^4.0.2":
+"postcss-load-config@npm:^4.0.1, postcss-load-config@npm:^4.0.2":
version: 4.0.2
resolution: "postcss-load-config@npm:4.0.2"
dependencies:
@@ -1864,7 +2568,7 @@ __metadata:
languageName: node
linkType: hard
-"postcss-nested@npm:^6.2.0":
+"postcss-nested@npm:^6.0.1, postcss-nested@npm:^6.2.0":
version: 6.2.0
resolution: "postcss-nested@npm:6.2.0"
dependencies:
@@ -1875,7 +2579,7 @@ __metadata:
languageName: node
linkType: hard
-"postcss-selector-parser@npm:^6.1.1, postcss-selector-parser@npm:^6.1.2":
+"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.1.1, postcss-selector-parser@npm:^6.1.2":
version: 6.1.2
resolution: "postcss-selector-parser@npm:6.1.2"
dependencies:
@@ -1914,6 +2618,24 @@ __metadata:
languageName: node
linkType: hard
+"postcss@npm:^8.4.23":
+ version: 8.5.3
+ resolution: "postcss@npm:8.5.3"
+ dependencies:
+ nanoid: "npm:^3.3.8"
+ picocolors: "npm:^1.1.1"
+ source-map-js: "npm:^1.2.1"
+ checksum: 10c0/b75510d7b28c3ab728c8733dd01538314a18c52af426f199a3c9177e63eb08602a3938bfb66b62dc01350b9aed62087eabbf229af97a1659eb8d3513cec823b3
+ languageName: node
+ linkType: hard
+
+"potpack@npm:^1.0.1":
+ version: 1.0.2
+ resolution: "potpack@npm:1.0.2"
+ checksum: 10c0/670c23898a4257130858b960c2e654d3327c0f6a7e7091ff5846f213e65af8f9476320b995b8ad561a47a4d1c359c7ef347de57d22e7b02597051abb52bc85c4
+ languageName: node
+ linkType: hard
+
"prettier-plugin-tailwindcss@npm:0.6.8":
version: 0.6.8
resolution: "prettier-plugin-tailwindcss@npm:0.6.8"
@@ -1981,6 +2703,15 @@ __metadata:
languageName: node
linkType: hard
+"prettier@npm:^3.2.5":
+ version: 3.5.3
+ resolution: "prettier@npm:3.5.3"
+ bin:
+ prettier: bin/prettier.cjs
+ checksum: 10c0/3880cb90b9dc0635819ab52ff571518c35bd7f15a6e80a2054c05dbc8a3aa6e74f135519e91197de63705bcb38388ded7e7230e2178432a1468005406238b877
+ languageName: node
+ linkType: hard
+
"proc-log@npm:^4.1.0, proc-log@npm:^4.2.0":
version: 4.2.0
resolution: "proc-log@npm:4.2.0"
@@ -1998,6 +2729,26 @@ __metadata:
languageName: node
linkType: hard
+"promise-worker-transferable@npm:^1.0.4":
+ version: 1.0.4
+ resolution: "promise-worker-transferable@npm:1.0.4"
+ dependencies:
+ is-promise: "npm:^2.1.0"
+ lie: "npm:^3.0.2"
+ checksum: 10c0/110d273cbba2631c318762f02c159531f1e05e4af91080368b9d4c02b880824ae4c49a8ec7094c6434989ea2ee8de913b21c809279babeaf447fc90a682dcd7c
+ languageName: node
+ linkType: hard
+
+"prompts@npm:^2.4.2":
+ version: 2.4.2
+ resolution: "prompts@npm:2.4.2"
+ dependencies:
+ kleur: "npm:^3.0.3"
+ sisteransi: "npm:^1.0.5"
+ checksum: 10c0/16f1ac2977b19fe2cf53f8411cc98db7a3c8b115c479b2ca5c82b5527cd937aa405fa04f9a5960abeb9daef53191b53b4d13e35c1f5d50e8718c76917c5f1ea4
+ languageName: node
+ linkType: hard
+
"queue-microtask@npm:^1.2.2":
version: 1.2.3
resolution: "queue-microtask@npm:1.2.3"
@@ -2017,6 +2768,30 @@ __metadata:
languageName: node
linkType: hard
+"react-reconciler@npm:^0.31.0":
+ version: 0.31.0
+ resolution: "react-reconciler@npm:0.31.0"
+ dependencies:
+ scheduler: "npm:^0.25.0"
+ peerDependencies:
+ react: ^19.0.0
+ checksum: 10c0/97920e1866c7206e200c3920c133c2e85f62a3c54fd9bc4b83c10c558d83d98eb378caab4fe37498e0cc1b1b2665d898627f2ae2537b29c8ab295ec8abc0c580
+ languageName: node
+ linkType: hard
+
+"react-use-measure@npm:^2.1.7":
+ version: 2.1.7
+ resolution: "react-use-measure@npm:2.1.7"
+ peerDependencies:
+ react: ">=16.13"
+ react-dom: ">=16.13"
+ peerDependenciesMeta:
+ react-dom:
+ optional: true
+ checksum: 10c0/ff24130e6f95e853feb6892fb74af08dbc5aae3574b701169e3bc3adb392c3162f51a58ddfe39bb7337db13ae609bbec0bb51a9de8b5fae5420f9d17e1f8b542
+ languageName: node
+ linkType: hard
+
"react@npm:18.3.1":
version: 18.3.1
resolution: "react@npm:18.3.1"
@@ -2044,6 +2819,20 @@ __metadata:
languageName: node
linkType: hard
+"regenerator-runtime@npm:^0.14.0":
+ version: 0.14.1
+ resolution: "regenerator-runtime@npm:0.14.1"
+ checksum: 10c0/1b16eb2c4bceb1665c89de70dcb64126a22bc8eb958feef3cd68fe11ac6d2a4899b5cd1b80b0774c7c03591dc57d16631a7f69d2daa2ec98100e2f29f7ec4cc4
+ languageName: node
+ linkType: hard
+
+"require-from-string@npm:^2.0.2":
+ version: 2.0.2
+ resolution: "require-from-string@npm:2.0.2"
+ checksum: 10c0/aaa267e0c5b022fc5fd4eef49d8285086b15f2a1c54b28240fdf03599cbd9c26049fee3eab894f2e1f6ca65e513b030a7c264201e3f005601e80c49fb2937ce2
+ languageName: node
+ linkType: hard
+
"resolve@npm:^1.1.7, resolve@npm:^1.22.8":
version: 1.22.8
resolution: "resolve@npm:1.22.8"
@@ -2057,6 +2846,19 @@ __metadata:
languageName: node
linkType: hard
+"resolve@npm:^1.22.2":
+ version: 1.22.10
+ resolution: "resolve@npm:1.22.10"
+ dependencies:
+ is-core-module: "npm:^2.16.0"
+ path-parse: "npm:^1.0.7"
+ supports-preserve-symlinks-flag: "npm:^1.0.0"
+ bin:
+ resolve: bin/resolve
+ checksum: 10c0/8967e1f4e2cc40f79b7e080b4582b9a8c5ee36ffb46041dccb20e6461161adf69f843b43067b4a375de926a2cd669157e29a29578191def399dd5ef89a1b5203
+ languageName: node
+ linkType: hard
+
"resolve@patch:resolve@npm%3A^1.1.7#optional!builtin, resolve@patch:resolve@npm%3A^1.22.8#optional!builtin":
version: 1.22.8
resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d"
@@ -2070,6 +2872,29 @@ __metadata:
languageName: node
linkType: hard
+"resolve@patch:resolve@npm%3A^1.22.2#optional!builtin":
+ version: 1.22.10
+ resolution: "resolve@patch:resolve@npm%3A1.22.10#optional!builtin::version=1.22.10&hash=c3c19d"
+ dependencies:
+ is-core-module: "npm:^2.16.0"
+ path-parse: "npm:^1.0.7"
+ supports-preserve-symlinks-flag: "npm:^1.0.0"
+ bin:
+ resolve: bin/resolve
+ checksum: 10c0/52a4e505bbfc7925ac8f4cd91fd8c4e096b6a89728b9f46861d3b405ac9a1ccf4dcbf8befb4e89a2e11370dacd0160918163885cbc669369590f2f31f4c58939
+ languageName: node
+ linkType: hard
+
+"restore-cursor@npm:^5.0.0":
+ version: 5.1.0
+ resolution: "restore-cursor@npm:5.1.0"
+ dependencies:
+ onetime: "npm:^7.0.0"
+ signal-exit: "npm:^4.1.0"
+ checksum: 10c0/c2ba89131eea791d1b25205bdfdc86699767e2b88dee2a590b1a6caa51737deac8bad0260a5ded2f7c074b7db2f3a626bcf1fcf3cdf35974cbeea5e2e6764f60
+ languageName: node
+ linkType: hard
+
"retry@npm:^0.12.0":
version: 0.12.0
resolution: "retry@npm:0.12.0"
@@ -2109,6 +2934,13 @@ __metadata:
languageName: node
linkType: hard
+"scheduler@npm:^0.25.0":
+ version: 0.25.0
+ resolution: "scheduler@npm:0.25.0"
+ checksum: 10c0/a4bb1da406b613ce72c1299db43759526058fdcc413999c3c3e0db8956df7633acf395cb20eb2303b6a65d658d66b6585d344460abaee8080b4aa931f10eaafe
+ languageName: node
+ linkType: hard
+
"semver@npm:^7.3.5, semver@npm:^7.6.3":
version: 7.6.3
resolution: "semver@npm:7.6.3"
@@ -2203,7 +3035,7 @@ __metadata:
languageName: node
linkType: hard
-"signal-exit@npm:^4.0.1":
+"signal-exit@npm:^4.0.1, signal-exit@npm:^4.1.0":
version: 4.1.0
resolution: "signal-exit@npm:4.1.0"
checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83
@@ -2219,6 +3051,13 @@ __metadata:
languageName: node
linkType: hard
+"sisteransi@npm:^1.0.5":
+ version: 1.0.5
+ resolution: "sisteransi@npm:1.0.5"
+ checksum: 10c0/230ac975cca485b7f6fe2b96a711aa62a6a26ead3e6fb8ba17c5a00d61b8bed0d7adc21f5626b70d7c33c62ff4e63933017a6462942c719d1980bb0b1207ad46
+ languageName: node
+ linkType: hard
+
"smart-buffer@npm:^4.2.0":
version: 4.2.0
resolution: "smart-buffer@npm:4.2.0"
@@ -2270,6 +3109,33 @@ __metadata:
languageName: node
linkType: hard
+"stats-gl@npm:^2.2.8":
+ version: 2.4.2
+ resolution: "stats-gl@npm:2.4.2"
+ dependencies:
+ "@types/three": "npm:*"
+ three: "npm:^0.170.0"
+ peerDependencies:
+ "@types/three": "*"
+ three: "*"
+ checksum: 10c0/cff079103d4004cdfd72d65c977b7237a929b02f57b275081188e9313d74620b70ea0a57e0561fb6a43b1597830068b4adb2625dbc08b99799fd12a71ec54729
+ languageName: node
+ linkType: hard
+
+"stats.js@npm:^0.17.0":
+ version: 0.17.0
+ resolution: "stats.js@npm:0.17.0"
+ checksum: 10c0/03392b4b9eb15cb285b8cf46c5dd68e4e7b556d8e4c72a3a48e6bd2ab6f2e72a02b145d465f594450df081d8f94a45e8ac1112a0d507a200a5768504082ca080
+ languageName: node
+ linkType: hard
+
+"stdin-discarder@npm:^0.2.2":
+ version: 0.2.2
+ resolution: "stdin-discarder@npm:0.2.2"
+ checksum: 10c0/c78375e82e956d7a64be6e63c809c7f058f5303efcaf62ea48350af072bacdb99c06cba39209b45a071c1acbd49116af30df1df9abb448df78a6005b72f10537
+ languageName: node
+ linkType: hard
+
"streamsearch@npm:^1.1.0":
version: 1.1.0
resolution: "streamsearch@npm:1.1.0"
@@ -2299,6 +3165,17 @@ __metadata:
languageName: node
linkType: hard
+"string-width@npm:^7.2.0":
+ version: 7.2.0
+ resolution: "string-width@npm:7.2.0"
+ dependencies:
+ emoji-regex: "npm:^10.3.0"
+ get-east-asian-width: "npm:^1.0.0"
+ strip-ansi: "npm:^7.1.0"
+ checksum: 10c0/eb0430dd43f3199c7a46dcbf7a0b34539c76fe3aa62763d0b0655acdcbdf360b3f66f3d58ca25ba0205f42ea3491fa00f09426d3b7d3040e506878fc7664c9b9
+ languageName: node
+ linkType: hard
+
"strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1":
version: 6.0.1
resolution: "strip-ansi@npm:6.0.1"
@@ -2308,7 +3185,7 @@ __metadata:
languageName: node
linkType: hard
-"strip-ansi@npm:^7.0.1":
+"strip-ansi@npm:^7.0.1, strip-ansi@npm:^7.1.0":
version: 7.1.0
resolution: "strip-ansi@npm:7.1.0"
dependencies:
@@ -2333,7 +3210,7 @@ __metadata:
languageName: node
linkType: hard
-"sucrase@npm:^3.35.0":
+"sucrase@npm:^3.32.0, sucrase@npm:^3.35.0":
version: 3.35.0
resolution: "sucrase@npm:3.35.0"
dependencies:
@@ -2358,6 +3235,15 @@ __metadata:
languageName: node
linkType: hard
+"suspend-react@npm:^0.1.3":
+ version: 0.1.3
+ resolution: "suspend-react@npm:0.1.3"
+ peerDependencies:
+ react: ">=17.0"
+ checksum: 10c0/c35436f492a5cab85a2aac8f5ee5af8f67edbab3a49e12d15c7f770aae4cf09fe2925b3b8c122929210c1f28aa0958f91684a687d6608f116f7da8406d8a2f1c
+ languageName: node
+ linkType: hard
+
"tabbable@npm:^6.0.0":
version: 6.2.0
resolution: "tabbable@npm:6.2.0"
@@ -2365,6 +3251,40 @@ __metadata:
languageName: node
linkType: hard
+"tailwindcss@npm:3.3.2":
+ version: 3.3.2
+ resolution: "tailwindcss@npm:3.3.2"
+ dependencies:
+ "@alloc/quick-lru": "npm:^5.2.0"
+ arg: "npm:^5.0.2"
+ chokidar: "npm:^3.5.3"
+ didyoumean: "npm:^1.2.2"
+ dlv: "npm:^1.1.3"
+ fast-glob: "npm:^3.2.12"
+ glob-parent: "npm:^6.0.2"
+ is-glob: "npm:^4.0.3"
+ jiti: "npm:^1.18.2"
+ lilconfig: "npm:^2.1.0"
+ micromatch: "npm:^4.0.5"
+ normalize-path: "npm:^3.0.0"
+ object-hash: "npm:^3.0.0"
+ picocolors: "npm:^1.0.0"
+ postcss: "npm:^8.4.23"
+ postcss-import: "npm:^15.1.0"
+ postcss-js: "npm:^4.0.1"
+ postcss-load-config: "npm:^4.0.1"
+ postcss-nested: "npm:^6.0.1"
+ postcss-selector-parser: "npm:^6.0.11"
+ postcss-value-parser: "npm:^4.2.0"
+ resolve: "npm:^1.22.2"
+ sucrase: "npm:^3.32.0"
+ bin:
+ tailwind: lib/cli.js
+ tailwindcss: lib/cli.js
+ checksum: 10c0/334e9828da03daaf9ebb3a539fd8b940b3625d60caf6e51e05400fb723ed4fbcb2fb2f0dc0012a10ad9d1469127ab543bbbf8a672f4932e27509ac39c312af28
+ languageName: node
+ linkType: hard
+
"tailwindcss@npm:3.4.15":
version: 3.4.15
resolution: "tailwindcss@npm:3.4.15"
@@ -2430,6 +3350,45 @@ __metadata:
languageName: node
linkType: hard
+"three-mesh-bvh@npm:^0.8.3":
+ version: 0.8.3
+ resolution: "three-mesh-bvh@npm:0.8.3"
+ peerDependencies:
+ three: ">= 0.159.0"
+ checksum: 10c0/d1f052d4606498acf57e08e28d01c84157eb388d46be8e03bc839630dc4eb919d5bb5e2ed4e9113d39cbc3cda29f09212e3450e1bb21de6615ec330f2575fc28
+ languageName: node
+ linkType: hard
+
+"three-stdlib@npm:^2.35.6":
+ version: 2.35.14
+ resolution: "three-stdlib@npm:2.35.14"
+ dependencies:
+ "@types/draco3d": "npm:^1.4.0"
+ "@types/offscreencanvas": "npm:^2019.6.4"
+ "@types/webxr": "npm:^0.5.2"
+ draco3d: "npm:^1.4.1"
+ fflate: "npm:^0.6.9"
+ potpack: "npm:^1.0.1"
+ peerDependencies:
+ three: ">=0.128.0"
+ checksum: 10c0/a70c3a09bde3c292c3e172d52891f846df3dfb375e2868ff09dbbfe5771b17258f632748745ea788927d332f5e1a2822864cb66510f23542a9973c9ebc549f26
+ languageName: node
+ linkType: hard
+
+"three@npm:^0.170.0":
+ version: 0.170.0
+ resolution: "three@npm:0.170.0"
+ checksum: 10c0/eeaa1eccb31467654a044fb90634b3b6bb8d0768a4f029c082fb6aa22aec0d6362d0e3af74938caa1db512b7823a031b54a76e88fba6cfd535054165ea9667c9
+ languageName: node
+ linkType: hard
+
+"three@npm:^0.174.0":
+ version: 0.174.0
+ resolution: "three@npm:0.174.0"
+ checksum: 10c0/704c3aaa72a7e97ad4f829e81870c8add856ab5a8fb4fc34e391033c527df5cb87a283edb88e69d2d6974bee8afe732c616e879081c8ea232103aa806b97793b
+ languageName: node
+ linkType: hard
+
"to-regex-range@npm:^5.0.1":
version: 5.0.1
resolution: "to-regex-range@npm:5.0.1"
@@ -2439,6 +3398,36 @@ __metadata:
languageName: node
linkType: hard
+"troika-three-text@npm:^0.52.0":
+ version: 0.52.3
+ resolution: "troika-three-text@npm:0.52.3"
+ dependencies:
+ bidi-js: "npm:^1.0.2"
+ troika-three-utils: "npm:^0.52.0"
+ troika-worker-utils: "npm:^0.52.0"
+ webgl-sdf-generator: "npm:1.1.1"
+ peerDependencies:
+ three: ">=0.125.0"
+ checksum: 10c0/25c3ae9db859771896422d15d91f67e3b501ed65b6394ce4985a1bb68376c6f5d0dbc4a1da923dc96f6d760ec6544324f46123ca5d08bddbbccd0c63208d839d
+ languageName: node
+ linkType: hard
+
+"troika-three-utils@npm:^0.52.0":
+ version: 0.52.0
+ resolution: "troika-three-utils@npm:0.52.0"
+ peerDependencies:
+ three: ">=0.125.0"
+ checksum: 10c0/6fe5de1e9540bb8c79314a49aee47fdd6f9e739992a6a04b111b364efdd0a8b15af6786d12512edf5b1a2a5f3e324906489533c0645d4d2c70a95e5ddf27b04f
+ languageName: node
+ linkType: hard
+
+"troika-worker-utils@npm:^0.52.0":
+ version: 0.52.0
+ resolution: "troika-worker-utils@npm:0.52.0"
+ checksum: 10c0/bcd776324ce3e941c1a913531cee6022c867b71bc2d6bb67f1eadf6df96fd4f865c51b90ac58fc5c0ae3346a4bd8360b0a52398864800a7a9c60473151d452d5
+ languageName: node
+ linkType: hard
+
"ts-interface-checker@npm:^0.1.9":
version: 0.1.13
resolution: "ts-interface-checker@npm:0.1.13"
@@ -2453,6 +3442,26 @@ __metadata:
languageName: node
linkType: hard
+"tunnel-rat@npm:^0.1.2":
+ version: 0.1.2
+ resolution: "tunnel-rat@npm:0.1.2"
+ dependencies:
+ zustand: "npm:^4.3.2"
+ checksum: 10c0/93cd50c7c9141e2662707602a21401145092e5a3c815b57a752937419ab6187a2ff36fa7e0f65e0c587022149bf2d323ace07dff61106511b7d4845e53390cc9
+ languageName: node
+ linkType: hard
+
+"tw-to-css@npm:^0.0.12":
+ version: 0.0.12
+ resolution: "tw-to-css@npm:0.0.12"
+ dependencies:
+ postcss: "npm:8.4.31"
+ postcss-css-variables: "npm:0.18.0"
+ tailwindcss: "npm:3.3.2"
+ checksum: 10c0/44436354b366c124b793aa30bb20002a6cc482aa30c4adc13cecdbb2bd1356fa9657ab929ce0cffe13cac67f8e31e73f480022fc41a4f57d383956f20075c986
+ languageName: node
+ linkType: hard
+
"typescript@npm:5.6.3":
version: 5.6.3
resolution: "typescript@npm:5.6.3"
@@ -2512,6 +3521,15 @@ __metadata:
languageName: node
linkType: hard
+"use-sync-external-store@npm:^1.2.2, use-sync-external-store@npm:^1.4.0":
+ version: 1.4.0
+ resolution: "use-sync-external-store@npm:1.4.0"
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ checksum: 10c0/ec011a5055962c0f6b509d6e78c0b143f8cd069890ae370528753053c55e3b360d3648e76cfaa854faa7a59eb08d6c5fb1015e60ffde9046d32f5b2a295acea5
+ languageName: node
+ linkType: hard
+
"util-deprecate@npm:^1.0.2":
version: 1.0.2
resolution: "util-deprecate@npm:1.0.2"
@@ -2519,6 +3537,27 @@ __metadata:
languageName: node
linkType: hard
+"utility-types@npm:^3.11.0":
+ version: 3.11.0
+ resolution: "utility-types@npm:3.11.0"
+ checksum: 10c0/2f1580137b0c3e6cf5405f37aaa8f5249961a76d26f1ca8efc0ff49a2fc0e0b2db56de8e521a174d075758e0c7eb3e590edec0832eb44478b958f09914920f19
+ languageName: node
+ linkType: hard
+
+"webgl-constants@npm:^1.1.1":
+ version: 1.1.1
+ resolution: "webgl-constants@npm:1.1.1"
+ checksum: 10c0/525a9838b0cbcbab902d1bc5457882424a9c146f851042c901ae457123193f5c5e47846b47c1c999e4f3abc24322cac494cea0cc52fec28bd8eb3a05cd79d573
+ languageName: node
+ linkType: hard
+
+"webgl-sdf-generator@npm:1.1.1":
+ version: 1.1.1
+ resolution: "webgl-sdf-generator@npm:1.1.1"
+ checksum: 10c0/769bfab22a9485a59bda9448d1d8684228adc9ebdac2cc69012a0854282385d1bef319f703758829e2c647e7532a9844e62977110e825bd75a3e0b8a0ee276ce
+ languageName: node
+ linkType: hard
+
"which@npm:^2.0.1":
version: 2.0.2
resolution: "which@npm:2.0.2"
@@ -2579,6 +3618,13 @@ __metadata:
languageName: node
linkType: hard
+"yoga-layout@npm:^3.2.1":
+ version: 3.2.1
+ resolution: "yoga-layout@npm:3.2.1"
+ checksum: 10c0/9001e51be993c85e03757e5a04a2b61b8b30c9e5a7865d0156ca87a6431a3b717d51eb4990bfe588189fcfeac688dd9c3de707bbd50d1c344a84e63974cc54a8
+ languageName: node
+ linkType: hard
+
"zod@npm:3.23.8":
version: 3.23.8
resolution: "zod@npm:3.23.8"
@@ -2586,6 +3632,13 @@ __metadata:
languageName: node
linkType: hard
+"zod@npm:^3.22.4":
+ version: 3.24.2
+ resolution: "zod@npm:3.24.2"
+ checksum: 10c0/c638c7220150847f13ad90635b3e7d0321b36cce36f3fc6050ed960689594c949c326dfe2c6fa87c14b126ee5d370ccdebd6efb304f41ef5557a4aaca2824565
+ languageName: node
+ linkType: hard
+
"zustand@npm:5.0.1":
version: 5.0.1
resolution: "zustand@npm:5.0.1"
@@ -2606,3 +3659,44 @@ __metadata:
checksum: 10c0/b4239c8bf3988bfdaaed1c48f3958d0b047b721c4908a76bd78e73387d107963cda774541cf303c2ea89261481c995aa6666e7e77c30717ad440cdb499d9e5ca
languageName: node
linkType: hard
+
+"zustand@npm:^4.3.2, zustand@npm:^4.5.2":
+ version: 4.5.6
+ resolution: "zustand@npm:4.5.6"
+ dependencies:
+ use-sync-external-store: "npm:^1.2.2"
+ peerDependencies:
+ "@types/react": ">=16.8"
+ immer: ">=9.0.6"
+ react: ">=16.8"
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ immer:
+ optional: true
+ react:
+ optional: true
+ checksum: 10c0/5b39aff2ef57e5a8ada647261ec1115697d397be311c51461d9ea81b5b63c6d2c498b960477ad2db72dc21db6aa229a92bdf644f6a8ecf7b1d71df5b4a5e95d3
+ languageName: node
+ linkType: hard
+
+"zustand@npm:^5.0.1, zustand@npm:^5.0.3":
+ version: 5.0.3
+ resolution: "zustand@npm:5.0.3"
+ peerDependencies:
+ "@types/react": ">=18.0.0"
+ immer: ">=9.0.6"
+ react: ">=18.0.0"
+ use-sync-external-store: ">=1.2.0"
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ immer:
+ optional: true
+ react:
+ optional: true
+ use-sync-external-store:
+ optional: true
+ checksum: 10c0/dad96c6c123fda088c583d5df6692e9245cd207583078dc15f93d255a67b0f346bad4535545c98852ecde93d254812a0c799579dfde2ab595016b99fbe20e4d5
+ languageName: node
+ linkType: hard