@oruga-ui/oruga-next
Version:
UI components for Vue.js and CSS framework agnostic
467 lines (466 loc) • 18.9 kB
JavaScript
"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