@weasel-js/labkit 1.4.0-pre.1 → 1.4.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/dist/_dts/{CanvasStackContext-LnCfqNBA.d.ts → CanvasStackContext-BIRUVVGH.d.ts} +1 -1
- package/dist/_dts/PrefsForm.d-CgxUequc.d.ts +20 -0
- package/dist/_dts/{frac-C-2c72Ij.d.ts → frac-X7mWgd7y.d.ts} +10 -4
- package/dist/_dts/{index-BDVzvRzQ.d.ts → index-FEa1MudK.d.ts} +8 -2
- package/dist/_dts/{types-DYMaEvM5.d.ts → types-ChVJJHvk.d.ts} +3 -0
- package/dist/_dts/{types-D6s4b7if.d.ts → types-lg4TSCb2.d.ts} +3 -1
- package/dist/_dts/{useTrialState-gmMvZqPc.d.ts → useTrialState-Cdm13fvl.d.ts} +2 -1
- package/dist/_dts/weasel-canvas-FJTFi3ZZ.d.ts +5041 -0
- package/dist/canvas/index.d.ts +16 -16
- package/dist/canvas/index.js +2 -2
- package/dist/chrome/index.d.ts +6 -6
- package/dist/chrome/index.js +5 -5
- package/dist/chunk-2YILQ7Y5.js +33 -0
- package/dist/chunk-2YILQ7Y5.js.map +1 -0
- package/dist/{chunk-TO2FUOKF.js → chunk-53AZ2O2N.js} +16 -13
- package/dist/chunk-53AZ2O2N.js.map +1 -0
- package/dist/{chunk-QB5SM4BM.js → chunk-7TRFMIWX.js} +55 -41
- package/dist/chunk-7TRFMIWX.js.map +1 -0
- package/dist/{chunk-6OEYTYML.js → chunk-BMQWLKOL.js} +15 -15
- package/dist/chunk-BMQWLKOL.js.map +1 -0
- package/dist/{chunk-M75ZU6ZZ.js → chunk-D7QIPGEB.js} +3 -3
- package/dist/{chunk-M75ZU6ZZ.js.map → chunk-D7QIPGEB.js.map} +1 -1
- package/dist/{chunk-L5QJOOLV.js → chunk-DG2IFMLA.js} +1309 -273
- package/dist/chunk-DG2IFMLA.js.map +1 -0
- package/dist/{chunk-LN6JDUGB.js → chunk-HXXTULDN.js} +2 -2
- package/dist/{chunk-LN6JDUGB.js.map → chunk-HXXTULDN.js.map} +1 -1
- package/dist/{chunk-RBGKL7NF.js → chunk-J6SBFZYT.js} +1807 -1814
- package/dist/chunk-J6SBFZYT.js.map +1 -0
- package/dist/{chunk-XJ6N32QP.js → chunk-LJSIUFYD.js} +14 -30
- package/dist/chunk-LJSIUFYD.js.map +1 -0
- package/dist/{chunk-AE5CNVRU.js → chunk-MIT3ISW4.js} +37 -31
- package/dist/chunk-MIT3ISW4.js.map +1 -0
- package/dist/{chunk-HHGVISVZ.js → chunk-MSR7EVS6.js} +7 -5
- package/dist/chunk-MSR7EVS6.js.map +1 -0
- package/dist/{chunk-ESIQNQ6K.js → chunk-OFCBEZMU.js} +12 -6
- package/dist/chunk-OFCBEZMU.js.map +1 -0
- package/dist/{chunk-HMFODCOX.js → chunk-PP7ZWAMV.js} +83 -75
- package/dist/chunk-PP7ZWAMV.js.map +1 -0
- package/dist/{chunk-E2UQVZ44.js → chunk-RLOXQZW3.js} +3 -3
- package/dist/{chunk-E2UQVZ44.js.map → chunk-RLOXQZW3.js.map} +1 -1
- package/dist/controls/index.d.ts +4 -3
- package/dist/controls/index.js +3 -3
- package/dist/dragdrop/index.d.ts +5 -5
- package/dist/dragdrop/index.js +2 -2
- package/dist/index.d.ts +57 -77
- package/dist/index.js +308 -161
- package/dist/index.js.map +1 -1
- package/dist/job/index.js +1 -1
- package/dist/layers/index.d.ts +6 -6
- package/dist/layers/index.js +3 -3
- package/dist/loupe/index.d.ts +7 -13
- package/dist/loupe/index.js +2 -2
- package/dist/passthrough/weasel-canvas.d.ts +3 -343
- package/dist/passthrough/weasel-canvas.js +1 -1
- package/dist/passthrough/weasel-ui.d.ts +141 -2866
- package/dist/passthrough/weasel-ui.js +2 -2
- package/dist/primitives/index.js +4 -4
- package/dist/state/index.d.ts +3 -3
- package/dist/state/index.js +4 -2
- package/dist/state/index.js.map +1 -1
- package/dist/styles.css +74 -5
- package/dist/surface/index.d.ts +17 -2
- package/dist/surface/index.js +3 -2
- package/dist/ui/layers/index.js +2 -2
- package/dist/undo/index.d.ts +6 -5
- package/package.json +8 -8
- package/src/annotations/AnnotationOverlay.tsx +10 -6
- package/src/annotations/Annotations.less +6 -0
- package/src/annotations/Annotations.overlay.test.tsx +113 -0
- package/src/annotations/MarkList.tsx +3 -2
- package/src/canvas/CanvasStack.tsx +8 -13
- package/src/canvas/useOrbit.test.ts +93 -1
- package/src/canvas/useOrbit.ts +41 -34
- package/src/canvas/usePanZoom.test.ts +102 -1
- package/src/canvas/usePanZoom.ts +54 -36
- package/src/config/builder.test.ts +5 -0
- package/src/config/builder.ts +6 -0
- package/src/config/types.ts +1 -0
- package/src/controls/ControlPanel.test.tsx +23 -0
- package/src/controls/ControlPanel.tsx +3 -0
- package/src/job/useJob.ts +1 -1
- package/src/lab/Lab.surface.test.tsx +8 -3
- package/src/lab/LabHeader.test.tsx +12 -0
- package/src/lab/LabHeader.tsx +16 -6
- package/src/lab/Workspace.tsx +1 -1
- package/src/layers/LayerList.test.tsx +72 -1
- package/src/layers/LayerList.tsx +40 -32
- package/src/passthrough/weasel-ui.test.ts +9 -0
- package/src/passthrough/weasel-ui.ts +4 -0
- package/src/primitives/FloatingPanel.test.tsx +82 -0
- package/src/primitives/FloatingPanel.tsx +59 -41
- package/src/primitives/ZoomControl.tsx +2 -0
- package/src/state/store.ts +10 -0
- package/src/state/types.ts +3 -0
- package/src/surface/AGENTS.md +11 -1
- package/src/surface/index.ts +7 -1
- package/src/surface/useSurfaceTile.ts +20 -2
- package/src/surface/useTiledSurface.ts +4 -1
- package/src/theme/Interstellar.stories.tsx +4 -3
- package/src/theme/base.less +39 -1
- package/src/trial/Trial.less +27 -5
- package/src/trial/TrialBody.test.tsx +67 -0
- package/src/trial/TrialBody.tsx +155 -0
- package/src/trial/TrialChrome.tsx +18 -10
- package/src/trial/index.ts +2 -0
- package/dist/_dts/DrawCommand-B3bskUsC.d.ts +0 -564
- package/dist/_dts/PrefsForm-BkUJZx0A.d.ts +0 -204
- package/dist/_dts/fitViewToBounds-dZ2UDB6e.d.ts +0 -21
- package/dist/_dts/shapeKinds-Cx_rxwsa.d.ts +0 -87
- package/dist/_dts/types-C-gh9Ap-.d.ts +0 -695
- package/dist/chunk-6OEYTYML.js.map +0 -1
- package/dist/chunk-AE5CNVRU.js.map +0 -1
- package/dist/chunk-ESIQNQ6K.js.map +0 -1
- package/dist/chunk-HHGVISVZ.js.map +0 -1
- package/dist/chunk-HMFODCOX.js.map +0 -1
- package/dist/chunk-L5QJOOLV.js.map +0 -1
- package/dist/chunk-QB5SM4BM.js.map +0 -1
- package/dist/chunk-RBGKL7NF.js.map +0 -1
- package/dist/chunk-TO2FUOKF.js.map +0 -1
- package/dist/chunk-XJ6N32QP.js.map +0 -1
package/dist/canvas/index.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { ReactNode, WheelEvent, PointerEvent } from 'react';
|
|
3
|
-
import { V as ViewTransform, c as WorldSpec, a2 as ViewportSize, a as Point, W as WorldFrame } from '../_dts/frac-
|
|
4
|
-
export { x as DEFAULT_FRAME, a4 as applyCamera, aa as resolveFrame } from '../_dts/frac-
|
|
5
|
-
import { C as CanvasLayerDescriptor } from '../_dts/CanvasStackContext-
|
|
6
|
-
export { a as CanvasStackContext, b as CanvasStackContextValue, c as CanvasStackSurface } from '../_dts/CanvasStackContext-
|
|
7
|
-
import '../_dts/types-
|
|
8
|
-
import '../_dts/
|
|
9
|
-
import '../_dts/
|
|
2
|
+
import { ReactNode, WheelEvent, PointerEvent as PointerEvent$1 } from 'react';
|
|
3
|
+
import { V as ViewTransform, c as WorldSpec, a2 as ViewportSize, a as Point, W as WorldFrame } from '../_dts/frac-X7mWgd7y.js';
|
|
4
|
+
export { x as DEFAULT_FRAME, a4 as applyCamera, aa as resolveFrame } from '../_dts/frac-X7mWgd7y.js';
|
|
5
|
+
import { C as CanvasLayerDescriptor } from '../_dts/CanvasStackContext-BIRUVVGH.js';
|
|
6
|
+
export { a as CanvasStackContext, b as CanvasStackContextValue, c as CanvasStackSurface } from '../_dts/CanvasStackContext-BIRUVVGH.js';
|
|
7
|
+
import '../_dts/types-lg4TSCb2.js';
|
|
8
|
+
import '../_dts/weasel-canvas-FJTFi3ZZ.js';
|
|
9
|
+
import '../_dts/PrefsForm.d-CgxUequc.js';
|
|
10
|
+
import '../_dts/types-ChVJJHvk.js';
|
|
10
11
|
import '../_dts/types-DJ79Tg5J.js';
|
|
11
|
-
import '../_dts/types-C-gh9Ap-.js';
|
|
12
12
|
|
|
13
13
|
/** Props for `<CanvasStack>`. */
|
|
14
14
|
interface CanvasStackProps {
|
|
@@ -99,9 +99,7 @@ interface UseOrbitOptions {
|
|
|
99
99
|
}
|
|
100
100
|
interface OrbitHandlers {
|
|
101
101
|
onWheel: (e: WheelEvent<HTMLElement>) => void;
|
|
102
|
-
onPointerDown: (e: PointerEvent<HTMLElement>) => void;
|
|
103
|
-
onPointerMove: (e: PointerEvent<HTMLElement>) => void;
|
|
104
|
-
onPointerUp: (e: PointerEvent<HTMLElement>) => void;
|
|
102
|
+
onPointerDown: (e: PointerEvent$1<HTMLElement>) => void;
|
|
105
103
|
onDoubleClick: () => void;
|
|
106
104
|
isDragging: () => boolean;
|
|
107
105
|
}
|
|
@@ -120,15 +118,17 @@ interface UsePanZoomOptions {
|
|
|
120
118
|
* wheel anchors in this frame; omitting it anchors at the element's
|
|
121
119
|
* top-left, which is what labkit did before a frame could be declared. */
|
|
122
120
|
frame?: WorldFrame;
|
|
121
|
+
/** A primary-button press released without ever crossing the drag
|
|
122
|
+
* threshold. The pointer session owns the release, so the gesture's end is
|
|
123
|
+
* reported here rather than left for a consumer's own `onPointerUp`. */
|
|
124
|
+
onTap?: (e: PointerEvent) => void;
|
|
123
125
|
}
|
|
124
126
|
interface PanZoomHandlers {
|
|
125
127
|
onWheel: (e: WheelEvent<HTMLElement>) => void;
|
|
126
|
-
onPointerDown: (e: PointerEvent<HTMLElement>) => void;
|
|
127
|
-
onPointerMove: (e: PointerEvent<HTMLElement>) => void;
|
|
128
|
-
onPointerUp: (e: PointerEvent<HTMLElement>) => void;
|
|
128
|
+
onPointerDown: (e: PointerEvent$1<HTMLElement>) => void;
|
|
129
129
|
isDragging: () => boolean;
|
|
130
130
|
}
|
|
131
|
-
declare function usePanZoom({ view, onViewChange, minZoom, maxZoom, frame, }: UsePanZoomOptions): PanZoomHandlers;
|
|
131
|
+
declare function usePanZoom({ view, onViewChange, minZoom, maxZoom, frame, onTap, }: UsePanZoomOptions): PanZoomHandlers;
|
|
132
132
|
|
|
133
133
|
export { CanvasLayerDescriptor, CanvasStack, PITCH_LIMIT, ViewportSize, WorldFrame, WorldSpec, centerOn, clampPitch, orbitAfterDrag, orbitAfterWheel, screenToWorld, useOrbit, usePanZoom, worldToScreen, wrapYaw, zoomAt };
|
|
134
134
|
export type { CanvasStackProps, OrbitHandlers, OrbitView, PanZoomHandlers, UseOrbitOptions, UsePanZoomOptions, Vec3, ZoomAtOptions };
|
package/dist/canvas/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { CanvasStack, PITCH_LIMIT, clampPitch, orbitAfterDrag, orbitAfterWheel, useOrbit, usePanZoom, wrapYaw } from '../chunk-
|
|
1
|
+
export { CanvasStack, PITCH_LIMIT, clampPitch, orbitAfterDrag, orbitAfterWheel, useOrbit, usePanZoom, wrapYaw } from '../chunk-PP7ZWAMV.js';
|
|
2
2
|
export { centerOn, zoomAt } from '../chunk-CTRKTLYZ.js';
|
|
3
3
|
export { DEFAULT_FRAME, applyCamera, resolveFrame, screenToWorld, worldToScreen } from '../chunk-2AYGEN57.js';
|
|
4
4
|
export { CanvasStackContext } from '../chunk-CQLQPQ4P.js';
|
|
5
|
-
import '../chunk-
|
|
5
|
+
import '../chunk-DG2IFMLA.js';
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
|
7
7
|
//# sourceMappingURL=index.js.map
|
package/dist/chrome/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { c as ControlRenderer } from '../_dts/types-
|
|
2
|
-
import { I as Instrument, _ as TrialChromeContext, m as TrialContribution } from '../_dts/frac-
|
|
3
|
-
export { z as IconComponent, O as SidebarSection, Q as StatusReadout, Y as ToolItem, Z as ToolbarItem, $ as TrialRegion, a1 as ViewportControl } from '../_dts/frac-
|
|
1
|
+
import { c as ControlRenderer } from '../_dts/types-lg4TSCb2.js';
|
|
2
|
+
import { I as Instrument, _ as TrialChromeContext, m as TrialContribution } from '../_dts/frac-X7mWgd7y.js';
|
|
3
|
+
export { z as IconComponent, O as SidebarSection, Q as StatusReadout, Y as ToolItem, Z as ToolbarItem, $ as TrialRegion, a1 as ViewportControl } from '../_dts/frac-X7mWgd7y.js';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
|
-
import '../_dts/
|
|
5
|
+
import '../_dts/weasel-canvas-FJTFi3ZZ.js';
|
|
6
6
|
import 'react';
|
|
7
|
-
import '../_dts/
|
|
7
|
+
import '../_dts/PrefsForm.d-CgxUequc.js';
|
|
8
|
+
import '../_dts/types-ChVJJHvk.js';
|
|
8
9
|
import '../_dts/types-DJ79Tg5J.js';
|
|
9
|
-
import '../_dts/types-C-gh9Ap-.js';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* The contributions a trial gets from what its instrument declared. This is
|
package/dist/chrome/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, ViewportRegion, builtinContributions, mergeContributions, suppressContributions } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-
|
|
1
|
+
export { PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, ViewportRegion, builtinContributions, mergeContributions, suppressContributions } from '../chunk-BMQWLKOL.js';
|
|
2
|
+
import '../chunk-MSR7EVS6.js';
|
|
3
|
+
import '../chunk-53AZ2O2N.js';
|
|
4
4
|
import '../chunk-SBXNQW4G.js';
|
|
5
|
-
import '../chunk-
|
|
5
|
+
import '../chunk-J6SBFZYT.js';
|
|
6
6
|
import '../chunk-CQLQPQ4P.js';
|
|
7
|
-
import '../chunk-
|
|
7
|
+
import '../chunk-DG2IFMLA.js';
|
|
8
8
|
//# sourceMappingURL=index.js.map
|
|
9
9
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
import { useStore } from 'zustand/react';
|
|
3
|
+
import { jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
// src/state/context.tsx
|
|
6
|
+
var LabStoreContext = createContext(null);
|
|
7
|
+
function LabStoreProvider({
|
|
8
|
+
store,
|
|
9
|
+
children
|
|
10
|
+
}) {
|
|
11
|
+
return /* @__PURE__ */ jsx(LabStoreContext.Provider, { value: { store }, children });
|
|
12
|
+
}
|
|
13
|
+
function useLabStore() {
|
|
14
|
+
const ctx = useContext(LabStoreContext);
|
|
15
|
+
if (!ctx) throw new Error("[labkit] useLabStore must be used inside <LabStoreProvider>");
|
|
16
|
+
return useStore(ctx.store);
|
|
17
|
+
}
|
|
18
|
+
var TrialIdContext = createContext(null);
|
|
19
|
+
function TrialIdProvider({
|
|
20
|
+
trialId,
|
|
21
|
+
children
|
|
22
|
+
}) {
|
|
23
|
+
return /* @__PURE__ */ jsx(TrialIdContext.Provider, { value: trialId, children });
|
|
24
|
+
}
|
|
25
|
+
function useTrialId() {
|
|
26
|
+
const id = useContext(TrialIdContext);
|
|
27
|
+
if (!id) throw new Error("[labkit] useTrialId must be used inside <TrialIdProvider>");
|
|
28
|
+
return id;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { LabStoreContext, LabStoreProvider, TrialIdContext, TrialIdProvider, useLabStore, useTrialId };
|
|
32
|
+
//# sourceMappingURL=chunk-2YILQ7Y5.js.map
|
|
33
|
+
//# sourceMappingURL=chunk-2YILQ7Y5.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/state/context.tsx"],"names":[],"mappings":";;;;;AASO,IAAM,eAAA,GAAkB,cAA2B,IAAI;AAGvD,SAAS,gBAAA,CAAiB;AAAA,EAC/B,KAAA;AAAA,EACA;AACF,CAAA,EAGiB;AACf,EAAA,uBAAO,GAAA,CAAC,gBAAgB,QAAA,EAAhB,EAAyB,OAAO,EAAE,KAAA,IAAU,QAAA,EAAS,CAAA;AAC/D;AAGO,SAAS,WAAA,GAAgE;AAC9E,EAAA,MAAM,GAAA,GAAM,WAAW,eAAe,CAAA;AACtC,EAAA,IAAI,CAAC,GAAA,EAAK,MAAM,IAAI,MAAM,6DAA6D,CAAA;AACvF,EAAA,OAAO,QAAA,CAAS,IAAI,KAAK,CAAA;AAC3B;AAGO,IAAM,cAAA,GAAiB,cAA6B,IAAI;AAIxD,SAAS,eAAA,CAAgB;AAAA,EAC9B,OAAA;AAAA,EACA;AACF,CAAA,EAGiB;AACf,EAAA,2BAAQ,cAAA,CAAe,QAAA,EAAf,EAAwB,KAAA,EAAO,SAAU,QAAA,EAAS,CAAA;AAC5D;AAIO,SAAS,UAAA,GAAqB;AACnC,EAAA,MAAM,EAAA,GAAK,WAAW,cAAc,CAAA;AACpC,EAAA,IAAI,CAAC,EAAA,EAAI,MAAM,IAAI,MAAM,2DAA2D,CAAA;AACpF,EAAA,OAAO,EAAA;AACT","file":"chunk-2YILQ7Y5.js","sourcesContent":["import { createContext, type ReactElement, type ReactNode, useContext } from 'react';\nimport { useStore } from 'zustand/react';\nimport type { LabStore } from './store';\nimport type { LabStoreState } from './types';\n\ntype LabStoreCtx = { store: LabStore } | null;\n\n/** Context carrying the lab store. Prefer `useLabStore`; this is exported for\n * code that needs to read the context without subscribing. */\nexport const LabStoreContext = createContext<LabStoreCtx>(null);\n\n/** Provides a lab store to its subtree. */\nexport function LabStoreProvider({\n store,\n children,\n}: {\n store: LabStore;\n children: ReactNode;\n}): ReactElement {\n return <LabStoreContext.Provider value={{ store }}>{children}</LabStoreContext.Provider>;\n}\n\n/** Subscribe to the whole lab store. Throws outside a `<LabStoreProvider>`. */\nexport function useLabStore(): LabStoreState & ReturnType<LabStore['getState']> {\n const ctx = useContext(LabStoreContext);\n if (!ctx) throw new Error('[labkit] useLabStore must be used inside <LabStoreProvider>');\n return useStore(ctx.store);\n}\n\n/** Context carrying which trial the subtree belongs to. */\nexport const TrialIdContext = createContext<string | null>(null);\n\n/** Names the trial its subtree belongs to, so an instrument's hooks can\n * find their own record in the store without being passed an id. */\nexport function TrialIdProvider({\n trialId,\n children,\n}: {\n trialId: string;\n children: ReactNode;\n}): ReactElement {\n return <TrialIdContext.Provider value={trialId}>{children}</TrialIdContext.Provider>;\n}\n\n/** The id of the trial this component is inside. Throws outside a\n * `<TrialIdProvider>`. */\nexport function useTrialId(): string {\n const id = useContext(TrialIdContext);\n if (!id) throw new Error('[labkit] useTrialId must be used inside <TrialIdProvider>');\n return id;\n}\n"]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isBuiltinToolPref } from './chunk-
|
|
1
|
+
import { C2, x3, k, P2, N2, A2, D, M2, T2, j2 } from './chunk-J6SBFZYT.js';
|
|
2
|
+
import { isBuiltinToolPref } from './chunk-DG2IFMLA.js';
|
|
3
3
|
import { useMemo, useState, useRef, useEffect } from 'react';
|
|
4
4
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
5
5
|
|
|
@@ -100,13 +100,13 @@ function ControlPanel({
|
|
|
100
100
|
);
|
|
101
101
|
const gridPack = pack === "one-up" ? "auto-color" : "pairs";
|
|
102
102
|
return /* @__PURE__ */ jsxs(
|
|
103
|
-
|
|
103
|
+
C2,
|
|
104
104
|
{
|
|
105
105
|
pack: gridPack,
|
|
106
106
|
className: className ? `lk-control-panel ${className}` : "lk-control-panel",
|
|
107
107
|
children: [
|
|
108
108
|
loose.map(row),
|
|
109
|
-
resolved.sections.map((section) => /* @__PURE__ */ jsx(
|
|
109
|
+
resolved.sections.map((section) => /* @__PURE__ */ jsx(x3, { title: section.label, pack: gridPack, children: section.paths.map(row) }, section.label))
|
|
110
110
|
]
|
|
111
111
|
}
|
|
112
112
|
);
|
|
@@ -143,15 +143,17 @@ function ControlRow({
|
|
|
143
143
|
const min = extra(leaf, "min");
|
|
144
144
|
const max = extra(leaf, "max");
|
|
145
145
|
const step = extra(leaf, "step");
|
|
146
|
+
const suffix = extra(leaf, "suffix");
|
|
146
147
|
if (extra(leaf, "control") === "slider" && min !== void 0 && max !== void 0) {
|
|
147
148
|
return /* @__PURE__ */ jsx(
|
|
148
|
-
|
|
149
|
+
D,
|
|
149
150
|
{
|
|
150
151
|
label,
|
|
151
152
|
value: read(),
|
|
152
153
|
min,
|
|
153
154
|
max,
|
|
154
155
|
step,
|
|
156
|
+
unit: suffix,
|
|
155
157
|
onChange: write,
|
|
156
158
|
layout,
|
|
157
159
|
span: wide,
|
|
@@ -162,13 +164,14 @@ function ControlRow({
|
|
|
162
164
|
const lo = min ?? Number.NEGATIVE_INFINITY;
|
|
163
165
|
const hi = max ?? Number.POSITIVE_INFINITY;
|
|
164
166
|
return /* @__PURE__ */ jsx(
|
|
165
|
-
|
|
167
|
+
M2,
|
|
166
168
|
{
|
|
167
169
|
label,
|
|
168
170
|
value: read(),
|
|
169
171
|
min,
|
|
170
172
|
max,
|
|
171
173
|
step,
|
|
174
|
+
unit: suffix,
|
|
172
175
|
onChange: (n) => write(Math.min(hi, Math.max(lo, n))),
|
|
173
176
|
layout,
|
|
174
177
|
description
|
|
@@ -177,7 +180,7 @@ function ControlRow({
|
|
|
177
180
|
}
|
|
178
181
|
case "boolean":
|
|
179
182
|
return /* @__PURE__ */ jsx(
|
|
180
|
-
|
|
183
|
+
A2,
|
|
181
184
|
{
|
|
182
185
|
label,
|
|
183
186
|
value: read(),
|
|
@@ -188,7 +191,7 @@ function ControlRow({
|
|
|
188
191
|
case "enum": {
|
|
189
192
|
const options = extra(leaf, "options") ?? [];
|
|
190
193
|
const segmented = extra(leaf, "control") === "radio";
|
|
191
|
-
const Row = segmented ?
|
|
194
|
+
const Row = segmented ? P2 : N2;
|
|
192
195
|
return /* @__PURE__ */ jsx(
|
|
193
196
|
Row,
|
|
194
197
|
{
|
|
@@ -216,7 +219,7 @@ function ControlRow({
|
|
|
216
219
|
}
|
|
217
220
|
);
|
|
218
221
|
case "color":
|
|
219
|
-
return /* @__PURE__ */ jsx(
|
|
222
|
+
return /* @__PURE__ */ jsx(k, { label, value: read(), onChange: write, description });
|
|
220
223
|
case "paint":
|
|
221
224
|
case "object":
|
|
222
225
|
return /* @__PURE__ */ jsx(UnwiredRow, { label, kind: leaf.kind, description });
|
|
@@ -233,7 +236,7 @@ function UnwiredRow({
|
|
|
233
236
|
kind,
|
|
234
237
|
description
|
|
235
238
|
}) {
|
|
236
|
-
return /* @__PURE__ */ jsx(
|
|
239
|
+
return /* @__PURE__ */ jsx(T2, { label, description, children: /* @__PURE__ */ jsxs("span", { className: "lk-control-panel__unknown", children: [
|
|
237
240
|
"no control for \u201C",
|
|
238
241
|
kind,
|
|
239
242
|
"\u201D"
|
|
@@ -265,7 +268,7 @@ function DebouncedTextRow({
|
|
|
265
268
|
[]
|
|
266
269
|
);
|
|
267
270
|
return /* @__PURE__ */ jsx(
|
|
268
|
-
|
|
271
|
+
j2,
|
|
269
272
|
{
|
|
270
273
|
label,
|
|
271
274
|
layout,
|
|
@@ -289,5 +292,5 @@ function DebouncedTextRow({
|
|
|
289
292
|
}
|
|
290
293
|
|
|
291
294
|
export { ControlPanel, fromConfigFields, isLeafVisible };
|
|
292
|
-
//# sourceMappingURL=chunk-
|
|
293
|
-
//# sourceMappingURL=chunk-
|
|
295
|
+
//# sourceMappingURL=chunk-53AZ2O2N.js.map
|
|
296
|
+
//# sourceMappingURL=chunk-53AZ2O2N.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config/fromConfigField.ts","../src/config/visible.ts","../src/controls/ControlPanel.tsx"],"names":["C","x","value","M","A","P","N","T","j"],"mappings":"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","file":"chunk-53AZ2O2N.js","sourcesContent":["import type { PrefLeaf } from '@weasel-js/ui';\nimport type { ConfigField } from '../controls/types';\nimport type { LeafPatch, ResolvedConfig } from './types';\n\n/** One `ConfigField` as the `Pref*` vocabulary spells it. The two describe the\n * same thing; `ConfigField` just keys on the control where `PrefLeaf`\n * separates the value's kind from how it is presented. */\nfunction toLeaf(field: ConfigField): LeafPatch {\n const base = { name: field.label, description: '' };\n switch (field.type) {\n case 'slider':\n return {\n ...base,\n kind: 'number',\n control: 'slider',\n min: field.min,\n max: field.max,\n step: field.step,\n };\n case 'number':\n return {\n ...base,\n kind: 'number',\n control: 'input',\n min: field.min,\n max: field.max,\n step: field.step,\n };\n case 'checkbox':\n return { ...base, kind: 'boolean', control: 'checkbox' };\n case 'select':\n return { ...base, kind: 'enum', options: field.options };\n case 'text':\n return {\n ...base,\n kind: 'string',\n placeholder: field.placeholder,\n maxLength: field.maxLength,\n debounceMs: field.debounceMs,\n };\n case 'color':\n return { ...base, kind: 'color' };\n default:\n // A schema can arrive from outside TypeScript. Carry the kind through\n // so a lab-supplied renderer can still claim it.\n return { ...base, kind: (field as ConfigField).type };\n }\n}\n\n/**\n * Adapt a legacy `configSchema(): ConfigField[]` into the resolved shape, so\n * both instrument paths reach one renderer.\n *\n * Rules do not run here: a hand-written `ConfigField` already states its label\n * and control, which is everything the rule chain would have inferred.\n */\nexport function fromConfigFields(fields: readonly ConfigField[]): ResolvedConfig {\n const children: Record<string, PrefLeaf> = {};\n for (const field of fields) {\n const patch = toLeaf(field);\n for (const key of Object.keys(patch)) {\n if ((patch as Record<string, unknown>)[key] === undefined) {\n delete (patch as Record<string, unknown>)[key];\n }\n }\n children[field.key] = { ...patch, default: field.default } as PrefLeaf;\n }\n return {\n group: { name: '', children },\n sections: [],\n showIf: new Map(),\n renderers: {},\n };\n}\n","import type { ResolvedConfig } from './types';\n\n/**\n * Whether a leaf's row should be drawn right now.\n *\n * `hidden` is the leaf's own static flag; `showIf` is the schema's predicate\n * over the live config. Both are presentational — a hidden leaf keeps its\n * value and the instrument still reads it.\n */\nexport function isLeafVisible(\n resolved: ResolvedConfig,\n path: string,\n config: Record<string, unknown>,\n showHidden = false,\n): boolean {\n const leaf = resolved.group.children[path];\n if (leaf && 'hidden' in leaf && leaf.hidden === true && !showHidden) return false;\n const predicate = resolved.showIf.get(path);\n return predicate ? predicate(config) : true;\n}\n","import { isBuiltinToolPref } from '@weasel-js/core';\nimport {\n CheckboxRow,\n ColorRow,\n NumberRow,\n type PrefLeaf,\n PropertyGroup,\n PropertyList,\n PropertyRow,\n type PropertyRowLayout,\n SelectRow,\n SliderRow,\n TextRow,\n ToggleRow,\n} from '@weasel-js/ui';\nimport { type ReactNode, useEffect, useMemo, useRef, useState } from 'react';\nimport { fromConfigFields } from '../config/fromConfigField';\nimport type { ControlRenderer, ResolvedConfig } from '../config/types';\nimport { isLeafVisible } from '../config/visible';\nimport type { ConfigField } from './types';\n\n/** How a panel packs its rows into the two-column property grid.\n * - `'auto'`: narrow controls (numbers, checkboxes, dropdowns, colours) sit\n * two per row; the ones that need the width — text, sliders, segmented\n * toggles — span it.\n * - `'pairs'`: every row pairs. A control that needs the full width says so\n * itself, with `<PropertyRow span>`.\n * - `'one-up'`: one control per row, colours excepted.\n */\nexport type ControlPack = 'auto' | 'pairs' | 'one-up';\n\nexport interface ControlPanelProps<TC extends Record<string, unknown>> {\n /** The instrument's resolved config schema. */\n schema?: ResolvedConfig;\n /** @deprecated Pass `schema`. A field list is adapted into one internally. */\n fields?: ConfigField[];\n config: TC;\n setConfig: (key: keyof TC, value: unknown) => void;\n /**\n * Control overrides and app-defined kinds, PrefsForm-style. Keys are config\n * paths (checked first) or leaf kinds. A renderer returning `null` collapses\n * the row; entries override the built-in rows on collision.\n */\n renderers?: Record<string, ControlRenderer>;\n /** How rows pack into the two-column grid. Defaults to `'pairs'`. */\n pack?: ControlPack;\n /** Where a row's label sits relative to its control. Defaults to `'block'`\n * — above it, which is what leaves a paired row room for its value. */\n layout?: PropertyRowLayout;\n /** Draw leaves marked `hidden`. */\n showHidden?: boolean;\n className?: string;\n}\n\n/** Render an instrument's config schema as a stack of controls, each writing\n * back through `setConfig`. Built on the property rows, so a lab's controls\n * are the same aligned, themed rows the rest of the kit uses. */\nexport function ControlPanel<TC extends Record<string, unknown>>({\n schema,\n fields,\n config,\n setConfig,\n renderers,\n pack = 'pairs',\n layout = 'block',\n showHidden = false,\n className,\n}: ControlPanelProps<TC>) {\n const resolved = useMemo(() => schema ?? fromConfigFields(fields ?? []), [schema, fields]);\n\n const paths = Object.keys(resolved.group.children);\n const sectioned = new Set(resolved.sections.flatMap((s) => s.paths));\n const loose = paths.filter((p) => !sectioned.has(p));\n\n const row = (path: string): ReactNode => (\n <ControlRow\n key={path}\n path={path}\n resolved={resolved}\n config={config}\n setConfig={setConfig}\n renderers={renderers}\n pack={pack}\n layout={layout}\n showHidden={showHidden}\n />\n );\n\n const gridPack = pack === 'one-up' ? 'auto-color' : 'pairs';\n return (\n <PropertyList\n pack={gridPack}\n className={className ? `lk-control-panel ${className}` : 'lk-control-panel'}\n >\n {loose.map(row)}\n {resolved.sections.map((section) => (\n <PropertyGroup key={section.label} title={section.label} pack={gridPack}>\n {section.paths.map(row)}\n </PropertyGroup>\n ))}\n </PropertyList>\n );\n}\n\ninterface ControlRowProps<TC extends Record<string, unknown>> {\n path: string;\n resolved: ResolvedConfig;\n config: TC;\n setConfig: (key: keyof TC, value: unknown) => void;\n renderers?: Record<string, ControlRenderer>;\n pack: ControlPack;\n layout: PropertyRowLayout;\n showHidden: boolean;\n}\n\n/** Reads a labkit-only extra off a leaf. `PrefLeaf` has no field for these,\n * and extra keys survive the resolve pass at runtime. */\nfunction extra<T>(leaf: PrefLeaf, key: string): T | undefined {\n return (leaf as unknown as Record<string, T | undefined>)[key];\n}\n\nfunction ControlRow<TC extends Record<string, unknown>>({\n path,\n resolved,\n config,\n setConfig,\n renderers,\n pack,\n layout,\n showHidden,\n}: ControlRowProps<TC>) {\n const leaf = resolved.group.children[path] as PrefLeaf | undefined;\n if (!leaf || !('kind' in leaf)) return null;\n if (!isLeafVisible(resolved, path, config as Record<string, unknown>, showHidden)) return null;\n\n const write = (value: unknown): void => setConfig(path as keyof TC, value);\n const fallback = extra<unknown>(leaf, 'default');\n const value = config[path] ?? fallback;\n\n // Most specific wins, and within a tier the lab's entry beats the\n // instrument's: controls[path] -> node .render -> controls[kind] -> built-in.\n const custom = renderers?.[path] ?? resolved.renderers[path] ?? renderers?.[leaf.kind];\n // A custom row places itself like any other; one that needs the full width\n // says so with `<PropertyRow span>`, which is the same opt-out a built-in has.\n if (custom) return custom({ path, pref: leaf, value, setValue: write });\n\n const label = leaf.name;\n const description = leaf.description;\n const read = <T,>(): T => value as T;\n // `auto` gives the whole width to the controls that read badly at half of a\n // sidebar's: free text, a slider track, a segmented toggle. `pairs` doesn't.\n const wide = pack === 'auto';\n\n if (!isBuiltinToolPref(leaf))\n return <UnwiredRow label={label} kind={leaf.kind} description={description} />;\n\n switch (leaf.kind) {\n case 'number': {\n const min = extra<number>(leaf, 'min');\n const max = extra<number>(leaf, 'max');\n const step = extra<number>(leaf, 'step');\n const suffix = extra<string>(leaf, 'suffix');\n if (extra<string>(leaf, 'control') === 'slider' && min !== undefined && max !== undefined) {\n return (\n <SliderRow\n label={label}\n value={read<number>()}\n min={min}\n max={max}\n step={step}\n unit={suffix}\n onChange={write}\n layout={layout}\n span={wide}\n description={description}\n />\n );\n }\n // NumberRow commits every keystroke and does not clamp, so the bounds a\n // schema declares are enforced here — an instrument should never be\n // handed a config value outside the range it asked for.\n const lo = min ?? Number.NEGATIVE_INFINITY;\n const hi = max ?? Number.POSITIVE_INFINITY;\n return (\n <NumberRow\n label={label}\n value={read<number>()}\n min={min}\n max={max}\n step={step}\n unit={suffix}\n onChange={(n) => write(Math.min(hi, Math.max(lo, n)))}\n layout={layout}\n description={description}\n />\n );\n }\n case 'boolean':\n return (\n <CheckboxRow\n label={label}\n value={read<boolean>()}\n onChange={write}\n description={description}\n />\n );\n case 'enum': {\n const options = extra<readonly { value: string; label: string }[]>(leaf, 'options') ?? [];\n const segmented = extra<string>(leaf, 'control') === 'radio';\n const Row = segmented ? ToggleRow : SelectRow;\n return (\n <Row\n label={label}\n value={read<string>()}\n options={options}\n onChange={write}\n layout={layout}\n span={segmented && wide}\n description={description}\n />\n );\n }\n case 'string':\n return (\n <DebouncedTextRow\n leaf={leaf}\n label={label}\n value={read<string>()}\n write={write}\n layout={layout}\n span={wide}\n description={description}\n />\n );\n case 'color':\n return (\n <ColorRow label={label} value={read<string>()} onChange={write} description={description} />\n );\n case 'paint':\n case 'object':\n // Declined: a hex swatch would write a solid over a gradient, and a flat\n // row would write one field into a half-built object. Override with\n // `render` to edit either.\n return <UnwiredRow label={label} kind={leaf.kind} description={description} />;\n default: {\n // Not reachable while every built-in kind has an arm — and a new kind\n // that lacks one is a compile error here, never a blank row.\n const _exhaustive: never = leaf;\n throw new Error(\n `ControlPanel: no control for built-in pref kind \"${(_exhaustive as { kind: string }).kind}\"`,\n );\n }\n }\n}\n\n/** A leaf this panel has no control for is named rather than dropped: a silent\n * gap reads as \"this control does not exist\". */\nfunction UnwiredRow({\n label,\n kind,\n description,\n}: {\n label: string;\n kind: string;\n description?: string;\n}) {\n return (\n <PropertyRow label={label} description={description}>\n <span className=\"lk-control-panel__unknown\">no control for “{kind}”</span>\n </PropertyRow>\n );\n}\n\n/** Text writes are debounced so typing does not re-run the instrument on every\n * keystroke, which means the row is locally controlled between commits and has\n * to notice when the config changes underneath it. */\nfunction DebouncedTextRow({\n leaf,\n label,\n value,\n write,\n layout,\n span,\n description,\n}: {\n leaf: PrefLeaf;\n label: string;\n value: string;\n write: (value: unknown) => void;\n layout?: PropertyRowLayout;\n span?: boolean;\n description?: string;\n}) {\n const debounceMs = extra<number>(leaf, 'debounceMs') ?? 150;\n const [local, setLocal] = useState(value);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const lastExternal = useRef(value);\n\n useEffect(() => {\n if (value !== lastExternal.current) {\n lastExternal.current = value;\n setLocal(value);\n }\n }, [value]);\n\n useEffect(\n () => () => {\n if (timer.current) clearTimeout(timer.current);\n },\n [],\n );\n\n return (\n <TextRow\n label={label}\n layout={layout}\n span={span}\n description={description}\n value={local}\n placeholder={extra<string>(leaf, 'placeholder')}\n maxLength={extra<number>(leaf, 'maxLength')}\n onChange={(next) => {\n setLocal(next);\n if (timer.current) clearTimeout(timer.current);\n const commit = () => {\n lastExternal.current = next;\n write(next);\n };\n if (debounceMs === 0) commit();\n else timer.current = setTimeout(commit, debounceMs);\n }}\n />\n );\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ce, le } from './chunk-J6SBFZYT.js';
|
|
2
|
+
import { openPointerSession } from './chunk-DG2IFMLA.js';
|
|
2
3
|
import { useRef, useMemo, useState, useEffect } from 'react';
|
|
3
4
|
import { floatingStrategy, DEFAULT_INSET, DEFAULT_ANCHOR, FLOATING_DRAG_PREFIX } from 'windease';
|
|
4
5
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
@@ -78,56 +79,69 @@ function FloatingPanel({
|
|
|
78
79
|
options
|
|
79
80
|
}).placements.get(ITEM_ID);
|
|
80
81
|
const dragging = useRef(null);
|
|
81
|
-
const
|
|
82
|
+
const session = useRef(null);
|
|
82
83
|
const [isDragging, setDragging] = useState(false);
|
|
84
|
+
const layout = useRef({ container, options, item });
|
|
85
|
+
layout.current = { container, options, item };
|
|
86
|
+
useEffect(() => () => session.current?.cancel(), []);
|
|
83
87
|
const onPointerDown = (e) => {
|
|
84
88
|
if (isInteractive(e.target)) return;
|
|
85
89
|
e.stopPropagation();
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
if (
|
|
92
|
-
dragging.current =
|
|
93
|
-
setDragging(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
90
|
+
const origin = e.currentTarget;
|
|
91
|
+
const pointerId = e.pointerId;
|
|
92
|
+
const start = { x: e.clientX, y: e.clientY };
|
|
93
|
+
const end = () => {
|
|
94
|
+
session.current = null;
|
|
95
|
+
if (!dragging.current) return;
|
|
96
|
+
dragging.current = null;
|
|
97
|
+
setDragging(false);
|
|
98
|
+
try {
|
|
99
|
+
origin.releasePointerCapture?.(pointerId);
|
|
100
|
+
} catch {
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
session.current = openPointerSession(
|
|
104
|
+
origin,
|
|
105
|
+
e,
|
|
106
|
+
{
|
|
107
|
+
onMove: (ev) => {
|
|
108
|
+
if (!dragging.current) {
|
|
109
|
+
if (Math.hypot(ev.clientX - start.x, ev.clientY - start.y) < DRAG_THRESHOLD) return;
|
|
110
|
+
dragging.current = { ...start };
|
|
111
|
+
setDragging(true);
|
|
112
|
+
origin.setPointerCapture?.(pointerId);
|
|
113
|
+
}
|
|
114
|
+
const from = dragging.current;
|
|
115
|
+
const dx = ev.clientX - from.x;
|
|
116
|
+
const dy = ev.clientY - from.y;
|
|
117
|
+
if (dx === 0 && dy === 0) return;
|
|
118
|
+
dragging.current = { x: ev.clientX, y: ev.clientY };
|
|
119
|
+
const { container: box, options: opts, item: only } = layout.current;
|
|
120
|
+
setPlace(
|
|
121
|
+
(prev) => strategy.reduce?.(
|
|
122
|
+
{ at: { [ITEM_ID]: prev }, inner: void 0 },
|
|
123
|
+
{
|
|
124
|
+
affordanceId: `${FLOATING_DRAG_PREFIX}${ITEM_ID}`,
|
|
125
|
+
kind: "drag",
|
|
126
|
+
payload: { dx, dy }
|
|
127
|
+
},
|
|
128
|
+
{ container: box, options: opts, items: [only] }
|
|
129
|
+
).at[ITEM_ID] ?? prev
|
|
130
|
+
);
|
|
109
131
|
},
|
|
110
|
-
|
|
111
|
-
|
|
132
|
+
onEnd: end,
|
|
133
|
+
onCancel: end
|
|
134
|
+
},
|
|
135
|
+
{ capture: false }
|
|
112
136
|
);
|
|
113
137
|
};
|
|
114
|
-
const endDrag = (e) => {
|
|
115
|
-
pending.current = null;
|
|
116
|
-
if (!dragging.current) return;
|
|
117
|
-
dragging.current = null;
|
|
118
|
-
setDragging(false);
|
|
119
|
-
e.currentTarget.releasePointerCapture?.(e.pointerId);
|
|
120
|
-
};
|
|
121
138
|
return /* @__PURE__ */ jsx(
|
|
122
139
|
"div",
|
|
123
140
|
{
|
|
124
141
|
className: className ? `lk-floating-panel ${className}` : "lk-floating-panel",
|
|
125
142
|
"data-dragging": isDragging ? "true" : void 0,
|
|
126
143
|
"data-placed": rect ? "true" : void 0,
|
|
127
|
-
onPointerCancel: endDrag,
|
|
128
144
|
onPointerDown,
|
|
129
|
-
onPointerMove,
|
|
130
|
-
onPointerUp: endDrag,
|
|
131
145
|
ref,
|
|
132
146
|
style: {
|
|
133
147
|
position: "absolute",
|
|
@@ -168,12 +182,12 @@ function JobProgress({ job, className }) {
|
|
|
168
182
|
determinate ? ` / ${total}` : ""
|
|
169
183
|
] }),
|
|
170
184
|
failures.length > 0 && /* @__PURE__ */ jsxs("span", { className: "lk-job__failures", title: failures.map((f) => f.error).join("\n"), children: [
|
|
171
|
-
/* @__PURE__ */ jsx(
|
|
185
|
+
/* @__PURE__ */ jsx(ce, { size: 14 }),
|
|
172
186
|
failures.length,
|
|
173
187
|
" failed"
|
|
174
188
|
] }),
|
|
175
189
|
error && /* @__PURE__ */ jsxs("span", { className: "lk-job__error", title: error, children: [
|
|
176
|
-
/* @__PURE__ */ jsx(
|
|
190
|
+
/* @__PURE__ */ jsx(le, { size: 14 }),
|
|
177
191
|
error
|
|
178
192
|
] }),
|
|
179
193
|
status === "running" && /* @__PURE__ */ jsx("button", { type: "button", className: "lk-job__cancel", onClick: job.cancel, children: "Cancel" })
|
|
@@ -216,5 +230,5 @@ function Sidebar({ children, title, collapsed = false, onToggle }) {
|
|
|
216
230
|
}
|
|
217
231
|
|
|
218
232
|
export { FloatingPanel, JobProgress, Legend, Sidebar };
|
|
219
|
-
//# sourceMappingURL=chunk-
|
|
220
|
-
//# sourceMappingURL=chunk-
|
|
233
|
+
//# sourceMappingURL=chunk-7TRFMIWX.js.map
|
|
234
|
+
//# sourceMappingURL=chunk-7TRFMIWX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/primitives/FloatingPanel.tsx","../src/primitives/JobProgress.tsx","../src/primitives/Legend.tsx","../src/primitives/Sidebar.tsx"],"names":["jsx","jsxs"],"mappings":"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","file":"chunk-7TRFMIWX.js","sourcesContent":["import { openPointerSession, type PointerSession } from '@weasel-js/core';\nimport type React from 'react';\nimport { type CSSProperties, type ReactNode, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n type Corner,\n DEFAULT_ANCHOR,\n DEFAULT_INSET,\n FLOATING_DRAG_PREFIX,\n type FloatingPlacement,\n floatingStrategy,\n} from 'windease';\n\n/** The strategy holds a map keyed by item id; a panel is always a lone item. */\nconst ITEM_ID = 'panel';\n\n/** Props for `<FloatingPanel>`. */\nexport interface FloatingPanelProps {\n children: ReactNode;\n /** Corner it rests in before it has ever been dragged. Default `'bottom-left'`. */\n anchor?: Corner;\n /** Corners that may capture it. Default: all four. */\n snapCorners?: readonly Corner[];\n /** Pixels in from a corner when snapped. Default 12. */\n inset?: number;\n /** localStorage key to remember its position under. Omit to forget on reload. */\n storageKey?: string;\n className?: string;\n}\n\n/**\n * The panel's footprint is its border box — `contentRect` excludes padding and\n * border, which would place a panel that then overflows its corner by exactly\n * that much.\n */\nfunction borderBoxOf(entry: ResizeObserverEntry): { w: number; h: number } {\n const box = entry.borderBoxSize?.[0];\n if (box) return { w: box.inlineSize, h: box.blockSize };\n return { w: entry.contentRect.width, h: entry.contentRect.height };\n}\n\n/** How far the pointer must travel before a press becomes a drag. */\nconst DRAG_THRESHOLD = 3;\n\n/** A pointerdown on one of these is the child's, not a drag. */\nfunction isInteractive(target: EventTarget | null): boolean {\n if (!(target instanceof Element)) return false;\n return target.closest('input, button, a, select, textarea, [data-no-drag]') !== null;\n}\n\nfunction readStored(key: string | undefined): FloatingPlacement | null {\n if (!key) return null;\n try {\n const raw = localStorage.getItem(key);\n return raw ? (JSON.parse(raw) as FloatingPlacement) : null;\n } catch {\n return null;\n }\n}\n\n/**\n * A draggable box that floats over its offset parent and snaps to its corners.\n *\n * Drives windease's `floatingStrategy` as a pure function rather than mounting a\n * windease container: a lab overlay has one item and no zone tree, so the node\n * model would be all cost. Pointer handling is therefore this component's, and\n * windease's own affordance rendering never participates.\n */\nexport function FloatingPanel({\n children,\n anchor = DEFAULT_ANCHOR,\n snapCorners,\n inset = DEFAULT_INSET,\n storageKey,\n className,\n}: FloatingPanelProps) {\n const ref = useRef<HTMLDivElement>(null);\n const strategy = useMemo(() => floatingStrategy(), []);\n const options = useMemo(() => ({ defaultAnchor: anchor, inset }), [anchor, inset]);\n\n const [container, setContainer] = useState({ w: 0, h: 0 });\n const [size, setSize] = useState({ w: 0, h: 0 });\n const [place, setPlace] = useState<FloatingPlacement>(\n () => readStored(storageKey) ?? { x: 0, y: 0, anchor },\n );\n\n useEffect(() => {\n if (!storageKey) return;\n try {\n localStorage.setItem(storageKey, JSON.stringify(place));\n } catch {\n // A full or disabled store is not worth failing a lab over.\n }\n }, [place, storageKey]);\n\n const item = useMemo(\n () => ({\n id: ITEM_ID,\n meta: { floating: true, ...(snapCorners ? { snapCorners: [...snapCorners] } : {}) },\n natural: size,\n }),\n [size, snapCorners],\n );\n\n useEffect(() => {\n const el = ref.current;\n const parent = el?.offsetParent ?? el?.parentElement;\n if (!el || !parent) return;\n // Sizes come off the entry, not the DOM: jsdom reports 0 for every\n // clientWidth/offsetWidth, and an unmeasured item is withheld from layout.\n const observer = new ResizeObserver((entries) => {\n for (const entry of entries) {\n if (entry.target === parent) {\n setContainer({ w: entry.contentRect.width, h: entry.contentRect.height });\n } else {\n setSize(borderBoxOf(entry));\n }\n }\n });\n observer.observe(parent);\n observer.observe(el);\n return () => observer.disconnect();\n }, []);\n\n const rect = strategy\n .layout({\n items: [item],\n container,\n state: { at: { [ITEM_ID]: place }, inner: undefined },\n options,\n })\n .placements.get(ITEM_ID);\n\n const dragging = useRef<{ x: number; y: number } | null>(null);\n const session = useRef<PointerSession | null>(null);\n const [isDragging, setDragging] = useState(false);\n // A drag outlives the render that started it, so the reducer's inputs are\n // read here and not from that render's closure — a container resized\n // mid-drag would otherwise place the panel against its old box.\n const layout = useRef({ container, options, item });\n layout.current = { container, options, item };\n\n useEffect(() => () => session.current?.cancel(), []);\n\n const onPointerDown = (e: React.PointerEvent<HTMLDivElement>) => {\n if (isInteractive(e.target)) return;\n // The canvas stack underneath owns pan/zoom on the same pointer events.\n e.stopPropagation();\n const origin = e.currentTarget;\n const pointerId = e.pointerId;\n const start = { x: e.clientX, y: e.clientY };\n\n const end = () => {\n session.current = null;\n if (!dragging.current) return;\n dragging.current = null;\n setDragging(false);\n try {\n origin.releasePointerCapture?.(pointerId);\n } catch {\n // Capture is already gone whenever the session ended by losing it.\n }\n };\n\n // Armed, not capturing. Capture retargets mouseup to this element, and the\n // browser then synthesizes no `click` on the child under the cursor — so\n // capturing on press makes every non-native control in the panel dead to a\n // real mouse, silently. `isInteractive` only exempts the names it lists; a\n // `role=\"button\"` span, a react-aria control or a canvas is not among them.\n session.current = openPointerSession(\n origin,\n e,\n {\n onMove: (ev) => {\n if (!dragging.current) {\n if (Math.hypot(ev.clientX - start.x, ev.clientY - start.y) < DRAG_THRESHOLD) return;\n dragging.current = { ...start };\n setDragging(true);\n origin.setPointerCapture?.(pointerId);\n }\n const from = dragging.current;\n const dx = ev.clientX - from.x;\n const dy = ev.clientY - from.y;\n if (dx === 0 && dy === 0) return;\n dragging.current = { x: ev.clientX, y: ev.clientY };\n const { container: box, options: opts, item: only } = layout.current;\n setPlace(\n (prev) =>\n strategy.reduce?.(\n { at: { [ITEM_ID]: prev }, inner: undefined },\n {\n affordanceId: `${FLOATING_DRAG_PREFIX}${ITEM_ID}`,\n kind: 'drag',\n payload: { dx, dy },\n },\n { container: box, options: opts, items: [only] },\n ).at[ITEM_ID] ?? prev,\n );\n },\n onEnd: end,\n onCancel: end,\n },\n { capture: false },\n );\n };\n\n return (\n <div\n className={className ? `lk-floating-panel ${className}` : 'lk-floating-panel'}\n data-dragging={isDragging ? 'true' : undefined}\n data-placed={rect ? 'true' : undefined}\n onPointerDown={onPointerDown}\n ref={ref}\n style={\n {\n position: 'absolute',\n left: `${rect?.x ?? 0}px`,\n top: `${rect?.y ?? 0}px`,\n } as CSSProperties\n }\n >\n {children}\n </div>\n );\n}\n","import { ErrorIcon, WarningIcon } from '@weasel-js/ui';\nimport type { JobHandle } from '../job/types';\n\n/** Props for `<JobProgress>`. */\nexport interface JobProgressProps {\n job: JobHandle;\n className?: string;\n}\n\n/** A running job's progress, failures and outcome. Determinate once the job\n * reports a total; a job that cannot count up front never sends one, so the\n * bar stays indeterminate rather than inventing a denominator. */\nexport function JobProgress({ job, className }: JobProgressProps) {\n const { status, done, total, failures, error } = job;\n if (status === 'idle') return null;\n\n const determinate = total !== null && total > 0;\n const fraction = determinate ? Math.min(1, done / total) : 0;\n const cls = ['lk-job', `lk-job--${status}`, className].filter(Boolean).join(' ');\n\n return (\n <div className={cls}>\n <div\n className={`lk-job__track${determinate ? '' : ' lk-job__track--indeterminate'}`}\n role=\"progressbar\"\n aria-label=\"Job progress\"\n aria-valuenow={determinate ? done : undefined}\n aria-valuemin={determinate ? 0 : undefined}\n aria-valuemax={determinate ? total : undefined}\n >\n {/* Scaling a full-width bar keeps the fill off the layout path, so\n progress updates never reflow the status bar. */}\n <div\n className=\"lk-job__fill\"\n style={{ transform: `scaleX(${determinate ? fraction : 1})` }}\n />\n </div>\n\n <span className=\"lk-job__count\">\n {done}\n {determinate ? ` / ${total}` : ''}\n </span>\n\n {failures.length > 0 && (\n <span className=\"lk-job__failures\" title={failures.map((f) => f.error).join('\\n')}>\n <WarningIcon size={14} />\n {failures.length} failed\n </span>\n )}\n\n {error && (\n <span className=\"lk-job__error\" title={error}>\n <ErrorIcon size={14} />\n {error}\n </span>\n )}\n\n {status === 'running' && (\n <button type=\"button\" className=\"lk-job__cancel\" onClick={job.cancel}>\n Cancel\n </button>\n )}\n </div>\n );\n}\n","import type { CSSProperties } from 'react';\n\n/** How a legend entry's swatch is drawn, matching how the thing looks on canvas. */\nexport type LegendMark = 'line' | 'dash' | 'dot' | 'band';\n\n/** One row of a legend: a swatch and what it means. */\nexport interface LegendEntry {\n key: string;\n label: string;\n color: string;\n /** Defaults to `'line'`. */\n mark?: LegendMark;\n}\n\n/** Props for `<Legend>`. */\nexport interface LegendProps {\n entries: readonly LegendEntry[];\n className?: string;\n}\n\n/** A color key. Presentational only — no handlers, no state, no hover behavior. */\nexport function Legend({ entries, className }: LegendProps) {\n return (\n <ul className={className ? `lk-legend ${className}` : 'lk-legend'}>\n {entries.map((entry) => {\n const mark = entry.mark ?? 'line';\n return (\n <li className=\"lk-legend__row\" key={entry.key}>\n <span\n aria-hidden=\"true\"\n className={`lk-legend__swatch lk-legend__swatch--${mark}`}\n style={{ '--lk-legend-ink': entry.color } as CSSProperties}\n />\n <span className=\"lk-legend__label\">{entry.label}</span>\n </li>\n );\n })}\n </ul>\n );\n}\n","import type { ReactNode } from 'react';\n\n/** Props for `<Sidebar>`. */\nexport interface SidebarProps {\n children: ReactNode;\n title?: string;\n collapsed?: boolean;\n onToggle?: () => void;\n}\n\n/** A collapsible side panel with an optional title. Collapse state is the\n * caller's to hold. */\nexport function Sidebar({ children, title, collapsed = false, onToggle }: SidebarProps) {\n const className = `lk-sidebar${collapsed ? ' lk-sidebar--collapsed' : ''}`;\n return (\n <aside className={className}>\n {(title || onToggle) && (\n <div className=\"lk-sidebar-header\">\n {title && <span className=\"lk-sidebar-title\">{title}</span>}\n {onToggle && (\n <button\n type=\"button\"\n className=\"lk-sidebar-toggle\"\n onClick={onToggle}\n aria-label={collapsed ? 'Expand sidebar' : 'Collapse sidebar'}\n >\n {collapsed ? '›' : '‹'}\n </button>\n )}\n </div>\n )}\n <div className=\"lk-sidebar-body\">{children}</div>\n </aside>\n );\n}\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Toolbar, ZoomControl, ScaleIndicator, FpsMeter, useRovingTabIndex, StatusBar } from './chunk-
|
|
2
|
-
import { ControlPanel } from './chunk-
|
|
3
|
-
import { b,
|
|
4
|
-
import { SelectIcon, PencilIcon, LineIcon, ArrowIcon, RectIcon, EllipseIcon, TextIcon } from './chunk-
|
|
1
|
+
import { Toolbar, ZoomControl, ScaleIndicator, FpsMeter, useRovingTabIndex, StatusBar } from './chunk-MSR7EVS6.js';
|
|
2
|
+
import { ControlPanel } from './chunk-53AZ2O2N.js';
|
|
3
|
+
import { b, h3, u, A, j, U, M, x, N, p, _, v, P, y, n4, o3 } from './chunk-J6SBFZYT.js';
|
|
4
|
+
import { SelectIcon, PencilIcon, LineIcon, ArrowIcon, RectIcon, EllipseIcon, TextIcon } from './chunk-DG2IFMLA.js';
|
|
5
5
|
import { createContext, useContext, useState, useId, useRef, useSyncExternalStore, useCallback } from 'react';
|
|
6
6
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
7
7
|
|
|
@@ -98,7 +98,7 @@ function ExportMenu() {
|
|
|
98
98
|
}
|
|
99
99
|
),
|
|
100
100
|
/* @__PURE__ */ jsx(
|
|
101
|
-
|
|
101
|
+
h3,
|
|
102
102
|
{
|
|
103
103
|
triggerRef: { current: anchor },
|
|
104
104
|
isOpen: open,
|
|
@@ -188,13 +188,13 @@ function MarkList({ meaning, config }) {
|
|
|
188
188
|
)
|
|
189
189
|
] }),
|
|
190
190
|
/* @__PURE__ */ jsx(
|
|
191
|
-
|
|
191
|
+
u,
|
|
192
192
|
{
|
|
193
193
|
className: "lk-mark-list__title",
|
|
194
194
|
"aria-label": `Title of ${a.kind} on ${a.target}`,
|
|
195
195
|
value: a.title ?? "",
|
|
196
196
|
placeholder: "Untitled",
|
|
197
|
-
onChange: (
|
|
197
|
+
onChange: (next) => marks.update(a.id, { title: next })
|
|
198
198
|
}
|
|
199
199
|
),
|
|
200
200
|
statuses.length > 0 ? (
|
|
@@ -253,7 +253,7 @@ function builtinContributions(instrument, ctx, controls) {
|
|
|
253
253
|
region: "toolbar",
|
|
254
254
|
group: "history",
|
|
255
255
|
item: {
|
|
256
|
-
icon:
|
|
256
|
+
icon: A,
|
|
257
257
|
label: "Undo",
|
|
258
258
|
shortcut: "Mod+Z",
|
|
259
259
|
disabled: !ctx.canUndo,
|
|
@@ -265,7 +265,7 @@ function builtinContributions(instrument, ctx, controls) {
|
|
|
265
265
|
region: "toolbar",
|
|
266
266
|
group: "history",
|
|
267
267
|
item: {
|
|
268
|
-
icon:
|
|
268
|
+
icon: j,
|
|
269
269
|
label: "Redo",
|
|
270
270
|
shortcut: "Mod+Shift+Z",
|
|
271
271
|
disabled: !ctx.canRedo,
|
|
@@ -291,7 +291,7 @@ function builtinContributions(instrument, ctx, controls) {
|
|
|
291
291
|
region: "toolbar",
|
|
292
292
|
group: "view",
|
|
293
293
|
item: {
|
|
294
|
-
icon:
|
|
294
|
+
icon: U,
|
|
295
295
|
label: "Loupe",
|
|
296
296
|
pressed: ctx.loupeOn,
|
|
297
297
|
onActivate: ctx.toggleLoupe
|
|
@@ -304,7 +304,7 @@ function builtinContributions(instrument, ctx, controls) {
|
|
|
304
304
|
region: "viewport",
|
|
305
305
|
group: "zoom",
|
|
306
306
|
item: {
|
|
307
|
-
icon:
|
|
307
|
+
icon: M,
|
|
308
308
|
label: "Zoom out",
|
|
309
309
|
onActivate: () => ctx.setZoom(zoom / ZOOM_STEP)
|
|
310
310
|
}
|
|
@@ -323,7 +323,7 @@ function builtinContributions(instrument, ctx, controls) {
|
|
|
323
323
|
id: "actual-size",
|
|
324
324
|
region: "viewport",
|
|
325
325
|
group: "zoom",
|
|
326
|
-
item: { icon:
|
|
326
|
+
item: { icon: N, label: "Actual size", onActivate: () => ctx.setZoom(1) }
|
|
327
327
|
});
|
|
328
328
|
out.push({
|
|
329
329
|
id: "zoom-control",
|
|
@@ -418,7 +418,7 @@ function builtinContributions(instrument, ctx, controls) {
|
|
|
418
418
|
region: "titlebar",
|
|
419
419
|
end: true,
|
|
420
420
|
item: {
|
|
421
|
-
icon:
|
|
421
|
+
icon: P,
|
|
422
422
|
label: "Save snapshot",
|
|
423
423
|
shortcut: "Mod+S",
|
|
424
424
|
onActivate: () => ctx.saveSnapshot()
|
|
@@ -665,5 +665,5 @@ function ViewportRegion({ contributions, ctx }) {
|
|
|
665
665
|
}
|
|
666
666
|
|
|
667
667
|
export { ANNOTATION_TOOLS, ANNOTATION_WEASEL_TOOLS, AnnotationsContext, ExportMenu, MarkList, PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, ViewportRegion, annotationToolInfo, builtinContributions, mergeContributions, suppressContributions, useAnnotations, useAnnotationsOptional };
|
|
668
|
-
//# sourceMappingURL=chunk-
|
|
669
|
-
//# sourceMappingURL=chunk-
|
|
668
|
+
//# sourceMappingURL=chunk-BMQWLKOL.js.map
|
|
669
|
+
//# sourceMappingURL=chunk-BMQWLKOL.js.map
|