@konstructio/ui
Version:
A set of reusable and customizable React components built for konstruct.io
507 lines (506 loc) • 18.8 kB
JavaScript
import { jsx as i, jsxs as A, Fragment as ae } from "react/jsx-runtime";
import { S as B } from "../../index-BvoZGpli.js";
import * as n from "react";
import { useRef as xe, useEffect as be, useMemo as re, isValidElement as ne, useCallback as ge } from "react";
import * as Se from "react-dom";
import { P as D, c as Ne, a as Ie, b as x, d as Ae, u as De } from "../../index-DKfEnhKr.js";
import { u as ie } from "../../index-DLcqcWxM.js";
import { c as _e } from "../../index-BG8O18ZY.js";
import { B as Fe, R as Le } from "../../index-BlSRBdPy.js";
import { P as Me } from "../../index-DMb4KD0b.js";
import { P as Oe } from "../../index-AV6ZtGhy.js";
import { u as X } from "../../index-0ioNhtNM.js";
import { R as ke } from "../../index-BKjcReYh.js";
import { cn as j } from "../../utils/index.js";
import { closeToastVariants as Ve, toastVariants as Ke, viewportToastVariants as He } from "./Toast.variants.js";
import { X as We } from "../../x-Eoa9FJjA.js";
var Ue = Object.freeze({
// See: https://github.com/twbs/bootstrap/blob/main/scss/mixins/_visually-hidden.scss
position: "absolute",
border: 0,
width: 1,
height: 1,
padding: 0,
margin: -1,
overflow: "hidden",
clip: "rect(0, 0, 0, 0)",
whiteSpace: "nowrap",
wordWrap: "normal"
}), Xe = "VisuallyHidden", Q = n.forwardRef(
(e, o) => /* @__PURE__ */ i(
D.span,
{
...e,
ref: o,
style: { ...Ue, ...e.style }
}
)
);
Q.displayName = Xe;
var Z = "ToastProvider", [ee, Ye, $e] = _e("Toast"), [ce, St] = Ne("Toast", [$e]), [Be, Y] = ce(Z), ue = (e) => {
const {
__scopeToast: o,
label: r = "Notification",
duration: t = 5e3,
swipeDirection: u = "right",
swipeThreshold: d = 50,
children: f
} = e, [w, v] = n.useState(null), [c, E] = n.useState(0), T = n.useRef(!1), N = n.useRef(!1);
return r.trim() || console.error(
`Invalid prop \`label\` supplied to \`${Z}\`. Expected non-empty \`string\`.`
), /* @__PURE__ */ i(ee.Provider, { scope: o, children: /* @__PURE__ */ i(
Be,
{
scope: o,
label: r,
duration: t,
swipeDirection: u,
swipeThreshold: d,
toastCount: c,
viewport: w,
onViewportChange: v,
onToastAdd: n.useCallback(() => E((R) => R + 1), []),
onToastRemove: n.useCallback(() => E((R) => R - 1), []),
isFocusedToastEscapeKeyDownRef: T,
isClosePausedRef: N,
children: f
}
) });
};
ue.displayName = Z;
var le = "ToastViewport", je = ["F8"], z = "toast.viewportPause", G = "toast.viewportResume", de = n.forwardRef(
(e, o) => {
const {
__scopeToast: r,
hotkey: t = je,
label: u = "Notifications ({hotkey})",
...d
} = e, f = Y(le, r), w = Ye(r), v = n.useRef(null), c = n.useRef(null), E = n.useRef(null), T = n.useRef(null), N = ie(o, T, f.onViewportChange), R = t.join("+").replace(/Key/g, "").replace(/Digit/g, ""), b = f.toastCount > 0;
n.useEffect(() => {
const s = (h) => {
t.length !== 0 && t.every((m) => h[m] || h.code === m) && T.current?.focus();
};
return document.addEventListener("keydown", s), () => document.removeEventListener("keydown", s);
}, [t]), n.useEffect(() => {
const s = v.current, h = T.current;
if (b && s && h) {
const p = () => {
if (!f.isClosePausedRef.current) {
const y = new CustomEvent(z);
h.dispatchEvent(y), f.isClosePausedRef.current = !0;
}
}, m = () => {
if (f.isClosePausedRef.current) {
const y = new CustomEvent(G);
h.dispatchEvent(y), f.isClosePausedRef.current = !1;
}
}, P = (y) => {
!s.contains(y.relatedTarget) && m();
}, C = () => {
s.contains(document.activeElement) || m();
};
return s.addEventListener("focusin", p), s.addEventListener("focusout", P), s.addEventListener("pointermove", p), s.addEventListener("pointerleave", C), window.addEventListener("blur", p), window.addEventListener("focus", m), () => {
s.removeEventListener("focusin", p), s.removeEventListener("focusout", P), s.removeEventListener("pointermove", p), s.removeEventListener("pointerleave", C), window.removeEventListener("blur", p), window.removeEventListener("focus", m);
};
}
}, [b, f.isClosePausedRef]);
const l = n.useCallback(
({ tabbingDirection: s }) => {
const p = w().map((m) => {
const P = m.ref.current, C = [P, ...at(P)];
return s === "forwards" ? C : C.reverse();
});
return (s === "forwards" ? p.reverse() : p).flat();
},
[w]
);
return n.useEffect(() => {
const s = T.current;
if (s) {
const h = (p) => {
const m = p.altKey || p.ctrlKey || p.metaKey;
if (p.key === "Tab" && !m) {
const C = document.activeElement, y = p.shiftKey;
if (p.target === s && y) {
c.current?.focus();
return;
}
const F = l({ tabbingDirection: y ? "backwards" : "forwards" }), V = F.findIndex((I) => I === C);
q(F.slice(V + 1)) ? p.preventDefault() : y ? c.current?.focus() : E.current?.focus();
}
};
return s.addEventListener("keydown", h), () => s.removeEventListener("keydown", h);
}
}, [w, l]), /* @__PURE__ */ A(
Fe,
{
ref: v,
role: "region",
"aria-label": u.replace("{hotkey}", R),
tabIndex: -1,
style: { pointerEvents: b ? void 0 : "none" },
children: [
b && /* @__PURE__ */ i(
J,
{
ref: c,
onFocusFromOutsideViewport: () => {
const s = l({
tabbingDirection: "forwards"
});
q(s);
}
}
),
/* @__PURE__ */ i(ee.Slot, { scope: r, children: /* @__PURE__ */ i(D.ol, { tabIndex: -1, ...d, ref: N }) }),
b && /* @__PURE__ */ i(
J,
{
ref: E,
onFocusFromOutsideViewport: () => {
const s = l({
tabbingDirection: "backwards"
});
q(s);
}
}
)
]
}
);
}
);
de.displayName = le;
var fe = "ToastFocusProxy", J = n.forwardRef(
(e, o) => {
const { __scopeToast: r, onFocusFromOutsideViewport: t, ...u } = e, d = Y(fe, r);
return /* @__PURE__ */ i(
Q,
{
tabIndex: 0,
...u,
ref: o,
style: { position: "fixed" },
onFocus: (f) => {
const w = f.relatedTarget;
!d.viewport?.contains(w) && t();
}
}
);
}
);
J.displayName = fe;
var O = "Toast", qe = "toast.swipeStart", ze = "toast.swipeMove", Ge = "toast.swipeCancel", Je = "toast.swipeEnd", pe = n.forwardRef(
(e, o) => {
const { forceMount: r, open: t, defaultOpen: u, onOpenChange: d, ...f } = e, [w, v] = Ie({
prop: t,
defaultProp: u ?? !0,
onChange: d,
caller: O
});
return /* @__PURE__ */ i(Oe, { present: r || w, children: /* @__PURE__ */ i(
et,
{
open: w,
...f,
ref: o,
onClose: () => v(!1),
onPause: X(e.onPause),
onResume: X(e.onResume),
onSwipeStart: x(e.onSwipeStart, (c) => {
c.currentTarget.setAttribute("data-swipe", "start");
}),
onSwipeMove: x(e.onSwipeMove, (c) => {
const { x: E, y: T } = c.detail.delta;
c.currentTarget.setAttribute("data-swipe", "move"), c.currentTarget.style.setProperty("--radix-toast-swipe-move-x", `${E}px`), c.currentTarget.style.setProperty("--radix-toast-swipe-move-y", `${T}px`);
}),
onSwipeCancel: x(e.onSwipeCancel, (c) => {
c.currentTarget.setAttribute("data-swipe", "cancel"), c.currentTarget.style.removeProperty("--radix-toast-swipe-move-x"), c.currentTarget.style.removeProperty("--radix-toast-swipe-move-y"), c.currentTarget.style.removeProperty("--radix-toast-swipe-end-x"), c.currentTarget.style.removeProperty("--radix-toast-swipe-end-y");
}),
onSwipeEnd: x(e.onSwipeEnd, (c) => {
const { x: E, y: T } = c.detail.delta;
c.currentTarget.setAttribute("data-swipe", "end"), c.currentTarget.style.removeProperty("--radix-toast-swipe-move-x"), c.currentTarget.style.removeProperty("--radix-toast-swipe-move-y"), c.currentTarget.style.setProperty("--radix-toast-swipe-end-x", `${E}px`), c.currentTarget.style.setProperty("--radix-toast-swipe-end-y", `${T}px`), v(!1);
})
}
) });
}
);
pe.displayName = O;
var [Qe, Ze] = ce(O, {
onClose() {
}
}), et = n.forwardRef(
(e, o) => {
const {
__scopeToast: r,
type: t = "foreground",
duration: u,
open: d,
onClose: f,
onEscapeKeyDown: w,
onPause: v,
onResume: c,
onSwipeStart: E,
onSwipeMove: T,
onSwipeCancel: N,
onSwipeEnd: R,
...b
} = e, l = Y(O, r), [s, h] = n.useState(null), p = ie(o, (a) => h(a)), m = n.useRef(null), P = n.useRef(null), C = u || l.duration, y = n.useRef(0), _ = n.useRef(C), k = n.useRef(0), { onToastAdd: F, onToastRemove: V } = l, I = X(() => {
s?.contains(document.activeElement) && l.viewport?.focus(), f();
}), K = n.useCallback(
(a) => {
!a || a === 1 / 0 || (window.clearTimeout(k.current), y.current = (/* @__PURE__ */ new Date()).getTime(), k.current = window.setTimeout(I, a));
},
[I]
);
n.useEffect(() => {
const a = l.viewport;
if (a) {
const g = () => {
K(_.current), c?.();
}, S = () => {
const L = (/* @__PURE__ */ new Date()).getTime() - y.current;
_.current = _.current - L, window.clearTimeout(k.current), v?.();
};
return a.addEventListener(z, S), a.addEventListener(G, g), () => {
a.removeEventListener(z, S), a.removeEventListener(G, g);
};
}
}, [l.viewport, C, v, c, K]), n.useEffect(() => {
d && !l.isClosePausedRef.current && K(C);
}, [d, C, l.isClosePausedRef, K]), n.useEffect(() => (F(), () => V()), [F, V]);
const te = n.useMemo(() => s ? Pe(s) : null, [s]);
return l.viewport ? /* @__PURE__ */ A(ae, { children: [
te && /* @__PURE__ */ i(
tt,
{
__scopeToast: r,
role: "status",
"aria-live": t === "foreground" ? "assertive" : "polite",
children: te
}
),
/* @__PURE__ */ i(Qe, { scope: r, onClose: I, children: Se.createPortal(
/* @__PURE__ */ i(ee.ItemSlot, { scope: r, children: /* @__PURE__ */ i(
Le,
{
asChild: !0,
onEscapeKeyDown: x(w, () => {
l.isFocusedToastEscapeKeyDownRef.current || I(), l.isFocusedToastEscapeKeyDownRef.current = !1;
}),
children: /* @__PURE__ */ i(
D.li,
{
tabIndex: 0,
"data-state": d ? "open" : "closed",
"data-swipe-direction": l.swipeDirection,
...b,
ref: p,
style: { userSelect: "none", touchAction: "none", ...e.style },
onKeyDown: x(e.onKeyDown, (a) => {
a.key === "Escape" && (w?.(a.nativeEvent), a.nativeEvent.defaultPrevented || (l.isFocusedToastEscapeKeyDownRef.current = !0, I()));
}),
onPointerDown: x(e.onPointerDown, (a) => {
a.button === 0 && (m.current = { x: a.clientX, y: a.clientY });
}),
onPointerMove: x(e.onPointerMove, (a) => {
if (!m.current) return;
const g = a.clientX - m.current.x, S = a.clientY - m.current.y, L = !!P.current, M = ["left", "right"].includes(l.swipeDirection), H = ["left", "up"].includes(l.swipeDirection) ? Math.min : Math.max, Ce = M ? H(0, g) : 0, Re = M ? 0 : H(0, S), $ = a.pointerType === "touch" ? 10 : 2, W = { x: Ce, y: Re }, oe = { originalEvent: a, delta: W };
L ? (P.current = W, U(ze, T, oe, {
discrete: !1
})) : se(W, l.swipeDirection, $) ? (P.current = W, U(qe, E, oe, {
discrete: !1
}), a.target.setPointerCapture(a.pointerId)) : (Math.abs(g) > $ || Math.abs(S) > $) && (m.current = null);
}),
onPointerUp: x(e.onPointerUp, (a) => {
const g = P.current, S = a.target;
if (S.hasPointerCapture(a.pointerId) && S.releasePointerCapture(a.pointerId), P.current = null, m.current = null, g) {
const L = a.currentTarget, M = { originalEvent: a, delta: g };
se(g, l.swipeDirection, l.swipeThreshold) ? U(Je, R, M, {
discrete: !0
}) : U(
Ge,
N,
M,
{
discrete: !0
}
), L.addEventListener("click", (H) => H.preventDefault(), {
once: !0
});
}
})
}
)
}
) }),
l.viewport
) })
] }) : null;
}
), tt = (e) => {
const { __scopeToast: o, children: r, ...t } = e, u = Y(O, o), [d, f] = n.useState(!1), [w, v] = n.useState(!1);
return nt(() => f(!0)), n.useEffect(() => {
const c = window.setTimeout(() => v(!0), 1e3);
return () => window.clearTimeout(c);
}, []), w ? null : /* @__PURE__ */ i(Me, { asChild: !0, children: /* @__PURE__ */ i(Q, { ...t, children: d && /* @__PURE__ */ A(ae, { children: [
u.label,
" ",
r
] }) }) });
}, ot = "ToastTitle", me = n.forwardRef(
(e, o) => {
const { __scopeToast: r, ...t } = e;
return /* @__PURE__ */ i(D.div, { ...t, ref: o });
}
);
me.displayName = ot;
var rt = "ToastDescription", we = n.forwardRef(
(e, o) => {
const { __scopeToast: r, ...t } = e;
return /* @__PURE__ */ i(D.div, { ...t, ref: o });
}
);
we.displayName = rt;
var Te = "ToastAction", ve = n.forwardRef(
(e, o) => {
const { altText: r, ...t } = e;
return r.trim() ? /* @__PURE__ */ i(he, { altText: r, asChild: !0, children: /* @__PURE__ */ i(ye, { ...t, ref: o }) }) : (console.error(
`Invalid prop \`altText\` supplied to \`${Te}\`. Expected non-empty \`string\`.`
), null);
}
);
ve.displayName = Te;
var Ee = "ToastClose", ye = n.forwardRef(
(e, o) => {
const { __scopeToast: r, ...t } = e, u = Ze(Ee, r);
return /* @__PURE__ */ i(he, { asChild: !0, children: /* @__PURE__ */ i(
D.button,
{
type: "button",
...t,
ref: o,
onClick: x(e.onClick, u.onClose)
}
) });
}
);
ye.displayName = Ee;
var he = n.forwardRef((e, o) => {
const { __scopeToast: r, altText: t, ...u } = e;
return /* @__PURE__ */ i(
D.div,
{
"data-radix-toast-announce-exclude": "",
"data-radix-toast-announce-alt": t || void 0,
...u,
ref: o
}
);
});
function Pe(e) {
const o = [];
return Array.from(e.childNodes).forEach((t) => {
if (t.nodeType === t.TEXT_NODE && t.textContent && o.push(t.textContent), st(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 && o.push(f);
} else
o.push(...Pe(t));
}
}), o;
}
function U(e, o, r, { discrete: t }) {
const u = r.originalEvent.currentTarget, d = new CustomEvent(e, { bubbles: !0, cancelable: !0, detail: r });
o && u.addEventListener(e, o, { once: !0 }), t ? Ae(u, d) : u.dispatchEvent(d);
}
var se = (e, o, r = 0) => {
const t = Math.abs(e.x), u = Math.abs(e.y), d = t > u;
return o === "left" || o === "right" ? d && t > r : !d && u > r;
};
function nt(e = () => {
}) {
const o = X(e);
De(() => {
let r = 0, t = 0;
return r = window.requestAnimationFrame(() => t = window.requestAnimationFrame(o)), () => {
window.cancelAnimationFrame(r), window.cancelAnimationFrame(t);
};
}, [o]);
}
function st(e) {
return e.nodeType === e.ELEMENT_NODE;
}
function at(e) {
const o = [], r = 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 (; r.nextNode(); ) o.push(r.currentNode);
return o;
}
function q(e) {
const o = document.activeElement;
return e.some((r) => r === o ? !0 : (r.focus(), document.activeElement !== o));
}
var it = ue, ct = de, ut = pe, lt = me, dt = we, ft = ve;
const Nt = ({
title: e,
duration: o = 5e3,
titleClassName: r,
descriptionClassName: t,
description: u,
children: d,
theme: f,
showCloseButton: w = !0,
closeButtonClassName: v,
className: c,
open: E = !1,
setOpen: T,
variant: N
}) => {
const R = xe(0);
be(() => () => clearTimeout(R.current), []);
const b = re(() => ne(e) ? /* @__PURE__ */ i(B, { className: r, children: e }) : e, [e, r]), l = re(() => ne(u) ? /* @__PURE__ */ i(B, { className: t, children: u }) : u, [u, t]), s = ge(() => {
T(!1), R.current = window.setTimeout(() => T(!0), 100);
}, [T]);
return /* @__PURE__ */ A(it, { swipeDirection: "right", duration: o, children: [
/* @__PURE__ */ i(B, { onClick: s, children: d }),
/* @__PURE__ */ A(
ut,
{
className: j(Ke({ variant: N, className: c })),
"data-theme": f,
open: E,
onOpenChange: T,
children: [
/* @__PURE__ */ A("div", { className: "flex gap-2 items-center flex-1", children: [
/* @__PURE__ */ i(lt, { asChild: !0, className: r, children: b }),
l && /* @__PURE__ */ i(dt, { asChild: !0, children: l })
] }),
w && /* @__PURE__ */ i(ft, { asChild: !0, altText: "Close the toast", children: /* @__PURE__ */ A("button", { type: "button", className: "absolute right-1.5 top-1.5", children: [
/* @__PURE__ */ i(
We,
{
className: j(
Ve({
className: v
})
)
}
),
/* @__PURE__ */ i(ke, { children: "Close toast" })
] }) })
]
}
),
/* @__PURE__ */ i(ct, { className: j(He()) })
] });
};
export {
Nt as Toast
};