@g4rcez/components 2.2.3 → 2.2.4

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.
@@ -5,9 +5,11 @@ declare const variants: (props?: ({
5
5
  theme?: "info" | "warn" | "muted" | "danger" | "success" | "secondary" | "default" | null | undefined;
6
6
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
7
7
  type NotificationOptions = Partial<{
8
+ id: string;
8
9
  title: Label;
9
10
  timeout: number;
10
11
  closable: boolean;
12
+ loading: boolean;
11
13
  theme: VariantProps<typeof variants>["theme"];
12
14
  }>;
13
15
  type NotificationSubscriber = {
@@ -1 +1 @@
1
- {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../../src/components/display/notifications.tsx"],"names":[],"mappings":"AACA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAIlE,OAAO,EAAiB,KAAK,iBAAiB,EAAmC,MAAM,OAAO,CAAC;AAE/F,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,QAAA,MAAM,QAAQ;;mFAgBb,CAAC;AAEF,KAAK,mBAAmB,GAAG,OAAO,CAAC;IACjC,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,YAAY,CAAC,OAAO,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC;CAC/C,CAAC,CAAC;AAIH,KAAK,sBAAsB,GAAG;IAAE,KAAK,EAAE,MAAM,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC;AAEvE,KAAK,eAAe,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,mBAAmB,KAAK,sBAAsB,CAAC;AAMlG,eAAO,MAAM,eAAe,uBAAwC,CAAC;AAwDrE,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAqE1E,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,GAAO,EAAE,OAAc,EAAE,EAAE,iBAAiB,CAAC,iBAAiB,CAAC,+BAMxG"}
1
+ {"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../../../src/components/display/notifications.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AASlE,OAAO,EAAiB,KAAK,iBAAiB,EAAmC,MAAM,OAAO,CAAC;AAG/F,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEpC,QAAA,MAAM,QAAQ;;mFAgBb,CAAC;AAYF,KAAK,mBAAmB,GAAG,OAAO,CAAC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,KAAK,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,YAAY,CAAC,OAAO,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC;CAC/C,CAAC,CAAC;AAQH,KAAK,sBAAsB,GAAG;IAAE,KAAK,EAAE,MAAM,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,IAAI,CAAA;CAAE,CAAC;AAEvE,KAAK,eAAe,GAAG,CAAC,WAAW,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,mBAAmB,KAAK,sBAAsB,CAAC;AAMlG,eAAO,MAAM,eAAe,uBAAwC,CAAC;AAoDrE,MAAM,MAAM,iBAAiB,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAyF1E,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,GAAO,EAAE,OAAc,EAAE,EAAE,iBAAiB,CAAC,iBAAiB,CAAC,+BAMxG"}
@@ -1,14 +1,15 @@
1
1
  "use client";
2
+ import { Toast as Base } from "@base-ui/react/toast";
2
3
  import { cva } from "class-variance-authority";
3
- import { XIcon } from "lucide-react";
4
+ import { XIcon, CheckCircleIcon, TriangleAlertIcon, InfoIcon, Loader2Icon, } from "lucide-react";
4
5
  import { AnimatePresence, motion } from "motion/react";
5
- import { Toast as Base } from "@base-ui/react/toast";
6
6
  import { createContext, useCallback, useContext, useRef } from "react";
7
7
  import { useHover } from "../../hooks/use-hover";
8
- const variants = cva("relative isolate z-tooltip flex justify-between overflow-hidden whitespace-wrap rounded-lg border text-sm shadow-shadow-notification", {
8
+ import { css } from "../../lib/dom";
9
+ const variants = cva("relative isolate z-tooltip flex w-full flex-col overflow-hidden rounded-xl border bg-card-background backdrop-blur-md text-sm shadow-notification transition-all duration-300", {
9
10
  variants: {
10
11
  theme: {
11
- default: "border-card-border bg-card-background text-foreground",
12
+ default: "border-card-border text-foreground shadow-black/5",
12
13
  info: "bg-alert-info-bg text-alert-info-text border-alert-info-border",
13
14
  warn: "bg-alert-warn-bg text-alert-warn-text border-alert-warn-border",
14
15
  muted: "bg-alert-muted-bg text-alert-muted-text border-alert-muted-border",
@@ -19,34 +20,46 @@ const variants = cva("relative isolate z-tooltip flex justify-between overflow-h
19
20
  },
20
21
  defaultVariants: { theme: "default" },
21
22
  });
23
+ const themeIcons = {
24
+ default: InfoIcon,
25
+ info: InfoIcon,
26
+ warn: TriangleAlertIcon,
27
+ muted: InfoIcon,
28
+ danger: TriangleAlertIcon,
29
+ success: CheckCircleIcon,
30
+ secondary: InfoIcon,
31
+ };
22
32
  const NotificationContext = createContext(() => {
23
33
  throw new Error("Not implemented");
24
34
  });
25
35
  export const useNotification = () => useContext(NotificationContext);
26
- const animatedIndex = {
27
- 0: { opacity: 1, y: [10, 15], scale: [1, 0.98] },
28
- 1: { opacity: 1, y: [15, 20], scale: [1, 0.97] },
29
- 2: { opacity: 1, y: [20, 25], scale: [1, 0.96] },
30
- default: { opacity: 1, y: [25, 30], scale: [1, 0.95] },
31
- };
32
36
  function Notification(props) {
33
37
  const closable = props.toast.data?.closable ?? true;
34
- const variant = props.hover ? "hover" : props.isLast ? "isLast" : "other";
35
- const className = variants({ theme: props.toast.data?.theme || "default" });
36
- return (<Base.Root toast={props.toast} swipeDirection={["down", "right"]}>
37
- <motion.li layout layoutScroll animate={variant} data-index={props.index} initial={{ y: -100, zIndex: -1 }} className="absolute top-0 right-0 w-80 pointer-events-auto text-select" transition={{ type: "spring", mass: 1.2, damping: 30, stiffness: 200 }} exit={{ opacity: [0.9, 0], transition: { opacity: { bounce: 0.25, duration: 0.3 } } }} variants={{
38
- isLast: { y: 10, scale: 1, animationDuration: "300ms", opacity: 1 },
39
- hover: { y: 0, position: "static", scale: 1, opacity: 1 },
40
- other: animatedIndex[props.reversedIndex] || animatedIndex.default,
41
- }}>
42
- <Base.Content className={className}>
43
- <div className="flex flex-col p-4">
44
- {props.toast.title ? (<Base.Title className="text-lg font-medium leading-relaxed select-text"/>) : null}
45
- <Base.Description className="select-text"/>
38
+ const loading = props.toast.data?.loading ?? false;
39
+ const theme = props.toast.data?.theme || "default";
40
+ const className = variants({ theme });
41
+ const Icon = loading ? Loader2Icon : (themeIcons[theme] || InfoIcon);
42
+ return (<Base.Root toast={props.toast} swipeDirection="right">
43
+ <motion.li layout initial={{ opacity: 0, y: -20, scale: 0.95 }} animate={{ opacity: 1, y: 0, scale: 1 }} exit={{ opacity: 0, scale: 0.9, y: -20, transition: { duration: 0.2 } }} transition={{
44
+ type: "spring",
45
+ damping: 25,
46
+ stiffness: 300,
47
+ }} className="pointer-events-auto list-none w-full">
48
+ <Base.Content className={css(className, "shadow-lg")}>
49
+ <div className="flex items-start gap-3 p-4">
50
+ <div className={css("mt-0.5 shrink-0 opacity-80", loading && "animate-spin")}>
51
+ <Icon className="size-4"/>
52
+ </div>
53
+
54
+ <div className="flex flex-1 flex-col gap-1 overflow-hidden">
55
+ {props.toast.title ? (<Base.Title className="truncate font-semibold leading-tight tracking-tight select-text"/>) : null}
56
+ <Base.Description className="text-xs font-medium opacity-90 select-text leading-relaxed line-clamp-2"/>
57
+ </div>
58
+
59
+ {closable && !loading ? (<Base.Close className="shrink-0 -mr-1 -mt-1 p-1.5 rounded-lg text-foreground/40 transition hover:bg-foreground/10 hover:text-foreground">
60
+ <XIcon className="size-3.5"/>
61
+ </Base.Close>) : null}
46
62
  </div>
47
- {closable ? (<Base.Close className="absolute top-2 right-2 p-1 rounded-full transition text-foreground hover:bg-danger/10 hover:text-danger-hover">
48
- <XIcon className="size-5"/>
49
- </Base.Close>) : null}
50
63
  </Base.Content>
51
64
  </motion.li>
52
65
  </Base.Root>);
@@ -55,16 +68,17 @@ function NotificationsViewport({ max = 5 }) {
55
68
  const ref = useRef(null);
56
69
  const hover = useHover(ref);
57
70
  const toastManager = Base.useToastManager();
58
- const toasts = toastManager.toasts.slice(-max);
59
- return (<Base.Viewport ref={ref} data-items={toasts.length} style={{
60
- justifyContent: "start",
61
- height: `${(hover ? toasts.length : Math.min(1, toasts.length)) * 7}rem`,
62
- }} className="fixed right-4 top-10 flex w-80 list-none flex-col-reverse items-end gap-4 overflow-y-clip overflow-x-visible data-[items=true]:pb-8 max-sm:top-20">
63
- <motion.ol className="flex flex-col gap-4">
64
- <AnimatePresence presenceAffectsLayout mode="popLayout">
65
- {toasts.reverse().map((toast, index, list) => (<Notification toast={toast} hover={hover} index={index} key={toast.id} isLast={list.length - 1 === index} reversedIndex={list.length - (index + 1)}/>))}
66
- </AnimatePresence>
67
- </motion.ol>
71
+ const allToasts = max ? toastManager.toasts.slice(0, max) : toastManager.toasts;
72
+ const visibleToasts = hover ? allToasts : allToasts.slice(0, 3);
73
+ const hiddenCount = allToasts.length - visibleToasts.length;
74
+ return (<Base.Viewport ref={ref} className="fixed left-1/2 top-6 z-[100] flex w-full max-w-[380px] -translate-x-1/2 flex-col gap-3 outline-none pointer-events-none overflow-visible">
75
+ <AnimatePresence mode="popLayout" initial={false}>
76
+ {visibleToasts.map((toast) => (<Notification key={toast.id} toast={toast}/>))}
77
+ </AnimatePresence>
78
+
79
+ {!hover && hiddenCount > 0 && (<motion.div layout initial={{ opacity: 0, y: -10 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -10 }} className="self-center px-3 py-1 text-[10px] font-bold tracking-wider uppercase bg-card-background/80 backdrop-blur shadow-sm border border-card-border rounded-full text-foreground/50 pointer-events-auto cursor-default transition-all hover:bg-card-background hover:text-foreground/80">
80
+ +{hiddenCount} more
81
+ </motion.div>)}
68
82
  </Base.Viewport>);
69
83
  }
70
84
  function NotificationsInner({ children, max = 5 }) {
@@ -73,11 +87,25 @@ function NotificationsInner({ children, max = 5 }) {
73
87
  toastManager.toasts.forEach((t) => toastManager.close(t.id));
74
88
  }, [toastManager]);
75
89
  const notify = useCallback((description, args) => {
90
+ const data = { theme: args?.theme, closable: args?.closable, loading: args?.loading };
91
+ if (args?.id) {
92
+ const existing = toastManager.toasts.find((t) => t.id === args.id);
93
+ if (existing) {
94
+ toastManager.update(args.id, {
95
+ description,
96
+ title: args.title,
97
+ timeout: args.timeout,
98
+ data,
99
+ });
100
+ return { close: () => toastManager.close(args.id), clear };
101
+ }
102
+ }
76
103
  const id = toastManager.add({
77
104
  description,
105
+ id: args?.id,
78
106
  title: args?.title,
79
107
  timeout: args?.timeout,
80
- data: { theme: args?.theme, closable: args?.closable },
108
+ data,
81
109
  });
82
110
  return {
83
111
  close: () => toastManager.close(id),
@@ -22,7 +22,7 @@ type MenuItemProps = {
22
22
  Right?: React.FC<LucideProps>;
23
23
  };
24
24
  export declare const MenuItem: React.ForwardRefExoticComponent<Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, keyof MenuItemProps> & MenuItemProps & React.RefAttributes<HTMLButtonElement>>;
25
- export declare const Menu: React.ForwardRefExoticComponent<(Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "label" | "children" | "hover" | "open" | "restoreFocus" | "nested" | "asChild" | "isParent" | "floatingClassName" | "FloatingComponent"> & Partial<{
25
+ export declare const Menu: React.ForwardRefExoticComponent<(Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "label" | "children" | "hover" | "open" | "asChild" | "restoreFocus" | "nested" | "isParent" | "floatingClassName" | "FloatingComponent"> & Partial<{
26
26
  hover: boolean;
27
27
  open?: boolean;
28
28
  nested: boolean;
@@ -34,7 +34,7 @@ export declare const Menu: React.ForwardRefExoticComponent<(Omit<Omit<React.Deta
34
34
  FloatingComponent: React.ElementType;
35
35
  } & {
36
36
  label: string;
37
- }>, "ref"> | Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "label" | "children" | "hover" | "open" | "restoreFocus" | "nested" | "asChild" | "isParent" | "floatingClassName" | "FloatingComponent"> & Partial<{
37
+ }>, "ref"> | Omit<Omit<React.DetailedHTMLProps<React.ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, "label" | "children" | "hover" | "open" | "asChild" | "restoreFocus" | "nested" | "isParent" | "floatingClassName" | "FloatingComponent"> & Partial<{
38
38
  hover: boolean;
39
39
  open?: boolean;
40
40
  nested: boolean;
@@ -2,6 +2,8 @@ import { type ElementProps } from "@floating-ui/react";
2
2
  import { HTMLMotionProps } from "motion/react";
3
3
  import React from "react";
4
4
  import { Label, Override } from "../../types";
5
+ import { ButtonProps } from "../core/button";
6
+ export declare const useConfirm: () => (options: ConfirmOptions) => Promise<boolean>;
5
7
  export type ModalType = "dialog" | "drawer" | "sheet";
6
8
  export type DrawerPosition = "left" | "right";
7
9
  export type ModalProps = Override<HTMLMotionProps<"div">, ({
@@ -32,11 +34,22 @@ export type ModalProps = Override<HTMLMotionProps<"div">, ({
32
34
  interactions: ElementProps[];
33
35
  trigger: Label | React.FC<any>;
34
36
  }>>;
35
- type ModalRef = {
37
+ export type ModalRef = {
36
38
  context: any;
37
39
  floating: HTMLElement | null;
38
40
  };
39
- export declare const Modal: React.ForwardRefExoticComponent<(Omit<Omit<HTMLMotionProps<"div">, "footer" | "title" | "className" | "role" | "onChange" | "position" | "open" | "resizer" | "type" | "layoutId" | "trigger" | "closeOnFocusOut" | "asChild" | "animated" | "closable" | "forceType" | "bodyClassName" | "overlayClassName" | "overlayClickClose" | "interactions" | "ariaTitle"> & {
41
+ type ButtonConfirmationAction = {
42
+ value?: any;
43
+ text?: Label;
44
+ theme?: ButtonProps["theme"];
45
+ };
46
+ export type ConfirmOptions = {
47
+ title?: Label;
48
+ description?: Label;
49
+ cancel?: ButtonConfirmationAction;
50
+ confirm?: ButtonConfirmationAction;
51
+ };
52
+ export declare const Modal: React.ForwardRefExoticComponent<(Omit<Omit<HTMLMotionProps<"div">, "footer" | "title" | "className" | "role" | "onChange" | "position" | "open" | "resizer" | "type" | "layoutId" | "animated" | "asChild" | "closable" | "forceType" | "bodyClassName" | "overlayClassName" | "overlayClickClose" | "closeOnFocusOut" | "interactions" | "trigger" | "ariaTitle"> & {
40
53
  title: Label;
41
54
  ariaTitle?: string;
42
55
  } & {
@@ -62,7 +75,7 @@ export declare const Modal: React.ForwardRefExoticComponent<(Omit<Omit<HTMLMotio
62
75
  trigger: Label | React.FC<any>;
63
76
  }> & {
64
77
  children?: React.ReactNode | undefined;
65
- }, "ref"> | Omit<Omit<HTMLMotionProps<"div">, "footer" | "title" | "className" | "role" | "onChange" | "position" | "open" | "resizer" | "type" | "layoutId" | "trigger" | "closeOnFocusOut" | "asChild" | "animated" | "closable" | "forceType" | "bodyClassName" | "overlayClassName" | "overlayClickClose" | "interactions" | "ariaTitle"> & {
78
+ }, "ref"> | Omit<Omit<HTMLMotionProps<"div">, "footer" | "title" | "className" | "role" | "onChange" | "position" | "open" | "resizer" | "type" | "layoutId" | "animated" | "asChild" | "closable" | "forceType" | "bodyClassName" | "overlayClassName" | "overlayClickClose" | "closeOnFocusOut" | "interactions" | "trigger" | "ariaTitle"> & {
66
79
  ariaTitle: string;
67
80
  title?: Label;
68
81
  } & {
@@ -88,6 +101,11 @@ export declare const Modal: React.ForwardRefExoticComponent<(Omit<Omit<HTMLMotio
88
101
  trigger: Label | React.FC<any>;
89
102
  }> & {
90
103
  children?: React.ReactNode | undefined;
91
- }, "ref">) & React.RefAttributes<ModalRef>>;
104
+ }, "ref">) & React.RefAttributes<ModalRef>> & {
105
+ confirm: (options: ConfirmOptions) => Promise<boolean>;
106
+ };
107
+ export declare const ModalConfirmProvider: ({ children }: {
108
+ children: React.ReactNode;
109
+ }) => React.JSX.Element;
92
110
  export {};
93
111
  //# sourceMappingURL=modal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../../src/components/floating/modal.tsx"],"names":[],"mappings":"AACA,OAAO,EASL,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EAAmB,eAAe,EAA4F,MAAM,cAAc,CAAC;AAE1J,OAAO,KAA+G,MAAM,OAAO,CAAC;AAGpI,OAAO,EAAE,KAAK,EAAO,QAAQ,EAAE,MAAM,aAAa,CAAC;AAKnD,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEtD,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,OAAO,CAAC;AAuD9C,MAAM,MAAM,UAAU,GAAG,QAAQ,CAC/B,eAAe,CAAC,KAAK,CAAC,EACtB,CAAC;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,CAAC,GAAG;IAC9E,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC,GAAG,OAAO,CAAC;IACV,MAAM,EAAE,KAAK,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,cAAc,CAAC;IACzB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,eAAe,EAAE,OAAO,CAAC;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,YAAY,EAAE,YAAY,EAAE,CAAC;IAC7B,OAAO,EAAE,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;CAChC,CAAC,CACH,CAAC;AAgFF,KAAK,QAAQ,GAAG;IAAE,OAAO,EAAE,GAAG,CAAC;IAAC,QAAQ,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,CAAC;AAI/D,eAAO,MAAM,KAAK;WA1GN,KAAK;gBAAc,MAAM;;UAC3B,OAAO;cACH,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI;;YAE9B,KAAK;UACP,SAAS;cACL,OAAO;aACR,OAAO;cACN,MAAM;aACP,OAAO;eACL,MAAM;cACP,OAAO;eACN,OAAO;mBACH,MAAM;sBACH,MAAM;cACd,cAAc;uBACL,OAAO;qBACT,OAAO;UAClB,QAAQ;kBACA,YAAY,EAAE;aACnB,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC;;;;eApBqB,MAAM;YAAU,KAAK;;UAClE,OAAO;cACH,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI;;YAE9B,KAAK;UACP,SAAS;cACL,OAAO;aACR,OAAO;cACN,MAAM;aACP,OAAO;eACL,MAAM;cACP,OAAO;eACN,OAAO;mBACH,MAAM;sBACH,MAAM;cACd,cAAc;uBACL,OAAO;qBACT,OAAO;UAClB,QAAQ;kBACA,YAAY,EAAE;aACnB,KAAK,GAAG,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC;;;2CA8UjC,CAAC"}
1
+ {"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../../src/components/floating/modal.tsx"],"names":[],"mappings":"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"}
@@ -4,10 +4,13 @@ import { cva } from "class-variance-authority";
4
4
  import { XIcon } from "lucide-react";
5
5
  import { AnimatePresence, motion, MotionConfig, useMotionValue, animate } from "motion/react";
6
6
  import { Slot } from "../core/slot";
7
- import React, { forwardRef, Fragment, useEffect, useId, useImperativeHandle, useRef } from "react";
7
+ import React, { forwardRef, Fragment, useEffect, useId, useImperativeHandle, useRef, useState, useCallback } from "react";
8
8
  import { useMediaQuery } from "../../hooks/use-media-query";
9
9
  import { css, mergeRefs } from "../../lib/dom";
10
10
  import { useFloatingRef } from "../../hooks/use-floating-ref";
11
+ import { Button } from "../core/button";
12
+ const ConfirmContext = React.createContext(async () => false);
13
+ export const useConfirm = () => React.useContext(ConfirmContext);
11
14
  const animationDuration = "500ms";
12
15
  const drawerLeft = {
13
16
  exit: { x: ["0%", "-30%"], opacity: 0, animationDuration },
@@ -92,7 +95,7 @@ const fetchPosition = (isDesktop, forceType, propsType, propsPosition) => {
92
95
  return forceType ? positions[type] : positions.sheet;
93
96
  };
94
97
  const noop = [];
95
- export const Modal = forwardRef(({ open, title, footer, asChild, trigger, children, onChange, ariaTitle, className, bodyClassName, resizer = true, animated = true, closable = true, forceType = false, layoutId = undefined, overlayClassName = "", type: _type = "dialog", position: propsPosition, overlayClickClose = false, closeOnFocusOut = false, interactions: outInteractions = noop, ...props }, externalRef) => {
98
+ const InternalModal = forwardRef(({ open, title, footer, asChild, trigger, children, onChange, ariaTitle, className, bodyClassName, resizer = true, animated = true, closable = true, forceType = false, layoutId = undefined, overlayClassName = "", type: _type = "dialog", position: propsPosition, overlayClickClose = false, closeOnFocusOut = false, interactions: outInteractions = noop, ...props }, externalRef) => {
96
99
  const root = useFloatingRef();
97
100
  const innerContent = useRef(null);
98
101
  const removeScrollRef = useRef(null);
@@ -243,3 +246,50 @@ export const Modal = forwardRef(({ open, title, footer, asChild, trigger, childr
243
246
  </MotionConfig>
244
247
  </Fragment>);
245
248
  });
249
+ let confirmGlobal = async () => {
250
+ if (typeof window !== "undefined") {
251
+ console.warn("ConfirmationProvider is not mounted");
252
+ }
253
+ return false;
254
+ };
255
+ export const Modal = Object.assign(InternalModal, {
256
+ confirm: (options) => confirmGlobal(options),
257
+ });
258
+ export const ModalConfirmProvider = ({ children }) => {
259
+ const [open, setOpen] = useState(false);
260
+ const [options, setOptions] = useState({});
261
+ const [resolve, setResolve] = useState(() => { });
262
+ const confirmAction = useCallback((opts) => {
263
+ setOptions(opts);
264
+ setOpen(true);
265
+ return new Promise((res) => {
266
+ setResolve(() => res);
267
+ });
268
+ }, []);
269
+ useEffect(() => {
270
+ confirmGlobal = confirmAction;
271
+ }, [confirmAction]);
272
+ const onConfirm = () => {
273
+ setOpen(false);
274
+ const value = options.confirm?.value ?? true;
275
+ resolve(value ?? true);
276
+ };
277
+ const onCancel = () => {
278
+ setOpen(false);
279
+ const value = options.cancel?.value ?? false;
280
+ resolve(value ?? false);
281
+ };
282
+ return (<ConfirmContext.Provider value={confirmAction}>
283
+ {children}
284
+ <InternalModal open={open} type="dialog" closable={false} onChange={setOpen} overlayClickClose={false} title={options.title || "Confirmation"} className="container max-w-dialog lg:max-w-96" footer={<div className="flex gap-2 justify-end">
285
+ <Button theme={options.cancel?.theme || "ghost-muted"} onClick={onCancel}>
286
+ {options.cancel?.text || "Cancel"}
287
+ </Button>
288
+ <Button theme={options.confirm?.theme || "primary"} onClick={onConfirm}>
289
+ {options.confirm?.text || "Confirm"}
290
+ </Button>
291
+ </div>}>
292
+ <div className="py-2 text-foreground">{options.description}</div>
293
+ </InternalModal>
294
+ </ConfirmContext.Provider>);
295
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"use-components-provider.d.ts","sourceRoot":"","sources":["../../src/hooks/use-components-provider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,iBAAiB,EAAW,MAAM,OAAO,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAW,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAuB,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnF,OAAO,EAAiB,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEjE,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,YAAY,CAAC;IAClB,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,MAAM,EAAE,OAAO,OAAO,CAAC,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;CAClC,CAAC,CAAC;AAEH,eAAO,MAAM,kBAAkB,GAAI,OAAO,iBAAiB,CAAC,YAAY,CAAC,sBAYxE,CAAC"}
1
+ {"version":3,"file":"use-components-provider.d.ts","sourceRoot":"","sources":["../../src/hooks/use-components-provider.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,iBAAiB,EAAW,MAAM,OAAO,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAClD,OAAO,EAAW,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAuB,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnF,OAAO,EAAiB,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAGjE,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,YAAY,CAAC;IAClB,MAAM,EAAE,OAAO,GAAG,SAAS,CAAC;IAC5B,MAAM,EAAE,OAAO,OAAO,CAAC,IAAI,CAAC;IAC5B,WAAW,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;CAClC,CAAC,CAAC;AAEH,eAAO,MAAM,kBAAkB,GAAI,OAAO,iBAAiB,CAAC,YAAY,CAAC,sBAgBxE,CAAC"}
@@ -4,6 +4,7 @@ import { parsers } from "../styles/design-tokens";
4
4
  import { Context } from "../config/context";
5
5
  import { defaultTranslations } from "../config/default-translations";
6
6
  import { defaultTweaks } from "../config/default-tweaks";
7
+ import { ModalConfirmProvider } from "../components/floating/modal";
7
8
  export const ComponentsProvider = (props) => {
8
9
  const memoMap = useMemo(() => ({
9
10
  locale: props.locale,
@@ -12,5 +13,7 @@ export const ComponentsProvider = (props) => {
12
13
  parser: props.parser || parsers.hsla,
13
14
  map: { ...defaultTranslations, ...props.map },
14
15
  }), [props]);
15
- return <Context.Provider value={memoMap}>{props.children}</Context.Provider>;
16
+ return (<Context.Provider value={memoMap}>
17
+ <ModalConfirmProvider>{props.children}</ModalConfirmProvider>
18
+ </Context.Provider>);
16
19
  };