@weasel-js/labkit 1.4.2 → 1.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -2
- package/dist/_dts/{CanvasStackContext-kjILVnPj.d.ts → CanvasStackContext-Dde8_1my.d.ts} +1 -1
- package/dist/_dts/{PrefsForm.d-CgxUequc.d.ts → PrefsForm.d-DDHFANkc.d.ts} +1 -1
- package/dist/_dts/{frac-A4R6v4ld.d.ts → frac-B5mB8LsJ.d.ts} +7 -4
- package/dist/_dts/{index-CsU9WhjM.d.ts → index-DelFfeV0.d.ts} +15 -7
- package/dist/_dts/types-B9_zrHmb.d.ts +166 -0
- package/dist/_dts/{types-BbXpvQa8.d.ts → types-BP2OCcpg.d.ts} +21 -3
- package/dist/_dts/types-x92Kfeme.d.ts +62 -0
- package/dist/_dts/{useTrialState-DKjqpv20.d.ts → useTrialState-D6Vb3T-g.d.ts} +7 -7
- package/dist/canvas/index.d.ts +9 -8
- package/dist/canvas/index.js +1 -2
- package/dist/chrome/index.d.ts +7 -6
- package/dist/chrome/index.js +5 -5
- package/dist/{chunk-UTOEDPNU.js → chunk-2RQPGOQF.js} +7 -6
- package/dist/chunk-2RQPGOQF.js.map +1 -0
- package/dist/{chunk-ULDW42CR.js → chunk-5TROQVQ2.js} +25 -21
- package/dist/chunk-5TROQVQ2.js.map +1 -0
- package/dist/{chunk-XKENZTNE.js → chunk-ASWKLRKJ.js} +65 -49
- package/dist/chunk-ASWKLRKJ.js.map +1 -0
- package/dist/{chunk-W2FJR5FF.js → chunk-C42T6DJT.js} +74 -76
- package/dist/chunk-C42T6DJT.js.map +1 -0
- package/dist/chunk-E44SU6XS.js +50 -0
- package/dist/chunk-E44SU6XS.js.map +1 -0
- package/dist/{chunk-WS6ZRV75.js → chunk-FQMJUVHJ.js} +3 -3
- package/dist/{chunk-WS6ZRV75.js.map → chunk-FQMJUVHJ.js.map} +1 -1
- package/dist/{chunk-FJG4PHTL.js → chunk-I6JCVE24.js} +3 -3
- package/dist/chunk-I6JCVE24.js.map +1 -0
- package/dist/{chunk-NSOVI3AZ.js → chunk-ISCOFAUO.js} +6 -6
- package/dist/{chunk-NSOVI3AZ.js.map → chunk-ISCOFAUO.js.map} +1 -1
- package/dist/chunk-MHAGC6VD.js +7320 -0
- package/dist/chunk-MHAGC6VD.js.map +1 -0
- package/dist/{chunk-UDXOYZEC.js → chunk-QAGAHJKZ.js} +4 -4
- package/dist/{chunk-UDXOYZEC.js.map → chunk-QAGAHJKZ.js.map} +1 -1
- package/dist/{chunk-TN7YSJVU.js → chunk-RS3HRQWU.js} +3 -3
- package/dist/{chunk-TN7YSJVU.js.map → chunk-RS3HRQWU.js.map} +1 -1
- package/dist/{chunk-D5KQ5OY6.js → chunk-TJ7QY3OC.js} +3 -3
- package/dist/{chunk-D5KQ5OY6.js.map → chunk-TJ7QY3OC.js.map} +1 -1
- package/dist/controls/index.d.ts +5 -4
- package/dist/controls/index.js +3 -3
- package/dist/dragdrop/index.d.ts +6 -5
- package/dist/dragdrop/index.js +1 -2
- package/dist/index.d.ts +90 -23
- package/dist/index.js +199 -117
- package/dist/index.js.map +1 -1
- package/dist/layers/index.d.ts +7 -6
- package/dist/layers/index.js +2 -3
- package/dist/loupe/index.d.ts +8 -7
- package/dist/loupe/index.js +1 -2
- package/dist/passthrough/weasel-canvas.d.ts +1 -3
- package/dist/passthrough/weasel-canvas.js +1 -1
- package/dist/passthrough/weasel-canvas.js.map +1 -1
- package/dist/passthrough/weasel-ui.d.ts +88 -20
- package/dist/passthrough/weasel-ui.js +1 -2
- package/dist/primitives/index.js +3 -4
- package/dist/state/index.d.ts +6 -3
- package/dist/state/index.js +3 -2
- package/dist/state/index.js.map +1 -1
- package/dist/styles.css +2 -2
- package/dist/surface/index.js +1 -2
- package/dist/ui/layers/index.js +1 -2
- package/dist/undo/index.d.ts +6 -6
- package/package.json +7 -7
- package/src/annotations/ExportMenu.test.tsx +16 -0
- package/src/annotations/ExportMenu.tsx +0 -5
- package/src/config/builder.test.ts +56 -2
- package/src/config/builder.ts +73 -13
- package/src/config/index.ts +16 -1
- package/src/config/path.test.ts +109 -0
- package/src/config/path.ts +76 -0
- package/src/config/resolve.test.ts +93 -2
- package/src/config/resolve.ts +72 -29
- package/src/config/types.ts +99 -9
- package/src/config/visible.ts +6 -4
- package/src/controls/ControlPanel.stories.tsx +38 -4
- package/src/controls/ControlPanel.test.tsx +114 -0
- package/src/controls/ControlPanel.tsx +99 -50
- package/src/index.ts +16 -1
- package/src/instrument/serializers.ts +36 -0
- package/src/instrument/types.ts +4 -2
- package/src/lab/Lab.test.tsx +29 -1
- package/src/lab/Lab.tsx +10 -1
- package/src/lab/LabShell.test.tsx +8 -0
- package/src/lab/LabShell.tsx +3 -1
- package/src/primitives/ZoomControl.less +6 -2
- package/src/primitives/ZoomControl.tsx +1 -0
- package/src/state/helpers.ts +1 -1
- package/src/state/store.test.ts +155 -1
- package/src/state/store.ts +30 -24
- package/src/state/types.ts +24 -3
- package/src/state/useTrialState.ts +1 -1
- package/src/trial/Trial.config.test.tsx +44 -0
- package/src/trial/Trial.tsx +3 -3
- package/src/trial/TrialChrome.tsx +10 -5
- package/src/trial/trialOps.ts +4 -8
- package/dist/_dts/types-lg4TSCb2.d.ts +0 -164
- package/dist/_dts/weasel-canvas-FJTFi3ZZ.d.ts +0 -5041
- package/dist/chunk-54ZWZ5FQ.js +0 -29997
- package/dist/chunk-54ZWZ5FQ.js.map +0 -1
- package/dist/chunk-FJG4PHTL.js.map +0 -1
- package/dist/chunk-ISSVF5PT.js +0 -7263
- package/dist/chunk-ISSVF5PT.js.map +0 -1
- package/dist/chunk-ULDW42CR.js.map +0 -1
- package/dist/chunk-UTOEDPNU.js.map +0 -1
- package/dist/chunk-W2FJR5FF.js.map +0 -1
- package/dist/chunk-XKENZTNE.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,35 +1,38 @@
|
|
|
1
1
|
import { createEventBus, pushSnapshot, redo, undo } from './chunk-RL2LOLNI.js';
|
|
2
2
|
export { clearUndo, createEventBus, emptyStack, pushSnapshot, redo, undo } from './chunk-RL2LOLNI.js';
|
|
3
|
-
import { useDragDrop, DragOverlay, Palette } from './chunk-
|
|
4
|
-
import { useSurfaceOptional, useSurfaceCanvas, useTileId, useTiledSurface, SurfaceContext, SurfaceCanvasContext } from './chunk-
|
|
5
|
-
export { SurfaceCanvasContext, SurfaceContext, composeRects, rectsEqual, toDeviceRect, useSurface, useSurfaceCanvas, useSurfaceOptional, useSurfaceTile, useTileId, useTiledSurface } from './chunk-
|
|
3
|
+
import { useDragDrop, DragOverlay, Palette } from './chunk-RS3HRQWU.js';
|
|
4
|
+
import { useSurfaceOptional, useSurfaceCanvas, useTileId, useTiledSurface, SurfaceContext, SurfaceCanvasContext } from './chunk-FQMJUVHJ.js';
|
|
5
|
+
export { SurfaceCanvasContext, SurfaceContext, composeRects, rectsEqual, toDeviceRect, useSurface, useSurfaceCanvas, useSurfaceOptional, useSurfaceTile, useTileId, useTiledSurface } from './chunk-FQMJUVHJ.js';
|
|
6
6
|
import { useJob } from './chunk-HXXTULDN.js';
|
|
7
7
|
export { useJob } from './chunk-HXXTULDN.js';
|
|
8
|
-
import { ANNOTATION_WEASEL_TOOLS, annotationToolInfo, suppressContributions, mergeContributions, builtinContributions, TitleBarRegion, ToolbarRegion, PaletteRegion, ViewportRegion, SidebarRegion, StatusRegion, AnnotationsContext } from './chunk-
|
|
9
|
-
export { ANNOTATION_TOOLS, ANNOTATION_WEASEL_TOOLS, AnnotationsContext, ExportMenu, MarkList, PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, ViewportRegion, annotationToolInfo, builtinContributions, mergeContributions, suppressContributions, useAnnotations, useAnnotationsOptional } from './chunk-
|
|
10
|
-
import { JobProgress } from './chunk-
|
|
11
|
-
export { FloatingPanel, JobProgress, Legend, Sidebar } from './chunk-
|
|
12
|
-
export { FpsMeter, ScaleIndicator, StatusBar, Toolbar, ZoomControl } from './chunk-
|
|
13
|
-
import { createLabStore, panelKey, noneAdapter } from './chunk-
|
|
14
|
-
export { CURRENT_DOCUMENT_VERSION, createMemoryAdapter, dockPanel, labDocumentKey, localStorageAdapter, noneAdapter, panelKey, quarantineKey, sessionStorageAdapter, undockPanel, urlHashAdapter, useTrialState } from './chunk-
|
|
8
|
+
import { ANNOTATION_WEASEL_TOOLS, annotationToolInfo, suppressContributions, mergeContributions, builtinContributions, TitleBarRegion, ToolbarRegion, PaletteRegion, ViewportRegion, SidebarRegion, StatusRegion, AnnotationsContext } from './chunk-C42T6DJT.js';
|
|
9
|
+
export { ANNOTATION_TOOLS, ANNOTATION_WEASEL_TOOLS, AnnotationsContext, ExportMenu, MarkList, PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, ViewportRegion, annotationToolInfo, builtinContributions, mergeContributions, suppressContributions, useAnnotations, useAnnotationsOptional } from './chunk-C42T6DJT.js';
|
|
10
|
+
import { JobProgress } from './chunk-QAGAHJKZ.js';
|
|
11
|
+
export { FloatingPanel, JobProgress, Legend, Sidebar } from './chunk-QAGAHJKZ.js';
|
|
12
|
+
export { FpsMeter, ScaleIndicator, StatusBar, Toolbar, ZoomControl } from './chunk-2RQPGOQF.js';
|
|
13
|
+
import { createLabStore, panelKey, noneAdapter } from './chunk-5TROQVQ2.js';
|
|
14
|
+
export { CURRENT_DOCUMENT_VERSION, createMemoryAdapter, dockPanel, labDocumentKey, localStorageAdapter, noneAdapter, panelKey, quarantineKey, sessionStorageAdapter, undockPanel, urlHashAdapter, useTrialState } from './chunk-5TROQVQ2.js';
|
|
15
15
|
import { LabStoreContext, TrialIdProvider } from './chunk-2YILQ7Y5.js';
|
|
16
16
|
export { LabStoreContext, LabStoreProvider, TrialIdContext, TrialIdProvider, useLabStore, useTrialId } from './chunk-2YILQ7Y5.js';
|
|
17
|
-
import { fromConfigFields } from './chunk-
|
|
18
|
-
export { ControlPanel, fromConfigFields, isLeafVisible } from './chunk-
|
|
19
|
-
import {
|
|
20
|
-
export {
|
|
21
|
-
import {
|
|
22
|
-
export {
|
|
17
|
+
import { fromConfigFields } from './chunk-ASWKLRKJ.js';
|
|
18
|
+
export { ControlPanel, fromConfigFields, isLeafVisible } from './chunk-ASWKLRKJ.js';
|
|
19
|
+
import { hasConfigPath, schemaNodeAtPath, withValueAtPath, fillConfigDefaults } from './chunk-E44SU6XS.js';
|
|
20
|
+
export { fillConfigDefaults, hasConfigPath, schemaNodeAtPath, valueAtPath, withValueAtPath } from './chunk-E44SU6XS.js';
|
|
21
|
+
import { CanvasStack } from './chunk-I6JCVE24.js';
|
|
22
|
+
export { CanvasStack, PITCH_LIMIT, clampPitch, orbitAfterDrag, orbitAfterWheel, useOrbit, usePanZoom, wrapYaw } from './chunk-I6JCVE24.js';
|
|
23
|
+
import { LayerList } from './chunk-ISCOFAUO.js';
|
|
24
|
+
export { LayerList } from './chunk-ISCOFAUO.js';
|
|
23
25
|
import './chunk-SBXNQW4G.js';
|
|
24
|
-
import { E, w, T, C,
|
|
25
|
-
export { M2 as CheckboxRow, j2 as ColorRow,
|
|
26
|
-
import { resolveLoupe, TrialLoupe } from './chunk-
|
|
27
|
-
export { CanvasLoupe, DomLoupe, LOUPE_DEFAULTS, LoupeBubble, TrialLoupe, drawCanvasLens, lensCamera, lensSourceRect, resolveLoupe, sampleStack, useLoupe } from './chunk-
|
|
26
|
+
import { E, w, T, C, g, r6 } from './chunk-MHAGC6VD.js';
|
|
27
|
+
export { M2 as CheckboxRow, j2 as ColorRow, y3 as CurveField, R as EffectCard, B as EffectCardList, c3 as LayerStack, P2 as NumberRow, V as PropertyGroup, T2 as PropertyList, w2 as PropertyPanel, D as PropertyRow, E2 as PropertySpan, F as SelectRow, k as SliderRow, L2 as Subpanel, N2 as TextRow, I as ToggleRow } from './chunk-MHAGC6VD.js';
|
|
28
|
+
import { resolveLoupe, TrialLoupe } from './chunk-TJ7QY3OC.js';
|
|
29
|
+
export { CanvasLoupe, DomLoupe, LOUPE_DEFAULTS, LoupeBubble, TrialLoupe, drawCanvasLens, lensCamera, lensSourceRect, resolveLoupe, sampleStack, useLoupe } from './chunk-TJ7QY3OC.js';
|
|
28
30
|
export { centerOn, zoomAt } from './chunk-CTRKTLYZ.js';
|
|
29
31
|
import { applyCamera } from './chunk-2AYGEN57.js';
|
|
30
32
|
export { DEFAULT_FRAME, applyCamera, resolveFrame, screenToWorld, worldToScreen } from './chunk-2AYGEN57.js';
|
|
31
33
|
export { CanvasStackContext } from './chunk-CQLQPQ4P.js';
|
|
32
|
-
import { textCommand, linePath, markerDrawCommands, ellipsePath, rectPath, createScene, asNodeId as asNodeId$1, WeaselProvider, SceneCanvas, sceneFromJSON, PathBuilder, renderSceneToPixels, useActiveToolContext, resolveStrokeWidth, getMarker, getPaintKind, boundsOfPath,
|
|
34
|
+
import { textCommand, linePath, markerDrawCommands, ellipsePath, rectPath, createScene, asNodeId as asNodeId$1, WeaselProvider, SceneCanvas, sceneFromJSON, PathBuilder, renderSceneToPixels, useActiveToolContext, resolveStrokeWidth, getMarker, getPaintKind, boundsOfPath, PATH_M, PATH_L, PATH_C, PATH_Q, PATH_Z, SCRIPT_METRICS } from '@weasel-js/core';
|
|
35
|
+
import { tileGeometry } from '@weasel-js/core/patterns-builtin';
|
|
33
36
|
import { createContext, useState, useRef, useEffect, useContext, useMemo, Children, useLayoutEffect, useCallback, useSyncExternalStore } from 'react';
|
|
34
37
|
import { createPortal } from 'react-dom';
|
|
35
38
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -37,7 +40,6 @@ import { useStore } from 'zustand/react';
|
|
|
37
40
|
import { asNodeId, Store, createNode, stripStrategy, floatingStrategy, gridStrategy } from 'windease';
|
|
38
41
|
import { Provider, StrategyRegistryProvider, Container, DragProvider, useDragHandle } from 'windease/react';
|
|
39
42
|
|
|
40
|
-
// ../svg/dist/index.js
|
|
41
43
|
var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
|
|
42
44
|
function multiply(a, b) {
|
|
43
45
|
return [
|
|
@@ -421,17 +423,18 @@ function paintAttrs(paint, name, registry, includeOpacity = true) {
|
|
|
421
423
|
return [`${name}="url(#${id})"`];
|
|
422
424
|
}
|
|
423
425
|
function coreStrokeAttrs(stroke, registry) {
|
|
424
|
-
|
|
426
|
+
const paint = stroke?.paint;
|
|
427
|
+
if (!stroke || !paint) return [];
|
|
425
428
|
const width = resolveStrokeWidth(stroke.width ?? 1, 1);
|
|
426
429
|
if (!(width > 0)) return [];
|
|
427
430
|
const attrs = [];
|
|
428
|
-
if ("color" in
|
|
429
|
-
attrs.push(`stroke="${
|
|
430
|
-
if (
|
|
431
|
-
attrs.push(`stroke-opacity="${trimNumber(
|
|
431
|
+
if ("color" in paint) {
|
|
432
|
+
attrs.push(`stroke="${paint.color}"`);
|
|
433
|
+
if (paint.opacity != null && paint.opacity !== 1) {
|
|
434
|
+
attrs.push(`stroke-opacity="${trimNumber(paint.opacity)}"`);
|
|
432
435
|
}
|
|
433
436
|
} else {
|
|
434
|
-
attrs.push(`stroke="url(#${registry.register(
|
|
437
|
+
attrs.push(`stroke="url(#${registry.register(paint)})"`);
|
|
435
438
|
}
|
|
436
439
|
attrs.push(`stroke-width="${trimNumber(width)}"`);
|
|
437
440
|
if (stroke.cap) attrs.push(`stroke-linecap="${stroke.cap}"`);
|
|
@@ -549,7 +552,9 @@ function textXml(node, registry, namespaces) {
|
|
|
549
552
|
}
|
|
550
553
|
const decoration = textDecorationValue(style?.underline, style?.strikethrough, style?.overline);
|
|
551
554
|
if (decoration) attrs.push(`text-decoration="${decoration}"`);
|
|
552
|
-
if (node.fill) {
|
|
555
|
+
if (node.fill === null) {
|
|
556
|
+
attrs.push('fill="none"');
|
|
557
|
+
} else if (node.fill) {
|
|
553
558
|
if ("color" in node.fill) {
|
|
554
559
|
attrs.push(`fill="${node.fill.color}"`);
|
|
555
560
|
if (node.fill.opacity != null && node.fill.opacity !== 1) {
|
|
@@ -631,8 +636,6 @@ function pathBounds(path) {
|
|
|
631
636
|
const b = boundsOfPath(path);
|
|
632
637
|
return { minX: b.x, minY: b.y, maxX: b.x + b.width, maxY: b.y + b.height };
|
|
633
638
|
}
|
|
634
|
-
|
|
635
|
-
// src/annotations/paint.ts
|
|
636
639
|
var MARK_COLOR = "#e5484d";
|
|
637
640
|
var MARK_WIDTH = 2;
|
|
638
641
|
var TEXT_SIZE = 14;
|
|
@@ -742,8 +745,6 @@ function resolveMarkStyle(data, opts) {
|
|
|
742
745
|
stale: isStale(data.seen, opts.config, opts.positionDependsOn ?? [])
|
|
743
746
|
};
|
|
744
747
|
}
|
|
745
|
-
|
|
746
|
-
// src/annotations/svgNodes.ts
|
|
747
748
|
var NO_PAINT = { kind: "none" };
|
|
748
749
|
function toSvgPaint(paint) {
|
|
749
750
|
if (!paint) return NO_PAINT;
|
|
@@ -799,7 +800,7 @@ function capturePlan(base, format) {
|
|
|
799
800
|
if (format === "svg") return "svg-document";
|
|
800
801
|
return base?.kind === "svg" ? "svg-document" : "raster-stack";
|
|
801
802
|
}
|
|
802
|
-
function nestBaseSvg(markup, w3,
|
|
803
|
+
function nestBaseSvg(markup, w3, h) {
|
|
803
804
|
const doc = new DOMParser().parseFromString(markup, "image/svg+xml");
|
|
804
805
|
const root = doc.documentElement;
|
|
805
806
|
if (doc.getElementsByTagName("parsererror").length > 0 || root.localName !== "svg") {
|
|
@@ -808,16 +809,16 @@ function nestBaseSvg(markup, w3, h2) {
|
|
|
808
809
|
root.setAttribute("x", "0");
|
|
809
810
|
root.setAttribute("y", "0");
|
|
810
811
|
root.setAttribute("width", String(w3));
|
|
811
|
-
root.setAttribute("height", String(
|
|
812
|
+
root.setAttribute("height", String(h));
|
|
812
813
|
return new XMLSerializer().serializeToString(root);
|
|
813
814
|
}
|
|
814
|
-
function embedRasterBase(base, w3,
|
|
815
|
+
function embedRasterBase(base, w3, h, onWarn) {
|
|
815
816
|
const href = base.kind === "canvas" ? base.canvas.toDataURL() : base.kind === "image" ? base.src : "";
|
|
816
817
|
if (base.kind === "image" && !href.startsWith("data:")) {
|
|
817
818
|
onWarn?.(`base image '${href}' is a reference, so this SVG is not self-contained`);
|
|
818
819
|
}
|
|
819
|
-
return serializeSvg([{ kind: "image", href, x: 0, y: 0, width: w3, height:
|
|
820
|
-
viewBox: { x: 0, y: 0, width: w3, height:
|
|
820
|
+
return serializeSvg([{ kind: "image", href, x: 0, y: 0, width: w3, height: h }], {
|
|
821
|
+
viewBox: { x: 0, y: 0, width: w3, height: h }
|
|
821
822
|
});
|
|
822
823
|
}
|
|
823
824
|
function markNodesOf(scene, draw) {
|
|
@@ -833,15 +834,15 @@ function markNodesOf(scene, draw) {
|
|
|
833
834
|
}
|
|
834
835
|
function composeCaptureSvg(args) {
|
|
835
836
|
const { base, scene, draw, scale, onWarn } = args;
|
|
836
|
-
const { w: w3, h
|
|
837
|
-
const baseXml = base === void 0 ? "" : base.kind === "svg" ? nestBaseSvg(base.markup, w3,
|
|
837
|
+
const { w: w3, h } = draw.content;
|
|
838
|
+
const baseXml = base === void 0 ? "" : base.kind === "svg" ? nestBaseSvg(base.markup, w3, h) : embedRasterBase(base, w3, h, onWarn);
|
|
838
839
|
const marksXml = serializeSvg(markNodesOf(scene, draw), {
|
|
839
|
-
viewBox: { x: 0, y: 0, width: w3, height:
|
|
840
|
+
viewBox: { x: 0, y: 0, width: w3, height: h },
|
|
840
841
|
onWarn
|
|
841
842
|
});
|
|
842
843
|
const outW = Math.max(1, Math.round(w3 * scale));
|
|
843
|
-
const outH = Math.max(1, Math.round(
|
|
844
|
-
return `<svg xmlns="${SVG_NS}" width="${outW}" height="${outH}" viewBox="0 0 ${w3} ${
|
|
844
|
+
const outH = Math.max(1, Math.round(h * scale));
|
|
845
|
+
return `<svg xmlns="${SVG_NS}" width="${outW}" height="${outH}" viewBox="0 0 ${w3} ${h}">${baseXml}${marksXml}</svg>`;
|
|
845
846
|
}
|
|
846
847
|
function context2d(width, height) {
|
|
847
848
|
const canvas = document.createElement("canvas");
|
|
@@ -1041,8 +1042,6 @@ function drop(stack, value) {
|
|
|
1041
1042
|
}
|
|
1042
1043
|
}
|
|
1043
1044
|
}
|
|
1044
|
-
|
|
1045
|
-
// src/annotations/store.ts
|
|
1046
1045
|
function createAnnotationScene() {
|
|
1047
1046
|
return createScene({ systemLayers: [{ id: "marks" }] });
|
|
1048
1047
|
}
|
|
@@ -1430,6 +1429,9 @@ function AnnotationTargets({
|
|
|
1430
1429
|
}
|
|
1431
1430
|
|
|
1432
1431
|
// src/config/builder.ts
|
|
1432
|
+
function isConfigBranch(entry) {
|
|
1433
|
+
return "children" in entry;
|
|
1434
|
+
}
|
|
1433
1435
|
var BaseNode = class {
|
|
1434
1436
|
constructor(defaultValue, annotations = {}, options = {}) {
|
|
1435
1437
|
this.annotations = annotations;
|
|
@@ -1469,9 +1471,10 @@ var BaseNode = class {
|
|
|
1469
1471
|
pair(pair) {
|
|
1470
1472
|
return this.ann({ pair });
|
|
1471
1473
|
}
|
|
1472
|
-
/** Render under a named section heading.
|
|
1473
|
-
section
|
|
1474
|
-
|
|
1474
|
+
/** Render under a named section heading. `collapsed` opens the section
|
|
1475
|
+
* folded — say it on any one of the section's leaves. */
|
|
1476
|
+
section(label, opts = {}) {
|
|
1477
|
+
return this.opt({ section: { label, ...opts } });
|
|
1475
1478
|
}
|
|
1476
1479
|
/** Show this row only while the predicate holds. Presentational — the value
|
|
1477
1480
|
* stays in config and the instrument still reads it. */
|
|
@@ -1555,6 +1558,45 @@ var CustomNode = class _CustomNode extends BaseNode {
|
|
|
1555
1558
|
return new _CustomNode(this.kind, this.default, annotations, options);
|
|
1556
1559
|
}
|
|
1557
1560
|
};
|
|
1561
|
+
var GroupNode = class _GroupNode {
|
|
1562
|
+
constructor(children, annotations = {}, options = {}) {
|
|
1563
|
+
this.children = children;
|
|
1564
|
+
this.annotations = annotations;
|
|
1565
|
+
this.options = options;
|
|
1566
|
+
}
|
|
1567
|
+
children;
|
|
1568
|
+
annotations;
|
|
1569
|
+
options;
|
|
1570
|
+
with(annotations, options) {
|
|
1571
|
+
return new _GroupNode(this.children, annotations, options);
|
|
1572
|
+
}
|
|
1573
|
+
/** Heading for the group's rows. Defaults to the key, title-cased. */
|
|
1574
|
+
label(name) {
|
|
1575
|
+
return this.with({ ...this.annotations, name }, this.options);
|
|
1576
|
+
}
|
|
1577
|
+
/** Longer help text. Carried on the resolved `PrefGroup`, where weasel-ui's
|
|
1578
|
+
* `PrefsForm` draws it under the heading; `ControlPanel` has no place for
|
|
1579
|
+
* it yet and shows the heading alone. */
|
|
1580
|
+
describe(description) {
|
|
1581
|
+
return this.with({ ...this.annotations, description }, this.options);
|
|
1582
|
+
}
|
|
1583
|
+
/** Render this whole group under a named section heading. */
|
|
1584
|
+
section(label, opts = {}) {
|
|
1585
|
+
return this.with(this.annotations, { ...this.options, section: { label, ...opts } });
|
|
1586
|
+
}
|
|
1587
|
+
/** Show this group only while the predicate holds. Presentational — every
|
|
1588
|
+
* value beneath it stays in config and the instrument still reads it. */
|
|
1589
|
+
showIf(predicate) {
|
|
1590
|
+
return this.with(this.annotations, { ...this.options, showIf: predicate });
|
|
1591
|
+
}
|
|
1592
|
+
};
|
|
1593
|
+
function shapeDefaults(shape) {
|
|
1594
|
+
const out = {};
|
|
1595
|
+
for (const [key, entry] of Object.entries(shape)) {
|
|
1596
|
+
out[key] = isConfigBranch(entry) ? shapeDefaults(entry.children) : entry.default;
|
|
1597
|
+
}
|
|
1598
|
+
return out;
|
|
1599
|
+
}
|
|
1558
1600
|
var expand = (options) => options.map((o) => typeof o === "string" ? { value: o, label: o } : o);
|
|
1559
1601
|
var f = {
|
|
1560
1602
|
number: (def) => new NumberNode(def),
|
|
@@ -1568,18 +1610,15 @@ var f = {
|
|
|
1568
1610
|
/** A leaf with no declared kind: the rule chain decides, which is how a lab
|
|
1569
1611
|
* states a convention like "every `*Color` key is a color picker". */
|
|
1570
1612
|
value: (def) => new ValueNode(def),
|
|
1613
|
+
/** A branch: its children nest under this key, so `grid: f.group({ size })`
|
|
1614
|
+
* puts the value at `config.grid.size` and addresses it as `'grid.size'`.
|
|
1615
|
+
* Groups nest as deeply as the schema wants. */
|
|
1616
|
+
group: (children) => new GroupNode(children),
|
|
1571
1617
|
/** A leaf of a kind a lab supplies the control for, through `controls`. */
|
|
1572
1618
|
custom: (kind, def, validate) => new CustomNode(kind, def, {}, validate ? { validate } : {}),
|
|
1573
|
-
/** Collect leaves into an instrument's config. */
|
|
1619
|
+
/** Collect leaves and groups into an instrument's config. */
|
|
1574
1620
|
schema(nodes) {
|
|
1575
|
-
return {
|
|
1576
|
-
nodes,
|
|
1577
|
-
defaults: () => {
|
|
1578
|
-
const out = {};
|
|
1579
|
-
for (const [key, node] of Object.entries(nodes)) out[key] = node.default;
|
|
1580
|
-
return out;
|
|
1581
|
-
}
|
|
1582
|
-
};
|
|
1621
|
+
return { nodes, defaults: () => shapeDefaults(nodes) };
|
|
1583
1622
|
}
|
|
1584
1623
|
};
|
|
1585
1624
|
|
|
@@ -1627,36 +1666,55 @@ function defined(annotations) {
|
|
|
1627
1666
|
return out;
|
|
1628
1667
|
}
|
|
1629
1668
|
function resolveConfigSchema(schema, rules = []) {
|
|
1669
|
+
const sink = {
|
|
1670
|
+
sections: [],
|
|
1671
|
+
showIf: /* @__PURE__ */ new Map(),
|
|
1672
|
+
renderers: {},
|
|
1673
|
+
chain: [...rules, ...builtinRules]
|
|
1674
|
+
};
|
|
1675
|
+
const group = resolveShape(schema.nodes, "", "", sink);
|
|
1676
|
+
return { group, sections: sink.sections, showIf: sink.showIf, renderers: sink.renderers };
|
|
1677
|
+
}
|
|
1678
|
+
function resolveShape(shape, at, name, sink) {
|
|
1630
1679
|
const children = {};
|
|
1631
|
-
const
|
|
1632
|
-
const
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
for (const [key, node] of Object.entries(schema.nodes)) {
|
|
1637
|
-
const seed = defined({
|
|
1638
|
-
...node.annotations,
|
|
1639
|
-
...node.kind === null ? {} : { kind: node.kind }
|
|
1640
|
-
});
|
|
1641
|
-
const patch = applyRules(seed, { key, path: key, default: node.default }, chain2);
|
|
1642
|
-
children[key] = { ...patch, default: node.default };
|
|
1643
|
-
const { section, showIf: predicate, render } = node.options;
|
|
1680
|
+
const sections = /* @__PURE__ */ new Map();
|
|
1681
|
+
for (const [key, entry] of Object.entries(shape)) {
|
|
1682
|
+
const path = at === "" ? key : `${at}.${key}`;
|
|
1683
|
+
children[key] = resolveEntry(entry, key, path, sink);
|
|
1684
|
+
const { section, showIf: predicate } = entry.options;
|
|
1644
1685
|
if (section !== void 0) {
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1686
|
+
let spec = sections.get(section.label);
|
|
1687
|
+
if (!spec) {
|
|
1688
|
+
spec = { at, label: section.label, paths: [] };
|
|
1689
|
+
sections.set(section.label, spec);
|
|
1690
|
+
sink.sections.push(spec);
|
|
1691
|
+
}
|
|
1692
|
+
spec.paths.push(path);
|
|
1693
|
+
if (section.collapsed !== void 0) {
|
|
1694
|
+
spec.collapsed = (spec.collapsed ?? false) || section.collapsed;
|
|
1648
1695
|
}
|
|
1649
|
-
sectionPaths.get(section)?.push(key);
|
|
1650
1696
|
}
|
|
1651
|
-
if (predicate) showIf.set(
|
|
1652
|
-
if (render) renderers[
|
|
1697
|
+
if (predicate) sink.showIf.set(path, predicate);
|
|
1698
|
+
if (!isConfigBranch(entry) && entry.options.render) sink.renderers[path] = entry.options.render;
|
|
1699
|
+
}
|
|
1700
|
+
return { name, children };
|
|
1701
|
+
}
|
|
1702
|
+
function resolveEntry(entry, key, path, sink) {
|
|
1703
|
+
if (isConfigBranch(entry)) {
|
|
1704
|
+
const group = resolveShape(
|
|
1705
|
+
entry.children,
|
|
1706
|
+
path,
|
|
1707
|
+
entry.annotations.name ?? titleCase(key),
|
|
1708
|
+
sink
|
|
1709
|
+
);
|
|
1710
|
+
return entry.annotations.description === void 0 ? group : { ...group, description: entry.annotations.description };
|
|
1653
1711
|
}
|
|
1654
|
-
const
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
})
|
|
1659
|
-
return {
|
|
1712
|
+
const seed = defined({
|
|
1713
|
+
...entry.annotations,
|
|
1714
|
+
...entry.kind === null ? {} : { kind: entry.kind }
|
|
1715
|
+
});
|
|
1716
|
+
const patch = applyRules(seed, { key, path, default: entry.default }, sink.chain);
|
|
1717
|
+
return { ...patch, default: entry.default };
|
|
1660
1718
|
}
|
|
1661
1719
|
var LabContext = createContext(null);
|
|
1662
1720
|
function useLabContext() {
|
|
@@ -2304,9 +2362,9 @@ function hexToRgba(hex, alpha) {
|
|
|
2304
2362
|
const body = m[1];
|
|
2305
2363
|
const full = body.length === 3 ? body.replace(/./g, (c2) => c2 + c2) : body;
|
|
2306
2364
|
const r2 = Number.parseInt(full.slice(0, 2), 16);
|
|
2307
|
-
const
|
|
2365
|
+
const g2 = Number.parseInt(full.slice(2, 4), 16);
|
|
2308
2366
|
const b = Number.parseInt(full.slice(4, 6), 16);
|
|
2309
|
-
return `rgba(${r2}, ${
|
|
2367
|
+
return `rgba(${r2}, ${g2}, ${b}, ${alpha})`;
|
|
2310
2368
|
}
|
|
2311
2369
|
var REF = /^\{([^}]+)\}$/;
|
|
2312
2370
|
function refTarget(value) {
|
|
@@ -2444,6 +2502,25 @@ function useThemeOptional() {
|
|
|
2444
2502
|
return useContext(ThemeContext);
|
|
2445
2503
|
}
|
|
2446
2504
|
|
|
2505
|
+
// src/instrument/serializers.ts
|
|
2506
|
+
function configDefaultsOf(instruments) {
|
|
2507
|
+
const out = {};
|
|
2508
|
+
for (const instrument of instruments) out[instrument.name] = () => instrument.defaultConfig();
|
|
2509
|
+
return out;
|
|
2510
|
+
}
|
|
2511
|
+
function serializersOf(instruments) {
|
|
2512
|
+
const out = {};
|
|
2513
|
+
for (const instrument of instruments) {
|
|
2514
|
+
const { name, serialize: serialize2, deserialize } = instrument;
|
|
2515
|
+
if (!serialize2 && !deserialize) continue;
|
|
2516
|
+
out[name] = {
|
|
2517
|
+
...serialize2 ? { serialize: (state) => serialize2(state) } : {},
|
|
2518
|
+
...deserialize ? { deserialize: (data, config) => deserialize(data, config) } : {}
|
|
2519
|
+
};
|
|
2520
|
+
}
|
|
2521
|
+
return out;
|
|
2522
|
+
}
|
|
2523
|
+
|
|
2447
2524
|
// ../theme/dist/index.js
|
|
2448
2525
|
var ALPHA_EXT = "com.weasel.alpha";
|
|
2449
2526
|
var isToken = (v) => typeof v === "object" && v !== null && "$value" in v;
|
|
@@ -2452,9 +2529,9 @@ function flattenTokens(doc) {
|
|
|
2452
2529
|
for (const [groupName, group] of Object.entries(doc)) {
|
|
2453
2530
|
if (groupName.startsWith("$")) continue;
|
|
2454
2531
|
if (typeof group !== "object" || group === null) continue;
|
|
2455
|
-
const
|
|
2456
|
-
const groupType =
|
|
2457
|
-
for (const [leaf, node] of Object.entries(
|
|
2532
|
+
const g2 = group;
|
|
2533
|
+
const groupType = g2.$type;
|
|
2534
|
+
for (const [leaf, node] of Object.entries(g2)) {
|
|
2458
2535
|
if (leaf.startsWith("$")) continue;
|
|
2459
2536
|
if (!isToken(node)) continue;
|
|
2460
2537
|
const type = node.$type ?? groupType;
|
|
@@ -2813,16 +2890,16 @@ function TrialChrome({
|
|
|
2813
2890
|
configSchema,
|
|
2814
2891
|
configFields: instrument.config ? [] : instrument.configSchema?.() ?? [],
|
|
2815
2892
|
config: record.config,
|
|
2816
|
-
setConfig: (
|
|
2893
|
+
setConfig: (path, value) => {
|
|
2817
2894
|
const prevConfig = record.config;
|
|
2818
|
-
if (process.env.NODE_ENV !== "production" && !(
|
|
2895
|
+
if (process.env.NODE_ENV !== "production" && !hasConfigPath(prevConfig, path) && schemaNodeAtPath(configSchema.group, path) === void 0) {
|
|
2819
2896
|
console.warn(
|
|
2820
|
-
`[labkit] setConfig: unknown
|
|
2897
|
+
`[labkit] setConfig: unknown path "${path}" for instrument "${record.instrumentName}"`
|
|
2821
2898
|
);
|
|
2822
2899
|
}
|
|
2823
|
-
updateTrialConfig(trialId,
|
|
2900
|
+
updateTrialConfig(trialId, path, value);
|
|
2824
2901
|
if (instrument.onConfigChange) {
|
|
2825
|
-
const nextConfig =
|
|
2902
|
+
const nextConfig = withValueAtPath(prevConfig, path, value);
|
|
2826
2903
|
const nextState = instrument.onConfigChange(nextConfig, prevConfig, record.state);
|
|
2827
2904
|
updateTrialState(trialId, nextState);
|
|
2828
2905
|
}
|
|
@@ -3086,11 +3163,11 @@ function TrialRuntime({ record, instrument, store, isLast, chrome, suppress }) {
|
|
|
3086
3163
|
updateTrialState(record.id, next);
|
|
3087
3164
|
bus.emit("state.change");
|
|
3088
3165
|
},
|
|
3089
|
-
setConfig: (
|
|
3090
|
-
const evt = `config.change:${
|
|
3166
|
+
setConfig: (path, value) => {
|
|
3167
|
+
const evt = `config.change:${path}`;
|
|
3091
3168
|
snapshotIfNeeded("config.change");
|
|
3092
3169
|
snapshotIfNeeded(evt);
|
|
3093
|
-
updateTrialConfig(record.id,
|
|
3170
|
+
updateTrialConfig(record.id, path, value);
|
|
3094
3171
|
bus.emit("config.change");
|
|
3095
3172
|
bus.emit(evt);
|
|
3096
3173
|
},
|
|
@@ -3335,12 +3412,7 @@ function initialView(instrument) {
|
|
|
3335
3412
|
return declared ? structuredClone(declared) : { ...DEFAULT_VIEW2, pan: { ...DEFAULT_VIEW2.pan } };
|
|
3336
3413
|
}
|
|
3337
3414
|
function seedConfig(defaults, seed) {
|
|
3338
|
-
|
|
3339
|
-
const out = { ...defaults };
|
|
3340
|
-
for (const [key, value] of Object.entries(seed)) {
|
|
3341
|
-
if (value !== void 0) out[key] = value;
|
|
3342
|
-
}
|
|
3343
|
-
return out;
|
|
3415
|
+
return seed ? fillConfigDefaults(seed, defaults) : defaults;
|
|
3344
3416
|
}
|
|
3345
3417
|
function addTrial(trials, instruments, instrumentName, options = {}) {
|
|
3346
3418
|
const instrument = findInstrument(instruments, instrumentName);
|
|
@@ -3427,7 +3499,7 @@ function LabHeader() {
|
|
|
3427
3499
|
// Held at null so the control stays an "add one" action rather than
|
|
3428
3500
|
// reading as the current instrument.
|
|
3429
3501
|
/* @__PURE__ */ jsx(
|
|
3430
|
-
|
|
3502
|
+
g,
|
|
3431
3503
|
{
|
|
3432
3504
|
className: "lk-lab-header__add-select",
|
|
3433
3505
|
"aria-label": "Add trial",
|
|
@@ -3441,7 +3513,7 @@ function LabHeader() {
|
|
|
3441
3513
|
)
|
|
3442
3514
|
),
|
|
3443
3515
|
/* @__PURE__ */ jsx(
|
|
3444
|
-
|
|
3516
|
+
r6,
|
|
3445
3517
|
{
|
|
3446
3518
|
className: "lk-lab-header__mode",
|
|
3447
3519
|
ariaLabel: "Color mode",
|
|
@@ -3494,14 +3566,18 @@ function useResolvedMode(mode) {
|
|
|
3494
3566
|
function LabShell({ title, children, header, footer, mode = "auto" }) {
|
|
3495
3567
|
const resolved = useResolvedMode(mode);
|
|
3496
3568
|
const outer = useThemeOptional();
|
|
3497
|
-
const shell =
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3569
|
+
const shell = (
|
|
3570
|
+
// Overlays portal here rather than to the themed wrapper above: `.lk-root`
|
|
3571
|
+
// carries the element defaults a lab's bare markup is styled by.
|
|
3572
|
+
/* @__PURE__ */ jsxs("div", { className: "lk-root lk-shell", "data-wzl-portal-host": "", children: [
|
|
3573
|
+
/* @__PURE__ */ jsxs("header", { className: "lk-shell-header", children: [
|
|
3574
|
+
/* @__PURE__ */ jsx("h1", { className: "lk-shell-title", children: title }),
|
|
3575
|
+
header && /* @__PURE__ */ jsx("div", { className: "lk-shell-header-actions", children: header })
|
|
3576
|
+
] }),
|
|
3577
|
+
/* @__PURE__ */ jsx("main", { className: "lk-shell-body", children }),
|
|
3578
|
+
footer && /* @__PURE__ */ jsx("footer", { className: "lk-shell-footer", children: footer })
|
|
3579
|
+
] })
|
|
3580
|
+
);
|
|
3505
3581
|
return outer ? shell : /* @__PURE__ */ jsx(ThemeProvider, { theme: interstellarTheme, mode: resolved, children: shell });
|
|
3506
3582
|
}
|
|
3507
3583
|
var ZONE_ID2 = asNodeId("lk-workspace");
|
|
@@ -3657,7 +3733,13 @@ function Workspace({
|
|
|
3657
3733
|
) : reorderable ? /* @__PURE__ */ jsx(DragProvider, { children: grid }) : grid }) });
|
|
3658
3734
|
}
|
|
3659
3735
|
function buildStore(instruments, defaultInstrument, storage, storageKey, initialMode) {
|
|
3660
|
-
const store = createLabStore({
|
|
3736
|
+
const store = createLabStore({
|
|
3737
|
+
storageKey,
|
|
3738
|
+
storage,
|
|
3739
|
+
initialMode,
|
|
3740
|
+
serializers: serializersOf(instruments),
|
|
3741
|
+
configDefaults: configDefaultsOf(instruments)
|
|
3742
|
+
});
|
|
3661
3743
|
if (store.getState().trials.length === 0) {
|
|
3662
3744
|
const seeded = addTrial([], instruments, defaultInstrument);
|
|
3663
3745
|
const record = seeded[0];
|
|
@@ -3730,11 +3812,11 @@ function Lab({
|
|
|
3730
3812
|
const c2 = ownCanvasRef.current;
|
|
3731
3813
|
if (!c2) return;
|
|
3732
3814
|
const w3 = Math.round(frame.size.width * frame.dpr);
|
|
3733
|
-
const
|
|
3734
|
-
if (bufferRef.current.w === w3 && bufferRef.current.h ===
|
|
3735
|
-
bufferRef.current = { w: w3, h
|
|
3815
|
+
const h = Math.round(frame.size.height * frame.dpr);
|
|
3816
|
+
if (bufferRef.current.w === w3 && bufferRef.current.h === h) return;
|
|
3817
|
+
bufferRef.current = { w: w3, h };
|
|
3736
3818
|
c2.width = w3;
|
|
3737
|
-
c2.height =
|
|
3819
|
+
c2.height = h;
|
|
3738
3820
|
c2.style.width = `${frame.size.width}px`;
|
|
3739
3821
|
c2.style.height = `${frame.size.height}px`;
|
|
3740
3822
|
surfaceRef.current?.invalidateAll();
|
|
@@ -3874,6 +3956,6 @@ function Lab({
|
|
|
3874
3956
|
) }) });
|
|
3875
3957
|
}
|
|
3876
3958
|
|
|
3877
|
-
export { AnnotationOverlay, AnnotationTargets, DEFAULT_VIEW, Lab, LabContext, LabPalette, LabShell, Trial, TrialBody, TrialChrome, Workspace, addTrial, annotationsFromJSON, applyRules, as2DView, builtinRules, capturePlan, captureTarget, cloneTrial, closeTrial, composeCaptureSvg, createAnnotationScene, createAnnotationStore, createMarkDrawOne, defineInstrument, f, fitView, fracContains, fracIntersects, fracToWorld, fromWeaselView, interstellarTheme, isStale, markCommands, markSvgNodes, reorderTrials, resetTrial, resolveConfigSchema, resolveMarkStyle, roundFrac, seenFrom, titleCase, toWeaselView, useConfigSchema, useLabContext, validateConfigSchema, worldToFrac };
|
|
3959
|
+
export { AnnotationOverlay, AnnotationTargets, DEFAULT_VIEW, Lab, LabContext, LabPalette, LabShell, Trial, TrialBody, TrialChrome, Workspace, addTrial, annotationsFromJSON, applyRules, as2DView, builtinRules, capturePlan, captureTarget, cloneTrial, closeTrial, composeCaptureSvg, createAnnotationScene, createAnnotationStore, createMarkDrawOne, defineInstrument, f, fitView, fracContains, fracIntersects, fracToWorld, fromWeaselView, interstellarTheme, isConfigBranch, isStale, markCommands, markSvgNodes, reorderTrials, resetTrial, resolveConfigSchema, resolveMarkStyle, roundFrac, seenFrom, titleCase, toWeaselView, useConfigSchema, useLabContext, validateConfigSchema, worldToFrac };
|
|
3878
3960
|
//# sourceMappingURL=index.js.map
|
|
3879
3961
|
//# sourceMappingURL=index.js.map
|