@oruga-ui/oruga-next
Version:
UI components for Vue.js and CSS framework agnostic
441 lines (440 loc) • 17.6 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 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