@weasel-js/labkit 1.7.3 → 1.8.1
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/README.md +24 -0
- package/dist/_dts/{CanvasStackContext-Cjy6I-Iv.d.ts → CanvasStackContext-B05ZM04l.d.ts} +3 -1
- package/dist/_dts/{Stage-D6t7o0pF.d.ts → Stage-CIJlbjrE.d.ts} +5 -3
- package/dist/_dts/{index-DCMA4Fy1.d.ts → index-8geQNQet.d.ts} +84 -12
- package/dist/_dts/{index-BTmaRy6a.d.ts → index-DRi3V5sN.d.ts} +6 -4
- package/dist/_dts/{types-BUBSIZuV.d.ts → types-DUfQ0isU.d.ts} +5 -1
- package/dist/_dts/{useTrialState-Bh8bzFgE.d.ts → useTrialState-Ar0AFpCe.d.ts} +94 -87
- package/dist/canvas/index.d.ts +5 -5
- package/dist/canvas/index.js +2 -2
- package/dist/chrome/index.d.ts +3 -3
- package/dist/chrome/index.js +7 -7
- package/dist/{chunk-HBGH344L.js → chunk-4RCVWX4M.js} +55 -18
- package/dist/chunk-4RCVWX4M.js.map +1 -0
- package/dist/{chunk-WIG6XHJ7.js → chunk-6IIKLXBZ.js} +13 -4
- package/dist/chunk-6IIKLXBZ.js.map +1 -0
- package/dist/{chunk-F4ACIK7Z.js → chunk-6Q6ACJ3H.js} +3 -3
- package/dist/{chunk-F4ACIK7Z.js.map → chunk-6Q6ACJ3H.js.map} +1 -1
- package/dist/{chunk-PMLZP7RT.js → chunk-7ALJOVGP.js} +5 -9
- package/dist/chunk-7ALJOVGP.js.map +1 -0
- package/dist/{chunk-XE5HJOPL.js → chunk-7FMZT2WL.js} +3 -3
- package/dist/{chunk-XE5HJOPL.js.map → chunk-7FMZT2WL.js.map} +1 -1
- package/dist/{chunk-XVUKDSYV.js → chunk-AVOILDN2.js} +2 -2
- package/dist/{chunk-XVUKDSYV.js.map → chunk-AVOILDN2.js.map} +1 -1
- package/dist/{chunk-2N7UBSS2.js → chunk-J5MDJEOZ.js} +3 -3
- package/dist/{chunk-2N7UBSS2.js.map → chunk-J5MDJEOZ.js.map} +1 -1
- package/dist/{chunk-LPGBC63T.js → chunk-KHB3KRRQ.js} +7 -7
- package/dist/chunk-KHB3KRRQ.js.map +1 -0
- package/dist/{chunk-IBVRMHW5.js → chunk-NHIO2O3O.js} +31 -30
- package/dist/chunk-NHIO2O3O.js.map +1 -0
- package/dist/{chunk-EESJUSYR.js → chunk-QMAY74TP.js} +56 -5
- package/dist/chunk-QMAY74TP.js.map +1 -0
- package/dist/{chunk-4X44DMRS.js → chunk-RN7T7OBO.js} +46 -24
- package/dist/chunk-RN7T7OBO.js.map +1 -0
- package/dist/{chunk-4TJ34FXA.js → chunk-RXO5UEGT.js} +5 -12
- package/dist/chunk-RXO5UEGT.js.map +1 -0
- package/dist/{chunk-E6NARGU7.js → chunk-SQX35X5V.js} +3 -3
- package/dist/{chunk-E6NARGU7.js.map → chunk-SQX35X5V.js.map} +1 -1
- package/dist/{chunk-YCFKW5RX.js → chunk-T5OEUNCB.js} +16 -2
- package/dist/chunk-T5OEUNCB.js.map +1 -0
- package/dist/{chunk-RL2LOLNI.js → chunk-UX66USTN.js} +2 -2
- package/dist/chunk-UX66USTN.js.map +1 -0
- package/dist/{chunk-IRMPZIYU.js → chunk-V4SMGEYY.js} +6732 -6507
- package/dist/chunk-V4SMGEYY.js.map +1 -0
- package/dist/{chunk-E23Q6A3Y.js → chunk-VCK5T6EP.js} +3 -3
- package/dist/{chunk-E23Q6A3Y.js.map → chunk-VCK5T6EP.js.map} +1 -1
- package/dist/{chunk-T6DLGEJB.js → chunk-XWR2P6MR.js} +23 -6
- package/dist/chunk-XWR2P6MR.js.map +1 -0
- package/dist/{chunk-XSJJTXNA.js → chunk-YZA73U4A.js} +19 -19
- package/dist/chunk-YZA73U4A.js.map +1 -0
- package/dist/config/index.d.ts +12 -5
- package/dist/config/index.js +2 -2
- package/dist/controls/index.d.ts +2 -2
- package/dist/controls/index.js +5 -5
- package/dist/dragdrop/index.d.ts +2 -2
- package/dist/dragdrop/index.js +2 -2
- package/dist/index.d.ts +158 -16
- package/dist/index.js +1036 -415
- package/dist/index.js.map +1 -1
- package/dist/layers/index.d.ts +2 -2
- package/dist/layers/index.js +3 -3
- package/dist/loupe/index.d.ts +176 -28
- package/dist/loupe/index.js +547 -141
- package/dist/loupe/index.js.map +1 -1
- package/dist/overview/index.d.ts +1 -1
- package/dist/overview/index.js +5 -5
- package/dist/passthrough/weasel-ui.js +3 -3
- package/dist/primitives/index.d.ts +4 -19
- package/dist/primitives/index.js +7 -7
- package/dist/state/index.d.ts +6 -8
- package/dist/state/index.js +5 -5
- package/dist/styles.css +181 -44
- package/dist/surface/index.d.ts +20 -1
- package/dist/surface/index.js +2 -2
- package/dist/undo/index.d.ts +19 -8
- package/dist/undo/index.js +1 -1
- package/package.json +11 -11
- package/src/annotations/AnnotationOverlay.abandon.test.tsx +4 -0
- package/src/annotations/AnnotationOverlay.tsx +10 -1
- package/src/annotations/Annotations.less +2 -0
- package/src/annotations/Annotations.overlay.test.tsx +29 -0
- package/src/canvas/CanvasStack.test.tsx +35 -0
- package/src/canvas/CanvasStack.tsx +12 -1
- package/src/canvas/useLayerScheduler.ts +14 -0
- package/src/chrome/builtins.test.ts +14 -0
- package/src/chrome/builtins.tsx +17 -2
- package/src/chrome/regions/StatusRegion.tsx +20 -14
- package/src/chrome/regions/regions.test.tsx +28 -0
- package/src/chrome/types.ts +8 -0
- package/src/clock/clock.browser.test.less +5 -0
- package/src/clock/clock.browser.test.tsx +77 -0
- package/src/clock/clock.integration.test.tsx +95 -0
- package/src/clock/clockRegistry.test.ts +33 -0
- package/src/clock/clockRegistry.ts +46 -0
- package/src/clock/hooks.ts +44 -0
- package/src/clock/index.ts +2 -0
- package/src/clock/trialClock.test.ts +265 -0
- package/src/clock/trialClock.ts +245 -0
- package/src/clock/useClockLoop.ts +45 -0
- package/src/config/builder.ts +11 -1
- package/src/config/resolve.test.ts +12 -0
- package/src/config/resolve.ts +5 -0
- package/src/config/types.ts +5 -1
- package/src/controls/ControlMatrix.test.tsx +10 -0
- package/src/controls/ControlMatrix.tsx +110 -58
- package/src/controls/ControlPanel.test.tsx +30 -0
- package/src/index.ts +3 -2
- package/src/instrument/types.ts +21 -1
- package/src/lab/Lab.chrome.test.tsx +8 -1
- package/src/lab/Lab.presentation.test.tsx +113 -0
- package/src/lab/Lab.surface.test.tsx +20 -9
- package/src/lab/Lab.tsx +132 -257
- package/src/lab/LabLightbox.browser.test.less +17 -0
- package/src/lab/LabLightbox.browser.test.tsx +216 -0
- package/src/lab/LabShell.less +10 -3
- package/src/lab/LabSurface.tsx +129 -0
- package/src/lab/Workspace.stories.tsx +18 -0
- package/src/lab/Workspace.surface.test.tsx +4 -0
- package/src/lab/Workspace.test.tsx +37 -1
- package/src/lab/Workspace.tsx +34 -6
- package/src/lab/index.ts +2 -0
- package/src/lab/nebula.ts +30 -0
- package/src/lab/openLab.test.ts +81 -0
- package/src/lab/openLab.ts +119 -0
- package/src/lab/presentation.browser.test.less +5 -0
- package/src/lab/presentation.browser.test.tsx +119 -0
- package/src/lab/presentation.less +64 -0
- package/src/lab/presentation.tsx +47 -0
- package/src/lab/useFocusPick.ts +43 -0
- package/src/lightbox/Lightbox.browser.test.less +14 -0
- package/src/lightbox/Lightbox.browser.test.tsx +113 -0
- package/src/lightbox/Lightbox.less +128 -0
- package/src/lightbox/Lightbox.test.tsx +195 -0
- package/src/lightbox/Lightbox.tsx +205 -0
- package/src/lightbox/LightboxContext.ts +38 -0
- package/src/lightbox/LightboxLayers.tsx +40 -0
- package/src/lightbox/index.ts +8 -0
- package/src/lightbox/modal.ts +94 -0
- package/src/loupe/AGENTS.md +40 -2
- package/src/loupe/CanvasLoupe.tsx +5 -4
- package/src/loupe/DomLoupe.tsx +7 -5
- package/src/loupe/Loupe.less +15 -0
- package/src/loupe/LoupeBubble.tsx +35 -13
- package/src/loupe/SourceLoupe.browser.test.tsx +204 -0
- package/src/loupe/SourceLoupe.tsx +60 -0
- package/src/loupe/TrialLoupe.browser.test.tsx +342 -0
- package/src/loupe/TrialLoupe.tsx +126 -28
- package/src/loupe/canvasLens.ts +20 -17
- package/src/loupe/index.ts +26 -2
- package/src/loupe/sourceLens.test.ts +65 -0
- package/src/loupe/sourceLens.ts +97 -0
- package/src/loupe/types.test.ts +6 -0
- package/src/loupe/types.ts +109 -7
- package/src/loupe/useLoupe.test.tsx +188 -3
- package/src/loupe/useLoupe.ts +106 -11
- package/src/primitives/index.ts +2 -2
- package/src/specimen/Specimen.tsx +0 -7
- package/src/state/helpers.test.ts +4 -11
- package/src/state/helpers.ts +2 -8
- package/src/state/index.ts +0 -2
- package/src/state/openLabStore.test.ts +10 -8
- package/src/state/openLabStore.ts +1 -1
- package/src/state/store.test.ts +2 -2
- package/src/state/store.ts +15 -16
- package/src/state/types.ts +9 -9
- package/src/styles.less +2 -1
- package/src/surface/AGENTS.md +13 -0
- package/src/surface/index.ts +1 -0
- package/src/surface/useSurfaceTile.test.tsx +4 -0
- package/src/surface/useSurfaceTile.ts +17 -1
- package/src/surface/useTiledSurface.test.tsx +65 -0
- package/src/surface/useTiledSurface.ts +68 -1
- package/src/theme/interstellar.theme.json +0 -14
- package/src/trial/Trial.stories.tsx +0 -1
- package/src/trial/Trial.test.tsx +40 -3
- package/src/trial/Trial.tsx +87 -43
- package/src/trial/TrialChrome.tsx +20 -2
- package/src/trial/trialOps.test.ts +1 -2
- package/src/trial/trialOps.ts +2 -3
- package/src/undo/stateOp.ts +21 -0
- package/src/undo/undoStack.ts +18 -6
- package/dist/chunk-4TJ34FXA.js.map +0 -1
- package/dist/chunk-4X44DMRS.js.map +0 -1
- package/dist/chunk-EESJUSYR.js.map +0 -1
- package/dist/chunk-HBGH344L.js.map +0 -1
- package/dist/chunk-IBVRMHW5.js.map +0 -1
- package/dist/chunk-IRMPZIYU.js.map +0 -1
- package/dist/chunk-LPGBC63T.js.map +0 -1
- package/dist/chunk-PMLZP7RT.js.map +0 -1
- package/dist/chunk-RL2LOLNI.js.map +0 -1
- package/dist/chunk-T6DLGEJB.js.map +0 -1
- package/dist/chunk-WIG6XHJ7.js.map +0 -1
- package/dist/chunk-XSJJTXNA.js.map +0 -1
- package/dist/chunk-YCFKW5RX.js.map +0 -1
- package/src/primitives/StatusBar.less +0 -34
- package/src/primitives/StatusBar.stories.tsx +0 -24
- package/src/primitives/StatusBar.test.tsx +0 -25
- package/src/primitives/StatusBar.tsx +0 -28
package/src/undo/undoStack.ts
CHANGED
|
@@ -1,17 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @deprecated The whole module. A trial's undo runs on weasel-history
|
|
3
|
+
* (`TrialRecord.history`); for an undo of your own, `createHistory` from
|
|
4
|
+
* `@weasel-js/core`. Kept until sherpa's studio, its last user, moves off it.
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
/** Undo history as two stacks of state snapshots: what has been done, and
|
|
2
|
-
* what has been undone. The present state is held elsewhere, not here.
|
|
8
|
+
* what has been undone. The present state is held elsewhere, not here.
|
|
9
|
+
* @deprecated See the module comment. */
|
|
3
10
|
export interface UndoStack {
|
|
4
11
|
past: unknown[];
|
|
5
12
|
future: unknown[];
|
|
6
13
|
}
|
|
7
14
|
|
|
8
|
-
/** A fresh, empty history.
|
|
15
|
+
/** A fresh, empty history.
|
|
16
|
+
* @deprecated See the module comment. */
|
|
9
17
|
export function emptyStack(): UndoStack {
|
|
10
18
|
return { past: [], future: [] };
|
|
11
19
|
}
|
|
12
20
|
|
|
13
21
|
/** Record a new snapshot, discarding the redo branch and the oldest entry
|
|
14
|
-
* once `maxDepth` is reached.
|
|
22
|
+
* once `maxDepth` is reached.
|
|
23
|
+
* @deprecated See the module comment. */
|
|
15
24
|
export function pushSnapshot(stack: UndoStack, snapshot: unknown, maxDepth: number): UndoStack {
|
|
16
25
|
const past = stack.past.length >= maxDepth ? stack.past.slice(1) : stack.past.slice();
|
|
17
26
|
past.push(snapshot);
|
|
@@ -20,7 +29,8 @@ export function pushSnapshot(stack: UndoStack, snapshot: unknown, maxDepth: numb
|
|
|
20
29
|
|
|
21
30
|
/** Step back one snapshot, returning the new history and the state to restore.
|
|
22
31
|
* `null` when there is nothing to undo. The caller supplies `current` so it
|
|
23
|
-
* can be redone.
|
|
32
|
+
* can be redone.
|
|
33
|
+
* @deprecated See the module comment. */
|
|
24
34
|
export function undo(
|
|
25
35
|
stack: UndoStack,
|
|
26
36
|
current: unknown,
|
|
@@ -32,7 +42,8 @@ export function undo(
|
|
|
32
42
|
}
|
|
33
43
|
|
|
34
44
|
/** Step forward one snapshot, returning the new history and the state to
|
|
35
|
-
* restore. `null` when there is nothing to redo.
|
|
45
|
+
* restore. `null` when there is nothing to redo.
|
|
46
|
+
* @deprecated See the module comment. */
|
|
36
47
|
export function redo(
|
|
37
48
|
stack: UndoStack,
|
|
38
49
|
current: unknown,
|
|
@@ -43,7 +54,8 @@ export function redo(
|
|
|
43
54
|
return { stack: { past: [...stack.past, current], future }, snapshot };
|
|
44
55
|
}
|
|
45
56
|
|
|
46
|
-
/** Discard the whole history.
|
|
57
|
+
/** Discard the whole history.
|
|
58
|
+
* @deprecated See the module comment. */
|
|
47
59
|
export function clearUndo(_stack: UndoStack): UndoStack {
|
|
48
60
|
return emptyStack();
|
|
49
61
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/primitives/Toolbar.tsx","../src/primitives/fpsAverage.ts","../src/primitives/FpsMeter.tsx","../src/primitives/ScaleIndicator.tsx","../src/primitives/ZoomControl.tsx","../src/primitives/StatusBar.tsx"],"names":["c","jsx","jsxs"],"mappings":"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","file":"chunk-4TJ34FXA.js","sourcesContent":["import type { MouseEventHandler, ReactNode } from 'react';\nimport { useRovingTabIndex } from '../passthrough/weasel-ui';\n\n/** Props for `<Toolbar>`. */\nexport interface ToolbarProps {\n children: ReactNode;\n /** Names the toolbar for assistive tech. Required by the APG pattern when a\n * view holds more than one. */\n 'aria-label'?: string;\n}\n\n/** A horizontal bar of controls. Fill it with `<Toolbar.Title>`,\n * `<Toolbar.Group>`, `<Toolbar.Button>` and `<Toolbar.Spacer>`. */\nexport function Toolbar({ children, 'aria-label': ariaLabel }: ToolbarProps) {\n const { rootRef, onKeyDown } = useRovingTabIndex<HTMLDivElement>({ orientation: 'horizontal' });\n return (\n <div\n ref={rootRef}\n className=\"lk-toolbar\"\n role=\"toolbar\"\n aria-label={ariaLabel}\n onKeyDown={onKeyDown}\n >\n {children}\n </div>\n );\n}\n\ninterface TitleProps {\n children: ReactNode;\n}\nfunction Title({ children }: TitleProps) {\n return <span className=\"lk-toolbar-title\">{children}</span>;\n}\n\n/** Props for `<Toolbar.Group>`. */\nexport interface ToolbarGroupProps {\n children: ReactNode;\n /** Pushes this group, and everything after it, to the far end. */\n end?: boolean;\n 'aria-label'?: string;\n}\n\n/** Related controls, kept tight and ruled off from their neighbors. Group\n * rather than separate with repeated `<Toolbar.Spacer>`: consecutive spacers\n * share the free space, so every gap collapses to the same slack and the bar\n * reads as one undifferentiated run. */\nfunction Group({ children, end, 'aria-label': ariaLabel }: ToolbarGroupProps) {\n return (\n // biome-ignore lint/a11y/useSemanticElements: a group inside role=\"toolbar\" is the APG pattern; the rule is local and cannot see the parent. <fieldset> means form controls, needs a <legend> to be named, and its UA min-width breaks flex children.\n <div\n className={`lk-toolbar-group${end ? ' lk-toolbar-group--end' : ''}`}\n role=\"group\"\n aria-label={ariaLabel}\n >\n {children}\n </div>\n );\n}\n\n/** Props for `<Toolbar.Button>`. */\nexport interface ToolbarButtonProps {\n children: ReactNode;\n onClick: MouseEventHandler<HTMLButtonElement>;\n disabled?: boolean;\n title?: string;\n /** Required when `children` is an icon with no text of its own. */\n 'aria-label'?: string;\n /** `danger` reddens on hover — for actions that discard work. */\n variant?: 'default' | 'danger';\n /** Square, for a button whose whole content is one glyph. */\n iconOnly?: boolean;\n /** Makes this a toggle: `aria-pressed`, and held down while true. */\n pressed?: boolean;\n}\n\nfunction Button({\n children,\n onClick,\n disabled,\n title,\n 'aria-label': ariaLabel,\n variant = 'default',\n iconOnly,\n pressed,\n}: ToolbarButtonProps) {\n const cls = [\n 'lk-toolbar-button',\n variant === 'danger' && 'lk-toolbar-button--danger',\n iconOnly && 'lk-toolbar-button--icon',\n pressed && 'lk-toolbar-button--pressed',\n ]\n .filter(Boolean)\n .join(' ');\n return (\n <button\n type=\"button\"\n className={cls}\n onClick={onClick}\n disabled={disabled}\n title={title}\n aria-label={ariaLabel ?? title}\n aria-pressed={pressed}\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 ruled-off run of related controls. */\nToolbar.Group = Group;\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","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 { useVisibleRaf } from '@weasel-js/core';\nimport { 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 const rootRef = useRef<HTMLDivElement | null>(null);\n\n const loop = useVisibleRaf(\n (time) => {\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 loop.request();\n },\n {\n target: rootRef,\n // The gap spent suspended is not a frame that took an hour to draw.\n onResume: () => {\n lastTimeRef.current = null;\n },\n },\n );\n\n useEffect(() => {\n loop.request();\n return () => loop.cancel();\n }, [loop]);\n\n return (\n <div className=\"lk-fps-meter\" ref={rootRef}>\n <span className=\"lk-fps-meter-label\">FPS</span>\n {/* The number is its own cell because it is the only part that changes:\n in one box with the label, every digit it gains or loses resizes the\n readout, and the status bar it sits in wraps to a second line and\n back — which in a small trial resizes the window. */}\n <span className=\"lk-fps-meter-value\">{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 { normalizeZoom } from '@weasel-js/core';\nimport { NumberField, Slider } from '../passthrough/weasel-ui';\n\n/** Props for `<ZoomControl>`. */\nexport interface ZoomControlProps {\n /** Current zoom as a scale factor: 1 is actual size. */\n zoom: number;\n /** Fired continuously while the slider drags. */\n onZoomChange: (zoom: number) => void;\n /** Fired when a drag settles or the field is committed. Defaults to\n * `onZoomChange`. */\n onZoomCommit?: (zoom: number) => void;\n /** Smallest selectable zoom. Defaults to 0.1 (10%). */\n min?: number;\n /** Largest selectable zoom. Defaults to 8 (800%). */\n max?: number;\n className?: string;\n}\n\n// Zoom is perceptually geometric — halving is as big a step as doubling — so\n// the slider runs on log2 and 100% lands mid-track for a symmetric range.\nconst toTrack = (zoom: number): number => Math.log2(zoom);\nconst fromTrack = (v: number): number => 2 ** v;\n\nconst clamp = (v: number, lo: number, hi: number): number => Math.max(lo, Math.min(hi, v));\n\n/** Zoom as a log-scaled slider with an editable percentage beside it. Pair it\n * with zoom-in / zoom-out buttons in a `<Toolbar.Group>`; this component owns\n * only the continuous part. */\nexport function ZoomControl({\n zoom,\n onZoomChange,\n onZoomCommit,\n min: minProp = 0.1,\n max: maxProp = 8,\n className,\n}: ZoomControlProps) {\n const min = normalizeZoom(minProp);\n const max = normalizeZoom(maxProp);\n const commit = onZoomCommit ?? onZoomChange;\n const emit = (track: number, done: boolean): void => {\n const next = clamp(fromTrack(track), min, max);\n (done ? commit : onZoomChange)(next);\n };\n\n return (\n <div className={`lk-zoom${className ? ` ${className}` : ''}`}>\n <Slider\n className=\"lk-zoom__slider\"\n ariaLabel=\"Zoom\"\n density=\"slim\"\n min={toTrack(min)}\n max={toTrack(max)}\n // Detents at the octaves plus actual size, so 25/50/100/200/400% are\n // reachable by drag rather than only by typing.\n stops={[-2, -1, 0, 1, 2]}\n thumbs={[{ value: clamp(toTrack(zoom), toTrack(min), toTrack(max)) }]}\n onInput={(next) => emit(next[0].value, false)}\n onChange={(next) => emit(next[0].value, true)}\n readoutPlacement=\"none\"\n />\n {/* `style: 'percent'` formats a fraction, so the field carries the scale\n factor itself and renders 0.5 as \"50%\". */}\n <NumberField\n className=\"lk-zoom__field\"\n width=\"fit\"\n aria-label=\"Zoom\"\n value={zoom}\n minValue={min}\n maxValue={max}\n step={0.01}\n hideSteppers\n ghost\n formatOptions={{ style: 'percent', maximumFractionDigits: 0 }}\n onChange={(next) => {\n if (!Number.isFinite(next)) return;\n commit(clamp(next, min, max));\n }}\n />\n </div>\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\n/** Props for `<StatusBar.Section>`. */\nexport interface StatusBarSectionProps {\n children: ReactNode;\n /** Pushes this section, and everything after it, to the far end. */\n end?: boolean;\n}\nfunction Section({ children, end }: StatusBarSectionProps) {\n return (\n <span className={`lk-status-bar-section${end ? ' lk-status-bar-section--end' : ''}`}>\n {children}\n </span>\n );\n}\n\n/** One readout within a status bar. */\nStatusBar.Section = Section;\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/annotations/ExportMenu.tsx","../src/annotations/MarkList.tsx","../src/chrome/builtins.tsx","../src/annotations/toolMap.ts","../src/tools/labTool.ts","../src/chrome/merge.ts","../src/chrome/regions/SidebarRegion.tsx","../src/chrome/regions/StatusRegion.tsx","../src/chrome/regions/ToolbarRegion.tsx","../src/chrome/LabChrome.tsx","../src/chrome/regions/PaletteRegion.tsx","../src/chrome/regions/TitleBarRegion.tsx","../src/chrome/regions/ViewportRegion.tsx"],"names":["a","v","jsx","jsxs","u","c","p","n","o","renderEntry"],"mappings":"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","file":"chunk-4X44DMRS.js","sourcesContent":["import { ExportIcon } from '@weasel-js/ui';\nimport { useId, useState } from 'react';\nimport { Callout } from '../passthrough/weasel-ui';\nimport { Toolbar } from '../primitives/Toolbar';\nimport { useAnnotationsOptional } from './AnnotationsContext';\nimport type { CaptureResult } from './types';\n\nconst SCALES = [1, 2, 4] as const;\nconst FORMATS = [\n { id: 'png', label: 'PNG' },\n { id: 'svg', label: 'SVG' },\n] as const;\n\ntype Format = (typeof FORMATS)[number]['id'];\n\nfunction fileName(result: CaptureResult): string {\n return `${result.target.replace(/[^a-z0-9._-]+/gi, '-')}.${result.format}`;\n}\n\n/** A blob the person asked for, handed to the browser's own save flow. The\n * object URL is revoked on the next turn — revoking it synchronously races\n * the navigation the click starts. */\nfunction download(result: CaptureResult): void {\n const url = URL.createObjectURL(result.blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = fileName(result);\n a.click();\n setTimeout(() => URL.revokeObjectURL(url), 0);\n}\n\n/** PNG goes to the clipboard as an image. SVG goes as text: `image/svg+xml`\n * needs Chromium's `web ` prefix and nothing else reads it, while the markup\n * is what a person pasting a vector export actually wants. */\nasync function copy(result: CaptureResult): Promise<void> {\n if (result.format === 'svg') {\n await navigator.clipboard.writeText(await result.blob.text());\n return;\n }\n await navigator.clipboard.write([new ClipboardItem({ 'image/png': result.blob })]);\n}\n\n/**\n * Export a target's picture with its marks on it.\n *\n * A panel rather than a button because a mark belongs to a target: with more\n * than one pane, \"export\" on its own does not say what.\n *\n * Reads the store through the hook the way `<MarkList>` does — the chrome\n * context carries no instrument state and is not the route to it.\n */\nexport function ExportMenu() {\n const marks = useAnnotationsOptional();\n const [anchor, setAnchor] = useState<HTMLSpanElement | null>(null);\n const [open, setOpen] = useState(false);\n const [target, setTarget] = useState<string | null>(null);\n const [format, setFormat] = useState<Format>('png');\n const [scale, setScale] = useState<number>(2);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const titleId = useId();\n\n if (!marks) return null;\n const targets = marks.targets();\n const chosen = target ?? targets[0]?.id ?? null;\n\n const run = async (then: (r: CaptureResult) => void | Promise<void>): Promise<void> => {\n if (!chosen) return;\n setBusy(true);\n setError(null);\n try {\n await then(await marks.capture(chosen, { format, scale }));\n setOpen(false);\n } catch (err) {\n setError(err instanceof Error ? err.message : String(err));\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <span className=\"lk-export\" ref={setAnchor}>\n <Toolbar.Button\n iconOnly\n pressed={open}\n aria-label=\"Export\"\n title=\"Export\"\n onClick={() => setOpen((was) => !was)}\n >\n <ExportIcon size={16} />\n </Toolbar.Button>\n <Callout\n triggerRef={{ current: anchor }}\n isOpen={open}\n onOpenChange={setOpen}\n onDismiss={() => setOpen(false)}\n placement=\"bottom end\"\n aria-labelledby={titleId}\n >\n <div className=\"lk-export__panel\">\n <span className=\"lk-export__title\" id={titleId}>\n Export\n </span>\n\n <label className=\"lk-export__row\">\n <span>Target</span>\n {/* Native controls: role, name and keyboard operability for free,\n and a five-control panel is not the place to rebuild them. */}\n <select\n aria-label=\"Target\"\n value={chosen ?? ''}\n onChange={(e) => setTarget(e.target.value)}\n >\n {targets.map((t) => (\n <option key={t.id} value={t.id}>\n {t.id}\n </option>\n ))}\n </select>\n </label>\n\n {/* A <fieldset>/<legend> cannot do this: a legend is outside its\n fieldset's grid formatting context, so it will not take a grid\n column and every choice row drops below its own label. */}\n <div className=\"lk-export__row\">\n <span>Format</span>\n <span className=\"lk-export__choices\" role=\"radiogroup\" aria-label=\"Format\">\n {FORMATS.map((f) => (\n <label key={f.id}>\n <input\n type=\"radio\"\n name=\"lk-export-format\"\n checked={format === f.id}\n onChange={() => setFormat(f.id)}\n />\n {f.label}\n </label>\n ))}\n </span>\n </div>\n\n <div className=\"lk-export__row\">\n <span>Scale</span>\n <span className=\"lk-export__choices\" role=\"radiogroup\" aria-label=\"Scale\">\n {SCALES.map((s) => (\n <label key={s}>\n <input\n type=\"radio\"\n name=\"lk-export-scale\"\n checked={scale === s}\n onChange={() => setScale(s)}\n />\n {s}×\n </label>\n ))}\n </span>\n </div>\n\n <div className=\"lk-export__actions\">\n <button type=\"button\" disabled={busy || !chosen} onClick={() => run(download)}>\n Download\n </button>\n <button type=\"button\" disabled={busy || !chosen} onClick={() => run(copy)}>\n Copy\n </button>\n </div>\n\n {error ? (\n <p className=\"lk-export__error\" role=\"alert\">\n {error}\n </p>\n ) : null}\n </div>\n </Callout>\n </span>\n );\n}\n","import { CloseButton, Input } from '../passthrough/weasel-ui';\nimport { useAnnotations } from './AnnotationsContext';\nimport type { AnnotationMeaning } from './types';\n\n/** Props for `<MarkList>`. */\nexport interface MarkListProps {\n /** The instrument's vocabulary. Omitted, rows carry no status control —\n * a host that declared none owns what a mark means. */\n meaning?: AnnotationMeaning;\n /** The live config, for answering staleness. */\n config: unknown;\n}\n\n/** Every mark on this trial's targets: what it says, and whether it still\n * describes the picture under it.\n *\n * Reads the store through the hook, which re-renders on every mutation — so a\n * mark drawn on a pane appears here without anything wiring the two. */\nexport function MarkList({ meaning, config }: MarkListProps) {\n const marks = useAnnotations();\n const all = marks.query();\n const statuses = meaning?.statuses ?? [];\n\n if (all.length === 0) {\n return <div className=\"lk-mark-list__empty\">No marks yet</div>;\n }\n\n return (\n <ul className=\"lk-mark-list\">\n {all.map((a) => {\n const stale = marks.isStale(a, config);\n return (\n <li className=\"lk-mark-list__row\" key={a.id}>\n <div className=\"lk-mark-list__head\">\n <span className=\"lk-mark-list__kind\">{a.kind}</span>\n <span className=\"lk-mark-list__target\">{a.target}</span>\n {stale ? <span className=\"lk-mark-list__stale\">stale</span> : null}\n <CloseButton\n className=\"lk-mark-list__drop\"\n ariaLabel={`Remove ${a.kind} on ${a.target}`}\n onClick={() => marks.remove(a.id)}\n />\n </div>\n <Input\n aria-label={`Title of ${a.kind} on ${a.target}`}\n value={a.title ?? ''}\n placeholder=\"Untitled\"\n onChange={(next) => marks.update(a.id, { title: next })}\n />\n {statuses.length > 0 ? (\n // A native select: it carries role, name and keyboard operability\n // for free, and a sidebar row is not the place to rebuild them.\n <select\n className=\"lk-mark-list__status\"\n aria-label={`Status of ${a.kind} on ${a.target}`}\n value={a.status ?? ''}\n onChange={(e) => marks.update(a.id, { status: e.target.value })}\n >\n <option value=\"\">—</option>\n {statuses.map((s) => (\n <option key={s.id} value={s.id}>\n {s.label}\n </option>\n ))}\n </select>\n ) : null}\n </li>\n );\n })}\n </ul>\n );\n}\n","import {\n CloneIcon,\n CloseIcon,\n FitIcon,\n LoupeIcon,\n RedoIcon,\n ResetIcon,\n SnapshotIcon,\n UndoIcon,\n ZoomInIcon,\n ZoomOutIcon,\n} from '@weasel-js/ui';\nimport { ExportMenu } from '../annotations/ExportMenu';\nimport { MarkList } from '../annotations/MarkList';\nimport type { ControlRenderer } from '../config/types';\nimport { ControlPanel } from '../controls/ControlPanel';\nimport type { Instrument } from '../instrument/types';\nimport { MenuButton } from '../passthrough/weasel-ui';\nimport { FpsMeter } from '../primitives/FpsMeter';\nimport { ScaleIndicator } from '../primitives/ScaleIndicator';\nimport { ZoomControl } from '../primitives/ZoomControl';\nimport type { TrialChromeContext, TrialContribution } from './types';\n\nconst ZOOM_STEP = 1.25;\n\n/** The property groups inside a contribution are folded under keys prefixed\n * with that contribution's id, so a group called `marks` cannot fold the\n * sidebar section of the same name. `ControlPanel` keys by bare label, so the\n * prefix goes on here and comes off again. */\nfunction groupFolds(\n collapsedSections: Readonly<Record<string, boolean>>,\n id: string,\n): Record<string, boolean> {\n const prefix = `${id}/`;\n const out: Record<string, boolean> = {};\n for (const [key, value] of Object.entries(collapsedSections)) {\n if (key.startsWith(prefix)) out[key.slice(prefix.length)] = value;\n }\n return out;\n}\n\n/** Built-in ids contributed only while runtime state says so — the loupe\n * toggle appears once a lens mounts, after the trial's first render. */\nexport const TRANSIENT_BUILTINS: ReadonlySet<string> = new Set(['loupe']);\n\n/**\n * The contributions a trial gets from what its instrument declared. This is\n * the whole \"declaring a capability provides the chrome\" rule — it replaces\n * the presence checks that used to be spread across the runtime.\n */\nexport function builtinContributions(\n instrument: Instrument,\n ctx: TrialChromeContext,\n controls?: Record<string, ControlRenderer>,\n): TrialContribution[] {\n const out: TrialContribution[] = [];\n const zoom = ctx.zoom;\n\n // Weasel history is the undo authority for marks, so declaring `annotations`\n // gets the buttons whether or not the instrument also declares `undo`.\n if (instrument.undo != null || instrument.annotations != null) {\n out.push({\n id: 'undo',\n region: 'toolbar',\n group: 'history',\n item: {\n icon: UndoIcon,\n label: 'Undo',\n shortcut: 'Mod+Z',\n disabled: !ctx.canUndo,\n onActivate: ctx.undo,\n },\n });\n out.push({\n id: 'redo',\n region: 'toolbar',\n group: 'history',\n item: {\n icon: RedoIcon,\n label: 'Redo',\n shortcut: 'Mod+Shift+Z',\n disabled: !ctx.canRedo,\n onActivate: ctx.redo,\n },\n });\n }\n\n // A tool id shares the contribution namespace, so a tool called `close`\n // collides with the built-in close button and throws. Annotation tools are\n // not here: the lab's rail carries them.\n for (const t of instrument.tools?.tools ?? []) {\n out.push({\n id: t.id,\n region: 'palette',\n group: t.group,\n item: { icon: t.icon, label: t.label, shortcut: t.shortcut },\n });\n }\n\n if (ctx.hasLoupe) {\n out.push({\n id: 'loupe',\n region: 'toolbar',\n group: 'view',\n item: {\n icon: LoupeIcon,\n label: 'Loupe',\n pressed: ctx.loupeOn,\n onActivate: ctx.toggleLoupe,\n },\n });\n }\n\n // Zoom acts on the view of the trial, so it is a viewport control. A trial\n // holding a non-2D view reports zoom as null and gets none of this.\n if ((instrument.canvas != null || instrument.stage != null) && zoom !== null) {\n out.push({\n id: 'zoom-out',\n region: 'viewport',\n group: 'zoom',\n item: {\n icon: ZoomOutIcon,\n label: 'Zoom out',\n onActivate: () => ctx.setZoom(zoom / ZOOM_STEP),\n },\n });\n out.push({\n id: 'zoom-in',\n region: 'viewport',\n group: 'zoom',\n item: {\n icon: ZoomInIcon,\n label: 'Zoom in',\n onActivate: () => ctx.setZoom(zoom * ZOOM_STEP),\n },\n });\n out.push({\n id: 'actual-size',\n region: 'viewport',\n group: 'zoom',\n item: { icon: FitIcon, label: 'Actual size', onActivate: () => ctx.setZoom(1) },\n });\n out.push({\n id: 'zoom-control',\n region: 'viewport',\n group: 'zoom',\n render: (c) => <ZoomControl zoom={c.zoom ?? 1} onZoomChange={c.setZoom} />,\n });\n out.push({\n id: 'scale',\n region: 'status',\n group: 'view',\n render: (c) => <ScaleIndicator zoom={c.zoom ?? 1} />,\n });\n if (instrument.canvas != null) {\n out.push({\n id: 'fps',\n region: 'status',\n group: 'view',\n end: true,\n render: () => <FpsMeter />,\n });\n }\n }\n\n if (instrument.annotations != null) {\n // A popover, so it takes the `render` escape: the panel picks a target,\n // and an icon button cannot ask which one.\n out.push({\n id: 'export',\n region: 'toolbar',\n group: 'trial',\n end: true,\n render: () => <ExportMenu />,\n });\n out.push({\n id: 'marks',\n region: 'sidebar',\n item: {\n title: 'Marks',\n body: <MarkList meaning={instrument.annotations.meaning} config={ctx.config} />,\n },\n });\n }\n\n if (Object.keys(ctx.configSchema.group.children).length > 0) {\n out.push({\n id: 'settings',\n region: 'sidebar',\n item: {\n title: 'Settings',\n body: (\n <ControlPanel\n schema={ctx.configSchema}\n config={ctx.config as Record<string, unknown>}\n auto={ctx.auto}\n setConfig={(key, value) => ctx.setConfig(String(key), value)}\n renderers={controls}\n collapsed={groupFolds(ctx.collapsedSections, 'settings')}\n onCollapse={(label, next) => ctx.setSectionCollapsed(`settings/${label}`, next)}\n />\n ),\n },\n });\n }\n\n if (ctx.savedSnapshots.length > 0) {\n // A menu is not an icon button, so it takes the render escape.\n out.push({\n id: 'snapshot-load',\n region: 'toolbar',\n group: 'trial',\n end: true,\n render: (c) => (\n <MenuButton\n aria-label=\"Load snapshot\"\n label=\"Load…\"\n items={c.savedSnapshots.map((sn) => ({ value: sn.id, label: sn.name }))}\n onAction={(id) => c.loadSnapshot(id)}\n />\n ),\n });\n }\n out.push({\n id: 'clone',\n region: 'titlebar',\n end: true,\n item: { icon: CloneIcon, label: 'Clone trial', onActivate: ctx.clone },\n });\n out.push({\n id: 'reset',\n region: 'titlebar',\n end: true,\n item: { icon: ResetIcon, label: 'Reset trial', onActivate: ctx.reset },\n });\n out.push({\n id: 'snapshot',\n region: 'titlebar',\n end: true,\n item: {\n icon: SnapshotIcon,\n label: 'Save snapshot',\n shortcut: 'Mod+S',\n onActivate: () => ctx.saveSnapshot(),\n },\n });\n out.push({\n id: 'close',\n region: 'titlebar',\n end: true,\n item: {\n icon: CloseIcon,\n label: ctx.isLastTrial ? 'Cannot close the last trial' : 'Close trial',\n danger: true,\n disabled: ctx.isLastTrial,\n onActivate: ctx.close,\n },\n });\n\n return out;\n}\n","import type { BuiltinToolId } from '@weasel-js/core';\nimport {\n ArrowIcon,\n EllipseIcon,\n HandIcon,\n LineIcon,\n PencilIcon,\n RectIcon,\n SelectIcon,\n TextIcon,\n} from '@weasel-js/ui';\nimport type { InstrumentList } from '../instrument/types';\nimport type { TrialTool } from '../tools/types';\nimport type { AnnotationKind } from './types';\n\n/** Which weasel tool an annotation tool drives, and what kind of mark that\n * makes. `select` makes none. */\nexport interface AnnotationToolInfo {\n weaselTool: BuiltinToolId;\n kind?: AnnotationKind;\n}\n\n// `arrow` and `stroke` have no weasel tool of their own, so the kind cannot be\n// read back from the insert — the overlay takes it from the tool id it holds.\nconst TOOLS: Record<string, AnnotationToolInfo> = {\n select: { weaselTool: 'select' },\n stroke: { weaselTool: 'pencil', kind: 'stroke' },\n line: { weaselTool: 'line', kind: 'line' },\n arrow: { weaselTool: 'line', kind: 'arrow' },\n rect: { weaselTool: 'rect', kind: 'rect' },\n ellipse: { weaselTool: 'ellipse', kind: 'ellipse' },\n text: { weaselTool: 'text', kind: 'text' },\n};\n\n/** The tools a lab's rail gets when any instrument declares `annotations`.\n * Ids share the lab's contribution namespace with its own `tools`, and the\n * lab's tool slot holds whichever is active. */\nexport const ANNOTATION_TOOLS: readonly TrialTool[] = [\n // Not in `TOOLS`: an id the map does not carry is what leaves the overlay idle.\n { id: 'pointer', label: 'Interact', icon: HandIcon, group: 'annotate' },\n { id: 'select', label: 'Select', icon: SelectIcon, group: 'annotate' },\n { id: 'stroke', label: 'Freehand', icon: PencilIcon, group: 'annotate' },\n { id: 'line', label: 'Line', icon: LineIcon, group: 'annotate' },\n { id: 'arrow', label: 'Arrow', icon: ArrowIcon, group: 'annotate' },\n { id: 'rect', label: 'Rectangle', icon: RectIcon, group: 'annotate' },\n { id: 'ellipse', label: 'Ellipse', icon: EllipseIcon, group: 'annotate' },\n { id: 'text', label: 'Text', icon: TextIcon, group: 'annotate' },\n];\n\n/** The annotation tools a lab's rail carries for these instruments: none\n * without an annotating instrument, else the union of what each asks for. */\nexport function labAnnotationTools(instruments: InstrumentList): readonly TrialTool[] {\n const wanted = new Set<string>();\n for (const i of instruments) {\n if (i.annotations == null) continue;\n if (i.annotations.tools == null) return ANNOTATION_TOOLS;\n for (const id of i.annotations.tools) wanted.add(id);\n }\n return ANNOTATION_TOOLS.filter((t) => wanted.has(t.id));\n}\n\n/** What `id` drives, or undefined for a tool that is not one of these. */\nexport function annotationToolInfo(id: string | null): AnnotationToolInfo | undefined {\n return id === null ? undefined : TOOLS[id];\n}\n\n/** Every weasel tool the overlay has to mount for this palette to work. */\nexport const ANNOTATION_WEASEL_TOOLS: readonly BuiltinToolId[] = [\n ...new Set(Object.values(TOOLS).map((t) => t.weaselTool)),\n];\n","import { labAnnotationTools } from '../annotations/toolMap';\nimport type { InstrumentList } from '../instrument/types';\n\n/**\n * The tool the lab's slot holds, once its default is applied: a lab with any\n * annotating instrument starts in `pointer`, so a first click reaches the\n * instrument rather than the marks over it, or in the first annotation tool\n * its rail carries when `pointer` is not among them.\n */\nexport function resolveLabTool(slot: string | null, instruments: InstrumentList): string | null {\n if (slot !== null) return slot;\n const tools = labAnnotationTools(instruments);\n if (tools.some((t) => t.id === 'pointer')) return 'pointer';\n return tools[0]?.id ?? null;\n}\n","/**\n * Concatenate contribution bundles into one list, preserving order — order\n * decides how a region lays its contributions out, so it is part of the\n * result, not an accident of it.\n *\n * Throws on a duplicate id rather than dropping one: a contribution silently\n * losing to a later bundle is the failure a registry exists to prevent.\n */\nexport function mergeContributions<T extends { id: string }>(\n ...bundles: readonly (readonly T[])[]\n): T[] {\n const out: T[] = [];\n const seen = new Set<string>();\n for (const bundle of bundles) {\n for (const entry of bundle) {\n if (seen.has(entry.id)) {\n throw new Error(\n `[labkit] mergeContributions: duplicate contribution id \"${entry.id}\". ` +\n 'Two bundles registered the same id; rename one, or suppress the ' +\n 'built-in before adding yours.',\n );\n }\n seen.add(entry.id);\n out.push(entry);\n }\n }\n return out;\n}\n\n/**\n * Drop contributions by id. Throws when an id is not present: a typo that\n * silently suppresses nothing is the same class of bug as a duplicate id\n * silently winning. `transient` names ids that are legitimately absent at\n * times — contributed only while some runtime state holds.\n */\nexport function suppressContributions<T extends { id: string }>(\n bundle: readonly T[],\n ids: readonly string[],\n transient: ReadonlySet<string> = new Set(),\n): T[] {\n const present = new Set(bundle.map((c) => c.id));\n for (const id of ids) {\n if (!present.has(id) && !transient.has(id)) {\n throw new Error(\n `[labkit] cannot suppress \"${id}\": no contribution with that id. ` +\n `Present ids: ${[...present].join(', ')}`,\n );\n }\n }\n const drop = new Set(ids);\n return bundle.filter((c) => !drop.has(c.id));\n}\n","import { type StanceProps, useStance } from '@weasel-js/ui';\nimport type { ReactNode } from 'react';\nimport type {\n RegionContribution,\n SidebarSection,\n SidebarSlotContext,\n TrialChromeContext,\n} from '../types';\n\n/** Props for `<SidebarRegion>`. */\nexport interface SidebarRegionProps<TCtx extends SidebarSlotContext = TrialChromeContext> {\n contributions: readonly RegionContribution<NoInfer<TCtx>>[];\n ctx: TCtx;\n /** Which region's items to lay out. */\n region?: string;\n}\n\nfunction Section({\n title,\n collapsed,\n onCollapsedChange,\n onUndock,\n children,\n stance,\n tone,\n}: StanceProps & {\n title: string;\n collapsed: boolean;\n onCollapsedChange: (collapsed: boolean) => void;\n onUndock?: () => void;\n children: ReactNode;\n}) {\n return (\n <section className=\"lk-sidebar-section\" {...useStance({ stance, tone })}>\n <div className=\"lk-sidebar-section__bar\">\n <button\n type=\"button\"\n className=\"lk-sidebar-section__head\"\n aria-expanded={!collapsed}\n onClick={() => onCollapsedChange(!collapsed)}\n >\n {title}\n </button>\n {onUndock ? (\n <button\n type=\"button\"\n className=\"lk-sidebar-section__undock\"\n aria-label={`Undock ${title}`}\n title={`Undock ${title}`}\n onClick={onUndock}\n >\n ⧉\n </button>\n ) : null}\n </div>\n {collapsed ? null : <div className=\"lk-sidebar-section__body\">{children}</div>}\n </section>\n );\n}\n\n/** Lays `sidebar` contributions out as titled, collapsible sections — a\n * trial's, or the lab's. A section the trial has torn out is not rendered\n * here — `Trial` portals its body into the workspace instead. A context with\n * no `undockPanel` offers no tear-out. */\nexport function SidebarRegion<TCtx extends SidebarSlotContext = TrialChromeContext>({\n contributions,\n ctx,\n region = 'sidebar',\n}: SidebarRegionProps<TCtx>) {\n if (contributions.length === 0) return null;\n return (\n <>\n {contributions.map((c) => {\n if (c.render) return <div key={c.id}>{c.render(ctx)}</div>;\n if (c.region !== region || !c.item) return null;\n if (ctx.undockedPanels?.includes(c.id)) return null;\n const item = c.item as SidebarSection;\n return (\n <Section\n key={c.id}\n title={item.title}\n stance={item.stance}\n tone={item.tone}\n collapsed={ctx.collapsedSections[c.id] ?? item.defaultCollapsed ?? false}\n onCollapsedChange={(next) => ctx.setSectionCollapsed(c.id, next)}\n onUndock={\n ctx.undockPanel && item.undockable !== false\n ? () => ctx.undockPanel?.(c.id, item.undockAs ?? 'tile')\n : undefined\n }\n >\n {item.body}\n </Section>\n );\n })}\n </>\n );\n}\n","import { StatusBar } from '../../primitives/StatusBar';\nimport type { RegionContribution, StatusReadout, TrialChromeContext } from '../types';\n\n/** Props for `<StatusRegion>`. */\nexport interface StatusRegionProps<TCtx = TrialChromeContext> {\n contributions: readonly RegionContribution<NoInfer<TCtx>>[];\n ctx: TCtx;\n /** Which region's readouts to lay out; the lab's footer is `footer`. */\n region?: string;\n}\n\n/** Lays a bar's readouts out. */\nexport function StatusRegion<TCtx = TrialChromeContext>({\n contributions,\n ctx,\n region = 'status',\n}: StatusRegionProps<TCtx>) {\n if (contributions.length === 0) return null;\n return (\n <StatusBar>\n {contributions.map((c) => {\n if (c.render)\n return (\n <StatusBar.Section key={c.id} end={c.end}>\n {c.render(ctx)}\n </StatusBar.Section>\n );\n if (c.region !== region || !c.item) return null;\n const item = c.item as StatusReadout;\n return (\n <StatusBar.Section key={c.id} end={c.end}>\n <span title={item.title}>{item.text}</span>\n </StatusBar.Section>\n );\n })}\n </StatusBar>\n );\n}\n","import type { ReactNode } from 'react';\nimport { Toolbar } from '../../primitives/Toolbar';\nimport type { RegionContribution, ToolbarItem, TrialChromeContext } from '../types';\n\n/** Props for `<ToolbarRegion>`. */\nexport interface ToolbarRegionProps<TCtx = TrialChromeContext> {\n contributions: readonly RegionContribution<NoInfer<TCtx>>[];\n ctx: TCtx;\n /** Which region's items to lay out; the lab's action bar is `header`. */\n region?: string;\n /** The bar's accessible name. */\n label?: string;\n}\n\ninterface Group<TCtx> {\n key: string;\n end: boolean;\n entries: RegionContribution<TCtx>[];\n}\n\n/** Bucket by group, preserving first-appearance order. Ungrouped\n * contributions each become their own bucket so they stay in place. */\nfunction groupsOf<TCtx>(contributions: readonly RegionContribution<TCtx>[]): Group<TCtx>[] {\n const groups: Group<TCtx>[] = [];\n const byKey = new Map<string, Group<TCtx>>();\n for (const c of contributions) {\n if (c.group == null) {\n groups.push({ key: c.id, end: c.end ?? false, entries: [c] });\n continue;\n }\n let g = byKey.get(c.group);\n if (!g) {\n g = { key: c.group, end: c.end ?? false, entries: [] };\n byKey.set(c.group, g);\n groups.push(g);\n }\n g.entries.push(c);\n }\n return groups;\n}\n\nfunction renderEntry<TCtx>(c: RegionContribution<TCtx>, ctx: TCtx, region: string): ReactNode {\n if (c.render) return <span key={c.id}>{c.render(ctx)}</span>;\n if (c.region !== region || !c.item) return null;\n const {\n icon: Icon,\n label,\n shortcut,\n disabled,\n danger,\n showLabel,\n pressed,\n onActivate,\n } = c.item as ToolbarItem<TCtx>;\n return (\n <Toolbar.Button\n key={c.id}\n iconOnly={!showLabel}\n variant={danger ? 'danger' : 'default'}\n disabled={disabled}\n pressed={pressed}\n aria-label={label}\n title={shortcut ? `${label} (${shortcut})` : label}\n onClick={() => onActivate(ctx)}\n >\n <Icon size={16} />\n {showLabel ? <span>{label}</span> : null}\n </Toolbar.Button>\n );\n}\n\n/** Lays a bar's contributions out, grouped by their `group`. */\nexport function ToolbarRegion<TCtx = TrialChromeContext>({\n contributions,\n ctx,\n region = 'toolbar',\n label = 'Trial actions',\n}: ToolbarRegionProps<TCtx>) {\n if (contributions.length === 0) return null;\n const groups = groupsOf(contributions);\n return (\n <Toolbar aria-label={label}>\n {groups.map((g) => (\n <Toolbar.Group key={g.key} end={g.end} aria-label={g.key}>\n {g.entries.map((c) => renderEntry(c, ctx, region))}\n </Toolbar.Group>\n ))}\n </Toolbar>\n );\n}\n","import { useContext, useMemo } from 'react';\nimport { useStore } from 'zustand/react';\nimport { useLabContext } from '../lab/LabContext';\nimport { LabStoreContext } from '../state/context';\nimport { usePersistedState } from '../state/usePersistedState';\nimport { resolveLabTool } from '../tools/labTool';\nimport type { TrialTool } from '../tools/types';\nimport type { LabChromeContext, LabContribution, LabRegion } from './labTypes';\nimport { mergeContributions } from './merge';\nimport { SidebarRegion } from './regions/SidebarRegion';\nimport { StatusRegion } from './regions/StatusRegion';\nimport { ToolbarRegion } from './regions/ToolbarRegion';\n\n/** The lab's chrome context: the lab itself, plus the lab's tool slot. Throws\n * outside a `<Lab>`. */\nexport function useLabChromeContext(): LabChromeContext {\n const lab = useLabContext();\n const storeCtx = useContext(LabStoreContext);\n if (!storeCtx) throw new Error('[labkit] lab chrome requires <LabStoreProvider>');\n const slot = useStore(storeCtx.store, (s) => s.activeToolId);\n const storeInstruments = useStore(storeCtx.store, (s) => s.instruments);\n const activeToolId = resolveLabTool(slot, storeInstruments ?? lab.instruments);\n const setLabTool = useStore(storeCtx.store, (s) => s.setLabTool);\n return useMemo(\n () => ({ ...lab, activeToolId, setActiveTool: setLabTool }),\n [lab, activeToolId, setLabTool],\n );\n}\n\n/** The lab's contributions for one region, in declaration order. */\nexport function contributionsIn<TCtx = LabChromeContext>(\n contributions: readonly LabContribution<TCtx>[],\n region: LabRegion,\n): LabContribution<TCtx>[] {\n return contributions.filter((c) => c.region === region);\n}\n\n/** The palette contributions a lab's `tools` stand for. Declaring a tool is\n * shorthand for contributing a palette item that writes the lab's tool\n * slot. */\nexport function toolContributions(tools: readonly TrialTool[]): LabContribution[] {\n return tools.map((t) => ({\n id: t.id,\n region: 'palette' as const,\n ...(t.group === undefined ? {} : { group: t.group }),\n item: {\n icon: t.icon,\n label: t.label,\n ...(t.shortcut === undefined ? {} : { shortcut: t.shortcut }),\n },\n }));\n}\n\n/** Everything the lab's chrome renders, from both of the ways a lab declares\n * it. Tools and contributions share one id namespace, so a tool colliding\n * with a contribution throws here rather than one of them silently losing. */\nexport function labContributions(\n tools: readonly TrialTool[] | undefined,\n chrome: readonly LabContribution[] | undefined,\n): LabContribution[] {\n return mergeContributions<LabContribution>(toolContributions(tools ?? []), [...(chrome ?? [])]);\n}\n\n/** Props shared by the lab's region mounts. Each takes the lab's whole\n * contribution list and lays out the part addressed to it. */\nexport interface LabRegionProps {\n contributions: readonly LabContribution[];\n}\n\n/** The lab's action bar, in the shell header beside the title. */\nexport function LabHeaderRegion({ contributions }: LabRegionProps) {\n const ctx = useLabChromeContext();\n return (\n <ToolbarRegion\n region=\"header\"\n label=\"Lab actions\"\n contributions={contributionsIn(contributions, 'header')}\n ctx={ctx}\n />\n );\n}\n\nfunction LabSections({ contributions, region }: LabRegionProps & { region: 'sidebar' | 'aside' }) {\n const lab = useLabChromeContext();\n const [collapsedSections, setFolds] = usePersistedState<Record<string, boolean>>(\n `lk-lab-${region}-folds`,\n {},\n { scope: 'lab' },\n );\n const ctx = useMemo(\n () => ({\n ...lab,\n collapsedSections,\n setSectionCollapsed: (key: string, collapsed: boolean) =>\n setFolds((f) => ({ ...f, [key]: collapsed })),\n }),\n [lab, collapsedSections, setFolds],\n );\n return (\n <SidebarRegion\n contributions={contributionsIn(contributions, region)}\n ctx={ctx}\n region={region}\n />\n );\n}\n\n/** The lab's sidebar sections. Fold state is a lab-scoped persisted value, so it\n * survives a reload in a stored lab and lasts the session in an unstored one. */\nexport function LabSidebarRegion({ contributions }: LabRegionProps) {\n return <LabSections contributions={contributions} region=\"sidebar\" />;\n}\n\n/** The lab's aside sections, on the far side of the workspace from the sidebar.\n * Fold state persists the way the sidebar's does. */\nexport function LabAsideRegion({ contributions }: LabRegionProps) {\n return <LabSections contributions={contributions} region=\"aside\" />;\n}\n\n/** The lab's readouts, in the shell footer below the workspace. */\nexport function LabFooterRegion({ contributions }: LabRegionProps) {\n const ctx = useLabChromeContext();\n return (\n <StatusRegion\n region=\"footer\"\n contributions={contributionsIn(contributions, 'footer')}\n ctx={ctx}\n />\n );\n}\n","import { ToolButton, ToolGroup, useRovingTabIndex } from '../../passthrough/weasel-ui';\nimport type { RegionContribution, ToolItem, ToolSlotContext, TrialChromeContext } from '../types';\n\n/** Props for `<PaletteRegion>`. */\nexport interface PaletteRegionProps<TCtx extends ToolSlotContext = TrialChromeContext> {\n contributions: readonly RegionContribution<NoInfer<TCtx>>[];\n ctx: TCtx;\n /** Which region's items to lay out. The lab's rail names the same box\n * `palette` too, so this only moves for a chrome that does not. */\n region?: string;\n}\n\n/** A tool strip: a trial's, or the lab's. Selection lives in whichever tool\n * slot the context carries; this region only reflects it. An item carrying\n * `onActivate` is a command instead — it presses, and never latches. */\nexport function PaletteRegion<TCtx extends ToolSlotContext = TrialChromeContext>({\n contributions,\n ctx,\n region = 'palette',\n}: PaletteRegionProps<TCtx>) {\n const { rootRef, onKeyDown } = useRovingTabIndex<HTMLDivElement>({ orientation: 'vertical' });\n if (contributions.length === 0) return null;\n return (\n <div\n ref={rootRef}\n className=\"lk-palette-region\"\n role=\"toolbar\"\n aria-label=\"Tools\"\n aria-orientation=\"vertical\"\n onKeyDown={onKeyDown}\n >\n <ToolGroup orientation=\"vertical\">\n {contributions.map((c) => {\n if (c.render) return <span key={c.id}>{c.render(ctx)}</span>;\n if (c.region !== region || !c.item) return null;\n const { icon: Icon, label, shortcut, disabled, onActivate } = c.item as ToolItem<TCtx>;\n return (\n <ToolButton\n key={c.id}\n icon={<Icon size={16} />}\n label={label}\n shortcut={shortcut}\n active={onActivate ? false : ctx.activeToolId === c.id}\n disabled={disabled}\n onClick={onActivate ? () => onActivate(ctx) : () => ctx.setActiveTool(c.id)}\n />\n );\n })}\n </ToolGroup>\n </div>\n );\n}\n","import type { ReactNode } from 'react';\nimport type { TrialChromeContext, TrialContribution } from '../types';\n\n/** Which end of the title bar a `<TitleBarRegion>` lays out: `'lead'` renders\n * the contributions that leave `end` unset, before the title; `'actions'`\n * renders the ones that set it, after everything else. */\nexport type TitleBarPlacement = 'lead' | 'actions';\n\n/** Props for `<TitleBarRegion>`. */\nexport interface TitleBarRegionProps {\n contributions: readonly TrialContribution[];\n ctx: TrialChromeContext;\n /** Defaults to `'actions'`, where the built-ins live. */\n placement?: TitleBarPlacement;\n}\n\nfunction renderEntry(c: TrialContribution, ctx: TrialChromeContext): ReactNode {\n if (c.render) return <span key={c.id}>{c.render(ctx)}</span>;\n if (c.region !== 'titlebar' || !c.item) return null;\n const { icon: Icon, label, shortcut, disabled, danger, onActivate } = c.item;\n return (\n <button\n key={c.id}\n type=\"button\"\n className={`lk-titlebar-button${danger ? ' lk-titlebar-button--danger' : ''}`}\n disabled={disabled}\n aria-label={label}\n title={shortcut ? `${label} (${shortcut})` : label}\n onClick={() => onActivate(ctx)}\n // The bar behind these buttons is the window drag surface, so a press\n // that lands here must not also start a drag.\n onPointerDown={(e) => e.stopPropagation()}\n onMouseDown={(e) => e.stopPropagation()}\n >\n <Icon size={16} />\n </button>\n );\n}\n\n/** Lays a trial's `titlebar` contributions out at one end of the bar. */\nexport function TitleBarRegion({ contributions, ctx, placement = 'actions' }: TitleBarRegionProps) {\n const wanted = placement === 'actions';\n const mine = contributions.filter((c) => (c.end ?? false) === wanted);\n if (mine.length === 0) return null;\n return (\n <span className={wanted ? 'lk-trial__titlebar-actions' : 'lk-trial__titlebar-lead'}>\n {mine.map((c) => renderEntry(c, ctx))}\n </span>\n );\n}\n","import { useRovingTabIndex } from '../../passthrough/weasel-ui';\nimport type { TrialChromeContext, TrialContribution } from '../types';\n\n/** Props for `<ViewportRegion>`. */\nexport interface ViewportRegionProps {\n contributions: readonly TrialContribution[];\n ctx: TrialChromeContext;\n}\n\n/**\n * Controls acting on the view of a trial. Anchored inside the content well\n * rather than in the toolbar, which acts on the trial itself.\n */\nexport function ViewportRegion({ contributions, ctx }: ViewportRegionProps) {\n const { rootRef, onKeyDown } = useRovingTabIndex<HTMLDivElement>({ orientation: 'horizontal' });\n if (contributions.length === 0) return null;\n return (\n <div\n ref={rootRef}\n className=\"lk-viewport-controls\"\n role=\"toolbar\"\n aria-label=\"View\"\n onKeyDown={onKeyDown}\n >\n {contributions.map((c) => {\n if (c.render) {\n return (\n <span key={c.id} className=\"lk-viewport-controls__item\">\n {c.render(ctx)}\n </span>\n );\n }\n if (c.region !== 'viewport' || !c.item) return null;\n const { icon: Icon, label, disabled, onActivate } = c.item;\n return (\n <button\n key={c.id}\n type=\"button\"\n className=\"lk-viewport-controls__button\"\n aria-label={label}\n title={label}\n disabled={disabled}\n onClick={() => onActivate(ctx)}\n >\n <Icon size={16} />\n </button>\n );\n })}\n </div>\n );\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/surface/composeRects.ts","../src/surface/deviceRect.ts","../src/surface/useTiledSurface.ts"],"names":[],"mappings":"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","file":"chunk-EESJUSYR.js","sourcesContent":["import type { Box, Rect } from './rect';\n\n/** Every tile's box expressed against the container's origin. */\nexport function composeRects(container: Box, tiles: ReadonlyMap<string, Box>): Map<string, Rect> {\n const out = new Map<string, Rect>();\n for (const [id, tile] of tiles) {\n out.set(id, {\n x: tile.left - container.left,\n y: tile.top - container.top,\n w: tile.width,\n h: tile.height,\n });\n }\n return out;\n}\n\nexport function rectsEqual(a: Rect | undefined, b: Rect): boolean {\n return a !== undefined && a.x === b.x && a.y === b.y && a.w === b.w && a.h === b.h;\n}\n","import type { Rect } from './rect';\n\n/**\n * A DOM rect as a GL viewport rect: origin at the bottom-left, every edge snapped\n * to the device-pixel grid. Still CSS pixels, because three.js applies its own\n * pixel ratio — snapping here is what stops a tile and its neighbour rounding\n * apart and leaving a hairline column between them.\n */\nexport function toDeviceRect(rect: Rect, surfaceHeight: number, dpr: number): Rect {\n const snap = (v: number) => Math.round(v * dpr) / dpr;\n const x = snap(rect.x);\n const y = snap(surfaceHeight - rect.y - rect.h);\n return {\n x,\n y,\n w: snap(rect.x + rect.w) - x,\n h: snap(surfaceHeight - rect.y) - y,\n };\n}\n","import { useLatest, useVisibleRaf } from '@weasel-js/core';\nimport { useCallback, useEffect, useMemo, useRef } from 'react';\nimport { composeRects, rectsEqual } from './composeRects';\nimport type { Box, Rect } from './rect';\n\n/** What a surface owner is handed once per animation frame. `rects` carries every\n * tile, not only the dirty ones: a scissored draw has to know where it is drawing\n * relative to a surface that may have resized under it.\n *\n * Its keys are what `useTileId` returns — `<trial>/<id>` for a tile registered\n * inside a trial — not the bare id the tile was named with. */\nexport interface SurfaceFrame {\n dirty: ReadonlySet<string>;\n rects: ReadonlyMap<string, Rect>;\n dpr: number;\n size: { width: number; height: number };\n /** The tile geometry changed this frame — a tile moved, resized, appeared or\n * went away, or the dpr did. Every tile is dirty on such a frame, but the\n * pixels a tile vacated are in no tile's scissor now, so the owner clears\n * the whole buffer. `<Lab>` does; a host owning its own surface must too. */\n retiled: boolean;\n}\n\n/** The invalidators and the two ref callbacks that publish geometry. */\nexport interface SurfaceHandle {\n /** Mark one tile for redraw. */\n invalidate: (id: string) => void;\n /** Mark every tile — what a resize or a tile-set change means. */\n invalidateAll: () => void;\n /** Re-measure before the next frame. The escape hatch for a host that knows it\n * moved something a ResizeObserver cannot see. */\n invalidateRects: () => void;\n registerTile: (id: string, el: HTMLElement | null) => void;\n /** Register a tenant's whole-buffer clear. Every one registered runs, before\n * any painter, on a frame where the tile geometry changed — the pixels a\n * tile vacated are in no scissor now, and only the context that drew them\n * can erase them. Backend-agnostic by necessity: labkit owns the canvas,\n * never the context. */\n registerClear: (id: string, clear: SurfaceClear) => () => void;\n /** Subscribe a tile to the frames it is dirty on. A tile paints on its own\n * loop, so this is how the surface wakes one: a resize of the shared buffer\n * clears every tile, not only the one that moved. */\n registerPainter: (id: string, paint: TilePainter) => () => void;\n containerRef: (el: HTMLElement | null) => void;\n /** The element tile rects are measured against, and so the one a tile's own\n * chrome positions itself inside. Null before the owner attaches it. */\n getContainer: () => HTMLElement | null;\n}\n\n/** What a tile's painter is handed: where it sits on the surface now, and the\n * frame that dirtied it. */\nexport type TilePainter = (rect: Rect, frame: SurfaceFrame) => void;\n\n/** Erase the whole shared buffer. Device pixels, because that is what a GL\n * viewport takes. */\nexport type SurfaceClear = (size: { width: number; height: number }, dpr: number) => void;\n\n/** Inputs to `useTiledSurface`. `onFrame` runs once per frame that has dirty\n * tiles, before any tile paints — the place to size the shared buffer. */\nexport interface UseTiledSurfaceOptions {\n onFrame: (frame: SurfaceFrame) => void;\n}\n\n/**\n * Share one drawing buffer among tiles laid out by the DOM. Tiles register\n * their elements; the hook measures them against the container, re-measures on\n * resize, and batches invalidations into one visible-only frame that calls\n * `onFrame`, then (on a retiled frame) the registered clears, then each dirty\n * tile's painter.\n */\nexport function useTiledSurface({ onFrame }: UseTiledSurfaceOptions): SurfaceHandle {\n const container = useRef<HTMLElement | null>(null);\n const tiles = useRef(new Map<string, HTMLElement>());\n const rects = useRef(new Map<string, Rect>());\n const dirty = useRef(new Set<string>());\n const painters = useRef(new Map<string, TilePainter>());\n const clears = useRef(new Map<string, SurfaceClear>());\n const needsMeasure = useRef(true);\n const observer = useRef<ResizeObserver | null>(null);\n const lastDpr = useRef(0);\n\n // Held in a ref so a caller passing an inline closure does not re-create every\n // callback below on each render.\n const onFrameRef = useLatest(onFrame);\n\n const measure = useCallback((): boolean => {\n const el = container.current;\n if (!el) return false;\n const boxes = new Map<string, Box>();\n for (const [id, tile] of tiles.current) boxes.set(id, tile.getBoundingClientRect());\n const next = composeRects(el.getBoundingClientRect(), boxes);\n let changed = next.size !== rects.current.size;\n for (const [id, rect] of next) {\n if (!rectsEqual(rects.current.get(id), rect)) changed = true;\n }\n rects.current = next;\n return changed;\n }, []);\n\n const frameLoop = useVisibleRaf(\n () => {\n const el = container.current;\n if (!el) {\n dirty.current.clear();\n return;\n }\n let retiled = false;\n if (needsMeasure.current) {\n needsMeasure.current = false;\n if (measure()) {\n retiled = true;\n for (const id of rects.current.keys()) dirty.current.add(id);\n // Geometry that changed may still be moving: a panel whose size has\n // settled while its position animates gives `ResizeObserver` nothing\n // more to report, and the tile would hold the frame it was caught\n // mid-flight at. Measure again next frame, and keep going until a\n // measurement finds nothing moved.\n needsMeasure.current = true;\n schedule();\n }\n }\n const dpr = globalThis.devicePixelRatio ?? 1;\n if (dpr !== lastDpr.current) {\n lastDpr.current = dpr;\n retiled = true;\n for (const id of rects.current.keys()) dirty.current.add(id);\n }\n if (dirty.current.size === 0) return;\n const box = el.getBoundingClientRect();\n const frame: SurfaceFrame = {\n dirty: new Set(dirty.current),\n rects: new Map(rects.current),\n dpr,\n size: { width: box.width, height: box.height },\n retiled,\n };\n // Cleared before the owner runs, not after the painters: sizing the\n // buffer blanks every tile, so the owner answers with `invalidateAll`,\n // and a set cleared at the end of the frame would swallow it.\n dirty.current.clear();\n onFrameRef.current(frame);\n // After the owner sized the buffer, before anything paints into it.\n if (retiled) {\n for (const clear of clears.current.values()) clear(frame.size, dpr);\n }\n // After the owner, which is what resized the buffer this frame — and\n // whatever it just dirtied paints now rather than a frame later.\n const painting = new Set(frame.dirty);\n for (const id of dirty.current) painting.add(id);\n dirty.current.clear();\n const paintFrame: SurfaceFrame = { ...frame, dirty: painting };\n for (const id of painting) {\n const rect = frame.rects.get(id);\n if (rect) painters.current.get(id)?.(rect, paintFrame);\n }\n },\n // The host attaches its container through `containerRef`, which may land\n // well after this hook's first effect; the gate re-resolves it per request.\n { target: () => container.current },\n );\n\n const schedule = useCallback(() => {\n frameLoop.request();\n }, [frameLoop]);\n\n const invalidate = useCallback(\n (id: string) => {\n dirty.current.add(id);\n schedule();\n },\n [schedule],\n );\n\n const invalidateAll = useCallback(() => {\n for (const id of tiles.current.keys()) dirty.current.add(id);\n schedule();\n }, [schedule]);\n\n const invalidateRects = useCallback(() => {\n needsMeasure.current = true;\n schedule();\n }, [schedule]);\n\n const registerTile = useCallback(\n (id: string, el: HTMLElement | null) => {\n const known = tiles.current.get(id);\n if (known === el) return;\n if (known) observer.current?.unobserve(known);\n if (el) {\n tiles.current.set(id, el);\n observer.current?.observe(el);\n } else {\n tiles.current.delete(id);\n rects.current.delete(id);\n dirty.current.delete(id);\n }\n needsMeasure.current = true;\n schedule();\n },\n [schedule],\n );\n\n const registerClear = useCallback((id: string, clear: SurfaceClear) => {\n clears.current.set(id, clear);\n return () => {\n if (clears.current.get(id) === clear) clears.current.delete(id);\n };\n }, []);\n\n const registerPainter = useCallback((id: string, paint: TilePainter) => {\n painters.current.set(id, paint);\n return () => {\n if (painters.current.get(id) === paint) painters.current.delete(id);\n };\n }, []);\n\n const getContainer = useCallback(() => container.current, []);\n\n const containerRef = useCallback(\n (el: HTMLElement | null) => {\n if (container.current === el) return;\n if (container.current) observer.current?.unobserve(container.current);\n container.current = el;\n if (el) observer.current?.observe(el);\n needsMeasure.current = true;\n schedule();\n },\n [schedule],\n );\n\n useEffect(() => {\n const ro = new ResizeObserver(() => {\n needsMeasure.current = true;\n schedule();\n });\n observer.current = ro;\n if (container.current) ro.observe(container.current);\n for (const el of tiles.current.values()) ro.observe(el);\n return () => {\n ro.disconnect();\n observer.current = null;\n frameLoop.cancel();\n };\n }, [schedule, frameLoop]);\n\n return useMemo(\n () => ({\n invalidate,\n invalidateAll,\n invalidateRects,\n registerTile,\n registerClear,\n registerPainter,\n containerRef,\n getContainer,\n }),\n [\n invalidate,\n invalidateAll,\n invalidateRects,\n registerTile,\n registerClear,\n registerPainter,\n containerRef,\n getContainer,\n ],\n );\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/controls/ControlMatrix.tsx"],"names":["auto","l","c","i","RACPopover","RACDialog","ae","h"],"mappings":"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","file":"chunk-HBGH344L.js","sourcesContent":["import { getAlpha01, isBuiltinToolPref, toHex8, withAlpha01 } from '@weasel-js/core';\nimport {\n Button,\n Focusable,\n isPrefLeaf,\n type PrefLeaf,\n type PropertyControlProps,\n PropertyHelp,\n PropertyList,\n PropertyPanel,\n prefFieldProps,\n type StanceProps,\n Tooltip,\n TooltipTrigger,\n useOverlayPortal,\n} from '@weasel-js/ui';\nimport {\n type CSSProperties,\n type DOMAttributes,\n type MouseEvent,\n type ReactElement,\n type ReactNode,\n useRef,\n useState,\n} from 'react';\nimport { Dialog as RACDialog, Popover as RACPopover } from 'react-aria-components';\nimport { auto as autoValue } from '../config/auto';\nimport { schemaNodeAtPath, valueAtPath } from '../config/path';\nimport type { ResolvedConfig } from '../config/types';\nimport { ControlRow } from './ControlPanel';\nimport { summarizeValue } from './inDialog';\n\n/** One column of a {@link ControlMatrix}: a config group, every one the same shape. */\nexport interface ControlMatrixColumn {\n /** Config path prefix of this column's group, e.g. `'looks.window'`. */\n key: string;\n /** Short header shown at narrow width, e.g. `'Win'`. */\n label: string;\n /** Full name, for the header's tooltip and accessible name, e.g. `'Window'`. */\n title?: string;\n}\n\n/** One row of a {@link ControlMatrix}: a setting every column's group may hold. */\nexport interface ControlMatrixRow {\n /** Path of the setting inside each column's group, e.g. `'background'` or `'fill.colorBy'`. */\n key: string;\n /** Row label. Defaults to the leaf's own name from the schema. */\n label?: string;\n}\n\nexport interface ControlMatrixProps extends StanceProps {\n /** Heads the matrix. With `title`, `stance` or `tone` given it sits in a\n * `<PropertyPanel>`, as a `ControlPanel` does. */\n title?: ReactNode;\n /** The whole resolved schema. A cell's leaf is looked up at\n * `${column.key}.${row.key}`; a cell with none draws a dash. */\n schema: ResolvedConfig;\n /** The scopes. The first is the fallback the others inherit from: its cells\n * never inherit, and its header is emphasized. */\n columns: readonly ControlMatrixColumn[];\n rows: readonly ControlMatrixRow[];\n /** Values to show, already resolved: an inherited cell's value is the one it\n * inherits. */\n config: Record<string, unknown>;\n /** Full dotted paths whose cells inherit, drawn ghosted. */\n auto: ReadonlySet<string>;\n /** Writes a value, which pins the cell, or labkit's `auto` sentinel, which\n * unpins it. */\n setConfig: (path: string, value: unknown) => void;\n /** Clicking a column header. Without it the headers are plain text. */\n onColumnClick?: (column: ControlMatrixColumn) => void;\n /** What an inherited cell's tooltip says. Defaults to `from <first column>`. */\n inheritHint?: (column: ControlMatrixColumn) => string;\n className?: string;\n}\n\nconst NO_AUTO: ReadonlySet<string> = new Set();\nconst noop = (): void => {};\n\nconst nameOf = (column: ControlMatrixColumn): string => column.title ?? column.label;\n\n/** The open popover: which cell, and the element it hangs off. */\ninterface OpenCell {\n path: string;\n leaf: PrefLeaf;\n column: ControlMatrixColumn;\n first: boolean;\n label: string;\n}\n\n/**\n * One setting across several config groups of the same shape: settings down\n * the side, scopes across the top, a compact read-only cell at each crossing.\n * A cell inherits from the first column until it is pinned; inherited cells\n * draw ghosted. Click a cell to edit it with the control a `ControlPanel` would\n * draw (a boolean flips and a color opens its picker in place); editing pins,\n * and the popover's Inherit button — or Option/Alt-click on the cell — unpins.\n */\nexport function ControlMatrix({\n title,\n stance,\n tone,\n schema,\n columns,\n rows,\n config,\n auto,\n setConfig,\n onColumnClick,\n inheritHint,\n className,\n}: ControlMatrixProps): ReactElement {\n const fallback = columns[0];\n const hintFor =\n inheritHint ?? ((_: ControlMatrixColumn) => (fallback ? `from ${nameOf(fallback)}` : ''));\n const [open, setOpen] = useState<OpenCell | null>(null);\n const triggerRef = useRef<HTMLElement | null>(null);\n const { anchor, portalProps } = useOverlayPortal();\n\n const leafAt = (path: string): PrefLeaf | undefined => {\n const node = schemaNodeAtPath(schema.group, path);\n return node && isPrefLeaf(node) ? node : undefined;\n };\n\n const rowSpecs = rows.map((row) => {\n const leaves = columns.map((column) => leafAt(`${column.key}.${row.key}`));\n const named = leaves.find((leaf) => leaf !== undefined);\n return { row, leaves, label: row.label ?? named?.name ?? row.key, about: named?.description };\n });\n\n const table = (\n <div className={className ? `lk-control-matrix ${className}` : 'lk-control-matrix'}>\n {anchor}\n <table className=\"lk-control-matrix__table\">\n <thead>\n <tr>\n <td className=\"lk-control-matrix__corner\" />\n {columns.map((column, i) => (\n <th\n key={column.key}\n scope=\"col\"\n className={i === 0 ? 'lk-control-matrix__head is-first' : 'lk-control-matrix__head'}\n >\n <ColumnHeader column={column} onClick={onColumnClick} />\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rowSpecs.map(({ row, leaves, label, about }) => (\n <tr key={row.key}>\n <th scope=\"row\" className=\"lk-control-matrix__label\">\n <span className=\"lk-control-matrix__label-text\">{label}</span>\n {about ? <PropertyHelp label={label} description={about} /> : null}\n </th>\n {columns.map((column, i) => {\n const path = `${column.key}.${row.key}`;\n const leaf = leaves[i];\n if (!leaf) {\n return (\n <td key={column.key} className=\"lk-control-matrix__cell is-missing\">\n <span role=\"img\" aria-label={`${nameOf(column)} has no ${label}`}>\n —\n </span>\n </td>\n );\n }\n const first = i === 0;\n const inherited = !first && auto.has(path);\n return (\n <td\n key={column.key}\n className={\n inherited ? 'lk-control-matrix__cell is-inherited' : 'lk-control-matrix__cell'\n }\n >\n <Cell\n path={path}\n leaf={leaf}\n value={valueAtPath(config, path)}\n name={`${nameOf(column)} ${label}`}\n hint={inherited ? hintFor(column) : undefined}\n canUnpin={!first && !inherited}\n setConfig={setConfig}\n onOpen={(el) => {\n triggerRef.current = el;\n setOpen({ path, leaf, column, first, label });\n }}\n />\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n <RACPopover\n triggerRef={triggerRef}\n isOpen={open !== null}\n onOpenChange={(next) => {\n if (!next) setOpen(null);\n }}\n placement=\"bottom\"\n className=\"lk-control-matrix__popover\"\n data-weasel-overlay=\"\"\n {...portalProps}\n >\n {open ? (\n <RACDialog\n className=\"lk-control-matrix__editor\"\n aria-label={`${nameOf(open.column)} ${open.label}`}\n >\n <PropertyList pack=\"one-up\">\n <ControlRow\n path={open.path}\n leaf={open.leaf}\n resolved={schema}\n config={config}\n shown={config}\n setConfig={setConfig}\n pack=\"one-up\"\n auto={NO_AUTO}\n setRowAuto={noop}\n />\n </PropertyList>\n {clearable(open.leaf) ? (\n <div className=\"lk-control-matrix__editor-actions\">\n <Button\n size=\"sm\"\n variant=\"ghost\"\n disabled={!valueAtPath(config, open.path) || auto.has(open.path)}\n onClick={() => setConfig(open.path, null)}\n >\n Clear\n </Button>\n </div>\n ) : null}\n {open.first ? null : (\n <div className=\"lk-control-matrix__editor-actions\">\n <Button\n size=\"sm\"\n variant=\"ghost\"\n disabled={auto.has(open.path)}\n tooltip={`Inherit ${hintFor(open.column)}`}\n onClick={() => setConfig(open.path, autoValue)}\n >\n Inherit\n </Button>\n </div>\n )}\n </RACDialog>\n ) : null}\n </RACPopover>\n </div>\n );\n\n if (title === undefined && stance === undefined && tone === undefined) return table;\n return (\n <PropertyPanel title={title} stance={stance} tone={tone}>\n {table}\n </PropertyPanel>\n );\n}\n\nfunction ColumnHeader({\n column,\n onClick,\n}: {\n column: ControlMatrixColumn;\n onClick?: (column: ControlMatrixColumn) => void;\n}) {\n const name = nameOf(column);\n if (!onClick) {\n return column.title && column.title !== column.label ? (\n <abbr title={column.title} className=\"lk-control-matrix__head-text\">\n {column.label}\n </abbr>\n ) : (\n <span className=\"lk-control-matrix__head-text\">{column.label}</span>\n );\n }\n return (\n <TooltipTrigger>\n <Focusable>\n <button\n type=\"button\"\n className=\"lk-control-matrix__head-button\"\n aria-label={name}\n onClick={() => onClick(column)}\n >\n {column.label}\n </button>\n </Focusable>\n <Tooltip>{name}</Tooltip>\n </TooltipTrigger>\n );\n}\n\n/** A color leaf whose default is empty: unset is a value of its own, not black. */\nconst clearable = (leaf: PrefLeaf): boolean => leaf.kind === 'color' && leaf.default === '';\n\n/** The number of decimals a step implies: `0.05` shows two, `1` none. */\nfunction decimalsOf(step: number | undefined): number {\n if (step === undefined || !Number.isFinite(step) || step <= 0) return 0;\n const text = String(step);\n const exp = /e-(\\d+)$/.exec(text);\n if (exp) return Number(exp[1]);\n const dot = text.indexOf('.');\n return dot === -1 ? 0 : text.length - dot - 1;\n}\n\n/** What a cell shows of a value it opens a popover to edit. */\nfunction summaryOf(field: PropertyControlProps | null, value: unknown): ReactNode {\n if (field?.kind === 'number') {\n return typeof field.value === 'number' ? field.value.toFixed(decimalsOf(field.step)) : '—';\n }\n if (field?.kind === 'enum') {\n const option = field.options.find((o) => o.value === field.value);\n if (!option) return '—';\n return typeof option.glyph === 'string' ? option.glyph : option.label;\n }\n if (field?.kind === 'string') return field.value || '—';\n return summarizeValue(value);\n}\n\nfunction Cell({\n path,\n leaf,\n value,\n name,\n hint,\n canUnpin,\n setConfig,\n onOpen,\n}: {\n path: string;\n leaf: PrefLeaf;\n value: unknown;\n /** The cell's accessible name: column and row. */\n name: string;\n /** Present while the cell inherits: where from. */\n hint?: string;\n canUnpin: boolean;\n setConfig: (path: string, value: unknown) => void;\n onOpen: (el: HTMLElement) => void;\n}) {\n const shown = value ?? leaf.default;\n const write = (next: unknown): void => setConfig(path, next);\n const field = isBuiltinToolPref(leaf)\n ? prefFieldProps(leaf, { value: shown, setValue: write })\n : null;\n const label = hint ? `${name}, ${hint}` : name;\n\n // Option/Alt-click hands a pinned cell back to the fallback, and does nothing\n // else on any cell — it must not also flip or open what it lands on.\n const unpinned = (e: MouseEvent): boolean => {\n if (!e.altKey) return false;\n e.preventDefault();\n if (canUnpin) setConfig(path, autoValue);\n return true;\n };\n\n // The shape `Focusable` asks of the element it makes a tooltip trigger.\n let control: ReactElement<DOMAttributes<HTMLElement>, string>;\n if (field?.kind === 'boolean') {\n const on = field.value === true;\n control = (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={on}\n aria-label={label}\n className=\"lk-control-matrix__switch\"\n onClick={(e) => {\n if (!unpinned(e)) field.onChange(!on);\n }}\n >\n <span className=\"lk-control-matrix__track\" aria-hidden=\"true\">\n <span className=\"lk-control-matrix__thumb\" />\n </span>\n </button>\n );\n } else if (field?.kind === 'color' && !clearable(leaf)) {\n const stored =\n typeof field.value === 'string' && field.value !== '' ? toHex8(field.value) : '#000000ff';\n control = (\n <input\n type=\"color\"\n aria-label={label}\n className=\"lk-control-matrix__swatch\"\n value={stored.slice(0, 7)}\n onClick={(e) => {\n unpinned(e);\n }}\n onChange={(e) => {\n const rgb = e.currentTarget.value;\n field.onChange(field.alpha ? withAlpha01(rgb, getAlpha01(stored)) : rgb);\n }}\n />\n );\n } else if (field?.kind === 'color') {\n // A color that may be unset opens the popover, which is the only place it can be cleared.\n const set = typeof field.value === 'string' && field.value !== '';\n control = (\n <button\n type=\"button\"\n aria-label={set ? label : `${label}, unset`}\n aria-haspopup=\"dialog\"\n className=\"lk-control-matrix__value\"\n onClick={(e) => {\n if (!unpinned(e)) onOpen(e.currentTarget);\n }}\n >\n <span\n className={set ? 'lk-control-matrix__chip' : 'lk-control-matrix__chip is-unset'}\n style={set ? ({ '--lk-chip': field.value } as CSSProperties) : undefined}\n aria-hidden=\"true\"\n />\n </button>\n );\n } else {\n const valueClass =\n field?.kind === 'number' ? 'lk-control-matrix__value is-number' : 'lk-control-matrix__value';\n control = (\n <button\n type=\"button\"\n aria-label={label}\n aria-haspopup=\"dialog\"\n className={valueClass}\n onClick={(e) => {\n if (!unpinned(e)) onOpen(e.currentTarget);\n }}\n >\n {summaryOf(field, shown)}\n </button>\n );\n }\n\n if (!hint) return control;\n return (\n <TooltipTrigger>\n <Focusable>{control}</Focusable>\n <Tooltip>{hint}</Tooltip>\n </TooltipTrigger>\n );\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/state/document.ts","../src/state/undock.ts","../src/instrument/serializers.ts","../src/state/store.ts","../src/state/openLabStore.ts","../src/state/useTrialState.ts"],"names":[],"mappings":"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","file":"chunk-IBVRMHW5.js","sourcesContent":["import { labStorageKey } from './helpers';\nimport type {\n LabDocument,\n LabMode,\n Migration,\n SavedSnapshot,\n SerializedTrial,\n StorageAdapter,\n} from './types';\nimport type { UndockedPanels } from './undock';\n\n/** Bumped whenever the persisted shape changes; every bump needs a migration. */\nexport const CURRENT_DOCUMENT_VERSION = 4;\n\n/** Where a version-3 lab kept its one document. Read once, to fold it into\n * records, then deleted. */\nexport function labDocumentKey(storageKey: string): string {\n return `lk:${storageKey}:doc`;\n}\n\n/** Where a document that failed to migrate is set aside, so a bad migration\n * loses state loudly rather than silently. */\nexport function quarantineKey(storageKey: string): string {\n return `lk:${storageKey}:quarantine`;\n}\n\n/** A fresh document at the current version. */\nexport function emptyDocument(mode: LabMode): LabDocument {\n return {\n version: CURRENT_DOCUMENT_VERSION,\n undockedPanels: {},\n trials: [],\n saves: [],\n layout: {},\n mode,\n };\n}\n\n/** What a migration run produced: the migrated document, or why it refused. */\nexport type MigrationOutcome =\n | { ok: true; doc: Record<string, unknown>; migrated: boolean }\n | { ok: false; reason: 'future' | 'failed'; error?: unknown };\n\n/** Walk a document forward to `target`, one migration at a time. A version\n * above `target` is refused rather than parsed under a shape it may not\n * have. */\nexport function runMigrations(\n raw: Record<string, unknown>,\n migrations: Migration[],\n target: number,\n): MigrationOutcome {\n const from = typeof raw.version === 'number' ? raw.version : 0;\n if (from > target) return { ok: false, reason: 'future' };\n if (from === target) return { ok: true, doc: raw, migrated: false };\n\n let doc = raw;\n try {\n for (let v = from; v < target; v++) {\n const migration = migrations[v];\n if (!migration) throw new Error(`[labkit] no migration from version ${v}`);\n doc = migration(doc);\n }\n } catch (error) {\n return { ok: false, reason: 'failed', error };\n }\n return { ok: true, doc, migrated: true };\n}\n\nconst LEGACY_BUCKETS = ['workspaces', 'saves', 'layout', 'theme'] as const;\n\n/** The four keys a lab used before it was one document. */\nexport function legacyKeys(storageKey: string): string[] {\n return LEGACY_BUCKETS.map((bucket) => labStorageKey(storageKey, bucket));\n}\n\n/** A value some substrate returned for an old key: already parsed, or a JSON\n * string from a store that does not parse. `undefined` when it is neither. */\nexport function parseStored(value: unknown): unknown {\n if (typeof value !== 'string') return value;\n try {\n return JSON.parse(value);\n } catch {\n return undefined;\n }\n}\n\nfunction bucketOr<T>(value: unknown, fallback: T, bucket: string, shape: 'array' | 'object'): T {\n if (value === undefined) return fallback;\n const parsed = parseStored(value);\n const fits = shape === 'array' ? Array.isArray(parsed) : !!parsed && typeof parsed === 'object';\n if (fits) return parsed as T;\n console.warn(`[labkit] unparseable legacy bucket \"${bucket}\", dropping it`);\n return fallback;\n}\n\n/** Assemble a version-0 document out of the four pre-document keys, or null\n * if none of them is present. `fallbackMode` is used when the theme key is\n * absent or holds something unrecognized; `interstellar` passes through\n * untouched for `migrateV0toV1` to coerce. */\nexport async function readLegacyDocument(\n read: (key: string) => Promise<unknown>,\n storageKey: string,\n fallbackMode: LabMode,\n): Promise<Record<string, unknown> | null> {\n const [workspaces, saves, layout, theme] = await Promise.all(\n LEGACY_BUCKETS.map((bucket) => read(labStorageKey(storageKey, bucket))),\n );\n if ([workspaces, saves, layout, theme].every((v) => v === undefined)) return null;\n\n const mode =\n theme === 'light' || theme === 'dark' || theme === 'auto' || theme === 'interstellar'\n ? theme\n : fallbackMode;\n\n return {\n version: 0,\n workspaces: bucketOr(workspaces, [], 'workspaces', 'array'),\n saves: bucketOr(saves, [], 'saves', 'array'),\n layout: bucketOr(layout, {}, 'layout', 'object'),\n mode,\n };\n}\n\n/** Whether two stored values hold the same data. Stored values are\n * structured-clone copies, so identity says nothing. */\nexport function sameStored(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n\n/** Delete `keys` and read each back, so an adapter whose delete silently did\n * nothing is caught. `true` only once all of them are gone. */\nexport async function deleteConfirmed(storage: StorageAdapter, keys: string[]): Promise<boolean> {\n try {\n await Promise.all(keys.map((key) => storage.delete(key)));\n const left = await Promise.all(keys.map((key) => storage.get(key)));\n return left.every((v) => v === undefined);\n } catch {\n return false;\n }\n}\n\n/** Set `value` aside under the quarantine key, reading it back to confirm it\n * landed. Returns `false` when it did not — a full disk is exactly when a\n * document goes unreadable — so the caller can leave the original alone\n * rather than overwrite the only copy of it. */\nexport async function quarantineDocument(\n storage: StorageAdapter,\n storageKey: string,\n value: unknown,\n): Promise<boolean> {\n try {\n await storage.set(quarantineKey(storageKey), value);\n return sameStored(await storage.get(quarantineKey(storageKey)), value);\n } catch {\n return false;\n }\n}\n\n/** Fill in whatever a document is missing or holds the wrong shape of, so a\n * hydrated store never sees `undefined` where a section should be. Applied to\n * every document, migrated or already current. */\nexport function normalizeDocument(\n doc: Record<string, unknown>,\n fallbackMode: LabMode,\n): LabDocument {\n const mode =\n doc.mode === 'light' || doc.mode === 'dark' || doc.mode === 'auto' ? doc.mode : fallbackMode;\n return {\n version: CURRENT_DOCUMENT_VERSION,\n trials: Array.isArray(doc.trials) ? (doc.trials as SerializedTrial[]) : [],\n saves: Array.isArray(doc.saves) ? (doc.saves as SavedSnapshot[]) : [],\n layout:\n doc.layout && typeof doc.layout === 'object' ? (doc.layout as Record<string, unknown>) : {},\n undockedPanels:\n doc.undockedPanels && typeof doc.undockedPanels === 'object'\n ? (doc.undockedPanels as UndockedPanels)\n : {},\n mode,\n };\n}\n\n/** Version 0 (four loose keys) to version 1 (one document). Normalizes the\n * mode, including `interstellar` — the dark mode's name back when it was a\n * theme. Coerces against version 1's own field names rather than reusing\n * `normalizeDocument`, which produces the current shape and would drop\n * `workspaces` from a document it labels version 1. */\nexport function migrateV0toV1(doc: Record<string, unknown>): Record<string, unknown> {\n const raw = doc.mode === 'interstellar' ? 'dark' : doc.mode;\n const mode = raw === 'light' || raw === 'dark' || raw === 'auto' ? raw : 'auto';\n return {\n version: 1,\n workspaces: Array.isArray(doc.workspaces) ? doc.workspaces : [],\n saves: Array.isArray(doc.saves) ? doc.saves : [],\n layout: doc.layout && typeof doc.layout === 'object' ? doc.layout : {},\n mode,\n };\n}\n\n/** Version 1 to version 2: the vocabulary refresh renamed a tile from\n * workspace to trial. Only the records field moves; a record's own fields are\n * unchanged. */\nexport function migrateV1toV2(doc: Record<string, unknown>): Record<string, unknown> {\n const { workspaces, ...rest } = doc;\n return { ...rest, trials: Array.isArray(workspaces) ? workspaces : [], version: 2 };\n}\n\n/** Version 2 to version 3: undocked sidebar panels became persisted state.\n * Nothing existing moves; the field simply starts empty. */\nexport function migrateV2toV3(doc: Record<string, unknown>): Record<string, unknown> {\n return { ...doc, undockedPanels: {}, version: 3 };\n}\n\n/** Version 3 to version 4: a lab is stored as records under one prefix\n * instead of one document. The joined shape does not change. */\nexport function migrateV3toV4(doc: Record<string, unknown>): Record<string, unknown> {\n return { ...doc, version: 4 };\n}\n\n/** Index `i` migrates a version-`i` document to version `i + 1`. */\nexport const MIGRATIONS: Migration[] = [migrateV0toV1, migrateV1toV2, migrateV2toV3, migrateV3toV4];\n","/** A sidebar section torn out of its trial, and where it went. */\nexport interface UndockedPanel {\n trialId: string;\n sectionId: string;\n as: 'tile' | 'floating';\n}\n\n/** Undocked panels, keyed by {@link panelKey}. */\nexport type UndockedPanels = Record<string, UndockedPanel>;\n\n/** The `UndockedPanels` key for one trial's section. */\nexport function panelKey(trialId: string, sectionId: string): string {\n return `${trialId}::${sectionId}`;\n}\n\n/** `panels` with the section marked undocked `as` a tile or a floating panel,\n * replacing any earlier entry for it. Returns a new record. */\nexport function undockPanel(\n panels: UndockedPanels,\n trialId: string,\n sectionId: string,\n as: UndockedPanel['as'] = 'tile',\n): UndockedPanels {\n return { ...panels, [panelKey(trialId, sectionId)]: { trialId, sectionId, as } };\n}\n\n/** Dock one section back, or — with no `sectionId` — every panel the trial\n * owns, which is what closing a trial wants. */\nexport function dockPanel(\n panels: UndockedPanels,\n trialId: string,\n sectionId?: string,\n): UndockedPanels {\n const out: UndockedPanels = {};\n for (const [key, panel] of Object.entries(panels)) {\n if (panel.trialId === trialId && (sectionId === undefined || panel.sectionId === sectionId)) {\n continue;\n }\n out[key] = panel;\n }\n return out;\n}\n","import { resolveConfigSchema } from '../config/resolve';\nimport type { ResolvedConfig } from '../config/types';\nimport type { InstrumentSerializers } from '../state/types';\nimport type { Instrument, InstrumentList } from './types';\n\n/**\n * One instrument's config schema, resolved without the lab's rules — which\n * neither the store nor a trial composed outside a lab has access to. No rule\n * can reach `autoResolve`, `unpinned` or `manual`, so for reading those the\n * two resolutions agree; anything reading the rendered leaves wants\n * `useConfigSchema` instead. `undefined` for a legacy `configSchema()`\n * instrument, which declares no auto annotations at all.\n */\nexport function unruledConfigSchema(\n // biome-ignore lint/suspicious/noExplicitAny: instruments are stored contravariantly; see InstrumentList\n instrument: Instrument<any, any, any>, // eslint-disable-line @typescript-eslint/no-explicit-any\n): ResolvedConfig | undefined {\n return instrument.config ? resolveConfigSchema(instrument.config, []) : undefined;\n}\n\n/** Each instrument's unruled config schema, keyed by name — what the store\n * reads a leaf's auto annotations off. */\nexport function configSchemasOf(instruments: InstrumentList): Record<string, ResolvedConfig> {\n const out: Record<string, ResolvedConfig> = {};\n for (const instrument of instruments) {\n const schema = unruledConfigSchema(instrument);\n if (schema) out[instrument.name] = schema;\n }\n return out;\n}\n\n/**\n * Each instrument's default config, keyed by name — what `createLabStore`\n * fills a stored config's gaps from, so one saved before its schema grew a\n * branch still loads.\n */\nexport function configDefaultsOf(instruments: InstrumentList): Record<string, () => unknown> {\n const out: Record<string, () => unknown> = {};\n for (const instrument of instruments) out[instrument.name] = () => instrument.defaultConfig();\n return out;\n}\n\n/** Each instrument's `migrateConfig`, keyed by name, for those that declare one. */\nexport function configMigrationsOf(\n instruments: InstrumentList,\n): Record<string, (stored: unknown) => unknown> {\n const out: Record<string, (stored: unknown) => unknown> = {};\n for (const { name, migrateConfig } of instruments) {\n if (migrateConfig) out[name] = (stored) => migrateConfig(stored);\n }\n return out;\n}\n\n/**\n * The `serialize` / `deserialize` an instrument list declares, keyed by\n * instrument name — what `createLabStore` needs to rebuild a trial's state\n * from storage.\n *\n * An instrument declaring neither gets no entry, which is what leaves a\n * JSON-safe state to pass through untouched.\n */\nexport function serializersOf(instruments: InstrumentList): InstrumentSerializers {\n const out: InstrumentSerializers = {};\n for (const instrument of instruments) {\n const { name, serialize, deserialize } = instrument;\n if (!serialize && !deserialize) continue;\n out[name] = {\n ...(serialize ? { serialize: (state: unknown) => serialize(state) } : {}),\n ...(deserialize\n ? { deserialize: (data: unknown, config: unknown) => deserialize(data, config) }\n : {}),\n };\n }\n return out;\n}\n","import { createStore, type StoreApi } from 'zustand/vanilla';\nimport { applyConfigWrite } from '../config/autoConfig';\nimport { fillConfigDefaults } from '../config/path';\nimport {\n configDefaultsOf,\n configMigrationsOf,\n configSchemasOf,\n serializersOf,\n} from '../instrument/serializers';\nimport type { InstrumentList } from '../instrument/types';\nimport { emptyDocument } from './document';\nimport { deserializeTrials, emptyUndoStack, newId } from './helpers';\nimport type {\n CreateLabStoreOptions,\n InstrumentHooks,\n InstrumentSerializers,\n LabMode,\n LabStoreState,\n SavedSnapshot,\n SerializedTrial,\n TrialRecord,\n} from './types';\nimport {\n dockPanel as dockPanelIn,\n type UndockedPanel,\n undockPanel as undockPanelIn,\n} from './undock';\n\n/** Every mutation a lab store supports: managing trials, saving and\n * restoring snapshots, and setting the color mode. */\nexport interface LabStoreActions {\n addTrial: (record: Omit<TrialRecord, 'undoStack'>) => void;\n removeTrial: (id: string) => void;\n updateTrialState: <TS>(id: string, next: TS | ((prev: TS) => TS)) => void;\n /** Write one config value. `path` is dotted for a value nested under an\n * `f.group`, and the bare key for one at the root. */\n updateTrialConfig: (id: string, path: string, value: unknown) => void;\n updateTrialView: (id: string, view: unknown) => void;\n updateTrialSidebarWidth: (id: string, width: number) => void;\n /** Retitle a trial. `null` returns it to its instrument's name. */\n setTrialTitle: (id: string, title: string | null) => void;\n /** Fold or unfold one of a trial's sections. */\n setTrialSectionCollapsed: (id: string, key: string, collapsed: boolean) => void;\n updateTrialAnnotations: (id: string, doc: unknown) => void;\n updateTrialUndoStack: (\n id: string,\n next: TrialRecord['undoStack'] | ((prev: TrialRecord['undoStack']) => TrialRecord['undoStack']),\n ) => void;\n setTrialInstrument: (id: string, instrumentName: string) => void;\n saveSnapshot: (trialId: string, name: string) => void;\n loadSnapshot: (snapshotId: string, trialId: string) => void;\n deleteSnapshot: (snapshotId: string) => void;\n listSnapshots: (trialId?: string) => SavedSnapshot[];\n setMode: (mode: LabMode) => void;\n setLabTool: (id: string | null) => void;\n setTrialTool: (trialId: string, id: string | null) => void;\n setLayout: (layout: Record<string, unknown>) => void;\n /** Tear a sidebar section out of its trial. Default target is a workspace tile. */\n undockPanel: (trialId: string, sectionId: string, as?: UndockedPanel['as']) => void;\n /** Put one section back, or — with no `sectionId` — every panel the trial owns. */\n dockPanel: (trialId: string, sectionId?: string) => void;\n /** Replace the lab's instruments. Trials and saves of an instrument that is\n * new or a different object are brought up to date against it in the same\n * write; every other trial keeps its object. */\n setInstruments: (instruments: InstrumentList) => void;\n /** The per-instrument hooks in force now. Read them at use; never keep them. */\n instrumentHooks: () => InstrumentHooks;\n}\n\n/** A lab's store: its state and its actions. How each instrument's state is\n * serialized comes in through `CreateLabStoreOptions.instruments`. */\nexport type LabStore = StoreApi<LabStoreState & LabStoreActions>;\n\n/** Build a lab store holding `initial`, or an empty lab. It knows nothing\n * about storage; `openLabStore` reads a stored lab and binds one of these to\n * it. */\nexport function createLabStore(options: CreateLabStoreOptions = {}): LabStore {\n let hooks: InstrumentHooks = options.instruments\n ? hooksOf(options.instruments)\n : {\n serializers: options.serializers ?? {},\n configDefaults: options.configDefaults ?? {},\n configMigrations: options.configMigrations ?? {},\n configSchemas: options.configSchemas ?? {},\n };\n const initial = options.initial ?? emptyDocument(options.initialMode ?? 'auto');\n\n const store = createStore<LabStoreState & LabStoreActions>()((set, get) => ({\n trials: hydrateTrials(initial.trials, hooks.serializers, hooks),\n savedSnapshots: hydrateSnapshots(initial.saves, hooks),\n mode: initial.mode,\n layout: initial.layout,\n undockedPanels: initial.undockedPanels,\n activeToolId: null,\n instruments: options.instruments ?? null,\n\n addTrial: (record) => {\n set((s) => ({\n trials: [...s.trials, { ...record, undoStack: emptyUndoStack() }],\n }));\n },\n\n removeTrial: (id) => {\n set((s) => ({\n trials: s.trials.filter((w) => w.id !== id),\n undockedPanels: dockPanelIn(s.undockedPanels, id),\n }));\n },\n\n updateTrialState: (id, next) => {\n set((s) => ({\n trials: s.trials.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 // An updater that returns its input means \"nothing changed\", and must not\n // cost a new record: the trial re-renders on record identity, so\n // allocating here turns the standard React bail-out into a render loop.\n if (Object.is(nextState, w.state)) return w;\n return { ...w, state: nextState };\n }),\n }));\n },\n\n updateTrialConfig: (id, path, value) => {\n set((s) => ({\n trials: s.trials.map((w) => {\n if (w.id !== id) return w;\n const was = w.auto ?? [];\n // The sentinel is never stored: it becomes membership in `auto`, and\n // the pinned value at the path is left exactly where it is.\n const next = applyConfigWrite(w.config, was, path, value);\n if (next.config === w.config && next.autoPaths === was) return w;\n const { auto: _was, ...kept } = w;\n const record: TrialRecord = { ...kept, config: next.config };\n if (next.autoPaths.length > 0) record.auto = next.autoPaths;\n return record;\n }),\n }));\n },\n\n updateTrialView: (id, view) => {\n set((s) => ({\n trials: s.trials.map((w) => (w.id === id && !Object.is(view, w.view) ? { ...w, view } : w)),\n }));\n },\n\n updateTrialSidebarWidth: (id, width) => {\n set((s) => ({\n trials: s.trials.map((w) =>\n w.id === id && w.sidebarWidth !== width ? { ...w, sidebarWidth: width } : w,\n ),\n }));\n },\n\n setTrialTitle: (id, title) => {\n set((s) => ({\n trials: s.trials.map((w) => {\n if (w.id !== id) return w;\n const next = title === null ? undefined : title;\n if ((w.title ?? undefined) === next) return w;\n return { ...w, title: next };\n }),\n }));\n },\n\n setTrialSectionCollapsed: (id, key, collapsed) => {\n set((s) => ({\n trials: s.trials.map((w) => {\n if (w.id !== id) return w;\n if (w.collapsedSections?.[key] === collapsed) return w;\n return { ...w, collapsedSections: { ...w.collapsedSections, [key]: collapsed } };\n }),\n }));\n },\n\n updateTrialAnnotations: (id, doc) => {\n set((s) => ({\n trials: s.trials.map((w) =>\n w.id === id && !Object.is(doc, w.annotations) ? { ...w, annotations: doc } : w,\n ),\n }));\n },\n\n updateTrialUndoStack: (id, next) => {\n set((s) => ({\n trials: s.trials.map((w) => {\n if (w.id !== id) return w;\n const undoStack =\n typeof next === 'function'\n ? (next as (prev: TrialRecord['undoStack']) => TrialRecord['undoStack'])(w.undoStack)\n : next;\n return { ...w, undoStack };\n }),\n }));\n },\n\n setTrialInstrument: (id, instrumentName) => {\n set((s) => ({\n trials: s.trials.map((w) => (w.id === id ? { ...w, instrumentName } : w)),\n }));\n },\n\n saveSnapshot: (trialId, name) => {\n const trial = get().trials.find((w) => w.id === trialId);\n if (!trial) return;\n const reg = hooks.serializers[trial.instrumentName];\n const serializedState = reg?.serialize\n ? reg.serialize(trial.state)\n : structuredClone(trial.state);\n const clonedConfig = structuredClone(trial.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: newId(),\n name,\n trialId,\n instrumentName: trial.instrumentName,\n config: clonedConfig,\n state: serializedState,\n auto: [...(trial.auto ?? [])],\n savedAt,\n };\n set((s) => ({ savedSnapshots: [...s.savedSnapshots, snapshot] }));\n },\n\n loadSnapshot: (snapshotId, trialId) => {\n const snapshot = get().savedSnapshots.find((sn) => sn.id === snapshotId);\n if (!snapshot) return;\n const trial = get().trials.find((w) => w.id === trialId);\n if (!trial) return;\n if (snapshot.instrumentName !== trial.instrumentName) {\n console.warn(\n `[labkit] loadSnapshot: instrument mismatch (snapshot=${snapshot.instrumentName}, trial=${trial.instrumentName}); refusing to load`,\n );\n return;\n }\n const reg = hooks.serializers[snapshot.instrumentName];\n const restoredState = reg?.deserialize\n ? reg.deserialize(snapshot.state, snapshot.config)\n : snapshot.state;\n set((s) => ({\n trials: s.trials.map((w) => {\n if (w.id !== trialId) return w;\n const loaded: TrialRecord = { ...w, state: restoredState, config: snapshot.config };\n if (snapshot.auto === undefined) return loaded;\n delete loaded.auto;\n if (snapshot.auto.length > 0) loaded.auto = [...snapshot.auto];\n return loaded;\n }),\n }));\n },\n\n deleteSnapshot: (snapshotId) => {\n set((s) => ({\n savedSnapshots: s.savedSnapshots.filter((sn) => sn.id !== snapshotId),\n }));\n },\n\n listSnapshots: (trialId) => {\n const all = get().savedSnapshots;\n const filtered = trialId ? all.filter((sn) => sn.trialId === trialId) : all;\n return [...filtered].sort((a, b) => b.savedAt - a.savedAt);\n },\n\n setMode: (mode) => {\n set({ mode });\n },\n\n setLabTool: (id) => set({ activeToolId: id }),\n\n setTrialTool: (trialId, id) =>\n set((s) => ({\n trials: s.trials.map((t) => (t.id === trialId ? { ...t, activeToolId: id } : t)),\n })),\n\n undockPanel: (trialId, sectionId, as) => {\n set((s) => ({ undockedPanels: undockPanelIn(s.undockedPanels, trialId, sectionId, as) }));\n },\n\n dockPanel: (trialId, sectionId) => {\n set((s) => ({ undockedPanels: dockPanelIn(s.undockedPanels, trialId, sectionId) }));\n },\n\n setLayout: (layout) => {\n set({ layout });\n },\n\n setInstruments: (instruments) => {\n const before = get().instruments;\n if (before === instruments) return;\n const next = mergedHooks(hooks, instruments);\n const previous = new Map((before ?? []).map((i) => [i.name, i]));\n const changed = new Set(\n instruments.filter((i) => previous.get(i.name) !== i).map((i) => i.name),\n );\n if (changed.size === 0) {\n hooks = next;\n set({ instruments });\n return;\n }\n const s = get();\n const trials = s.trials.map((w) =>\n changed.has(w.instrumentName)\n ? { ...w, config: hydratedConfig(next, w.instrumentName, w.config) }\n : w,\n );\n const savedSnapshots = s.savedSnapshots.map((sn) =>\n changed.has(sn.instrumentName)\n ? { ...sn, config: hydratedConfig(next, sn.instrumentName, sn.config) }\n : sn,\n );\n hooks = next;\n set({ instruments, trials, savedSnapshots });\n },\n\n instrumentHooks: () => hooks,\n }));\n\n return store;\n}\n\nfunction hooksOf(instruments: InstrumentList): InstrumentHooks {\n return {\n serializers: serializersOf(instruments),\n configDefaults: configDefaultsOf(instruments),\n configSchemas: configSchemasOf(instruments),\n configMigrations: configMigrationsOf(instruments),\n };\n}\n\n/** Hooks for `instruments`, keeping those of any instrument no longer listed:\n * its trials stay open, and their state still has to round-trip. A listed\n * name takes its hooks wholly from the new list. */\nfunction mergedHooks(old: InstrumentHooks, instruments: InstrumentList): InstrumentHooks {\n const listed = new Set(instruments.map((i) => i.name));\n const fresh = hooksOf(instruments);\n const unlisted = <T>(entries: Record<string, T>): Record<string, T> =>\n Object.fromEntries(Object.entries(entries).filter(([name]) => !listed.has(name)));\n return {\n serializers: { ...unlisted(old.serializers), ...fresh.serializers },\n configDefaults: { ...unlisted(old.configDefaults), ...fresh.configDefaults },\n configSchemas: { ...unlisted(old.configSchemas), ...fresh.configSchemas },\n configMigrations: { ...unlisted(old.configMigrations), ...fresh.configMigrations },\n };\n}\n\n/** How a stored config is brought up to date on the way in. */\nexport type ConfigHydration = Pick<CreateLabStoreOptions, 'configDefaults' | 'configMigrations'>;\n\nfunction hydratedConfig(\n hydration: ConfigHydration,\n instrumentName: string,\n config: unknown,\n): unknown {\n const migrate = hydration.configMigrations?.[instrumentName];\n const moved = migrate ? migrate(config) : config;\n const defaults = hydration.configDefaults?.[instrumentName];\n return defaults ? fillConfigDefaults(moved, defaults()) : moved;\n}\n\n/** Rebuild stored trials: migrate each config, fill its gaps from its\n * instrument's defaults, then run the deserializer against the result. */\nexport function hydrateTrials(\n trials: SerializedTrial[],\n serializers: InstrumentSerializers,\n hydration: ConfigHydration = {},\n): TrialRecord[] {\n return deserializeTrials(\n trials.map((t) => ({ ...t, config: hydratedConfig(hydration, t.instrumentName, t.config) })),\n serializers,\n );\n}\n\n/** Bring each stored snapshot's config up to date the way `hydrateTrials` does a trial's. */\nexport function hydrateSnapshots(\n saves: SavedSnapshot[],\n hydration: ConfigHydration = {},\n): SavedSnapshot[] {\n return saves.map((sn) => ({\n ...sn,\n config: hydratedConfig(hydration, sn.instrumentName, sn.config),\n }));\n}\n","import {\n CURRENT_DOCUMENT_VERSION,\n deleteConfirmed,\n emptyDocument,\n labDocumentKey,\n legacyKeys,\n MIGRATIONS,\n normalizeDocument,\n parseStored,\n quarantineDocument,\n readLegacyDocument,\n runMigrations,\n sameStored,\n} from './document';\nimport { serializeTrials } from './helpers';\nimport {\n compareTrialOrder,\n documentOfRecords,\n LAYOUT_RECORD,\n type LabMeta,\n labPrefix,\n META_RECORD,\n parseRecordName,\n recordsOfDocument,\n saveRecord,\n trialRecord,\n trialValuesPrefix,\n UNDOCK_RECORD,\n} from './labRecords';\nimport { type OwnedRecordCache, openRecords, type RecordCache } from './records';\nimport { createLabStore, hydrateSnapshots, hydrateTrials, type LabStore } from './store';\nimport type {\n CreateLabStoreOptions,\n LabDocument,\n LabMode,\n SavedSnapshot,\n SerializedTrial,\n StorageAdapter,\n TrialRecord,\n} from './types';\n\n/** Options for `openLabStore`. `storageKey` names the lab, so two labs on one\n * origin keep separate records. */\nexport interface OpenLabStoreOptions extends Omit<CreateLabStoreOptions, 'initial'> {\n storageKey: string;\n storage: StorageAdapter;\n}\n\n/** A lab store bound to its records. */\nexport interface OpenedLabStore {\n store: LabStore;\n /** Every record of the lab, `usePersistedState` values included. */\n records: RecordCache;\n /** Send queued writes and stop hearing other writers. */\n close(): Promise<void>;\n}\n\n/**\n * Read a stored lab and return a store bound to it: every change to the store\n * is written as the records it touched, and another writer's records are\n * applied back into the store. A lab stored before records existed is folded\n * forward on the way in.\n */\nexport async function openLabStore(options: OpenLabStoreOptions): Promise<OpenedLabStore> {\n const records = await openRecords({\n storage: options.storage,\n prefix: labPrefix(options.storageKey),\n });\n const { doc, orders } = await readLab(options, records);\n const store = createLabStore({ ...options, initial: doc });\n const unbind = bindLabStore(store, records, { orders });\n return {\n store,\n records,\n close: async () => {\n unbind();\n await records.close();\n },\n };\n}\n\ninterface ReadLab {\n doc: LabDocument;\n orders: Map<string, number>;\n}\n\nfunction emptyLab(mode: LabMode): ReadLab {\n return { doc: emptyDocument(mode), orders: new Map() };\n}\n\nfunction ordersOf(doc: LabDocument): Map<string, number> {\n return new Map(doc.trials.map((t, i) => [t.id, i]));\n}\n\nasync function readLab(options: OpenLabStoreOptions, records: OwnedRecordCache): Promise<ReadLab> {\n const mode = options.initialMode ?? 'auto';\n if (!records.writable) return emptyLab(mode);\n\n const joined = documentOfRecords(records.entries());\n if (!joined) return foldOldStorage(options, records);\n\n const outcome = runMigrations(joined.doc, MIGRATIONS, CURRENT_DOCUMENT_VERSION);\n if (outcome.ok) {\n return { doc: normalizeDocument(outcome.doc, mode), orders: joined.orders };\n }\n const why =\n outcome.reason === 'future' ? 'are from a newer version of labkit' : 'failed to migrate';\n console.warn(`[labkit] lab records ${why}; starting empty and leaving them alone`, outcome.error);\n records.stopWriting();\n return emptyLab(mode);\n}\n\n/** Fold a version-3 document, or the four keys before it, into records. The\n * old keys are deleted only once every record has been read back. */\nasync function foldOldStorage(\n options: OpenLabStoreOptions,\n records: OwnedRecordCache,\n): Promise<ReadLab> {\n const { storage, storageKey } = options;\n const mode = options.initialMode ?? 'auto';\n\n let raw: unknown;\n let oldKeys: string[];\n try {\n const stored = await storage.get(labDocumentKey(storageKey));\n if (stored !== undefined) {\n raw = stored;\n oldKeys = [labDocumentKey(storageKey)];\n } else {\n raw = await readLegacyDocument((key) => storage.get(key), storageKey, mode);\n oldKeys = legacyKeys(storageKey);\n if (raw === null) return emptyLab(mode);\n }\n } catch (error) {\n console.warn(\n `[labkit] could not read the old storage for \"${storageKey}\"; not persisting`,\n error,\n );\n records.stopWriting();\n return emptyLab(mode);\n }\n\n const setAside = async (value: unknown, why: string, error?: unknown): Promise<ReadLab> => {\n if (await quarantineDocument(storage, storageKey, value)) {\n console.warn(`[labkit] ${why}; quarantined it and starting empty`, error);\n await deleteConfirmed(storage, oldKeys);\n records.set(META_RECORD, { version: CURRENT_DOCUMENT_VERSION, mode } satisfies LabMeta);\n } else {\n console.warn(\n `[labkit] ${why} and could not be quarantined; leaving it in place and not persisting`,\n error,\n );\n records.stopWriting();\n }\n return emptyLab(mode);\n };\n\n const parsed = parseStored(raw);\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n return setAside(raw, 'lab document is unparseable');\n }\n const outcome = runMigrations(\n parsed as Record<string, unknown>,\n MIGRATIONS,\n CURRENT_DOCUMENT_VERSION,\n );\n if (!outcome.ok) {\n if (outcome.reason === 'future') {\n console.warn(\n '[labkit] lab document is from a newer version of labkit; starting empty and leaving it alone',\n );\n records.stopWriting();\n return emptyLab(mode);\n }\n return setAside(parsed, 'lab document failed to migrate', outcome.error);\n }\n\n const doc = normalizeDocument(outcome.doc, mode);\n const entries = recordsOfDocument(doc);\n records.seed(entries);\n if (await writeConfirmed(storage, records.prefix, entries)) {\n await deleteConfirmed(storage, oldKeys);\n } else {\n console.warn(\n `[labkit] keeping the old storage for \"${storageKey}\": could not confirm its records were written`,\n );\n }\n return { doc, orders: ordersOf(doc) };\n}\n\n/** Write `entries` in order and read every one back. */\nasync function writeConfirmed(\n storage: StorageAdapter,\n prefix: string,\n entries: [string, unknown][],\n): Promise<boolean> {\n try {\n for (const [name, value] of entries) await storage.set(prefix + name, value);\n const back = new Map(await storage.list(prefix));\n return entries.every(([name, value]) => sameStored(back.get(prefix + name), value));\n } catch {\n return false;\n }\n}\n\ninterface BindOptions {\n orders: Map<string, number>;\n}\n\nfunction persistedFieldsDiffer(a: TrialRecord, b: TrialRecord): boolean {\n if (a === b) return false;\n const left = a as unknown as Record<string, unknown>;\n const right = b as unknown as Record<string, unknown>;\n for (const key of new Set([...Object.keys(left), ...Object.keys(right)])) {\n if (key !== 'undoStack' && !Object.is(left[key], right[key])) return true;\n }\n return false;\n}\n\n/** Keep `store` and `records` in step, both ways. Returns the unbinding. */\nfunction bindLabStore(store: LabStore, records: RecordCache, options: BindOptions): () => void {\n const orderOf = new Map(options.orders);\n let applyingRemote = false;\n\n const nextOrder = (): number => {\n let max = -1;\n for (const order of orderOf.values()) max = Math.max(max, order);\n return max + 1;\n };\n\n const writeTrial = (trial: TrialRecord): void => {\n const [serialized] = serializeTrials([trial], store.getState().instrumentHooks().serializers);\n records.set(trialRecord(trial.id), { ...serialized, order: orderOf.get(trial.id) });\n };\n\n const inStoredOrder = (trials: TrialRecord[]): boolean => {\n for (let i = 1; i < trials.length; i++) {\n const a = trials[i - 1] as TrialRecord;\n const b = trials[i] as TrialRecord;\n const at = { trial: a, order: orderOf.get(a.id) ?? 0 };\n const bt = { trial: b, order: orderOf.get(b.id) ?? 0 };\n if (compareTrialOrder(at, bt) >= 0) return false;\n }\n return true;\n };\n\n const offStore = store.subscribe((state, prev) => {\n if (applyingRemote) return;\n let wrote = false;\n\n if (state.trials !== prev.trials) {\n const before = new Map(prev.trials.map((t) => [t.id, t]));\n const now = new Set(state.trials.map((t) => t.id));\n for (const t of prev.trials) {\n if (now.has(t.id)) continue;\n records.delete(trialRecord(t.id));\n for (const [name] of records.entries(trialValuesPrefix(t.id))) records.delete(name);\n orderOf.delete(t.id);\n wrote = true;\n }\n const added = state.trials.filter((t) => !before.has(t.id));\n for (const t of added) orderOf.set(t.id, nextOrder());\n if (inStoredOrder(state.trials)) {\n for (const t of state.trials) {\n const old = before.get(t.id);\n if (old && !persistedFieldsDiffer(old, t)) continue;\n writeTrial(t);\n wrote = true;\n }\n } else {\n // A reorder, or a trial inserted mid-list: renumber them all.\n for (const [i, t] of state.trials.entries()) orderOf.set(t.id, i);\n for (const t of state.trials) writeTrial(t);\n wrote = true;\n }\n }\n\n if (state.savedSnapshots !== prev.savedSnapshots) {\n const before = new Map(prev.savedSnapshots.map((s) => [s.id, s]));\n const now = new Set(state.savedSnapshots.map((s) => s.id));\n for (const s of state.savedSnapshots) {\n if (before.get(s.id) === s) continue;\n records.set(saveRecord(s.id), s);\n wrote = true;\n }\n for (const s of prev.savedSnapshots) {\n if (now.has(s.id)) continue;\n records.delete(saveRecord(s.id));\n wrote = true;\n }\n }\n\n if (state.layout !== prev.layout) {\n records.set(LAYOUT_RECORD, state.layout);\n wrote = true;\n }\n if (state.undockedPanels !== prev.undockedPanels) {\n records.set(UNDOCK_RECORD, state.undockedPanels);\n wrote = true;\n }\n if (state.mode !== prev.mode || (wrote && !records.has(META_RECORD))) {\n records.set(META_RECORD, {\n version: CURRENT_DOCUMENT_VERSION,\n mode: state.mode,\n } satisfies LabMeta);\n }\n });\n\n const offRecords = records.subscribe((changes) => {\n const remote = changes.filter((c) => c.origin === 'remote');\n if (remote.length === 0) return;\n\n const current = store.getState();\n let trials = current.trials;\n let saves = current.savedSnapshots;\n const patch: Partial<Pick<typeof current, 'layout' | 'undockedPanels' | 'mode'>> = {};\n\n for (const { name, value } of remote) {\n const parsed = parseRecordName(name);\n if (!parsed) continue;\n switch (parsed.kind) {\n case 'trial': {\n const id = parsed.id;\n if (value === undefined || !value || typeof value !== 'object') {\n trials = trials.filter((t) => t.id !== id);\n orderOf.delete(id);\n break;\n }\n const { order, ...rest } = value as SerializedTrial & { order?: unknown };\n orderOf.set(\n id,\n typeof order === 'number' && Number.isFinite(order) ? order : nextOrder(),\n );\n // Hydrating starts an empty undo history: the old one describes a\n // state that no longer exists.\n const hooks = store.getState().instrumentHooks();\n const [replacement] = hydrateTrials([{ ...rest, id }], hooks.serializers, hooks);\n if (!replacement) break;\n trials = trials.some((t) => t.id === id)\n ? trials.map((t) => (t.id === id ? replacement : t))\n : [...trials, replacement];\n break;\n }\n case 'save': {\n const id = parsed.id;\n if (value === undefined || !value || typeof value !== 'object') {\n saves = saves.filter((s) => s.id !== id);\n break;\n }\n const [snapshot] = hydrateSnapshots(\n [{ ...(value as SavedSnapshot), id }],\n store.getState().instrumentHooks(),\n );\n if (!snapshot) break;\n saves = saves.some((s) => s.id === id)\n ? saves.map((s) => (s.id === id ? snapshot : s))\n : [...saves, snapshot];\n break;\n }\n case 'layout':\n patch.layout = (value as Record<string, unknown> | undefined) ?? {};\n break;\n case 'undock':\n patch.undockedPanels = (value as typeof current.undockedPanels | undefined) ?? {};\n break;\n case 'meta': {\n const meta = value as Partial<LabMeta> | undefined;\n if (typeof meta?.version === 'number' && meta.version > CURRENT_DOCUMENT_VERSION) {\n console.warn(\n '[labkit] another tab wrote this lab with a newer labkit; no longer persisting',\n );\n if ('stopWriting' in records) (records as OwnedRecordCache).stopWriting();\n break;\n }\n if (meta?.mode === 'light' || meta?.mode === 'dark' || meta?.mode === 'auto') {\n patch.mode = meta.mode;\n }\n break;\n }\n }\n }\n\n if (trials !== current.trials) {\n trials = [...trials].sort((a, b) =>\n compareTrialOrder(\n { trial: a, order: orderOf.get(a.id) ?? 0 },\n { trial: b, order: orderOf.get(b.id) ?? 0 },\n ),\n );\n }\n applyingRemote = true;\n try {\n store.setState({ ...patch, trials, savedSnapshots: saves });\n } finally {\n applyingRemote = false;\n }\n });\n\n return () => {\n offStore();\n offRecords();\n };\n}\n","import { useContext } from 'react';\nimport { useStore } from 'zustand/react';\nimport { useResolvedConfig } from '../config/useResolvedConfig';\nimport { LabStoreContext, TrialIdContext } from './context';\nimport type { TrialStateHandle } from './types';\n\n/** An instrument's own state and config, plus setters. Reads the surrounding\n * trial id, so an instrument never has to know which trial it is\n * running in. Throws outside a lab store and trial. */\nexport function useTrialState<TS = unknown, TC = unknown>(): TrialStateHandle<TS, TC> {\n const ctx = useContext(LabStoreContext);\n if (!ctx) throw new Error('[labkit] useTrialState must be used inside <LabStoreProvider>');\n\n const trialId = useContext(TrialIdContext);\n if (!trialId) throw new Error('[labkit] useTrialState must be used inside <TrialIdProvider>');\n\n const record = useStore(ctx.store, (s) => s.trials.find((w) => w.id === trialId));\n\n if (!record) throw new Error(`[labkit] No trial found with id \"${trialId}\"`);\n\n const updateTrialState = useStore(ctx.store, (s) => s.updateTrialState);\n const updateTrialConfig = useStore(ctx.store, (s) => s.updateTrialConfig);\n // The store's own copy, not `useConfigSchema`: that reads `LabContext`, and\n // this hook only has the store's.\n const instrumentHooks = useStore(ctx.store, (s) => s.instrumentHooks);\n const schema = instrumentHooks().configSchemas[record.instrumentName];\n const { config, auto } = useResolvedConfig<TC>(schema, record.config as TC, record.auto);\n\n return {\n state: record.state as TS,\n config,\n raw: record.config as TC,\n auto,\n setState: (next) => updateTrialState(trialId, next as Parameters<typeof updateTrialState>[1]),\n setConfig: (path, value) => updateTrialConfig(trialId, path, value),\n };\n}\n"]}
|