@pixerate/editor-react 0.76.0 → 0.78.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/dist/PaintGradientEditorView-CCPCY5Ib.d.cts +14 -0
  2. package/dist/PaintGradientEditorView-CCPCY5Ib.d.ts +14 -0
  3. package/dist/canvas/index.cjs +662 -561
  4. package/dist/canvas/index.cjs.map +1 -1
  5. package/dist/canvas/index.d.cts +36 -5
  6. package/dist/canvas/index.d.ts +36 -5
  7. package/dist/canvas/index.js +232 -129
  8. package/dist/canvas/index.js.map +1 -1
  9. package/dist/{chunk-LWMUV5TC.js → chunk-2EW42UXC.js} +639 -461
  10. package/dist/chunk-2EW42UXC.js.map +1 -0
  11. package/dist/chunk-FX3EREF5.js +206 -0
  12. package/dist/chunk-FX3EREF5.js.map +1 -0
  13. package/dist/chunk-MO354USR.js +126 -0
  14. package/dist/chunk-MO354USR.js.map +1 -0
  15. package/dist/chunk-ZQZAKUUM.js +416 -0
  16. package/dist/chunk-ZQZAKUUM.js.map +1 -0
  17. package/dist/effects/index.cjs +606 -0
  18. package/dist/effects/index.cjs.map +1 -0
  19. package/dist/effects/index.d.cts +80 -0
  20. package/dist/effects/index.d.ts +80 -0
  21. package/dist/effects/index.js +16 -0
  22. package/dist/effects/index.js.map +1 -0
  23. package/dist/image-editor/index.cjs +1388 -534
  24. package/dist/image-editor/index.cjs.map +1 -1
  25. package/dist/image-editor/index.d.cts +36 -3
  26. package/dist/image-editor/index.d.ts +36 -3
  27. package/dist/image-editor/index.js +10 -1
  28. package/dist/index.cjs +1806 -952
  29. package/dist/index.cjs.map +1 -1
  30. package/dist/index.d.cts +4 -1
  31. package/dist/index.d.ts +4 -1
  32. package/dist/index.js +10 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/paint-editor/index.cjs +438 -289
  35. package/dist/paint-editor/index.cjs.map +1 -1
  36. package/dist/paint-editor/index.d.cts +8 -3
  37. package/dist/paint-editor/index.d.ts +8 -3
  38. package/dist/paint-editor/index.js +215 -187
  39. package/dist/paint-editor/index.js.map +1 -1
  40. package/dist/parameters/index.js +55 -439
  41. package/dist/parameters/index.js.map +1 -1
  42. package/dist/video-editor/index.cjs +732 -17
  43. package/dist/video-editor/index.cjs.map +1 -1
  44. package/dist/video-editor/index.d.cts +31 -3
  45. package/dist/video-editor/index.d.ts +31 -3
  46. package/dist/video-editor/index.js +184 -17
  47. package/dist/video-editor/index.js.map +1 -1
  48. package/package.json +8 -3
  49. package/dist/chunk-LWMUV5TC.js.map +0 -1
@@ -0,0 +1,416 @@
1
+ // src/parameters/fields.tsx
2
+ import { useRef } from "react";
3
+ import {
4
+ choiceOptionLabel,
5
+ formatParameterNumber,
6
+ getChoiceOptions,
7
+ isSliderField,
8
+ normalizeHexColor,
9
+ parameterLabel,
10
+ parameterStep,
11
+ parseParameterNumberInput,
12
+ clampParameterNumber,
13
+ vectorComponentField,
14
+ vectorSize
15
+ } from "@pixerate/editor/parameters";
16
+ import { jsx, jsxs } from "react/jsx-runtime";
17
+ var parameterInputClass = "h-7 w-full min-w-0 rounded-md border border-input bg-background px-2 text-xs text-foreground tabular-nums focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:cursor-not-allowed disabled:opacity-50";
18
+ var parameterButtonClass = "inline-flex h-7 items-center justify-center gap-1 rounded-md border border-input bg-background px-2 text-xs text-foreground hover:bg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:pointer-events-none disabled:opacity-50";
19
+ var rangeClass = "h-4 w-full min-w-0 flex-1 cursor-pointer accent-primary disabled:cursor-not-allowed disabled:opacity-50";
20
+ function ParameterCommitInput({ value, onCommit, multiline, className, onKeyDown, ...rest }) {
21
+ const commit = (el) => {
22
+ if (el.value !== value) onCommit(el.value, el);
23
+ };
24
+ const keyDown = (e) => {
25
+ onKeyDown?.(e);
26
+ if (e.defaultPrevented) return;
27
+ if (e.key === "Enter" && (!multiline || e.metaKey || e.ctrlKey)) {
28
+ e.preventDefault();
29
+ commit(e.currentTarget);
30
+ }
31
+ if (e.key === "Escape") e.currentTarget.value = value;
32
+ };
33
+ const props = {
34
+ defaultValue: value,
35
+ className: className ?? parameterInputClass,
36
+ onBlur: (e) => commit(e.currentTarget),
37
+ onKeyDown: keyDown,
38
+ ...rest
39
+ };
40
+ return multiline ? /* @__PURE__ */ jsx("textarea", { ...props, className: `${props.className} h-auto min-h-[3.5rem] py-1` }, value) : /* @__PURE__ */ jsx("input", { type: "text", ...props }, value);
41
+ }
42
+ var plainNumber = (field, value) => formatParameterNumber({ ...field, unit: void 0 }, value);
43
+ function ParameterNumberInput({
44
+ field,
45
+ value,
46
+ onChange,
47
+ disabled,
48
+ id,
49
+ "aria-label": ariaLabel
50
+ }) {
51
+ return /* @__PURE__ */ jsxs("div", { className: "relative min-w-0 flex-1", children: [
52
+ /* @__PURE__ */ jsx(
53
+ ParameterCommitInput,
54
+ {
55
+ id,
56
+ inputMode: "decimal",
57
+ "aria-label": ariaLabel ?? parameterLabel(field),
58
+ value: plainNumber(field, value),
59
+ disabled: disabled || field.readOnly,
60
+ className: `${parameterInputClass} ${field.unit ? "pr-6" : ""}`,
61
+ onCommit: (text, input) => {
62
+ const n = parseParameterNumberInput(field, text);
63
+ if (n === null || n === value) input.value = plainNumber(field, value);
64
+ else onChange(n);
65
+ },
66
+ onKeyDown: (e) => {
67
+ if (e.key !== "ArrowUp" && e.key !== "ArrowDown") return;
68
+ e.preventDefault();
69
+ const step = parameterStep(field) * (e.shiftKey ? 10 : 1);
70
+ onChange(clampParameterNumber(field, value + (e.key === "ArrowUp" ? step : -step)));
71
+ }
72
+ }
73
+ ),
74
+ field.unit && /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 text-[10px] text-muted-foreground", children: field.unit })
75
+ ] });
76
+ }
77
+ function ParameterSlider(props) {
78
+ const { field, value, onChange, onGestureStart, onGestureEnd, disabled } = props;
79
+ const dragging = useRef(false);
80
+ const end = () => {
81
+ if (!dragging.current) return;
82
+ dragging.current = false;
83
+ onGestureEnd?.();
84
+ };
85
+ if (!isSliderField(field)) return /* @__PURE__ */ jsx(ParameterNumberInput, { ...props });
86
+ const step = parameterStep(field);
87
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
88
+ /* @__PURE__ */ jsx(
89
+ "input",
90
+ {
91
+ type: "range",
92
+ "aria-label": parameterLabel(field),
93
+ "aria-valuetext": formatParameterNumber(field, value),
94
+ min: field.min,
95
+ max: field.max,
96
+ step,
97
+ value,
98
+ disabled: disabled || field.readOnly,
99
+ className: rangeClass,
100
+ onPointerDown: () => {
101
+ if (dragging.current) return;
102
+ dragging.current = true;
103
+ onGestureStart?.();
104
+ },
105
+ onPointerUp: end,
106
+ onPointerCancel: end,
107
+ onBlur: end,
108
+ onChange: (e) => onChange(clampParameterNumber(field, Number(e.target.value)))
109
+ }
110
+ ),
111
+ /* @__PURE__ */ jsx("div", { className: "w-20 shrink-0", children: /* @__PURE__ */ jsx(ParameterNumberInput, { ...props, id: props.id, "aria-label": `${parameterLabel(field)} value` }) })
112
+ ] });
113
+ }
114
+ function ParameterToggle({ field, value, onChange, disabled, id }) {
115
+ return /* @__PURE__ */ jsx(
116
+ "button",
117
+ {
118
+ type: "button",
119
+ role: "switch",
120
+ id,
121
+ "aria-checked": value,
122
+ "aria-label": parameterLabel(field),
123
+ disabled: disabled || field.readOnly,
124
+ onClick: () => onChange(!value),
125
+ className: `relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border border-transparent transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:opacity-50 ${value ? "bg-primary" : "bg-muted"}`,
126
+ children: /* @__PURE__ */ jsx(
127
+ "span",
128
+ {
129
+ className: `pointer-events-none block h-4 w-4 rounded-full bg-background shadow transition-transform ${value ? "translate-x-4" : "translate-x-0.5"}`
130
+ }
131
+ )
132
+ }
133
+ );
134
+ }
135
+ function ParameterSelect({ field, value, onChange, disabled, id }) {
136
+ const options = getChoiceOptions(field);
137
+ const off = disabled || field.readOnly;
138
+ if (field.control === "segmented") {
139
+ return /* @__PURE__ */ jsx("div", { role: "radiogroup", "aria-label": parameterLabel(field), className: "inline-flex flex-wrap rounded-md border border-input bg-muted p-0.5", children: options.map((o) => /* @__PURE__ */ jsx(
140
+ "button",
141
+ {
142
+ type: "button",
143
+ role: "radio",
144
+ "aria-checked": o.value === value,
145
+ title: o.description,
146
+ disabled: off,
147
+ onClick: () => onChange(o.value),
148
+ className: `rounded px-2 py-0.5 text-xs disabled:opacity-50 ${o.value === value ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
149
+ children: choiceOptionLabel(o)
150
+ },
151
+ String(o.value)
152
+ )) });
153
+ }
154
+ const index = options.findIndex((o) => o.value === value);
155
+ return /* @__PURE__ */ jsx(
156
+ "select",
157
+ {
158
+ id,
159
+ "aria-label": parameterLabel(field),
160
+ value: String(index),
161
+ disabled: off,
162
+ onChange: (e) => {
163
+ const option = options[Number(e.target.value)];
164
+ if (option) onChange(option.value);
165
+ },
166
+ className: parameterInputClass,
167
+ children: options.map((o, i) => /* @__PURE__ */ jsx("option", { value: String(i), title: o.description, children: choiceOptionLabel(o) }, String(o.value)))
168
+ }
169
+ );
170
+ }
171
+ function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd, disabled, id }) {
172
+ const picking = useRef(false);
173
+ const alpha = !!field.alpha;
174
+ const hex = normalizeHexColor(value, true) ?? "#000000ff";
175
+ const rgb = hex.slice(0, 7);
176
+ const a = hex.slice(7);
177
+ const off = disabled || field.readOnly;
178
+ const start = () => {
179
+ if (picking.current) return;
180
+ picking.current = true;
181
+ onGestureStart?.();
182
+ };
183
+ const end = () => {
184
+ if (!picking.current) return;
185
+ picking.current = false;
186
+ onGestureEnd?.();
187
+ };
188
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
189
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
190
+ /* @__PURE__ */ jsxs("span", { className: "relative h-7 w-9 shrink-0 overflow-hidden rounded-md border border-input bg-[repeating-conic-gradient(#d4d4d8_0_25%,#fff_0_50%)] bg-[length:8px_8px]", children: [
191
+ /* @__PURE__ */ jsx("span", { className: "absolute inset-0", style: { background: alpha ? hex : rgb } }),
192
+ /* @__PURE__ */ jsx(
193
+ "input",
194
+ {
195
+ type: "color",
196
+ "aria-label": parameterLabel(field),
197
+ value: rgb,
198
+ disabled: off,
199
+ className: "absolute inset-0 h-full w-full cursor-pointer opacity-0 disabled:cursor-not-allowed",
200
+ onChange: (e) => {
201
+ start();
202
+ onChange(alpha ? `${e.target.value}${a}` : e.target.value);
203
+ },
204
+ onBlur: end
205
+ }
206
+ )
207
+ ] }),
208
+ /* @__PURE__ */ jsx(
209
+ ParameterCommitInput,
210
+ {
211
+ id,
212
+ "aria-label": `${parameterLabel(field)} hex`,
213
+ value: alpha ? hex : rgb,
214
+ disabled: off,
215
+ spellCheck: false,
216
+ className: `${parameterInputClass} font-mono`,
217
+ onCommit: (text) => {
218
+ const next = normalizeHexColor(text, alpha);
219
+ if (next) onChange(next);
220
+ }
221
+ }
222
+ )
223
+ ] }),
224
+ alpha && /* @__PURE__ */ jsx(
225
+ "input",
226
+ {
227
+ type: "range",
228
+ "aria-label": `${parameterLabel(field)} opacity`,
229
+ min: 0,
230
+ max: 255,
231
+ step: 1,
232
+ value: parseInt(a, 16),
233
+ disabled: off,
234
+ className: rangeClass,
235
+ onPointerDown: start,
236
+ onPointerUp: end,
237
+ onPointerCancel: end,
238
+ onBlur: end,
239
+ onChange: (e) => onChange(`${rgb}${Number(e.target.value).toString(16).padStart(2, "0")}`)
240
+ }
241
+ ),
242
+ field.swatches && field.swatches.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: field.swatches.map((s) => {
243
+ const swatch = normalizeHexColor(s, alpha);
244
+ if (!swatch) return null;
245
+ return /* @__PURE__ */ jsx(
246
+ "button",
247
+ {
248
+ type: "button",
249
+ title: swatch,
250
+ "aria-label": `${parameterLabel(field)} ${swatch}`,
251
+ "aria-pressed": swatch === (alpha ? hex : rgb),
252
+ disabled: off,
253
+ onClick: () => onChange(swatch),
254
+ className: "h-5 w-5 rounded border border-input aria-pressed:ring-1 aria-pressed:ring-primary",
255
+ style: { background: swatch }
256
+ },
257
+ s
258
+ );
259
+ }) })
260
+ ] });
261
+ }
262
+ function ParameterVector({ field, value, onChange, disabled, id }) {
263
+ const size = vectorSize(field);
264
+ return /* @__PURE__ */ jsx("div", { className: "grid gap-1.5", style: { gridTemplateColumns: `repeat(${size}, minmax(0, 1fr))` }, children: Array.from({ length: size }, (_, i) => {
265
+ const component = vectorComponentField(field, i);
266
+ return /* @__PURE__ */ jsxs("label", { className: "flex min-w-0 items-center gap-1", children: [
267
+ /* @__PURE__ */ jsx("span", { className: "w-3 shrink-0 text-[10px] uppercase text-muted-foreground", children: component.label }),
268
+ /* @__PURE__ */ jsx(
269
+ ParameterNumberInput,
270
+ {
271
+ field: component,
272
+ value: value[i] ?? 0,
273
+ id: i === 0 ? id : void 0,
274
+ "aria-label": `${parameterLabel(field)} ${component.label}`,
275
+ disabled: disabled || field.readOnly,
276
+ onChange: (n) => onChange(Array.from({ length: size }, (_2, j) => j === i ? n : value[j] ?? 0))
277
+ }
278
+ )
279
+ ] }, i);
280
+ }) });
281
+ }
282
+ function ParameterImage({ field, value, onChange, disabled, id, resolveFile }) {
283
+ const off = disabled || field.readOnly;
284
+ const name = parameterLabel(field);
285
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
286
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
287
+ /* @__PURE__ */ jsx("div", { className: "flex h-12 w-16 shrink-0 items-center justify-center overflow-hidden rounded-md border border-input bg-muted", children: value ? /* @__PURE__ */ jsx("img", { src: value, alt: name, className: "h-full w-full object-cover" }) : /* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground", children: "None" }) }),
288
+ /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
289
+ /* @__PURE__ */ jsx(
290
+ ParameterCommitInput,
291
+ {
292
+ id,
293
+ "aria-label": `${name} URL`,
294
+ placeholder: "Image URL",
295
+ value: value.startsWith("data:") ? "" : value,
296
+ disabled: off,
297
+ onCommit: (text) => onChange(text.trim())
298
+ }
299
+ ),
300
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1", children: [
301
+ resolveFile && /* @__PURE__ */ jsxs("label", { className: `${parameterButtonClass} cursor-pointer ${off ? "pointer-events-none opacity-50" : ""}`, children: [
302
+ "Choose file\u2026",
303
+ /* @__PURE__ */ jsx(
304
+ "input",
305
+ {
306
+ type: "file",
307
+ className: "sr-only",
308
+ accept: field.accept ?? "image/*",
309
+ disabled: off,
310
+ "aria-label": `${name} file`,
311
+ onChange: async (e) => {
312
+ const file = e.target.files?.[0];
313
+ e.target.value = "";
314
+ if (file) onChange(await resolveFile(file));
315
+ }
316
+ }
317
+ )
318
+ ] }),
319
+ value && /* @__PURE__ */ jsx("button", { type: "button", className: parameterButtonClass, disabled: off, onClick: () => onChange(""), "aria-label": `Clear ${name}`, children: "Clear" })
320
+ ] })
321
+ ] })
322
+ ] }),
323
+ field.options && field.options.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: field.options.map((o) => /* @__PURE__ */ jsx(
324
+ "button",
325
+ {
326
+ type: "button",
327
+ title: o.label ?? o.url,
328
+ "aria-label": o.label ?? o.url,
329
+ "aria-pressed": o.url === value,
330
+ disabled: off,
331
+ onClick: () => onChange(o.url),
332
+ className: "h-9 w-12 overflow-hidden rounded border border-input aria-pressed:ring-2 aria-pressed:ring-primary",
333
+ children: /* @__PURE__ */ jsx("img", { src: o.url, alt: "", className: "h-full w-full object-cover" })
334
+ },
335
+ o.url
336
+ )) })
337
+ ] });
338
+ }
339
+ function ParameterText({ field, value, onChange, disabled, id }) {
340
+ return /* @__PURE__ */ jsx(
341
+ ParameterCommitInput,
342
+ {
343
+ id,
344
+ "aria-label": parameterLabel(field),
345
+ multiline: field.multiline,
346
+ placeholder: field.placeholder,
347
+ maxLength: field.maxLength,
348
+ value,
349
+ disabled: disabled || field.readOnly,
350
+ onCommit: onChange
351
+ }
352
+ );
353
+ }
354
+ function KeyframeDiamond({ state, onToggle, label, disabled, className = "" }) {
355
+ const keyed = state === "keyed";
356
+ return /* @__PURE__ */ jsx(
357
+ "button",
358
+ {
359
+ type: "button",
360
+ "data-key-state": state,
361
+ "aria-pressed": keyed,
362
+ "aria-label": `${keyed ? "Remove" : "Add"} keyframe for ${label}`,
363
+ title: keyed ? "Remove keyframe here" : "Add keyframe at the playhead",
364
+ disabled,
365
+ onClick: onToggle,
366
+ className: `inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:opacity-40 ${state === "none" ? "text-muted-foreground hover:text-foreground" : "text-amber-500"} ${className}`,
367
+ children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 10 10", className: "h-2.5 w-2.5", "aria-hidden": "true", children: /* @__PURE__ */ jsx(
368
+ "path",
369
+ {
370
+ d: "M5 0.8 9.2 5 5 9.2 0.8 5Z",
371
+ fill: keyed ? "currentColor" : "none",
372
+ stroke: "currentColor",
373
+ strokeWidth: "1.3",
374
+ opacity: state === "animated" ? 0.7 : 1
375
+ }
376
+ ) })
377
+ }
378
+ );
379
+ }
380
+ function ParameterFieldControl({ field, value, onChange, resolveFile, ...rest }) {
381
+ const set = onChange;
382
+ switch (field.type) {
383
+ case "number":
384
+ case "int":
385
+ return /* @__PURE__ */ jsx(ParameterSlider, { field, value, onChange: set, ...rest });
386
+ case "boolean":
387
+ return /* @__PURE__ */ jsx(ParameterToggle, { field, value, onChange: set, ...rest });
388
+ case "choice":
389
+ return /* @__PURE__ */ jsx(ParameterSelect, { field, value, onChange: set, ...rest });
390
+ case "color":
391
+ return /* @__PURE__ */ jsx(ParameterColor, { field, value, onChange: set, ...rest });
392
+ case "vector":
393
+ return /* @__PURE__ */ jsx(ParameterVector, { field, value, onChange: set, ...rest });
394
+ case "image":
395
+ return /* @__PURE__ */ jsx(ParameterImage, { field, value, onChange: set, resolveFile, ...rest });
396
+ case "text":
397
+ return /* @__PURE__ */ jsx(ParameterText, { field, value, onChange: set, ...rest });
398
+ }
399
+ }
400
+
401
+ export {
402
+ parameterInputClass,
403
+ parameterButtonClass,
404
+ ParameterCommitInput,
405
+ ParameterNumberInput,
406
+ ParameterSlider,
407
+ ParameterToggle,
408
+ ParameterSelect,
409
+ ParameterColor,
410
+ ParameterVector,
411
+ ParameterImage,
412
+ ParameterText,
413
+ KeyframeDiamond,
414
+ ParameterFieldControl
415
+ };
416
+ //# sourceMappingURL=chunk-ZQZAKUUM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/parameters/fields.tsx"],"sourcesContent":["import React, { useRef } from 'react';\nimport {\n choiceOptionLabel,\n formatParameterNumber,\n getChoiceOptions,\n isSliderField,\n normalizeHexColor,\n parameterLabel,\n parameterStep,\n parseParameterNumberInput,\n clampParameterNumber,\n vectorComponentField,\n vectorSize,\n type BooleanParameterField,\n type ChoiceParameterField,\n type ColorParameterField,\n type ImageParameterField,\n type NumberParameterField,\n type ParameterField,\n type ParameterKeyState,\n type ParameterValue,\n type TextParameterField,\n type VectorParameterField,\n} from '@pixerate/editor/parameters';\n\n/** Props every field control takes. Controls are controller-free: wire them to anything. */\nexport interface ParameterControlProps<F extends ParameterField, V extends ParameterValue> {\n field: F;\n value: V;\n onChange: (value: V) => void;\n /** A continuous edit (slider drag, colour pick) started: merge changes into one undo step. */\n onGestureStart?: () => void;\n onGestureEnd?: () => void;\n disabled?: boolean;\n /** DOM id of the main input (for a `<label htmlFor>`). */\n id?: string;\n}\n\nexport const parameterInputClass =\n 'h-7 w-full min-w-0 rounded-md border border-input bg-background px-2 text-xs text-foreground tabular-nums focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:cursor-not-allowed disabled:opacity-50';\nexport const parameterButtonClass =\n 'inline-flex h-7 items-center justify-center gap-1 rounded-md border border-input bg-background px-2 text-xs text-foreground hover:bg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:pointer-events-none disabled:opacity-50';\nconst rangeClass = 'h-4 w-full min-w-0 flex-1 cursor-pointer accent-primary disabled:cursor-not-allowed disabled:opacity-50';\n\ntype CommitInputProps = {\n value: string;\n /** Called with the text and the element (e.g. to show the stored value again after a refused edit). */\n onCommit: (value: string, input: HTMLInputElement | HTMLTextAreaElement) => void;\n multiline?: boolean;\n} & Omit<React.InputHTMLAttributes<HTMLInputElement> & React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'value' | 'onChange' | 'defaultValue'>;\n\n/** A text box that commits on blur or Enter (Mod+Enter when multiline) and resets on Escape. */\nexport function ParameterCommitInput({ value, onCommit, multiline, className, onKeyDown, ...rest }: CommitInputProps) {\n const commit = (el: HTMLInputElement | HTMLTextAreaElement) => {\n if (el.value !== value) onCommit(el.value, el);\n };\n const keyDown = (e: React.KeyboardEvent<HTMLInputElement & HTMLTextAreaElement>) => {\n onKeyDown?.(e);\n if (e.defaultPrevented) return;\n if (e.key === 'Enter' && (!multiline || e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n commit(e.currentTarget);\n }\n if (e.key === 'Escape') e.currentTarget.value = value;\n };\n const props = {\n defaultValue: value,\n className: className ?? parameterInputClass,\n onBlur: (e: React.FocusEvent<HTMLInputElement & HTMLTextAreaElement>) => commit(e.currentTarget),\n onKeyDown: keyDown,\n ...rest,\n };\n // `key` remounts the box when the value changes from outside.\n return multiline ? (\n <textarea key={value} {...props} className={`${props.className} h-auto min-h-[3.5rem] py-1`} />\n ) : (\n <input key={value} type=\"text\" {...props} />\n );\n}\n\nconst plainNumber = (field: NumberParameterField, value: number) => formatParameterNumber({ ...field, unit: undefined }, value);\n\n/** A number box: type a value (units allowed), or step with the arrow keys (Shift ×10). */\nexport function ParameterNumberInput({\n field,\n value,\n onChange,\n disabled,\n id,\n 'aria-label': ariaLabel,\n}: ParameterControlProps<NumberParameterField, number> & { 'aria-label'?: string }) {\n return (\n <div className=\"relative min-w-0 flex-1\">\n <ParameterCommitInput\n id={id}\n inputMode=\"decimal\"\n aria-label={ariaLabel ?? parameterLabel(field)}\n value={plainNumber(field, value)}\n disabled={disabled || field.readOnly}\n className={`${parameterInputClass} ${field.unit ? 'pr-6' : ''}`}\n onCommit={(text, input) => {\n const n = parseParameterNumberInput(field, text);\n // Show the stored value again when the text was not a number or clamps to it.\n if (n === null || n === value) input.value = plainNumber(field, value);\n else onChange(n);\n }}\n onKeyDown={(e) => {\n if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown') return;\n e.preventDefault();\n const step = parameterStep(field) * (e.shiftKey ? 10 : 1);\n onChange(clampParameterNumber(field, value + (e.key === 'ArrowUp' ? step : -step)));\n }}\n />\n {field.unit && (\n <span className=\"pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 text-[10px] text-muted-foreground\">{field.unit}</span>\n )}\n </div>\n );\n}\n\n/** A slider plus number box for `number` / `int` fields (number box only for `control: 'input'` or unbounded fields). */\nexport function ParameterSlider(props: ParameterControlProps<NumberParameterField, number>) {\n const { field, value, onChange, onGestureStart, onGestureEnd, disabled } = props;\n const dragging = useRef(false);\n const end = () => {\n if (!dragging.current) return;\n dragging.current = false;\n onGestureEnd?.();\n };\n if (!isSliderField(field)) return <ParameterNumberInput {...props} />;\n const step = parameterStep(field);\n return (\n <div className=\"flex items-center gap-2\">\n <input\n type=\"range\"\n aria-label={parameterLabel(field)}\n aria-valuetext={formatParameterNumber(field, value)}\n min={field.min}\n max={field.max}\n step={step}\n value={value}\n disabled={disabled || field.readOnly}\n className={rangeClass}\n onPointerDown={() => {\n if (dragging.current) return;\n dragging.current = true;\n onGestureStart?.();\n }}\n onPointerUp={end}\n onPointerCancel={end}\n onBlur={end}\n onChange={(e) => onChange(clampParameterNumber(field, Number(e.target.value)))}\n />\n <div className=\"w-20 shrink-0\">\n <ParameterNumberInput {...props} id={props.id} aria-label={`${parameterLabel(field)} value`} />\n </div>\n </div>\n );\n}\n\n/** An on/off switch for `boolean` fields. */\nexport function ParameterToggle({ field, value, onChange, disabled, id }: ParameterControlProps<BooleanParameterField, boolean>) {\n return (\n <button\n type=\"button\"\n role=\"switch\"\n id={id}\n aria-checked={value}\n aria-label={parameterLabel(field)}\n disabled={disabled || field.readOnly}\n onClick={() => onChange(!value)}\n className={`relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border border-transparent transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:opacity-50 ${\n value ? 'bg-primary' : 'bg-muted'\n }`}\n >\n <span\n className={`pointer-events-none block h-4 w-4 rounded-full bg-background shadow transition-transform ${value ? 'translate-x-4' : 'translate-x-0.5'}`}\n />\n </button>\n );\n}\n\n/** A dropdown (or segmented buttons with `control: 'segmented'`) for `choice` fields. */\nexport function ParameterSelect({ field, value, onChange, disabled, id }: ParameterControlProps<ChoiceParameterField, string | number>) {\n const options = getChoiceOptions(field);\n const off = disabled || field.readOnly;\n if (field.control === 'segmented') {\n return (\n <div role=\"radiogroup\" aria-label={parameterLabel(field)} className=\"inline-flex flex-wrap rounded-md border border-input bg-muted p-0.5\">\n {options.map((o) => (\n <button\n key={String(o.value)}\n type=\"button\"\n role=\"radio\"\n aria-checked={o.value === value}\n title={o.description}\n disabled={off}\n onClick={() => onChange(o.value)}\n className={`rounded px-2 py-0.5 text-xs disabled:opacity-50 ${\n o.value === value ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'\n }`}\n >\n {choiceOptionLabel(o)}\n </button>\n ))}\n </div>\n );\n }\n const index = options.findIndex((o) => o.value === value);\n return (\n <select\n id={id}\n aria-label={parameterLabel(field)}\n value={String(index)}\n disabled={off}\n onChange={(e) => {\n const option = options[Number(e.target.value)];\n if (option) onChange(option.value);\n }}\n className={parameterInputClass}\n >\n {options.map((o, i) => (\n <option key={String(o.value)} value={String(i)} title={o.description}>\n {choiceOptionLabel(o)}\n </option>\n ))}\n </select>\n );\n}\n\n/** A colour picker with a hex box, an alpha slider (with `alpha`) and swatches. */\nexport function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd, disabled, id }: ParameterControlProps<ColorParameterField, string>) {\n const picking = useRef(false);\n const alpha = !!field.alpha;\n const hex = normalizeHexColor(value, true) ?? '#000000ff';\n const rgb = hex.slice(0, 7);\n const a = hex.slice(7);\n const off = disabled || field.readOnly;\n const start = () => {\n if (picking.current) return;\n picking.current = true;\n onGestureStart?.();\n };\n const end = () => {\n if (!picking.current) return;\n picking.current = false;\n onGestureEnd?.();\n };\n return (\n <div className=\"space-y-1.5\">\n <div className=\"flex items-center gap-2\">\n <span className=\"relative h-7 w-9 shrink-0 overflow-hidden rounded-md border border-input bg-[repeating-conic-gradient(#d4d4d8_0_25%,#fff_0_50%)] bg-[length:8px_8px]\">\n <span className=\"absolute inset-0\" style={{ background: alpha ? hex : rgb }} />\n <input\n type=\"color\"\n aria-label={parameterLabel(field)}\n value={rgb}\n disabled={off}\n className=\"absolute inset-0 h-full w-full cursor-pointer opacity-0 disabled:cursor-not-allowed\"\n onChange={(e) => {\n start();\n onChange(alpha ? `${e.target.value}${a}` : e.target.value);\n }}\n onBlur={end}\n />\n </span>\n <ParameterCommitInput\n id={id}\n aria-label={`${parameterLabel(field)} hex`}\n value={alpha ? hex : rgb}\n disabled={off}\n spellCheck={false}\n className={`${parameterInputClass} font-mono`}\n onCommit={(text) => {\n const next = normalizeHexColor(text, alpha);\n if (next) onChange(next);\n }}\n />\n </div>\n {alpha && (\n <input\n type=\"range\"\n aria-label={`${parameterLabel(field)} opacity`}\n min={0}\n max={255}\n step={1}\n value={parseInt(a, 16)}\n disabled={off}\n className={rangeClass}\n onPointerDown={start}\n onPointerUp={end}\n onPointerCancel={end}\n onBlur={end}\n onChange={(e) => onChange(`${rgb}${Number(e.target.value).toString(16).padStart(2, '0')}`)}\n />\n )}\n {field.swatches && field.swatches.length > 0 && (\n <div className=\"flex flex-wrap gap-1\">\n {field.swatches.map((s) => {\n const swatch = normalizeHexColor(s, alpha);\n if (!swatch) return null;\n return (\n <button\n key={s}\n type=\"button\"\n title={swatch}\n aria-label={`${parameterLabel(field)} ${swatch}`}\n aria-pressed={swatch === (alpha ? hex : rgb)}\n disabled={off}\n onClick={() => onChange(swatch)}\n className=\"h-5 w-5 rounded border border-input aria-pressed:ring-1 aria-pressed:ring-primary\"\n style={{ background: swatch }}\n />\n );\n })}\n </div>\n )}\n </div>\n );\n}\n\n/** One number box per component for `vector` fields. */\nexport function ParameterVector({ field, value, onChange, disabled, id }: ParameterControlProps<VectorParameterField, number[]>) {\n const size = vectorSize(field);\n return (\n <div className=\"grid gap-1.5\" style={{ gridTemplateColumns: `repeat(${size}, minmax(0, 1fr))` }}>\n {Array.from({ length: size }, (_, i) => {\n const component = vectorComponentField(field, i);\n return (\n <label key={i} className=\"flex min-w-0 items-center gap-1\">\n <span className=\"w-3 shrink-0 text-[10px] uppercase text-muted-foreground\">{component.label}</span>\n <ParameterNumberInput\n field={component}\n value={value[i] ?? 0}\n id={i === 0 ? id : undefined}\n aria-label={`${parameterLabel(field)} ${component.label}`}\n disabled={disabled || field.readOnly}\n onChange={(n) => onChange(Array.from({ length: size }, (_, j) => (j === i ? n : (value[j] ?? 0))))}\n />\n </label>\n );\n })}\n </div>\n );\n}\n\nexport interface ParameterImageProps extends ParameterControlProps<ImageParameterField, string> {\n /** Turns a picked file into a URL (upload it, or `URL.createObjectURL`). Without it there is no file button. */\n resolveFile?: (file: File) => string | Promise<string>;\n}\n\n/** An image picker: suggested thumbnails, a URL box, an optional file button and a clear button. */\nexport function ParameterImage({ field, value, onChange, disabled, id, resolveFile }: ParameterImageProps) {\n const off = disabled || field.readOnly;\n const name = parameterLabel(field);\n return (\n <div className=\"space-y-1.5\">\n <div className=\"flex items-center gap-2\">\n <div className=\"flex h-12 w-16 shrink-0 items-center justify-center overflow-hidden rounded-md border border-input bg-muted\">\n {value ? (\n <img src={value} alt={name} className=\"h-full w-full object-cover\" />\n ) : (\n <span className=\"text-[10px] text-muted-foreground\">None</span>\n )}\n </div>\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <ParameterCommitInput\n id={id}\n aria-label={`${name} URL`}\n placeholder=\"Image URL\"\n value={value.startsWith('data:') ? '' : value}\n disabled={off}\n onCommit={(text) => onChange(text.trim())}\n />\n <div className=\"flex gap-1\">\n {resolveFile && (\n <label className={`${parameterButtonClass} cursor-pointer ${off ? 'pointer-events-none opacity-50' : ''}`}>\n Choose file…\n <input\n type=\"file\"\n className=\"sr-only\"\n accept={field.accept ?? 'image/*'}\n disabled={off}\n aria-label={`${name} file`}\n onChange={async (e) => {\n const file = e.target.files?.[0];\n e.target.value = '';\n if (file) onChange(await resolveFile(file));\n }}\n />\n </label>\n )}\n {value && (\n <button type=\"button\" className={parameterButtonClass} disabled={off} onClick={() => onChange('')} aria-label={`Clear ${name}`}>\n Clear\n </button>\n )}\n </div>\n </div>\n </div>\n {field.options && field.options.length > 0 && (\n <div className=\"flex flex-wrap gap-1\">\n {field.options.map((o) => (\n <button\n key={o.url}\n type=\"button\"\n title={o.label ?? o.url}\n aria-label={o.label ?? o.url}\n aria-pressed={o.url === value}\n disabled={off}\n onClick={() => onChange(o.url)}\n className=\"h-9 w-12 overflow-hidden rounded border border-input aria-pressed:ring-2 aria-pressed:ring-primary\"\n >\n <img src={o.url} alt=\"\" className=\"h-full w-full object-cover\" />\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/** A text box (or textarea with `multiline`) that commits on blur or Enter. */\nexport function ParameterText({ field, value, onChange, disabled, id }: ParameterControlProps<TextParameterField, string>) {\n return (\n <ParameterCommitInput\n id={id}\n aria-label={parameterLabel(field)}\n multiline={field.multiline}\n placeholder={field.placeholder}\n maxLength={field.maxLength}\n value={value}\n disabled={disabled || field.readOnly}\n onCommit={onChange}\n />\n );\n}\n\nexport interface KeyframeDiamondProps {\n state: ParameterKeyState;\n onToggle: () => void;\n /** The parameter's label (for the accessible name). */\n label: string;\n disabled?: boolean;\n className?: string;\n}\n\n/** A keyframe toggle: filled when a key sits at the playhead, tinted when the value is animated. */\nexport function KeyframeDiamond({ state, onToggle, label, disabled, className = '' }: KeyframeDiamondProps) {\n const keyed = state === 'keyed';\n return (\n <button\n type=\"button\"\n data-key-state={state}\n aria-pressed={keyed}\n aria-label={`${keyed ? 'Remove' : 'Add'} keyframe for ${label}`}\n title={keyed ? 'Remove keyframe here' : 'Add keyframe at the playhead'}\n disabled={disabled}\n onClick={onToggle}\n className={`inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:opacity-40 ${\n state === 'none' ? 'text-muted-foreground hover:text-foreground' : 'text-amber-500'\n } ${className}`}\n >\n <svg viewBox=\"0 0 10 10\" className=\"h-2.5 w-2.5\" aria-hidden=\"true\">\n <path\n d=\"M5 0.8 9.2 5 5 9.2 0.8 5Z\"\n fill={keyed ? 'currentColor' : 'none'}\n stroke=\"currentColor\"\n strokeWidth=\"1.3\"\n opacity={state === 'animated' ? 0.7 : 1}\n />\n </svg>\n </button>\n );\n}\n\nexport interface ParameterFieldControlProps extends ParameterControlProps<ParameterField, ParameterValue> {\n resolveFile?: ParameterImageProps['resolveFile'];\n}\n\n/** The control for any field type. */\nexport function ParameterFieldControl({ field, value, onChange, resolveFile, ...rest }: ParameterFieldControlProps) {\n const set = onChange as (value: any) => void;\n switch (field.type) {\n case 'number':\n case 'int':\n return <ParameterSlider field={field} value={value as number} onChange={set} {...rest} />;\n case 'boolean':\n return <ParameterToggle field={field} value={value as boolean} onChange={set} {...rest} />;\n case 'choice':\n return <ParameterSelect field={field} value={value as string | number} onChange={set} {...rest} />;\n case 'color':\n return <ParameterColor field={field} value={value as string} onChange={set} {...rest} />;\n case 'vector':\n return <ParameterVector field={field} value={value as number[]} onChange={set} {...rest} />;\n case 'image':\n return <ParameterImage field={field} value={value as string} onChange={set} resolveFile={resolveFile} {...rest} />;\n case 'text':\n return <ParameterText field={field} value={value as string} onChange={set} {...rest} />;\n }\n}\n\n"],"mappings":"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","names":["_"]}