@weasel-js/labkit 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_dts/{DrawCommand-CitWPxMY.d.ts → DrawCommand-uKHt4Vul.d.ts} +56 -0
- package/dist/_dts/{index-C6Yze7sQ.d.ts → index-CFlDPeZh.d.ts} +30 -1
- package/dist/_dts/{types-Si4Fw-1F.d.ts → types-x92Kfeme.d.ts} +14 -0
- package/dist/_dts/{useExperimentState-CJn2hHzd.d.ts → useExperimentState-vrttakTt.d.ts} +43 -0
- package/dist/canvas/index.d.ts +13 -2
- package/dist/canvas/index.js +2 -2
- package/dist/{chunk-3P56ZCCJ.js → chunk-3WPOGKUP.js} +93 -62
- package/dist/chunk-3WPOGKUP.js.map +1 -0
- package/dist/{chunk-54IQ2DX7.js → chunk-574LJAV4.js} +3 -3
- package/dist/chunk-574LJAV4.js.map +1 -0
- package/dist/{chunk-VLAHRJOC.js → chunk-5R2ATYPJ.js} +2 -2
- package/dist/{chunk-VLAHRJOC.js.map → chunk-5R2ATYPJ.js.map} +1 -1
- package/dist/{chunk-2ZRE7WGQ.js → chunk-73PXCRCR.js} +3 -3
- package/dist/chunk-73PXCRCR.js.map +1 -0
- package/dist/{chunk-PWC7AQZM.js → chunk-CPUJ3QXL.js} +2 -2
- package/dist/chunk-CPUJ3QXL.js.map +1 -0
- package/dist/{chunk-R4TACNW7.js → chunk-N5KTQKQA.js} +11 -11
- package/dist/chunk-N5KTQKQA.js.map +1 -0
- package/dist/{chunk-HXZHVU4G.js → chunk-PMAU3SEE.js} +3 -3
- package/dist/chunk-PMAU3SEE.js.map +1 -0
- package/dist/{chunk-7BKDG73Z.js → chunk-RL2LOLNI.js} +2 -2
- package/dist/chunk-RL2LOLNI.js.map +1 -0
- package/dist/{chunk-2QNYYL3V.js → chunk-SFL7NFKN.js} +2 -2
- package/dist/chunk-SFL7NFKN.js.map +1 -0
- package/dist/{chunk-53XSBIUK.js → chunk-T7OKNJTY.js} +2 -2
- package/dist/chunk-T7OKNJTY.js.map +1 -0
- package/dist/controls/index.d.ts +4 -2
- package/dist/controls/index.js +1 -1
- package/dist/dragdrop/index.d.ts +2 -2
- package/dist/index.d.ts +122 -6
- package/dist/index.js +18 -18
- package/dist/index.js.map +1 -1
- package/dist/layers/index.d.ts +6 -3
- package/dist/layers/index.js +1 -1
- package/dist/passthrough/weasel-canvas.d.ts +5 -1
- package/dist/passthrough/weasel-canvas.js +1 -1
- package/dist/passthrough/weasel-ui.d.ts +444 -7
- package/dist/passthrough/weasel-ui.js +2 -2
- package/dist/primitives/index.d.ts +13 -0
- package/dist/primitives/index.js +2 -2
- package/dist/state/index.d.ts +15 -2
- package/dist/state/index.js +2 -2
- package/dist/state/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/ui/layers/index.d.ts +5 -0
- package/dist/ui/layers/index.js +3 -3
- package/dist/undo/index.d.ts +17 -2
- package/dist/undo/index.js +1 -1
- package/package.json +1 -1
- package/src/canvas/CanvasStack.tsx +4 -0
- package/src/canvas/CanvasStackContext.ts +3 -0
- package/src/canvas/canvasCoords.ts +2 -0
- package/src/canvas/useLayerScheduler.ts +2 -0
- package/src/controls/ControlPanel.tsx +2 -0
- package/src/controls/types.ts +14 -0
- package/src/instrument/capabilityDetector.ts +3 -0
- package/src/instrument/defineInstrument.ts +2 -0
- package/src/instrument/types.ts +29 -0
- package/src/instrument/validateConfigSchema.ts +5 -0
- package/src/lab/Lab.tsx +3 -0
- package/src/lab/LabContext.ts +5 -0
- package/src/lab/LabShell.tsx +4 -0
- package/src/lab/WorkspaceGrid.tsx +2 -0
- package/src/lab/gridDims.ts +2 -0
- package/src/layers/LayerList.tsx +3 -0
- package/src/primitives/FpsMeter.tsx +1 -0
- package/src/primitives/ScaleIndicator.tsx +4 -0
- package/src/primitives/Sidebar.tsx +3 -0
- package/src/primitives/StatusBar.tsx +3 -0
- package/src/primitives/Toolbar.tsx +6 -0
- package/src/state/SingletonExperiment.tsx +1 -0
- package/src/state/adapters.ts +8 -0
- package/src/state/context.tsx +9 -0
- package/src/state/helpers.ts +12 -0
- package/src/state/store.ts +6 -0
- package/src/state/types.ts +17 -0
- package/src/state/useExperimentState.ts +3 -0
- package/src/ui/layers/LayerStack.tsx +5 -0
- package/src/ui/properties/CurveField.tsx +4 -1
- package/src/ui/properties/EffectCard.tsx +12 -0
- package/src/ui/properties/PropertyGroup.tsx +1 -0
- package/src/ui/properties/PropertyPanel.tsx +28 -0
- package/src/undo/eventBus.ts +4 -0
- package/src/undo/undoStack.ts +11 -0
- package/src/workspace/DefaultSidebar.tsx +3 -0
- package/src/workspace/DefaultStatusBar.tsx +3 -0
- package/src/workspace/DefaultToolbar.tsx +3 -0
- package/src/workspace/Workspace.tsx +3 -0
- package/src/workspace/WorkspaceChrome.tsx +4 -0
- package/src/workspace/slotTypes.ts +9 -0
- package/src/workspace/workspaceOps.ts +8 -0
- package/dist/chunk-2QNYYL3V.js.map +0 -1
- package/dist/chunk-2ZRE7WGQ.js.map +0 -1
- package/dist/chunk-3P56ZCCJ.js.map +0 -1
- package/dist/chunk-53XSBIUK.js.map +0 -1
- package/dist/chunk-54IQ2DX7.js.map +0 -1
- package/dist/chunk-7BKDG73Z.js.map +0 -1
- package/dist/chunk-HXZHVU4G.js.map +0 -1
- package/dist/chunk-PWC7AQZM.js.map +0 -1
- package/dist/chunk-R4TACNW7.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CanvasStackContext } from './chunk-
|
|
1
|
+
import { CanvasStackContext } from './chunk-CPUJ3QXL.js';
|
|
2
2
|
import { useState, useRef, useEffect, useContext } from 'react';
|
|
3
3
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
4
|
|
|
@@ -122,5 +122,5 @@ Toolbar.Button = Button;
|
|
|
122
122
|
Toolbar.Spacer = Spacer;
|
|
123
123
|
|
|
124
124
|
export { FpsMeter, ScaleIndicator, Sidebar, StatusBar, Toolbar };
|
|
125
|
-
//# sourceMappingURL=chunk-
|
|
126
|
-
//# sourceMappingURL=chunk-
|
|
125
|
+
//# sourceMappingURL=chunk-PMAU3SEE.js.map
|
|
126
|
+
//# sourceMappingURL=chunk-PMAU3SEE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/primitives/fpsAverage.ts","../src/primitives/FpsMeter.tsx","../src/primitives/ScaleIndicator.tsx","../src/primitives/Sidebar.tsx","../src/primitives/StatusBar.tsx","../src/primitives/Toolbar.tsx"],"names":["jsxs","jsx"],"mappings":"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","file":"chunk-PMAU3SEE.js","sourcesContent":["export function rollingAverage(samples: readonly number[]): number {\n if (samples.length === 0) return 0;\n const sum = samples.reduce((acc, n) => acc + n, 0);\n return Math.round(sum / samples.length);\n}\n","import { useEffect, useRef, useState } from 'react';\nimport { rollingAverage } from './fpsAverage';\n\nconst SAMPLE_WINDOW = 30;\n\n/** A live frame-rate readout, averaged over the last 30 frames. */\nexport function FpsMeter() {\n const [fps, setFps] = useState(0);\n const samplesRef = useRef<number[]>([]);\n const lastTimeRef = useRef<number | null>(null);\n\n useEffect(() => {\n let rafId = 0;\n const tick = (time: number) => {\n const last = lastTimeRef.current;\n if (last !== null) {\n const delta = time - last;\n if (delta > 0) {\n const samples = samplesRef.current;\n samples.push(1000 / delta);\n if (samples.length > SAMPLE_WINDOW) samples.shift();\n setFps(rollingAverage(samples));\n }\n }\n lastTimeRef.current = time;\n rafId = requestAnimationFrame(tick);\n };\n rafId = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(rafId);\n }, []);\n\n return (\n <div className=\"lk-fps-meter\">\n <span className=\"lk-fps-meter-value\">FPS {fps}</span>\n </div>\n );\n}\n","import { useContext } from 'react';\nimport { CanvasStackContext } from '../canvas/CanvasStackContext';\n\n/** Props for `<ScaleIndicator>`. */\nexport interface ScaleIndicatorProps {\n /** Current view zoom factor. If omitted, reads from CanvasStackContext. Defaults to 1. */\n zoom?: number;\n /** World pixels per unit at zoom=1. Default: 1. */\n pixelsPerUnit?: number;\n /** Unit label. Default: 'px'. */\n unit?: string;\n /** Target bar width in display pixels. Default: 100. */\n targetWidth?: number;\n}\n\n// Rounds n to a \"nice\" number — 1, 2, 5, 10, 20, 50, ...\nfunction niceNumber(n: number): number {\n if (n <= 0) return 1;\n const exp = Math.floor(Math.log10(n));\n const fraction = n / 10 ** exp;\n let nice: number;\n if (fraction < 1.5) nice = 1;\n else if (fraction < 3.5) nice = 2;\n else if (fraction < 7.5) nice = 5;\n else nice = 10;\n return nice * 10 ** exp;\n}\n\n/** A scale bar: a labeled rule showing how far a round number of world units\n * is at the current zoom. Reads the zoom from the surrounding canvas stack\n * unless one is passed. */\nexport function ScaleIndicator({\n zoom,\n pixelsPerUnit = 1,\n unit = 'px',\n targetWidth = 100,\n}: ScaleIndicatorProps) {\n const ctxValue = useContext(CanvasStackContext);\n const effectiveZoom = zoom ?? ctxValue?.view.zoom ?? 1;\n const effectivePxPerUnit = pixelsPerUnit * effectiveZoom;\n const targetUnits = targetWidth / effectivePxPerUnit;\n const niceUnits = niceNumber(targetUnits);\n const barWidth = niceUnits * effectivePxPerUnit;\n return (\n <div className=\"lk-scale-indicator\" role=\"img\" aria-label={`Scale: ${niceUnits} ${unit}`}>\n <div className=\"lk-scale-indicator-bar\" style={{ width: `${barWidth}px` }} />\n <span className=\"lk-scale-indicator-label\">\n {niceUnits} {unit}\n </span>\n </div>\n );\n}\n","import type { ReactNode } from 'react';\n\n/** Props for `<Sidebar>`. */\nexport interface SidebarProps {\n children: ReactNode;\n title?: string;\n collapsed?: boolean;\n onToggle?: () => void;\n}\n\n/** A collapsible side panel with an optional title. Collapse state is the\n * caller's to hold. */\nexport function Sidebar({ children, title, collapsed = false, onToggle }: SidebarProps) {\n const className = `lk-sidebar${collapsed ? ' lk-sidebar--collapsed' : ''}`;\n return (\n <aside className={className}>\n {(title || onToggle) && (\n <div className=\"lk-sidebar-header\">\n {title && <span className=\"lk-sidebar-title\">{title}</span>}\n {onToggle && (\n <button\n type=\"button\"\n className=\"lk-sidebar-toggle\"\n onClick={onToggle}\n aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}\n >\n {collapsed ? '›' : '‹'}\n </button>\n )}\n </div>\n )}\n <div className=\"lk-sidebar-body\">{children}</div>\n </aside>\n );\n}\n","import type { ReactNode } from 'react';\n\n/** Props for `<StatusBar>`. */\nexport interface StatusBarProps {\n children: ReactNode;\n}\n\n/** A footer strip for readouts. Fill it with `<StatusBar.Section>`. */\nexport function StatusBar({ children }: StatusBarProps) {\n return <div className=\"lk-status-bar\">{children}</div>;\n}\n\ninterface SectionProps {\n children: ReactNode;\n}\nfunction Section({ children }: SectionProps) {\n return <span className=\"lk-status-bar-section\">{children}</span>;\n}\n\n/** One readout within a status bar. */\nStatusBar.Section = Section;\n","import type { MouseEventHandler, ReactNode } from 'react';\n\n/** Props for `<Toolbar>`. */\nexport interface ToolbarProps {\n children: ReactNode;\n}\n\n/** A horizontal bar of controls. Fill it with `<Toolbar.Title>`,\n * `<Toolbar.Button>` and `<Toolbar.Spacer>`. */\nexport function Toolbar({ children }: ToolbarProps) {\n return <div className=\"lk-toolbar\">{children}</div>;\n}\n\ninterface TitleProps {\n children: ReactNode;\n}\nfunction Title({ children }: TitleProps) {\n return <span className=\"lk-toolbar-title\">{children}</span>;\n}\n\ninterface ButtonProps {\n children: ReactNode;\n onClick: MouseEventHandler<HTMLButtonElement>;\n disabled?: boolean;\n title?: string;\n}\nfunction Button({ children, onClick, disabled, title }: ButtonProps) {\n return (\n <button\n type=\"button\"\n className=\"lk-toolbar-button\"\n onClick={onClick}\n disabled={disabled}\n title={title}\n >\n {children}\n </button>\n );\n}\n\nfunction Spacer() {\n return <span className=\"lk-toolbar-spacer\" aria-hidden=\"true\" />;\n}\n\n/** A label within a toolbar. */\nToolbar.Title = Title;\n/** A button within a toolbar. */\nToolbar.Button = Button;\n/** Flexible space that pushes what follows to the far end of the toolbar. */\nToolbar.Spacer = Spacer;\n"]}
|
|
@@ -50,5 +50,5 @@ function clearUndo(_stack) {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
export { clearUndo, createEventBus, emptyStack, pushSnapshot, redo, undo };
|
|
53
|
-
//# sourceMappingURL=chunk-
|
|
54
|
-
//# sourceMappingURL=chunk-
|
|
53
|
+
//# sourceMappingURL=chunk-RL2LOLNI.js.map
|
|
54
|
+
//# sourceMappingURL=chunk-RL2LOLNI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/undo/eventBus.ts","../src/undo/undoStack.ts"],"names":[],"mappings":";AAYO,SAAS,cAAA,GAA2B;AACzC,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAgC;AACtD,EAAA,OAAO;AAAA,IACL,EAAA,CAAG,OAAO,QAAA,EAAU;AAClB,MAAA,IAAI,GAAA,GAAM,SAAA,CAAU,GAAA,CAAI,KAAK,CAAA;AAC7B,MAAA,IAAI,CAAC,GAAA,EAAK;AACR,QAAA,GAAA,uBAAU,GAAA,EAAI;AACd,QAAA,SAAA,CAAU,GAAA,CAAI,OAAO,GAAG,CAAA;AAAA,MAC1B;AACA,MAAA,GAAA,CAAI,IAAI,QAAQ,CAAA;AAChB,MAAA,OAAO,MAAM;AACX,QAAA,GAAA,EAAK,OAAO,QAAQ,CAAA;AAAA,MACtB,CAAA;AAAA,IACF,CAAA;AAAA,IACA,KAAK,KAAA,EAAO;AACV,MAAA,MAAM,GAAA,GAAM,SAAA,CAAU,GAAA,CAAI,KAAK,CAAA;AAC/B,MAAA,IAAI,CAAC,GAAA,EAAK;AACV,MAAA,KAAA,MAAW,EAAA,IAAM,CAAC,GAAG,GAAG,GAAG,EAAA,EAAG;AAAA,IAChC,CAAA;AAAA,IACA,KAAA,GAAQ;AACN,MAAA,SAAA,CAAU,KAAA,EAAM;AAAA,IAClB;AAAA,GACF;AACF;;;AC3BO,SAAS,UAAA,GAAwB;AACtC,EAAA,OAAO,EAAE,IAAA,EAAM,EAAC,EAAG,MAAA,EAAQ,EAAC,EAAE;AAChC;AAIO,SAAS,YAAA,CAAa,KAAA,EAAkB,QAAA,EAAmB,QAAA,EAA6B;AAC7F,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,IAAA,CAAK,MAAA,IAAU,QAAA,GAAW,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,GAAI,KAAA,CAAM,IAAA,CAAK,KAAA,EAAM;AACpF,EAAA,IAAA,CAAK,KAAK,QAAQ,CAAA;AAClB,EAAA,OAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,EAAC,EAAE;AAC5B;AAKO,SAAS,IAAA,CACd,OACA,OAAA,EACgD;AAChD,EAAA,IAAI,KAAA,CAAM,IAAA,CAAK,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AACpC,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,IAAA,CAAK,KAAA,EAAM;AAC9B,EAAA,MAAM,QAAA,GAAW,KAAK,GAAA,EAAI;AAC1B,EAAA,OAAO,EAAE,KAAA,EAAO,EAAE,IAAA,EAAM,MAAA,EAAQ,CAAC,GAAG,KAAA,CAAM,MAAA,EAAQ,OAAO,CAAA,EAAE,EAAG,QAAA,EAAS;AACzE;AAIO,SAAS,IAAA,CACd,OACA,OAAA,EACgD;AAChD,EAAA,IAAI,KAAA,CAAM,MAAA,CAAO,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AACtC,EAAA,MAAM,MAAA,GAAS,KAAA,CAAM,MAAA,CAAO,KAAA,EAAM;AAClC,EAAA,MAAM,QAAA,GAAW,OAAO,GAAA,EAAI;AAC5B,EAAA,OAAO,EAAE,KAAA,EAAO,EAAE,IAAA,EAAM,CAAC,GAAG,KAAA,CAAM,IAAA,EAAM,OAAO,CAAA,EAAG,MAAA,EAAO,EAAG,QAAA,EAAS;AACvE;AAGO,SAAS,UAAU,MAAA,EAA8B;AACtD,EAAA,OAAO,UAAA,EAAW;AACpB","file":"chunk-RL2LOLNI.js","sourcesContent":["/** A subscriber to a named event. */\nexport type EventListener = () => void;\n\n/** Named-event pub/sub, the channel an instrument's `emit` writes to and undo\n * snapshotting listens on. */\nexport interface EventBus {\n on(event: string, listener: EventListener): () => void;\n emit(event: string): void;\n clear(): void;\n}\n\n/** Build an empty event bus. */\nexport function createEventBus(): EventBus {\n const listeners = new Map<string, Set<EventListener>>();\n return {\n on(event, listener) {\n let set = listeners.get(event);\n if (!set) {\n set = new Set();\n listeners.set(event, set);\n }\n set.add(listener);\n return () => {\n set?.delete(listener);\n };\n },\n emit(event) {\n const set = listeners.get(event);\n if (!set) return;\n for (const fn of [...set]) fn();\n },\n clear() {\n listeners.clear();\n },\n };\n}\n","/** Undo history as two stacks of state snapshots: what has been done, and\n * what has been undone. The present state is held elsewhere, not here. */\nexport interface UndoStack {\n past: unknown[];\n future: unknown[];\n}\n\n/** A fresh, empty history. */\nexport function emptyStack(): UndoStack {\n return { past: [], future: [] };\n}\n\n/** Record a new snapshot, discarding the redo branch and the oldest entry\n * once `maxDepth` is reached. */\nexport function pushSnapshot(stack: UndoStack, snapshot: unknown, maxDepth: number): UndoStack {\n const past = stack.past.length >= maxDepth ? stack.past.slice(1) : stack.past.slice();\n past.push(snapshot);\n return { past, future: [] };\n}\n\n/** Step back one snapshot, returning the new history and the state to restore.\n * `null` when there is nothing to undo. The caller supplies `current` so it\n * can be redone. */\nexport function undo(\n stack: UndoStack,\n current: unknown,\n): { stack: UndoStack; snapshot: unknown } | null {\n if (stack.past.length === 0) return null;\n const past = stack.past.slice();\n const snapshot = past.pop();\n return { stack: { past, future: [...stack.future, current] }, snapshot };\n}\n\n/** Step forward one snapshot, returning the new history and the state to\n * restore. `null` when there is nothing to redo. */\nexport function redo(\n stack: UndoStack,\n current: unknown,\n): { stack: UndoStack; snapshot: unknown } | null {\n if (stack.future.length === 0) return null;\n const future = stack.future.slice();\n const snapshot = future.pop();\n return { stack: { past: [...stack.past, current], future }, snapshot };\n}\n\n/** Discard the whole history. */\nexport function clearUndo(_stack: UndoStack): UndoStack {\n return emptyStack();\n}\n"]}
|
|
@@ -82,5 +82,5 @@ function LayerList({ layers, visibility, onReorder, onToggle, className }) {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
export { LayerList };
|
|
85
|
-
//# sourceMappingURL=chunk-
|
|
86
|
-
//# sourceMappingURL=chunk-
|
|
85
|
+
//# sourceMappingURL=chunk-SFL7NFKN.js.map
|
|
86
|
+
//# sourceMappingURL=chunk-SFL7NFKN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/layers/LayerList.tsx"],"names":[],"mappings":";;;;AAoBO,SAAS,UAAU,EAAE,MAAA,EAAQ,YAAY,SAAA,EAAW,QAAA,EAAU,WAAU,EAAmB;AAChG,EAAA,MAAM,cAAc,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,EAAE,QAAQ,CAAA;AACpD,EAAA,MAAM,SAAS,MAAA,CAAO,MAAA,CAAO,CAAC,CAAA,KAAM,EAAE,QAAQ,CAAA;AAC9C,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAI,SAAwB,IAAI,CAAA;AAC9D,EAAA,MAAM,OAAA,GAAU,OAAyB,IAAI,CAAA;AAE7C,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,IAAA,uBACE,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,SAAA,GAAY,CAAA,cAAA,EAAiB,SAAS,CAAA,CAAA,GAAK,eAAA,EACzD,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,sBAAA,EAAuB,uBAAS,CAAA,EACjD,CAAA;AAAA,EAEJ;AAEA,EAAA,MAAM,SAAA,GAAY,CAAC,CAAA,EAA8B,KAAA,KAAkB;AACjE,IAAA,CAAA,CAAE,aAAA,CAAc,iBAAA,CAAkB,CAAA,CAAE,SAAS,CAAA;AAC7C,IAAA,OAAA,CAAQ,OAAA,GAAU,EAAE,SAAA,EAAW,CAAA,CAAE,WAAW,SAAA,EAAW,KAAA,EAAO,MAAA,EAAQ,CAAA,CAAE,OAAA,EAAQ;AAChF,IAAA,YAAA,CAAa,KAAK,CAAA;AAAA,EACpB,CAAA;AAEA,EAAA,MAAM,QAAA,GAAW,CAAC,CAAA,KAAiC;AACjD,IAAA,MAAM,OAAO,OAAA,CAAQ,OAAA;AACrB,IAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,SAAA,KAAc,EAAE,SAAA,EAAW;AAC7C,IAAA,MAAM,SAAA,GAAY,EAAA;AAClB,IAAA,MAAM,QAAQ,IAAA,CAAK,KAAA,CAAA,CAAO,EAAE,OAAA,GAAU,IAAA,CAAK,UAAU,SAAS,CAAA;AAC9D,IAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,WAAA,CAAY,MAAA,GAAS,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,SAAA,GAAY,KAAK,CAAC,CAAA;AACnF,IAAA,YAAA,CAAa,MAAM,CAAA;AAAA,EACrB,CAAA;AAEA,EAAA,MAAM,OAAA,GAAU,CAAC,CAAA,KAAiC;AAChD,IAAA,MAAM,OAAO,OAAA,CAAQ,OAAA;AACrB,IAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,SAAA,KAAc,EAAE,SAAA,EAAW;AAC7C,IAAA,IAAI,CAAA,CAAE,aAAA,CAAc,iBAAA,CAAkB,CAAA,CAAE,SAAS,CAAA,EAAG;AAClD,MAAA,CAAA,CAAE,aAAA,CAAc,qBAAA,CAAsB,CAAA,CAAE,SAAS,CAAA;AAAA,IACnD;AACA,IAAA,IAAI,SAAA,KAAc,IAAA,IAAQ,SAAA,KAAc,IAAA,CAAK,SAAA,EAAW;AACtD,MAAA,MAAM,IAAA,GAAO,CAAC,GAAG,WAAW,CAAA;AAC5B,MAAA,MAAM,CAAC,KAAK,CAAA,GAAI,KAAK,MAAA,CAAO,IAAA,CAAK,WAAW,CAAC,CAAA;AAC7C,MAAA,IAAI,KAAA,EAAO,IAAA,CAAK,MAAA,CAAO,SAAA,EAAW,GAAG,KAAK,CAAA;AAC1C,MAAA,SAAA,CAAU,CAAC,GAAG,IAAA,EAAM,GAAG,MAAM,CAAC,CAAA;AAAA,IAChC;AACA,IAAA,OAAA,CAAQ,OAAA,GAAU,IAAA;AAClB,IAAA,YAAA,CAAa,IAAI,CAAA;AAAA,EACnB,CAAA;AAEA,EAAA,4BACG,KAAA,EAAA,EAAI,SAAA,EAAW,YAAY,CAAA,cAAA,EAAiB,SAAS,KAAK,eAAA,EACxD,QAAA,EAAA;AAAA,IAAA,WAAA,CAAY,GAAA,CAAI,CAAC,KAAA,EAAO,CAAA,KAAM;AAC7B,MAAA,MAAM,aAAa,SAAA,KAAc,CAAA;AACjC,MAAA,uBACE,IAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UAEC,SAAA,EACE,aAAa,iDAAA,GAAoD,oBAAA;AAAA,UAGnE,QAAA,EAAA;AAAA,4BAAA,GAAA;AAAA,cAAC,QAAA;AAAA,cAAA;AAAA,gBACC,IAAA,EAAK,QAAA;AAAA,gBACL,SAAA,EAAU,uBAAA;AAAA,gBACV,YAAA,EAAY,CAAA,QAAA,EAAW,KAAA,CAAM,KAAK,CAAA,CAAA;AAAA,gBAClC,aAAA,EAAe,CAAC,CAAA,KAAM,SAAA,CAAU,GAAG,CAAC,CAAA;AAAA,gBACpC,aAAA,EAAe,QAAA;AAAA,gBACf,WAAA,EAAa,OAAA;AAAA,gBACd,QAAA,EAAA;AAAA;AAAA,aAED;AAAA,4BACA,GAAA;AAAA,cAAC,OAAA;AAAA,cAAA;AAAA,gBACC,SAAA,EAAU,sBAAA;AAAA,gBACV,IAAA,EAAK,UAAA;AAAA,gBACL,OAAA,EAAS,UAAA,CAAW,KAAA,CAAM,EAAE,CAAA,KAAM,KAAA;AAAA,gBAClC,QAAA,EAAU,CAAC,CAAA,KAAM,QAAA,CAAS,MAAM,EAAA,EAAI,CAAA,CAAE,OAAO,OAAO,CAAA;AAAA,gBACpD,YAAA,EAAY,CAAA,OAAA,EAAU,KAAA,CAAM,KAAK,CAAA;AAAA;AAAA,aACnC;AAAA,4BACA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,sBAAA,EAAwB,gBAAM,KAAA,EAAM;AAAA;AAAA,SAAA;AAAA,QAtB/C,KAAA,CAAM;AAAA,OAuBb;AAAA,IAEJ,CAAC,CAAA;AAAA,IACA,OAAO,GAAA,CAAI,CAAC,0BACX,IAAA,CAAC,KAAA,EAAA,EAAmB,WAAU,+CAAA,EAC5B,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,UAAK,SAAA,EAAU,qBAAA,EAAsB,MAAK,KAAA,EAAM,YAAA,EAAW,aAAY,QAAA,EAAA,WAAA,EAExE,CAAA;AAAA,sBACA,GAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,sBAAA,EAAwB,gBAAM,KAAA,EAAM;AAAA,KAAA,EAAA,EAJ5C,KAAA,CAAM,EAKhB,CACD;AAAA,GAAA,EACH,CAAA;AAEJ","file":"chunk-SFL7NFKN.js","sourcesContent":["import { type PointerEvent, useRef, useState } from 'react';\nimport type { LayerDescriptor } from '../instrument/types';\n\n/** Props for `<LayerList>`. */\nexport interface LayerListProps {\n layers: LayerDescriptor[];\n visibility: Record<string, boolean>;\n onReorder: (newOrder: LayerDescriptor[]) => void;\n onToggle: (id: string, visible: boolean) => void;\n className?: string;\n}\n\ninterface DragState {\n pointerId: number;\n fromIndex: number;\n startY: number;\n}\n\n/** A reorderable list of layers with per-layer visibility toggles. Layers\n * marked `alwaysOn` are pinned and cannot be reordered or hidden. */\nexport function LayerList({ layers, visibility, onReorder, onToggle, className }: LayerListProps) {\n const reorderable = layers.filter((l) => !l.alwaysOn);\n const pinned = layers.filter((l) => l.alwaysOn);\n const [dragIndex, setDragIndex] = useState<number | null>(null);\n const dragRef = useRef<DragState | null>(null);\n\n if (layers.length === 0) {\n return (\n <div className={className ? `lk-layer-list ${className}` : 'lk-layer-list'}>\n <div className=\"lk-layer-list__empty\">No layers</div>\n </div>\n );\n }\n\n const startDrag = (e: PointerEvent<HTMLElement>, index: number) => {\n e.currentTarget.setPointerCapture(e.pointerId);\n dragRef.current = { pointerId: e.pointerId, fromIndex: index, startY: e.clientY };\n setDragIndex(index);\n };\n\n const moveDrag = (e: PointerEvent<HTMLElement>) => {\n const drag = dragRef.current;\n if (!drag || drag.pointerId !== e.pointerId) return;\n const rowHeight = 28;\n const delta = Math.round((e.clientY - drag.startY) / rowHeight);\n const target = Math.min(reorderable.length - 1, Math.max(0, drag.fromIndex + delta));\n setDragIndex(target);\n };\n\n const endDrag = (e: PointerEvent<HTMLElement>) => {\n const drag = dragRef.current;\n if (!drag || drag.pointerId !== e.pointerId) return;\n if (e.currentTarget.hasPointerCapture(e.pointerId)) {\n e.currentTarget.releasePointerCapture(e.pointerId);\n }\n if (dragIndex !== null && dragIndex !== drag.fromIndex) {\n const next = [...reorderable];\n const [moved] = next.splice(drag.fromIndex, 1);\n if (moved) next.splice(dragIndex, 0, moved);\n onReorder([...next, ...pinned]);\n }\n dragRef.current = null;\n setDragIndex(null);\n };\n\n return (\n <div className={className ? `lk-layer-list ${className}` : 'lk-layer-list'}>\n {reorderable.map((layer, i) => {\n const isDragging = dragIndex === i;\n return (\n <div\n key={layer.id}\n className={\n isDragging ? 'lk-layer-list__row lk-layer-list__row--dragging' : 'lk-layer-list__row'\n }\n >\n <button\n type=\"button\"\n className=\"lk-layer-list__handle\"\n aria-label={`Reorder ${layer.label}`}\n onPointerDown={(e) => startDrag(e, i)}\n onPointerMove={moveDrag}\n onPointerUp={endDrag}\n >\n ⋮⋮\n </button>\n <input\n className=\"lk-layer-list__check\"\n type=\"checkbox\"\n checked={visibility[layer.id] !== false}\n onChange={(e) => onToggle(layer.id, e.target.checked)}\n aria-label={`Toggle ${layer.label}`}\n />\n <span className=\"lk-layer-list__label\">{layer.label}</span>\n </div>\n );\n })}\n {pinned.map((layer) => (\n <div key={layer.id} className=\"lk-layer-list__row lk-layer-list__row--pinned\">\n <span className=\"lk-layer-list__lock\" role=\"img\" aria-label=\"Always on\">\n 🔒\n </span>\n <span className=\"lk-layer-list__label\">{layer.label}</span>\n </div>\n ))}\n </div>\n );\n}\n"]}
|
|
@@ -347,5 +347,5 @@ function useExperimentState() {
|
|
|
347
347
|
}
|
|
348
348
|
|
|
349
349
|
export { LabStoreContext, LabStoreProvider, WorkspaceIdContext, WorkspaceIdProvider, createLabStore, createMemoryAdapter, decodeUrlHash, deserializeWorkspaces, emptyUndoStack, encodeUrlHash, labStorageKey, localStorageAdapter, noneAdapter, serializeWorkspaces, sessionStorageAdapter, urlHashAdapter, useExperimentState, useLabStore, useWorkspaceId };
|
|
350
|
-
//# sourceMappingURL=chunk-
|
|
351
|
-
//# sourceMappingURL=chunk-
|
|
350
|
+
//# sourceMappingURL=chunk-T7OKNJTY.js.map
|
|
351
|
+
//# sourceMappingURL=chunk-T7OKNJTY.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/state/helpers.ts","../src/state/adapters.ts","../src/state/context.tsx","../src/state/store.ts","../src/state/useExperimentState.ts"],"names":["useContext","useStore"],"mappings":"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","file":"chunk-T7OKNJTY.js","sourcesContent":["import type { InstrumentSerializers, UndoStack, WorkspaceRecord } from './types';\n\n/** The storage key a lab writes one of its three buckets under. Namespaced by\n * `storageKey` so two labs sharing an origin do not collide. */\nexport function labStorageKey(\n storageKey: string,\n bucket: 'workspaces' | 'saves' | 'theme',\n): string {\n return `lk:${storageKey}:${bucket}`;\n}\n\n/** Encode a string for the URL fragment. */\nexport function encodeUrlHash(value: string): string {\n return btoa(encodeURIComponent(value));\n}\n\n/** Decode a URL fragment written by `encodeUrlHash`, or `null` if it is\n * malformed. */\nexport function decodeUrlHash(hash: string): string | null {\n if (!hash) return null;\n try {\n return decodeURIComponent(atob(hash));\n } catch {\n return null;\n }\n}\n\n/** A fresh, empty undo history. */\nexport function emptyUndoStack(): UndoStack {\n return { past: [], future: [] };\n}\n\ntype SerializedRecord = Omit<WorkspaceRecord, 'undoStack'>;\n\n/** Serialize workspaces for storage, running each instrument's own serializer\n * over its state. Undo history is deliberately dropped — it does not survive\n * a reload. */\nexport function serializeWorkspaces(\n workspaces: WorkspaceRecord[],\n serializers: InstrumentSerializers,\n): string {\n const records: SerializedRecord[] = workspaces.map(({ undoStack: _undo, ...w }) => {\n const s = serializers[w.instrumentName];\n return {\n ...w,\n state: s?.serialize ? s.serialize(w.state) : w.state,\n };\n });\n return JSON.stringify(records);\n}\n\n/** Rebuild workspaces from storage, running each instrument's deserializer\n * over its state and starting each with an empty undo history. Returns an\n * empty list rather than throwing on malformed input. */\nexport function deserializeWorkspaces(\n raw: string,\n deserializers: InstrumentSerializers,\n): WorkspaceRecord[] {\n try {\n const records = JSON.parse(raw) as SerializedRecord[];\n return records.map((r) => {\n const d = deserializers[r.instrumentName];\n return {\n ...r,\n state: d?.deserialize ? d.deserialize(r.state) : r.state,\n undoStack: emptyUndoStack(),\n };\n });\n } catch {\n console.warn('[labkit] deserializeWorkspaces: failed to parse, returning empty list');\n return [];\n }\n}\n","import { decodeUrlHash, encodeUrlHash } from './helpers';\nimport type { StorageAdapter } from './types';\n\n/** Persist to `localStorage` — state survives a reload and a new tab. Falls\n * back to no-ops when storage is unavailable. */\nexport const localStorageAdapter: StorageAdapter = {\n read: (key) => {\n try {\n return localStorage.getItem(key);\n } catch {\n return null;\n }\n },\n write: (key, value) => {\n try {\n localStorage.setItem(key, value);\n } catch (e) {\n console.warn('[labkit] localStorage write failed:', e);\n }\n },\n delete: (key) => {\n try {\n localStorage.removeItem(key);\n } catch {\n /* ignore */\n }\n },\n};\n\n/** Persist to `sessionStorage` — state survives a reload but not a new tab. */\nexport const sessionStorageAdapter: StorageAdapter = {\n read: (key) => {\n try {\n return sessionStorage.getItem(key);\n } catch {\n return null;\n }\n },\n write: (key, value) => {\n try {\n sessionStorage.setItem(key, value);\n } catch (e) {\n console.warn('[labkit] sessionStorage write failed:', e);\n }\n },\n delete: (key) => {\n try {\n sessionStorage.removeItem(key);\n } catch {\n /* ignore */\n }\n },\n};\n\nconst URL_HASH_GUARD = typeof window !== 'undefined';\n\nfunction readHashMap(): Record<string, string> {\n if (!URL_HASH_GUARD) return {};\n const raw = decodeUrlHash(window.location.hash.replace(/^#/, ''));\n if (!raw) return {};\n try {\n return JSON.parse(raw) as Record<string, string>;\n } catch {\n return {};\n }\n}\n\nfunction writeHashMap(map: Record<string, string>): void {\n if (!URL_HASH_GUARD) return;\n const encoded = encodeUrlHash(JSON.stringify(map));\n window.history.replaceState(null, '', `#${encoded}`);\n}\n\n/** Persist into the URL fragment, so the page's link carries its state and\n * can be shared or bookmarked. */\nexport const urlHashAdapter: StorageAdapter = {\n read: (key) => readHashMap()[key] ?? null,\n write: (key, value) => {\n const map = readHashMap();\n map[key] = value;\n writeHashMap(map);\n },\n delete: (key) => {\n const map = readHashMap();\n delete map[key];\n writeHashMap(map);\n },\n};\n\n/** An in-memory store, discarded on reload. For tests, and for labs that\n * should start fresh every time. */\nexport function createMemoryAdapter(): StorageAdapter {\n const store = new Map<string, string>();\n return {\n read: (key) => store.get(key) ?? null,\n write: (key, value) => {\n store.set(key, value);\n },\n delete: (key) => {\n store.delete(key);\n },\n };\n}\n\n/** Persists nothing and reads back nothing. */\nexport const noneAdapter: StorageAdapter = {\n read: () => null,\n write: () => {},\n delete: () => {},\n};\n","import { createContext, type ReactElement, type ReactNode, useContext } from 'react';\nimport { useStore } from 'zustand/react';\nimport type { LabStore } from './store';\nimport type { LabStoreState } from './types';\n\ntype LabStoreCtx = { store: LabStore } | null;\n\n/** Context carrying the lab store. Prefer `useLabStore`; this is exported for\n * code that needs to read the context without subscribing. */\nexport const LabStoreContext = createContext<LabStoreCtx>(null);\n\n/** Provides a lab store to its subtree. */\nexport function LabStoreProvider({\n store,\n children,\n}: {\n store: LabStore;\n children: ReactNode;\n}): ReactElement {\n return <LabStoreContext.Provider value={{ store }}>{children}</LabStoreContext.Provider>;\n}\n\n/** Subscribe to the whole lab store. Throws outside a `<LabStoreProvider>`. */\nexport function useLabStore(): LabStoreState & ReturnType<LabStore['getState']> {\n const ctx = useContext(LabStoreContext);\n if (!ctx) throw new Error('[labkit] useLabStore must be used inside <LabStoreProvider>');\n return useStore(ctx.store);\n}\n\n/** Context carrying which workspace the subtree belongs to. */\nexport const WorkspaceIdContext = createContext<string | null>(null);\n\n/** Names the workspace its subtree belongs to, so an instrument's hooks can\n * find their own record in the store without being passed an id. */\nexport function WorkspaceIdProvider({\n workspaceId,\n children,\n}: {\n workspaceId: string;\n children: ReactNode;\n}): ReactElement {\n return <WorkspaceIdContext.Provider value={workspaceId}>{children}</WorkspaceIdContext.Provider>;\n}\n\n/** The id of the workspace this component is inside. Throws outside a\n * `<WorkspaceIdProvider>`. */\nexport function useWorkspaceId(): string {\n const id = useContext(WorkspaceIdContext);\n if (!id) throw new Error('[labkit] useWorkspaceId must be used inside <WorkspaceIdProvider>');\n return id;\n}\n","import { createStore, type StoreApi } from 'zustand/vanilla';\nimport {\n deserializeWorkspaces,\n emptyUndoStack,\n labStorageKey,\n serializeWorkspaces,\n} from './helpers';\nimport type {\n CreateLabStoreOptions,\n InstrumentSerializers,\n LabMode,\n LabStoreState,\n SavedSnapshot,\n WorkspaceRecord,\n} from './types';\n\n/** Every mutation a lab store supports: managing workspaces, saving and\n * restoring snapshots, and setting the color mode. */\nexport interface LabStoreActions {\n addWorkspace: (record: Omit<WorkspaceRecord, 'undoStack'>) => void;\n removeWorkspace: (id: string) => void;\n updateWorkspaceState: <TS>(id: string, next: TS | ((prev: TS) => TS)) => void;\n updateWorkspaceConfig: <TC>(id: string, key: keyof TC, value: TC[keyof TC]) => void;\n updateWorkspaceView: (id: string, view: WorkspaceRecord['view']) => void;\n updateWorkspaceUndoStack: (\n id: string,\n next:\n | WorkspaceRecord['undoStack']\n | ((prev: WorkspaceRecord['undoStack']) => WorkspaceRecord['undoStack']),\n ) => void;\n setWorkspaceInstrument: (id: string, instrumentName: string) => void;\n saveSnapshot: (workspaceId: string, name: string) => void;\n loadSnapshot: (snapshotId: string, workspaceId: string) => void;\n deleteSnapshot: (snapshotId: string) => void;\n listSnapshots: (workspaceId?: string) => SavedSnapshot[];\n setMode: (mode: LabMode) => void;\n}\n\n/** A lab's store: its state and actions, plus the hook instruments use to\n * register how their state is serialized. */\nexport type LabStore = StoreApi<LabStoreState & LabStoreActions> & {\n registerSerializers: (s: InstrumentSerializers) => void;\n};\n\n/** Build a lab store, hydrating from storage if anything was saved under the\n * same key. Writes back are debounced. */\nexport function createLabStore(options: CreateLabStoreOptions): LabStore {\n let serializers: InstrumentSerializers = {};\n let flushTimer: ReturnType<typeof setTimeout> | null = null;\n\n const workspacesRaw = options.storage.read(labStorageKey(options.storageKey, 'workspaces'));\n let hydratedWorkspaces: WorkspaceRecord[] = [];\n if (workspacesRaw) {\n hydratedWorkspaces = deserializeWorkspaces(workspacesRaw, serializers);\n }\n\n const savesRaw = options.storage.read(labStorageKey(options.storageKey, 'saves'));\n let hydratedSnapshots: SavedSnapshot[] = [];\n if (savesRaw) {\n try {\n hydratedSnapshots = JSON.parse(savesRaw) as SavedSnapshot[];\n } catch {\n console.warn('[labkit] failed to parse saved snapshots, starting empty');\n hydratedSnapshots = [];\n }\n }\n\n const modeRaw = options.storage.read(labStorageKey(options.storageKey, 'theme'));\n // `interstellar` was the dark mode's name back when it was a theme.\n const stored = modeRaw === 'interstellar' ? 'dark' : modeRaw;\n let hydratedMode: LabMode;\n if (stored === 'light' || stored === 'dark' || stored === 'auto') {\n hydratedMode = stored;\n } else {\n hydratedMode = options.initialMode ?? 'auto';\n }\n\n const store = createStore<LabStoreState & LabStoreActions>()((set, get) => ({\n workspaces: hydratedWorkspaces,\n savedSnapshots: hydratedSnapshots,\n mode: hydratedMode,\n\n addWorkspace: (record) => {\n set((s) => ({\n workspaces: [...s.workspaces, { ...record, undoStack: emptyUndoStack() }],\n }));\n scheduleFlush();\n },\n\n removeWorkspace: (id) => {\n set((s) => ({ workspaces: s.workspaces.filter((w) => w.id !== id) }));\n scheduleFlush();\n },\n\n updateWorkspaceState: (id, next) => {\n set((s) => ({\n workspaces: s.workspaces.map((w) => {\n if (w.id !== id) return w;\n const nextState =\n typeof next === 'function' ? (next as (prev: unknown) => unknown)(w.state) : next;\n return { ...w, state: nextState };\n }),\n }));\n scheduleFlush();\n },\n\n updateWorkspaceConfig: (id, key, value) => {\n set((s) => ({\n workspaces: s.workspaces.map((w) => {\n if (w.id !== id) return w;\n return {\n ...w,\n config: { ...(w.config as Record<string, unknown>), [key as string]: value },\n };\n }),\n }));\n scheduleFlush();\n },\n\n updateWorkspaceView: (id, view) => {\n set((s) => ({\n workspaces: s.workspaces.map((w) => (w.id === id ? { ...w, view } : w)),\n }));\n scheduleFlush();\n },\n\n updateWorkspaceUndoStack: (id, next) => {\n set((s) => ({\n workspaces: s.workspaces.map((w) => {\n if (w.id !== id) return w;\n const undoStack =\n typeof next === 'function'\n ? (next as (prev: WorkspaceRecord['undoStack']) => WorkspaceRecord['undoStack'])(\n w.undoStack,\n )\n : next;\n return { ...w, undoStack };\n }),\n }));\n },\n\n setWorkspaceInstrument: (id, instrumentName) => {\n set((s) => ({\n workspaces: s.workspaces.map((w) => (w.id === id ? { ...w, instrumentName } : w)),\n }));\n scheduleFlush();\n },\n\n saveSnapshot: (workspaceId, name) => {\n const workspace = get().workspaces.find((w) => w.id === workspaceId);\n if (!workspace) return;\n const reg = serializers[workspace.instrumentName];\n const serializedState = reg?.serialize\n ? reg.serialize(workspace.state)\n : structuredClone(workspace.state);\n const clonedConfig = structuredClone(workspace.config);\n const lastAt = get().savedSnapshots.reduce((m, sn) => (sn.savedAt > m ? sn.savedAt : m), 0);\n const savedAt = Math.max(Date.now(), lastAt + 1);\n const snapshot: SavedSnapshot = {\n id: crypto.randomUUID(),\n name,\n workspaceId,\n instrumentName: workspace.instrumentName,\n config: clonedConfig,\n state: serializedState,\n savedAt,\n };\n set((s) => ({ savedSnapshots: [...s.savedSnapshots, snapshot] }));\n scheduleFlush();\n },\n\n loadSnapshot: (snapshotId, workspaceId) => {\n const snapshot = get().savedSnapshots.find((sn) => sn.id === snapshotId);\n if (!snapshot) return;\n const workspace = get().workspaces.find((w) => w.id === workspaceId);\n if (!workspace) return;\n if (snapshot.instrumentName !== workspace.instrumentName) {\n console.warn(\n `[labkit] loadSnapshot: instrument mismatch (snapshot=${snapshot.instrumentName}, workspace=${workspace.instrumentName}); refusing to load`,\n );\n return;\n }\n const reg = serializers[snapshot.instrumentName];\n const restoredState = reg?.deserialize ? reg.deserialize(snapshot.state) : snapshot.state;\n set((s) => ({\n workspaces: s.workspaces.map((w) =>\n w.id === workspaceId ? { ...w, state: restoredState, config: snapshot.config } : w,\n ),\n }));\n scheduleFlush();\n },\n\n deleteSnapshot: (snapshotId) => {\n set((s) => ({\n savedSnapshots: s.savedSnapshots.filter((sn) => sn.id !== snapshotId),\n }));\n scheduleFlush();\n },\n\n listSnapshots: (workspaceId) => {\n const all = get().savedSnapshots;\n const filtered = workspaceId ? all.filter((sn) => sn.workspaceId === workspaceId) : all;\n return [...filtered].sort((a, b) => b.savedAt - a.savedAt);\n },\n\n setMode: (mode) => {\n set({ mode });\n scheduleFlush();\n },\n }));\n\n function scheduleFlush(): void {\n if (flushTimer) clearTimeout(flushTimer);\n flushTimer = setTimeout(() => {\n const s = store.getState();\n options.storage.write(\n labStorageKey(options.storageKey, 'workspaces'),\n serializeWorkspaces(s.workspaces, serializers),\n );\n options.storage.write(\n labStorageKey(options.storageKey, 'saves'),\n JSON.stringify(s.savedSnapshots),\n );\n options.storage.write(labStorageKey(options.storageKey, 'theme'), s.mode);\n flushTimer = null;\n }, 300);\n }\n\n return Object.assign(store, {\n registerSerializers(s: InstrumentSerializers) {\n serializers = s;\n },\n });\n}\n","import { useContext } from 'react';\nimport { useStore } from 'zustand/react';\nimport { LabStoreContext, WorkspaceIdContext } from './context';\nimport type { ExperimentStateHandle } from './types';\n\n/** An instrument's own state and config, plus setters. Reads the surrounding\n * workspace id, so an instrument never has to know which workspace it is\n * running in. Throws outside a lab store and workspace. */\nexport function useExperimentState<TS = unknown, TC = unknown>(): ExperimentStateHandle<TS, TC> {\n const ctx = useContext(LabStoreContext);\n if (!ctx) throw new Error('[labkit] useExperimentState must be used inside <LabStoreProvider>');\n\n const workspaceId = useContext(WorkspaceIdContext);\n if (!workspaceId)\n throw new Error('[labkit] useExperimentState must be used inside <WorkspaceIdProvider>');\n\n const record = useStore(ctx.store, (s) => s.workspaces.find((w) => w.id === workspaceId));\n\n if (!record) throw new Error(`[labkit] No workspace found with id \"${workspaceId}\"`);\n\n const updateWorkspaceState = useStore(ctx.store, (s) => s.updateWorkspaceState);\n const updateWorkspaceConfig = useStore(ctx.store, (s) => s.updateWorkspaceConfig);\n\n return {\n state: record.state as TS,\n config: record.config as TC,\n setState: (next) =>\n updateWorkspaceState(workspaceId, next as Parameters<typeof updateWorkspaceState>[1]),\n setConfig: (key, value) => updateWorkspaceConfig(workspaceId, key as never, value as never),\n };\n}\n"]}
|
package/dist/controls/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { C as ConfigField } from '../_dts/types-
|
|
3
|
-
export { a as CheckboxField, b as ColorField, d as ConfigFieldType, N as NumberField, S as SelectField, e as SelectOption, f as SliderField, T as TextField } from '../_dts/types-
|
|
2
|
+
import { C as ConfigField } from '../_dts/types-x92Kfeme.js';
|
|
3
|
+
export { a as CheckboxField, b as ColorField, d as ConfigFieldType, N as NumberField, S as SelectField, e as SelectOption, f as SliderField, T as TextField } from '../_dts/types-x92Kfeme.js';
|
|
4
4
|
|
|
5
5
|
interface ControlPanelProps<TC extends Record<string, unknown>> {
|
|
6
6
|
fields: ConfigField[];
|
|
@@ -8,6 +8,8 @@ interface ControlPanelProps<TC extends Record<string, unknown>> {
|
|
|
8
8
|
setConfig: (key: keyof TC, value: unknown) => void;
|
|
9
9
|
className?: string;
|
|
10
10
|
}
|
|
11
|
+
/** Render an instrument's config schema as a stack of controls, each writing
|
|
12
|
+
* back through `setConfig`. */
|
|
11
13
|
declare function ControlPanel<TC extends Record<string, unknown>>({ fields, config, setConfig, className, }: ControlPanelProps<TC>): react_jsx_runtime.JSX.Element;
|
|
12
14
|
|
|
13
15
|
export { ConfigField, ControlPanel };
|
package/dist/controls/index.js
CHANGED
package/dist/dragdrop/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { D as DragDropCapability, b as DragFeedback, P as PaletteItem } from '../_dts/index-
|
|
1
|
+
export { D as DragDropCapability, b as DragFeedback, P as PaletteItem } from '../_dts/index-CFlDPeZh.js';
|
|
2
2
|
import 'react';
|
|
3
|
-
import '../_dts/types-
|
|
3
|
+
import '../_dts/types-x92Kfeme.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,42 +1,55 @@
|
|
|
1
1
|
export { CanvasLayerDescriptor, CanvasStack, CanvasStackContext, CanvasStackContextValue, CanvasStackProps, screenToWorld, worldToScreen } from './canvas/index.js';
|
|
2
2
|
export { ControlPanel } from './controls/index.js';
|
|
3
|
-
import { C as ConfigField } from './_dts/types-
|
|
4
|
-
export { a as CheckboxField, b as ColorField, c as ConfigFieldBase, d as ConfigFieldType, N as NumberField, S as SelectField, e as SelectOption, f as SliderField, T as TextField } from './_dts/types-
|
|
5
|
-
import { I as Instrument } from './_dts/index-
|
|
6
|
-
export { C as CanvasCapability, a as CanvasLayer, D as DragDropCapability, b as DragFeedback, H as HitResult, L as LayerCapability, c as LayerDescriptor, P as PaletteItem, d as Point, R as RenderContext, S as SystemEvent, U as UndoCapability, V as ViewTransform } from './_dts/index-
|
|
3
|
+
import { C as ConfigField } from './_dts/types-x92Kfeme.js';
|
|
4
|
+
export { a as CheckboxField, b as ColorField, c as ConfigFieldBase, d as ConfigFieldType, N as NumberField, S as SelectField, e as SelectOption, f as SliderField, T as TextField } from './_dts/types-x92Kfeme.js';
|
|
5
|
+
import { I as Instrument } from './_dts/index-CFlDPeZh.js';
|
|
6
|
+
export { C as CanvasCapability, a as CanvasLayer, D as DragDropCapability, b as DragFeedback, H as HitResult, L as LayerCapability, c as LayerDescriptor, P as PaletteItem, d as Point, R as RenderContext, S as SystemEvent, U as UndoCapability, V as ViewTransform } from './_dts/index-CFlDPeZh.js';
|
|
7
7
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
8
8
|
import * as react from 'react';
|
|
9
9
|
import { ReactNode } from 'react';
|
|
10
|
-
import { S as StorageAdapter, o as LabMode, W as WorkspaceRecord, e as SavedSnapshot } from './_dts/useExperimentState-
|
|
11
|
-
export { C as CreateLabStoreOptions, E as ExperimentStateHandle, b as LabStoreContext, c as LabStoreProvider, d as LabStoreState, U as UndoStack, f as WorkspaceIdContext, g as WorkspaceIdProvider, i as createMemoryAdapter, l as localStorageAdapter, n as noneAdapter, s as sessionStorageAdapter, u as urlHashAdapter, j as useExperimentState, k as useLabStore, m as useWorkspaceId } from './_dts/useExperimentState-
|
|
10
|
+
import { S as StorageAdapter, o as LabMode, W as WorkspaceRecord, e as SavedSnapshot } from './_dts/useExperimentState-vrttakTt.js';
|
|
11
|
+
export { C as CreateLabStoreOptions, E as ExperimentStateHandle, b as LabStoreContext, c as LabStoreProvider, d as LabStoreState, U as UndoStack, f as WorkspaceIdContext, g as WorkspaceIdProvider, i as createMemoryAdapter, l as localStorageAdapter, n as noneAdapter, s as sessionStorageAdapter, u as urlHashAdapter, j as useExperimentState, k as useLabStore, m as useWorkspaceId } from './_dts/useExperimentState-vrttakTt.js';
|
|
12
12
|
export { LayerList, LayerListProps } from './layers/index.js';
|
|
13
13
|
export { FpsMeter, ScaleIndicator, ScaleIndicatorProps, Sidebar, SidebarProps, StatusBar, StatusBarProps, Toolbar, ToolbarProps } from './primitives/index.js';
|
|
14
14
|
export { LayerStack, LayerStackItem, LayerStackProps } from './ui/layers/index.js';
|
|
15
15
|
export { EventBus, EventListener, clearUndo, createEventBus, emptyStack, pushSnapshot, redo, undo } from './undo/index.js';
|
|
16
16
|
import 'zustand/vanilla';
|
|
17
17
|
|
|
18
|
+
/** Which optional capabilities an instrument declared — what the workspace
|
|
19
|
+
* consults to decide which chrome to show. */
|
|
18
20
|
interface CapabilityFlags {
|
|
19
21
|
hasCanvas: boolean;
|
|
20
22
|
hasLayers: boolean;
|
|
21
23
|
hasDragDrop: boolean;
|
|
22
24
|
hasUndo: boolean;
|
|
23
25
|
}
|
|
26
|
+
/** Read an instrument's declared capabilities off its definition. */
|
|
24
27
|
declare function detectCapabilities(instrument: Instrument<unknown, unknown>): CapabilityFlags;
|
|
25
28
|
|
|
29
|
+
/** Identity at runtime; exists so an instrument's state and config types are
|
|
30
|
+
* inferred from the spec rather than having to be written out. */
|
|
26
31
|
declare function defineInstrument<TS, TC>(spec: Instrument<TS, TC>): Instrument<TS, TC>;
|
|
27
32
|
|
|
33
|
+
/** Whether a config schema is usable, and every problem found rather than
|
|
34
|
+
* just the first. */
|
|
28
35
|
interface ValidationResult {
|
|
29
36
|
valid: boolean;
|
|
30
37
|
errors: string[];
|
|
31
38
|
}
|
|
39
|
+
/** Check a config schema for the mistakes that would otherwise surface as a
|
|
40
|
+
* silently broken control: empty or duplicate keys, unknown field types, and
|
|
41
|
+
* fields whose own constraints do not hold. */
|
|
32
42
|
declare function validateConfigSchema(fields: ConfigField[]): ValidationResult;
|
|
33
43
|
|
|
44
|
+
/** A grid's column and row counts. */
|
|
34
45
|
interface GridDims {
|
|
35
46
|
cols: number;
|
|
36
47
|
rows: number;
|
|
37
48
|
}
|
|
49
|
+
/** The most nearly square grid that fits `count` items. */
|
|
38
50
|
declare function gridDims(count: number): GridDims;
|
|
39
51
|
|
|
52
|
+
/** Props for `<Lab>`. */
|
|
40
53
|
interface LabProps {
|
|
41
54
|
instruments: Instrument[];
|
|
42
55
|
defaultInstrument: string;
|
|
@@ -53,8 +66,13 @@ interface LabProps {
|
|
|
53
66
|
title?: string;
|
|
54
67
|
children?: ReactNode;
|
|
55
68
|
}
|
|
69
|
+
/** The lab runtime: creates the store, provides it, and renders one workspace
|
|
70
|
+
* per record in a grid. Each workspace runs one of `instruments`. */
|
|
56
71
|
declare function Lab({ instruments, defaultInstrument, storage, storageKey, mode, nebula, title, children, }: LabProps): react_jsx_runtime.JSX.Element;
|
|
57
72
|
|
|
73
|
+
/** Lab-wide state and commands: the available instruments, the open
|
|
74
|
+
* workspaces and the operations over them, saved snapshots, and the color
|
|
75
|
+
* mode. */
|
|
58
76
|
interface LabContextValue {
|
|
59
77
|
instruments: Instrument[];
|
|
60
78
|
workspaces: WorkspaceRecord[];
|
|
@@ -69,9 +87,12 @@ interface LabContextValue {
|
|
|
69
87
|
mode: LabMode;
|
|
70
88
|
setMode: (m: LabMode) => void;
|
|
71
89
|
}
|
|
90
|
+
/** Context carrying the surrounding lab. Prefer `useLabContext`. */
|
|
72
91
|
declare const LabContext: react.Context<LabContextValue | null>;
|
|
92
|
+
/** The surrounding lab. Throws outside a `<Lab>`. */
|
|
73
93
|
declare function useLabContext(): LabContextValue;
|
|
74
94
|
|
|
95
|
+
/** Props for `<LabShell>`. */
|
|
75
96
|
interface LabShellProps {
|
|
76
97
|
title: string;
|
|
77
98
|
children: ReactNode;
|
|
@@ -82,14 +103,23 @@ interface LabShellProps {
|
|
|
82
103
|
/** Color mode. "auto" (default) follows prefers-color-scheme. */
|
|
83
104
|
mode?: LabMode;
|
|
84
105
|
}
|
|
106
|
+
/** Page frame for a lab: a titled header, a body, and an optional footer,
|
|
107
|
+
* themed for the resolved color mode. Presentational only — use `<Lab>` when
|
|
108
|
+
* the workspace runtime is wanted too. */
|
|
85
109
|
declare function LabShell({ title, children, header, footer, mode }: LabShellProps): react_jsx_runtime.JSX.Element;
|
|
86
110
|
|
|
111
|
+
/** Props for `<WorkspaceGrid>`. */
|
|
87
112
|
interface WorkspaceGridProps {
|
|
88
113
|
children: ReactNode;
|
|
89
114
|
}
|
|
115
|
+
/** Lays its children out in the most nearly square grid that fits them. */
|
|
90
116
|
declare function WorkspaceGrid({ children }: WorkspaceGridProps): react_jsx_runtime.JSX.Element;
|
|
91
117
|
|
|
92
118
|
type TokenValue = string | number | readonly (string | number)[];
|
|
119
|
+
/**
|
|
120
|
+
* A single design token as authored, before aliases are resolved: a DTCG-shaped
|
|
121
|
+
* `{ type, value }` pair where `value` may still be a `{ref}` to another token.
|
|
122
|
+
*/
|
|
93
123
|
interface RawToken {
|
|
94
124
|
readonly type: string;
|
|
95
125
|
readonly value: TokenValue;
|
|
@@ -97,8 +127,17 @@ interface RawToken {
|
|
|
97
127
|
readonly alpha?: number | undefined;
|
|
98
128
|
readonly description?: string | undefined;
|
|
99
129
|
}
|
|
130
|
+
/** A token graph flattened to one level, keyed by token name (no `--wzl-`
|
|
131
|
+
* prefix). Still unresolved — see `ResolvedTokenMap` for the output side. */
|
|
100
132
|
type FlatTokens = Record<string, RawToken>;
|
|
101
133
|
|
|
134
|
+
/**
|
|
135
|
+
* A theme: a named set of design tokens, organized into a mode-invariant layer
|
|
136
|
+
* plus one layer per mode (light, dark, …), optionally extending another theme.
|
|
137
|
+
* Tokens are held unresolved — aliases between them are collapsed later by
|
|
138
|
+
* `resolveTheme`, so an override of a base primitive still reaches everything
|
|
139
|
+
* that references it.
|
|
140
|
+
*/
|
|
102
141
|
interface Theme {
|
|
103
142
|
readonly name: string;
|
|
104
143
|
readonly extends: Theme | null;
|
|
@@ -114,6 +153,8 @@ interface Theme {
|
|
|
114
153
|
*/
|
|
115
154
|
declare const interstellarTheme: Theme;
|
|
116
155
|
|
|
156
|
+
/** An annotation drawn over a curve plot: a shaded band across a range of x,
|
|
157
|
+
* or a vertical line at one x. */
|
|
117
158
|
type CurveMark = {
|
|
118
159
|
kind: 'band';
|
|
119
160
|
x: [number, number];
|
|
@@ -123,6 +164,7 @@ type CurveMark = {
|
|
|
123
164
|
x: number;
|
|
124
165
|
color?: string;
|
|
125
166
|
};
|
|
167
|
+
/** Props for `<CurveField>`. */
|
|
126
168
|
interface CurveFieldProps {
|
|
127
169
|
/** Flat [x0, y0, x1, y1, …] — matches how curve-as-array configs
|
|
128
170
|
* serialize in JSON snapshots. */
|
|
@@ -148,12 +190,16 @@ interface CurveFieldProps {
|
|
|
148
190
|
*/
|
|
149
191
|
declare function CurveField({ values, min, max, step, width, height, defaults, onChange, marks, }: CurveFieldProps): react_jsx_runtime.JSX.Element;
|
|
150
192
|
|
|
193
|
+
/** Props for `<Subpanel>`. */
|
|
151
194
|
interface SubpanelProps {
|
|
152
195
|
title: ReactNode;
|
|
153
196
|
children: ReactNode;
|
|
154
197
|
className?: string;
|
|
155
198
|
}
|
|
199
|
+
/** A typographic divider inside a property list: a small title flanked by a
|
|
200
|
+
* rule. Purely a heading — use `<PropertyGroup>` for a bordered section. */
|
|
156
201
|
declare function Subpanel({ title, children, className }: SubpanelProps): react_jsx_runtime.JSX.Element;
|
|
202
|
+
/** Props for `<EffectCard>`. */
|
|
157
203
|
interface EffectCardProps {
|
|
158
204
|
/** Card title rendered in the title bar (e.g. effect kind label or a select). */
|
|
159
205
|
title: ReactNode;
|
|
@@ -183,10 +229,15 @@ interface EffectCardProps {
|
|
|
183
229
|
children?: ReactNode;
|
|
184
230
|
className?: string;
|
|
185
231
|
}
|
|
232
|
+
/** An accented, collapsible card for one item in a list of like things —
|
|
233
|
+
* effects, layers, tails. The accent color rebinds the theme accent token
|
|
234
|
+
* within the card, so its controls pick it up too. */
|
|
186
235
|
declare function EffectCard({ title, primary, accent, index, expanded, onToggleExpanded, onRemove, draggable, onPressHandle, onReleaseHandle, onDragStart, onDragEnd, onDragOver, onDragLeave, onDrop, dragging, children, className, }: EffectCardProps): react_jsx_runtime.JSX.Element;
|
|
236
|
+
/** The minimum an item must carry to appear in an `<EffectCardList>`. */
|
|
187
237
|
interface EffectCardListItem {
|
|
188
238
|
id: string | number;
|
|
189
239
|
}
|
|
240
|
+
/** Props for `<EffectCardList>`. */
|
|
190
241
|
interface EffectCardListProps<T extends EffectCardListItem> {
|
|
191
242
|
items: ReadonlyArray<T>;
|
|
192
243
|
renderItem: (item: T, helpers: {
|
|
@@ -201,8 +252,12 @@ interface EffectCardListProps<T extends EffectCardListItem> {
|
|
|
201
252
|
/** IDs to render expanded on first mount. Defaults to all collapsed. */
|
|
202
253
|
defaultExpandedIds?: ReadonlyArray<T['id']>;
|
|
203
254
|
}
|
|
255
|
+
/** A drag-reorderable list of `<EffectCard>`s. Owns the expanded and dragging
|
|
256
|
+
* state and hands it back to `renderItem`, so the caller only supplies each
|
|
257
|
+
* card's contents. */
|
|
204
258
|
declare function EffectCardList<T extends EffectCardListItem>({ items, renderItem, onReorder, empty, defaultExpandedIds, }: EffectCardListProps<T>): react_jsx_runtime.JSX.Element;
|
|
205
259
|
|
|
260
|
+
/** Props for `<PropertyGroup>`. */
|
|
206
261
|
interface PropertyGroupProps {
|
|
207
262
|
/** Title rendered between two rules at the top of the group. */
|
|
208
263
|
title: ReactNode;
|
|
@@ -225,13 +280,18 @@ interface PropertyGroupProps {
|
|
|
225
280
|
*/
|
|
226
281
|
declare function PropertyGroup({ title, hidden, children, className, pack, }: PropertyGroupProps): react_jsx_runtime.JSX.Element | null;
|
|
227
282
|
|
|
283
|
+
/** Props for `<PropertyPanel>`. */
|
|
228
284
|
interface PropertyPanelProps {
|
|
229
285
|
title?: ReactNode;
|
|
230
286
|
children: ReactNode;
|
|
231
287
|
className?: string;
|
|
232
288
|
}
|
|
289
|
+
/** A titled panel holding property rows — the sidebar container the rest of
|
|
290
|
+
* this module's components fill. */
|
|
233
291
|
declare function PropertyPanel({ title, children, className }: PropertyPanelProps): react_jsx_runtime.JSX.Element;
|
|
292
|
+
/** How a property list packs its rows into two columns. */
|
|
234
293
|
type PropertyListPack = 'auto-color' | 'pairs';
|
|
294
|
+
/** Props for `<PropertyList>`. */
|
|
235
295
|
interface PropertyListProps {
|
|
236
296
|
children: ReactNode;
|
|
237
297
|
className?: string;
|
|
@@ -250,8 +310,11 @@ interface PropertyListProps {
|
|
|
250
310
|
* nest inside <PropertyPanel/> for the standard glass card.
|
|
251
311
|
*/
|
|
252
312
|
declare function PropertyList({ children, className, pack }: PropertyListProps): react_jsx_runtime.JSX.Element;
|
|
313
|
+
/** Which control shape a row holds, which decides its intrinsic layout. */
|
|
253
314
|
type PropertyRowVariant = 'default' | 'color' | 'checkbox';
|
|
315
|
+
/** Whether a row's label sits above its control or beside it. */
|
|
254
316
|
type PropertyRowLayout = 'block' | 'inline';
|
|
317
|
+
/** Props for `<PropertyRow>`. */
|
|
255
318
|
interface PropertyRowProps {
|
|
256
319
|
label: ReactNode;
|
|
257
320
|
/** Right-aligned readout shown next to the label (e.g. current value). */
|
|
@@ -267,7 +330,10 @@ interface PropertyRowProps {
|
|
|
267
330
|
htmlFor?: string;
|
|
268
331
|
className?: string;
|
|
269
332
|
}
|
|
333
|
+
/** The label-plus-control frame every typed row below is built from. Use it
|
|
334
|
+
* directly for a control this module does not cover. */
|
|
270
335
|
declare function PropertyRow({ label, readout, variant, layout, children, htmlFor, className, }: PropertyRowProps): react_jsx_runtime.JSX.Element;
|
|
336
|
+
/** Props for `<SliderRow>`. */
|
|
271
337
|
interface SliderRowProps {
|
|
272
338
|
label: ReactNode;
|
|
273
339
|
value: number;
|
|
@@ -285,7 +351,10 @@ interface SliderRowProps {
|
|
|
285
351
|
unit?: ReactNode;
|
|
286
352
|
layout?: PropertyRowLayout;
|
|
287
353
|
}
|
|
354
|
+
/** A bounded number edited by dragging, with a live readout whose precision
|
|
355
|
+
* follows `step`. */
|
|
288
356
|
declare function SliderRow({ label, value, min, max, step, onChange, format, unit, layout, }: SliderRowProps): react_jsx_runtime.JSX.Element;
|
|
357
|
+
/** Props for `<ColorRow>`. */
|
|
289
358
|
interface ColorRowProps {
|
|
290
359
|
label: ReactNode;
|
|
291
360
|
value: string;
|
|
@@ -299,13 +368,17 @@ interface ColorRowProps {
|
|
|
299
368
|
*/
|
|
300
369
|
alphaDisabled?: boolean;
|
|
301
370
|
}
|
|
371
|
+
/** A color swatch, optionally with an alpha slider beneath it. */
|
|
302
372
|
declare function ColorRow({ label, value, onChange, alpha, onAlphaChange, alphaDisabled, }: ColorRowProps): react_jsx_runtime.JSX.Element;
|
|
373
|
+
/** Props for `<CheckboxRow>`. */
|
|
303
374
|
interface CheckboxRowProps {
|
|
304
375
|
label: ReactNode;
|
|
305
376
|
value: boolean;
|
|
306
377
|
onChange: (next: boolean) => void;
|
|
307
378
|
}
|
|
379
|
+
/** A boolean checkbox. */
|
|
308
380
|
declare function CheckboxRow({ label, value, onChange }: CheckboxRowProps): react_jsx_runtime.JSX.Element;
|
|
381
|
+
/** Props for `<TextRow>`. */
|
|
309
382
|
interface TextRowProps {
|
|
310
383
|
label: ReactNode;
|
|
311
384
|
value: string;
|
|
@@ -314,7 +387,9 @@ interface TextRowProps {
|
|
|
314
387
|
maxLength?: number;
|
|
315
388
|
layout?: PropertyRowLayout;
|
|
316
389
|
}
|
|
390
|
+
/** A single-line text input. */
|
|
317
391
|
declare function TextRow({ label, value, onChange, placeholder, maxLength, layout }: TextRowProps): react_jsx_runtime.JSX.Element;
|
|
392
|
+
/** Props for `<NumberRow>`. */
|
|
318
393
|
interface NumberRowProps {
|
|
319
394
|
label: ReactNode;
|
|
320
395
|
value: number;
|
|
@@ -325,11 +400,14 @@ interface NumberRowProps {
|
|
|
325
400
|
placeholder?: string;
|
|
326
401
|
layout?: PropertyRowLayout;
|
|
327
402
|
}
|
|
403
|
+
/** A number typed directly. Reach for `<SliderRow>` when the range matters
|
|
404
|
+
* more than the exact value. */
|
|
328
405
|
declare function NumberRow({ label, value, onChange, min, max, step, placeholder, layout, }: NumberRowProps): react_jsx_runtime.JSX.Element;
|
|
329
406
|
interface SelectOption<T extends string> {
|
|
330
407
|
value: T;
|
|
331
408
|
label: ReactNode;
|
|
332
409
|
}
|
|
410
|
+
/** Props for `<SelectRow>`. */
|
|
333
411
|
interface SelectRowProps<T extends string> {
|
|
334
412
|
label: ReactNode;
|
|
335
413
|
value: T;
|
|
@@ -337,7 +415,10 @@ interface SelectRowProps<T extends string> {
|
|
|
337
415
|
onChange: (next: T) => void;
|
|
338
416
|
layout?: PropertyRowLayout;
|
|
339
417
|
}
|
|
418
|
+
/** A dropdown over a fixed set of choices. Prefer `<ToggleRow>` when there
|
|
419
|
+
* are only two or three and they should all stay visible. */
|
|
340
420
|
declare function SelectRow<T extends string>({ label, value, options, onChange, layout, }: SelectRowProps<T>): react_jsx_runtime.JSX.Element;
|
|
421
|
+
/** Props for `<ToggleRow>`. */
|
|
341
422
|
interface ToggleRowProps<T extends string> {
|
|
342
423
|
label: ReactNode;
|
|
343
424
|
value: T;
|
|
@@ -345,8 +426,12 @@ interface ToggleRowProps<T extends string> {
|
|
|
345
426
|
onChange: (next: T) => void;
|
|
346
427
|
layout?: PropertyRowLayout;
|
|
347
428
|
}
|
|
429
|
+
/** A segmented control: the same choice as a select, with every option
|
|
430
|
+
* visible at once. */
|
|
348
431
|
declare function ToggleRow<T extends string>({ label, value, options, onChange, layout, }: ToggleRowProps<T>): react_jsx_runtime.JSX.Element;
|
|
349
432
|
|
|
433
|
+
/** What a workspace hands its toolbar: which instrument is running, the undo
|
|
434
|
+
* state and commands, the zoom controls, and the snapshot commands. */
|
|
350
435
|
interface WorkspaceToolbarContext {
|
|
351
436
|
workspaceId: string;
|
|
352
437
|
instrumentName: string;
|
|
@@ -369,6 +454,8 @@ interface WorkspaceToolbarContext {
|
|
|
369
454
|
close: () => void;
|
|
370
455
|
isLastWorkspace: boolean;
|
|
371
456
|
}
|
|
457
|
+
/** What a workspace hands its sidebar: the instrument's config schema, its
|
|
458
|
+
* current values, and the setter. */
|
|
372
459
|
interface WorkspaceSidebarContext {
|
|
373
460
|
workspaceId: string;
|
|
374
461
|
instrumentName: string;
|
|
@@ -376,33 +463,50 @@ interface WorkspaceSidebarContext {
|
|
|
376
463
|
config: unknown;
|
|
377
464
|
setConfig: (key: string, value: unknown) => void;
|
|
378
465
|
}
|
|
466
|
+
/** What a workspace hands its status bar. */
|
|
379
467
|
interface WorkspaceStatusBarContext {
|
|
380
468
|
workspaceId: string;
|
|
381
469
|
instrumentName: string;
|
|
382
470
|
zoom: number;
|
|
383
471
|
}
|
|
472
|
+
/** Replaces a workspace's toolbar. Receives everything the default one uses,
|
|
473
|
+
* so a custom toolbar need not reach into the store. */
|
|
384
474
|
type ToolbarSlot = (ctx: WorkspaceToolbarContext) => ReactNode;
|
|
475
|
+
/** Replaces a workspace's sidebar. */
|
|
385
476
|
type SidebarSlot = (ctx: WorkspaceSidebarContext) => ReactNode;
|
|
477
|
+
/** Replaces a workspace's status bar. */
|
|
386
478
|
type StatusBarSlot = (ctx: WorkspaceStatusBarContext) => ReactNode;
|
|
387
479
|
|
|
480
|
+
/** Props for `<DefaultSidebar>`. */
|
|
388
481
|
interface DefaultSidebarProps {
|
|
389
482
|
ctx: WorkspaceSidebarContext;
|
|
390
483
|
}
|
|
484
|
+
/** The sidebar a workspace renders when no `sidebar` slot is supplied: a
|
|
485
|
+
* control panel over the instrument's config schema. */
|
|
391
486
|
declare function DefaultSidebar({ ctx }: DefaultSidebarProps): react_jsx_runtime.JSX.Element;
|
|
392
487
|
|
|
488
|
+
/** Props for `<DefaultStatusBar>`. */
|
|
393
489
|
interface DefaultStatusBarProps {
|
|
394
490
|
ctx: WorkspaceStatusBarContext;
|
|
395
491
|
}
|
|
492
|
+
/** The status bar a workspace renders when no `statusBar` slot is supplied:
|
|
493
|
+
* the instrument's name and the current zoom. */
|
|
396
494
|
declare function DefaultStatusBar({ ctx }: DefaultStatusBarProps): react_jsx_runtime.JSX.Element;
|
|
397
495
|
|
|
496
|
+
/** Props for `<DefaultToolbar>`. */
|
|
398
497
|
interface DefaultToolbarProps {
|
|
399
498
|
ctx: WorkspaceToolbarContext;
|
|
400
499
|
}
|
|
500
|
+
/** The toolbar a workspace renders when no `toolbar` slot is supplied. Only
|
|
501
|
+
* shows the controls the instrument's declared capabilities support. */
|
|
401
502
|
declare function DefaultToolbar({ ctx }: DefaultToolbarProps): react_jsx_runtime.JSX.Element;
|
|
402
503
|
|
|
504
|
+
/** Props for `<Workspace>`. */
|
|
403
505
|
interface WorkspaceProps {
|
|
404
506
|
id: string;
|
|
405
507
|
}
|
|
508
|
+
/** Renders one workspace from the lab store: looks up its record and
|
|
509
|
+
* instrument, and mounts the instrument inside the workspace chrome. */
|
|
406
510
|
declare function Workspace({ id }: WorkspaceProps): react_jsx_runtime.JSX.Element;
|
|
407
511
|
|
|
408
512
|
interface UndoBindings {
|
|
@@ -411,6 +515,7 @@ interface UndoBindings {
|
|
|
411
515
|
undo: () => void;
|
|
412
516
|
redo: () => void;
|
|
413
517
|
}
|
|
518
|
+
/** Props for `<WorkspaceChrome>`. */
|
|
414
519
|
interface WorkspaceChromeProps {
|
|
415
520
|
workspaceId: string;
|
|
416
521
|
record: WorkspaceRecord;
|
|
@@ -423,11 +528,22 @@ interface WorkspaceChromeProps {
|
|
|
423
528
|
sidebarExtras?: ReactNode;
|
|
424
529
|
children: ReactNode;
|
|
425
530
|
}
|
|
531
|
+
/** The frame around a running instrument — toolbar, sidebar, status bar —
|
|
532
|
+
* each replaceable by a slot. Assembles the slot contexts and wires the undo
|
|
533
|
+
* keyboard shortcuts. */
|
|
426
534
|
declare function WorkspaceChrome({ workspaceId, record, instrument, isLastWorkspace, toolbar, sidebar, statusBar, undoBindings, sidebarExtras, children, }: WorkspaceChromeProps): react_jsx_runtime.JSX.Element;
|
|
427
535
|
|
|
536
|
+
/** Append a new workspace running `instrumentName`, at that instrument's
|
|
537
|
+
* default config and initial state. */
|
|
428
538
|
declare function addWorkspace(workspaces: WorkspaceRecord[], instruments: Instrument[], instrumentName: string): WorkspaceRecord[];
|
|
539
|
+
/** Insert a deep copy of a workspace directly after it. The copy starts with
|
|
540
|
+
* an empty undo history — the original's is not shared. */
|
|
429
541
|
declare function cloneWorkspace(workspaces: WorkspaceRecord[], id: string): WorkspaceRecord[];
|
|
542
|
+
/** Remove a workspace, unless it is the last one — a lab always has at least
|
|
543
|
+
* one. */
|
|
430
544
|
declare function closeWorkspace(workspaces: WorkspaceRecord[], id: string): WorkspaceRecord[];
|
|
545
|
+
/** Return a workspace to its instrument's defaults, keeping its id and its
|
|
546
|
+
* place in the list. */
|
|
431
547
|
declare function resetWorkspace(workspaces: WorkspaceRecord[], id: string, instruments: Instrument[]): WorkspaceRecord[];
|
|
432
548
|
|
|
433
549
|
export { CheckboxRow, ColorRow, ConfigField, CurveField, DefaultSidebar, DefaultStatusBar, DefaultToolbar, EffectCard, EffectCardList, Instrument, Lab, LabContext, LabMode, LabShell, NumberRow, PropertyGroup, PropertyList, PropertyPanel, PropertyRow, SavedSnapshot, SelectRow, SliderRow, StorageAdapter, Subpanel, TextRow, ToggleRow, Workspace, WorkspaceChrome, WorkspaceGrid, WorkspaceRecord, addWorkspace, cloneWorkspace, closeWorkspace, defineInstrument, detectCapabilities, gridDims, interstellarTheme, resetWorkspace, useLabContext, validateConfigSchema };
|