UNPKG

@oruga-ui/oruga-next

Version:

UI components for Vue.js and CSS framework agnostic

467 lines (466 loc) 18.9 kB
"use strict"; /*! Oruga v0.11.0 | 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-ZtEqoTvT.cjs"); const PlainButton = require("./PlainButton-PZqIRrwr.cjs"); const config = require("./config-eYBvpFOZ.cjs"); const defineClasses = require("./defineClasses-Cqhbv-UT.cjs"); const useParentProvider = require("./useParentProvider-CPNahRzD.cjs"); const useOptions = require("./useOptions-YcqJ438a.cjs"); const helpers = require("./helpers.cjs"); const useSequentialId = require("./useSequentialId-BnH6otip.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) { var _a; if (typeof ((_a = menuItem.parent.value) == null ? void 0 : _a.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) { var _a; if (!parent.value.accordion) return; isExpanded.value = state; if (typeof ((_a = menuItem.parent.value) == null ? void 0 : _a.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(() => { var _a; return { focsuedIdentifier: (_a = focusedItem.value) == null ? void 0 : _a.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) => { var _a; if (!excludedItems.map((i) => i == null ? void 0 : i.identifier).includes(item.identifier)) (_a = item.data) == null ? void 0 : _a.reset(); }); } const vmodel = vue.useModel(__props, "modelValue"); const selectedItem = vue.ref(); function selectItem(item) { var _a; const value = (_a = item == null ? void 0 : item.data) == null ? void 0 : _a.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() { var _a, _b; if (!focusedItem.value) return; if ((_a = focusedItem.value.data) == null ? void 0 : _a.expanded) (_b = focusedItem.value.data) == null ? void 0 : _b.setExpand(false); else moveFocus(-1); } function onExpend() { var _a, _b, _c; if (!focusedItem.value) return; if (((_a = focusedItem.value.data) == null ? void 0 : _a.hasChildren) && !((_b = focusedItem.value.data) == null ? void 0 : _b.expanded)) (_c = focusedItem.value.data) == null ? void 0 : _c.setExpand(true); else moveFocus(1); } function setFocus(item) { focusedItem.value = item; } function moveFocus(delta) { var _a; if (!isNotEmpty.value) return; const item = getFirstViableItem(((_a = focusedItem.value) == null ? void 0 : _a.index) || 0, delta); setFocus(item); } function onUpPressed() { moveFocus(-1); } function onDownPressed() { moveFocus(1); } function onEnter(event) { var _a; if (!focusedItem.value) return; setFocus(focusedItem.value); (_a = focusedItem.value.data) == null ? void 0 : _a.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) { var _a, _b; let newIndex = helpers.mod( ((_a = focusedItem.value) == null ? void 0 : _a.index) == startingIndex ? startingIndex + delta : startingIndex, childItems.value.length ); for (; newIndex !== ((_b = focusedItem.value) == null ? void 0 : _b.index); newIndex = helpers.mod(newIndex + delta, childItems.value.length)) { if (isItemViable(childItems.value[newIndex])) break; } return childItems.value[newIndex]; } function isItemViable(item) { var _a, _b, _c, _d; return !((_a = item.data) == null ? void 0 : _a.disabled) && !((_b = item.data) == null ? void 0 : _b.hidden) && (((_d = (_c = item.data) == null ? void 0 : _c.parent) == null ? void 0 : _d.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) => { var _a, _b, _c, _d, _e, _f, _g, _h; 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: (_a = focusedItem.value) == null ? void 0 : _a.data, focusedIndex: (_b = focusedItem.value) == null ? void 0 : _b.index, selected: (_c = selectedItem.value) == null ? void 0 : _c.data, selectedIndex: (_d = selectedItem.value) == null ? void 0 : _d.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: (_e = focusedItem.value) == null ? void 0 : _e.data, focusedIndex: (_f = focusedItem.value) == null ? void 0 : _f.index, selected: (_g = selectedItem.value) == null ? void 0 : _g.data, selectedIndex: (_h = selectedItem.value) == null ? void 0 : _h.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