@weasel-js/labkit 1.6.0 → 1.7.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/dist/_dts/{CanvasStackContext-DQgcH1ny.d.ts → CanvasStackContext-D2jnIwfk.d.ts} +1 -1
- package/dist/_dts/FloatingPanel-7j0IcXwz.d.ts +30 -0
- package/dist/_dts/{LayerList.d-2c9yup5Y.d.ts → LayerList.d-DiuEArKq.d.ts} +4 -4
- package/dist/_dts/PrefsRow.d-TOZ7BgD9.d.ts +79 -0
- package/dist/_dts/PropertyPanel.d-D-1paCbE.d.ts +141 -0
- package/dist/_dts/{Select.d-BchGMC2Y.d.ts → Select.d-Bensr_MT.d.ts} +15 -6
- package/dist/_dts/Stage-CCWfQQWM.d.ts +202 -0
- package/dist/_dts/index-B2Yj5aA0.d.ts +274 -0
- package/dist/_dts/{index-B0--8PEM.d.ts → index-CsYqUHD3.d.ts} +12 -13
- package/dist/_dts/{types-B7y8hX1D.d.ts → types-CRPSGFAp.d.ts} +33 -5
- package/dist/_dts/{frac-DTRq7Xpb.d.ts → types-CSm9jgol.d.ts} +700 -650
- package/dist/_dts/{useTrialState-CP4jfuKl.d.ts → useTrialState-CTZPgeZ7.d.ts} +2 -3
- package/dist/canvas/index.d.ts +40 -8
- package/dist/canvas/index.js +5 -3
- package/dist/chrome/index.d.ts +5 -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-275JRRVD.js +728 -0
- package/dist/chunk-275JRRVD.js.map +1 -0
- package/dist/chunk-3RY6WL5T.js +38 -0
- package/dist/chunk-3RY6WL5T.js.map +1 -0
- package/dist/chunk-4LJSC7MB.js +143 -0
- package/dist/chunk-4LJSC7MB.js.map +1 -0
- package/dist/{chunk-3FI7Y4R4.js → chunk-7BO7HNGF.js} +5 -5
- package/dist/{chunk-3FI7Y4R4.js.map → chunk-7BO7HNGF.js.map} +1 -1
- package/dist/chunk-AWQG7FCC.js +19 -0
- package/dist/chunk-AWQG7FCC.js.map +1 -0
- package/dist/chunk-CZZPXUOU.js +3 -0
- package/dist/{chunk-SBXNQW4G.js.map → chunk-CZZPXUOU.js.map} +1 -1
- package/dist/{chunk-ZORVNOKX.js → chunk-FMK7UQ6V.js} +24 -145
- package/dist/chunk-FMK7UQ6V.js.map +1 -0
- package/dist/{chunk-BVL7Y574.js → chunk-FZ7YFQN7.js} +26 -10
- package/dist/chunk-FZ7YFQN7.js.map +1 -0
- package/dist/{chunk-USO6TERP.js → chunk-GOZLNM4L.js} +11 -9
- package/dist/chunk-GOZLNM4L.js.map +1 -0
- package/dist/{chunk-H5VIV7MQ.js → chunk-I5DUQ5HM.js} +88 -82
- package/dist/chunk-I5DUQ5HM.js.map +1 -0
- package/dist/chunk-J7OWWTCW.js +143 -0
- package/dist/chunk-J7OWWTCW.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-VQ47KWD5.js → chunk-KMJ7RWD3.js} +18 -7
- package/dist/chunk-KMJ7RWD3.js.map +1 -0
- package/dist/{chunk-ERFMC6WU.js → chunk-M7HP3FTK.js} +20 -11
- package/dist/chunk-M7HP3FTK.js.map +1 -0
- package/dist/chunk-MIM5R4ZT.js +14972 -0
- package/dist/chunk-MIM5R4ZT.js.map +1 -0
- package/dist/{chunk-HFRE4QQV.js → chunk-T5IBSPAM.js} +96 -32
- package/dist/chunk-T5IBSPAM.js.map +1 -0
- package/dist/chunk-UNAZSLWE.js +294 -0
- package/dist/chunk-UNAZSLWE.js.map +1 -0
- package/dist/{chunk-RS3HRQWU.js → chunk-WPLAANH4.js} +4 -3
- package/dist/chunk-WPLAANH4.js.map +1 -0
- package/dist/{chunk-AWH3SRPW.js → chunk-Y23G2VZL.js} +5 -37
- package/dist/chunk-Y23G2VZL.js.map +1 -0
- package/dist/{chunk-MOLIUNVH.js → chunk-YT75VYRD.js} +4 -4
- package/dist/{chunk-MOLIUNVH.js.map → chunk-YT75VYRD.js.map} +1 -1
- package/dist/chunk-ZIFPHIWZ.js +302 -0
- package/dist/chunk-ZIFPHIWZ.js.map +1 -0
- package/dist/config/index.d.ts +48 -40
- package/dist/config/index.js +4 -5
- package/dist/controls/index.d.ts +91 -7
- package/dist/controls/index.js +5 -4
- package/dist/dragdrop/index.d.ts +9 -7
- package/dist/dragdrop/index.js +3 -2
- package/dist/index.d.ts +294 -82
- package/dist/index.js +425 -402
- package/dist/index.js.map +1 -1
- package/dist/layers/index.d.ts +4 -5
- package/dist/layers/index.js +2 -1
- package/dist/loupe/index.d.ts +20 -17
- package/dist/loupe/index.js +5 -3
- package/dist/overview/index.d.ts +56 -0
- package/dist/overview/index.js +289 -0
- package/dist/overview/index.js.map +1 -0
- package/dist/passthrough/weasel-ui.d.ts +239 -69
- package/dist/passthrough/weasel-ui.js +3 -2
- package/dist/primitives/index.d.ts +5 -204
- package/dist/primitives/index.js +6 -4
- package/dist/state/index.d.ts +8 -8
- package/dist/state/index.js +4 -5
- package/dist/state/index.js.map +1 -1
- package/dist/styles.css +152 -82
- package/dist/undo/index.d.ts +4 -4
- package/package.json +17 -12
- package/src/annotations/AnnotationOverlay.tsx +2 -2
- package/src/annotations/Annotations.less +0 -10
- package/src/annotations/MarkList.tsx +4 -8
- package/src/annotations/index.ts +1 -0
- package/src/annotations/paint.test.ts +3 -14
- package/src/annotations/paint.ts +3 -19
- package/src/annotations/store.test.ts +26 -0
- package/src/annotations/store.ts +25 -6
- package/src/annotations/svgNodes.test.ts +6 -9
- package/src/annotations/svgNodes.ts +3 -3
- package/src/annotations/toolMap.test.ts +37 -2
- package/src/annotations/toolMap.ts +13 -0
- package/src/annotations/types.ts +27 -0
- package/src/canvas/AGENTS.md +9 -10
- package/src/canvas/CameraInput.test.tsx +136 -0
- package/src/canvas/CameraInput.tsx +322 -0
- package/src/canvas/CanvasStack.tsx +47 -58
- package/src/canvas/LinkedCursor.less +16 -0
- package/src/canvas/LinkedCursor.tsx +54 -0
- package/src/canvas/Stage.test.tsx +33 -4
- package/src/canvas/Stage.tsx +47 -37
- package/src/canvas/cameraRegistry.test.ts +55 -0
- package/src/canvas/cameraRegistry.ts +86 -0
- package/src/canvas/cameraView.test.ts +60 -0
- package/src/canvas/cameraView.ts +61 -0
- package/src/canvas/cameraZoom.test.ts +46 -0
- package/src/canvas/cameraZoom.ts +24 -0
- package/src/canvas/index.ts +23 -2
- package/src/canvas/sharedScope.test.tsx +94 -0
- package/src/chrome/ChromeRegions.stories.tsx +1 -0
- package/src/chrome/regions/PaletteRegion.less +0 -7
- package/src/chrome/regions/SidebarRegion.less +12 -2
- package/src/chrome/regions/SidebarRegion.test.tsx +9 -2
- package/src/config/builder.test.ts +2 -1
- package/src/config/builder.ts +15 -8
- package/src/config/entry.test.ts +3 -1
- package/src/config/fromConfigField.test.ts +14 -0
- package/src/config/fromConfigField.ts +19 -4
- package/src/config/index.ts +4 -1
- package/src/config/path.ts +2 -5
- package/src/config/resolve.ts +15 -1
- package/src/config/sectionTree.test.ts +12 -6
- package/src/config/sectionTree.ts +15 -5
- package/src/config/types.ts +34 -9
- package/src/controls/ControlPanel.less +1 -1
- package/src/controls/ControlPanel.stories.tsx +3 -2
- package/src/controls/ControlPanel.test.tsx +76 -13
- package/src/controls/ControlPanel.tsx +80 -11
- package/src/controls/inDialog.test.tsx +18 -0
- package/src/controls/inDialog.tsx +2 -10
- package/src/index.test.ts +1 -1
- package/src/index.ts +23 -5
- package/src/instrument/SineWave.smoke.test.tsx +2 -0
- package/src/instrument/types.ts +10 -1
- package/src/lab/Lab.nebula.test.tsx +11 -2
- package/src/lab/Lab.test.tsx +3 -1
- package/src/lab/Lab.tsx +87 -76
- package/src/lab/{LabFit.stories.less → LabFit.browser.test.less} +1 -1
- package/src/lab/{LabFit.stories.tsx → LabFit.browser.test.tsx} +41 -63
- package/src/lab/LabFullChrome.stories.tsx +1 -0
- package/src/lab/LabHeader.test.tsx +24 -14
- package/src/lab/LabHeader.tsx +11 -12
- package/src/lab/LabShell.less +8 -17
- package/src/lab/LabSwitcher.less +6 -6
- package/src/lab/LabZoom.test.tsx +223 -0
- package/src/lab/LabZoom.tsx +170 -0
- package/src/lab/index.ts +1 -0
- package/src/loupe/AGENTS.md +7 -6
- package/src/loupe/LoupeGestures.tsx +15 -10
- 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 +376 -0
- package/src/overview/index.ts +2 -0
- package/src/passthrough/weasel-ui.test.ts +2 -0
- package/src/passthrough/weasel-ui.ts +23 -4
- package/src/primitives/FloatingPanel.test.tsx +11 -0
- package/src/primitives/FloatingPanel.tsx +2 -5
- package/src/primitives/JobProgress.less +1 -1
- package/src/primitives/Legend.stories.tsx +1 -0
- package/src/primitives/Readout.browser.test.tsx +137 -0
- package/src/primitives/Readout.less +12 -0
- package/src/primitives/Readout.stories.tsx +58 -0
- package/src/primitives/Readout.test.tsx +93 -0
- package/src/primitives/Readout.tsx +56 -0
- package/src/primitives/index.ts +2 -0
- package/src/specimen/Specimen.stories.tsx +1 -0
- package/src/specimen/Specimen.tsx +21 -4
- package/src/state/Persistence.browser.test.tsx +47 -0
- package/src/state/labRecords.test.ts +4 -1
- package/src/state/store.test.ts +9 -5
- package/src/state/usePersistedState.test.tsx +1 -1
- package/src/state/useTrialState.test.tsx +1 -1
- package/src/styles.less +3 -0
- package/src/theme/Interstellar.stories.tsx +4 -6
- package/src/theme/base.less +21 -47
- package/src/theme/interstellar.test.ts +1 -1
- package/src/theme/interstellar.theme.json +10 -3
- package/src/tools/labTool.ts +6 -2
- package/src/trial/Trial.annotations.test.tsx +16 -0
- package/src/trial/Trial.less +0 -13
- package/src/trial/Trial.loupe.test.tsx +73 -1
- package/src/trial/Trial.stories.tsx +2 -0
- package/src/trial/Trial.tsx +23 -1
- package/src/trial/TrialChrome.tsx +21 -3
- package/src/trial/trialOps.test.ts +4 -4
- package/dist/_dts/PrefsRow.d-DFpPIeIC.d.ts +0 -39
- package/dist/_dts/inDialog-D5ZKGjiD.d.ts +0 -23
- package/dist/_dts/index-DINmCuLA.d.ts +0 -453
- package/dist/_dts/number.d-OeQYQoUO.d.ts +0 -28
- package/dist/_dts/usePanZoom-Bq73pwFe.d.ts +0 -117
- package/dist/chunk-2AYGEN57.js +0 -32
- package/dist/chunk-2AYGEN57.js.map +0 -1
- package/dist/chunk-AWH3SRPW.js.map +0 -1
- package/dist/chunk-BVL7Y574.js.map +0 -1
- package/dist/chunk-ERFMC6WU.js.map +0 -1
- package/dist/chunk-H5VIV7MQ.js.map +0 -1
- package/dist/chunk-HFRE4QQV.js.map +0 -1
- package/dist/chunk-RS3HRQWU.js.map +0 -1
- package/dist/chunk-SBXNQW4G.js +0 -3
- package/dist/chunk-TT5C5S6R.js +0 -368
- package/dist/chunk-TT5C5S6R.js.map +0 -1
- package/dist/chunk-USO6TERP.js.map +0 -1
- package/dist/chunk-VQ47KWD5.js.map +0 -1
- package/dist/chunk-WUJXJC5O.js +0 -14568
- package/dist/chunk-WUJXJC5O.js.map +0 -1
- package/dist/chunk-ZORVNOKX.js.map +0 -1
- package/src/canvas/usePanZoom.test.ts +0 -244
- package/src/canvas/usePanZoom.ts +0 -147
- package/src/state/Persistence.stories.tsx +0 -75
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { useSurfaceOptional } from './chunk-WIG6XHJ7.js';
|
|
2
|
+
import { CameraContext, pointerElsewhere, STAGE_VIEW_ID, normalize2DView, useCameraView, CameraScope, CameraInput } from './chunk-UNAZSLWE.js';
|
|
3
|
+
import { resolveFrame, DEFAULT_FRAME } from './chunk-24W5VEJW.js';
|
|
4
|
+
import { CanvasStackContext } from './chunk-CQLQPQ4P.js';
|
|
5
|
+
import { useContext, useRef, useState, useEffect, useMemo } from 'react';
|
|
6
|
+
import { usePointerPosition, crosshairRects, useVisibleRaf } from '@weasel-js/core';
|
|
7
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
8
|
+
|
|
9
|
+
var ARMS = ["left", "right", "up", "down"];
|
|
10
|
+
function LinkedCursor() {
|
|
11
|
+
const camera = useContext(CameraContext);
|
|
12
|
+
const pointer = usePointerPosition();
|
|
13
|
+
if (!camera) return null;
|
|
14
|
+
const local = pointerElsewhere(pointer, STAGE_VIEW_ID, camera.frame);
|
|
15
|
+
if (!local) return null;
|
|
16
|
+
const v = camera.view.get();
|
|
17
|
+
const x = (local.x - v.x) * v.scale.x;
|
|
18
|
+
const y = (local.y * camera.frame.yDir - v.y) * v.scale.y;
|
|
19
|
+
const { halo, bars } = crosshairRects(x, y, 1);
|
|
20
|
+
const arms = ARMS.map((name, i) => ({ name, halo: halo[i], bar: bars[i] }));
|
|
21
|
+
return /* @__PURE__ */ jsxs("svg", { className: "lk-linked-cursor", "aria-hidden": "true", children: [
|
|
22
|
+
arms.map(
|
|
23
|
+
({ name, halo: r }) => r ? /* @__PURE__ */ jsx(
|
|
24
|
+
"rect",
|
|
25
|
+
{
|
|
26
|
+
className: "lk-linked-cursor__halo",
|
|
27
|
+
x: r.x,
|
|
28
|
+
y: r.y,
|
|
29
|
+
width: r.w,
|
|
30
|
+
height: r.h
|
|
31
|
+
},
|
|
32
|
+
`halo-${name}`
|
|
33
|
+
) : null
|
|
34
|
+
),
|
|
35
|
+
arms.map(
|
|
36
|
+
({ name, bar: r }) => r ? /* @__PURE__ */ jsx(
|
|
37
|
+
"rect",
|
|
38
|
+
{
|
|
39
|
+
className: "lk-linked-cursor__bar",
|
|
40
|
+
x: r.x,
|
|
41
|
+
y: r.y,
|
|
42
|
+
width: r.w,
|
|
43
|
+
height: r.h
|
|
44
|
+
},
|
|
45
|
+
`bar-${name}`
|
|
46
|
+
) : null
|
|
47
|
+
)
|
|
48
|
+
] });
|
|
49
|
+
}
|
|
50
|
+
function useLayerScheduler({
|
|
51
|
+
layers,
|
|
52
|
+
view,
|
|
53
|
+
frame = DEFAULT_FRAME,
|
|
54
|
+
canvasRefs,
|
|
55
|
+
size,
|
|
56
|
+
host
|
|
57
|
+
}) {
|
|
58
|
+
const dirty = useRef(/* @__PURE__ */ new Set());
|
|
59
|
+
const lastRenderRef = useRef(/* @__PURE__ */ new Map());
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
for (const layer of layers) {
|
|
62
|
+
const prev = lastRenderRef.current.get(layer.id);
|
|
63
|
+
if (prev !== layer.render) dirty.current.add(layer.id);
|
|
64
|
+
lastRenderRef.current.set(layer.id, layer.render);
|
|
65
|
+
}
|
|
66
|
+
for (const id of [...lastRenderRef.current.keys()]) {
|
|
67
|
+
if (!layers.find((l) => l.id === id)) lastRenderRef.current.delete(id);
|
|
68
|
+
}
|
|
69
|
+
}, [layers]);
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
for (const layer of layers) dirty.current.add(layer.id);
|
|
72
|
+
}, [view, frame, size, layers]);
|
|
73
|
+
const frameLoop = useVisibleRaf(
|
|
74
|
+
() => {
|
|
75
|
+
if (dirty.current.size === 0) return;
|
|
76
|
+
const map = canvasRefs.current;
|
|
77
|
+
if (!map) {
|
|
78
|
+
dirty.current.clear();
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
for (const layer of layers) {
|
|
82
|
+
if (!dirty.current.has(layer.id)) continue;
|
|
83
|
+
if (!layer.visible) continue;
|
|
84
|
+
const canvas = map.get(layer.id);
|
|
85
|
+
if (!canvas) continue;
|
|
86
|
+
const ctx = canvas.getContext("2d");
|
|
87
|
+
if (!ctx) continue;
|
|
88
|
+
ctx.save();
|
|
89
|
+
ctx.setTransform(size.dpr, 0, 0, size.dpr, 0, 0);
|
|
90
|
+
ctx.clearRect(0, 0, size.width, size.height);
|
|
91
|
+
layer.render(ctx, view, frame);
|
|
92
|
+
ctx.restore();
|
|
93
|
+
}
|
|
94
|
+
dirty.current.clear();
|
|
95
|
+
},
|
|
96
|
+
{ target: host }
|
|
97
|
+
);
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
if (dirty.current.size > 0) frameLoop.request();
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
function CanvasStack({
|
|
103
|
+
layers,
|
|
104
|
+
view: viewProp,
|
|
105
|
+
onViewChange,
|
|
106
|
+
worldSpec,
|
|
107
|
+
minZoom,
|
|
108
|
+
maxZoom,
|
|
109
|
+
width = "100%",
|
|
110
|
+
height = "100%",
|
|
111
|
+
className,
|
|
112
|
+
onResize,
|
|
113
|
+
onHitTest,
|
|
114
|
+
children,
|
|
115
|
+
yoke
|
|
116
|
+
}) {
|
|
117
|
+
const view = normalize2DView(viewProp);
|
|
118
|
+
const containerRef = useRef(null);
|
|
119
|
+
const canvasMap = useRef(/* @__PURE__ */ new Map());
|
|
120
|
+
const [size, setSize] = useState({ width: 0, height: 0, dpr: 1 });
|
|
121
|
+
const setCanvasRef = (id, el) => {
|
|
122
|
+
if (el) canvasMap.current.set(id, el);
|
|
123
|
+
else canvasMap.current.delete(id);
|
|
124
|
+
};
|
|
125
|
+
useEffect(() => {
|
|
126
|
+
const el = containerRef.current;
|
|
127
|
+
if (!el) return;
|
|
128
|
+
const update = () => {
|
|
129
|
+
const rect = el.getBoundingClientRect();
|
|
130
|
+
const dpr = window.devicePixelRatio ?? 1;
|
|
131
|
+
setSize((prev) => {
|
|
132
|
+
if (prev.width === rect.width && prev.height === rect.height && prev.dpr === dpr) {
|
|
133
|
+
return prev;
|
|
134
|
+
}
|
|
135
|
+
return { width: rect.width, height: rect.height, dpr };
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
update();
|
|
139
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
140
|
+
const ro = new ResizeObserver(update);
|
|
141
|
+
ro.observe(el);
|
|
142
|
+
return () => ro.disconnect();
|
|
143
|
+
}, []);
|
|
144
|
+
const onResizeRef = useRef(onResize);
|
|
145
|
+
onResizeRef.current = onResize;
|
|
146
|
+
useEffect(() => {
|
|
147
|
+
if (size.width === 0 && size.height === 0) return;
|
|
148
|
+
onResizeRef.current?.({ width: size.width, height: size.height });
|
|
149
|
+
}, [size.width, size.height]);
|
|
150
|
+
const frame = useMemo(() => resolveFrame(worldSpec, size), [worldSpec, size]);
|
|
151
|
+
const camera = useCameraView({
|
|
152
|
+
view: viewProp,
|
|
153
|
+
onViewChange,
|
|
154
|
+
frame,
|
|
155
|
+
hostRef: containerRef,
|
|
156
|
+
minZoom,
|
|
157
|
+
maxZoom
|
|
158
|
+
});
|
|
159
|
+
const cameraCtx = useMemo(
|
|
160
|
+
() => ({ view: camera, frame, element: () => containerRef.current }),
|
|
161
|
+
[camera, frame]
|
|
162
|
+
);
|
|
163
|
+
useLayerScheduler({ layers, view, frame, canvasRefs: canvasMap, size, host: containerRef });
|
|
164
|
+
const ctxValue = useMemo(
|
|
165
|
+
() => ({
|
|
166
|
+
view,
|
|
167
|
+
frame,
|
|
168
|
+
surface: { element: containerRef, size, canvases: canvasMap, layers }
|
|
169
|
+
}),
|
|
170
|
+
[view, frame, size, layers]
|
|
171
|
+
);
|
|
172
|
+
const containerStyle = { width, height };
|
|
173
|
+
const canvasPx = {
|
|
174
|
+
width: Math.max(0, Math.round(size.width * size.dpr)),
|
|
175
|
+
height: Math.max(0, Math.round(size.height * size.dpr))
|
|
176
|
+
};
|
|
177
|
+
const canvasCss = {
|
|
178
|
+
width: size.width,
|
|
179
|
+
height: size.height
|
|
180
|
+
};
|
|
181
|
+
return /* @__PURE__ */ jsx(CameraScope, { yoke, children: /* @__PURE__ */ jsx(CameraContext.Provider, { value: cameraCtx, children: /* @__PURE__ */ jsxs(CanvasStackContext.Provider, { value: ctxValue, children: [
|
|
182
|
+
/* @__PURE__ */ jsx(CameraInput, { hostRef: containerRef, camera, frame, onTap: onHitTest }),
|
|
183
|
+
/* @__PURE__ */ jsxs(
|
|
184
|
+
"div",
|
|
185
|
+
{
|
|
186
|
+
ref: containerRef,
|
|
187
|
+
className: className ? `lk-canvas-stack ${className}` : "lk-canvas-stack",
|
|
188
|
+
style: containerStyle,
|
|
189
|
+
children: [
|
|
190
|
+
layers.map((layer) => /* @__PURE__ */ jsx(
|
|
191
|
+
"canvas",
|
|
192
|
+
{
|
|
193
|
+
ref: (el) => setCanvasRef(layer.id, el),
|
|
194
|
+
className: "lk-canvas-stack__canvas",
|
|
195
|
+
width: canvasPx.width,
|
|
196
|
+
height: canvasPx.height,
|
|
197
|
+
style: { ...canvasCss, display: layer.visible ? "block" : "none" }
|
|
198
|
+
},
|
|
199
|
+
layer.id
|
|
200
|
+
)),
|
|
201
|
+
/* @__PURE__ */ jsx(LinkedCursor, {}),
|
|
202
|
+
/* @__PURE__ */ jsx("div", { className: "lk-canvas-stack__overlay", children })
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
)
|
|
206
|
+
] }) }) });
|
|
207
|
+
}
|
|
208
|
+
function fitStage(size, viewport) {
|
|
209
|
+
if (!(size.width > 0 && size.height > 0 && viewport.width > 0 && viewport.height > 0)) {
|
|
210
|
+
return { zoom: 1, pan: { x: 0, y: 0 } };
|
|
211
|
+
}
|
|
212
|
+
const zoom = Math.min(1, viewport.width / size.width, viewport.height / size.height);
|
|
213
|
+
return {
|
|
214
|
+
zoom,
|
|
215
|
+
pan: {
|
|
216
|
+
x: (viewport.width - size.width * zoom) / 2,
|
|
217
|
+
y: (viewport.height - size.height * zoom) / 2
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function Stage({
|
|
222
|
+
size,
|
|
223
|
+
view: viewProp,
|
|
224
|
+
onViewChange,
|
|
225
|
+
minZoom,
|
|
226
|
+
maxZoom,
|
|
227
|
+
onResize,
|
|
228
|
+
hostRef,
|
|
229
|
+
overlay,
|
|
230
|
+
children,
|
|
231
|
+
yoke
|
|
232
|
+
}) {
|
|
233
|
+
const view = normalize2DView(viewProp);
|
|
234
|
+
const host = useRef(null);
|
|
235
|
+
const surface = useSurfaceOptional();
|
|
236
|
+
const camera = useCameraView({
|
|
237
|
+
view: viewProp,
|
|
238
|
+
onViewChange,
|
|
239
|
+
frame: DEFAULT_FRAME,
|
|
240
|
+
hostRef: host,
|
|
241
|
+
minZoom,
|
|
242
|
+
maxZoom
|
|
243
|
+
});
|
|
244
|
+
const cameraCtx = useMemo(
|
|
245
|
+
() => ({
|
|
246
|
+
view: camera,
|
|
247
|
+
frame: DEFAULT_FRAME,
|
|
248
|
+
element: () => host.current,
|
|
249
|
+
content: { x: 0, y: 0, width: size.width, height: size.height }
|
|
250
|
+
}),
|
|
251
|
+
[camera, size.width, size.height]
|
|
252
|
+
);
|
|
253
|
+
const onResizeRef = useRef(onResize);
|
|
254
|
+
onResizeRef.current = onResize;
|
|
255
|
+
useEffect(() => {
|
|
256
|
+
const el = host.current;
|
|
257
|
+
if (!el) return;
|
|
258
|
+
const measure = () => {
|
|
259
|
+
const rect = el.getBoundingClientRect();
|
|
260
|
+
if (rect.width > 0 && rect.height > 0) {
|
|
261
|
+
onResizeRef.current?.({ width: rect.width, height: rect.height });
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
measure();
|
|
265
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
266
|
+
const ro = new ResizeObserver(measure);
|
|
267
|
+
ro.observe(el);
|
|
268
|
+
return () => ro.disconnect();
|
|
269
|
+
}, []);
|
|
270
|
+
useEffect(() => {
|
|
271
|
+
surface?.invalidateRects();
|
|
272
|
+
}, [surface, view.zoom, view.pan.x, view.pan.y]);
|
|
273
|
+
const cameraVars = {
|
|
274
|
+
["--lk-stage-x"]: `${view.pan.x}px`,
|
|
275
|
+
["--lk-stage-y"]: `${view.pan.y}px`,
|
|
276
|
+
["--lk-stage-zoom"]: String(view.zoom),
|
|
277
|
+
["--lk-stage-w"]: `${size.width}px`,
|
|
278
|
+
["--lk-stage-h"]: `${size.height}px`
|
|
279
|
+
};
|
|
280
|
+
return /* @__PURE__ */ jsx(CameraScope, { yoke, children: /* @__PURE__ */ jsxs(CameraContext.Provider, { value: cameraCtx, children: [
|
|
281
|
+
/* @__PURE__ */ jsx(CameraInput, { hostRef: host, camera, frame: DEFAULT_FRAME }),
|
|
282
|
+
/* @__PURE__ */ jsxs(
|
|
283
|
+
"div",
|
|
284
|
+
{
|
|
285
|
+
ref: (el) => {
|
|
286
|
+
host.current = el;
|
|
287
|
+
if (hostRef) hostRef.current = el;
|
|
288
|
+
},
|
|
289
|
+
className: "lk-stage",
|
|
290
|
+
children: [
|
|
291
|
+
/* @__PURE__ */ jsx("div", { className: "lk-stage__content", style: cameraVars, children }),
|
|
292
|
+
/* @__PURE__ */ jsx(LinkedCursor, {}),
|
|
293
|
+
overlay
|
|
294
|
+
]
|
|
295
|
+
}
|
|
296
|
+
)
|
|
297
|
+
] }) });
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export { CanvasStack, LinkedCursor, Stage, fitStage };
|
|
301
|
+
//# sourceMappingURL=chunk-ZIFPHIWZ.js.map
|
|
302
|
+
//# sourceMappingURL=chunk-ZIFPHIWZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/canvas/LinkedCursor.tsx","../src/canvas/useLayerScheduler.ts","../src/canvas/CanvasStack.tsx","../src/canvas/Stage.tsx"],"names":["useRef","useEffect","jsx","jsxs","useMemo"],"mappings":"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","file":"chunk-ZIFPHIWZ.js","sourcesContent":["import { crosshairRects, usePointerPosition } from '@weasel-js/core';\nimport { useContext } from 'react';\nimport { CameraContext, pointerElsewhere, STAGE_VIEW_ID } from './CameraInput';\n\n/** `crosshairRects` returns its four arms in this order. */\nconst ARMS = ['left', 'right', 'up', 'down'] as const;\n\n/**\n * The other side of a linked cursor: a crosshair on the camera's own element\n * wherever the shared pointer is over some other view — an overview, say. The\n * same crosshair core paints on a weasel canvas.\n */\nexport function LinkedCursor() {\n const camera = useContext(CameraContext);\n const pointer = usePointerPosition();\n if (!camera) return null;\n const local = pointerElsewhere(pointer, STAGE_VIEW_ID, camera.frame);\n if (!local) return null;\n // `pointerElsewhere` hands back the instrument's world; the camera works\n // frame-local, and the map is its own inverse.\n const v = camera.view.get();\n const x = (local.x - v.x) * v.scale.x;\n const y = (local.y * camera.frame.yDir - v.y) * v.scale.y;\n const { halo, bars } = crosshairRects(x, y, 1);\n const arms = ARMS.map((name, i) => ({ name, halo: halo[i], bar: bars[i] }));\n return (\n <svg className=\"lk-linked-cursor\" aria-hidden=\"true\">\n {arms.map(({ name, halo: r }) =>\n r ? (\n <rect\n key={`halo-${name}`}\n className=\"lk-linked-cursor__halo\"\n x={r.x}\n y={r.y}\n width={r.w}\n height={r.h}\n />\n ) : null,\n )}\n {arms.map(({ name, bar: r }) =>\n r ? (\n <rect\n key={`bar-${name}`}\n className=\"lk-linked-cursor__bar\"\n x={r.x}\n y={r.y}\n width={r.w}\n height={r.h}\n />\n ) : null,\n )}\n </svg>\n );\n}\n","import { useVisibleRaf } from '@weasel-js/core';\nimport { type RefObject, useEffect, useRef } from 'react';\nimport type { ViewTransform } from '../instrument/types';\nimport { DEFAULT_FRAME, type WorldFrame } from './worldSpec';\n\n/** One layer of a canvas stack: its id, whether it is currently shown, and how\n * it paints itself. */\nexport interface CanvasLayerDescriptor {\n id: string;\n visible: boolean;\n render: (ctx: CanvasRenderingContext2D, view: ViewTransform, frame: WorldFrame) => void;\n}\n\ninterface SchedulerOptions {\n layers: CanvasLayerDescriptor[];\n view: ViewTransform;\n /** The instrument's coordinate system, resolved against `size`. */\n frame?: WorldFrame;\n canvasRefs: RefObject<Map<string, HTMLCanvasElement>>;\n size: { width: number; height: number; dpr: number };\n /** The element the stack occupies. Given one, the scheduler also stops while\n * the stack sits outside the viewport. */\n host?: RefObject<Element | null>;\n}\n\nexport function useLayerScheduler({\n layers,\n view,\n frame = DEFAULT_FRAME,\n canvasRefs,\n size,\n host,\n}: SchedulerOptions): void {\n const dirty = useRef<Set<string>>(new Set());\n const lastRenderRef = useRef<Map<string, CanvasLayerDescriptor['render']>>(new Map());\n\n useEffect(() => {\n for (const layer of layers) {\n const prev = lastRenderRef.current.get(layer.id);\n if (prev !== layer.render) dirty.current.add(layer.id);\n lastRenderRef.current.set(layer.id, layer.render);\n }\n for (const id of [...lastRenderRef.current.keys()]) {\n if (!layers.find((l) => l.id === id)) lastRenderRef.current.delete(id);\n }\n }, [layers]);\n\n // biome-ignore lint/correctness/useExhaustiveDependencies: re-mark dirty when view or size changes\n useEffect(() => {\n for (const layer of layers) dirty.current.add(layer.id);\n }, [view, frame, size, layers]);\n\n // Painting only what is dirty is not the same as doing nothing: a hidden tab\n // still commits React updates, and the effect above marks every layer dirty\n // on any view or size change. The gate is what actually stops the work.\n const frameLoop = useVisibleRaf(\n () => {\n if (dirty.current.size === 0) return;\n const map = canvasRefs.current;\n if (!map) {\n dirty.current.clear();\n return;\n }\n for (const layer of layers) {\n if (!dirty.current.has(layer.id)) continue;\n if (!layer.visible) continue;\n const canvas = map.get(layer.id);\n if (!canvas) continue;\n const ctx = canvas.getContext('2d');\n if (!ctx) continue;\n ctx.save();\n ctx.setTransform(size.dpr, 0, 0, size.dpr, 0, 0);\n ctx.clearRect(0, 0, size.width, size.height);\n layer.render(ctx, view, frame);\n ctx.restore();\n }\n dirty.current.clear();\n },\n { target: host },\n );\n\n useEffect(() => {\n if (dirty.current.size > 0) frameLoop.request();\n });\n}\n","import type { Yoke } from '@weasel-js/core';\nimport { type CSSProperties, type ReactNode, useEffect, useMemo, useRef, useState } from 'react';\nimport type { Point, ViewTransform } from '../instrument/types';\nimport { normalize2DView } from '../state/view';\nimport { CameraContext, CameraInput, CameraScope, useCameraView } from './CameraInput';\nimport { CanvasStackContext } from './CanvasStackContext';\nimport { LinkedCursor } from './LinkedCursor';\nimport { type CanvasLayerDescriptor, useLayerScheduler } from './useLayerScheduler';\nimport { resolveFrame, type ViewportSize, type WorldSpec } from './worldSpec';\n\n/** Props for `<CanvasStack>`. */\nexport interface CanvasStackProps {\n layers: CanvasLayerDescriptor[];\n view: ViewTransform;\n onViewChange: (v: ViewTransform) => void;\n /** The instrument's coordinate system. Omitted, world (0,0) sits at the\n * element's top-left with y running down. */\n worldSpec?: WorldSpec;\n minZoom?: number;\n maxZoom?: number;\n width?: number | string;\n height?: number | string;\n className?: string;\n /** Fired whenever the stack is measured, so a consumer can place a view that\n * only makes sense in terms of the viewport. */\n onResize?: (size: ViewportSize) => void;\n onHitTest?: (worldPos: Point) => void;\n children?: ReactNode;\n /** A yoke to join, from `useYoke()`: cameras on one yoke share their tool\n * and gesture in flight. Omitted, this one keeps its own. */\n yoke?: Yoke;\n}\n\n/** Stacks one `<canvas>` per layer and drives them from a shared view, so a\n * layer that changes rarely is not redrawn with one that changes every frame.\n * Handles sizing and device pixel ratio; pan and zoom route through weasel's\n * gesture dispatcher (`<CameraInput>`). */\nexport function CanvasStack({\n layers,\n view: viewProp,\n onViewChange,\n worldSpec,\n minZoom,\n maxZoom,\n width = '100%',\n height = '100%',\n className,\n onResize,\n onHitTest,\n children,\n yoke,\n}: CanvasStackProps) {\n const view = normalize2DView(viewProp);\n const containerRef = useRef<HTMLDivElement | null>(null);\n const canvasMap = useRef<Map<string, HTMLCanvasElement>>(new Map());\n const [size, setSize] = useState({ width: 0, height: 0, dpr: 1 });\n\n const setCanvasRef = (id: string, el: HTMLCanvasElement | null): void => {\n if (el) canvasMap.current.set(id, el);\n else canvasMap.current.delete(id);\n };\n\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n const update = () => {\n const rect = el.getBoundingClientRect();\n const dpr = window.devicePixelRatio ?? 1;\n setSize((prev) => {\n if (prev.width === rect.width && prev.height === rect.height && prev.dpr === dpr) {\n return prev;\n }\n return { width: rect.width, height: rect.height, dpr };\n });\n };\n update();\n if (typeof ResizeObserver === 'undefined') return;\n const ro = new ResizeObserver(update);\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n const onResizeRef = useRef(onResize);\n onResizeRef.current = onResize;\n useEffect(() => {\n if (size.width === 0 && size.height === 0) return;\n onResizeRef.current?.({ width: size.width, height: size.height });\n }, [size.width, size.height]);\n\n const frame = useMemo(() => resolveFrame(worldSpec, size), [worldSpec, size]);\n\n const camera = useCameraView({\n view: viewProp,\n onViewChange,\n frame,\n hostRef: containerRef,\n minZoom,\n maxZoom,\n });\n const cameraCtx = useMemo(\n () => ({ view: camera, frame, element: () => containerRef.current }),\n [camera, frame],\n );\n useLayerScheduler({ layers, view, frame, canvasRefs: canvasMap, size, host: containerRef });\n\n const ctxValue = useMemo(\n () => ({\n view,\n frame,\n surface: { element: containerRef, size, canvases: canvasMap, layers },\n }),\n [view, frame, size, layers],\n );\n\n const containerStyle: CSSProperties = { width, height };\n const canvasPx = {\n width: Math.max(0, Math.round(size.width * size.dpr)),\n height: Math.max(0, Math.round(size.height * size.dpr)),\n };\n const canvasCss: CSSProperties = {\n width: size.width,\n height: size.height,\n };\n\n return (\n <CameraScope yoke={yoke}>\n <CameraContext.Provider value={cameraCtx}>\n <CanvasStackContext.Provider value={ctxValue}>\n <CameraInput hostRef={containerRef} camera={camera} frame={frame} onTap={onHitTest} />\n <div\n ref={containerRef}\n className={className ? `lk-canvas-stack ${className}` : 'lk-canvas-stack'}\n style={containerStyle}\n >\n {layers.map((layer) => (\n <canvas\n key={layer.id}\n ref={(el) => setCanvasRef(layer.id, el)}\n className=\"lk-canvas-stack__canvas\"\n width={canvasPx.width}\n height={canvasPx.height}\n style={{ ...canvasCss, display: layer.visible ? 'block' : 'none' }}\n />\n ))}\n <LinkedCursor />\n <div className=\"lk-canvas-stack__overlay\">{children}</div>\n </div>\n </CanvasStackContext.Provider>\n </CameraContext.Provider>\n </CameraScope>\n );\n}\n","import type { Yoke } from '@weasel-js/core';\nimport { type CSSProperties, type ReactNode, useEffect, useMemo, useRef } from 'react';\nimport type { ViewTransform } from '../instrument/types';\nimport { normalize2DView } from '../state/view';\nimport { useSurfaceOptional } from '../surface/useSurfaceTile';\nimport { CameraContext, CameraInput, CameraScope, useCameraView } from './CameraInput';\nimport { LinkedCursor } from './LinkedCursor';\nimport { DEFAULT_FRAME, type ViewportSize } from './worldSpec';\n\n/** Props for `<Stage>`. */\nexport interface StageProps {\n /** The content's own size in CSS pixels, at zoom 1. */\n size: ViewportSize;\n view: ViewTransform;\n onViewChange: (v: ViewTransform) => void;\n minZoom?: number;\n maxZoom?: number;\n /** Fired whenever the stage's viewport is measured at a non-zero size. */\n onResize?: (viewport: ViewportSize) => void;\n /** Handed the viewport element, for a consumer tracking the pointer over it. */\n hostRef?: { current: HTMLDivElement | null };\n /** Drawn over the content in viewport pixels, outside the camera. */\n overlay?: ReactNode;\n children?: ReactNode;\n /** A yoke to join, from `useYoke()`: cameras on one yoke share their tool\n * and gesture in flight. Omitted, this one keeps its own. */\n yoke?: Yoke;\n}\n\n/**\n * The camera a stage opens at: the content centered in its viewport, shrunk to\n * fit if it has to be and never enlarged past its own size.\n */\nexport function fitStage(size: ViewportSize, viewport: ViewportSize): ViewTransform {\n if (!(size.width > 0 && size.height > 0 && viewport.width > 0 && viewport.height > 0)) {\n return { zoom: 1, pan: { x: 0, y: 0 } };\n }\n const zoom = Math.min(1, viewport.width / size.width, viewport.height / size.height);\n return {\n zoom,\n pan: {\n x: (viewport.width - size.width * zoom) / 2,\n y: (viewport.height - size.height * zoom) / 2,\n },\n };\n}\n\n/**\n * DOM content of a fixed size, panned and zoomed by a camera — what\n * `<CanvasStack>` is for layers drawn to a canvas. Pan and zoom route through\n * weasel's gesture dispatcher (`<CameraInput>`). The content is laid out at\n * its own size and transformed, so everything inside keeps its layout and a\n * measurement of any element in it reports where it is actually drawn.\n */\nexport function Stage({\n size,\n view: viewProp,\n onViewChange,\n minZoom,\n maxZoom,\n onResize,\n hostRef,\n overlay,\n children,\n yoke,\n}: StageProps) {\n const view = normalize2DView(viewProp);\n const host = useRef<HTMLDivElement | null>(null);\n const surface = useSurfaceOptional();\n const camera = useCameraView({\n view: viewProp,\n onViewChange,\n frame: DEFAULT_FRAME,\n hostRef: host,\n minZoom,\n maxZoom,\n });\n const cameraCtx = useMemo(\n () => ({\n view: camera,\n frame: DEFAULT_FRAME,\n element: () => host.current,\n content: { x: 0, y: 0, width: size.width, height: size.height },\n }),\n [camera, size.width, size.height],\n );\n\n const onResizeRef = useRef(onResize);\n onResizeRef.current = onResize;\n useEffect(() => {\n const el = host.current;\n if (!el) return;\n const measure = () => {\n const rect = el.getBoundingClientRect();\n if (rect.width > 0 && rect.height > 0) {\n onResizeRef.current?.({ width: rect.width, height: rect.height });\n }\n };\n measure();\n if (typeof ResizeObserver === 'undefined') return;\n const ro = new ResizeObserver(measure);\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n // A transform moves every tile inside the content without resizing anything,\n // and a ResizeObserver reports only resizes.\n // biome-ignore lint/correctness/useExhaustiveDependencies: the camera is the trigger, not an input — the effect re-measures whenever it moves.\n useEffect(() => {\n surface?.invalidateRects();\n }, [surface, view.zoom, view.pan.x, view.pan.y]);\n\n // The camera changes every frame of a pan, and a transform has nowhere to\n // live but the element's own style: set as custom properties the stylesheet\n // reads.\n const cameraVars = {\n ['--lk-stage-x' as string]: `${view.pan.x}px`,\n ['--lk-stage-y' as string]: `${view.pan.y}px`,\n ['--lk-stage-zoom' as string]: String(view.zoom),\n ['--lk-stage-w' as string]: `${size.width}px`,\n ['--lk-stage-h' as string]: `${size.height}px`,\n } as CSSProperties;\n\n return (\n <CameraScope yoke={yoke}>\n <CameraContext.Provider value={cameraCtx}>\n <CameraInput hostRef={host} camera={camera} frame={DEFAULT_FRAME} />\n <div\n ref={(el) => {\n host.current = el;\n if (hostRef) hostRef.current = el;\n }}\n className=\"lk-stage\"\n >\n <div className=\"lk-stage__content\" style={cameraVars}>\n {children}\n </div>\n <LinkedCursor />\n {overlay}\n </div>\n </CameraContext.Provider>\n </CameraScope>\n );\n}\n"]}
|
package/dist/config/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
|
|
1
|
+
import { a5 as Auto } from '../_dts/types-CSm9jgol.js';
|
|
2
|
+
import { Instrument } from '../index.js';
|
|
3
|
+
export { aC as auto, aI as isAuto } from '../_dts/types-CSm9jgol.js';
|
|
4
|
+
import { R as ResolvedConfig, l as ConfigNode, A as Annotations, N as NodeOptions, S as SectionOption, d as ControlRenderer, I as InDialogOptions, n as ConfigOption, p as ConfigShape, h as ConfigBranch, B as BranchAnnotations, e as BranchOptions, b as ConfigSchema, q as InferConfig, i as ConfigEntry, c as ConfigRule, L as LeafPatch, o as ConfigRuleContext } from '../_dts/types-CRPSGFAp.js';
|
|
5
|
+
import { ConfigField } from '../controls/index.js';
|
|
6
|
+
export { m as ConfigOf, C as ConfigPath, D as DialogSpec, E as EntryValue, r as NodeValue, t as SectionSpec, V as ValueAtPath } from '../_dts/types-CRPSGFAp.js';
|
|
7
|
+
import { D as Display } from '../_dts/PrefsRow.d-TOZ7BgD9.js';
|
|
8
|
+
import { ToolPrefNumberUnit, ToolPrefLeaf, ToolPrefGroup } from '@weasel-js/core';
|
|
7
9
|
import 'react';
|
|
8
|
-
import '../_dts/PrefsRow.d-DFpPIeIC.js';
|
|
9
10
|
import '@weasel-js/theme';
|
|
10
11
|
import '../_dts/types-DJ79Tg5J.js';
|
|
11
12
|
|
|
@@ -80,9 +81,9 @@ declare class NumberNode extends BaseNode<number> {
|
|
|
80
81
|
/** A display suffix for the value — `'px'`, `'ms'`, `'°'`. Presentation only:
|
|
81
82
|
* it is never parsed, and the stored value stays a plain number. */
|
|
82
83
|
suffix(suffix: string): this;
|
|
83
|
-
/** Show the value
|
|
84
|
-
* only: the stored value stays a plain number
|
|
85
|
-
|
|
84
|
+
/** Show, speak and read the value through a display — `compact()` reads
|
|
85
|
+
* `2.00M`. Presentation only: the stored value stays a plain number. */
|
|
86
|
+
display(display: Display): this;
|
|
86
87
|
/**
|
|
87
88
|
* Store the value in one unit and edit it in another — radians stored,
|
|
88
89
|
* degrees typed. `min`, `max` and `step` are declared in the stored unit
|
|
@@ -157,6 +158,9 @@ declare class GroupNode<S extends ConfigShape> implements ConfigBranch<S> {
|
|
|
157
158
|
/** Show this group only while the predicate holds. Presentational — every
|
|
158
159
|
* value beneath it stays in config and the instrument still reads it. */
|
|
159
160
|
showIf(predicate: (config: Record<string, unknown>) => boolean): GroupNode<S>;
|
|
161
|
+
/** Put a button on the group's heading that returns every value beneath it
|
|
162
|
+
* to its default, leaving the rest of the config alone. */
|
|
163
|
+
resettable(): GroupNode<S>;
|
|
160
164
|
}
|
|
161
165
|
/**
|
|
162
166
|
* Builds an instrument's config: the values, their types, and how each is
|
|
@@ -202,37 +206,12 @@ declare const f: {
|
|
|
202
206
|
*
|
|
203
207
|
* Rules do not run here: a hand-written `ConfigField` already states its label
|
|
204
208
|
* and control, which is everything the rule chain would have inferred.
|
|
205
|
-
*/
|
|
206
|
-
declare function fromConfigFields(fields: readonly ConfigField[]): ResolvedConfig;
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* A resolved schema rearranged so its sections are groups.
|
|
210
|
-
*
|
|
211
|
-
* `PrefsForm`'s rail navigates the schema tree — top-level groups are its
|
|
212
|
-
* items, their group children indent under them. A resolved schema keeps its
|
|
213
|
-
* sections beside the tree instead, so a flat schema's rail comes out as one
|
|
214
|
-
* unnamed item however many headings the panel draws. This puts the sections
|
|
215
|
-
* where the rail looks for them.
|
|
216
|
-
*/
|
|
217
|
-
interface SectionTree {
|
|
218
|
-
/** The rail's schema. Top-level children are the schema's root sections,
|
|
219
|
-
* followed by any root node no section claimed. */
|
|
220
|
-
group: ToolPrefGroup;
|
|
221
|
-
/** `config` renested to mirror `group` — the value tree `PrefsForm` takes. */
|
|
222
|
-
values: Record<string, unknown>;
|
|
223
|
-
/** The config path a path within `group` stands for. */
|
|
224
|
-
pathAt: (railPath: string) => string;
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Turn a resolved schema's root sections into the top level of a `PrefGroup`,
|
|
228
|
-
* for `PrefsForm`'s rail layout.
|
|
229
209
|
*
|
|
230
|
-
* A
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
* bucket rows inside a pane, which is the panel's job and not the rail's.
|
|
210
|
+
* A dotted `key` is a config path, as it is to every read and write, so its
|
|
211
|
+
* leaf is filed under headless groups at that path rather than as one child
|
|
212
|
+
* whose name contains dots — which no path lookup would find.
|
|
234
213
|
*/
|
|
235
|
-
declare function
|
|
214
|
+
declare function fromConfigFields(fields: readonly ConfigField[]): ResolvedConfig;
|
|
236
215
|
|
|
237
216
|
/** The value at a dotted path. `undefined` when a segment is missing or the
|
|
238
217
|
* walk hits something that is not a record. */
|
|
@@ -285,6 +264,35 @@ declare const builtinRules: readonly ConfigRule[];
|
|
|
285
264
|
*/
|
|
286
265
|
declare function applyRules(seed: LeafPatch, ctx: Omit<ConfigRuleContext, 'leaf'>, rules: readonly ConfigRule[]): LeafPatch;
|
|
287
266
|
|
|
267
|
+
/**
|
|
268
|
+
* A resolved schema rearranged so its sections are groups.
|
|
269
|
+
*
|
|
270
|
+
* `PrefsForm`'s rail navigates the schema tree — top-level groups are its
|
|
271
|
+
* items, their group children indent under them. A resolved schema keeps its
|
|
272
|
+
* sections beside the tree instead, so a flat schema's rail comes out as one
|
|
273
|
+
* unnamed item however many headings the panel draws. This puts the sections
|
|
274
|
+
* where the rail looks for them.
|
|
275
|
+
*/
|
|
276
|
+
interface SectionTree {
|
|
277
|
+
/** The rail's schema. Top-level children are the schema's root sections,
|
|
278
|
+
* followed by any root node no section claimed. */
|
|
279
|
+
group: ToolPrefGroup;
|
|
280
|
+
/** `config` renested to mirror `group` — the value tree `PrefsForm` takes. */
|
|
281
|
+
values: Record<string, unknown>;
|
|
282
|
+
/** The config path a path within `group` stands for. */
|
|
283
|
+
pathAt: (railPath: string) => string;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Turn a resolved schema's root sections into the top level of a `PrefGroup`,
|
|
287
|
+
* for `PrefsForm`'s rail layout.
|
|
288
|
+
*
|
|
289
|
+
* A section naming a group brings that group in whole, so it lands as an
|
|
290
|
+
* indented rail item; a section naming a leaf drops it loose into the
|
|
291
|
+
* section's own pane. Sections nested under a group are left alone — they
|
|
292
|
+
* bucket rows inside a pane, which is the panel's job and not the rail's.
|
|
293
|
+
*/
|
|
294
|
+
declare function sectionTree(resolved: ResolvedConfig, config: Record<string, unknown>, showHidden?: boolean): SectionTree;
|
|
295
|
+
|
|
288
296
|
/**
|
|
289
297
|
* An instrument's controls, resolved against the surrounding lab's rules.
|
|
290
298
|
*
|
|
@@ -314,5 +322,5 @@ declare function useResolvedConfig<TC>(schema: ResolvedConfig | undefined, confi
|
|
|
314
322
|
*/
|
|
315
323
|
declare function isLeafVisible(resolved: ResolvedConfig, path: string, config: Record<string, unknown>, showHidden?: boolean): boolean;
|
|
316
324
|
|
|
317
|
-
export { Annotations, Auto, BaseNode, BooleanNode, BranchAnnotations, BranchOptions, ColorNode, ConfigBranch, ConfigEntry, ConfigNode, ConfigOption, ConfigRule, ConfigRuleContext, ConfigSchema, ConfigShape, ControlRenderer, CustomNode, EnumNode, GroupNode, InferConfig, LeafPatch, ListNode, NodeOptions, NumberNode, ResolvedConfig, StringNode, ValueNode, applyRules, autoPathsOf, builtinRules, f, fillConfigDefaults, fromConfigFields, hasConfigPath, isConfigBranch, isLeafVisible, resolveAutoConfig, resolveConfigSchema, schemaNodeAtPath, sectionTree, titleCase, useConfigSchema, useResolvedConfig, valueAtPath, withValueAtPath };
|
|
325
|
+
export { Annotations, Auto, BaseNode, BooleanNode, BranchAnnotations, BranchOptions, ColorNode, ConfigBranch, ConfigEntry, ConfigNode, ConfigOption, ConfigRule, ConfigRuleContext, ConfigSchema, ConfigShape, ControlRenderer, CustomNode, EnumNode, GroupNode, InDialogOptions, InferConfig, LeafPatch, ListNode, NodeOptions, NumberNode, ResolvedConfig, SectionOption, StringNode, ValueNode, applyRules, autoPathsOf, builtinRules, f, fillConfigDefaults, fromConfigFields, hasConfigPath, isConfigBranch, isLeafVisible, resolveAutoConfig, resolveConfigSchema, schemaNodeAtPath, sectionTree, titleCase, useConfigSchema, useResolvedConfig, valueAtPath, withValueAtPath };
|
|
318
326
|
export type { SectionTree };
|
package/dist/config/index.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
export { sectionTree, useConfigSchema } from '../chunk-
|
|
1
|
+
export { sectionTree, useConfigSchema } from '../chunk-GOZLNM4L.js';
|
|
2
2
|
import '../chunk-Z76KEZAX.js';
|
|
3
|
-
export { BaseNode, BooleanNode, ColorNode, CustomNode, EnumNode, GroupNode, ListNode, NumberNode, StringNode, ValueNode, applyRules, builtinRules, f, isConfigBranch, resolveConfigSchema, titleCase, useResolvedConfig } from '../chunk-
|
|
4
|
-
export { fromConfigFields, isLeafVisible } from '../chunk-
|
|
5
|
-
export { auto, autoPathsOf, fillConfigDefaults, hasConfigPath, isAuto, resolveAutoConfig, schemaNodeAtPath, valueAtPath, withValueAtPath } from '../chunk-
|
|
6
|
-
import '../chunk-WUJXJC5O.js';
|
|
3
|
+
export { BaseNode, BooleanNode, ColorNode, CustomNode, EnumNode, GroupNode, ListNode, NumberNode, StringNode, ValueNode, applyRules, builtinRules, f, isConfigBranch, resolveConfigSchema, titleCase, useResolvedConfig } from '../chunk-FZ7YFQN7.js';
|
|
4
|
+
export { fromConfigFields, isLeafVisible } from '../chunk-KMJ7RWD3.js';
|
|
5
|
+
export { auto, autoPathsOf, fillConfigDefaults, hasConfigPath, isAuto, resolveAutoConfig, schemaNodeAtPath, valueAtPath, withValueAtPath } from '../chunk-Y23G2VZL.js';
|
|
7
6
|
//# sourceMappingURL=index.js.map
|
|
8
7
|
//# sourceMappingURL=index.js.map
|
package/dist/controls/index.d.ts
CHANGED
|
@@ -1,9 +1,93 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import '
|
|
5
|
-
import '
|
|
6
|
-
import '../_dts/
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { StanceProps } from '../passthrough/weasel-ui.js';
|
|
4
|
+
import { PropertyRowLayout } from '../index.js';
|
|
5
|
+
import { PropertyDensity, PropertyAlign } from '../passthrough/weasel-ui.js';
|
|
6
|
+
import { a as ConfigField, I as InDialogOptions } from '../_dts/types-CRPSGFAp.js';
|
|
7
|
+
import { ResolvedConfig, ControlRenderer } from '../config/index.js';
|
|
8
|
+
export { f as CheckboxField, g as ColorField, k as ConfigFieldType, s as NumberField, u as SelectField, v as SelectOption, w as SliderField, T as TextField } from '../_dts/types-CRPSGFAp.js';
|
|
7
9
|
import '@weasel-js/theme';
|
|
8
10
|
import '@weasel-js/core';
|
|
9
|
-
|
|
11
|
+
|
|
12
|
+
/** How a panel packs its rows into the two-column property grid.
|
|
13
|
+
* - `'auto'`: narrow controls (numbers, checkboxes, dropdowns, colors) sit
|
|
14
|
+
* two per row; the ones that need the width — text, sliders, segmented
|
|
15
|
+
* toggles — span it.
|
|
16
|
+
* - `'pairs'`: every row pairs. A control that needs the full width says so
|
|
17
|
+
* itself, with `<PropertyRow span>`.
|
|
18
|
+
* - `'one-up'`: one control per row, colors excepted.
|
|
19
|
+
*/
|
|
20
|
+
type ControlPack = 'auto' | 'pairs' | 'one-up';
|
|
21
|
+
interface ControlPanelProps<TC extends Record<string, unknown>> extends StanceProps {
|
|
22
|
+
/** The instrument's resolved config schema. */
|
|
23
|
+
schema?: ResolvedConfig;
|
|
24
|
+
/** @deprecated Pass `schema`. A field list is adapted into one internally. */
|
|
25
|
+
fields?: ConfigField[];
|
|
26
|
+
config: TC;
|
|
27
|
+
/** Writes one value. The path is dotted for a leaf inside an `f.group`, and
|
|
28
|
+
* the bare key for one at the root. */
|
|
29
|
+
setConfig: (path: string, value: unknown) => void;
|
|
30
|
+
/**
|
|
31
|
+
* Control overrides and app-defined kinds, PrefsForm-style. Keys are config
|
|
32
|
+
* paths (checked first) or leaf kinds. A renderer returning `null` collapses
|
|
33
|
+
* the row; entries override the built-in rows on collision.
|
|
34
|
+
*/
|
|
35
|
+
renderers?: Record<string, ControlRenderer>;
|
|
36
|
+
/** How rows pack into the two-column grid. Defaults to `'pairs'`. */
|
|
37
|
+
pack?: ControlPack;
|
|
38
|
+
/**
|
|
39
|
+
* Where a row's label sits relative to its control. Unset takes each row's
|
|
40
|
+
* own orientation — `block` (label above, which is what leaves a paired row
|
|
41
|
+
* room for its value) for most, `inline` for colors and checkboxes.
|
|
42
|
+
*/
|
|
43
|
+
layout?: PropertyRowLayout;
|
|
44
|
+
/** Room the rows get. Passed straight to the property list. */
|
|
45
|
+
density?: PropertyDensity;
|
|
46
|
+
/** Cross-axis alignment of an inline row's label and control. */
|
|
47
|
+
align?: PropertyAlign;
|
|
48
|
+
/**
|
|
49
|
+
* Fold each section away behind a twisty, starting `'open'` or `'closed'`.
|
|
50
|
+
* Unset draws the heading alone, as the panel always has — unless a section
|
|
51
|
+
* in the schema declares how it opens, which makes that section foldable on
|
|
52
|
+
* its own and outranks this for that one section.
|
|
53
|
+
*/
|
|
54
|
+
collapse?: 'open' | 'closed';
|
|
55
|
+
/**
|
|
56
|
+
* Which sections are folded, keyed as `onCollapse` reports them. Given, the
|
|
57
|
+
* panel keeps no state of its own: every toggle arrives at `onCollapse`
|
|
58
|
+
* instead, which is where a lab that remembers a trial's sections writes
|
|
59
|
+
* them.
|
|
60
|
+
*/
|
|
61
|
+
collapsed?: Readonly<Record<string, boolean>>;
|
|
62
|
+
/** A fold moved. The key is a section's label — prefixed by its group's
|
|
63
|
+
* dotted path when the section sits inside one — or a group's own path. */
|
|
64
|
+
onCollapse?: (key: string, collapsed: boolean) => void;
|
|
65
|
+
/** Dotted paths currently unpinned. A row in this set hides its control and
|
|
66
|
+
* reads out `auto`, and clicking its label writes the sentinel back through
|
|
67
|
+
* `setConfig`. Omitted, the panel keeps the set itself: the labels still
|
|
68
|
+
* toggle and the sentinel never reaches `setConfig`, which would otherwise
|
|
69
|
+
* store it as the row's value. */
|
|
70
|
+
auto?: ReadonlySet<string>;
|
|
71
|
+
/** Draw leaves marked `hidden`. */
|
|
72
|
+
showHidden?: boolean;
|
|
73
|
+
/** Heads the panel. With `title`, `stance` or `tone` given, the rows sit in a
|
|
74
|
+
* `<PropertyPanel>` carrying them; with none, they are the bare list. */
|
|
75
|
+
title?: ReactNode;
|
|
76
|
+
className?: string;
|
|
77
|
+
}
|
|
78
|
+
/** Render an instrument's config schema as a stack of controls, each writing
|
|
79
|
+
* back through `setConfig`. Built on the property rows, so a lab's controls
|
|
80
|
+
* are the same aligned, themed rows the rest of the kit uses. */
|
|
81
|
+
declare function ControlPanel<TC extends Record<string, unknown>>({ schema, fields, config, setConfig, renderers, pack, layout, density, align, collapse, collapsed, onCollapse, auto: given, showHidden, title, stance, tone, className, }: ControlPanelProps<TC>): react.JSX.Element;
|
|
82
|
+
|
|
83
|
+
/** The one-line summary a dialog row shows when it is given none. */
|
|
84
|
+
declare function summarizeValue(value: unknown): string;
|
|
85
|
+
/**
|
|
86
|
+
* Moves a control into a modal: the row becomes a button showing a summary of
|
|
87
|
+
* the value, and the button opens a dialog whose body is `body`, handed the
|
|
88
|
+
* same context a row renderer gets. For a leaf whose editor will never fit a
|
|
89
|
+
* sidebar row.
|
|
90
|
+
*/
|
|
91
|
+
declare function inDialog(body: ControlRenderer, opts?: InDialogOptions): ControlRenderer;
|
|
92
|
+
|
|
93
|
+
export { ConfigField, ControlPanel, InDialogOptions, inDialog, summarizeValue };
|
package/dist/controls/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export { ControlPanel } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
|
|
4
|
-
import '../chunk-
|
|
1
|
+
export { ControlPanel, inDialog, summarizeValue } from '../chunk-T5IBSPAM.js';
|
|
2
|
+
import '../chunk-KMJ7RWD3.js';
|
|
3
|
+
import '../chunk-Y23G2VZL.js';
|
|
4
|
+
import '../chunk-MIM5R4ZT.js';
|
|
5
|
+
import '../chunk-275JRRVD.js';
|
|
5
6
|
//# sourceMappingURL=index.js.map
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
package/dist/dragdrop/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { n as PaletteItem, o as DragFeedback, q as DragDropCapability } from '../_dts/types-CSm9jgol.js';
|
|
2
|
+
import { WorldSpec } from '../canvas/index.js';
|
|
3
|
+
import { Point, ViewTransform } from '../index.js';
|
|
4
|
+
import * as react from 'react';
|
|
3
5
|
import { RefObject, PointerEvent, ReactPortal } from 'react';
|
|
4
|
-
import '../_dts/PrefsRow.d-DFpPIeIC.js';
|
|
5
|
-
import '@weasel-js/theme';
|
|
6
6
|
import '@weasel-js/core';
|
|
7
|
-
import '../_dts/
|
|
7
|
+
import '../_dts/PrefsRow.d-TOZ7BgD9.js';
|
|
8
|
+
import '@weasel-js/theme';
|
|
9
|
+
import '../_dts/types-CRPSGFAp.js';
|
|
8
10
|
import '../_dts/types-DJ79Tg5J.js';
|
|
9
11
|
|
|
10
12
|
interface DragState {
|
|
@@ -32,7 +34,7 @@ declare function useDragDrop<TS, TC>({ capability, canvasContainerRef, view, sta
|
|
|
32
34
|
interface DragOverlayProps {
|
|
33
35
|
drag: DragState | null;
|
|
34
36
|
}
|
|
35
|
-
declare function DragOverlay({ drag }: DragOverlayProps):
|
|
37
|
+
declare function DragOverlay({ drag }: DragOverlayProps): react.JSX.Element | null;
|
|
36
38
|
|
|
37
39
|
interface DragGhostProps {
|
|
38
40
|
item: PaletteItem;
|
|
@@ -45,7 +47,7 @@ interface PaletteProps {
|
|
|
45
47
|
onDragStart: (item: PaletteItem, e: PointerEvent) => void;
|
|
46
48
|
className?: string;
|
|
47
49
|
}
|
|
48
|
-
declare function Palette({ items, onDragStart, className }: PaletteProps):
|
|
50
|
+
declare function Palette({ items, onDragStart, className }: PaletteProps): react.JSX.Element;
|
|
49
51
|
|
|
50
52
|
export { DragDropCapability, DragFeedback, DragGhost, DragOverlay, Palette, PaletteItem, useDragDrop };
|
|
51
53
|
export type { DragGhostProps, DragOverlayProps, DragState, PaletteProps, UseDragDropArgs, UseDragDropResult };
|