UNPKG

@oruga-ui/oruga-next

Version:

UI components for Vue.js and CSS framework agnostic

452 lines (451 loc) 17.9 kB
"use strict"; /*! Oruga v0.11.4 | MIT License | github.com/oruga-ui/oruga */ Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } }); const vue = require("vue"); const Icon_vue_vue_type_script_setup_true_lang = require("./Icon.vue_vue_type_script_setup_true_lang-B81OsVYw.cjs"); const PlainButton = require("./PlainButton-Qt1U5Xjx.cjs"); const config = require("./config-D4SNSQp_.cjs"); const useParentProvider = require("./useParentProvider-D71VAfNa.cjs"); const useOptions = require("./useOptions-CT_6HbPj.cjs"); const defineClasses = require("./defineClasses-CEpmGBsu.cjs"); const helpers = require("./helpers.cjs"); const useSequentialId = require("./useSequentialId-Du428Zv5.cjs"); const _hoisted_1$1 = ["id", "data-id"]; const _hoisted_2$1 = ["id"]; const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({ ...{ isOruga: true, name: "OMenuItem", configField: "menu", inheritAttrs: false }, __name: "MenuItem", props: /* @__PURE__ */ vue.mergeModels({ override: { type: Boolean, default: void 0 }, value: {}, active: { type: Boolean, default: false }, options: { default: void 0 }, label: { default: void 0 }, expanded: { type: Boolean, default: false }, disabled: { type: Boolean, default: false }, hidden: { type: Boolean, default: false }, submenuId: { default: () => vue.useId() }, icon: { default: void 0 }, iconPack: { default: () => config.getDefault("menu.iconPack") }, iconSize: { default: () => config.getDefault("menu.iconSize") }, animation: { default: () => config.getDefault("menu.animation", "slide") }, tag: { default: () => config.getDefault("menu.itemTag", PlainButton.PlainButton) }, itemClass: {}, itemActiveClass: {}, itemFocusedClass: {}, itemDisabledClass: {}, itemButtonClass: {}, itemButtonActiveClass: {}, itemButtonFocusedClass: {}, itemButtonDisabledClass: {}, itemButtonIconClass: {}, itemSubmenuClass: {} }, { "active": { type: Boolean, ...{ default: false } }, "activeModifiers": {} }), emits: /* @__PURE__ */ vue.mergeModels(["update:active", "click"], ["update:active"]), setup(__props, { emit: __emit }) { const props = __props; const emits = __emit; const itemValue = props.value ?? vue.useId(); const provideData = vue.computed(() => ({ expanded: isExpanded.value, setExpand, triggerReset })); const { childItems } = useParentProvider.useProviderParent({ key: "menu-item", data: provideData }); const menuItem = useParentProvider.useProviderChild({ key: "menu-item", needParent: false }); const providedData = vue.computed(() => ({ ...props, value: itemValue, parent: menuItem.parent.value, hasChildren: hasChildren.value, expanded: isExpanded.value, setExpand, reset, selectItem })); const { parent, item } = useParentProvider.useProviderChild({ data: providedData }); const nextSequence = parent.value.nextSequence; const normalizedOptions = vue.computed( () => useOptions.normalizeOptions(props.options, nextSequence) ); const isActive = vue.useModel(__props, "active"); const hasChildren = vue.computed(() => !!childItems.value.length); const isFocused = vue.computed( () => item.value.identifier === parent.value.focsuedIdentifier ); function selectItem(event) { if (props.disabled || parent.value.disabled) return; triggerReset(); isActive.value = !isActive.value; if (parent.value.accordion) isExpanded.value = isActive.value; parent.value.selectItem(isActive.value ? item.value : void 0); emits("click", itemValue, event); } function triggerReset(childs) { if (typeof menuItem.parent.value?.triggerReset === "function") { menuItem.parent.value.triggerReset( childs ? [item.value, ...childs] : [item.value] ); } else if (typeof parent.value.resetMenu === "function") { parent.value.resetMenu(childs ? [item.value, ...childs] : [item.value]); } } const isExpanded = vue.ref(props.expanded); if (!parent.value.accordion) isExpanded.value = true; function setExpand(state) { if (!parent.value.accordion) return; isExpanded.value = state; if (typeof menuItem.parent.value?.setExpand === "function") menuItem.parent.value.setExpand(state); } function reset() { if (parent.value.accordion) isExpanded.value = false; isActive.value = false; } const itemClasses = defineClasses.defineClasses( ["itemClass", "o-menu__item"], ["itemActiveClass", "o-menu__item--active", null, isActive], ["itemFocusedClass", "o-menu__item--focused", null, isFocused], [ "itemDisabledClass", "o-menu__item--disabled", null, vue.computed(() => props.disabled || parent.value.disabled) ] ); const buttonClasses = defineClasses.defineClasses( ["itemButtonClass", "o-menu__item__button"], ["itemButtonActiveClass", "o-menu__item__button--active", null, isActive], [ "itemButtonFocusedClass", "o-menu__item__button--focused", null, isFocused ], [ "itemButtonDisabledClass", "o-menu__item__button--disabled", null, vue.computed(() => props.disabled || parent.value.disabled) ], [ "itemButtonIconClass", "o-menu__item__button--icon", null, vue.computed(() => !!props.icon) ] ); const submenuClasses = defineClasses.defineClasses([ "itemSubmenuClass", "o-menu__item__submenu" ]); return (_ctx, _cache) => { const _component_OMenuItem = vue.resolveComponent("OMenuItem"); return vue.withDirectives((vue.openBlock(), vue.createElementBlock("li", { id: `${vue.unref(parent).menuId}-${vue.unref(item).identifier}`, "data-oruga": "menu-item", "data-id": `menu-${vue.unref(item).identifier}`, class: vue.normalizeClass(vue.unref(itemClasses)), role: "none" }, [ (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(_ctx.tag), vue.mergeProps(_ctx.$attrs, { class: vue.unref(buttonClasses), role: vue.unref(parent).role + "item", disabled: _ctx.disabled || vue.unref(parent).disabled, tabindex: "-1", "aria-selected": vue.unref(parent).role == "tree" ? isActive.value : void 0, "aria-disabled": _ctx.disabled || vue.unref(parent).disabled, "aria-expanded": hasChildren.value ? isExpanded.value : void 0, "aria-owns": hasChildren.value ? _ctx.submenuId : void 0, onClick: selectItem, onKeydown: [ vue.withKeys(selectItem, ["enter"]), vue.withKeys(selectItem, ["space"]) ] }), { default: vue.withCtx(() => [ _ctx.icon ? (vue.openBlock(), vue.createBlock(Icon_vue_vue_type_script_setup_true_lang._sfc_main, { key: 0, icon: _ctx.icon, pack: _ctx.iconPack, size: _ctx.iconSize }, null, 8, ["icon", "pack", "size"])) : vue.createCommentVNode("", true), vue.renderSlot(_ctx.$slots, "label", { expanded: isExpanded.value, active: isActive.value }, () => [ vue.createElementVNode("span", null, vue.toDisplayString(_ctx.label), 1) ]) ]), _: 3 }, 16, ["class", "role", "disabled", "aria-selected", "aria-disabled", "aria-expanded", "aria-owns"])), _ctx.$slots.default || _ctx.options ? (vue.openBlock(), vue.createBlock(vue.Transition, { key: 0, name: _ctx.animation }, { default: vue.withCtx(() => [ vue.withDirectives(vue.createElementVNode("ul", { id: _ctx.submenuId, class: vue.normalizeClass(vue.unref(submenuClasses)), tabindex: "-1", role: "group" }, [ vue.renderSlot(_ctx.$slots, "default", {}, () => [ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(normalizedOptions.value, (option) => { return vue.openBlock(), vue.createBlock(_component_OMenuItem, vue.mergeProps({ key: option.key }, { ref_for: true }, option.attrs, { value: option.value, label: option.label, hidden: option.hidden }), null, 16, ["value", "label", "hidden"]); }), 128)) ]) ], 10, _hoisted_2$1), [ [vue.vShow, isExpanded.value] ]) ]), _: 3 }, 8, ["name"])) : vue.createCommentVNode("", true) ], 10, _hoisted_1$1)), [ [vue.vShow, !_ctx.hidden] ]); }; } }); const _hoisted_1 = ["id"]; const _hoisted_2 = ["id", "role", "aria-labelledby", "onKeydown"]; const _sfc_main = /* @__PURE__ */ vue.defineComponent({ ...{ isOruga: true, name: "OMenu", configField: "menu" }, __name: "Menu", props: /* @__PURE__ */ vue.mergeModels({ override: { type: Boolean, default: void 0 }, modelValue: { default: void 0 }, options: { default: void 0 }, label: { default: void 0 }, accordion: { type: Boolean, default: true }, disabled: { type: Boolean, default: false }, menuId: { default: () => vue.useId() }, labelId: { default: () => vue.useId() }, role: { default: () => config.getDefault("menu.role", "tree") }, icon: { default: void 0 }, iconPack: { default: () => config.getDefault("menu.iconPack") }, iconSize: { default: () => config.getDefault("menu.iconSize") }, rootClass: {}, listClass: {}, labelClass: {} }, { "modelValue": { default: void 0 }, "modelModifiers": {} }), emits: /* @__PURE__ */ vue.mergeModels(["update:model-value"], ["update:modelValue"]), setup(__props) { const props = __props; const rootRef = vue.useTemplateRef("rootElement"); const provideData = vue.computed(() => ({ focsuedIdentifier: focusedItem.value?.identifier, menuId: props.menuId, accordion: props.accordion, disabled: props.disabled, role: props.role, nextSequence, resetMenu, selectItem })); const { childItems } = useParentProvider.useProviderParent({ rootRef, data: provideData }); const { nextSequence } = useSequentialId.useSequentialId(); const normalizedOptions = vue.computed( () => useOptions.normalizeOptions(props.options, nextSequence) ); function resetMenu(excludedItems = []) { childItems.value.forEach((item) => { if (!excludedItems.map((i) => i?.identifier).includes(item.identifier)) item.data?.reset(); }); } const vmodel = vue.useModel(__props, "modelValue"); const selectedItem = vue.ref(); function selectItem(item) { const value = item?.data?.value; if (vmodel.value == value) return; vmodel.value = value; selectedItem.value = item; } const focusedItem = vue.ref(); const isNotEmpty = vue.computed(() => childItems.value.some(isItemViable)); function onCollapse() { if (!focusedItem.value) return; if (focusedItem.value.data?.expanded) focusedItem.value.data?.setExpand(false); else moveFocus(-1); } function onExpend() { if (!focusedItem.value) return; if (focusedItem.value.data?.hasChildren && !focusedItem.value.data?.expanded) focusedItem.value.data?.setExpand(true); else moveFocus(1); } function setFocus(item) { focusedItem.value = item; } function moveFocus(delta) { if (!isNotEmpty.value) return; const item = getFirstViableItem(focusedItem.value?.index || 0, delta); setFocus(item); } function onUpPressed() { moveFocus(-1); } function onDownPressed() { moveFocus(1); } function onEnter(event) { if (!focusedItem.value) return; setFocus(focusedItem.value); focusedItem.value.data?.selectItem(event); } function onHomePressed() { if (!isNotEmpty.value) return; const item = getFirstViableItem(0, 1); setFocus(item); } function onEndPressed() { if (!isNotEmpty.value) return; const item = getFirstViableItem(childItems.value.length - 1, -1); setFocus(item); } function getFirstViableItem(startingIndex, delta) { let newIndex = helpers.mod( focusedItem.value?.index == startingIndex ? startingIndex + delta : startingIndex, childItems.value.length ); for (; newIndex !== focusedItem.value?.index; newIndex = helpers.mod(newIndex + delta, childItems.value.length)) { if (isItemViable(childItems.value[newIndex])) break; } return childItems.value[newIndex]; } function isItemViable(item) { return !item.data?.disabled && !item.data?.hidden && (item.data?.parent?.expanded ?? true); } function onFocusLeave() { focusedItem.value = void 0; } const rootClasses = defineClasses.defineClasses(["rootClass", "o-menu"]); const listClasses = defineClasses.defineClasses(["listClass", "o-menu__list"]); const labelClasses = defineClasses.defineClasses(["labelClass", "o-menu__label"]); return (_ctx, _cache) => { return vue.openBlock(), vue.createElementBlock("nav", { ref: "rootElement", "data-oruga": "menu", class: vue.normalizeClass(vue.unref(rootClasses)), onFocusout: onFocusLeave }, [ _ctx.label || _ctx.$slots.label ? (vue.openBlock(), vue.createElementBlock("div", { key: 0, id: _ctx.labelId, class: vue.normalizeClass(vue.unref(labelClasses)) }, [ vue.renderSlot(_ctx.$slots, "label", { focused: focusedItem.value?.data, focusedIndex: focusedItem.value?.index, selected: selectedItem.value?.data, selectedIndex: selectedItem.value?.index }, () => [ _ctx.icon ? (vue.openBlock(), vue.createBlock(Icon_vue_vue_type_script_setup_true_lang._sfc_main, { key: 0, icon: _ctx.icon, pack: _ctx.iconPack, size: _ctx.iconSize }, null, 8, ["icon", "pack", "size"])) : vue.createCommentVNode("", true), vue.createElementVNode("span", null, vue.toDisplayString(_ctx.label), 1) ]) ], 10, _hoisted_1)) : vue.createCommentVNode("", true), vue.createElementVNode("ul", { id: _ctx.menuId, class: vue.normalizeClass(vue.unref(listClasses)), role: _ctx.role, tabindex: 0, "aria-labelledby": _ctx.labelId, onKeydown: [ vue.withKeys(onCollapse, ["left"]), vue.withKeys(onExpend, ["right"]), vue.withKeys(vue.withModifiers(onEnter, ["prevent"]), ["enter"]), vue.withKeys(vue.withModifiers(onEnter, ["prevent"]), ["space"]), vue.withKeys(vue.withModifiers(onUpPressed, ["prevent"]), ["up"]), vue.withKeys(vue.withModifiers(onDownPressed, ["prevent"]), ["down"]), vue.withKeys(vue.withModifiers(onHomePressed, ["prevent"]), ["home"]), vue.withKeys(vue.withModifiers(onEndPressed, ["prevent"]), ["end"]) ] }, [ vue.renderSlot(_ctx.$slots, "default", { focused: focusedItem.value?.data, focusedIndex: focusedItem.value?.index, selected: selectedItem.value?.data, selectedIndex: selectedItem.value?.index }, () => [ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(normalizedOptions.value, (option) => { return vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: option.key }, [ vue.unref(useOptions.isGroupOption)(option) ? (vue.openBlock(), vue.createBlock(_sfc_main$1, vue.mergeProps({ key: 0, ref_for: true }, option.attrs, { label: option.label, hidden: option.hidden }), { default: vue.withCtx(() => [ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(option.options, (_option) => { return vue.openBlock(), vue.createBlock(_sfc_main$1, vue.mergeProps({ ref_for: true }, _option.attrs, { key: _option.key, value: _option.value, label: _option.label, hidden: _option.hidden }), null, 16, ["value", "label", "hidden"]); }), 128)) ]), _: 2 }, 1040, ["label", "hidden"])) : (vue.openBlock(), vue.createBlock(_sfc_main$1, vue.mergeProps({ key: 1, ref_for: true }, option.attrs, { value: option.value, label: option.label, hidden: option.hidden }), null, 16, ["value", "label", "hidden"])) ], 64); }), 128)) ]) ], 42, _hoisted_2) ], 34); }; } }); const index = { install(app) { config.registerComponent(app, _sfc_main); config.registerComponent(app, _sfc_main$1); } }; exports.OMenu = _sfc_main; exports.OMenuItem = _sfc_main$1; exports.default = index; //# sourceMappingURL=menu.cjs.map