@pixerate/editor-react 0.19.1 → 0.20.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/parameters/useParameters.ts","../../src/parameters/fields.tsx","../../src/parameters/ParametersPanel.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n ParametersController,\n createParameterCommands,\n type ParameterCommandOptions,\n type ParametersControllerOptions,\n type ParametersState,\n type ParameterValue,\n type ParameterSetResult,\n} from '@pixerate/editor/parameters';\n\n/**\n * A `ParametersController` created once for the component's lifetime. When `options.schema`\n * changes (a new object), the controller's schema is replaced and fitting values are kept.\n */\nexport function useParametersController(options: ParametersControllerOptions): ParametersController {\n const ref = useRef<ParametersController | null>(null);\n if (!ref.current) ref.current = new ParametersController(options);\n const controller = ref.current;\n const schema = options.schema;\n const first = useRef(true);\n useEffect(() => {\n if (first.current) {\n first.current = false;\n return;\n }\n controller.setSchema(schema);\n }, [controller, schema]);\n return controller;\n}\n\n/** The controller's state (re-renders on every change). */\nexport function useParametersState(controller: ParametersController): ParametersState {\n return useSyncExternalStore(controller.subscribe, controller.getState, controller.getState);\n}\n\nexport interface UseParametersResult {\n controller: ParametersController;\n state: ParametersState;\n values: ParametersState['values'];\n setValue: (id: string, value: ParameterValue) => ParameterSetResult;\n undo: () => void;\n redo: () => void;\n reset: (ids?: readonly string[]) => void;\n randomize: (ids?: readonly string[]) => void;\n}\n\n/**\n * Subscribes to a parameters controller and exposes its state with bound actions. Pass\n * options instead of a controller to create one for the component's lifetime.\n */\nexport function useParameters(controllerOrOptions: ParametersController | ParametersControllerOptions): UseParametersResult {\n const own = useRef<ParametersController | null>(null);\n let controller: ParametersController;\n if (controllerOrOptions instanceof ParametersController) controller = controllerOrOptions;\n else {\n if (!own.current) own.current = new ParametersController(controllerOrOptions);\n controller = own.current;\n }\n const state = useParametersState(controller);\n const actions = useMemo(\n () => ({\n setValue: (id: string, value: ParameterValue) => controller.setValue(id, value),\n undo: () => void controller.undo(),\n redo: () => void controller.redo(),\n reset: (ids?: readonly string[]) => void controller.reset(ids),\n randomize: (ids?: readonly string[]) => void controller.randomize({ ids }),\n }),\n [controller],\n );\n return { controller, state, values: state.values, ...actions };\n}\n\n/** Anything with `register(specs) → unregister` (a `CommandRegistry`). */\nexport interface ParameterCommandTarget {\n register(specs: any): () => void;\n}\n\n/**\n * Registers the controller's palette / agent commands (`parameters.set`, `…randomize`, …)\n * in `registry` while mounted, so `createCommandToolProvider` exposes them to agents.\n */\nexport function useParameterCommands(\n registry: ParameterCommandTarget | null | undefined,\n controller: ParametersController,\n options: ParameterCommandOptions = {},\n): void {\n const { prefix, group, scope } = options;\n useEffect(() => {\n if (!registry) return;\n return registry.register(createParameterCommands(controller, { prefix, group, scope }));\n }, [registry, controller, prefix, group, scope]);\n}\n","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","import React, { useId, useState } from 'react';\nimport {\n isParameterGroup,\n parameterLabel,\n parameterValuesEqual,\n type ParameterField,\n type ParameterGroup,\n type ParameterSchemaItem,\n type ParametersController,\n type ParametersState,\n} from '@pixerate/editor/parameters';\nimport { KeyframeDiamond, ParameterFieldControl, parameterButtonClass, parameterInputClass, type ParameterImageProps } from './fields';\nimport { useParametersState } from './useParameters';\n\nexport interface ParametersPanelProps {\n controller: ParametersController;\n /** Heading (default: the schema's title). Pass `null` for none. */\n title?: React.ReactNode;\n /** Undo, redo, reset and randomize buttons (default `true`). */\n showToolbar?: boolean;\n /** The preset picker with save and delete (default `true`). */\n showPresets?: boolean;\n /** Keyframe diamonds (default: when the controller has a keyframes adapter). */\n showKeyframes?: boolean;\n /** Per-field reset buttons on changed values (default `true`). */\n showFieldReset?: boolean;\n /** Turns a picked file into a URL for image fields. */\n resolveFile?: ParameterImageProps['resolveFile'];\n /** Shown when the schema has no fields. */\n emptyMessage?: React.ReactNode;\n className?: string;\n}\n\nfunction FieldRow({\n controller,\n state,\n field,\n idBase,\n showKeyframes,\n showFieldReset,\n resolveFile,\n}: {\n controller: ParametersController;\n state: ParametersState;\n field: ParameterField;\n idBase: string;\n showKeyframes: boolean;\n showFieldReset: boolean;\n resolveFile?: ParameterImageProps['resolveFile'];\n}) {\n const label = parameterLabel(field);\n const inputId = `${idBase}-${field.id}`;\n const value = state.values[field.id];\n const error = state.errors[field.id];\n const changed = !parameterValuesEqual(value, state.defaults[field.id]);\n return (\n <div data-parameter-id={field.id} data-parameter-type={field.type} className=\"space-y-1\">\n <div className=\"flex min-h-[1.25rem] items-center gap-1.5\">\n {showKeyframes && (\n <KeyframeDiamond state={state.keys[field.id] ?? 'none'} label={label} onToggle={() => controller.toggleKeyframe(field.id)} />\n )}\n <label htmlFor={inputId} className=\"min-w-0 flex-1 truncate text-xs font-medium text-foreground\" title={field.description}>\n {label}\n </label>\n {showFieldReset && changed && !field.readOnly && (\n <button\n type=\"button\"\n className=\"rounded px-1 text-[11px] text-muted-foreground hover:text-foreground\"\n title={`Reset to ${String(state.defaults[field.id])}`}\n aria-label={`Reset ${label}`}\n onClick={() => controller.reset([field.id])}\n >\n ↺\n </button>\n )}\n </div>\n {field.description && <p className=\"text-[11px] leading-snug text-muted-foreground\">{field.description}</p>}\n <ParameterFieldControl\n field={field}\n value={value}\n id={inputId}\n resolveFile={resolveFile}\n onChange={(v) => controller.setValue(field.id, v)}\n onGestureStart={() => controller.beginGesture(field.id)}\n onGestureEnd={() => controller.endGesture()}\n />\n {error && (\n <p role=\"alert\" className=\"text-[11px] text-destructive\">\n {error}\n </p>\n )}\n </div>\n );\n}\n\nfunction PresetBar({ controller, state }: { controller: ParametersController; state: ParametersState }) {\n const [saving, setSaving] = useState(false);\n const [name, setName] = useState('');\n const [message, setMessage] = useState<string | null>(null);\n const active = state.presets.find((p) => p.name === state.activePreset);\n const save = (e: React.FormEvent) => {\n e.preventDefault();\n const result = controller.savePreset(name);\n if (result.ok) {\n setSaving(false);\n setName('');\n setMessage(null);\n } else setMessage(result.message);\n };\n return (\n <div className=\"space-y-1.5\" data-parameter-presets=\"\">\n <div className=\"flex items-center gap-1.5\">\n <select\n aria-label=\"Preset\"\n className={parameterInputClass}\n value={state.activePreset ?? ''}\n onChange={(e) => e.target.value && controller.applyPreset(e.target.value)}\n >\n <option value=\"\">{state.presets.length ? 'Presets…' : 'No presets'}</option>\n {state.presets.map((p) => (\n <option key={p.name} value={p.name} title={p.description}>\n {p.name}\n </option>\n ))}\n </select>\n <button type=\"button\" className={parameterButtonClass} onClick={() => setSaving((s) => !s)} aria-expanded={saving}>\n Save…\n </button>\n {active && !active.builtIn && (\n <button type=\"button\" className={parameterButtonClass} aria-label={`Delete preset ${active.name}`} onClick={() => controller.deletePreset(active.name)}>\n Delete\n </button>\n )}\n </div>\n {saving && (\n <form className=\"flex items-center gap-1.5\" onSubmit={save}>\n <input\n autoFocus\n aria-label=\"Preset name\"\n placeholder=\"Preset name\"\n className={parameterInputClass}\n value={name}\n onChange={(e) => setName(e.target.value)}\n />\n <button type=\"submit\" className={parameterButtonClass}>\n Save\n </button>\n </form>\n )}\n {message && (\n <p role=\"alert\" className=\"text-[11px] text-destructive\">\n {message}\n </p>\n )}\n </div>\n );\n}\n\n/**\n * Renders a whole parameter schema: collapsible groups, one control per visible field,\n * keyframe diamonds, per-field reset, presets, and undo / redo / reset / randomize. Slider\n * drags and colour picks are one undo step each.\n */\nexport function ParametersPanel({\n controller,\n title,\n showToolbar = true,\n showPresets = true,\n showKeyframes,\n showFieldReset = true,\n resolveFile,\n emptyMessage = 'No parameters.',\n className = '',\n}: ParametersPanelProps) {\n const state = useParametersState(controller);\n const idBase = useId();\n const keys = showKeyframes ?? state.keyframesEnabled;\n const heading = title === undefined ? state.schema.title : title;\n\n const renderItems = (items: readonly ParameterSchemaItem[]): React.ReactNode =>\n items.map((item) => {\n if (state.visible[item.id] === false) return null;\n if (isParameterGroup(item)) return renderGroup(item);\n return (\n <FieldRow\n key={item.id}\n controller={controller}\n state={state}\n field={item}\n idBase={idBase}\n showKeyframes={keys}\n showFieldReset={showFieldReset}\n resolveFile={resolveFile}\n />\n );\n });\n\n const renderGroup = (group: ParameterGroup) => {\n const collapsed = !!state.collapsed[group.id];\n const bodyId = `${idBase}-group-${group.id}`;\n return (\n <section key={group.id} data-parameter-group={group.id} className=\"rounded-md border border-border\">\n <button\n type=\"button\"\n aria-expanded={!collapsed}\n aria-controls={bodyId}\n onClick={() => controller.toggleCollapsed(group.id)}\n className=\"flex w-full items-center gap-1.5 px-2 py-1.5 text-left text-xs font-semibold text-foreground hover:bg-muted\"\n >\n <span aria-hidden=\"true\" className={`inline-block text-[10px] text-muted-foreground transition-transform ${collapsed ? '' : 'rotate-90'}`}>\n ▶\n </span>\n {parameterLabel(group)}\n </button>\n {!collapsed && (\n <div id={bodyId} className=\"space-y-3 border-t border-border px-2 py-2\">\n {group.description && <p className=\"text-[11px] text-muted-foreground\">{group.description}</p>}\n {renderItems(group.fields)}\n </div>\n )}\n </section>\n );\n };\n\n return (\n <div className={`space-y-3 text-foreground ${className}`} data-parameters-panel=\"\">\n {(heading || showToolbar) && (\n <div className=\"flex flex-wrap items-center gap-1.5\">\n {heading && <h3 className=\"mr-auto text-sm font-semibold\">{heading}</h3>}\n {showToolbar && (\n <div className=\"flex flex-wrap gap-1\" role=\"toolbar\" aria-label=\"Parameter actions\">\n <button\n type=\"button\"\n className={parameterButtonClass}\n disabled={!state.canUndo}\n title={state.canUndo ? `Undo ${state.undoLabel}` : 'Nothing to undo'}\n onClick={() => controller.undo()}\n >\n Undo\n </button>\n <button\n type=\"button\"\n className={parameterButtonClass}\n disabled={!state.canRedo}\n title={state.canRedo ? `Redo ${state.redoLabel}` : 'Nothing to redo'}\n onClick={() => controller.redo()}\n >\n Redo\n </button>\n <button type=\"button\" className={parameterButtonClass} disabled={!state.modified} onClick={() => controller.reset()}>\n Reset\n </button>\n <button type=\"button\" className={parameterButtonClass} onClick={() => controller.randomize()}>\n Randomize\n </button>\n </div>\n )}\n </div>\n )}\n {showPresets && <PresetBar controller={controller} state={state} />}\n {state.fields.length === 0 ? <p className=\"text-xs text-muted-foreground\">{emptyMessage}</p> : renderItems(state.schema.fields)}\n </div>\n );\n}\n"],"mappings":"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","names":["useRef","_","parameterLabel","jsx","jsxs","parameterLabel"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor-react",
3
- "version": "0.19.1",
3
+ "version": "0.20.0",
4
4
  "description": "React bindings and prompt/rich-text components for @pixerate/editor",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -53,6 +53,11 @@
53
53
  "types": "./dist/tokens/index.d.ts",
54
54
  "import": "./dist/tokens/index.js",
55
55
  "require": "./dist/tokens/index.cjs"
56
+ },
57
+ "./parameters": {
58
+ "types": "./dist/parameters/index.d.ts",
59
+ "import": "./dist/parameters/index.js",
60
+ "require": "./dist/parameters/index.cjs"
56
61
  }
57
62
  },
58
63
  "typesVersions": {
@@ -77,6 +82,9 @@
77
82
  ],
78
83
  "tokens": [
79
84
  "./dist/tokens/index.d.ts"
85
+ ],
86
+ "parameters": [
87
+ "./dist/parameters/index.d.ts"
80
88
  ]
81
89
  }
82
90
  },
@@ -88,7 +96,7 @@
88
96
  "@tiptap/extension-bubble-menu": "^2.11.5",
89
97
  "@tiptap/extension-placeholder": "^2.11.5",
90
98
  "@tiptap/starter-kit": "^2.11.5",
91
- "@pixerate/editor": "0.28.0"
99
+ "@pixerate/editor": "0.29.0"
92
100
  },
93
101
  "peerDependencies": {
94
102
  "@dagrejs/dagre": "^1.1.8",