@oruga-ui/oruga-next
Version:
UI components for Vue.js and CSS framework agnostic
250 lines (249 loc) • 10.8 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 config = require("./config-eYBvpFOZ.cjs");
const helpers = require("./helpers.cjs");
const defineClasses = require("./defineClasses-Cqhbv-UT.cjs");
const useMatchMedia = require("./useMatchMedia-EgWTgaUx.cjs");
const useClickOutside = require("./useClickOutside-CoQ2BNWF.cjs");
const usePreventScrolling = require("./usePreventScrolling-Ct3PCoON.cjs");
const useConfig = require("./useConfig-Zt3uf2uW.cjs");
const useTrapFocus = require("./useTrapFocus-DXSX2lWD.cjs");
const useProgrammatic = require("./useProgrammatic-D_ewnsB3.cjs");
const _hoisted_1 = ["role", "aria-label", "aria-modal"];
const _hoisted_2 = { key: 0 };
const _sfc_main = /* @__PURE__ */ vue.defineComponent({
...{
isOruga: true,
name: "OModal",
configField: "modal",
inheritAttrs: false
},
__name: "Modal",
props: /* @__PURE__ */ vue.mergeModels({
override: { type: Boolean, default: void 0 },
active: { type: Boolean, default: false },
fullScreen: { type: Boolean, default: false },
content: { default: void 0 },
width: { default: () => config.getDefault("modal.width", 960) },
animation: { default: () => config.getDefault("modal.animation", "zoom-out") },
overlay: { type: Boolean, default: () => config.getDefault("modal.overlay", true) },
cancelable: { type: [Array, Boolean], default: () => config.getDefault("modal.cancelable", ["escape", "x", "outside"]) },
clipScroll: { type: Boolean, default: () => config.getDefault("modal.clipScroll", false) },
trapFocus: { type: Boolean, default: () => config.getDefault("modal.trapFocus", true) },
alert: { type: Boolean, default: () => config.getDefault("modal.alert", false) },
ariaLabel: { default: () => config.getDefault("modal.ariaLabel") },
autoFocus: { type: Boolean, default: () => config.getDefault("modal.autoFocus", true) },
closeIcon: { default: () => config.getDefault("modal.closeIcon", "close") },
closeIconSize: { default: () => config.getDefault("modal.closeIconSize", "medium") },
ariaCloseLabel: { default: () => config.getDefault("modal.ariaCloseLabel", "Close") },
mobileBreakpoint: { default: () => config.getDefault("modal.mobileBreakpoint") },
teleport: { type: [Boolean, String, Object], default: () => config.getDefault("modal.teleport", false) },
container: {},
component: { default: void 0 },
props: { default: void 0 },
events: { default: void 0 },
rootClass: {},
mobileClass: {},
activeClass: {},
overlayClass: {},
contentClass: {},
fullScreenClass: {},
closeClass: {},
scrollClipClass: {},
scrollKeepClass: {}
}, {
"active": { type: Boolean, ...{ default: false } },
"activeModifiers": {}
}),
emits: /* @__PURE__ */ vue.mergeModels(["update:active", "close"], ["update:active"]),
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emits = __emit;
const { vTrapFocus } = useTrapFocus.useTrapFocus();
const rootRef = vue.useTemplateRef("rootElement");
const contentRef = vue.useTemplateRef("contentElement");
const isActive = vue.useModel(__props, "active");
const { isMobile } = useMatchMedia.useMatchMedia(props.mobileBreakpoint);
const _teleport = vue.computed(
() => typeof props.teleport === "boolean" ? { to: useConfig.useTeleportDefault(), disabled: !props.teleport } : { to: props.teleport, disabled: false }
);
const showX = vue.computed(
() => Array.isArray(props.cancelable) ? props.cancelable.indexOf("x") >= 0 : props.cancelable
);
const customStyle = vue.computed(
() => !props.fullScreen ? { maxWidth: helpers.toCssDimension(props.width) } : null
);
const toggleScroll = usePreventScrolling.usePreventScrolling(props.clipScroll);
vue.watch(isActive, (value) => {
if (props.overlay) toggleScroll(value);
if (value && props.autoFocus)
vue.nextTick(() => {
if (rootRef.value) rootRef.value.focus();
});
});
vue.onMounted(() => {
if (isActive.value && props.overlay) toggleScroll(isActive.value);
});
if (config.isClient) {
if (!props.overlay)
useClickOutside.useClickOutside(contentRef, onClickedOutside, {
trigger: isActive
});
}
function onClickedOutside(event) {
if (!isActive.value || isAnimating.value) return;
if (props.overlay || contentRef.value && !event.composedPath().includes(contentRef.value))
event.preventDefault();
cancel("outside");
}
function onEscapePress() {
if (!isActive.value) return;
cancel("escape");
}
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 = vue.ref(!props.active);
function afterEnter() {
isAnimating.value = false;
}
function beforeLeave() {
isAnimating.value = true;
}
const rootClasses = defineClasses.defineClasses(
["rootClass", "o-modal"],
["mobileClass", "o-modal--mobile", null, isMobile],
["activeClass", "o-modal--active", null, isActive]
);
const overlayClasses = defineClasses.defineClasses(["overlayClass", "o-modal__overlay"]);
const contentClasses = defineClasses.defineClasses(
["contentClass", "o-modal__content"],
[
"fullScreenClass",
"o-modal__content--full-screen",
null,
vue.computed(() => props.fullScreen)
]
);
const closeClasses = defineClasses.defineClasses(["closeClass", "o-modal__close"]);
__expose({ close });
return (_ctx, _cache) => {
return vue.openBlock(), vue.createBlock(vue.Teleport, {
to: _teleport.value.to,
disabled: _teleport.value.disabled
}, [
vue.createVNode(vue.Transition, {
name: _ctx.animation,
onAfterEnter: afterEnter,
onBeforeLeave: beforeLeave
}, {
default: vue.withCtx(() => [
vue.withDirectives((vue.openBlock(), vue.createElementBlock("div", vue.mergeProps({ ref: "rootElement" }, _ctx.$attrs, {
"data-oruga": "modal",
class: vue.unref(rootClasses),
tabindex: -1,
role: _ctx.alert ? "alertdialog" : "dialog",
"aria-label": _ctx.ariaLabel,
"aria-modal": isActive.value,
onKeyup: vue.withKeys(onEscapePress, ["escape"])
}), [
_ctx.overlay ? (vue.openBlock(), vue.createElementBlock("div", {
key: 0,
class: vue.normalizeClass(vue.unref(overlayClasses)),
tabindex: "-1",
onClick: onClickedOutside
}, null, 2)) : vue.createCommentVNode("", true),
vue.createElementVNode("div", {
ref: "contentElement",
class: vue.normalizeClass(vue.unref(contentClasses)),
style: vue.normalizeStyle(customStyle.value)
}, [
_ctx.component ? (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(_ctx.component), vue.mergeProps({ key: 0 }, _ctx.$props.props, vue.toHandlers(_ctx.$props.events || {}), { onClose: close }), null, 16)) : vue.renderSlot(_ctx.$slots, "default", {
key: 1,
close
}, () => [
_ctx.content ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2, vue.toDisplayString(_ctx.content), 1)) : vue.createCommentVNode("", true)
]),
showX.value ? vue.withDirectives((vue.openBlock(), vue.createBlock(Icon_vue_vue_type_script_setup_true_lang._sfc_main, {
key: 2,
class: vue.normalizeClass(vue.unref(closeClasses)),
icon: _ctx.closeIcon,
size: _ctx.closeIconSize,
clickable: "",
"aria-label": _ctx.ariaCloseLabel,
onClick: _cache[0] || (_cache[0] = ($event) => cancel("x"))
}, null, 8, ["class", "icon", "size", "aria-label"])), [
[vue.vShow, !isAnimating.value]
]) : vue.createCommentVNode("", true)
], 6)
], 16, _hoisted_1)), [
[vue.vShow, isActive.value],
[vue.unref(vTrapFocus), _ctx.trapFocus && isActive.value]
])
]),
_: 3
}, 8, ["name"])
], 8, ["to", "disabled"]);
};
}
});
const registry = new useProgrammatic.InstanceRegistry();
const ModalProgrammatic = {
/** Returns the number of registered active instances. */
count: registry.count,
/**
* Create a new programmatic modal component instance.
* @param options modal content string or modal component props object
* @param target specify a target the component get rendered into - default is `document.body`
* @returns ProgrammaticExpose
*/
open(options, target) {
const _options = typeof options === "string" ? { content: options } : options;
const componentProps = {
active: true,
// set the active default state to true
..._options
};
return useProgrammatic.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 modal 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 modal instance registry. */
closeAll(...args) {
registry.walk((entry) => {
var _a;
return (_a = entry.exposed) == null ? void 0 : _a.close(...args);
});
}
};
const index = {
install(app) {
config.registerComponent(app, _sfc_main);
config.registerComponentProgrammatic(app, "modal", ModalProgrammatic);
}
};
exports.ModalProgrammatic = ModalProgrammatic;
exports.OModal = _sfc_main;
exports.default = index;
//# sourceMappingURL=modal.cjs.map