@vielzeug/craftit 2.1.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -124
- package/dist/controls/a11y-control.cjs +1 -1
- package/dist/controls/a11y-control.cjs.map +1 -1
- package/dist/controls/a11y-control.d.ts +1 -1
- package/dist/controls/a11y-control.d.ts.map +1 -1
- package/dist/controls/a11y-control.js +1 -1
- package/dist/controls/a11y-control.js.map +1 -1
- package/dist/controls/checkable-control.cjs +1 -1
- package/dist/controls/checkable-control.cjs.map +1 -1
- package/dist/controls/checkable-control.d.ts +7 -7
- package/dist/controls/checkable-control.d.ts.map +1 -1
- package/dist/controls/checkable-control.js +1 -1
- package/dist/controls/checkable-control.js.map +1 -1
- package/dist/controls/choice-field-control.cjs +2 -0
- package/dist/controls/choice-field-control.cjs.map +1 -0
- package/dist/controls/choice-field-control.d.ts +3 -0
- package/dist/controls/choice-field-control.d.ts.map +1 -0
- package/dist/controls/choice-field-control.js +2 -0
- package/dist/controls/choice-field-control.js.map +1 -0
- package/dist/controls/field-control.cjs +1 -1
- package/dist/controls/field-control.cjs.map +1 -1
- package/dist/controls/field-control.d.ts +28 -73
- package/dist/controls/field-control.d.ts.map +1 -1
- package/dist/controls/field-control.js +1 -1
- package/dist/controls/field-control.js.map +1 -1
- package/dist/controls/index.d.ts +11 -9
- package/dist/controls/index.d.ts.map +1 -1
- package/dist/controls/internal/control-state.cjs +1 -1
- package/dist/controls/internal/control-state.cjs.map +1 -1
- package/dist/controls/internal/control-state.d.ts +6 -4
- package/dist/controls/internal/control-state.d.ts.map +1 -1
- package/dist/controls/internal/control-state.js +1 -1
- package/dist/controls/internal/control-state.js.map +1 -1
- package/dist/controls/internal/keyboard-utils.cjs.map +1 -1
- package/dist/controls/internal/keyboard-utils.js.map +1 -1
- package/dist/controls/internal/number-utils.cjs.map +1 -1
- package/dist/controls/internal/number-utils.js.map +1 -1
- package/dist/controls/internal/validation-utils.cjs.map +1 -1
- package/dist/controls/internal/validation-utils.js.map +1 -1
- package/dist/controls/list-control.cjs +1 -1
- package/dist/controls/list-control.cjs.map +1 -1
- package/dist/controls/list-control.d.ts +10 -8
- package/dist/controls/list-control.d.ts.map +1 -1
- package/dist/controls/list-control.js +1 -1
- package/dist/controls/list-control.js.map +1 -1
- package/dist/controls/overlay-control.cjs +1 -1
- package/dist/controls/overlay-control.cjs.map +1 -1
- package/dist/controls/overlay-control.d.ts +17 -14
- package/dist/controls/overlay-control.d.ts.map +1 -1
- package/dist/controls/overlay-control.js +1 -1
- package/dist/controls/overlay-control.js.map +1 -1
- package/dist/controls/popup-list-control.cjs +2 -0
- package/dist/controls/popup-list-control.cjs.map +1 -0
- package/dist/controls/popup-list-control.d.ts +160 -0
- package/dist/controls/popup-list-control.d.ts.map +1 -0
- package/dist/controls/popup-list-control.js +2 -0
- package/dist/controls/popup-list-control.js.map +1 -0
- package/dist/controls/press-control.cjs.map +1 -1
- package/dist/controls/press-control.js.map +1 -1
- package/dist/controls/slider-control.cjs.map +1 -1
- package/dist/controls/slider-control.js.map +1 -1
- package/dist/controls/spinner-control.cjs.map +1 -1
- package/dist/controls/spinner-control.js.map +1 -1
- package/dist/controls/swipe-control.cjs +2 -0
- package/dist/controls/swipe-control.cjs.map +1 -0
- package/dist/controls/swipe-control.d.ts +32 -0
- package/dist/controls/swipe-control.d.ts.map +1 -0
- package/dist/controls/swipe-control.js +2 -0
- package/dist/controls/swipe-control.js.map +1 -0
- package/dist/controls/text-field-control.cjs +2 -0
- package/dist/controls/text-field-control.cjs.map +1 -0
- package/dist/controls/text-field-control.d.ts +3 -0
- package/dist/controls/text-field-control.d.ts.map +1 -0
- package/dist/controls/text-field-control.js +2 -0
- package/dist/controls/text-field-control.js.map +1 -0
- package/dist/controls.cjs +1 -1
- package/dist/controls.js +1 -1
- package/dist/craftit.cjs +1 -1
- package/dist/craftit.cjs.map +1 -1
- package/dist/craftit.js +1 -1
- package/dist/craftit.js.map +1 -1
- package/dist/directives/classMap.cjs +2 -0
- package/dist/directives/classMap.cjs.map +1 -0
- package/dist/directives/classMap.d.ts +19 -0
- package/dist/directives/classMap.d.ts.map +1 -0
- package/dist/directives/classMap.js +2 -0
- package/dist/directives/classMap.js.map +1 -0
- package/dist/directives/each.cjs +1 -1
- package/dist/directives/each.cjs.map +1 -1
- package/dist/directives/each.d.ts +5 -30
- package/dist/directives/each.d.ts.map +1 -1
- package/dist/directives/each.js +1 -1
- package/dist/directives/each.js.map +1 -1
- package/dist/directives/guard.cjs +2 -0
- package/dist/directives/guard.cjs.map +1 -0
- package/dist/directives/guard.d.ts +10 -0
- package/dist/directives/guard.d.ts.map +1 -0
- package/dist/directives/guard.js +2 -0
- package/dist/directives/guard.js.map +1 -0
- package/dist/directives/live.cjs +2 -0
- package/dist/directives/live.cjs.map +1 -0
- package/dist/directives/live.d.ts +23 -0
- package/dist/directives/live.d.ts.map +1 -0
- package/dist/directives/live.js +2 -0
- package/dist/directives/live.js.map +1 -0
- package/dist/directives/raw.cjs +1 -1
- package/dist/directives/raw.cjs.map +1 -1
- package/dist/directives/raw.d.ts +3 -5
- package/dist/directives/raw.d.ts.map +1 -1
- package/dist/directives/raw.js +1 -1
- package/dist/directives/raw.js.map +1 -1
- package/dist/directives/resource.cjs +2 -0
- package/dist/directives/resource.cjs.map +1 -0
- package/dist/directives/resource.d.ts +32 -0
- package/dist/directives/resource.d.ts.map +1 -0
- package/dist/directives/resource.js +2 -0
- package/dist/directives/resource.js.map +1 -0
- package/dist/directives/styleMap.cjs +2 -0
- package/dist/directives/styleMap.cjs.map +1 -0
- package/dist/directives/styleMap.d.ts +11 -0
- package/dist/directives/styleMap.d.ts.map +1 -0
- package/dist/directives/styleMap.js +2 -0
- package/dist/directives/styleMap.js.map +1 -0
- package/dist/directives/when.cjs +1 -1
- package/dist/directives/when.cjs.map +1 -1
- package/dist/directives/when.d.ts +6 -19
- package/dist/directives/when.d.ts.map +1 -1
- package/dist/directives/when.js +1 -1
- package/dist/directives/when.js.map +1 -1
- package/dist/errors.cjs +2 -0
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.ts +12 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +2 -0
- package/dist/errors.js.map +1 -0
- package/dist/form.cjs +1 -1
- package/dist/form.cjs.map +1 -1
- package/dist/form.d.ts +3 -17
- package/dist/form.d.ts.map +1 -1
- package/dist/form.js +1 -1
- package/dist/form.js.map +1 -1
- package/dist/host.cjs +1 -1
- package/dist/host.cjs.map +1 -1
- package/dist/host.d.ts +40 -37
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +1 -1
- package/dist/host.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +16 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/internal.cjs +1 -1
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.ts +60 -120
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1 -1
- package/dist/internal.js.map +1 -1
- package/dist/observers/index.d.ts +1 -0
- package/dist/observers/index.d.ts.map +1 -1
- package/dist/observers/intersection-observe.cjs +1 -1
- package/dist/observers/intersection-observe.cjs.map +1 -1
- package/dist/observers/intersection-observe.d.ts +1 -1
- package/dist/observers/intersection-observe.js +1 -1
- package/dist/observers/intersection-observe.js.map +1 -1
- package/dist/observers/media-observe.cjs +1 -1
- package/dist/observers/media-observe.cjs.map +1 -1
- package/dist/observers/media-observe.d.ts +1 -1
- package/dist/observers/media-observe.js +1 -1
- package/dist/observers/media-observe.js.map +1 -1
- package/dist/observers/mutation-observe.cjs +2 -0
- package/dist/observers/mutation-observe.cjs.map +1 -0
- package/dist/observers/mutation-observe.d.ts +10 -0
- package/dist/observers/mutation-observe.d.ts.map +1 -0
- package/dist/observers/mutation-observe.js +2 -0
- package/dist/observers/mutation-observe.js.map +1 -0
- package/dist/observers/resize-observe.cjs +1 -1
- package/dist/observers/resize-observe.cjs.map +1 -1
- package/dist/observers/resize-observe.d.ts +1 -1
- package/dist/observers/resize-observe.js +1 -1
- package/dist/observers/resize-observe.js.map +1 -1
- package/dist/observers.cjs +1 -1
- package/dist/observers.js +1 -1
- package/dist/props.cjs +1 -1
- package/dist/props.cjs.map +1 -1
- package/dist/props.d.ts +18 -31
- package/dist/props.d.ts.map +1 -1
- package/dist/props.js +1 -1
- package/dist/props.js.map +1 -1
- package/dist/registration.cjs +1 -1
- package/dist/registration.cjs.map +1 -1
- package/dist/registration.d.ts +27 -7
- package/dist/registration.d.ts.map +1 -1
- package/dist/registration.js +1 -1
- package/dist/registration.js.map +1 -1
- package/dist/runtime.cjs +1 -1
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.ts +29 -17
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +1 -1
- package/dist/runtime.js.map +1 -1
- package/dist/template-bindings.cjs +1 -1
- package/dist/template-bindings.cjs.map +1 -1
- package/dist/template-bindings.d.ts +10 -47
- package/dist/template-bindings.d.ts.map +1 -1
- package/dist/template-bindings.js +1 -1
- package/dist/template-bindings.js.map +1 -1
- package/dist/template-compiler.cjs +1 -1
- package/dist/template-compiler.cjs.map +1 -1
- package/dist/template-compiler.d.ts +1 -21
- package/dist/template-compiler.d.ts.map +1 -1
- package/dist/template-compiler.js +1 -1
- package/dist/template-compiler.js.map +1 -1
- package/dist/testing/testing.cjs +1 -1
- package/dist/testing/testing.cjs.map +1 -1
- package/dist/testing/testing.d.ts +12 -5
- package/dist/testing/testing.d.ts.map +1 -1
- package/dist/testing/testing.js +1 -1
- package/dist/testing/testing.js.map +1 -1
- package/package.json +6 -12
- package/dist/component.cjs +0 -2
- package/dist/component.cjs.map +0 -1
- package/dist/component.d.ts +0 -39
- package/dist/component.d.ts.map +0 -1
- package/dist/component.js +0 -2
- package/dist/component.js.map +0 -1
- package/dist/controls/list-key-control.cjs +0 -2
- package/dist/controls/list-key-control.cjs.map +0 -1
- package/dist/controls/list-key-control.d.ts +0 -14
- package/dist/controls/list-key-control.d.ts.map +0 -1
- package/dist/controls/list-key-control.js +0 -2
- package/dist/controls/list-key-control.js.map +0 -1
- package/dist/directives/attr.cjs +0 -2
- package/dist/directives/attr.cjs.map +0 -1
- package/dist/directives/attr.d.ts +0 -12
- package/dist/directives/attr.d.ts.map +0 -1
- package/dist/directives/attr.js +0 -2
- package/dist/directives/attr.js.map +0 -1
- package/dist/directives/bind.cjs +0 -2
- package/dist/directives/bind.cjs.map +0 -1
- package/dist/directives/bind.d.ts +0 -38
- package/dist/directives/bind.d.ts.map +0 -1
- package/dist/directives/bind.js +0 -2
- package/dist/directives/bind.js.map +0 -1
- package/dist/directives/choose.cjs +0 -2
- package/dist/directives/choose.cjs.map +0 -1
- package/dist/directives/choose.d.ts +0 -39
- package/dist/directives/choose.d.ts.map +0 -1
- package/dist/directives/choose.js +0 -2
- package/dist/directives/choose.js.map +0 -1
- package/dist/directives/classes.cjs +0 -2
- package/dist/directives/classes.cjs.map +0 -1
- package/dist/directives/classes.d.ts +0 -20
- package/dist/directives/classes.d.ts.map +0 -1
- package/dist/directives/classes.js +0 -2
- package/dist/directives/classes.js.map +0 -1
- package/dist/directives/index.d.ts +0 -13
- package/dist/directives/index.d.ts.map +0 -1
- package/dist/directives/memo.cjs +0 -2
- package/dist/directives/memo.cjs.map +0 -1
- package/dist/directives/memo.d.ts +0 -27
- package/dist/directives/memo.d.ts.map +0 -1
- package/dist/directives/memo.js +0 -2
- package/dist/directives/memo.js.map +0 -1
- package/dist/directives/on.cjs +0 -2
- package/dist/directives/on.cjs.map +0 -1
- package/dist/directives/on.d.ts +0 -25
- package/dist/directives/on.d.ts.map +0 -1
- package/dist/directives/on.js +0 -2
- package/dist/directives/on.js.map +0 -1
- package/dist/directives/spread.cjs +0 -2
- package/dist/directives/spread.cjs.map +0 -1
- package/dist/directives/spread.d.ts +0 -14
- package/dist/directives/spread.d.ts.map +0 -1
- package/dist/directives/spread.js +0 -2
- package/dist/directives/spread.js.map +0 -1
- package/dist/directives/style.cjs +0 -2
- package/dist/directives/style.cjs.map +0 -1
- package/dist/directives/style.d.ts +0 -22
- package/dist/directives/style.d.ts.map +0 -1
- package/dist/directives/style.js +0 -2
- package/dist/directives/style.js.map +0 -1
- package/dist/directives/until.cjs +0 -2
- package/dist/directives/until.cjs.map +0 -1
- package/dist/directives/until.d.ts +0 -26
- package/dist/directives/until.d.ts.map +0 -1
- package/dist/directives/until.js +0 -2
- package/dist/directives/until.js.map +0 -1
- package/dist/directives.cjs +0 -1
- package/dist/directives.js +0 -1
- package/dist/runtime-bindings.cjs +0 -2
- package/dist/runtime-bindings.cjs.map +0 -1
- package/dist/runtime-bindings.d.ts +0 -6
- package/dist/runtime-bindings.d.ts.map +0 -1
- package/dist/runtime-bindings.js +0 -2
- package/dist/runtime-bindings.js.map +0 -1
- package/dist/runtime-core.cjs +0 -2
- package/dist/runtime-core.cjs.map +0 -1
- package/dist/runtime-core.d.ts +0 -21
- package/dist/runtime-core.d.ts.map +0 -1
- package/dist/runtime-core.js +0 -2
- package/dist/runtime-core.js.map +0 -1
- package/dist/runtime-lifecycle.cjs +0 -2
- package/dist/runtime-lifecycle.cjs.map +0 -1
- package/dist/runtime-lifecycle.d.ts +0 -24
- package/dist/runtime-lifecycle.d.ts.map +0 -1
- package/dist/runtime-lifecycle.js +0 -2
- package/dist/runtime-lifecycle.js.map +0 -1
- package/dist/template-dom.cjs +0 -2
- package/dist/template-dom.cjs.map +0 -1
- package/dist/template-dom.d.ts +0 -13
- package/dist/template-dom.d.ts.map +0 -1
- package/dist/template-dom.js +0 -2
- package/dist/template-dom.js.map +0 -1
- package/dist/template-html.cjs +0 -2
- package/dist/template-html.cjs.map +0 -1
- package/dist/template-html.d.ts +0 -23
- package/dist/template-html.d.ts.map +0 -1
- package/dist/template-html.js +0 -2
- package/dist/template-html.js.map +0 -1
- package/dist/template.cjs +0 -2
- package/dist/template.cjs.map +0 -1
- package/dist/template.d.ts +0 -10
- package/dist/template.d.ts.map +0 -1
- package/dist/template.js +0 -2
- package/dist/template.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-control.cjs","names":[],"sources":["../../src/controls/field-control.ts"],"sourcesContent":["import { computed, isSignal, type ReadonlySignal, type Signal, signal } from '@vielzeug/stateit';\n\nimport { spread } from '../directives/spread';\nimport { defineField, type FormFieldHandle } from '../form';\nimport { createId, ref, type Directive } from '../internal';\nimport { effect, handle, onElement, watch } from '../runtime-lifecycle';\nimport {\n createControlState,\n type ControlContextOptions,\n type ControlValidationMode,\n type FormControlValidationTrigger,\n} from './internal/control-state';\n\nexport type { FormControlValidationTrigger } from './internal/control-state';\nexport { createValidationControl } from './internal/control-state';\nexport type { ValidationReporter } from './internal/control-state';\n\n// Discriminated union types for text vs checkable variants\nexport type TextFieldControlContext = {\n disabled?: ReadonlySignal<boolean | undefined>;\n validateOn?: ReadonlySignal<ControlValidationMode>;\n};\n\nexport type TextFieldOptions = Omit<ControlContextOptions, 'disabled' | 'validateOn'> & {\n autocomplete?: ReadonlySignal<string | undefined>;\n context?: TextFieldControlContext;\n disabled?: ReadonlySignal<boolean | undefined>;\n elementRef?: { value: HTMLInputElement | HTMLTextAreaElement | null };\n error?: ReadonlySignal<string | undefined>;\n helper?: ReadonlySignal<string | undefined>;\n inputmode?: ReadonlySignal<string | undefined>;\n label?: ReadonlySignal<string | undefined>;\n labelPlacement?: ReadonlySignal<'inset' | 'outside' | undefined>;\n maxLength?: ReadonlySignal<number | undefined>;\n minLength?: ReadonlySignal<number | undefined>;\n name?: ReadonlySignal<string | undefined>;\n onBlur?: (event: FocusEvent) => void;\n onChange?: (event: Event, value: string) => void;\n onInput?: (event: Event, value: string) => void;\n onInputExtra?: (event: Event) => void;\n onReset?: () => void;\n pattern?: ReadonlySignal<string | undefined>;\n placeholder?: ReadonlySignal<string | undefined>;\n prefix: string;\n readOnly?: ReadonlySignal<boolean | undefined>;\n required?: ReadonlySignal<boolean | undefined>;\n rows?: ReadonlySignal<number | undefined>;\n type?: ReadonlySignal<string | undefined> | (() => string | undefined) | string;\n validateOn?: ReadonlySignal<ControlValidationMode>;\n value: ReadonlySignal<string | undefined>;\n};\n\nexport type ChoiceFieldOptions<T> = {\n context?: TextFieldControlContext;\n disabled?: ReadonlySignal<boolean | undefined>;\n error?: ReadonlySignal<string | undefined>;\n getValue: (item: T) => string;\n helper?: ReadonlySignal<string | undefined>;\n label?: ReadonlySignal<string | undefined>;\n labelPlacement?: ReadonlySignal<'inset' | 'outside' | undefined>;\n mapControlledValue: (value: string) => T;\n multiple?: ReadonlySignal<boolean | undefined>;\n name?: ReadonlySignal<string | undefined>;\n onReset?: () => void;\n prefix: string;\n validateOn?: ReadonlySignal<ControlValidationMode>;\n value: ReadonlySignal<string | undefined>;\n};\n\nexport type CheckableStateOptions = ControlContextOptions & {\n checked: ReadonlySignal<boolean | undefined>;\n clearIndeterminateFirst?: boolean;\n error?: ReadonlySignal<string | undefined>;\n group?: { toggle: (value: string, originalEvent?: Event) => void };\n helper?: ReadonlySignal<string | undefined>;\n indeterminate?: ReadonlySignal<boolean | undefined>;\n label?: ReadonlySignal<string | undefined>;\n labelPlacement?: ReadonlySignal<'inset' | 'outside' | undefined>;\n name?: ReadonlySignal<string | undefined>;\n onReset?: () => void;\n onToggle?: (payload: CheckableChangePayload) => void;\n prefix: string;\n value: ReadonlySignal<string | undefined>;\n};\n\nexport type CheckableChangePayload = {\n checked: boolean;\n fieldValue: string;\n originalEvent?: Event;\n};\n\nexport type FieldControlBaseHandle = {\n disabled: ReadonlySignal<boolean>;\n errorId: string;\n field: FormFieldHandle;\n fieldId: string;\n helperId: string;\n labelInsetId: string;\n labelInsetRef: { value: HTMLLabelElement | null };\n labelOutsideId: string;\n labelOutsideRef: { value: HTMLLabelElement | null };\n triggerValidation: (on: FormControlValidationTrigger) => void;\n validateOn: ReadonlySignal<ControlValidationMode> | undefined;\n};\n\nexport type TextFieldHandle = FieldControlBaseHandle & {\n assistive: ReadonlySignal<AssistiveState>;\n attrs: Directive;\n clear: (event?: Event) => void;\n value: Signal<string>;\n};\n\nexport type AssistiveState = {\n counterAtLimit: boolean;\n counterNearLimit: boolean;\n counterText: string;\n errorText: string;\n hasCounter: boolean;\n hasError: boolean;\n hasHelper: boolean;\n helperText: string;\n hidden: boolean;\n isError: boolean;\n showHelper: boolean;\n text: string;\n};\n\nexport type AssistiveOptions = {\n error?: ReadonlySignal<string | undefined>;\n helper?: ReadonlySignal<string | undefined>;\n maxLength?: ReadonlySignal<number | undefined>;\n value?: ReadonlySignal<string | undefined>;\n};\n\nexport type TextFieldLifecycleOptions = {\n element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;\n onBlur?: (event: FocusEvent) => void;\n onChange?: (event: Event, value: string) => void;\n onInput?: (event: Event, value: string) => void;\n triggerValidation?: (on: FormControlValidationTrigger) => void;\n};\n\nexport type CheckableStateHandle = FieldControlBaseHandle & {\n assistive: ReadonlySignal<AssistiveState>;\n checked: Signal<boolean>;\n indeterminate: Signal<boolean>;\n toggle: (event: Event) => void;\n value: Signal<string>;\n};\n\nexport type ChoiceFieldHandle<T> = FieldControlBaseHandle & {\n assistive: ReadonlySignal<AssistiveState>;\n clear: () => void;\n field: FormFieldHandle;\n formValue: ReadonlySignal<string>;\n isMultiple: ReadonlySignal<boolean>;\n isSelected: (value: string) => boolean;\n removeValue: (value: string) => void;\n replaceSelectedItems: (items: T[]) => void;\n selectedItems: Signal<T[]>;\n selectedValues: ReadonlySignal<string[]>;\n selectItem: (item: T) => void;\n toggleItem: (item: T) => void;\n};\n\ntype ReactiveValue<T> = ReadonlySignal<T> | (() => T) | T;\n\n/**\n * Generates a stable set of ARIA-related IDs for a field control.\n * Snapshot `name` at call time — IDs are stable strings, not reactive.\n */\nconst createFieldIds = (prefix: string, name?: string | null) => {\n const normalizedName = name && name.trim() ? name.trim() : createId().replace(/^cft-/, '');\n const fieldId = `${prefix}-${normalizedName}`;\n const labelInsetId = `label-${fieldId}`;\n\n return {\n errorId: `error-${fieldId}`,\n fieldId,\n helperId: `helper-${fieldId}`,\n labelInsetId,\n labelOutsideId: `${labelInsetId}-outside`,\n };\n};\n\nconst createBaseFieldHandle = (\n options: {\n label?: ReadonlySignal<string | undefined>;\n labelPlacement?: ReadonlySignal<'inset' | 'outside' | undefined>;\n name?: ReadonlySignal<string | undefined>;\n prefix: string;\n } & ControlContextOptions,\n) => {\n const controlState = createControlState(options);\n const ids = createFieldIds(options.prefix, options.name?.value);\n const labelInsetRef = ref<HTMLLabelElement>();\n const labelOutsideRef = ref<HTMLLabelElement>();\n\n const syncLabels = () => {\n const placement = options.labelPlacement?.value ?? 'inset';\n const text = options.label?.value ?? '';\n\n if (labelInsetRef.value) {\n labelInsetRef.value.textContent = text;\n labelInsetRef.value.hidden = !text || placement !== 'inset';\n }\n\n if (labelOutsideRef.value) {\n labelOutsideRef.value.textContent = text;\n labelOutsideRef.value.hidden = !text || placement !== 'outside';\n }\n };\n\n effect(syncLabels);\n\n return {\n disabled: controlState.disabled,\n errorId: ids.errorId,\n fieldId: ids.fieldId,\n helperId: ids.helperId,\n labelInsetId: ids.labelInsetId,\n labelInsetRef,\n labelOutsideId: ids.labelOutsideId,\n labelOutsideRef,\n triggerValidation: (field: FormFieldHandle, on: FormControlValidationTrigger) =>\n controlState.triggerValidation(field, on),\n validateOn: controlState.validateOn,\n };\n};\n\nconst resolveControlContext = (options: {\n context?: TextFieldControlContext;\n disabled?: ReadonlySignal<boolean | undefined>;\n validateOn?: ReadonlySignal<ControlValidationMode>;\n}) => {\n return {\n disabled: computed(() => Boolean(options.disabled?.value) || Boolean(options.context?.disabled?.value)),\n validateOn: options.validateOn ?? options.context?.validateOn,\n };\n};\n\nexport const createAssistiveState = (options: AssistiveOptions) => {\n return computed<AssistiveState>(() => {\n const value = options.value?.value ?? '';\n const errorText = options.error?.value ?? '';\n const helperText = options.helper?.value ?? '';\n const hasError = Boolean(errorText);\n const hasHelper = Boolean(helperText);\n const text = errorText || helperText || '';\n const maxLength = options.maxLength?.value;\n const parsedMaxLength = Number(maxLength);\n const validMaxLength = Number.isFinite(parsedMaxLength) && parsedMaxLength > 0 ? parsedMaxLength : null;\n const hasCounter = validMaxLength !== null;\n const counterText = hasCounter ? `${value.length} / ${validMaxLength}` : '';\n const ratio = hasCounter ? value.length / validMaxLength : 0;\n\n return {\n counterAtLimit: hasCounter ? ratio >= 1 : false,\n counterNearLimit: hasCounter ? ratio >= 0.9 && ratio < 1 : false,\n counterText,\n errorText,\n hasCounter,\n hasError,\n hasHelper,\n helperText,\n hidden: !text,\n isError: hasError,\n showHelper: !hasError && hasHelper,\n text,\n };\n });\n};\n\nconst resolveReactiveValue = <T>(value: ReactiveValue<T> | undefined): T | undefined => {\n if (value === undefined) return undefined;\n\n if (isSignal(value)) return (value as ReadonlySignal<T>).value;\n\n if (typeof value === 'function') return (value as () => T)();\n\n return value;\n};\n\nconst optionalStringSource = (value: ReactiveValue<string | undefined> | undefined): (() => string | undefined) => {\n return () => {\n const next = resolveReactiveValue(value);\n\n if (next == null || next === '') return undefined;\n\n return String(next);\n };\n};\n\nconst optionalNumberSource = (value: ReactiveValue<number | undefined> | undefined): (() => number | undefined) => {\n return () => {\n const next = resolveReactiveValue(value);\n\n if (next == null || Number.isNaN(Number(next)) || Number(next) <= 0) return undefined;\n\n return Number(next);\n };\n};\n\nexport const createTextFieldControl = (options: TextFieldOptions): TextFieldHandle => {\n const value = signal('');\n const controlContext = resolveControlContext(options);\n const base = createBaseFieldHandle({\n ...options,\n ...controlContext,\n });\n\n watch(\n options.value,\n (next) => {\n value.value = String(next ?? '');\n },\n { immediate: true },\n );\n\n const field = defineField(\n {\n disabled: base.disabled,\n value,\n },\n {\n onReset: () => {\n value.value = '';\n options.onReset?.();\n },\n },\n );\n\n const assistive = createAssistiveState({\n error: options.error,\n helper: options.helper,\n maxLength: options.maxLength,\n value,\n });\n\n const clear = (event?: Event): void => {\n event?.preventDefault?.();\n\n value.value = '';\n options.onInput?.(event ?? new Event('input'), '');\n options.onChange?.(event ?? new Event('change'), '');\n base.triggerValidation(field, 'change');\n options.elementRef?.value?.focus();\n };\n\n if (options.elementRef) {\n onElement(options.elementRef, (element) => {\n mountTextFieldLifecycle({\n element,\n onBlur: options.onBlur,\n onChange: options.onChange,\n onInput: (event, nextValue) => {\n options.onInputExtra?.(event);\n options.onInput?.(event, nextValue);\n },\n triggerValidation: (on) => base.triggerValidation(field, on),\n });\n });\n }\n\n const attrs = spread({\n '?required': options.required,\n '.disabled': options.disabled,\n '.readOnly': options.readOnly,\n '.type': options.type,\n '.value': value,\n autocomplete: optionalStringSource(options.autocomplete),\n inputmode: optionalStringSource(options.inputmode),\n maxlength: optionalNumberSource(options.maxLength),\n minlength: optionalNumberSource(options.minLength),\n name: optionalStringSource(options.name),\n pattern: optionalStringSource(options.pattern),\n placeholder: optionalStringSource(options.placeholder),\n rows: optionalNumberSource(options.rows),\n });\n\n return {\n assistive,\n attrs,\n ...base,\n clear,\n field,\n triggerValidation: (on: FormControlValidationTrigger) => base.triggerValidation(field, on),\n value,\n };\n};\n\nexport const mountTextFieldLifecycle = (options: TextFieldLifecycleOptions): void => {\n const { element, onBlur, onChange, onInput, triggerValidation } = options;\n\n if (onInput) {\n handle(element, 'input', (event: Event) => {\n onInput(event, element.value);\n });\n }\n\n handle(element, 'change', (event: Event) => {\n onChange?.(event, element.value);\n triggerValidation?.('change');\n });\n\n handle(element, 'blur', (event: Event) => {\n onBlur?.(event as FocusEvent);\n triggerValidation?.('blur');\n });\n};\n\nconst parseChoiceFieldValues = (value: string | undefined): string[] => {\n if (!value) return [];\n\n return value\n .split(',')\n .map((entry) => entry.trim())\n .filter(Boolean);\n};\n\nexport const createChoiceFieldControl = <T>(options: ChoiceFieldOptions<T>): ChoiceFieldHandle<T> => {\n const controlContext = resolveControlContext(options);\n const base = createBaseFieldHandle({\n ...controlContext,\n label: options.label,\n labelPlacement: options.labelPlacement,\n name: options.name,\n prefix: options.prefix,\n });\n const selectedItems = signal<T[]>([]);\n const isMultiple = computed(() => Boolean(options.multiple?.value));\n const selectedValues = computed(() => selectedItems.value.map((item) => options.getValue(item)));\n const formValue = computed(() =>\n isMultiple.value ? selectedValues.value.join(',') : (selectedValues.value[0] ?? ''),\n );\n\n const normalizeSelectedItems = (items: T[]): T[] => {\n const normalized = isMultiple.value ? items : items.slice(0, 1);\n const uniqueItems: T[] = [];\n const seen = new Set<string>();\n\n for (const item of normalized) {\n const value = options.getValue(item);\n\n if (seen.has(value)) continue;\n\n seen.add(value);\n uniqueItems.push(item);\n }\n\n return uniqueItems;\n };\n\n const replaceSelectedItems = (items: T[]): void => {\n selectedItems.value = normalizeSelectedItems(items);\n };\n\n const clear = (): void => {\n replaceSelectedItems([]);\n };\n\n const removeValue = (value: string): void => {\n selectedItems.value = selectedItems.value.filter((item) => options.getValue(item) !== value);\n };\n\n const selectItem = (item: T): void => {\n if (isMultiple.value) {\n const value = options.getValue(item);\n\n if (selectedItems.value.some((current) => options.getValue(current) === value)) return;\n\n replaceSelectedItems([...selectedItems.value, item]);\n\n return;\n }\n\n replaceSelectedItems([item]);\n };\n\n const toggleItem = (item: T): void => {\n if (isMultiple.value) {\n const value = options.getValue(item);\n\n if (selectedItems.value.some((current) => options.getValue(current) === value)) {\n removeValue(value);\n\n return;\n }\n\n replaceSelectedItems([...selectedItems.value, item]);\n\n return;\n }\n\n replaceSelectedItems([item]);\n };\n\n const syncControlledValue = (nextValue: unknown): void => {\n const values = parseChoiceFieldValues(typeof nextValue === 'string' ? nextValue : String(nextValue ?? ''));\n\n replaceSelectedItems(values.map((value) => options.mapControlledValue(value)));\n };\n\n const field = defineField(\n {\n disabled: base.disabled,\n value: formValue,\n },\n {\n onReset: () => {\n clear();\n options.onReset?.();\n },\n },\n );\n\n const assistive = createAssistiveState({\n error: options.error,\n helper: options.helper,\n });\n\n watch(\n options.value,\n (next) => {\n syncControlledValue(next);\n },\n { immediate: true },\n );\n\n if (options.multiple) {\n watch(options.multiple, () => syncControlledValue(options.value.value));\n }\n\n return {\n ...base,\n assistive,\n clear,\n field,\n formValue,\n isMultiple,\n isSelected: (value: string) => selectedItems.value.some((item) => options.getValue(item) === value),\n removeValue,\n replaceSelectedItems,\n selectedItems,\n selectedValues,\n selectItem,\n toggleItem,\n triggerValidation: (on: FormControlValidationTrigger) => base.triggerValidation(field, on),\n };\n};\n\nexport const createCheckableStateControl = (options: CheckableStateOptions): CheckableStateHandle => {\n const value = signal('');\n const base = createBaseFieldHandle(options);\n const checked = signal(Boolean(options.checked.value));\n const indeterminate = signal(Boolean(options.indeterminate?.value));\n const assistive = createAssistiveState({ error: options.error, helper: options.helper });\n\n watch(\n options.checked,\n (next) => {\n checked.value = Boolean(next);\n },\n { immediate: true },\n );\n\n if (options.indeterminate) {\n watch(\n options.indeterminate,\n (next) => {\n indeterminate.value = Boolean(next);\n },\n { immediate: true },\n );\n }\n\n const field = defineField(\n {\n disabled: base.disabled,\n toFormValue: (next: string | null) => next,\n value: computed(() => (checked.value ? (options.value.value ?? '') : null)),\n },\n {\n onReset: () => {\n checked.value = Boolean(options.checked.value);\n indeterminate.value = Boolean(options.indeterminate?.value);\n options.onReset?.();\n },\n },\n );\n\n watch(\n options.value,\n (next) => {\n value.value = String(next ?? '');\n },\n { immediate: true },\n );\n\n const createPayload = (event: Event): CheckableChangePayload => ({\n checked: checked.value,\n fieldValue: options.value.value ?? '',\n originalEvent: event,\n });\n\n const toggle = (event: Event): void => {\n if (base.disabled.value) return;\n\n if (options.group) {\n indeterminate.value = false;\n options.group.toggle(options.value.value ?? '', event);\n options.onToggle?.(createPayload(event));\n\n return;\n }\n\n if (options.clearIndeterminateFirst && indeterminate.value) {\n indeterminate.value = false;\n } else {\n checked.value = !checked.value;\n indeterminate.value = false;\n }\n\n options.onToggle?.(createPayload(event));\n };\n\n return {\n ...base,\n assistive,\n checked,\n field,\n indeterminate,\n toggle,\n triggerValidation: (on: FormControlValidationTrigger) => base.triggerValidation(field, on),\n value,\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"field-control.cjs","names":[],"sources":["../../src/controls/field-control.ts"],"sourcesContent":["import { computed, type ReadonlySignal, type Signal } from '@vielzeug/stateit';\n\nimport { defineField, type FormFieldOptions } from '../form';\nimport { createId } from '../internal';\nimport { listen } from '../runtime';\nimport {\n createControlState,\n type ControlContextOptions,\n type ControlValidationMode,\n type FormControlValidationTrigger,\n} from './internal/control-state';\n\nexport type { FormControlValidationTrigger } from './internal/control-state';\nexport type { ValidationReporter } from './internal/control-state';\n\nexport type TextFieldControlContext = ControlContextOptions;\n\nexport type FieldBaseOptions = {\n context?: TextFieldControlContext;\n disabled?: ReadonlySignal<boolean | undefined>;\n error?: ReadonlySignal<string | undefined>;\n helper?: ReadonlySignal<string | undefined>;\n name?: ReadonlySignal<string | undefined>;\n prefix: string;\n validateOn?: ReadonlySignal<ControlValidationMode>;\n};\n\nexport type TextFieldOptions = FieldBaseOptions & {\n elementRef?: { value: HTMLInputElement | HTMLTextAreaElement | null };\n maxLength?: ReadonlySignal<number | undefined>;\n onBlur?: (event: FocusEvent) => void;\n onChange?: (event: Event, value: string) => void;\n onInput?: (event: Event, value: string) => void;\n onInputExtra?: (event: Event) => void;\n value: ReadonlySignal<string | undefined>;\n};\n\nexport type ChoiceFieldOptions = FieldBaseOptions & {\n multiple?: ReadonlySignal<boolean | undefined>;\n value: ReadonlySignal<string | undefined>;\n};\n\nexport type CheckableStateOptions = FieldBaseOptions & {\n checked: ReadonlySignal<boolean | undefined>;\n clearIndeterminateFirst?: boolean;\n group?: { toggle: (value: string, originalEvent?: Event) => void };\n indeterminate?: ReadonlySignal<boolean | undefined>;\n onToggle?: (payload: CheckableChangePayload) => void;\n value: ReadonlySignal<string | undefined>;\n};\n\nexport type CheckableChangePayload = {\n checked: boolean;\n originalEvent?: Event;\n value: string;\n};\n\nexport type FieldControlBaseHandle = {\n disabled: ReadonlySignal<boolean>;\n errorId: string;\n fieldId: string;\n helperId: string;\n labelInsetId: string;\n labelOutsideId: string;\n triggerValidation: (on: FormControlValidationTrigger) => void;\n};\n\nexport type TextFieldHandle = FieldControlBaseHandle & {\n assistive: ReadonlySignal<AssistiveState>;\n clear: (event?: Event) => void;\n value: Signal<string>;\n};\n\nexport type AssistiveState = {\n counterAtLimit: boolean;\n counterNearLimit: boolean;\n counterText: string;\n errorText: string;\n hasCounter: boolean;\n helperText: string;\n};\n\nexport type AssistiveOptions = {\n error?: ReadonlySignal<string | undefined>;\n helper?: ReadonlySignal<string | undefined>;\n maxLength?: ReadonlySignal<number | undefined>;\n value?: ReadonlySignal<string | undefined>;\n};\n\nexport type TextFieldLifecycleOptions = {\n element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;\n onBlur?: (event: FocusEvent) => void;\n onChange?: (event: Event, value: string) => void;\n onInput?: (event: Event, value: string) => void;\n triggerValidation?: (on: FormControlValidationTrigger) => void;\n};\n\nexport type CheckableStateHandle = FieldControlBaseHandle & {\n assistive: ReadonlySignal<AssistiveState>;\n checked: Signal<boolean>;\n indeterminate: Signal<boolean>;\n toggle: (event: Event) => void;\n value: Signal<string>;\n};\n\nexport type ChoiceFieldHandle = FieldControlBaseHandle & {\n assistive: ReadonlySignal<AssistiveState>;\n clear: () => void;\n formValue: ReadonlySignal<string>;\n removeValue: (value: string) => void;\n selectedValues: ReadonlySignal<string[]>;\n selectValue: (value: string) => void;\n setValues: (values: string[]) => void;\n toggleValue: (value: string) => void;\n};\n\n/**\n * Generates a stable set of ARIA-related IDs for a field control.\n * Snapshot `name` at call time — IDs are stable strings, not reactive.\n */\nconst createFieldIds = (prefix: string, name?: string | null) => {\n const normalizedName = name && name.trim() ? name.trim() : createId().replace(/^cft-/, '');\n const fieldId = `${prefix}-${normalizedName}`;\n const labelInsetId = `label-${fieldId}`;\n\n return {\n errorId: `error-${fieldId}`,\n fieldId,\n helperId: `helper-${fieldId}`,\n labelInsetId,\n labelOutsideId: `${labelInsetId}-outside`,\n };\n};\n\nexport const createFieldControlBase = <T = unknown>(\n options: {\n context?: TextFieldControlContext;\n name?: ReadonlySignal<string | undefined>;\n prefix: string;\n } & ControlContextOptions,\n fieldOptions: Omit<FormFieldOptions<T>, 'disabled'> & {\n disabled?: FormFieldOptions<T>['disabled'];\n },\n): {\n base: Omit<FieldControlBaseHandle, 'triggerValidation'>;\n triggerValidation: (on: FormControlValidationTrigger) => void;\n} => {\n const controlState = createControlState(options);\n const ids = createFieldIds(options.prefix, options.name?.value);\n\n const base: Omit<FieldControlBaseHandle, 'triggerValidation'> = {\n disabled: controlState.disabled,\n errorId: ids.errorId,\n fieldId: ids.fieldId,\n helperId: ids.helperId,\n labelInsetId: ids.labelInsetId,\n labelOutsideId: ids.labelOutsideId,\n };\n\n const field = defineField<T>({\n ...fieldOptions,\n disabled: fieldOptions.disabled ?? base.disabled,\n });\n\n return {\n base,\n triggerValidation: (on) => controlState.triggerValidation(field, on),\n };\n};\n\nexport const createAssistiveState = (options: AssistiveOptions) => {\n return computed<AssistiveState>(() => {\n const value = options.value?.value ?? '';\n const errorText = options.error?.value ?? '';\n const helperText = options.helper?.value ?? '';\n const maxLength = options.maxLength?.value;\n const parsedMaxLength = Number(maxLength);\n const validMaxLength = Number.isFinite(parsedMaxLength) && parsedMaxLength > 0 ? parsedMaxLength : null;\n const hasCounter = validMaxLength !== null;\n const counterText = hasCounter ? `${value.length} / ${validMaxLength}` : '';\n const ratio = hasCounter ? value.length / validMaxLength : 0;\n\n return {\n counterAtLimit: hasCounter ? ratio >= 1 : false,\n counterNearLimit: hasCounter ? ratio >= 0.9 && ratio < 1 : false,\n counterText,\n errorText,\n hasCounter,\n helperText,\n };\n });\n};\n\n/** @internal */\nexport const mountTextFieldLifecycle = (options: TextFieldLifecycleOptions): (() => void) => {\n const { element, onBlur, onChange, onInput, triggerValidation } = options;\n const disposers: Array<() => void> = [];\n\n if (onInput) {\n disposers.push(\n listen(element, 'input', (event: Event) => {\n // Prevent the native composed event from bubbling out of the shadow DOM\n // and being re-targeted onto the host element. The component emits its\n // own structured CustomEvent so external listeners never need the raw one.\n event.stopPropagation();\n onInput(event, element.value);\n }),\n );\n }\n\n disposers.push(\n listen(element, 'change', (event: Event) => {\n // Same reason as above — suppress the native change event from escaping.\n event.stopPropagation();\n onChange?.(event, element.value);\n triggerValidation?.('change');\n }),\n );\n\n disposers.push(\n listen(element, 'blur', (event: Event) => {\n onBlur?.(event as FocusEvent);\n triggerValidation?.('blur');\n }),\n );\n\n return () => {\n for (const dispose of disposers) dispose();\n };\n};\n"],"mappings":"qKAwHA,IAAM,GAAkB,EAAgB,IAAyB,CAE/D,IAAM,EAAU,GAAG,EAAO,GADH,GAAQ,EAAK,KAAK,EAAI,EAAK,KAAK,EAAI,EAAA,SAAS,EAAE,QAAQ,QAAS,EAAE,IAEnF,EAAe,SAAS,IAE9B,MAAO,CACL,QAAS,SAAS,IAClB,UACA,SAAU,UAAU,IACpB,eACA,eAAgB,GAAG,EAAa,SAClC,CACF,EAEa,GACX,EAKA,IAMG,CACH,IAAM,EAAe,EAAA,mBAAmB,CAAO,EACzC,EAAM,EAAe,EAAQ,OAAQ,EAAQ,MAAM,KAAK,EAExD,EAA0D,CAC9D,SAAU,EAAa,SACvB,QAAS,EAAI,QACb,QAAS,EAAI,QACb,SAAU,EAAI,SACd,aAAc,EAAI,aAClB,eAAgB,EAAI,cACtB,EAEM,EAAQ,EAAA,YAAe,CAC3B,GAAG,EACH,SAAU,EAAa,UAAY,EAAK,QAC1C,CAAC,EAED,MAAO,CACL,OACA,kBAAoB,GAAO,EAAa,kBAAkB,EAAO,CAAE,CACrE,CACF,EAEa,EAAwB,IACnC,EAAA,EAAA,cAAsC,CACpC,IAAM,EAAQ,EAAQ,OAAO,OAAS,GAChC,EAAY,EAAQ,OAAO,OAAS,GACpC,EAAa,EAAQ,QAAQ,OAAS,GACtC,EAAY,EAAQ,WAAW,MAC/B,EAAkB,OAAO,CAAS,EAClC,EAAiB,OAAO,SAAS,CAAe,GAAK,EAAkB,EAAI,EAAkB,KAC7F,EAAa,IAAmB,KAChC,EAAc,EAAa,GAAG,EAAM,OAAO,KAAK,IAAmB,GACnE,EAAQ,EAAa,EAAM,OAAS,EAAiB,EAE3D,MAAO,CACL,eAAgB,EAAa,GAAS,EAAI,GAC1C,iBAAkB,EAAa,GAAS,IAAO,EAAQ,EAAI,GAC3D,cACA,YACA,aACA,YACF,CACF,CAAC,EAIU,EAA2B,GAAqD,CAC3F,GAAM,CAAE,UAAS,SAAQ,WAAU,UAAS,qBAAsB,EAC5D,EAA+B,CAAC,EA8BtC,OA5BI,GACF,EAAU,KACR,EAAA,OAAO,EAAS,QAAU,GAAiB,CAIzC,EAAM,gBAAgB,EACtB,EAAQ,EAAO,EAAQ,KAAK,CAC9B,CAAC,CACH,EAGF,EAAU,KACR,EAAA,OAAO,EAAS,SAAW,GAAiB,CAE1C,EAAM,gBAAgB,EACtB,IAAW,EAAO,EAAQ,KAAK,EAC/B,IAAoB,QAAQ,CAC9B,CAAC,CACH,EAEA,EAAU,KACR,EAAA,OAAO,EAAS,OAAS,GAAiB,CACxC,IAAS,CAAmB,EAC5B,IAAoB,MAAM,CAC5B,CAAC,CACH,MAEa,CACX,IAAK,IAAM,KAAW,EAAW,EAAQ,CAC3C,CACF"}
|
|
@@ -1,102 +1,59 @@
|
|
|
1
1
|
import { type ReadonlySignal, type Signal } from '@vielzeug/stateit';
|
|
2
|
-
import { type
|
|
3
|
-
import { type Directive } from '../internal';
|
|
2
|
+
import { type FormFieldOptions } from '../form';
|
|
4
3
|
import { type ControlContextOptions, type ControlValidationMode, type FormControlValidationTrigger } from './internal/control-state';
|
|
5
4
|
export type { FormControlValidationTrigger } from './internal/control-state';
|
|
6
|
-
export { createValidationControl } from './internal/control-state';
|
|
7
5
|
export type { ValidationReporter } from './internal/control-state';
|
|
8
|
-
export type TextFieldControlContext =
|
|
6
|
+
export type TextFieldControlContext = ControlContextOptions;
|
|
7
|
+
export type FieldBaseOptions = {
|
|
8
|
+
context?: TextFieldControlContext;
|
|
9
9
|
disabled?: ReadonlySignal<boolean | undefined>;
|
|
10
|
+
error?: ReadonlySignal<string | undefined>;
|
|
11
|
+
helper?: ReadonlySignal<string | undefined>;
|
|
12
|
+
name?: ReadonlySignal<string | undefined>;
|
|
13
|
+
prefix: string;
|
|
10
14
|
validateOn?: ReadonlySignal<ControlValidationMode>;
|
|
11
15
|
};
|
|
12
|
-
export type TextFieldOptions =
|
|
13
|
-
autocomplete?: ReadonlySignal<string | undefined>;
|
|
14
|
-
context?: TextFieldControlContext;
|
|
15
|
-
disabled?: ReadonlySignal<boolean | undefined>;
|
|
16
|
+
export type TextFieldOptions = FieldBaseOptions & {
|
|
16
17
|
elementRef?: {
|
|
17
18
|
value: HTMLInputElement | HTMLTextAreaElement | null;
|
|
18
19
|
};
|
|
19
|
-
error?: ReadonlySignal<string | undefined>;
|
|
20
|
-
helper?: ReadonlySignal<string | undefined>;
|
|
21
|
-
inputmode?: ReadonlySignal<string | undefined>;
|
|
22
|
-
label?: ReadonlySignal<string | undefined>;
|
|
23
|
-
labelPlacement?: ReadonlySignal<'inset' | 'outside' | undefined>;
|
|
24
20
|
maxLength?: ReadonlySignal<number | undefined>;
|
|
25
|
-
minLength?: ReadonlySignal<number | undefined>;
|
|
26
|
-
name?: ReadonlySignal<string | undefined>;
|
|
27
21
|
onBlur?: (event: FocusEvent) => void;
|
|
28
22
|
onChange?: (event: Event, value: string) => void;
|
|
29
23
|
onInput?: (event: Event, value: string) => void;
|
|
30
24
|
onInputExtra?: (event: Event) => void;
|
|
31
|
-
onReset?: () => void;
|
|
32
|
-
pattern?: ReadonlySignal<string | undefined>;
|
|
33
|
-
placeholder?: ReadonlySignal<string | undefined>;
|
|
34
|
-
prefix: string;
|
|
35
|
-
readOnly?: ReadonlySignal<boolean | undefined>;
|
|
36
|
-
required?: ReadonlySignal<boolean | undefined>;
|
|
37
|
-
rows?: ReadonlySignal<number | undefined>;
|
|
38
|
-
type?: ReadonlySignal<string | undefined> | (() => string | undefined) | string;
|
|
39
|
-
validateOn?: ReadonlySignal<ControlValidationMode>;
|
|
40
25
|
value: ReadonlySignal<string | undefined>;
|
|
41
26
|
};
|
|
42
|
-
export type ChoiceFieldOptions
|
|
43
|
-
context?: TextFieldControlContext;
|
|
44
|
-
disabled?: ReadonlySignal<boolean | undefined>;
|
|
45
|
-
error?: ReadonlySignal<string | undefined>;
|
|
46
|
-
getValue: (item: T) => string;
|
|
47
|
-
helper?: ReadonlySignal<string | undefined>;
|
|
48
|
-
label?: ReadonlySignal<string | undefined>;
|
|
49
|
-
labelPlacement?: ReadonlySignal<'inset' | 'outside' | undefined>;
|
|
50
|
-
mapControlledValue: (value: string) => T;
|
|
27
|
+
export type ChoiceFieldOptions = FieldBaseOptions & {
|
|
51
28
|
multiple?: ReadonlySignal<boolean | undefined>;
|
|
52
|
-
name?: ReadonlySignal<string | undefined>;
|
|
53
|
-
onReset?: () => void;
|
|
54
|
-
prefix: string;
|
|
55
|
-
validateOn?: ReadonlySignal<ControlValidationMode>;
|
|
56
29
|
value: ReadonlySignal<string | undefined>;
|
|
57
30
|
};
|
|
58
|
-
export type CheckableStateOptions =
|
|
31
|
+
export type CheckableStateOptions = FieldBaseOptions & {
|
|
59
32
|
checked: ReadonlySignal<boolean | undefined>;
|
|
60
33
|
clearIndeterminateFirst?: boolean;
|
|
61
|
-
error?: ReadonlySignal<string | undefined>;
|
|
62
34
|
group?: {
|
|
63
35
|
toggle: (value: string, originalEvent?: Event) => void;
|
|
64
36
|
};
|
|
65
|
-
helper?: ReadonlySignal<string | undefined>;
|
|
66
37
|
indeterminate?: ReadonlySignal<boolean | undefined>;
|
|
67
|
-
label?: ReadonlySignal<string | undefined>;
|
|
68
|
-
labelPlacement?: ReadonlySignal<'inset' | 'outside' | undefined>;
|
|
69
|
-
name?: ReadonlySignal<string | undefined>;
|
|
70
|
-
onReset?: () => void;
|
|
71
38
|
onToggle?: (payload: CheckableChangePayload) => void;
|
|
72
|
-
prefix: string;
|
|
73
39
|
value: ReadonlySignal<string | undefined>;
|
|
74
40
|
};
|
|
75
41
|
export type CheckableChangePayload = {
|
|
76
42
|
checked: boolean;
|
|
77
|
-
fieldValue: string;
|
|
78
43
|
originalEvent?: Event;
|
|
44
|
+
value: string;
|
|
79
45
|
};
|
|
80
46
|
export type FieldControlBaseHandle = {
|
|
81
47
|
disabled: ReadonlySignal<boolean>;
|
|
82
48
|
errorId: string;
|
|
83
|
-
field: FormFieldHandle;
|
|
84
49
|
fieldId: string;
|
|
85
50
|
helperId: string;
|
|
86
51
|
labelInsetId: string;
|
|
87
|
-
labelInsetRef: {
|
|
88
|
-
value: HTMLLabelElement | null;
|
|
89
|
-
};
|
|
90
52
|
labelOutsideId: string;
|
|
91
|
-
labelOutsideRef: {
|
|
92
|
-
value: HTMLLabelElement | null;
|
|
93
|
-
};
|
|
94
53
|
triggerValidation: (on: FormControlValidationTrigger) => void;
|
|
95
|
-
validateOn: ReadonlySignal<ControlValidationMode> | undefined;
|
|
96
54
|
};
|
|
97
55
|
export type TextFieldHandle = FieldControlBaseHandle & {
|
|
98
56
|
assistive: ReadonlySignal<AssistiveState>;
|
|
99
|
-
attrs: Directive;
|
|
100
57
|
clear: (event?: Event) => void;
|
|
101
58
|
value: Signal<string>;
|
|
102
59
|
};
|
|
@@ -106,13 +63,7 @@ export type AssistiveState = {
|
|
|
106
63
|
counterText: string;
|
|
107
64
|
errorText: string;
|
|
108
65
|
hasCounter: boolean;
|
|
109
|
-
hasError: boolean;
|
|
110
|
-
hasHelper: boolean;
|
|
111
66
|
helperText: string;
|
|
112
|
-
hidden: boolean;
|
|
113
|
-
isError: boolean;
|
|
114
|
-
showHelper: boolean;
|
|
115
|
-
text: string;
|
|
116
67
|
};
|
|
117
68
|
export type AssistiveOptions = {
|
|
118
69
|
error?: ReadonlySignal<string | undefined>;
|
|
@@ -134,23 +85,27 @@ export type CheckableStateHandle = FieldControlBaseHandle & {
|
|
|
134
85
|
toggle: (event: Event) => void;
|
|
135
86
|
value: Signal<string>;
|
|
136
87
|
};
|
|
137
|
-
export type ChoiceFieldHandle
|
|
88
|
+
export type ChoiceFieldHandle = FieldControlBaseHandle & {
|
|
138
89
|
assistive: ReadonlySignal<AssistiveState>;
|
|
139
90
|
clear: () => void;
|
|
140
|
-
field: FormFieldHandle;
|
|
141
91
|
formValue: ReadonlySignal<string>;
|
|
142
|
-
isMultiple: ReadonlySignal<boolean>;
|
|
143
|
-
isSelected: (value: string) => boolean;
|
|
144
92
|
removeValue: (value: string) => void;
|
|
145
|
-
replaceSelectedItems: (items: T[]) => void;
|
|
146
|
-
selectedItems: Signal<T[]>;
|
|
147
93
|
selectedValues: ReadonlySignal<string[]>;
|
|
148
|
-
|
|
149
|
-
|
|
94
|
+
selectValue: (value: string) => void;
|
|
95
|
+
setValues: (values: string[]) => void;
|
|
96
|
+
toggleValue: (value: string) => void;
|
|
97
|
+
};
|
|
98
|
+
export declare const createFieldControlBase: <T = unknown>(options: {
|
|
99
|
+
context?: TextFieldControlContext;
|
|
100
|
+
name?: ReadonlySignal<string | undefined>;
|
|
101
|
+
prefix: string;
|
|
102
|
+
} & ControlContextOptions, fieldOptions: Omit<FormFieldOptions<T>, "disabled"> & {
|
|
103
|
+
disabled?: FormFieldOptions<T>["disabled"];
|
|
104
|
+
}) => {
|
|
105
|
+
base: Omit<FieldControlBaseHandle, "triggerValidation">;
|
|
106
|
+
triggerValidation: (on: FormControlValidationTrigger) => void;
|
|
150
107
|
};
|
|
151
108
|
export declare const createAssistiveState: (options: AssistiveOptions) => import("@vielzeug/stateit").ComputedSignal<AssistiveState>;
|
|
152
|
-
|
|
153
|
-
export declare const mountTextFieldLifecycle: (options: TextFieldLifecycleOptions) => void;
|
|
154
|
-
export declare const createChoiceFieldControl: <T>(options: ChoiceFieldOptions<T>) => ChoiceFieldHandle<T>;
|
|
155
|
-
export declare const createCheckableStateControl: (options: CheckableStateOptions) => CheckableStateHandle;
|
|
109
|
+
/** @internal */
|
|
110
|
+
export declare const mountTextFieldLifecycle: (options: TextFieldLifecycleOptions) => (() => void);
|
|
156
111
|
//# sourceMappingURL=field-control.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-control.d.ts","sourceRoot":"","sources":["../../src/controls/field-control.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"field-control.d.ts","sourceRoot":"","sources":["../../src/controls/field-control.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{listen as e}from"../runtime.js";import{createId as t}from"../internal.js";import{defineField as n}from"../form.js";import{createControlState as r}from"./internal/control-state.js";import{computed as i}from"@vielzeug/stateit";var a=(e,n)=>{let r=`${e}-${n&&n.trim()?n.trim():t().replace(/^cft-/,``)}`,i=`label-${r}`;return{errorId:`error-${r}`,fieldId:r,helperId:`helper-${r}`,labelInsetId:i,labelOutsideId:`${i}-outside`}},o=(e,t)=>{let i=r(e),o=a(e.prefix,e.name?.value),s={disabled:i.disabled,errorId:o.errorId,fieldId:o.fieldId,helperId:o.helperId,labelInsetId:o.labelInsetId,labelOutsideId:o.labelOutsideId},c=n({...t,disabled:t.disabled??s.disabled});return{base:s,triggerValidation:e=>i.triggerValidation(c,e)}},s=e=>i(()=>{let t=e.value?.value??``,n=e.error?.value??``,r=e.helper?.value??``,i=e.maxLength?.value,a=Number(i),o=Number.isFinite(a)&&a>0?a:null,s=o!==null,c=s?`${t.length} / ${o}`:``,l=s?t.length/o:0;return{counterAtLimit:s?l>=1:!1,counterNearLimit:s?l>=.9&&l<1:!1,counterText:c,errorText:n,hasCounter:s,helperText:r}}),c=t=>{let{element:n,onBlur:r,onChange:i,onInput:a,triggerValidation:o}=t,s=[];return a&&s.push(e(n,`input`,e=>{e.stopPropagation(),a(e,n.value)})),s.push(e(n,`change`,e=>{e.stopPropagation(),i?.(e,n.value),o?.(`change`)})),s.push(e(n,`blur`,e=>{r?.(e),o?.(`blur`)})),()=>{for(let e of s)e()}};export{s as createAssistiveState,o as createFieldControlBase,c as mountTextFieldLifecycle};
|
|
2
2
|
//# sourceMappingURL=field-control.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-control.js","names":[],"sources":["../../src/controls/field-control.ts"],"sourcesContent":["import { computed, isSignal, type ReadonlySignal, type Signal, signal } from '@vielzeug/stateit';\n\nimport { spread } from '../directives/spread';\nimport { defineField, type FormFieldHandle } from '../form';\nimport { createId, ref, type Directive } from '../internal';\nimport { effect, handle, onElement, watch } from '../runtime-lifecycle';\nimport {\n createControlState,\n type ControlContextOptions,\n type ControlValidationMode,\n type FormControlValidationTrigger,\n} from './internal/control-state';\n\nexport type { FormControlValidationTrigger } from './internal/control-state';\nexport { createValidationControl } from './internal/control-state';\nexport type { ValidationReporter } from './internal/control-state';\n\n// Discriminated union types for text vs checkable variants\nexport type TextFieldControlContext = {\n disabled?: ReadonlySignal<boolean | undefined>;\n validateOn?: ReadonlySignal<ControlValidationMode>;\n};\n\nexport type TextFieldOptions = Omit<ControlContextOptions, 'disabled' | 'validateOn'> & {\n autocomplete?: ReadonlySignal<string | undefined>;\n context?: TextFieldControlContext;\n disabled?: ReadonlySignal<boolean | undefined>;\n elementRef?: { value: HTMLInputElement | HTMLTextAreaElement | null };\n error?: ReadonlySignal<string | undefined>;\n helper?: ReadonlySignal<string | undefined>;\n inputmode?: ReadonlySignal<string | undefined>;\n label?: ReadonlySignal<string | undefined>;\n labelPlacement?: ReadonlySignal<'inset' | 'outside' | undefined>;\n maxLength?: ReadonlySignal<number | undefined>;\n minLength?: ReadonlySignal<number | undefined>;\n name?: ReadonlySignal<string | undefined>;\n onBlur?: (event: FocusEvent) => void;\n onChange?: (event: Event, value: string) => void;\n onInput?: (event: Event, value: string) => void;\n onInputExtra?: (event: Event) => void;\n onReset?: () => void;\n pattern?: ReadonlySignal<string | undefined>;\n placeholder?: ReadonlySignal<string | undefined>;\n prefix: string;\n readOnly?: ReadonlySignal<boolean | undefined>;\n required?: ReadonlySignal<boolean | undefined>;\n rows?: ReadonlySignal<number | undefined>;\n type?: ReadonlySignal<string | undefined> | (() => string | undefined) | string;\n validateOn?: ReadonlySignal<ControlValidationMode>;\n value: ReadonlySignal<string | undefined>;\n};\n\nexport type ChoiceFieldOptions<T> = {\n context?: TextFieldControlContext;\n disabled?: ReadonlySignal<boolean | undefined>;\n error?: ReadonlySignal<string | undefined>;\n getValue: (item: T) => string;\n helper?: ReadonlySignal<string | undefined>;\n label?: ReadonlySignal<string | undefined>;\n labelPlacement?: ReadonlySignal<'inset' | 'outside' | undefined>;\n mapControlledValue: (value: string) => T;\n multiple?: ReadonlySignal<boolean | undefined>;\n name?: ReadonlySignal<string | undefined>;\n onReset?: () => void;\n prefix: string;\n validateOn?: ReadonlySignal<ControlValidationMode>;\n value: ReadonlySignal<string | undefined>;\n};\n\nexport type CheckableStateOptions = ControlContextOptions & {\n checked: ReadonlySignal<boolean | undefined>;\n clearIndeterminateFirst?: boolean;\n error?: ReadonlySignal<string | undefined>;\n group?: { toggle: (value: string, originalEvent?: Event) => void };\n helper?: ReadonlySignal<string | undefined>;\n indeterminate?: ReadonlySignal<boolean | undefined>;\n label?: ReadonlySignal<string | undefined>;\n labelPlacement?: ReadonlySignal<'inset' | 'outside' | undefined>;\n name?: ReadonlySignal<string | undefined>;\n onReset?: () => void;\n onToggle?: (payload: CheckableChangePayload) => void;\n prefix: string;\n value: ReadonlySignal<string | undefined>;\n};\n\nexport type CheckableChangePayload = {\n checked: boolean;\n fieldValue: string;\n originalEvent?: Event;\n};\n\nexport type FieldControlBaseHandle = {\n disabled: ReadonlySignal<boolean>;\n errorId: string;\n field: FormFieldHandle;\n fieldId: string;\n helperId: string;\n labelInsetId: string;\n labelInsetRef: { value: HTMLLabelElement | null };\n labelOutsideId: string;\n labelOutsideRef: { value: HTMLLabelElement | null };\n triggerValidation: (on: FormControlValidationTrigger) => void;\n validateOn: ReadonlySignal<ControlValidationMode> | undefined;\n};\n\nexport type TextFieldHandle = FieldControlBaseHandle & {\n assistive: ReadonlySignal<AssistiveState>;\n attrs: Directive;\n clear: (event?: Event) => void;\n value: Signal<string>;\n};\n\nexport type AssistiveState = {\n counterAtLimit: boolean;\n counterNearLimit: boolean;\n counterText: string;\n errorText: string;\n hasCounter: boolean;\n hasError: boolean;\n hasHelper: boolean;\n helperText: string;\n hidden: boolean;\n isError: boolean;\n showHelper: boolean;\n text: string;\n};\n\nexport type AssistiveOptions = {\n error?: ReadonlySignal<string | undefined>;\n helper?: ReadonlySignal<string | undefined>;\n maxLength?: ReadonlySignal<number | undefined>;\n value?: ReadonlySignal<string | undefined>;\n};\n\nexport type TextFieldLifecycleOptions = {\n element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;\n onBlur?: (event: FocusEvent) => void;\n onChange?: (event: Event, value: string) => void;\n onInput?: (event: Event, value: string) => void;\n triggerValidation?: (on: FormControlValidationTrigger) => void;\n};\n\nexport type CheckableStateHandle = FieldControlBaseHandle & {\n assistive: ReadonlySignal<AssistiveState>;\n checked: Signal<boolean>;\n indeterminate: Signal<boolean>;\n toggle: (event: Event) => void;\n value: Signal<string>;\n};\n\nexport type ChoiceFieldHandle<T> = FieldControlBaseHandle & {\n assistive: ReadonlySignal<AssistiveState>;\n clear: () => void;\n field: FormFieldHandle;\n formValue: ReadonlySignal<string>;\n isMultiple: ReadonlySignal<boolean>;\n isSelected: (value: string) => boolean;\n removeValue: (value: string) => void;\n replaceSelectedItems: (items: T[]) => void;\n selectedItems: Signal<T[]>;\n selectedValues: ReadonlySignal<string[]>;\n selectItem: (item: T) => void;\n toggleItem: (item: T) => void;\n};\n\ntype ReactiveValue<T> = ReadonlySignal<T> | (() => T) | T;\n\n/**\n * Generates a stable set of ARIA-related IDs for a field control.\n * Snapshot `name` at call time — IDs are stable strings, not reactive.\n */\nconst createFieldIds = (prefix: string, name?: string | null) => {\n const normalizedName = name && name.trim() ? name.trim() : createId().replace(/^cft-/, '');\n const fieldId = `${prefix}-${normalizedName}`;\n const labelInsetId = `label-${fieldId}`;\n\n return {\n errorId: `error-${fieldId}`,\n fieldId,\n helperId: `helper-${fieldId}`,\n labelInsetId,\n labelOutsideId: `${labelInsetId}-outside`,\n };\n};\n\nconst createBaseFieldHandle = (\n options: {\n label?: ReadonlySignal<string | undefined>;\n labelPlacement?: ReadonlySignal<'inset' | 'outside' | undefined>;\n name?: ReadonlySignal<string | undefined>;\n prefix: string;\n } & ControlContextOptions,\n) => {\n const controlState = createControlState(options);\n const ids = createFieldIds(options.prefix, options.name?.value);\n const labelInsetRef = ref<HTMLLabelElement>();\n const labelOutsideRef = ref<HTMLLabelElement>();\n\n const syncLabels = () => {\n const placement = options.labelPlacement?.value ?? 'inset';\n const text = options.label?.value ?? '';\n\n if (labelInsetRef.value) {\n labelInsetRef.value.textContent = text;\n labelInsetRef.value.hidden = !text || placement !== 'inset';\n }\n\n if (labelOutsideRef.value) {\n labelOutsideRef.value.textContent = text;\n labelOutsideRef.value.hidden = !text || placement !== 'outside';\n }\n };\n\n effect(syncLabels);\n\n return {\n disabled: controlState.disabled,\n errorId: ids.errorId,\n fieldId: ids.fieldId,\n helperId: ids.helperId,\n labelInsetId: ids.labelInsetId,\n labelInsetRef,\n labelOutsideId: ids.labelOutsideId,\n labelOutsideRef,\n triggerValidation: (field: FormFieldHandle, on: FormControlValidationTrigger) =>\n controlState.triggerValidation(field, on),\n validateOn: controlState.validateOn,\n };\n};\n\nconst resolveControlContext = (options: {\n context?: TextFieldControlContext;\n disabled?: ReadonlySignal<boolean | undefined>;\n validateOn?: ReadonlySignal<ControlValidationMode>;\n}) => {\n return {\n disabled: computed(() => Boolean(options.disabled?.value) || Boolean(options.context?.disabled?.value)),\n validateOn: options.validateOn ?? options.context?.validateOn,\n };\n};\n\nexport const createAssistiveState = (options: AssistiveOptions) => {\n return computed<AssistiveState>(() => {\n const value = options.value?.value ?? '';\n const errorText = options.error?.value ?? '';\n const helperText = options.helper?.value ?? '';\n const hasError = Boolean(errorText);\n const hasHelper = Boolean(helperText);\n const text = errorText || helperText || '';\n const maxLength = options.maxLength?.value;\n const parsedMaxLength = Number(maxLength);\n const validMaxLength = Number.isFinite(parsedMaxLength) && parsedMaxLength > 0 ? parsedMaxLength : null;\n const hasCounter = validMaxLength !== null;\n const counterText = hasCounter ? `${value.length} / ${validMaxLength}` : '';\n const ratio = hasCounter ? value.length / validMaxLength : 0;\n\n return {\n counterAtLimit: hasCounter ? ratio >= 1 : false,\n counterNearLimit: hasCounter ? ratio >= 0.9 && ratio < 1 : false,\n counterText,\n errorText,\n hasCounter,\n hasError,\n hasHelper,\n helperText,\n hidden: !text,\n isError: hasError,\n showHelper: !hasError && hasHelper,\n text,\n };\n });\n};\n\nconst resolveReactiveValue = <T>(value: ReactiveValue<T> | undefined): T | undefined => {\n if (value === undefined) return undefined;\n\n if (isSignal(value)) return (value as ReadonlySignal<T>).value;\n\n if (typeof value === 'function') return (value as () => T)();\n\n return value;\n};\n\nconst optionalStringSource = (value: ReactiveValue<string | undefined> | undefined): (() => string | undefined) => {\n return () => {\n const next = resolveReactiveValue(value);\n\n if (next == null || next === '') return undefined;\n\n return String(next);\n };\n};\n\nconst optionalNumberSource = (value: ReactiveValue<number | undefined> | undefined): (() => number | undefined) => {\n return () => {\n const next = resolveReactiveValue(value);\n\n if (next == null || Number.isNaN(Number(next)) || Number(next) <= 0) return undefined;\n\n return Number(next);\n };\n};\n\nexport const createTextFieldControl = (options: TextFieldOptions): TextFieldHandle => {\n const value = signal('');\n const controlContext = resolveControlContext(options);\n const base = createBaseFieldHandle({\n ...options,\n ...controlContext,\n });\n\n watch(\n options.value,\n (next) => {\n value.value = String(next ?? '');\n },\n { immediate: true },\n );\n\n const field = defineField(\n {\n disabled: base.disabled,\n value,\n },\n {\n onReset: () => {\n value.value = '';\n options.onReset?.();\n },\n },\n );\n\n const assistive = createAssistiveState({\n error: options.error,\n helper: options.helper,\n maxLength: options.maxLength,\n value,\n });\n\n const clear = (event?: Event): void => {\n event?.preventDefault?.();\n\n value.value = '';\n options.onInput?.(event ?? new Event('input'), '');\n options.onChange?.(event ?? new Event('change'), '');\n base.triggerValidation(field, 'change');\n options.elementRef?.value?.focus();\n };\n\n if (options.elementRef) {\n onElement(options.elementRef, (element) => {\n mountTextFieldLifecycle({\n element,\n onBlur: options.onBlur,\n onChange: options.onChange,\n onInput: (event, nextValue) => {\n options.onInputExtra?.(event);\n options.onInput?.(event, nextValue);\n },\n triggerValidation: (on) => base.triggerValidation(field, on),\n });\n });\n }\n\n const attrs = spread({\n '?required': options.required,\n '.disabled': options.disabled,\n '.readOnly': options.readOnly,\n '.type': options.type,\n '.value': value,\n autocomplete: optionalStringSource(options.autocomplete),\n inputmode: optionalStringSource(options.inputmode),\n maxlength: optionalNumberSource(options.maxLength),\n minlength: optionalNumberSource(options.minLength),\n name: optionalStringSource(options.name),\n pattern: optionalStringSource(options.pattern),\n placeholder: optionalStringSource(options.placeholder),\n rows: optionalNumberSource(options.rows),\n });\n\n return {\n assistive,\n attrs,\n ...base,\n clear,\n field,\n triggerValidation: (on: FormControlValidationTrigger) => base.triggerValidation(field, on),\n value,\n };\n};\n\nexport const mountTextFieldLifecycle = (options: TextFieldLifecycleOptions): void => {\n const { element, onBlur, onChange, onInput, triggerValidation } = options;\n\n if (onInput) {\n handle(element, 'input', (event: Event) => {\n onInput(event, element.value);\n });\n }\n\n handle(element, 'change', (event: Event) => {\n onChange?.(event, element.value);\n triggerValidation?.('change');\n });\n\n handle(element, 'blur', (event: Event) => {\n onBlur?.(event as FocusEvent);\n triggerValidation?.('blur');\n });\n};\n\nconst parseChoiceFieldValues = (value: string | undefined): string[] => {\n if (!value) return [];\n\n return value\n .split(',')\n .map((entry) => entry.trim())\n .filter(Boolean);\n};\n\nexport const createChoiceFieldControl = <T>(options: ChoiceFieldOptions<T>): ChoiceFieldHandle<T> => {\n const controlContext = resolveControlContext(options);\n const base = createBaseFieldHandle({\n ...controlContext,\n label: options.label,\n labelPlacement: options.labelPlacement,\n name: options.name,\n prefix: options.prefix,\n });\n const selectedItems = signal<T[]>([]);\n const isMultiple = computed(() => Boolean(options.multiple?.value));\n const selectedValues = computed(() => selectedItems.value.map((item) => options.getValue(item)));\n const formValue = computed(() =>\n isMultiple.value ? selectedValues.value.join(',') : (selectedValues.value[0] ?? ''),\n );\n\n const normalizeSelectedItems = (items: T[]): T[] => {\n const normalized = isMultiple.value ? items : items.slice(0, 1);\n const uniqueItems: T[] = [];\n const seen = new Set<string>();\n\n for (const item of normalized) {\n const value = options.getValue(item);\n\n if (seen.has(value)) continue;\n\n seen.add(value);\n uniqueItems.push(item);\n }\n\n return uniqueItems;\n };\n\n const replaceSelectedItems = (items: T[]): void => {\n selectedItems.value = normalizeSelectedItems(items);\n };\n\n const clear = (): void => {\n replaceSelectedItems([]);\n };\n\n const removeValue = (value: string): void => {\n selectedItems.value = selectedItems.value.filter((item) => options.getValue(item) !== value);\n };\n\n const selectItem = (item: T): void => {\n if (isMultiple.value) {\n const value = options.getValue(item);\n\n if (selectedItems.value.some((current) => options.getValue(current) === value)) return;\n\n replaceSelectedItems([...selectedItems.value, item]);\n\n return;\n }\n\n replaceSelectedItems([item]);\n };\n\n const toggleItem = (item: T): void => {\n if (isMultiple.value) {\n const value = options.getValue(item);\n\n if (selectedItems.value.some((current) => options.getValue(current) === value)) {\n removeValue(value);\n\n return;\n }\n\n replaceSelectedItems([...selectedItems.value, item]);\n\n return;\n }\n\n replaceSelectedItems([item]);\n };\n\n const syncControlledValue = (nextValue: unknown): void => {\n const values = parseChoiceFieldValues(typeof nextValue === 'string' ? nextValue : String(nextValue ?? ''));\n\n replaceSelectedItems(values.map((value) => options.mapControlledValue(value)));\n };\n\n const field = defineField(\n {\n disabled: base.disabled,\n value: formValue,\n },\n {\n onReset: () => {\n clear();\n options.onReset?.();\n },\n },\n );\n\n const assistive = createAssistiveState({\n error: options.error,\n helper: options.helper,\n });\n\n watch(\n options.value,\n (next) => {\n syncControlledValue(next);\n },\n { immediate: true },\n );\n\n if (options.multiple) {\n watch(options.multiple, () => syncControlledValue(options.value.value));\n }\n\n return {\n ...base,\n assistive,\n clear,\n field,\n formValue,\n isMultiple,\n isSelected: (value: string) => selectedItems.value.some((item) => options.getValue(item) === value),\n removeValue,\n replaceSelectedItems,\n selectedItems,\n selectedValues,\n selectItem,\n toggleItem,\n triggerValidation: (on: FormControlValidationTrigger) => base.triggerValidation(field, on),\n };\n};\n\nexport const createCheckableStateControl = (options: CheckableStateOptions): CheckableStateHandle => {\n const value = signal('');\n const base = createBaseFieldHandle(options);\n const checked = signal(Boolean(options.checked.value));\n const indeterminate = signal(Boolean(options.indeterminate?.value));\n const assistive = createAssistiveState({ error: options.error, helper: options.helper });\n\n watch(\n options.checked,\n (next) => {\n checked.value = Boolean(next);\n },\n { immediate: true },\n );\n\n if (options.indeterminate) {\n watch(\n options.indeterminate,\n (next) => {\n indeterminate.value = Boolean(next);\n },\n { immediate: true },\n );\n }\n\n const field = defineField(\n {\n disabled: base.disabled,\n toFormValue: (next: string | null) => next,\n value: computed(() => (checked.value ? (options.value.value ?? '') : null)),\n },\n {\n onReset: () => {\n checked.value = Boolean(options.checked.value);\n indeterminate.value = Boolean(options.indeterminate?.value);\n options.onReset?.();\n },\n },\n );\n\n watch(\n options.value,\n (next) => {\n value.value = String(next ?? '');\n },\n { immediate: true },\n );\n\n const createPayload = (event: Event): CheckableChangePayload => ({\n checked: checked.value,\n fieldValue: options.value.value ?? '',\n originalEvent: event,\n });\n\n const toggle = (event: Event): void => {\n if (base.disabled.value) return;\n\n if (options.group) {\n indeterminate.value = false;\n options.group.toggle(options.value.value ?? '', event);\n options.onToggle?.(createPayload(event));\n\n return;\n }\n\n if (options.clearIndeterminateFirst && indeterminate.value) {\n indeterminate.value = false;\n } else {\n checked.value = !checked.value;\n indeterminate.value = false;\n }\n\n options.onToggle?.(createPayload(event));\n };\n\n return {\n ...base,\n assistive,\n checked,\n field,\n indeterminate,\n toggle,\n triggerValidation: (on: FormControlValidationTrigger) => base.triggerValidation(field, on),\n value,\n };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"field-control.js","names":[],"sources":["../../src/controls/field-control.ts"],"sourcesContent":["import { computed, type ReadonlySignal, type Signal } from '@vielzeug/stateit';\n\nimport { defineField, type FormFieldOptions } from '../form';\nimport { createId } from '../internal';\nimport { listen } from '../runtime';\nimport {\n createControlState,\n type ControlContextOptions,\n type ControlValidationMode,\n type FormControlValidationTrigger,\n} from './internal/control-state';\n\nexport type { FormControlValidationTrigger } from './internal/control-state';\nexport type { ValidationReporter } from './internal/control-state';\n\nexport type TextFieldControlContext = ControlContextOptions;\n\nexport type FieldBaseOptions = {\n context?: TextFieldControlContext;\n disabled?: ReadonlySignal<boolean | undefined>;\n error?: ReadonlySignal<string | undefined>;\n helper?: ReadonlySignal<string | undefined>;\n name?: ReadonlySignal<string | undefined>;\n prefix: string;\n validateOn?: ReadonlySignal<ControlValidationMode>;\n};\n\nexport type TextFieldOptions = FieldBaseOptions & {\n elementRef?: { value: HTMLInputElement | HTMLTextAreaElement | null };\n maxLength?: ReadonlySignal<number | undefined>;\n onBlur?: (event: FocusEvent) => void;\n onChange?: (event: Event, value: string) => void;\n onInput?: (event: Event, value: string) => void;\n onInputExtra?: (event: Event) => void;\n value: ReadonlySignal<string | undefined>;\n};\n\nexport type ChoiceFieldOptions = FieldBaseOptions & {\n multiple?: ReadonlySignal<boolean | undefined>;\n value: ReadonlySignal<string | undefined>;\n};\n\nexport type CheckableStateOptions = FieldBaseOptions & {\n checked: ReadonlySignal<boolean | undefined>;\n clearIndeterminateFirst?: boolean;\n group?: { toggle: (value: string, originalEvent?: Event) => void };\n indeterminate?: ReadonlySignal<boolean | undefined>;\n onToggle?: (payload: CheckableChangePayload) => void;\n value: ReadonlySignal<string | undefined>;\n};\n\nexport type CheckableChangePayload = {\n checked: boolean;\n originalEvent?: Event;\n value: string;\n};\n\nexport type FieldControlBaseHandle = {\n disabled: ReadonlySignal<boolean>;\n errorId: string;\n fieldId: string;\n helperId: string;\n labelInsetId: string;\n labelOutsideId: string;\n triggerValidation: (on: FormControlValidationTrigger) => void;\n};\n\nexport type TextFieldHandle = FieldControlBaseHandle & {\n assistive: ReadonlySignal<AssistiveState>;\n clear: (event?: Event) => void;\n value: Signal<string>;\n};\n\nexport type AssistiveState = {\n counterAtLimit: boolean;\n counterNearLimit: boolean;\n counterText: string;\n errorText: string;\n hasCounter: boolean;\n helperText: string;\n};\n\nexport type AssistiveOptions = {\n error?: ReadonlySignal<string | undefined>;\n helper?: ReadonlySignal<string | undefined>;\n maxLength?: ReadonlySignal<number | undefined>;\n value?: ReadonlySignal<string | undefined>;\n};\n\nexport type TextFieldLifecycleOptions = {\n element: HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;\n onBlur?: (event: FocusEvent) => void;\n onChange?: (event: Event, value: string) => void;\n onInput?: (event: Event, value: string) => void;\n triggerValidation?: (on: FormControlValidationTrigger) => void;\n};\n\nexport type CheckableStateHandle = FieldControlBaseHandle & {\n assistive: ReadonlySignal<AssistiveState>;\n checked: Signal<boolean>;\n indeterminate: Signal<boolean>;\n toggle: (event: Event) => void;\n value: Signal<string>;\n};\n\nexport type ChoiceFieldHandle = FieldControlBaseHandle & {\n assistive: ReadonlySignal<AssistiveState>;\n clear: () => void;\n formValue: ReadonlySignal<string>;\n removeValue: (value: string) => void;\n selectedValues: ReadonlySignal<string[]>;\n selectValue: (value: string) => void;\n setValues: (values: string[]) => void;\n toggleValue: (value: string) => void;\n};\n\n/**\n * Generates a stable set of ARIA-related IDs for a field control.\n * Snapshot `name` at call time — IDs are stable strings, not reactive.\n */\nconst createFieldIds = (prefix: string, name?: string | null) => {\n const normalizedName = name && name.trim() ? name.trim() : createId().replace(/^cft-/, '');\n const fieldId = `${prefix}-${normalizedName}`;\n const labelInsetId = `label-${fieldId}`;\n\n return {\n errorId: `error-${fieldId}`,\n fieldId,\n helperId: `helper-${fieldId}`,\n labelInsetId,\n labelOutsideId: `${labelInsetId}-outside`,\n };\n};\n\nexport const createFieldControlBase = <T = unknown>(\n options: {\n context?: TextFieldControlContext;\n name?: ReadonlySignal<string | undefined>;\n prefix: string;\n } & ControlContextOptions,\n fieldOptions: Omit<FormFieldOptions<T>, 'disabled'> & {\n disabled?: FormFieldOptions<T>['disabled'];\n },\n): {\n base: Omit<FieldControlBaseHandle, 'triggerValidation'>;\n triggerValidation: (on: FormControlValidationTrigger) => void;\n} => {\n const controlState = createControlState(options);\n const ids = createFieldIds(options.prefix, options.name?.value);\n\n const base: Omit<FieldControlBaseHandle, 'triggerValidation'> = {\n disabled: controlState.disabled,\n errorId: ids.errorId,\n fieldId: ids.fieldId,\n helperId: ids.helperId,\n labelInsetId: ids.labelInsetId,\n labelOutsideId: ids.labelOutsideId,\n };\n\n const field = defineField<T>({\n ...fieldOptions,\n disabled: fieldOptions.disabled ?? base.disabled,\n });\n\n return {\n base,\n triggerValidation: (on) => controlState.triggerValidation(field, on),\n };\n};\n\nexport const createAssistiveState = (options: AssistiveOptions) => {\n return computed<AssistiveState>(() => {\n const value = options.value?.value ?? '';\n const errorText = options.error?.value ?? '';\n const helperText = options.helper?.value ?? '';\n const maxLength = options.maxLength?.value;\n const parsedMaxLength = Number(maxLength);\n const validMaxLength = Number.isFinite(parsedMaxLength) && parsedMaxLength > 0 ? parsedMaxLength : null;\n const hasCounter = validMaxLength !== null;\n const counterText = hasCounter ? `${value.length} / ${validMaxLength}` : '';\n const ratio = hasCounter ? value.length / validMaxLength : 0;\n\n return {\n counterAtLimit: hasCounter ? ratio >= 1 : false,\n counterNearLimit: hasCounter ? ratio >= 0.9 && ratio < 1 : false,\n counterText,\n errorText,\n hasCounter,\n helperText,\n };\n });\n};\n\n/** @internal */\nexport const mountTextFieldLifecycle = (options: TextFieldLifecycleOptions): (() => void) => {\n const { element, onBlur, onChange, onInput, triggerValidation } = options;\n const disposers: Array<() => void> = [];\n\n if (onInput) {\n disposers.push(\n listen(element, 'input', (event: Event) => {\n // Prevent the native composed event from bubbling out of the shadow DOM\n // and being re-targeted onto the host element. The component emits its\n // own structured CustomEvent so external listeners never need the raw one.\n event.stopPropagation();\n onInput(event, element.value);\n }),\n );\n }\n\n disposers.push(\n listen(element, 'change', (event: Event) => {\n // Same reason as above — suppress the native change event from escaping.\n event.stopPropagation();\n onChange?.(event, element.value);\n triggerValidation?.('change');\n }),\n );\n\n disposers.push(\n listen(element, 'blur', (event: Event) => {\n onBlur?.(event as FocusEvent);\n triggerValidation?.('blur');\n }),\n );\n\n return () => {\n for (const dispose of disposers) dispose();\n };\n};\n"],"mappings":"wOAwHA,IAAM,GAAkB,EAAgB,IAAyB,CAE/D,IAAM,EAAU,GAAG,EAAO,GADH,GAAQ,EAAK,KAAK,EAAI,EAAK,KAAK,EAAI,EAAS,EAAE,QAAQ,QAAS,EAAE,IAEnF,EAAe,SAAS,IAE9B,MAAO,CACL,QAAS,SAAS,IAClB,UACA,SAAU,UAAU,IACpB,eACA,eAAgB,GAAG,EAAa,SAClC,CACF,EAEa,GACX,EAKA,IAMG,CACH,IAAM,EAAe,EAAmB,CAAO,EACzC,EAAM,EAAe,EAAQ,OAAQ,EAAQ,MAAM,KAAK,EAExD,EAA0D,CAC9D,SAAU,EAAa,SACvB,QAAS,EAAI,QACb,QAAS,EAAI,QACb,SAAU,EAAI,SACd,aAAc,EAAI,aAClB,eAAgB,EAAI,cACtB,EAEM,EAAQ,EAAe,CAC3B,GAAG,EACH,SAAU,EAAa,UAAY,EAAK,QAC1C,CAAC,EAED,MAAO,CACL,OACA,kBAAoB,GAAO,EAAa,kBAAkB,EAAO,CAAE,CACrE,CACF,EAEa,EAAwB,GAC5B,MAA+B,CACpC,IAAM,EAAQ,EAAQ,OAAO,OAAS,GAChC,EAAY,EAAQ,OAAO,OAAS,GACpC,EAAa,EAAQ,QAAQ,OAAS,GACtC,EAAY,EAAQ,WAAW,MAC/B,EAAkB,OAAO,CAAS,EAClC,EAAiB,OAAO,SAAS,CAAe,GAAK,EAAkB,EAAI,EAAkB,KAC7F,EAAa,IAAmB,KAChC,EAAc,EAAa,GAAG,EAAM,OAAO,KAAK,IAAmB,GACnE,EAAQ,EAAa,EAAM,OAAS,EAAiB,EAE3D,MAAO,CACL,eAAgB,EAAa,GAAS,EAAI,GAC1C,iBAAkB,EAAa,GAAS,IAAO,EAAQ,EAAI,GAC3D,cACA,YACA,aACA,YACF,CACF,CAAC,EAIU,EAA2B,GAAqD,CAC3F,GAAM,CAAE,UAAS,SAAQ,WAAU,UAAS,qBAAsB,EAC5D,EAA+B,CAAC,EA8BtC,OA5BI,GACF,EAAU,KACR,EAAO,EAAS,QAAU,GAAiB,CAIzC,EAAM,gBAAgB,EACtB,EAAQ,EAAO,EAAQ,KAAK,CAC9B,CAAC,CACH,EAGF,EAAU,KACR,EAAO,EAAS,SAAW,GAAiB,CAE1C,EAAM,gBAAgB,EACtB,IAAW,EAAO,EAAQ,KAAK,EAC/B,IAAoB,QAAQ,CAC9B,CAAC,CACH,EAEA,EAAU,KACR,EAAO,EAAS,OAAS,GAAiB,CACxC,IAAS,CAAmB,EAC5B,IAAoB,MAAM,CAC5B,CAAC,CACH,MAEa,CACX,IAAK,IAAM,KAAW,EAAW,EAAQ,CAC3C,CACF"}
|
package/dist/controls/index.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
export { createCheckableFieldControl
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
6
|
-
export {
|
|
7
|
-
export { createOverlayControl, type OverlayCloseReason, type
|
|
8
|
-
export { createSpinnerControl
|
|
9
|
-
export { createSliderControl
|
|
1
|
+
export { createCheckableFieldControl } from './checkable-control';
|
|
2
|
+
export { type CheckableChangePayload } from './field-control';
|
|
3
|
+
export { createTextField } from './text-field-control';
|
|
4
|
+
export { createChoiceField } from './choice-field-control';
|
|
5
|
+
export { createListControl } from './list-control';
|
|
6
|
+
export { createPressControl } from './press-control';
|
|
7
|
+
export { createOverlayControl, type OverlayCloseReason, type OverlayOpenReason, type OverlayCloseDetail, type OverlayOpenDetail, } from './overlay-control';
|
|
8
|
+
export { createSpinnerControl } from './spinner-control';
|
|
9
|
+
export { createSliderControl } from './slider-control';
|
|
10
|
+
export { createSwipeControl, type SwipeAxis, type SwipeControl, type SwipeControlDetail } from './swipe-control';
|
|
11
|
+
export { createPopupListControl } from './popup-list-control';
|
|
10
12
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/controls/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/controls/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAElE,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EACL,oBAAoB,EACpB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACjH,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
let e=require(`@vielzeug/stateit`);var t=
|
|
1
|
+
let e=require(`@vielzeug/stateit`);var t=t=>{let n=(0,e.computed)(()=>!!t.disabled?.value||!!t.context?.disabled?.value),r=t.validateOn??t.context?.validateOn;return{disabled:n,triggerValidation:(e,t)=>{r?.value===t&&e.reportValidity()},validateOn:r}};exports.createControlState=t;
|
|
2
2
|
//# sourceMappingURL=control-state.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-state.cjs","names":[],"sources":["../../../src/controls/internal/control-state.ts"],"sourcesContent":["import { computed, type ReadonlySignal } from '@vielzeug/stateit';\n\nexport type FormControlValidationTrigger = 'blur' | 'change';\n\nexport type ControlValidationMode = 'blur' | 'change' | 'submit' | undefined;\n\nexport type ValidationReporter = {\n reportValidity: () => void;\n};\n\nexport type ControlContextOptions = {\n disabled?: ReadonlySignal<boolean | undefined>;\n validateOn?: ReadonlySignal<ControlValidationMode>;\n};\n\
|
|
1
|
+
{"version":3,"file":"control-state.cjs","names":[],"sources":["../../../src/controls/internal/control-state.ts"],"sourcesContent":["import { computed, type ReadonlySignal } from '@vielzeug/stateit';\n\nexport type FormControlValidationTrigger = 'blur' | 'change';\n\nexport type ControlValidationMode = 'blur' | 'change' | 'submit' | undefined;\n\nexport type ValidationReporter = {\n reportValidity: () => void;\n};\n\nexport type ControlContextOptions = {\n disabled?: ReadonlySignal<boolean | undefined>;\n validateOn?: ReadonlySignal<ControlValidationMode>;\n};\n\nexport type ControlStateOptions = {\n context?: ControlContextOptions;\n disabled?: ReadonlySignal<boolean | undefined>;\n validateOn?: ReadonlySignal<ControlValidationMode>;\n};\n\nexport const createControlState = (options: ControlStateOptions) => {\n const disabled = computed(() => Boolean(options.disabled?.value) || Boolean(options.context?.disabled?.value));\n\n const validateOn = options.validateOn ?? options.context?.validateOn;\n\n return {\n disabled,\n triggerValidation: (field: ValidationReporter, on: FormControlValidationTrigger): void => {\n if (validateOn?.value === on) field.reportValidity();\n },\n validateOn,\n };\n};\n"],"mappings":"mCAqBA,IAAa,EAAsB,GAAiC,CAClE,IAAM,GAAA,EAAA,EAAA,cAA0B,EAAQ,EAAQ,UAAU,OAAU,EAAQ,EAAQ,SAAS,UAAU,KAAM,EAEvG,EAAa,EAAQ,YAAc,EAAQ,SAAS,WAE1D,MAAO,CACL,WACA,mBAAoB,EAA2B,IAA2C,CACpF,GAAY,QAAU,GAAI,EAAM,eAAe,CACrD,EACA,YACF,CACF"}
|
|
@@ -8,12 +8,14 @@ export type ControlContextOptions = {
|
|
|
8
8
|
disabled?: ReadonlySignal<boolean | undefined>;
|
|
9
9
|
validateOn?: ReadonlySignal<ControlValidationMode>;
|
|
10
10
|
};
|
|
11
|
-
export
|
|
11
|
+
export type ControlStateOptions = {
|
|
12
|
+
context?: ControlContextOptions;
|
|
13
|
+
disabled?: ReadonlySignal<boolean | undefined>;
|
|
14
|
+
validateOn?: ReadonlySignal<ControlValidationMode>;
|
|
15
|
+
};
|
|
16
|
+
export declare const createControlState: (options: ControlStateOptions) => {
|
|
12
17
|
disabled: import("@vielzeug/stateit").ComputedSignal<boolean>;
|
|
13
18
|
triggerValidation: (field: ValidationReporter, on: FormControlValidationTrigger) => void;
|
|
14
19
|
validateOn: ReadonlySignal<ControlValidationMode> | undefined;
|
|
15
20
|
};
|
|
16
|
-
export declare const createValidationControl: (validateOn: ReadonlySignal<ControlValidationMode> | undefined, field: ValidationReporter) => {
|
|
17
|
-
triggerValidation: (on: FormControlValidationTrigger) => void;
|
|
18
|
-
};
|
|
19
21
|
//# sourceMappingURL=control-state.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-state.d.ts","sourceRoot":"","sources":["../../../src/controls/internal/control-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAElE,MAAM,MAAM,4BAA4B,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7D,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE7E,MAAM,MAAM,kBAAkB,GAAG;IAC/B,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,EAAE,cAAc,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;IAC/C,UAAU,CAAC,EAAE,cAAc,CAAC,qBAAqB,CAAC,CAAC;CACpD,CAAC;
|
|
1
|
+
{"version":3,"file":"control-state.d.ts","sourceRoot":"","sources":["../../../src/controls/internal/control-state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAElE,MAAM,MAAM,4BAA4B,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7D,MAAM,MAAM,qBAAqB,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAE7E,MAAM,MAAM,kBAAkB,GAAG;IAC/B,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,CAAC,EAAE,cAAc,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;IAC/C,UAAU,CAAC,EAAE,cAAc,CAAC,qBAAqB,CAAC,CAAC;CACpD,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,CAAC,EAAE,qBAAqB,CAAC;IAChC,QAAQ,CAAC,EAAE,cAAc,CAAC,OAAO,GAAG,SAAS,CAAC,CAAC;IAC/C,UAAU,CAAC,EAAE,cAAc,CAAC,qBAAqB,CAAC,CAAC;CACpD,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,SAAS,mBAAmB;;+BAOhC,kBAAkB,MAAM,4BAA4B,KAAG,IAAI;;CAKzF,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{computed as e}from"@vielzeug/stateit";var t=
|
|
1
|
+
import{computed as e}from"@vielzeug/stateit";var t=t=>{let n=e(()=>!!t.disabled?.value||!!t.context?.disabled?.value),r=t.validateOn??t.context?.validateOn;return{disabled:n,triggerValidation:(e,t)=>{r?.value===t&&e.reportValidity()},validateOn:r}};export{t as createControlState};
|
|
2
2
|
//# sourceMappingURL=control-state.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-state.js","names":[],"sources":["../../../src/controls/internal/control-state.ts"],"sourcesContent":["import { computed, type ReadonlySignal } from '@vielzeug/stateit';\n\nexport type FormControlValidationTrigger = 'blur' | 'change';\n\nexport type ControlValidationMode = 'blur' | 'change' | 'submit' | undefined;\n\nexport type ValidationReporter = {\n reportValidity: () => void;\n};\n\nexport type ControlContextOptions = {\n disabled?: ReadonlySignal<boolean | undefined>;\n validateOn?: ReadonlySignal<ControlValidationMode>;\n};\n\
|
|
1
|
+
{"version":3,"file":"control-state.js","names":[],"sources":["../../../src/controls/internal/control-state.ts"],"sourcesContent":["import { computed, type ReadonlySignal } from '@vielzeug/stateit';\n\nexport type FormControlValidationTrigger = 'blur' | 'change';\n\nexport type ControlValidationMode = 'blur' | 'change' | 'submit' | undefined;\n\nexport type ValidationReporter = {\n reportValidity: () => void;\n};\n\nexport type ControlContextOptions = {\n disabled?: ReadonlySignal<boolean | undefined>;\n validateOn?: ReadonlySignal<ControlValidationMode>;\n};\n\nexport type ControlStateOptions = {\n context?: ControlContextOptions;\n disabled?: ReadonlySignal<boolean | undefined>;\n validateOn?: ReadonlySignal<ControlValidationMode>;\n};\n\nexport const createControlState = (options: ControlStateOptions) => {\n const disabled = computed(() => Boolean(options.disabled?.value) || Boolean(options.context?.disabled?.value));\n\n const validateOn = options.validateOn ?? options.context?.validateOn;\n\n return {\n disabled,\n triggerValidation: (field: ValidationReporter, on: FormControlValidationTrigger): void => {\n if (validateOn?.value === on) field.reportValidity();\n },\n validateOn,\n };\n};\n"],"mappings":"6CAqBA,IAAa,EAAsB,GAAiC,CAClE,IAAM,EAAW,MAAe,EAAQ,EAAQ,UAAU,OAAU,EAAQ,EAAQ,SAAS,UAAU,KAAM,EAEvG,EAAa,EAAQ,YAAc,EAAQ,SAAS,WAE1D,MAAO,CACL,WACA,mBAAoB,EAA2B,IAA2C,CACpF,GAAY,QAAU,GAAI,EAAM,eAAe,CACrD,EACA,YACF,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyboard-utils.cjs","names":[],"sources":["../../../src/controls/internal/keyboard-utils.ts"],"sourcesContent":["export type KeyboardDispatchOptions = {\n disabled?: () => boolean;\n keymap: Record<string, (event: KeyboardEvent) => boolean | void>;\n preventDefault?: 'after' | 'before' | false;\n};\n\nexport const dispatchKeyboardAction = (event: KeyboardEvent, options: KeyboardDispatchOptions): boolean => {\n if (options.disabled?.()) return false;\n\n const action = options.keymap[event.key];\n\n if (!action) return false;\n\n const preventDefaultMode = options.preventDefault ?? 'before';\n\n if (preventDefaultMode === 'before') event.preventDefault();\n\n const handled = action(event) !== false;\n\n if (preventDefaultMode === 'after' && handled) event.preventDefault();\n\n return handled;\n};\n"],"mappings":"AAMA,IAAa,GAA0B,EAAsB,IAA8C,CACzG,GAAI,EAAQ,
|
|
1
|
+
{"version":3,"file":"keyboard-utils.cjs","names":[],"sources":["../../../src/controls/internal/keyboard-utils.ts"],"sourcesContent":["export type KeyboardDispatchOptions = {\n disabled?: () => boolean;\n keymap: Record<string, (event: KeyboardEvent) => boolean | void>;\n preventDefault?: 'after' | 'before' | false;\n};\n\nexport const dispatchKeyboardAction = (event: KeyboardEvent, options: KeyboardDispatchOptions): boolean => {\n if (options.disabled?.()) return false;\n\n const action = options.keymap[event.key];\n\n if (!action) return false;\n\n const preventDefaultMode = options.preventDefault ?? 'before';\n\n if (preventDefaultMode === 'before') event.preventDefault();\n\n const handled = action(event) !== false;\n\n if (preventDefaultMode === 'after' && handled) event.preventDefault();\n\n return handled;\n};\n"],"mappings":"AAMA,IAAa,GAA0B,EAAsB,IAA8C,CACzG,GAAI,EAAQ,WAAW,EAAG,MAAO,GAEjC,IAAM,EAAS,EAAQ,OAAO,EAAM,KAEpC,GAAI,CAAC,EAAQ,MAAO,GAEpB,IAAM,EAAqB,EAAQ,gBAAkB,SAEjD,IAAuB,UAAU,EAAM,eAAe,EAE1D,IAAM,EAAU,EAAO,CAAK,IAAM,GAIlC,OAFI,IAAuB,SAAW,GAAS,EAAM,eAAe,EAE7D,CACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyboard-utils.js","names":[],"sources":["../../../src/controls/internal/keyboard-utils.ts"],"sourcesContent":["export type KeyboardDispatchOptions = {\n disabled?: () => boolean;\n keymap: Record<string, (event: KeyboardEvent) => boolean | void>;\n preventDefault?: 'after' | 'before' | false;\n};\n\nexport const dispatchKeyboardAction = (event: KeyboardEvent, options: KeyboardDispatchOptions): boolean => {\n if (options.disabled?.()) return false;\n\n const action = options.keymap[event.key];\n\n if (!action) return false;\n\n const preventDefaultMode = options.preventDefault ?? 'before';\n\n if (preventDefaultMode === 'before') event.preventDefault();\n\n const handled = action(event) !== false;\n\n if (preventDefaultMode === 'after' && handled) event.preventDefault();\n\n return handled;\n};\n"],"mappings":"AAMA,IAAa,GAA0B,EAAsB,IAA8C,CACzG,GAAI,EAAQ,
|
|
1
|
+
{"version":3,"file":"keyboard-utils.js","names":[],"sources":["../../../src/controls/internal/keyboard-utils.ts"],"sourcesContent":["export type KeyboardDispatchOptions = {\n disabled?: () => boolean;\n keymap: Record<string, (event: KeyboardEvent) => boolean | void>;\n preventDefault?: 'after' | 'before' | false;\n};\n\nexport const dispatchKeyboardAction = (event: KeyboardEvent, options: KeyboardDispatchOptions): boolean => {\n if (options.disabled?.()) return false;\n\n const action = options.keymap[event.key];\n\n if (!action) return false;\n\n const preventDefaultMode = options.preventDefault ?? 'before';\n\n if (preventDefaultMode === 'before') event.preventDefault();\n\n const handled = action(event) !== false;\n\n if (preventDefaultMode === 'after' && handled) event.preventDefault();\n\n return handled;\n};\n"],"mappings":"AAMA,IAAa,GAA0B,EAAsB,IAA8C,CACzG,GAAI,EAAQ,WAAW,EAAG,MAAO,GAEjC,IAAM,EAAS,EAAQ,OAAO,EAAM,KAEpC,GAAI,CAAC,EAAQ,MAAO,GAEpB,IAAM,EAAqB,EAAQ,gBAAkB,SAEjD,IAAuB,UAAU,EAAM,eAAe,EAE1D,IAAM,EAAU,EAAO,CAAK,IAAM,GAIlC,OAFI,IAAuB,SAAW,GAAS,EAAM,eAAe,EAE7D,CACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-utils.cjs","names":[],"sources":["../../../src/controls/internal/number-utils.ts"],"sourcesContent":["export const toFiniteNumber = (value: unknown): number | undefined => {\n const parsed = Number(value);\n\n return Number.isFinite(parsed) ? parsed : undefined;\n};\n\nexport const toFiniteNumberOr = (value: unknown, fallback: number): number => {\n return toFiniteNumber(value) ?? fallback;\n};\n\nexport const toPositiveStep = (value: unknown, fallback: number): number => {\n return Math.abs(toFiniteNumberOr(value, fallback)) || fallback;\n};\n\nexport const normalizeFinite = (value: number, fallback: number): number => {\n return Number.isFinite(value) ? value : fallback;\n};\n\nexport const clampNumber = (value: number, min?: number, max?: number): number => {\n if (min != null && value < min) return min;\n\n if (max != null && value > max) return max;\n\n return value;\n};\n"],"mappings":"AAAA,IAAa,EAAkB,GAAuC,CACpE,IAAM,EAAS,OAAO,
|
|
1
|
+
{"version":3,"file":"number-utils.cjs","names":[],"sources":["../../../src/controls/internal/number-utils.ts"],"sourcesContent":["export const toFiniteNumber = (value: unknown): number | undefined => {\n const parsed = Number(value);\n\n return Number.isFinite(parsed) ? parsed : undefined;\n};\n\nexport const toFiniteNumberOr = (value: unknown, fallback: number): number => {\n return toFiniteNumber(value) ?? fallback;\n};\n\nexport const toPositiveStep = (value: unknown, fallback: number): number => {\n return Math.abs(toFiniteNumberOr(value, fallback)) || fallback;\n};\n\nexport const normalizeFinite = (value: number, fallback: number): number => {\n return Number.isFinite(value) ? value : fallback;\n};\n\nexport const clampNumber = (value: number, min?: number, max?: number): number => {\n if (min != null && value < min) return min;\n\n if (max != null && value > max) return max;\n\n return value;\n};\n"],"mappings":"AAAA,IAAa,EAAkB,GAAuC,CACpE,IAAM,EAAS,OAAO,CAAK,EAE3B,OAAO,OAAO,SAAS,CAAM,EAAI,EAAS,IAAA,EAC5C,EAEa,GAAoB,EAAgB,IACxC,EAAe,CAAK,GAAK,EAGrB,GAAkB,EAAgB,IACtC,KAAK,IAAI,EAAiB,EAAO,CAAQ,CAAC,GAAK,EAG3C,GAAmB,EAAe,IACtC,OAAO,SAAS,CAAK,EAAI,EAAQ,EAG7B,GAAe,EAAe,EAAc,IACnD,GAAO,MAAQ,EAAQ,EAAY,EAEnC,GAAO,MAAQ,EAAQ,EAAY,EAEhC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"number-utils.js","names":[],"sources":["../../../src/controls/internal/number-utils.ts"],"sourcesContent":["export const toFiniteNumber = (value: unknown): number | undefined => {\n const parsed = Number(value);\n\n return Number.isFinite(parsed) ? parsed : undefined;\n};\n\nexport const toFiniteNumberOr = (value: unknown, fallback: number): number => {\n return toFiniteNumber(value) ?? fallback;\n};\n\nexport const toPositiveStep = (value: unknown, fallback: number): number => {\n return Math.abs(toFiniteNumberOr(value, fallback)) || fallback;\n};\n\nexport const normalizeFinite = (value: number, fallback: number): number => {\n return Number.isFinite(value) ? value : fallback;\n};\n\nexport const clampNumber = (value: number, min?: number, max?: number): number => {\n if (min != null && value < min) return min;\n\n if (max != null && value > max) return max;\n\n return value;\n};\n"],"mappings":"AAAA,IAAa,EAAkB,GAAuC,CACpE,IAAM,EAAS,OAAO,
|
|
1
|
+
{"version":3,"file":"number-utils.js","names":[],"sources":["../../../src/controls/internal/number-utils.ts"],"sourcesContent":["export const toFiniteNumber = (value: unknown): number | undefined => {\n const parsed = Number(value);\n\n return Number.isFinite(parsed) ? parsed : undefined;\n};\n\nexport const toFiniteNumberOr = (value: unknown, fallback: number): number => {\n return toFiniteNumber(value) ?? fallback;\n};\n\nexport const toPositiveStep = (value: unknown, fallback: number): number => {\n return Math.abs(toFiniteNumberOr(value, fallback)) || fallback;\n};\n\nexport const normalizeFinite = (value: number, fallback: number): number => {\n return Number.isFinite(value) ? value : fallback;\n};\n\nexport const clampNumber = (value: number, min?: number, max?: number): number => {\n if (min != null && value < min) return min;\n\n if (max != null && value > max) return max;\n\n return value;\n};\n"],"mappings":"AAAA,IAAa,EAAkB,GAAuC,CACpE,IAAM,EAAS,OAAO,CAAK,EAE3B,OAAO,OAAO,SAAS,CAAM,EAAI,EAAS,IAAA,EAC5C,EAEa,GAAoB,EAAgB,IACxC,EAAe,CAAK,GAAK,EAGrB,GAAkB,EAAgB,IACtC,KAAK,IAAI,EAAiB,EAAO,CAAQ,CAAC,GAAK,EAG3C,GAAmB,EAAe,IACtC,OAAO,SAAS,CAAK,EAAI,EAAQ,EAG7B,GAAe,EAAe,EAAc,IACnD,GAAO,MAAQ,EAAQ,EAAY,EAEnC,GAAO,MAAQ,EAAQ,EAAY,EAEhC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation-utils.cjs","names":[],"sources":["../../../src/controls/internal/validation-utils.ts"],"sourcesContent":["/**\n * Shared validation utilities for control factories.\n * Only genuinely useful abstractions - trivial wrappers removed.\n */\n\n/**\n * Find index of first item matching predicate (forward scan).\n */\nexport const findForward = <T>(items: T[], start: number, predicate: (item: T, index: number) => boolean): number => {\n for (let idx = start; idx < items.length; idx++) {\n if (predicate(items[idx], idx)) return idx;\n }\n\n return -1;\n};\n\n/**\n * Find index of first item matching predicate (backward scan).\n */\nexport const findBackward = <T>(items: T[], start: number, predicate: (item: T, index: number) => boolean): number => {\n for (let idx = start; idx >= 0; idx--) {\n if (predicate(items[idx], idx)) return idx;\n }\n\n return -1;\n};\n"],"mappings":"AAQA,IAAa,GAAkB,EAAY,EAAe,IAA2D,CACnH,IAAK,IAAI,EAAM,EAAO,EAAM,EAAM,OAAQ,IACxC,GAAI,EAAU,EAAM,GAAM,
|
|
1
|
+
{"version":3,"file":"validation-utils.cjs","names":[],"sources":["../../../src/controls/internal/validation-utils.ts"],"sourcesContent":["/**\n * Shared validation utilities for control factories.\n * Only genuinely useful abstractions - trivial wrappers removed.\n */\n\n/**\n * Find index of first item matching predicate (forward scan).\n */\nexport const findForward = <T>(items: T[], start: number, predicate: (item: T, index: number) => boolean): number => {\n for (let idx = start; idx < items.length; idx++) {\n if (predicate(items[idx], idx)) return idx;\n }\n\n return -1;\n};\n\n/**\n * Find index of first item matching predicate (backward scan).\n */\nexport const findBackward = <T>(items: T[], start: number, predicate: (item: T, index: number) => boolean): number => {\n for (let idx = start; idx >= 0; idx--) {\n if (predicate(items[idx], idx)) return idx;\n }\n\n return -1;\n};\n"],"mappings":"AAQA,IAAa,GAAkB,EAAY,EAAe,IAA2D,CACnH,IAAK,IAAI,EAAM,EAAO,EAAM,EAAM,OAAQ,IACxC,GAAI,EAAU,EAAM,GAAM,CAAG,EAAG,OAAO,EAGzC,MAAO,EACT,EAKa,GAAmB,EAAY,EAAe,IAA2D,CACpH,IAAK,IAAI,EAAM,EAAO,GAAO,EAAG,IAC9B,GAAI,EAAU,EAAM,GAAM,CAAG,EAAG,OAAO,EAGzC,MAAO,EACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation-utils.js","names":[],"sources":["../../../src/controls/internal/validation-utils.ts"],"sourcesContent":["/**\n * Shared validation utilities for control factories.\n * Only genuinely useful abstractions - trivial wrappers removed.\n */\n\n/**\n * Find index of first item matching predicate (forward scan).\n */\nexport const findForward = <T>(items: T[], start: number, predicate: (item: T, index: number) => boolean): number => {\n for (let idx = start; idx < items.length; idx++) {\n if (predicate(items[idx], idx)) return idx;\n }\n\n return -1;\n};\n\n/**\n * Find index of first item matching predicate (backward scan).\n */\nexport const findBackward = <T>(items: T[], start: number, predicate: (item: T, index: number) => boolean): number => {\n for (let idx = start; idx >= 0; idx--) {\n if (predicate(items[idx], idx)) return idx;\n }\n\n return -1;\n};\n"],"mappings":"AAQA,IAAa,GAAkB,EAAY,EAAe,IAA2D,CACnH,IAAK,IAAI,EAAM,EAAO,EAAM,EAAM,OAAQ,IACxC,GAAI,EAAU,EAAM,GAAM,
|
|
1
|
+
{"version":3,"file":"validation-utils.js","names":[],"sources":["../../../src/controls/internal/validation-utils.ts"],"sourcesContent":["/**\n * Shared validation utilities for control factories.\n * Only genuinely useful abstractions - trivial wrappers removed.\n */\n\n/**\n * Find index of first item matching predicate (forward scan).\n */\nexport const findForward = <T>(items: T[], start: number, predicate: (item: T, index: number) => boolean): number => {\n for (let idx = start; idx < items.length; idx++) {\n if (predicate(items[idx], idx)) return idx;\n }\n\n return -1;\n};\n\n/**\n * Find index of first item matching predicate (backward scan).\n */\nexport const findBackward = <T>(items: T[], start: number, predicate: (item: T, index: number) => boolean): number => {\n for (let idx = start; idx >= 0; idx--) {\n if (predicate(items[idx], idx)) return idx;\n }\n\n return -1;\n};\n"],"mappings":"AAQA,IAAa,GAAkB,EAAY,EAAe,IAA2D,CACnH,IAAK,IAAI,EAAM,EAAO,EAAM,EAAM,OAAQ,IACxC,GAAI,EAAU,EAAM,GAAM,CAAG,EAAG,OAAO,EAGzC,MAAO,EACT,EAKa,GAAmB,EAAY,EAAe,IAA2D,CACpH,IAAK,IAAI,EAAM,EAAO,GAAO,EAAG,IAC9B,GAAI,EAAU,EAAM,GAAM,CAAG,EAAG,OAAO,EAGzC,MAAO,EACT"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`./internal/validation-utils.cjs`);var
|
|
1
|
+
const e=require(`./internal/keyboard-utils.cjs`),t=require(`./internal/validation-utils.cjs`);var n={first:[`Home`],last:[`End`],next:[`ArrowDown`],prev:[`ArrowUp`]},r=r=>{let i=(e,t)=>r.isItemDisabled?.(e,t)??e.disabled,a=e=>(e>=0&&r.setIndex(e),e),o=(e,n,r)=>r===`forward`?t.findForward(e,n,(e,t)=>!i(e,t)):t.findBackward(e,n,(e,t)=>!i(e,t)),s=()=>{let e=r.getItems();if(!e.length)return-1;let t=o(e,0,`forward`);return t<0?-1:a(t)},c=()=>{let e=r.getItems();if(!e.length)return-1;let t=o(e,e.length-1,`backward`);return t<0?-1:a(t)},l=e=>{let t=r.getItems();if(!t.length)return-1;let n=Math.min(Math.max(e,0),t.length-1);return i(t[n],n)?r.getIndex():a(n)},u=e=>{let t=r.getItems(),n=r.getIndex();if(!t.length)return-1;let i=o(t,n<0?e===`forward`?0:t.length-1:e===`forward`?n+1:n-1,e);if(i>=0)return a(i);if(r.loop){let n=o(t,e===`forward`?0:t.length-1,e);if(n>=0)return a(n)}return n},d=()=>u(`forward`),f=()=>u(`backward`),p=()=>{let e=r.getItems(),t=r.getIndex();return t>=0&&t<e.length?e[t]:void 0},m=()=>{r.setIndex(-1)},h=()=>!!r.disabled?.(),g=()=>{let e=typeof r.keys==`function`?r.keys():r.keys;return{first:e?.first??n.first,last:e?.last??n.last,next:e?.next??n.next,prev:e?.prev??n.prev}},_=null,v,y=()=>{let e=g(),t={};for(let n of[`next`,`prev`,`first`,`last`])for(let i of e[n])t[i]=e=>{let t={first:s,last:c,next:d,prev:f}[n]();r.onNavigate?.(n,t,e)};return t},b=()=>{if(typeof r.keys==`function`){let e=r.keys();e!==v&&(v=e,_=y())}else _||=y();return _};return{first:s,getActiveItem:p,handleKeydown:t=>e.dispatchKeyboardAction(t,{disabled:h,keymap:b()}),last:c,next:d,prev:f,reset:m,set:l}};exports.createListControl=r;
|
|
2
2
|
//# sourceMappingURL=list-control.cjs.map
|