@weasel-js/labkit 1.2.0 → 1.3.0-pre.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/{DrawCommand-C_XboUpz.d.ts → DrawCommand-DBB45NfN.d.ts} +196 -52
- package/dist/_dts/PrefsForm-BYa6cWnO.d.ts +201 -0
- package/dist/_dts/index-DgcNdEdh.d.ts +314 -0
- package/dist/_dts/types-1Sdxy_Pv.d.ts +90 -0
- package/dist/_dts/types-AHlQxBNN.d.ts +162 -0
- package/dist/_dts/{useTrialState-BMNIx3Cy.d.ts → useTrialState-CsGMjhu9.d.ts} +5 -87
- package/dist/canvas/index.d.ts +7 -3
- package/dist/canvas/index.js +2 -1
- package/dist/chrome/index.d.ts +86 -0
- package/dist/chrome/index.js +8 -0
- package/dist/chrome/index.js.map +1 -0
- package/dist/{chunk-VUU5UXHE.js → chunk-4TMMVIDM.js} +8 -5
- package/dist/chunk-4TMMVIDM.js.map +1 -0
- package/dist/{chunk-THBG7FQZ.js → chunk-HFDVGF4X.js} +15 -12
- package/dist/chunk-HFDVGF4X.js.map +1 -0
- package/dist/{chunk-574LJAV4.js → chunk-NS54R52R.js} +31 -21
- package/dist/chunk-NS54R52R.js.map +1 -0
- package/dist/{chunk-G5TJVQQT.js → chunk-O2BULFHX.js} +5 -14
- package/dist/chunk-O2BULFHX.js.map +1 -0
- package/dist/chunk-O7NVSCLN.js +266 -0
- package/dist/chunk-O7NVSCLN.js.map +1 -0
- package/dist/chunk-PO6L3NSH.js +366 -0
- package/dist/chunk-PO6L3NSH.js.map +1 -0
- package/dist/chunk-PQJ5B2U2.js +27 -0
- package/dist/chunk-PQJ5B2U2.js.map +1 -0
- package/dist/chunk-RVNN4CHQ.js +212 -0
- package/dist/chunk-RVNN4CHQ.js.map +1 -0
- package/dist/chunk-TLGRYALP.js +6151 -0
- package/dist/chunk-TLGRYALP.js.map +1 -0
- package/dist/{chunk-SFL7NFKN.js → chunk-V7PRSIRQ.js} +15 -7
- package/dist/chunk-V7PRSIRQ.js.map +1 -0
- package/dist/{chunk-BOHF3PQO.js → chunk-Z6HJ5FEM.js} +8111 -5190
- package/dist/chunk-Z6HJ5FEM.js.map +1 -0
- package/dist/chunk-ZZAYVX4X.js +505 -0
- package/dist/chunk-ZZAYVX4X.js.map +1 -0
- package/dist/controls/index.d.ts +19 -5
- package/dist/controls/index.js +3 -1
- package/dist/dragdrop/index.d.ts +4 -2
- package/dist/index.d.ts +246 -106
- package/dist/index.js +673 -559
- package/dist/index.js.map +1 -1
- package/dist/layers/index.d.ts +5 -3
- package/dist/layers/index.js +2 -1
- package/dist/passthrough/weasel-canvas.d.ts +69 -13
- package/dist/passthrough/weasel-canvas.js +1 -1
- package/dist/passthrough/weasel-ui.d.ts +3799 -3672
- package/dist/passthrough/weasel-ui.js +2 -2
- package/dist/primitives/index.d.ts +102 -8
- package/dist/primitives/index.js +4 -1
- package/dist/state/index.d.ts +3 -2
- package/dist/state/index.js +2 -2
- package/dist/styles.css +542 -153
- package/dist/surface/index.js +2 -1
- package/dist/ui/layers/index.js +4 -3
- package/dist/undo/index.d.ts +4 -2
- package/package.json +16 -7
- package/src/canvas/AGENTS.md +4 -0
- package/src/canvas/CanvasStack.tsx +6 -2
- package/src/canvas/useLayerScheduler.ts +22 -15
- package/src/canvas/usePanZoom.test.ts +80 -0
- package/src/canvas/usePanZoom.ts +16 -2
- package/src/chrome/ChromeRegions.stories.tsx +106 -0
- package/src/chrome/builtins.test.ts +153 -0
- package/src/chrome/builtins.tsx +205 -0
- package/src/chrome/index.ts +25 -0
- package/src/chrome/merge.test.ts +51 -0
- package/src/chrome/merge.ts +52 -0
- package/src/chrome/regions/PaletteRegion.less +14 -0
- package/src/chrome/regions/PaletteRegion.test.tsx +36 -0
- package/src/chrome/regions/PaletteRegion.tsx +41 -0
- package/src/chrome/regions/SidebarRegion.tsx +56 -0
- package/src/chrome/regions/StatusRegion.tsx +31 -0
- package/src/chrome/regions/TitleBarRegion.tsx +41 -0
- package/src/chrome/regions/ToolbarRegion.test.tsx +82 -0
- package/src/chrome/regions/ToolbarRegion.tsx +71 -0
- package/src/chrome/regions/ViewportRegion.less +42 -0
- package/src/chrome/regions/ViewportRegion.tsx +37 -0
- package/src/chrome/regions/regions.test.tsx +81 -0
- package/src/chrome/types.ts +127 -0
- package/src/config/builder.test.ts +87 -0
- package/src/config/builder.ts +224 -0
- package/src/config/fromConfigField.test.ts +93 -0
- package/src/config/fromConfigField.ts +74 -0
- package/src/config/index.ts +22 -0
- package/src/config/resolve.test.ts +120 -0
- package/src/config/resolve.ts +67 -0
- package/src/config/rules.ts +68 -0
- package/src/config/types.ts +108 -0
- package/src/config/useConfigSchema.ts +30 -0
- package/src/config/visible.ts +20 -0
- package/src/controls/ControlPanel.less +4 -58
- package/src/controls/ControlPanel.stories.tsx +86 -0
- package/src/controls/ControlPanel.test.tsx +223 -10
- package/src/controls/ControlPanel.tsx +202 -203
- package/src/dragdrop/DragDropRuntime.tsx +36 -18
- package/src/dragdrop/DragGhost.less +1 -1
- package/src/dragdrop/Palette.less +1 -1
- package/src/index.ts +25 -3
- package/src/instrument/SineWave.smoke.test.tsx +8 -1
- package/src/instrument/defineInstrument.test.ts +38 -1
- package/src/instrument/defineInstrument.ts +31 -4
- package/src/instrument/index.ts +1 -0
- package/src/instrument/types.ts +27 -4
- package/src/instrument/validateConfigSchema.test.ts +13 -3
- package/src/instrument/validateConfigSchema.ts +7 -10
- package/src/lab/Lab.chrome.test.tsx +65 -0
- package/src/lab/Lab.tsx +58 -15
- package/src/lab/LabContext.ts +6 -0
- package/src/lab/LabFullChrome.stories.tsx +308 -0
- package/src/lab/LabHeader.test.tsx +42 -0
- package/src/lab/LabHeader.tsx +57 -0
- package/src/lab/LabPalette.test.tsx +35 -0
- package/src/lab/LabPalette.tsx +34 -0
- package/src/lab/LabShell.less +50 -3
- package/src/lab/Workspace.less +1 -30
- package/src/lab/Workspace.test.tsx +20 -10
- package/src/lab/Workspace.tsx +5 -8
- package/src/lab/index.ts +2 -0
- package/src/layers/AGENTS.md +1 -1
- package/src/layers/LayerList.less +31 -7
- package/src/layers/LayerList.tsx +17 -4
- package/src/passthrough/weasel-ui.ts +23 -0
- package/src/primitives/DragHandleGlyph.tsx +29 -0
- package/src/primitives/FloatingPanel.less +28 -0
- package/src/primitives/FloatingPanel.stories.tsx +46 -0
- package/src/primitives/FloatingPanel.test.tsx +240 -0
- package/src/primitives/FloatingPanel.tsx +190 -0
- package/src/primitives/FpsMeter.test.tsx +44 -0
- package/src/primitives/FpsMeter.tsx +20 -9
- package/src/primitives/JobProgress.less +69 -0
- package/src/primitives/JobProgress.stories.tsx +48 -0
- package/src/primitives/JobProgress.tsx +65 -0
- package/src/primitives/Legend.less +47 -0
- package/src/primitives/Legend.stories.tsx +32 -0
- package/src/primitives/Legend.test.tsx +57 -0
- package/src/primitives/Legend.tsx +40 -0
- package/src/primitives/Sidebar.less +32 -2
- package/src/primitives/StatusBar.less +7 -0
- package/src/primitives/StatusBar.tsx +10 -3
- package/src/primitives/Toolbar.less +50 -3
- package/src/primitives/Toolbar.test.tsx +67 -1
- package/src/primitives/Toolbar.tsx +72 -6
- package/src/primitives/ZoomControl.less +31 -0
- package/src/primitives/ZoomControl.tsx +76 -0
- package/src/primitives/floating.entry.test.tsx +14 -0
- package/src/primitives/index.ts +10 -2
- package/src/primitives/useRovingTabIndex.test.ts +27 -0
- package/src/primitives/useRovingTabIndex.ts +79 -0
- package/src/state/store.ts +11 -3
- package/src/state/toolSlot.test.ts +36 -0
- package/src/state/types.ts +4 -0
- package/src/styles.less +6 -0
- package/src/surface/useTiledSurface.ts +14 -10
- package/src/test-setup.ts +26 -0
- package/src/theme/base.less +19 -2
- package/src/theme/interstellar.tokens.json +6 -2
- package/src/tools/types.ts +24 -0
- package/src/trial/Trial.config.test.tsx +113 -0
- package/src/trial/Trial.job.test.tsx +13 -15
- package/src/trial/Trial.less +115 -10
- package/src/trial/Trial.stories.tsx +1 -0
- package/src/trial/Trial.test.tsx +67 -96
- package/src/trial/Trial.tsx +80 -39
- package/src/trial/TrialChrome.tsx +99 -80
- package/src/trial/TrialDragContext.ts +10 -0
- package/src/trial/TrialTitleBar.tsx +41 -0
- package/src/trial/index.ts +1 -15
- package/src/trial/trialChrome.borders.test.ts +38 -0
- package/src/ui/layers/LayerStack.less +9 -9
- package/src/ui/layers/LayerStack.tsx +1 -13
- package/src/ui/properties/CurveField.less +2 -2
- package/src/ui/properties/CurveField.test.tsx +11 -11
- package/src/ui/properties/PropertyGroup.less +2 -2
- package/src/ui/properties/PropertyPanel.less +55 -41
- package/src/ui/properties/SpeechBalloonPanels.stories.tsx +4 -2
- package/src/ui/properties/storyLayouts.tsx +2 -2
- package/dist/_dts/index-JFAYj5Tv.d.ts +0 -144
- package/dist/_dts/types-x92Kfeme.d.ts +0 -62
- package/dist/chunk-574LJAV4.js.map +0 -1
- package/dist/chunk-5R2ATYPJ.js +0 -201
- package/dist/chunk-5R2ATYPJ.js.map +0 -1
- package/dist/chunk-73KA7WBO.js +0 -5992
- package/dist/chunk-73KA7WBO.js.map +0 -1
- package/dist/chunk-BOHF3PQO.js.map +0 -1
- package/dist/chunk-G5TJVQQT.js.map +0 -1
- package/dist/chunk-PMAU3SEE.js +0 -126
- package/dist/chunk-PMAU3SEE.js.map +0 -1
- package/dist/chunk-SFL7NFKN.js.map +0 -1
- package/dist/chunk-THBG7FQZ.js.map +0 -1
- package/dist/chunk-VUU5UXHE.js.map +0 -1
- package/src/instrument/capabilityDetector.test.ts +0 -64
- package/src/instrument/capabilityDetector.ts +0 -20
- package/src/trial/DefaultSidebar.tsx +0 -29
- package/src/trial/DefaultStatusBar.tsx +0 -19
- package/src/trial/DefaultToolbar.tsx +0 -92
- package/src/trial/slotTypes.ts +0 -54
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
import { p } from './chunk-TLGRYALP.js';
|
|
2
|
+
import { isBuiltinToolPref } from './chunk-Z6HJ5FEM.js';
|
|
3
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
import { useState, useMemo, useRef, useEffect } from 'react';
|
|
5
|
+
|
|
6
|
+
// src/config/fromConfigField.ts
|
|
7
|
+
function toLeaf(field) {
|
|
8
|
+
const base = { name: field.label, description: "" };
|
|
9
|
+
switch (field.type) {
|
|
10
|
+
case "slider":
|
|
11
|
+
return {
|
|
12
|
+
...base,
|
|
13
|
+
kind: "number",
|
|
14
|
+
control: "slider",
|
|
15
|
+
min: field.min,
|
|
16
|
+
max: field.max,
|
|
17
|
+
step: field.step
|
|
18
|
+
};
|
|
19
|
+
case "number":
|
|
20
|
+
return {
|
|
21
|
+
...base,
|
|
22
|
+
kind: "number",
|
|
23
|
+
control: "input",
|
|
24
|
+
min: field.min,
|
|
25
|
+
max: field.max,
|
|
26
|
+
step: field.step
|
|
27
|
+
};
|
|
28
|
+
case "checkbox":
|
|
29
|
+
return { ...base, kind: "boolean", control: "checkbox" };
|
|
30
|
+
case "select":
|
|
31
|
+
return { ...base, kind: "enum", options: field.options };
|
|
32
|
+
case "text":
|
|
33
|
+
return {
|
|
34
|
+
...base,
|
|
35
|
+
kind: "string",
|
|
36
|
+
placeholder: field.placeholder,
|
|
37
|
+
maxLength: field.maxLength,
|
|
38
|
+
debounceMs: field.debounceMs
|
|
39
|
+
};
|
|
40
|
+
case "color":
|
|
41
|
+
return { ...base, kind: "color" };
|
|
42
|
+
default:
|
|
43
|
+
return { ...base, kind: field.type };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function fromConfigFields(fields) {
|
|
47
|
+
const children = {};
|
|
48
|
+
for (const field of fields) {
|
|
49
|
+
const patch = toLeaf(field);
|
|
50
|
+
for (const key of Object.keys(patch)) {
|
|
51
|
+
if (patch[key] === void 0) {
|
|
52
|
+
delete patch[key];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
children[field.key] = { ...patch, default: field.default };
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
group: { name: "", children },
|
|
59
|
+
sections: [],
|
|
60
|
+
showIf: /* @__PURE__ */ new Map(),
|
|
61
|
+
renderers: {}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// src/config/visible.ts
|
|
66
|
+
function isLeafVisible(resolved, path, config, showHidden = false) {
|
|
67
|
+
const leaf = resolved.group.children[path];
|
|
68
|
+
if (leaf && "hidden" in leaf && leaf.hidden === true && !showHidden) return false;
|
|
69
|
+
const predicate = resolved.showIf.get(path);
|
|
70
|
+
return predicate ? predicate(config) : true;
|
|
71
|
+
}
|
|
72
|
+
function PropertyGroup({
|
|
73
|
+
title,
|
|
74
|
+
hidden,
|
|
75
|
+
children,
|
|
76
|
+
className,
|
|
77
|
+
pack = "auto-color"
|
|
78
|
+
}) {
|
|
79
|
+
if (hidden) return null;
|
|
80
|
+
const packClass = pack === "pairs" ? " lk-property-group--pairs" : "";
|
|
81
|
+
const cls = `lk-property-group${packClass}${className ? ` ${className}` : ""}`;
|
|
82
|
+
return /* @__PURE__ */ jsxs("div", { className: cls, children: [
|
|
83
|
+
/* @__PURE__ */ jsxs("h3", { className: "lk-property-group__title", children: [
|
|
84
|
+
/* @__PURE__ */ jsx("hr", {}),
|
|
85
|
+
/* @__PURE__ */ jsx("span", { children: title }),
|
|
86
|
+
/* @__PURE__ */ jsx("hr", {})
|
|
87
|
+
] }),
|
|
88
|
+
/* @__PURE__ */ jsx("div", { className: "lk-property-group__body", children })
|
|
89
|
+
] });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// src/ui/format.ts
|
|
93
|
+
var MINUS = "\u2212";
|
|
94
|
+
function formatNumber(n, fractionDigits) {
|
|
95
|
+
if (!Number.isFinite(n)) return String(n);
|
|
96
|
+
const s = fractionDigits == null ? String(n) : n.toFixed(fractionDigits);
|
|
97
|
+
return s.startsWith("-") ? MINUS + s.slice(1) : s;
|
|
98
|
+
}
|
|
99
|
+
function parseSignedNumber(s) {
|
|
100
|
+
return Number(s.replace(MINUS, "-"));
|
|
101
|
+
}
|
|
102
|
+
function PropertyPanel({ title, children, className }) {
|
|
103
|
+
const cls = className ? `lk-property-panel ${className}` : "lk-property-panel";
|
|
104
|
+
return /* @__PURE__ */ jsxs("div", { className: cls, children: [
|
|
105
|
+
title != null && /* @__PURE__ */ jsx("h2", { className: "lk-property-panel__title", children: title }),
|
|
106
|
+
children
|
|
107
|
+
] });
|
|
108
|
+
}
|
|
109
|
+
function PropertyList({ children, className, pack = "auto-color" }) {
|
|
110
|
+
const packClass = pack === "pairs" ? " lk-property-list--pairs" : "";
|
|
111
|
+
const cls = `lk-property-list${packClass}${className ? ` ${className}` : ""}`;
|
|
112
|
+
return /* @__PURE__ */ jsx("div", { className: cls, children });
|
|
113
|
+
}
|
|
114
|
+
function PropertyRow({
|
|
115
|
+
label,
|
|
116
|
+
readout,
|
|
117
|
+
variant = "default",
|
|
118
|
+
layout = "block",
|
|
119
|
+
children,
|
|
120
|
+
htmlFor,
|
|
121
|
+
className
|
|
122
|
+
}) {
|
|
123
|
+
const variantClass = variant === "default" ? "" : ` lk-property-row--${variant}`;
|
|
124
|
+
const layoutClass = variant === "default" && layout === "inline" ? " lk-property-row--inline" : "";
|
|
125
|
+
const cls = `lk-property-row${variantClass}${layoutClass}${className ? ` ${className}` : ""}`;
|
|
126
|
+
return /* @__PURE__ */ jsxs("label", { className: cls, htmlFor, children: [
|
|
127
|
+
/* @__PURE__ */ jsxs("span", { className: "lk-property-row__label", children: [
|
|
128
|
+
label,
|
|
129
|
+
readout != null && /* @__PURE__ */ jsx("em", { className: "lk-property-row__readout", children: readout })
|
|
130
|
+
] }),
|
|
131
|
+
children
|
|
132
|
+
] });
|
|
133
|
+
}
|
|
134
|
+
function SliderRow({
|
|
135
|
+
label,
|
|
136
|
+
value,
|
|
137
|
+
min,
|
|
138
|
+
max,
|
|
139
|
+
step = 1,
|
|
140
|
+
onChange,
|
|
141
|
+
format,
|
|
142
|
+
unit,
|
|
143
|
+
layout
|
|
144
|
+
}) {
|
|
145
|
+
const decimals = step >= 1 ? 0 : Math.min(6, Math.max(0, Math.ceil(-Math.log10(step))));
|
|
146
|
+
const effectiveFormat = format ?? ((n) => formatNumber(n, decimals));
|
|
147
|
+
return /* @__PURE__ */ jsx(
|
|
148
|
+
PropertyRow,
|
|
149
|
+
{
|
|
150
|
+
label,
|
|
151
|
+
readout: /* @__PURE__ */ jsx(
|
|
152
|
+
EditableReadout,
|
|
153
|
+
{
|
|
154
|
+
value,
|
|
155
|
+
min,
|
|
156
|
+
max,
|
|
157
|
+
format: effectiveFormat,
|
|
158
|
+
unit,
|
|
159
|
+
onCommit: onChange
|
|
160
|
+
}
|
|
161
|
+
),
|
|
162
|
+
layout,
|
|
163
|
+
children: /* @__PURE__ */ jsx(
|
|
164
|
+
"input",
|
|
165
|
+
{
|
|
166
|
+
type: "range",
|
|
167
|
+
tabIndex: -1,
|
|
168
|
+
min,
|
|
169
|
+
max,
|
|
170
|
+
step,
|
|
171
|
+
value,
|
|
172
|
+
onChange: (e) => {
|
|
173
|
+
const v = Number(e.target.value);
|
|
174
|
+
p("property-panel", "slider", { label, value: v });
|
|
175
|
+
onChange(v);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
)
|
|
179
|
+
}
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
function EditableReadout({ value, min, max, format, unit, onCommit }) {
|
|
183
|
+
const [draft, setDraft] = useState(null);
|
|
184
|
+
const fmt = (n) => format ? format(n) : formatNumber(n);
|
|
185
|
+
const displayValue = draft !== null ? draft : (() => {
|
|
186
|
+
const formatted = fmt(value);
|
|
187
|
+
return typeof formatted === "string" ? formatted : String(formatted);
|
|
188
|
+
})();
|
|
189
|
+
const suffix = unit == null ? null : typeof unit === "string" ? /* @__PURE__ */ jsx("span", { className: "lk-property-row__readout-unit", children: unit }) : unit;
|
|
190
|
+
const commit = () => {
|
|
191
|
+
if (draft !== null) {
|
|
192
|
+
const n = parseSignedNumber(draft);
|
|
193
|
+
if (Number.isFinite(n)) onCommit(Math.min(max, Math.max(min, n)));
|
|
194
|
+
}
|
|
195
|
+
setDraft(null);
|
|
196
|
+
};
|
|
197
|
+
return /* @__PURE__ */ jsxs("span", { className: "lk-property-row__readout-group", children: [
|
|
198
|
+
/* @__PURE__ */ jsx(
|
|
199
|
+
"input",
|
|
200
|
+
{
|
|
201
|
+
type: "text",
|
|
202
|
+
inputMode: "decimal",
|
|
203
|
+
className: "lk-property-row__readout-input",
|
|
204
|
+
value: displayValue,
|
|
205
|
+
onFocus: (e) => {
|
|
206
|
+
const formatted = fmt(value);
|
|
207
|
+
setDraft(typeof formatted === "string" ? formatted : String(formatted));
|
|
208
|
+
e.currentTarget.select();
|
|
209
|
+
},
|
|
210
|
+
onChange: (e) => setDraft(e.target.value.replace(/-/g, "\u2212")),
|
|
211
|
+
onBlur: commit,
|
|
212
|
+
onClick: (e) => {
|
|
213
|
+
e.preventDefault();
|
|
214
|
+
e.stopPropagation();
|
|
215
|
+
e.currentTarget.focus();
|
|
216
|
+
},
|
|
217
|
+
onMouseDown: (e) => e.stopPropagation(),
|
|
218
|
+
onKeyDown: (e) => {
|
|
219
|
+
if (e.key === "Enter") {
|
|
220
|
+
commit();
|
|
221
|
+
e.currentTarget.blur();
|
|
222
|
+
} else if (e.key === "Escape") {
|
|
223
|
+
setDraft(null);
|
|
224
|
+
e.currentTarget.blur();
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
),
|
|
229
|
+
suffix
|
|
230
|
+
] });
|
|
231
|
+
}
|
|
232
|
+
function ColorRow({
|
|
233
|
+
label,
|
|
234
|
+
value,
|
|
235
|
+
onChange,
|
|
236
|
+
alpha,
|
|
237
|
+
onAlphaChange,
|
|
238
|
+
alphaDisabled
|
|
239
|
+
}) {
|
|
240
|
+
const showAlpha = alpha != null;
|
|
241
|
+
const className = alphaDisabled ? "lk-property-row--alpha-disabled" : void 0;
|
|
242
|
+
return /* @__PURE__ */ jsxs(PropertyRow, { label, variant: "color", className, children: [
|
|
243
|
+
/* @__PURE__ */ jsx("input", { type: "color", value, onChange: (e) => onChange(e.target.value) }),
|
|
244
|
+
showAlpha && /* @__PURE__ */ jsx(
|
|
245
|
+
"input",
|
|
246
|
+
{
|
|
247
|
+
type: "range",
|
|
248
|
+
className: "lk-property-row__alpha",
|
|
249
|
+
min: 0,
|
|
250
|
+
max: 1,
|
|
251
|
+
step: 0.01,
|
|
252
|
+
value: alpha,
|
|
253
|
+
disabled: alphaDisabled,
|
|
254
|
+
onChange: (e) => onAlphaChange?.(Number(e.target.value))
|
|
255
|
+
}
|
|
256
|
+
)
|
|
257
|
+
] });
|
|
258
|
+
}
|
|
259
|
+
function CheckboxRow({ label, value, onChange }) {
|
|
260
|
+
return /* @__PURE__ */ jsx(PropertyRow, { label, variant: "checkbox", children: /* @__PURE__ */ jsx("input", { type: "checkbox", checked: value, onChange: (e) => onChange(e.target.checked) }) });
|
|
261
|
+
}
|
|
262
|
+
function TextRow({ label, value, onChange, placeholder, maxLength, layout }) {
|
|
263
|
+
return /* @__PURE__ */ jsx(PropertyRow, { label, layout, children: /* @__PURE__ */ jsx(
|
|
264
|
+
"input",
|
|
265
|
+
{
|
|
266
|
+
type: "text",
|
|
267
|
+
value,
|
|
268
|
+
placeholder,
|
|
269
|
+
maxLength,
|
|
270
|
+
onChange: (e) => onChange(e.target.value)
|
|
271
|
+
}
|
|
272
|
+
) });
|
|
273
|
+
}
|
|
274
|
+
function NumberRow({
|
|
275
|
+
label,
|
|
276
|
+
value,
|
|
277
|
+
onChange,
|
|
278
|
+
min,
|
|
279
|
+
max,
|
|
280
|
+
step,
|
|
281
|
+
placeholder,
|
|
282
|
+
layout
|
|
283
|
+
}) {
|
|
284
|
+
return /* @__PURE__ */ jsx(PropertyRow, { label, layout, children: /* @__PURE__ */ jsx(
|
|
285
|
+
"input",
|
|
286
|
+
{
|
|
287
|
+
type: "number",
|
|
288
|
+
value,
|
|
289
|
+
min,
|
|
290
|
+
max,
|
|
291
|
+
step,
|
|
292
|
+
placeholder,
|
|
293
|
+
onChange: (e) => {
|
|
294
|
+
const raw = e.target.value;
|
|
295
|
+
if (raw === "") return;
|
|
296
|
+
const n = Number(raw);
|
|
297
|
+
if (Number.isFinite(n)) onChange(n);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
) });
|
|
301
|
+
}
|
|
302
|
+
function SelectRow({
|
|
303
|
+
label,
|
|
304
|
+
value,
|
|
305
|
+
options,
|
|
306
|
+
onChange,
|
|
307
|
+
layout
|
|
308
|
+
}) {
|
|
309
|
+
return /* @__PURE__ */ jsx(PropertyRow, { label, layout, children: /* @__PURE__ */ jsx(
|
|
310
|
+
"select",
|
|
311
|
+
{
|
|
312
|
+
value,
|
|
313
|
+
onChange: (e) => {
|
|
314
|
+
const v = e.target.value;
|
|
315
|
+
p("property-panel", "select", { label, value: v });
|
|
316
|
+
onChange(v);
|
|
317
|
+
},
|
|
318
|
+
children: options.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label }, opt.value))
|
|
319
|
+
}
|
|
320
|
+
) });
|
|
321
|
+
}
|
|
322
|
+
function ToggleRow({
|
|
323
|
+
label,
|
|
324
|
+
value,
|
|
325
|
+
options,
|
|
326
|
+
onChange,
|
|
327
|
+
layout
|
|
328
|
+
}) {
|
|
329
|
+
return /* @__PURE__ */ jsx(PropertyRow, { label, layout, children: /* @__PURE__ */ jsx("div", { className: "lk-property-row__toggle", children: options.map((opt) => {
|
|
330
|
+
const selected = opt.value === value;
|
|
331
|
+
return /* @__PURE__ */ jsx(
|
|
332
|
+
"button",
|
|
333
|
+
{
|
|
334
|
+
type: "button",
|
|
335
|
+
"aria-pressed": selected,
|
|
336
|
+
className: selected ? "lk-property-row__toggle-button lk-property-row__toggle-button--selected" : "lk-property-row__toggle-button",
|
|
337
|
+
onClick: () => onChange(opt.value),
|
|
338
|
+
children: opt.label
|
|
339
|
+
},
|
|
340
|
+
opt.value
|
|
341
|
+
);
|
|
342
|
+
}) }) });
|
|
343
|
+
}
|
|
344
|
+
function ControlPanel({
|
|
345
|
+
schema,
|
|
346
|
+
fields,
|
|
347
|
+
config,
|
|
348
|
+
setConfig,
|
|
349
|
+
renderers,
|
|
350
|
+
showHidden = false,
|
|
351
|
+
className
|
|
352
|
+
}) {
|
|
353
|
+
const resolved = useMemo(
|
|
354
|
+
() => schema ?? fromConfigFields(fields ?? []),
|
|
355
|
+
[schema, fields]
|
|
356
|
+
);
|
|
357
|
+
const paths = Object.keys(resolved.group.children);
|
|
358
|
+
const sectioned = new Set(resolved.sections.flatMap((s) => s.paths));
|
|
359
|
+
const loose = paths.filter((p2) => !sectioned.has(p2));
|
|
360
|
+
const row = (path) => /* @__PURE__ */ jsx(
|
|
361
|
+
ControlRow,
|
|
362
|
+
{
|
|
363
|
+
path,
|
|
364
|
+
resolved,
|
|
365
|
+
config,
|
|
366
|
+
setConfig,
|
|
367
|
+
renderers,
|
|
368
|
+
showHidden
|
|
369
|
+
},
|
|
370
|
+
path
|
|
371
|
+
);
|
|
372
|
+
return /* @__PURE__ */ jsxs(PropertyList, { className: className ? `lk-control-panel ${className}` : "lk-control-panel", children: [
|
|
373
|
+
loose.map(row),
|
|
374
|
+
resolved.sections.map((section) => /* @__PURE__ */ jsx(PropertyGroup, { title: section.label, children: section.paths.map(row) }, section.label))
|
|
375
|
+
] });
|
|
376
|
+
}
|
|
377
|
+
function extra(leaf, key) {
|
|
378
|
+
return leaf[key];
|
|
379
|
+
}
|
|
380
|
+
function ControlRow({
|
|
381
|
+
path,
|
|
382
|
+
resolved,
|
|
383
|
+
config,
|
|
384
|
+
setConfig,
|
|
385
|
+
renderers,
|
|
386
|
+
showHidden
|
|
387
|
+
}) {
|
|
388
|
+
const leaf = resolved.group.children[path];
|
|
389
|
+
if (!leaf || !("kind" in leaf)) return null;
|
|
390
|
+
if (!isLeafVisible(resolved, path, config, showHidden)) return null;
|
|
391
|
+
const write = (value2) => setConfig(path, value2);
|
|
392
|
+
const fallback = extra(leaf, "default");
|
|
393
|
+
const value = config[path] ?? fallback;
|
|
394
|
+
const custom = renderers?.[path] ?? resolved.renderers[path] ?? renderers?.[leaf.kind];
|
|
395
|
+
if (custom) return custom({ path, pref: leaf, value, setValue: write });
|
|
396
|
+
const label = leaf.name;
|
|
397
|
+
const read = () => value;
|
|
398
|
+
if (!isBuiltinToolPref(leaf)) return /* @__PURE__ */ jsx(UnwiredRow, { label, kind: leaf.kind });
|
|
399
|
+
switch (leaf.kind) {
|
|
400
|
+
case "number": {
|
|
401
|
+
const min = extra(leaf, "min");
|
|
402
|
+
const max = extra(leaf, "max");
|
|
403
|
+
const step = extra(leaf, "step");
|
|
404
|
+
if (extra(leaf, "control") === "slider" && min !== void 0 && max !== void 0) {
|
|
405
|
+
return /* @__PURE__ */ jsx(
|
|
406
|
+
SliderRow,
|
|
407
|
+
{
|
|
408
|
+
label,
|
|
409
|
+
value: read(),
|
|
410
|
+
min,
|
|
411
|
+
max,
|
|
412
|
+
step,
|
|
413
|
+
onChange: write
|
|
414
|
+
}
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
const lo = min ?? Number.NEGATIVE_INFINITY;
|
|
418
|
+
const hi = max ?? Number.POSITIVE_INFINITY;
|
|
419
|
+
return /* @__PURE__ */ jsx(
|
|
420
|
+
NumberRow,
|
|
421
|
+
{
|
|
422
|
+
label,
|
|
423
|
+
value: read(),
|
|
424
|
+
min,
|
|
425
|
+
max,
|
|
426
|
+
step,
|
|
427
|
+
onChange: (n) => write(Math.min(hi, Math.max(lo, n)))
|
|
428
|
+
}
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
case "boolean":
|
|
432
|
+
return /* @__PURE__ */ jsx(CheckboxRow, { label, value: read(), onChange: write });
|
|
433
|
+
case "enum": {
|
|
434
|
+
const options = extra(leaf, "options") ?? [];
|
|
435
|
+
const Row = extra(leaf, "control") === "radio" ? ToggleRow : SelectRow;
|
|
436
|
+
return /* @__PURE__ */ jsx(Row, { label, value: read(), options, onChange: write });
|
|
437
|
+
}
|
|
438
|
+
case "string":
|
|
439
|
+
return /* @__PURE__ */ jsx(DebouncedTextRow, { leaf, label, value: read(), write });
|
|
440
|
+
case "color":
|
|
441
|
+
return /* @__PURE__ */ jsx(ColorRow, { label, value: read(), onChange: write });
|
|
442
|
+
case "paint":
|
|
443
|
+
case "object":
|
|
444
|
+
return /* @__PURE__ */ jsx(UnwiredRow, { label, kind: leaf.kind });
|
|
445
|
+
default: {
|
|
446
|
+
const _exhaustive = leaf;
|
|
447
|
+
throw new Error(
|
|
448
|
+
`ControlPanel: no control for built-in pref kind "${_exhaustive.kind}"`
|
|
449
|
+
);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
function UnwiredRow({ label, kind }) {
|
|
454
|
+
return /* @__PURE__ */ jsx(PropertyRow, { label, children: /* @__PURE__ */ jsxs("span", { className: "lk-control-panel__unknown", children: [
|
|
455
|
+
"no control for \u201C",
|
|
456
|
+
kind,
|
|
457
|
+
"\u201D"
|
|
458
|
+
] }) });
|
|
459
|
+
}
|
|
460
|
+
function DebouncedTextRow({
|
|
461
|
+
leaf,
|
|
462
|
+
label,
|
|
463
|
+
value,
|
|
464
|
+
write
|
|
465
|
+
}) {
|
|
466
|
+
const debounceMs = extra(leaf, "debounceMs") ?? 150;
|
|
467
|
+
const [local, setLocal] = useState(value);
|
|
468
|
+
const timer = useRef(null);
|
|
469
|
+
const lastExternal = useRef(value);
|
|
470
|
+
useEffect(() => {
|
|
471
|
+
if (value !== lastExternal.current) {
|
|
472
|
+
lastExternal.current = value;
|
|
473
|
+
setLocal(value);
|
|
474
|
+
}
|
|
475
|
+
}, [value]);
|
|
476
|
+
useEffect(
|
|
477
|
+
() => () => {
|
|
478
|
+
if (timer.current) clearTimeout(timer.current);
|
|
479
|
+
},
|
|
480
|
+
[]
|
|
481
|
+
);
|
|
482
|
+
return /* @__PURE__ */ jsx(
|
|
483
|
+
TextRow,
|
|
484
|
+
{
|
|
485
|
+
label,
|
|
486
|
+
value: local,
|
|
487
|
+
placeholder: extra(leaf, "placeholder"),
|
|
488
|
+
maxLength: extra(leaf, "maxLength"),
|
|
489
|
+
onChange: (next) => {
|
|
490
|
+
setLocal(next);
|
|
491
|
+
if (timer.current) clearTimeout(timer.current);
|
|
492
|
+
const commit = () => {
|
|
493
|
+
lastExternal.current = next;
|
|
494
|
+
write(next);
|
|
495
|
+
};
|
|
496
|
+
if (debounceMs === 0) commit();
|
|
497
|
+
else timer.current = setTimeout(commit, debounceMs);
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
export { CheckboxRow, ColorRow, ControlPanel, NumberRow, PropertyGroup, PropertyList, PropertyPanel, PropertyRow, SelectRow, SliderRow, TextRow, ToggleRow, fromConfigFields, isLeafVisible };
|
|
504
|
+
//# sourceMappingURL=chunk-ZZAYVX4X.js.map
|
|
505
|
+
//# sourceMappingURL=chunk-ZZAYVX4X.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config/fromConfigField.ts","../src/config/visible.ts","../src/ui/properties/PropertyGroup.tsx","../src/ui/format.ts","../src/ui/properties/PropertyPanel.tsx","../src/controls/ControlPanel.tsx"],"names":["jsxs","jsx","p","value","useState"],"mappings":"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","file":"chunk-ZZAYVX4X.js","sourcesContent":["import type { PrefLeaf } from '@weasel-js/ui';\nimport type { ConfigField } from '../controls/types';\nimport type { LeafPatch, ResolvedConfig } from './types';\n\n/** One `ConfigField` as the `Pref*` vocabulary spells it. The two describe the\n * same thing; `ConfigField` just keys on the control where `PrefLeaf`\n * separates the value's kind from how it is presented. */\nfunction toLeaf(field: ConfigField): LeafPatch {\n const base = { name: field.label, description: '' };\n switch (field.type) {\n case 'slider':\n return {\n ...base,\n kind: 'number',\n control: 'slider',\n min: field.min,\n max: field.max,\n step: field.step,\n };\n case 'number':\n return {\n ...base,\n kind: 'number',\n control: 'input',\n min: field.min,\n max: field.max,\n step: field.step,\n };\n case 'checkbox':\n return { ...base, kind: 'boolean', control: 'checkbox' };\n case 'select':\n return { ...base, kind: 'enum', options: field.options };\n case 'text':\n return {\n ...base,\n kind: 'string',\n placeholder: field.placeholder,\n maxLength: field.maxLength,\n debounceMs: field.debounceMs,\n };\n case 'color':\n return { ...base, kind: 'color' };\n default:\n // A schema can arrive from outside TypeScript. Carry the kind through\n // so a lab-supplied renderer can still claim it.\n return { ...base, kind: (field as ConfigField).type };\n }\n}\n\n/**\n * Adapt a legacy `configSchema(): ConfigField[]` into the resolved shape, so\n * both instrument paths reach one renderer.\n *\n * Rules do not run here: a hand-written `ConfigField` already states its label\n * and control, which is everything the rule chain would have inferred.\n */\nexport function fromConfigFields(fields: readonly ConfigField[]): ResolvedConfig {\n const children: Record<string, PrefLeaf> = {};\n for (const field of fields) {\n const patch = toLeaf(field);\n for (const key of Object.keys(patch)) {\n if ((patch as Record<string, unknown>)[key] === undefined) {\n delete (patch as Record<string, unknown>)[key];\n }\n }\n children[field.key] = { ...patch, default: field.default } as PrefLeaf;\n }\n return {\n group: { name: '', children },\n sections: [],\n showIf: new Map(),\n renderers: {},\n };\n}\n","import type { ResolvedConfig } from './types';\n\n/**\n * Whether a leaf's row should be drawn right now.\n *\n * `hidden` is the leaf's own static flag; `showIf` is the schema's predicate\n * over the live config. Both are presentational — a hidden leaf keeps its\n * value and the instrument still reads it.\n */\nexport function isLeafVisible(\n resolved: ResolvedConfig,\n path: string,\n config: Record<string, unknown>,\n showHidden = false,\n): boolean {\n const leaf = resolved.group.children[path];\n if (leaf && 'hidden' in leaf && leaf.hidden === true && !showHidden) return false;\n const predicate = resolved.showIf.get(path);\n return predicate ? predicate(config) : true;\n}\n","import type { ReactNode } from 'react';\n\n/** Props for `<PropertyGroup>`. */\nexport interface PropertyGroupProps {\n /** Title rendered between two rules at the top of the group. */\n title: ReactNode;\n /** When true the group renders nothing — useful for conditional sections. */\n hidden?: boolean;\n children: ReactNode;\n className?: string;\n /**\n * How rows pack into the 2-column grid.\n * - `'auto-color'` (default): only color rows pair side-by-side; everything\n * else spans the full width.\n * - `'pairs'`: every row auto-places into the 2-column grid two-per-row.\n */\n pack?: 'auto-color' | 'pairs';\n}\n\n/**\n * Visually-bordered group inside a PropertyList. Use to scope a set of\n * related rows under a heading (e.g. \"Aqua\", \"Bevel\", \"Dome\" sections\n * inside a fill effect's controls).\n */\nexport function PropertyGroup({\n title,\n hidden,\n children,\n className,\n pack = 'auto-color',\n}: PropertyGroupProps) {\n if (hidden) return null;\n const packClass = pack === 'pairs' ? ' lk-property-group--pairs' : '';\n const cls = `lk-property-group${packClass}${className ? ` ${className}` : ''}`;\n return (\n <div className={cls}>\n <h3 className=\"lk-property-group__title\">\n <hr />\n <span>{title}</span>\n <hr />\n </h3>\n <div className=\"lk-property-group__body\">{children}</div>\n </div>\n );\n}\n","// Display formatting helpers shared across the UI.\n//\n// House style: render negative numbers with the typographic MINUS SIGN\n// (U+2212, \"−\") instead of ASCII hyphen-minus (\"-\"). Editing surfaces should\n// accept either glyph on input via `parseSignedNumber`.\n\nconst MINUS = '−';\n\n/** Format a finite number for display, swapping the leading \"-\" to U+2212. */\nexport function formatNumber(n: number, fractionDigits?: number): string {\n if (!Number.isFinite(n)) return String(n);\n const s = fractionDigits == null ? String(n) : n.toFixed(fractionDigits);\n return s.startsWith('-') ? MINUS + s.slice(1) : s;\n}\n\n/** Parse a string that may use U+2212 or ASCII hyphen-minus for the negative sign. */\nexport function parseSignedNumber(s: string): number {\n return Number(s.replace(MINUS, '-'));\n}\n\n/** Zoom for display. Below 2x a percentage reads naturally; past it the\n * numbers get long and a multiplier is what people say out loud, so 250%\n * shows as `2.5x`. Past 100x a tenth is noise, so the decimal is dropped\n * and thousands are grouped: `1009.74` reads as `1,010x`. */\nexport function formatZoom(zoom: number): string {\n if (!Number.isFinite(zoom)) return String(zoom);\n if (zoom <= 2) return `${formatNumber(Math.round(zoom * 100))}%`;\n if (zoom >= 100) return `${Math.round(zoom).toLocaleString('en-US')}x`;\n return `${formatNumber(Math.round(zoom * 10) / 10)}x`;\n}\n","import { type ReactNode, useState } from 'react';\nimport { dlog } from '../../passthrough/weasel-ui';\nimport { formatNumber, parseSignedNumber } from '../format';\n\n/** Props for `<PropertyPanel>`. */\nexport interface PropertyPanelProps {\n title?: ReactNode;\n children: ReactNode;\n className?: string;\n}\n\n/** A titled panel holding property rows — the sidebar container the rest of\n * this module's components fill. */\nexport function PropertyPanel({ title, children, className }: PropertyPanelProps) {\n const cls = className ? `lk-property-panel ${className}` : 'lk-property-panel';\n return (\n <div className={cls}>\n {title != null && <h2 className=\"lk-property-panel__title\">{title}</h2>}\n {children}\n </div>\n );\n}\n\n/** How a property list packs its rows into two columns. */\nexport type PropertyListPack = 'auto-color' | 'pairs';\n\n/** Props for `<PropertyList>`. */\nexport interface PropertyListProps {\n children: ReactNode;\n className?: string;\n /**\n * How rows pack into the 2-column grid.\n * - `'auto-color'` (default): only color rows pair side-by-side; everything\n * else spans the full width. Right for sparse top-level panels.\n * - `'pairs'`: every row auto-places into the 2-column grid two-per-row.\n * Headers, subpanels, and full-width children (`<hr>`, curve blocks)\n * still span via `lk-property-list__span`. Right for dense effect bodies.\n */\n pack?: PropertyListPack;\n}\n\n/**\n * Grid container for PropertyRows. Use standalone for chrome-less layouts, or\n * nest inside <PropertyPanel/> for the standard glass card.\n */\nexport function PropertyList({ children, className, pack = 'auto-color' }: PropertyListProps) {\n const packClass = pack === 'pairs' ? ' lk-property-list--pairs' : '';\n const cls = `lk-property-list${packClass}${className ? ` ${className}` : ''}`;\n return <div className={cls}>{children}</div>;\n}\n\n/** Which control shape a row holds, which decides its intrinsic layout. */\nexport type PropertyRowVariant = 'default' | 'color' | 'checkbox';\n/** Whether a row's label sits above its control or beside it. */\nexport type PropertyRowLayout = 'block' | 'inline';\n\n/** Props for `<PropertyRow>`. */\nexport interface PropertyRowProps {\n label: ReactNode;\n /** Right-aligned readout shown next to the label (e.g. current value). */\n readout?: ReactNode;\n variant?: PropertyRowVariant;\n /**\n * Label position relative to the control. \"block\" (default) stacks\n * label above control; \"inline\" places the label to the left.\n * Color and checkbox variants are always inline by their own nature.\n */\n layout?: PropertyRowLayout;\n children: ReactNode;\n htmlFor?: string;\n className?: string;\n}\n\n/** The label-plus-control frame every typed row below is built from. Use it\n * directly for a control this module does not cover. */\nexport function PropertyRow({\n label,\n readout,\n variant = 'default',\n layout = 'block',\n children,\n htmlFor,\n className,\n}: PropertyRowProps) {\n const variantClass = variant === 'default' ? '' : ` lk-property-row--${variant}`;\n // Layout only meaningfully applies to the default variant; color and\n // checkbox have their own intrinsic orientation.\n const layoutClass =\n variant === 'default' && layout === 'inline' ? ' lk-property-row--inline' : '';\n const cls = `lk-property-row${variantClass}${layoutClass}${className ? ` ${className}` : ''}`;\n return (\n <label className={cls} htmlFor={htmlFor}>\n <span className=\"lk-property-row__label\">\n {label}\n {readout != null && <em className=\"lk-property-row__readout\">{readout}</em>}\n </span>\n {children}\n </label>\n );\n}\n\n// ── Row implementations ──────────────────────────────────────────────\n\n/** Props for `<SliderRow>`. */\nexport interface SliderRowProps {\n label: ReactNode;\n value: number;\n min: number;\n max: number;\n step?: number;\n onChange: (next: number) => void;\n /** Override how the value is rendered next to the label. Defaults to `value.toString()`. */\n format?: (value: number) => ReactNode;\n /**\n * Optional suffix rendered next to the readout. A string becomes a\n * baseline-aligned dim \"word\" unit (e.g. \"px\"); pass JSX like `<sup>°</sup>`\n * to get the browser's native super positioning for symbol units.\n */\n unit?: ReactNode;\n layout?: PropertyRowLayout;\n}\n\n/** A bounded number edited by dragging, with a live readout whose precision\n * follows `step`. */\nexport function SliderRow({\n label,\n value,\n min,\n max,\n step = 1,\n onChange,\n format,\n unit,\n layout,\n}: SliderRowProps) {\n // Default readout precision tracks `step`: integer steps → 0 decimals,\n // 0.1 → 1 decimal, 0.05/0.02/0.01 → 2 decimals, 0.005 → 3, etc. Callers\n // can still pass an explicit `format` to override (e.g. for a custom\n // unit string or a non-decimal display like fractions).\n const decimals = step >= 1 ? 0 : Math.min(6, Math.max(0, Math.ceil(-Math.log10(step))));\n const effectiveFormat = format ?? ((n: number) => formatNumber(n, decimals));\n return (\n <PropertyRow\n label={label}\n readout={\n <EditableReadout\n value={value}\n min={min}\n max={max}\n format={effectiveFormat}\n unit={unit}\n onCommit={onChange}\n />\n }\n layout={layout}\n >\n <input\n type=\"range\"\n tabIndex={-1}\n min={min}\n max={max}\n step={step}\n value={value}\n onChange={(e) => {\n const v = Number(e.target.value);\n dlog('property-panel', 'slider', { label, value: v });\n onChange(v);\n }}\n />\n </PropertyRow>\n );\n}\n\ninterface EditableReadoutProps {\n value: number;\n min: number;\n max: number;\n format?: (value: number) => ReactNode;\n unit?: ReactNode;\n onCommit: (next: number) => void;\n}\n\n/**\n * Readout that swaps to a number input on click, commits on Enter/blur,\n * cancels on Escape. Clicks are stopped so the wrapping <label> doesn't\n * forward focus to the slider thumb.\n */\nfunction EditableReadout({ value, min, max, format, unit, onCommit }: EditableReadoutProps) {\n // Draft is non-null only while the input is focused. Live value mirrors\n // into the input otherwise. Pattern mirrors speech-balloons Lab.tsx:893-942.\n const [draft, setDraft] = useState<string | null>(null);\n const fmt = (n: number) => (format ? format(n) : formatNumber(n));\n const displayValue =\n draft !== null\n ? draft\n : (() => {\n const formatted = fmt(value);\n return typeof formatted === 'string' ? formatted : String(formatted);\n })();\n\n const suffix =\n unit == null ? null : typeof unit === 'string' ? (\n <span className=\"lk-property-row__readout-unit\">{unit}</span>\n ) : (\n unit\n );\n\n const commit = () => {\n if (draft !== null) {\n const n = parseSignedNumber(draft);\n if (Number.isFinite(n)) onCommit(Math.min(max, Math.max(min, n)));\n }\n setDraft(null);\n };\n\n return (\n <span className=\"lk-property-row__readout-group\">\n <input\n type=\"text\"\n inputMode=\"decimal\"\n className=\"lk-property-row__readout-input\"\n value={displayValue}\n onFocus={(e) => {\n const formatted = fmt(value);\n setDraft(typeof formatted === 'string' ? formatted : String(formatted));\n e.currentTarget.select();\n }}\n onChange={(e) => setDraft(e.target.value.replace(/-/g, '−'))}\n onBlur={commit}\n onClick={(e) => {\n // Stop the click from reaching the wrapping <label> (which would\n // forward focus to the slider thumb).\n e.preventDefault();\n e.stopPropagation();\n e.currentTarget.focus();\n }}\n onMouseDown={(e) => e.stopPropagation()}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n commit();\n e.currentTarget.blur();\n } else if (e.key === 'Escape') {\n setDraft(null);\n e.currentTarget.blur();\n }\n }}\n />\n {suffix}\n </span>\n );\n}\n\n/** Props for `<ColorRow>`. */\nexport interface ColorRowProps {\n label: ReactNode;\n value: string;\n onChange: (next: string) => void;\n /** 0..1 alpha. When provided, a translucent slider renders beneath the swatch. */\n alpha?: number;\n onAlphaChange?: (next: number) => void;\n /**\n * Render the alpha track as inert (dimmed, no thumb, not-allowed cursor).\n * Use when the color's consumer drops alpha so the affordance reads dead.\n */\n alphaDisabled?: boolean;\n}\n\n/** A color swatch, optionally with an alpha slider beneath it. */\nexport function ColorRow({\n label,\n value,\n onChange,\n alpha,\n onAlphaChange,\n alphaDisabled,\n}: ColorRowProps) {\n const showAlpha = alpha != null;\n const className = alphaDisabled ? 'lk-property-row--alpha-disabled' : undefined;\n return (\n <PropertyRow label={label} variant=\"color\" className={className}>\n <input type=\"color\" value={value} onChange={(e) => onChange(e.target.value)} />\n {showAlpha && (\n <input\n type=\"range\"\n className=\"lk-property-row__alpha\"\n min={0}\n max={1}\n step={0.01}\n value={alpha}\n disabled={alphaDisabled}\n onChange={(e) => onAlphaChange?.(Number(e.target.value))}\n />\n )}\n </PropertyRow>\n );\n}\n\n/** Props for `<CheckboxRow>`. */\nexport interface CheckboxRowProps {\n label: ReactNode;\n value: boolean;\n onChange: (next: boolean) => void;\n}\n\n/** A boolean checkbox. */\nexport function CheckboxRow({ label, value, onChange }: CheckboxRowProps) {\n return (\n <PropertyRow label={label} variant=\"checkbox\">\n <input type=\"checkbox\" checked={value} onChange={(e) => onChange(e.target.checked)} />\n </PropertyRow>\n );\n}\n\n/** Props for `<TextRow>`. */\nexport interface TextRowProps {\n label: ReactNode;\n value: string;\n onChange: (next: string) => void;\n placeholder?: string;\n maxLength?: number;\n layout?: PropertyRowLayout;\n}\n\n/** A single-line text input. */\nexport function TextRow({ label, value, onChange, placeholder, maxLength, layout }: TextRowProps) {\n return (\n <PropertyRow label={label} layout={layout}>\n <input\n type=\"text\"\n value={value}\n placeholder={placeholder}\n maxLength={maxLength}\n onChange={(e) => onChange(e.target.value)}\n />\n </PropertyRow>\n );\n}\n\n/** Props for `<NumberRow>`. */\nexport interface NumberRowProps {\n label: ReactNode;\n value: number;\n onChange: (next: number) => void;\n min?: number;\n max?: number;\n step?: number;\n placeholder?: string;\n layout?: PropertyRowLayout;\n}\n\n/** A number typed directly. Reach for `<SliderRow>` when the range matters\n * more than the exact value. */\nexport function NumberRow({\n label,\n value,\n onChange,\n min,\n max,\n step,\n placeholder,\n layout,\n}: NumberRowProps) {\n return (\n <PropertyRow label={label} layout={layout}>\n <input\n type=\"number\"\n value={value}\n min={min}\n max={max}\n step={step}\n placeholder={placeholder}\n onChange={(e) => {\n const raw = e.target.value;\n if (raw === '') return;\n const n = Number(raw);\n if (Number.isFinite(n)) onChange(n);\n }}\n />\n </PropertyRow>\n );\n}\n\nexport interface SelectOption<T extends string> {\n value: T;\n label: ReactNode;\n}\n\n/** Props for `<SelectRow>`. */\nexport interface SelectRowProps<T extends string> {\n label: ReactNode;\n value: T;\n options: ReadonlyArray<SelectOption<T>>;\n onChange: (next: T) => void;\n layout?: PropertyRowLayout;\n}\n\n/** A dropdown over a fixed set of choices. Prefer `<ToggleRow>` when there\n * are only two or three and they should all stay visible. */\nexport function SelectRow<T extends string>({\n label,\n value,\n options,\n onChange,\n layout,\n}: SelectRowProps<T>) {\n return (\n <PropertyRow label={label} layout={layout}>\n <select\n value={value}\n onChange={(e) => {\n const v = e.target.value as T;\n dlog('property-panel', 'select', { label, value: v });\n onChange(v);\n }}\n >\n {options.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {/* HTML <option> only renders text; ReactNode → string coerce */}\n {opt.label as string}\n </option>\n ))}\n </select>\n </PropertyRow>\n );\n}\n\n/** Props for `<ToggleRow>`. */\nexport interface ToggleRowProps<T extends string> {\n label: ReactNode;\n value: T;\n options: ReadonlyArray<SelectOption<T>>;\n onChange: (next: T) => void;\n layout?: PropertyRowLayout;\n}\n\n/** A segmented control: the same choice as a select, with every option\n * visible at once. */\nexport function ToggleRow<T extends string>({\n label,\n value,\n options,\n onChange,\n layout,\n}: ToggleRowProps<T>) {\n return (\n <PropertyRow label={label} layout={layout}>\n <div className=\"lk-property-row__toggle\">\n {options.map((opt) => {\n const selected = opt.value === value;\n return (\n <button\n key={opt.value}\n type=\"button\"\n aria-pressed={selected}\n className={\n selected\n ? 'lk-property-row__toggle-button lk-property-row__toggle-button--selected'\n : 'lk-property-row__toggle-button'\n }\n onClick={() => onChange(opt.value)}\n >\n {opt.label}\n </button>\n );\n })}\n </div>\n </PropertyRow>\n );\n}\n","import { isBuiltinToolPref } from '@weasel-js/core';\nimport type { PrefLeaf } from '@weasel-js/ui';\nimport { useEffect, useMemo, useRef, useState, type ReactNode } from 'react';\nimport { fromConfigFields } from '../config/fromConfigField';\nimport type { ControlRenderer, ResolvedConfig } from '../config/types';\nimport { isLeafVisible } from '../config/visible';\nimport { PropertyGroup } from '../ui/properties/PropertyGroup';\nimport {\n CheckboxRow,\n ColorRow,\n NumberRow,\n PropertyList,\n PropertyRow,\n SelectRow,\n TextRow,\n ToggleRow,\n SliderRow,\n} from '../ui/properties/PropertyPanel';\nimport type { ConfigField } from './types';\n\nexport interface ControlPanelProps<TC extends Record<string, unknown>> {\n /** The instrument's resolved config schema. */\n schema?: ResolvedConfig;\n /** @deprecated Pass `schema`. A field list is adapted into one internally. */\n fields?: ConfigField[];\n config: TC;\n setConfig: (key: keyof TC, value: unknown) => void;\n /**\n * Control overrides and app-defined kinds, PrefsForm-style. Keys are config\n * paths (checked first) or leaf kinds. A renderer returning `null` collapses\n * the row; entries override the built-in rows on collision.\n */\n renderers?: Record<string, ControlRenderer>;\n /** Draw leaves marked `hidden`. */\n showHidden?: boolean;\n className?: string;\n}\n\n/** Render an instrument's config schema as a stack of controls, each writing\n * back through `setConfig`. Built on the property rows, so a lab's controls\n * are the same aligned, themed rows the rest of the kit uses. */\nexport function ControlPanel<TC extends Record<string, unknown>>({\n schema,\n fields,\n config,\n setConfig,\n renderers,\n showHidden = false,\n className,\n}: ControlPanelProps<TC>) {\n const resolved = useMemo(\n () => schema ?? fromConfigFields(fields ?? []),\n [schema, fields],\n );\n\n const paths = Object.keys(resolved.group.children);\n const sectioned = new Set(resolved.sections.flatMap((s) => s.paths));\n const loose = paths.filter((p) => !sectioned.has(p));\n\n const row = (path: string): ReactNode => (\n <ControlRow\n key={path}\n path={path}\n resolved={resolved}\n config={config}\n setConfig={setConfig}\n renderers={renderers}\n showHidden={showHidden}\n />\n );\n\n return (\n <PropertyList className={className ? `lk-control-panel ${className}` : 'lk-control-panel'}>\n {loose.map(row)}\n {resolved.sections.map((section) => (\n <PropertyGroup key={section.label} title={section.label}>\n {section.paths.map(row)}\n </PropertyGroup>\n ))}\n </PropertyList>\n );\n}\n\ninterface ControlRowProps<TC extends Record<string, unknown>> {\n path: string;\n resolved: ResolvedConfig;\n config: TC;\n setConfig: (key: keyof TC, value: unknown) => void;\n renderers?: Record<string, ControlRenderer>;\n showHidden: boolean;\n}\n\n/** Reads a labkit-only extra off a leaf. `PrefLeaf` has no field for these,\n * and extra keys survive the resolve pass at runtime. */\nfunction extra<T>(leaf: PrefLeaf, key: string): T | undefined {\n return (leaf as unknown as Record<string, T | undefined>)[key];\n}\n\nfunction ControlRow<TC extends Record<string, unknown>>({\n path,\n resolved,\n config,\n setConfig,\n renderers,\n showHidden,\n}: ControlRowProps<TC>) {\n const leaf = resolved.group.children[path] as PrefLeaf | undefined;\n if (!leaf || !('kind' in leaf)) return null;\n if (!isLeafVisible(resolved, path, config as Record<string, unknown>, showHidden)) return null;\n\n const write = (value: unknown): void => setConfig(path as keyof TC, value);\n const fallback = extra<unknown>(leaf, 'default');\n const value = config[path] ?? fallback;\n\n // Most specific wins, and within a tier the lab's entry beats the\n // instrument's: controls[path] -> node .render -> controls[kind] -> built-in.\n const custom =\n renderers?.[path] ?? resolved.renderers[path] ?? renderers?.[leaf.kind];\n if (custom) return custom({ path, pref: leaf, value, setValue: write });\n\n const label = leaf.name;\n const read = <T,>(): T => value as T;\n\n if (!isBuiltinToolPref(leaf)) return <UnwiredRow label={label} kind={leaf.kind} />;\n\n switch (leaf.kind) {\n case 'number': {\n const min = extra<number>(leaf, 'min');\n const max = extra<number>(leaf, 'max');\n const step = extra<number>(leaf, 'step');\n if (extra<string>(leaf, 'control') === 'slider' && min !== undefined && max !== undefined) {\n return (\n <SliderRow\n label={label}\n value={read<number>()}\n min={min}\n max={max}\n step={step}\n onChange={write}\n />\n );\n }\n // NumberRow commits every keystroke and does not clamp, so the bounds a\n // schema declares are enforced here — an instrument should never be\n // handed a config value outside the range it asked for.\n const lo = min ?? Number.NEGATIVE_INFINITY;\n const hi = max ?? Number.POSITIVE_INFINITY;\n return (\n <NumberRow\n label={label}\n value={read<number>()}\n min={min}\n max={max}\n step={step}\n onChange={(n) => write(Math.min(hi, Math.max(lo, n)))}\n />\n );\n }\n case 'boolean':\n return <CheckboxRow label={label} value={read<boolean>()} onChange={write} />;\n case 'enum': {\n const options = extra<readonly { value: string; label: string }[]>(leaf, 'options') ?? [];\n const Row = extra<string>(leaf, 'control') === 'radio' ? ToggleRow : SelectRow;\n return (\n <Row label={label} value={read<string>()} options={options} onChange={write} />\n );\n }\n case 'string':\n return <DebouncedTextRow leaf={leaf} label={label} value={read<string>()} write={write} />;\n case 'color':\n return <ColorRow label={label} value={read<string>()} onChange={write} />;\n case 'paint':\n case 'object':\n // Declined: a hex swatch would write a solid over a gradient, and a flat\n // row would write one field into a half-built object. Override with\n // `render` to edit either.\n return <UnwiredRow label={label} kind={leaf.kind} />;\n default: {\n // Not reachable while every built-in kind has an arm — and a new kind\n // that lacks one is a compile error here, never a blank row.\n const _exhaustive: never = leaf;\n throw new Error(\n `ControlPanel: no control for built-in pref kind \"${(_exhaustive as { kind: string }).kind}\"`,\n );\n }\n }\n}\n\n/** A leaf this panel has no control for is named rather than dropped: a silent\n * gap reads as \"this control does not exist\". */\nfunction UnwiredRow({ label, kind }: { label: string; kind: string }) {\n return (\n <PropertyRow label={label}>\n <span className=\"lk-control-panel__unknown\">no control for “{kind}”</span>\n </PropertyRow>\n );\n}\n\n/** Text writes are debounced so typing does not re-run the instrument on every\n * keystroke, which means the row is locally controlled between commits and has\n * to notice when the config changes underneath it. */\nfunction DebouncedTextRow({\n leaf,\n label,\n value,\n write,\n}: {\n leaf: PrefLeaf;\n label: string;\n value: string;\n write: (value: unknown) => void;\n}) {\n const debounceMs = extra<number>(leaf, 'debounceMs') ?? 150;\n const [local, setLocal] = useState(value);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const lastExternal = useRef(value);\n\n useEffect(() => {\n if (value !== lastExternal.current) {\n lastExternal.current = value;\n setLocal(value);\n }\n }, [value]);\n\n useEffect(\n () => () => {\n if (timer.current) clearTimeout(timer.current);\n },\n [],\n );\n\n return (\n <TextRow\n label={label}\n value={local}\n placeholder={extra<string>(leaf, 'placeholder')}\n maxLength={extra<number>(leaf, 'maxLength')}\n onChange={(next) => {\n setLocal(next);\n if (timer.current) clearTimeout(timer.current);\n const commit = () => {\n lastExternal.current = next;\n write(next);\n };\n if (debounceMs === 0) commit();\n else timer.current = setTimeout(commit, debounceMs);\n }}\n />\n );\n}\n"]}
|
package/dist/controls/index.d.ts
CHANGED
|
@@ -1,15 +1,29 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import {
|
|
3
|
-
export {
|
|
2
|
+
import { R as ResolvedConfig, d as ConfigField, a as ControlRenderer } from '../_dts/types-AHlQxBNN.js';
|
|
3
|
+
export { g as CheckboxField, h as ColorField, j as ConfigFieldType, m as NumberField, n as SelectField, o as SelectOption, p as SliderField, T as TextField } from '../_dts/types-AHlQxBNN.js';
|
|
4
|
+
import '../_dts/PrefsForm-BYa6cWnO.js';
|
|
5
|
+
import 'react';
|
|
4
6
|
|
|
5
7
|
interface ControlPanelProps<TC extends Record<string, unknown>> {
|
|
6
|
-
|
|
8
|
+
/** The instrument's resolved config schema. */
|
|
9
|
+
schema?: ResolvedConfig;
|
|
10
|
+
/** @deprecated Pass `schema`. A field list is adapted into one internally. */
|
|
11
|
+
fields?: ConfigField[];
|
|
7
12
|
config: TC;
|
|
8
13
|
setConfig: (key: keyof TC, value: unknown) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Control overrides and app-defined kinds, PrefsForm-style. Keys are config
|
|
16
|
+
* paths (checked first) or leaf kinds. A renderer returning `null` collapses
|
|
17
|
+
* the row; entries override the built-in rows on collision.
|
|
18
|
+
*/
|
|
19
|
+
renderers?: Record<string, ControlRenderer>;
|
|
20
|
+
/** Draw leaves marked `hidden`. */
|
|
21
|
+
showHidden?: boolean;
|
|
9
22
|
className?: string;
|
|
10
23
|
}
|
|
11
24
|
/** Render an instrument's config schema as a stack of controls, each writing
|
|
12
|
-
* back through `setConfig`.
|
|
13
|
-
|
|
25
|
+
* back through `setConfig`. Built on the property rows, so a lab's controls
|
|
26
|
+
* are the same aligned, themed rows the rest of the kit uses. */
|
|
27
|
+
declare function ControlPanel<TC extends Record<string, unknown>>({ schema, fields, config, setConfig, renderers, showHidden, className, }: ControlPanelProps<TC>): react_jsx_runtime.JSX.Element;
|
|
14
28
|
|
|
15
29
|
export { ConfigField, ControlPanel };
|
package/dist/controls/index.js
CHANGED
package/dist/dragdrop/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export { D as DragDropCapability,
|
|
1
|
+
export { D as DragDropCapability, d as DragFeedback, P as PaletteItem } from '../_dts/index-DgcNdEdh.js';
|
|
2
2
|
import 'react';
|
|
3
|
-
import '../_dts/types-
|
|
3
|
+
import '../_dts/types-AHlQxBNN.js';
|
|
4
|
+
import '../_dts/PrefsForm-BYa6cWnO.js';
|
|
5
|
+
import '../_dts/types-1Sdxy_Pv.js';
|
|
4
6
|
import '../_dts/types-DJ79Tg5J.js';
|