| import { addMeltEventListener, makeElement, createElHelpers, disabledAttr, kbd, omit, overridable, styleToString, toWritableStores, } from '../../internal/helpers/index.js'; | |
| import { writable } from 'svelte/store'; | |
| import { executeCallbacks } from '../../internal/helpers/callbacks.js'; | |
| const defaults = { | |
| defaultChecked: false, | |
| disabled: false, | |
| required: false, | |
| name: '', | |
| value: '', | |
| }; | |
| const { name } = createElHelpers('switch'); | |
| export function createSwitch(props) { | |
| const propsWithDefaults = { ...defaults, ...props }; | |
| const options = toWritableStores(omit(propsWithDefaults, 'checked')); | |
| const { disabled, required, name: nameStore, value } = options; | |
| const checkedWritable = propsWithDefaults.checked ?? writable(propsWithDefaults.defaultChecked); | |
| const checked = overridable(checkedWritable, propsWithDefaults?.onCheckedChange); | |
| function toggleSwitch() { | |
| if (disabled.get()) | |
| return; | |
| checked.update((prev) => !prev); | |
| } | |
| const root = makeElement(name(), { | |
| stores: [checked, disabled, required], | |
| returned: ([$checked, $disabled, $required]) => { | |
| return { | |
| 'data-disabled': disabledAttr($disabled), | |
| disabled: disabledAttr($disabled), | |
| 'data-state': $checked ? 'checked' : 'unchecked', | |
| type: 'button', | |
| role: 'switch', | |
| 'aria-checked': $checked ? 'true' : 'false', | |
| 'aria-required': $required ? 'true' : undefined, | |
| }; | |
| }, | |
| action(node) { | |
| const unsub = executeCallbacks(addMeltEventListener(node, 'click', () => { | |
| toggleSwitch(); | |
| }), addMeltEventListener(node, 'keydown', (e) => { | |
| if (e.key !== kbd.ENTER && e.key !== kbd.SPACE) | |
| return; | |
| e.preventDefault(); | |
| toggleSwitch(); | |
| })); | |
| return { | |
| destroy: unsub, | |
| }; | |
| }, | |
| }); | |
| const input = makeElement(name('input'), { | |
| stores: [checked, nameStore, required, disabled, value], | |
| returned: ([$checked, $name, $required, $disabled, $value]) => { | |
| return { | |
| type: 'checkbox', | |
| 'aria-hidden': true, | |
| hidden: true, | |
| tabindex: -1, | |
| name: $name, | |
| value: $value, | |
| checked: $checked, | |
| required: $required, | |
| disabled: disabledAttr($disabled), | |
| style: styleToString({ | |
| position: 'absolute', | |
| opacity: 0, | |
| 'pointer-events': 'none', | |
| margin: 0, | |
| transform: 'translateX(-100%)', | |
| }), | |
| }; | |
| }, | |
| }); | |
| return { | |
| elements: { | |
| root, | |
| input, | |
| }, | |
| states: { | |
| checked, | |
| }, | |
| options, | |
| }; | |
| } | |