UNPKG

@cgi-learning-hub/ui

Version:

@cgi-learning-hub/ui is an open-source React component library that implements UI for HUB's features

745 lines (744 loc) 24 kB
import * as u from "react"; import { P as n } from "./index-B9vkf41S.js"; import { F as me, G as be, H as J } from "./generateUtilityClasses-B_xKAflz.js"; import { m as he } from "./memoTheme-C-PaH-Cy.js"; import { o as H } from "./ownerWindow-niciwP7I.js"; import { o as O } from "./ownerDocument-CUrv0DIK.js"; import { u as re } from "./useForkRef-u29GSuCu.js"; import { a as Q } from "./useEventCallback-Y2KwRxBw.js"; import { c as Z } from "./createChainedFunction-C0nujS3O.js"; import { e as ge, u as ee } from "./useSlot-BSkdRaZr.js"; import { jsxs as se, jsx as j } from "react/jsx-runtime"; import { u as Ee, s as ie, c as Te } from "./DefaultPropsProvider-BrmlvPWg.js"; import { e as ye, P as xe, H as Re } from "./Portal-PkRJuFYN.js"; import { g as Pe, e as ae } from "./elementAcceptingRef-CZLfau9O.js"; import { B as ve } from "./Backdrop-BvL371G3.js"; function ke(e = window) { const t = e.document.documentElement.clientWidth; return e.innerWidth - t; } function Ie(e) { const t = O(e); return t.body === e ? H(e).innerWidth > t.documentElement.clientWidth : e.scrollHeight > e.clientHeight; } function K(e, t) { t ? e.setAttribute("aria-hidden", "true") : e.removeAttribute("aria-hidden"); } function te(e) { return parseInt(H(e).getComputedStyle(e).paddingRight, 10) || 0; } function Ne(e) { const s = ["TEMPLATE", "SCRIPT", "STYLE", "LINK", "MAP", "META", "NOSCRIPT", "PICTURE", "COL", "COLGROUP", "PARAM", "SLOT", "SOURCE", "TRACK"].includes(e.tagName), o = e.tagName === "INPUT" && e.getAttribute("type") === "hidden"; return s || o; } function oe(e, t, s, o, i) { const r = [t, s, ...o]; [].forEach.call(e.children, (a) => { const c = !r.includes(a), m = !Ne(a); c && m && K(a, i); }); } function Y(e, t) { let s = -1; return e.some((o, i) => t(o) ? (s = i, !0) : !1), s; } function Fe(e, t) { const s = [], o = e.container; if (!t.disableScrollLock) { if (Ie(o)) { const a = ke(H(o)); s.push({ value: o.style.paddingRight, property: "padding-right", el: o }), o.style.paddingRight = `${te(o) + a}px`; const c = O(o).querySelectorAll(".mui-fixed"); [].forEach.call(c, (m) => { s.push({ value: m.style.paddingRight, property: "padding-right", el: m }), m.style.paddingRight = `${te(m) + a}px`; }); } let r; if (o.parentNode instanceof DocumentFragment) r = O(o).body; else { const a = o.parentElement, c = H(o); r = (a == null ? void 0 : a.nodeName) === "HTML" && c.getComputedStyle(a).overflowY === "scroll" ? a : o; } s.push({ value: r.style.overflow, property: "overflow", el: r }, { value: r.style.overflowX, property: "overflow-x", el: r }, { value: r.style.overflowY, property: "overflow-y", el: r }), r.style.overflow = "hidden"; } return () => { s.forEach(({ value: r, el: a, property: c }) => { r ? a.style.setProperty(c, r) : a.style.removeProperty(c); }); }; } function Se(e) { const t = []; return [].forEach.call(e.children, (s) => { s.getAttribute("aria-hidden") === "true" && t.push(s); }), t; } class Ce { constructor() { this.modals = [], this.containers = []; } add(t, s) { let o = this.modals.indexOf(t); if (o !== -1) return o; o = this.modals.length, this.modals.push(t), t.modalRef && K(t.modalRef, !1); const i = Se(s); oe(s, t.mount, t.modalRef, i, !0); const r = Y(this.containers, (a) => a.container === s); return r !== -1 ? (this.containers[r].modals.push(t), o) : (this.containers.push({ modals: [t], container: s, restore: null, hiddenSiblings: i }), o); } mount(t, s) { const o = Y(this.containers, (r) => r.modals.includes(t)), i = this.containers[o]; i.restore || (i.restore = Fe(i, s)); } remove(t, s = !0) { const o = this.modals.indexOf(t); if (o === -1) return o; const i = Y(this.containers, (a) => a.modals.includes(t)), r = this.containers[i]; if (r.modals.splice(r.modals.indexOf(t), 1), this.modals.splice(o, 1), r.modals.length === 0) r.restore && r.restore(), t.modalRef && K(t.modalRef, s), oe(r.container, t.mount, t.modalRef, r.hiddenSiblings, !1), this.containers.splice(i, 1); else { const a = r.modals[r.modals.length - 1]; a.modalRef && K(a.modalRef, !1); } return o; } isTopModal(t) { return this.modals.length > 0 && this.modals[this.modals.length - 1] === t; } } const Me = ["input", "select", "textarea", "a[href]", "button", "[tabindex]", "audio[controls]", "video[controls]", '[contenteditable]:not([contenteditable="false"])'].join(","); function we(e) { const t = parseInt(e.getAttribute("tabindex") || "", 10); return Number.isNaN(t) ? e.contentEditable === "true" || (e.nodeName === "AUDIO" || e.nodeName === "VIDEO" || e.nodeName === "DETAILS") && e.getAttribute("tabindex") === null ? 0 : e.tabIndex : t; } function Oe(e) { if (e.tagName !== "INPUT" || e.type !== "radio" || !e.name) return !1; const t = (o) => e.ownerDocument.querySelector(`input[type="radio"]${o}`); let s = t(`[name="${e.name}"]:checked`); return s || (s = t(`[name="${e.name}"]`)), s !== e; } function Ae(e) { return !(e.disabled || e.tagName === "INPUT" && e.type === "hidden" || Oe(e)); } function De(e) { const t = [], s = []; return Array.from(e.querySelectorAll(Me)).forEach((o, i) => { const r = we(o); r === -1 || !Ae(o) || (r === 0 ? t.push(o) : s.push({ documentOrder: i, tabIndex: r, node: o })); }), s.sort((o, i) => o.tabIndex === i.tabIndex ? o.documentOrder - i.documentOrder : o.tabIndex - i.tabIndex).map((o) => o.node).concat(t); } function Le() { return !0; } function z(e) { const { children: t, disableAutoFocus: s = !1, disableEnforceFocus: o = !1, disableRestoreFocus: i = !1, getTabbable: r = De, isEnabled: a = Le, open: c } = e, m = u.useRef(!1), E = u.useRef(null), v = u.useRef(null), h = u.useRef(null), y = u.useRef(null), b = u.useRef(!1), p = u.useRef(null), M = re(Pe(t), p), N = u.useRef(null); u.useEffect(() => { !c || !p.current || (b.current = !s); }, [s, c]), u.useEffect(() => { if (!c || !p.current) return; const l = O(p.current); return p.current.contains(l.activeElement) || (p.current.hasAttribute("tabIndex") || (process.env.NODE_ENV !== "production" && console.error(["MUI: The modal content node does not accept focus.", 'For the benefit of assistive technologies, the tabIndex of the node is being set to "-1".'].join(` `)), p.current.setAttribute("tabIndex", "-1")), b.current && p.current.focus()), () => { i || (h.current && h.current.focus && (m.current = !0, h.current.focus()), h.current = null); }; }, [c]), u.useEffect(() => { if (!c || !p.current) return; const l = O(p.current), g = (T) => { N.current = T, !(o || !a() || T.key !== "Tab") && l.activeElement === p.current && T.shiftKey && (m.current = !0, v.current && v.current.focus()); }, k = () => { var x, w; const T = p.current; if (T === null) return; if (!l.hasFocus() || !a() || m.current) { m.current = !1; return; } if (T.contains(l.activeElement) || o && l.activeElement !== E.current && l.activeElement !== v.current) return; if (l.activeElement !== y.current) y.current = null; else if (y.current !== null) return; if (!b.current) return; let S = []; if ((l.activeElement === E.current || l.activeElement === v.current) && (S = r(p.current)), S.length > 0) { const D = !!((x = N.current) != null && x.shiftKey && ((w = N.current) == null ? void 0 : w.key) === "Tab"), U = S[0], L = S[S.length - 1]; typeof U != "string" && typeof L != "string" && (D ? L.focus() : U.focus()); } else T.focus(); }; l.addEventListener("focusin", k), l.addEventListener("keydown", g, !0); const A = setInterval(() => { l.activeElement && l.activeElement.tagName === "BODY" && k(); }, 50); return () => { clearInterval(A), l.removeEventListener("focusin", k), l.removeEventListener("keydown", g, !0); }; }, [s, o, i, a, c, r]); const F = (l) => { h.current === null && (h.current = l.relatedTarget), b.current = !0, y.current = l.target; const g = t.props.onFocus; g && g(l); }, R = (l) => { h.current === null && (h.current = l.relatedTarget), b.current = !0; }; return /* @__PURE__ */ se(u.Fragment, { children: [/* @__PURE__ */ j("div", { tabIndex: c ? 0 : -1, onFocus: R, ref: E, "data-testid": "sentinelStart" }), /* @__PURE__ */ u.cloneElement(t, { ref: M, onFocus: F }), /* @__PURE__ */ j("div", { tabIndex: c ? 0 : -1, onFocus: R, ref: v, "data-testid": "sentinelEnd" })] }); } process.env.NODE_ENV !== "production" && (z.propTypes = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ // │ To update them, edit the TypeScript types and run `pnpm proptypes`. │ // └─────────────────────────────────────────────────────────────────────┘ /** * A single child content element. */ children: ae, /** * If `true`, the focus trap will not automatically shift focus to itself when it opens, and * replace it to the last focused element when it closes. * This also works correctly with any focus trap children that have the `disableAutoFocus` prop. * * Generally this should never be set to `true` as it makes the focus trap less * accessible to assistive technologies, like screen readers. * @default false */ disableAutoFocus: n.bool, /** * If `true`, the focus trap will not prevent focus from leaving the focus trap while open. * * Generally this should never be set to `true` as it makes the focus trap less * accessible to assistive technologies, like screen readers. * @default false */ disableEnforceFocus: n.bool, /** * If `true`, the focus trap will not restore focus to previously focused element once * focus trap is hidden or unmounted. * @default false */ disableRestoreFocus: n.bool, /** * Returns an array of ordered tabbable nodes (i.e. in tab order) within the root. * For instance, you can provide the "tabbable" npm dependency. * @param {HTMLElement} root */ getTabbable: n.func, /** * This prop extends the `open` prop. * It allows to toggle the open state without having to wait for a rerender when changing the `open` prop. * This prop should be memoized. * It can be used to support multiple focus trap mounted at the same time. * @default function defaultIsEnabled(): boolean { * return true; * } */ isEnabled: n.func, /** * If `true`, focus is locked. */ open: n.bool.isRequired }); process.env.NODE_ENV !== "production" && (z.propTypes = ye(z.propTypes)); function Be(e) { return typeof e == "function" ? e() : e; } function je(e) { return e ? e.props.hasOwnProperty("in") : !1; } const ne = () => { }, q = new Ce(); function Ke(e) { const { container: t, disableEscapeKeyDown: s = !1, disableScrollLock: o = !1, closeAfterTransition: i = !1, onTransitionEnter: r, onTransitionExited: a, children: c, onClose: m, open: E, rootRef: v } = e, h = u.useRef({}), y = u.useRef(null), b = u.useRef(null), p = re(b, v), [M, N] = u.useState(!E), F = je(c); let R = !0; (e["aria-hidden"] === "false" || e["aria-hidden"] === !1) && (R = !1); const l = () => O(y.current), g = () => (h.current.modalRef = b.current, h.current.mount = y.current, h.current), k = () => { q.mount(g(), { disableScrollLock: o }), b.current && (b.current.scrollTop = 0); }, A = Q(() => { const f = Be(t) || l().body; q.add(g(), f), b.current && k(); }), T = () => q.isTopModal(g()), S = Q((f) => { y.current = f, f && (E && T() ? k() : b.current && K(b.current, R)); }), x = u.useCallback(() => { q.remove(g(), R); }, [R]); u.useEffect(() => () => { x(); }, [x]), u.useEffect(() => { E ? A() : (!F || !i) && x(); }, [E, x, F, i, A]); const w = (f) => (d) => { var P; (P = f.onKeyDown) == null || P.call(f, d), !(d.key !== "Escape" || d.which === 229 || // Wait until IME is settled. !T()) && (s || (d.stopPropagation(), m && m(d, "escapeKeyDown"))); }, D = (f) => (d) => { var P; (P = f.onClick) == null || P.call(f, d), d.target === d.currentTarget && m && m(d, "backdropClick"); }; return { getRootProps: (f = {}) => { const d = ge(e); delete d.onTransitionEnter, delete d.onTransitionExited; const P = { ...d, ...f }; return { /* * Marking an element with the role presentation indicates to assistive technology * that this element should be ignored; it exists to support the web application and * is not meant for humans to interact with directly. * https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-static-element-interactions.md */ role: "presentation", ...P, onKeyDown: w(P), ref: p }; }, getBackdropProps: (f = {}) => { const d = f; return { "aria-hidden": !0, ...d, onClick: D(d), open: E }; }, getTransitionProps: () => { const f = () => { N(!1), r && r(); }, d = () => { N(!0), a && a(), i && x(); }; return { onEnter: Z(f, (c == null ? void 0 : c.props.onEnter) ?? ne), onExited: Z(d, (c == null ? void 0 : c.props.onExited) ?? ne) }; }, rootRef: p, portalRef: S, isTopModal: T, exited: M, hasTransition: F }; } function Ue(e) { return be("MuiModal", e); } const st = me("MuiModal", ["root", "hidden", "backdrop"]), We = (e) => { const { open: t, exited: s, classes: o } = e; return Te({ root: ["root", !t && s && "hidden"], backdrop: ["backdrop"] }, Ue, o); }, qe = ie("div", { name: "MuiModal", slot: "Root", overridesResolver: (e, t) => { const { ownerState: s } = e; return [t.root, !s.open && s.exited && t.hidden]; } })(he(({ theme: e }) => ({ position: "fixed", zIndex: (e.vars || e).zIndex.modal, right: 0, bottom: 0, top: 0, left: 0, variants: [{ props: ({ ownerState: t }) => !t.open && t.exited, style: { visibility: "hidden" } }] }))), He = ie(ve, { name: "MuiModal", slot: "Backdrop" })({ zIndex: -1 }), ze = /* @__PURE__ */ u.forwardRef(function(t, s) { const o = Ee({ name: "MuiModal", props: t }), { BackdropComponent: i = He, BackdropProps: r, classes: a, className: c, closeAfterTransition: m = !1, children: E, container: v, component: h, components: y = {}, componentsProps: b = {}, disableAutoFocus: p = !1, disableEnforceFocus: M = !1, disableEscapeKeyDown: N = !1, disablePortal: F = !1, disableRestoreFocus: R = !1, disableScrollLock: l = !1, hideBackdrop: g = !1, keepMounted: k = !1, onClose: A, onTransitionEnter: T, onTransitionExited: S, open: x, slotProps: w = {}, slots: D = {}, // eslint-disable-next-line react/prop-types theme: U, ...L } = o, V = { ...o, closeAfterTransition: m, disableAutoFocus: p, disableEnforceFocus: M, disableEscapeKeyDown: N, disablePortal: F, disableRestoreFocus: R, disableScrollLock: l, hideBackdrop: g, keepMounted: k }, { getRootProps: f, getBackdropProps: d, getTransitionProps: P, portalRef: ce, isTopModal: le, exited: _, hasTransition: G } = Ke({ ...V, rootRef: s }), B = { ...V, exited: _ }, I = We(B), W = {}; if (E.props.tabIndex === void 0 && (W.tabIndex = "-1"), G) { const { onEnter: C, onExited: $ } = P(); W.onEnter = C, W.onExited = $; } const X = { slots: { root: y.Root, backdrop: y.Backdrop, ...D }, slotProps: { ...b, ...w } }, [ue, de] = ee("root", { ref: s, elementType: qe, externalForwardedProps: { ...X, ...L, component: h }, getSlotProps: f, ownerState: B, className: J(c, I == null ? void 0 : I.root, !B.open && B.exited && (I == null ? void 0 : I.hidden)) }), [fe, pe] = ee("backdrop", { ref: r == null ? void 0 : r.ref, elementType: i, externalForwardedProps: X, shouldForwardComponentProp: !0, additionalProps: r, getSlotProps: (C) => d({ ...C, onClick: ($) => { C != null && C.onClick && C.onClick($); } }), className: J(r == null ? void 0 : r.className, I == null ? void 0 : I.backdrop), ownerState: B }); return !k && !x && (!G || _) ? null : /* @__PURE__ */ j(xe, { ref: ce, container: v, disablePortal: F, children: /* @__PURE__ */ se(ue, { ...de, children: [!g && i ? /* @__PURE__ */ j(fe, { ...pe }) : null, /* @__PURE__ */ j(z, { disableEnforceFocus: M, disableAutoFocus: p, disableRestoreFocus: R, isEnabled: le, open: x, children: /* @__PURE__ */ u.cloneElement(E, W) })] }) }); }); process.env.NODE_ENV !== "production" && (ze.propTypes = { // ┌────────────────────────────── Warning ──────────────────────────────┐ // │ These PropTypes are generated from the TypeScript type definitions. │ // │ To update them, edit the d.ts file and run `pnpm proptypes`. │ // └─────────────────────────────────────────────────────────────────────┘ /** * A backdrop component. This prop enables custom backdrop rendering. * @deprecated Use `slots.backdrop` instead. While this prop currently works, it will be removed in the next major version. * Use the `slots.backdrop` prop to make your application ready for the next version of Material UI. * @default styled(Backdrop, { * name: 'MuiModal', * slot: 'Backdrop', * })({ * zIndex: -1, * }) */ BackdropComponent: n.elementType, /** * Props applied to the [`Backdrop`](https://mui.com/material-ui/api/backdrop/) element. * @deprecated Use `slotProps.backdrop` instead. */ BackdropProps: n.object, /** * A single child content element. */ children: ae.isRequired, /** * Override or extend the styles applied to the component. */ classes: n.object, /** * @ignore */ className: n.string, /** * When set to true the Modal waits until a nested Transition is completed before closing. * @default false */ closeAfterTransition: n.bool, /** * The component used for the root node. * Either a string to use a HTML element or a component. */ component: n.elementType, /** * The components used for each slot inside. * * @deprecated Use the `slots` prop instead. This prop will be removed in a future major release. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details. * * @default {} */ components: n.shape({ Backdrop: n.elementType, Root: n.elementType }), /** * The extra props for the slot components. * You can override the existing props or add new ones. * * @deprecated Use the `slotProps` prop instead. This prop will be removed in a future major release. See [Migrating from deprecated APIs](https://mui.com/material-ui/migration/migrating-from-deprecated-apis/) for more details. * * @default {} */ componentsProps: n.shape({ backdrop: n.oneOfType([n.func, n.object]), root: n.oneOfType([n.func, n.object]) }), /** * An HTML element or function that returns one. * The `container` will have the portal children appended to it. * * You can also provide a callback, which is called in a React layout effect. * This lets you set the container from a ref, and also makes server-side rendering possible. * * By default, it uses the body of the top-level document object, * so it's simply `document.body` most of the time. */ container: n.oneOfType([Re, n.func]), /** * If `true`, the modal will not automatically shift focus to itself when it opens, and * replace it to the last focused element when it closes. * This also works correctly with any modal children that have the `disableAutoFocus` prop. * * Generally this should never be set to `true` as it makes the modal less * accessible to assistive technologies, like screen readers. * @default false */ disableAutoFocus: n.bool, /** * If `true`, the modal will not prevent focus from leaving the modal while open. * * Generally this should never be set to `true` as it makes the modal less * accessible to assistive technologies, like screen readers. * @default false */ disableEnforceFocus: n.bool, /** * If `true`, hitting escape will not fire the `onClose` callback. * @default false */ disableEscapeKeyDown: n.bool, /** * The `children` will be under the DOM hierarchy of the parent component. * @default false */ disablePortal: n.bool, /** * If `true`, the modal will not restore focus to previously focused element once * modal is hidden or unmounted. * @default false */ disableRestoreFocus: n.bool, /** * Disable the scroll lock behavior. * @default false */ disableScrollLock: n.bool, /** * If `true`, the backdrop is not rendered. * @default false */ hideBackdrop: n.bool, /** * Always keep the children in the DOM. * This prop can be useful in SEO situation or * when you want to maximize the responsiveness of the Modal. * @default false */ keepMounted: n.bool, /** * Callback fired when the component requests to be closed. * The `reason` parameter can optionally be used to control the response to `onClose`. * * @param {object} event The event source of the callback. * @param {string} reason Can be: `"escapeKeyDown"`, `"backdropClick"`. */ onClose: n.func, /** * A function called when a transition enters. */ onTransitionEnter: n.func, /** * A function called when a transition has exited. */ onTransitionExited: n.func, /** * If `true`, the component is shown. */ open: n.bool.isRequired, /** * The props used for each slot inside the Modal. * @default {} */ slotProps: n.shape({ backdrop: n.oneOfType([n.func, n.object]), root: n.oneOfType([n.func, n.object]) }), /** * The components used for each slot inside the Modal. * Either a string to use a HTML element or a component. * @default {} */ slots: n.shape({ backdrop: n.elementType, root: n.elementType }), /** * The system prop that allows defining system overrides as well as additional CSS styles. */ sx: n.oneOfType([n.arrayOf(n.oneOfType([n.func, n.object, n.bool])), n.func, n.object]) }); export { z as F, ze as M, Ce as a, ke as b, Ue as g, st as m };