@weasel-js/labkit 1.4.2 → 1.4.4
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-kTEZvEgE.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-z7ker2Vx.d.ts} +11 -7
- package/dist/_dts/{index-CsU9WhjM.d.ts → index-Blv9uQzu.d.ts} +42 -9
- 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-ULDW42CR.js → chunk-2P6PP5N4.js} +33 -23
- package/dist/chunk-2P6PP5N4.js.map +1 -0
- package/dist/{chunk-W2FJR5FF.js → chunk-64ZCN3DA.js} +74 -76
- package/dist/chunk-64ZCN3DA.js.map +1 -0
- package/dist/{chunk-NSOVI3AZ.js → chunk-BKFVHKJH.js} +6 -6
- package/dist/{chunk-NSOVI3AZ.js.map → chunk-BKFVHKJH.js.map} +1 -1
- 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-UDXOYZEC.js → chunk-MOM3GOVY.js} +4 -4
- package/dist/{chunk-UDXOYZEC.js.map → chunk-MOM3GOVY.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-UTOEDPNU.js → chunk-SMHP6XZ4.js} +7 -6
- package/dist/chunk-SMHP6XZ4.js.map +1 -0
- package/dist/{chunk-D5KQ5OY6.js → chunk-TJ7QY3OC.js} +3 -3
- package/dist/{chunk-D5KQ5OY6.js.map → chunk-TJ7QY3OC.js.map} +1 -1
- package/dist/{chunk-XKENZTNE.js → chunk-U3IYHIAE.js} +71 -55
- package/dist/chunk-U3IYHIAE.js.map +1 -0
- package/dist/chunk-W3ECWC2K.js +7335 -0
- package/dist/chunk-W3ECWC2K.js.map +1 -0
- 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 +139 -26
- package/dist/index.js +309 -144
- 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 +98 -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 +82 -15
- 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/annotations/frac.test.ts +4 -4
- package/src/annotations/frac.ts +3 -2
- package/src/annotations/index.ts +1 -1
- package/src/annotations/store.ts +2 -2
- package/src/annotations/svgNodes.ts +1 -2
- 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 +17 -2
- 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 +17 -3
- package/src/lab/LabSwitcher.less +85 -0
- package/src/lab/LabSwitcher.test.tsx +96 -0
- package/src/lab/LabSwitcher.tsx +112 -0
- package/src/lab/index.ts +2 -0
- package/src/primitives/ZoomControl.less +6 -2
- package/src/primitives/ZoomControl.tsx +1 -0
- package/src/state/helpers.test.ts +20 -0
- package/src/state/helpers.ts +17 -1
- package/src/state/store.test.ts +155 -1
- package/src/state/store.ts +32 -26
- package/src/state/types.ts +24 -3
- package/src/state/useTrialState.ts +1 -1
- package/src/styles.less +1 -0
- package/src/theme/base.less +4 -4
- 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 +7 -10
- 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/README.md
CHANGED
|
@@ -13,10 +13,16 @@ algorithm and would rather not build the page around it.
|
|
|
13
13
|
## Install
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
npm i @weasel-js/labkit
|
|
16
|
+
npm i @weasel-js/labkit @weasel-js/core
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
`@weasel-js/core` is a peer dependency, pinned to the matching version. labkit
|
|
20
|
+
does not ship its own copy: core keeps its content handlers, paint kinds, shape
|
|
21
|
+
painters and markers in module-global registries, and two copies means anything
|
|
22
|
+
registered through one is invisible to the other — a blank canvas with no error.
|
|
23
|
+
Installing it alongside is what guarantees there is exactly one.
|
|
24
|
+
|
|
25
|
+
React 19 is a peer dependency too (`react` and `react-dom`, `^19.0.0`). One
|
|
20
26
|
stylesheet import covers everything labkit draws, including the theme tokens and
|
|
21
27
|
the `@weasel-js/ui` components it passes through:
|
|
22
28
|
|
|
@@ -70,6 +76,18 @@ renders the settings panel from it. `render` returns the instrument's own DOM;
|
|
|
70
76
|
returning `null` alongside `canvas` means the canvas layers are the whole
|
|
71
77
|
picture. `storage` keeps open trials and their state across reloads.
|
|
72
78
|
|
|
79
|
+
A value is addressed by its path: `bins` above sits at `config.bins` and is
|
|
80
|
+
written as `setConfig('bins', 40)`. `f.group` nests one —
|
|
81
|
+
`paper: f.group({ width: f.number(210) })` puts the value at
|
|
82
|
+
`config.paper.width` and addresses it as `'paper.width'`, in `setConfig`, in a
|
|
83
|
+
control override, and anywhere else a path is taken. `.section('Advanced')` is
|
|
84
|
+
the other thing and only looks like it: it puts a heading over sibling rows and
|
|
85
|
+
leaves their paths alone.
|
|
86
|
+
|
|
87
|
+
A stored config missing something its schema has since gained — a whole nested
|
|
88
|
+
group included — is filled from the instrument's defaults as it loads, so
|
|
89
|
+
growing a schema never strands a saved trial or a snapshot.
|
|
90
|
+
|
|
73
91
|
## Capabilities
|
|
74
92
|
|
|
75
93
|
A capability is a field on the instrument. Declaring it is what makes the trial
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { RefObject } from 'react';
|
|
3
|
-
import { V as ViewTransform, W as WorldFrame } from './frac-
|
|
3
|
+
import { V as ViewTransform, W as WorldFrame } from './frac-z7ker2Vx.js';
|
|
4
4
|
|
|
5
5
|
/** One layer of a canvas stack: its id, whether it is currently shown, and how
|
|
6
6
|
* it paints itself. */
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ComponentType, ReactNode, RefObject } from 'react';
|
|
2
|
-
import { R as ResolvedConfig,
|
|
3
|
-
import {
|
|
2
|
+
import { R as ResolvedConfig, a as ConfigSchema, C as ConfigPath } from './types-B9_zrHmb.js';
|
|
3
|
+
import { C as ConfigField } from './types-x92Kfeme.js';
|
|
4
|
+
import { c as SavedSnapshot, i as TrialInfo } from './types-BP2OCcpg.js';
|
|
4
5
|
import { J as JobHandle, a as JobCapability } from './types-DJ79Tg5J.js';
|
|
5
|
-
import {
|
|
6
|
+
import { Scene } from '@weasel-js/core';
|
|
6
7
|
|
|
7
8
|
/** How an instrument's world sits on the canvas, independent of the camera.
|
|
8
9
|
* The defaults reproduce the convention labkit shipped before this existed:
|
|
@@ -299,7 +300,9 @@ interface RenderContext<TS = unknown, TC = unknown> {
|
|
|
299
300
|
state: TS;
|
|
300
301
|
config: TC;
|
|
301
302
|
setState: (next: TS | ((prev: TS) => TS)) => void;
|
|
302
|
-
|
|
303
|
+
/** Write one config value, by dotted path — `'grid.size'` for a leaf under
|
|
304
|
+
* an `f.group`, `'cellSize'` for one at the root. */
|
|
305
|
+
setConfig: (path: ConfigPath<TC>, value: unknown) => void;
|
|
303
306
|
/** labkit persists `view` and restores it on Reset without ever reading
|
|
304
307
|
* into it. */
|
|
305
308
|
trial: TrialInfo & {
|
|
@@ -751,8 +754,9 @@ declare function roundFrac(f: FracRect): FracRect;
|
|
|
751
754
|
* mark stays reachable. */
|
|
752
755
|
declare function fracContains(box: FracRect, pt: FracPoint, tol?: number): boolean;
|
|
753
756
|
/** Whether `outer` wholly encloses `inner`. A marquee takes what it encloses,
|
|
754
|
-
* not what it grazes — brushing selection is a different gesture
|
|
755
|
-
|
|
757
|
+
* not what it grazes — brushing selection is a different gesture, and this
|
|
758
|
+
* answers false for two rects that merely overlap. */
|
|
759
|
+
declare function fracEncloses(outer: FracRect, inner: FracRect): boolean;
|
|
756
760
|
|
|
757
|
-
export { LOUPE_DEFAULTS as L, annotationsFromJSON as a3, applyCamera as a4, createAnnotationScene as a5, createAnnotationStore as a6, fracContains as a7,
|
|
761
|
+
export { LOUPE_DEFAULTS as L, annotationsFromJSON as a3, applyCamera as a4, createAnnotationScene as a5, createAnnotationStore as a6, fracContains as a7, fracEncloses as a8, fracToWorld as a9, resolveFrame as aa, resolveLoupe as ab, roundFrac as ac, worldToFrac as ad, DEFAULT_FRAME as x };
|
|
758
762
|
export type { TrialRegion as $, AnnotationData as A, LayerCapability as B, CaptureSource as C, DragFeedback as D, LayerDescriptor as E, FracPoint as F, LoupeCapability as G, HitResult as H, Instrument as I, LoupeDeclaration as J, LoupeRenderArgs as K, MarkScene as M, ResolvedLoupe as N, SidebarSection as O, PaletteItem as P, StatusReadout as Q, RenderContext as R, SerializedAnnotations as S, TrialTool as T, SystemEvent as U, ViewTransform as V, WorldFrame as W, ToolCapability as X, ToolItem as Y, ToolbarItem as Z, TrialChromeContext as _, Point as a, UndoCapability as a0, ViewportControl as a1, ViewportSize as a2, LoupePoint as ae, LoupeMode as af, DragDropCapability as b, WorldSpec as c, WorldRect as d, AnnotationMeaning as e, CaptureOptions as f, CaptureResult as g, AnnotationTarget as h, AnnotationsApi as i, AnnotationsCapability as j, AnnotationKind as k, InstrumentList as l, TrialContribution as m, Annotation as n, AnnotationInit as o, AnnotationPatch as p, AnnotationQuery as q, AnnotationStatus as r, AnnotationStoreOptions as s, AnnotationTargetInfo as t, CanvasCapability as u, CanvasLayer as v, CaptureDeps as w, FracRect as y, IconComponent as z };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { R as ResolvedConfig,
|
|
3
|
+
import { R as ResolvedConfig, c as ControlRenderer } from './types-B9_zrHmb.js';
|
|
4
|
+
import { C as ConfigField } from './types-x92Kfeme.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* How much room a container gives its rows — gaps, padding, and field height,
|
|
@@ -143,10 +144,24 @@ declare function SliderRow({ label, value, min, max, step, onChange, onInput, fo
|
|
|
143
144
|
interface ColorRowProps extends PropertyMetricProps {
|
|
144
145
|
label: ReactNode;
|
|
145
146
|
value: string;
|
|
147
|
+
/**
|
|
148
|
+
* The committed color. Given `onInput` as well, it fires once the picker
|
|
149
|
+
* closes; on its own it fires on every move inside it, which is what a row
|
|
150
|
+
* with one callback has always done.
|
|
151
|
+
*/
|
|
146
152
|
onChange: (next: string) => void;
|
|
153
|
+
/**
|
|
154
|
+
* The live color, fired continuously while the picker is open. Pass it
|
|
155
|
+
* alongside `onChange` when the write is expensive — cheap state here, the
|
|
156
|
+
* costly work there. Mirrors `<Slider>`'s `onInput` / `onChange` pair.
|
|
157
|
+
*/
|
|
158
|
+
onInput?: (next: string) => void;
|
|
147
159
|
/** 0..1 alpha. When provided, a translucent slider renders beneath the swatch. */
|
|
148
160
|
alpha?: number;
|
|
161
|
+
/** The committed alpha, on the same terms as `onChange`. */
|
|
149
162
|
onAlphaChange?: (next: number) => void;
|
|
163
|
+
/** The live alpha, on the same terms as `onInput`. */
|
|
164
|
+
onAlphaInput?: (next: number) => void;
|
|
150
165
|
/**
|
|
151
166
|
* Render the alpha track as inert (dimmed, no thumb, not-allowed cursor).
|
|
152
167
|
* Use when the color's consumer drops alpha so the affordance reads dead.
|
|
@@ -159,7 +174,7 @@ interface ColorRowProps extends PropertyMetricProps {
|
|
|
159
174
|
span?: boolean;
|
|
160
175
|
}
|
|
161
176
|
/** A color swatch, optionally with an alpha slider beneath it. */
|
|
162
|
-
declare function ColorRow({ label, value, onChange, alpha, onAlphaChange, alphaDisabled, layout, description, span, density, align, }: ColorRowProps): react_jsx_runtime.JSX.Element;
|
|
177
|
+
declare function ColorRow({ label, value, onChange, onInput, alpha, onAlphaChange, onAlphaInput, alphaDisabled, layout, description, span, density, align, }: ColorRowProps): react_jsx_runtime.JSX.Element;
|
|
163
178
|
/** Props for `<CheckboxRow>`. */
|
|
164
179
|
interface CheckboxRowProps extends PropertyMetricProps {
|
|
165
180
|
label: ReactNode;
|
|
@@ -191,7 +206,18 @@ declare function TextRow({ label, value, onChange, placeholder, maxLength, layou
|
|
|
191
206
|
interface NumberRowProps extends PropertyMetricProps {
|
|
192
207
|
label: ReactNode;
|
|
193
208
|
value: number;
|
|
209
|
+
/**
|
|
210
|
+
* The committed value. Given `onInput` as well, it fires on blur or Enter;
|
|
211
|
+
* on its own it fires on every keystroke, which is what a row with one
|
|
212
|
+
* callback has always done.
|
|
213
|
+
*/
|
|
194
214
|
onChange: (next: number) => void;
|
|
215
|
+
/**
|
|
216
|
+
* The live value, fired per keystroke. Pass it alongside `onChange` when the
|
|
217
|
+
* write is expensive — cheap state here, the costly work there. Mirrors
|
|
218
|
+
* `<Slider>`'s `onInput` / `onChange` pair.
|
|
219
|
+
*/
|
|
220
|
+
onInput?: (next: number) => void;
|
|
195
221
|
min?: number;
|
|
196
222
|
max?: number;
|
|
197
223
|
step?: number;
|
|
@@ -209,7 +235,7 @@ interface NumberRowProps extends PropertyMetricProps {
|
|
|
209
235
|
}
|
|
210
236
|
/** A number typed directly. Reach for `<SliderRow>` when the range matters
|
|
211
237
|
* more than the exact value. */
|
|
212
|
-
declare function NumberRow({ label, value, onChange, min, max, step, placeholder, unit, layout, description, span, density, align, }: NumberRowProps): react_jsx_runtime.JSX.Element;
|
|
238
|
+
declare function NumberRow({ label, value, onChange, onInput, min, max, step, placeholder, unit, layout, description, span, density, align, }: NumberRowProps): react_jsx_runtime.JSX.Element;
|
|
213
239
|
interface PropertyOption<T extends string> {
|
|
214
240
|
value: T;
|
|
215
241
|
label: ReactNode;
|
|
@@ -258,7 +284,9 @@ interface ControlPanelProps<TC extends Record<string, unknown>> {
|
|
|
258
284
|
/** @deprecated Pass `schema`. A field list is adapted into one internally. */
|
|
259
285
|
fields?: ConfigField[];
|
|
260
286
|
config: TC;
|
|
261
|
-
|
|
287
|
+
/** Writes one value. The path is dotted for a leaf inside an `f.group`, and
|
|
288
|
+
* the bare key for one at the root. */
|
|
289
|
+
setConfig: (path: string, value: unknown) => void;
|
|
262
290
|
/**
|
|
263
291
|
* Control overrides and app-defined kinds, PrefsForm-style. Keys are config
|
|
264
292
|
* paths (checked first) or leaf kinds. A renderer returning `null` collapses
|
|
@@ -279,16 +307,21 @@ interface ControlPanelProps<TC extends Record<string, unknown>> {
|
|
|
279
307
|
align?: PropertyAlign;
|
|
280
308
|
/**
|
|
281
309
|
* Fold each section away behind a twisty, starting `'open'` or `'closed'`.
|
|
282
|
-
* Unset draws the heading alone, as the panel always has
|
|
310
|
+
* Unset draws the heading alone, as the panel always has — unless a section
|
|
311
|
+
* in the schema declares how it opens, which makes that section foldable on
|
|
312
|
+
* its own and outranks this for that one section.
|
|
283
313
|
*/
|
|
284
314
|
collapse?: 'open' | 'closed';
|
|
285
315
|
/**
|
|
286
|
-
* Which sections are folded, keyed
|
|
287
|
-
* no state of its own: every toggle arrives at `onCollapse`
|
|
288
|
-
* is where a lab that remembers a trial's sections writes
|
|
316
|
+
* Which sections are folded, keyed as `onCollapse` reports them. Given, the
|
|
317
|
+
* panel keeps no state of its own: every toggle arrives at `onCollapse`
|
|
318
|
+
* instead, which is where a lab that remembers a trial's sections writes
|
|
319
|
+
* them.
|
|
289
320
|
*/
|
|
290
321
|
collapsed?: Readonly<Record<string, boolean>>;
|
|
291
|
-
|
|
322
|
+
/** A fold moved. The key is a section's label — prefixed by its group's
|
|
323
|
+
* dotted path when the section sits inside one — or a group's own path. */
|
|
324
|
+
onCollapse?: (key: string, collapsed: boolean) => void;
|
|
292
325
|
/** Draw leaves marked `hidden`. */
|
|
293
326
|
showHidden?: boolean;
|
|
294
327
|
className?: string;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { ToolPrefLeaf, ToolPrefGroup } from '@weasel-js/core';
|
|
2
|
+
import { P as PrefRenderer } from './PrefsForm.d-DDHFANkc.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Renders the control cell for one config leaf. Identical to weasel-ui's
|
|
6
|
+
* `PrefRenderer` on purpose — aliased rather than redeclared so the two
|
|
7
|
+
* cannot drift.
|
|
8
|
+
*/
|
|
9
|
+
type ControlRenderer = PrefRenderer;
|
|
10
|
+
/** One labeled choice in an `enum` leaf. */
|
|
11
|
+
interface ConfigOption {
|
|
12
|
+
value: string;
|
|
13
|
+
label: string;
|
|
14
|
+
}
|
|
15
|
+
/** Everything a leaf can carry beyond its kind and default. A flat union of
|
|
16
|
+
* every `Pref*` leaf's extras, plus labkit's own `debounceMs`. */
|
|
17
|
+
interface Annotations {
|
|
18
|
+
name?: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
hidden?: boolean;
|
|
21
|
+
block?: boolean;
|
|
22
|
+
pair?: string;
|
|
23
|
+
min?: number;
|
|
24
|
+
max?: number;
|
|
25
|
+
step?: number;
|
|
26
|
+
suffix?: string;
|
|
27
|
+
control?: string;
|
|
28
|
+
options?: readonly ConfigOption[];
|
|
29
|
+
placeholder?: string;
|
|
30
|
+
maxLength?: number;
|
|
31
|
+
/** Milliseconds to debounce a string leaf's live writes. Default 150. */
|
|
32
|
+
debounceMs?: number;
|
|
33
|
+
}
|
|
34
|
+
/** What a rule contributes. `kind` is honored only while it is still unset,
|
|
35
|
+
* which is what makes `f.value` claimable and a kinded factory final. */
|
|
36
|
+
type LeafPatch = Annotations & {
|
|
37
|
+
kind?: string;
|
|
38
|
+
};
|
|
39
|
+
/** What a rule is given for the leaf it is deciding about. */
|
|
40
|
+
interface ConfigRuleContext {
|
|
41
|
+
/** The leaf's own key — its last path segment, and what a label is titled
|
|
42
|
+
* from. */
|
|
43
|
+
key: string;
|
|
44
|
+
/** Dotted path within the schema, which is the path the value is written
|
|
45
|
+
* at. Equal to `key` for a leaf sitting at the root. */
|
|
46
|
+
path: string;
|
|
47
|
+
/** The leaf's default value. A rule may read it but never change it. */
|
|
48
|
+
default: unknown;
|
|
49
|
+
/** What earlier rules and the author's own annotations have settled. */
|
|
50
|
+
leaf: Readonly<LeafPatch>;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Decides part of how a leaf is presented. Returns a patch, or null to
|
|
54
|
+
* abstain. Merging is gap-filling: a property already settled is never
|
|
55
|
+
* overwritten, so the author's annotations beat every rule and a consumer's
|
|
56
|
+
* rules beat labkit's built-ins.
|
|
57
|
+
*/
|
|
58
|
+
type ConfigRule = (ctx: ConfigRuleContext) => LeafPatch | null;
|
|
59
|
+
/** A presentational bucket of nodes, rendered under one heading. Buckets
|
|
60
|
+
* siblings: a section never nests a value, which is what separates it from
|
|
61
|
+
* `f.group`. */
|
|
62
|
+
interface SectionSpec {
|
|
63
|
+
/** Dotted path of the group whose children this buckets. `''` is the root,
|
|
64
|
+
* which is where every section of a flat schema sits. */
|
|
65
|
+
at: string;
|
|
66
|
+
label: string;
|
|
67
|
+
/** Full dotted paths, so a section under a group names its children the way
|
|
68
|
+
* everything else does. */
|
|
69
|
+
paths: readonly string[];
|
|
70
|
+
/** Whether the section opens folded. Set, the panel folds this section
|
|
71
|
+
* whether or not it was given a panel-wide `collapse`; a fold the reader
|
|
72
|
+
* has since toggled outranks it. */
|
|
73
|
+
collapsed?: boolean;
|
|
74
|
+
}
|
|
75
|
+
/** A schema resolved against a set of rules: the vocabulary weasel-ui renders,
|
|
76
|
+
* plus the three things labkit keeps on the side because `PrefLeaf` has no
|
|
77
|
+
* field for them. */
|
|
78
|
+
interface ResolvedConfig {
|
|
79
|
+
/** The schema as a `PrefGroup` tree: an `f.group` is a nested group, so a
|
|
80
|
+
* leaf's dotted path within it is the path its value is written at. */
|
|
81
|
+
group: ToolPrefGroup;
|
|
82
|
+
sections: readonly SectionSpec[];
|
|
83
|
+
showIf: ReadonlyMap<string, (config: Record<string, unknown>) => boolean>;
|
|
84
|
+
/** Node-level `.render` overrides, keyed by path. */
|
|
85
|
+
renderers: Readonly<Record<string, ControlRenderer>>;
|
|
86
|
+
}
|
|
87
|
+
/** How a node names the section it belongs to: the heading, and how that
|
|
88
|
+
* section opens. Every node in one section repeats the heading; only one of
|
|
89
|
+
* them has to say `collapsed`. */
|
|
90
|
+
interface SectionOption {
|
|
91
|
+
label: string;
|
|
92
|
+
collapsed?: boolean;
|
|
93
|
+
}
|
|
94
|
+
/** Per-node extras that do not belong on a `PrefLeaf`. */
|
|
95
|
+
interface NodeOptions extends BranchOptions {
|
|
96
|
+
render?: ControlRenderer;
|
|
97
|
+
validate?: (leaf: ToolPrefLeaf) => string[];
|
|
98
|
+
}
|
|
99
|
+
/** What a branch can say about itself, beyond its children. */
|
|
100
|
+
interface BranchOptions {
|
|
101
|
+
section?: SectionOption;
|
|
102
|
+
/** Show this node only while the predicate holds. On a group it hides the
|
|
103
|
+
* whole subtree; the values stay in config either way. */
|
|
104
|
+
showIf?: (config: Record<string, unknown>) => boolean;
|
|
105
|
+
}
|
|
106
|
+
/** A group's own annotations: what it is called and, optionally, why. */
|
|
107
|
+
interface BranchAnnotations {
|
|
108
|
+
name?: string;
|
|
109
|
+
description?: string;
|
|
110
|
+
}
|
|
111
|
+
/** The builder's leaf: a kind (or null, to be decided by rules), a default,
|
|
112
|
+
* an annotation bag, and the extras above. */
|
|
113
|
+
interface ConfigNode<T = unknown> {
|
|
114
|
+
readonly kind: string | null;
|
|
115
|
+
readonly default: T;
|
|
116
|
+
readonly annotations: Readonly<Annotations>;
|
|
117
|
+
readonly options: Readonly<NodeOptions>;
|
|
118
|
+
}
|
|
119
|
+
/** The builder's branch: named children, nested as deeply as the schema
|
|
120
|
+
* wants. A branch nests the value too — `grid: f.group({ size })` puts the
|
|
121
|
+
* value at `grid.size`, where `.section('Grid')` would have left it at
|
|
122
|
+
* `size`. */
|
|
123
|
+
interface ConfigBranch<S extends ConfigShape = ConfigShape> {
|
|
124
|
+
readonly children: S;
|
|
125
|
+
readonly annotations: Readonly<BranchAnnotations>;
|
|
126
|
+
readonly options: Readonly<BranchOptions>;
|
|
127
|
+
}
|
|
128
|
+
/** Either half of a schema tree. */
|
|
129
|
+
type ConfigEntry = ConfigNode | ConfigBranch;
|
|
130
|
+
/** The children of a schema or a group. */
|
|
131
|
+
type ConfigShape = {
|
|
132
|
+
readonly [key: string]: ConfigEntry;
|
|
133
|
+
};
|
|
134
|
+
/** The value type a node produces. */
|
|
135
|
+
type NodeValue<N> = N extends ConfigNode<infer T> ? T : never;
|
|
136
|
+
/** The value type a schema entry produces — a leaf's own, or a branch's
|
|
137
|
+
* nested record. */
|
|
138
|
+
type EntryValue<E> = E extends ConfigBranch<infer S> ? InferConfig<S> : E extends ConfigNode<infer T> ? T : never;
|
|
139
|
+
/** The config type a builder shape produces. */
|
|
140
|
+
type InferConfig<S> = {
|
|
141
|
+
[K in keyof S]: EntryValue<S[K]>;
|
|
142
|
+
};
|
|
143
|
+
/** Whether a config value has children a path can descend into. Arrays and
|
|
144
|
+
* functions are values, not branches. */
|
|
145
|
+
type Branching<V> = V extends readonly unknown[] ? false : V extends (...args: never[]) => unknown ? false : V extends object ? true : false;
|
|
146
|
+
/**
|
|
147
|
+
* Every dotted path a config offers, a group's own path included. A config
|
|
148
|
+
* whose shape is not known — `unknown`, or a bare record — gives `string`,
|
|
149
|
+
* which is what keeps a generic instrument writable.
|
|
150
|
+
*/
|
|
151
|
+
type ConfigPath<T> = unknown extends T ? string : T extends object ? {
|
|
152
|
+
[K in keyof T & string]: Branching<T[K]> extends true ? K | `${K}.${ConfigPath<T[K]>}` : K;
|
|
153
|
+
}[keyof T & string] : never;
|
|
154
|
+
/** The type at a dotted path, or `unknown` where the path is not one the
|
|
155
|
+
* config's type spells out. */
|
|
156
|
+
type ValueAtPath<T, P extends string> = unknown extends T ? unknown : P extends `${infer Head}.${infer Rest}` ? Head extends keyof T ? ValueAtPath<T[Head], Rest> : unknown : P extends keyof T ? T[P] : unknown;
|
|
157
|
+
/** An instrument's config, declared once. */
|
|
158
|
+
interface ConfigSchema<TC> {
|
|
159
|
+
readonly nodes: ConfigShape;
|
|
160
|
+
/** The starting config — what `defaultConfig()` would have returned. */
|
|
161
|
+
defaults(): TC;
|
|
162
|
+
}
|
|
163
|
+
/** The config type behind a schema: `ConfigOf<typeof sceneConfig>`. */
|
|
164
|
+
type ConfigOf<S> = S extends ConfigSchema<infer TC> ? TC : never;
|
|
165
|
+
|
|
166
|
+
export type { Annotations as A, BranchAnnotations as B, ConfigPath as C, EntryValue as E, InferConfig as I, LeafPatch as L, NodeOptions as N, ResolvedConfig as R, SectionSpec as S, ValueAtPath as V, ConfigSchema as a, ConfigNode as b, ControlRenderer as c, ConfigOption as d, ConfigShape as e, ConfigBranch as f, BranchOptions as g, ConfigEntry as h, ConfigRule as i, ConfigRuleContext as j, ConfigOf as k, NodeValue as l };
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { C as ConfigPath, V as ValueAtPath } from './types-B9_zrHmb.js';
|
|
2
|
+
|
|
1
3
|
/** A sidebar section torn out of its trial, and where it went. */
|
|
2
4
|
interface UndockedPanel {
|
|
3
5
|
trialId: string;
|
|
@@ -101,7 +103,9 @@ interface TrialStateHandle<TS, TC> {
|
|
|
101
103
|
state: TS;
|
|
102
104
|
setState: (next: TS | ((prev: TS) => TS)) => void;
|
|
103
105
|
config: TC;
|
|
104
|
-
|
|
106
|
+
/** Write one config value, by dotted path — `'grid.size'` for a leaf under
|
|
107
|
+
* an `f.group`, `'cellSize'` for one at the root. */
|
|
108
|
+
setConfig: <P extends ConfigPath<TC> & string>(path: P, value: ValueAtPath<TC, P>) => void;
|
|
105
109
|
}
|
|
106
110
|
/** Options for `createLabStore`. `storageKey` namespaces the keys written, so
|
|
107
111
|
* two labs on one origin do not collide. */
|
|
@@ -109,12 +113,26 @@ interface CreateLabStoreOptions {
|
|
|
109
113
|
storageKey: string;
|
|
110
114
|
storage: StorageAdapter;
|
|
111
115
|
initialMode?: LabMode;
|
|
116
|
+
/** Each instrument's default config, keyed by instrument name, used to fill
|
|
117
|
+
* the gaps in a stored one. A config saved before its schema grew a branch
|
|
118
|
+
* arrives holding that branch's defaults rather than `undefined`, and keeps
|
|
119
|
+
* whatever keys the schema has since stopped naming. `<Lab>` collects these
|
|
120
|
+
* off its `instruments`. */
|
|
121
|
+
configDefaults?: Record<string, () => unknown>;
|
|
122
|
+
/** How each instrument's state survives a reload. Hydration is the first
|
|
123
|
+
* thing `createLabStore` does, so these have to arrive with the store —
|
|
124
|
+
* anything registered afterwards is already too late to read the document
|
|
125
|
+
* it was built from. `<Lab>` collects them off its `instruments`. */
|
|
126
|
+
serializers?: InstrumentSerializers;
|
|
112
127
|
}
|
|
113
128
|
/** Per-instrument serialize/deserialize hooks, keyed by instrument name. An
|
|
114
|
-
* instrument whose state is already JSON-safe needs no entry.
|
|
129
|
+
* instrument whose state is already JSON-safe needs no entry. `deserialize`
|
|
130
|
+
* is handed the config the state was saved against — a trial's own for a
|
|
131
|
+
* reload, the snapshot's for a load — since a state rebuilt without it can
|
|
132
|
+
* disagree with the settings sitting next to it. */
|
|
115
133
|
type InstrumentSerializers = Record<string, {
|
|
116
134
|
serialize?: (state: unknown) => unknown;
|
|
117
|
-
deserialize?: (data: unknown) => unknown;
|
|
135
|
+
deserialize?: (data: unknown, config: unknown) => unknown;
|
|
118
136
|
} | undefined>;
|
|
119
137
|
/** A trial as it is persisted: everything but the undo history, which is
|
|
120
138
|
* session-only. */
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/** Which control a config field is edited with. */
|
|
2
|
+
type ConfigFieldType = 'slider' | 'checkbox' | 'select' | 'number' | 'text' | 'color';
|
|
3
|
+
/** What every config field carries: the config key it writes, the label shown
|
|
4
|
+
* beside it, and which control renders it. */
|
|
5
|
+
interface ConfigFieldBase {
|
|
6
|
+
key: string;
|
|
7
|
+
label: string;
|
|
8
|
+
type: ConfigFieldType;
|
|
9
|
+
}
|
|
10
|
+
/** A bounded number edited by dragging. */
|
|
11
|
+
interface SliderField extends ConfigFieldBase {
|
|
12
|
+
type: 'slider';
|
|
13
|
+
default: number;
|
|
14
|
+
min: number;
|
|
15
|
+
max: number;
|
|
16
|
+
step?: number;
|
|
17
|
+
}
|
|
18
|
+
/** A boolean. */
|
|
19
|
+
interface CheckboxField extends ConfigFieldBase {
|
|
20
|
+
type: 'checkbox';
|
|
21
|
+
default: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** One choice in a select field. */
|
|
24
|
+
interface SelectOption {
|
|
25
|
+
value: string;
|
|
26
|
+
label: string;
|
|
27
|
+
}
|
|
28
|
+
/** A fixed set of labeled choices. */
|
|
29
|
+
interface SelectField extends ConfigFieldBase {
|
|
30
|
+
type: 'select';
|
|
31
|
+
default: string;
|
|
32
|
+
options: SelectOption[];
|
|
33
|
+
}
|
|
34
|
+
/** A number typed directly, optionally bounded. Use a slider field instead
|
|
35
|
+
* when the range matters more than the exact value. */
|
|
36
|
+
interface NumberField extends ConfigFieldBase {
|
|
37
|
+
type: 'number';
|
|
38
|
+
default: number;
|
|
39
|
+
min?: number;
|
|
40
|
+
max?: number;
|
|
41
|
+
step?: number;
|
|
42
|
+
}
|
|
43
|
+
/** A free-text string. Writes are debounced so typing does not re-run the
|
|
44
|
+
* instrument on every keystroke. */
|
|
45
|
+
interface TextField extends ConfigFieldBase {
|
|
46
|
+
type: 'text';
|
|
47
|
+
default: string;
|
|
48
|
+
placeholder?: string;
|
|
49
|
+
maxLength?: number;
|
|
50
|
+
/** Milliseconds to debounce live setConfig calls. Default 150 ms. Set to 0 to disable. */
|
|
51
|
+
debounceMs?: number;
|
|
52
|
+
}
|
|
53
|
+
/** A color, as a CSS color string. */
|
|
54
|
+
interface ColorField extends ConfigFieldBase {
|
|
55
|
+
type: 'color';
|
|
56
|
+
default: string;
|
|
57
|
+
}
|
|
58
|
+
/** One field of an instrument's config schema. The schema is what the control
|
|
59
|
+
* panel renders, and what `validateConfigSchema` checks. */
|
|
60
|
+
type ConfigField = SliderField | CheckboxField | SelectField | NumberField | TextField | ColorField;
|
|
61
|
+
|
|
62
|
+
export type { ConfigField as C, NumberField as N, SelectField as S, TextField as T, CheckboxField as a, ColorField as b, ConfigFieldBase as c, ConfigFieldType as d, SelectOption as e, SliderField as f };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as StorageAdapter, b as LabStoreState, T as TrialRecord, c as SavedSnapshot, h as LabMode, e as UndockedPanel,
|
|
1
|
+
import { a as StorageAdapter, b as LabStoreState, T as TrialRecord, c as SavedSnapshot, h as LabMode, e as UndockedPanel, C as CreateLabStoreOptions, d as TrialStateHandle } from './types-BP2OCcpg.js';
|
|
2
2
|
import * as react from 'react';
|
|
3
3
|
import { ReactNode, ReactElement } from 'react';
|
|
4
4
|
import { StoreApi } from 'zustand/vanilla';
|
|
@@ -23,7 +23,9 @@ interface LabStoreActions {
|
|
|
23
23
|
addTrial: (record: Omit<TrialRecord, 'undoStack'>) => void;
|
|
24
24
|
removeTrial: (id: string) => void;
|
|
25
25
|
updateTrialState: <TS>(id: string, next: TS | ((prev: TS) => TS)) => void;
|
|
26
|
-
|
|
26
|
+
/** Write one config value. `path` is dotted for a value nested under an
|
|
27
|
+
* `f.group`, and the bare key for one at the root. */
|
|
28
|
+
updateTrialConfig: (id: string, path: string, value: unknown) => void;
|
|
27
29
|
updateTrialView: (id: string, view: unknown) => void;
|
|
28
30
|
updateTrialSidebarWidth: (id: string, width: number) => void;
|
|
29
31
|
/** Retitle a trial. `null` returns it to its instrument's name. */
|
|
@@ -46,11 +48,9 @@ interface LabStoreActions {
|
|
|
46
48
|
/** Put one section back, or — with no `sectionId` — every panel the trial owns. */
|
|
47
49
|
dockPanel: (trialId: string, sectionId?: string) => void;
|
|
48
50
|
}
|
|
49
|
-
/** A lab's store: its state and actions
|
|
50
|
-
*
|
|
51
|
-
type LabStore = StoreApi<LabStoreState & LabStoreActions
|
|
52
|
-
registerSerializers: (s: InstrumentSerializers) => void;
|
|
53
|
-
};
|
|
51
|
+
/** A lab's store: its state and its actions. How each instrument's state is
|
|
52
|
+
* serialized comes in through `CreateLabStoreOptions.serializers`. */
|
|
53
|
+
type LabStore = StoreApi<LabStoreState & LabStoreActions>;
|
|
54
54
|
/** Build a lab store, hydrating from storage if anything was saved under the
|
|
55
55
|
* same key. Writes back are debounced. */
|
|
56
56
|
declare function createLabStore(options: CreateLabStoreOptions): LabStore;
|
package/dist/canvas/index.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode, WheelEvent, PointerEvent as PointerEvent$1 } from 'react';
|
|
3
|
-
import { V as ViewTransform, c as WorldSpec, a2 as ViewportSize, a as Point, W as WorldFrame } from '../_dts/frac-
|
|
4
|
-
export { x as DEFAULT_FRAME, a4 as applyCamera, aa as resolveFrame } from '../_dts/frac-
|
|
5
|
-
import { C as CanvasLayerDescriptor } from '../_dts/CanvasStackContext-
|
|
6
|
-
export { a as CanvasStackContext, b as CanvasStackContextValue, c as CanvasStackSurface } from '../_dts/CanvasStackContext-
|
|
7
|
-
import '../_dts/types-
|
|
8
|
-
import '
|
|
9
|
-
import '../_dts/PrefsForm.d-
|
|
10
|
-
import '../_dts/types-
|
|
3
|
+
import { V as ViewTransform, c as WorldSpec, a2 as ViewportSize, a as Point, W as WorldFrame } from '../_dts/frac-z7ker2Vx.js';
|
|
4
|
+
export { x as DEFAULT_FRAME, a4 as applyCamera, aa as resolveFrame } from '../_dts/frac-z7ker2Vx.js';
|
|
5
|
+
import { C as CanvasLayerDescriptor } from '../_dts/CanvasStackContext-kTEZvEgE.js';
|
|
6
|
+
export { a as CanvasStackContext, b as CanvasStackContextValue, c as CanvasStackSurface } from '../_dts/CanvasStackContext-kTEZvEgE.js';
|
|
7
|
+
import '../_dts/types-B9_zrHmb.js';
|
|
8
|
+
import '@weasel-js/core';
|
|
9
|
+
import '../_dts/PrefsForm.d-DDHFANkc.js';
|
|
10
|
+
import '../_dts/types-x92Kfeme.js';
|
|
11
|
+
import '../_dts/types-BP2OCcpg.js';
|
|
11
12
|
import '../_dts/types-DJ79Tg5J.js';
|
|
12
13
|
|
|
13
14
|
/** Props for `<CanvasStack>`. */
|
package/dist/canvas/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
export { CanvasStack, PITCH_LIMIT, clampPitch, orbitAfterDrag, orbitAfterWheel, useOrbit, usePanZoom, wrapYaw } from '../chunk-
|
|
1
|
+
export { CanvasStack, PITCH_LIMIT, clampPitch, orbitAfterDrag, orbitAfterWheel, useOrbit, usePanZoom, wrapYaw } from '../chunk-I6JCVE24.js';
|
|
2
2
|
export { centerOn, zoomAt } from '../chunk-CTRKTLYZ.js';
|
|
3
3
|
export { DEFAULT_FRAME, applyCamera, resolveFrame, screenToWorld, worldToScreen } from '../chunk-2AYGEN57.js';
|
|
4
4
|
export { CanvasStackContext } from '../chunk-CQLQPQ4P.js';
|
|
5
|
-
import '../chunk-54ZWZ5FQ.js';
|
|
6
5
|
//# sourceMappingURL=index.js.map
|
|
7
6
|
//# sourceMappingURL=index.js.map
|
package/dist/chrome/index.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { c as ControlRenderer } from '../_dts/types-
|
|
2
|
-
import { I as Instrument, _ as TrialChromeContext, m as TrialContribution } from '../_dts/frac-
|
|
3
|
-
export { z as IconComponent, O as SidebarSection, Q as StatusReadout, Y as ToolItem, Z as ToolbarItem, $ as TrialRegion, a1 as ViewportControl } from '../_dts/frac-
|
|
1
|
+
import { c as ControlRenderer } from '../_dts/types-B9_zrHmb.js';
|
|
2
|
+
import { I as Instrument, _ as TrialChromeContext, m as TrialContribution } from '../_dts/frac-z7ker2Vx.js';
|
|
3
|
+
export { z as IconComponent, O as SidebarSection, Q as StatusReadout, Y as ToolItem, Z as ToolbarItem, $ as TrialRegion, a1 as ViewportControl } from '../_dts/frac-z7ker2Vx.js';
|
|
4
4
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
|
-
import '
|
|
5
|
+
import '@weasel-js/core';
|
|
6
|
+
import '../_dts/PrefsForm.d-DDHFANkc.js';
|
|
6
7
|
import 'react';
|
|
7
|
-
import '../_dts/
|
|
8
|
-
import '../_dts/types-
|
|
8
|
+
import '../_dts/types-x92Kfeme.js';
|
|
9
|
+
import '../_dts/types-BP2OCcpg.js';
|
|
9
10
|
import '../_dts/types-DJ79Tg5J.js';
|
|
10
11
|
|
|
11
12
|
/**
|
package/dist/chrome/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, ViewportRegion, builtinContributions, mergeContributions, suppressContributions } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-
|
|
1
|
+
export { PaletteRegion, SidebarRegion, StatusRegion, TitleBarRegion, ToolbarRegion, ViewportRegion, builtinContributions, mergeContributions, suppressContributions } from '../chunk-64ZCN3DA.js';
|
|
2
|
+
import '../chunk-SMHP6XZ4.js';
|
|
3
|
+
import '../chunk-U3IYHIAE.js';
|
|
4
|
+
import '../chunk-E44SU6XS.js';
|
|
4
5
|
import '../chunk-SBXNQW4G.js';
|
|
5
|
-
import '../chunk-
|
|
6
|
+
import '../chunk-W3ECWC2K.js';
|
|
6
7
|
import '../chunk-CQLQPQ4P.js';
|
|
7
|
-
import '../chunk-54ZWZ5FQ.js';
|
|
8
8
|
//# sourceMappingURL=index.js.map
|
|
9
9
|
//# sourceMappingURL=index.js.map
|