|
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, |
|
}; |
|
} |
|
|