import { addMeltEventListener, makeElement, disabledAttr, executeCallbacks, kbd, omit, overridable, styleToString, toWritableStores, } from '../../internal/helpers/index.js'; import { derived, writable } from 'svelte/store'; const defaults = { disabled: false, required: false, name: undefined, value: 'on', defaultChecked: false, }; export function createCheckbox(props) { const withDefaults = { ...defaults, ...props }; const options = toWritableStores(omit(withDefaults, 'checked', 'defaultChecked')); const { disabled, name, required, value } = options; // States const checkedWritable = withDefaults.checked ?? writable(withDefaults.defaultChecked); const checked = overridable(checkedWritable, withDefaults?.onCheckedChange); const root = makeElement('checkbox', { stores: [checked, disabled, required], returned: ([$checked, $disabled, $required]) => { return { 'data-disabled': disabledAttr($disabled), disabled: disabledAttr($disabled), 'data-state': $checked === 'indeterminate' ? 'indeterminate' : $checked ? 'checked' : 'unchecked', type: 'button', role: 'checkbox', 'aria-checked': $checked === 'indeterminate' ? 'mixed' : $checked, 'aria-required': $required, }; }, action: (node) => { const unsub = executeCallbacks(addMeltEventListener(node, 'keydown', (e) => { // According to WAI ARIA, Checkboxes don't activate on enter keypress if (e.key === kbd.ENTER) e.preventDefault(); }), addMeltEventListener(node, 'click', () => { if (disabled.get()) return; checked.update((value) => { if (value === 'indeterminate') return true; return !value; }); })); return { destroy: unsub, }; }, }); const input = makeElement('checkbox-input', { stores: [checked, name, value, required, disabled], returned: ([$checked, $name, $value, $required, $disabled]) => { return { type: 'checkbox', 'aria-hidden': true, hidden: true, tabindex: -1, name: $name, value: $value, checked: $checked === 'indeterminate' ? false : $checked, required: $required, disabled: disabledAttr($disabled), style: styleToString({ position: 'absolute', opacity: 0, 'pointer-events': 'none', margin: 0, transform: 'translateX(-100%)', }), }; }, }); const isIndeterminate = derived(checked, ($checked) => $checked === 'indeterminate'); const isChecked = derived(checked, ($checked) => $checked === true); return { elements: { root, input, }, states: { checked, }, helpers: { isIndeterminate, isChecked, }, options, }; }