@weasel-js/labkit 1.8.0 → 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-C0fzFsQg.d.ts → CanvasStackContext-B05ZM04l.d.ts} +3 -1
- package/dist/_dts/{Stage-Cvwxdnfp.d.ts → Stage-CIJlbjrE.d.ts} +5 -3
- package/dist/_dts/{index-DRaswz91.d.ts → index-8geQNQet.d.ts} +83 -11
- package/dist/_dts/{index-DEHRoTXK.d.ts → index-DRi3V5sN.d.ts} +5 -3
- package/dist/_dts/{useTrialState-CS4TdWPW.d.ts → useTrialState-Ar0AFpCe.d.ts} +94 -87
- package/dist/canvas/index.d.ts +4 -4
- package/dist/canvas/index.js +2 -2
- package/dist/chrome/index.d.ts +2 -2
- package/dist/chrome/index.js +7 -7
- package/dist/{chunk-YX75W6EK.js → chunk-4RCVWX4M.js} +8 -8
- 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-NVKBL7ZE.js → chunk-KHB3KRRQ.js} +7 -7
- package/dist/chunk-KHB3KRRQ.js.map +1 -0
- package/dist/{chunk-XXACAPVU.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-YDE6XATS.js → chunk-RN7T7OBO.js} +44 -22
- package/dist/chunk-RN7T7OBO.js.map +1 -0
- package/dist/{chunk-3L4MLLQB.js → chunk-RXO5UEGT.js} +4 -11
- package/dist/chunk-RXO5UEGT.js.map +1 -0
- package/dist/{chunk-MOTDMMMN.js → chunk-SQX35X5V.js} +3 -3
- package/dist/{chunk-MOTDMMMN.js.map → chunk-SQX35X5V.js.map} +1 -1
- package/dist/{chunk-J5HJJDLF.js → chunk-T5OEUNCB.js} +7 -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-WURZTJGQ.js → chunk-V4SMGEYY.js} +4858 -4806
- 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-7KAETQSS.js → chunk-YZA73U4A.js} +7 -7
- package/dist/chunk-YZA73U4A.js.map +1 -0
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.js +2 -2
- package/dist/controls/index.js +5 -5
- package/dist/dragdrop/index.d.ts +1 -1
- package/dist/dragdrop/index.js +2 -2
- package/dist/index.d.ts +157 -15
- package/dist/index.js +893 -258
- package/dist/index.js.map +1 -1
- package/dist/layers/index.d.ts +1 -1
- package/dist/layers/index.js +3 -3
- package/dist/loupe/index.d.ts +175 -27
- package/dist/loupe/index.js +547 -141
- package/dist/loupe/index.js.map +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 +5 -7
- package/dist/state/index.js +5 -5
- package/dist/styles.css +173 -38
- package/dist/surface/index.d.ts +20 -1
- package/dist/surface/index.js +2 -2
- package/dist/undo/index.d.ts +18 -7
- 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/resolve.test.ts +12 -0
- package/src/config/resolve.ts +5 -0
- package/src/controls/ControlMatrix.tsx +56 -54
- 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/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-3L4MLLQB.js.map +0 -1
- package/dist/chunk-7KAETQSS.js.map +0 -1
- package/dist/chunk-EESJUSYR.js.map +0 -1
- package/dist/chunk-J5HJJDLF.js.map +0 -1
- package/dist/chunk-NVKBL7ZE.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-WURZTJGQ.js.map +0 -1
- package/dist/chunk-XXACAPVU.js.map +0 -1
- package/dist/chunk-YDE6XATS.js.map +0 -1
- package/dist/chunk-YX75W6EK.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/dist/index.js
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
1
|
import { LoupeSwitchContext } from './chunk-2ES4W47N.js';
|
|
2
2
|
export { LoupeSwitchContext } from './chunk-2ES4W47N.js';
|
|
3
|
-
import { createEventBus
|
|
4
|
-
export { clearUndo, createEventBus, emptyStack, pushSnapshot, redo, undo } from './chunk-
|
|
5
|
-
import { useDragDrop, DragOverlay, Palette } from './chunk-
|
|
6
|
-
import { useTiledSurface } from './chunk-
|
|
7
|
-
export { composeRects, toDeviceRect, useTiledSurface } from './chunk-
|
|
3
|
+
import { createEventBus } from './chunk-UX66USTN.js';
|
|
4
|
+
export { clearUndo, createEventBus, emptyStack, pushSnapshot, redo, undo } from './chunk-UX66USTN.js';
|
|
5
|
+
import { useDragDrop, DragOverlay, Palette } from './chunk-J5MDJEOZ.js';
|
|
6
|
+
import { useTiledSurface } from './chunk-QMAY74TP.js';
|
|
7
|
+
export { composeRects, toDeviceRect, useTiledSurface } from './chunk-QMAY74TP.js';
|
|
8
8
|
import { useJob } from './chunk-EFXRM6XQ.js';
|
|
9
9
|
export { useJob } from './chunk-EFXRM6XQ.js';
|
|
10
|
-
import { markCommands, boundsOf, roundFrac, worldToFrac, fracToWorld, fracEncloses, fracContains, POINT_MARK_SHAPE, roundPoints, fromShape, markSvgNodes, toShape } from './chunk-
|
|
11
|
-
export { fracContains, fracEncloses, fracToWorld, markCommands, markSvgNodes, roundFrac, worldToFrac } from './chunk-
|
|
12
|
-
import { ANNOTATION_WEASEL_TOOLS, annotationToolInfo, suppressContributions, mergeContributions, builtinContributions, TRANSIENT_BUILTINS, TitleBarRegion, ToolbarRegion, PaletteRegion, ViewportRegion, SidebarRegion, StatusRegion, resolveLabTool, useLabChromeContext, labContributions, labAnnotationTools, LabHeaderRegion, LabFooterRegion, LabAsideRegion, LabSidebarRegion } from './chunk-
|
|
13
|
-
export { ANNOTATION_TOOLS, ANNOTATION_WEASEL_TOOLS, ExportMenu, LabAsideRegion, LabFooterRegion, LabHeaderRegion, LabSidebarRegion, MarkList, PaletteRegion, SidebarRegion, StatusRegion, TRANSIENT_BUILTINS, TitleBarRegion, ToolbarRegion, ViewportRegion, annotationToolInfo, builtinContributions, contributionsIn, labContributions, mergeContributions, suppressContributions, toolContributions, useLabChromeContext } from './chunk-
|
|
10
|
+
import { markCommands, boundsOf, roundFrac, worldToFrac, fracToWorld, fracEncloses, fracContains, POINT_MARK_SHAPE, roundPoints, fromShape, markSvgNodes, toShape } from './chunk-6Q6ACJ3H.js';
|
|
11
|
+
export { fracContains, fracEncloses, fracToWorld, markCommands, markSvgNodes, roundFrac, worldToFrac } from './chunk-6Q6ACJ3H.js';
|
|
12
|
+
import { ANNOTATION_WEASEL_TOOLS, annotationToolInfo, suppressContributions, mergeContributions, builtinContributions, TRANSIENT_BUILTINS, TitleBarRegion, ToolbarRegion, PaletteRegion, ViewportRegion, SidebarRegion, StatusRegion, resolveLabTool, useLabChromeContext, labContributions, labAnnotationTools, LabHeaderRegion, LabFooterRegion, LabAsideRegion, LabSidebarRegion } from './chunk-RN7T7OBO.js';
|
|
13
|
+
export { ANNOTATION_TOOLS, ANNOTATION_WEASEL_TOOLS, ExportMenu, LabAsideRegion, LabFooterRegion, LabHeaderRegion, LabSidebarRegion, MarkList, PaletteRegion, SidebarRegion, StatusRegion, TRANSIENT_BUILTINS, TitleBarRegion, ToolbarRegion, ViewportRegion, annotationToolInfo, builtinContributions, contributionsIn, labContributions, mergeContributions, suppressContributions, toolContributions, useLabChromeContext } from './chunk-RN7T7OBO.js';
|
|
14
14
|
import { AnnotationsContext } from './chunk-3RY6WL5T.js';
|
|
15
15
|
export { AnnotationsContext, useAnnotations, useAnnotationsOptional } from './chunk-3RY6WL5T.js';
|
|
16
|
-
import { Split, JobProgress, Legend } from './chunk-
|
|
17
|
-
export { JobProgress, Legend, Readout, Split } from './chunk-
|
|
18
|
-
import { FloatingPanel } from './chunk-
|
|
19
|
-
export { FloatingPanel } from './chunk-
|
|
20
|
-
import { Toolbar,
|
|
21
|
-
export { FpsMeter, ScaleIndicator,
|
|
16
|
+
import { Split, JobProgress, Legend } from './chunk-KHB3KRRQ.js';
|
|
17
|
+
export { JobProgress, Legend, Readout, Split } from './chunk-KHB3KRRQ.js';
|
|
18
|
+
import { FloatingPanel } from './chunk-7FMZT2WL.js';
|
|
19
|
+
export { FloatingPanel } from './chunk-7FMZT2WL.js';
|
|
20
|
+
import { Toolbar, ScaleIndicator, ZoomControl } from './chunk-RXO5UEGT.js';
|
|
21
|
+
export { FpsMeter, ScaleIndicator, Toolbar, ZoomControl } from './chunk-RXO5UEGT.js';
|
|
22
22
|
import './chunk-CZZPXUOU.js';
|
|
23
|
-
import { unruledConfigSchema, createLabStore, openLabStore, panelKey } from './chunk-
|
|
24
|
-
export { CURRENT_DOCUMENT_VERSION, dockPanel, labDocumentKey, openLabStore, panelKey, quarantineKey, undockPanel, useTrialState } from './chunk-
|
|
25
|
-
import { newId, useWarnIgnoredChange, useOpenOnce, PersistenceContext, createRecordCache, noneAdapter, defaultStorage, usePersistedState } from './chunk-
|
|
26
|
-
export { Persistence, createIndexedDbAdapter, createMemoryAdapter, indexedDbAdapter, localStorageAdapter, noneAdapter, sessionStorageAdapter, urlHashAdapter, usePersistedState } from './chunk-
|
|
27
|
-
export { ControlMatrix } from './chunk-
|
|
28
|
-
export { ControlPanel, inDialog, summarizeValue } from './chunk-
|
|
29
|
-
import { useConfigSchema } from './chunk-
|
|
30
|
-
export { sectionTree, useConfigSchema } from './chunk-
|
|
31
|
-
import {
|
|
23
|
+
import { unruledConfigSchema, createLabStore, openLabStore, panelKey } from './chunk-NHIO2O3O.js';
|
|
24
|
+
export { CURRENT_DOCUMENT_VERSION, dockPanel, labDocumentKey, openLabStore, panelKey, quarantineKey, undockPanel, useTrialState } from './chunk-NHIO2O3O.js';
|
|
25
|
+
import { valueRecord, newId, useWarnIgnoredChange, useOpenOnce, PersistenceContext, createRecordCache, noneAdapter, defaultStorage, usePersistedState } from './chunk-7ALJOVGP.js';
|
|
26
|
+
export { Persistence, createIndexedDbAdapter, createMemoryAdapter, indexedDbAdapter, localStorageAdapter, noneAdapter, sessionStorageAdapter, urlHashAdapter, usePersistedState } from './chunk-7ALJOVGP.js';
|
|
27
|
+
export { ControlMatrix } from './chunk-4RCVWX4M.js';
|
|
28
|
+
export { ControlPanel, inDialog, summarizeValue } from './chunk-YZA73U4A.js';
|
|
29
|
+
import { useConfigSchema } from './chunk-SQX35X5V.js';
|
|
30
|
+
export { sectionTree, useConfigSchema } from './chunk-SQX35X5V.js';
|
|
31
|
+
import { LabContext, useLabContext } from './chunk-Z76KEZAX.js';
|
|
32
32
|
export { LabContext, useLabContext } from './chunk-Z76KEZAX.js';
|
|
33
|
-
import { useResolvedConfig } from './chunk-
|
|
34
|
-
export { BaseNode, BooleanNode, ColorNode, CustomNode, EnumNode, GroupNode, ListNode, NumberNode, StringNode, ValueNode, applyRules, builtinRules, f, isConfigBranch, resolveConfigSchema, titleCase, useResolvedConfig } from './chunk-
|
|
33
|
+
import { useResolvedConfig } from './chunk-T5OEUNCB.js';
|
|
34
|
+
export { BaseNode, BooleanNode, ColorNode, CustomNode, EnumNode, GroupNode, ListNode, NumberNode, StringNode, ValueNode, applyRules, builtinRules, f, isConfigBranch, resolveConfigSchema, titleCase, useResolvedConfig } from './chunk-T5OEUNCB.js';
|
|
35
35
|
export { fromConfigFields, isLeafVisible } from './chunk-WLMDTI2Q.js';
|
|
36
36
|
import { hasConfigPath, schemaNodeAtPath, applyConfigWrite, resolveAutoConfig, isAuto, isRecord, autoPathsOf, fillConfigDefaults } from './chunk-READTDQX.js';
|
|
37
37
|
export { auto, autoPathsOf, fillConfigDefaults, hasConfigPath, isAuto, resolveAutoConfig, schemaNodeAtPath, valueAtPath, withValueAtPath } from './chunk-READTDQX.js';
|
|
38
|
-
import { CanvasStack, Stage, fitStage } from './chunk-
|
|
39
|
-
export { CanvasStack, Stage, fitStage } from './chunk-
|
|
38
|
+
import { CanvasStack, Stage, fitStage } from './chunk-XWR2P6MR.js';
|
|
39
|
+
export { CanvasStack, Stage, fitStage } from './chunk-XWR2P6MR.js';
|
|
40
40
|
export { centerOn, zoomAt } from './chunk-ROGJWDQA.js';
|
|
41
41
|
export { screenToWorld, worldToScreen } from './chunk-FG3EXZDV.js';
|
|
42
|
-
import { useSurfaceOptional, useSurfaceCanvas, useTileId, SurfaceContext, SurfaceCanvasContext } from './chunk-
|
|
43
|
-
export { SurfaceCanvasContext, SurfaceContext, useSurface, useSurfaceCanvas, useSurfaceOptional, useSurfaceTile, useTileId } from './chunk-
|
|
42
|
+
import { useSurfaceOptional, useSurfaceCanvas, useTileId, useTileInScope, SurfaceContext, SurfaceCanvasContext } from './chunk-6IIKLXBZ.js';
|
|
43
|
+
export { SurfaceCanvasContext, SurfaceContext, useSurface, useSurfaceCanvas, useSurfaceOptional, useSurfaceTile, useTileId, useTileInScope } from './chunk-6IIKLXBZ.js';
|
|
44
44
|
import { CameraWheelContext, as2DView, CameraRegistryContext, DEFAULT_VIEW, CameraPublishContext, createCameraRegistry, withZoom } from './chunk-VYVGVBGY.js';
|
|
45
45
|
export { CameraContext, CameraInput, CameraPublishContext, CameraRegistryContext, CameraScope, DEFAULT_VIEW, as2DView, createCameraRegistry, usePublishCamera } from './chunk-VYVGVBGY.js';
|
|
46
46
|
import { applyCamera } from './chunk-ULYYNWGP.js';
|
|
@@ -50,12 +50,12 @@ export { CanvasStackContext } from './chunk-ZQIHJXP4.js';
|
|
|
50
50
|
import { LabStoreContext, TrialIdProvider, TrialIdContext } from './chunk-2YILQ7Y5.js';
|
|
51
51
|
export { LabStoreContext, LabStoreProvider, TrialIdContext, TrialIdProvider, useLabStore, useTrialId } from './chunk-2YILQ7Y5.js';
|
|
52
52
|
import './chunk-2RVCB2PT.js';
|
|
53
|
-
import {
|
|
54
|
-
export { c as Button, V as CloseIcon,
|
|
55
|
-
import { serializeSvg } from './chunk-
|
|
56
|
-
import './chunk-
|
|
57
|
-
import { makeViewportZoomAction, createScene, asNodeId as asNodeId$1, registerNodeShape, useLatest, WeaselProvider, SceneCanvas, createPointerStore, PointerContextProvider, DepRegistryProvider, ActionsProvider, ActiveToolContextProvider, useActionsRegistry, useDepSource, ActionDisabledReason, useGestureDispatcher, sceneFromJSON, warmRender, renderSceneToPixels, useActiveToolContext } from '@weasel-js/core';
|
|
58
|
-
import { createContext, useState, useRef, useEffect, useInsertionEffect, useCallback, useContext,
|
|
53
|
+
import { A2, T, Z, U, V, de, G, p6, o3, c, Xt, c4, a5, l5, u3, s3, r3, a7, i3, o5, s5, c5, l8, p, f3, u2, y, O2, b4, l9, w2, c6, i4, h2, j, k2, ce2, le, ye, b3, j2, n6, a8, C3, l3, u, v3, d2, j3, r4, n7, r5, i5, p2, f2, n8, o4, p4, l7, w, L, n9, j4, xe, n2 } from './chunk-V4SMGEYY.js';
|
|
54
|
+
export { c as Button, V as CloseIcon, we as CollapseIcon, _ as CurveField, s as DetailList, c2 as DetailRow, Te as ExpandIcon, l as Icon, u2 as Input, l10 as Jog, A2 as LayerList, oe as PauseIcon, ae as PlayIcon, be as PropertyControl, ye as PropertyField, b3 as PropertyGroup, le as PropertyList, ce2 as PropertyPanel, L2 as PropertyRow, ue as PropertySpan, B as ResetIcon, O2 as Select, n7 as StatusBar, r5 as StatusBarItem, i5 as StatusBarSpacer, ce as StepBackIcon, $ as StepForwardIcon, se as StopIcon, x2 as Subpanel, s3 as ToggleBar, oe2 as TokenPanel, H2 as inferTokenType, T as moveLayers, O3 as refitScale } from './chunk-V4SMGEYY.js';
|
|
55
|
+
import { serializeSvg } from './chunk-VCK5T6EP.js';
|
|
56
|
+
import './chunk-AVOILDN2.js';
|
|
57
|
+
import { makeViewportZoomAction, createScene, asNodeId as asNodeId$1, registerNodeShape, useLatest, WeaselProvider, SceneCanvas, createPointerStore, PointerContextProvider, DepRegistryProvider, ActionsProvider, ActiveToolContextProvider, useActionsRegistry, useDepSource, ActionDisabledReason, useGestureDispatcher, sceneFromJSON, warmRender, renderSceneToPixels, useActiveToolContext, createHistory, useVisibleRaf, stableStringify } from '@weasel-js/core';
|
|
58
|
+
import { createContext, useState, useRef, useEffect, useInsertionEffect, useCallback, useContext, useSyncExternalStore, useReducer, useLayoutEffect, useMemo, useId, Children } from 'react';
|
|
59
59
|
import { flushSync, createPortal } from 'react-dom';
|
|
60
60
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
61
61
|
import { defineTheme, weaselTheme, colorCount, resolveTheme, colorAt } from '@weasel-js/theme';
|
|
@@ -668,6 +668,7 @@ function AnnotationOverlay({
|
|
|
668
668
|
const configRef = useLatest(config);
|
|
669
669
|
const id = target.id;
|
|
670
670
|
const tileId = useTileId(id);
|
|
671
|
+
const inScope = useTileInScope(tileId);
|
|
671
672
|
const lastTile = useRef(null);
|
|
672
673
|
useEffect(() => {
|
|
673
674
|
const el = target.ref.current ?? null;
|
|
@@ -758,6 +759,7 @@ function AnnotationOverlay({
|
|
|
758
759
|
className: "lk-annotate__input",
|
|
759
760
|
"data-annotation-target": id,
|
|
760
761
|
"data-idle": annotationToolInfo(activeToolId) ? void 0 : "",
|
|
762
|
+
hidden: !inScope,
|
|
761
763
|
role: "application",
|
|
762
764
|
"aria-label": `Annotations on ${id}`,
|
|
763
765
|
tabIndex: 0,
|
|
@@ -811,6 +813,62 @@ function AnnotationTargets({
|
|
|
811
813
|
t.id
|
|
812
814
|
)) });
|
|
813
815
|
}
|
|
816
|
+
function createClockRegistry() {
|
|
817
|
+
const handles = /* @__PURE__ */ new Map();
|
|
818
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
819
|
+
const notify = () => {
|
|
820
|
+
for (const l8 of [...listeners]) l8();
|
|
821
|
+
};
|
|
822
|
+
return {
|
|
823
|
+
register(trialId, handle) {
|
|
824
|
+
handles.set(trialId, handle);
|
|
825
|
+
notify();
|
|
826
|
+
return () => {
|
|
827
|
+
if (handles.get(trialId) !== handle) return;
|
|
828
|
+
handles.delete(trialId);
|
|
829
|
+
notify();
|
|
830
|
+
};
|
|
831
|
+
},
|
|
832
|
+
get: (trialId) => handles.get(trialId) ?? null,
|
|
833
|
+
all: () => handles.values(),
|
|
834
|
+
subscribe(listener) {
|
|
835
|
+
listeners.add(listener);
|
|
836
|
+
return () => {
|
|
837
|
+
listeners.delete(listener);
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
var ClockRegistryContext = createContext(null);
|
|
843
|
+
var TrialClockContext = createContext(null);
|
|
844
|
+
|
|
845
|
+
// src/clock/hooks.ts
|
|
846
|
+
var NO_SUBSCRIBE = () => () => {
|
|
847
|
+
};
|
|
848
|
+
function useTrialClock(trialId) {
|
|
849
|
+
const registry = useContext(ClockRegistryContext);
|
|
850
|
+
const own = useContext(TrialClockContext);
|
|
851
|
+
const lab = useContext(LabContext);
|
|
852
|
+
useSyncExternalStore(registry?.subscribe ?? NO_SUBSCRIBE, () => registry ? resolve() : own);
|
|
853
|
+
function resolve() {
|
|
854
|
+
if (trialId !== void 0) return registry?.get(trialId) ?? null;
|
|
855
|
+
if (own) return own;
|
|
856
|
+
const focused = lab?.focusedTrialId;
|
|
857
|
+
return focused ? registry?.get(focused) ?? null : null;
|
|
858
|
+
}
|
|
859
|
+
const clock = resolve()?.clock ?? null;
|
|
860
|
+
const [, bump] = useReducer((n6) => n6 + 1, 0);
|
|
861
|
+
useEffect(() => clock?.subscribe(bump), [clock]);
|
|
862
|
+
return clock;
|
|
863
|
+
}
|
|
864
|
+
function useClockFrame(fn) {
|
|
865
|
+
const handle = useContext(TrialClockContext);
|
|
866
|
+
const latest = useLatest(fn);
|
|
867
|
+
useEffect(
|
|
868
|
+
() => handle?.onFrame((elapsed, pass) => latest.current(elapsed, pass)),
|
|
869
|
+
[handle, latest]
|
|
870
|
+
);
|
|
871
|
+
}
|
|
814
872
|
|
|
815
873
|
// src/instrument/defineInstrument.ts
|
|
816
874
|
function defineInstrument(spec) {
|
|
@@ -870,6 +928,41 @@ function validateConfigSchema(fields) {
|
|
|
870
928
|
return { valid: errors.length === 0, errors };
|
|
871
929
|
}
|
|
872
930
|
var AnnotationPreloadContext = createContext(null);
|
|
931
|
+
function useClockLoop(registry) {
|
|
932
|
+
const loop = useVisibleRaf(
|
|
933
|
+
(timestamp) => {
|
|
934
|
+
let live = false;
|
|
935
|
+
for (const { clock } of registry.all()) {
|
|
936
|
+
if (clock.inert) continue;
|
|
937
|
+
clock.sync(timestamp);
|
|
938
|
+
if (!clock.inert) live = true;
|
|
939
|
+
}
|
|
940
|
+
if (live) loop.request();
|
|
941
|
+
},
|
|
942
|
+
{
|
|
943
|
+
onResume: () => {
|
|
944
|
+
for (const { clock } of registry.all()) clock.rebase();
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
);
|
|
948
|
+
useEffect(() => {
|
|
949
|
+
let unwakes = [];
|
|
950
|
+
const attach = () => {
|
|
951
|
+
for (const off2 of unwakes) off2();
|
|
952
|
+
unwakes = [];
|
|
953
|
+
for (const { clock } of registry.all()) {
|
|
954
|
+
unwakes.push(clock.onWake(() => loop.request()));
|
|
955
|
+
if (!clock.inert) loop.request();
|
|
956
|
+
}
|
|
957
|
+
};
|
|
958
|
+
attach();
|
|
959
|
+
const off = registry.subscribe(attach);
|
|
960
|
+
return () => {
|
|
961
|
+
off();
|
|
962
|
+
for (const unwake of unwakes) unwake();
|
|
963
|
+
};
|
|
964
|
+
}, [registry, loop]);
|
|
965
|
+
}
|
|
873
966
|
|
|
874
967
|
// src/theme/interstellar.theme.json
|
|
875
968
|
var interstellar_theme_default = {
|
|
@@ -996,6 +1089,180 @@ var interstellarTheme = defineTheme({
|
|
|
996
1089
|
extends: weaselTheme
|
|
997
1090
|
});
|
|
998
1091
|
|
|
1092
|
+
// src/clock/trialClock.ts
|
|
1093
|
+
var passesOf = (loop) => loop === true ? Number.POSITIVE_INFINITY : loop === false ? 1 : Math.max(1, loop);
|
|
1094
|
+
var checkRate = (rate, seekable) => {
|
|
1095
|
+
if (!Number.isFinite(rate)) throw new RangeError(`labkit: a clock's rate is finite, not ${rate}`);
|
|
1096
|
+
if (rate < 0 && !seekable)
|
|
1097
|
+
throw new RangeError("labkit: a clock that is not seekable cannot run backward");
|
|
1098
|
+
};
|
|
1099
|
+
function createTrialClock(spec, start) {
|
|
1100
|
+
const duration = spec.duration ?? Number.POSITIVE_INFINITY;
|
|
1101
|
+
const seekable = spec.seekable ?? true;
|
|
1102
|
+
const openRate = spec.rate ?? 0;
|
|
1103
|
+
checkRate(openRate, seekable);
|
|
1104
|
+
let loop = spec.loop ?? false;
|
|
1105
|
+
let span = duration * passesOf(loop);
|
|
1106
|
+
let rate = start ? start.rate : openRate;
|
|
1107
|
+
let elapsed = start ? Math.min(Math.max(0, start.elapsed), span) : 0;
|
|
1108
|
+
let ramp = null;
|
|
1109
|
+
let last = Number.NaN;
|
|
1110
|
+
let changed = false;
|
|
1111
|
+
let slept = false;
|
|
1112
|
+
let wakeFired = false;
|
|
1113
|
+
const wakes = /* @__PURE__ */ new Set();
|
|
1114
|
+
const subs = /* @__PURE__ */ new Set();
|
|
1115
|
+
const frames = /* @__PURE__ */ new Set();
|
|
1116
|
+
const isInert = () => rate === 0 && ramp === null && !changed;
|
|
1117
|
+
const notify = () => {
|
|
1118
|
+
for (const fn of [...subs]) fn();
|
|
1119
|
+
};
|
|
1120
|
+
const change = () => {
|
|
1121
|
+
changed = true;
|
|
1122
|
+
if (wakeFired) return;
|
|
1123
|
+
wakeFired = true;
|
|
1124
|
+
for (const fn of [...wakes]) fn();
|
|
1125
|
+
};
|
|
1126
|
+
const passAt = () => duration > 0 && Number.isFinite(duration) ? elapsed >= span ? passesOf(loop) - 1 : Math.floor(elapsed / duration) : 0;
|
|
1127
|
+
const phaseAt = () => duration > 0 && Number.isFinite(duration) ? elapsed >= span ? 1 : elapsed % duration / duration : 0;
|
|
1128
|
+
const advance = (dt) => {
|
|
1129
|
+
if (!ramp) return rate * dt;
|
|
1130
|
+
if (dt >= ramp.left) {
|
|
1131
|
+
const area2 = (rate + ramp.to) / 2 * ramp.left + ramp.to * (dt - ramp.left);
|
|
1132
|
+
rate = ramp.to;
|
|
1133
|
+
ramp = null;
|
|
1134
|
+
notify();
|
|
1135
|
+
return area2;
|
|
1136
|
+
}
|
|
1137
|
+
const next = rate + (ramp.to - rate) * dt / ramp.left;
|
|
1138
|
+
const area = (rate + next) / 2 * dt;
|
|
1139
|
+
rate = next;
|
|
1140
|
+
ramp.left -= dt;
|
|
1141
|
+
return area;
|
|
1142
|
+
};
|
|
1143
|
+
const clock = {
|
|
1144
|
+
get elapsed() {
|
|
1145
|
+
return elapsed;
|
|
1146
|
+
},
|
|
1147
|
+
get pass() {
|
|
1148
|
+
return passAt();
|
|
1149
|
+
},
|
|
1150
|
+
get phase() {
|
|
1151
|
+
return phaseAt();
|
|
1152
|
+
},
|
|
1153
|
+
get rate() {
|
|
1154
|
+
return rate;
|
|
1155
|
+
},
|
|
1156
|
+
set rate(next) {
|
|
1157
|
+
checkRate(next, seekable);
|
|
1158
|
+
rate = next;
|
|
1159
|
+
ramp = null;
|
|
1160
|
+
change();
|
|
1161
|
+
notify();
|
|
1162
|
+
},
|
|
1163
|
+
get loop() {
|
|
1164
|
+
return loop;
|
|
1165
|
+
},
|
|
1166
|
+
set loop(next) {
|
|
1167
|
+
loop = next;
|
|
1168
|
+
span = duration * passesOf(loop);
|
|
1169
|
+
elapsed = Math.min(elapsed, span);
|
|
1170
|
+
change();
|
|
1171
|
+
notify();
|
|
1172
|
+
},
|
|
1173
|
+
ramp(to, over) {
|
|
1174
|
+
checkRate(to, seekable);
|
|
1175
|
+
if (!(over > 0)) {
|
|
1176
|
+
clock.rate = to;
|
|
1177
|
+
return;
|
|
1178
|
+
}
|
|
1179
|
+
ramp = { to, left: over };
|
|
1180
|
+
change();
|
|
1181
|
+
notify();
|
|
1182
|
+
},
|
|
1183
|
+
seek(target) {
|
|
1184
|
+
if (!seekable) throw new Error("labkit: this clock is not seekable");
|
|
1185
|
+
elapsed = Math.min(Math.max(0, target), span);
|
|
1186
|
+
change();
|
|
1187
|
+
notify();
|
|
1188
|
+
},
|
|
1189
|
+
sync(timestamp) {
|
|
1190
|
+
const wasChanged = changed;
|
|
1191
|
+
const before = elapsed;
|
|
1192
|
+
if (!Number.isNaN(last) && !slept) {
|
|
1193
|
+
elapsed += advance(Math.max(0, timestamp - last));
|
|
1194
|
+
if (elapsed >= span && rate > 0) {
|
|
1195
|
+
elapsed = span;
|
|
1196
|
+
rate = 0;
|
|
1197
|
+
ramp = null;
|
|
1198
|
+
notify();
|
|
1199
|
+
} else if (elapsed <= 0 && rate < 0) {
|
|
1200
|
+
elapsed = 0;
|
|
1201
|
+
rate = 0;
|
|
1202
|
+
ramp = null;
|
|
1203
|
+
notify();
|
|
1204
|
+
}
|
|
1205
|
+
}
|
|
1206
|
+
last = timestamp;
|
|
1207
|
+
changed = false;
|
|
1208
|
+
wakeFired = false;
|
|
1209
|
+
slept = isInert();
|
|
1210
|
+
if (elapsed !== before || wasChanged) {
|
|
1211
|
+
const pass = passAt();
|
|
1212
|
+
for (const fn of [...frames]) fn(elapsed, pass);
|
|
1213
|
+
}
|
|
1214
|
+
},
|
|
1215
|
+
rebase() {
|
|
1216
|
+
last = Number.NaN;
|
|
1217
|
+
},
|
|
1218
|
+
get inert() {
|
|
1219
|
+
return isInert();
|
|
1220
|
+
},
|
|
1221
|
+
onWake(fn) {
|
|
1222
|
+
wakes.add(fn);
|
|
1223
|
+
return () => {
|
|
1224
|
+
wakes.delete(fn);
|
|
1225
|
+
};
|
|
1226
|
+
},
|
|
1227
|
+
subscribe(fn) {
|
|
1228
|
+
subs.add(fn);
|
|
1229
|
+
return () => {
|
|
1230
|
+
subs.delete(fn);
|
|
1231
|
+
};
|
|
1232
|
+
}
|
|
1233
|
+
};
|
|
1234
|
+
return {
|
|
1235
|
+
clock,
|
|
1236
|
+
reset() {
|
|
1237
|
+
elapsed = 0;
|
|
1238
|
+
rate = openRate;
|
|
1239
|
+
ramp = null;
|
|
1240
|
+
change();
|
|
1241
|
+
notify();
|
|
1242
|
+
},
|
|
1243
|
+
onFrame(fn) {
|
|
1244
|
+
frames.add(fn);
|
|
1245
|
+
return () => {
|
|
1246
|
+
frames.delete(fn);
|
|
1247
|
+
};
|
|
1248
|
+
}
|
|
1249
|
+
};
|
|
1250
|
+
}
|
|
1251
|
+
|
|
1252
|
+
// src/undo/stateOp.ts
|
|
1253
|
+
function stateOp(before, read, write) {
|
|
1254
|
+
let after;
|
|
1255
|
+
const forward = {
|
|
1256
|
+
label: "state",
|
|
1257
|
+
apply: () => write(structuredClone(after)),
|
|
1258
|
+
invert: () => {
|
|
1259
|
+
after = structuredClone(read());
|
|
1260
|
+
return { label: "state", apply: () => write(structuredClone(before)), invert: () => forward };
|
|
1261
|
+
}
|
|
1262
|
+
};
|
|
1263
|
+
return forward;
|
|
1264
|
+
}
|
|
1265
|
+
|
|
999
1266
|
// src/canvas/cameraZoom.ts
|
|
1000
1267
|
function atScale(view, scale, at) {
|
|
1001
1268
|
return {
|
|
@@ -1013,6 +1280,36 @@ function zoomCameraTo(camera, zoom) {
|
|
|
1013
1280
|
const scale = Math.min(max, Math.max(min, zoom));
|
|
1014
1281
|
camera.set(atScale(camera.get(), scale, viewMiddle(camera)));
|
|
1015
1282
|
}
|
|
1283
|
+
var PresentationContext = createContext(null);
|
|
1284
|
+
function usePresentation() {
|
|
1285
|
+
const value = useContext(PresentationContext);
|
|
1286
|
+
if (!value) throw new Error("[labkit] usePresentation() must be called inside <Lab>");
|
|
1287
|
+
return value;
|
|
1288
|
+
}
|
|
1289
|
+
function usePresentedTrial(trialId) {
|
|
1290
|
+
const presented = useContext(PresentationContext)?.trialId === trialId;
|
|
1291
|
+
const surface = useSurfaceOptional();
|
|
1292
|
+
const [el, ref] = useState(null);
|
|
1293
|
+
useLayoutEffect(() => {
|
|
1294
|
+
if (!presented || !el || !surface) return;
|
|
1295
|
+
surface.scope(el);
|
|
1296
|
+
return () => surface.scope(null);
|
|
1297
|
+
}, [presented, el, surface]);
|
|
1298
|
+
return { presented, ref };
|
|
1299
|
+
}
|
|
1300
|
+
function hasPresentParam() {
|
|
1301
|
+
return typeof location !== "undefined" && new URLSearchParams(location.search).has("present");
|
|
1302
|
+
}
|
|
1303
|
+
var LightboxContext = createContext(null);
|
|
1304
|
+
function useLightbox() {
|
|
1305
|
+
return useContext(LightboxContext);
|
|
1306
|
+
}
|
|
1307
|
+
function useLightboxControl() {
|
|
1308
|
+
const ctx = useContext(LightboxContext);
|
|
1309
|
+
const claim = ctx?.claimControl;
|
|
1310
|
+
useLayoutEffect(() => claim?.(), [claim]);
|
|
1311
|
+
return ctx;
|
|
1312
|
+
}
|
|
1016
1313
|
function TrialBody({ sidebar, children, contentClassName, ...rest }) {
|
|
1017
1314
|
return /* @__PURE__ */ jsx(
|
|
1018
1315
|
Split,
|
|
@@ -1131,6 +1428,7 @@ function TrialChrome({
|
|
|
1131
1428
|
children
|
|
1132
1429
|
}) {
|
|
1133
1430
|
const lab = useLabContext();
|
|
1431
|
+
const { presented, ref: presentedRef } = usePresentedTrial(trialId);
|
|
1134
1432
|
const storeCtx = useContext(LabStoreContext);
|
|
1135
1433
|
if (!storeCtx) throw new Error("[labkit] TrialChrome requires <LabStoreProvider>");
|
|
1136
1434
|
const updateTrialView = useStore(storeCtx.store, (s4) => s4.updateTrialView);
|
|
@@ -1160,6 +1458,7 @@ function TrialChrome({
|
|
|
1160
1458
|
cameras?.subscribe ?? noSubscribe,
|
|
1161
1459
|
() => cameras?.get(trialId) ?? null
|
|
1162
1460
|
);
|
|
1461
|
+
const lightbox = useLightboxControl();
|
|
1163
1462
|
const ctx = useMemo(() => {
|
|
1164
1463
|
const setZoom = (z) => {
|
|
1165
1464
|
if (camera) zoomCameraTo(camera, z);
|
|
@@ -1180,6 +1479,9 @@ function TrialChrome({
|
|
|
1180
1479
|
hasLoupe: loupe != null,
|
|
1181
1480
|
loupeOn: loupe?.on ?? false,
|
|
1182
1481
|
toggleLoupe: loupe?.toggle ?? NO_OP,
|
|
1482
|
+
canExpand: lightbox != null,
|
|
1483
|
+
expanded: lightbox?.expanded ?? false,
|
|
1484
|
+
toggleExpanded: lightbox?.toggle ?? NO_OP,
|
|
1183
1485
|
configSchema,
|
|
1184
1486
|
configFields: instrument.config ? [] : instrument.configSchema?.() ?? [],
|
|
1185
1487
|
config: record.config,
|
|
@@ -1225,6 +1527,7 @@ function TrialChrome({
|
|
|
1225
1527
|
updateTrialState,
|
|
1226
1528
|
undoBindings,
|
|
1227
1529
|
loupe,
|
|
1530
|
+
lightbox,
|
|
1228
1531
|
view2d,
|
|
1229
1532
|
activeToolId,
|
|
1230
1533
|
setActiveTool,
|
|
@@ -1255,7 +1558,7 @@ function TrialChrome({
|
|
|
1255
1558
|
const inRegion = (region) => contributions.filter((c6) => c6.region === region);
|
|
1256
1559
|
const handleKeyDown = (e) => {
|
|
1257
1560
|
const mod = e.metaKey || e.ctrlKey;
|
|
1258
|
-
if (!mod) return;
|
|
1561
|
+
if (!mod || presented) return;
|
|
1259
1562
|
if (e.key === "z" || e.key === "Z") {
|
|
1260
1563
|
e.preventDefault();
|
|
1261
1564
|
if (e.shiftKey) ctx.redo();
|
|
@@ -1268,9 +1571,11 @@ function TrialChrome({
|
|
|
1268
1571
|
return /* @__PURE__ */ jsxs(
|
|
1269
1572
|
"section",
|
|
1270
1573
|
{
|
|
1574
|
+
ref: presentedRef,
|
|
1271
1575
|
className: "lk-trial",
|
|
1272
1576
|
"data-trial-id": trialId,
|
|
1273
1577
|
"data-focused": lab.trials.length > 1 && lab.focusedTrialId === trialId ? "true" : void 0,
|
|
1578
|
+
"data-lk-presented": presented ? "" : void 0,
|
|
1274
1579
|
"aria-label": `Trial ${title}`,
|
|
1275
1580
|
tabIndex: -1,
|
|
1276
1581
|
onKeyDown: handleKeyDown,
|
|
@@ -1291,7 +1596,10 @@ function TrialChrome({
|
|
|
1291
1596
|
{
|
|
1292
1597
|
width: record.sidebarWidth,
|
|
1293
1598
|
onWidthChange: (w3) => updateTrialSidebarWidth(trialId, w3),
|
|
1294
|
-
contentClassName:
|
|
1599
|
+
contentClassName: [
|
|
1600
|
+
instrument.canvas || instrument.stage ? "lk-trial__content--flush" : "",
|
|
1601
|
+
presented ? "lk-trial__stage" : ""
|
|
1602
|
+
].filter(Boolean).join(" ") || void 0,
|
|
1295
1603
|
sidebar: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1296
1604
|
/* @__PURE__ */ jsx(SidebarRegion, { contributions: inRegion("sidebar"), ctx }),
|
|
1297
1605
|
/* @__PURE__ */ jsx(
|
|
@@ -1399,7 +1707,8 @@ function TrialRuntime({
|
|
|
1399
1707
|
const updateTrialState = useStore(store, (s4) => s4.updateTrialState);
|
|
1400
1708
|
const updateTrialConfig = useStore(store, (s4) => s4.updateTrialConfig);
|
|
1401
1709
|
const updateTrialView = useStore(store, (s4) => s4.updateTrialView);
|
|
1402
|
-
const
|
|
1710
|
+
const setTrialHistory = useStore(store, (s4) => s4.setTrialHistory);
|
|
1711
|
+
const updateTrialClock = useStore(store, (s4) => s4.updateTrialClock);
|
|
1403
1712
|
const updateTrialAnnotations = useStore(store, (s4) => s4.updateTrialAnnotations);
|
|
1404
1713
|
const labToolId = useStore(store, (s4) => s4.activeToolId);
|
|
1405
1714
|
const setLabTool = useStore(store, (s4) => s4.setLabTool);
|
|
@@ -1422,6 +1731,25 @@ function TrialRuntime({
|
|
|
1422
1731
|
() => (instrument.canvas?.layers ?? []).filter((l8) => layerVisibility[l8.id] !== false).map((l8) => l8.id),
|
|
1423
1732
|
[instrument.canvas, layerVisibility]
|
|
1424
1733
|
);
|
|
1734
|
+
const [clockHandle] = useState(
|
|
1735
|
+
() => instrument.clock ? createTrialClock(instrument.clock, record.clock) : null
|
|
1736
|
+
);
|
|
1737
|
+
const clocks = useContext(ClockRegistryContext);
|
|
1738
|
+
useEffect(() => {
|
|
1739
|
+
if (!clockHandle || !clocks) return;
|
|
1740
|
+
return clocks.register(record.id, clockHandle);
|
|
1741
|
+
}, [clocks, clockHandle, record.id]);
|
|
1742
|
+
useEffect(() => {
|
|
1743
|
+
if (!clockHandle) return;
|
|
1744
|
+
const { clock } = clockHandle;
|
|
1745
|
+
return clock.subscribe(
|
|
1746
|
+
() => updateTrialClock(record.id, { elapsed: clock.elapsed, rate: clock.rate })
|
|
1747
|
+
);
|
|
1748
|
+
}, [clockHandle, record.id, updateTrialClock]);
|
|
1749
|
+
const ticks = useMemo(
|
|
1750
|
+
() => clockHandle ? (fn) => clockHandle.onFrame(() => fn()) : void 0,
|
|
1751
|
+
[clockHandle]
|
|
1752
|
+
);
|
|
1425
1753
|
const undoCap = instrument.undo;
|
|
1426
1754
|
const undoEvents = useMemo(() => new Set(undoCap?.snapshotOn ?? ["state.change"]), [undoCap]);
|
|
1427
1755
|
const maxDepth = undoCap?.maxDepth ?? 50;
|
|
@@ -1429,8 +1757,14 @@ function TrialRuntime({
|
|
|
1429
1757
|
if (!undoCap || !undoEvents.has(event)) return;
|
|
1430
1758
|
const current = store.getState().trials.find((w3) => w3.id === record.id);
|
|
1431
1759
|
if (!current) return;
|
|
1432
|
-
|
|
1433
|
-
|
|
1760
|
+
let history = current.history;
|
|
1761
|
+
if (!history) {
|
|
1762
|
+
history = createHistory(null, { historyLimit: maxDepth });
|
|
1763
|
+
setTrialHistory(record.id, history);
|
|
1764
|
+
}
|
|
1765
|
+
const read = () => store.getState().trials.find((w3) => w3.id === record.id)?.state;
|
|
1766
|
+
const write = (state) => updateTrialState(record.id, state);
|
|
1767
|
+
history.recordEntry([stateOp(structuredClone(current.state), read, write)], event);
|
|
1434
1768
|
};
|
|
1435
1769
|
const setView = (v2) => updateTrialView(record.id, v2);
|
|
1436
1770
|
const stage = instrument.canvas ? void 0 : instrument.stage;
|
|
@@ -1559,7 +1893,8 @@ function TrialRuntime({
|
|
|
1559
1893
|
},
|
|
1560
1894
|
activeToolId: resolvedToolId,
|
|
1561
1895
|
visibleLayers,
|
|
1562
|
-
pointer
|
|
1896
|
+
pointer,
|
|
1897
|
+
...clockHandle ? { clock: clockHandle.clock } : {}
|
|
1563
1898
|
},
|
|
1564
1899
|
emit: (event) => {
|
|
1565
1900
|
snapshotIfNeeded(event);
|
|
@@ -1567,28 +1902,17 @@ function TrialRuntime({
|
|
|
1567
1902
|
},
|
|
1568
1903
|
job: jobCap ? job : void 0
|
|
1569
1904
|
};
|
|
1570
|
-
const
|
|
1571
|
-
const result = undo(record.undoStack, structuredClone(record.state));
|
|
1572
|
-
if (!result) return;
|
|
1573
|
-
updateTrialState(record.id, result.snapshot);
|
|
1574
|
-
updateTrialUndoStack(record.id, result.stack);
|
|
1575
|
-
};
|
|
1576
|
-
const redoState = () => {
|
|
1577
|
-
const result = redo(record.undoStack, structuredClone(record.state));
|
|
1578
|
-
if (!result) return;
|
|
1579
|
-
updateTrialState(record.id, result.snapshot);
|
|
1580
|
-
updateTrialUndoStack(record.id, result.stack);
|
|
1581
|
-
};
|
|
1905
|
+
const stateHistory = useHistoryVersion(record.history);
|
|
1582
1906
|
const undoBindings = undoCap || annotationsCap ? {
|
|
1583
|
-
canUndo: markMoves.undo || (undoCap ?
|
|
1584
|
-
canRedo: markMoves.redo || (undoCap ?
|
|
1907
|
+
canUndo: markMoves.undo || (undoCap ? stateHistory?.canUndo() ?? false : false),
|
|
1908
|
+
canRedo: markMoves.redo || (undoCap ? stateHistory?.canRedo() ?? false : false),
|
|
1585
1909
|
undo: () => {
|
|
1586
1910
|
if (annotationsCap && annotations.undo()) return;
|
|
1587
|
-
if (undoCap)
|
|
1911
|
+
if (undoCap) stateHistory?.undo();
|
|
1588
1912
|
},
|
|
1589
1913
|
redo: () => {
|
|
1590
1914
|
if (annotationsCap && annotations.redo()) return;
|
|
1591
|
-
if (undoCap)
|
|
1915
|
+
if (undoCap) stateHistory?.redo();
|
|
1592
1916
|
}
|
|
1593
1917
|
} : void 0;
|
|
1594
1918
|
const loupeBindings = lenses > 0 ? { on: loupeOn, toggle: () => setLoupeOn((v2) => !v2) } : void 0;
|
|
@@ -1596,15 +1920,24 @@ function TrialRuntime({
|
|
|
1596
1920
|
if (!instrument.canvas) return [];
|
|
1597
1921
|
const baseLayers = instrument.canvas.layers;
|
|
1598
1922
|
const ordered = layerOrder ? [...baseLayers].sort((a4, b3) => layerOrder.indexOf(a4.id) - layerOrder.indexOf(b3.id)) : baseLayers;
|
|
1923
|
+
const clock = clockHandle?.clock;
|
|
1599
1924
|
return ordered.map((layer) => ({
|
|
1600
1925
|
id: layer.id,
|
|
1601
1926
|
visible: layerVisibility[layer.id] !== false,
|
|
1927
|
+
timed: layer.timed === true,
|
|
1602
1928
|
render: (ctx, view, frame) => {
|
|
1603
1929
|
applyCamera(ctx, view, frame);
|
|
1604
|
-
layer.draw(ctx, {
|
|
1930
|
+
layer.draw(ctx, {
|
|
1931
|
+
state: record.state,
|
|
1932
|
+
config,
|
|
1933
|
+
zoom: view.zoom,
|
|
1934
|
+
elapsed: clock?.elapsed ?? 0,
|
|
1935
|
+
pass: clock?.pass ?? 0,
|
|
1936
|
+
phase: clock?.phase ?? 0
|
|
1937
|
+
});
|
|
1605
1938
|
}
|
|
1606
1939
|
}));
|
|
1607
|
-
}, [instrument.canvas, record.state, config, layerVisibility, layerOrder]);
|
|
1940
|
+
}, [instrument.canvas, record.state, config, layerVisibility, layerOrder, clockHandle]);
|
|
1608
1941
|
const layerDescriptors = useMemo(() => {
|
|
1609
1942
|
if (!instrument.layers) return [];
|
|
1610
1943
|
return instrument.layers.ids.map((l8) => typeof l8 === "string" ? { id: l8, label: l8 } : l8);
|
|
@@ -1680,6 +2013,7 @@ function TrialRuntime({
|
|
|
1680
2013
|
onResize: placeView,
|
|
1681
2014
|
minZoom: instrument.canvas.minZoom,
|
|
1682
2015
|
maxZoom: instrument.canvas.maxZoom,
|
|
2016
|
+
ticks,
|
|
1683
2017
|
children: instrument.render(renderCtx)
|
|
1684
2018
|
}
|
|
1685
2019
|
),
|
|
@@ -1709,11 +2043,11 @@ function TrialRuntime({
|
|
|
1709
2043
|
);
|
|
1710
2044
|
const layerListNode = useMemo(
|
|
1711
2045
|
() => instrument.layers && layerDescriptors.length > 0 ? /* @__PURE__ */ jsx(
|
|
1712
|
-
|
|
2046
|
+
A2,
|
|
1713
2047
|
{
|
|
1714
2048
|
items: layerItems,
|
|
1715
2049
|
onReorder: (move) => {
|
|
1716
|
-
setLayerOrder(
|
|
2050
|
+
setLayerOrder(T(layerItems, move).map((l8) => l8.id));
|
|
1717
2051
|
bus.emit("layers.reorder");
|
|
1718
2052
|
},
|
|
1719
2053
|
onVisibilityChange: (lid, visible) => {
|
|
@@ -1754,7 +2088,7 @@ function TrialRuntime({
|
|
|
1754
2088
|
}
|
|
1755
2089
|
) : null;
|
|
1756
2090
|
const scopedBody = /* @__PURE__ */ jsx(WeaselProvider, { isolate: true, children: /* @__PURE__ */ jsx(PointerContextProvider, { store: pointer, children: /* @__PURE__ */ jsx(CameraPublishContext.Provider, { value: publishCamera, children: /* @__PURE__ */ jsx(LoupeSwitchContext.Provider, { value: loupeSwitch, children: body }) }) }) });
|
|
1757
|
-
return /* @__PURE__ */ jsx(TrialIdProvider, { trialId: record.id, children: /* @__PURE__ */ jsx(AnnotationsContext.Provider, { value: annotationsCap ? provided : null, children: /* @__PURE__ */ jsx(CameraWheelContext.Provider, { value: wheelSlot, children: /* @__PURE__ */ jsxs(
|
|
2091
|
+
return /* @__PURE__ */ jsx(TrialIdProvider, { trialId: record.id, children: /* @__PURE__ */ jsx(TrialClockContext.Provider, { value: clockHandle, children: /* @__PURE__ */ jsx(AnnotationsContext.Provider, { value: annotationsCap ? provided : null, children: /* @__PURE__ */ jsx(CameraWheelContext.Provider, { value: wheelSlot, children: /* @__PURE__ */ jsxs(
|
|
1758
2092
|
TrialChrome,
|
|
1759
2093
|
{
|
|
1760
2094
|
job: jobCap ? job : void 0,
|
|
@@ -1774,7 +2108,13 @@ function TrialRuntime({
|
|
|
1774
2108
|
annotationOverlays
|
|
1775
2109
|
]
|
|
1776
2110
|
}
|
|
1777
|
-
) }) }) });
|
|
2111
|
+
) }) }) }) });
|
|
2112
|
+
}
|
|
2113
|
+
var NO_SUBSCRIBE2 = () => () => {
|
|
2114
|
+
};
|
|
2115
|
+
function useHistoryVersion(history) {
|
|
2116
|
+
useSyncExternalStore(history?.subscribe ?? NO_SUBSCRIBE2, () => history?.getVersion() ?? 0);
|
|
2117
|
+
return history;
|
|
1778
2118
|
}
|
|
1779
2119
|
|
|
1780
2120
|
// src/trial/trialOps.ts
|
|
@@ -1827,8 +2167,7 @@ function addTrial(trials, instruments, instrumentName, options = {}) {
|
|
|
1827
2167
|
instrumentName,
|
|
1828
2168
|
config,
|
|
1829
2169
|
state,
|
|
1830
|
-
view: initialView(instrument)
|
|
1831
|
-
undoStack: { past: [], future: [] }
|
|
2170
|
+
view: initialView(instrument)
|
|
1832
2171
|
};
|
|
1833
2172
|
if (options.config) record.configSeed = seeded.config;
|
|
1834
2173
|
if (seeded.autoPaths.length > 0) record.autoSeed = seeded.autoPaths;
|
|
@@ -1839,13 +2178,13 @@ function cloneTrial(trials, id) {
|
|
|
1839
2178
|
const sourceIdx = trials.findIndex((w3) => w3.id === id);
|
|
1840
2179
|
const source = trials[sourceIdx];
|
|
1841
2180
|
if (!source) return trials;
|
|
2181
|
+
const { history: _history, ...rest } = source;
|
|
1842
2182
|
const clone = {
|
|
1843
|
-
...
|
|
2183
|
+
...rest,
|
|
1844
2184
|
id: newId(),
|
|
1845
2185
|
config: structuredClone(source.config),
|
|
1846
2186
|
state: structuredClone(source.state),
|
|
1847
|
-
view: structuredClone(source.view)
|
|
1848
|
-
undoStack: { past: [], future: [] }
|
|
2187
|
+
view: structuredClone(source.view)
|
|
1849
2188
|
};
|
|
1850
2189
|
return [...trials.slice(0, sourceIdx + 1), clone, ...trials.slice(sourceIdx + 1)];
|
|
1851
2190
|
}
|
|
@@ -2112,6 +2451,91 @@ function LabShell({
|
|
|
2112
2451
|
footer && /* @__PURE__ */ jsx("footer", { className: "lk-shell-footer", children: footer })
|
|
2113
2452
|
] });
|
|
2114
2453
|
}
|
|
2454
|
+
var NONE = { below: [], above: [] };
|
|
2455
|
+
var LightboxLayersContext = createContext(NONE);
|
|
2456
|
+
function LightboxLayers({ below, above, children }) {
|
|
2457
|
+
const value = useMemo(
|
|
2458
|
+
() => ({ below: below ?? NONE.below, above: above ?? NONE.above }),
|
|
2459
|
+
[below, above]
|
|
2460
|
+
);
|
|
2461
|
+
return /* @__PURE__ */ jsx(LightboxLayersContext.Provider, { value, children });
|
|
2462
|
+
}
|
|
2463
|
+
function useLightboxLayers() {
|
|
2464
|
+
return useContext(LightboxLayersContext);
|
|
2465
|
+
}
|
|
2466
|
+
function LabSurface({ bodyRef, children }) {
|
|
2467
|
+
const outerSurface = useSurfaceOptional();
|
|
2468
|
+
const outerOver = useSurfaceCanvas("over");
|
|
2469
|
+
const outerUnder = useSurfaceCanvas("under");
|
|
2470
|
+
const [ownOver, setOwnOver] = useState(null);
|
|
2471
|
+
const [ownUnder, setOwnUnder] = useState(null);
|
|
2472
|
+
const [underLayer, setUnderLayer] = useState(null);
|
|
2473
|
+
const [overLayer, setOverLayer] = useState(null);
|
|
2474
|
+
const ownOverRef = useRef(null);
|
|
2475
|
+
const ownUnderRef = useRef(null);
|
|
2476
|
+
const bufferRef = useRef({ w: 0, h: 0 });
|
|
2477
|
+
const surfaceRef = useRef(null);
|
|
2478
|
+
const onFrame = useCallback((frame) => {
|
|
2479
|
+
const canvases2 = [ownUnderRef.current, ownOverRef.current].filter((c6) => c6 !== null);
|
|
2480
|
+
if (canvases2.length === 0) return;
|
|
2481
|
+
const w3 = Math.round(frame.size.width * frame.dpr);
|
|
2482
|
+
const h2 = Math.round(frame.size.height * frame.dpr);
|
|
2483
|
+
if (bufferRef.current.w !== w3 || bufferRef.current.h !== h2) {
|
|
2484
|
+
bufferRef.current = { w: w3, h: h2 };
|
|
2485
|
+
for (const c6 of canvases2) {
|
|
2486
|
+
c6.width = w3;
|
|
2487
|
+
c6.height = h2;
|
|
2488
|
+
c6.style.width = `${frame.size.width}px`;
|
|
2489
|
+
c6.style.height = `${frame.size.height}px`;
|
|
2490
|
+
}
|
|
2491
|
+
surfaceRef.current?.invalidateAll();
|
|
2492
|
+
return;
|
|
2493
|
+
}
|
|
2494
|
+
}, []);
|
|
2495
|
+
const ownSurface = useTiledSurface({ onFrame });
|
|
2496
|
+
useInsertionEffect(() => {
|
|
2497
|
+
surfaceRef.current = ownSurface;
|
|
2498
|
+
}, [ownSurface]);
|
|
2499
|
+
const attachOwnSurface = ownSurface.containerRef;
|
|
2500
|
+
const overLayerRef = useCallback(
|
|
2501
|
+
(el) => {
|
|
2502
|
+
setOverLayer(el);
|
|
2503
|
+
attachOwnSurface(el);
|
|
2504
|
+
},
|
|
2505
|
+
[attachOwnSurface]
|
|
2506
|
+
);
|
|
2507
|
+
const surface = outerSurface ?? ownSurface;
|
|
2508
|
+
const canvases = useMemo(
|
|
2509
|
+
() => outerSurface ? { over: outerOver, under: outerUnder } : { over: ownOver, under: ownUnder },
|
|
2510
|
+
[outerSurface, outerOver, outerUnder, ownOver, ownUnder]
|
|
2511
|
+
);
|
|
2512
|
+
const below = useMemo(() => [underLayer], [underLayer]);
|
|
2513
|
+
const above = useMemo(() => [overLayer], [overLayer]);
|
|
2514
|
+
const body = /* @__PURE__ */ jsxs("div", { className: "lk-lab__body", ref: bodyRef, children: [
|
|
2515
|
+
outerSurface ? null : /* @__PURE__ */ jsx("div", { className: "lk-lab__layer lk-lab__layer--under", ref: setUnderLayer, children: /* @__PURE__ */ jsx(
|
|
2516
|
+
"canvas",
|
|
2517
|
+
{
|
|
2518
|
+
className: "lk-lab__surface",
|
|
2519
|
+
ref: (el) => {
|
|
2520
|
+
ownUnderRef.current = el;
|
|
2521
|
+
setOwnUnder(el);
|
|
2522
|
+
}
|
|
2523
|
+
}
|
|
2524
|
+
) }),
|
|
2525
|
+
children,
|
|
2526
|
+
outerSurface ? null : /* @__PURE__ */ jsx("div", { className: "lk-lab__layer lk-lab__layer--over", ref: overLayerRef, children: /* @__PURE__ */ jsx(
|
|
2527
|
+
"canvas",
|
|
2528
|
+
{
|
|
2529
|
+
className: "lk-lab__surface",
|
|
2530
|
+
ref: (el) => {
|
|
2531
|
+
ownOverRef.current = el;
|
|
2532
|
+
setOwnOver(el);
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
) })
|
|
2536
|
+
] });
|
|
2537
|
+
return /* @__PURE__ */ jsx(SurfaceContext.Provider, { value: surface, children: /* @__PURE__ */ jsx(SurfaceCanvasContext.Provider, { value: canvases, children: /* @__PURE__ */ jsx(LightboxLayers, { below, above, children: body }) }) });
|
|
2538
|
+
}
|
|
2115
2539
|
var ZOOM_ID = "viewport.zoom";
|
|
2116
2540
|
var NO_TOOLS = /* @__PURE__ */ new Map();
|
|
2117
2541
|
var CHANNELS = { contextMenu: false, ingest: false };
|
|
@@ -2187,7 +2611,7 @@ function LabZoomControls() {
|
|
|
2187
2611
|
title: hint("Zoom out", "out"),
|
|
2188
2612
|
disabled: !canOut,
|
|
2189
2613
|
onClick: run("out"),
|
|
2190
|
-
children: /* @__PURE__ */ jsx(
|
|
2614
|
+
children: /* @__PURE__ */ jsx(Z, { size: 16 })
|
|
2191
2615
|
}
|
|
2192
2616
|
),
|
|
2193
2617
|
/* @__PURE__ */ jsx(
|
|
@@ -2215,6 +2639,311 @@ function LabZoomControls() {
|
|
|
2215
2639
|
}
|
|
2216
2640
|
var noSubscribe2 = () => () => {
|
|
2217
2641
|
};
|
|
2642
|
+
var NEBULA_SLOTS = [
|
|
2643
|
+
{ cx: "18%", cy: "30%", sx: "60%", sy: "80%", stop: "70%" },
|
|
2644
|
+
{ cx: "78%", cy: "70%", sx: "55%", sy: "90%", stop: "65%" },
|
|
2645
|
+
{ cx: "50%", cy: "50%", sx: "50%", sy: "70%", stop: "75%" },
|
|
2646
|
+
{ cx: "12%", cy: "82%", sx: "50%", sy: "70%", stop: "70%" },
|
|
2647
|
+
{ cx: "85%", cy: "18%", sx: "55%", sy: "80%", stop: "70%" }
|
|
2648
|
+
];
|
|
2649
|
+
function buildNebula(list, theme, mode, density) {
|
|
2650
|
+
const ctx = { theme, resolved: resolveTheme(theme, { mode, density }) };
|
|
2651
|
+
const n6 = colorCount(list, ctx) ?? NEBULA_SLOTS.length;
|
|
2652
|
+
const colors = Array.from({ length: n6 }, (_2, i4) => colorAt(list, i4, ctx));
|
|
2653
|
+
const blobs = colors.map((c6, i4) => {
|
|
2654
|
+
const p5 = NEBULA_SLOTS[i4 % NEBULA_SLOTS.length];
|
|
2655
|
+
return `radial-gradient(ellipse ${p5.sx} ${p5.sy} at ${p5.cx} ${p5.cy}, color-mix(in srgb, ${c6} 22%, transparent), transparent ${p5.stop})`;
|
|
2656
|
+
});
|
|
2657
|
+
blobs.push("radial-gradient(ellipse at center, #0a0a18 0%, #02020a 100%)");
|
|
2658
|
+
return blobs.join(", ");
|
|
2659
|
+
}
|
|
2660
|
+
function presentStorageKey(storageKey) {
|
|
2661
|
+
return `${storageKey}:present`;
|
|
2662
|
+
}
|
|
2663
|
+
var SEED_RECORD = valueRecord(null, "lk-present-seed");
|
|
2664
|
+
function seedPresentedTrial(store, records, { instruments, defaultInstrument }, seed) {
|
|
2665
|
+
const instrument = seed.instrument ?? defaultInstrument;
|
|
2666
|
+
const fingerprint = stableStringify({ ...seed, instrument });
|
|
2667
|
+
const trials = store.getState().trials;
|
|
2668
|
+
if (trials.length > 0 && records.get(SEED_RECORD) === fingerprint) return;
|
|
2669
|
+
const record = addTrial([], instruments, instrument, { config: seed.config })[0];
|
|
2670
|
+
if (!record) return;
|
|
2671
|
+
store.setState({ trials: [] });
|
|
2672
|
+
store.getState().addTrial({
|
|
2673
|
+
...record,
|
|
2674
|
+
..."state" in seed ? { state: seed.state } : {},
|
|
2675
|
+
..."view" in seed ? { view: seed.view } : {}
|
|
2676
|
+
});
|
|
2677
|
+
records.set(SEED_RECORD, fingerprint);
|
|
2678
|
+
}
|
|
2679
|
+
function seedDefaultTrial(store, instruments, defaultInstrument) {
|
|
2680
|
+
if (store.getState().trials.length > 0) return;
|
|
2681
|
+
const record = addTrial([], instruments, defaultInstrument)[0];
|
|
2682
|
+
if (!record) return;
|
|
2683
|
+
store.getState().addTrial(record);
|
|
2684
|
+
}
|
|
2685
|
+
function openUnstoredLab(options, seed) {
|
|
2686
|
+
const { instruments, defaultInstrument, mode } = options;
|
|
2687
|
+
const store = createLabStore({ initialMode: mode ?? "auto", instruments });
|
|
2688
|
+
const records = createRecordCache({ storage: noneAdapter, prefix: "", writable: false });
|
|
2689
|
+
if (seed) seedPresentedTrial(store, records, options, seed);
|
|
2690
|
+
else seedDefaultTrial(store, instruments, defaultInstrument);
|
|
2691
|
+
return { store, records, close: () => records.close(), marks: /* @__PURE__ */ new Map() };
|
|
2692
|
+
}
|
|
2693
|
+
async function openStoredLab(options, storageKey, storage, seed) {
|
|
2694
|
+
const { instruments, defaultInstrument, mode } = options;
|
|
2695
|
+
const opened = await openLabStore({
|
|
2696
|
+
storageKey,
|
|
2697
|
+
storage: storage ?? await defaultStorage(),
|
|
2698
|
+
initialMode: mode ?? "auto",
|
|
2699
|
+
instruments
|
|
2700
|
+
});
|
|
2701
|
+
if (seed) seedPresentedTrial(opened.store, opened.records, options, seed);
|
|
2702
|
+
else seedDefaultTrial(opened.store, instruments, defaultInstrument);
|
|
2703
|
+
const marks = /* @__PURE__ */ new Map();
|
|
2704
|
+
await Promise.all(
|
|
2705
|
+
opened.store.getState().trials.map(async (trial) => {
|
|
2706
|
+
const kept = instruments.find((i4) => i4.name === trial.instrumentName)?.annotations?.storage;
|
|
2707
|
+
if (!kept) return;
|
|
2708
|
+
try {
|
|
2709
|
+
marks.set(trial.id, await kept.load());
|
|
2710
|
+
} catch (error) {
|
|
2711
|
+
console.warn(`[labkit] could not load the marks of trial "${trial.id}"`, error);
|
|
2712
|
+
marks.set(trial.id, null);
|
|
2713
|
+
}
|
|
2714
|
+
})
|
|
2715
|
+
);
|
|
2716
|
+
return { ...opened, marks };
|
|
2717
|
+
}
|
|
2718
|
+
function useFocusPick(labBody, store, pick) {
|
|
2719
|
+
useEffect(() => {
|
|
2720
|
+
if (!labBody) return;
|
|
2721
|
+
const pickFrom = (node) => {
|
|
2722
|
+
const owned = new Set(store.getState().trials.map((t) => t.id));
|
|
2723
|
+
const nearest = (from) => from?.closest(".lk-trial[data-trial-id]") ?? null;
|
|
2724
|
+
let trial = typeof node?.closest === "function" ? nearest(node) : null;
|
|
2725
|
+
while (trial && !owned.has(trial.dataset.trialId ?? "")) trial = nearest(trial.parentElement);
|
|
2726
|
+
if (trial?.dataset.trialId) pick(trial.dataset.trialId);
|
|
2727
|
+
};
|
|
2728
|
+
const onInput = (event) => pickFrom(event.target);
|
|
2729
|
+
let pending;
|
|
2730
|
+
const doc = labBody.ownerDocument;
|
|
2731
|
+
const win = doc.defaultView;
|
|
2732
|
+
const onBlur = () => {
|
|
2733
|
+
clearTimeout(pending);
|
|
2734
|
+
pending = setTimeout(() => pickFrom(doc.activeElement), 0);
|
|
2735
|
+
};
|
|
2736
|
+
labBody.addEventListener("pointerdown", onInput, true);
|
|
2737
|
+
labBody.addEventListener("focusin", onInput, true);
|
|
2738
|
+
win?.addEventListener("blur", onBlur);
|
|
2739
|
+
return () => {
|
|
2740
|
+
clearTimeout(pending);
|
|
2741
|
+
labBody.removeEventListener("pointerdown", onInput, true);
|
|
2742
|
+
labBody.removeEventListener("focusin", onInput, true);
|
|
2743
|
+
win?.removeEventListener("blur", onBlur);
|
|
2744
|
+
};
|
|
2745
|
+
}, [labBody, store, pick]);
|
|
2746
|
+
}
|
|
2747
|
+
|
|
2748
|
+
// src/lightbox/modal.ts
|
|
2749
|
+
var OWN_DOUBLE_CLICK = [
|
|
2750
|
+
"button",
|
|
2751
|
+
"a[href]",
|
|
2752
|
+
"input",
|
|
2753
|
+
"select",
|
|
2754
|
+
"textarea",
|
|
2755
|
+
"label",
|
|
2756
|
+
"summary",
|
|
2757
|
+
'[contenteditable]:not([contenteditable="false"])',
|
|
2758
|
+
'[role="button"]',
|
|
2759
|
+
'[role="checkbox"]',
|
|
2760
|
+
'[role="combobox"]',
|
|
2761
|
+
'[role="link"]',
|
|
2762
|
+
'[role="menuitem"]',
|
|
2763
|
+
'[role="option"]',
|
|
2764
|
+
'[role="radio"]',
|
|
2765
|
+
'[role="separator"]',
|
|
2766
|
+
'[role="slider"]',
|
|
2767
|
+
'[role="spinbutton"]',
|
|
2768
|
+
'[role="switch"]',
|
|
2769
|
+
'[role="tab"]',
|
|
2770
|
+
'[role="textbox"]',
|
|
2771
|
+
"[data-lk-lightbox-ignore]"
|
|
2772
|
+
].join(",");
|
|
2773
|
+
function opensLightbox(event, root) {
|
|
2774
|
+
if (event.defaultPrevented) return false;
|
|
2775
|
+
const target = event.target;
|
|
2776
|
+
if (!(target instanceof Element)) return true;
|
|
2777
|
+
const owner = target.closest(OWN_DOUBLE_CLICK);
|
|
2778
|
+
return owner === null || !root.contains(owner);
|
|
2779
|
+
}
|
|
2780
|
+
function inertOutside(keep) {
|
|
2781
|
+
const path = /* @__PURE__ */ new Set();
|
|
2782
|
+
for (const el of keep) {
|
|
2783
|
+
for (let node = el; node && node !== document.body; node = node.parentElement) {
|
|
2784
|
+
path.add(node);
|
|
2785
|
+
}
|
|
2786
|
+
}
|
|
2787
|
+
const marked = [];
|
|
2788
|
+
for (const node of path) {
|
|
2789
|
+
const parent = node.parentElement;
|
|
2790
|
+
if (!parent) continue;
|
|
2791
|
+
for (const sibling of Array.from(parent.children)) {
|
|
2792
|
+
if (path.has(sibling) || sibling.hasAttribute("inert")) continue;
|
|
2793
|
+
sibling.setAttribute("inert", "");
|
|
2794
|
+
marked.push(sibling);
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
return () => {
|
|
2798
|
+
for (const sibling of marked) sibling.removeAttribute("inert");
|
|
2799
|
+
};
|
|
2800
|
+
}
|
|
2801
|
+
function liftStack(stack, self) {
|
|
2802
|
+
if (typeof self.showPopover !== "function") return () => {
|
|
2803
|
+
};
|
|
2804
|
+
stack.forEach((el, i4) => {
|
|
2805
|
+
el.setAttribute("popover", "manual");
|
|
2806
|
+
if (el !== self) el.setAttribute("data-lk-lightbox-layer", "");
|
|
2807
|
+
if (i4 === 0) el.setAttribute("data-lk-lightbox-scrim", "");
|
|
2808
|
+
el.showPopover();
|
|
2809
|
+
});
|
|
2810
|
+
return () => {
|
|
2811
|
+
for (const el of [...stack].reverse()) {
|
|
2812
|
+
if (el.matches(":popover-open")) el.hidePopover();
|
|
2813
|
+
el.removeAttribute("popover");
|
|
2814
|
+
el.removeAttribute("data-lk-lightbox-layer");
|
|
2815
|
+
el.removeAttribute("data-lk-lightbox-scrim");
|
|
2816
|
+
}
|
|
2817
|
+
};
|
|
2818
|
+
}
|
|
2819
|
+
function dialogProps(label) {
|
|
2820
|
+
return {
|
|
2821
|
+
role: "dialog",
|
|
2822
|
+
"aria-modal": true,
|
|
2823
|
+
"aria-label": label,
|
|
2824
|
+
"data-wzl-portal-host": ""
|
|
2825
|
+
};
|
|
2826
|
+
}
|
|
2827
|
+
function Lightbox({
|
|
2828
|
+
children,
|
|
2829
|
+
label = "Expanded view",
|
|
2830
|
+
disabled = false,
|
|
2831
|
+
expandOnDoubleClick = false,
|
|
2832
|
+
expanded: expandedProp,
|
|
2833
|
+
onExpandedChange,
|
|
2834
|
+
className
|
|
2835
|
+
}) {
|
|
2836
|
+
const [own, setOwn] = useState(false);
|
|
2837
|
+
const expanded = !disabled && (expandedProp ?? own);
|
|
2838
|
+
const onChangeRef = useLatest(onExpandedChange);
|
|
2839
|
+
const expandedRef = useLatest(expanded);
|
|
2840
|
+
const rootRef = useRef(null);
|
|
2841
|
+
const closeRef = useRef(null);
|
|
2842
|
+
const [claims, setClaims] = useState(0);
|
|
2843
|
+
const layers = useLightboxLayers();
|
|
2844
|
+
const surface = useSurfaceOptional();
|
|
2845
|
+
const set = useCallback(
|
|
2846
|
+
(next) => {
|
|
2847
|
+
if (next === expandedRef.current) return;
|
|
2848
|
+
setOwn(next);
|
|
2849
|
+
onChangeRef.current?.(next);
|
|
2850
|
+
},
|
|
2851
|
+
[expandedRef, onChangeRef]
|
|
2852
|
+
);
|
|
2853
|
+
const ctx = useMemo(
|
|
2854
|
+
() => disabled ? null : {
|
|
2855
|
+
expanded,
|
|
2856
|
+
open: () => set(true),
|
|
2857
|
+
close: () => set(false),
|
|
2858
|
+
toggle: () => set(!expandedRef.current),
|
|
2859
|
+
claimControl: () => {
|
|
2860
|
+
setClaims((n6) => n6 + 1);
|
|
2861
|
+
return () => setClaims((n6) => n6 - 1);
|
|
2862
|
+
}
|
|
2863
|
+
},
|
|
2864
|
+
[disabled, expanded, set, expandedRef]
|
|
2865
|
+
);
|
|
2866
|
+
useLayoutEffect(() => {
|
|
2867
|
+
const el = rootRef.current;
|
|
2868
|
+
if (!expanded || !el) return;
|
|
2869
|
+
const returnTo = document.activeElement;
|
|
2870
|
+
const stack = [...layers.below, el, ...layers.above].filter(
|
|
2871
|
+
(layer) => layer !== null
|
|
2872
|
+
);
|
|
2873
|
+
const unlift = liftStack(stack, el);
|
|
2874
|
+
const release = inertOutside(stack);
|
|
2875
|
+
surface?.scope(el);
|
|
2876
|
+
closeRef.current?.focus({ preventScroll: true });
|
|
2877
|
+
return () => {
|
|
2878
|
+
surface?.scope(null);
|
|
2879
|
+
release();
|
|
2880
|
+
unlift();
|
|
2881
|
+
if (returnTo?.isConnected) returnTo.focus({ preventScroll: true });
|
|
2882
|
+
};
|
|
2883
|
+
}, [expanded, layers, surface]);
|
|
2884
|
+
useEffect(() => {
|
|
2885
|
+
if (!expanded) return;
|
|
2886
|
+
const onKey = (e) => {
|
|
2887
|
+
if (e.key !== "Escape" || e.defaultPrevented) return;
|
|
2888
|
+
e.preventDefault();
|
|
2889
|
+
set(false);
|
|
2890
|
+
};
|
|
2891
|
+
document.addEventListener("keydown", onKey);
|
|
2892
|
+
return () => document.removeEventListener("keydown", onKey);
|
|
2893
|
+
}, [expanded, set]);
|
|
2894
|
+
const onDoubleClick = (e) => {
|
|
2895
|
+
if (disabled || !expandOnDoubleClick || !opensLightbox(e, e.currentTarget)) return;
|
|
2896
|
+
e.preventDefault();
|
|
2897
|
+
set(!expanded);
|
|
2898
|
+
};
|
|
2899
|
+
const onClick = (e) => {
|
|
2900
|
+
if (expanded && e.target === e.currentTarget) set(false);
|
|
2901
|
+
};
|
|
2902
|
+
const classes = ["lk-lightbox"];
|
|
2903
|
+
if (expanded) classes.push("lk-lightbox--expanded");
|
|
2904
|
+
if (className) classes.push(className);
|
|
2905
|
+
let control = null;
|
|
2906
|
+
if (expanded) {
|
|
2907
|
+
control = /* @__PURE__ */ jsx(
|
|
2908
|
+
"button",
|
|
2909
|
+
{
|
|
2910
|
+
ref: closeRef,
|
|
2911
|
+
type: "button",
|
|
2912
|
+
className: "lk-lightbox__button lk-lightbox__close",
|
|
2913
|
+
"aria-label": "Close expanded view",
|
|
2914
|
+
title: "Close (Esc)",
|
|
2915
|
+
onClick: () => set(false),
|
|
2916
|
+
children: /* @__PURE__ */ jsx(V, { size: 16 })
|
|
2917
|
+
}
|
|
2918
|
+
);
|
|
2919
|
+
} else if (!disabled && claims === 0) {
|
|
2920
|
+
control = /* @__PURE__ */ jsx(
|
|
2921
|
+
"button",
|
|
2922
|
+
{
|
|
2923
|
+
type: "button",
|
|
2924
|
+
className: "lk-lightbox__button lk-lightbox__open",
|
|
2925
|
+
"aria-label": "Expand",
|
|
2926
|
+
title: "Expand",
|
|
2927
|
+
onClick: () => set(true),
|
|
2928
|
+
children: /* @__PURE__ */ jsx(de, { size: 16 })
|
|
2929
|
+
}
|
|
2930
|
+
);
|
|
2931
|
+
}
|
|
2932
|
+
return /* @__PURE__ */ jsx(LightboxContext.Provider, { value: ctx, children: /* @__PURE__ */ jsxs(
|
|
2933
|
+
"div",
|
|
2934
|
+
{
|
|
2935
|
+
ref: rootRef,
|
|
2936
|
+
className: classes.join(" "),
|
|
2937
|
+
...expanded ? dialogProps(label) : null,
|
|
2938
|
+
onDoubleClick,
|
|
2939
|
+
onClick,
|
|
2940
|
+
children: [
|
|
2941
|
+
/* @__PURE__ */ jsx("div", { className: "lk-lightbox__frame", children }),
|
|
2942
|
+
control
|
|
2943
|
+
]
|
|
2944
|
+
}
|
|
2945
|
+
) });
|
|
2946
|
+
}
|
|
2218
2947
|
var ZONE_ID = asNodeId("lk-workspace");
|
|
2219
2948
|
var STRATEGIES = { grid: gridStrategy, floating: floatingStrategy };
|
|
2220
2949
|
var FLOAT_ZONE_ID = asNodeId("lk-workspace-floating");
|
|
@@ -2261,7 +2990,9 @@ function Workspace({
|
|
|
2261
2990
|
onLayoutChange,
|
|
2262
2991
|
gap = 12,
|
|
2263
2992
|
padding = 0,
|
|
2264
|
-
viewport
|
|
2993
|
+
viewport,
|
|
2994
|
+
lightbox = true,
|
|
2995
|
+
expandOnDoubleClick = false
|
|
2265
2996
|
}) {
|
|
2266
2997
|
const items = Children.toArray(children);
|
|
2267
2998
|
const tilePanels = useMemo(() => (panels ?? []).filter((p5) => p5.as === "tile"), [panels]);
|
|
@@ -2318,6 +3049,8 @@ function Workspace({
|
|
|
2318
3049
|
[onReorder]
|
|
2319
3050
|
);
|
|
2320
3051
|
const chrome = useMemo(() => {
|
|
3052
|
+
const lightboxFor = typeof lightbox === "function" ? lightbox : () => lightbox;
|
|
3053
|
+
const doubleClickFor = typeof expandOnDoubleClick === "function" ? expandOnDoubleClick : () => expandOnDoubleClick;
|
|
2321
3054
|
const byId = new Map(nodeIds.map((id, i4) => [id, items[i4]]));
|
|
2322
3055
|
const panelByNode = new Map(
|
|
2323
3056
|
tilePanels.map((p5) => [`lk-panel-${p5.key}`, p5])
|
|
@@ -2329,15 +3062,28 @@ function Workspace({
|
|
|
2329
3062
|
return /* @__PURE__ */ jsx(PanelFrame, { panel });
|
|
2330
3063
|
},
|
|
2331
3064
|
[KIND]: ({ node }) => {
|
|
2332
|
-
const
|
|
2333
|
-
|
|
3065
|
+
const id = String(node.id);
|
|
3066
|
+
const tile = (
|
|
3067
|
+
// `disabled` rather than leaving the wrapper out, so turning the
|
|
3068
|
+
// lightbox off cannot remount the tile.
|
|
3069
|
+
/* @__PURE__ */ jsx(
|
|
3070
|
+
Lightbox,
|
|
3071
|
+
{
|
|
3072
|
+
className: "lk-trial-tile",
|
|
3073
|
+
disabled: !lightboxFor(id),
|
|
3074
|
+
expandOnDoubleClick: doubleClickFor(id),
|
|
3075
|
+
children: byId.get(node.id) ?? null
|
|
3076
|
+
}
|
|
3077
|
+
)
|
|
3078
|
+
);
|
|
3079
|
+
if (!reorderable) return tile;
|
|
2334
3080
|
return (
|
|
2335
3081
|
// No grip strip: the trial's own title bar is the drag surface.
|
|
2336
|
-
/* @__PURE__ */ jsx(TrialDragContext.Provider, { value: { nodeId: node.id }, children:
|
|
3082
|
+
/* @__PURE__ */ jsx(TrialDragContext.Provider, { value: { nodeId: node.id }, children: tile })
|
|
2337
3083
|
);
|
|
2338
3084
|
}
|
|
2339
3085
|
};
|
|
2340
|
-
}, [nodeIds, items, reorderable, tilePanels]);
|
|
3086
|
+
}, [nodeIds, items, reorderable, tilePanels, lightbox, expandOnDoubleClick]);
|
|
2341
3087
|
const floatingLayer = floatPanels.length === 0 ? null : /* @__PURE__ */ jsx("div", { className: "lk-workspace__floating", children: floatPanels.map((p5) => /* @__PURE__ */ jsx(PanelFrame, { panel: p5, floating: true }, p5.key)) });
|
|
2342
3088
|
const grid = /* @__PURE__ */ jsx(
|
|
2343
3089
|
Container,
|
|
@@ -2360,42 +3106,6 @@ function Workspace({
|
|
|
2360
3106
|
] })
|
|
2361
3107
|
) : reorderable ? /* @__PURE__ */ jsx(DragProvider, { children: grid }) : grid }) });
|
|
2362
3108
|
}
|
|
2363
|
-
function seedDefaultTrial(store, instruments, defaultInstrument) {
|
|
2364
|
-
if (store.getState().trials.length > 0) return;
|
|
2365
|
-
const record = addTrial([], instruments, defaultInstrument)[0];
|
|
2366
|
-
if (!record) return;
|
|
2367
|
-
const { undoStack: _undoStack, ...rest } = record;
|
|
2368
|
-
store.getState().addTrial(rest);
|
|
2369
|
-
}
|
|
2370
|
-
function openUnstoredLab({ instruments, defaultInstrument, mode }) {
|
|
2371
|
-
const store = createLabStore({ initialMode: mode ?? "auto", instruments });
|
|
2372
|
-
seedDefaultTrial(store, instruments, defaultInstrument);
|
|
2373
|
-
const records = createRecordCache({ storage: noneAdapter, prefix: "", writable: false });
|
|
2374
|
-
return { store, records, close: () => records.close(), marks: /* @__PURE__ */ new Map() };
|
|
2375
|
-
}
|
|
2376
|
-
async function openStoredLab({ instruments, defaultInstrument, mode }, storageKey, storage) {
|
|
2377
|
-
const opened = await openLabStore({
|
|
2378
|
-
storageKey,
|
|
2379
|
-
storage: storage ?? await defaultStorage(),
|
|
2380
|
-
initialMode: mode ?? "auto",
|
|
2381
|
-
instruments
|
|
2382
|
-
});
|
|
2383
|
-
seedDefaultTrial(opened.store, instruments, defaultInstrument);
|
|
2384
|
-
const marks = /* @__PURE__ */ new Map();
|
|
2385
|
-
await Promise.all(
|
|
2386
|
-
opened.store.getState().trials.map(async (trial) => {
|
|
2387
|
-
const kept = instruments.find((i4) => i4.name === trial.instrumentName)?.annotations?.storage;
|
|
2388
|
-
if (!kept) return;
|
|
2389
|
-
try {
|
|
2390
|
-
marks.set(trial.id, await kept.load());
|
|
2391
|
-
} catch (error) {
|
|
2392
|
-
console.warn(`[labkit] could not load the marks of trial "${trial.id}"`, error);
|
|
2393
|
-
marks.set(trial.id, null);
|
|
2394
|
-
}
|
|
2395
|
-
})
|
|
2396
|
-
);
|
|
2397
|
-
return { ...opened, marks };
|
|
2398
|
-
}
|
|
2399
3109
|
function LabFallback({
|
|
2400
3110
|
title,
|
|
2401
3111
|
mode,
|
|
@@ -2424,24 +3134,6 @@ function LabFallback({
|
|
|
2424
3134
|
}
|
|
2425
3135
|
);
|
|
2426
3136
|
}
|
|
2427
|
-
var NEBULA_SLOTS = [
|
|
2428
|
-
{ cx: "18%", cy: "30%", sx: "60%", sy: "80%", stop: "70%" },
|
|
2429
|
-
{ cx: "78%", cy: "70%", sx: "55%", sy: "90%", stop: "65%" },
|
|
2430
|
-
{ cx: "50%", cy: "50%", sx: "50%", sy: "70%", stop: "75%" },
|
|
2431
|
-
{ cx: "12%", cy: "82%", sx: "50%", sy: "70%", stop: "70%" },
|
|
2432
|
-
{ cx: "85%", cy: "18%", sx: "55%", sy: "80%", stop: "70%" }
|
|
2433
|
-
];
|
|
2434
|
-
function buildNebula(list, theme, mode, density) {
|
|
2435
|
-
const ctx = { theme, resolved: resolveTheme(theme, { mode, density }) };
|
|
2436
|
-
const n6 = colorCount(list, ctx) ?? NEBULA_SLOTS.length;
|
|
2437
|
-
const colors = Array.from({ length: n6 }, (_2, i4) => colorAt(list, i4, ctx));
|
|
2438
|
-
const blobs = colors.map((c6, i4) => {
|
|
2439
|
-
const p5 = NEBULA_SLOTS[i4 % NEBULA_SLOTS.length];
|
|
2440
|
-
return `radial-gradient(ellipse ${p5.sx} ${p5.sy} at ${p5.cx} ${p5.cy}, color-mix(in srgb, ${c6} 22%, transparent), transparent ${p5.stop})`;
|
|
2441
|
-
});
|
|
2442
|
-
blobs.push("radial-gradient(ellipse at center, #0a0a18 0%, #02020a 100%)");
|
|
2443
|
-
return blobs.join(", ");
|
|
2444
|
-
}
|
|
2445
3137
|
function LabPanes({
|
|
2446
3138
|
contributions,
|
|
2447
3139
|
children
|
|
@@ -2498,13 +3190,21 @@ function Lab(props) {
|
|
|
2498
3190
|
if (process.env.NODE_ENV !== "production" && props.instruments.length === 0) {
|
|
2499
3191
|
throw new Error("[labkit] <Lab> requires a non-empty `instruments` array");
|
|
2500
3192
|
}
|
|
2501
|
-
const { storageKey, storage } = props;
|
|
2502
|
-
useWarnIgnoredChange("<Lab>", { storageKey, storage });
|
|
2503
|
-
const
|
|
2504
|
-
|
|
2505
|
-
|
|
3193
|
+
const { storageKey, storage, present } = props;
|
|
3194
|
+
useWarnIgnoredChange("<Lab>", { storageKey, storage, present });
|
|
3195
|
+
const [startsPresenting] = useState(() => present === true || hasPresentParam());
|
|
3196
|
+
if (process.env.NODE_ENV !== "production" && props.seed && !startsPresenting) {
|
|
3197
|
+
warnSeedIgnored();
|
|
3198
|
+
}
|
|
3199
|
+
const opened = useOpenOnce(() => {
|
|
3200
|
+
const seed = startsPresenting ? props.seed ?? {} : void 0;
|
|
3201
|
+
if (storageKey === void 0) return openUnstoredLab(props, seed);
|
|
3202
|
+
const key = startsPresenting ? presentStorageKey(storageKey) : storageKey;
|
|
3203
|
+
return openStoredLab(props, key, storage, seed);
|
|
3204
|
+
});
|
|
2506
3205
|
if (!opened) {
|
|
2507
3206
|
if (props.fallback !== void 0) return props.fallback;
|
|
3207
|
+
if (startsPresenting) return null;
|
|
2508
3208
|
return /* @__PURE__ */ jsx(
|
|
2509
3209
|
LabFallback,
|
|
2510
3210
|
{
|
|
@@ -2517,7 +3217,13 @@ function Lab(props) {
|
|
|
2517
3217
|
}
|
|
2518
3218
|
);
|
|
2519
3219
|
}
|
|
2520
|
-
return /* @__PURE__ */ jsx(LabRuntime, { ...props, opened });
|
|
3220
|
+
return /* @__PURE__ */ jsx(LabRuntime, { ...props, opened, startsPresenting });
|
|
3221
|
+
}
|
|
3222
|
+
var seedWarned = false;
|
|
3223
|
+
function warnSeedIgnored() {
|
|
3224
|
+
if (seedWarned) return;
|
|
3225
|
+
seedWarned = true;
|
|
3226
|
+
console.warn("[labkit] <Lab> reads `seed` only when it starts presenting; it is ignored here");
|
|
2521
3227
|
}
|
|
2522
3228
|
function LabRuntime({
|
|
2523
3229
|
instruments,
|
|
@@ -2532,13 +3238,15 @@ function LabRuntime({
|
|
|
2532
3238
|
chrome,
|
|
2533
3239
|
labChrome,
|
|
2534
3240
|
suppress,
|
|
3241
|
+
expandOnDoubleClick = false,
|
|
2535
3242
|
addTrial: addTrial2,
|
|
2536
3243
|
zoom = true,
|
|
2537
3244
|
tools,
|
|
2538
3245
|
configRules,
|
|
2539
3246
|
controls,
|
|
2540
3247
|
children,
|
|
2541
|
-
opened
|
|
3248
|
+
opened,
|
|
3249
|
+
startsPresenting
|
|
2542
3250
|
}) {
|
|
2543
3251
|
const { store } = opened;
|
|
2544
3252
|
useLayoutEffect(() => {
|
|
@@ -2546,86 +3254,42 @@ function LabRuntime({
|
|
|
2546
3254
|
}, [instruments, store]);
|
|
2547
3255
|
const trials = useStore(store, (s4) => s4.trials);
|
|
2548
3256
|
const [cameras] = useState(createCameraRegistry);
|
|
3257
|
+
const [clocks] = useState(createClockRegistry);
|
|
3258
|
+
useClockLoop(clocks);
|
|
2549
3259
|
const [focusPick, setFocusPick] = useState(null);
|
|
2550
3260
|
const focusedTrialId = trials.some((t) => t.id === focusPick) ? focusPick : trials[0]?.id ?? null;
|
|
3261
|
+
const [presentedBy, setPresentedBy] = useState(
|
|
3262
|
+
startsPresenting ? "mount" : null
|
|
3263
|
+
);
|
|
3264
|
+
const presenting = presentedBy !== null;
|
|
3265
|
+
const presentation = useMemo(
|
|
3266
|
+
() => ({
|
|
3267
|
+
active: presenting,
|
|
3268
|
+
enter: () => setPresentedBy((by) => by ?? "enter"),
|
|
3269
|
+
exit: () => setPresentedBy(null),
|
|
3270
|
+
trialId: presenting ? focusedTrialId : null
|
|
3271
|
+
}),
|
|
3272
|
+
[presenting, focusedTrialId]
|
|
3273
|
+
);
|
|
2551
3274
|
const savedSnapshots = useStore(store, (s4) => s4.savedSnapshots);
|
|
2552
3275
|
const modeValue = useStore(store, (s4) => s4.mode);
|
|
2553
3276
|
const layout = useStore(store, (s4) => s4.layout);
|
|
2554
3277
|
const undockedPanels = useStore(store, (s4) => s4.undockedPanels);
|
|
2555
3278
|
const panelHostsRef = useRef(null);
|
|
2556
3279
|
if (panelHostsRef.current === null) panelHostsRef.current = createPanelHostRegistry();
|
|
2557
|
-
const outerSurface = useSurfaceOptional();
|
|
2558
|
-
const outerOver = useSurfaceCanvas("over");
|
|
2559
|
-
const outerUnder = useSurfaceCanvas("under");
|
|
2560
|
-
const [ownOver, setOwnOver] = useState(null);
|
|
2561
|
-
const [ownUnder, setOwnUnder] = useState(null);
|
|
2562
|
-
const ownOverRef = useRef(null);
|
|
2563
|
-
const ownUnderRef = useRef(null);
|
|
2564
|
-
const bufferRef = useRef({ w: 0, h: 0 });
|
|
2565
|
-
const surfaceRef = useRef(null);
|
|
2566
|
-
const onFrame = useCallback((frame) => {
|
|
2567
|
-
const canvases = [ownUnderRef.current, ownOverRef.current].filter((c6) => c6 !== null);
|
|
2568
|
-
if (canvases.length === 0) return;
|
|
2569
|
-
const w3 = Math.round(frame.size.width * frame.dpr);
|
|
2570
|
-
const h2 = Math.round(frame.size.height * frame.dpr);
|
|
2571
|
-
if (bufferRef.current.w !== w3 || bufferRef.current.h !== h2) {
|
|
2572
|
-
bufferRef.current = { w: w3, h: h2 };
|
|
2573
|
-
for (const c6 of canvases) {
|
|
2574
|
-
c6.width = w3;
|
|
2575
|
-
c6.height = h2;
|
|
2576
|
-
c6.style.width = `${frame.size.width}px`;
|
|
2577
|
-
c6.style.height = `${frame.size.height}px`;
|
|
2578
|
-
}
|
|
2579
|
-
surfaceRef.current?.invalidateAll();
|
|
2580
|
-
return;
|
|
2581
|
-
}
|
|
2582
|
-
}, []);
|
|
2583
|
-
const ownSurface = useTiledSurface({ onFrame });
|
|
2584
|
-
useInsertionEffect(() => {
|
|
2585
|
-
surfaceRef.current = ownSurface;
|
|
2586
|
-
}, [ownSurface]);
|
|
2587
3280
|
const [labBody, setLabBody] = useState(null);
|
|
2588
|
-
const attachOwnSurface = ownSurface.containerRef;
|
|
2589
|
-
const labBodyRef = useCallback(
|
|
2590
|
-
(el) => {
|
|
2591
|
-
setLabBody(el);
|
|
2592
|
-
if (!outerSurface) attachOwnSurface(el);
|
|
2593
|
-
},
|
|
2594
|
-
[outerSurface, attachOwnSurface]
|
|
2595
|
-
);
|
|
2596
3281
|
useLabFitWarning(labBody);
|
|
3282
|
+
useFocusPick(labBody, store, setFocusPick);
|
|
2597
3283
|
useEffect(() => {
|
|
2598
|
-
if (!labBody) return;
|
|
2599
|
-
const pick = (node) => {
|
|
2600
|
-
const owned = new Set(store.getState().trials.map((t) => t.id));
|
|
2601
|
-
const nearest = (from) => from?.closest(".lk-trial[data-trial-id]") ?? null;
|
|
2602
|
-
let trial = typeof node?.closest === "function" ? nearest(node) : null;
|
|
2603
|
-
while (trial && !owned.has(trial.dataset.trialId ?? "")) trial = nearest(trial.parentElement);
|
|
2604
|
-
if (trial?.dataset.trialId) setFocusPick(trial.dataset.trialId);
|
|
2605
|
-
};
|
|
2606
|
-
const onInput = (event) => pick(event.target);
|
|
2607
|
-
let pending;
|
|
3284
|
+
if (presentedBy !== "enter" || !labBody) return;
|
|
2608
3285
|
const doc = labBody.ownerDocument;
|
|
2609
|
-
const
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
pending = setTimeout(() => pick(doc.activeElement), 0);
|
|
3286
|
+
const onKeyDown = (event) => {
|
|
3287
|
+
if (event.key !== "Escape" || event.defaultPrevented) return;
|
|
3288
|
+
setPresentedBy(null);
|
|
2613
3289
|
};
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
return () => {
|
|
2618
|
-
clearTimeout(pending);
|
|
2619
|
-
labBody.removeEventListener("pointerdown", onInput, true);
|
|
2620
|
-
labBody.removeEventListener("focusin", onInput, true);
|
|
2621
|
-
win?.removeEventListener("blur", onBlur);
|
|
2622
|
-
};
|
|
2623
|
-
}, [labBody, store]);
|
|
2624
|
-
const surface = outerSurface ?? ownSurface;
|
|
2625
|
-
const surfaceCanvases = useMemo(
|
|
2626
|
-
() => outerSurface ? { over: outerOver, under: outerUnder } : { over: ownOver, under: ownUnder },
|
|
2627
|
-
[outerSurface, outerOver, outerUnder, ownOver, ownUnder]
|
|
2628
|
-
);
|
|
3290
|
+
doc.addEventListener("keydown", onKeyDown);
|
|
3291
|
+
return () => doc.removeEventListener("keydown", onKeyDown);
|
|
3292
|
+
}, [presentedBy, labBody]);
|
|
2629
3293
|
const workspacePanels = useMemo(
|
|
2630
3294
|
() => Object.entries(undockedPanels).map(([key, panel]) => ({
|
|
2631
3295
|
key,
|
|
@@ -2698,6 +3362,7 @@ function LabRuntime({
|
|
|
2698
3362
|
(w3) => w3.id === id ? { ...w3, config: record.config, state: record.state, view: record.view } : w3
|
|
2699
3363
|
)
|
|
2700
3364
|
}));
|
|
3365
|
+
clocks.get(id)?.reset();
|
|
2701
3366
|
},
|
|
2702
3367
|
savedSnapshots,
|
|
2703
3368
|
saveSnapshot: (trialId, name) => {
|
|
@@ -2718,6 +3383,7 @@ function LabRuntime({
|
|
|
2718
3383
|
controls
|
|
2719
3384
|
};
|
|
2720
3385
|
}, [
|
|
3386
|
+
clocks,
|
|
2721
3387
|
instruments,
|
|
2722
3388
|
trials,
|
|
2723
3389
|
focusedTrialId,
|
|
@@ -2745,15 +3411,19 @@ function LabRuntime({
|
|
|
2745
3411
|
onReorder: (ids) => contextValue.reorderTrials(ids),
|
|
2746
3412
|
layout,
|
|
2747
3413
|
onLayoutChange: (next) => store.getState().setLayout(next),
|
|
3414
|
+
expandOnDoubleClick: typeof expandOnDoubleClick === "function" ? (id) => {
|
|
3415
|
+
const trial = trials.find((t) => t.id === id);
|
|
3416
|
+
return trial ? expandOnDoubleClick(trial) : false;
|
|
3417
|
+
} : expandOnDoubleClick,
|
|
2748
3418
|
children: trials.map((w3) => /* @__PURE__ */ jsx(Trial, { id: w3.id, chrome, suppress }, w3.id))
|
|
2749
3419
|
}
|
|
2750
3420
|
);
|
|
2751
|
-
return /* @__PURE__ */ jsx(LabStoreContext.Provider, { value: { store }, children: /* @__PURE__ */ jsx(PersistenceContext.Provider, { value: opened.records, children: /* @__PURE__ */ jsx(AnnotationPreloadContext.Provider, { value: opened.marks, children: /* @__PURE__ */ jsx(LabContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(CameraRegistryContext.Provider, { value: cameras, children: /* @__PURE__ */ jsx(
|
|
3421
|
+
return /* @__PURE__ */ jsx(LabStoreContext.Provider, { value: { store }, children: /* @__PURE__ */ jsx(PersistenceContext.Provider, { value: opened.records, children: /* @__PURE__ */ jsx(AnnotationPreloadContext.Provider, { value: opened.marks, children: /* @__PURE__ */ jsx(LabContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(PresentationContext.Provider, { value: presentation, children: /* @__PURE__ */ jsx(CameraRegistryContext.Provider, { value: cameras, children: /* @__PURE__ */ jsx(ClockRegistryContext.Provider, { value: clocks, children: /* @__PURE__ */ jsx(
|
|
2752
3422
|
ThemeProvider,
|
|
2753
3423
|
{
|
|
2754
3424
|
theme,
|
|
2755
3425
|
selection: { mode: resolvedMode, density: density ?? "comfortable" },
|
|
2756
|
-
className: "lk-lab",
|
|
3426
|
+
className: presenting ? "lk-lab lk-lab--present" : "lk-lab",
|
|
2757
3427
|
style: backdropStyle,
|
|
2758
3428
|
children: /* @__PURE__ */ jsx(
|
|
2759
3429
|
LabShell,
|
|
@@ -2768,53 +3438,22 @@ function LabRuntime({
|
|
|
2768
3438
|
] }) : footer,
|
|
2769
3439
|
header: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2770
3440
|
/* @__PURE__ */ jsx(LabHeader, { ...addTrial2 !== void 0 ? { addTrial: addTrial2 } : {} }),
|
|
2771
|
-
zoom ? /* @__PURE__ */ jsx(LabZoom, {}) : null,
|
|
3441
|
+
zoom && !presenting ? /* @__PURE__ */ jsx(LabZoom, {}) : null,
|
|
2772
3442
|
children,
|
|
2773
3443
|
/* @__PURE__ */ jsx(LabHeaderRegion, { contributions: labChromeAll }),
|
|
2774
3444
|
/* @__PURE__ */ jsx(LabThemeSwitcher, {})
|
|
2775
3445
|
] }),
|
|
2776
|
-
children: /* @__PURE__ */ jsx(PanelHostContext.Provider, { value: panelHostsRef.current, children: /* @__PURE__ */ jsx(
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2784
|
-
/* @__PURE__ */ jsx(
|
|
2785
|
-
"canvas",
|
|
2786
|
-
{
|
|
2787
|
-
className: "lk-lab__surface lk-lab__surface--under",
|
|
2788
|
-
ref: (el) => {
|
|
2789
|
-
ownUnderRef.current = el;
|
|
2790
|
-
setOwnUnder(el);
|
|
2791
|
-
}
|
|
2792
|
-
}
|
|
2793
|
-
),
|
|
2794
|
-
/* @__PURE__ */ jsx(
|
|
2795
|
-
"canvas",
|
|
2796
|
-
{
|
|
2797
|
-
className: "lk-lab__surface lk-lab__surface--over",
|
|
2798
|
-
ref: (el) => {
|
|
2799
|
-
ownOverRef.current = el;
|
|
2800
|
-
setOwnOver(el);
|
|
2801
|
-
}
|
|
2802
|
-
}
|
|
2803
|
-
)
|
|
2804
|
-
] })
|
|
2805
|
-
),
|
|
2806
|
-
hasPaneChrome ? /* @__PURE__ */ jsxs(LabPanes, { contributions: labChromeAll, children: [
|
|
2807
|
-
/* @__PURE__ */ jsx(LabPalette, { contributions: labChromeAll }),
|
|
2808
|
-
workspace
|
|
2809
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2810
|
-
/* @__PURE__ */ jsx(LabPalette, { contributions: labChromeAll }),
|
|
2811
|
-
workspace
|
|
2812
|
-
] })
|
|
2813
|
-
] }) }) }) })
|
|
3446
|
+
children: /* @__PURE__ */ jsx(PanelHostContext.Provider, { value: panelHostsRef.current, children: /* @__PURE__ */ jsx(LabSurface, { bodyRef: setLabBody, children: hasPaneChrome ? /* @__PURE__ */ jsxs(LabPanes, { contributions: labChromeAll, children: [
|
|
3447
|
+
/* @__PURE__ */ jsx(LabPalette, { contributions: labChromeAll }),
|
|
3448
|
+
workspace
|
|
3449
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3450
|
+
/* @__PURE__ */ jsx(LabPalette, { contributions: labChromeAll }),
|
|
3451
|
+
workspace
|
|
3452
|
+
] }) }) })
|
|
2814
3453
|
}
|
|
2815
3454
|
)
|
|
2816
3455
|
}
|
|
2817
|
-
) }) }) }) }) });
|
|
3456
|
+
) }) }) }) }) }) }) });
|
|
2818
3457
|
}
|
|
2819
3458
|
function LabBoundary({ children }) {
|
|
2820
3459
|
return /* @__PURE__ */ jsx(LabStoreContext.Provider, { value: null, children: /* @__PURE__ */ jsx(PersistenceContext.Provider, { value: null, children: /* @__PURE__ */ jsx(AnnotationPreloadContext.Provider, { value: null, children: /* @__PURE__ */ jsx(LabContext.Provider, { value: null, children: /* @__PURE__ */ jsx(PanelHostContext.Provider, { value: null, children: /* @__PURE__ */ jsx(SurfaceContext.Provider, { value: null, children: /* @__PURE__ */ jsx(SurfaceCanvasContext.Provider, { value: { over: null, under: null }, children: /* @__PURE__ */ jsx(TrialIdContext.Provider, { value: null, children: /* @__PURE__ */ jsx(AnnotationsContext.Provider, { value: null, children: /* @__PURE__ */ jsx(CameraWheelContext.Provider, { value: null, children: /* @__PURE__ */ jsx(CanvasStackContext.Provider, { value: null, children: /* @__PURE__ */ jsx(TrialDragContext.Provider, { value: null, children: /* @__PURE__ */ jsx(ThemeContext.Provider, { value: null, children }) }) }) }) }) }) }) }) }) }) }) }) });
|
|
@@ -3014,8 +3653,8 @@ function ButtonsAndToggles() {
|
|
|
3014
3653
|
] }) }),
|
|
3015
3654
|
/* @__PURE__ */ jsx(Cell, { label: "Keycaps", children: /* @__PURE__ */ jsxs("div", { className: "lk-specimen__row", children: [
|
|
3016
3655
|
/* @__PURE__ */ jsx(p, { keys: [{ label: "\u2318" }, { label: "\u21E7" }, { label: "K" }], separator: "+" }),
|
|
3017
|
-
/* @__PURE__ */ jsx(
|
|
3018
|
-
/* @__PURE__ */ jsx(
|
|
3656
|
+
/* @__PURE__ */ jsx(f3, { label: "K" }),
|
|
3657
|
+
/* @__PURE__ */ jsx(f3, { label: "\u2325", variant: "minimal" })
|
|
3019
3658
|
] }) })
|
|
3020
3659
|
] });
|
|
3021
3660
|
}
|
|
@@ -3157,7 +3796,7 @@ function PanelsAndRows() {
|
|
|
3157
3796
|
]);
|
|
3158
3797
|
const [panelCollapsed, setPanelCollapsed] = useState(false);
|
|
3159
3798
|
return /* @__PURE__ */ jsxs(Section, { title: "Panels & property rows", children: [
|
|
3160
|
-
/* @__PURE__ */ jsx(Cell, { label: "PropertyPanel", children: /* @__PURE__ */ jsx(
|
|
3799
|
+
/* @__PURE__ */ jsx(Cell, { label: "PropertyPanel", children: /* @__PURE__ */ jsx(ce2, { title: "Shape", children: /* @__PURE__ */ jsxs(le, { children: [
|
|
3161
3800
|
/* @__PURE__ */ jsx(
|
|
3162
3801
|
ye,
|
|
3163
3802
|
{
|
|
@@ -3262,10 +3901,10 @@ function PanelsAndRows() {
|
|
|
3262
3901
|
}
|
|
3263
3902
|
) }),
|
|
3264
3903
|
/* @__PURE__ */ jsx(Cell, { label: "LayerList", children: /* @__PURE__ */ jsx(
|
|
3265
|
-
|
|
3904
|
+
A2,
|
|
3266
3905
|
{
|
|
3267
3906
|
items: layers,
|
|
3268
|
-
onReorder: (move) => setLayers(
|
|
3907
|
+
onReorder: (move) => setLayers(T(layers, move)),
|
|
3269
3908
|
renderBody: (item) => /* @__PURE__ */ jsxs("div", { children: [
|
|
3270
3909
|
"settings for ",
|
|
3271
3910
|
item.label
|
|
@@ -3310,7 +3949,7 @@ function OverlaysAndFeedback() {
|
|
|
3310
3949
|
),
|
|
3311
3950
|
/* @__PURE__ */ jsx(c, { onClick: () => setDialogOpen(true), children: "Dialog" }),
|
|
3312
3951
|
/* @__PURE__ */ jsx(
|
|
3313
|
-
|
|
3952
|
+
d2,
|
|
3314
3953
|
{
|
|
3315
3954
|
isOpen: dialogOpen,
|
|
3316
3955
|
onOpenChange: setDialogOpen,
|
|
@@ -3362,7 +4001,7 @@ function ListsAndData() {
|
|
|
3362
4001
|
}
|
|
3363
4002
|
) }),
|
|
3364
4003
|
/* @__PURE__ */ jsx(Cell, { label: "DataGrid", children: /* @__PURE__ */ jsx(
|
|
3365
|
-
|
|
4004
|
+
f2,
|
|
3366
4005
|
{
|
|
3367
4006
|
rows: [
|
|
3368
4007
|
{ id: "1", name: "accent", count: 3 },
|
|
@@ -3524,7 +4163,7 @@ function EditorsAndPlots() {
|
|
|
3524
4163
|
}
|
|
3525
4164
|
) }),
|
|
3526
4165
|
/* @__PURE__ */ jsx(Cell, { label: "Timeline", wide: true, children: /* @__PURE__ */ jsx("div", { className: "lk-specimen__timeline", children: /* @__PURE__ */ jsx(
|
|
3527
|
-
|
|
4166
|
+
xe,
|
|
3528
4167
|
{
|
|
3529
4168
|
tracks,
|
|
3530
4169
|
duration: 2e3,
|
|
@@ -3549,10 +4188,6 @@ function LabChrome() {
|
|
|
3549
4188
|
/* @__PURE__ */ jsx(Toolbar.Group, { end: true, children: /* @__PURE__ */ jsx(Toolbar.Button, { onClick: () => {
|
|
3550
4189
|
}, children: "Save" }) })
|
|
3551
4190
|
] }) }),
|
|
3552
|
-
/* @__PURE__ */ jsx(Cell, { label: "StatusBar", children: /* @__PURE__ */ jsxs(StatusBar, { children: [
|
|
3553
|
-
/* @__PURE__ */ jsx(StatusBar.Section, { children: "Items: 12" }),
|
|
3554
|
-
/* @__PURE__ */ jsx(StatusBar.Section, { children: "Zoom: 100%" })
|
|
3555
|
-
] }) }),
|
|
3556
4191
|
/* @__PURE__ */ jsxs(Cell, { label: "Legend, JobProgress", children: [
|
|
3557
4192
|
/* @__PURE__ */ jsx(Legend, { entries: LEGEND }),
|
|
3558
4193
|
/* @__PURE__ */ jsx(JobProgress, { job: JOB })
|
|
@@ -3587,6 +4222,6 @@ function Specimen({ className }) {
|
|
|
3587
4222
|
] });
|
|
3588
4223
|
}
|
|
3589
4224
|
|
|
3590
|
-
export { AnnotationOverlay, AnnotationTargets, Lab, LabBoundary, LabPalette, LabRoot, LabShell, LabSwitcher, LabZoom, SPECIMEN_SECTIONS, Specimen, Trial, TrialBody, TrialChrome, Workspace, addTrial, annotationsFromJSON, capturePlan, captureTarget, cloneTrial, closeTrial, composeCaptureSvg, createAnnotationScene, createAnnotationStore, createMarkDrawOne, currentPage, defineInstrument, fitView, fromWeaselView, interstellarTheme, isStale, reorderTrials, resetTrial, resolveMarkStyle, seenFrom, toWeaselView, validateConfigSchema };
|
|
4225
|
+
export { AnnotationOverlay, AnnotationTargets, Lab, LabBoundary, LabPalette, LabRoot, LabShell, LabSwitcher, LabZoom, Lightbox, LightboxLayers, SPECIMEN_SECTIONS, Specimen, Trial, TrialBody, TrialChrome, Workspace, addTrial, annotationsFromJSON, capturePlan, captureTarget, cloneTrial, closeTrial, composeCaptureSvg, createAnnotationScene, createAnnotationStore, createMarkDrawOne, currentPage, defineInstrument, fitView, fromWeaselView, interstellarTheme, isStale, reorderTrials, resetTrial, resolveMarkStyle, seenFrom, toWeaselView, useClockFrame, useLightbox, useLightboxControl, useLightboxLayers, usePresentation, useTrialClock, validateConfigSchema };
|
|
3591
4226
|
//# sourceMappingURL=index.js.map
|
|
3592
4227
|
//# sourceMappingURL=index.js.map
|