@weasel-js/labkit 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_dts/{CanvasStackContext-DQgcH1ny.d.ts → CanvasStackContext-D2jnIwfk.d.ts} +1 -1
- package/dist/_dts/FloatingPanel-7j0IcXwz.d.ts +30 -0
- package/dist/_dts/{LayerList.d-2c9yup5Y.d.ts → LayerList.d-DiuEArKq.d.ts} +4 -4
- package/dist/_dts/PrefsRow.d-TOZ7BgD9.d.ts +79 -0
- package/dist/_dts/PropertyPanel.d-D-1paCbE.d.ts +141 -0
- package/dist/_dts/{Select.d-BchGMC2Y.d.ts → Select.d-Bensr_MT.d.ts} +15 -6
- package/dist/_dts/Stage-CCWfQQWM.d.ts +202 -0
- package/dist/_dts/index-B2Yj5aA0.d.ts +274 -0
- package/dist/_dts/{index-B0--8PEM.d.ts → index-CsYqUHD3.d.ts} +12 -13
- package/dist/_dts/{types-B7y8hX1D.d.ts → types-CRPSGFAp.d.ts} +33 -5
- package/dist/_dts/{frac-DTRq7Xpb.d.ts → types-CSm9jgol.d.ts} +700 -650
- package/dist/_dts/{useTrialState-CP4jfuKl.d.ts → useTrialState-CTZPgeZ7.d.ts} +2 -3
- package/dist/canvas/index.d.ts +40 -8
- package/dist/canvas/index.js +5 -3
- package/dist/chrome/index.d.ts +5 -6
- package/dist/chrome/index.js +9 -7
- package/dist/chunk-24W5VEJW.js +18 -0
- package/dist/chunk-24W5VEJW.js.map +1 -0
- package/dist/chunk-275JRRVD.js +728 -0
- package/dist/chunk-275JRRVD.js.map +1 -0
- package/dist/chunk-3RY6WL5T.js +38 -0
- package/dist/chunk-3RY6WL5T.js.map +1 -0
- package/dist/chunk-4LJSC7MB.js +143 -0
- package/dist/chunk-4LJSC7MB.js.map +1 -0
- package/dist/{chunk-3FI7Y4R4.js → chunk-7BO7HNGF.js} +5 -5
- package/dist/{chunk-3FI7Y4R4.js.map → chunk-7BO7HNGF.js.map} +1 -1
- package/dist/chunk-AWQG7FCC.js +19 -0
- package/dist/chunk-AWQG7FCC.js.map +1 -0
- package/dist/chunk-CZZPXUOU.js +3 -0
- package/dist/{chunk-SBXNQW4G.js.map → chunk-CZZPXUOU.js.map} +1 -1
- package/dist/{chunk-ZORVNOKX.js → chunk-FMK7UQ6V.js} +24 -145
- package/dist/chunk-FMK7UQ6V.js.map +1 -0
- package/dist/{chunk-BVL7Y574.js → chunk-FZ7YFQN7.js} +26 -10
- package/dist/chunk-FZ7YFQN7.js.map +1 -0
- package/dist/{chunk-USO6TERP.js → chunk-GOZLNM4L.js} +11 -9
- package/dist/chunk-GOZLNM4L.js.map +1 -0
- package/dist/{chunk-H5VIV7MQ.js → chunk-I5DUQ5HM.js} +88 -82
- package/dist/chunk-I5DUQ5HM.js.map +1 -0
- package/dist/chunk-J7OWWTCW.js +143 -0
- package/dist/chunk-J7OWWTCW.js.map +1 -0
- package/dist/{chunk-H6ZAOWNE.js → chunk-JVBYV6TL.js} +3 -3
- package/dist/{chunk-H6ZAOWNE.js.map → chunk-JVBYV6TL.js.map} +1 -1
- package/dist/{chunk-VQ47KWD5.js → chunk-KMJ7RWD3.js} +18 -7
- package/dist/chunk-KMJ7RWD3.js.map +1 -0
- package/dist/{chunk-ERFMC6WU.js → chunk-M7HP3FTK.js} +20 -11
- package/dist/chunk-M7HP3FTK.js.map +1 -0
- package/dist/chunk-MIM5R4ZT.js +14972 -0
- package/dist/chunk-MIM5R4ZT.js.map +1 -0
- package/dist/{chunk-HFRE4QQV.js → chunk-T5IBSPAM.js} +96 -32
- package/dist/chunk-T5IBSPAM.js.map +1 -0
- package/dist/chunk-UNAZSLWE.js +294 -0
- package/dist/chunk-UNAZSLWE.js.map +1 -0
- package/dist/{chunk-RS3HRQWU.js → chunk-WPLAANH4.js} +4 -3
- package/dist/chunk-WPLAANH4.js.map +1 -0
- package/dist/{chunk-AWH3SRPW.js → chunk-Y23G2VZL.js} +5 -37
- package/dist/chunk-Y23G2VZL.js.map +1 -0
- package/dist/{chunk-MOLIUNVH.js → chunk-YT75VYRD.js} +4 -4
- package/dist/{chunk-MOLIUNVH.js.map → chunk-YT75VYRD.js.map} +1 -1
- package/dist/chunk-ZIFPHIWZ.js +302 -0
- package/dist/chunk-ZIFPHIWZ.js.map +1 -0
- package/dist/config/index.d.ts +48 -40
- package/dist/config/index.js +4 -5
- package/dist/controls/index.d.ts +91 -7
- package/dist/controls/index.js +5 -4
- package/dist/dragdrop/index.d.ts +9 -7
- package/dist/dragdrop/index.js +3 -2
- package/dist/index.d.ts +294 -82
- package/dist/index.js +425 -402
- package/dist/index.js.map +1 -1
- package/dist/layers/index.d.ts +4 -5
- package/dist/layers/index.js +2 -1
- package/dist/loupe/index.d.ts +20 -17
- package/dist/loupe/index.js +5 -3
- package/dist/overview/index.d.ts +56 -0
- package/dist/overview/index.js +289 -0
- package/dist/overview/index.js.map +1 -0
- package/dist/passthrough/weasel-ui.d.ts +239 -69
- package/dist/passthrough/weasel-ui.js +3 -2
- package/dist/primitives/index.d.ts +5 -204
- package/dist/primitives/index.js +6 -4
- package/dist/state/index.d.ts +8 -8
- package/dist/state/index.js +4 -5
- package/dist/state/index.js.map +1 -1
- package/dist/styles.css +152 -82
- package/dist/undo/index.d.ts +4 -4
- package/package.json +17 -12
- package/src/annotations/AnnotationOverlay.tsx +2 -2
- package/src/annotations/Annotations.less +0 -10
- package/src/annotations/MarkList.tsx +4 -8
- package/src/annotations/index.ts +1 -0
- package/src/annotations/paint.test.ts +3 -14
- package/src/annotations/paint.ts +3 -19
- package/src/annotations/store.test.ts +26 -0
- package/src/annotations/store.ts +25 -6
- package/src/annotations/svgNodes.test.ts +6 -9
- package/src/annotations/svgNodes.ts +3 -3
- package/src/annotations/toolMap.test.ts +37 -2
- package/src/annotations/toolMap.ts +13 -0
- package/src/annotations/types.ts +27 -0
- package/src/canvas/AGENTS.md +9 -10
- package/src/canvas/CameraInput.test.tsx +136 -0
- package/src/canvas/CameraInput.tsx +322 -0
- package/src/canvas/CanvasStack.tsx +47 -58
- package/src/canvas/LinkedCursor.less +16 -0
- package/src/canvas/LinkedCursor.tsx +54 -0
- package/src/canvas/Stage.test.tsx +33 -4
- package/src/canvas/Stage.tsx +47 -37
- package/src/canvas/cameraRegistry.test.ts +55 -0
- package/src/canvas/cameraRegistry.ts +86 -0
- package/src/canvas/cameraView.test.ts +60 -0
- package/src/canvas/cameraView.ts +61 -0
- package/src/canvas/cameraZoom.test.ts +46 -0
- package/src/canvas/cameraZoom.ts +24 -0
- package/src/canvas/index.ts +23 -2
- package/src/canvas/sharedScope.test.tsx +94 -0
- package/src/chrome/ChromeRegions.stories.tsx +1 -0
- package/src/chrome/regions/PaletteRegion.less +0 -7
- package/src/chrome/regions/SidebarRegion.less +12 -2
- package/src/chrome/regions/SidebarRegion.test.tsx +9 -2
- package/src/config/builder.test.ts +2 -1
- package/src/config/builder.ts +15 -8
- package/src/config/entry.test.ts +3 -1
- package/src/config/fromConfigField.test.ts +14 -0
- package/src/config/fromConfigField.ts +19 -4
- package/src/config/index.ts +4 -1
- package/src/config/path.ts +2 -5
- package/src/config/resolve.ts +15 -1
- package/src/config/sectionTree.test.ts +12 -6
- package/src/config/sectionTree.ts +15 -5
- package/src/config/types.ts +34 -9
- package/src/controls/ControlPanel.less +1 -1
- package/src/controls/ControlPanel.stories.tsx +3 -2
- package/src/controls/ControlPanel.test.tsx +76 -13
- package/src/controls/ControlPanel.tsx +80 -11
- package/src/controls/inDialog.test.tsx +18 -0
- package/src/controls/inDialog.tsx +2 -10
- package/src/index.test.ts +1 -1
- package/src/index.ts +23 -5
- package/src/instrument/SineWave.smoke.test.tsx +2 -0
- package/src/instrument/types.ts +10 -1
- package/src/lab/Lab.nebula.test.tsx +11 -2
- package/src/lab/Lab.test.tsx +3 -1
- package/src/lab/Lab.tsx +87 -76
- package/src/lab/{LabFit.stories.less → LabFit.browser.test.less} +1 -1
- package/src/lab/{LabFit.stories.tsx → LabFit.browser.test.tsx} +41 -63
- package/src/lab/LabFullChrome.stories.tsx +1 -0
- package/src/lab/LabHeader.test.tsx +24 -14
- package/src/lab/LabHeader.tsx +11 -12
- package/src/lab/LabShell.less +8 -17
- package/src/lab/LabSwitcher.less +6 -6
- package/src/lab/LabZoom.test.tsx +223 -0
- package/src/lab/LabZoom.tsx +170 -0
- package/src/lab/index.ts +1 -0
- package/src/loupe/AGENTS.md +7 -6
- package/src/loupe/LoupeGestures.tsx +15 -10
- package/src/loupe/TrialLoupe.tsx +5 -5
- package/src/loupe/index.ts +1 -0
- package/src/loupe/loupeActions.ts +6 -2
- package/src/overview/AGENTS.md +38 -0
- package/src/overview/OverviewMarks.test.tsx +100 -0
- package/src/overview/OverviewMarks.tsx +93 -0
- package/src/overview/TrialOverview.less +53 -0
- package/src/overview/TrialOverview.stories.tsx +50 -0
- package/src/overview/TrialOverview.test.tsx +116 -0
- package/src/overview/TrialOverview.tsx +376 -0
- package/src/overview/index.ts +2 -0
- package/src/passthrough/weasel-ui.test.ts +2 -0
- package/src/passthrough/weasel-ui.ts +23 -4
- package/src/primitives/FloatingPanel.test.tsx +11 -0
- package/src/primitives/FloatingPanel.tsx +2 -5
- package/src/primitives/JobProgress.less +1 -1
- package/src/primitives/Legend.stories.tsx +1 -0
- package/src/primitives/Readout.browser.test.tsx +137 -0
- package/src/primitives/Readout.less +12 -0
- package/src/primitives/Readout.stories.tsx +58 -0
- package/src/primitives/Readout.test.tsx +93 -0
- package/src/primitives/Readout.tsx +56 -0
- package/src/primitives/index.ts +2 -0
- package/src/specimen/Specimen.stories.tsx +1 -0
- package/src/specimen/Specimen.tsx +21 -4
- package/src/state/Persistence.browser.test.tsx +47 -0
- package/src/state/labRecords.test.ts +4 -1
- package/src/state/store.test.ts +9 -5
- package/src/state/usePersistedState.test.tsx +1 -1
- package/src/state/useTrialState.test.tsx +1 -1
- package/src/styles.less +3 -0
- package/src/theme/Interstellar.stories.tsx +4 -6
- package/src/theme/base.less +21 -47
- package/src/theme/interstellar.test.ts +1 -1
- package/src/theme/interstellar.theme.json +10 -3
- package/src/tools/labTool.ts +6 -2
- package/src/trial/Trial.annotations.test.tsx +16 -0
- package/src/trial/Trial.less +0 -13
- package/src/trial/Trial.loupe.test.tsx +73 -1
- package/src/trial/Trial.stories.tsx +2 -0
- package/src/trial/Trial.tsx +23 -1
- package/src/trial/TrialChrome.tsx +21 -3
- package/src/trial/trialOps.test.ts +4 -4
- package/dist/_dts/PrefsRow.d-DFpPIeIC.d.ts +0 -39
- package/dist/_dts/inDialog-D5ZKGjiD.d.ts +0 -23
- package/dist/_dts/index-DINmCuLA.d.ts +0 -453
- package/dist/_dts/number.d-OeQYQoUO.d.ts +0 -28
- package/dist/_dts/usePanZoom-Bq73pwFe.d.ts +0 -117
- package/dist/chunk-2AYGEN57.js +0 -32
- package/dist/chunk-2AYGEN57.js.map +0 -1
- package/dist/chunk-AWH3SRPW.js.map +0 -1
- package/dist/chunk-BVL7Y574.js.map +0 -1
- package/dist/chunk-ERFMC6WU.js.map +0 -1
- package/dist/chunk-H5VIV7MQ.js.map +0 -1
- package/dist/chunk-HFRE4QQV.js.map +0 -1
- package/dist/chunk-RS3HRQWU.js.map +0 -1
- package/dist/chunk-SBXNQW4G.js +0 -3
- package/dist/chunk-TT5C5S6R.js +0 -368
- package/dist/chunk-TT5C5S6R.js.map +0 -1
- package/dist/chunk-USO6TERP.js.map +0 -1
- package/dist/chunk-VQ47KWD5.js.map +0 -1
- package/dist/chunk-WUJXJC5O.js +0 -14568
- package/dist/chunk-WUJXJC5O.js.map +0 -1
- package/dist/chunk-ZORVNOKX.js.map +0 -1
- package/src/canvas/usePanZoom.test.ts +0 -244
- package/src/canvas/usePanZoom.ts +0 -147
- package/src/state/Persistence.stories.tsx +0 -75
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { RefObject } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { b as ViewTransform, W as WorldFrame } from './types-CSm9jgol.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. */
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import react__default, { ReactNode } from 'react';
|
|
2
|
+
import { Corner } from 'windease';
|
|
3
|
+
|
|
4
|
+
/** Props for `<FloatingPanel>`. */
|
|
5
|
+
interface FloatingPanelProps {
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
/** Corner it rests in before it has ever been dragged. Default `'bottom-left'`. */
|
|
8
|
+
anchor?: Corner;
|
|
9
|
+
/** Corners that may capture it. Default: all four. */
|
|
10
|
+
snapCorners?: readonly Corner[];
|
|
11
|
+
/** Pixels in from a corner when snapped. Default 12. */
|
|
12
|
+
inset?: number;
|
|
13
|
+
/** Name to remember its position under, through `usePersistedState` — so it
|
|
14
|
+
* is remembered only inside a lab or a `<Persistence>`. Omit to forget on
|
|
15
|
+
* reload. */
|
|
16
|
+
persist?: string;
|
|
17
|
+
className?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A draggable box that floats over its offset parent and snaps to its corners.
|
|
21
|
+
*
|
|
22
|
+
* Drives windease's `floatingStrategy` as a pure function rather than mounting a
|
|
23
|
+
* windease container: a lab overlay has one item and no zone tree, so the node
|
|
24
|
+
* model would be all cost. Pointer handling is therefore this component's, and
|
|
25
|
+
* windease's own affordance rendering never participates.
|
|
26
|
+
*/
|
|
27
|
+
declare function FloatingPanel({ children, anchor, snapCorners, inset, persist, className, }: FloatingPanelProps): react__default.JSX.Element;
|
|
28
|
+
|
|
29
|
+
export { FloatingPanel as a };
|
|
30
|
+
export type { FloatingPanelProps as F };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { S as StanceProps } from './PrefsRow.d-
|
|
3
|
+
import { S as StanceProps } from './PrefsRow.d-TOZ7BgD9.js';
|
|
4
4
|
|
|
5
5
|
/** One layer. With a body (see `renderBody`) it draws as a card that folds its
|
|
6
6
|
* body away; without one, as a one-line row. Either can hold child layers. */
|
|
@@ -49,7 +49,7 @@ interface LayerListProps {
|
|
|
49
49
|
onSelect?: (ids: string[]) => void;
|
|
50
50
|
/** Adds a visibility checkbox to every unlocked layer. */
|
|
51
51
|
onVisibilityChange?: (id: string, visible: boolean) => void;
|
|
52
|
-
/** Adds a
|
|
52
|
+
/** Adds a remove button to every unlocked layer. */
|
|
53
53
|
onRemove?: (id: string) => void;
|
|
54
54
|
/** A layer's controls. Returning `null` leaves that layer a one-line row. */
|
|
55
55
|
renderBody?: (item: LayerListItem) => ReactNode;
|
|
@@ -77,7 +77,7 @@ declare function moveLayers(items: LayerListItem[], move: LayerMove): LayerListI
|
|
|
77
77
|
* card whose controls fold away; either can nest child layers. Selection,
|
|
78
78
|
* visibility, removal and an add palette are each on when their handler is given.
|
|
79
79
|
*/
|
|
80
|
-
declare function LayerList(props: LayerListProps):
|
|
80
|
+
declare function LayerList(props: LayerListProps): react.JSX.Element;
|
|
81
81
|
|
|
82
82
|
export { LayerList as L, moveLayers as m };
|
|
83
83
|
export type { LayerListItem as a, LayerListProps as b, LayerMove as c };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Stance } from '@weasel-js/theme';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { ToolPrefLeaf } from '@weasel-js/core';
|
|
4
|
+
|
|
5
|
+
/** What one unit is worth in base units: `base = value * factor + offset`. */
|
|
6
|
+
interface UnitScale {
|
|
7
|
+
factor: number;
|
|
8
|
+
/** Where this unit puts zero, in base units. Absent is 0 — a pure scale. */
|
|
9
|
+
offset?: number;
|
|
10
|
+
}
|
|
11
|
+
/** One unit's conversion. A bare number is the `{ factor }` shorthand. */
|
|
12
|
+
type UnitEntry = number | UnitScale;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* How a number shows, speaks and reads back, as plain data: `{ kind: 'fraction',
|
|
16
|
+
* maxDenominator: 64 }`. Data rather than a function so a tagged value keeps its
|
|
17
|
+
* presentation through JSON, history snapshots and `structuredClone`. The
|
|
18
|
+
* behavior lives on the registered {@link DisplayKind} of the same `kind`.
|
|
19
|
+
*/
|
|
20
|
+
interface Display {
|
|
21
|
+
readonly kind: string;
|
|
22
|
+
readonly [option: string]: unknown;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Display-formatter for numbers. Use this anywhere a number is shown to
|
|
27
|
+
* a user. The whole point: negative values get prefixed with the real
|
|
28
|
+
* MINUS SIGN (U+2212) instead of the ASCII HYPHEN-MINUS (U+002D) that
|
|
29
|
+
* `toLocaleString` and template literals produce by default.
|
|
30
|
+
*
|
|
31
|
+
* U+2212 is the same visual width as `+` and reads as a sign rather
|
|
32
|
+
* than a hyphen — columns of signed numbers align cleanly and the
|
|
33
|
+
* glyph doesn't get confused with a bullet or list dash.
|
|
34
|
+
*/
|
|
35
|
+
declare const MINUS_SIGN = "\u2212";
|
|
36
|
+
/**
|
|
37
|
+
* Formats a number for display, substituting {@link MINUS_SIGN} for the ASCII
|
|
38
|
+
* hyphen `toLocaleString` emits. Non-finite values stringify as-is.
|
|
39
|
+
*/
|
|
40
|
+
declare function formatNumber(value: number, options?: Intl.NumberFormatOptions): string;
|
|
41
|
+
/** Suffixes a person may type, each mapped to its conversion into the shown unit. */
|
|
42
|
+
type UnitTable = Record<string, UnitEntry>;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* What a surface holds, and which of its peers it is. Every surface that takes
|
|
46
|
+
* these takes both, and the theme decides how each looks.
|
|
47
|
+
*/
|
|
48
|
+
interface StanceProps {
|
|
49
|
+
/** The class of content the surface holds. Omitted, it draws as it always has. */
|
|
50
|
+
stance?: Stance;
|
|
51
|
+
/**
|
|
52
|
+
* Which of its peers this is: an index into the theme's tone list, wrapping,
|
|
53
|
+
* or a color given directly. Independent of `stance`, and allowed without one.
|
|
54
|
+
*/
|
|
55
|
+
tone?: number | string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** What a {@link PrefRenderer} is given for the leaf it is rendering. */
|
|
59
|
+
interface PrefRenderContext {
|
|
60
|
+
/** Dotted path of the leaf within the schema root. */
|
|
61
|
+
path: string;
|
|
62
|
+
/** The schema node. App renderers narrow this to their own kind shape. */
|
|
63
|
+
pref: ToolPrefLeaf;
|
|
64
|
+
/** Current value — `values` at `path`, falling back to `pref.default`. */
|
|
65
|
+
value: unknown;
|
|
66
|
+
setValue: (value: unknown) => void;
|
|
67
|
+
/** Whether this leaf is currently auto — not pinned, computed by the owner. */
|
|
68
|
+
auto: boolean;
|
|
69
|
+
/** Toggle this leaf's auto state. */
|
|
70
|
+
setAuto: (next: boolean) => void;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Renders the control cell for one preference leaf. Returning `null`
|
|
74
|
+
* collapses the row.
|
|
75
|
+
*/
|
|
76
|
+
type PrefRenderer = (ctx: PrefRenderContext) => ReactNode;
|
|
77
|
+
|
|
78
|
+
export { MINUS_SIGN as M, formatNumber as f };
|
|
79
|
+
export type { Display as D, PrefRenderer as P, StanceProps as S, UnitTable as U, PrefRenderContext as a };
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { S as StanceProps } from './PrefsRow.d-TOZ7BgD9.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* How much room a container gives its rows — gaps, padding, and field height,
|
|
7
|
+
* moved together. Set on any container in the family; it reaches every
|
|
8
|
+
* descendant, so an inner group can differ from the panel around it.
|
|
9
|
+
*/
|
|
10
|
+
type PropertyDensity = 'tight' | 'normal' | 'roomy';
|
|
11
|
+
/** Where an inline row's label and control sit on the row's cross axis. Set on
|
|
12
|
+
* a container to line a whole column of them up. */
|
|
13
|
+
type PropertyAlign = 'start' | 'center' | 'end' | 'baseline';
|
|
14
|
+
/** Metric props every container in the family takes. Both reach descendants,
|
|
15
|
+
* so the nearest container that states one wins. */
|
|
16
|
+
interface PropertyMetricProps {
|
|
17
|
+
/** Room the rows get. Unset inherits from an outer container, else `normal`. */
|
|
18
|
+
density?: PropertyDensity;
|
|
19
|
+
/**
|
|
20
|
+
* Cross-axis alignment of an inline row's label and control. `baseline` sits
|
|
21
|
+
* the control on the label's first-line baseline, which is what lines a
|
|
22
|
+
* column of swatches up against labels of different heights. Unset keeps each
|
|
23
|
+
* variant's own alignment — a color row centers its label and swatch and
|
|
24
|
+
* sinks the pair to the row's bottom edge, which keeps a paired alpha track
|
|
25
|
+
* level with its neighbour.
|
|
26
|
+
*/
|
|
27
|
+
align?: PropertyAlign;
|
|
28
|
+
}
|
|
29
|
+
/** Props for `<PropertyPanel>`. */
|
|
30
|
+
interface PropertyPanelProps extends PropertyMetricProps, StanceProps {
|
|
31
|
+
title?: ReactNode;
|
|
32
|
+
/** Controls on the trailing edge of the title row — a switch, a clear
|
|
33
|
+
* button. They sit outside the heading, so they neither take its type nor
|
|
34
|
+
* join its accessible name. */
|
|
35
|
+
actions?: ReactNode;
|
|
36
|
+
/**
|
|
37
|
+
* Lets text inside the panel be selected and copied. A panel is chrome by
|
|
38
|
+
* default, so a drag across it moves a slider rather than painting a
|
|
39
|
+
* selection; a `debug` panel defaults to selectable, since what it shows —
|
|
40
|
+
* ids, keys, traces — is there to be copied.
|
|
41
|
+
*/
|
|
42
|
+
selectable?: boolean;
|
|
43
|
+
children: ReactNode;
|
|
44
|
+
className?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* A titled panel holding property rows — the sidebar container the rest of
|
|
48
|
+
* this module's components fill.
|
|
49
|
+
*
|
|
50
|
+
* `stance` says what kind of content it holds and `tone` which of its peers it
|
|
51
|
+
* is; the theme's `--wzl-panel-*` and `--wzl-stance-*` slots decide how each looks. A stanced
|
|
52
|
+
* panel's title takes the row-label recipe rather than the display title.
|
|
53
|
+
*/
|
|
54
|
+
declare function PropertyPanel({ title, actions, selectable, children, className, density, align, stance, tone, }: PropertyPanelProps): react.JSX.Element;
|
|
55
|
+
/** How a property list packs its rows into two columns. */
|
|
56
|
+
type PropertyListPack = 'auto-color' | 'pairs' | 'one-up';
|
|
57
|
+
/** Props for `<PropertyList>`. */
|
|
58
|
+
interface PropertyListProps extends PropertyMetricProps {
|
|
59
|
+
children: ReactNode;
|
|
60
|
+
className?: string;
|
|
61
|
+
/**
|
|
62
|
+
* How rows pack into the 2-column grid.
|
|
63
|
+
* - `'auto-color'` (default): only color rows pair side-by-side; everything
|
|
64
|
+
* else spans the full width. Right for sparse top-level panels.
|
|
65
|
+
* - `'pairs'`: every row auto-places into the 2-column grid two-per-row.
|
|
66
|
+
* Headers and subpanels still span the full width; wrap any other
|
|
67
|
+
* full-width child in `<PropertySpan>`. Right for dense effect bodies.
|
|
68
|
+
* - `'one-up'`: every row spans the full width, color rows included. Right
|
|
69
|
+
* for a palette — a column of swatches read as a group.
|
|
70
|
+
*/
|
|
71
|
+
pack?: PropertyListPack;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Grid container for PropertyRows. Use standalone for chrome-less layouts, or
|
|
75
|
+
* nest inside <PropertyPanel/> for the standard glass card.
|
|
76
|
+
*/
|
|
77
|
+
declare const PropertyList: react.ForwardRefExoticComponent<PropertyListProps & react.RefAttributes<HTMLDivElement>>;
|
|
78
|
+
/** Props for `<PropertySpan>`. */
|
|
79
|
+
interface PropertySpanProps {
|
|
80
|
+
children: ReactNode;
|
|
81
|
+
className?: string;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Wrapper that makes an arbitrary child span both columns of a
|
|
85
|
+
* `<PropertyList pack="pairs">`, a `<PropertyGroup pack="pairs">` body, or a
|
|
86
|
+
* `<Subpanel>`. `<PropertyRow span>` covers the row case; this covers
|
|
87
|
+
* everything else a consumer puts in the grid.
|
|
88
|
+
*/
|
|
89
|
+
declare function PropertySpan({ children, className }: PropertySpanProps): react.JSX.Element;
|
|
90
|
+
/** Which control shape a row holds, which decides its intrinsic layout. */
|
|
91
|
+
type PropertyRowVariant = 'default' | 'color' | 'checkbox';
|
|
92
|
+
/** Whether a row's label sits above its control or beside it. */
|
|
93
|
+
type PropertyRowLayout = 'block' | 'inline';
|
|
94
|
+
/** Props for `<PropertyRow>`. */
|
|
95
|
+
interface PropertyRowProps extends PropertyMetricProps {
|
|
96
|
+
label: ReactNode;
|
|
97
|
+
/** Right-aligned readout shown next to the label (e.g. current value). */
|
|
98
|
+
readout?: ReactNode;
|
|
99
|
+
/**
|
|
100
|
+
* Help text for the row, shown in a tooltip off an ⓘ affordance beside the
|
|
101
|
+
* label. Empty or absent renders no affordance.
|
|
102
|
+
*/
|
|
103
|
+
description?: string;
|
|
104
|
+
variant?: PropertyRowVariant;
|
|
105
|
+
/**
|
|
106
|
+
* Label position relative to the control. Unset takes the variant's own
|
|
107
|
+
* orientation: `block` — label above control — for the default variant, and
|
|
108
|
+
* `inline` for the color and checkbox variants, which read as a row.
|
|
109
|
+
*/
|
|
110
|
+
layout?: PropertyRowLayout;
|
|
111
|
+
/**
|
|
112
|
+
* Take the full width of the enclosing grid. Only has an effect inside a
|
|
113
|
+
* `<PropertyList pack="pairs">` or a `<Subpanel>`; elsewhere rows are already
|
|
114
|
+
* full width.
|
|
115
|
+
*/
|
|
116
|
+
span?: boolean;
|
|
117
|
+
children: ReactNode;
|
|
118
|
+
htmlFor?: string;
|
|
119
|
+
/** The control is a group of several (a segmented toggle), not one element.
|
|
120
|
+
* The row then renders as a `<div>`: a `<label>` hands a click on its text to
|
|
121
|
+
* its first control, which in a group means selecting the first option. Each
|
|
122
|
+
* member has to carry its own name. */
|
|
123
|
+
group?: boolean;
|
|
124
|
+
className?: string;
|
|
125
|
+
/** The row is auto: its value is not pinned and the owner computes it. The
|
|
126
|
+
* control is hidden — its box kept, so the row does not resize — and the
|
|
127
|
+
* row reads out the word instead. */
|
|
128
|
+
auto?: boolean;
|
|
129
|
+
/** Given, the row's label toggles `auto` when it is clicked. Omitted, the row
|
|
130
|
+
* can show an auto state but not change it.
|
|
131
|
+
*
|
|
132
|
+
* The label then names that toggle, so a control passed as `children` has to
|
|
133
|
+
* carry its own accessible name — every `<PropertyField>` does. */
|
|
134
|
+
onAutoChange?: (next: boolean) => void;
|
|
135
|
+
}
|
|
136
|
+
/** The label-plus-control frame `<PropertyField>` draws its rows in. Use it
|
|
137
|
+
* directly for a control no field kind covers. */
|
|
138
|
+
declare function PropertyRow({ label, readout, description, variant, layout, span, children, htmlFor, group, className, density, align, auto, onAutoChange, }: PropertyRowProps): react.JSX.Element;
|
|
139
|
+
|
|
140
|
+
export { PropertyList as c, PropertyPanel as e, PropertyRow as g, PropertySpan as j };
|
|
141
|
+
export type { PropertyMetricProps as P, PropertyRowLayout as a, PropertyListPack as b, PropertyListProps as d, PropertyPanelProps as f, PropertyRowProps as h, PropertyRowVariant as i, PropertySpanProps as k, PropertyAlign as l, PropertyDensity as m };
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
1
|
import * as react from 'react';
|
|
3
2
|
import { ReactNode, ButtonHTMLAttributes, ReactElement } from 'react';
|
|
4
|
-
import { S as StanceProps } from './PrefsRow.d-
|
|
3
|
+
import { S as StanceProps } from './PrefsRow.d-TOZ7BgD9.js';
|
|
5
4
|
import { TextFieldProps, ValidationResult, SelectProps as SelectProps$1, ListBoxItemProps } from 'react-aria-components';
|
|
6
5
|
|
|
7
6
|
declare const ICON_PATHS: {
|
|
@@ -29,6 +28,12 @@ declare const ICON_PATHS: {
|
|
|
29
28
|
readonly superscript: "<path d=\"M3.6 8.6 10.4 16.4M10.4 8.6 3.6 16.4\"/><path d=\"M11.9 5.3a2.2 2.2 0 1 1 4.3.8c0 1.4-4.3 2.2-4.3 3.5h4.5\"/>";
|
|
30
29
|
readonly subscript: "<path d=\"M3.6 3.6 10.4 11.4M10.4 3.6 3.6 11.4\"/><path d=\"M11.9 11.5a2.2 2.2 0 1 1 4.3.8c0 1.4-4.3 2.2-4.3 3.5h4.5\"/>";
|
|
31
30
|
readonly code: "<path d=\"M7 6.2 3.2 10 7 13.8M13 6.2 16.8 10 13 13.8\"/><path d=\"M11.2 4.8 8.8 15.2\"/>";
|
|
31
|
+
readonly textAlignLeft: "<path d=\"M3 4.375H17M3 8.125H12M3 11.875H17M3 15.625H12\"/>";
|
|
32
|
+
readonly textAlignCenter: "<path d=\"M3 4.375H17M5.5 8.125H14.5M3 11.875H17M5.5 15.625H14.5\"/>";
|
|
33
|
+
readonly textAlignRight: "<path d=\"M3 4.375H17M8 8.125H17M3 11.875H17M8 15.625H17\"/>";
|
|
34
|
+
readonly textAlignTop: "<rect x=\"1.875\" y=\"1.875\" width=\"16.25\" height=\"16.25\" rx=\"2\" stroke-width=\"1\"/><path d=\"M5.5 5.625H14.5M7 9.375H13\"/>";
|
|
35
|
+
readonly textAlignMiddle: "<rect x=\"1.875\" y=\"1.875\" width=\"16.25\" height=\"16.25\" rx=\"2\" stroke-width=\"1\"/><path d=\"M5.5 8.125H14.5M7 11.875H13\"/>";
|
|
36
|
+
readonly textAlignBottom: "<rect x=\"1.875\" y=\"1.875\" width=\"16.25\" height=\"16.25\" rx=\"2\" stroke-width=\"1\"/><path d=\"M5.5 10.625H14.5M7 14.375H13\"/>";
|
|
32
37
|
readonly play: "<path d=\"M7.6 5.2 15.6 10 7.6 14.8Z\"/>";
|
|
33
38
|
readonly pause: "<path d=\"M7.8 5.2v9.6M12.2 5.2v9.6\"/>";
|
|
34
39
|
readonly stop: "<rect x=\"5.6\" y=\"5.6\" width=\"8.8\" height=\"8.8\" rx=\"1.4\"/>";
|
|
@@ -47,6 +52,10 @@ declare const ICON_PATHS: {
|
|
|
47
52
|
readonly modeLight: "<circle cx=\"10\" cy=\"10\" r=\"3.5\"/><path d=\"M15.3 10L17.7 10M13.75 6.25L15.44 4.56M10 4.7L10 2.3M6.25 6.25L4.56 4.56M4.7 10L2.3 10M6.25 13.75L4.56 15.44M10 15.3L10 17.7M13.75 13.75L15.44 15.44\"/>";
|
|
48
53
|
readonly modeDark: "<path d=\"M8.19 3.55A6.7 6.7 0 1 0 16.45 11.81A5.9 5.9 0 0 1 8.19 3.55Z\"/>";
|
|
49
54
|
readonly modeAuto: "<path d=\"M10 2.6Q10 10 17.4 10Q10 10 10 17.4Q10 10 2.6 10Q10 10 10 2.6Z\"/>";
|
|
55
|
+
readonly statusSuccess: "<circle cx=\"10\" cy=\"10\" r=\"7\"/><path d=\"M6.84 10.33 8.89 12.38 13.17 7.62\"/>";
|
|
56
|
+
readonly statusAccent: "<circle cx=\"10\" cy=\"10\" r=\"7\" fill=\"currentColor\"/>";
|
|
57
|
+
readonly statusNeutral: "<path d=\"M10 3A7 7 0 0 1 10 17Z\" fill=\"currentColor\" stroke=\"none\"/><circle cx=\"10\" cy=\"10\" r=\"7\"/>";
|
|
58
|
+
readonly statusMuted: "<path d=\"M11.44 3.15A7 7 0 0 0 8.56 3.15M4.79 5.33A7 7 0 0 0 3.35 7.82M3.35 12.18A7 7 0 0 0 4.79 14.67M8.56 16.85A7 7 0 0 0 11.44 16.85M15.21 14.67A7 7 0 0 0 16.65 12.18M16.65 7.82A7 7 0 0 0 15.21 5.33\"/>";
|
|
50
59
|
readonly crosshair: "<circle cx=\"10\" cy=\"10\" r=\"5.6\"/><path d=\"M10 2.8v4.4M10 12.8v4.4M2.8 10h4.4M12.8 10h4.4\"/>";
|
|
51
60
|
readonly fullscreen: "<path d=\"M11.6 3.6h4.8v4.8M8.4 16.4H3.6v-4.8\"/><path d=\"M16.4 3.6 11.2 8.8M3.6 16.4 8.8 11.2\"/>";
|
|
52
61
|
readonly compare: "<rect x=\"3.4\" y=\"4.6\" width=\"13.2\" height=\"10.8\" rx=\"1.6\"/><path d=\"M10 4.6v10.8\" stroke-width=\"1\"/><path d=\"M5.2 7.6h3.4M5.2 10h2.6M5.2 12.4h3.4\" stroke-width=\"1\"/><path d=\"M11.4 7.6h3.4M11.4 10h3.4M11.4 12.4h1.8\" stroke-width=\"1\"/>";
|
|
@@ -239,7 +248,7 @@ interface IconProps {
|
|
|
239
248
|
* in; reach for this when the glyph is chosen at runtime. */
|
|
240
249
|
declare function Icon({ name, className, size, label, filled, fillOpacity, }: IconProps & {
|
|
241
250
|
name: IconName;
|
|
242
|
-
}):
|
|
251
|
+
}): react.JSX.Element;
|
|
243
252
|
|
|
244
253
|
/** The tooltip fields a segmented bar's item carries. */
|
|
245
254
|
interface SegmentTooltipFields {
|
|
@@ -407,7 +416,7 @@ type FieldProps = {
|
|
|
407
416
|
* compose Field internally. Use Field directly when you need a custom
|
|
408
417
|
* control to sit in the same visual rhythm.
|
|
409
418
|
*/
|
|
410
|
-
declare function Field({ orientation, className, children }: FieldProps):
|
|
419
|
+
declare function Field({ orientation, className, children }: FieldProps): react.JSX.Element;
|
|
411
420
|
/**
|
|
412
421
|
* The class names {@link Field} paints its slots with, so a control composing
|
|
413
422
|
* its own layout can match the same form-row rhythm.
|
|
@@ -553,7 +562,7 @@ type SelectProps<T extends Key = string> = Omit<SelectProps$1<object>, 'children
|
|
|
553
562
|
* `aria-label` or a string `label`, as `Button` does; `tooltip` replaces that
|
|
554
563
|
* text.
|
|
555
564
|
*/
|
|
556
|
-
declare function Select<T extends Key = string>(props: SelectProps<T>):
|
|
565
|
+
declare function Select<T extends Key = string>(props: SelectProps<T>): react.JSX.Element;
|
|
557
566
|
/** Props for {@link SelectItem}, on top of React Aria's `ListBoxItem` props. */
|
|
558
567
|
type SelectItemProps = Omit<ListBoxItemProps, 'className' | 'children'> & {
|
|
559
568
|
children?: ReactNode;
|
|
@@ -564,7 +573,7 @@ type SelectItemProps = Omit<ListBoxItemProps, 'className' | 'children'> & {
|
|
|
564
573
|
* selected. A string child supplies its own `textValue`; anything richer must
|
|
565
574
|
* pass one so type-to-select and screen readers have something to read.
|
|
566
575
|
*/
|
|
567
|
-
declare function SelectItem({ children, className, textValue, ...rest }: SelectItemProps):
|
|
576
|
+
declare function SelectItem({ children, className, textValue, ...rest }: SelectItemProps): react.JSX.Element;
|
|
568
577
|
|
|
569
578
|
export { Button as B, Select as S, ToggleBar as T, Icon as d, Input as e, Field as m, ICON_PATHS as o, SelectItem as q, fieldClasses as t };
|
|
570
579
|
export type { FieldOrientation as F, IconProps as I, OverlayPortalProps as O, WithoutPortalTarget as W, ButtonProps as a, ButtonSize as b, ButtonVariant as c, InputProps as f, SelectProps as g, ToggleBarItem as h, ToggleBarProps as i, ToggleBarSize as j, ToggleBarVariant as k, SegmentTooltipFields as l, FieldProps as n, IconName as p, SelectItemProps as r, SelectOption as s };
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { RefObject, ReactNode } from 'react';
|
|
3
|
+
import { ViewApi, Yoke } from '@weasel-js/core';
|
|
4
|
+
import { W as WorldFrame, P as Point, b as ViewTransform, l as WorldSpec, V as ViewportSize } from './types-CSm9jgol.js';
|
|
5
|
+
import { C as CanvasLayerDescriptor } from './CanvasStackContext-D2jnIwfk.js';
|
|
6
|
+
|
|
7
|
+
/** The view id the stage publishes its pointer under. */
|
|
8
|
+
declare const STAGE_VIEW_ID = "stage";
|
|
9
|
+
/**
|
|
10
|
+
* A camera, as the things that sit beside it read it: an overview, a loupe, a
|
|
11
|
+
* linked cursor. Points are *frame-local* — the world with `y` multiplied by
|
|
12
|
+
* `frame.yDir` — which is the space `view` works in.
|
|
13
|
+
*/
|
|
14
|
+
interface CameraContextValue {
|
|
15
|
+
/** The camera as a weasel `ViewApi`, clamped to its zoom range. */
|
|
16
|
+
view: ViewApi;
|
|
17
|
+
frame: WorldFrame;
|
|
18
|
+
/** The element the camera's dispatcher listens on. */
|
|
19
|
+
element: () => HTMLElement | null;
|
|
20
|
+
/** The content's own rect, frame-local, when it has one — a `<Stage>`'s. */
|
|
21
|
+
content?: {
|
|
22
|
+
x: number;
|
|
23
|
+
y: number;
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/** The camera around the caller, or `null` outside one. */
|
|
29
|
+
declare const CameraContext: react.Context<CameraContextValue | null>;
|
|
30
|
+
/**
|
|
31
|
+
* The input scope a camera routes through. Inside another camera — a loupe or
|
|
32
|
+
* an overlay laid over a canvas stack — it joins that camera's scope, so its
|
|
33
|
+
* actions reach the dispatcher already listening there. Anywhere else it
|
|
34
|
+
* mounts a scope of its own, which keeps its own tool unless it joins `yoke`:
|
|
35
|
+
* a camera beside another never takes that one's gestures. The pointer store is the exception — one
|
|
36
|
+
* already in scope is kept, since sharing it is the point.
|
|
37
|
+
*/
|
|
38
|
+
declare function CameraScope({ yoke, children }: {
|
|
39
|
+
yoke?: Yoke;
|
|
40
|
+
children: ReactNode;
|
|
41
|
+
}): react.JSX.Element;
|
|
42
|
+
/** Options for {@link useCameraView}. */
|
|
43
|
+
interface CameraViewOptions {
|
|
44
|
+
view: ViewTransform;
|
|
45
|
+
onViewChange: (v: ViewTransform) => void;
|
|
46
|
+
frame: WorldFrame;
|
|
47
|
+
hostRef: RefObject<HTMLElement | null>;
|
|
48
|
+
minZoom?: number;
|
|
49
|
+
maxZoom?: number;
|
|
50
|
+
}
|
|
51
|
+
/** A camera's zoom limits, after widening to admit its opening zoom. */
|
|
52
|
+
interface ZoomRange {
|
|
53
|
+
min: number;
|
|
54
|
+
max: number;
|
|
55
|
+
}
|
|
56
|
+
/** A labkit camera: a weasel `ViewApi` that also says how far it zooms. */
|
|
57
|
+
interface CameraView extends ViewApi {
|
|
58
|
+
zoomRange(): ZoomRange;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A labkit camera as a stable `ViewApi`. Its zoom range is widened to keep the
|
|
62
|
+
* opening zoom reachable — captured once, so a zoom-out cannot shrink the
|
|
63
|
+
* range and strand the opening view behind it.
|
|
64
|
+
*/
|
|
65
|
+
declare function useCameraView({ view, onViewChange, frame, hostRef, minZoom, maxZoom, }: CameraViewOptions): CameraView;
|
|
66
|
+
/** Props for `<CameraInput>`. */
|
|
67
|
+
interface CameraInputProps {
|
|
68
|
+
hostRef: RefObject<HTMLElement | null>;
|
|
69
|
+
/** Published to the host's camera registry while its scope is the active
|
|
70
|
+
* one, so chrome acting on "the camera" acts on the one last used. */
|
|
71
|
+
camera: CameraView;
|
|
72
|
+
frame: WorldFrame;
|
|
73
|
+
/** A primary-button press released without crossing the drag threshold, at
|
|
74
|
+
* the world point it landed on. */
|
|
75
|
+
onTap?: (world: Point) => void;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Mounts the dispatcher on `hostRef` and routes the camera's gestures through
|
|
79
|
+
* it. Render it inside a `<CameraScope>`; with no actions registry in scope it
|
|
80
|
+
* renders nothing.
|
|
81
|
+
*/
|
|
82
|
+
declare function CameraInput(props: CameraInputProps): react.JSX.Element | null;
|
|
83
|
+
|
|
84
|
+
/** Props for `<CanvasStack>`. */
|
|
85
|
+
interface CanvasStackProps {
|
|
86
|
+
layers: CanvasLayerDescriptor[];
|
|
87
|
+
view: ViewTransform;
|
|
88
|
+
onViewChange: (v: ViewTransform) => void;
|
|
89
|
+
/** The instrument's coordinate system. Omitted, world (0,0) sits at the
|
|
90
|
+
* element's top-left with y running down. */
|
|
91
|
+
worldSpec?: WorldSpec;
|
|
92
|
+
minZoom?: number;
|
|
93
|
+
maxZoom?: number;
|
|
94
|
+
width?: number | string;
|
|
95
|
+
height?: number | string;
|
|
96
|
+
className?: string;
|
|
97
|
+
/** Fired whenever the stack is measured, so a consumer can place a view that
|
|
98
|
+
* only makes sense in terms of the viewport. */
|
|
99
|
+
onResize?: (size: ViewportSize) => void;
|
|
100
|
+
onHitTest?: (worldPos: Point) => void;
|
|
101
|
+
children?: ReactNode;
|
|
102
|
+
/** A yoke to join, from `useYoke()`: cameras on one yoke share their tool
|
|
103
|
+
* and gesture in flight. Omitted, this one keeps its own. */
|
|
104
|
+
yoke?: Yoke;
|
|
105
|
+
}
|
|
106
|
+
/** Stacks one `<canvas>` per layer and drives them from a shared view, so a
|
|
107
|
+
* layer that changes rarely is not redrawn with one that changes every frame.
|
|
108
|
+
* Handles sizing and device pixel ratio; pan and zoom route through weasel's
|
|
109
|
+
* gesture dispatcher (`<CameraInput>`). */
|
|
110
|
+
declare function CanvasStack({ layers, view: viewProp, onViewChange, worldSpec, minZoom, maxZoom, width, height, className, onResize, onHitTest, children, yoke, }: CanvasStackProps): react.JSX.Element;
|
|
111
|
+
|
|
112
|
+
/** Bounds and coordinate system a {@link zoomAt} works in. */
|
|
113
|
+
interface ZoomAtOptions {
|
|
114
|
+
/** The instrument's coordinate system, resolved against the viewport.
|
|
115
|
+
* Omitted, `at` is measured from the element's top-left. */
|
|
116
|
+
frame?: WorldFrame;
|
|
117
|
+
min?: number;
|
|
118
|
+
max?: number;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Zoom a view by `factor` about a fixed point, so whatever world coordinate
|
|
122
|
+
* `at` was over stays under it.
|
|
123
|
+
*
|
|
124
|
+
* `at` is in the element's own pixels — a cursor position, or the centre of a
|
|
125
|
+
* lens. The clamp is applied before the pan is solved, so a zoom that hits a
|
|
126
|
+
* bound still anchors on the zoom it actually reached.
|
|
127
|
+
*/
|
|
128
|
+
declare function zoomAt(view: ViewTransform, factor: number, at: Point, { frame, min, max }?: ZoomAtOptions): ViewTransform;
|
|
129
|
+
/** The view that puts a world point at the centre of a `size` viewport, at
|
|
130
|
+
* `zoom`. What a lens showing a region around one point renders through. */
|
|
131
|
+
declare function centerOn(world: Point, zoom: number, size: ViewportSize, frame?: WorldFrame): ViewTransform;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Cameras by key, for chrome that acts on a camera it does not contain — the
|
|
135
|
+
* lab's zoom controls, which drive whichever trial has the focus.
|
|
136
|
+
*/
|
|
137
|
+
interface CameraRegistry {
|
|
138
|
+
/** Publish `camera` under `key` and return its release. Registrants for one
|
|
139
|
+
* key stack, newest live. */
|
|
140
|
+
register(key: string, camera: CameraView): () => void;
|
|
141
|
+
get(key: string): CameraView | null;
|
|
142
|
+
/** Fires after any register or release. Shaped for `useSyncExternalStore`. */
|
|
143
|
+
subscribe(listener: () => void): () => void;
|
|
144
|
+
}
|
|
145
|
+
declare function createCameraRegistry(): CameraRegistry;
|
|
146
|
+
/** The registry a lab keeps its trials' cameras in. */
|
|
147
|
+
declare const CameraRegistryContext: react.Context<CameraRegistry | null>;
|
|
148
|
+
/** Where a camera publishes itself. The host binds the key — a trial provides
|
|
149
|
+
* one that registers under its own id — so the camera needs no name. */
|
|
150
|
+
declare const CameraPublishContext: react.Context<((camera: CameraView) => () => void) | null>;
|
|
151
|
+
/** Publish `camera` to the host in scope for as long as the caller is mounted,
|
|
152
|
+
* and again each time its input scope becomes the active one — a registry
|
|
153
|
+
* key stacks newest-live, so the camera last used is the one chrome reaches.
|
|
154
|
+
* Call it inside the camera's scope. */
|
|
155
|
+
declare function usePublishCamera(camera: CameraView): void;
|
|
156
|
+
|
|
157
|
+
/** Project a world point into screen coordinates under a view.
|
|
158
|
+
*
|
|
159
|
+
* `frame` is the instrument's declared coordinate system, resolved against the
|
|
160
|
+
* viewport; omitting it gives labkit's original one — origin at the top-left,
|
|
161
|
+
* y downward. */
|
|
162
|
+
declare function worldToScreen(world: Point, view: ViewTransform, frame?: WorldFrame): Point;
|
|
163
|
+
/** Unproject a screen point back to world coordinates under a view. */
|
|
164
|
+
declare function screenToWorld(screen: Point, view: ViewTransform, frame?: WorldFrame): Point;
|
|
165
|
+
|
|
166
|
+
/** Props for `<Stage>`. */
|
|
167
|
+
interface StageProps {
|
|
168
|
+
/** The content's own size in CSS pixels, at zoom 1. */
|
|
169
|
+
size: ViewportSize;
|
|
170
|
+
view: ViewTransform;
|
|
171
|
+
onViewChange: (v: ViewTransform) => void;
|
|
172
|
+
minZoom?: number;
|
|
173
|
+
maxZoom?: number;
|
|
174
|
+
/** Fired whenever the stage's viewport is measured at a non-zero size. */
|
|
175
|
+
onResize?: (viewport: ViewportSize) => void;
|
|
176
|
+
/** Handed the viewport element, for a consumer tracking the pointer over it. */
|
|
177
|
+
hostRef?: {
|
|
178
|
+
current: HTMLDivElement | null;
|
|
179
|
+
};
|
|
180
|
+
/** Drawn over the content in viewport pixels, outside the camera. */
|
|
181
|
+
overlay?: ReactNode;
|
|
182
|
+
children?: ReactNode;
|
|
183
|
+
/** A yoke to join, from `useYoke()`: cameras on one yoke share their tool
|
|
184
|
+
* and gesture in flight. Omitted, this one keeps its own. */
|
|
185
|
+
yoke?: Yoke;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* The camera a stage opens at: the content centered in its viewport, shrunk to
|
|
189
|
+
* fit if it has to be and never enlarged past its own size.
|
|
190
|
+
*/
|
|
191
|
+
declare function fitStage(size: ViewportSize, viewport: ViewportSize): ViewTransform;
|
|
192
|
+
/**
|
|
193
|
+
* DOM content of a fixed size, panned and zoomed by a camera — what
|
|
194
|
+
* `<CanvasStack>` is for layers drawn to a canvas. Pan and zoom route through
|
|
195
|
+
* weasel's gesture dispatcher (`<CameraInput>`). The content is laid out at
|
|
196
|
+
* its own size and transformed, so everything inside keeps its layout and a
|
|
197
|
+
* measurement of any element in it reports where it is actually drawn.
|
|
198
|
+
*/
|
|
199
|
+
declare function Stage({ size, view: viewProp, onViewChange, minZoom, maxZoom, onResize, hostRef, overlay, children, yoke, }: StageProps): react.JSX.Element;
|
|
200
|
+
|
|
201
|
+
export { CameraContext as C, STAGE_VIEW_ID as S, CameraInput as b, CameraPublishContext as d, CameraRegistryContext as f, CameraScope as g, CanvasStack as j, Stage as l, centerOn as o, createCameraRegistry as p, fitStage as q, usePublishCamera as r, screenToWorld as s, useCameraView as u, worldToScreen as w, zoomAt as z };
|
|
202
|
+
export type { ZoomAtOptions as Z, CameraContextValue as a, CameraInputProps as c, CameraRegistry as e, CameraView as h, CameraViewOptions as i, CanvasStackProps as k, StageProps as m, ZoomRange as n };
|