@ulu/frontend
Version:
A framework-agnostic frontend toolkit providing a modular, tree-shakable library of accessible components and utilities. Designed for seamless integration, it features a highly configurable SCSS system for any environment and vanilla JavaScript modules op
156 lines (155 loc) • 5.62 kB
JavaScript
var I = Object.defineProperty;
var m = Object.getOwnPropertySymbols;
var R = Object.prototype.hasOwnProperty, E = Object.prototype.propertyIsEnumerable;
var p = (s, t, e) => t in s ? I(s, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : s[t] = e, $ = (s, t) => {
for (var e in t || (t = {}))
R.call(t, e) && p(s, e, t[e]);
if (m)
for (var e of m(t))
E.call(t, e) && p(s, e, t[e]);
return s;
};
import { ComponentInitializer as v } from "../core/component.js";
import { wrapSettingString as c } from "../core/settings.js";
import { getCoreEventName as f } from "../core/events.js";
import { Resizer as w } from "./resizer.js";
import { baseAttribute as g, closeAttribute as A, defaults as H } from "./dialog.js";
import { createElementFromHtml as M, getElement as S } from "@ulu/utils/browser/dom.js";
import { getSoleIframeLayout as D } from "../utils/iframe.js";
const n = new v({
type: "modal-builder",
baseAttribute: "data-ulu-modal-builder"
}), L = {
title: null,
titleIcon: null,
titleClass: "",
labelledby: null,
describedby: null,
nonModal: !1,
documentEnd: !0,
allowResize: !1,
position: "center",
bodyFills: !1,
noBackdrop: !1,
size: "default",
print: !1,
noMinHeight: !1,
fullscreenMobile: !1,
class: "",
baseClass: "modal",
footerElement: null,
footerHtml: null,
classClose: "button button--icon",
classCloseIcon: c("iconClassClose", (s) => `${s} button__icon`),
classResizerIcon: c("iconClassDragX"),
classResizerIconBoth: c("iconClassDragBoth"),
debug: !1,
autoIframe: !1,
templateCloseIcon(s) {
const { baseClass: t, classCloseIcon: e } = s;
return `<span class="${t}__close-icon ${e}" aria-hidden="true"></span>`;
},
templateResizerIcon(s) {
const { baseClass: t, classResizerIcon: e, classResizerIconBoth: a } = s, o = s.position === "center" ? a : e;
return `<span class="${t}__resizer-icon ${o}" aria-hidden="true"></span>`;
},
/**
* Default modal template
* @param {String} id ID for new modal
* @param {Object} config Resolved options
* @returns {String} Markup for modal
*/
template(s, t) {
const { baseClass: e, describedby: a, footerHtml: o } = t, i = [
e,
`${e}--${t.position}`,
`${e}--${t.size}`,
`${e}--${t.allowResize ? "resize" : "no-resize"}`,
...t.title ? [] : [`${e}--no-header`],
...t.bodyFills ? [`${e}--body-fills`] : [],
...t.noBackdrop ? [`${e}--no-backdrop`] : [],
...t.noMinHeight ? [`${e}--no-min-height`] : [],
...t.fullscreenMobile ? [`${e}--fullscreen-mobile`] : [],
...t.class ? [t.class] : []
], r = t.title ? `${s}--title` : t.labelledby;
return `
<dialog
id="${s}"
class="${i.join(" ")}"
${r ? `aria-labelledby="${r}"` : ""}
${a ? `aria-describedby="${a}"` : ""}
>
${t.title ? `
<header class="${e}__header">
<h2 id="${r}" class="${e}__title ${t.titleClass}">
${t.titleIcon ? `<span class="${e}__title-icon ${t.titleIcon}" aria-hidden="true"></span>` : ""}
<span class="${e}__title-text">${t.title}</span>
</h2>
<button class="${e}__close ${t.classClose}" aria-label="Close modal" ${A} autofocus>
${t.templateCloseIcon(t)}
</button>
</header>
` : ""}
<div class="${e}__body" ${n.getAttribute("body")}></div>
${o ? `<div class="${e}__footer">${o}</div>` : ""}
${t.allowResize ? `<button class="${e}__resizer" type="button" ${n.getAttribute("resizer")}>
${t.templateResizerIcon(t)}
</button>` : ""}
</dialog>
`;
}
};
let u = $({}, L);
function J(s) {
u = Object.assign({}, u, s);
}
function Y() {
n.init({
withData: !0,
coreEvents: ["pageModified"],
setup({ element: s, data: t }) {
O(s, t);
}
});
}
function O(s, t) {
const e = Object.assign({}, u, t), { position: a } = e;
if (e.debug && n.log(e, s), !s.id)
throw new Error("Missing ID on modal");
const o = e.template(s.id, e), i = M(o.trim()), r = (l) => i.querySelector(n.attributeSelector(l)), d = r("body"), h = r("resizer"), C = B(e);
if (s.removeAttribute("id"), s.removeAttribute("hidden"), s.removeAttribute(n.getAttribute()), s.parentNode.replaceChild(i, s), d.appendChild(s), i.setAttribute(g, JSON.stringify(C)), e.footerElement) {
const l = S(e.footerElement);
l && (l.classList.add(`${e.baseClass}__footer`), d.after(l));
}
if (e.autoIframe) {
const l = D(s);
l && (l.iframe.classList.add(`${e.baseClass}__frame-content`), l.isStaticSize ? (i.classList.add(`${e.baseClass}--frame-ratio`), d.style.aspectRatio = l.aspectRatio) : (i.classList.add(`${e.baseClass}--frame-fill`), l.fillHeight && (d.style.minHeight = l.fillHeight)));
}
let b;
const z = ["left", "right", "center"], _ = a === "center", y = a === "right";
if (e.allowResize)
if (z.includes(a)) {
const l = _ ? { fromX: "right", fromY: "bottom", multiplier: 2 } : { fromX: y ? "left" : "right" };
b = new w(i, h, l);
} else
console.warn(`${a} is not supported for resizing`);
if (e.print) {
let l;
document.addEventListener(f("beforePrint"), () => {
l = s.cloneNode(!0), i.after(l);
}), document.addEventListener(f("afterPrint"), () => {
l.remove();
});
}
return { modal: i, resizer: b };
}
function B(s) {
return Object.keys(H).reduce((t, e) => (e in s && (t[e] = s[e]), t), {});
}
export {
O as buildModal,
L as defaults,
Y as init,
n as initializer,
J as setDefaults
};