@particle-academy/react-fancy 5.17.0 → 5.17.1

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.
@@ -43,7 +43,14 @@ function ModalHeader({ children, className }) {
43
43
  }
44
44
  ModalHeader.displayName = "ModalHeader";
45
45
  function ModalBody({ children, className }) {
46
- return /* @__PURE__ */ jsx("div", { "data-react-fancy-modal-body": "", className: cn("flex-1 overflow-y-auto px-6 py-4 text-zinc-700 dark:text-zinc-300", className), children });
46
+ return (
47
+ // `min-h-0` is load-bearing, not decoration. A flex child defaults to
48
+ // `min-height: auto`, which refuses to shrink below its content — so
49
+ // `flex-1` alone would push the panel through its own max-height and the
50
+ // scrollbar would never appear. This is what permits the overflow that
51
+ // `overflow-y-auto` then handles.
52
+ /* @__PURE__ */ jsx("div", { "data-react-fancy-modal-body": "", className: cn("min-h-0 flex-1 overflow-y-auto px-6 py-4 text-zinc-700 dark:text-zinc-300", className), children })
53
+ );
47
54
  }
48
55
  ModalBody.displayName = "ModalBody";
49
56
  function ModalFooter({ children, className }) {
@@ -60,12 +67,13 @@ function ModalFooter({ children, className }) {
60
67
  );
61
68
  }
62
69
  ModalFooter.displayName = "ModalFooter";
70
+ var VIEWPORT_CAP = "max-h-[calc(100vh-2rem)] max-h-[calc(100dvh-2rem)]";
63
71
  var SIZE_MAP = {
64
- sm: "max-w-sm",
65
- md: "max-w-lg",
66
- lg: "max-w-2xl",
67
- xl: "max-w-4xl",
68
- full: "max-w-[calc(100vw-2rem)] max-h-[calc(100vh-2rem)]"
72
+ sm: `max-w-sm ${VIEWPORT_CAP}`,
73
+ md: `max-w-lg ${VIEWPORT_CAP}`,
74
+ lg: `max-w-2xl ${VIEWPORT_CAP}`,
75
+ xl: `max-w-4xl ${VIEWPORT_CAP}`,
76
+ full: `max-w-[calc(100vw-2rem)] ${VIEWPORT_CAP}`
69
77
  };
70
78
  function ModalRoot({
71
79
  children,
@@ -133,5 +141,5 @@ var Modal = Object.assign(ModalRoot, {
133
141
  });
134
142
 
135
143
  export { Modal, useModal };
136
- //# sourceMappingURL=chunk-MYF2PDTU.js.map
137
- //# sourceMappingURL=chunk-MYF2PDTU.js.map
144
+ //# sourceMappingURL=chunk-M645OITZ.js.map
145
+ //# sourceMappingURL=chunk-M645OITZ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Modal/Modal.context.ts","../src/components/Modal/ModalHeader.tsx","../src/components/Modal/ModalBody.tsx","../src/components/Modal/ModalFooter.tsx","../src/components/Modal/Modal.tsx"],"names":["jsx","jsxs"],"mappings":"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","file":"chunk-M645OITZ.js","sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { ModalContextValue } from \"./Modal.types\";\n\nexport const ModalContext = createContext<ModalContextValue | null>(null);\n\nexport function useModal(): ModalContextValue {\n const ctx = useContext(ModalContext);\n if (!ctx) {\n throw new Error(\"Modal compound components must be used within <Modal>\");\n }\n return ctx;\n}\n","import { X } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport { useModal } from \"./Modal.context\";\nimport type { ModalHeaderProps } from \"./Modal.types\";\n\nexport function ModalHeader({ children, className }: ModalHeaderProps) {\n const { close } = useModal();\n\n return (\n <div\n data-react-fancy-modal-header=\"\"\n className={cn(\n \"flex items-center justify-between border-b border-zinc-200 px-6 py-4 dark:border-zinc-700\",\n className,\n )}\n >\n <div className=\"text-lg font-semibold text-zinc-900 dark:text-zinc-100\">{children}</div>\n <button\n type=\"button\"\n onClick={close}\n className=\"rounded-lg p-1 text-zinc-400 transition-colors hover:bg-zinc-100 hover:text-zinc-600 dark:hover:bg-zinc-800 dark:hover:text-zinc-300\"\n aria-label=\"Close\"\n >\n <X size={20} />\n </button>\n </div>\n );\n}\n\nModalHeader.displayName = \"ModalHeader\";\n","import { cn } from \"../../utils/cn\";\nimport type { ModalBodyProps } from \"./Modal.types\";\n\nexport function ModalBody({ children, className }: ModalBodyProps) {\n return (\n // `min-h-0` is load-bearing, not decoration. A flex child defaults to\n // `min-height: auto`, which refuses to shrink below its content — so\n // `flex-1` alone would push the panel through its own max-height and the\n // scrollbar would never appear. This is what permits the overflow that\n // `overflow-y-auto` then handles.\n <div data-react-fancy-modal-body=\"\" className={cn(\"min-h-0 flex-1 overflow-y-auto px-6 py-4 text-zinc-700 dark:text-zinc-300\", className)}>\n {children}\n </div>\n );\n}\n\nModalBody.displayName = \"ModalBody\";\n","import { cn } from \"../../utils/cn\";\nimport type { ModalFooterProps } from \"./Modal.types\";\n\nexport function ModalFooter({ children, className }: ModalFooterProps) {\n return (\n <div\n data-react-fancy-modal-footer=\"\"\n className={cn(\n \"flex items-center justify-end gap-3 border-t border-zinc-200 px-6 py-4 dark:border-zinc-700\",\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\nModalFooter.displayName = \"ModalFooter\";\n","import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Portal } from \"../Portal\";\nimport { ModalContext } from \"./Modal.context\";\nimport { ModalHeader } from \"./ModalHeader\";\nimport { ModalBody } from \"./ModalBody\";\nimport { ModalFooter } from \"./ModalFooter\";\nimport { useFocusTrap } from \"../../hooks/use-focus-trap\";\nimport { useEscapeKey } from \"../../hooks/use-escape-key\";\nimport { useAnimation } from \"../../hooks/use-animation\";\nimport type { ModalProps } from \"./Modal.types\";\n\n/**\n * Every size is capped against the VIEWPORT, not just the width.\n *\n * Only `full` used to carry a max-height. The other four were width-constrained\n * and vertically unbounded, so a modal with long content simply grew past the\n * bottom of the screen and the rest became unreachable — no scrollbar, because\n * there was no overflow to scroll: the box got taller instead.\n *\n * `ModalBody` already had `flex-1 overflow-y-auto` and the panel already had\n * `overflow-hidden`. The scrolling machinery was complete and inert, waiting on\n * the one constraint that makes it engage.\n *\n * `dvh` over `vh` deliberately: on mobile browsers `100vh` is the tallest the\n * viewport ever gets, ignoring the address bar, so a `vh`-capped modal still\n * runs under the chrome on exactly the devices with least room. `dvh` tracks\n * the visible height. The `vh` fallback is listed first for any engine that\n * does not know `dvh` yet — an unknown unit drops the declaration, so ordering\n * is what keeps the old behaviour rather than none.\n */\nconst VIEWPORT_CAP = \"max-h-[calc(100vh-2rem)] max-h-[calc(100dvh-2rem)]\";\n\nconst SIZE_MAP = {\n sm: `max-w-sm ${VIEWPORT_CAP}`,\n md: `max-w-lg ${VIEWPORT_CAP}`,\n lg: `max-w-2xl ${VIEWPORT_CAP}`,\n xl: `max-w-4xl ${VIEWPORT_CAP}`,\n full: `max-w-[calc(100vw-2rem)] ${VIEWPORT_CAP}`,\n} as const;\n\nfunction ModalRoot({\n children,\n open,\n onClose,\n size = \"md\",\n className,\n ...rest\n}: ModalProps) {\n const panelRef = useRef<HTMLDivElement>(null);\n\n const close = useCallback(() => onClose(), [onClose]);\n useEscapeKey(close, open);\n useFocusTrap(panelRef, open);\n\n // Body scroll lock\n useEffect(() => {\n if (open) {\n const original = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = original;\n };\n }\n }, [open]);\n\n const { mounted, className: animClass, ref: animRef } = useAnimation({\n open,\n enterClass: \"fancy-slide-up\",\n exitClass: \"fancy-fade-out\",\n });\n\n const ctx = useMemo(() => ({ open, close }), [open, close]);\n\n if (!mounted) return null;\n\n return (\n <ModalContext.Provider value={ctx}>\n <Portal>\n <div className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n {/* Backdrop */}\n <div\n className=\"absolute inset-0 bg-black/50 backdrop-blur-sm\"\n onClick={close}\n aria-hidden=\"true\"\n />\n {/* Panel */}\n <div\n ref={(node) => {\n panelRef.current = node;\n (animRef as React.MutableRefObject<HTMLElement | null>).current =\n node;\n }}\n data-react-fancy-modal=\"\"\n role=\"dialog\"\n aria-modal=\"true\"\n {...rest}\n className={cn(\n \"relative flex w-full flex-col overflow-hidden rounded-2xl border border-zinc-200 bg-white shadow-xl dark:border-zinc-700 dark:bg-zinc-900\",\n SIZE_MAP[size],\n animClass,\n className,\n )}\n >\n {children}\n </div>\n </div>\n </Portal>\n </ModalContext.Provider>\n );\n}\n\nexport const Modal = Object.assign(ModalRoot, {\n Header: ModalHeader,\n Body: ModalBody,\n Footer: ModalFooter,\n});\n"]}
@@ -45,7 +45,14 @@ function ModalHeader({ children, className }) {
45
45
  }
46
46
  ModalHeader.displayName = "ModalHeader";
47
47
  function ModalBody({ children, className }) {
48
- return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-react-fancy-modal-body": "", className: chunk3Z6ALUWP_cjs.cn("flex-1 overflow-y-auto px-6 py-4 text-zinc-700 dark:text-zinc-300", className), children });
48
+ return (
49
+ // `min-h-0` is load-bearing, not decoration. A flex child defaults to
50
+ // `min-height: auto`, which refuses to shrink below its content — so
51
+ // `flex-1` alone would push the panel through its own max-height and the
52
+ // scrollbar would never appear. This is what permits the overflow that
53
+ // `overflow-y-auto` then handles.
54
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "data-react-fancy-modal-body": "", className: chunk3Z6ALUWP_cjs.cn("min-h-0 flex-1 overflow-y-auto px-6 py-4 text-zinc-700 dark:text-zinc-300", className), children })
55
+ );
49
56
  }
50
57
  ModalBody.displayName = "ModalBody";
51
58
  function ModalFooter({ children, className }) {
@@ -62,12 +69,13 @@ function ModalFooter({ children, className }) {
62
69
  );
63
70
  }
64
71
  ModalFooter.displayName = "ModalFooter";
72
+ var VIEWPORT_CAP = "max-h-[calc(100vh-2rem)] max-h-[calc(100dvh-2rem)]";
65
73
  var SIZE_MAP = {
66
- sm: "max-w-sm",
67
- md: "max-w-lg",
68
- lg: "max-w-2xl",
69
- xl: "max-w-4xl",
70
- full: "max-w-[calc(100vw-2rem)] max-h-[calc(100vh-2rem)]"
74
+ sm: `max-w-sm ${VIEWPORT_CAP}`,
75
+ md: `max-w-lg ${VIEWPORT_CAP}`,
76
+ lg: `max-w-2xl ${VIEWPORT_CAP}`,
77
+ xl: `max-w-4xl ${VIEWPORT_CAP}`,
78
+ full: `max-w-[calc(100vw-2rem)] ${VIEWPORT_CAP}`
71
79
  };
72
80
  function ModalRoot({
73
81
  children,
@@ -136,5 +144,5 @@ var Modal = Object.assign(ModalRoot, {
136
144
 
137
145
  exports.Modal = Modal;
138
146
  exports.useModal = useModal;
139
- //# sourceMappingURL=chunk-TZKZ2LUF.cjs.map
140
- //# sourceMappingURL=chunk-TZKZ2LUF.cjs.map
147
+ //# sourceMappingURL=chunk-UPVWN72I.cjs.map
148
+ //# sourceMappingURL=chunk-UPVWN72I.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Modal/Modal.context.ts","../src/components/Modal/ModalHeader.tsx","../src/components/Modal/ModalBody.tsx","../src/components/Modal/ModalFooter.tsx","../src/components/Modal/Modal.tsx"],"names":["createContext","useContext","jsxs","cn","jsx","X","useRef","useCallback","useEscapeKey","useFocusTrap","useEffect","useAnimation","useMemo","Portal"],"mappings":"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","file":"chunk-UPVWN72I.cjs","sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { ModalContextValue } from \"./Modal.types\";\n\nexport const ModalContext = createContext<ModalContextValue | null>(null);\n\nexport function useModal(): ModalContextValue {\n const ctx = useContext(ModalContext);\n if (!ctx) {\n throw new Error(\"Modal compound components must be used within <Modal>\");\n }\n return ctx;\n}\n","import { X } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport { useModal } from \"./Modal.context\";\nimport type { ModalHeaderProps } from \"./Modal.types\";\n\nexport function ModalHeader({ children, className }: ModalHeaderProps) {\n const { close } = useModal();\n\n return (\n <div\n data-react-fancy-modal-header=\"\"\n className={cn(\n \"flex items-center justify-between border-b border-zinc-200 px-6 py-4 dark:border-zinc-700\",\n className,\n )}\n >\n <div className=\"text-lg font-semibold text-zinc-900 dark:text-zinc-100\">{children}</div>\n <button\n type=\"button\"\n onClick={close}\n className=\"rounded-lg p-1 text-zinc-400 transition-colors hover:bg-zinc-100 hover:text-zinc-600 dark:hover:bg-zinc-800 dark:hover:text-zinc-300\"\n aria-label=\"Close\"\n >\n <X size={20} />\n </button>\n </div>\n );\n}\n\nModalHeader.displayName = \"ModalHeader\";\n","import { cn } from \"../../utils/cn\";\nimport type { ModalBodyProps } from \"./Modal.types\";\n\nexport function ModalBody({ children, className }: ModalBodyProps) {\n return (\n // `min-h-0` is load-bearing, not decoration. A flex child defaults to\n // `min-height: auto`, which refuses to shrink below its content — so\n // `flex-1` alone would push the panel through its own max-height and the\n // scrollbar would never appear. This is what permits the overflow that\n // `overflow-y-auto` then handles.\n <div data-react-fancy-modal-body=\"\" className={cn(\"min-h-0 flex-1 overflow-y-auto px-6 py-4 text-zinc-700 dark:text-zinc-300\", className)}>\n {children}\n </div>\n );\n}\n\nModalBody.displayName = \"ModalBody\";\n","import { cn } from \"../../utils/cn\";\nimport type { ModalFooterProps } from \"./Modal.types\";\n\nexport function ModalFooter({ children, className }: ModalFooterProps) {\n return (\n <div\n data-react-fancy-modal-footer=\"\"\n className={cn(\n \"flex items-center justify-end gap-3 border-t border-zinc-200 px-6 py-4 dark:border-zinc-700\",\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\nModalFooter.displayName = \"ModalFooter\";\n","import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Portal } from \"../Portal\";\nimport { ModalContext } from \"./Modal.context\";\nimport { ModalHeader } from \"./ModalHeader\";\nimport { ModalBody } from \"./ModalBody\";\nimport { ModalFooter } from \"./ModalFooter\";\nimport { useFocusTrap } from \"../../hooks/use-focus-trap\";\nimport { useEscapeKey } from \"../../hooks/use-escape-key\";\nimport { useAnimation } from \"../../hooks/use-animation\";\nimport type { ModalProps } from \"./Modal.types\";\n\n/**\n * Every size is capped against the VIEWPORT, not just the width.\n *\n * Only `full` used to carry a max-height. The other four were width-constrained\n * and vertically unbounded, so a modal with long content simply grew past the\n * bottom of the screen and the rest became unreachable — no scrollbar, because\n * there was no overflow to scroll: the box got taller instead.\n *\n * `ModalBody` already had `flex-1 overflow-y-auto` and the panel already had\n * `overflow-hidden`. The scrolling machinery was complete and inert, waiting on\n * the one constraint that makes it engage.\n *\n * `dvh` over `vh` deliberately: on mobile browsers `100vh` is the tallest the\n * viewport ever gets, ignoring the address bar, so a `vh`-capped modal still\n * runs under the chrome on exactly the devices with least room. `dvh` tracks\n * the visible height. The `vh` fallback is listed first for any engine that\n * does not know `dvh` yet — an unknown unit drops the declaration, so ordering\n * is what keeps the old behaviour rather than none.\n */\nconst VIEWPORT_CAP = \"max-h-[calc(100vh-2rem)] max-h-[calc(100dvh-2rem)]\";\n\nconst SIZE_MAP = {\n sm: `max-w-sm ${VIEWPORT_CAP}`,\n md: `max-w-lg ${VIEWPORT_CAP}`,\n lg: `max-w-2xl ${VIEWPORT_CAP}`,\n xl: `max-w-4xl ${VIEWPORT_CAP}`,\n full: `max-w-[calc(100vw-2rem)] ${VIEWPORT_CAP}`,\n} as const;\n\nfunction ModalRoot({\n children,\n open,\n onClose,\n size = \"md\",\n className,\n ...rest\n}: ModalProps) {\n const panelRef = useRef<HTMLDivElement>(null);\n\n const close = useCallback(() => onClose(), [onClose]);\n useEscapeKey(close, open);\n useFocusTrap(panelRef, open);\n\n // Body scroll lock\n useEffect(() => {\n if (open) {\n const original = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = original;\n };\n }\n }, [open]);\n\n const { mounted, className: animClass, ref: animRef } = useAnimation({\n open,\n enterClass: \"fancy-slide-up\",\n exitClass: \"fancy-fade-out\",\n });\n\n const ctx = useMemo(() => ({ open, close }), [open, close]);\n\n if (!mounted) return null;\n\n return (\n <ModalContext.Provider value={ctx}>\n <Portal>\n <div className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n {/* Backdrop */}\n <div\n className=\"absolute inset-0 bg-black/50 backdrop-blur-sm\"\n onClick={close}\n aria-hidden=\"true\"\n />\n {/* Panel */}\n <div\n ref={(node) => {\n panelRef.current = node;\n (animRef as React.MutableRefObject<HTMLElement | null>).current =\n node;\n }}\n data-react-fancy-modal=\"\"\n role=\"dialog\"\n aria-modal=\"true\"\n {...rest}\n className={cn(\n \"relative flex w-full flex-col overflow-hidden rounded-2xl border border-zinc-200 bg-white shadow-xl dark:border-zinc-700 dark:bg-zinc-900\",\n SIZE_MAP[size],\n animClass,\n className,\n )}\n >\n {children}\n </div>\n </div>\n </Portal>\n </ModalContext.Provider>\n );\n}\n\nexport const Modal = Object.assign(ModalRoot, {\n Header: ModalHeader,\n Body: ModalBody,\n Footer: ModalFooter,\n});\n"]}
package/dist/index.cjs CHANGED
@@ -33,7 +33,7 @@ var chunkIXHZVFHX_cjs = require('./chunk-IXHZVFHX.cjs');
33
33
  var chunk6Y2QO7YV_cjs = require('./chunk-6Y2QO7YV.cjs');
34
34
  var chunkVQ4M25U3_cjs = require('./chunk-VQ4M25U3.cjs');
35
35
  var chunkRR7BWUVP_cjs = require('./chunk-RR7BWUVP.cjs');
36
- var chunkTZKZ2LUF_cjs = require('./chunk-TZKZ2LUF.cjs');
36
+ var chunkUPVWN72I_cjs = require('./chunk-UPVWN72I.cjs');
37
37
  var chunkI6L7OP7G_cjs = require('./chunk-I6L7OP7G.cjs');
38
38
  var chunkB3HVWXIQ_cjs = require('./chunk-B3HVWXIQ.cjs');
39
39
  var chunkE7PHL3TD_cjs = require('./chunk-E7PHL3TD.cjs');
@@ -250,11 +250,11 @@ Object.defineProperty(exports, "Separator", {
250
250
  });
251
251
  Object.defineProperty(exports, "Modal", {
252
252
  enumerable: true,
253
- get: function () { return chunkTZKZ2LUF_cjs.Modal; }
253
+ get: function () { return chunkUPVWN72I_cjs.Modal; }
254
254
  });
255
255
  Object.defineProperty(exports, "useModal", {
256
256
  enumerable: true,
257
- get: function () { return chunkTZKZ2LUF_cjs.useModal; }
257
+ get: function () { return chunkUPVWN72I_cjs.useModal; }
258
258
  });
259
259
  Object.defineProperty(exports, "MoodMeter", {
260
260
  enumerable: true,
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ export { PullQuote } from './chunk-YCZN4FWI.js';
31
31
  export { ReasonTag } from './chunk-HNITJ2UR.js';
32
32
  export { Section } from './chunk-PG3ILQIW.js';
33
33
  export { Separator } from './chunk-QFFC2DKK.js';
34
- export { Modal, useModal } from './chunk-MYF2PDTU.js';
34
+ export { Modal, useModal } from './chunk-M645OITZ.js';
35
35
  export { MoodMeter } from './chunk-32AJIHBZ.js';
36
36
  export { Navbar, useNavbar } from './chunk-D4WM23Y4.js';
37
37
  export { OtpInput } from './chunk-UCYAHLGM.js';
package/dist/modal.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkTZKZ2LUF_cjs = require('./chunk-TZKZ2LUF.cjs');
3
+ var chunkUPVWN72I_cjs = require('./chunk-UPVWN72I.cjs');
4
4
  require('./chunk-TXTRTTG7.cjs');
5
5
  require('./chunk-3WGRVDQR.cjs');
6
6
  require('./chunk-NBZC6LOB.cjs');
@@ -11,11 +11,11 @@ require('./chunk-3Z6ALUWP.cjs');
11
11
 
12
12
  Object.defineProperty(exports, "Modal", {
13
13
  enumerable: true,
14
- get: function () { return chunkTZKZ2LUF_cjs.Modal; }
14
+ get: function () { return chunkUPVWN72I_cjs.Modal; }
15
15
  });
16
16
  Object.defineProperty(exports, "useModal", {
17
17
  enumerable: true,
18
- get: function () { return chunkTZKZ2LUF_cjs.useModal; }
18
+ get: function () { return chunkUPVWN72I_cjs.useModal; }
19
19
  });
20
20
  //# sourceMappingURL=modal.cjs.map
21
21
  //# sourceMappingURL=modal.cjs.map
package/dist/modal.js CHANGED
@@ -1,4 +1,4 @@
1
- export { Modal, useModal } from './chunk-MYF2PDTU.js';
1
+ export { Modal, useModal } from './chunk-M645OITZ.js';
2
2
  import './chunk-5U2DZ7AV.js';
3
3
  import './chunk-CHADHN6M.js';
4
4
  import './chunk-WHEXTDPV.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@particle-academy/react-fancy",
3
- "version": "5.17.0",
3
+ "version": "5.17.1",
4
4
  "description": "React UI component library for Human+ UX — controlled, agent-bridgeable primitives",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/Modal/Modal.context.ts","../src/components/Modal/ModalHeader.tsx","../src/components/Modal/ModalBody.tsx","../src/components/Modal/ModalFooter.tsx","../src/components/Modal/Modal.tsx"],"names":["jsx","jsxs"],"mappings":"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","file":"chunk-MYF2PDTU.js","sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { ModalContextValue } from \"./Modal.types\";\n\nexport const ModalContext = createContext<ModalContextValue | null>(null);\n\nexport function useModal(): ModalContextValue {\n const ctx = useContext(ModalContext);\n if (!ctx) {\n throw new Error(\"Modal compound components must be used within <Modal>\");\n }\n return ctx;\n}\n","import { X } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport { useModal } from \"./Modal.context\";\nimport type { ModalHeaderProps } from \"./Modal.types\";\n\nexport function ModalHeader({ children, className }: ModalHeaderProps) {\n const { close } = useModal();\n\n return (\n <div\n data-react-fancy-modal-header=\"\"\n className={cn(\n \"flex items-center justify-between border-b border-zinc-200 px-6 py-4 dark:border-zinc-700\",\n className,\n )}\n >\n <div className=\"text-lg font-semibold text-zinc-900 dark:text-zinc-100\">{children}</div>\n <button\n type=\"button\"\n onClick={close}\n className=\"rounded-lg p-1 text-zinc-400 transition-colors hover:bg-zinc-100 hover:text-zinc-600 dark:hover:bg-zinc-800 dark:hover:text-zinc-300\"\n aria-label=\"Close\"\n >\n <X size={20} />\n </button>\n </div>\n );\n}\n\nModalHeader.displayName = \"ModalHeader\";\n","import { cn } from \"../../utils/cn\";\nimport type { ModalBodyProps } from \"./Modal.types\";\n\nexport function ModalBody({ children, className }: ModalBodyProps) {\n return (\n <div data-react-fancy-modal-body=\"\" className={cn(\"flex-1 overflow-y-auto px-6 py-4 text-zinc-700 dark:text-zinc-300\", className)}>\n {children}\n </div>\n );\n}\n\nModalBody.displayName = \"ModalBody\";\n","import { cn } from \"../../utils/cn\";\nimport type { ModalFooterProps } from \"./Modal.types\";\n\nexport function ModalFooter({ children, className }: ModalFooterProps) {\n return (\n <div\n data-react-fancy-modal-footer=\"\"\n className={cn(\n \"flex items-center justify-end gap-3 border-t border-zinc-200 px-6 py-4 dark:border-zinc-700\",\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\nModalFooter.displayName = \"ModalFooter\";\n","import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Portal } from \"../Portal\";\nimport { ModalContext } from \"./Modal.context\";\nimport { ModalHeader } from \"./ModalHeader\";\nimport { ModalBody } from \"./ModalBody\";\nimport { ModalFooter } from \"./ModalFooter\";\nimport { useFocusTrap } from \"../../hooks/use-focus-trap\";\nimport { useEscapeKey } from \"../../hooks/use-escape-key\";\nimport { useAnimation } from \"../../hooks/use-animation\";\nimport type { ModalProps } from \"./Modal.types\";\n\nconst SIZE_MAP = {\n sm: \"max-w-sm\",\n md: \"max-w-lg\",\n lg: \"max-w-2xl\",\n xl: \"max-w-4xl\",\n full: \"max-w-[calc(100vw-2rem)] max-h-[calc(100vh-2rem)]\",\n} as const;\n\nfunction ModalRoot({\n children,\n open,\n onClose,\n size = \"md\",\n className,\n ...rest\n}: ModalProps) {\n const panelRef = useRef<HTMLDivElement>(null);\n\n const close = useCallback(() => onClose(), [onClose]);\n useEscapeKey(close, open);\n useFocusTrap(panelRef, open);\n\n // Body scroll lock\n useEffect(() => {\n if (open) {\n const original = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = original;\n };\n }\n }, [open]);\n\n const { mounted, className: animClass, ref: animRef } = useAnimation({\n open,\n enterClass: \"fancy-slide-up\",\n exitClass: \"fancy-fade-out\",\n });\n\n const ctx = useMemo(() => ({ open, close }), [open, close]);\n\n if (!mounted) return null;\n\n return (\n <ModalContext.Provider value={ctx}>\n <Portal>\n <div className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n {/* Backdrop */}\n <div\n className=\"absolute inset-0 bg-black/50 backdrop-blur-sm\"\n onClick={close}\n aria-hidden=\"true\"\n />\n {/* Panel */}\n <div\n ref={(node) => {\n panelRef.current = node;\n (animRef as React.MutableRefObject<HTMLElement | null>).current =\n node;\n }}\n data-react-fancy-modal=\"\"\n role=\"dialog\"\n aria-modal=\"true\"\n {...rest}\n className={cn(\n \"relative flex w-full flex-col overflow-hidden rounded-2xl border border-zinc-200 bg-white shadow-xl dark:border-zinc-700 dark:bg-zinc-900\",\n SIZE_MAP[size],\n animClass,\n className,\n )}\n >\n {children}\n </div>\n </div>\n </Portal>\n </ModalContext.Provider>\n );\n}\n\nexport const Modal = Object.assign(ModalRoot, {\n Header: ModalHeader,\n Body: ModalBody,\n Footer: ModalFooter,\n});\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/Modal/Modal.context.ts","../src/components/Modal/ModalHeader.tsx","../src/components/Modal/ModalBody.tsx","../src/components/Modal/ModalFooter.tsx","../src/components/Modal/Modal.tsx"],"names":["createContext","useContext","jsxs","cn","jsx","X","useRef","useCallback","useEscapeKey","useFocusTrap","useEffect","useAnimation","useMemo","Portal"],"mappings":"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","file":"chunk-TZKZ2LUF.cjs","sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { ModalContextValue } from \"./Modal.types\";\n\nexport const ModalContext = createContext<ModalContextValue | null>(null);\n\nexport function useModal(): ModalContextValue {\n const ctx = useContext(ModalContext);\n if (!ctx) {\n throw new Error(\"Modal compound components must be used within <Modal>\");\n }\n return ctx;\n}\n","import { X } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport { useModal } from \"./Modal.context\";\nimport type { ModalHeaderProps } from \"./Modal.types\";\n\nexport function ModalHeader({ children, className }: ModalHeaderProps) {\n const { close } = useModal();\n\n return (\n <div\n data-react-fancy-modal-header=\"\"\n className={cn(\n \"flex items-center justify-between border-b border-zinc-200 px-6 py-4 dark:border-zinc-700\",\n className,\n )}\n >\n <div className=\"text-lg font-semibold text-zinc-900 dark:text-zinc-100\">{children}</div>\n <button\n type=\"button\"\n onClick={close}\n className=\"rounded-lg p-1 text-zinc-400 transition-colors hover:bg-zinc-100 hover:text-zinc-600 dark:hover:bg-zinc-800 dark:hover:text-zinc-300\"\n aria-label=\"Close\"\n >\n <X size={20} />\n </button>\n </div>\n );\n}\n\nModalHeader.displayName = \"ModalHeader\";\n","import { cn } from \"../../utils/cn\";\nimport type { ModalBodyProps } from \"./Modal.types\";\n\nexport function ModalBody({ children, className }: ModalBodyProps) {\n return (\n <div data-react-fancy-modal-body=\"\" className={cn(\"flex-1 overflow-y-auto px-6 py-4 text-zinc-700 dark:text-zinc-300\", className)}>\n {children}\n </div>\n );\n}\n\nModalBody.displayName = \"ModalBody\";\n","import { cn } from \"../../utils/cn\";\nimport type { ModalFooterProps } from \"./Modal.types\";\n\nexport function ModalFooter({ children, className }: ModalFooterProps) {\n return (\n <div\n data-react-fancy-modal-footer=\"\"\n className={cn(\n \"flex items-center justify-end gap-3 border-t border-zinc-200 px-6 py-4 dark:border-zinc-700\",\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\nModalFooter.displayName = \"ModalFooter\";\n","import { useCallback, useEffect, useMemo, useRef } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { Portal } from \"../Portal\";\nimport { ModalContext } from \"./Modal.context\";\nimport { ModalHeader } from \"./ModalHeader\";\nimport { ModalBody } from \"./ModalBody\";\nimport { ModalFooter } from \"./ModalFooter\";\nimport { useFocusTrap } from \"../../hooks/use-focus-trap\";\nimport { useEscapeKey } from \"../../hooks/use-escape-key\";\nimport { useAnimation } from \"../../hooks/use-animation\";\nimport type { ModalProps } from \"./Modal.types\";\n\nconst SIZE_MAP = {\n sm: \"max-w-sm\",\n md: \"max-w-lg\",\n lg: \"max-w-2xl\",\n xl: \"max-w-4xl\",\n full: \"max-w-[calc(100vw-2rem)] max-h-[calc(100vh-2rem)]\",\n} as const;\n\nfunction ModalRoot({\n children,\n open,\n onClose,\n size = \"md\",\n className,\n ...rest\n}: ModalProps) {\n const panelRef = useRef<HTMLDivElement>(null);\n\n const close = useCallback(() => onClose(), [onClose]);\n useEscapeKey(close, open);\n useFocusTrap(panelRef, open);\n\n // Body scroll lock\n useEffect(() => {\n if (open) {\n const original = document.body.style.overflow;\n document.body.style.overflow = \"hidden\";\n return () => {\n document.body.style.overflow = original;\n };\n }\n }, [open]);\n\n const { mounted, className: animClass, ref: animRef } = useAnimation({\n open,\n enterClass: \"fancy-slide-up\",\n exitClass: \"fancy-fade-out\",\n });\n\n const ctx = useMemo(() => ({ open, close }), [open, close]);\n\n if (!mounted) return null;\n\n return (\n <ModalContext.Provider value={ctx}>\n <Portal>\n <div className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n {/* Backdrop */}\n <div\n className=\"absolute inset-0 bg-black/50 backdrop-blur-sm\"\n onClick={close}\n aria-hidden=\"true\"\n />\n {/* Panel */}\n <div\n ref={(node) => {\n panelRef.current = node;\n (animRef as React.MutableRefObject<HTMLElement | null>).current =\n node;\n }}\n data-react-fancy-modal=\"\"\n role=\"dialog\"\n aria-modal=\"true\"\n {...rest}\n className={cn(\n \"relative flex w-full flex-col overflow-hidden rounded-2xl border border-zinc-200 bg-white shadow-xl dark:border-zinc-700 dark:bg-zinc-900\",\n SIZE_MAP[size],\n animClass,\n className,\n )}\n >\n {children}\n </div>\n </div>\n </Portal>\n </ModalContext.Provider>\n );\n}\n\nexport const Modal = Object.assign(ModalRoot, {\n Header: ModalHeader,\n Body: ModalBody,\n Footer: ModalFooter,\n});\n"]}