UNPKG

bits-ui

Version:

The headless components for Svelte.

153 lines (152 loc) 4.74 kB
import { createDropdownMenu, } from "@melt-ui/svelte"; import { getContext, setContext } from "svelte"; import { getPositioningUpdater } from "../floating/helpers.js"; import { createBitAttrs, generateId, getOptionUpdater, removeUndefined, } from "../../internal/index.js"; export function getMenuData() { const NAME = "menu"; const SUB_NAME = "menu-submenu"; const RADIO_GROUP_NAME = "menu-radiogroup"; const CHECKBOX_ITEM_NAME = "menu-checkboxitem"; const RADIO_ITEM_NAME = "menu-radioitem"; const GROUP_NAME = "menu-group"; const PARTS = [ "arrow", "checkbox-indicator", "checkbox-item", "content", "group", "item", "label", "radio-group", "radio-item", "radio-indicator", "separator", "sub-content", "sub-trigger", "trigger", ]; return { NAME, SUB_NAME, RADIO_GROUP_NAME, CHECKBOX_ITEM_NAME, RADIO_ITEM_NAME, GROUP_NAME, PARTS, }; } export function getCtx() { const { NAME } = getMenuData(); return getContext(NAME); } export function setCtx(props) { const { NAME, PARTS } = getMenuData(); const getAttrs = createBitAttrs("menu", PARTS); const dropdownMenu = { ...createDropdownMenu({ ...removeUndefined(props), forceVisible: true }), getAttrs, }; setContext(NAME, dropdownMenu); return { ...dropdownMenu, updateOption: getOptionUpdater(dropdownMenu.options), }; } export function setSubMenuCtx(props) { const { SUB_NAME } = getMenuData(); const { builders: { createSubmenu }, getAttrs, } = getCtx(); const sub = { ...createSubmenu(removeUndefined(props)), getAttrs }; setContext(SUB_NAME, sub); return { ...sub, updateOption: getOptionUpdater(sub.options), }; } export function setRadioGroupCtx(props) { const { RADIO_GROUP_NAME } = getMenuData(); const { builders: { createMenuRadioGroup }, getAttrs, } = getCtx(); const radioGroup = createMenuRadioGroup(props); setContext(RADIO_GROUP_NAME, { ...radioGroup, getAttrs }); return { ...radioGroup, getAttrs, }; } export function setRadioItem(value) { const { RADIO_ITEM_NAME, RADIO_GROUP_NAME } = getMenuData(); const dropdownMenu = getContext(RADIO_GROUP_NAME); setContext(RADIO_ITEM_NAME, { ...dropdownMenu, value }); return { ...dropdownMenu, value, }; } export function getRadioIndicator() { const { RADIO_ITEM_NAME } = getMenuData(); const radioItem = getContext(RADIO_ITEM_NAME); return { ...radioItem, }; } export function getSubTrigger() { const { SUB_NAME } = getMenuData(); const submenu = getContext(SUB_NAME); return submenu; } export function getSubmenuCtx() { const { SUB_NAME } = getMenuData(); return getContext(SUB_NAME); } export function setCheckboxItem(props) { const { CHECKBOX_ITEM_NAME } = getMenuData(); const { builders: { createCheckboxItem }, getAttrs, } = getCtx(); const checkboxItem = createCheckboxItem(removeUndefined(props)); setContext(CHECKBOX_ITEM_NAME, checkboxItem.states.checked); return { ...checkboxItem, updateOption: getOptionUpdater(checkboxItem.options), getAttrs, }; } export function getCheckboxIndicator() { const { CHECKBOX_ITEM_NAME } = getMenuData(); return getContext(CHECKBOX_ITEM_NAME); } export function setGroupCtx() { const { GROUP_NAME } = getMenuData(); const { elements: { group }, getAttrs, } = getCtx(); const id = generateId(); setContext(GROUP_NAME, id); return { group, id, getAttrs }; } export function getGroupLabel() { const { GROUP_NAME } = getMenuData(); const id = getContext(GROUP_NAME) ?? generateId(); const { elements: { groupLabel }, getAttrs, } = getCtx(); return { groupLabel, id, getAttrs }; } export function setArrow(size = 8) { const menu = getCtx(); menu.options.arrowSize.set(size); return menu; } export function updatePositioning(props) { const defaultPlacement = { side: "bottom", align: "center", }; const withDefaults = { ...defaultPlacement, ...props }; const { options: { positioning }, } = getCtx(); const updater = getPositioningUpdater(positioning); updater(withDefaults); } export function updateSubPositioning(props) { const defaultSubPlacement = { side: "right", align: "start", }; const withDefaults = { ...defaultSubPlacement, ...props }; const { options: { positioning }, } = getSubmenuCtx(); const updater = getPositioningUpdater(positioning); updater(withDefaults); }