UNPKG

@oruga-ui/oruga-next

Version:

UI components for Vue.js and CSS framework agnostic

441 lines (440 loc) 17.6 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 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 Icon_vue_vue_type_script_setup_true_lang = require("./Icon.vue_vue_type_script_setup_true_lang-ZtEqoTvT.cjs"); const SlotComponent = require("./SlotComponent-BMmH3QFp.cjs"); const helpers = require("./helpers.cjs"); const useOptions = require("./useOptions-YcqJ438a.cjs"); const useSequentialId = require("./useSequentialId-BnH6otip.cjs"); const _hoisted_1 = ["id", "data-id", "hidden", "aria-labelledby"]; const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({ ...{ isOruga: true, name: "OTabItem", configField: "tabs", inheritAttrs: false }, __name: "TabItem", props: { override: { type: Boolean, default: void 0 }, value: { default: void 0 }, label: { default: void 0 }, disabled: { type: Boolean, default: false }, visible: { type: Boolean, default: true }, icon: { default: () => config.getDefault("tabs.icon") }, iconPack: { default: () => config.getDefault("tabs.iconPack") }, tag: { default: () => config.getDefault("tabs.itemTag", PlainButton.PlainButton) }, content: { default: void 0 }, component: { default: void 0 }, props: { default: void 0 }, events: { default: void 0 }, tabClass: {}, tabActiveClass: {}, tabPreviousClass: {}, tabNextClass: {}, tabDisabledClass: {}, tabIconClass: {}, tabLabelClass: {}, tabPanelClass: {} }, emits: ["activate", "deactivate"], setup(__props, { emit: __emit }) { const props = __props; const emits = __emit; const itemValue = props.value ?? vue.useId(); const slots = vue.useSlots(); const providedData = vue.computed(() => ({ ...props, value: itemValue, $slots: slots, tabClasses: tabClasses.value, iconClasses: tabIconClasses.value, labelClasses: tabLabelClasses.value, isTransitioning: isTransitioning.value, activate, deactivate })); const { parent, item } = useParentProvider.useProviderChild({ data: providedData }); const transitionName = vue.ref(); const isActive = vue.computed(() => item.value.index === parent.value.activeIndex); const isTransitioning = vue.ref(false); const nextAnimation = vue.computed(() => { const idx = parent.value.vertical && parent.value.animation.length === 4 ? 2 : 0; return parent.value.animation[idx]; }); const prevAnimation = vue.computed(() => { const idx = parent.value.vertical && parent.value.animation.length === 4 ? 3 : 1; return parent.value.animation[idx]; }); function activate(oldIndex) { transitionName.value = item.value.index < oldIndex ? nextAnimation.value : prevAnimation.value; emits("activate"); } function deactivate(newIndex) { transitionName.value = newIndex < item.value.index ? nextAnimation.value : prevAnimation.value; emits("deactivate"); } function afterEnter() { isTransitioning.value = true; } function beforeLeave() { isTransitioning.value = true; } const tabClasses = defineClasses.defineClasses( ["tabClass", "o-tabs__tab"], ["tabActiveClass", "o-tabs__tab--active", null, isActive], [ "tabDisabledClass", "o-tabs__tab--disabled", null, vue.computed(() => props.disabled) ], [ "tabPreviousClass", "o-tabs__tab--previous", null, vue.computed(() => { var _a; return item.value.index < ((_a = parent.value) == null ? void 0 : _a.activeIndex); }) ], [ "tabNextClass", "o-tabs__tab--next", null, vue.computed(() => { var _a; return item.value.index > ((_a = parent.value) == null ? void 0 : _a.activeIndex); }) ] ); const tabIconClasses = defineClasses.defineClasses(["tabIconClass", "o-tabs__tab-icon"]); const tabLabelClasses = defineClasses.defineClasses(["tabLabelClass", "o-tabs__tab-label"]); const panelClasses = defineClasses.defineClasses(["tabPanelClass", "o-tabs__panel"]); return (_ctx, _cache) => { return vue.unref(parent) ? (vue.openBlock(), vue.createBlock(vue.Transition, { key: 0, css: vue.unref(parent).animated, name: transitionName.value, appear: vue.unref(parent).animateInitially, onAfterEnter: afterEnter, onBeforeLeave: beforeLeave }, { default: vue.withCtx(() => [ vue.withDirectives(vue.createElementVNode("div", vue.mergeProps(_ctx.$attrs, { id: `tabpanel-${vue.unref(item).identifier}`, "data-oruga": "tabs-item", "data-id": `tabs-${vue.unref(item).identifier}`, class: vue.unref(panelClasses), role: "tabpanel", hidden: !isActive.value, "aria-labelledby": `tab-${vue.unref(item).identifier}`, "aria-roledescription": "item" }), [ vue.renderSlot(_ctx.$slots, "default", { active: isActive.value && _ctx.visible }, () => [ _ctx.component ? (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(_ctx.component), vue.mergeProps({ key: 0 }, _ctx.$props.props, vue.toHandlers(_ctx.$props.events || {})), null, 16)) : (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 1 }, [ vue.createTextVNode(vue.toDisplayString(_ctx.content), 1) ], 64)) ]), vue.createCommentVNode("", true) ], 16, _hoisted_1), [ [vue.vShow, isActive.value && _ctx.visible] ]) ]), _: 3 }, 8, ["css", "name", "appear"])) : vue.createCommentVNode("", true); }; } }); const _sfc_main = /* @__PURE__ */ vue.defineComponent({ ...{ isOruga: true, name: "OTabs", configField: "tabs" }, __name: "Tabs", props: /* @__PURE__ */ vue.mergeModels({ override: { type: Boolean, default: void 0 }, modelValue: { default: void 0 }, options: { default: void 0 }, variant: { default: () => config.getDefault("tabs.variant") }, size: { default: () => config.getDefault("tabs.size") }, vertical: { type: Boolean, default: () => config.getDefault("tabs.vertical", false) }, position: { default: void 0 }, type: { default: () => config.getDefault("tabs.type", "default") }, expanded: { type: Boolean, default: false }, tag: { default: () => config.getDefault("tabs.tag", "div") }, activateOnFocus: { type: Boolean, default: false }, animated: { type: Boolean, default: () => config.getDefault("tabs.animated", true) }, animation: { default: () => config.getDefault("tabs.animation", [ "slide-next", "slide-prev", "slide-down", "slide-up" ]) }, animateInitially: { type: Boolean, default: () => config.getDefault("tabs.animateInitially", false) }, multiline: { type: Boolean, default: false }, ariaLabel: { default: () => config.getDefault("tabs.ariaLabel") }, rootClass: {}, positionClass: {}, sizeClass: {}, typeClass: {}, expandedClass: {}, verticalClass: {}, multilineClass: {}, listClass: {}, contentClass: {}, transitioningClass: {} }, { "modelValue": { default: void 0 }, "modelModifiers": {} }), emits: /* @__PURE__ */ vue.mergeModels(["update:model-value", "change"], ["update:modelValue"]), setup(__props, { emit: __emit }) { const props = __props; const emits = __emit; const rootRef = vue.useTemplateRef("rootElement"); const provideData = vue.computed(() => { var _a; return { activeIndex: ((_a = activeItem.value) == null ? void 0 : _a.index) ?? 0, type: props.type, vertical: props.vertical, animated: props.animated, animation: props.animation, animateInitially: props.animateInitially }; }); const { childItems } = useParentProvider.useProviderParent({ rootRef, data: provideData }); const items = vue.computed(() => { if (!childItems.value) return []; return childItems.value.map((column) => ({ index: column.index, identifier: column.identifier, ...vue.toValue(column.data) })); }); const { nextSequence } = useSequentialId.useSequentialId(); const normalizedOptions = vue.computed( () => useOptions.normalizeOptions(props.options, nextSequence) ); const vmodel = vue.useModel(__props, "modelValue"); vue.watch( () => props.modelValue, (value) => { if (vmodel.value !== value) performAction(value); } ); const activeItem = vue.ref(); vue.watchEffect(() => { activeItem.value = helpers.isDefined(vmodel.value) ? items.value.find((item) => item.value === vmodel.value) || items.value[0] : items.value[0]; }); const isTransitioning = vue.computed( () => items.value.some((item) => item.isTransitioning) ); vue.onMounted(() => { var _a; if (!vmodel.value) vmodel.value = (_a = items.value[0]) == null ? void 0 : _a.value; }); function itemClick(item) { if (vmodel.value !== item.value) performAction(item.value); } function onNext(event, index2) { if (props.vertical && event.key == "ArrowDown" || !props.vertical && event.key == "ArrowRight") { const newIndex = helpers.mod(index2 + 1, items.value.length); const item = getFirstViableItem(newIndex, true); moveFocus(item); } } function onPrev(event, index2) { if (props.vertical && event.key == "ArrowUp" || !props.vertical && event.key == "ArrowLeft") { const newIndex = helpers.mod(index2 - 1, items.value.length); const item = getFirstViableItem(newIndex, false); moveFocus(item); } } function onHomePressed() { if (items.value.length < 1) return; const item = getFirstViableItem(0, true); moveFocus(item); } function onEndPressed() { if (items.value.length < 1) return; const item = getFirstViableItem(items.value.length - 1, false); moveFocus(item); } function moveFocus(item) { var _a; if (props.activateOnFocus) { itemClick(item); } else { const el = (_a = rootRef.value) == null ? void 0 : _a.querySelector( `#tab-${item.identifier}` ); el == null ? void 0 : el.focus(); } } function getFirstViableItem(startingIndex, forward) { var _a; const direction = forward ? 1 : -1; let newIndex = startingIndex; for (; newIndex !== ((_a = activeItem.value) == null ? void 0 : _a.index); newIndex = helpers.mod(newIndex + direction, items.value.length)) { if (items.value[newIndex].visible && !items.value[newIndex].disabled) break; } return items.value[newIndex]; } function performAction(newValue) { const oldValue = vmodel.value; const oldItem = activeItem.value; const newItem = items.value.find((item) => item.value === newValue) || items.value[0]; if (oldItem && newItem) { oldItem.deactivate(newItem.index); newItem.activate(oldItem.index); } vue.nextTick(() => { vmodel.value = newValue; emits("change", newValue, oldValue); }); } const rootClasses = defineClasses.defineClasses( ["rootClass", "o-tabs"], [ "positionClass", "o-tabs--", vue.computed(() => props.position), vue.computed(() => !!props.position) ], [ "sizeClass", "o-tabs--", vue.computed(() => props.size), vue.computed(() => !!props.size) ], [ "typeClass", "o-tabs--", vue.computed(() => props.type), vue.computed(() => !!props.type) ], ["expandedClass", "o-tabs--expanded", null, vue.computed(() => props.expanded)], ["verticalClass", "o-tabs--vertical", null, vue.computed(() => props.vertical)], [ "multilineClass", "o-tabs--multiline", null, vue.computed(() => props.multiline) ] ); const tablistClasses = defineClasses.defineClasses(["listClass", "o-tabs__list"]); const contentClasses = defineClasses.defineClasses( ["contentClass", "o-tabs__content"], [ "transitioningClass", "o-tabs__content--transitioning", null, isTransitioning ] ); return (_ctx, _cache) => { return vue.openBlock(), vue.createElementBlock("div", { ref: "rootElement", "data-oruga": "tabs", class: vue.normalizeClass(vue.unref(rootClasses)) }, [ (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(props.tag), { class: vue.normalizeClass(vue.unref(tablistClasses)), role: "tablist", "aria-label": _ctx.ariaLabel, "aria-orientation": _ctx.vertical ? "vertical" : "horizontal" }, { default: vue.withCtx(() => [ vue.renderSlot(_ctx.$slots, "before"), (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(items.value, (childItem) => { var _a, _b, _c; return vue.withDirectives((vue.openBlock(), vue.createBlock(vue.unref(SlotComponent.OSlotComponent), { id: `tab-${childItem.identifier}`, key: childItem.identifier, component: childItem, tag: childItem.tag, name: "header", class: vue.normalizeClass(childItem.tabClasses), role: "tab", tabindex: childItem.value === ((_a = activeItem.value) == null ? void 0 : _a.value) ? 0 : -1, "aria-current": childItem.value === ((_b = activeItem.value) == null ? void 0 : _b.value) ? "true" : void 0, "aria-controls": `tabpanel-${childItem.identifier}`, "aria-selected": childItem.value === ((_c = activeItem.value) == null ? void 0 : _c.value), onClick: ($event) => itemClick(childItem), onKeydown: [ vue.withKeys(vue.withModifiers(($event) => itemClick(childItem), ["prevent"]), ["enter"]), vue.withKeys(vue.withModifiers(($event) => itemClick(childItem), ["prevent"]), ["space"]), vue.withKeys(vue.withModifiers(($event) => onPrev($event, childItem.index), ["prevent"]), ["left"]), vue.withKeys(vue.withModifiers(($event) => onNext($event, childItem.index), ["prevent"]), ["right"]), vue.withKeys(vue.withModifiers(($event) => onPrev($event, childItem.index), ["prevent"]), ["up"]), vue.withKeys(vue.withModifiers(($event) => onNext($event, childItem.index), ["prevent"]), ["down"]), vue.withKeys(vue.withModifiers(onHomePressed, ["prevent"]), ["home"]), vue.withKeys(vue.withModifiers(onEndPressed, ["prevent"]), ["end"]) ] }, { default: vue.withCtx(() => [ childItem.icon ? (vue.openBlock(), vue.createBlock(Icon_vue_vue_type_script_setup_true_lang._sfc_main, { key: 0, class: vue.normalizeClass(childItem.iconClasses), icon: childItem.icon, pack: childItem.iconPack, size: _ctx.size }, null, 8, ["class", "icon", "pack", "size"])) : vue.createCommentVNode("", true), vue.createElementVNode("span", { class: vue.normalizeClass(childItem.labelClasses) }, vue.toDisplayString(childItem.label), 3) ]), _: 2 }, 1032, ["id", "component", "tag", "class", "tabindex", "aria-current", "aria-controls", "aria-selected", "onClick", "onKeydown"])), [ [vue.vShow, childItem.visible] ]); }), 128)), vue.renderSlot(_ctx.$slots, "after") ]), _: 3 }, 8, ["class", "aria-label", "aria-orientation"])), vue.createElementVNode("section", { class: vue.normalizeClass(vue.unref(contentClasses)) }, [ vue.renderSlot(_ctx.$slots, "default", {}, () => [ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(normalizedOptions.value, (option) => { return vue.withDirectives((vue.openBlock(), vue.createBlock(_sfc_main$1, vue.mergeProps({ ref_for: true }, option.attrs, { key: option.key, value: option.value, label: option.label }), null, 16, ["value", "label"])), [ [vue.vShow, !option.hidden] ]); }), 128)) ]) ], 2) ], 2); }; } }); const index = { install(app) { config.registerComponent(app, _sfc_main); config.registerComponent(app, _sfc_main$1); } }; exports.OTabItem = _sfc_main$1; exports.OTabs = _sfc_main; exports.default = index; //# sourceMappingURL=tabs.cjs.map