UNPKG

@melt-ui/svelte

Version:
63 lines (62 loc) 2.37 kB
import { addMeltEventListener, makeElement, createElHelpers, disabledAttr, omit, overridable, styleToString, toWritableStores, } from '../../internal/helpers/index.js'; import { derived, writable } from 'svelte/store'; const defaults = { defaultOpen: false, disabled: false, forceVisible: false, }; const { name } = createElHelpers('collapsible'); export function createCollapsible(props) { const withDefaults = { ...defaults, ...props }; const options = toWritableStores(omit(withDefaults, 'open', 'defaultOpen', 'onOpenChange')); const { disabled, forceVisible } = options; const openWritable = withDefaults.open ?? writable(withDefaults.defaultOpen); const open = overridable(openWritable, withDefaults?.onOpenChange); const root = makeElement(name(), { stores: [open, disabled], returned: ([$open, $disabled]) => ({ 'data-state': $open ? 'open' : 'closed', 'data-disabled': disabledAttr($disabled), }), }); const trigger = makeElement(name('trigger'), { stores: [open, disabled], returned: ([$open, $disabled]) => ({ 'data-state': $open ? 'open' : 'closed', 'data-disabled': disabledAttr($disabled), disabled: disabledAttr($disabled), }), action: (node) => { const unsub = addMeltEventListener(node, 'click', () => { const disabled = node.dataset.disabled !== undefined; if (disabled) return; open.update(($open) => !$open); }); return { destroy: unsub, }; }, }); const isVisible = derived([open, forceVisible], ([$open, $forceVisible]) => $open || $forceVisible); const content = makeElement(name('content'), { stores: [isVisible, open, disabled], returned: ([$isVisible, $open, $disabled]) => ({ 'data-state': $open ? 'open' : 'closed', 'data-disabled': disabledAttr($disabled), hidden: $isVisible ? undefined : true, style: $isVisible ? undefined : styleToString({ display: 'none' }), }), }); return { elements: { root, trigger, content, }, states: { open, }, options, }; }