@weasel-js/labkit 1.5.1 → 1.6.0
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-CJNMS6mz.d.ts → CanvasStackContext-DQgcH1ny.d.ts} +1 -1
- package/dist/_dts/LayerList.d-2c9yup5Y.d.ts +83 -0
- package/dist/_dts/{PrefsForm.d-DPy9I8It.d.ts → PrefsRow.d-DFpPIeIC.d.ts} +16 -1
- package/dist/_dts/{Select.d-Gwr8fLpK.d.ts → Select.d-BchGMC2Y.d.ts} +129 -12
- package/dist/_dts/{frac-B4okC2lX.d.ts → frac-DTRq7Xpb.d.ts} +31 -13
- package/dist/_dts/inDialog-D5ZKGjiD.d.ts +23 -0
- package/dist/_dts/{index-CSJoj4LC.d.ts → index-B0--8PEM.d.ts} +5 -4
- package/dist/_dts/index-DINmCuLA.d.ts +453 -0
- package/dist/_dts/number.d-OeQYQoUO.d.ts +28 -0
- package/dist/_dts/{types-DzoNY1pO.d.ts → types-B7y8hX1D.d.ts} +6 -6
- package/dist/_dts/{usePanZoom-Pzf9f2jh.d.ts → usePanZoom-Bq73pwFe.d.ts} +4 -47
- package/dist/_dts/{useTrialState-uLlmaccn.d.ts → useTrialState-CP4jfuKl.d.ts} +1 -1
- package/dist/canvas/index.d.ts +6 -5
- package/dist/canvas/index.js +1 -1
- package/dist/chrome/index.d.ts +5 -4
- package/dist/chrome/index.js +7 -7
- package/dist/chunk-2RVCB2PT.js +3 -0
- package/dist/chunk-2RVCB2PT.js.map +1 -0
- package/dist/{chunk-UN4U4P63.js → chunk-3FI7Y4R4.js} +9 -9
- package/dist/chunk-3FI7Y4R4.js.map +1 -0
- package/dist/{chunk-7PFH3CNM.js → chunk-AWH3SRPW.js} +31 -5
- package/dist/chunk-AWH3SRPW.js.map +1 -0
- package/dist/{chunk-ZDHY47EV.js → chunk-BVL7Y574.js} +25 -9
- package/dist/chunk-BVL7Y574.js.map +1 -0
- package/dist/{chunk-IHUVQ3TX.js → chunk-H5VIV7MQ.js} +31 -27
- package/dist/chunk-H5VIV7MQ.js.map +1 -0
- package/dist/chunk-HFRE4QQV.js +400 -0
- package/dist/chunk-HFRE4QQV.js.map +1 -0
- package/dist/{chunk-IXTQI7JX.js → chunk-MOLIUNVH.js} +4 -4
- package/dist/{chunk-IXTQI7JX.js.map → chunk-MOLIUNVH.js.map} +1 -1
- package/dist/{chunk-CEIUBPPW.js → chunk-TT5C5S6R.js} +3 -86
- package/dist/chunk-TT5C5S6R.js.map +1 -0
- package/dist/chunk-USO6TERP.js +90 -0
- package/dist/chunk-USO6TERP.js.map +1 -0
- package/dist/{chunk-PHK4W562.js → chunk-VQ47KWD5.js} +3 -3
- package/dist/{chunk-PHK4W562.js.map → chunk-VQ47KWD5.js.map} +1 -1
- package/dist/chunk-WUJXJC5O.js +14568 -0
- package/dist/chunk-WUJXJC5O.js.map +1 -0
- package/dist/{chunk-EHGVROVV.js → chunk-ZORVNOKX.js} +6 -25
- package/dist/chunk-ZORVNOKX.js.map +1 -0
- package/dist/config/index.d.ts +53 -11
- package/dist/config/index.js +5 -5
- package/dist/controls/index.d.ts +6 -3
- package/dist/controls/index.js +4 -4
- package/dist/dragdrop/index.d.ts +4 -3
- package/dist/index.d.ts +139 -114
- package/dist/index.js +470 -479
- package/dist/index.js.map +1 -1
- package/dist/layers/index.d.ts +6 -35
- package/dist/layers/index.js +2 -3
- package/dist/loupe/index.d.ts +6 -5
- package/dist/passthrough/weasel-ui.d.ts +421 -215
- package/dist/passthrough/weasel-ui.js +1 -1
- package/dist/primitives/index.d.ts +2 -13
- package/dist/primitives/index.js +4 -4
- package/dist/state/index.d.ts +6 -5
- package/dist/state/index.js +5 -5
- package/dist/styles.css +410 -190
- package/dist/undo/index.d.ts +4 -3
- package/package.json +9 -13
- package/src/annotations/frac.test.ts +7 -0
- package/src/annotations/paint.test.ts +21 -0
- package/src/annotations/paint.ts +12 -0
- package/src/annotations/store.test.ts +31 -0
- package/src/annotations/types.ts +3 -2
- package/src/canvas/Stage.test.tsx +18 -0
- package/src/canvas/index.ts +0 -9
- package/src/chrome/labTypes.ts +1 -1
- package/src/chrome/regions/PaletteRegion.test.tsx +18 -0
- package/src/chrome/regions/PaletteRegion.tsx +5 -4
- package/src/chrome/regions/SidebarRegion.less +197 -0
- package/src/chrome/regions/SidebarRegion.test.tsx +20 -0
- package/src/chrome/regions/SidebarRegion.tsx +7 -2
- package/src/chrome/regions/TitleBarRegion.tsx +1 -1
- package/src/chrome/types.ts +13 -4
- package/src/config/autoConfig.ts +2 -2
- package/src/config/builder.ts +23 -5
- package/src/config/entry.test.ts +8 -0
- package/src/config/index.ts +2 -0
- package/src/config/rules.ts +2 -0
- package/src/config/sectionTree.test.ts +146 -0
- package/src/config/sectionTree.ts +124 -0
- package/src/config/types.ts +4 -4
- package/src/controls/AutoControls.stories.tsx +6 -6
- package/src/controls/ControlPanel.less +27 -0
- package/src/controls/ControlPanel.stories.tsx +95 -1
- package/src/controls/ControlPanel.test.tsx +82 -112
- package/src/controls/ControlPanel.tsx +159 -396
- package/src/controls/inDialog.test.tsx +82 -0
- package/src/controls/inDialog.tsx +46 -0
- package/src/controls/index.ts +1 -0
- package/src/index.test.ts +0 -2
- package/src/index.ts +14 -35
- package/src/instrument/types.ts +5 -2
- package/src/lab/Lab.nebula.test.tsx +31 -0
- package/src/lab/Lab.tsx +57 -18
- 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/passthrough/weasel-ui.ts +25 -10
- package/src/primitives/FpsMeter.less +6 -1
- package/src/primitives/FpsMeter.test.tsx +12 -4
- package/src/primitives/FpsMeter.tsx +6 -1
- package/src/primitives/JobProgress.stories.tsx +1 -1
- package/src/primitives/StatusBar.less +6 -0
- package/src/primitives/index.ts +0 -2
- package/src/specimen/Specimen.tsx +42 -56
- package/src/state/types.ts +8 -2
- package/src/state/view.test.ts +4 -4
- package/src/styles.less +4 -2
- package/src/theme/Interstellar.stories.tsx +8 -9
- 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/trial/Trial.canvas.test.tsx +9 -5
- package/src/trial/Trial.config.test.tsx +1 -1
- package/src/trial/Trial.tsx +30 -8
- package/dist/_dts/index-BNdz-tNd.d.ts +0 -423
- package/dist/chunk-7PFH3CNM.js.map +0 -1
- package/dist/chunk-CEIUBPPW.js.map +0 -1
- package/dist/chunk-EH7UEQV7.js +0 -590
- package/dist/chunk-EH7UEQV7.js.map +0 -1
- package/dist/chunk-EHGVROVV.js.map +0 -1
- package/dist/chunk-IHUVQ3TX.js.map +0 -1
- package/dist/chunk-MDVTK5U3.js +0 -170
- package/dist/chunk-MDVTK5U3.js.map +0 -1
- package/dist/chunk-PJ7WEQBJ.js +0 -18
- package/dist/chunk-PJ7WEQBJ.js.map +0 -1
- package/dist/chunk-T3EC2DXD.js +0 -12628
- package/dist/chunk-T3EC2DXD.js.map +0 -1
- package/dist/chunk-UN4U4P63.js.map +0 -1
- package/dist/chunk-ZDHY47EV.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/useOrbit.test.ts +0 -167
- package/src/canvas/useOrbit.ts +0 -156
- 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,18 @@ 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 kind="number" label="Count" value={count} min={0} max={100} step={1} onChange={setCount} />
|
|
472
|
+
<PropertyField
|
|
473
|
+
kind="enum"
|
|
475
474
|
label="Line cap"
|
|
476
475
|
value={cap}
|
|
477
476
|
onChange={setCap}
|
|
@@ -480,7 +479,9 @@ function PanelsAndRows() {
|
|
|
480
479
|
{ value: 'round', label: 'Round' },
|
|
481
480
|
]}
|
|
482
481
|
/>
|
|
483
|
-
<
|
|
482
|
+
<PropertyField
|
|
483
|
+
kind="enum"
|
|
484
|
+
control="toggle"
|
|
484
485
|
label="Align"
|
|
485
486
|
value={side}
|
|
486
487
|
onChange={setSide}
|
|
@@ -490,10 +491,10 @@ function PanelsAndRows() {
|
|
|
490
491
|
{ value: 'right', label: 'R' },
|
|
491
492
|
]}
|
|
492
493
|
/>
|
|
493
|
-
<
|
|
494
|
-
<
|
|
494
|
+
<PropertyField kind="string" label="Label" value={label} onChange={setLabel} />
|
|
495
|
+
<PropertyField kind="boolean" label="Visible" value={visible} onChange={setVisible} />
|
|
495
496
|
<PropertyGroup title="Bevel" defaultCollapsed>
|
|
496
|
-
<
|
|
497
|
+
<PropertyField kind="number" control="slider" label="Rings" value={32} min={4} max={96} step={1} onChange={() => {}} />
|
|
497
498
|
</PropertyGroup>
|
|
498
499
|
</PropertyList>
|
|
499
500
|
</PropertyPanel>
|
|
@@ -505,18 +506,16 @@ function PanelsAndRows() {
|
|
|
505
506
|
onChange={(path, value) => setPrefs((prev) => setAt(prev, path, value))}
|
|
506
507
|
/>
|
|
507
508
|
</Cell>
|
|
508
|
-
<Cell label="
|
|
509
|
-
<
|
|
509
|
+
<Cell label="LayerList">
|
|
510
|
+
<LayerList
|
|
510
511
|
items={layers}
|
|
511
|
-
onReorder={(
|
|
512
|
-
setLayers(ids.flatMap((id) => layers.filter((item) => item.id === id)))
|
|
513
|
-
}
|
|
512
|
+
onReorder={(move) => setLayers(moveLayers(layers, move))}
|
|
514
513
|
renderBody={(item) => <div>settings for {item.label}</div>}
|
|
515
514
|
/>
|
|
516
515
|
</Cell>
|
|
517
516
|
<Cell label="Sidebar, SidebarPanel">
|
|
518
517
|
<div className="lk-specimen__box">
|
|
519
|
-
<
|
|
518
|
+
<Sidebar side="right" ariaLabel="Specimen sidebar">
|
|
520
519
|
<SidebarPanel
|
|
521
520
|
title="Selection"
|
|
522
521
|
collapsed={panelCollapsed}
|
|
@@ -525,7 +524,7 @@ function PanelsAndRows() {
|
|
|
525
524
|
>
|
|
526
525
|
<div className="lk-specimen__pad">2 items selected</div>
|
|
527
526
|
</SidebarPanel>
|
|
528
|
-
</
|
|
527
|
+
</Sidebar>
|
|
529
528
|
</div>
|
|
530
529
|
</Cell>
|
|
531
530
|
</Section>
|
|
@@ -554,8 +553,8 @@ function OverlaysAndFeedback() {
|
|
|
554
553
|
triggerRef={calloutAnchor}
|
|
555
554
|
isOpen={calloutOpen}
|
|
556
555
|
onOpenChange={setCalloutOpen}
|
|
557
|
-
|
|
558
|
-
title="
|
|
556
|
+
stance="notice"
|
|
557
|
+
title="Notice"
|
|
559
558
|
>
|
|
560
559
|
Neutral guidance.
|
|
561
560
|
</Callout>
|
|
@@ -587,9 +586,9 @@ function OverlaysAndFeedback() {
|
|
|
587
586
|
variant="solid"
|
|
588
587
|
size="sm"
|
|
589
588
|
segments={[
|
|
590
|
-
{ text: 'main',
|
|
591
|
-
{ text: '✓ 12',
|
|
592
|
-
{ text: '~/proj',
|
|
589
|
+
{ text: 'main', status: 'accent', endCap: 'chevron' },
|
|
590
|
+
{ text: '✓ 12', status: 'info', endCap: 'slant' },
|
|
591
|
+
{ text: '~/proj', status: 'muted' },
|
|
593
592
|
]}
|
|
594
593
|
/>
|
|
595
594
|
</Cell>
|
|
@@ -799,7 +798,6 @@ function EditorsAndPlots() {
|
|
|
799
798
|
}
|
|
800
799
|
|
|
801
800
|
function LabChrome() {
|
|
802
|
-
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
|
|
803
801
|
const [zoom, setZoom] = useState(1);
|
|
804
802
|
return (
|
|
805
803
|
<Section title="Lab chrome">
|
|
@@ -823,18 +821,6 @@ function LabChrome() {
|
|
|
823
821
|
<StatusBar.Section>Zoom: 100%</StatusBar.Section>
|
|
824
822
|
</StatusBar>
|
|
825
823
|
</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
824
|
<Cell label="Legend, JobProgress">
|
|
839
825
|
<Legend entries={LEGEND} />
|
|
840
826
|
<JobProgress job={JOB} />
|
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,12 @@ 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;
|
|
83
|
+
|
|
84
|
+
/** How much room the lab's own chrome takes — the theme's density axis, named
|
|
85
|
+
* the way the theme names it. A lab's instruments are unaffected: this sizes
|
|
86
|
+
* the shell around them. */
|
|
87
|
+
export type LabDensity = 'compact' | 'comfortable' | 'roomy';
|
|
82
88
|
|
|
83
89
|
/** Everything a lab persists: its trials, its saved snapshots, and the
|
|
84
90
|
* chosen color mode. */
|
|
@@ -126,7 +132,7 @@ export interface TrialStateHandle<TS, TC> {
|
|
|
126
132
|
setState: (next: TS | ((prev: TS) => TS)) => void;
|
|
127
133
|
config: TC;
|
|
128
134
|
/** The config as stored, before any auto path is resolved. What the control
|
|
129
|
-
* panel renders, so
|
|
135
|
+
* panel renders, so an auto row pins back to the value it was holding. */
|
|
130
136
|
raw: TC;
|
|
131
137
|
/** Dotted paths this trial has unpinned. */
|
|
132
138
|
auto: ReadonlySet<string>;
|
package/src/state/view.test.ts
CHANGED
|
@@ -5,13 +5,13 @@ import { openLabStore } from './openLabStore';
|
|
|
5
5
|
import { createLabStore } from './store';
|
|
6
6
|
import { as2DView, DEFAULT_VIEW, normalize2DView, withZoom } from './view';
|
|
7
7
|
|
|
8
|
-
interface
|
|
8
|
+
interface ArbitraryTrialView {
|
|
9
9
|
yaw: number;
|
|
10
10
|
pitch: number;
|
|
11
11
|
distance: number;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
const orbit:
|
|
14
|
+
const orbit: ArbitraryTrialView = { yaw: 1.1, pitch: 0.3, distance: 9 };
|
|
15
15
|
|
|
16
16
|
describe('as2DView', () => {
|
|
17
17
|
it('accepts the 2D shape', () => {
|
|
@@ -54,7 +54,7 @@ describe('a trial view labkit does not interpret', () => {
|
|
|
54
54
|
|
|
55
55
|
store.getState().updateTrialView('w1', orbit);
|
|
56
56
|
|
|
57
|
-
expect(store.getState().trials[0]?.view as
|
|
57
|
+
expect(store.getState().trials[0]?.view as ArbitraryTrialView).toEqual(orbit);
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
it('round-trips that view through persistence', async () => {
|
|
@@ -76,7 +76,7 @@ describe('a trial view labkit does not interpret', () => {
|
|
|
76
76
|
storageKey: 'view-b',
|
|
77
77
|
storage: createMemoryAdapter(backing),
|
|
78
78
|
});
|
|
79
|
-
expect(hydrated.store.getState().trials[0]?.view as
|
|
79
|
+
expect(hydrated.store.getState().trials[0]?.view as ArbitraryTrialView).toEqual(orbit);
|
|
80
80
|
});
|
|
81
81
|
});
|
|
82
82
|
|
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,11 @@
|
|
|
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';
|
|
23
26
|
@import './loupe/Loupe.less';
|
|
24
|
-
@import './layers/LayerList.less';
|
|
25
27
|
@import './annotations/Annotations.less';
|
|
26
28
|
@import './dragdrop/Palette.less';
|
|
27
29
|
@import './dragdrop/DragGhost.less';
|
|
@@ -2,12 +2,9 @@ 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
4
|
import {
|
|
5
|
-
|
|
6
|
-
ColorRow,
|
|
5
|
+
PropertyField,
|
|
7
6
|
PropertyList,
|
|
8
7
|
PropertyPanel,
|
|
9
|
-
SliderRow,
|
|
10
|
-
TextRow,
|
|
11
8
|
} from '@weasel-js/ui';
|
|
12
9
|
import './Interstellar.stories.less';
|
|
13
10
|
|
|
@@ -148,7 +145,9 @@ function LivePanelPreview() {
|
|
|
148
145
|
<h3 className="lk-theme-doc__heading">Live panel</h3>
|
|
149
146
|
<PropertyPanel title="Sample">
|
|
150
147
|
<PropertyList>
|
|
151
|
-
<
|
|
148
|
+
<PropertyField
|
|
149
|
+
kind="number"
|
|
150
|
+
control="slider"
|
|
152
151
|
label="Opacity"
|
|
153
152
|
value={0.65}
|
|
154
153
|
min={0}
|
|
@@ -157,10 +156,10 @@ function LivePanelPreview() {
|
|
|
157
156
|
onChange={() => {}}
|
|
158
157
|
format={(v) => v.toFixed(2)}
|
|
159
158
|
/>
|
|
160
|
-
<
|
|
161
|
-
<
|
|
162
|
-
<
|
|
163
|
-
<
|
|
159
|
+
<PropertyField kind="color" label="Fill" value="#b08adb" onChange={() => {}} />
|
|
160
|
+
<PropertyField kind="color" label="Stroke" value="#1a1428" onChange={() => {}} />
|
|
161
|
+
<PropertyField kind="string" label="Name" value="Untitled" onChange={() => {}} />
|
|
162
|
+
<PropertyField kind="boolean" label="Visible" value={true} onChange={() => {}} />
|
|
164
163
|
</PropertyList>
|
|
165
164
|
</PropertyPanel>
|
|
166
165
|
</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({
|
|
@@ -93,16 +93,20 @@ describe('an auto config path', () => {
|
|
|
93
93
|
render: () => null,
|
|
94
94
|
canvas: { layers: [{ id: 'main', draw }] },
|
|
95
95
|
});
|
|
96
|
-
|
|
96
|
+
const { container } = render(
|
|
97
|
+
<Lab instruments={[instrument as Instrument]} defaultInstrument="Auto" />,
|
|
98
|
+
);
|
|
97
99
|
await new Promise((r) => requestAnimationFrame(() => r(null)));
|
|
98
100
|
|
|
99
101
|
expect(draw).toHaveBeenCalledWith(
|
|
100
102
|
expect.anything(),
|
|
101
103
|
expect.objectContaining({ config: { gap: 18 } }),
|
|
102
104
|
);
|
|
103
|
-
// The panel is handed the raw config, but
|
|
104
|
-
// resolver decided
|
|
105
|
-
|
|
105
|
+
// The panel is handed the raw config, but an auto row holds what the
|
|
106
|
+
// resolver decided, so pinning it keeps the number the instrument drew.
|
|
107
|
+
// The row hides its control while auto, which takes it out of the
|
|
108
|
+
// accessibility tree — so this reads the element rather than the role.
|
|
109
|
+
expect(container.querySelector('input[type=range]')).toHaveValue('18');
|
|
106
110
|
});
|
|
107
111
|
});
|
|
108
112
|
|
|
@@ -181,7 +185,7 @@ describe('LabProps.instruments', () => {
|
|
|
181
185
|
render(<Lab instruments={[instrument]} defaultInstrument="Probe" />);
|
|
182
186
|
expect([...seen]).toEqual(['grid', 'glyph']);
|
|
183
187
|
|
|
184
|
-
await userEvent.click(screen.getByRole('checkbox', { name: '
|
|
188
|
+
await userEvent.click(screen.getByRole('checkbox', { name: 'Show grid' }));
|
|
185
189
|
expect([...seen]).toEqual(['glyph']);
|
|
186
190
|
});
|
|
187
191
|
});
|