@weasel-js/labkit 1.5.2 → 1.6.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 +3 -7
- package/dist/_dts/{CanvasStackContext-CMMo180l.d.ts → CanvasStackContext-Wo6OwIVM.d.ts} +1 -1
- package/dist/_dts/FloatingPanel-7j0IcXwz.d.ts +30 -0
- package/dist/_dts/LayerList.d-BoELAMsM.d.ts +83 -0
- package/dist/_dts/{PrefsForm.d-DPy9I8It.d.ts → PrefsRow.d-DFpPIeIC.d.ts} +16 -1
- package/dist/_dts/PropertyField.d-D0ndfIIt.d.ts +404 -0
- package/dist/_dts/{Select.d-ZTiwzYyT.d.ts → Select.d-Cr8-zoup.d.ts} +105 -15
- package/dist/_dts/{usePanZoom-SSTZe410.d.ts → Stage-DWBBi8IU.d.ts} +80 -35
- package/dist/_dts/{index-DlKolEIZ.d.ts → index-CKyX0ME_.d.ts} +12 -13
- package/dist/_dts/{frac-B4hFJMiN.d.ts → types-B7yBTTF9.d.ts} +709 -651
- package/dist/_dts/{types-Db-3NNk1.d.ts → types-DTuViBvc.d.ts} +21 -2
- package/dist/_dts/{useTrialState-pnAE-UBD.d.ts → useTrialState-CMaV6UD4.d.ts} +2 -3
- package/dist/canvas/index.d.ts +41 -8
- package/dist/canvas/index.js +5 -3
- package/dist/chrome/index.d.ts +6 -6
- package/dist/chrome/index.js +9 -7
- package/dist/chunk-24W5VEJW.js +18 -0
- package/dist/chunk-24W5VEJW.js.map +1 -0
- package/dist/chunk-2RVCB2PT.js +3 -0
- package/dist/chunk-2RVCB2PT.js.map +1 -0
- package/dist/chunk-3RY6WL5T.js +38 -0
- package/dist/chunk-3RY6WL5T.js.map +1 -0
- package/dist/{chunk-CKUKF72R.js → chunk-4TT3PNPR.js} +68 -55
- package/dist/chunk-4TT3PNPR.js.map +1 -0
- package/dist/{chunk-KJCUERQF.js → chunk-6FLXL3I7.js} +9 -164
- package/dist/chunk-6FLXL3I7.js.map +1 -0
- package/dist/chunk-ASOK76ZH.js +431 -0
- package/dist/chunk-ASOK76ZH.js.map +1 -0
- package/dist/chunk-AWQG7FCC.js +19 -0
- package/dist/chunk-AWQG7FCC.js.map +1 -0
- package/dist/chunk-CGHF6RZV.js +300 -0
- package/dist/chunk-CGHF6RZV.js.map +1 -0
- package/dist/chunk-DWMSB4CA.js +228 -0
- package/dist/chunk-DWMSB4CA.js.map +1 -0
- package/dist/chunk-GHGO52SO.js +92 -0
- package/dist/chunk-GHGO52SO.js.map +1 -0
- package/dist/{chunk-LRI3MBGR.js → chunk-HKV7LRHY.js} +4 -4
- package/dist/{chunk-LRI3MBGR.js.map → chunk-HKV7LRHY.js.map} +1 -1
- package/dist/{chunk-EMXAIRUJ.js → chunk-IRTGUQ5O.js} +5 -4
- package/dist/chunk-IRTGUQ5O.js.map +1 -0
- package/dist/{chunk-H6ZAOWNE.js → chunk-JVBYV6TL.js} +3 -3
- package/dist/{chunk-H6ZAOWNE.js.map → chunk-JVBYV6TL.js.map} +1 -1
- package/dist/chunk-KHK5FGER.js +145 -0
- package/dist/chunk-KHK5FGER.js.map +1 -0
- package/dist/chunk-NEXR37YJ.js +144 -0
- package/dist/chunk-NEXR37YJ.js.map +1 -0
- package/dist/{chunk-A2ACAGW6.js → chunk-O6FFFOHS.js} +32 -7
- package/dist/chunk-O6FFFOHS.js.map +1 -0
- package/dist/chunk-QGMOA2YE.js +731 -0
- package/dist/chunk-QGMOA2YE.js.map +1 -0
- package/dist/{chunk-ERFMC6WU.js → chunk-S4NCI32V.js} +19 -10
- package/dist/chunk-S4NCI32V.js.map +1 -0
- package/dist/{chunk-753Y6HE6.js → chunk-SLAQPUI4.js} +4 -4
- package/dist/chunk-SLAQPUI4.js.map +1 -0
- package/dist/{chunk-REOBGYMC.js → chunk-TJ77A4A3.js} +3 -5
- package/dist/chunk-TJ77A4A3.js.map +1 -0
- package/dist/chunk-TYN6MLXX.js +13864 -0
- package/dist/chunk-TYN6MLXX.js.map +1 -0
- package/dist/{chunk-RS3HRQWU.js → chunk-WPLAANH4.js} +4 -3
- package/dist/chunk-WPLAANH4.js.map +1 -0
- package/dist/config/index.d.ts +51 -7
- package/dist/config/index.js +4 -5
- package/dist/controls/index.d.ts +92 -5
- package/dist/controls/index.js +5 -4
- package/dist/dragdrop/index.d.ts +9 -6
- package/dist/dragdrop/index.js +3 -2
- package/dist/index.d.ts +108 -154
- package/dist/index.js +456 -600
- package/dist/index.js.map +1 -1
- package/dist/layers/index.d.ts +5 -35
- package/dist/layers/index.js +3 -3
- package/dist/loupe/index.d.ts +21 -17
- package/dist/loupe/index.js +5 -3
- package/dist/overview/index.d.ts +56 -0
- package/dist/overview/index.js +288 -0
- package/dist/overview/index.js.map +1 -0
- package/dist/passthrough/weasel-ui.d.ts +434 -231
- package/dist/passthrough/weasel-ui.js +2 -1
- package/dist/primitives/index.d.ts +19 -54
- package/dist/primitives/index.js +6 -4
- package/dist/state/index.d.ts +8 -7
- package/dist/state/index.js +4 -5
- package/dist/state/index.js.map +1 -1
- package/dist/styles.css +360 -174
- package/dist/undo/index.d.ts +5 -4
- package/package.json +13 -13
- package/src/annotations/frac.test.ts +7 -0
- package/src/annotations/index.ts +1 -0
- package/src/annotations/paint.test.ts +21 -0
- package/src/annotations/paint.ts +12 -0
- package/src/annotations/store.test.ts +57 -0
- package/src/annotations/store.ts +25 -6
- package/src/annotations/toolMap.test.ts +37 -2
- package/src/annotations/toolMap.ts +13 -0
- package/src/annotations/types.ts +30 -2
- package/src/canvas/AGENTS.md +8 -10
- package/src/canvas/CameraInput.test.tsx +136 -0
- package/src/canvas/CameraInput.tsx +311 -0
- package/src/canvas/CanvasStack.tsx +42 -58
- package/src/canvas/LinkedCursor.less +16 -0
- package/src/canvas/LinkedCursor.tsx +54 -0
- package/src/canvas/Stage.test.tsx +18 -0
- package/src/canvas/Stage.tsx +42 -37
- package/src/canvas/cameraView.test.ts +60 -0
- package/src/canvas/cameraView.ts +61 -0
- package/src/canvas/index.ts +11 -2
- package/src/chrome/regions/SidebarRegion.less +197 -0
- package/src/chrome/regions/SidebarRegion.test.tsx +27 -0
- package/src/chrome/regions/SidebarRegion.tsx +7 -2
- package/src/chrome/types.ts +5 -2
- package/src/config/autoConfig.ts +2 -2
- package/src/config/builder.ts +21 -2
- package/src/config/entry.test.ts +10 -0
- package/src/config/fromConfigField.ts +1 -0
- package/src/config/index.ts +5 -0
- package/src/config/resolve.ts +11 -1
- package/src/config/rules.ts +2 -0
- package/src/config/sectionTree.test.ts +152 -0
- package/src/config/sectionTree.ts +134 -0
- package/src/config/types.ts +21 -0
- package/src/controls/ControlPanel.less +4 -0
- package/src/controls/ControlPanel.stories.tsx +55 -2
- package/src/controls/ControlPanel.test.tsx +40 -3
- package/src/controls/ControlPanel.tsx +134 -336
- package/src/controls/inDialog.test.tsx +100 -0
- package/src/controls/inDialog.tsx +38 -0
- package/src/controls/index.ts +1 -0
- package/src/index.test.ts +1 -1
- package/src/index.ts +18 -29
- package/src/instrument/SineWave.smoke.test.tsx +2 -0
- package/src/instrument/types.ts +15 -3
- package/src/lab/Lab.nebula.test.tsx +40 -0
- package/src/lab/Lab.test.tsx +3 -1
- package/src/lab/Lab.tsx +42 -19
- package/src/lab/LabBoundary.test.tsx +66 -0
- package/src/lab/LabBoundary.tsx +56 -0
- package/src/lab/LabHeader.tsx +4 -23
- package/src/lab/LabRoot.tsx +2 -3
- package/src/lab/LabShell.less +0 -1
- package/src/lab/LabShell.stories.tsx +15 -0
- package/src/lab/LabShell.test.tsx +18 -0
- package/src/lab/LabShell.tsx +14 -1
- package/src/lab/LabSwitcher.less +1 -1
- package/src/lab/LabSwitcher.test.tsx +41 -0
- package/src/lab/LabSwitcher.tsx +30 -8
- package/src/lab/index.ts +1 -0
- package/src/layers/AGENTS.md +18 -74
- package/src/layers/index.ts +4 -2
- package/src/loupe/AGENTS.md +7 -6
- package/src/loupe/LoupeGestures.tsx +14 -9
- package/src/loupe/TrialLoupe.tsx +5 -5
- package/src/loupe/index.ts +1 -0
- package/src/loupe/loupeActions.ts +6 -2
- package/src/overview/AGENTS.md +38 -0
- package/src/overview/OverviewMarks.test.tsx +100 -0
- package/src/overview/OverviewMarks.tsx +93 -0
- package/src/overview/TrialOverview.less +53 -0
- package/src/overview/TrialOverview.stories.tsx +50 -0
- package/src/overview/TrialOverview.test.tsx +116 -0
- package/src/overview/TrialOverview.tsx +374 -0
- package/src/overview/index.ts +2 -0
- package/src/passthrough/weasel-ui.ts +32 -10
- package/src/primitives/index.ts +0 -2
- package/src/specimen/Specimen.tsx +59 -56
- package/src/state/labRecords.test.ts +4 -1
- package/src/state/store.test.ts +4 -4
- package/src/state/types.ts +2 -1
- package/src/state/useTrialState.test.tsx +1 -1
- package/src/styles.less +6 -2
- package/src/theme/Interstellar.stories.tsx +8 -13
- package/src/theme/base.less +3 -20
- package/src/theme/interstellar.test.ts +6 -3
- package/src/theme/interstellar.theme.json +0 -56
- package/src/theme/interstellar.ts +2 -2
- package/src/tools/labTool.ts +6 -2
- package/src/trial/Trial.annotations.test.tsx +16 -0
- package/src/trial/Trial.canvas.test.tsx +1 -1
- package/src/trial/Trial.loupe.test.tsx +73 -1
- package/src/trial/Trial.stories.tsx +2 -0
- package/src/trial/Trial.tsx +47 -9
- package/src/trial/trialOps.test.ts +4 -4
- package/dist/_dts/index-8LiKe3A-.d.ts +0 -410
- package/dist/chunk-2AYGEN57.js +0 -32
- package/dist/chunk-2AYGEN57.js.map +0 -1
- package/dist/chunk-6BUQ77ZV.js +0 -18
- package/dist/chunk-6BUQ77ZV.js.map +0 -1
- package/dist/chunk-753Y6HE6.js.map +0 -1
- package/dist/chunk-A2ACAGW6.js.map +0 -1
- package/dist/chunk-CKUKF72R.js.map +0 -1
- package/dist/chunk-D35PFTS7.js +0 -170
- package/dist/chunk-D35PFTS7.js.map +0 -1
- package/dist/chunk-EMXAIRUJ.js.map +0 -1
- package/dist/chunk-ERFMC6WU.js.map +0 -1
- package/dist/chunk-FKLT3ITC.js +0 -590
- package/dist/chunk-FKLT3ITC.js.map +0 -1
- package/dist/chunk-KJCUERQF.js.map +0 -1
- package/dist/chunk-LASCBWW7.js +0 -13456
- package/dist/chunk-LASCBWW7.js.map +0 -1
- package/dist/chunk-REOBGYMC.js.map +0 -1
- package/dist/chunk-RS3HRQWU.js.map +0 -1
- package/dist/chunk-TT5C5S6R.js +0 -368
- package/dist/chunk-TT5C5S6R.js.map +0 -1
- package/dist/ui/layers/index.d.ts +0 -66
- package/dist/ui/layers/index.js +0 -3
- package/dist/ui/layers/index.js.map +0 -1
- package/src/canvas/usePanZoom.test.ts +0 -244
- package/src/canvas/usePanZoom.ts +0 -147
- package/src/lab/useSystemMode.ts +0 -30
- package/src/layers/LayerList.less +0 -93
- package/src/layers/LayerList.stories.tsx +0 -66
- package/src/layers/LayerList.test.tsx +0 -232
- package/src/layers/LayerList.tsx +0 -268
- package/src/primitives/Sidebar.less +0 -112
- package/src/primitives/Sidebar.stories.tsx +0 -38
- package/src/primitives/Sidebar.test.tsx +0 -74
- package/src/primitives/Sidebar.tsx +0 -35
- package/src/ui/layers/index.ts +0 -5
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import type { FillStyle, GradientFill, Track } from '@weasel-js/core';
|
|
2
2
|
import {
|
|
3
|
-
ActionsBar,
|
|
4
3
|
Badge,
|
|
5
4
|
type Band,
|
|
6
5
|
BandEditor,
|
|
7
6
|
Button,
|
|
7
|
+
ButtonBar,
|
|
8
8
|
Callout,
|
|
9
9
|
Checkbox,
|
|
10
|
-
CheckboxRow,
|
|
11
10
|
ColorField,
|
|
12
|
-
ColorRow,
|
|
13
11
|
ComboBox,
|
|
14
12
|
type ControlPoint,
|
|
15
13
|
CurveEditor,
|
|
@@ -24,11 +22,11 @@ import {
|
|
|
24
22
|
ItemList,
|
|
25
23
|
KeyCap,
|
|
26
24
|
KeySequence,
|
|
27
|
-
|
|
28
|
-
type
|
|
25
|
+
LayerList,
|
|
26
|
+
type LayerListItem,
|
|
29
27
|
MenuButton,
|
|
28
|
+
moveLayers,
|
|
30
29
|
NumberField,
|
|
31
|
-
NumberRow,
|
|
32
30
|
OptionsBar,
|
|
33
31
|
PaintInput,
|
|
34
32
|
Plot2D,
|
|
@@ -36,6 +34,7 @@ import {
|
|
|
36
34
|
Powerline,
|
|
37
35
|
type PrefGroup,
|
|
38
36
|
PrefsForm,
|
|
37
|
+
PropertyField,
|
|
39
38
|
PropertyGroup,
|
|
40
39
|
PropertyList,
|
|
41
40
|
PropertyPanel,
|
|
@@ -44,10 +43,9 @@ import {
|
|
|
44
43
|
RangeSlider,
|
|
45
44
|
ResizeHandle,
|
|
46
45
|
Select,
|
|
47
|
-
|
|
46
|
+
Sidebar,
|
|
48
47
|
SidebarPanel,
|
|
49
48
|
Slider,
|
|
50
|
-
SliderRow,
|
|
51
49
|
StatusBarItem,
|
|
52
50
|
StatusBarSpacer,
|
|
53
51
|
Switch,
|
|
@@ -55,18 +53,15 @@ import {
|
|
|
55
53
|
TabList,
|
|
56
54
|
TabPanel,
|
|
57
55
|
Tabs,
|
|
58
|
-
TextRow,
|
|
59
56
|
type Thumb,
|
|
60
57
|
Timeline,
|
|
61
58
|
ToastRegion,
|
|
62
59
|
ToggleBar,
|
|
63
|
-
ToggleRow,
|
|
64
60
|
ToolButton,
|
|
65
61
|
ToolGroup,
|
|
66
62
|
ToolOptionsBar,
|
|
67
63
|
Tooltip,
|
|
68
64
|
TooltipTrigger,
|
|
69
|
-
Sidebar as UiSidebar,
|
|
70
65
|
StatusBar as UiStatusBar,
|
|
71
66
|
} from '@weasel-js/ui';
|
|
72
67
|
import { type CSSProperties, type ReactNode, useId, useMemo, useRef, useState } from 'react';
|
|
@@ -76,7 +71,6 @@ import { FloatingPanel } from '../primitives/FloatingPanel';
|
|
|
76
71
|
import { JobProgress } from '../primitives/JobProgress';
|
|
77
72
|
import { Legend, type LegendEntry } from '../primitives/Legend';
|
|
78
73
|
import { ScaleIndicator } from '../primitives/ScaleIndicator';
|
|
79
|
-
import { Sidebar } from '../primitives/Sidebar';
|
|
80
74
|
import { Split } from '../primitives/Split';
|
|
81
75
|
import { StatusBar } from '../primitives/StatusBar';
|
|
82
76
|
import { Toolbar } from '../primitives/Toolbar';
|
|
@@ -213,19 +207,19 @@ function ButtonsAndToggles() {
|
|
|
213
207
|
</Cell>
|
|
214
208
|
<Cell label="Badge">
|
|
215
209
|
<div className="lk-specimen__row">
|
|
216
|
-
<Badge shape="pill"
|
|
210
|
+
<Badge shape="pill" status="accent" variant="outline" size="sm">
|
|
217
211
|
ACCENT
|
|
218
212
|
</Badge>
|
|
219
|
-
<Badge
|
|
213
|
+
<Badge status="info" variant="subtle">
|
|
220
214
|
INFO
|
|
221
215
|
</Badge>
|
|
222
|
-
<Badge
|
|
216
|
+
<Badge status="warn" variant="solid">
|
|
223
217
|
WARN
|
|
224
218
|
</Badge>
|
|
225
|
-
<Badge
|
|
219
|
+
<Badge status="danger" variant="solid">
|
|
226
220
|
DANGER
|
|
227
221
|
</Badge>
|
|
228
|
-
<Badge
|
|
222
|
+
<Badge status="muted">MUTED</Badge>
|
|
229
223
|
</div>
|
|
230
224
|
</Cell>
|
|
231
225
|
<Cell label="Checkbox, Switch">
|
|
@@ -269,7 +263,7 @@ function ButtonsAndToggles() {
|
|
|
269
263
|
]}
|
|
270
264
|
/>
|
|
271
265
|
</Cell>
|
|
272
|
-
<Cell label="OptionsBar,
|
|
266
|
+
<Cell label="OptionsBar, ButtonBar">
|
|
273
267
|
<div className="lk-specimen__row">
|
|
274
268
|
<OptionsBar
|
|
275
269
|
ariaLabel="Text style"
|
|
@@ -278,7 +272,7 @@ function ButtonsAndToggles() {
|
|
|
278
272
|
{ value: 'i', label: 'I', selected: italic, onChange: setItalic },
|
|
279
273
|
]}
|
|
280
274
|
/>
|
|
281
|
-
<
|
|
275
|
+
<ButtonBar
|
|
282
276
|
items={[
|
|
283
277
|
{ value: 'undo', label: 'Undo', onAction: () => {} },
|
|
284
278
|
{ value: 'redo', label: 'Redo', onAction: () => {} },
|
|
@@ -297,7 +291,6 @@ function ButtonsAndToggles() {
|
|
|
297
291
|
]}
|
|
298
292
|
/>
|
|
299
293
|
<Disclosure open={open} onToggle={() => setOpen((o) => !o)} label="Shapes" />
|
|
300
|
-
<Disclosure open={false} onToggle={() => {}} label="Down" direction="down" />
|
|
301
294
|
</div>
|
|
302
295
|
</Cell>
|
|
303
296
|
<Cell label="Tabs">
|
|
@@ -436,7 +429,7 @@ function PanelsAndRows() {
|
|
|
436
429
|
const [label, setLabel] = useState('Badge');
|
|
437
430
|
const [visible, setVisible] = useState(true);
|
|
438
431
|
const [prefs, setPrefs] = useState<Record<string, unknown>>({});
|
|
439
|
-
const [layers, setLayers] = useState<
|
|
432
|
+
const [layers, setLayers] = useState<LayerListItem[]>([
|
|
440
433
|
{ id: 'base', label: 'Base coat' },
|
|
441
434
|
{ id: 'wash', label: 'Wash' },
|
|
442
435
|
]);
|
|
@@ -446,7 +439,9 @@ function PanelsAndRows() {
|
|
|
446
439
|
<Cell label="PropertyPanel">
|
|
447
440
|
<PropertyPanel title="Shape">
|
|
448
441
|
<PropertyList>
|
|
449
|
-
<
|
|
442
|
+
<PropertyField
|
|
443
|
+
kind="number"
|
|
444
|
+
control="slider"
|
|
450
445
|
label="Opacity"
|
|
451
446
|
value={opacity}
|
|
452
447
|
min={0}
|
|
@@ -454,7 +449,9 @@ function PanelsAndRows() {
|
|
|
454
449
|
step={0.01}
|
|
455
450
|
onChange={setOpacity}
|
|
456
451
|
/>
|
|
457
|
-
<
|
|
452
|
+
<PropertyField
|
|
453
|
+
kind="number"
|
|
454
|
+
control="slider"
|
|
458
455
|
label="Radius"
|
|
459
456
|
value={radius}
|
|
460
457
|
min={0}
|
|
@@ -462,16 +459,26 @@ function PanelsAndRows() {
|
|
|
462
459
|
unit="px"
|
|
463
460
|
onChange={setRadius}
|
|
464
461
|
/>
|
|
465
|
-
<
|
|
462
|
+
<PropertyField
|
|
463
|
+
kind="color"
|
|
466
464
|
label="Fill"
|
|
467
465
|
value={fill}
|
|
468
466
|
onChange={setFill}
|
|
469
467
|
alpha={alpha}
|
|
470
468
|
onAlphaChange={setAlpha}
|
|
471
469
|
/>
|
|
472
|
-
<
|
|
473
|
-
<
|
|
474
|
-
|
|
470
|
+
<PropertyField kind="color" label="Stroke" value={stroke} onChange={setStroke} />
|
|
471
|
+
<PropertyField
|
|
472
|
+
kind="number"
|
|
473
|
+
label="Count"
|
|
474
|
+
value={count}
|
|
475
|
+
min={0}
|
|
476
|
+
max={100}
|
|
477
|
+
step={1}
|
|
478
|
+
onChange={setCount}
|
|
479
|
+
/>
|
|
480
|
+
<PropertyField
|
|
481
|
+
kind="enum"
|
|
475
482
|
label="Line cap"
|
|
476
483
|
value={cap}
|
|
477
484
|
onChange={setCap}
|
|
@@ -480,7 +487,9 @@ function PanelsAndRows() {
|
|
|
480
487
|
{ value: 'round', label: 'Round' },
|
|
481
488
|
]}
|
|
482
489
|
/>
|
|
483
|
-
<
|
|
490
|
+
<PropertyField
|
|
491
|
+
kind="enum"
|
|
492
|
+
control="toggle"
|
|
484
493
|
label="Align"
|
|
485
494
|
value={side}
|
|
486
495
|
onChange={setSide}
|
|
@@ -490,10 +499,19 @@ function PanelsAndRows() {
|
|
|
490
499
|
{ value: 'right', label: 'R' },
|
|
491
500
|
]}
|
|
492
501
|
/>
|
|
493
|
-
<
|
|
494
|
-
<
|
|
502
|
+
<PropertyField kind="string" label="Label" value={label} onChange={setLabel} />
|
|
503
|
+
<PropertyField kind="boolean" label="Visible" value={visible} onChange={setVisible} />
|
|
495
504
|
<PropertyGroup title="Bevel" defaultCollapsed>
|
|
496
|
-
<
|
|
505
|
+
<PropertyField
|
|
506
|
+
kind="number"
|
|
507
|
+
control="slider"
|
|
508
|
+
label="Rings"
|
|
509
|
+
value={32}
|
|
510
|
+
min={4}
|
|
511
|
+
max={96}
|
|
512
|
+
step={1}
|
|
513
|
+
onChange={() => {}}
|
|
514
|
+
/>
|
|
497
515
|
</PropertyGroup>
|
|
498
516
|
</PropertyList>
|
|
499
517
|
</PropertyPanel>
|
|
@@ -505,18 +523,16 @@ function PanelsAndRows() {
|
|
|
505
523
|
onChange={(path, value) => setPrefs((prev) => setAt(prev, path, value))}
|
|
506
524
|
/>
|
|
507
525
|
</Cell>
|
|
508
|
-
<Cell label="
|
|
509
|
-
<
|
|
526
|
+
<Cell label="LayerList">
|
|
527
|
+
<LayerList
|
|
510
528
|
items={layers}
|
|
511
|
-
onReorder={(
|
|
512
|
-
setLayers(ids.flatMap((id) => layers.filter((item) => item.id === id)))
|
|
513
|
-
}
|
|
529
|
+
onReorder={(move) => setLayers(moveLayers(layers, move))}
|
|
514
530
|
renderBody={(item) => <div>settings for {item.label}</div>}
|
|
515
531
|
/>
|
|
516
532
|
</Cell>
|
|
517
533
|
<Cell label="Sidebar, SidebarPanel">
|
|
518
534
|
<div className="lk-specimen__box">
|
|
519
|
-
<
|
|
535
|
+
<Sidebar side="right" ariaLabel="Specimen sidebar">
|
|
520
536
|
<SidebarPanel
|
|
521
537
|
title="Selection"
|
|
522
538
|
collapsed={panelCollapsed}
|
|
@@ -525,7 +541,7 @@ function PanelsAndRows() {
|
|
|
525
541
|
>
|
|
526
542
|
<div className="lk-specimen__pad">2 items selected</div>
|
|
527
543
|
</SidebarPanel>
|
|
528
|
-
</
|
|
544
|
+
</Sidebar>
|
|
529
545
|
</div>
|
|
530
546
|
</Cell>
|
|
531
547
|
</Section>
|
|
@@ -554,8 +570,8 @@ function OverlaysAndFeedback() {
|
|
|
554
570
|
triggerRef={calloutAnchor}
|
|
555
571
|
isOpen={calloutOpen}
|
|
556
572
|
onOpenChange={setCalloutOpen}
|
|
557
|
-
|
|
558
|
-
title="
|
|
573
|
+
stance="notice"
|
|
574
|
+
title="Notice"
|
|
559
575
|
>
|
|
560
576
|
Neutral guidance.
|
|
561
577
|
</Callout>
|
|
@@ -587,9 +603,9 @@ function OverlaysAndFeedback() {
|
|
|
587
603
|
variant="solid"
|
|
588
604
|
size="sm"
|
|
589
605
|
segments={[
|
|
590
|
-
{ text: 'main',
|
|
591
|
-
{ text: '✓ 12',
|
|
592
|
-
{ text: '~/proj',
|
|
606
|
+
{ text: 'main', status: 'accent', endCap: 'chevron' },
|
|
607
|
+
{ text: '✓ 12', status: 'info', endCap: 'slant' },
|
|
608
|
+
{ text: '~/proj', status: 'muted' },
|
|
593
609
|
]}
|
|
594
610
|
/>
|
|
595
611
|
</Cell>
|
|
@@ -799,7 +815,6 @@ function EditorsAndPlots() {
|
|
|
799
815
|
}
|
|
800
816
|
|
|
801
817
|
function LabChrome() {
|
|
802
|
-
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
|
|
803
818
|
const [zoom, setZoom] = useState(1);
|
|
804
819
|
return (
|
|
805
820
|
<Section title="Lab chrome">
|
|
@@ -823,18 +838,6 @@ function LabChrome() {
|
|
|
823
838
|
<StatusBar.Section>Zoom: 100%</StatusBar.Section>
|
|
824
839
|
</StatusBar>
|
|
825
840
|
</Cell>
|
|
826
|
-
<Cell label="Sidebar">
|
|
827
|
-
<div className="lk-specimen__box">
|
|
828
|
-
<div className="lk-specimen__box-main">main</div>
|
|
829
|
-
<Sidebar
|
|
830
|
-
title="Controls"
|
|
831
|
-
collapsed={sidebarCollapsed}
|
|
832
|
-
onToggle={() => setSidebarCollapsed((v) => !v)}
|
|
833
|
-
>
|
|
834
|
-
<p>One slider</p>
|
|
835
|
-
</Sidebar>
|
|
836
|
-
</div>
|
|
837
|
-
</Cell>
|
|
838
841
|
<Cell label="Legend, JobProgress">
|
|
839
842
|
<Legend entries={LEGEND} />
|
|
840
843
|
<JobProgress job={JOB} />
|
|
@@ -96,7 +96,10 @@ describe('documents and records', () => {
|
|
|
96
96
|
['trial:z', { instrumentName: 'T', order: 0 }],
|
|
97
97
|
['trial:m', { instrumentName: 'T', order: 0 }],
|
|
98
98
|
]);
|
|
99
|
-
expect((joined?.doc.trials as { id: string }[])
|
|
99
|
+
expect((joined?.doc.trials as { id: string }[] | undefined)?.map((t) => t.id)).toEqual([
|
|
100
|
+
'm',
|
|
101
|
+
'z',
|
|
102
|
+
]);
|
|
100
103
|
});
|
|
101
104
|
|
|
102
105
|
it('is null without a meta record', () => {
|
package/src/state/store.test.ts
CHANGED
|
@@ -84,7 +84,7 @@ describe('updateTrialState', () => {
|
|
|
84
84
|
s.getState().updateTrialState('w1', (prev: unknown) => ({
|
|
85
85
|
n: (prev as { n: number }).n + 1,
|
|
86
86
|
}));
|
|
87
|
-
expect((s.getState().trials[0]?.state as { n: number })
|
|
87
|
+
expect((s.getState().trials[0]?.state as { n: number } | undefined)?.n).toBe(2);
|
|
88
88
|
});
|
|
89
89
|
});
|
|
90
90
|
|
|
@@ -99,8 +99,8 @@ describe('updateTrialConfig', () => {
|
|
|
99
99
|
view: { zoom: 1, pan: { x: 0, y: 0 } },
|
|
100
100
|
});
|
|
101
101
|
s.getState().updateTrialConfig('w1', 'x', 99);
|
|
102
|
-
expect((s.getState().trials[0]?.config as { x: number })
|
|
103
|
-
expect((s.getState().trials[0]?.config as { y: number })
|
|
102
|
+
expect((s.getState().trials[0]?.config as { x: number } | undefined)?.x).toBe(99);
|
|
103
|
+
expect((s.getState().trials[0]?.config as { y: number } | undefined)?.y).toBe(2);
|
|
104
104
|
});
|
|
105
105
|
|
|
106
106
|
it('writes down a dotted path without disturbing its siblings', () => {
|
|
@@ -161,7 +161,7 @@ describe('save/load/delete snapshots', () => {
|
|
|
161
161
|
s.getState().updateTrialState('w1', { n: 99 });
|
|
162
162
|
const snapId = s.getState().savedSnapshots[0]?.id ?? '';
|
|
163
163
|
s.getState().loadSnapshot(snapId, 'w1');
|
|
164
|
-
expect((s.getState().trials[0]?.state as { n: number })
|
|
164
|
+
expect((s.getState().trials[0]?.state as { n: number } | undefined)?.n).toBe(5);
|
|
165
165
|
});
|
|
166
166
|
|
|
167
167
|
it('loadSnapshot restores the auto paths the trial had when saved', () => {
|
package/src/state/types.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ColorModePreference } from '@weasel-js/theme';
|
|
1
2
|
import type { Auto } from '../config/auto';
|
|
2
3
|
import type { ConfigPath, ResolvedConfig, ValueAtPath } from '../config/types';
|
|
3
4
|
import type { InstrumentList } from '../instrument/types';
|
|
@@ -78,7 +79,7 @@ export interface SavedSnapshot {
|
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
/** `auto` follows the OS; the other two are an explicit choice. */
|
|
81
|
-
export type LabMode =
|
|
82
|
+
export type LabMode = ColorModePreference;
|
|
82
83
|
|
|
83
84
|
/** How much room the lab's own chrome takes — the theme's density axis, named
|
|
84
85
|
* the way the theme names it. A lab's instruments are unaffected: this sizes
|
|
@@ -173,7 +173,7 @@ describe('auto paths', () => {
|
|
|
173
173
|
store.getState().updateTrialConfig('w1', 'gap', 30);
|
|
174
174
|
const rec = store.getState().trials[0];
|
|
175
175
|
expect(rec?.auto).toBeUndefined();
|
|
176
|
-
expect((rec?.config as { gap: number })
|
|
176
|
+
expect((rec?.config as { gap: number } | undefined)?.gap).toBe(30);
|
|
177
177
|
});
|
|
178
178
|
|
|
179
179
|
it('does not allocate a new record when the path is already auto', () => {
|
package/src/styles.less
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
// Imports compile-time only. Component .less files are added in later steps.
|
|
2
|
+
// Left as a CSS @import for the consumer's bundler to resolve; build-css.mjs
|
|
3
|
+
// swaps it for the faces themselves, pointed at dist/fonts/.
|
|
4
|
+
@import (css) '@weasel-js/theme/faces.css';
|
|
2
5
|
@import './theme/base.less';
|
|
3
6
|
@import './lab/Workspace.less';
|
|
4
7
|
@import './lab/LabShell.less';
|
|
5
8
|
@import './lab/LabSwitcher.less';
|
|
6
9
|
@import './primitives/Toolbar.less';
|
|
7
|
-
@import './primitives/Sidebar.less';
|
|
8
10
|
@import './primitives/Split.less';
|
|
9
11
|
@import './primitives/ZoomControl.less';
|
|
10
12
|
@import './primitives/StatusBar.less';
|
|
@@ -17,11 +19,13 @@
|
|
|
17
19
|
@import './trial/Trial.less';
|
|
18
20
|
@import './chrome/regions/ViewportRegion.less';
|
|
19
21
|
@import './chrome/regions/PaletteRegion.less';
|
|
22
|
+
@import './chrome/regions/SidebarRegion.less';
|
|
20
23
|
@import './controls/ControlPanel.less';
|
|
21
24
|
@import './canvas/CanvasStack.less';
|
|
22
25
|
@import './canvas/Stage.less';
|
|
26
|
+
@import './canvas/LinkedCursor.less';
|
|
27
|
+
@import './overview/TrialOverview.less';
|
|
23
28
|
@import './loupe/Loupe.less';
|
|
24
|
-
@import './layers/LayerList.less';
|
|
25
29
|
@import './annotations/Annotations.less';
|
|
26
30
|
@import './dragdrop/Palette.less';
|
|
27
31
|
@import './dragdrop/DragGhost.less';
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@weasel-js/forge';
|
|
2
2
|
import type { TokenName } from '@weasel-js/theme';
|
|
3
3
|
import { useTheme } from '@weasel-js/theme/react';
|
|
4
|
-
import {
|
|
5
|
-
CheckboxRow,
|
|
6
|
-
ColorRow,
|
|
7
|
-
PropertyList,
|
|
8
|
-
PropertyPanel,
|
|
9
|
-
SliderRow,
|
|
10
|
-
TextRow,
|
|
11
|
-
} from '@weasel-js/ui';
|
|
4
|
+
import { PropertyField, PropertyList, PropertyPanel } from '@weasel-js/ui';
|
|
12
5
|
import './Interstellar.stories.less';
|
|
13
6
|
|
|
14
7
|
const meta: Meta = {
|
|
@@ -148,7 +141,9 @@ function LivePanelPreview() {
|
|
|
148
141
|
<h3 className="lk-theme-doc__heading">Live panel</h3>
|
|
149
142
|
<PropertyPanel title="Sample">
|
|
150
143
|
<PropertyList>
|
|
151
|
-
<
|
|
144
|
+
<PropertyField
|
|
145
|
+
kind="number"
|
|
146
|
+
control="slider"
|
|
152
147
|
label="Opacity"
|
|
153
148
|
value={0.65}
|
|
154
149
|
min={0}
|
|
@@ -157,10 +152,10 @@ function LivePanelPreview() {
|
|
|
157
152
|
onChange={() => {}}
|
|
158
153
|
format={(v) => v.toFixed(2)}
|
|
159
154
|
/>
|
|
160
|
-
<
|
|
161
|
-
<
|
|
162
|
-
<
|
|
163
|
-
<
|
|
155
|
+
<PropertyField kind="color" label="Fill" value="#b08adb" onChange={() => {}} />
|
|
156
|
+
<PropertyField kind="color" label="Stroke" value="#1a1428" onChange={() => {}} />
|
|
157
|
+
<PropertyField kind="string" label="Name" value="Untitled" onChange={() => {}} />
|
|
158
|
+
<PropertyField kind="boolean" label="Visible" value={true} onChange={() => {}} />
|
|
164
159
|
</PropertyList>
|
|
165
160
|
</PropertyPanel>
|
|
166
161
|
</div>
|
package/src/theme/base.less
CHANGED
|
@@ -1,25 +1,8 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
@font-face {
|
|
4
|
-
font-family: 'Oswald';
|
|
5
|
-
font-style: normal;
|
|
6
|
-
font-weight: 200 700;
|
|
7
|
-
font-display: swap;
|
|
8
|
-
// URL is resolved relative to the COMPILED stylesheet at dist/styles.css,
|
|
9
|
-
// so this points to dist/fonts/. Source-tree usage (less compilation
|
|
10
|
-
// happens before the file is moved) doesn't need to resolve the URL.
|
|
11
|
-
src: url('./fonts/oswald-latin-variable.woff2') format('woff2');
|
|
12
|
-
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
|
|
13
|
-
U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
|
|
14
|
-
U+2212, U+2215, U+FEFF, U+FFFD;
|
|
15
|
-
}
|
|
1
|
+
// The Oswald and Inter faces come from @weasel-js/theme/faces.css, imported at
|
|
2
|
+
// the top of styles.less.
|
|
16
3
|
|
|
17
4
|
// Resets and global element defaults.
|
|
18
5
|
.lk-root {
|
|
19
|
-
// labkit's own vocabulary over the theme's raw scale — named for the thing
|
|
20
|
-
// rather than the step, so "the workspace is too tight" has one place to go.
|
|
21
|
-
--lk-workspace-pad: var(--wzl-space-sm);
|
|
22
|
-
|
|
23
6
|
font-family: var(--wzl-font-ui);
|
|
24
7
|
font-size: var(--wzl-font-size);
|
|
25
8
|
font-weight: var(--wzl-font-weight-light);
|
|
@@ -52,7 +35,7 @@
|
|
|
52
35
|
|
|
53
36
|
&:hover {
|
|
54
37
|
border-color: var(--wzl-accent);
|
|
55
|
-
color: var(--wzl-accent);
|
|
38
|
+
color: var(--wzl-accent-fg);
|
|
56
39
|
}
|
|
57
40
|
|
|
58
41
|
&:focus-visible {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { resolveTheme, THEME_SOURCES, type ThemeDefinition } from '@weasel-js/theme';
|
|
1
|
+
import { resolveTheme, THEME_SOURCES, type ThemeDefinition, weaselTheme } from '@weasel-js/theme';
|
|
2
2
|
import { derive } from '@weasel-js/theme/engine';
|
|
3
3
|
import { describe, expect, it } from 'vitest';
|
|
4
4
|
import { interstellarTheme } from './interstellar';
|
|
@@ -19,8 +19,11 @@ describe('interstellarTheme', () => {
|
|
|
19
19
|
// Values carried over verbatim from the retired Less.
|
|
20
20
|
expect(dark['--wzl-surface']).toBe('#0a0a14');
|
|
21
21
|
expect(dark['--wzl-accent']).toBe('#b08adb');
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
// Light mode is weasel's own: interstellar restyles the dark only.
|
|
23
|
+
const weasel = resolveTheme(weaselTheme, { mode: 'light' });
|
|
24
|
+
expect(light['--wzl-surface']).toBe(weasel['--wzl-surface']);
|
|
25
|
+
expect(light['--wzl-accent']).toBe(weasel['--wzl-accent']);
|
|
26
|
+
expect(light['--wzl-border']).toBe(weasel['--wzl-border']);
|
|
24
27
|
|
|
25
28
|
// Inherited from weasel — interstellar overrides values, not the token set.
|
|
26
29
|
expect(dark['--wzl-space-md']).toBe('12px');
|
|
@@ -27,10 +27,6 @@
|
|
|
27
27
|
"dark": {
|
|
28
28
|
"value": "#0a0a14",
|
|
29
29
|
"type": "color"
|
|
30
|
-
},
|
|
31
|
-
"light": {
|
|
32
|
-
"value": "#fafaf7",
|
|
33
|
-
"type": "color"
|
|
34
30
|
}
|
|
35
31
|
},
|
|
36
32
|
"surface-raised": {
|
|
@@ -38,10 +34,6 @@
|
|
|
38
34
|
"dark": {
|
|
39
35
|
"value": "rgba(20, 20, 36, 0.55)",
|
|
40
36
|
"type": "color"
|
|
41
|
-
},
|
|
42
|
-
"light": {
|
|
43
|
-
"value": "#ffffff",
|
|
44
|
-
"type": "color"
|
|
45
37
|
}
|
|
46
38
|
},
|
|
47
39
|
"surface-sunken": {
|
|
@@ -49,10 +41,6 @@
|
|
|
49
41
|
"dark": {
|
|
50
42
|
"value": "#02020a",
|
|
51
43
|
"type": "color"
|
|
52
|
-
},
|
|
53
|
-
"light": {
|
|
54
|
-
"value": "#f0ebe2",
|
|
55
|
-
"type": "color"
|
|
56
44
|
}
|
|
57
45
|
},
|
|
58
46
|
"border": {
|
|
@@ -60,10 +48,6 @@
|
|
|
60
48
|
"dark": {
|
|
61
49
|
"value": "rgba(255, 255, 255, 0.14)",
|
|
62
50
|
"type": "color"
|
|
63
|
-
},
|
|
64
|
-
"light": {
|
|
65
|
-
"value": "#c9bba5",
|
|
66
|
-
"type": "color"
|
|
67
51
|
}
|
|
68
52
|
},
|
|
69
53
|
"line-subtle": {
|
|
@@ -71,10 +55,6 @@
|
|
|
71
55
|
"dark": {
|
|
72
56
|
"value": "rgba(255, 255, 255, 0.08)",
|
|
73
57
|
"type": "color"
|
|
74
|
-
},
|
|
75
|
-
"light": {
|
|
76
|
-
"value": "rgba(0, 0, 0, 0.08)",
|
|
77
|
-
"type": "color"
|
|
78
58
|
}
|
|
79
59
|
},
|
|
80
60
|
"fg": {
|
|
@@ -82,10 +62,6 @@
|
|
|
82
62
|
"dark": {
|
|
83
63
|
"value": "#e8e8f0",
|
|
84
64
|
"type": "color"
|
|
85
|
-
},
|
|
86
|
-
"light": {
|
|
87
|
-
"value": "#2a2018",
|
|
88
|
-
"type": "color"
|
|
89
65
|
}
|
|
90
66
|
},
|
|
91
67
|
"fg-muted": {
|
|
@@ -93,10 +69,6 @@
|
|
|
93
69
|
"dark": {
|
|
94
70
|
"value": "#a8a8c0",
|
|
95
71
|
"type": "color"
|
|
96
|
-
},
|
|
97
|
-
"light": {
|
|
98
|
-
"value": "#6b5c4a",
|
|
99
|
-
"type": "color"
|
|
100
72
|
}
|
|
101
73
|
},
|
|
102
74
|
"fg-subtle": {
|
|
@@ -104,10 +76,6 @@
|
|
|
104
76
|
"dark": {
|
|
105
77
|
"value": "#5a5a78",
|
|
106
78
|
"type": "color"
|
|
107
|
-
},
|
|
108
|
-
"light": {
|
|
109
|
-
"value": "#a89b85",
|
|
110
|
-
"type": "color"
|
|
111
79
|
}
|
|
112
80
|
},
|
|
113
81
|
"accent": {
|
|
@@ -115,10 +83,6 @@
|
|
|
115
83
|
"dark": {
|
|
116
84
|
"value": "#b08adb",
|
|
117
85
|
"type": "color"
|
|
118
|
-
},
|
|
119
|
-
"light": {
|
|
120
|
-
"value": "#a86f3c",
|
|
121
|
-
"type": "color"
|
|
122
86
|
}
|
|
123
87
|
},
|
|
124
88
|
"accent-hover": {
|
|
@@ -126,10 +90,6 @@
|
|
|
126
90
|
"dark": {
|
|
127
91
|
"value": "#c6a3ee",
|
|
128
92
|
"type": "color"
|
|
129
|
-
},
|
|
130
|
-
"light": {
|
|
131
|
-
"value": "#c2854f",
|
|
132
|
-
"type": "color"
|
|
133
93
|
}
|
|
134
94
|
},
|
|
135
95
|
"focus-ring": {
|
|
@@ -137,10 +97,6 @@
|
|
|
137
97
|
"dark": {
|
|
138
98
|
"value": "rgba(176, 138, 219, 0.45)",
|
|
139
99
|
"type": "color"
|
|
140
|
-
},
|
|
141
|
-
"light": {
|
|
142
|
-
"value": "rgba(168, 111, 60, 0.35)",
|
|
143
|
-
"type": "color"
|
|
144
100
|
}
|
|
145
101
|
},
|
|
146
102
|
"shadow": {
|
|
@@ -148,10 +104,6 @@
|
|
|
148
104
|
"dark": {
|
|
149
105
|
"value": "rgba(0, 0, 0, 0.7)",
|
|
150
106
|
"type": "color"
|
|
151
|
-
},
|
|
152
|
-
"light": {
|
|
153
|
-
"value": "rgba(80, 60, 40, 0.18)",
|
|
154
|
-
"type": "color"
|
|
155
107
|
}
|
|
156
108
|
},
|
|
157
109
|
"border-strong": {
|
|
@@ -159,10 +111,6 @@
|
|
|
159
111
|
"dark": {
|
|
160
112
|
"value": "rgba(255, 255, 255, 0.36)",
|
|
161
113
|
"type": "color"
|
|
162
|
-
},
|
|
163
|
-
"light": {
|
|
164
|
-
"value": "#9e8b71",
|
|
165
|
-
"type": "color"
|
|
166
114
|
}
|
|
167
115
|
},
|
|
168
116
|
"backdrop": {
|
|
@@ -170,10 +118,6 @@
|
|
|
170
118
|
"dark": {
|
|
171
119
|
"value": "radial-gradient(ellipse 60% 80% at 18% 30%, rgba(150, 80, 200, 0.22), transparent 70%), radial-gradient(ellipse 55% 90% at 78% 70%, rgba(220, 100, 140, 0.18), transparent 65%), radial-gradient(ellipse 50% 70% at 50% 50%, rgba(60, 110, 200, 0.18), transparent 75%), radial-gradient(ellipse at center, #0a0a18 0%, #02020a 100%)",
|
|
172
120
|
"type": "gradient"
|
|
173
|
-
},
|
|
174
|
-
"light": {
|
|
175
|
-
"value": "none",
|
|
176
|
-
"type": "gradient"
|
|
177
121
|
}
|
|
178
122
|
}
|
|
179
123
|
}
|
|
@@ -2,8 +2,8 @@ import { defineTheme, type Theme, type ThemeInput, weaselTheme } from '@weasel-j
|
|
|
2
2
|
import definition from './interstellar.theme.json' with { type: 'json' };
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* labkit's theme: a cosmic dark
|
|
6
|
-
*
|
|
5
|
+
* labkit's theme: a cosmic dark over the built-in weasel theme, whose light
|
|
6
|
+
* mode it keeps as is. A pins-only theme definition: nothing in it is
|
|
7
7
|
* derived, so it loads without the engine.
|
|
8
8
|
*/
|
|
9
9
|
export const interstellarTheme: Theme = defineTheme({
|
package/src/tools/labTool.ts
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
import { labAnnotationTools } from '../annotations/toolMap';
|
|
1
2
|
import type { InstrumentList } from '../instrument/types';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* The tool the lab's slot holds, once its default is applied: a lab with any
|
|
5
6
|
* annotating instrument starts in `pointer`, so a first click reaches the
|
|
6
|
-
* instrument rather than the marks over it
|
|
7
|
+
* instrument rather than the marks over it, or in the first annotation tool
|
|
8
|
+
* its rail carries when `pointer` is not among them.
|
|
7
9
|
*/
|
|
8
10
|
export function resolveLabTool(slot: string | null, instruments: InstrumentList): string | null {
|
|
9
11
|
if (slot !== null) return slot;
|
|
10
|
-
|
|
12
|
+
const tools = labAnnotationTools(instruments);
|
|
13
|
+
if (tools.some((t) => t.id === 'pointer')) return 'pointer';
|
|
14
|
+
return tools[0]?.id ?? null;
|
|
11
15
|
}
|