@oruga-ui/oruga-next
Version:
UI components for Vue.js and CSS framework agnostic
279 lines (278 loc) • 10.8 kB
JavaScript
/*! Oruga v0.11.0 | MIT License | github.com/oruga-ui/oruga */
import { defineComponent, mergeModels, useTemplateRef, useModel, computed, watch, onMounted, ref, createBlock, openBlock, Teleport, withDirectives, createElementBlock, mergeProps, unref, createCommentVNode, createVNode, normalizeClass, Transition, withCtx, createElementVNode, renderSlot, resolveDynamicComponent, toHandlers, vShow } from "vue";
import { i as isClient, g as getDefault, b as registerComponent, a as registerComponentProgrammatic } from "./config-Dl7tu_Ly.mjs";
import { d as defineClasses } from "./defineClasses-CWB9NuS-.mjs";
import { u as useEventListener } from "./useEventListener-nW3U5kAY.mjs";
import { u as useMatchMedia } from "./useMatchMedia-Go6cZv_b.mjs";
import { u as useClickOutside } from "./useClickOutside-Cq7Otb3W.mjs";
import { u as usePreventScrolling } from "./usePreventScrolling-CRyyOkPi.mjs";
import { u as useTeleportDefault } from "./useConfig-43UsDYp_.mjs";
import { u as useTrapFocus } from "./useTrapFocus-lpk0D-Ty.mjs";
import { I as InstanceRegistry, C as ComponentProgrammatic } from "./useProgrammatic-B50-6K60.mjs";
const _sfc_main = /* @__PURE__ */ defineComponent({
...{
isOruga: true,
name: "OSidebar",
configField: "sidebar",
inheritAttrs: false
},
__name: "Sidebar",
props: /* @__PURE__ */ mergeModels({
override: { type: Boolean, default: void 0 },
active: { type: Boolean, default: false },
overlay: { type: Boolean, default: () => getDefault("sidebar.overlay", false) },
inline: { type: Boolean, default: false },
position: { default: () => getDefault("sidebar.position", "left") },
fullheight: { type: Boolean, default: () => getDefault("sidebar.fullheight", false) },
fullwidth: { type: Boolean, default: () => getDefault("sidebar.fullwidth", false) },
reduce: { type: Boolean, default: () => getDefault("sidebar.reduce", false) },
mobile: { default: () => getDefault("sidebar.mobile") },
expandOnHover: { type: Boolean, default: () => getDefault("sidebar.expandOnHover", false) },
animation: { default: () => getDefault("sidebar.animation") },
cancelable: { type: [Array, Boolean], default: () => getDefault("sidebar.cancelable", ["escape", "outside"]) },
clipScroll: { type: Boolean, default: () => getDefault("sidebar.clipScroll", false) },
trapFocus: { type: Boolean, default: () => getDefault("sidebar.trapFocus", true) },
mobileBreakpoint: { default: () => getDefault("sidebar.mobileBreakpoint") },
teleport: { type: [Boolean, String, Object], default: () => getDefault("sidebar.teleport", false) },
container: {},
component: { default: void 0 },
props: { default: void 0 },
events: { default: void 0 },
rootClass: {},
mobileClass: {},
activeClass: {},
teleportClass: {},
inlineClass: {},
overlayClass: {},
contentClass: {},
hiddenClass: {},
visibleClass: {},
positionClass: {},
fullheightClass: {},
fullwidthClass: {},
reduceClass: {},
expandOnHoverClass: {},
scrollClipClass: {},
scrollKeepClass: {}
}, {
"active": { type: Boolean, ...{ default: false } },
"activeModifiers": {}
}),
emits: /* @__PURE__ */ mergeModels(["update:active", "close"], ["update:active"]),
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emits = __emit;
const { vTrapFocus } = useTrapFocus();
const rootRef = useTemplateRef("rootElement");
const contentRef = useTemplateRef("contentElement");
const isActive = useModel(__props, "active");
const { isMobile } = useMatchMedia(props.mobileBreakpoint);
const _teleport = computed(
() => typeof props.teleport === "boolean" ? { to: useTeleportDefault(), disabled: !props.teleport } : { to: props.teleport, disabled: false }
);
const transitionName = computed(() => {
if (props.animation) return props.animation;
const vertical = props.position === "top" || props.position === "bottom";
const right = props.position === "right";
const open = right ? !isActive.value : isActive.value;
return open ? vertical ? "slide-down" : "slide-next" : vertical ? "slide-up" : "slide-prev";
});
const hideOnMobile = computed(
() => props.mobile === "hidden" && isMobile.value
);
const toggleScroll = usePreventScrolling(props.clipScroll);
watch(
isActive,
(value) => {
if (props.overlay) toggleScroll(value);
},
{ flush: "post" }
);
onMounted(() => {
if (isActive.value && props.overlay) toggleScroll(true);
});
if (isClient) {
useEventListener(rootRef, "keyup", onKeyPress, { trigger: isActive });
if (!props.overlay)
useClickOutside(contentRef, clickedOutside, { trigger: isActive });
}
function onKeyPress(event) {
if (!isActive.value) return;
if (event.key === "Escape" || event.key === "Esc") cancel("escape");
}
function clickedOutside(event) {
if (props.inline || !isActive.value || isAnimating.value) return;
if (props.overlay || contentRef.value && !event.composedPath().includes(contentRef.value))
event.preventDefault();
cancel("outside");
}
function cancel(method) {
if (typeof props.cancelable === "boolean" && !props.cancelable || !props.cancelable || Array.isArray(props.cancelable) && !props.cancelable.includes(method))
return;
close(method);
}
function close(...args) {
isActive.value = false;
emits("close", ...args);
}
const isAnimating = ref(!props.active);
function afterEnter() {
isAnimating.value = false;
}
function beforeLeave() {
isAnimating.value = true;
}
const rootClasses = defineClasses(
["rootClass", "o-sidebar"],
["mobileClass", "o-sidebar--mobile", null, isMobile],
["activeClass", "o-sidebar--active", null, isActive],
[
"teleportClass",
"o-sidebar--teleport",
null,
computed(() => !!props.teleport)
],
["inlineClass", "o-sidebar--inline", null, computed(() => props.inline)]
);
const overlayClasses = defineClasses(["overlayClass", "o-sidebar__overlay"]);
const contentClasses = defineClasses(
["contentClass", "o-sidebar__content"],
[
"positionClass",
"o-sidebar__content--",
computed(() => props.position),
computed(() => !!props.position)
],
[
"fullheightClass",
"o-sidebar__content--fullheight",
null,
computed(() => props.fullheight)
],
[
"fullwidthClass",
"o-sidebar__content--fullwidth",
null,
computed(
() => props.fullwidth || isMobile.value && props.mobile === "expanded"
)
],
[
"reduceClass",
"o-sidebar__content--reduced",
null,
computed(
() => props.reduce || isMobile.value && props.mobile === "reduced"
)
],
[
"expandOnHoverClass",
"o-sidebar__content--hover-expand",
null,
computed(
() => props.expandOnHover && (!isMobile.value || props.mobile !== "expanded")
)
],
["visibleClass", "o-sidebar__content--visible", null, isActive],
[
"hiddenClass",
"o-sidebar__content--hidden",
null,
computed(() => !isActive.value)
]
);
__expose({ close });
return (_ctx, _cache) => {
return openBlock(), createBlock(Teleport, {
to: _teleport.value.to,
disabled: _teleport.value.disabled
}, [
withDirectives((openBlock(), createElementBlock("div", mergeProps({ ref: "rootElement" }, _ctx.$attrs, {
"data-oruga": "sidebar",
class: unref(rootClasses)
}), [
_ctx.overlay && isActive.value ? (openBlock(), createElementBlock("div", {
key: 0,
class: normalizeClass(unref(overlayClasses)),
tabindex: -1,
onClick: clickedOutside
}, null, 2)) : createCommentVNode("", true),
createVNode(Transition, {
name: transitionName.value,
onAfterEnter: afterEnter,
onBeforeLeave: beforeLeave
}, {
default: withCtx(() => [
withDirectives(createElementVNode("div", {
ref: "contentElement",
class: normalizeClass(unref(contentClasses))
}, [
renderSlot(_ctx.$slots, "default", { close }, () => [
_ctx.component ? (openBlock(), createBlock(resolveDynamicComponent(_ctx.component), mergeProps({ key: 0 }, _ctx.$props.props, toHandlers(_ctx.$props.events || {}), { onClose: close }), null, 16)) : createCommentVNode("", true)
])
], 2), [
[vShow, isActive.value]
])
]),
_: 3
}, 8, ["name"])
], 16)), [
[vShow, !hideOnMobile.value],
[unref(vTrapFocus), _ctx.trapFocus && isActive.value && !_ctx.inline]
])
], 8, ["to", "disabled"]);
};
}
});
const registry = new InstanceRegistry();
const SidebarProgrammatic = {
/** Returns the number of registered active instances. */
count: registry.count,
/**
* Create a new programmatic sidebar component instance.
* @param options sidebar component props object
* @param target specify a target the component get rendered into - default is `document.body`
* @returns ProgrammaticExpose
*/
open(options, target) {
const componentProps = {
active: true,
// set the active default state to true
...options
};
return ComponentProgrammatic.open(_sfc_main, {
registry,
// custom programmatic instance registry
target,
// target the component get rendered into
props: componentProps,
// component specific props
onClose: options.onClose
// on close event handler
});
},
/** Close the last registred instance in the sidebar programmatic instance registry. */
close(...args) {
var _a, _b;
(_b = (_a = registry.last()) == null ? void 0 : _a.exposed) == null ? void 0 : _b.close(...args);
},
/** Close all instances in the programmatic sidebar instance registry. */
closeAll(...args) {
registry.walk((entry) => {
var _a;
return (_a = entry.exposed) == null ? void 0 : _a.close(...args);
});
}
};
const index = {
install(app) {
registerComponent(app, _sfc_main);
registerComponentProgrammatic(app, "sidebar", SidebarProgrammatic);
}
};
export {
_sfc_main as OSidebar,
SidebarProgrammatic,
index as default
};
//# sourceMappingURL=sidebar.mjs.map