UNPKG

@konstructio/ui

Version:

A set of reusable and customizable React components built for konstruct.io

492 lines (491 loc) 18.6 kB
import { jsx as c, jsxs as D, Fragment as se } from "react/jsx-runtime"; import { u as ae, S as j } from "../../index-B_6_jmOO.js"; import * as s from "react"; import { useRef as Re, useEffect as be, useMemo as oe, isValidElement as re, useCallback as ge } from "react"; import { P as L, r as Se, d as Ie } from "../../index-D7QNmo_D.js"; import { c as Ne, a as Ae, b, d as X, u as Fe } from "../../index-Cva-e5M4.js"; import { c as _e } from "../../index-BbsJ0VIJ.js"; import { B as De, R as Le, P as Me } from "../../index-D_76wh4w.js"; import { P as Oe } from "../../index-Dj1pom3_.js"; import { V as ie, R as ke } from "../../index-CbTU3cnP.js"; import { cn as q } from "../../utils/index.js"; import { closeToastVariants as Ve, toastVariants as Ke, viewportToastVariants as He } from "./Toast.variants.js"; import { X as We } from "../../x-DU-Zw-L_.js"; import { useTheme as Xe } from "../../contexts/theme.hook.js"; var Z = "ToastProvider", [ee, $e, Ue] = _e("Toast"), [ce, bt] = Ne("Toast", [Ue]), [Ye, $] = ce(Z), ue = (e) => { const { __scopeToast: r, label: o = "Notification", duration: t = 5e3, swipeDirection: u = "right", swipeThreshold: d = 50, children: f } = e, [m, v] = s.useState(null), [n, y] = s.useState(0), w = s.useRef(!1), S = s.useRef(!1); return o.trim() || console.error( `Invalid prop \`label\` supplied to \`${Z}\`. Expected non-empty \`string\`.` ), /* @__PURE__ */ c(ee.Provider, { scope: r, children: /* @__PURE__ */ c( Ye, { scope: r, label: o, duration: t, swipeDirection: u, swipeThreshold: d, toastCount: n, viewport: m, onViewportChange: v, onToastAdd: s.useCallback(() => y((g) => g + 1), []), onToastRemove: s.useCallback(() => y((g) => g - 1), []), isFocusedToastEscapeKeyDownRef: w, isClosePausedRef: S, children: f } ) }); }; ue.displayName = Z; var le = "ToastViewport", Be = ["F8"], G = "toast.viewportPause", J = "toast.viewportResume", de = s.forwardRef( (e, r) => { const { __scopeToast: o, hotkey: t = Be, label: u = "Notifications ({hotkey})", ...d } = e, f = $(le, o), m = $e(o), v = s.useRef(null), n = s.useRef(null), y = s.useRef(null), w = s.useRef(null), S = ae(r, w, f.onViewportChange), g = t.join("+").replace(/Key/g, "").replace(/Digit/g, ""), R = f.toastCount > 0; s.useEffect(() => { const a = (h) => { var T; t.length !== 0 && t.every((E) => h[E] || h.code === E) && ((T = w.current) == null || T.focus()); }; return document.addEventListener("keydown", a), () => document.removeEventListener("keydown", a); }, [t]), s.useEffect(() => { const a = v.current, h = w.current; if (R && a && h) { const p = () => { if (!f.isClosePausedRef.current) { const P = new CustomEvent(G); h.dispatchEvent(P), f.isClosePausedRef.current = !0; } }, T = () => { if (f.isClosePausedRef.current) { const P = new CustomEvent(J); h.dispatchEvent(P), f.isClosePausedRef.current = !1; } }, E = (P) => { !a.contains(P.relatedTarget) && T(); }, C = () => { a.contains(document.activeElement) || T(); }; return a.addEventListener("focusin", p), a.addEventListener("focusout", E), a.addEventListener("pointermove", p), a.addEventListener("pointerleave", C), window.addEventListener("blur", p), window.addEventListener("focus", T), () => { a.removeEventListener("focusin", p), a.removeEventListener("focusout", E), a.removeEventListener("pointermove", p), a.removeEventListener("pointerleave", C), window.removeEventListener("blur", p), window.removeEventListener("focus", T); }; } }, [R, f.isClosePausedRef]); const l = s.useCallback( ({ tabbingDirection: a }) => { const p = m().map((T) => { const E = T.ref.current, C = [E, ...st(E)]; return a === "forwards" ? C : C.reverse(); }); return (a === "forwards" ? p.reverse() : p).flat(); }, [m] ); return s.useEffect(() => { const a = w.current; if (a) { const h = (p) => { var C, P, N; const T = p.altKey || p.ctrlKey || p.metaKey; if (p.key === "Tab" && !T) { const M = document.activeElement, F = p.shiftKey; if (p.target === a && F) { (C = n.current) == null || C.focus(); return; } const A = l({ tabbingDirection: F ? "backwards" : "forwards" }), V = A.findIndex((i) => i === M); z(A.slice(V + 1)) ? p.preventDefault() : F ? (P = n.current) == null || P.focus() : (N = y.current) == null || N.focus(); } }; return a.addEventListener("keydown", h), () => a.removeEventListener("keydown", h); } }, [m, l]), /* @__PURE__ */ D( De, { ref: v, role: "region", "aria-label": u.replace("{hotkey}", g), tabIndex: -1, style: { pointerEvents: R ? void 0 : "none" }, children: [ R && /* @__PURE__ */ c( Q, { ref: n, onFocusFromOutsideViewport: () => { const a = l({ tabbingDirection: "forwards" }); z(a); } } ), /* @__PURE__ */ c(ee.Slot, { scope: o, children: /* @__PURE__ */ c(L.ol, { tabIndex: -1, ...d, ref: S }) }), R && /* @__PURE__ */ c( Q, { ref: y, onFocusFromOutsideViewport: () => { const a = l({ tabbingDirection: "backwards" }); z(a); } } ) ] } ); } ); de.displayName = le; var fe = "ToastFocusProxy", Q = s.forwardRef( (e, r) => { const { __scopeToast: o, onFocusFromOutsideViewport: t, ...u } = e, d = $(fe, o); return /* @__PURE__ */ c( ie, { "aria-hidden": !0, tabIndex: 0, ...u, ref: r, style: { position: "fixed" }, onFocus: (f) => { var n; const m = f.relatedTarget; !((n = d.viewport) != null && n.contains(m)) && t(); } } ); } ); Q.displayName = fe; var U = "Toast", je = "toast.swipeStart", qe = "toast.swipeMove", ze = "toast.swipeCancel", Ge = "toast.swipeEnd", pe = s.forwardRef( (e, r) => { const { forceMount: o, open: t, defaultOpen: u, onOpenChange: d, ...f } = e, [m = !0, v] = Ae({ prop: t, defaultProp: u, onChange: d }); return /* @__PURE__ */ c(Oe, { present: o || m, children: /* @__PURE__ */ c( Ze, { open: m, ...f, ref: r, onClose: () => v(!1), onPause: X(e.onPause), onResume: X(e.onResume), onSwipeStart: b(e.onSwipeStart, (n) => { n.currentTarget.setAttribute("data-swipe", "start"); }), onSwipeMove: b(e.onSwipeMove, (n) => { const { x: y, y: w } = n.detail.delta; n.currentTarget.setAttribute("data-swipe", "move"), n.currentTarget.style.setProperty("--radix-toast-swipe-move-x", `${y}px`), n.currentTarget.style.setProperty("--radix-toast-swipe-move-y", `${w}px`); }), onSwipeCancel: b(e.onSwipeCancel, (n) => { n.currentTarget.setAttribute("data-swipe", "cancel"), n.currentTarget.style.removeProperty("--radix-toast-swipe-move-x"), n.currentTarget.style.removeProperty("--radix-toast-swipe-move-y"), n.currentTarget.style.removeProperty("--radix-toast-swipe-end-x"), n.currentTarget.style.removeProperty("--radix-toast-swipe-end-y"); }), onSwipeEnd: b(e.onSwipeEnd, (n) => { const { x: y, y: w } = n.detail.delta; n.currentTarget.setAttribute("data-swipe", "end"), n.currentTarget.style.removeProperty("--radix-toast-swipe-move-x"), n.currentTarget.style.removeProperty("--radix-toast-swipe-move-y"), n.currentTarget.style.setProperty("--radix-toast-swipe-end-x", `${y}px`), n.currentTarget.style.setProperty("--radix-toast-swipe-end-y", `${w}px`), v(!1); }) } ) }); } ); pe.displayName = U; var [Je, Qe] = ce(U, { onClose() { } }), Ze = s.forwardRef( (e, r) => { const { __scopeToast: o, type: t = "foreground", duration: u, open: d, onClose: f, onEscapeKeyDown: m, onPause: v, onResume: n, onSwipeStart: y, onSwipeMove: w, onSwipeCancel: S, onSwipeEnd: g, ...R } = e, l = $(U, o), [a, h] = s.useState(null), p = ae(r, (i) => h(i)), T = s.useRef(null), E = s.useRef(null), C = u || l.duration, P = s.useRef(0), N = s.useRef(C), M = s.useRef(0), { onToastAdd: F, onToastRemove: Y } = l, _ = X(() => { var x; (a == null ? void 0 : a.contains(document.activeElement)) && ((x = l.viewport) == null || x.focus()), f(); }), A = s.useCallback( (i) => { !i || i === 1 / 0 || (window.clearTimeout(M.current), P.current = (/* @__PURE__ */ new Date()).getTime(), M.current = window.setTimeout(_, i)); }, [_] ); s.useEffect(() => { const i = l.viewport; if (i) { const x = () => { A(N.current), n == null || n(); }, I = () => { const O = (/* @__PURE__ */ new Date()).getTime() - P.current; N.current = N.current - O, window.clearTimeout(M.current), v == null || v(); }; return i.addEventListener(G, I), i.addEventListener(J, x), () => { i.removeEventListener(G, I), i.removeEventListener(J, x); }; } }, [l.viewport, C, v, n, A]), s.useEffect(() => { d && !l.isClosePausedRef.current && A(C); }, [d, C, l.isClosePausedRef, A]), s.useEffect(() => (F(), () => Y()), [F, Y]); const V = s.useMemo(() => a ? Ce(a) : null, [a]); return l.viewport ? /* @__PURE__ */ D(se, { children: [ V && /* @__PURE__ */ c( et, { __scopeToast: o, role: "status", "aria-live": t === "foreground" ? "assertive" : "polite", "aria-atomic": !0, children: V } ), /* @__PURE__ */ c(Je, { scope: o, onClose: _, children: Se.createPortal( /* @__PURE__ */ c(ee.ItemSlot, { scope: o, children: /* @__PURE__ */ c( Le, { asChild: !0, onEscapeKeyDown: b(m, () => { l.isFocusedToastEscapeKeyDownRef.current || _(), l.isFocusedToastEscapeKeyDownRef.current = !1; }), children: /* @__PURE__ */ c( L.li, { role: "status", "aria-live": "off", "aria-atomic": !0, tabIndex: 0, "data-state": d ? "open" : "closed", "data-swipe-direction": l.swipeDirection, ...R, ref: p, style: { userSelect: "none", touchAction: "none", ...e.style }, onKeyDown: b(e.onKeyDown, (i) => { i.key === "Escape" && (m == null || m(i.nativeEvent), i.nativeEvent.defaultPrevented || (l.isFocusedToastEscapeKeyDownRef.current = !0, _())); }), onPointerDown: b(e.onPointerDown, (i) => { i.button === 0 && (T.current = { x: i.clientX, y: i.clientY }); }), onPointerMove: b(e.onPointerMove, (i) => { if (!T.current) return; const x = i.clientX - T.current.x, I = i.clientY - T.current.y, O = !!E.current, k = ["left", "right"].includes(l.swipeDirection), K = ["left", "up"].includes(l.swipeDirection) ? Math.min : Math.max, Pe = k ? K(0, x) : 0, xe = k ? 0 : K(0, I), B = i.pointerType === "touch" ? 10 : 2, H = { x: Pe, y: xe }, te = { originalEvent: i, delta: H }; O ? (E.current = H, W(qe, w, te, { discrete: !1 })) : ne(H, l.swipeDirection, B) ? (E.current = H, W(je, y, te, { discrete: !1 }), i.target.setPointerCapture(i.pointerId)) : (Math.abs(x) > B || Math.abs(I) > B) && (T.current = null); }), onPointerUp: b(e.onPointerUp, (i) => { const x = E.current, I = i.target; if (I.hasPointerCapture(i.pointerId) && I.releasePointerCapture(i.pointerId), E.current = null, T.current = null, x) { const O = i.currentTarget, k = { originalEvent: i, delta: x }; ne(x, l.swipeDirection, l.swipeThreshold) ? W(Ge, g, k, { discrete: !0 }) : W( ze, S, k, { discrete: !0 } ), O.addEventListener("click", (K) => K.preventDefault(), { once: !0 }); } }) } ) } ) }), l.viewport ) }) ] }) : null; } ), et = (e) => { const { __scopeToast: r, children: o, ...t } = e, u = $(U, r), [d, f] = s.useState(!1), [m, v] = s.useState(!1); return rt(() => f(!0)), s.useEffect(() => { const n = window.setTimeout(() => v(!0), 1e3); return () => window.clearTimeout(n); }, []), m ? null : /* @__PURE__ */ c(Me, { asChild: !0, children: /* @__PURE__ */ c(ie, { ...t, children: d && /* @__PURE__ */ D(se, { children: [ u.label, " ", o ] }) }) }); }, tt = "ToastTitle", me = s.forwardRef( (e, r) => { const { __scopeToast: o, ...t } = e; return /* @__PURE__ */ c(L.div, { ...t, ref: r }); } ); me.displayName = tt; var ot = "ToastDescription", Te = s.forwardRef( (e, r) => { const { __scopeToast: o, ...t } = e; return /* @__PURE__ */ c(L.div, { ...t, ref: r }); } ); Te.displayName = ot; var ve = "ToastAction", we = s.forwardRef( (e, r) => { const { altText: o, ...t } = e; return o.trim() ? /* @__PURE__ */ c(ye, { altText: o, asChild: !0, children: /* @__PURE__ */ c(he, { ...t, ref: r }) }) : (console.error( `Invalid prop \`altText\` supplied to \`${ve}\`. Expected non-empty \`string\`.` ), null); } ); we.displayName = ve; var Ee = "ToastClose", he = s.forwardRef( (e, r) => { const { __scopeToast: o, ...t } = e, u = Qe(Ee, o); return /* @__PURE__ */ c(ye, { asChild: !0, children: /* @__PURE__ */ c( L.button, { type: "button", ...t, ref: r, onClick: b(e.onClick, u.onClose) } ) }); } ); he.displayName = Ee; var ye = s.forwardRef((e, r) => { const { __scopeToast: o, altText: t, ...u } = e; return /* @__PURE__ */ c( L.div, { "data-radix-toast-announce-exclude": "", "data-radix-toast-announce-alt": t || void 0, ...u, ref: r } ); }); function Ce(e) { const r = []; return Array.from(e.childNodes).forEach((t) => { if (t.nodeType === t.TEXT_NODE && t.textContent && r.push(t.textContent), nt(t)) { const u = t.ariaHidden || t.hidden || t.style.display === "none", d = t.dataset.radixToastAnnounceExclude === ""; if (!u) if (d) { const f = t.dataset.radixToastAnnounceAlt; f && r.push(f); } else r.push(...Ce(t)); } }), r; } function W(e, r, o, { discrete: t }) { const u = o.originalEvent.currentTarget, d = new CustomEvent(e, { bubbles: !0, cancelable: !0, detail: o }); r && u.addEventListener(e, r, { once: !0 }), t ? Ie(u, d) : u.dispatchEvent(d); } var ne = (e, r, o = 0) => { const t = Math.abs(e.x), u = Math.abs(e.y), d = t > u; return r === "left" || r === "right" ? d && t > o : !d && u > o; }; function rt(e = () => { }) { const r = X(e); Fe(() => { let o = 0, t = 0; return o = window.requestAnimationFrame(() => t = window.requestAnimationFrame(r)), () => { window.cancelAnimationFrame(o), window.cancelAnimationFrame(t); }; }, [r]); } function nt(e) { return e.nodeType === e.ELEMENT_NODE; } function st(e) { const r = [], o = document.createTreeWalker(e, NodeFilter.SHOW_ELEMENT, { acceptNode: (t) => { const u = t.tagName === "INPUT" && t.type === "hidden"; return t.disabled || t.hidden || u ? NodeFilter.FILTER_SKIP : t.tabIndex >= 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP; } }); for (; o.nextNode(); ) r.push(o.currentNode); return r; } function z(e) { const r = document.activeElement; return e.some((o) => o === r ? !0 : (o.focus(), document.activeElement !== r)); } var at = ue, it = de, ct = pe, ut = me, lt = Te, dt = we; const gt = ({ title: e, duration: r = 5e3, titleClassName: o, descriptionClassName: t, description: u, children: d, theme: f, showCloseButton: m = !0, closeButtonClassName: v, className: n, open: y = !1, setOpen: w }) => { const S = Re(0), { theme: g } = Xe(), R = f ?? g; be(() => () => clearTimeout(S.current), []); const l = oe(() => re(e) ? /* @__PURE__ */ c(j, { className: o, children: e }) : e, [e, o]), a = oe(() => re(u) ? /* @__PURE__ */ c(j, { className: t, children: u }) : u, [u, t]), h = ge(() => { w(!1), S.current = window.setTimeout(() => w(!0), 100); }, [w]); return /* @__PURE__ */ D(at, { swipeDirection: "right", duration: r, children: [ /* @__PURE__ */ c(j, { onClick: h, children: d }), /* @__PURE__ */ D( ct, { className: q(Ke({ theme: R, className: n })), open: y, onOpenChange: w, children: [ /* @__PURE__ */ c(ut, { asChild: !0, className: o, children: l }), a && /* @__PURE__ */ c(lt, { asChild: !0, children: a }), m && /* @__PURE__ */ c(dt, { asChild: !0, altText: "Close the toast", children: /* @__PURE__ */ D("button", { type: "button", className: "absolute right-1.5 top-1.5", children: [ /* @__PURE__ */ c( We, { className: q( Ve({ theme: R, className: v }) ) } ), /* @__PURE__ */ c(ke, { children: "Close toast" }) ] }) }) ] } ), /* @__PURE__ */ c( it, { className: q(He({ theme: R })) } ) ] }); }; export { gt as Toast };