import { html, type TemplateResult } from 'lit'; import { formatUsageFromDefaults, type PlaygroundControl, type PlaygroundDefinition, type PlaygroundPreviewHandlers, type PlaygroundProps, whenBoolean, whenString, } from '../types.js'; const ATTRIBUTE_NAMES: Record = { strokeWidth: 'stroke-width', showValue: 'show-value', valueTemplate: 'value-template', valueColor: 'value-color', rangeColor: 'range-color', textColor: 'text-color', ariaLabel: 'aria-label', ariaLabelledby: 'aria-labelledby', nuiType: 'nui-type', knobClass: 'knob-class', }; export const NUI_KNOB_DEFAULTS: PlaygroundProps = { value: '60', min: '0', max: '100', step: '1', size: '100', strokeWidth: '14', showValue: true, valueTemplate: '{value}', valueColor: '', rangeColor: '', textColor: '', readonly: false, disabled: false, tabindex: '0', unstyled: false, nuiType: '', knobClass: '', ariaLabel: '', ariaLabelledby: '', }; const CONTROLS: PlaygroundControl[] = [ { key: 'value', label: 'value', type: 'text', section: 'Content', placeholder: '60', }, { key: 'valueTemplate', label: 'value-template', type: 'text', section: 'Content', placeholder: '{value}', }, { key: 'knobClass', label: 'knob-class', type: 'text', section: 'Content', }, { key: 'valueColor', label: 'value-color', type: 'text', section: 'Appearance', }, { key: 'rangeColor', label: 'range-color', type: 'text', section: 'Appearance', }, { key: 'textColor', label: 'text-color', type: 'text', section: 'Appearance', }, { key: 'nuiType', label: 'nui-type', type: 'text', section: 'Appearance' }, { key: 'showValue', label: 'show-value', type: 'boolean', section: 'Modifiers', }, { key: 'unstyled', label: 'unstyled', type: 'boolean', section: 'Modifiers', }, { key: 'min', label: 'min', type: 'text', section: 'Layout', placeholder: '0', }, { key: 'max', label: 'max', type: 'text', section: 'Layout', placeholder: '100', }, { key: 'step', label: 'step', type: 'text', section: 'Layout', placeholder: '1', }, { key: 'size', label: 'size', type: 'text', section: 'Layout', placeholder: '100', }, { key: 'strokeWidth', label: 'stroke-width', type: 'text', section: 'Layout', placeholder: '14', }, { key: 'disabled', label: 'disabled', type: 'boolean', section: 'State' }, { key: 'readonly', label: 'readonly', type: 'boolean', section: 'State' }, { key: 'tabindex', label: 'tabindex', type: 'text', section: 'HTML', placeholder: '0', }, { key: 'ariaLabel', label: 'aria-label', type: 'text', section: 'HTML', }, { key: 'ariaLabelledby', label: 'aria-labelledby', type: 'text', section: 'HTML', }, ]; function handleKnobChange( event: Event, handlers?: PlaygroundPreviewHandlers, ): void { if (!handlers) { return; } const value = (event as CustomEvent<{ value: number }>).detail.value; handlers.onPropChange('value', String(value)); } function renderPreview( props: PlaygroundProps, handlers?: PlaygroundPreviewHandlers, ): TemplateResult { return html` 0 ? Number(props.step) : 1} size=${Number(props.size) > 0 ? Number(props.size) : 100} stroke-width=${Number(props.strokeWidth) > 0 ? Number(props.strokeWidth) : 14} value-template=${whenString(props.valueTemplate)} value-color=${whenString(props.valueColor)} range-color=${whenString(props.rangeColor)} text-color=${whenString(props.textColor)} knob-class=${whenString(props.knobClass)} nui-type=${whenString(props.nuiType)} aria-label=${whenString(props.ariaLabel)} aria-labelledby=${whenString(props.ariaLabelledby)} tabindex=${Number(props.tabindex)} .showValue=${Boolean(props.showValue)} ?readonly=${whenBoolean(props.readonly)} ?disabled=${whenBoolean(props.disabled)} ?unstyled=${whenBoolean(props.unstyled)} @input=${(event: Event) => handleKnobChange(event, handlers)} > `; } export const nuiKnobPlayground: PlaygroundDefinition = { tag: 'nui-knob', label: 'Knob', description: 'Circular dial for numeric input with drag, click, and keyboard support.', defaults: NUI_KNOB_DEFAULTS, controls: CONTROLS, renderPreview, formatUsage: (props) => formatUsageFromDefaults( 'nui-knob', props, NUI_KNOB_DEFAULTS, ATTRIBUTE_NAMES, ), };