@weasel-js/labkit 1.5.2 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.md +3 -7
  2. package/dist/_dts/{CanvasStackContext-CMMo180l.d.ts → CanvasStackContext-DQgcH1ny.d.ts} +1 -1
  3. package/dist/_dts/LayerList.d-2c9yup5Y.d.ts +83 -0
  4. package/dist/_dts/{PrefsForm.d-DPy9I8It.d.ts → PrefsRow.d-DFpPIeIC.d.ts} +16 -1
  5. package/dist/_dts/{Select.d-ZTiwzYyT.d.ts → Select.d-BchGMC2Y.d.ts} +102 -11
  6. package/dist/_dts/{frac-B4hFJMiN.d.ts → frac-DTRq7Xpb.d.ts} +18 -10
  7. package/dist/_dts/inDialog-D5ZKGjiD.d.ts +23 -0
  8. package/dist/_dts/{index-DlKolEIZ.d.ts → index-B0--8PEM.d.ts} +2 -2
  9. package/dist/_dts/index-DINmCuLA.d.ts +453 -0
  10. package/dist/_dts/number.d-OeQYQoUO.d.ts +28 -0
  11. package/dist/_dts/{types-Db-3NNk1.d.ts → types-B7y8hX1D.d.ts} +2 -2
  12. package/dist/_dts/{usePanZoom-SSTZe410.d.ts → usePanZoom-Bq73pwFe.d.ts} +2 -2
  13. package/dist/_dts/{useTrialState-pnAE-UBD.d.ts → useTrialState-CP4jfuKl.d.ts} +1 -1
  14. package/dist/canvas/index.d.ts +6 -5
  15. package/dist/chrome/index.d.ts +5 -4
  16. package/dist/chrome/index.js +7 -7
  17. package/dist/chunk-2RVCB2PT.js +3 -0
  18. package/dist/chunk-2RVCB2PT.js.map +1 -0
  19. package/dist/{chunk-753Y6HE6.js → chunk-3FI7Y4R4.js} +4 -4
  20. package/dist/chunk-3FI7Y4R4.js.map +1 -0
  21. package/dist/{chunk-REOBGYMC.js → chunk-AWH3SRPW.js} +31 -5
  22. package/dist/chunk-AWH3SRPW.js.map +1 -0
  23. package/dist/{chunk-A2ACAGW6.js → chunk-BVL7Y574.js} +22 -5
  24. package/dist/chunk-BVL7Y574.js.map +1 -0
  25. package/dist/{chunk-CKUKF72R.js → chunk-H5VIV7MQ.js} +26 -22
  26. package/dist/chunk-H5VIV7MQ.js.map +1 -0
  27. package/dist/chunk-HFRE4QQV.js +400 -0
  28. package/dist/chunk-HFRE4QQV.js.map +1 -0
  29. package/dist/{chunk-LRI3MBGR.js → chunk-MOLIUNVH.js} +4 -4
  30. package/dist/{chunk-LRI3MBGR.js.map → chunk-MOLIUNVH.js.map} +1 -1
  31. package/dist/chunk-USO6TERP.js +90 -0
  32. package/dist/chunk-USO6TERP.js.map +1 -0
  33. package/dist/{chunk-EMXAIRUJ.js → chunk-VQ47KWD5.js} +3 -3
  34. package/dist/{chunk-EMXAIRUJ.js.map → chunk-VQ47KWD5.js.map} +1 -1
  35. package/dist/chunk-WUJXJC5O.js +14568 -0
  36. package/dist/chunk-WUJXJC5O.js.map +1 -0
  37. package/dist/{chunk-KJCUERQF.js → chunk-ZORVNOKX.js} +6 -25
  38. package/dist/chunk-ZORVNOKX.js.map +1 -0
  39. package/dist/config/index.d.ts +50 -7
  40. package/dist/config/index.js +5 -5
  41. package/dist/controls/index.d.ts +6 -3
  42. package/dist/controls/index.js +4 -4
  43. package/dist/dragdrop/index.d.ts +4 -3
  44. package/dist/index.d.ts +83 -102
  45. package/dist/index.js +430 -458
  46. package/dist/index.js.map +1 -1
  47. package/dist/layers/index.d.ts +6 -35
  48. package/dist/layers/index.js +2 -3
  49. package/dist/loupe/index.d.ts +6 -5
  50. package/dist/passthrough/weasel-ui.d.ts +407 -204
  51. package/dist/passthrough/weasel-ui.js +1 -1
  52. package/dist/primitives/index.d.ts +2 -13
  53. package/dist/primitives/index.js +4 -4
  54. package/dist/state/index.d.ts +6 -5
  55. package/dist/state/index.js +5 -5
  56. package/dist/styles.css +298 -174
  57. package/dist/undo/index.d.ts +4 -3
  58. package/package.json +9 -13
  59. package/src/annotations/frac.test.ts +7 -0
  60. package/src/annotations/paint.test.ts +21 -0
  61. package/src/annotations/paint.ts +12 -0
  62. package/src/annotations/store.test.ts +31 -0
  63. package/src/annotations/types.ts +3 -2
  64. package/src/canvas/Stage.test.tsx +18 -0
  65. package/src/chrome/regions/SidebarRegion.less +197 -0
  66. package/src/chrome/regions/SidebarRegion.test.tsx +20 -0
  67. package/src/chrome/regions/SidebarRegion.tsx +7 -2
  68. package/src/chrome/types.ts +5 -2
  69. package/src/config/autoConfig.ts +2 -2
  70. package/src/config/builder.ts +20 -1
  71. package/src/config/entry.test.ts +8 -0
  72. package/src/config/index.ts +2 -0
  73. package/src/config/rules.ts +2 -0
  74. package/src/config/sectionTree.test.ts +146 -0
  75. package/src/config/sectionTree.ts +124 -0
  76. package/src/controls/ControlPanel.less +4 -0
  77. package/src/controls/ControlPanel.stories.tsx +55 -2
  78. package/src/controls/ControlPanel.test.tsx +30 -3
  79. package/src/controls/ControlPanel.tsx +116 -337
  80. package/src/controls/inDialog.test.tsx +82 -0
  81. package/src/controls/inDialog.tsx +46 -0
  82. package/src/controls/index.ts +1 -0
  83. package/src/index.ts +11 -26
  84. package/src/instrument/types.ts +5 -2
  85. package/src/lab/Lab.nebula.test.tsx +31 -0
  86. package/src/lab/Lab.tsx +38 -15
  87. package/src/lab/LabBoundary.test.tsx +66 -0
  88. package/src/lab/LabBoundary.tsx +56 -0
  89. package/src/lab/LabHeader.tsx +4 -23
  90. package/src/lab/LabRoot.tsx +2 -3
  91. package/src/lab/LabShell.less +0 -1
  92. package/src/lab/LabShell.stories.tsx +15 -0
  93. package/src/lab/LabShell.test.tsx +18 -0
  94. package/src/lab/LabShell.tsx +14 -1
  95. package/src/lab/LabSwitcher.less +1 -1
  96. package/src/lab/LabSwitcher.test.tsx +41 -0
  97. package/src/lab/LabSwitcher.tsx +30 -8
  98. package/src/lab/index.ts +1 -0
  99. package/src/layers/AGENTS.md +18 -74
  100. package/src/layers/index.ts +4 -2
  101. package/src/passthrough/weasel-ui.ts +25 -10
  102. package/src/primitives/index.ts +0 -2
  103. package/src/specimen/Specimen.tsx +42 -56
  104. package/src/state/types.ts +2 -1
  105. package/src/styles.less +4 -2
  106. package/src/theme/Interstellar.stories.tsx +8 -9
  107. package/src/theme/base.less +3 -20
  108. package/src/theme/interstellar.test.ts +6 -3
  109. package/src/theme/interstellar.theme.json +0 -56
  110. package/src/theme/interstellar.ts +2 -2
  111. package/src/trial/Trial.canvas.test.tsx +1 -1
  112. package/src/trial/Trial.tsx +30 -8
  113. package/dist/_dts/index-8LiKe3A-.d.ts +0 -410
  114. package/dist/chunk-6BUQ77ZV.js +0 -18
  115. package/dist/chunk-6BUQ77ZV.js.map +0 -1
  116. package/dist/chunk-753Y6HE6.js.map +0 -1
  117. package/dist/chunk-A2ACAGW6.js.map +0 -1
  118. package/dist/chunk-CKUKF72R.js.map +0 -1
  119. package/dist/chunk-D35PFTS7.js +0 -170
  120. package/dist/chunk-D35PFTS7.js.map +0 -1
  121. package/dist/chunk-FKLT3ITC.js +0 -590
  122. package/dist/chunk-FKLT3ITC.js.map +0 -1
  123. package/dist/chunk-KJCUERQF.js.map +0 -1
  124. package/dist/chunk-LASCBWW7.js +0 -13456
  125. package/dist/chunk-LASCBWW7.js.map +0 -1
  126. package/dist/chunk-REOBGYMC.js.map +0 -1
  127. package/dist/ui/layers/index.d.ts +0 -66
  128. package/dist/ui/layers/index.js +0 -3
  129. package/dist/ui/layers/index.js.map +0 -1
  130. package/src/lab/useSystemMode.ts +0 -30
  131. package/src/layers/LayerList.less +0 -93
  132. package/src/layers/LayerList.stories.tsx +0 -66
  133. package/src/layers/LayerList.test.tsx +0 -232
  134. package/src/layers/LayerList.tsx +0 -268
  135. package/src/primitives/Sidebar.less +0 -112
  136. package/src/primitives/Sidebar.stories.tsx +0 -38
  137. package/src/primitives/Sidebar.test.tsx +0 -74
  138. package/src/primitives/Sidebar.tsx +0 -35
  139. package/src/ui/layers/index.ts +0 -5
@@ -1,5 +1,5 @@
1
1
  import { usePersistedState } from './chunk-RWNDDKOH.js';
2
- import { ue, de } from './chunk-LASCBWW7.js';
2
+ import { We, Ge } from './chunk-WUJXJC5O.js';
3
3
  import { openPointerSession } from '@weasel-js/core';
4
4
  import { useRef, useMemo, useState, useEffect } from 'react';
5
5
  import { asNodeId, floatingStrategy, DEFAULT_INSET, DEFAULT_ANCHOR, Store, createNode, stripStrategy, FLOATING_DRAG_PREFIX } from 'windease';
@@ -170,12 +170,12 @@ function JobProgress({ job, className }) {
170
170
  determinate ? ` / ${total}` : ""
171
171
  ] }),
172
172
  failures.length > 0 && /* @__PURE__ */ jsxs("span", { className: "lk-job__failures", title: failures.map((f) => f.error).join("\n"), children: [
173
- /* @__PURE__ */ jsx(ue, { size: 14 }),
173
+ /* @__PURE__ */ jsx(We, { size: 14 }),
174
174
  failures.length,
175
175
  " failed"
176
176
  ] }),
177
177
  error && /* @__PURE__ */ jsxs("span", { className: "lk-job__error", title: error, children: [
178
- /* @__PURE__ */ jsx(de, { size: 14 }),
178
+ /* @__PURE__ */ jsx(Ge, { size: 14 }),
179
179
  error
180
180
  ] }),
181
181
  status === "running" && /* @__PURE__ */ jsx("button", { type: "button", className: "lk-job__cancel", onClick: job.cancel, children: "Cancel" })
@@ -197,25 +197,6 @@ function Legend({ entries, className }) {
197
197
  ] }, entry.key);
198
198
  }) });
199
199
  }
200
- function Sidebar({ children, title, collapsed = false, onToggle }) {
201
- const className = `lk-sidebar${collapsed ? " lk-sidebar--collapsed" : ""}`;
202
- return /* @__PURE__ */ jsxs("aside", { className, children: [
203
- (title || onToggle) && /* @__PURE__ */ jsxs("div", { className: "lk-sidebar-header", children: [
204
- title && /* @__PURE__ */ jsx("span", { className: "lk-sidebar-title", children: title }),
205
- onToggle && /* @__PURE__ */ jsx(
206
- "button",
207
- {
208
- type: "button",
209
- className: "lk-sidebar-toggle",
210
- onClick: onToggle,
211
- "aria-label": collapsed ? "Expand sidebar" : "Collapse sidebar",
212
- children: collapsed ? "\u203A" : "\u2039"
213
- }
214
- )
215
- ] }),
216
- /* @__PURE__ */ jsx("div", { className: "lk-sidebar-body", children })
217
- ] });
218
- }
219
200
  var ZONE_ID = asNodeId("lk-split");
220
201
  var SIDEBAR_ID = asNodeId("lk-split-sidebar");
221
202
  var CONTENT_ID = asNodeId("lk-split-content");
@@ -327,6 +308,6 @@ function Split({
327
308
  ) }) });
328
309
  }
329
310
 
330
- export { FloatingPanel, JobProgress, Legend, Sidebar, Split };
331
- //# sourceMappingURL=chunk-KJCUERQF.js.map
332
- //# sourceMappingURL=chunk-KJCUERQF.js.map
311
+ export { FloatingPanel, JobProgress, Legend, Split };
312
+ //# sourceMappingURL=chunk-ZORVNOKX.js.map
313
+ //# sourceMappingURL=chunk-ZORVNOKX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/primitives/FloatingPanel.tsx","../src/primitives/JobProgress.tsx","../src/primitives/Legend.tsx","../src/primitives/Split.tsx"],"names":["jsx","jsxs","useRef","store","useEffect","useMemo"],"mappings":"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","file":"chunk-ZORVNOKX.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';\nimport { usePersistedState } from '../state/usePersistedState';\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 /** Name to remember its position under, through `usePersistedState` — so it\n * is remembered only inside a lab or a `<Persistence>`. Omit to forget on\n * reload. */\n persist?: 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\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 persist,\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] = usePersistedState<FloatingPlacement>(persist, () => ({\n x: 0,\n y: 0,\n anchor,\n }));\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, useEffect, useMemo, useRef } from 'react';\nimport { asNodeId, createNode, Store, stripStrategy } from 'windease';\nimport { type ChromeMap, Container, Provider, StrategyRegistryProvider } from 'windease/react';\n\nconst ZONE_ID = asNodeId('lk-split');\nconst SIDEBAR_ID = asNodeId('lk-split-sidebar');\nconst CONTENT_ID = asNodeId('lk-split-content');\nconst STRATEGIES = { strip: stripStrategy as never };\n\n/** Props for `<Split>`. */\nexport interface SplitProps {\n /** The sidebar pane's contents. */\n sidebar: ReactNode;\n /** The edge the sidebar sits on. Read once, when the strip mounts. Default `'start'`. */\n side?: 'start' | 'end';\n /** The content pane's contents. */\n children: ReactNode;\n /** Names the sidebar pane, and through it the seam. Default `'Sidebar'`. */\n label?: string;\n /** Extra classes on the strip, which always has `lk-split`. */\n className?: string;\n /** The class on the sidebar pane. */\n sidebarClassName?: string;\n /** The class on the content pane. */\n contentClassName?: string;\n /** The sidebar's current extent in pixels. Omit to leave it unpersisted: the\n * seam still works, its result just does not outlive the mount. */\n width?: number;\n /** Where the sidebar starts before anyone drags it. */\n defaultWidth?: number;\n minWidth?: number;\n maxWidth?: number;\n /** How little the content pane may be squeezed to. Reported as the seam's\n * reachable maximum, so the drag stops there rather than clamping silently. */\n contentMinWidth?: number;\n /** Fires through the drag, not on release: the pane is already there. */\n onWidthChange?: (width: number) => void;\n /**\n * Fixed extent. Omit in an app — the strip measures its own box. Supply it\n * where nothing measures, notably jsdom, or both panes lay out at zero.\n */\n viewport?: { w: number; h: number };\n}\n\n/**\n * A sidebar and a content pane as a two-pane strip with a draggable seam.\n *\n * The seam is `stripStrategy`'s own resize affordance, so it arrives as a\n * `role=\"separator\"` carrying the reachable range, operable by pointer and by\n * arrows / Home / End, and clamped against the content pane's floor rather\n * than against the sidebar's alone.\n */\nexport function Split({\n sidebar,\n children,\n side = 'start',\n label = 'Sidebar',\n className,\n sidebarClassName,\n contentClassName,\n width,\n defaultWidth = 320,\n minWidth = 140,\n maxWidth = 720,\n contentMinWidth = 160,\n onWidthChange,\n viewport,\n}: SplitProps) {\n // The cross-axis half of every size hint below is inert: a horizontal strip\n // stretches its panes to the container's height and never reads `h`.\n const storeRef = useRef<Store | null>(null);\n if (storeRef.current === null) {\n const store = new Store();\n store.registerNode(\n createNode({\n kind: 'zone',\n id: ZONE_ID,\n // A strip's seam resizes the pane before it, which on the end side is the\n // content; 'neighbor' has the seam size the sidebar after it too.\n container: {\n strategyId: 'strip',\n config: {\n axis: 'x',\n resizable: true,\n ...(side === 'end' ? { resizeMode: 'neighbor' } : {}),\n },\n },\n }),\n );\n const sidebarNode = createNode({\n kind: 'sidebar',\n id: SIDEBAR_ID,\n parentId: ZONE_ID,\n meta: { title: label },\n placement: { size: { w: width ?? defaultWidth } },\n hints: { minSize: { w: minWidth, h: 0 }, maxSize: { w: maxWidth, h: 0 } },\n });\n const contentNode = createNode({\n kind: 'content',\n id: CONTENT_ID,\n parentId: ZONE_ID,\n meta: { title: 'Content' },\n hints: { minSize: { w: contentMinWidth, h: 0 } },\n });\n // A strip lays its children out in registration order.\n for (const node of side === 'end' ? [contentNode, sidebarNode] : [sidebarNode, contentNode]) {\n store.registerNode(node);\n }\n store.showNode(SIDEBAR_ID);\n store.showNode(CONTENT_ID);\n storeRef.current = store;\n }\n const store = storeRef.current;\n\n // What the store last held, so the placement event can tell a drag from the\n // echo of our own write and a controlled `width` does not fight the seam.\n const widthRef = useRef(width ?? defaultWidth);\n\n useEffect(() => {\n store.setHints(SIDEBAR_ID, {\n minSize: { w: minWidth, h: 0 },\n maxSize: { w: maxWidth, h: 0 },\n });\n store.setHints(CONTENT_ID, { minSize: { w: contentMinWidth, h: 0 } });\n }, [store, minWidth, maxWidth, contentMinWidth]);\n\n useEffect(() => {\n store.setMeta(SIDEBAR_ID, { title: label });\n }, [store, label]);\n\n useEffect(() => {\n if (width === undefined || width === widthRef.current) return;\n widthRef.current = width;\n store.patchPlacement(SIDEBAR_ID, { size: { w: width } });\n }, [store, width]);\n\n const onWidthChangeRef = useRef(onWidthChange);\n onWidthChangeRef.current = onWidthChange;\n useEffect(\n () =>\n store.events.on('node.placementChanged', () => {\n // A neighbor drag pins the content's width too; unpinned, it goes on filling the strip.\n if ((store.getPlacement(CONTENT_ID)?.size as { w?: number } | undefined)?.w !== undefined) {\n store.patchPlacement(CONTENT_ID, { size: {} });\n }\n const next = (store.getPlacement(SIDEBAR_ID)?.size as { w?: number } | undefined)?.w;\n if (typeof next !== 'number' || next === widthRef.current) return;\n widthRef.current = next;\n onWidthChangeRef.current?.(next);\n }),\n [store],\n );\n\n const chrome = useMemo<ChromeMap>(\n () => ({\n sidebar: () => <div className={sidebarClassName}>{sidebar}</div>,\n content: () => <div className={contentClassName}>{children}</div>,\n }),\n [sidebar, children, sidebarClassName, contentClassName],\n );\n\n return (\n <Provider store={store}>\n <StrategyRegistryProvider strategies={STRATEGIES}>\n <Container\n parentId={ZONE_ID}\n chrome={chrome}\n className={className ? `lk-split windease-zone ${className}` : 'lk-split windease-zone'}\n affordances\n viewport={viewport}\n />\n </StrategyRegistryProvider>\n </Provider>\n );\n}\n"]}
@@ -1,11 +1,13 @@
1
- import { a0 as Auto, K as Instrument } from '../_dts/frac-B4hFJMiN.js';
2
- export { ax as auto, aD as isAuto } from '../_dts/frac-B4hFJMiN.js';
3
- import { R as ResolvedConfig, l as ConfigNode, A as Annotations, N as NodeOptions, v as SectionOption, d as ControlRenderer, n as ConfigOption, p as ConfigShape, h as ConfigBranch, B as BranchAnnotations, e as BranchOptions, b as ConfigSchema, I as InferConfig, i as ConfigEntry, a as ConfigField, c as ConfigRule, L as LeafPatch, o as ConfigRuleContext } from '../_dts/types-Db-3NNk1.js';
4
- export { m as ConfigOf, C as ConfigPath, E as EntryValue, q as NodeValue, S as SectionSpec, V as ValueAtPath } from '../_dts/types-Db-3NNk1.js';
1
+ import { a2 as Auto, O as Instrument } from '../_dts/frac-DTRq7Xpb.js';
2
+ export { ax as auto, aD as isAuto } from '../_dts/frac-DTRq7Xpb.js';
3
+ import { R as ResolvedConfig, l as ConfigNode, A as Annotations, N as NodeOptions, v as SectionOption, C as ControlRenderer, n as ConfigOption, p as ConfigShape, h as ConfigBranch, B as BranchAnnotations, e as BranchOptions, c as ConfigSchema, I as InferConfig, i as ConfigEntry, b as ConfigField, d as ConfigRule, L as LeafPatch, o as ConfigRuleContext } from '../_dts/types-B7y8hX1D.js';
4
+ export { m as ConfigOf, a as ConfigPath, E as EntryValue, q as NodeValue, S as SectionSpec, V as ValueAtPath } from '../_dts/types-B7y8hX1D.js';
5
5
  import { ToolPrefNumberFormat, ToolPrefNumberUnit, ToolPrefLeaf, ToolPrefGroup } from '@weasel-js/core';
6
+ import { I as InDialogOptions } from '../_dts/inDialog-D5ZKGjiD.js';
6
7
  import 'react';
8
+ import '../_dts/PrefsRow.d-DFpPIeIC.js';
9
+ import '@weasel-js/theme';
7
10
  import '../_dts/types-DJ79Tg5J.js';
8
- import '../_dts/PrefsForm.d-DPy9I8It.js';
9
11
 
10
12
  /** The dotted paths a schema declares as starting auto — every leaf that said
11
13
  * `.initial(auto)`. This is what seeds a new trial's unpinned set. */
@@ -52,6 +54,9 @@ declare abstract class BaseNode<T> implements ConfigNode<T> {
52
54
  showIf(predicate: (config: Record<string, unknown>) => boolean): this;
53
55
  /** Draw this one row yourself, keeping the kind, default and validation. */
54
56
  render(renderer: ControlRenderer): this;
57
+ /** Draw this row as a button that opens a dialog, with `body` as the
58
+ * dialog's content — for an editor too big for the row. */
59
+ dialog(body: ControlRenderer, opts?: InDialogOptions): this;
55
60
  /**
56
61
  * Compute this leaf's value while it is auto, instead of leaving it
57
62
  * `undefined`. The resolver is given the config with every other auto path
@@ -75,7 +80,7 @@ declare class NumberNode extends BaseNode<number> {
75
80
  /** A display suffix for the value — `'px'`, `'ms'`, `'°'`. Presentation only:
76
81
  * it is never parsed, and the stored value stays a plain number. */
77
82
  suffix(suffix: string): this;
78
- /** Show the value in a named format — `'compact'` reads `2.0M`. Presentation
83
+ /** Show the value in a named format — `'compact'` reads `2.00M`. Presentation
79
84
  * only: the stored value stays a plain number, and a typed `2.5m` reads back. */
80
85
  format(format: ToolPrefNumberFormat): this;
81
86
  /**
@@ -102,6 +107,11 @@ declare class StringNode extends BaseNode<string> {
102
107
  /** Milliseconds to debounce live writes. 0 commits every keystroke. */
103
108
  debounce(debounceMs: number): this;
104
109
  }
110
+ declare class ListNode extends BaseNode<string[]> {
111
+ readonly kind = "list";
112
+ /** Shown in an empty entry. */
113
+ placeholder(placeholder: string): this;
114
+ }
105
115
  declare class ColorNode extends BaseNode<string> {
106
116
  readonly kind = "color";
107
117
  /** The value carries alpha as `#rrggbbaa`, and the row gets an opacity
@@ -166,6 +176,9 @@ declare const f: {
166
176
  boolean: (def: boolean) => BooleanNode;
167
177
  string: (def: string) => StringNode;
168
178
  color: (def: string) => ColorNode;
179
+ /** A list of strings. Its row summarizes the list, and opens a dialog to
180
+ * edit it one entry per field. */
181
+ list: (def: readonly string[]) => ListNode;
169
182
  /** A fixed set of choices. The default's literal type flows into the config
170
183
  * type, so `f.enum('fast', ['fast', 'accurate'])` gives
171
184
  * `'fast' | 'accurate'` with no `as const`. */
@@ -192,6 +205,35 @@ declare const f: {
192
205
  */
193
206
  declare function fromConfigFields(fields: readonly ConfigField[]): ResolvedConfig;
194
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
+ *
230
+ * A section naming a group brings that group in whole, so it lands as an
231
+ * indented rail item; a section naming a leaf drops it loose into the
232
+ * section's own pane. Sections nested under a group are left alone — they
233
+ * bucket rows inside a pane, which is the panel's job and not the rail's.
234
+ */
235
+ declare function sectionTree(resolved: ResolvedConfig, config: Record<string, unknown>, showHidden?: boolean): SectionTree;
236
+
195
237
  /** The value at a dotted path. `undefined` when a segment is missing or the
196
238
  * walk hits something that is not a record. */
197
239
  declare function valueAtPath(config: unknown, path: string): unknown;
@@ -272,4 +314,5 @@ declare function useResolvedConfig<TC>(schema: ResolvedConfig | undefined, confi
272
314
  */
273
315
  declare function isLeafVisible(resolved: ResolvedConfig, path: string, config: Record<string, unknown>, showHidden?: boolean): boolean;
274
316
 
275
- export { Annotations, Auto, BaseNode, BooleanNode, BranchAnnotations, BranchOptions, ColorNode, ConfigBranch, ConfigEntry, ConfigNode, ConfigOption, ConfigRule, ConfigRuleContext, ConfigSchema, ConfigShape, ControlRenderer, CustomNode, EnumNode, GroupNode, InferConfig, LeafPatch, NodeOptions, NumberNode, ResolvedConfig, StringNode, ValueNode, applyRules, autoPathsOf, builtinRules, f, fillConfigDefaults, fromConfigFields, hasConfigPath, isConfigBranch, isLeafVisible, resolveAutoConfig, resolveConfigSchema, schemaNodeAtPath, titleCase, useConfigSchema, useResolvedConfig, valueAtPath, withValueAtPath };
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 };
318
+ export type { SectionTree };
@@ -1,8 +1,8 @@
1
- export { useConfigSchema } from '../chunk-6BUQ77ZV.js';
1
+ export { sectionTree, useConfigSchema } from '../chunk-USO6TERP.js';
2
2
  import '../chunk-Z76KEZAX.js';
3
- export { BaseNode, BooleanNode, ColorNode, CustomNode, EnumNode, GroupNode, NumberNode, StringNode, ValueNode, applyRules, builtinRules, f, isConfigBranch, resolveConfigSchema, titleCase, useResolvedConfig } from '../chunk-A2ACAGW6.js';
4
- export { fromConfigFields, isLeafVisible } from '../chunk-EMXAIRUJ.js';
5
- export { auto, autoPathsOf, fillConfigDefaults, hasConfigPath, isAuto, resolveAutoConfig, schemaNodeAtPath, valueAtPath, withValueAtPath } from '../chunk-REOBGYMC.js';
6
- import '../chunk-LASCBWW7.js';
3
+ export { BaseNode, BooleanNode, ColorNode, CustomNode, EnumNode, GroupNode, ListNode, NumberNode, StringNode, ValueNode, applyRules, builtinRules, f, isConfigBranch, resolveConfigSchema, titleCase, useResolvedConfig } from '../chunk-BVL7Y574.js';
4
+ export { fromConfigFields, isLeafVisible } from '../chunk-VQ47KWD5.js';
5
+ export { auto, autoPathsOf, fillConfigDefaults, hasConfigPath, isAuto, resolveAutoConfig, schemaNodeAtPath, valueAtPath, withValueAtPath } from '../chunk-AWH3SRPW.js';
6
+ import '../chunk-WUJXJC5O.js';
7
7
  //# sourceMappingURL=index.js.map
8
8
  //# sourceMappingURL=index.js.map
@@ -1,6 +1,9 @@
1
- export { e as ControlPanel } from '../_dts/index-8LiKe3A-.js';
2
- export { f as CheckboxField, g as ColorField, a as ConfigField, k as ConfigFieldType, r as NumberField, s as SelectField, t as SelectOption, u as SliderField, T as TextField } from '../_dts/types-Db-3NNk1.js';
1
+ export { C as ControlPanel } from '../_dts/index-DINmCuLA.js';
2
+ export { I as InDialogOptions, i as inDialog, s as summarizeValue } from '../_dts/inDialog-D5ZKGjiD.js';
3
+ export { f as CheckboxField, g as ColorField, b as ConfigField, k as ConfigFieldType, r as NumberField, s as SelectField, t as SelectOption, u as SliderField, T as TextField } from '../_dts/types-B7y8hX1D.js';
3
4
  import 'react/jsx-runtime';
4
5
  import 'react';
6
+ import '../_dts/PrefsRow.d-DFpPIeIC.js';
7
+ import '@weasel-js/theme';
5
8
  import '@weasel-js/core';
6
- import '../_dts/PrefsForm.d-DPy9I8It.js';
9
+ import '../_dts/number.d-OeQYQoUO.js';
@@ -1,6 +1,6 @@
1
- export { ControlPanel } from '../chunk-FKLT3ITC.js';
2
- import '../chunk-EMXAIRUJ.js';
3
- import '../chunk-REOBGYMC.js';
4
- import '../chunk-LASCBWW7.js';
1
+ export { ControlPanel } from '../chunk-HFRE4QQV.js';
2
+ import '../chunk-VQ47KWD5.js';
3
+ export { inDialog, summarizeValue } from '../chunk-AWH3SRPW.js';
4
+ import '../chunk-WUJXJC5O.js';
5
5
  //# sourceMappingURL=index.js.map
6
6
  //# sourceMappingURL=index.js.map
@@ -1,9 +1,10 @@
1
- import { P as PaletteItem, l as Point, m as DragFeedback, n as DragDropCapability, k as ViewTransform, a as WorldSpec } from '../_dts/frac-B4hFJMiN.js';
1
+ import { P as PaletteItem, n as Point, o as DragFeedback, q as DragDropCapability, m as ViewTransform, b as WorldSpec } from '../_dts/frac-DTRq7Xpb.js';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  import { RefObject, PointerEvent, ReactPortal } from 'react';
4
- import '../_dts/types-Db-3NNk1.js';
4
+ import '../_dts/PrefsRow.d-DFpPIeIC.js';
5
+ import '@weasel-js/theme';
5
6
  import '@weasel-js/core';
6
- import '../_dts/PrefsForm.d-DPy9I8It.js';
7
+ import '../_dts/types-B7y8hX1D.js';
7
8
  import '../_dts/types-DJ79Tg5J.js';
8
9
 
9
10
  interface DragState {
package/dist/index.d.ts CHANGED
@@ -1,34 +1,35 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { I as IconProps } from './_dts/Select.d-ZTiwzYyT.js';
3
- export { B as Button, a as ButtonProps, b as ButtonSize, c as ButtonVariant, d as Icon, e as Input, f as InputProps, S as Select, g as SelectProps, T as ToggleBar, h as ToggleBarItem, i as ToggleBarProps, j as ToggleBarSize, k as ToggleBarVariant } from './_dts/Select.d-ZTiwzYyT.js';
4
- export { LayerStack, LayerStackItem, LayerStackProps } from './ui/layers/index.js';
2
+ import { I as IconProps } from './_dts/Select.d-BchGMC2Y.js';
3
+ export { B as Button, a as ButtonProps, b as ButtonSize, c as ButtonVariant, d as Icon, e as Input, f as InputProps, S as Select, g as SelectProps, T as ToggleBar, h as ToggleBarItem, i as ToggleBarProps, j as ToggleBarSize, k as ToggleBarVariant } from './_dts/Select.d-BchGMC2Y.js';
4
+ export { L as LayerList, a as LayerListItem, b as LayerListProps, c as LayerMove, m as moveLayers } from './_dts/LayerList.d-2c9yup5Y.js';
5
+ import { P as PropertyMetricProps, a as PropertyListPack } from './_dts/index-DINmCuLA.js';
6
+ export { C as ControlPanel, b as PropertyControl, c as PropertyControlProps, d as PropertyField, e as PropertyFieldProps, f as PropertyList, g as PropertyListProps, h as PropertyOption, i as PropertyPanel, j as PropertyPanelProps, k as PropertyRow, l as PropertyRowLayout, m as PropertyRowProps, n as PropertyRowVariant, o as PropertySpan, p as PropertySpanProps } from './_dts/index-DINmCuLA.js';
5
7
  import * as react from 'react';
6
8
  import { ReactNode } from 'react';
7
- import { P as PropertyMetricProps, a as PropertyListPack } from './_dts/index-8LiKe3A-.js';
8
- export { C as CheckboxRow, b as CheckboxRowProps, c as ColorRow, d as ColorRowProps, e as ControlPanel, N as NumberRow, f as NumberRowProps, g as PropertyList, h as PropertyListProps, i as PropertyOption, j as PropertyPanel, k as PropertyPanelProps, l as PropertyRow, m as PropertyRowLayout, n as PropertyRowProps, o as PropertyRowVariant, p as PropertySpan, q as PropertySpanProps, S as SelectRow, r as SelectRowProps, s as SliderRow, t as SliderRowProps, T as TextRow, u as TextRowProps, v as ToggleRow, w as ToggleRowProps } from './_dts/index-8LiKe3A-.js';
9
+ import { S as StanceProps } from './_dts/PrefsRow.d-DFpPIeIC.js';
9
10
  import { DrawCommand, SceneNode, View, Path, FillStyle, ScreenLength, StrokeAlign, StyledRun, TextStyle, TextVerticalAlign, Stroke, BuiltinToolId } from '@weasel-js/core';
10
- import { t as WorldRect, A as AnnotationData, v as AnnotationMeaning, w as MarkScene, x as CaptureSource, y as CaptureOptions, z as CaptureResult, B as AnnotationTarget, E as AnnotationsApi, F as AnnotationsCapability, G as TrialInfo, H as TrialTool, J as AnnotationKind, k as ViewTransform, K as Instrument, q as InstrumentList, o as LabMode, N as LabDensity, O as TrialContribution, c as StorageAdapter, T as TrialRecord } from './_dts/frac-B4hFJMiN.js';
11
- export { Q as Annotation, R as AnnotationInit, X as AnnotationPatch, Y as AnnotationQuery, Z as AnnotationStatus, _ as AnnotationStoreOptions, $ as AnnotationTargetInfo, a0 as Auto, a1 as CanvasCapability, a2 as CanvasLayer, a3 as CaptureDeps, a4 as ContributionBase, C as CreateLabStoreOptions, D as DEFAULT_FRAME, n as DragDropCapability, m as DragFeedback, a5 as FracPoint, a6 as FracRect, a7 as HitResult, a8 as IconComponent, a9 as LOUPE_DEFAULTS, L as LabDocument, d as LabStoreState, aa as LayerCapability, ab as LayerDescriptor, ac as LoupeCapability, ad as LoupeDeclaration, ae as LoupeRenderArgs, P as PaletteItem, l as Point, af as RegionContribution, ag as RenderContext, ah as ResolvedLoupe, e as SavedSnapshot, ai as SerializedAnnotations, S as SerializedTrial, aj as SidebarSection, ak as SidebarSlotContext, al as StageCapability, am as StatusReadout, f as StorageChange, an as SystemEvent, ao as ToolCapability, ap as ToolItem, aq as ToolSlotContext, ar as ToolbarItem, as as TrialChromeContext, at as TrialRegion, g as TrialStateHandle, au as UndoCapability, U as UndoStack, h as UndockedPanel, i as UndockedPanels, av as ViewportControl, V as ViewportSize, W as WorldFrame, a as WorldSpec, aw as annotationsFromJSON, b as applyCamera, ax as auto, ay as createAnnotationScene, az as createAnnotationStore, j as dockPanel, aA as fracContains, aB as fracEncloses, aC as fracToWorld, aD as isAuto, p as panelKey, r as resolveFrame, aE as resolveLoupe, aF as roundFrac, u as undockPanel, aG as worldToFrac } from './_dts/frac-B4hFJMiN.js';
12
- export { C as CanvasStack, a as CanvasStackProps, P as PanZoomHandlers, S as Stage, b as StageProps, U as UsePanZoomOptions, Z as ZoomAtOptions, c as centerOn, f as fitStage, s as screenToWorld, u as usePanZoom, w as worldToScreen, z as zoomAt } from './_dts/usePanZoom-SSTZe410.js';
13
- export { C as CanvasLayerDescriptor, a as CanvasStackContext, b as CanvasStackContextValue, c as CanvasStackSurface } from './_dts/CanvasStackContext-CMMo180l.js';
14
- import { L as LabContribution } from './_dts/index-DlKolEIZ.js';
15
- export { A as AddTrialOptions, a as LabAsideRegion, b as LabChromeContext, c as LabContext, d as LabContextValue, e as LabFooterRegion, f as LabHeaderRegion, g as LabRegion, h as LabRegionProps, i as LabSidebarRegion, P as PaletteRegion, j as PaletteRegionProps, S as SidebarRegion, k as SidebarRegionProps, l as StatusRegion, m as StatusRegionProps, T as TitleBarPlacement, n as TitleBarRegion, o as TitleBarRegionProps, p as ToolbarRegion, q as ToolbarRegionProps, V as ViewportRegion, r as ViewportRegionProps, s as addTrial, t as builtinContributions, u as cloneTrial, v as closeTrial, w as contributionsIn, x as labContributions, y as mergeContributions, z as reorderTrials, B as resetTrial, C as suppressContributions, D as toolContributions, E as useLabChromeContext, F as useLabContext } from './_dts/index-DlKolEIZ.js';
16
- export { BaseNode, BooleanNode, ColorNode, CustomNode, EnumNode, GroupNode, NumberNode, StringNode, ValueNode, applyRules, autoPathsOf, builtinRules, f, fillConfigDefaults, fromConfigFields, hasConfigPath, isConfigBranch, isLeafVisible, resolveAutoConfig, resolveConfigSchema, schemaNodeAtPath, titleCase, useConfigSchema, useResolvedConfig, valueAtPath, withValueAtPath } from './config/index.js';
17
- import { b as ConfigSchema, a as ConfigField, c as ConfigRule, d as ControlRenderer } from './_dts/types-Db-3NNk1.js';
18
- export { A as Annotations, B as BranchAnnotations, e as BranchOptions, f as CheckboxField, g as ColorField, h as ConfigBranch, i as ConfigEntry, j as ConfigFieldBase, k as ConfigFieldType, l as ConfigNode, m as ConfigOf, n as ConfigOption, C as ConfigPath, o as ConfigRuleContext, p as ConfigShape, E as EntryValue, I as InferConfig, L as LeafPatch, N as NodeOptions, q as NodeValue, r as NumberField, R as ResolvedConfig, S as SectionSpec, s as SelectField, t as SelectOption, u as SliderField, T as TextField, V as ValueAtPath } from './_dts/types-Db-3NNk1.js';
11
+ import { w as WorldRect, A as AnnotationData, x as AnnotationMeaning, y as MarkScene, z as CaptureSource, B as CaptureOptions, E as CaptureResult, F as AnnotationTarget, G as AnnotationsApi, H as AnnotationsCapability, J as TrialInfo, K as TrialTool, N as AnnotationKind, m as ViewTransform, O as Instrument, t as InstrumentList, s as LabMode, Q as LabDensity, R as TrialContribution, d as StorageAdapter, T as TrialRecord } from './_dts/frac-DTRq7Xpb.js';
12
+ export { X as Annotation, Y as AnnotationInit, Z as AnnotationPatch, _ as AnnotationQuery, $ as AnnotationStatus, a0 as AnnotationStoreOptions, a1 as AnnotationTargetInfo, a2 as Auto, a3 as CanvasCapability, a4 as CanvasLayer, a5 as CaptureDeps, a6 as ContributionBase, C as CreateLabStoreOptions, D as DEFAULT_FRAME, q as DragDropCapability, o as DragFeedback, a7 as FracPoint, a8 as FracRect, a9 as HitResult, aa as IconComponent, ab as LOUPE_DEFAULTS, e as LabDocument, f as LabStoreState, L as LayerCapability, a as LayerDescriptor, ac as LoupeCapability, ad as LoupeDeclaration, ae as LoupeRenderArgs, P as PaletteItem, n as Point, af as RegionContribution, ag as RenderContext, ah as ResolvedLoupe, g as SavedSnapshot, ai as SerializedAnnotations, S as SerializedTrial, aj as SidebarSection, ak as SidebarSlotContext, al as StageCapability, am as StatusReadout, h as StorageChange, an as SystemEvent, ao as ToolCapability, ap as ToolItem, aq as ToolSlotContext, ar as ToolbarItem, as as TrialChromeContext, at as TrialRegion, i as TrialStateHandle, au as UndoCapability, U as UndoStack, j as UndockedPanel, k as UndockedPanels, av as ViewportControl, V as ViewportSize, W as WorldFrame, b as WorldSpec, aw as annotationsFromJSON, c as applyCamera, ax as auto, ay as createAnnotationScene, az as createAnnotationStore, l as dockPanel, aA as fracContains, aB as fracEncloses, aC as fracToWorld, aD as isAuto, p as panelKey, r as resolveFrame, aE as resolveLoupe, aF as roundFrac, u as undockPanel, aG as worldToFrac } from './_dts/frac-DTRq7Xpb.js';
13
+ export { C as CanvasStack, a as CanvasStackProps, P as PanZoomHandlers, S as Stage, b as StageProps, U as UsePanZoomOptions, Z as ZoomAtOptions, c as centerOn, f as fitStage, s as screenToWorld, u as usePanZoom, w as worldToScreen, z as zoomAt } from './_dts/usePanZoom-Bq73pwFe.js';
14
+ export { C as CanvasLayerDescriptor, a as CanvasStackContext, b as CanvasStackContextValue, c as CanvasStackSurface } from './_dts/CanvasStackContext-DQgcH1ny.js';
15
+ import { L as LabContribution } from './_dts/index-B0--8PEM.js';
16
+ export { A as AddTrialOptions, a as LabAsideRegion, b as LabChromeContext, c as LabContext, d as LabContextValue, e as LabFooterRegion, f as LabHeaderRegion, g as LabRegion, h as LabRegionProps, i as LabSidebarRegion, P as PaletteRegion, j as PaletteRegionProps, S as SidebarRegion, k as SidebarRegionProps, l as StatusRegion, m as StatusRegionProps, T as TitleBarPlacement, n as TitleBarRegion, o as TitleBarRegionProps, p as ToolbarRegion, q as ToolbarRegionProps, V as ViewportRegion, r as ViewportRegionProps, s as addTrial, t as builtinContributions, u as cloneTrial, v as closeTrial, w as contributionsIn, x as labContributions, y as mergeContributions, z as reorderTrials, B as resetTrial, C as suppressContributions, D as toolContributions, E as useLabChromeContext, F as useLabContext } from './_dts/index-B0--8PEM.js';
17
+ export { BaseNode, BooleanNode, ColorNode, CustomNode, EnumNode, GroupNode, ListNode, NumberNode, SectionTree, StringNode, ValueNode, applyRules, autoPathsOf, builtinRules, f, fillConfigDefaults, fromConfigFields, hasConfigPath, isConfigBranch, isLeafVisible, resolveAutoConfig, resolveConfigSchema, schemaNodeAtPath, sectionTree, titleCase, useConfigSchema, useResolvedConfig, valueAtPath, withValueAtPath } from './config/index.js';
18
+ import { c as ConfigSchema, b as ConfigField, d as ConfigRule, C as ControlRenderer } from './_dts/types-B7y8hX1D.js';
19
+ export { A as Annotations, B as BranchAnnotations, e as BranchOptions, f as CheckboxField, g as ColorField, h as ConfigBranch, i as ConfigEntry, j as ConfigFieldBase, k as ConfigFieldType, l as ConfigNode, m as ConfigOf, n as ConfigOption, a as ConfigPath, o as ConfigRuleContext, p as ConfigShape, E as EntryValue, I as InferConfig, L as LeafPatch, N as NodeOptions, q as NodeValue, r as NumberField, R as ResolvedConfig, S as SectionSpec, s as SelectField, t as SelectOption, u as SliderField, T as TextField, V as ValueAtPath } from './_dts/types-B7y8hX1D.js';
20
+ export { I as InDialogOptions, i as inDialog, s as summarizeValue } from './_dts/inDialog-D5ZKGjiD.js';
19
21
  import { J as JobHandle } from './_dts/types-DJ79Tg5J.js';
20
22
  export { a as JobCapability, b as JobEvent, c as JobFailure, d as JobStatus } from './_dts/types-DJ79Tg5J.js';
21
23
  export { UseJobOptions, useJob } from './job/index.js';
22
- export { LayerList, LayerListProps, LayerTreeNode } from './layers/index.js';
24
+ import { Theme, ColorList } from '@weasel-js/theme';
23
25
  export { CanvasLoupe, CanvasLoupeProps, DomLoupe, DomLoupeProps, LOUPE_MAGNIFY_ID, LOUPE_PEEK_ID, LensCamera, LoupeBubble, LoupeBubbleProps, LoupeGestures, LoupeGesturesProps, LoupeInputApi, LoupeState, SourceRect, TrialLoupe, TrialLoupeProps, UseLoupeOptions, createLoupeActions, drawCanvasLens, lensCamera, lensSourceRect, sampleStack, useLoupe } from './loupe/index.js';
24
26
  import { SplitProps } from './primitives/index.js';
25
- export { FloatingPanel, FloatingPanelProps, FpsMeter, JobProgress, JobProgressProps, Legend, LegendEntry, LegendMark, LegendProps, ScaleIndicator, ScaleIndicatorProps, Sidebar, SidebarProps, Split, StatusBar, StatusBarProps, StatusBarSectionProps, Toolbar, ToolbarButtonProps, ToolbarGroupProps, ToolbarProps, ZoomControl, ZoomControlProps } from './primitives/index.js';
26
- export { C as CURRENT_DOCUMENT_VERSION, I as IndexedDbAdapterOptions, b as LabStoreContext, c as LabStoreProvider, O as OpenLabStoreOptions, d as OpenedLabStore, P as PersistedStateOptions, e as Persistence, f as PersistenceProps, R as RecordCache, g as RecordChange, T as TrialIdContext, h as TrialIdProvider, i as createIndexedDbAdapter, k as createMemoryAdapter, l as indexedDbAdapter, m as labDocumentKey, n as localStorageAdapter, o as noneAdapter, p as openLabStore, q as quarantineKey, s as sessionStorageAdapter, u as urlHashAdapter, r as useLabStore, t as usePersistedState, v as useTrialId, w as useTrialState } from './_dts/useTrialState-pnAE-UBD.js';
27
+ export { FloatingPanel, FloatingPanelProps, FpsMeter, JobProgress, JobProgressProps, Legend, LegendEntry, LegendMark, LegendProps, ScaleIndicator, ScaleIndicatorProps, Split, StatusBar, StatusBarProps, StatusBarSectionProps, Toolbar, ToolbarButtonProps, ToolbarGroupProps, ToolbarProps, ZoomControl, ZoomControlProps } from './primitives/index.js';
28
+ export { C as CURRENT_DOCUMENT_VERSION, I as IndexedDbAdapterOptions, b as LabStoreContext, c as LabStoreProvider, O as OpenLabStoreOptions, d as OpenedLabStore, P as PersistedStateOptions, e as Persistence, f as PersistenceProps, R as RecordCache, g as RecordChange, T as TrialIdContext, h as TrialIdProvider, i as createIndexedDbAdapter, k as createMemoryAdapter, l as indexedDbAdapter, m as labDocumentKey, n as localStorageAdapter, o as noneAdapter, p as openLabStore, q as quarantineKey, s as sessionStorageAdapter, u as urlHashAdapter, r as useLabStore, t as usePersistedState, v as useTrialId, w as useTrialState } from './_dts/useTrialState-CP4jfuKl.js';
27
29
  export { Box, Rect, SurfaceCanvasContext, SurfaceCanvases, SurfaceClear, SurfaceContext, SurfaceFrame, SurfaceHandle, SurfaceLayer, TilePainter, UseTiledSurfaceOptions, composeRects, rectsEqual, toDeviceRect, useSurface, useSurfaceCanvas, useSurfaceOptional, useSurfaceTile, useTileId, useTiledSurface } from './surface/index.js';
28
- import { Theme } from '@weasel-js/theme';
29
30
  export { EventBus, EventListener, clearUndo, createEventBus, emptyStack, pushSnapshot, redo, undo } from './undo/index.js';
30
31
  import 'react-aria-components';
31
- import './_dts/PrefsForm.d-DPy9I8It.js';
32
+ import './_dts/number.d-OeQYQoUO.js';
32
33
  import 'windease';
33
34
  import 'zustand/vanilla';
34
35
 
@@ -79,77 +80,14 @@ interface CurveFieldProps {
79
80
  */
80
81
  declare function CurveField({ values, min, max, step, width, height, defaults, onChange, marks, }: CurveFieldProps): react_jsx_runtime.JSX.Element;
81
82
 
82
- /** Props for `<Subpanel>`. */
83
- interface SubpanelProps extends PropertyMetricProps {
84
- title: ReactNode;
85
- children: ReactNode;
86
- className?: string;
87
- }
88
- /** A typographic divider inside a property list: a small title flanked by a
89
- * rule. Purely a heading — use `<PropertyGroup>` for a bordered section. */
90
- declare function Subpanel({ title, children, className, density, align }: SubpanelProps): react_jsx_runtime.JSX.Element;
91
- /** Props for `<EffectCard>`. */
92
- interface EffectCardProps {
93
- /** Card title rendered in the title bar (e.g. effect kind label or a select). */
94
- title: ReactNode;
95
- /** Optional badge/chip displayed before the remove button (e.g. primary value summary). */
96
- primary?: ReactNode;
97
- /** Optional accent color in any CSS color form. Sets --wzl-effect-card-accent on the card. */
98
- accent?: string;
99
- /** Optional ordinal badge that doubles as the drag handle (used by tail cards in SB). */
100
- index?: number;
101
- expanded?: boolean;
102
- onToggleExpanded?: () => void;
103
- onRemove?: () => void;
104
- /**
105
- * Drag-handle wiring. When provided, an inline handle (⋮⋮ icon or `index`)
106
- * activates HTML5 drag on press. Consumer owns the drag/drop coordination —
107
- * see EffectCardList for the batteries-included wrapper.
108
- */
109
- draggable?: boolean;
110
- onPressHandle?: () => void;
111
- onReleaseHandle?: () => void;
112
- onDragStart?: (e: React.DragEvent<HTMLDivElement>) => void;
113
- onDragEnd?: (e: React.DragEvent<HTMLDivElement>) => void;
114
- onDragOver?: (e: React.DragEvent<HTMLDivElement>) => void;
115
- onDragLeave?: (e: React.DragEvent<HTMLDivElement>) => void;
116
- onDrop?: (e: React.DragEvent<HTMLDivElement>) => void;
117
- dragging?: boolean;
118
- children?: ReactNode;
119
- className?: string;
120
- }
121
- /** An accented, collapsible card for one item in a list of like things —
122
- * effects, layers, tails. The accent color rebinds the theme accent token
123
- * within the card, so its controls pick it up too. */
124
- declare function EffectCard({ title, primary, accent, index, expanded, onToggleExpanded, onRemove, draggable, onPressHandle, onReleaseHandle, onDragStart, onDragEnd, onDragOver, onDragLeave, onDrop, dragging, children, className, }: EffectCardProps): react_jsx_runtime.JSX.Element;
125
- /** The minimum an item must carry to appear in an `<EffectCardList>`. */
126
- interface EffectCardListItem {
127
- id: string | number;
128
- }
129
- /** Props for `<EffectCardList>`. */
130
- interface EffectCardListProps<T extends EffectCardListItem> {
131
- items: ReadonlyArray<T>;
132
- renderItem: (item: T, helpers: {
133
- isExpanded: boolean;
134
- isDragging: boolean;
135
- toggleExpanded: () => void;
136
- cardProps: Pick<EffectCardProps, 'expanded' | 'dragging' | 'draggable' | 'onToggleExpanded' | 'onPressHandle' | 'onReleaseHandle' | 'onDragStart' | 'onDragEnd' | 'onDragOver' | 'onDragLeave' | 'onDrop'>;
137
- }) => ReactNode;
138
- onReorder: (sourceId: T['id'], targetId: T['id'], position: 'before' | 'after') => void;
139
- /** Optional rendered when the list is empty. */
140
- empty?: ReactNode;
141
- /** IDs to render expanded on first mount. Defaults to all collapsed. */
142
- defaultExpandedIds?: ReadonlyArray<T['id']>;
143
- }
144
- /** A drag-reorderable list of `<EffectCard>`s. Owns the expanded and dragging
145
- * state and hands it back to `renderItem`, so the caller only supplies each
146
- * card's contents. */
147
- declare function EffectCardList<T extends EffectCardListItem>({ items, renderItem, onReorder, empty, defaultExpandedIds, }: EffectCardListProps<T>): react_jsx_runtime.JSX.Element;
148
-
149
83
  /** Props for `<PropertyGroup>`. */
150
- interface PropertyGroupProps extends PropertyMetricProps {
84
+ interface PropertyGroupProps extends PropertyMetricProps, StanceProps {
151
85
  /** Title rendered between two rules at the top of the group. */
152
86
  title: ReactNode;
87
+ /** Before the title: a drag handle, an ordinal. Clicks here do not fold the group. */
88
+ leading?: ReactNode;
89
+ /** After the title: a summary of the group's value, a remove button. Clicks here do not fold the group. */
90
+ actions?: ReactNode;
153
91
  /** Help text for the whole group, drawn under the title and above the
154
92
  * rows. `<PropertyRow description>` covers the per-row case. */
155
93
  description?: ReactNode;
@@ -184,9 +122,24 @@ interface PropertyGroupProps extends PropertyMetricProps {
184
122
  * inside a fill effect's controls).
185
123
  *
186
124
  * A collapsible group keeps its rows mounted and hides them, so a control's
187
- * local state survives being folded away.
125
+ * local state survives being folded away. `stance` and `tone` work as on
126
+ * `<PropertyPanel>`; a tone also draws the group's leading edge in it, which
127
+ * is how a list of like groups — effects, tails — tells its members apart.
128
+ * `leading` and `actions` put a handle and controls in the title row, and the
129
+ * groups of a `<PropertyList>` reorder with `useReorderDragList`.
188
130
  */
189
- declare function PropertyGroup({ title, description, hidden, collapsible, defaultCollapsed, collapsed, onCollapsedChange, children, className, span, pack, density, align, }: PropertyGroupProps): react_jsx_runtime.JSX.Element | null;
131
+ declare function PropertyGroup({ title, leading, actions, description, hidden, collapsible, defaultCollapsed, collapsed, onCollapsedChange, children, className, span, pack, density, align, stance, tone, }: PropertyGroupProps): react_jsx_runtime.JSX.Element | null;
132
+
133
+ /** Props for `<Subpanel>`. */
134
+ interface SubpanelProps extends PropertyMetricProps, StanceProps {
135
+ title: ReactNode;
136
+ children: ReactNode;
137
+ className?: string;
138
+ }
139
+ /** A typographic divider inside a property list: a small title flanked by a
140
+ * rule. Purely a heading — use `<PropertyGroup>` for a bordered section. A
141
+ * stance or tone colors the title and rule. */
142
+ declare function Subpanel({ title, children, className, density, align, stance, tone }: SubpanelProps): react_jsx_runtime.JSX.Element;
190
143
 
191
144
  /** A design token as `TokenPanel` edits it. */
192
145
  interface TokenEntry {
@@ -815,7 +768,8 @@ declare function validateConfigSchema(fields: ConfigField[]): ValidationResult;
815
768
 
816
769
  /** One page in a project's set of labs. */
817
770
  interface LabPage {
818
- /** The page's own URL, and how the switcher knows which page is open. */
771
+ /** The page's own URL, and how the switcher knows which page is open. A
772
+ * hash route (`#/dev/tools`) names a page on the current document. */
819
773
  href: string;
820
774
  label: string;
821
775
  }
@@ -834,7 +788,11 @@ interface LabSwitcherProps {
834
788
  * Matched on the end of the path so a query string, a trailing slash or a
835
789
  * leftover `.html` cannot lose it: a project whose dev server maps `/stats`
836
790
  * to `stats.html` serves both spellings, and a bookmark from before the URLs
837
- * lost their extension still resolves to the same page. */
791
+ * lost their extension still resolves to the same page.
792
+ *
793
+ * A page whose `href` carries a hash is a route on a single document and wins
794
+ * when the path's hash is that route or one under it. A page without one
795
+ * ignores the hash, so an in-page anchor does not lose it. */
838
796
  declare function currentPage(path: string, pages: readonly LabPage[]): number;
839
797
  /** A project's lab title, doubling as the way to reach its other labs.
840
798
  *
@@ -859,15 +817,20 @@ interface LabBaseProps {
859
817
  * window is the whole app, rather than a panel beside one, reads better at
860
818
  * `'roomy'`. The trials' own contents are unaffected. */
861
819
  density?: LabDensity;
820
+ /** The theme the lab's chrome resolves against, applied at `mode` and
821
+ * `density`. Default `interstellarTheme`; extend it rather than replace it to
822
+ * keep the lab's look while changing a few tokens. */
823
+ theme?: Theme;
862
824
  /** Rendered while a stored lab loads. Default: the lab's empty shell. */
863
825
  fallback?: ReactNode;
864
826
  /**
865
- * Optional list of CSS colors used to compose the interstellar theme's
866
- * cosmic backdrop. Each color becomes one radial-gradient blob on the
867
- * dark void base. Order maps to a fixed spread of positions; extras wrap
868
- * around. Ignored unless the resolved mode is dark.
827
+ * Colors composing the interstellar theme's cosmic backdrop. Each becomes
828
+ * one radial-gradient blob on the dark void base, in a fixed spread of
829
+ * positions; extras wrap around. A theme ramp resolves against the lab's
830
+ * theme; a function list gives as many blobs as there are positions.
831
+ * Ignored unless the resolved mode is dark.
869
832
  */
870
- nebula?: readonly string[];
833
+ nebula?: ColorList;
871
834
  title?: string;
872
835
  /** The project's other labs. Given two or more, the title becomes the way to
873
836
  * reach them — the same switcher `<LabShell>` renders, so a lab reached from
@@ -914,7 +877,22 @@ type LabProps = LabBaseProps & ({
914
877
  });
915
878
  /** The lab runtime: opens the store, provides it, and renders one trial
916
879
  * per record in a grid. Each trial runs one of `instruments`. */
917
- declare function Lab(props: LabProps): string | number | bigint | boolean | react_jsx_runtime.JSX.Element | Iterable<ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | null;
880
+ declare function Lab(props: LabProps): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | react_jsx_runtime.JSX.Element | null;
881
+
882
+ /** Props for `<LabBoundary>`. */
883
+ interface LabBoundaryProps {
884
+ children: ReactNode;
885
+ }
886
+ /**
887
+ * Renders its children as though no lab, trial or theme were above them: every context a `<Lab>` or a
888
+ * `<Trial>` publishes reads as absent below it, so a labkit piece mounted inside a trial behaves the way it
889
+ * does on a bare page. A `<LabRoot>` under it applies its own theme instead of deferring to the lab's, and a
890
+ * `usePersistedState` under it keeps local state instead of writing into the enclosing lab's records.
891
+ *
892
+ * For a host that shows arbitrary content inside a trial, such as a component workshop; a lab's own chrome
893
+ * never needs it.
894
+ */
895
+ declare function LabBoundary({ children }: LabBoundaryProps): react_jsx_runtime.JSX.Element;
918
896
 
919
897
  /** Props for `<LabPalette>`. */
920
898
  interface LabPaletteProps {
@@ -964,11 +942,14 @@ interface LabShellProps {
964
942
  /** The path the switcher reads to mark the open page. Defaults to the
965
943
  * current location. */
966
944
  path?: string;
945
+ /** Set as `document.title` while the shell is mounted, and the previous
946
+ * title restored after. Omitted, the document's title is left alone. */
947
+ documentTitle?: string;
967
948
  }
968
949
  /** Page frame for a lab: a titled header, a body, and an optional footer,
969
950
  * themed for the resolved color mode. Presentational only — use `<Lab>` when
970
951
  * the trial runtime is wanted too. */
971
- declare function LabShell({ title, children, header, footer, mode, pages, path, }: LabShellProps): react_jsx_runtime.JSX.Element;
952
+ declare function LabShell({ title, children, header, footer, mode, pages, path, documentTitle, }: LabShellProps): react_jsx_runtime.JSX.Element;
972
953
 
973
954
  /** A tile's persisted extent, keyed by the id its caller gave it. Grid resizes
974
955
  * write `span`; `size` is here because a strategy swap would write that. */
@@ -1053,8 +1034,8 @@ declare const DEFAULT_VIEW: ViewTransform2D;
1053
1034
  declare function as2DView(view: unknown): ViewTransform2D | null;
1054
1035
 
1055
1036
  /**
1056
- * labkit's theme: a cosmic dark and a warm parchment light, extending the
1057
- * built-in weasel theme. A pins-only theme definition: nothing in it is
1037
+ * labkit's theme: a cosmic dark over the built-in weasel theme, whose light
1038
+ * mode it keeps as is. A pins-only theme definition: nothing in it is
1058
1039
  * derived, so it loads without the engine.
1059
1040
  */
1060
1041
  declare const interstellarTheme: Theme;
@@ -1126,5 +1107,5 @@ interface TrialChromeProps {
1126
1107
  * each region its slice. */
1127
1108
  declare function TrialChrome({ trialId, record, instrument, isLastTrial, undoBindings, job, loupe, trialChrome, chrome, suppress, activeToolId, setActiveTool, children, }: TrialChromeProps): react_jsx_runtime.JSX.Element;
1128
1109
 
1129
- export { ANNOTATION_TOOLS, ANNOTATION_WEASEL_TOOLS, AnnotationData, AnnotationKind, AnnotationMeaning, AnnotationOverlay, AnnotationTarget, AnnotationTargets, AnnotationsApi, AnnotationsCapability, AnnotationsContext, CaptureOptions, CaptureResult, CaptureSource, CloseIcon, CollapseIcon, ConfigField, ConfigRule, ConfigSchema, ControlRenderer, CurveField, DEFAULT_VIEW, EffectCard, EffectCardList, ExpandIcon, ExportMenu, IconProps, Instrument, InstrumentList, JobHandle, Jog, Lab, LabContribution, LabDensity, LabMode, LabPalette, LabRoot, LabShell, LabSwitcher, MarkList, MarkScene, PauseIcon, PlayIcon, PropertyGroup, PropertyListPack, ResetIcon, SPECIMEN_SECTIONS, Specimen, SplitProps, StepBackIcon, StepForwardIcon, StopIcon, StorageAdapter, Subpanel, TokenPanel, Trial, TrialBody, TrialChrome, TrialContribution, TrialInfo, TrialRecord, TrialTool, ViewTransform, Workspace, WorldRect, annotationToolInfo, as2DView, capturePlan, captureTarget, composeCaptureSvg, createMarkDrawOne, currentPage, defineInstrument, fitView, fromWeaselView, inferTokenType, interstellarTheme, isStale, markCommands, markSvgNodes, refitScale, resolveMarkStyle, seenFrom, toWeaselView, useAnnotations, useAnnotationsOptional, validateConfigSchema };
1130
- export type { AnnotationOverlayProps, AnnotationTargetsProps, AnnotationToolInfo, CaptureArgs, CapturePlan, ComposeSvgArgs, ContentSize, CurveFieldProps, CurveMark, EffectCardListItem, EffectCardListProps, EffectCardProps, InstrumentSpec, JogProps, LabPage, LabPaletteProps, LabProps, LabRootProps, LabShellProps, LabSwitcherProps, MarkDrawOptions, MarkListProps, MarkStyle, PaintableMark, PaneSize, PanelDescriptor, PropertyGroupProps, SubpanelProps, TokenCategory, TokenEntry, TokenPanelProps, TokenScale, TokenScaleRule, TrialBodyProps, TrialChromeProps, TrialLayout, TrialProps, UndoBindings, ValidationResult, ViewTransform2D, WorkspaceProps };
1110
+ export { ANNOTATION_TOOLS, ANNOTATION_WEASEL_TOOLS, AnnotationData, AnnotationKind, AnnotationMeaning, AnnotationOverlay, AnnotationTarget, AnnotationTargets, AnnotationsApi, AnnotationsCapability, AnnotationsContext, CaptureOptions, CaptureResult, CaptureSource, CloseIcon, CollapseIcon, ConfigField, ConfigRule, ConfigSchema, ControlRenderer, CurveField, DEFAULT_VIEW, ExpandIcon, ExportMenu, IconProps, Instrument, InstrumentList, JobHandle, Jog, Lab, LabBoundary, LabContribution, LabDensity, LabMode, LabPalette, LabRoot, LabShell, LabSwitcher, MarkList, MarkScene, PauseIcon, PlayIcon, PropertyGroup, PropertyListPack, ResetIcon, SPECIMEN_SECTIONS, Specimen, SplitProps, StepBackIcon, StepForwardIcon, StopIcon, StorageAdapter, Subpanel, TokenPanel, Trial, TrialBody, TrialChrome, TrialContribution, TrialInfo, TrialRecord, TrialTool, ViewTransform, Workspace, WorldRect, annotationToolInfo, as2DView, capturePlan, captureTarget, composeCaptureSvg, createMarkDrawOne, currentPage, defineInstrument, fitView, fromWeaselView, inferTokenType, interstellarTheme, isStale, markCommands, markSvgNodes, refitScale, resolveMarkStyle, seenFrom, toWeaselView, useAnnotations, useAnnotationsOptional, validateConfigSchema };
1111
+ export type { AnnotationOverlayProps, AnnotationTargetsProps, AnnotationToolInfo, CaptureArgs, CapturePlan, ComposeSvgArgs, ContentSize, CurveFieldProps, CurveMark, InstrumentSpec, JogProps, LabBoundaryProps, LabPage, LabPaletteProps, LabProps, LabRootProps, LabShellProps, LabSwitcherProps, MarkDrawOptions, MarkListProps, MarkStyle, PaintableMark, PaneSize, PanelDescriptor, PropertyGroupProps, SubpanelProps, TokenCategory, TokenEntry, TokenPanelProps, TokenScale, TokenScaleRule, TrialBodyProps, TrialChromeProps, TrialLayout, TrialProps, UndoBindings, ValidationResult, ViewTransform2D, WorkspaceProps };