@jbpark/ui-kit 3.2.0 → 3.3.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.
@@ -67,15 +67,15 @@ const Drawer = ({ open, title, extra, footer, closable = true, closeIcon, direct
67
67
  className: cn(classNames?.header, !title && "p-0"),
68
68
  children: [/* @__PURE__ */ jsxs("div", {
69
69
  className: "flex items-start gap-2",
70
- children: [renderConditional(closable ? closeIcon || /* @__PURE__ */ jsx(X, {}) : null, (v) => /* @__PURE__ */ jsx(Button, {
70
+ children: [closable && /* @__PURE__ */ jsx(Button, {
71
71
  type: "text",
72
72
  shape: "circle",
73
73
  size: "small",
74
74
  "aria-label": "닫기",
75
- icon: v,
75
+ icon: closeIcon || /* @__PURE__ */ jsx(X, {}),
76
76
  onClick: onClose,
77
77
  className: cn(classNames?.close)
78
- })), /* @__PURE__ */ jsxs("div", {
78
+ }), /* @__PURE__ */ jsxs("div", {
79
79
  className: "flex flex-1 items-start justify-between gap-2",
80
80
  children: [/* @__PURE__ */ jsx(DrawerTitle, {
81
81
  className: cn(classNames?.title),
@@ -1 +1 @@
1
- {"version":3,"file":"drawer.mjs","names":["drawer"],"sources":["../../../src/components/organisms/drawer.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect } from 'react';\n\nimport { X } from 'lucide-react';\n\nimport { drawer } from '@repo/ui/core';\nimport { cn, renderConditional } from '@repo/ui/utils';\n\nimport Button from '../atoms/button';\n\nconst {\n DrawerContent,\n Drawer: DrawerCore,\n DrawerDescription,\n DrawerFooter,\n DrawerHeader,\n DrawerTitle,\n} = drawer;\n\n// `document.body.style.pointerEvents` is global state, so several mask-less\n// overlays opening at once would otherwise race: each instance would capture\n// whatever the previous one had already written and the last cleanup would\n// restore a stale value. Reference counting makes only the first instance\n// capture the original value and only the last one restore it.\nlet maskLessOverlayCount = 0;\nlet originalBodyPointerEvents: string | null = null;\n\nexport interface Props {\n open: boolean;\n children?: React.ReactNode;\n title?: React.ReactNode;\n extra?: React.ReactNode;\n footer?: React.ReactNode;\n closable?: boolean;\n closeIcon?: React.ReactNode;\n direction?: 'top' | 'bottom' | 'left' | 'right';\n size?: 'small' | 'medium' | 'large' | 'full' | string;\n maskClosable?: boolean;\n handlebar?: boolean;\n draggable?: boolean;\n rounded?: boolean;\n mask?: boolean;\n className?: string;\n style?: React.CSSProperties;\n classNames?: {\n mask?: string;\n content?: string;\n handlebar?: string;\n header?: string;\n title?: string;\n close?: string;\n extra?: string;\n body?: string;\n footer?: string;\n };\n container?: HTMLElement;\n onClose: () => void;\n}\n\nconst SIZES: Record<string, string> = {\n small: '30%',\n medium: '50%',\n large: '75%',\n full: '90%',\n};\n\nconst getSizeStyles = (\n direction: 'top' | 'bottom' | 'left' | 'right',\n size: string,\n): React.CSSProperties => {\n const value = SIZES[size] || size;\n\n return direction === 'top' || direction === 'bottom'\n ? { height: value }\n : { width: value };\n};\n\nconst Drawer = ({\n open,\n title,\n extra,\n footer,\n closable = true,\n closeIcon,\n direction = 'bottom',\n size = 'medium',\n maskClosable = true,\n handlebar = true,\n draggable = false,\n rounded = false,\n mask = true,\n className,\n classNames,\n style,\n children,\n container,\n onClose,\n ...props\n}: Props) => {\n useEffect(() => {\n if (!open || mask) {\n return;\n }\n\n if (maskLessOverlayCount === 0) {\n originalBodyPointerEvents = document.body.style.pointerEvents;\n }\n maskLessOverlayCount += 1;\n\n const raf = window.requestAnimationFrame(() => {\n document.body.style.pointerEvents = 'auto';\n });\n\n return () => {\n window.cancelAnimationFrame(raf);\n maskLessOverlayCount -= 1;\n\n if (maskLessOverlayCount === 0) {\n document.body.style.pointerEvents = originalBodyPointerEvents ?? '';\n originalBodyPointerEvents = null;\n }\n };\n }, [open, mask]);\n\n return (\n <DrawerCore\n open={open}\n direction={direction}\n handleOnly={!draggable}\n container={container}\n onOpenChange={open => {\n if (!open) {\n onClose();\n }\n }}\n {...props}\n >\n <DrawerContent\n className={cn(\n 'border-none outline-none',\n rounded ? 'rounded-t-[30px]!' : 'rounded-none!',\n classNames?.content,\n className,\n //\n )}\n handlebar={handlebar}\n mask={mask}\n onPointerDownOutside={event => {\n if (!maskClosable) {\n event.preventDefault();\n }\n }}\n classNames={{\n mask: classNames?.mask || '',\n handlebar: classNames?.handlebar || '',\n }}\n style={{\n ...getSizeStyles(direction, size),\n ...style,\n }}\n >\n <DrawerHeader\n className={cn(\n classNames?.header,\n !title && 'p-0',\n //\n )}\n >\n <div className=\"flex items-start gap-2\">\n {renderConditional(closable ? closeIcon || <X /> : null, v => (\n <Button\n type=\"text\"\n shape=\"circle\"\n size=\"small\"\n aria-label=\"닫기\"\n icon={v}\n onClick={onClose}\n className={cn(classNames?.close)}\n />\n ))}\n <div className=\"flex flex-1 items-start justify-between gap-2\">\n <DrawerTitle className={cn(classNames?.title)}>\n {title}\n </DrawerTitle>\n {renderConditional(extra, v => (\n <div className={cn('shrink-0', classNames?.extra)}>{v}</div>\n ))}\n </div>\n </div>\n <DrawerDescription className=\"hidden\" />\n </DrawerHeader>\n <div\n className={cn(\n 'overflow-auto p-5',\n classNames?.body,\n //\n )}\n >\n {children}\n </div>\n {renderConditional(footer, v => (\n <DrawerFooter className={cn(classNames?.footer)}>{v}</DrawerFooter>\n ))}\n </DrawerContent>\n </DrawerCore>\n );\n};\n\nexport default Drawer;\n"],"mappings":";;;;;;;;;;AAWA,MAAM,EACJ,eACA,QAAQ,YACR,mBACA,cACA,cACA,gBACEA;AAOJ,IAAI,uBAAuB;AAC3B,IAAI,4BAA2C;AAkC/C,MAAM,QAAgC;CACpC,OAAO;CACP,QAAQ;CACR,OAAO;CACP,MAAM;CACP;AAED,MAAM,iBACJ,WACA,SACwB;CACxB,MAAM,QAAQ,MAAM,SAAS;AAE7B,QAAO,cAAc,SAAS,cAAc,WACxC,EAAE,QAAQ,OAAO,GACjB,EAAE,OAAO,OAAO;;AAGtB,MAAM,UAAU,EACd,MACA,OACA,OACA,QACA,WAAW,MACX,WACA,YAAY,UACZ,OAAO,UACP,eAAe,MACf,YAAY,MACZ,YAAY,OACZ,UAAU,OACV,OAAO,MACP,WACA,YACA,OACA,UACA,WACA,SACA,GAAG,YACQ;AACX,iBAAgB;AACd,MAAI,CAAC,QAAQ,KACX;AAGF,MAAI,yBAAyB,EAC3B,6BAA4B,SAAS,KAAK,MAAM;AAElD,0BAAwB;EAExB,MAAM,MAAM,OAAO,4BAA4B;AAC7C,YAAS,KAAK,MAAM,gBAAgB;IACpC;AAEF,eAAa;AACX,UAAO,qBAAqB,IAAI;AAChC,2BAAwB;AAExB,OAAI,yBAAyB,GAAG;AAC9B,aAAS,KAAK,MAAM,gBAAgB,6BAA6B;AACjE,gCAA4B;;;IAG/B,CAAC,MAAM,KAAK,CAAC;AAEhB,QACE,oBAAC;EACO;EACK;EACX,YAAY,CAAC;EACF;EACX,eAAc,SAAQ;AACpB,OAAI,CAAC,KACH,UAAS;;EAGb,GAAI;YAEJ,qBAAC;GACC,WAAW,GACT,4BACA,UAAU,sBAAsB,iBAChC,YAAY,SACZ,UAED;GACU;GACL;GACN,uBAAsB,UAAS;AAC7B,QAAI,CAAC,aACH,OAAM,gBAAgB;;GAG1B,YAAY;IACV,MAAM,YAAY,QAAQ;IAC1B,WAAW,YAAY,aAAa;IACrC;GACD,OAAO;IACL,GAAG,cAAc,WAAW,KAAK;IACjC,GAAG;IACJ;;IAED,qBAAC;KACC,WAAW,GACT,YAAY,QACZ,CAAC,SAAS,MAEX;gBAED,qBAAC;MAAI,WAAU;iBACZ,kBAAkB,WAAW,aAAa,oBAAC,MAAI,GAAG,OAAM,MACvD,oBAAC;OACC,MAAK;OACL,OAAM;OACN,MAAK;OACL,cAAW;OACX,MAAM;OACN,SAAS;OACT,WAAW,GAAG,YAAY,MAAM;QAChC,CACF,EACF,qBAAC;OAAI,WAAU;kBACb,oBAAC;QAAY,WAAW,GAAG,YAAY,MAAM;kBAC1C;SACW,EACb,kBAAkB,QAAO,MACxB,oBAAC;QAAI,WAAW,GAAG,YAAY,YAAY,MAAM;kBAAG;SAAQ,CAC5D;QACE;OACF,EACN,oBAAC,qBAAkB,WAAU,WAAW;MAC3B;IACf,oBAAC;KACC,WAAW,GACT,qBACA,YAAY,KAEb;KAEA;MACG;IACL,kBAAkB,SAAQ,MACzB,oBAAC;KAAa,WAAW,GAAG,YAAY,OAAO;eAAG;MAAiB,CACnE;;IACY;GACL"}
1
+ {"version":3,"file":"drawer.mjs","names":["drawer"],"sources":["../../../src/components/organisms/drawer.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect } from 'react';\n\nimport { X } from 'lucide-react';\n\nimport { drawer } from '@repo/ui/core';\nimport { cn, renderConditional } from '@repo/ui/utils';\n\nimport Button from '../atoms/button';\n\nconst {\n DrawerContent,\n Drawer: DrawerCore,\n DrawerDescription,\n DrawerFooter,\n DrawerHeader,\n DrawerTitle,\n} = drawer;\n\n// `document.body.style.pointerEvents` is global state, so several mask-less\n// overlays opening at once would otherwise race: each instance would capture\n// whatever the previous one had already written and the last cleanup would\n// restore a stale value. Reference counting makes only the first instance\n// capture the original value and only the last one restore it.\nlet maskLessOverlayCount = 0;\nlet originalBodyPointerEvents: string | null = null;\n\nexport interface Props {\n open: boolean;\n children?: React.ReactNode;\n title?: React.ReactNode;\n extra?: React.ReactNode;\n footer?: React.ReactNode;\n closable?: boolean;\n closeIcon?: React.ReactNode;\n direction?: 'top' | 'bottom' | 'left' | 'right';\n size?: 'small' | 'medium' | 'large' | 'full' | string;\n maskClosable?: boolean;\n handlebar?: boolean;\n draggable?: boolean;\n rounded?: boolean;\n mask?: boolean;\n className?: string;\n style?: React.CSSProperties;\n classNames?: {\n mask?: string;\n content?: string;\n handlebar?: string;\n header?: string;\n title?: string;\n close?: string;\n extra?: string;\n body?: string;\n footer?: string;\n };\n container?: HTMLElement;\n onClose: () => void;\n}\n\nconst SIZES: Record<string, string> = {\n small: '30%',\n medium: '50%',\n large: '75%',\n full: '90%',\n};\n\nconst getSizeStyles = (\n direction: 'top' | 'bottom' | 'left' | 'right',\n size: string,\n): React.CSSProperties => {\n const value = SIZES[size] || size;\n\n return direction === 'top' || direction === 'bottom'\n ? { height: value }\n : { width: value };\n};\n\nconst Drawer = ({\n open,\n title,\n extra,\n footer,\n closable = true,\n closeIcon,\n direction = 'bottom',\n size = 'medium',\n maskClosable = true,\n handlebar = true,\n draggable = false,\n rounded = false,\n mask = true,\n className,\n classNames,\n style,\n children,\n container,\n onClose,\n ...props\n}: Props) => {\n useEffect(() => {\n if (!open || mask) {\n return;\n }\n\n if (maskLessOverlayCount === 0) {\n originalBodyPointerEvents = document.body.style.pointerEvents;\n }\n maskLessOverlayCount += 1;\n\n const raf = window.requestAnimationFrame(() => {\n document.body.style.pointerEvents = 'auto';\n });\n\n return () => {\n window.cancelAnimationFrame(raf);\n maskLessOverlayCount -= 1;\n\n if (maskLessOverlayCount === 0) {\n document.body.style.pointerEvents = originalBodyPointerEvents ?? '';\n originalBodyPointerEvents = null;\n }\n };\n }, [open, mask]);\n\n return (\n <DrawerCore\n open={open}\n direction={direction}\n handleOnly={!draggable}\n container={container}\n onOpenChange={open => {\n if (!open) {\n onClose();\n }\n }}\n {...props}\n >\n <DrawerContent\n className={cn(\n 'border-none outline-none',\n rounded ? 'rounded-t-[30px]!' : 'rounded-none!',\n classNames?.content,\n className,\n //\n )}\n handlebar={handlebar}\n mask={mask}\n onPointerDownOutside={event => {\n if (!maskClosable) {\n event.preventDefault();\n }\n }}\n classNames={{\n mask: classNames?.mask || '',\n handlebar: classNames?.handlebar || '',\n }}\n style={{\n ...getSizeStyles(direction, size),\n ...style,\n }}\n >\n <DrawerHeader\n className={cn(\n classNames?.header,\n !title && 'p-0',\n //\n )}\n >\n <div className=\"flex items-start gap-2\">\n {closable && (\n <Button\n type=\"text\"\n shape=\"circle\"\n size=\"small\"\n aria-label=\"닫기\"\n icon={closeIcon || <X />}\n onClick={onClose}\n className={cn(classNames?.close)}\n />\n )}\n <div className=\"flex flex-1 items-start justify-between gap-2\">\n <DrawerTitle className={cn(classNames?.title)}>\n {title}\n </DrawerTitle>\n {renderConditional(extra, v => (\n <div className={cn('shrink-0', classNames?.extra)}>{v}</div>\n ))}\n </div>\n </div>\n <DrawerDescription className=\"hidden\" />\n </DrawerHeader>\n <div\n className={cn(\n 'overflow-auto p-5',\n classNames?.body,\n //\n )}\n >\n {children}\n </div>\n {renderConditional(footer, v => (\n <DrawerFooter className={cn(classNames?.footer)}>{v}</DrawerFooter>\n ))}\n </DrawerContent>\n </DrawerCore>\n );\n};\n\nexport default Drawer;\n"],"mappings":";;;;;;;;;;AAWA,MAAM,EACJ,eACA,QAAQ,YACR,mBACA,cACA,cACA,gBACEA;AAOJ,IAAI,uBAAuB;AAC3B,IAAI,4BAA2C;AAkC/C,MAAM,QAAgC;CACpC,OAAO;CACP,QAAQ;CACR,OAAO;CACP,MAAM;CACP;AAED,MAAM,iBACJ,WACA,SACwB;CACxB,MAAM,QAAQ,MAAM,SAAS;AAE7B,QAAO,cAAc,SAAS,cAAc,WACxC,EAAE,QAAQ,OAAO,GACjB,EAAE,OAAO,OAAO;;AAGtB,MAAM,UAAU,EACd,MACA,OACA,OACA,QACA,WAAW,MACX,WACA,YAAY,UACZ,OAAO,UACP,eAAe,MACf,YAAY,MACZ,YAAY,OACZ,UAAU,OACV,OAAO,MACP,WACA,YACA,OACA,UACA,WACA,SACA,GAAG,YACQ;AACX,iBAAgB;AACd,MAAI,CAAC,QAAQ,KACX;AAGF,MAAI,yBAAyB,EAC3B,6BAA4B,SAAS,KAAK,MAAM;AAElD,0BAAwB;EAExB,MAAM,MAAM,OAAO,4BAA4B;AAC7C,YAAS,KAAK,MAAM,gBAAgB;IACpC;AAEF,eAAa;AACX,UAAO,qBAAqB,IAAI;AAChC,2BAAwB;AAExB,OAAI,yBAAyB,GAAG;AAC9B,aAAS,KAAK,MAAM,gBAAgB,6BAA6B;AACjE,gCAA4B;;;IAG/B,CAAC,MAAM,KAAK,CAAC;AAEhB,QACE,oBAAC;EACO;EACK;EACX,YAAY,CAAC;EACF;EACX,eAAc,SAAQ;AACpB,OAAI,CAAC,KACH,UAAS;;EAGb,GAAI;YAEJ,qBAAC;GACC,WAAW,GACT,4BACA,UAAU,sBAAsB,iBAChC,YAAY,SACZ,UAED;GACU;GACL;GACN,uBAAsB,UAAS;AAC7B,QAAI,CAAC,aACH,OAAM,gBAAgB;;GAG1B,YAAY;IACV,MAAM,YAAY,QAAQ;IAC1B,WAAW,YAAY,aAAa;IACrC;GACD,OAAO;IACL,GAAG,cAAc,WAAW,KAAK;IACjC,GAAG;IACJ;;IAED,qBAAC;KACC,WAAW,GACT,YAAY,QACZ,CAAC,SAAS,MAEX;gBAED,qBAAC;MAAI,WAAU;iBACZ,YACC,oBAAC;OACC,MAAK;OACL,OAAM;OACN,MAAK;OACL,cAAW;OACX,MAAM,aAAa,oBAAC,MAAI;OACxB,SAAS;OACT,WAAW,GAAG,YAAY,MAAM;QAChC,EAEJ,qBAAC;OAAI,WAAU;kBACb,oBAAC;QAAY,WAAW,GAAG,YAAY,MAAM;kBAC1C;SACW,EACb,kBAAkB,QAAO,MACxB,oBAAC;QAAI,WAAW,GAAG,YAAY,YAAY,MAAM;kBAAG;SAAQ,CAC5D;QACE;OACF,EACN,oBAAC,qBAAkB,WAAU,WAAW;MAC3B;IACf,oBAAC;KACC,WAAW,GACT,qBACA,YAAY,KAEb;KAEA;MACG;IACL,kBAAkB,SAAQ,MACzB,oBAAC;KAAa,WAAW,GAAG,YAAY,OAAO;eAAG;MAAiB,CACnE;;IACY;GACL"}
@@ -1,4 +1,5 @@
1
1
  import { Drawer, Props } from "./drawer.mjs";
2
2
  import { List } from "./list/index.mjs";
3
3
  import { Modal } from "./modal.mjs";
4
- import { Swiper } from "./swiper/index.mjs";
4
+ import { Swiper } from "./swiper/index.mjs";
5
+ import { StaticProps, Toast } from "./toast.mjs";
@@ -0,0 +1,41 @@
1
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
2
+
3
+ //#region src/components/organisms/toast.d.ts
4
+ type ToastType = 'info' | 'success' | 'error' | 'warning';
5
+ interface Props {
6
+ type?: ToastType;
7
+ title: React.ReactNode;
8
+ description?: React.ReactNode;
9
+ icon?: React.ReactNode;
10
+ closable?: boolean;
11
+ action?: React.ReactNode;
12
+ className?: string;
13
+ onClose?: () => void;
14
+ }
15
+ interface StaticProps extends Props {
16
+ id?: string;
17
+ duration?: number;
18
+ container?: HTMLElement;
19
+ }
20
+ declare const Toast: {
21
+ ({
22
+ type,
23
+ title,
24
+ description,
25
+ icon,
26
+ closable,
27
+ action,
28
+ className,
29
+ onClose
30
+ }: Props): react_jsx_runtime0.JSX.Element;
31
+ destroy(id?: string): void;
32
+ destroyAll(): void;
33
+ info(title: React.ReactNode, props?: TriggerOptions): string | undefined;
34
+ success(title: React.ReactNode, props?: TriggerOptions): string | undefined;
35
+ error(title: React.ReactNode, props?: TriggerOptions): string | undefined;
36
+ warning(title: React.ReactNode, props?: TriggerOptions): string | undefined;
37
+ };
38
+ type TriggerOptions = Omit<StaticProps, 'type' | 'title'>;
39
+ //#endregion
40
+ export { StaticProps, Toast };
41
+ //# sourceMappingURL=toast.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toast.d.mts","names":[],"sources":["../../../src/components/organisms/toast.tsx"],"mappings":";;;KAaK,SAAA;AAAA,UAEY,KAAA;EACf,IAAA,GAAO,SAAA;EACP,KAAA,EAAO,KAAA,CAAM,SAAA;EACb,WAAA,GAAc,KAAA,CAAM,SAAA;EACpB,IAAA,GAAO,KAAA,CAAM,SAAA;EACb,QAAA;EACA,MAAA,GAAS,KAAA,CAAM,SAAA;EACf,SAAA;EACA,OAAA;AAAA;AAAA,UAGQ,WAAA,SAAoB,KAAA;EAC5B,EAAA;EACA,QAAA;EACA,SAAA,GAAY,WAAA;AAAA;AAAA,cA6DR,KAAA;EAAA;;;;;;;;;KASH,KAAA,GAAK,kBAAA,CAAA,GAAA,CAAA,OAAA;;;cAmKa,KAAA,CAAM,SAAA,EAAS,KAAA,GAAU,cAAA;iBAEtB,KAAA,CAAM,SAAA,EAAS,KAAA,GAAU,cAAA;eAE3B,KAAA,CAAM,SAAA,EAAS,KAAA,GAAU,cAAA;iBAEvB,KAAA,CAAM,SAAA,EAAS,KAAA,GAAU,cAAA;AAAA;AAAA,KAR5C,cAAA,GAAiB,IAAA,CAAK,WAAA"}
@@ -0,0 +1,197 @@
1
+ 'use client';
2
+
3
+ import { cn } from "../../utils.mjs";
4
+ import Button from "../../Button.mjs";
5
+ import { Check, Info, OctagonAlert, OctagonX, X } from "lucide-react";
6
+ import { useEffect, useState } from "react";
7
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
8
+ import { createPortal } from "react-dom";
9
+ import { createRoot } from "react-dom/client";
10
+ import { v4 } from "uuid";
11
+
12
+ //#region src/components/organisms/toast.tsx
13
+ const isBrowser = typeof window !== "undefined" && typeof document !== "undefined";
14
+ const containerStates = /* @__PURE__ */ new Map();
15
+ const getContainerState = (container) => {
16
+ let state = containerStates.get(container);
17
+ if (!state) {
18
+ state = {
19
+ stack: [],
20
+ update: null
21
+ };
22
+ containerStates.set(container, state);
23
+ }
24
+ return state;
25
+ };
26
+ const createToastRoot = (container) => {
27
+ if (!isBrowser) return null;
28
+ const targetContainer = container || document.body;
29
+ let rootEl = targetContainer.querySelector("#toast-root");
30
+ if (!rootEl) {
31
+ rootEl = document.createElement("div");
32
+ rootEl.setAttribute("id", "toast-root");
33
+ rootEl.setAttribute("role", "region");
34
+ rootEl.setAttribute("aria-label", "Notifications");
35
+ rootEl.style.zIndex = "10000";
36
+ rootEl.style.position = "fixed";
37
+ rootEl.style.right = "0";
38
+ rootEl.style.bottom = "0";
39
+ rootEl.style.display = "flex";
40
+ rootEl.style.flexDirection = "column-reverse";
41
+ rootEl.style.gap = "8px";
42
+ rootEl.style.padding = "16px";
43
+ rootEl.style.pointerEvents = "none";
44
+ targetContainer.appendChild(rootEl);
45
+ }
46
+ return rootEl;
47
+ };
48
+ const TYPE_ICONS = {
49
+ info: /* @__PURE__ */ jsx(Info, { className: "text-blue-400" }),
50
+ success: /* @__PURE__ */ jsx(Check, { className: "text-green-400" }),
51
+ error: /* @__PURE__ */ jsx(OctagonX, { className: "text-red-400" }),
52
+ warning: /* @__PURE__ */ jsx(OctagonAlert, { className: "text-yellow-400" })
53
+ };
54
+ const Toast = ({ type, title, description, icon, closable = true, action, className, onClose }) => {
55
+ return /* @__PURE__ */ jsxs("div", {
56
+ role: "status",
57
+ className: cn("pointer-events-auto flex w-80 items-start gap-3 rounded-lg", "bg-background text-foreground border p-4 shadow-lg", className),
58
+ children: [
59
+ (icon || type) && /* @__PURE__ */ jsx("div", {
60
+ className: "mt-0.5 shrink-0 [&_svg]:size-5",
61
+ children: icon || type && TYPE_ICONS[type]
62
+ }),
63
+ /* @__PURE__ */ jsxs("div", {
64
+ className: "flex-1 space-y-1",
65
+ children: [
66
+ /* @__PURE__ */ jsx("p", {
67
+ className: "text-sm font-medium",
68
+ children: title
69
+ }),
70
+ description && /* @__PURE__ */ jsx("p", {
71
+ className: "text-muted-foreground text-sm",
72
+ children: description
73
+ }),
74
+ action && /* @__PURE__ */ jsx("div", {
75
+ className: "pt-1",
76
+ children: action
77
+ })
78
+ ]
79
+ }),
80
+ closable && /* @__PURE__ */ jsx(Button, {
81
+ type: "text",
82
+ shape: "circle",
83
+ size: "small",
84
+ "aria-label": "Close",
85
+ icon: /* @__PURE__ */ jsx(X, {}),
86
+ onClick: onClose
87
+ })
88
+ ]
89
+ });
90
+ };
91
+ const DEFAULT_DURATION = 4e3;
92
+ const StaticToast = ({ id, duration = DEFAULT_DURATION, container, onClose, ...props }) => {
93
+ const [visible, setVisible] = useState(true);
94
+ const close = () => {
95
+ onClose?.();
96
+ setVisible(false);
97
+ setTimeout(() => {
98
+ Toast.destroy(id);
99
+ }, 200);
100
+ };
101
+ useEffect(() => {
102
+ if (!duration) return;
103
+ const timer = setTimeout(close, duration);
104
+ return () => clearTimeout(timer);
105
+ }, [duration]);
106
+ if (!isBrowser) return null;
107
+ return createPortal(/* @__PURE__ */ jsx("div", {
108
+ className: cn("transition-all duration-200", visible ? "opacity-100" : "translate-x-2 opacity-0"),
109
+ children: /* @__PURE__ */ jsx(Toast, {
110
+ ...props,
111
+ onClose: close
112
+ })
113
+ }), createToastRoot(container));
114
+ };
115
+ const ToastStackRenderer = ({ container }) => {
116
+ const [, forceUpdate] = useState({});
117
+ useEffect(() => {
118
+ const state = getContainerState(container);
119
+ state.update = () => forceUpdate({});
120
+ return () => {
121
+ state.update = null;
122
+ };
123
+ }, [container]);
124
+ const { stack } = getContainerState(container);
125
+ return /* @__PURE__ */ jsx(Fragment$1, { children: stack.map(({ id, ...props }) => /* @__PURE__ */ jsx(StaticToast, {
126
+ id,
127
+ ...props
128
+ }, id)) });
129
+ };
130
+ const toastRoots = /* @__PURE__ */ new Map();
131
+ const renderToast = (props) => {
132
+ if (!isBrowser) return;
133
+ const targetContainer = props.container || document.body;
134
+ const rootElement = createToastRoot(targetContainer);
135
+ if (!toastRoots.has(targetContainer)) {
136
+ const root = createRoot(rootElement);
137
+ toastRoots.set(targetContainer, root);
138
+ root.render(/* @__PURE__ */ jsx(ToastStackRenderer, { container: targetContainer }));
139
+ }
140
+ const state = getContainerState(targetContainer);
141
+ const id = props.id || v4();
142
+ state.stack.push({
143
+ ...props,
144
+ id
145
+ });
146
+ state.update?.();
147
+ return id;
148
+ };
149
+ Toast.destroy = (id) => {
150
+ if (!id) {
151
+ containerStates.forEach((state) => {
152
+ state.stack = [];
153
+ state.update?.();
154
+ });
155
+ toastRoots.forEach((root) => root.unmount());
156
+ toastRoots.clear();
157
+ containerStates.clear();
158
+ return;
159
+ }
160
+ containerStates.forEach((state, container) => {
161
+ if (!state.stack.some((toast) => toast.id === id)) return;
162
+ state.stack = state.stack.filter((toast) => toast.id !== id);
163
+ state.update?.();
164
+ if (!state.stack.length) {
165
+ toastRoots.get(container)?.unmount();
166
+ toastRoots.delete(container);
167
+ containerStates.delete(container);
168
+ }
169
+ });
170
+ };
171
+ Toast.destroyAll = () => {
172
+ Toast.destroy();
173
+ };
174
+ Toast.info = (title, props) => renderToast({
175
+ type: "info",
176
+ title,
177
+ ...props
178
+ });
179
+ Toast.success = (title, props) => renderToast({
180
+ type: "success",
181
+ title,
182
+ ...props
183
+ });
184
+ Toast.error = (title, props) => renderToast({
185
+ type: "error",
186
+ title,
187
+ ...props
188
+ });
189
+ Toast.warning = (title, props) => renderToast({
190
+ type: "warning",
191
+ title,
192
+ ...props
193
+ });
194
+
195
+ //#endregion
196
+ export { Toast as default };
197
+ //# sourceMappingURL=toast.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toast.mjs","names":["uuid"],"sources":["../../../src/components/organisms/toast.tsx"],"sourcesContent":["'use client';\n\nimport { useEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Root, createRoot } from 'react-dom/client';\n\nimport { Check, Info, OctagonAlert, OctagonX, X } from 'lucide-react';\nimport { v4 as uuid } from 'uuid';\n\nimport { cn } from '@repo/ui/utils';\n\nimport Button from '../atoms/button';\n\ntype ToastType = 'info' | 'success' | 'error' | 'warning';\n\nexport interface Props {\n type?: ToastType;\n title: React.ReactNode;\n description?: React.ReactNode;\n icon?: React.ReactNode;\n closable?: boolean;\n action?: React.ReactNode;\n className?: string;\n onClose?: () => void;\n}\n\ninterface StaticProps extends Props {\n id?: string;\n duration?: number;\n container?: HTMLElement;\n}\n\nconst isBrowser =\n typeof window !== 'undefined' && typeof document !== 'undefined';\n\ntype ContainerState = {\n stack: StaticProps[];\n update: (() => void) | null;\n};\n\nconst containerStates = new Map<HTMLElement, ContainerState>();\n\nconst getContainerState = (container: HTMLElement): ContainerState => {\n let state = containerStates.get(container);\n\n if (!state) {\n state = { stack: [], update: null };\n containerStates.set(container, state);\n }\n\n return state;\n};\n\nconst createToastRoot = (container?: HTMLElement) => {\n if (!isBrowser) {\n return null;\n }\n\n const targetContainer = container || document.body;\n let rootEl = targetContainer.querySelector(\n '#toast-root',\n ) as HTMLElement | null;\n\n if (!rootEl) {\n rootEl = document.createElement('div');\n rootEl.setAttribute('id', 'toast-root');\n rootEl.setAttribute('role', 'region');\n rootEl.setAttribute('aria-label', 'Notifications');\n rootEl.style.zIndex = '10000';\n rootEl.style.position = 'fixed';\n rootEl.style.right = '0';\n rootEl.style.bottom = '0';\n rootEl.style.display = 'flex';\n rootEl.style.flexDirection = 'column-reverse';\n rootEl.style.gap = '8px';\n rootEl.style.padding = '16px';\n rootEl.style.pointerEvents = 'none';\n targetContainer.appendChild(rootEl);\n }\n\n return rootEl;\n};\n\nconst TYPE_ICONS: Record<ToastType, React.ReactNode> = {\n info: <Info className=\"text-blue-400\" />,\n success: <Check className=\"text-green-400\" />,\n error: <OctagonX className=\"text-red-400\" />,\n warning: <OctagonAlert className=\"text-yellow-400\" />,\n};\n\nconst Toast = ({\n type,\n title,\n description,\n icon,\n closable = true,\n action,\n className,\n onClose,\n}: Props) => {\n return (\n <div\n role=\"status\"\n className={cn(\n 'pointer-events-auto flex w-80 items-start gap-3 rounded-lg',\n 'bg-background text-foreground border p-4 shadow-lg',\n className,\n //\n )}\n >\n {(icon || type) && (\n <div className=\"mt-0.5 shrink-0 [&_svg]:size-5\">\n {icon || (type && TYPE_ICONS[type])}\n </div>\n )}\n <div className=\"flex-1 space-y-1\">\n <p className=\"text-sm font-medium\">{title}</p>\n {description && (\n <p className=\"text-muted-foreground text-sm\">{description}</p>\n )}\n {action && <div className=\"pt-1\">{action}</div>}\n </div>\n {closable && (\n <Button\n type=\"text\"\n shape=\"circle\"\n size=\"small\"\n aria-label=\"Close\"\n icon={<X />}\n onClick={onClose}\n />\n )}\n </div>\n );\n};\n\nconst DEFAULT_DURATION = 4000;\n\nconst StaticToast = ({\n id,\n duration = DEFAULT_DURATION,\n container,\n onClose,\n ...props\n}: StaticProps) => {\n const [visible, setVisible] = useState(true);\n\n const close = () => {\n onClose?.();\n setVisible(false);\n setTimeout(() => {\n Toast.destroy(id);\n }, 200);\n };\n\n useEffect(() => {\n if (!duration) {\n return;\n }\n\n const timer = setTimeout(close, duration);\n return () => clearTimeout(timer);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [duration]);\n\n if (!isBrowser) {\n return null;\n }\n\n return createPortal(\n <div\n className={cn(\n 'transition-all duration-200',\n visible ? 'opacity-100' : 'translate-x-2 opacity-0',\n )}\n >\n <Toast {...props} onClose={close} />\n </div>,\n createToastRoot(container)!,\n );\n};\n\nconst ToastStackRenderer = ({ container }: { container: HTMLElement }) => {\n const [, forceUpdate] = useState({});\n\n useEffect(() => {\n const state = getContainerState(container);\n state.update = () => forceUpdate({});\n return () => {\n state.update = null;\n };\n }, [container]);\n\n const { stack } = getContainerState(container);\n\n return (\n <>\n {stack.map(({ id, ...props }) => (\n <StaticToast key={id} id={id} {...props} />\n ))}\n </>\n );\n};\n\nconst toastRoots = new Map<HTMLElement, Root>();\n\nconst renderToast = (props: StaticProps) => {\n if (!isBrowser) {\n return;\n }\n\n const targetContainer = props.container || document.body;\n const rootElement = createToastRoot(targetContainer)!;\n\n if (!toastRoots.has(targetContainer)) {\n const root = createRoot(rootElement);\n toastRoots.set(targetContainer, root);\n root.render(<ToastStackRenderer container={targetContainer} />);\n }\n\n const state = getContainerState(targetContainer);\n const id = props.id || uuid();\n state.stack.push({ ...props, id });\n state.update?.();\n\n return id;\n};\n\nToast.destroy = (id?: string) => {\n if (!id) {\n containerStates.forEach(state => {\n state.stack = [];\n state.update?.();\n });\n toastRoots.forEach(root => root.unmount());\n toastRoots.clear();\n containerStates.clear();\n return;\n }\n\n containerStates.forEach((state, container) => {\n if (!state.stack.some(toast => toast.id === id)) {\n return;\n }\n\n state.stack = state.stack.filter(toast => toast.id !== id);\n state.update?.();\n\n if (!state.stack.length) {\n toastRoots.get(container)?.unmount();\n toastRoots.delete(container);\n containerStates.delete(container);\n }\n });\n};\n\nToast.destroyAll = () => {\n Toast.destroy();\n};\n\ntype TriggerOptions = Omit<StaticProps, 'type' | 'title'>;\n\nToast.info = (title: React.ReactNode, props?: TriggerOptions) =>\n renderToast({ type: 'info', title, ...props });\nToast.success = (title: React.ReactNode, props?: TriggerOptions) =>\n renderToast({ type: 'success', title, ...props });\nToast.error = (title: React.ReactNode, props?: TriggerOptions) =>\n renderToast({ type: 'error', title, ...props });\nToast.warning = (title: React.ReactNode, props?: TriggerOptions) =>\n renderToast({ type: 'warning', title, ...props });\n\nexport default Toast;\nexport type { StaticProps as ToastOptions };\n"],"mappings":"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"}
@@ -8,7 +8,7 @@ declare namespace badge_d_exports {
8
8
  export { Badge, Props, badgeVariants };
9
9
  }
10
10
  declare const badgeVariants: (props?: ({
11
- variant?: "default" | "destructive" | "outline" | "secondary" | null | undefined;
11
+ variant?: "default" | "secondary" | "destructive" | "outline" | null | undefined;
12
12
  } & class_variance_authority_types0.ClassProp) | undefined) => string;
13
13
  type Props = React$1.ComponentProps<'span'> & VariantProps<typeof badgeVariants> & {
14
14
  asChild?: boolean;
@@ -8,7 +8,7 @@ declare namespace button_d_exports {
8
8
  export { Button, Props, buttonVariants };
9
9
  }
10
10
  declare const buttonVariants: (props?: ({
11
- variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
11
+ variant?: "link" | "default" | "secondary" | "destructive" | "outline" | "ghost" | null | undefined;
12
12
  size?: "default" | "icon" | "xs" | "sm" | "lg" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
13
13
  } & class_variance_authority_types0.ClassProp) | undefined) => string;
14
14
  type Props = React$1.ComponentProps<'button'> & VariantProps<typeof buttonVariants> & {
package/dist/index.d.mts CHANGED
@@ -29,10 +29,11 @@ import { Drawer, Props as Props$1 } from "./components/organisms/drawer.mjs";
29
29
  import { List } from "./components/organisms/list/index.mjs";
30
30
  import { Modal } from "./components/organisms/modal.mjs";
31
31
  import { Swiper } from "./components/organisms/swiper/index.mjs";
32
+ import { StaticProps, Toast } from "./components/organisms/toast.mjs";
32
33
  import "./components/organisms/index.mjs";
33
34
  import "./components/templates/index.mjs";
34
35
  import { ThemeConfig, ThemeToken } from "./providers/Config/types.mjs";
35
36
  import { useConfig } from "./providers/Config/context.mjs";
36
37
  import { Config, Props } from "./providers/Config/index.mjs";
37
38
  import "./providers/index.mjs";
38
- export { Button, Card, Checkbox, Collapse, ColorPicker, Config, Props as ConfigProps, DatePicker, Drawer, Props$1 as DrawerProps, Dropdown, FloatButton, Input, Layout, List, Marquees, Menu, Modal, Popover, Progress, Radio, Reveals, Select, Skeleton, Space, Spin, Splitter, Swiper, Switch, Tag, ThemeConfig, ThemeToken, Typography, Upload, UploadFile, useConfig };
39
+ export { Button, Card, Checkbox, Collapse, ColorPicker, Config, Props as ConfigProps, DatePicker, Drawer, Props$1 as DrawerProps, Dropdown, FloatButton, Input, Layout, List, Marquees, Menu, Modal, Popover, Progress, Radio, Reveals, Select, Skeleton, Space, Spin, Splitter, Swiper, Switch, Tag, ThemeConfig, ThemeToken, Toast, StaticProps as ToastOptions, Typography, Upload, UploadFile, useConfig };
package/dist/index.mjs CHANGED
@@ -27,8 +27,9 @@ import Drawer from "./components/organisms/drawer.mjs";
27
27
  import List from "./components/organisms/list/index.mjs";
28
28
  import Modal from "./components/organisms/modal.mjs";
29
29
  import Swiper from "./components/organisms/swiper/index.mjs";
30
+ import Toast from "./components/organisms/toast.mjs";
30
31
  import Layout from "./Layout.mjs";
31
32
  import { useConfig } from "./providers/Config/context.mjs";
32
33
  import Config from "./providers/Config/index.mjs";
33
34
 
34
- export { Button, Card, Checkbox, Collapse, ColorPicker, Config, DatePicker, Drawer, Dropdown, FloatButton, Input, Layout, List, Marquees, Menu, Modal, Popover, Progress, Radio, Reveals, Select, Skeleton, Space, Spin, Splitter, Swiper, Switch, Tag, Typography, Upload, useConfig };
35
+ export { Button, Card, Checkbox, Collapse, ColorPicker, Config, DatePicker, Drawer, Dropdown, FloatButton, Input, Layout, List, Marquees, Menu, Modal, Popover, Progress, Radio, Reveals, Select, Skeleton, Space, Spin, Splitter, Swiper, Switch, Tag, Toast, Typography, Upload, useConfig };
package/dist/style.css CHANGED
@@ -204,12 +204,18 @@
204
204
  container-type: inline-size;
205
205
  container-name: field-group;
206
206
  }
207
+ .pointer-events-auto {
208
+ pointer-events: auto;
209
+ }
207
210
  .pointer-events-none {
208
211
  pointer-events: none;
209
212
  }
210
213
  .invisible {
211
214
  visibility: hidden;
212
215
  }
216
+ .visible {
217
+ visibility: visible;
218
+ }
213
219
  .sr-only {
214
220
  position: absolute;
215
221
  width: 1px;
@@ -353,6 +359,9 @@
353
359
  .my-1 {
354
360
  margin-block: calc(var(--spacing) * 1);
355
361
  }
362
+ .mt-0\.5 {
363
+ margin-top: calc(var(--spacing) * 0.5);
364
+ }
356
365
  .mt-2 {
357
366
  margin-top: calc(var(--spacing) * 2);
358
367
  }
@@ -577,6 +586,9 @@
577
586
  .w-72 {
578
587
  width: calc(var(--spacing) * 72);
579
588
  }
589
+ .w-80 {
590
+ width: calc(var(--spacing) * 80);
591
+ }
580
592
  .w-100 {
581
593
  width: calc(var(--spacing) * 100);
582
594
  }
@@ -660,6 +672,10 @@
660
672
  --tw-translate-x: calc(calc(1/2 * 100%) * -1);
661
673
  translate: var(--tw-translate-x) var(--tw-translate-y);
662
674
  }
675
+ .translate-x-2 {
676
+ --tw-translate-x: calc(var(--spacing) * 2);
677
+ translate: var(--tw-translate-x) var(--tw-translate-y);
678
+ }
663
679
  .translate-x-\[-50\%\] {
664
680
  --tw-translate-x: -50%;
665
681
  translate: var(--tw-translate-x) var(--tw-translate-y);
@@ -800,6 +816,13 @@
800
816
  .gap-7 {
801
817
  gap: calc(var(--spacing) * 7);
802
818
  }
819
+ .space-y-1 {
820
+ :where(& > :not(:last-child)) {
821
+ --tw-space-y-reverse: 0;
822
+ margin-block-start: calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse));
823
+ margin-block-end: calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse)));
824
+ }
825
+ }
803
826
  .space-y-2 {
804
827
  :where(& > :not(:last-child)) {
805
828
  --tw-space-y-reverse: 0;
@@ -1119,6 +1142,9 @@
1119
1142
  .pt-0 {
1120
1143
  padding-top: calc(var(--spacing) * 0);
1121
1144
  }
1145
+ .pt-1 {
1146
+ padding-top: calc(var(--spacing) * 1);
1147
+ }
1122
1148
  .pt-2 {
1123
1149
  padding-top: calc(var(--spacing) * 2);
1124
1150
  }
@@ -2998,6 +3024,12 @@
2998
3024
  pointer-events: none;
2999
3025
  }
3000
3026
  }
3027
+ .\[\&_svg\]\:size-5 {
3028
+ & svg {
3029
+ width: calc(var(--spacing) * 5);
3030
+ height: calc(var(--spacing) * 5);
3031
+ }
3032
+ }
3001
3033
  .\[\&_svg\]\:shrink-0 {
3002
3034
  & svg {
3003
3035
  flex-shrink: 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbpark/ui-kit",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "Modern React UI component library built with TypeScript, Tailwind CSS, and Radix UI. Featuring atoms, molecules, organisms and layout templates for building beautiful interfaces.",
5
5
  "keywords": [
6
6
  "react",