@weasel-js/labkit 1.4.3 → 1.5.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/README.md +13 -2
- package/dist/_dts/{CanvasStackContext-Dde8_1my.d.ts → CanvasStackContext-CqkxkFJW.d.ts} +1 -1
- package/dist/_dts/ToggleBar.d-DbHoWKIA.d.ts +116 -0
- package/dist/_dts/{frac-B5mB8LsJ.d.ts → frac-8R6UmlvN.d.ts} +256 -33
- package/dist/_dts/index-B8uu2ba7.d.ts +237 -0
- package/dist/_dts/{index-DelFfeV0.d.ts → index-retnAut7.d.ts} +45 -12
- package/dist/_dts/{types-B9_zrHmb.d.ts → types-Ca2LCnPq.d.ts} +65 -2
- package/dist/_dts/usePanZoom-nS798rOF.d.ts +160 -0
- package/dist/_dts/useTrialState-jcx_TdU6.d.ts +212 -0
- package/dist/canvas/index.d.ts +17 -128
- package/dist/canvas/index.js +4 -2
- package/dist/chrome/index.d.ts +4 -92
- package/dist/chrome/index.js +9 -5
- package/dist/chunk-67SJLMC7.js +704 -0
- package/dist/chunk-67SJLMC7.js.map +1 -0
- package/dist/chunk-6ZDGOZQV.js +310 -0
- package/dist/chunk-6ZDGOZQV.js.map +1 -0
- package/dist/{chunk-QAGAHJKZ.js → chunk-EKIICY6X.js} +111 -25
- package/dist/chunk-EKIICY6X.js.map +1 -0
- package/dist/{chunk-CTRKTLYZ.js → chunk-H6ZAOWNE.js} +11 -11
- package/dist/chunk-H6ZAOWNE.js.map +1 -0
- package/dist/{chunk-2RQPGOQF.js → chunk-KJALCDWE.js} +9 -7
- package/dist/chunk-KJALCDWE.js.map +1 -0
- package/dist/{chunk-ISCOFAUO.js → chunk-MUKOW3TC.js} +3 -3
- package/dist/{chunk-ISCOFAUO.js.map → chunk-MUKOW3TC.js.map} +1 -1
- package/dist/chunk-NDRYLVOW.js +15 -0
- package/dist/chunk-NDRYLVOW.js.map +1 -0
- package/dist/{chunk-C42T6DJT.js → chunk-NS64DXMN.js} +226 -159
- package/dist/chunk-NS64DXMN.js.map +1 -0
- package/dist/{chunk-I6JCVE24.js → chunk-PGETSEDK.js} +135 -13
- package/dist/chunk-PGETSEDK.js.map +1 -0
- package/dist/{chunk-FQMJUVHJ.js → chunk-QLSV2N3G.js} +32 -37
- package/dist/chunk-QLSV2N3G.js.map +1 -0
- package/dist/chunk-RWNDDKOH.js +682 -0
- package/dist/chunk-RWNDDKOH.js.map +1 -0
- package/dist/chunk-S2SHZRD7.js +7681 -0
- package/dist/chunk-S2SHZRD7.js.map +1 -0
- package/dist/{chunk-ASWKLRKJ.js → chunk-TQBBYTAF.js} +19 -82
- package/dist/chunk-TQBBYTAF.js.map +1 -0
- package/dist/chunk-UU3NJO6N.js +72 -0
- package/dist/chunk-UU3NJO6N.js.map +1 -0
- package/dist/chunk-WIG6XHJ7.js +35 -0
- package/dist/chunk-WIG6XHJ7.js.map +1 -0
- package/dist/{chunk-TJ7QY3OC.js → chunk-ZPH5WTWF.js} +21 -15
- package/dist/chunk-ZPH5WTWF.js.map +1 -0
- package/dist/config/index.d.ts +232 -0
- package/dist/config/index.js +6 -0
- package/dist/config/index.js.map +1 -0
- package/dist/controls/index.d.ts +2 -3
- package/dist/controls/index.js +3 -2
- package/dist/dragdrop/index.d.ts +2 -4
- package/dist/index.d.ts +123 -348
- package/dist/index.js +794 -837
- package/dist/index.js.map +1 -1
- package/dist/layers/index.d.ts +3 -5
- package/dist/layers/index.js +2 -2
- package/dist/loupe/index.d.ts +6 -8
- package/dist/loupe/index.js +2 -2
- package/dist/passthrough/weasel-ui.d.ts +169 -117
- package/dist/passthrough/weasel-ui.js +1 -1
- package/dist/primitives/index.d.ts +53 -6
- package/dist/primitives/index.js +6 -4
- package/dist/state/index.d.ts +12 -7
- package/dist/state/index.js +16 -13
- package/dist/state/index.js.map +1 -1
- package/dist/styles.css +163 -62
- package/dist/surface/index.d.ts +44 -7
- package/dist/surface/index.js +2 -1
- package/dist/ui/layers/index.js +1 -1
- package/dist/undo/index.d.ts +2 -4
- package/package.json +15 -8
- package/src/annotations/AnnotationOverlay.tsx +53 -5
- package/src/annotations/Annotations.overlay.test.tsx +85 -6
- package/src/annotations/drawOne.test.ts +1 -1
- package/src/annotations/drawOne.ts +2 -2
- 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/paint.test.ts +2 -2
- package/src/annotations/paint.ts +1 -1
- package/src/annotations/preload.ts +6 -0
- package/src/annotations/store.test.ts +18 -0
- package/src/annotations/store.ts +7 -6
- package/src/annotations/svgNodes.test.ts +2 -2
- package/src/annotations/svgNodes.ts +1 -2
- package/src/annotations/toolMap.ts +3 -3
- package/src/annotations/types.ts +6 -3
- package/src/canvas/CameraWheelContext.ts +12 -0
- package/src/canvas/CanvasStack.test.tsx +25 -0
- package/src/canvas/CanvasStack.tsx +31 -4
- package/src/canvas/Stage.less +18 -0
- package/src/canvas/Stage.test.tsx +186 -0
- package/src/canvas/Stage.tsx +134 -0
- package/src/canvas/camera.test.ts +17 -2
- package/src/canvas/camera.ts +9 -9
- package/src/canvas/index.ts +4 -0
- package/src/canvas/usePanZoom.ts +10 -5
- package/src/chrome/ChromeRegions.stories.tsx +0 -3
- package/src/chrome/LabChrome.tsx +114 -0
- package/src/chrome/builtins.tsx +20 -31
- package/src/chrome/index.ts +15 -0
- package/src/chrome/labRegions.test.tsx +208 -0
- package/src/chrome/labTypes.ts +50 -0
- package/src/chrome/merge.ts +7 -9
- package/src/chrome/regions/PaletteRegion.test.tsx +6 -4
- package/src/chrome/regions/PaletteRegion.tsx +21 -9
- package/src/chrome/regions/SidebarRegion.tsx +25 -13
- package/src/chrome/regions/StatusRegion.tsx +15 -8
- package/src/chrome/regions/ToolbarRegion.tsx +30 -16
- package/src/chrome/types.ts +47 -20
- package/src/config/builder.test.ts +4 -0
- package/src/config/builder.ts +16 -10
- package/src/config/declarationEmit.fixture.ts +11 -0
- package/src/config/declarationEmit.test.ts +51 -0
- package/src/config/entry.test.ts +46 -0
- package/src/config/index.ts +13 -1
- package/src/config/nodeClasses.test.ts +18 -0
- package/src/config/types.ts +3 -1
- package/src/controls/ControlPanel.test.tsx +16 -0
- package/src/controls/ControlPanel.tsx +5 -2
- package/src/fake-indexeddb-auto.d.ts +5 -0
- package/src/index.test.ts +7 -0
- package/src/index.ts +39 -6
- package/src/instrument/serializers.test.ts +22 -0
- package/src/instrument/serializers.ts +11 -0
- package/src/instrument/types.ts +25 -1
- package/src/lab/Lab.less +4 -13
- package/src/lab/Lab.persist.test.tsx +147 -0
- package/src/lab/Lab.stories.tsx +0 -2
- package/src/lab/Lab.surface.test.tsx +66 -3
- package/src/lab/Lab.test.tsx +91 -17
- package/src/lab/Lab.tsx +337 -124
- package/src/lab/LabFit.stories.less +18 -0
- package/src/lab/LabFit.stories.tsx +219 -0
- package/src/lab/LabFullChrome.stories.tsx +0 -3
- package/src/lab/LabHeader.test.tsx +40 -9
- package/src/lab/LabHeader.tsx +7 -13
- package/src/lab/LabPalette.tsx +13 -26
- package/src/lab/LabShell.less +49 -12
- package/src/lab/LabShell.tsx +14 -2
- package/src/lab/LabSwitcher.less +92 -0
- package/src/lab/LabSwitcher.test.tsx +96 -0
- package/src/lab/LabSwitcher.tsx +112 -0
- package/src/lab/Workspace.surface.test.tsx +2 -1
- package/src/lab/fitCheck.test.ts +57 -0
- package/src/lab/fitCheck.ts +125 -0
- package/src/lab/index.ts +2 -0
- package/src/loupe/AGENTS.md +1 -1
- package/src/loupe/Loupe.less +1 -1
- package/src/loupe/canvasLens.ts +1 -1
- package/src/loupe/types.ts +1 -1
- package/src/loupe/useLoupe.test.tsx +1 -1
- package/src/loupe/useLoupe.ts +1 -1
- package/src/passthrough/weasel-ui.ts +9 -0
- package/src/primitives/FloatingPanel.stories.tsx +13 -1
- package/src/primitives/FloatingPanel.test.tsx +47 -16
- package/src/primitives/FloatingPanel.tsx +11 -25
- package/src/primitives/Split.less +14 -0
- package/src/primitives/Split.test.tsx +108 -0
- package/src/primitives/Split.tsx +159 -0
- package/src/primitives/ZoomControl.tsx +5 -2
- package/src/primitives/index.ts +2 -0
- package/src/state/Persistence.stories.tsx +75 -0
- package/src/state/Persistence.tsx +33 -0
- package/src/state/SingletonExperiment.test.tsx +47 -53
- package/src/state/SingletonExperiment.tsx +24 -13
- package/src/state/adapterContract.ts +116 -0
- package/src/state/adapters.test.ts +113 -61
- package/src/state/adapters.ts +328 -69
- package/src/state/document.test.ts +71 -96
- package/src/state/document.ts +66 -52
- package/src/state/helpers.test.ts +20 -0
- package/src/state/helpers.ts +16 -0
- package/src/state/index.ts +8 -0
- package/src/state/labRecords.test.ts +105 -0
- package/src/state/labRecords.ts +160 -0
- package/src/state/openLabStore.test.ts +658 -0
- package/src/state/openLabStore.ts +403 -0
- package/src/state/records.test.ts +234 -0
- package/src/state/records.ts +219 -0
- package/src/state/store.test.ts +104 -635
- package/src/state/store.ts +117 -158
- package/src/state/toolSlot.test.ts +1 -1
- package/src/state/types.ts +39 -15
- package/src/state/useOpenOnce.ts +68 -0
- package/src/state/usePersistedState.test.tsx +125 -0
- package/src/state/usePersistedState.ts +66 -0
- package/src/state/useTrialState.test.tsx +2 -3
- package/src/state/view.test.ts +49 -15
- package/src/state/view.ts +18 -1
- package/src/styles.less +3 -0
- package/src/surface/AGENTS.md +39 -7
- package/src/surface/SurfaceContext.ts +26 -3
- package/src/surface/index.ts +2 -0
- package/src/surface/useSurfaceTile.test.tsx +2 -1
- package/src/surface/useSurfaceTile.ts +6 -5
- package/src/surface/useTiledSurface.test.tsx +175 -0
- package/src/surface/useTiledSurface.ts +54 -5
- package/src/theme/Interstellar.stories.tsx +7 -7
- package/src/theme/base.less +4 -4
- package/src/theme/interstellar.test.ts +1 -1
- package/src/theme/interstellar.tokens.json +2 -2
- package/src/tools/labTool.ts +11 -0
- package/src/trial/Trial.annotations.persist.test.tsx +100 -58
- package/src/trial/Trial.annotations.test.tsx +47 -4
- package/src/trial/Trial.job.test.tsx +3 -3
- package/src/trial/Trial.less +1 -26
- package/src/trial/Trial.stories.tsx +1 -2
- package/src/trial/Trial.test.tsx +28 -4
- package/src/trial/Trial.trialId.test.tsx +23 -1
- package/src/trial/Trial.tsx +118 -38
- package/src/trial/TrialBody.tsx +17 -141
- package/src/trial/TrialChrome.tsx +7 -4
- package/src/trial/trialOps.ts +7 -4
- package/dist/_dts/types-BP2OCcpg.d.ts +0 -155
- package/dist/_dts/types-x92Kfeme.d.ts +0 -62
- package/dist/_dts/useTrialState-D6Vb3T-g.d.ts +0 -99
- package/dist/chunk-2RQPGOQF.js.map +0 -1
- package/dist/chunk-5TROQVQ2.js +0 -547
- package/dist/chunk-5TROQVQ2.js.map +0 -1
- package/dist/chunk-ASWKLRKJ.js.map +0 -1
- package/dist/chunk-C42T6DJT.js.map +0 -1
- package/dist/chunk-CTRKTLYZ.js.map +0 -1
- package/dist/chunk-FQMJUVHJ.js.map +0 -1
- package/dist/chunk-I6JCVE24.js.map +0 -1
- package/dist/chunk-MHAGC6VD.js +0 -7320
- package/dist/chunk-MHAGC6VD.js.map +0 -1
- package/dist/chunk-QAGAHJKZ.js.map +0 -1
- package/dist/chunk-TJ7QY3OC.js.map +0 -1
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { d as ControlRenderer, c as ConfigRule } from './types-Ca2LCnPq.js';
|
|
2
|
+
import { K as Instrument, aq as TrialChromeContext, N as TrialContribution, T as TrialRecord, q as InstrumentList, e as SavedSnapshot, o as LabMode, ao as ToolSlotContext, a2 as ContributionBase, ap as ToolbarItem, an as ToolItem, ah as SidebarSection, ak as StatusReadout, H as TrialTool, ad as RegionContribution, ai as SidebarSlotContext } from './frac-8R6UmlvN.js';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
import * as react from 'react';
|
|
5
|
+
import { ReactNode } from 'react';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The contributions a trial gets from what its instrument declared. This is
|
|
9
|
+
* the whole "declaring a capability provides the chrome" rule — it replaces
|
|
10
|
+
* the presence checks that used to be spread across the runtime.
|
|
11
|
+
*/
|
|
12
|
+
declare function builtinContributions(instrument: Instrument, ctx: TrialChromeContext, controls?: Record<string, ControlRenderer>): TrialContribution[];
|
|
13
|
+
|
|
14
|
+
/** What a trial opens on beyond its instrument's own defaults. */
|
|
15
|
+
interface AddTrialOptions<TC = Record<string, unknown>> {
|
|
16
|
+
/** Overlaid on `defaultConfig()` before `initialState` reads it, so a trial
|
|
17
|
+
* opened on a subject is running that subject from its first frame. Keys
|
|
18
|
+
* whose value is `undefined` are left to the default. */
|
|
19
|
+
config?: Partial<TC>;
|
|
20
|
+
}
|
|
21
|
+
/** Append a new trial running `instrumentName`, at that instrument's default
|
|
22
|
+
* config — with `options.config` written over it — and the initial state
|
|
23
|
+
* that config produces. */
|
|
24
|
+
declare function addTrial(trials: TrialRecord[], instruments: InstrumentList, instrumentName: string, options?: AddTrialOptions): TrialRecord[];
|
|
25
|
+
/** Insert a deep copy of a trial directly after it. The copy starts with
|
|
26
|
+
* an empty undo history — the original's is not shared. */
|
|
27
|
+
declare function cloneTrial(trials: TrialRecord[], id: string): TrialRecord[];
|
|
28
|
+
/** Remove a trial, unless it is the last one — a lab always has at least
|
|
29
|
+
* one. */
|
|
30
|
+
declare function closeTrial(trials: TrialRecord[], id: string): TrialRecord[];
|
|
31
|
+
/** Return a trial to what it opened on — its instrument's defaults under the
|
|
32
|
+
* seed `addTrial` was given — keeping its id and its place in the list. */
|
|
33
|
+
declare function resetTrial(trials: TrialRecord[], id: string, instruments: InstrumentList): TrialRecord[];
|
|
34
|
+
/**
|
|
35
|
+
* Reorder to match `ids`. Ids the list doesn't mention keep their relative
|
|
36
|
+
* order at the end, and ids it names that no longer exist are dropped — a
|
|
37
|
+
* reorder that raced a close should not resurrect the closed trial.
|
|
38
|
+
*/
|
|
39
|
+
declare function reorderTrials(trials: TrialRecord[], ids: readonly string[]): TrialRecord[];
|
|
40
|
+
|
|
41
|
+
/** Lab-wide state and commands: the available instruments, the open
|
|
42
|
+
* trials and the operations over them, saved snapshots, and the color
|
|
43
|
+
* mode. */
|
|
44
|
+
interface LabContextValue {
|
|
45
|
+
instruments: InstrumentList;
|
|
46
|
+
trials: TrialRecord[];
|
|
47
|
+
/** Open a trial running `instrumentName`. `options.config` is written over
|
|
48
|
+
* that instrument's defaults, which is where a trial opened on a subject
|
|
49
|
+
* says which subject. */
|
|
50
|
+
addTrial: (instrumentName: string, options?: AddTrialOptions) => void;
|
|
51
|
+
cloneTrial: (id: string) => void;
|
|
52
|
+
closeTrial: (id: string) => void;
|
|
53
|
+
resetTrial: (id: string) => void;
|
|
54
|
+
reorderTrials: (ids: readonly string[]) => void;
|
|
55
|
+
savedSnapshots: SavedSnapshot[];
|
|
56
|
+
saveSnapshot: (trialId: string, name?: string) => void;
|
|
57
|
+
loadSnapshot: (trialId: string, snapshotId: string) => void;
|
|
58
|
+
deleteSnapshot: (snapshotId: string) => void;
|
|
59
|
+
mode: LabMode;
|
|
60
|
+
setMode: (m: LabMode) => void;
|
|
61
|
+
/** Lab-wide rules run over every instrument's config leaves, before
|
|
62
|
+
* labkit's own inference. */
|
|
63
|
+
configRules?: readonly ConfigRule[];
|
|
64
|
+
/** Lab-wide control overrides, keyed by config path or by leaf kind. */
|
|
65
|
+
controls?: Record<string, ControlRenderer>;
|
|
66
|
+
}
|
|
67
|
+
/** Context carrying the surrounding lab. Prefer `useLabContext`. */
|
|
68
|
+
declare const LabContext: react.Context<LabContextValue | null>;
|
|
69
|
+
/** The surrounding lab. Throws outside a `<Lab>`. */
|
|
70
|
+
declare function useLabContext(): LabContextValue;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* A named position in the lab's own chrome — a box the shell owns, outside any
|
|
74
|
+
* one trial. `header` and `footer` are the shell's two bars, named as
|
|
75
|
+
* `<LabShell>` names them; `palette` is the tool rail down the side of the
|
|
76
|
+
* workspace; `sidebar` is a column of sections left of the tool rail.
|
|
77
|
+
*/
|
|
78
|
+
type LabRegion = 'header' | 'palette' | 'sidebar' | 'footer';
|
|
79
|
+
/**
|
|
80
|
+
* Everything a lab-level contribution can read and command: the lab's own
|
|
81
|
+
* state and operations, plus the lab's tool slot — which every trial whose
|
|
82
|
+
* instrument declares no tools of its own reflects and writes.
|
|
83
|
+
*/
|
|
84
|
+
interface LabChromeContext extends LabContextValue, ToolSlotContext {
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* A contribution to the lab's chrome. Shaped as `TrialContribution` is, and
|
|
88
|
+
* merged and suppressed by the same rules, but keyed to the lab's regions and
|
|
89
|
+
* rendered with the lab's context. Supplying `render` instead of `item` opts
|
|
90
|
+
* out of the region's layout.
|
|
91
|
+
*
|
|
92
|
+
* `TCtx` is what the chrome hands a handler. It defaults to `LabChromeContext`,
|
|
93
|
+
* which is what `<Lab>` renders its regions with; a consumer mounting the
|
|
94
|
+
* regions under a bare `<LabShell>` names whatever it passes as `ctx` instead.
|
|
95
|
+
*/
|
|
96
|
+
type LabContribution<TCtx = LabChromeContext> = (ContributionBase & {
|
|
97
|
+
region: 'header';
|
|
98
|
+
item: ToolbarItem<TCtx>;
|
|
99
|
+
render?: never;
|
|
100
|
+
}) | (ContributionBase & {
|
|
101
|
+
region: 'palette';
|
|
102
|
+
item: ToolItem;
|
|
103
|
+
render?: never;
|
|
104
|
+
}) | (ContributionBase & {
|
|
105
|
+
region: 'sidebar';
|
|
106
|
+
item: SidebarSection;
|
|
107
|
+
render?: never;
|
|
108
|
+
}) | (ContributionBase & {
|
|
109
|
+
region: 'footer';
|
|
110
|
+
item: StatusReadout;
|
|
111
|
+
render?: never;
|
|
112
|
+
}) | (ContributionBase & {
|
|
113
|
+
region: LabRegion;
|
|
114
|
+
item?: never;
|
|
115
|
+
render: (ctx: TCtx) => ReactNode;
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
/** The lab's chrome context: the lab itself, plus the lab's tool slot. Throws
|
|
119
|
+
* outside a `<Lab>`. */
|
|
120
|
+
declare function useLabChromeContext(): LabChromeContext;
|
|
121
|
+
/** The lab's contributions for one region, in declaration order. */
|
|
122
|
+
declare function contributionsIn<TCtx = LabChromeContext>(contributions: readonly LabContribution<TCtx>[], region: LabRegion): LabContribution<TCtx>[];
|
|
123
|
+
/** The palette contributions a lab's `tools` stand for. Declaring a tool is
|
|
124
|
+
* shorthand for contributing a palette item that writes the lab's tool
|
|
125
|
+
* slot. */
|
|
126
|
+
declare function toolContributions(tools: readonly TrialTool[]): LabContribution[];
|
|
127
|
+
/** Everything the lab's chrome renders, from both of the ways a lab declares
|
|
128
|
+
* it. Tools and contributions share one id namespace, so a tool colliding
|
|
129
|
+
* with a contribution throws here rather than one of them silently losing. */
|
|
130
|
+
declare function labContributions(tools: readonly TrialTool[] | undefined, chrome: readonly LabContribution[] | undefined): LabContribution[];
|
|
131
|
+
/** Props shared by the lab's region mounts. Each takes the lab's whole
|
|
132
|
+
* contribution list and lays out the part addressed to it. */
|
|
133
|
+
interface LabRegionProps {
|
|
134
|
+
contributions: readonly LabContribution[];
|
|
135
|
+
}
|
|
136
|
+
/** The lab's action bar, in the shell header beside the title. */
|
|
137
|
+
declare function LabHeaderRegion({ contributions }: LabRegionProps): react_jsx_runtime.JSX.Element;
|
|
138
|
+
/** The lab's sidebar sections. Fold state is a lab-scoped persisted value, so it
|
|
139
|
+
* survives a reload in a stored lab and lasts the session in an unstored one. */
|
|
140
|
+
declare function LabSidebarRegion({ contributions }: LabRegionProps): react_jsx_runtime.JSX.Element;
|
|
141
|
+
/** The lab's readouts, in the shell footer below the workspace. */
|
|
142
|
+
declare function LabFooterRegion({ contributions }: LabRegionProps): react_jsx_runtime.JSX.Element;
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Concatenate contribution bundles into one list, preserving order — order
|
|
146
|
+
* decides how a region lays its contributions out, so it is part of the
|
|
147
|
+
* result, not an accident of it.
|
|
148
|
+
*
|
|
149
|
+
* Throws on a duplicate id rather than dropping one: a contribution silently
|
|
150
|
+
* losing to a later bundle is the failure a registry exists to prevent.
|
|
151
|
+
*/
|
|
152
|
+
declare function mergeContributions<T extends {
|
|
153
|
+
id: string;
|
|
154
|
+
}>(...bundles: readonly (readonly T[])[]): T[];
|
|
155
|
+
/**
|
|
156
|
+
* Drop contributions by id. Throws when an id is not present: a typo that
|
|
157
|
+
* silently suppresses nothing is the same class of bug as a duplicate id
|
|
158
|
+
* silently winning.
|
|
159
|
+
*/
|
|
160
|
+
declare function suppressContributions<T extends {
|
|
161
|
+
id: string;
|
|
162
|
+
}>(bundle: readonly T[], ids: readonly string[]): T[];
|
|
163
|
+
|
|
164
|
+
/** Props for `<PaletteRegion>`. */
|
|
165
|
+
interface PaletteRegionProps<TCtx extends ToolSlotContext = TrialChromeContext> {
|
|
166
|
+
contributions: readonly RegionContribution<NoInfer<TCtx>>[];
|
|
167
|
+
ctx: TCtx;
|
|
168
|
+
/** Which region's items to lay out. The lab's rail names the same box
|
|
169
|
+
* `palette` too, so this only moves for a chrome that does not. */
|
|
170
|
+
region?: string;
|
|
171
|
+
}
|
|
172
|
+
/** A tool strip: a trial's, or the lab's. Selection lives in whichever tool
|
|
173
|
+
* slot the context carries; this region only reflects it. */
|
|
174
|
+
declare function PaletteRegion<TCtx extends ToolSlotContext = TrialChromeContext>({ contributions, ctx, region, }: PaletteRegionProps<TCtx>): react_jsx_runtime.JSX.Element | null;
|
|
175
|
+
|
|
176
|
+
/** Props for `<SidebarRegion>`. */
|
|
177
|
+
interface SidebarRegionProps<TCtx extends SidebarSlotContext = TrialChromeContext> {
|
|
178
|
+
contributions: readonly RegionContribution<NoInfer<TCtx>>[];
|
|
179
|
+
ctx: TCtx;
|
|
180
|
+
/** Which region's items to lay out. */
|
|
181
|
+
region?: string;
|
|
182
|
+
}
|
|
183
|
+
/** Lays `sidebar` contributions out as titled, collapsible sections — a
|
|
184
|
+
* trial's, or the lab's. A section the trial has torn out is not rendered
|
|
185
|
+
* here — `Trial` portals its body into the workspace instead. A context with
|
|
186
|
+
* no `undockPanel` offers no tear-out. */
|
|
187
|
+
declare function SidebarRegion<TCtx extends SidebarSlotContext = TrialChromeContext>({ contributions, ctx, region, }: SidebarRegionProps<TCtx>): react_jsx_runtime.JSX.Element | null;
|
|
188
|
+
|
|
189
|
+
/** Props for `<StatusRegion>`. */
|
|
190
|
+
interface StatusRegionProps<TCtx = TrialChromeContext> {
|
|
191
|
+
contributions: readonly RegionContribution<NoInfer<TCtx>>[];
|
|
192
|
+
ctx: TCtx;
|
|
193
|
+
/** Which region's readouts to lay out; the lab's footer is `footer`. */
|
|
194
|
+
region?: string;
|
|
195
|
+
}
|
|
196
|
+
/** Lays a bar's readouts out. */
|
|
197
|
+
declare function StatusRegion<TCtx = TrialChromeContext>({ contributions, ctx, region, }: StatusRegionProps<TCtx>): react_jsx_runtime.JSX.Element | null;
|
|
198
|
+
|
|
199
|
+
/** Which end of the title bar a `<TitleBarRegion>` lays out: `'lead'` renders
|
|
200
|
+
* the contributions that leave `end` unset, before the title; `'actions'`
|
|
201
|
+
* renders the ones that set it, after everything else. */
|
|
202
|
+
type TitleBarPlacement = 'lead' | 'actions';
|
|
203
|
+
/** Props for `<TitleBarRegion>`. */
|
|
204
|
+
interface TitleBarRegionProps {
|
|
205
|
+
contributions: readonly TrialContribution[];
|
|
206
|
+
ctx: TrialChromeContext;
|
|
207
|
+
/** Defaults to `'actions'`, where the built-ins live. */
|
|
208
|
+
placement?: TitleBarPlacement;
|
|
209
|
+
}
|
|
210
|
+
/** Lays a trial's `titlebar` contributions out at one end of the bar. */
|
|
211
|
+
declare function TitleBarRegion({ contributions, ctx, placement }: TitleBarRegionProps): react_jsx_runtime.JSX.Element | null;
|
|
212
|
+
|
|
213
|
+
/** Props for `<ToolbarRegion>`. */
|
|
214
|
+
interface ToolbarRegionProps<TCtx = TrialChromeContext> {
|
|
215
|
+
contributions: readonly RegionContribution<NoInfer<TCtx>>[];
|
|
216
|
+
ctx: TCtx;
|
|
217
|
+
/** Which region's items to lay out; the lab's action bar is `header`. */
|
|
218
|
+
region?: string;
|
|
219
|
+
/** The bar's accessible name. */
|
|
220
|
+
label?: string;
|
|
221
|
+
}
|
|
222
|
+
/** Lays a bar's contributions out, grouped by their `group`. */
|
|
223
|
+
declare function ToolbarRegion<TCtx = TrialChromeContext>({ contributions, ctx, region, label, }: ToolbarRegionProps<TCtx>): react_jsx_runtime.JSX.Element | null;
|
|
224
|
+
|
|
225
|
+
/** Props for `<ViewportRegion>`. */
|
|
226
|
+
interface ViewportRegionProps {
|
|
227
|
+
contributions: readonly TrialContribution[];
|
|
228
|
+
ctx: TrialChromeContext;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Controls acting on the view of a trial. Anchored inside the content well
|
|
232
|
+
* rather than in the toolbar, which acts on the trial itself.
|
|
233
|
+
*/
|
|
234
|
+
declare function ViewportRegion({ contributions, ctx }: ViewportRegionProps): react_jsx_runtime.JSX.Element | null;
|
|
235
|
+
|
|
236
|
+
export { suppressContributions as B, toolContributions as C, useLabChromeContext as D, useLabContext as E, PaletteRegion as P, SidebarRegion as S, ViewportRegion as V, LabContext as b, LabFooterRegion as d, LabHeaderRegion as e, LabSidebarRegion as h, StatusRegion as k, TitleBarRegion as m, ToolbarRegion as o, addTrial as r, builtinContributions as s, cloneTrial as t, closeTrial as u, contributionsIn as v, labContributions as w, mergeContributions as x, reorderTrials as y, resetTrial as z };
|
|
237
|
+
export type { AddTrialOptions as A, LabContribution as L, TitleBarPlacement as T, LabChromeContext as a, LabContextValue as c, LabRegion as f, LabRegionProps as g, PaletteRegionProps as i, SidebarRegionProps as j, StatusRegionProps as l, TitleBarRegionProps as n, ToolbarRegionProps as p, ViewportRegionProps as q };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { ToolPrefNumberFormat } from '@weasel-js/core';
|
|
4
|
+
import { R as ResolvedConfig, a as ConfigField, d as ControlRenderer } from './types-Ca2LCnPq.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* How much room a container gives its rows — gaps, padding, and field height,
|
|
@@ -126,6 +126,8 @@ interface SliderRowProps extends PropertyMetricProps {
|
|
|
126
126
|
onInput?: (next: number) => void;
|
|
127
127
|
/** Override how the value is rendered next to the label. Defaults to `value.toString()`. */
|
|
128
128
|
format?: (value: number) => ReactNode;
|
|
129
|
+
/** A named display for the value: `compact` reads `2.0M`. `format` wins when both are given. */
|
|
130
|
+
notation?: ToolPrefNumberFormat;
|
|
129
131
|
/**
|
|
130
132
|
* Optional suffix rendered next to the readout. A string becomes a
|
|
131
133
|
* baseline-aligned dim "word" unit (e.g. "px"); pass JSX like `<sup>°</sup>`
|
|
@@ -139,15 +141,29 @@ interface SliderRowProps extends PropertyMetricProps {
|
|
|
139
141
|
}
|
|
140
142
|
/** A bounded number edited by dragging, with a live readout whose precision
|
|
141
143
|
* follows `step`. */
|
|
142
|
-
declare function SliderRow({ label, value, min, max, step, onChange, onInput, format, unit, layout, description, span, density, align, }: SliderRowProps): react_jsx_runtime.JSX.Element;
|
|
144
|
+
declare function SliderRow({ label, value, min, max, step, onChange, onInput, format, notation, unit, layout, description, span, density, align, }: SliderRowProps): react_jsx_runtime.JSX.Element;
|
|
143
145
|
/** Props for `<ColorRow>`. */
|
|
144
146
|
interface ColorRowProps extends PropertyMetricProps {
|
|
145
147
|
label: ReactNode;
|
|
146
148
|
value: string;
|
|
149
|
+
/**
|
|
150
|
+
* The committed color. Given `onInput` as well, it fires once the picker
|
|
151
|
+
* closes; on its own it fires on every move inside it, which is what a row
|
|
152
|
+
* with one callback has always done.
|
|
153
|
+
*/
|
|
147
154
|
onChange: (next: string) => void;
|
|
155
|
+
/**
|
|
156
|
+
* The live color, fired continuously while the picker is open. Pass it
|
|
157
|
+
* alongside `onChange` when the write is expensive — cheap state here, the
|
|
158
|
+
* costly work there. Mirrors `<Slider>`'s `onInput` / `onChange` pair.
|
|
159
|
+
*/
|
|
160
|
+
onInput?: (next: string) => void;
|
|
148
161
|
/** 0..1 alpha. When provided, a translucent slider renders beneath the swatch. */
|
|
149
162
|
alpha?: number;
|
|
163
|
+
/** The committed alpha, on the same terms as `onChange`. */
|
|
150
164
|
onAlphaChange?: (next: number) => void;
|
|
165
|
+
/** The live alpha, on the same terms as `onInput`. */
|
|
166
|
+
onAlphaInput?: (next: number) => void;
|
|
151
167
|
/**
|
|
152
168
|
* Render the alpha track as inert (dimmed, no thumb, not-allowed cursor).
|
|
153
169
|
* Use when the color's consumer drops alpha so the affordance reads dead.
|
|
@@ -160,11 +176,12 @@ interface ColorRowProps extends PropertyMetricProps {
|
|
|
160
176
|
span?: boolean;
|
|
161
177
|
}
|
|
162
178
|
/** A color swatch, optionally with an alpha slider beneath it. */
|
|
163
|
-
declare function ColorRow({ label, value, onChange, alpha, onAlphaChange, alphaDisabled, layout, description, span, density, align, }: ColorRowProps): react_jsx_runtime.JSX.Element;
|
|
179
|
+
declare function ColorRow({ label, value, onChange, onInput, alpha, onAlphaChange, onAlphaInput, alphaDisabled, layout, description, span, density, align, }: ColorRowProps): react_jsx_runtime.JSX.Element;
|
|
164
180
|
/** Props for `<CheckboxRow>`. */
|
|
165
181
|
interface CheckboxRowProps extends PropertyMetricProps {
|
|
166
182
|
label: ReactNode;
|
|
167
|
-
|
|
183
|
+
/** Absent reads as unchecked. */
|
|
184
|
+
value: boolean | undefined;
|
|
168
185
|
onChange: (next: boolean) => void;
|
|
169
186
|
/** Label beside the box (default) or above it. */
|
|
170
187
|
layout?: PropertyRowLayout;
|
|
@@ -177,7 +194,8 @@ declare function CheckboxRow({ label, value, onChange, layout, span, description
|
|
|
177
194
|
/** Props for `<TextRow>`. */
|
|
178
195
|
interface TextRowProps extends PropertyMetricProps {
|
|
179
196
|
label: ReactNode;
|
|
180
|
-
|
|
197
|
+
/** Absent reads as an empty field. */
|
|
198
|
+
value: string | null | undefined;
|
|
181
199
|
onChange: (next: string) => void;
|
|
182
200
|
placeholder?: string;
|
|
183
201
|
maxLength?: number;
|
|
@@ -191,8 +209,20 @@ declare function TextRow({ label, value, onChange, placeholder, maxLength, layou
|
|
|
191
209
|
/** Props for `<NumberRow>`. */
|
|
192
210
|
interface NumberRowProps extends PropertyMetricProps {
|
|
193
211
|
label: ReactNode;
|
|
194
|
-
|
|
212
|
+
/** Absent reads as an empty field. */
|
|
213
|
+
value: number | null | undefined;
|
|
214
|
+
/**
|
|
215
|
+
* The committed value. Given `onInput` as well, it fires on blur or Enter;
|
|
216
|
+
* on its own it fires on every keystroke, which is what a row with one
|
|
217
|
+
* callback has always done.
|
|
218
|
+
*/
|
|
195
219
|
onChange: (next: number) => void;
|
|
220
|
+
/**
|
|
221
|
+
* The live value, fired per keystroke. Pass it alongside `onChange` when the
|
|
222
|
+
* write is expensive — cheap state here, the costly work there. Mirrors
|
|
223
|
+
* `<Slider>`'s `onInput` / `onChange` pair.
|
|
224
|
+
*/
|
|
225
|
+
onInput?: (next: number) => void;
|
|
196
226
|
min?: number;
|
|
197
227
|
max?: number;
|
|
198
228
|
step?: number;
|
|
@@ -210,7 +240,7 @@ interface NumberRowProps extends PropertyMetricProps {
|
|
|
210
240
|
}
|
|
211
241
|
/** A number typed directly. Reach for `<SliderRow>` when the range matters
|
|
212
242
|
* more than the exact value. */
|
|
213
|
-
declare function NumberRow({ label, value, onChange, min, max, step, placeholder, unit, layout, description, span, density, align, }: NumberRowProps): react_jsx_runtime.JSX.Element;
|
|
243
|
+
declare function NumberRow({ label, value, onChange, onInput, min, max, step, placeholder, unit, layout, description, span, density, align, }: NumberRowProps): react_jsx_runtime.JSX.Element;
|
|
214
244
|
interface PropertyOption<T extends string> {
|
|
215
245
|
value: T;
|
|
216
246
|
label: ReactNode;
|
|
@@ -218,9 +248,12 @@ interface PropertyOption<T extends string> {
|
|
|
218
248
|
/** Props for `<SelectRow>`. */
|
|
219
249
|
interface SelectRowProps<T extends string> extends PropertyMetricProps {
|
|
220
250
|
label: ReactNode;
|
|
221
|
-
|
|
251
|
+
/** Absent, or not one of `options`, shows a placeholder rather than the first option. */
|
|
252
|
+
value: T | undefined;
|
|
222
253
|
options: ReadonlyArray<PropertyOption<T>>;
|
|
223
254
|
onChange: (next: T) => void;
|
|
255
|
+
/** Shown while no option is chosen. Defaults to "Choose option…". */
|
|
256
|
+
placeholder?: string;
|
|
224
257
|
layout?: PropertyRowLayout;
|
|
225
258
|
description?: string;
|
|
226
259
|
/** Take the full width of the enclosing grid — see `<PropertyRow span>`. */
|
|
@@ -228,7 +261,7 @@ interface SelectRowProps<T extends string> extends PropertyMetricProps {
|
|
|
228
261
|
}
|
|
229
262
|
/** A dropdown over a fixed set of choices. Prefer `<ToggleRow>` when there
|
|
230
263
|
* are only two or three and they should all stay visible. */
|
|
231
|
-
declare function SelectRow<T extends string>({ label, value, options, onChange, layout, description, span, density, align, }: SelectRowProps<T>): react_jsx_runtime.JSX.Element;
|
|
264
|
+
declare function SelectRow<T extends string>({ label, value, options, onChange, placeholder, layout, description, span, density, align, }: SelectRowProps<T>): react_jsx_runtime.JSX.Element;
|
|
232
265
|
/** Props for `<ToggleRow>`. */
|
|
233
266
|
interface ToggleRowProps<T extends string> extends PropertyMetricProps {
|
|
234
267
|
label: ReactNode;
|
|
@@ -245,12 +278,12 @@ interface ToggleRowProps<T extends string> extends PropertyMetricProps {
|
|
|
245
278
|
declare function ToggleRow<T extends string>({ label, value, options, onChange, layout, description, span, density, align, }: ToggleRowProps<T>): react_jsx_runtime.JSX.Element;
|
|
246
279
|
|
|
247
280
|
/** How a panel packs its rows into the two-column property grid.
|
|
248
|
-
* - `'auto'`: narrow controls (numbers, checkboxes, dropdowns,
|
|
281
|
+
* - `'auto'`: narrow controls (numbers, checkboxes, dropdowns, colors) sit
|
|
249
282
|
* two per row; the ones that need the width — text, sliders, segmented
|
|
250
283
|
* toggles — span it.
|
|
251
284
|
* - `'pairs'`: every row pairs. A control that needs the full width says so
|
|
252
285
|
* itself, with `<PropertyRow span>`.
|
|
253
|
-
* - `'one-up'`: one control per row,
|
|
286
|
+
* - `'one-up'`: one control per row, colors excepted.
|
|
254
287
|
*/
|
|
255
288
|
type ControlPack = 'auto' | 'pairs' | 'one-up';
|
|
256
289
|
interface ControlPanelProps<TC extends Record<string, unknown>> {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ToolPrefLeaf, ToolPrefGroup } from '@weasel-js/core';
|
|
1
|
+
import { ToolPrefNumberFormat, ToolPrefLeaf, ToolPrefGroup } from '@weasel-js/core';
|
|
2
2
|
import { P as PrefRenderer } from './PrefsForm.d-DDHFANkc.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -24,6 +24,8 @@ interface Annotations {
|
|
|
24
24
|
max?: number;
|
|
25
25
|
step?: number;
|
|
26
26
|
suffix?: string;
|
|
27
|
+
/** How a number's value is shown. `compact` abbreviates from a thousand up. */
|
|
28
|
+
format?: ToolPrefNumberFormat;
|
|
27
29
|
control?: string;
|
|
28
30
|
options?: readonly ConfigOption[];
|
|
29
31
|
placeholder?: string;
|
|
@@ -163,4 +165,65 @@ interface ConfigSchema<TC> {
|
|
|
163
165
|
/** The config type behind a schema: `ConfigOf<typeof sceneConfig>`. */
|
|
164
166
|
type ConfigOf<S> = S extends ConfigSchema<infer TC> ? TC : never;
|
|
165
167
|
|
|
166
|
-
|
|
168
|
+
/** Which control a config field is edited with. */
|
|
169
|
+
type ConfigFieldType = 'slider' | 'checkbox' | 'select' | 'number' | 'text' | 'color';
|
|
170
|
+
/** What every config field carries: the config key it writes, the label shown
|
|
171
|
+
* beside it, and which control renders it. */
|
|
172
|
+
interface ConfigFieldBase {
|
|
173
|
+
key: string;
|
|
174
|
+
label: string;
|
|
175
|
+
type: ConfigFieldType;
|
|
176
|
+
}
|
|
177
|
+
/** A bounded number edited by dragging. */
|
|
178
|
+
interface SliderField extends ConfigFieldBase {
|
|
179
|
+
type: 'slider';
|
|
180
|
+
default: number;
|
|
181
|
+
min: number;
|
|
182
|
+
max: number;
|
|
183
|
+
step?: number;
|
|
184
|
+
}
|
|
185
|
+
/** A boolean. */
|
|
186
|
+
interface CheckboxField extends ConfigFieldBase {
|
|
187
|
+
type: 'checkbox';
|
|
188
|
+
default: boolean;
|
|
189
|
+
}
|
|
190
|
+
/** One choice in a select field. */
|
|
191
|
+
interface SelectOption {
|
|
192
|
+
value: string;
|
|
193
|
+
label: string;
|
|
194
|
+
}
|
|
195
|
+
/** A fixed set of labeled choices. */
|
|
196
|
+
interface SelectField extends ConfigFieldBase {
|
|
197
|
+
type: 'select';
|
|
198
|
+
default: string;
|
|
199
|
+
options: SelectOption[];
|
|
200
|
+
}
|
|
201
|
+
/** A number typed directly, optionally bounded. Use a slider field instead
|
|
202
|
+
* when the range matters more than the exact value. */
|
|
203
|
+
interface NumberField extends ConfigFieldBase {
|
|
204
|
+
type: 'number';
|
|
205
|
+
default: number;
|
|
206
|
+
min?: number;
|
|
207
|
+
max?: number;
|
|
208
|
+
step?: number;
|
|
209
|
+
}
|
|
210
|
+
/** A free-text string. Writes are debounced so typing does not re-run the
|
|
211
|
+
* instrument on every keystroke. */
|
|
212
|
+
interface TextField extends ConfigFieldBase {
|
|
213
|
+
type: 'text';
|
|
214
|
+
default: string;
|
|
215
|
+
placeholder?: string;
|
|
216
|
+
maxLength?: number;
|
|
217
|
+
/** Milliseconds to debounce live setConfig calls. Default 150 ms. Set to 0 to disable. */
|
|
218
|
+
debounceMs?: number;
|
|
219
|
+
}
|
|
220
|
+
/** A color, as a CSS color string. */
|
|
221
|
+
interface ColorField extends ConfigFieldBase {
|
|
222
|
+
type: 'color';
|
|
223
|
+
default: string;
|
|
224
|
+
}
|
|
225
|
+
/** One field of an instrument's config schema. The schema is what the control
|
|
226
|
+
* panel renders, and what `validateConfigSchema` checks. */
|
|
227
|
+
type ConfigField = SliderField | CheckboxField | SelectField | NumberField | TextField | ColorField;
|
|
228
|
+
|
|
229
|
+
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, TextField as T, ValueAtPath as V, ConfigField as a, ConfigSchema as b, ConfigRule as c, ControlRenderer as d, BranchOptions as e, CheckboxField as f, ColorField as g, ConfigBranch as h, ConfigEntry as i, ConfigFieldBase as j, ConfigFieldType as k, ConfigNode as l, ConfigOf as m, ConfigOption as n, ConfigRuleContext as o, ConfigShape as p, NodeValue as q, NumberField as r, SelectField as s, SelectOption as t, SliderField as u };
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode, WheelEvent, PointerEvent as PointerEvent$1 } from 'react';
|
|
3
|
+
import { k as ViewTransform, a as WorldSpec, V as ViewportSize, l as Point, W as WorldFrame } from './frac-8R6UmlvN.js';
|
|
4
|
+
import { C as CanvasLayerDescriptor } from './CanvasStackContext-CqkxkFJW.js';
|
|
5
|
+
|
|
6
|
+
/** Props for `<CanvasStack>`. */
|
|
7
|
+
interface CanvasStackProps {
|
|
8
|
+
layers: CanvasLayerDescriptor[];
|
|
9
|
+
view: ViewTransform;
|
|
10
|
+
onViewChange: (v: ViewTransform) => void;
|
|
11
|
+
/** The instrument's coordinate system. Omitted, world (0,0) sits at the
|
|
12
|
+
* element's top-left with y running down. */
|
|
13
|
+
worldSpec?: WorldSpec;
|
|
14
|
+
minZoom?: number;
|
|
15
|
+
maxZoom?: number;
|
|
16
|
+
width?: number | string;
|
|
17
|
+
height?: number | string;
|
|
18
|
+
className?: string;
|
|
19
|
+
/** Fired whenever the stack is measured, so a consumer can place a view that
|
|
20
|
+
* only makes sense in terms of the viewport. */
|
|
21
|
+
onResize?: (size: ViewportSize) => void;
|
|
22
|
+
onHitTest?: (worldPos: Point) => void;
|
|
23
|
+
children?: ReactNode;
|
|
24
|
+
}
|
|
25
|
+
/** Stacks one `<canvas>` per layer and drives them from a shared view, so a
|
|
26
|
+
* layer that changes rarely is not redrawn with one that changes every frame.
|
|
27
|
+
* Handles sizing, device pixel ratio, and pan/zoom. */
|
|
28
|
+
declare function CanvasStack({ layers, view: viewProp, onViewChange, worldSpec, minZoom, maxZoom, width, height, className, onResize, onHitTest, children, }: CanvasStackProps): react_jsx_runtime.JSX.Element;
|
|
29
|
+
|
|
30
|
+
/** Bounds and coordinate system a {@link zoomAt} works in. */
|
|
31
|
+
interface ZoomAtOptions {
|
|
32
|
+
/** The instrument's coordinate system, resolved against the viewport.
|
|
33
|
+
* Omitted, `at` is measured from the element's top-left. */
|
|
34
|
+
frame?: WorldFrame;
|
|
35
|
+
min?: number;
|
|
36
|
+
max?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Zoom a view by `factor` about a fixed point, so whatever world coordinate
|
|
40
|
+
* `at` was over stays under it.
|
|
41
|
+
*
|
|
42
|
+
* `at` is in the element's own pixels — a cursor position, or the centre of a
|
|
43
|
+
* lens. The clamp is applied before the pan is solved, so a zoom that hits a
|
|
44
|
+
* bound still anchors on the zoom it actually reached.
|
|
45
|
+
*/
|
|
46
|
+
declare function zoomAt(view: ViewTransform, factor: number, at: Point, { frame, min, max }?: ZoomAtOptions): ViewTransform;
|
|
47
|
+
/** The view that puts a world point at the centre of a `size` viewport, at
|
|
48
|
+
* `zoom`. What a lens showing a region around one point renders through. */
|
|
49
|
+
declare function centerOn(world: Point, zoom: number, size: ViewportSize, frame?: WorldFrame): ViewTransform;
|
|
50
|
+
|
|
51
|
+
/** Project a world point into screen coordinates under a view.
|
|
52
|
+
*
|
|
53
|
+
* `frame` is the instrument's declared coordinate system, resolved against the
|
|
54
|
+
* viewport; omitting it gives labkit's original one — origin at the top-left,
|
|
55
|
+
* y downward. */
|
|
56
|
+
declare function worldToScreen(world: Point, view: ViewTransform, frame?: WorldFrame): Point;
|
|
57
|
+
/** Unproject a screen point back to world coordinates under a view. */
|
|
58
|
+
declare function screenToWorld(screen: Point, view: ViewTransform, frame?: WorldFrame): Point;
|
|
59
|
+
|
|
60
|
+
/** Props for `<Stage>`. */
|
|
61
|
+
interface StageProps {
|
|
62
|
+
/** The content's own size in CSS pixels, at zoom 1. */
|
|
63
|
+
size: ViewportSize;
|
|
64
|
+
view: ViewTransform;
|
|
65
|
+
onViewChange: (v: ViewTransform) => void;
|
|
66
|
+
minZoom?: number;
|
|
67
|
+
maxZoom?: number;
|
|
68
|
+
/** Fired whenever the stage's viewport is measured at a non-zero size. */
|
|
69
|
+
onResize?: (viewport: ViewportSize) => void;
|
|
70
|
+
/** Handed the viewport element, for a consumer tracking the pointer over it. */
|
|
71
|
+
hostRef?: {
|
|
72
|
+
current: HTMLDivElement | null;
|
|
73
|
+
};
|
|
74
|
+
/** Drawn over the content in viewport pixels, outside the camera. */
|
|
75
|
+
overlay?: ReactNode;
|
|
76
|
+
children?: ReactNode;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* The camera a stage opens at: the content centered in its viewport, shrunk to
|
|
80
|
+
* fit if it has to be and never enlarged past its own size.
|
|
81
|
+
*/
|
|
82
|
+
declare function fitStage(size: ViewportSize, viewport: ViewportSize): ViewTransform;
|
|
83
|
+
/**
|
|
84
|
+
* DOM content of a fixed size, panned and zoomed by a camera — what
|
|
85
|
+
* `<CanvasStack>` is for layers drawn to a canvas. The content is laid out at
|
|
86
|
+
* its own size and transformed, so everything inside keeps its layout and a
|
|
87
|
+
* measurement of any element in it reports where it is actually drawn.
|
|
88
|
+
*/
|
|
89
|
+
declare function Stage({ size, view: viewProp, onViewChange, minZoom, maxZoom, onResize, hostRef, overlay, children, }: StageProps): react_jsx_runtime.JSX.Element;
|
|
90
|
+
|
|
91
|
+
/** A point in the space the instrument works in. */
|
|
92
|
+
interface Vec3 {
|
|
93
|
+
x: number;
|
|
94
|
+
y: number;
|
|
95
|
+
z: number;
|
|
96
|
+
}
|
|
97
|
+
/** An orbit camera as a trial view: where it looks from, and what it looks at.
|
|
98
|
+
* labkit does not turn this into a matrix — the host's renderer does. */
|
|
99
|
+
interface OrbitView {
|
|
100
|
+
yaw: number;
|
|
101
|
+
pitch: number;
|
|
102
|
+
distance: number;
|
|
103
|
+
target: Vec3;
|
|
104
|
+
}
|
|
105
|
+
/** Just short of the pole. At exactly ±PI/2 the azimuth is undefined and the
|
|
106
|
+
* camera rolls, which reads as the model jumping rather than as a limit. */
|
|
107
|
+
declare const PITCH_LIMIT: number;
|
|
108
|
+
declare function clampPitch(pitch: number): number;
|
|
109
|
+
declare function wrapYaw(yaw: number): number;
|
|
110
|
+
/** The view a drag of (dx, dy) from `start` produces. Absolute against the drag
|
|
111
|
+
* start, so it can be re-applied any number of times without compounding. */
|
|
112
|
+
declare function orbitAfterDrag(start: OrbitView, dx: number, dy: number): OrbitView;
|
|
113
|
+
/** Multiplicative, so one notch covers the same proportion of the distance
|
|
114
|
+
* whether the camera is near or far. */
|
|
115
|
+
declare function orbitAfterWheel(view: OrbitView, deltaY: number, minDistance: number, maxDistance: number): OrbitView;
|
|
116
|
+
interface UseOrbitOptions {
|
|
117
|
+
view: OrbitView;
|
|
118
|
+
onViewChange: (v: OrbitView) => void;
|
|
119
|
+
/** Restored on double-click. Defaults to the view the hook first saw. */
|
|
120
|
+
home?: OrbitView;
|
|
121
|
+
minDistance?: number;
|
|
122
|
+
maxDistance?: number;
|
|
123
|
+
}
|
|
124
|
+
interface OrbitHandlers {
|
|
125
|
+
onWheel: (e: WheelEvent<HTMLElement>) => void;
|
|
126
|
+
onPointerDown: (e: PointerEvent$1<HTMLElement>) => void;
|
|
127
|
+
onDoubleClick: () => void;
|
|
128
|
+
isDragging: () => boolean;
|
|
129
|
+
}
|
|
130
|
+
/** Pointer gestures over an orbit view: drag to turn, wheel or pinch to dolly,
|
|
131
|
+
* double-click to go home. The 3D peer of `usePanZoom`. */
|
|
132
|
+
declare function useOrbit({ view, onViewChange, home, minDistance, maxDistance, }: UseOrbitOptions): OrbitHandlers;
|
|
133
|
+
|
|
134
|
+
interface UsePanZoomOptions {
|
|
135
|
+
view: ViewTransform;
|
|
136
|
+
onViewChange: (v: ViewTransform) => void;
|
|
137
|
+
/** The opening `view.zoom` always stays reachable, widening these past
|
|
138
|
+
* whatever is passed here if it would otherwise exclude it. */
|
|
139
|
+
minZoom?: number;
|
|
140
|
+
maxZoom?: number;
|
|
141
|
+
/** The instrument's coordinate system, resolved against the viewport. The
|
|
142
|
+
* wheel anchors in this frame; omitting it anchors at the element's
|
|
143
|
+
* top-left, which is what labkit did before a frame could be declared. */
|
|
144
|
+
frame?: WorldFrame;
|
|
145
|
+
/** A primary-button press released without ever crossing the drag
|
|
146
|
+
* threshold. The pointer session owns the release, so the gesture's end is
|
|
147
|
+
* reported here rather than left for a consumer's own `onPointerUp`. */
|
|
148
|
+
onTap?: (e: PointerEvent) => void;
|
|
149
|
+
}
|
|
150
|
+
interface PanZoomHandlers {
|
|
151
|
+
/** Zoom about the pointer. `anchor` is the element the pointer position is
|
|
152
|
+
* measured against, for an event whose `currentTarget` is some other box. */
|
|
153
|
+
onWheel: (e: WheelEvent<HTMLElement> | globalThis.WheelEvent, anchor?: Element) => void;
|
|
154
|
+
onPointerDown: (e: PointerEvent$1<HTMLElement>) => void;
|
|
155
|
+
isDragging: () => boolean;
|
|
156
|
+
}
|
|
157
|
+
declare function usePanZoom({ view, onViewChange, minZoom, maxZoom, frame, onTap, }: UsePanZoomOptions): PanZoomHandlers;
|
|
158
|
+
|
|
159
|
+
export { CanvasStack as C, PITCH_LIMIT as P, Stage as S, centerOn as f, clampPitch as g, fitStage as h, orbitAfterWheel as i, usePanZoom as j, wrapYaw as k, orbitAfterDrag as o, screenToWorld as s, useOrbit as u, worldToScreen as w, zoomAt as z };
|
|
160
|
+
export type { OrbitHandlers as O, UseOrbitOptions as U, Vec3 as V, ZoomAtOptions as Z, CanvasStackProps as a, OrbitView as b, PanZoomHandlers as c, StageProps as d, UsePanZoomOptions as e };
|