@weasel-js/labkit 1.7.0 → 1.7.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 -3
- package/dist/_dts/{CanvasStackContext-D2jnIwfk.d.ts → CanvasStackContext-Cjy6I-Iv.d.ts} +4 -1
- package/dist/_dts/{Stage-CCWfQQWM.d.ts → Stage-D6t7o0pF.d.ts} +3 -2
- package/dist/_dts/{index-CsYqUHD3.d.ts → index-BTmaRy6a.d.ts} +10 -6
- package/dist/_dts/{types-CSm9jgol.d.ts → index-DCMA4Fy1.d.ts} +59 -113
- package/dist/_dts/{types-CRPSGFAp.d.ts → types-BUBSIZuV.d.ts} +8 -7
- package/dist/_dts/{useTrialState-CTZPgeZ7.d.ts → useTrialState-Bh8bzFgE.d.ts} +1 -1
- package/dist/canvas/index.d.ts +8 -6
- package/dist/canvas/index.js +6 -6
- package/dist/chrome/index.d.ts +7 -5
- package/dist/chrome/index.js +10 -9
- package/dist/chunk-2ES4W47N.js +8 -0
- package/dist/chunk-2ES4W47N.js.map +1 -0
- package/dist/{chunk-WPLAANH4.js → chunk-2N7UBSS2.js} +12 -12
- package/dist/chunk-2N7UBSS2.js.map +1 -0
- package/dist/chunk-4KSC7NXL.js +15491 -0
- package/dist/chunk-4KSC7NXL.js.map +1 -0
- package/dist/{chunk-7BO7HNGF.js → chunk-CEGFXTBD.js} +8 -61
- package/dist/chunk-CEGFXTBD.js.map +1 -0
- package/dist/{chunk-275JRRVD.js → chunk-E23Q6A3Y.js} +232 -37
- package/dist/chunk-E23Q6A3Y.js.map +1 -0
- package/dist/{chunk-GOZLNM4L.js → chunk-E6NARGU7.js} +5 -5
- package/dist/{chunk-GOZLNM4L.js.map → chunk-E6NARGU7.js.map} +1 -1
- package/dist/{chunk-IJJUK4FU.js → chunk-EESJUSYR.js} +5 -6
- package/dist/chunk-EESJUSYR.js.map +1 -0
- package/dist/{chunk-HXXTULDN.js → chunk-EFXRM6XQ.js} +8 -11
- package/dist/chunk-EFXRM6XQ.js.map +1 -0
- package/dist/chunk-F4ACIK7Z.js +210 -0
- package/dist/chunk-F4ACIK7Z.js.map +1 -0
- package/dist/{chunk-FMK7UQ6V.js → chunk-FB4MIZOO.js} +61 -44
- package/dist/chunk-FB4MIZOO.js.map +1 -0
- package/dist/{chunk-AWQG7FCC.js → chunk-FG3EXZDV.js} +3 -3
- package/dist/{chunk-AWQG7FCC.js.map → chunk-FG3EXZDV.js.map} +1 -1
- package/dist/{chunk-I5DUQ5HM.js → chunk-GAHELLJT.js} +75 -72
- package/dist/chunk-GAHELLJT.js.map +1 -0
- package/dist/{chunk-YT75VYRD.js → chunk-IBVRMHW5.js} +5 -5
- package/dist/{chunk-YT75VYRD.js.map → chunk-IBVRMHW5.js.map} +1 -1
- package/dist/{chunk-T5IBSPAM.js → chunk-JFOJESJF.js} +33 -23
- package/dist/chunk-JFOJESJF.js.map +1 -0
- package/dist/{chunk-RWNDDKOH.js → chunk-PMLZP7RT.js} +18 -15
- package/dist/chunk-PMLZP7RT.js.map +1 -0
- package/dist/{chunk-Y23G2VZL.js → chunk-READTDQX.js} +2 -2
- package/dist/chunk-READTDQX.js.map +1 -0
- package/dist/{chunk-JVBYV6TL.js → chunk-ROGJWDQA.js} +3 -3
- package/dist/{chunk-JVBYV6TL.js.map → chunk-ROGJWDQA.js.map} +1 -1
- package/dist/{chunk-ZIFPHIWZ.js → chunk-T6DLGEJB.js} +12 -14
- package/dist/chunk-T6DLGEJB.js.map +1 -0
- package/dist/{chunk-24W5VEJW.js → chunk-ULYYNWGP.js} +2 -2
- package/dist/{chunk-24W5VEJW.js.map → chunk-ULYYNWGP.js.map} +1 -1
- package/dist/{chunk-UNAZSLWE.js → chunk-VYVGVBGY.js} +17 -20
- package/dist/chunk-VYVGVBGY.js.map +1 -0
- package/dist/{chunk-KMJ7RWD3.js → chunk-WLMDTI2Q.js} +3 -3
- package/dist/{chunk-KMJ7RWD3.js.map → chunk-WLMDTI2Q.js.map} +1 -1
- package/dist/{chunk-J7OWWTCW.js → chunk-XE5HJOPL.js} +5 -6
- package/dist/chunk-XE5HJOPL.js.map +1 -0
- package/dist/chunk-XVUKDSYV.js +38 -0
- package/dist/chunk-XVUKDSYV.js.map +1 -0
- package/dist/{chunk-FZ7YFQN7.js → chunk-YCFKW5RX.js} +3 -3
- package/dist/chunk-YCFKW5RX.js.map +1 -0
- package/dist/{chunk-CQLQPQ4P.js → chunk-ZQIHJXP4.js} +2 -2
- package/dist/chunk-ZQIHJXP4.js.map +1 -0
- package/dist/config/index.d.ts +18 -10
- package/dist/config/index.js +4 -4
- package/dist/controls/index.d.ts +4 -7
- package/dist/controls/index.js +6 -5
- package/dist/dragdrop/index.d.ts +23 -3
- package/dist/dragdrop/index.js +4 -3
- package/dist/fonts/oswald-tabular-digits.woff2 +0 -0
- package/dist/index.d.ts +60 -714
- package/dist/index.js +357 -334
- package/dist/index.js.map +1 -1
- package/dist/job/index.d.ts +8 -0
- package/dist/job/index.js +1 -1
- package/dist/layers/index.d.ts +6 -5
- package/dist/layers/index.js +3 -2
- package/dist/loupe/index.d.ts +100 -30
- package/dist/loupe/index.js +585 -6
- package/dist/loupe/index.js.map +1 -1
- package/dist/overview/index.d.ts +4 -2
- package/dist/overview/index.js +15 -14
- package/dist/overview/index.js.map +1 -1
- package/dist/passthrough/weasel-canvas.d.ts +2 -0
- package/dist/passthrough/weasel-ui.d.ts +2 -2871
- package/dist/passthrough/weasel-ui.js +3 -2
- package/dist/primitives/index.d.ts +213 -3
- package/dist/primitives/index.js +8 -7
- package/dist/state/index.d.ts +7 -5
- package/dist/state/index.js +6 -6
- package/dist/styles.css +60 -44
- package/dist/surface/index.d.ts +10 -2
- package/dist/surface/index.js +1 -1
- package/dist/undo/index.d.ts +5 -3
- package/package.json +11 -11
- package/src/annotations/AnnotationOverlay.abandon.test.tsx +143 -0
- package/src/annotations/AnnotationOverlay.tsx +50 -31
- package/src/annotations/Annotations.overlay.test.tsx +31 -0
- package/src/annotations/capture.browser.test.ts +41 -0
- package/src/annotations/capture.ts +14 -7
- package/src/annotations/drawOne.ts +2 -2
- package/src/annotations/frac.test.ts +44 -1
- package/src/annotations/frac.ts +46 -18
- package/src/annotations/index.ts +1 -0
- package/src/annotations/paint.test.ts +74 -33
- package/src/annotations/paint.ts +70 -32
- package/src/annotations/store.test.ts +212 -2
- package/src/annotations/store.ts +130 -27
- package/src/annotations/svgNodes.test.ts +22 -10
- package/src/annotations/svgNodes.ts +3 -3
- package/src/annotations/types.ts +29 -10
- package/src/canvas/CameraInput.test.tsx +30 -0
- package/src/canvas/CameraInput.tsx +16 -15
- package/src/canvas/CanvasStack.tsx +5 -5
- package/src/canvas/CanvasStackContext.ts +4 -1
- package/src/canvas/Stage.tsx +3 -3
- package/src/canvas/cameraRegistry.ts +1 -0
- package/src/canvas/worldSpec.ts +3 -1
- package/src/chrome/builtins.test.ts +7 -6
- package/src/chrome/builtins.tsx +5 -1
- package/src/chrome/index.ts +1 -1
- package/src/chrome/merge.test.ts +5 -0
- package/src/chrome/merge.ts +4 -2
- package/src/chrome/regions/PaletteRegion.test.tsx +2 -3
- package/src/chrome/regions/PaletteRegion.tsx +3 -4
- package/src/chrome/regions/ViewportRegion.browser.test.less +6 -0
- package/src/chrome/regions/ViewportRegion.browser.test.tsx +38 -0
- package/src/chrome/regions/ViewportRegion.less +6 -0
- package/src/chrome/regions/ViewportRegion.tsx +10 -4
- package/src/chrome/types.ts +4 -2
- package/src/config/auto.ts +1 -0
- package/src/config/builder.ts +6 -0
- package/src/config/types.ts +2 -1
- package/src/controls/ControlPanel.test.tsx +37 -3
- package/src/controls/ControlPanel.tsx +12 -3
- package/src/dragdrop/DragDropRuntime.tsx +22 -13
- package/src/dragdrop/DragGhost.tsx +3 -0
- package/src/dragdrop/Palette.tsx +2 -0
- package/src/index.test.ts +5 -0
- package/src/index.ts +1 -1
- package/src/instrument/types.ts +0 -6
- package/src/job/useJob.ts +14 -9
- package/src/lab/Lab.tsx +5 -1
- package/src/lab/LabShell.less +1 -0
- package/src/lab/LabSwitcher.browser.test.tsx +27 -0
- package/src/lab/LabSwitcher.less +2 -0
- package/src/lab/LabZoom.tsx +4 -4
- package/src/lab/Workspace.tsx +48 -52
- package/src/loupe/AGENTS.md +28 -15
- package/src/loupe/CanvasLoupe.tsx +2 -3
- package/src/loupe/DomLoupe.tsx +1 -7
- package/src/loupe/Loupe.less +16 -0
- package/src/loupe/TrialLoupe.tsx +120 -57
- package/src/loupe/index.ts +1 -6
- package/src/loupe/types.test.ts +3 -3
- package/src/loupe/types.ts +24 -27
- package/src/loupe/useLoupe.test.tsx +29 -4
- package/src/loupe/useLoupe.ts +20 -17
- package/src/overview/OverviewMarks.tsx +12 -4
- package/src/overview/TrialOverview.tsx +3 -3
- package/src/passthrough/weasel-ui.test.ts +1 -1
- package/src/passthrough/weasel-ui.ts +1 -1
- package/src/primitives/FloatingPanel.tsx +7 -3
- package/src/primitives/JobProgress.less +1 -0
- package/src/primitives/Readout.test.tsx +2 -2
- package/src/primitives/Split.tsx +69 -41
- package/src/primitives/Toolbar.tsx +3 -3
- package/src/primitives/ZoomControl.less +1 -2
- package/src/specimen/Specimen.tsx +0 -1
- package/src/state/undock.ts +3 -0
- package/src/state/useOpenOnce.ts +20 -16
- package/src/state/view.ts +1 -0
- package/src/surface/index.ts +1 -1
- package/src/surface/useTiledSurface.test.tsx +14 -0
- package/src/surface/useTiledSurface.ts +11 -3
- package/src/trial/Trial.annotations.test.tsx +73 -0
- package/src/trial/Trial.less +0 -16
- package/src/trial/Trial.loupe.test.tsx +28 -11
- package/src/trial/Trial.tsx +74 -62
- package/src/trial/TrialChrome.tsx +6 -3
- package/src/trial/index.ts +2 -0
- package/src/trial/loupeSwitch.ts +15 -0
- package/dist/_dts/LayerList.d-DiuEArKq.d.ts +0 -83
- package/dist/_dts/PrefsRow.d-TOZ7BgD9.d.ts +0 -79
- package/dist/_dts/PropertyPanel.d-D-1paCbE.d.ts +0 -141
- package/dist/_dts/Select.d-Bensr_MT.d.ts +0 -579
- package/dist/_dts/index-B2Yj5aA0.d.ts +0 -274
- package/dist/chunk-275JRRVD.js.map +0 -1
- package/dist/chunk-4LJSC7MB.js +0 -143
- package/dist/chunk-4LJSC7MB.js.map +0 -1
- package/dist/chunk-7BO7HNGF.js.map +0 -1
- package/dist/chunk-CQLQPQ4P.js.map +0 -1
- package/dist/chunk-FMK7UQ6V.js.map +0 -1
- package/dist/chunk-FZ7YFQN7.js.map +0 -1
- package/dist/chunk-HXXTULDN.js.map +0 -1
- package/dist/chunk-I5DUQ5HM.js.map +0 -1
- package/dist/chunk-IJJUK4FU.js.map +0 -1
- package/dist/chunk-J7OWWTCW.js.map +0 -1
- package/dist/chunk-M7HP3FTK.js +0 -549
- package/dist/chunk-M7HP3FTK.js.map +0 -1
- package/dist/chunk-MIM5R4ZT.js +0 -14972
- package/dist/chunk-MIM5R4ZT.js.map +0 -1
- package/dist/chunk-RWNDDKOH.js.map +0 -1
- package/dist/chunk-T5IBSPAM.js.map +0 -1
- package/dist/chunk-UNAZSLWE.js.map +0 -1
- package/dist/chunk-WPLAANH4.js.map +0 -1
- package/dist/chunk-Y23G2VZL.js.map +0 -1
- package/dist/chunk-ZIFPHIWZ.js.map +0 -1
- package/src/primitives/useRovingTabIndex.test.ts +0 -48
- package/src/primitives/useRovingTabIndex.ts +0 -88
package/src/trial/Trial.tsx
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import {
|
|
2
|
+
createPointerStore,
|
|
3
|
+
PointerContextProvider,
|
|
4
|
+
useLatest,
|
|
5
|
+
WeaselProvider,
|
|
6
|
+
} from '@weasel-js/core';
|
|
7
|
+
import {
|
|
8
|
+
type ReactNode,
|
|
9
|
+
useCallback,
|
|
10
|
+
useContext,
|
|
11
|
+
useEffect,
|
|
12
|
+
useLayoutEffect,
|
|
13
|
+
useMemo,
|
|
14
|
+
useRef,
|
|
15
|
+
useState,
|
|
16
|
+
} from 'react';
|
|
3
17
|
import { useStore } from 'zustand/react';
|
|
4
18
|
import { AnnotationsContext } from '../annotations/AnnotationsContext';
|
|
5
19
|
import { AnnotationTargets } from '../annotations/AnnotationTargets';
|
|
6
20
|
import { AnnotationPreloadContext } from '../annotations/preload';
|
|
7
21
|
import { annotationsFromJSON } from '../annotations/store';
|
|
8
|
-
import type { AnnotationStorage, AnnotationTargetInfo } from '../annotations/types';
|
|
22
|
+
import type { AnnotationStorage, AnnotationsApi, AnnotationTargetInfo } from '../annotations/types';
|
|
9
23
|
import type { CameraView } from '../canvas/CameraInput';
|
|
10
24
|
import { CameraWheelContext, type CameraWheelSlot } from '../canvas/CameraWheelContext';
|
|
11
25
|
import { CanvasStack } from '../canvas/CanvasStack';
|
|
@@ -27,8 +41,6 @@ import type {
|
|
|
27
41
|
} from '../instrument/types';
|
|
28
42
|
import { useJob } from '../job/useJob';
|
|
29
43
|
import { useLabContext } from '../lab/LabContext';
|
|
30
|
-
import { TrialLoupe } from '../loupe/TrialLoupe';
|
|
31
|
-
import { resolveLoupe } from '../loupe/types';
|
|
32
44
|
import { LayerList, type LayerListItem, moveLayers } from '../passthrough/weasel-ui';
|
|
33
45
|
import { LabStoreContext, TrialIdProvider } from '../state/context';
|
|
34
46
|
import type { LabStore } from '../state/store';
|
|
@@ -37,6 +49,7 @@ import { as2DView, DEFAULT_VIEW, withZoom } from '../state/view';
|
|
|
37
49
|
import { resolveLabTool } from '../tools/labTool';
|
|
38
50
|
import { createEventBus, type EventBus } from '../undo/eventBus';
|
|
39
51
|
import { pushSnapshot, redo as undoRedo, undo as undoUndo } from '../undo/undoStack';
|
|
52
|
+
import { LoupeSwitchContext } from './loupeSwitch';
|
|
40
53
|
import type { LoupeBindings, UndoBindings } from './TrialChrome';
|
|
41
54
|
import { TrialChrome } from './TrialChrome';
|
|
42
55
|
|
|
@@ -145,7 +158,6 @@ function TrialRuntime({
|
|
|
145
158
|
);
|
|
146
159
|
const [pointer] = useState(createPointerStore);
|
|
147
160
|
const canvasContainerRef = useRef<HTMLDivElement | null>(null);
|
|
148
|
-
const loupeHostRef = useRef<HTMLDivElement | null>(null);
|
|
149
161
|
const updateTrialState = useStore(store, (s) => s.updateTrialState);
|
|
150
162
|
const updateTrialConfig = useStore(store, (s) => s.updateTrialConfig);
|
|
151
163
|
const updateTrialView = useStore(store, (s) => s.updateTrialView);
|
|
@@ -167,6 +179,12 @@ function TrialRuntime({
|
|
|
167
179
|
const [layerVisibility, setLayerVisibility] = useState<Record<string, boolean>>({});
|
|
168
180
|
const [layerOrder, setLayerOrder] = useState<string[] | null>(null);
|
|
169
181
|
const [loupeOn, setLoupeOn] = useState(false);
|
|
182
|
+
const [lenses, setLenses] = useState(0);
|
|
183
|
+
const mountLens = useCallback(() => {
|
|
184
|
+
setLenses((n) => n + 1);
|
|
185
|
+
return () => setLenses((n) => n - 1);
|
|
186
|
+
}, []);
|
|
187
|
+
const loupeSwitch = useMemo(() => ({ on: loupeOn, mount: mountLens }), [loupeOn, mountLens]);
|
|
170
188
|
|
|
171
189
|
const visibleLayers = useMemo(
|
|
172
190
|
() =>
|
|
@@ -207,43 +225,69 @@ function TrialRuntime({
|
|
|
207
225
|
// resizing or gaining a dependency must not need the store rebuilt. Held in
|
|
208
226
|
// a ref because the store is built once and closes over it.
|
|
209
227
|
const annotationsCap = instrument.annotations;
|
|
210
|
-
const targetsRef =
|
|
211
|
-
targetsRef.current = () =>
|
|
228
|
+
const targetsRef = useLatest((): readonly AnnotationTargetInfo[] =>
|
|
212
229
|
annotationsCap
|
|
213
230
|
? annotationsCap.targets(record.state, config, { id: record.id, view: record.view })
|
|
214
|
-
: []
|
|
231
|
+
: [],
|
|
232
|
+
);
|
|
215
233
|
|
|
216
234
|
// One store for the trial's lifetime.
|
|
217
235
|
const annotationsRef = useRef<ReturnType<typeof annotationsFromJSON> | null>(null);
|
|
218
236
|
// Read through refs for the same reason `targets` is: the store is built
|
|
219
237
|
// once, and an export must draw against the config the trial holds now.
|
|
220
|
-
const configRef =
|
|
221
|
-
configRef.current = config;
|
|
238
|
+
const configRef = useLatest(config);
|
|
222
239
|
// The instrument can be swapped under a live trial, so the capability is read at use too.
|
|
223
|
-
const capRef =
|
|
224
|
-
capRef.current = annotationsCap;
|
|
240
|
+
const capRef = useLatest(annotationsCap);
|
|
225
241
|
if (annotationsRef.current === null) {
|
|
226
242
|
// Seeded from wherever the marks were kept: the instrument's own store if
|
|
227
243
|
// it declared one, else this trial's slot.
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
244
|
+
annotationsRef.current = annotationsFromJSON(
|
|
245
|
+
annotationsCap?.storage ? keptMarks : record.annotations,
|
|
246
|
+
() => targetsRef.current(),
|
|
247
|
+
{
|
|
248
|
+
meaning: () => capRef.current?.meaning,
|
|
249
|
+
config: () => configRef.current,
|
|
250
|
+
onCapture: (result) => capRef.current?.onCapture?.(result),
|
|
251
|
+
selection: () => capRef.current?.selection,
|
|
252
|
+
},
|
|
253
|
+
);
|
|
234
254
|
}
|
|
235
255
|
const annotations = annotationsRef.current;
|
|
236
256
|
|
|
257
|
+
// Chrome reads the store while it renders — a mark list, the export menu,
|
|
258
|
+
// the overview — and the store reads the refs above, which hold the last
|
|
259
|
+
// commit. So once a change to them commits, those readers are told to read
|
|
260
|
+
// again. Through the context's `subscribe` alone: the store's own would have
|
|
261
|
+
// the debounce below save marks that did not change.
|
|
262
|
+
const inputsCommitted = useRef(new Set<() => void>());
|
|
263
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: these are what `targets` and `config` answer from — the signal, not values this reads
|
|
264
|
+
useLayoutEffect(() => {
|
|
265
|
+
for (const fn of inputsCommitted.current) fn();
|
|
266
|
+
}, [record.state, record.view, config, annotationsCap]);
|
|
267
|
+
const provided = useMemo<AnnotationsApi>(
|
|
268
|
+
() => ({
|
|
269
|
+
...annotations,
|
|
270
|
+
subscribe: (fn) => {
|
|
271
|
+
const off = annotations.subscribe(fn);
|
|
272
|
+
inputsCommitted.current.add(fn);
|
|
273
|
+
return () => {
|
|
274
|
+
off();
|
|
275
|
+
inputsCommitted.current.delete(fn);
|
|
276
|
+
};
|
|
277
|
+
},
|
|
278
|
+
}),
|
|
279
|
+
[annotations],
|
|
280
|
+
);
|
|
281
|
+
|
|
237
282
|
// Written on a trailing debounce rather than per notification: a scene
|
|
238
283
|
// mutates every frame of a drag, and a zustand write per frame re-renders
|
|
239
284
|
// every trial in the lab. The unmount flush is not an optimization — the
|
|
240
285
|
// last mark before a trial closes is otherwise lost.
|
|
241
286
|
const saveCap = annotationsCap?.storage;
|
|
242
|
-
const saveRef =
|
|
243
|
-
saveRef.current = (doc) => {
|
|
287
|
+
const saveRef = useLatest((doc: unknown): void => {
|
|
244
288
|
if (saveCap) saveCap.save(doc as never);
|
|
245
289
|
else updateTrialAnnotations(record.id, doc);
|
|
246
|
-
};
|
|
290
|
+
});
|
|
247
291
|
// Only when the pair flips, which is rare: bumping React state on every
|
|
248
292
|
// scene notification would re-render the trial on every frame of a drag,
|
|
249
293
|
// which is the thing the debounce below exists to avoid.
|
|
@@ -280,7 +324,7 @@ function TrialRuntime({
|
|
|
280
324
|
if (timer) clearTimeout(timer);
|
|
281
325
|
flush();
|
|
282
326
|
};
|
|
283
|
-
}, [annotations, annotationsCap]);
|
|
327
|
+
}, [annotations, annotationsCap, saveRef]);
|
|
284
328
|
|
|
285
329
|
// A trial gets its own slot when its instrument declares tools; otherwise it
|
|
286
330
|
// reads the lab's. Which slot a change writes follows from the same thing.
|
|
@@ -380,14 +424,8 @@ function TrialRuntime({
|
|
|
380
424
|
}
|
|
381
425
|
: undefined;
|
|
382
426
|
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
if (declared == null) return null;
|
|
386
|
-
return resolveLoupe(typeof declared === 'function' ? declared(config) : declared);
|
|
387
|
-
}, [instrument.loupe, config]);
|
|
388
|
-
const loupeBindings: LoupeBindings | undefined = loupeCap
|
|
389
|
-
? { on: loupeOn, toggle: () => setLoupeOn((v) => !v) }
|
|
390
|
-
: undefined;
|
|
427
|
+
const loupeBindings: LoupeBindings | undefined =
|
|
428
|
+
lenses > 0 ? { on: loupeOn, toggle: () => setLoupeOn((v) => !v) } : undefined;
|
|
391
429
|
|
|
392
430
|
const canvasLayers: CanvasLayerDescriptor[] = useMemo(() => {
|
|
393
431
|
if (!instrument.canvas) return [];
|
|
@@ -478,20 +516,6 @@ function TrialRuntime({
|
|
|
478
516
|
];
|
|
479
517
|
}, [canvasLayers, dragDropResult.drag]);
|
|
480
518
|
|
|
481
|
-
// The lens tracks the pointer over whatever box holds the content: the canvas
|
|
482
|
-
// stack's own element, which it takes from context, or the wrapper below.
|
|
483
|
-
const lens = loupeCap ? (
|
|
484
|
-
<TrialLoupe
|
|
485
|
-
capability={loupeCap}
|
|
486
|
-
enabled={loupeOn}
|
|
487
|
-
state={record.state}
|
|
488
|
-
config={config}
|
|
489
|
-
view={view2d ?? DEFAULT_VIEW}
|
|
490
|
-
worldSpec={instrument.canvas?.worldSpec}
|
|
491
|
-
hostRef={loupeHostRef}
|
|
492
|
-
/>
|
|
493
|
-
) : null;
|
|
494
|
-
|
|
495
519
|
let body: ReactNode;
|
|
496
520
|
if (instrument.canvas) {
|
|
497
521
|
body = (
|
|
@@ -506,7 +530,6 @@ function TrialRuntime({
|
|
|
506
530
|
maxZoom={instrument.canvas.maxZoom}
|
|
507
531
|
>
|
|
508
532
|
{instrument.render(renderCtx)}
|
|
509
|
-
{lens}
|
|
510
533
|
</CanvasStack>
|
|
511
534
|
<DragOverlay drag={dragDropResult.drag} />
|
|
512
535
|
</div>
|
|
@@ -520,24 +543,11 @@ function TrialRuntime({
|
|
|
520
543
|
onResize={placeView}
|
|
521
544
|
minZoom={stage.minZoom}
|
|
522
545
|
maxZoom={stage.maxZoom}
|
|
523
|
-
|
|
524
|
-
overlay={
|
|
525
|
-
<>
|
|
526
|
-
{stage.overlay?.(renderCtx)}
|
|
527
|
-
{lens}
|
|
528
|
-
</>
|
|
529
|
-
}
|
|
546
|
+
overlay={stage.overlay?.(renderCtx)}
|
|
530
547
|
>
|
|
531
548
|
{instrument.render(renderCtx)}
|
|
532
549
|
</Stage>
|
|
533
550
|
);
|
|
534
|
-
} else if (lens) {
|
|
535
|
-
body = (
|
|
536
|
-
<div ref={loupeHostRef} className="lk-trial__loupe-host">
|
|
537
|
-
{instrument.render(renderCtx)}
|
|
538
|
-
{lens}
|
|
539
|
-
</div>
|
|
540
|
-
);
|
|
541
551
|
} else {
|
|
542
552
|
body = instrument.render(renderCtx);
|
|
543
553
|
}
|
|
@@ -606,14 +616,16 @@ function TrialRuntime({
|
|
|
606
616
|
const scopedBody = (
|
|
607
617
|
<WeaselProvider isolate>
|
|
608
618
|
<PointerContextProvider store={pointer}>
|
|
609
|
-
<CameraPublishContext.Provider value={publishCamera}>
|
|
619
|
+
<CameraPublishContext.Provider value={publishCamera}>
|
|
620
|
+
<LoupeSwitchContext.Provider value={loupeSwitch}>{body}</LoupeSwitchContext.Provider>
|
|
621
|
+
</CameraPublishContext.Provider>
|
|
610
622
|
</PointerContextProvider>
|
|
611
623
|
</WeaselProvider>
|
|
612
624
|
);
|
|
613
625
|
|
|
614
626
|
return (
|
|
615
627
|
<TrialIdProvider trialId={record.id}>
|
|
616
|
-
<AnnotationsContext.Provider value={annotationsCap ?
|
|
628
|
+
<AnnotationsContext.Provider value={annotationsCap ? provided : null}>
|
|
617
629
|
<CameraWheelContext.Provider value={wheelSlot}>
|
|
618
630
|
<TrialChrome
|
|
619
631
|
job={jobCap ? job : undefined}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
import { useStore } from 'zustand/react';
|
|
9
9
|
import { CameraRegistryContext } from '../canvas/cameraRegistry';
|
|
10
10
|
import { zoomCameraTo } from '../canvas/cameraZoom';
|
|
11
|
-
import { builtinContributions } from '../chrome/builtins';
|
|
11
|
+
import { builtinContributions, TRANSIENT_BUILTINS } from '../chrome/builtins';
|
|
12
12
|
import { mergeContributions, suppressContributions } from '../chrome/merge';
|
|
13
13
|
import { PaletteRegion } from '../chrome/regions/PaletteRegion';
|
|
14
14
|
import { SidebarRegion } from '../chrome/regions/SidebarRegion';
|
|
@@ -38,6 +38,7 @@ export interface LoupeBindings {
|
|
|
38
38
|
toggle: () => void;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/** The trial's undo history as its chrome sees it. */
|
|
41
42
|
export interface UndoBindings {
|
|
42
43
|
canUndo: boolean;
|
|
43
44
|
canRedo: boolean;
|
|
@@ -54,8 +55,8 @@ export interface TrialChromeProps {
|
|
|
54
55
|
undoBindings?: UndoBindings;
|
|
55
56
|
/** Supplied when the instrument declares a `job`. */
|
|
56
57
|
job?: JobHandle;
|
|
57
|
-
/** Supplied
|
|
58
|
-
*
|
|
58
|
+
/** Supplied while a lens is mounted in the trial. The lens itself is the
|
|
59
|
+
* instrument's to mount; the chrome only offers the switch. */
|
|
59
60
|
loupe?: LoupeBindings;
|
|
60
61
|
/** Contributions the trial runtime itself adds — the drag palette and the
|
|
61
62
|
* layer list, which depend on runtime state the instrument cannot reach. */
|
|
@@ -157,6 +158,7 @@ export function TrialChrome({
|
|
|
157
158
|
canRedo: undoBindings?.canRedo ?? false,
|
|
158
159
|
undo: undoBindings?.undo ?? NO_OP,
|
|
159
160
|
redo: undoBindings?.redo ?? NO_OP,
|
|
161
|
+
hasLoupe: loupe != null,
|
|
160
162
|
loupeOn: loupe?.on ?? false,
|
|
161
163
|
toggleLoupe: loupe?.toggle ?? NO_OP,
|
|
162
164
|
configSchema,
|
|
@@ -233,6 +235,7 @@ export function TrialChrome({
|
|
|
233
235
|
[...(chrome ?? [])],
|
|
234
236
|
),
|
|
235
237
|
suppress ?? [],
|
|
238
|
+
TRANSIENT_BUILTINS,
|
|
236
239
|
),
|
|
237
240
|
[instrument, ctx, trialChrome, chrome, suppress, lab.controls],
|
|
238
241
|
);
|
package/src/trial/index.ts
CHANGED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createContext } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A trial's loupe switch, as a lens mounted inside the trial finds it. The
|
|
5
|
+
* trial offers its toolbar toggle while at least one lens has called `mount`,
|
|
6
|
+
* and every lens reads `on` as whether it is turned on.
|
|
7
|
+
*/
|
|
8
|
+
export interface LoupeSwitch {
|
|
9
|
+
on: boolean;
|
|
10
|
+
/** Reports a lens mounted; the returned function reports it gone. */
|
|
11
|
+
mount: () => () => void;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/** The loupe switch of the trial around the caller, or `null` outside one. */
|
|
15
|
+
export const LoupeSwitchContext = createContext<LoupeSwitch | null>(null);
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import * as react from 'react';
|
|
2
|
-
import { ReactNode } from 'react';
|
|
3
|
-
import { S as StanceProps } from './PrefsRow.d-TOZ7BgD9.js';
|
|
4
|
-
|
|
5
|
-
/** One layer. With a body (see `renderBody`) it draws as a card that folds its
|
|
6
|
-
* body away; without one, as a one-line row. Either can hold child layers. */
|
|
7
|
-
interface LayerListItem {
|
|
8
|
-
id: string;
|
|
9
|
-
/** The layer's name. Also what its controls are labeled by. */
|
|
10
|
-
label: string;
|
|
11
|
-
/** Shown in the header in place of `label` — a select that switches the
|
|
12
|
-
* layer's kind, say. */
|
|
13
|
-
title?: ReactNode;
|
|
14
|
-
/** Fixed-size content before the label: a color swatch, a kind icon. */
|
|
15
|
-
leading?: ReactNode;
|
|
16
|
-
/** Drawn in the drag handle in place of the grip — an ordinal. */
|
|
17
|
-
badge?: ReactNode;
|
|
18
|
-
/** Which of its list this layer is: an index into the theme's tone list, or
|
|
19
|
-
* a color. A card draws its edge and handle in it and recolors its controls. */
|
|
20
|
-
tone?: StanceProps['tone'];
|
|
21
|
-
/** Cannot be dragged, hidden or removed, walls off drops on either side, and
|
|
22
|
-
* selects alone rather than joining a multi-selection. */
|
|
23
|
-
locked?: boolean;
|
|
24
|
-
/** Shown or not, when the list has `onVisibilityChange`. Default true. */
|
|
25
|
-
visible?: boolean;
|
|
26
|
-
children?: LayerListItem[];
|
|
27
|
-
/** Folds the body and children away until the user opens them.
|
|
28
|
-
* `collapsedIds` overrides it. */
|
|
29
|
-
defaultCollapsed?: boolean;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* A reorder: `ids`, siblings under `parentId` (`null` at the top level), now
|
|
33
|
-
* sit as one block in list order starting at `index` of the parent's children.
|
|
34
|
-
* A drag never moves a layer to another parent.
|
|
35
|
-
*/
|
|
36
|
-
interface LayerMove {
|
|
37
|
-
ids: string[];
|
|
38
|
-
parentId: string | null;
|
|
39
|
-
index: number;
|
|
40
|
-
}
|
|
41
|
-
/** Props for `<LayerList>`. */
|
|
42
|
-
interface LayerListProps {
|
|
43
|
-
items: LayerListItem[];
|
|
44
|
-
/** Omit for a list the user cannot reorder. */
|
|
45
|
-
onReorder?: (move: LayerMove) => void;
|
|
46
|
-
/** Giving both makes rows selectable: a click selects one, shift-click adds
|
|
47
|
-
* or removes one, and dragging a selected row drags its selected siblings. */
|
|
48
|
-
selectedIds?: readonly string[];
|
|
49
|
-
onSelect?: (ids: string[]) => void;
|
|
50
|
-
/** Adds a visibility checkbox to every unlocked layer. */
|
|
51
|
-
onVisibilityChange?: (id: string, visible: boolean) => void;
|
|
52
|
-
/** Adds a remove button to every unlocked layer. */
|
|
53
|
-
onRemove?: (id: string) => void;
|
|
54
|
-
/** A layer's controls. Returning `null` leaves that layer a one-line row. */
|
|
55
|
-
renderBody?: (item: LayerListItem) => ReactNode;
|
|
56
|
-
/** Ids whose body and children are folded away. Giving it makes folding
|
|
57
|
-
* controlled; `onCollapsedChange` fires either way. */
|
|
58
|
-
collapsedIds?: readonly string[];
|
|
59
|
-
onCollapsedChange?: (ids: string[]) => void;
|
|
60
|
-
/** Heading above the list. */
|
|
61
|
-
title?: string;
|
|
62
|
-
/** Names the list for assistive tech when it has no `title`. */
|
|
63
|
-
label?: string;
|
|
64
|
-
/** Kinds the user can add, as buttons beside the title. Shown only with `onAdd`. */
|
|
65
|
-
addKinds?: string[];
|
|
66
|
-
onAdd?: (kind: string) => void;
|
|
67
|
-
/** Shown in place of the list when `items` is empty. */
|
|
68
|
-
empty?: ReactNode;
|
|
69
|
-
/** Appended to the root's class list — the module's own names are hashed. */
|
|
70
|
-
className?: string;
|
|
71
|
-
}
|
|
72
|
-
/** Returns `items` with `move` applied, for a consumer that holds the tree as state. */
|
|
73
|
-
declare function moveLayers(items: LayerListItem[], move: LayerMove): LayerListItem[];
|
|
74
|
-
/**
|
|
75
|
-
* An ordered, drag-reorderable list of layers — a document's objects, a lab's
|
|
76
|
-
* canvases, a fill's effects. Each layer is a one-line row or, with a body, a
|
|
77
|
-
* card whose controls fold away; either can nest child layers. Selection,
|
|
78
|
-
* visibility, removal and an add palette are each on when their handler is given.
|
|
79
|
-
*/
|
|
80
|
-
declare function LayerList(props: LayerListProps): react.JSX.Element;
|
|
81
|
-
|
|
82
|
-
export { LayerList as L, moveLayers as m };
|
|
83
|
-
export type { LayerListItem as a, LayerListProps as b, LayerMove as c };
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { Stance } from '@weasel-js/theme';
|
|
2
|
-
import { ReactNode } from 'react';
|
|
3
|
-
import { ToolPrefLeaf } from '@weasel-js/core';
|
|
4
|
-
|
|
5
|
-
/** What one unit is worth in base units: `base = value * factor + offset`. */
|
|
6
|
-
interface UnitScale {
|
|
7
|
-
factor: number;
|
|
8
|
-
/** Where this unit puts zero, in base units. Absent is 0 — a pure scale. */
|
|
9
|
-
offset?: number;
|
|
10
|
-
}
|
|
11
|
-
/** One unit's conversion. A bare number is the `{ factor }` shorthand. */
|
|
12
|
-
type UnitEntry = number | UnitScale;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* How a number shows, speaks and reads back, as plain data: `{ kind: 'fraction',
|
|
16
|
-
* maxDenominator: 64 }`. Data rather than a function so a tagged value keeps its
|
|
17
|
-
* presentation through JSON, history snapshots and `structuredClone`. The
|
|
18
|
-
* behavior lives on the registered {@link DisplayKind} of the same `kind`.
|
|
19
|
-
*/
|
|
20
|
-
interface Display {
|
|
21
|
-
readonly kind: string;
|
|
22
|
-
readonly [option: string]: unknown;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Display-formatter for numbers. Use this anywhere a number is shown to
|
|
27
|
-
* a user. The whole point: negative values get prefixed with the real
|
|
28
|
-
* MINUS SIGN (U+2212) instead of the ASCII HYPHEN-MINUS (U+002D) that
|
|
29
|
-
* `toLocaleString` and template literals produce by default.
|
|
30
|
-
*
|
|
31
|
-
* U+2212 is the same visual width as `+` and reads as a sign rather
|
|
32
|
-
* than a hyphen — columns of signed numbers align cleanly and the
|
|
33
|
-
* glyph doesn't get confused with a bullet or list dash.
|
|
34
|
-
*/
|
|
35
|
-
declare const MINUS_SIGN = "\u2212";
|
|
36
|
-
/**
|
|
37
|
-
* Formats a number for display, substituting {@link MINUS_SIGN} for the ASCII
|
|
38
|
-
* hyphen `toLocaleString` emits. Non-finite values stringify as-is.
|
|
39
|
-
*/
|
|
40
|
-
declare function formatNumber(value: number, options?: Intl.NumberFormatOptions): string;
|
|
41
|
-
/** Suffixes a person may type, each mapped to its conversion into the shown unit. */
|
|
42
|
-
type UnitTable = Record<string, UnitEntry>;
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* What a surface holds, and which of its peers it is. Every surface that takes
|
|
46
|
-
* these takes both, and the theme decides how each looks.
|
|
47
|
-
*/
|
|
48
|
-
interface StanceProps {
|
|
49
|
-
/** The class of content the surface holds. Omitted, it draws as it always has. */
|
|
50
|
-
stance?: Stance;
|
|
51
|
-
/**
|
|
52
|
-
* Which of its peers this is: an index into the theme's tone list, wrapping,
|
|
53
|
-
* or a color given directly. Independent of `stance`, and allowed without one.
|
|
54
|
-
*/
|
|
55
|
-
tone?: number | string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/** What a {@link PrefRenderer} is given for the leaf it is rendering. */
|
|
59
|
-
interface PrefRenderContext {
|
|
60
|
-
/** Dotted path of the leaf within the schema root. */
|
|
61
|
-
path: string;
|
|
62
|
-
/** The schema node. App renderers narrow this to their own kind shape. */
|
|
63
|
-
pref: ToolPrefLeaf;
|
|
64
|
-
/** Current value — `values` at `path`, falling back to `pref.default`. */
|
|
65
|
-
value: unknown;
|
|
66
|
-
setValue: (value: unknown) => void;
|
|
67
|
-
/** Whether this leaf is currently auto — not pinned, computed by the owner. */
|
|
68
|
-
auto: boolean;
|
|
69
|
-
/** Toggle this leaf's auto state. */
|
|
70
|
-
setAuto: (next: boolean) => void;
|
|
71
|
-
}
|
|
72
|
-
/**
|
|
73
|
-
* Renders the control cell for one preference leaf. Returning `null`
|
|
74
|
-
* collapses the row.
|
|
75
|
-
*/
|
|
76
|
-
type PrefRenderer = (ctx: PrefRenderContext) => ReactNode;
|
|
77
|
-
|
|
78
|
-
export { MINUS_SIGN as M, formatNumber as f };
|
|
79
|
-
export type { Display as D, PrefRenderer as P, StanceProps as S, UnitTable as U, PrefRenderContext as a };
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import * as react from 'react';
|
|
2
|
-
import { ReactNode } from 'react';
|
|
3
|
-
import { S as StanceProps } from './PrefsRow.d-TOZ7BgD9.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* How much room a container gives its rows — gaps, padding, and field height,
|
|
7
|
-
* moved together. Set on any container in the family; it reaches every
|
|
8
|
-
* descendant, so an inner group can differ from the panel around it.
|
|
9
|
-
*/
|
|
10
|
-
type PropertyDensity = 'tight' | 'normal' | 'roomy';
|
|
11
|
-
/** Where an inline row's label and control sit on the row's cross axis. Set on
|
|
12
|
-
* a container to line a whole column of them up. */
|
|
13
|
-
type PropertyAlign = 'start' | 'center' | 'end' | 'baseline';
|
|
14
|
-
/** Metric props every container in the family takes. Both reach descendants,
|
|
15
|
-
* so the nearest container that states one wins. */
|
|
16
|
-
interface PropertyMetricProps {
|
|
17
|
-
/** Room the rows get. Unset inherits from an outer container, else `normal`. */
|
|
18
|
-
density?: PropertyDensity;
|
|
19
|
-
/**
|
|
20
|
-
* Cross-axis alignment of an inline row's label and control. `baseline` sits
|
|
21
|
-
* the control on the label's first-line baseline, which is what lines a
|
|
22
|
-
* column of swatches up against labels of different heights. Unset keeps each
|
|
23
|
-
* variant's own alignment — a color row centers its label and swatch and
|
|
24
|
-
* sinks the pair to the row's bottom edge, which keeps a paired alpha track
|
|
25
|
-
* level with its neighbour.
|
|
26
|
-
*/
|
|
27
|
-
align?: PropertyAlign;
|
|
28
|
-
}
|
|
29
|
-
/** Props for `<PropertyPanel>`. */
|
|
30
|
-
interface PropertyPanelProps extends PropertyMetricProps, StanceProps {
|
|
31
|
-
title?: ReactNode;
|
|
32
|
-
/** Controls on the trailing edge of the title row — a switch, a clear
|
|
33
|
-
* button. They sit outside the heading, so they neither take its type nor
|
|
34
|
-
* join its accessible name. */
|
|
35
|
-
actions?: ReactNode;
|
|
36
|
-
/**
|
|
37
|
-
* Lets text inside the panel be selected and copied. A panel is chrome by
|
|
38
|
-
* default, so a drag across it moves a slider rather than painting a
|
|
39
|
-
* selection; a `debug` panel defaults to selectable, since what it shows —
|
|
40
|
-
* ids, keys, traces — is there to be copied.
|
|
41
|
-
*/
|
|
42
|
-
selectable?: boolean;
|
|
43
|
-
children: ReactNode;
|
|
44
|
-
className?: string;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* A titled panel holding property rows — the sidebar container the rest of
|
|
48
|
-
* this module's components fill.
|
|
49
|
-
*
|
|
50
|
-
* `stance` says what kind of content it holds and `tone` which of its peers it
|
|
51
|
-
* is; the theme's `--wzl-panel-*` and `--wzl-stance-*` slots decide how each looks. A stanced
|
|
52
|
-
* panel's title takes the row-label recipe rather than the display title.
|
|
53
|
-
*/
|
|
54
|
-
declare function PropertyPanel({ title, actions, selectable, children, className, density, align, stance, tone, }: PropertyPanelProps): react.JSX.Element;
|
|
55
|
-
/** How a property list packs its rows into two columns. */
|
|
56
|
-
type PropertyListPack = 'auto-color' | 'pairs' | 'one-up';
|
|
57
|
-
/** Props for `<PropertyList>`. */
|
|
58
|
-
interface PropertyListProps extends PropertyMetricProps {
|
|
59
|
-
children: ReactNode;
|
|
60
|
-
className?: string;
|
|
61
|
-
/**
|
|
62
|
-
* How rows pack into the 2-column grid.
|
|
63
|
-
* - `'auto-color'` (default): only color rows pair side-by-side; everything
|
|
64
|
-
* else spans the full width. Right for sparse top-level panels.
|
|
65
|
-
* - `'pairs'`: every row auto-places into the 2-column grid two-per-row.
|
|
66
|
-
* Headers and subpanels still span the full width; wrap any other
|
|
67
|
-
* full-width child in `<PropertySpan>`. Right for dense effect bodies.
|
|
68
|
-
* - `'one-up'`: every row spans the full width, color rows included. Right
|
|
69
|
-
* for a palette — a column of swatches read as a group.
|
|
70
|
-
*/
|
|
71
|
-
pack?: PropertyListPack;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Grid container for PropertyRows. Use standalone for chrome-less layouts, or
|
|
75
|
-
* nest inside <PropertyPanel/> for the standard glass card.
|
|
76
|
-
*/
|
|
77
|
-
declare const PropertyList: react.ForwardRefExoticComponent<PropertyListProps & react.RefAttributes<HTMLDivElement>>;
|
|
78
|
-
/** Props for `<PropertySpan>`. */
|
|
79
|
-
interface PropertySpanProps {
|
|
80
|
-
children: ReactNode;
|
|
81
|
-
className?: string;
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Wrapper that makes an arbitrary child span both columns of a
|
|
85
|
-
* `<PropertyList pack="pairs">`, a `<PropertyGroup pack="pairs">` body, or a
|
|
86
|
-
* `<Subpanel>`. `<PropertyRow span>` covers the row case; this covers
|
|
87
|
-
* everything else a consumer puts in the grid.
|
|
88
|
-
*/
|
|
89
|
-
declare function PropertySpan({ children, className }: PropertySpanProps): react.JSX.Element;
|
|
90
|
-
/** Which control shape a row holds, which decides its intrinsic layout. */
|
|
91
|
-
type PropertyRowVariant = 'default' | 'color' | 'checkbox';
|
|
92
|
-
/** Whether a row's label sits above its control or beside it. */
|
|
93
|
-
type PropertyRowLayout = 'block' | 'inline';
|
|
94
|
-
/** Props for `<PropertyRow>`. */
|
|
95
|
-
interface PropertyRowProps extends PropertyMetricProps {
|
|
96
|
-
label: ReactNode;
|
|
97
|
-
/** Right-aligned readout shown next to the label (e.g. current value). */
|
|
98
|
-
readout?: ReactNode;
|
|
99
|
-
/**
|
|
100
|
-
* Help text for the row, shown in a tooltip off an ⓘ affordance beside the
|
|
101
|
-
* label. Empty or absent renders no affordance.
|
|
102
|
-
*/
|
|
103
|
-
description?: string;
|
|
104
|
-
variant?: PropertyRowVariant;
|
|
105
|
-
/**
|
|
106
|
-
* Label position relative to the control. Unset takes the variant's own
|
|
107
|
-
* orientation: `block` — label above control — for the default variant, and
|
|
108
|
-
* `inline` for the color and checkbox variants, which read as a row.
|
|
109
|
-
*/
|
|
110
|
-
layout?: PropertyRowLayout;
|
|
111
|
-
/**
|
|
112
|
-
* Take the full width of the enclosing grid. Only has an effect inside a
|
|
113
|
-
* `<PropertyList pack="pairs">` or a `<Subpanel>`; elsewhere rows are already
|
|
114
|
-
* full width.
|
|
115
|
-
*/
|
|
116
|
-
span?: boolean;
|
|
117
|
-
children: ReactNode;
|
|
118
|
-
htmlFor?: string;
|
|
119
|
-
/** The control is a group of several (a segmented toggle), not one element.
|
|
120
|
-
* The row then renders as a `<div>`: a `<label>` hands a click on its text to
|
|
121
|
-
* its first control, which in a group means selecting the first option. Each
|
|
122
|
-
* member has to carry its own name. */
|
|
123
|
-
group?: boolean;
|
|
124
|
-
className?: string;
|
|
125
|
-
/** The row is auto: its value is not pinned and the owner computes it. The
|
|
126
|
-
* control is hidden — its box kept, so the row does not resize — and the
|
|
127
|
-
* row reads out the word instead. */
|
|
128
|
-
auto?: boolean;
|
|
129
|
-
/** Given, the row's label toggles `auto` when it is clicked. Omitted, the row
|
|
130
|
-
* can show an auto state but not change it.
|
|
131
|
-
*
|
|
132
|
-
* The label then names that toggle, so a control passed as `children` has to
|
|
133
|
-
* carry its own accessible name — every `<PropertyField>` does. */
|
|
134
|
-
onAutoChange?: (next: boolean) => void;
|
|
135
|
-
}
|
|
136
|
-
/** The label-plus-control frame `<PropertyField>` draws its rows in. Use it
|
|
137
|
-
* directly for a control no field kind covers. */
|
|
138
|
-
declare function PropertyRow({ label, readout, description, variant, layout, span, children, htmlFor, group, className, density, align, auto, onAutoChange, }: PropertyRowProps): react.JSX.Element;
|
|
139
|
-
|
|
140
|
-
export { PropertyList as c, PropertyPanel as e, PropertyRow as g, PropertySpan as j };
|
|
141
|
-
export type { PropertyMetricProps as P, PropertyRowLayout as a, PropertyListPack as b, PropertyListProps as d, PropertyPanelProps as f, PropertyRowProps as h, PropertyRowVariant as i, PropertySpanProps as k, PropertyAlign as l, PropertyDensity as m };
|