UNPKG

vira

Version:

A simple and highly versatile design system using element-vir.

123 lines (120 loc) 4.52 kB
import { classMap, css, defineElementEvent, html, listen, nothing, testId } from 'element-vir'; import { defineViraElement } from '../define-vira-element.js'; import { updateSelectedItems } from './pop-up-helpers.js'; import { ViraMenu } from './vira-menu.element.js'; import { PopUpMenuDirection, ViraPopUpMenu, } from './vira-pop-up-menu.element.js'; import { HorizontalAnchor, ViraPopUpTrigger, } from './vira-pop-up-trigger.element.js'; /** * Test ids for {@link ViraMenuTrigger}. * * @category Internal */ export const viraMenuTriggerTestIds = { menu: 'menu-trigger-menu', }; /** * A more specific wrapper of `ViraPopUpTrigger` that always opens a menu. * * @category PopUp * @category Elements */ export const ViraMenuTrigger = defineViraElement()({ tagName: 'vira-menu-trigger', styles: css ` :host { display: inline-flex; box-sizing: border-box; vertical-align: middle; max-width: 100%; } ${ViraPopUpTrigger} { width: 100%; } .full-width-menu { width: 100%; } `, events: { itemActivate: defineElementEvent(), openChange: defineElementEvent(), }, state() { return { navController: undefined, popUpManager: undefined, /** `undefined` means the pop up is not currently showing. */ showPopUpResult: undefined, }; }, render({ inputs, state, updateState, dispatch, events }) { return html ` <${ViraPopUpTrigger.assign({ isDisabled: inputs.isDisabled, keepOpenAfterInteraction: true, z_debug_forceOpenState: inputs.z_debug_forceOpenState, popUpOffset: inputs.popUpOffset, horizontalAnchor: inputs.horizontalAnchor || HorizontalAnchor.Left, })} class=${classMap({ open: !!state.showPopUpResult, })} ${listen(ViraPopUpTrigger.events.init, (event) => { updateState({ navController: event.detail.navController, popUpManager: event.detail.popUpManager, }); })} ${listen(ViraPopUpTrigger.events.openChange, (event) => { if (!!state.showPopUpResult !== !!event.detail) { dispatch(new events.openChange(event.detail)); } updateState({ showPopUpResult: event.detail, }); })} ${listen(ViraPopUpTrigger.events.navSelect, (event) => { const itemIndex = event.detail.x; const item = inputs.items[itemIndex]; if (!item) { throw new Error(`Found no dropdown option at index '${itemIndex}'`); } dispatch(new events.itemActivate(updateSelectedItems(item, inputs.selected, inputs.isMultiSelect))); if (!inputs.isMultiSelect) { /** * Defer pop up removal to prevent race conditions with element-internal * click handlers. */ globalThis.setTimeout(() => state.popUpManager?.removePopUp()); } })} > <slot slot=${ViraPopUpTrigger.slotNames.trigger}></slot> ${state.navController && state.showPopUpResult ? html ` <${ViraPopUpMenu.assign({ direction: state.showPopUpResult.popDown ? PopUpMenuDirection.Downwards : PopUpMenuDirection.Upwards, cornerStyle: inputs.menuCornerStyle, })} slot=${ViraPopUpTrigger.slotNames.popUp} class=${classMap({ 'full-width-menu': inputs.horizontalAnchor === HorizontalAnchor.Both, })} > <${ViraMenu.assign({ items: inputs.items, selected: inputs.selected, navController: state.navController, isMultiSelect: !!inputs.isMultiSelect, hideCheckIcons: inputs.hideCheckIcons, })} ${testId(viraMenuTriggerTestIds.menu)} ></${ViraMenu}> </${ViraPopUpMenu}> ` : nothing} </${ViraPopUpTrigger}> `; }, });