|
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; |
|
|
|
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) => { |
|
|
|
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, |
|
}; |
|
} |
|
|