@cystackapp/ui 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +105 -0
  2. package/dist/components/badge/Badge.js +3 -3
  3. package/dist/components/badge/variants/BadgeTag.js +1 -1
  4. package/dist/components/button/Button.d.ts +21 -0
  5. package/dist/components/button/Button.js +49 -0
  6. package/dist/components/button/ButtonLoader.d.ts +7 -0
  7. package/dist/components/button/ButtonLoader.js +44 -0
  8. package/dist/components/button/ButtonTestStory.d.ts +5 -0
  9. package/dist/components/button/button-variants.d.ts +13 -0
  10. package/dist/components/button/button-variants.js +58 -0
  11. package/dist/components/card/Card.d.ts +91 -0
  12. package/dist/components/card/Card.js +56 -0
  13. package/dist/components/card/Card.stories-ct.d.ts +1 -0
  14. package/dist/components/card/CardBody.d.ts +9 -0
  15. package/dist/components/card/CardBody.js +16 -0
  16. package/dist/components/card/CardHeader.d.ts +15 -0
  17. package/dist/components/card/CardHeader.js +79 -0
  18. package/dist/components/card/types.d.ts +1 -0
  19. package/dist/components/checkbox/Checkbox.d.ts +6 -0
  20. package/dist/components/checkbox/Checkbox.js +72 -0
  21. package/dist/components/checkbox/CheckboxTestStory.d.ts +7 -0
  22. package/dist/components/collapsible/Collapsible.d.ts +21 -0
  23. package/dist/components/collapsible/Collapsible.js +50 -0
  24. package/dist/components/input/Input.d.ts +11 -0
  25. package/dist/components/input/Input.js +39 -0
  26. package/dist/components/modal/Modal.d.ts +9 -0
  27. package/dist/components/modal/Modal.js +68 -0
  28. package/dist/components/modal/helpers/HeaderIcon.d.ts +8 -0
  29. package/dist/components/modal/helpers/HeaderIcon.js +32 -0
  30. package/dist/components/modal/helpers/Title.d.ts +6 -0
  31. package/dist/components/modal/helpers/Title.js +9 -0
  32. package/dist/components/modal/helpers/circles-sm.svg.js +5 -0
  33. package/dist/components/modal/modal-context.d.ts +2 -0
  34. package/dist/components/modal/modal-context.js +9 -0
  35. package/dist/components/modal/use-click-outside-modal.d.ts +2 -0
  36. package/dist/components/modal/use-click-outside-modal.js +15 -0
  37. package/dist/components/toast/ToastSlice.d.ts +11 -0
  38. package/dist/components/toast/ToastSlice.js +103 -0
  39. package/dist/components/toast/icons.d.ts +8 -0
  40. package/dist/components/toast/icons.js +19 -0
  41. package/dist/components/toast/index.d.ts +4 -0
  42. package/dist/components/toast/index.js +35 -0
  43. package/dist/components/toast/types.d.ts +14 -0
  44. package/dist/components/toast/use-toast-list.d.ts +4 -0
  45. package/dist/components/toast/use-toast-list.js +27 -0
  46. package/dist/index.d.ts +14 -0
  47. package/dist/index.js +55 -34
  48. package/dist/test-utils/expect-visibility.d.ts +45 -0
  49. package/dist/utils/observable.d.ts +7 -0
  50. package/dist/utils/observable.js +22 -0
  51. package/package.json +3 -2
  52. package/theme.css +3 -0
@@ -0,0 +1,72 @@
1
+ import { jsxs as l, jsx as s } from "react/jsx-runtime";
2
+ import { Check as d, Minus as b } from "@untitled-ui/icons-react";
3
+ import { forwardRef as u } from "react";
4
+ import { cn as t } from "../../utils/cn.js";
5
+ const c = u(
6
+ ({ checked: a, indeterminate: o, className: r, ...e }, n) => {
7
+ const i = !!o && !a;
8
+ return /* @__PURE__ */ l(
9
+ "label",
10
+ {
11
+ className: t(
12
+ "relative size-5 shrink-0 block rounded-md bg-white transition-all ease-out border overflow-hidden",
13
+ a || i ? e.disabled ? "border-gray-v2-300" : "border-brand-v2-600" : "border-gray-v2-300",
14
+ { "bg-gray-v2-50": e.disabled },
15
+ r
16
+ ),
17
+ children: [
18
+ /* @__PURE__ */ s(
19
+ "input",
20
+ {
21
+ ref: n,
22
+ ...e,
23
+ checked: a,
24
+ className: t(
25
+ "absolute top-0 left-0 z-10 size-full rounded-md appearance-none",
26
+ "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand-v2-400",
27
+ e.disabled ? "cursor-not-allowed" : "cursor-pointer"
28
+ ),
29
+ type: "checkbox"
30
+ }
31
+ ),
32
+ /* @__PURE__ */ l(
33
+ "span",
34
+ {
35
+ className: t(
36
+ "relative size-full transition-all ease-out rounded-0.5 flex justify-center items-center",
37
+ { "bg-brand-v2-600": !e.disabled },
38
+ { "scale-[40%] opacity-0 rotate-12": !(a || i) }
39
+ ),
40
+ children: [
41
+ /* @__PURE__ */ s(
42
+ d,
43
+ {
44
+ className: t(
45
+ "absolute size-[70%] transition-all ease-out",
46
+ e.disabled ? "text-gray-v2-300" : "text-white",
47
+ { "scale-0": !a }
48
+ )
49
+ }
50
+ ),
51
+ /* @__PURE__ */ s(
52
+ b,
53
+ {
54
+ className: t(
55
+ "absolute size-[70%] transition-all ease-out",
56
+ e.disabled ? "text-gray-v2-300" : "text-white",
57
+ { "scale-0": !i }
58
+ )
59
+ }
60
+ )
61
+ ]
62
+ }
63
+ )
64
+ ]
65
+ }
66
+ );
67
+ }
68
+ );
69
+ c.displayName = "Checkbox";
70
+ export {
71
+ c as Checkbox
72
+ };
@@ -0,0 +1,7 @@
1
+ export declare function CheckboxUnchecked(): import("react/jsx-runtime").JSX.Element;
2
+ export declare function CheckboxChecked(): import("react/jsx-runtime").JSX.Element;
3
+ export declare function CheckboxIndeterminate(): import("react/jsx-runtime").JSX.Element;
4
+ export declare function CheckboxCheckedAndIndeterminate(): import("react/jsx-runtime").JSX.Element;
5
+ export declare function CheckboxDisabled(): import("react/jsx-runtime").JSX.Element;
6
+ export declare function CheckboxDisabledChecked(): import("react/jsx-runtime").JSX.Element;
7
+ export declare function CheckboxWithClickCounter(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,21 @@
1
+ import { ReactNode } from 'react';
2
+ interface Props {
3
+ expanded: boolean;
4
+ duration?: number;
5
+ className?: string;
6
+ children?: ReactNode;
7
+ }
8
+ /**
9
+ * Pure animated collapse container. No trigger, no label — just an outer
10
+ * grid whose row template animates between `0fr` and `1fr`, with a delayed
11
+ * `visibility` transition so collapsed content is unreachable by pointer,
12
+ * focus, and assistive tech once the fade finishes.
13
+ *
14
+ * Consumers own the toggle UI (e.g. `Accordion` wraps its own `role=button`
15
+ * label around this; `Card` keeps its collapse button in `CardHeader`).
16
+ *
17
+ * @param expanded - Whether the content is shown.
18
+ * @param duration - Transition duration in milliseconds (default: 300).
19
+ */
20
+ export declare const Collapsible: ({ expanded, duration, className, children, }: Props) => import("react/jsx-runtime").JSX.Element;
21
+ export {};
@@ -0,0 +1,50 @@
1
+ import { jsx as r } from "react/jsx-runtime";
2
+ import { useState as f, useEffect as c } from "react";
3
+ import { cn as s } from "../../utils/cn.js";
4
+ const g = ({
5
+ expanded: i,
6
+ duration: n = 300,
7
+ className: e,
8
+ children: a
9
+ }) => {
10
+ const t = `${n}ms`, [l, o] = f(
11
+ i ? "visible" : "hidden"
12
+ );
13
+ return c(() => {
14
+ i && o("visible");
15
+ }, [i]), /* @__PURE__ */ r(
16
+ "div",
17
+ {
18
+ className: s(
19
+ "grid motion-safe:transition-[grid-template-rows] ease-out",
20
+ i ? "grid-rows-[1fr]" : "grid-rows-[0fr]",
21
+ e
22
+ ),
23
+ style: { transitionDuration: t },
24
+ onTransitionEnd: (m) => {
25
+ m.propertyName === "grid-template-rows" && !i && o("hidden");
26
+ },
27
+ children: /* @__PURE__ */ r(
28
+ "div",
29
+ {
30
+ className: s("min-h-0", {
31
+ "invisible opacity-0": !i
32
+ }),
33
+ style: {
34
+ overflow: l,
35
+ transitionProperty: "opacity, visibility",
36
+ transitionDuration: `${t}, 0s`,
37
+ transitionTimingFunction: "ease-out",
38
+ // Delay visibility so it hides only after the fade finishes.
39
+ // When expanding, no delay — content becomes visible immediately.
40
+ transitionDelay: i ? "0s, 0s" : `0s, ${t}`
41
+ },
42
+ children: a
43
+ }
44
+ )
45
+ }
46
+ );
47
+ };
48
+ export {
49
+ g as Collapsible
50
+ };
@@ -0,0 +1,11 @@
1
+ import { InputHTMLAttributes, ReactNode } from 'react';
2
+ interface Props extends Omit<InputHTMLAttributes<HTMLInputElement>, "prefix"> {
3
+ /** Marks the input as in an error state — switches the focus ring to error-v2. */
4
+ invalid?: boolean;
5
+ /** Content rendered before the input (e.g. an icon). */
6
+ prefix?: ReactNode;
7
+ /** Content rendered after the input (e.g. a unit label or clear button). */
8
+ suffix?: ReactNode;
9
+ }
10
+ export declare const Input: import('react').ForwardRefExoticComponent<Props & import('react').RefAttributes<HTMLInputElement>>;
11
+ export {};
@@ -0,0 +1,39 @@
1
+ import { jsxs as d, jsx as s } from "react/jsx-runtime";
2
+ import { forwardRef as u } from "react";
3
+ import { cn as c } from "../../utils/cn.js";
4
+ const e = {
5
+ default: "border-gray-v2-300 focus-within:border-brand-v2 focus-within:outline-brand-v2",
6
+ invalid: "border-error-v2-300 focus-within:border-error-v2 focus-within:outline-error-v2",
7
+ disabled: "bg-gray-v2-50 border-gray-v2-300 cursor-not-allowed"
8
+ }, p = u(
9
+ ({ invalid: o, prefix: a, suffix: n, className: i, disabled: r, ...t }, l) => /* @__PURE__ */ d(
10
+ "span",
11
+ {
12
+ className: c(
13
+ "bg-white rounded-lg border shadow-xs flex items-center gap-2 px-3 min-h-10 text-md transition-all outline outline-transparent",
14
+ o ? e.invalid : e.default,
15
+ { [e.disabled]: r },
16
+ i
17
+ ),
18
+ children: [
19
+ a,
20
+ /* @__PURE__ */ s(
21
+ "input",
22
+ {
23
+ ref: l,
24
+ disabled: r,
25
+ "aria-invalid": o,
26
+ className: "flex-1 min-w-0 bg-transparent outline-none text-gray-v2-900 placeholder:text-gray-v2-500 disabled:text-gray-v2-400 disabled:cursor-not-allowed",
27
+ ...t,
28
+ placeholder: r ? void 0 : t.placeholder
29
+ }
30
+ ),
31
+ n
32
+ ]
33
+ }
34
+ )
35
+ );
36
+ p.displayName = "Input";
37
+ export {
38
+ p as Input
39
+ };
@@ -0,0 +1,9 @@
1
+ import { ReactNode } from 'react';
2
+ interface Props {
3
+ isOpen: boolean;
4
+ onOpenChange: (open: boolean) => void;
5
+ children?: ReactNode;
6
+ className?: string;
7
+ }
8
+ export declare const Modal: ({ isOpen, onOpenChange, children, className }: Props) => import('react').ReactPortal;
9
+ export {};
@@ -0,0 +1,68 @@
1
+ import { jsx as r, jsxs as h } from "react/jsx-runtime";
2
+ import { useId as p, useRef as f, useCallback as x, useEffect as g } from "react";
3
+ import { createPortal as C } from "react-dom";
4
+ import { XClose as w } from "@untitled-ui/icons-react";
5
+ import { Button as E } from "../button/Button.js";
6
+ import { cn as u } from "../../utils/cn.js";
7
+ import { ModalContext as k } from "./modal-context.js";
8
+ import { useClickOutsideModal as A } from "./use-click-outside-modal.js";
9
+ const D = 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])', B = ({ isOpen: e, onOpenChange: a, children: m, className: b }) => {
10
+ const i = p(), n = f(null), o = f(null), y = (t) => {
11
+ if (!(!e || o.current === null) && (t.key === "Escape" && a(!1), t.key === "Tab")) {
12
+ const l = Array.from(
13
+ o.current.querySelectorAll(D)
14
+ ).filter((v) => !v.closest("[inert]"));
15
+ if (l.length === 0) return;
16
+ const c = l[0], d = l[l.length - 1];
17
+ t.shiftKey ? document.activeElement === c && (t.preventDefault(), d.focus()) : document.activeElement === d && (t.preventDefault(), c.focus());
18
+ }
19
+ }, s = x(
20
+ () => a(!1),
21
+ [a]
22
+ );
23
+ return A(s, n, [o]), g(() => (document.body.classList.toggle("overflow-hidden", e), () => document.body.classList.remove("overflow-hidden")), [e]), C(
24
+ /* @__PURE__ */ r(k.Provider, { value: i, children: /* @__PURE__ */ r(
25
+ "div",
26
+ {
27
+ ref: n,
28
+ className: u(
29
+ "fixed inset-0 flex items-center justify-center z-10 transition-opacity bg-gray-v2-950/48",
30
+ { "opacity-0 pointer-events-none": !e }
31
+ ),
32
+ onKeyDown: y,
33
+ children: /* @__PURE__ */ h(
34
+ "div",
35
+ {
36
+ ref: o,
37
+ role: "dialog",
38
+ "aria-modal": "true",
39
+ "aria-labelledby": i,
40
+ className: u(
41
+ "relative min-h-20 w-xl p-6 rounded-xl bg-white flex flex-col gap-5 overflow-hidden transition-all",
42
+ { "scale-90": !e },
43
+ b
44
+ ),
45
+ children: [
46
+ /* @__PURE__ */ r(
47
+ E,
48
+ {
49
+ variant: "tertiary",
50
+ color: "gray",
51
+ className: "absolute right-0 top-0 m-4",
52
+ onClick: s,
53
+ "aria-label": "Close",
54
+ children: /* @__PURE__ */ r(w, { className: "size-6 shrink-0 text-gray-v2-400" })
55
+ }
56
+ ),
57
+ m
58
+ ]
59
+ }
60
+ )
61
+ }
62
+ ) }),
63
+ document.body
64
+ );
65
+ };
66
+ export {
67
+ B as Modal
68
+ };
@@ -0,0 +1,8 @@
1
+ import { ReactNode, SVGProps } from 'react';
2
+ type IconType = "brand" | "gray" | "success" | "warning" | "error";
3
+ interface Props {
4
+ type?: IconType;
5
+ Icon: (props: SVGProps<SVGSVGElement>) => ReactNode;
6
+ }
7
+ export declare const ModalHeaderIcon: ({ type, Icon }: Props) => import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,32 @@
1
+ import { jsxs as o, jsx as e } from "react/jsx-runtime";
2
+ import "react";
3
+ import { cn as n } from "../../../utils/cn.js";
4
+ import a from "./circles-sm.svg.js";
5
+ const t = {
6
+ brand: "bg-brand-v2-100 border-brand-v2-50",
7
+ gray: "bg-gray-v2-100 border-gray-v2-50",
8
+ success: "bg-success-v2-100 border-success-v2-50",
9
+ warning: "bg-warning-v2-100 border-warning-v2-50",
10
+ error: "bg-error-v2-100 border-error-v2-50"
11
+ }, c = {
12
+ brand: "text-brand-v2-600",
13
+ gray: "text-gray-v2-600",
14
+ success: "text-success-v2-600",
15
+ warning: "text-warning-v2-600",
16
+ error: "text-error-v2-600"
17
+ }, g = ({ type: r = "brand", Icon: s }) => /* @__PURE__ */ o(
18
+ "div",
19
+ {
20
+ className: n(
21
+ "relative h-13 w-13 min-w-13 flex items-center justify-center rounded-full border-8",
22
+ t[r]
23
+ ),
24
+ children: [
25
+ /* @__PURE__ */ e(s, { className: n("h-6 w-6 min-w-6", c[r]) }),
26
+ /* @__PURE__ */ e(a, { className: "absolute h-84 w-84 min-w-84 pointer-events-none" })
27
+ ]
28
+ }
29
+ );
30
+ export {
31
+ g as ModalHeaderIcon
32
+ };
@@ -0,0 +1,6 @@
1
+ import { ReactNode } from 'react';
2
+ interface Props {
3
+ children: ReactNode;
4
+ }
5
+ export declare const ModalTitle: ({ children }: Props) => import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,9 @@
1
+ import { jsx as e } from "react/jsx-runtime";
2
+ import { useModalContext as r } from "../modal-context.js";
3
+ const i = ({ children: t }) => {
4
+ const o = r();
5
+ return /* @__PURE__ */ e("h2", { id: o, className: "text-lg font-semibold text-gray-v2-900", children: t });
6
+ };
7
+ export {
8
+ i as ModalTitle
9
+ };
@@ -0,0 +1,5 @@
1
+ import * as e from "react";
2
+ const r = (t) => /* @__PURE__ */ e.createElement("svg", { height: 336, width: 336, viewBox: "0 0 336 336", xmlns: "http://www.w3.org/2000/svg", ...t }, /* @__PURE__ */ e.createElement("defs", null, /* @__PURE__ */ e.createElement("radialGradient", { id: "radialGradient-mask", cx: "50%", cy: "50%", r: "50%", fx: "50%", fy: "50%" }, /* @__PURE__ */ e.createElement("stop", { offset: "0%", stopColor: "white" }), /* @__PURE__ */ e.createElement("stop", { offset: "100%", stopColor: "black" })), /* @__PURE__ */ e.createElement("mask", { id: "background-pattern-decorative-mask" }, /* @__PURE__ */ e.createElement("rect", { x: 0, y: 0, height: "100%", width: "100%", fill: "url(#radialGradient-mask)" }))), /* @__PURE__ */ e.createElement("g", { mask: "url(#background-pattern-decorative-mask)" }, /* @__PURE__ */ e.createElement("circle", { cx: 168, cy: 168, r: 168, stroke: "#E9EAEB", fill: "transparent" }), /* @__PURE__ */ e.createElement("circle", { cx: 168, cy: 168, r: 144, stroke: "#E9EAEB", fill: "transparent" }), /* @__PURE__ */ e.createElement("circle", { cx: 168, cy: 168, r: 120, stroke: "#E9EAEB", fill: "transparent" }), /* @__PURE__ */ e.createElement("circle", { cx: 168, cy: 168, r: 96, stroke: "#E9EAEB", fill: "transparent" }), /* @__PURE__ */ e.createElement("circle", { cx: 168, cy: 168, r: 72, stroke: "#E9EAEB", fill: "transparent" }), /* @__PURE__ */ e.createElement("circle", { cx: 168, cy: 168, r: 48, stroke: "#E9EAEB", fill: "transparent" })));
3
+ export {
4
+ r as default
5
+ };
@@ -0,0 +1,2 @@
1
+ export declare const ModalContext: import('react').Context<string | undefined>;
2
+ export declare function useModalContext(): string | undefined;
@@ -0,0 +1,9 @@
1
+ import { createContext as t, useContext as o } from "react";
2
+ const e = t(void 0);
3
+ function r() {
4
+ return o(e);
5
+ }
6
+ export {
7
+ e as ModalContext,
8
+ r as useModalContext
9
+ };
@@ -0,0 +1,2 @@
1
+ import { RefObject } from 'react';
2
+ export declare const useClickOutsideModal: (onClose: () => void, overlayRef: RefObject<HTMLDivElement>, modalRefs: RefObject<HTMLElement>[]) => void;
@@ -0,0 +1,15 @@
1
+ import { useEffect as u } from "react";
2
+ const d = (e, n, r) => {
3
+ u(() => {
4
+ function i(o) {
5
+ const { target: t } = o;
6
+ t instanceof Node && n.current && n.current.contains(t) && r.every((c) => !c.current || !c.current.contains(t)) && e();
7
+ }
8
+ return window.addEventListener("mousedown", i), () => {
9
+ window.removeEventListener("mousedown", i);
10
+ };
11
+ }, [n, r, e]);
12
+ };
13
+ export {
14
+ d as useClickOutsideModal
15
+ };
@@ -0,0 +1,11 @@
1
+ import { InternalToastProps } from './types';
2
+ import { Observable } from '../../utils/observable';
3
+ interface Props {
4
+ toast: InternalToastProps;
5
+ observable: Observable<InternalToastProps>;
6
+ }
7
+ /** A slice of toast. Freshly out of the toaster, crunchy on the outside, soft and tender on the inside.
8
+ * Or is it just notification's UI.
9
+ */
10
+ export declare const ToastSlice: ({ toast, observable }: Props) => import("react/jsx-runtime").JSX.Element;
11
+ export {};
@@ -0,0 +1,103 @@
1
+ import { jsxs as c, jsx as i } from "react/jsx-runtime";
2
+ import { useState as f, useRef as y, useMemo as T, useCallback as p, useEffect as l } from "react";
3
+ import { XClose as x } from "@untitled-ui/icons-react";
4
+ import { Button as w } from "../button/Button.js";
5
+ import { iconByToastType as B, styleToastType as N } from "./icons.js";
6
+ import { cn as m } from "../../utils/cn.js";
7
+ const k = 4e3, W = ({ toast: e, observable: r }) => {
8
+ var a, d;
9
+ const [h, g] = f(!1), n = y(null), o = T(() => ["peach"].includes(e.type) ? "gradient" : "normal", [e.type]), s = p(
10
+ (t) => {
11
+ r.notify({ ...t, status: "dismissed" });
12
+ },
13
+ [r]
14
+ ), u = p(
15
+ (t) => {
16
+ r.notify({ ...t, status: "destroyed" });
17
+ },
18
+ [r]
19
+ );
20
+ return l(() => {
21
+ g(!0);
22
+ }, []), l(() => {
23
+ const t = setTimeout(() => {
24
+ s(e);
25
+ }, k);
26
+ return () => clearTimeout(t);
27
+ }, [e, s]), /* @__PURE__ */ c(
28
+ "div",
29
+ {
30
+ ref: n,
31
+ style: h ? e.status === "dismissed" ? (
32
+ // The last state before toast is destroyed
33
+ {
34
+ height: 0,
35
+ minHeight: 0,
36
+ opacity: 0,
37
+ marginBottom: 0,
38
+ paddingTop: 0,
39
+ paddingBottom: 0,
40
+ borderWidth: 0
41
+ }
42
+ ) : (
43
+ // The stable state
44
+ {
45
+ height: (d = n.current) == null ? void 0 : d.offsetHeight,
46
+ marginBottom: "0.75rem",
47
+ paddingTop: "0.75rem",
48
+ paddingBottom: "0.75rem",
49
+ borderWidth: "1px"
50
+ }
51
+ ) : (
52
+ // The first state: before toast is mounted
53
+ {
54
+ transform: "translate(0, -100%)",
55
+ height: (a = n.current) == null ? void 0 : a.offsetHeight,
56
+ marginBottom: "0.75rem",
57
+ paddingTop: "0.75rem",
58
+ paddingBottom: "0.75rem",
59
+ borderWidth: "1px"
60
+ }
61
+ ),
62
+ className: m(
63
+ "px-6 flex items-center gap-3 rounded-md duration-300 ease-out shadow-sm-01 min-h-16 overflow-hidden",
64
+ N[e.type],
65
+ o === "gradient" && "text-white"
66
+ ),
67
+ onTransitionEnd: (t) => {
68
+ t.target === t.currentTarget && t.propertyName === "height" && u(e);
69
+ },
70
+ children: [
71
+ B[e.type],
72
+ /* @__PURE__ */ c("div", { className: "flex flex-col", children: [
73
+ /* @__PURE__ */ i("span", { className: "text-md font-medium w-80 min-h-[1em] wrap-break-words", children: e.message }),
74
+ e.detail ? /* @__PURE__ */ i(
75
+ "span",
76
+ {
77
+ className: m(
78
+ "text-sm w-80 min-h-[1em] wrap-break-words line-clamp-3",
79
+ o === "gradient" ? "text-white" : "text-gray-v2-500"
80
+ ),
81
+ children: e.detail
82
+ }
83
+ ) : null
84
+ ] }),
85
+ /* @__PURE__ */ i(
86
+ w,
87
+ {
88
+ variant: "tertiary",
89
+ color: "gray",
90
+ onClick: () => s(e),
91
+ className: m(
92
+ o === "gradient" && "text-white hover:bg-transparent"
93
+ ),
94
+ children: /* @__PURE__ */ i(x, { className: "size-5 shrink-0 text-gray-v2-400" })
95
+ }
96
+ )
97
+ ]
98
+ }
99
+ );
100
+ };
101
+ export {
102
+ W as ToastSlice
103
+ };
@@ -0,0 +1,8 @@
1
+ import { ReactNode } from 'react';
2
+ import { ToastType } from './types';
3
+ export declare const styleToastType: {
4
+ [T in ToastType]: string;
5
+ };
6
+ export declare const iconByToastType: {
7
+ [T in ToastType]: ReactNode;
8
+ };
@@ -0,0 +1,19 @@
1
+ import { jsx as e } from "react/jsx-runtime";
2
+ import { InfoCircle as r, XCircle as s, CheckCircle as i } from "@untitled-ui/icons-react";
3
+ const a = {
4
+ success: "bg-white border-success-v2-500",
5
+ error: "bg-white border-error-v2-500",
6
+ warning: "bg-white border-warning-v2-500",
7
+ info: "bg-white border-blue-v2-500",
8
+ peach: "bg-gradient-to-br from-[#d74874] to-[#da805f] border-transparent"
9
+ }, c = {
10
+ success: /* @__PURE__ */ e(i, { className: "text-success-v2-500 size-6 shrink-0" }),
11
+ error: /* @__PURE__ */ e(s, { className: "text-error-v2-500 size-6 shrink-0" }),
12
+ warning: /* @__PURE__ */ e(r, { className: "text-warning-v2-500 size-6 shrink-0" }),
13
+ info: /* @__PURE__ */ e(r, { className: "text-blue-v2-500 size-6 shrink-0" }),
14
+ peach: /* @__PURE__ */ e(r, { className: "text-white size-6 shrink-0" })
15
+ };
16
+ export {
17
+ c as iconByToastType,
18
+ a as styleToastType
19
+ };
@@ -0,0 +1,4 @@
1
+ import { WrittenOnTheToast } from './types';
2
+ /** Where we store the newly cooked toasts. When a toast is created, it will appear here. */
3
+ export declare const Toaster: () => import("react/jsx-runtime").JSX.Element;
4
+ export declare const createToast: (newToast: WrittenOnTheToast) => void;
@@ -0,0 +1,35 @@
1
+ import { jsx as r } from "react/jsx-runtime";
2
+ import { useEffect as a } from "react";
3
+ import { ToastSlice as n } from "./ToastSlice.js";
4
+ import { useToastList as i } from "./use-toast-list.js";
5
+ import { Observable as c } from "../../utils/observable.js";
6
+ const l = () => window.isSecureContext ? crypto.randomUUID() : crypto.getRandomValues(new Uint32Array(1))[0].toString(), e = new c(), s = /* @__PURE__ */ new Set(), b = () => {
7
+ const o = i(e);
8
+ return a(() => {
9
+ const t = Symbol();
10
+ return s.add(t), () => {
11
+ s.delete(t);
12
+ };
13
+ }, []), /* @__PURE__ */ r("div", { className: "flex flex-col", children: o.map((t) => /* @__PURE__ */ r(
14
+ n,
15
+ {
16
+ toast: t,
17
+ observable: e
18
+ },
19
+ `toast-${t.id}`
20
+ )) });
21
+ }, T = (o) => {
22
+ process.env.NODE_ENV !== "production" && s.size === 0 && console.warn(
23
+ "[Toaster] createToast was called but no <Toaster> is mounted. This toast will be lost."
24
+ );
25
+ const t = {
26
+ ...o,
27
+ id: l(),
28
+ status: "stable"
29
+ };
30
+ e.notify(t);
31
+ };
32
+ export {
33
+ b as Toaster,
34
+ T as createToast
35
+ };
@@ -0,0 +1,14 @@
1
+ import { ReactNode } from 'react';
2
+ export type ToastType = "error" | "warning" | "success" | "info" | "peach";
3
+ type ToastStatus = "stable" | "dismissed" | "destroyed";
4
+ /** The name is Bon, Jambon. */
5
+ export interface WrittenOnTheToast {
6
+ type: ToastType;
7
+ message: string;
8
+ detail?: ReactNode;
9
+ }
10
+ export interface InternalToastProps extends WrittenOnTheToast {
11
+ id: string;
12
+ status: ToastStatus;
13
+ }
14
+ export {};
@@ -0,0 +1,4 @@
1
+ import { InternalToastProps } from './types';
2
+ import { Observable } from '../../utils/observable';
3
+ /** Returns the list of current existing toasts. */
4
+ export declare const useToastList: (observable: Observable<InternalToastProps>) => InternalToastProps[];
@@ -0,0 +1,27 @@
1
+ import { useState as d, useEffect as f } from "react";
2
+ import { flushSync as m } from "react-dom";
3
+ const c = (i) => {
4
+ const [u, r] = d([]);
5
+ return f(() => i.subscribe((s) => {
6
+ if (s.status === "dismissed") {
7
+ r(
8
+ (t) => t.map(
9
+ (e) => e.id === s.id ? { ...e, status: "dismissed" } : e
10
+ )
11
+ );
12
+ return;
13
+ }
14
+ if (s.status === "destroyed") {
15
+ r((t) => t.filter((e) => e.id !== s.id));
16
+ return;
17
+ }
18
+ setTimeout(() => {
19
+ m(() => {
20
+ r((t) => [...t, s]);
21
+ });
22
+ });
23
+ }), [i]), u;
24
+ };
25
+ export {
26
+ c as useToastList
27
+ };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,6 @@
1
+ export { Button } from './components/button/Button';
2
+ export type { ButtonProps } from './components/button/Button';
3
+ export type { ButtonVariant, ButtonColor, ButtonSize, ButtonLoadingStyle, } from './components/button/button-variants';
1
4
  export { Badge } from './components/badge/Badge';
2
5
  export { BadgeTag, getBadgeAutoColor, TAG_ICON_COLOR_CLASSES, } from './components/badge/variants/BadgeTag';
3
6
  export { BadgeMore } from './components/badge/variants/BadgeMore';
@@ -18,6 +21,17 @@ export { PageTitle } from './components/page-title/PageTitle';
18
21
  export { Popover } from './components/popover/Popover';
19
22
  export { usePopoverCoord } from './components/popover/use-popover-coord';
20
23
  export type { PopoverPosition } from './components/popover/use-popover-coord';
24
+ export { Checkbox } from './components/checkbox/Checkbox';
21
25
  export { Switch } from './components/switch/Switch';
22
26
  export { Tooltip } from './components/tooltip/Tooltip';
27
+ export { Collapsible } from './components/collapsible/Collapsible';
28
+ export { Card } from './components/card/Card';
29
+ export type { CardSize } from './components/card/types';
30
+ export { Input } from './components/input/Input';
31
+ export { Toaster, createToast } from './components/toast/index';
32
+ export type { WrittenOnTheToast, ToastType } from './components/toast/types';
33
+ export { Modal } from './components/modal/Modal';
34
+ export { ModalHeaderIcon } from './components/modal/helpers/HeaderIcon';
35
+ export { ModalTitle } from './components/modal/helpers/Title';
36
+ export { useClickOutsideModal } from './components/modal/use-click-outside-modal';
23
37
  export { cn } from './utils/cn';