@fuf-stack/pixels 1.10.2 → 1.11.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 (77) hide show
  1. package/dist/Alert/Alert.cjs +18 -6
  2. package/dist/Alert/Alert.cjs.map +1 -1
  3. package/dist/Alert/Alert.d.cts +12 -0
  4. package/dist/Alert/Alert.d.cts.map +1 -1
  5. package/dist/Alert/Alert.d.ts +12 -0
  6. package/dist/Alert/Alert.d.ts.map +1 -1
  7. package/dist/Alert/Alert.js +18 -6
  8. package/dist/Alert/Alert.js.map +1 -1
  9. package/dist/Avatar/Avatar.d.cts +6 -6
  10. package/dist/Avatar/Avatar.d.ts +6 -6
  11. package/dist/Breadcrumb/Breadcrumb.d.cts +3 -3
  12. package/dist/Breadcrumb/Breadcrumb.d.ts +3 -3
  13. package/dist/Drawer/Drawer.d.cts +6 -6
  14. package/dist/Drawer/Drawer.d.ts +6 -6
  15. package/dist/Menu/Menu.d.cts +3 -3
  16. package/dist/Menu/Menu.d.ts +3 -3
  17. package/dist/Modal/Modal.cjs +1 -1
  18. package/dist/Modal/Modal.cjs.map +1 -1
  19. package/dist/Modal/Modal.d.cts +5 -1
  20. package/dist/Modal/Modal.d.cts.map +1 -1
  21. package/dist/Modal/Modal.d.ts +5 -1
  22. package/dist/Modal/Modal.d.ts.map +1 -1
  23. package/dist/Modal/Modal.js +2 -2
  24. package/dist/Modal/Modal.js.map +1 -1
  25. package/dist/Modal/ModalHost.cjs +40 -0
  26. package/dist/Modal/ModalHost.cjs.map +1 -0
  27. package/dist/Modal/ModalHost.d.cts +16 -0
  28. package/dist/Modal/ModalHost.d.cts.map +1 -0
  29. package/dist/Modal/ModalHost.d.ts +16 -0
  30. package/dist/Modal/ModalHost.d.ts.map +1 -0
  31. package/dist/Modal/ModalHost.js +39 -0
  32. package/dist/Modal/ModalHost.js.map +1 -0
  33. package/dist/Modal/index.cjs +4 -0
  34. package/dist/Modal/index.cjs.map +1 -1
  35. package/dist/Modal/index.d.cts +3 -1
  36. package/dist/Modal/index.d.ts +3 -1
  37. package/dist/Modal/index.js +3 -1
  38. package/dist/Modal/index.js.map +1 -1
  39. package/dist/Modal/modalStore.cjs +80 -0
  40. package/dist/Modal/modalStore.cjs.map +1 -0
  41. package/dist/Modal/modalStore.d.cts +31 -0
  42. package/dist/Modal/modalStore.d.cts.map +1 -0
  43. package/dist/Modal/modalStore.d.ts +31 -0
  44. package/dist/Modal/modalStore.d.ts.map +1 -0
  45. package/dist/Modal/modalStore.js +78 -0
  46. package/dist/Modal/modalStore.js.map +1 -0
  47. package/dist/Popover/Popover.d.cts +3 -3
  48. package/dist/Popover/Popover.d.ts +3 -3
  49. package/dist/SearchInput/SearchInput.d.cts +3 -3
  50. package/dist/SearchInput/SearchInput.d.ts +3 -3
  51. package/dist/Toast/Toaster.cjs +10 -2
  52. package/dist/Toast/Toaster.cjs.map +1 -1
  53. package/dist/Toast/Toaster.d.cts +5 -2
  54. package/dist/Toast/Toaster.d.cts.map +1 -1
  55. package/dist/Toast/Toaster.d.ts +5 -2
  56. package/dist/Toast/Toaster.d.ts.map +1 -1
  57. package/dist/Toast/Toaster.js +10 -2
  58. package/dist/Toast/Toaster.js.map +1 -1
  59. package/dist/Toast/index.cjs +3 -3
  60. package/dist/Toast/index.cjs.map +1 -1
  61. package/dist/Toast/index.d.cts +1 -1
  62. package/dist/Toast/index.d.ts +1 -1
  63. package/dist/Toast/index.js +1 -1
  64. package/dist/Toast/index.js.map +1 -1
  65. package/dist/Toast/{Toast.cjs → toast.cjs} +2 -2
  66. package/dist/Toast/{Toast.cjs.map → toast.cjs.map} +1 -1
  67. package/dist/Toast/{Toast.d.cts → toast.d.cts} +2 -2
  68. package/dist/Toast/{Toast.d.cts.map → toast.d.cts.map} +1 -1
  69. package/dist/Toast/{Toast.d.ts → toast.d.ts} +2 -2
  70. package/dist/Toast/{Toast.d.ts.map → toast.d.ts.map} +1 -1
  71. package/dist/Toast/{Toast.js → toast.js} +2 -2
  72. package/dist/Toast/{Toast.js.map → toast.js.map} +1 -1
  73. package/dist/index.cjs +6 -2
  74. package/dist/index.d.cts +4 -2
  75. package/dist/index.d.ts +4 -2
  76. package/dist/index.js +4 -2
  77. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.d.cts","names":[],"sources":["../../src/Modal/Modal.tsx"],"mappings":";;;;;cAea,aAAA,8BAAa,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAqBrB,YAAA,GAAe,OAAO,QAAQ,aAAA;AAAA,KAC9B,SAAA,GAAY,WAAW,QAAQ,aAAA;AAAA,UAEnB,YAAA,SAAmB,YAAA;EAkB3B;EAhBP,QAAA,GAAW,SAAA;EAFmC;EAI9C,SAAA,GAAY,SAAA;EAJsB;EAMlC,gBAAA;EAJW;EAMX,MAAA,GAAS,SAAA;EAJG;EAMZ,MAAA,GAAS,SAAA;EAFT;EAIA,MAAA;EAFA;EAIA,OAAA;EAFA;EAIA,eAAA,GAAkB,UAAA;EAAlB;EAEA,IAAA,GAAO,YAAA;EAAP;EAEA,MAAA;AAAA;;AAAM;AACP;cAKK,KAAA;EAAS,QAAA;EAAA,SAAA;EAAA,gBAAA;EAAA,MAAA;EAAA,MAAA;EAAA,MAAA;EAAA,OAAA;EAAA,eAAA;EAAA,IAAA;EAAA;AAAA,GAWZ,YAAA,iCAAU,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"Modal.d.cts","names":[],"sources":["../../src/Modal/Modal.tsx"],"mappings":";;;;;cAmBa,aAAA,8BAAa,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAqBrB,YAAA,GAAe,OAAO,QAAQ,aAAA;AAAA,KAC9B,SAAA,GAAY,WAAW,QAAQ,aAAA;AAAA,UAEnB,YAAA,SAAmB,YAAA;EAsB3B;EApBP,QAAA,GAAW,SAAA;EAFmC;EAI9C,SAAA,GAAY,SAAA;EAJsB;;;;;EAUlC,gBAAA;EAEA;EAAA,MAAA,GAAS,SAAA;EAET;EAAA,MAAA,GAAS,SAAA;EAET;EAAA,MAAA;EAIA;EAFA,OAAA;EAIA;EAFA,eAAA,GAAkB,UAAA;EAIlB;EAFA,IAAA,GAAO,YAAA;EAED;EAAN,MAAA;AAAA;;;;cAMI,KAAA;EAAS,QAAA;EAAA,SAAA;EAAA,gBAAA;EAAA,MAAA;EAAA,MAAA;EAAA,MAAA;EAAA,OAAA;EAAA,eAAA;EAAA,IAAA;EAAA;AAAA,GAWZ,YAAA,iCAAU,GAAA,CAAA,OAAA"}
@@ -89,7 +89,11 @@ interface ModalProps$1 extends VariantProps {
89
89
  children?: ReactNode;
90
90
  /** CSS class name */
91
91
  className?: ClassName;
92
- /** Disable animations completely */
92
+ /**
93
+ * Disable animations completely. Defaults to `true` in test environments so
94
+ * snapshots are deterministic (the open/close opacity tween otherwise
95
+ * captures a random mid-animation frame).
96
+ */
93
97
  disableAnimation?: boolean;
94
98
  /** modal footer */
95
99
  footer?: ReactNode;
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.d.ts","names":[],"sources":["../../src/Modal/Modal.tsx"],"mappings":";;;;;cAea,aAAA,8BAAa,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAqBrB,YAAA,GAAe,OAAO,QAAQ,aAAA;AAAA,KAC9B,SAAA,GAAY,WAAW,QAAQ,aAAA;AAAA,UAEnB,YAAA,SAAmB,YAAA;EAkB3B;EAhBP,QAAA,GAAW,SAAA;EAFmC;EAI9C,SAAA,GAAY,SAAA;EAJsB;EAMlC,gBAAA;EAJW;EAMX,MAAA,GAAS,SAAA;EAJG;EAMZ,MAAA,GAAS,SAAA;EAFT;EAIA,MAAA;EAFA;EAIA,OAAA;EAFA;EAIA,eAAA,GAAkB,UAAA;EAAlB;EAEA,IAAA,GAAO,YAAA;EAAP;EAEA,MAAA;AAAA;;AAAM;AACP;cAKK,OAAA;EAAS,QAAA;EAAA,SAAA;EAAA,gBAAA;EAAA,MAAA;EAAA,MAAA;EAAA,MAAA;EAAA,OAAA;EAAA,eAAA;EAAA,IAAA;EAAA;AAAA,GAWZ,YAAA,iCAAU,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"Modal.d.ts","names":[],"sources":["../../src/Modal/Modal.tsx"],"mappings":";;;;;cAmBa,aAAA,8BAAa,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAqBrB,YAAA,GAAe,OAAO,QAAQ,aAAA;AAAA,KAC9B,SAAA,GAAY,WAAW,QAAQ,aAAA;AAAA,UAEnB,YAAA,SAAmB,YAAA;EAsB3B;EApBP,QAAA,GAAW,SAAA;EAFmC;EAI9C,SAAA,GAAY,SAAA;EAJsB;;;;;EAUlC,gBAAA;EAEA;EAAA,MAAA,GAAS,SAAA;EAET;EAAA,MAAA,GAAS,SAAA;EAET;EAAA,MAAA;EAIA;EAFA,OAAA;EAIA;EAFA,eAAA,GAAkB,UAAA;EAIlB;EAFA,IAAA,GAAO,YAAA;EAED;EAAN,MAAA;AAAA;;;;cAMI,OAAA;EAAS,QAAA;EAAA,SAAA;EAAA,gBAAA;EAAA,MAAA;EAAA,MAAA;EAAA,MAAA;EAAA,OAAA;EAAA,eAAA;EAAA,IAAA;EAAA;AAAA,GAWZ,YAAA,iCAAU,GAAA,CAAA,OAAA"}
@@ -1,4 +1,4 @@
1
- import { tv, variantsToClassNames } from "@fuf-stack/pixel-utils";
1
+ import { isTestEnvironment, tv, variantsToClassNames } from "@fuf-stack/pixel-utils";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import { Modal, ModalBody, ModalContent, ModalFooter, ModalHeader } from "@heroui/modal";
4
4
  //#region src/Modal/Modal.tsx
@@ -23,7 +23,7 @@ const modalVariants = tv({
23
23
  /**
24
24
  * Modal component based on [HeroUI Modal](https://www.heroui.com//docs/components/modal)
25
25
  */
26
- const Modal$1 = ({ children = null, className = void 0, disableAnimation = false, footer = void 0, header = void 0, isOpen, onClose, portalContainer = void 0, size = "md", testId = void 0 }) => {
26
+ const Modal$1 = ({ children = null, className = void 0, disableAnimation = isTestEnvironment(), footer = void 0, header = void 0, isOpen, onClose, portalContainer = void 0, size = "md", testId = void 0 }) => {
27
27
  return /* @__PURE__ */ jsx(Modal, {
28
28
  backdrop: "opaque",
29
29
  classNames: variantsToClassNames(modalVariants({ size }), className, "base"),
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.js","names":["Modal","HeroModal","HeroModalContent","HeroModalHeader","HeroModalBody","HeroModalFooter"],"sources":["../../src/Modal/Modal.tsx"],"sourcesContent":["import type { TVClassName, TVProps } from '@fuf-stack/pixel-utils';\nimport type { ModalProps as HeroModalProps } from '@heroui/modal';\nimport type { ReactNode } from 'react';\n\nimport {\n Modal as HeroModal,\n ModalBody as HeroModalBody,\n ModalContent as HeroModalContent,\n ModalFooter as HeroModalFooter,\n ModalHeader as HeroModalHeader,\n} from '@heroui/modal';\n\nimport { tv, variantsToClassNames } from '@fuf-stack/pixel-utils';\n\n// modal variants\nexport const modalVariants = tv({\n slots: {\n backdrop: '',\n base: '',\n body: 'py-4',\n closeButton: '',\n footer: 'border-t border-t-divider',\n header: 'border-b border-b-divider',\n wrapper: '',\n },\n variants: {\n size: {\n sm: { base: 'max-w-sm' },\n md: { base: 'max-w-md' },\n lg: { base: 'max-w-lg' },\n xl: { base: 'max-w-5xl' },\n full: { base: 'h-[80dvh] max-w-full' },\n },\n },\n});\n\ntype VariantProps = TVProps<typeof modalVariants>;\ntype ClassName = TVClassName<typeof modalVariants>;\n\nexport interface ModalProps extends VariantProps {\n /** modal body content */\n children?: ReactNode;\n /** CSS class name */\n className?: ClassName;\n /** Disable animations completely */\n disableAnimation?: boolean;\n /** modal footer */\n footer?: ReactNode;\n /** modal header */\n header?: ReactNode;\n /** open state (controlled) */\n isOpen: boolean;\n /** close event handler */\n onClose: () => void;\n /** The container element in which the overlay portal will be placed */\n portalContainer?: HeroModalProps['portalContainer'];\n /** modal size */\n size?: VariantProps['size'];\n /** HTML data-testid attribute used in e2e tests */\n testId?: string;\n}\n\n/**\n * Modal component based on [HeroUI Modal](https://www.heroui.com//docs/components/modal)\n */\nconst Modal = ({\n children = null,\n className = undefined,\n disableAnimation = false,\n footer = undefined,\n header = undefined,\n isOpen,\n onClose,\n portalContainer = undefined,\n size = 'md',\n testId = undefined,\n}: ModalProps) => {\n // classNames from slots\n const variants = modalVariants({ size });\n const classNames = variantsToClassNames(variants, className, 'base');\n\n return (\n <HeroModal\n backdrop=\"opaque\"\n classNames={classNames}\n data-testid={testId}\n disableAnimation={disableAnimation}\n isOpen={isOpen}\n onClose={onClose}\n placement=\"center\"\n portalContainer={portalContainer}\n scrollBehavior=\"inside\"\n >\n <HeroModalContent data-testid={testId ? `modal_${testId}` : 'modal'}>\n {() => {\n return (\n <>\n {header ? <HeroModalHeader>{header}</HeroModalHeader> : null}\n <HeroModalBody id=\"modal_body\">{children}</HeroModalBody>\n {footer ? <HeroModalFooter>{footer}</HeroModalFooter> : null}\n </>\n );\n }}\n </HeroModalContent>\n </HeroModal>\n );\n};\n\nexport default Modal;\n"],"mappings":";;;;AAeA,MAAa,gBAAgB,GAAG;CAC9B,OAAO;EACL,UAAU;EACV,MAAM;EACN,MAAM;EACN,aAAa;EACb,QAAQ;EACR,QAAQ;EACR,SAAS;CACX;CACA,UAAU,EACR,MAAM;EACJ,IAAI,EAAE,MAAM,WAAW;EACvB,IAAI,EAAE,MAAM,WAAW;EACvB,IAAI,EAAE,MAAM,WAAW;EACvB,IAAI,EAAE,MAAM,YAAY;EACxB,MAAM,EAAE,MAAM,uBAAuB;CACvC,EACF;AACF,CAAC;;;;AA+BD,MAAMA,WAAS,EACb,WAAW,MACX,YAAY,KAAA,GACZ,mBAAmB,OACnB,SAAS,KAAA,GACT,SAAS,KAAA,GACT,QACA,SACA,kBAAkB,KAAA,GAClB,OAAO,MACP,SAAS,KAAA,QACO;CAKhB,OACE,oBAACC,OAAD;EACE,UAAS;EACT,YALe,qBADF,cAAc,EAAE,KAAK,CACS,GAAG,WAAW,MAKpC;EACrB,eAAa;EACK;EACV;EACC;EACT,WAAU;EACO;EACjB,gBAAe;YAEf,oBAACC,cAAD;GAAkB,eAAa,SAAS,SAAS,WAAW;mBACnD;IACL,OACE,qBAAA,UAAA,EAAA,UAAA;KACG,SAAS,oBAACC,aAAD,EAAA,UAAkB,OAAwB,CAAA,IAAI;KACxD,oBAACC,WAAD;MAAe,IAAG;MAAc;KAAwB,CAAA;KACvD,SAAS,oBAACC,aAAD,EAAA,UAAkB,OAAwB,CAAA,IAAI;IACxD,EAAA,CAAA;GAEN;EACgB,CAAA;CACT,CAAA;AAEf"}
1
+ {"version":3,"file":"Modal.js","names":["Modal","HeroModal","HeroModalContent","HeroModalHeader","HeroModalBody","HeroModalFooter"],"sources":["../../src/Modal/Modal.tsx"],"sourcesContent":["import type { TVClassName, TVProps } from '@fuf-stack/pixel-utils';\nimport type { ModalProps as HeroModalProps } from '@heroui/modal';\nimport type { ReactNode } from 'react';\n\nimport {\n Modal as HeroModal,\n ModalBody as HeroModalBody,\n ModalContent as HeroModalContent,\n ModalFooter as HeroModalFooter,\n ModalHeader as HeroModalHeader,\n} from '@heroui/modal';\n\nimport {\n isTestEnvironment,\n tv,\n variantsToClassNames,\n} from '@fuf-stack/pixel-utils';\n\n// modal variants\nexport const modalVariants = tv({\n slots: {\n backdrop: '',\n base: '',\n body: 'py-4',\n closeButton: '',\n footer: 'border-t border-t-divider',\n header: 'border-b border-b-divider',\n wrapper: '',\n },\n variants: {\n size: {\n sm: { base: 'max-w-sm' },\n md: { base: 'max-w-md' },\n lg: { base: 'max-w-lg' },\n xl: { base: 'max-w-5xl' },\n full: { base: 'h-[80dvh] max-w-full' },\n },\n },\n});\n\ntype VariantProps = TVProps<typeof modalVariants>;\ntype ClassName = TVClassName<typeof modalVariants>;\n\nexport interface ModalProps extends VariantProps {\n /** modal body content */\n children?: ReactNode;\n /** CSS class name */\n className?: ClassName;\n /**\n * Disable animations completely. Defaults to `true` in test environments so\n * snapshots are deterministic (the open/close opacity tween otherwise\n * captures a random mid-animation frame).\n */\n disableAnimation?: boolean;\n /** modal footer */\n footer?: ReactNode;\n /** modal header */\n header?: ReactNode;\n /** open state (controlled) */\n isOpen: boolean;\n /** close event handler */\n onClose: () => void;\n /** The container element in which the overlay portal will be placed */\n portalContainer?: HeroModalProps['portalContainer'];\n /** modal size */\n size?: VariantProps['size'];\n /** HTML data-testid attribute used in e2e tests */\n testId?: string;\n}\n\n/**\n * Modal component based on [HeroUI Modal](https://www.heroui.com//docs/components/modal)\n */\nconst Modal = ({\n children = null,\n className = undefined,\n disableAnimation = isTestEnvironment(),\n footer = undefined,\n header = undefined,\n isOpen,\n onClose,\n portalContainer = undefined,\n size = 'md',\n testId = undefined,\n}: ModalProps) => {\n // classNames from slots\n const variants = modalVariants({ size });\n const classNames = variantsToClassNames(variants, className, 'base');\n\n return (\n <HeroModal\n backdrop=\"opaque\"\n classNames={classNames}\n data-testid={testId}\n disableAnimation={disableAnimation}\n isOpen={isOpen}\n onClose={onClose}\n placement=\"center\"\n portalContainer={portalContainer}\n scrollBehavior=\"inside\"\n >\n <HeroModalContent data-testid={testId ? `modal_${testId}` : 'modal'}>\n {() => {\n return (\n <>\n {header ? <HeroModalHeader>{header}</HeroModalHeader> : null}\n <HeroModalBody id=\"modal_body\">{children}</HeroModalBody>\n {footer ? <HeroModalFooter>{footer}</HeroModalFooter> : null}\n </>\n );\n }}\n </HeroModalContent>\n </HeroModal>\n );\n};\n\nexport default Modal;\n"],"mappings":";;;;AAmBA,MAAa,gBAAgB,GAAG;CAC9B,OAAO;EACL,UAAU;EACV,MAAM;EACN,MAAM;EACN,aAAa;EACb,QAAQ;EACR,QAAQ;EACR,SAAS;CACX;CACA,UAAU,EACR,MAAM;EACJ,IAAI,EAAE,MAAM,WAAW;EACvB,IAAI,EAAE,MAAM,WAAW;EACvB,IAAI,EAAE,MAAM,WAAW;EACvB,IAAI,EAAE,MAAM,YAAY;EACxB,MAAM,EAAE,MAAM,uBAAuB;CACvC,EACF;AACF,CAAC;;;;AAmCD,MAAMA,WAAS,EACb,WAAW,MACX,YAAY,KAAA,GACZ,mBAAmB,kBAAkB,GACrC,SAAS,KAAA,GACT,SAAS,KAAA,GACT,QACA,SACA,kBAAkB,KAAA,GAClB,OAAO,MACP,SAAS,KAAA,QACO;CAKhB,OACE,oBAACC,OAAD;EACE,UAAS;EACT,YALe,qBADF,cAAc,EAAE,KAAK,CACS,GAAG,WAAW,MAKpC;EACrB,eAAa;EACK;EACV;EACC;EACT,WAAU;EACO;EACjB,gBAAe;YAEf,oBAACC,cAAD;GAAkB,eAAa,SAAS,SAAS,WAAW;mBACnD;IACL,OACE,qBAAA,UAAA,EAAA,UAAA;KACG,SAAS,oBAACC,aAAD,EAAA,UAAkB,OAAwB,CAAA,IAAI;KACxD,oBAACC,WAAD;MAAe,IAAG;MAAc;KAAwB,CAAA;KACvD,SAAS,oBAACC,aAAD,EAAA,UAAkB,OAAwB,CAAA,IAAI;IACxD,EAAA,CAAA;GAEN;EACgB,CAAA;CACT,CAAA;AAEf"}
@@ -0,0 +1,40 @@
1
+ require("../_virtual/_rolldown/runtime.cjs");
2
+ const require_Modal = require("./Modal.cjs");
3
+ const require_modalStore = require("./modalStore.cjs");
4
+ let react_jsx_runtime = require("react/jsx-runtime");
5
+ let react = require("react");
6
+ //#region src/Modal/ModalHost.tsx
7
+ /**
8
+ * Renders all modals opened via the imperative `modal.open()` API.
9
+ *
10
+ * Mount once at the top level of your app, similar to `<Toaster />`:
11
+ *
12
+ * ```tsx
13
+ * <ModalHost />
14
+ * ```
15
+ *
16
+ * Then open modals from anywhere with `modal.open({ ... })`.
17
+ */
18
+ const ModalHost = () => {
19
+ const entries = require_modalStore.useModalEntries();
20
+ (0, react.useEffect)(() => {
21
+ return () => {
22
+ require_modalStore.modal.reset();
23
+ };
24
+ }, []);
25
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: entries.map((entry) => {
26
+ const { id, isOpen, content, onClose: _onClose, ...modalProps } = entry;
27
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_Modal.default, {
28
+ ...modalProps,
29
+ isOpen,
30
+ onClose: () => {
31
+ require_modalStore.modal.close(id);
32
+ },
33
+ children: content
34
+ }, id);
35
+ }) });
36
+ };
37
+ //#endregion
38
+ exports.default = ModalHost;
39
+
40
+ //# sourceMappingURL=ModalHost.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModalHost.cjs","names":["useModalEntries","Modal"],"sources":["../../src/Modal/ModalHost.tsx"],"sourcesContent":["import { useEffect } from 'react';\n\nimport Modal from './Modal';\nimport { modal, useModalEntries } from './modalStore';\n\n/**\n * Renders all modals opened via the imperative `modal.open()` API.\n *\n * Mount once at the top level of your app, similar to `<Toaster />`:\n *\n * ```tsx\n * <ModalHost />\n * ```\n *\n * Then open modals from anywhere with `modal.open({ ... })`.\n */\nconst ModalHost = () => {\n const entries = useModalEntries();\n\n // Clear the store when the host unmounts so any still-open\n // modal does not re-appear when a new host mounts.\n useEffect(() => {\n return () => {\n modal.reset();\n };\n }, []);\n return (\n <>\n {entries.map((entry) => {\n const { id, isOpen, content, onClose: _onClose, ...modalProps } = entry;\n return (\n <Modal\n key={id}\n {...modalProps}\n isOpen={isOpen}\n onClose={() => {\n modal.close(id);\n }}\n >\n {content}\n </Modal>\n );\n })}\n </>\n );\n};\n\nexport default ModalHost;\n"],"mappings":";;;;;;;;;;;;;;;;;AAgBA,MAAM,kBAAkB;CACtB,MAAM,UAAUA,mBAAAA,gBAAgB;CAIhC,CAAA,GAAA,MAAA,iBAAgB;EACd,aAAa;GACX,mBAAA,MAAM,MAAM;EACd;CACF,GAAG,CAAC,CAAC;CACL,OACE,iBAAA,GAAA,kBAAA,KAAA,kBAAA,UAAA,EAAA,UACG,QAAQ,KAAK,UAAU;EACtB,MAAM,EAAE,IAAI,QAAQ,SAAS,SAAS,UAAU,GAAG,eAAe;EAClE,OACE,iBAAA,GAAA,kBAAA,KAACC,cAAAA,SAAD;GAEE,GAAI;GACI;GACR,eAAe;IACb,mBAAA,MAAM,MAAM,EAAE;GAChB;aAEC;EACI,GARA,EAQA;CAEX,CAAC,EACD,CAAA;AAEN"}
@@ -0,0 +1,16 @@
1
+ //#region src/Modal/ModalHost.d.ts
2
+ /**
3
+ * Renders all modals opened via the imperative `modal.open()` API.
4
+ *
5
+ * Mount once at the top level of your app, similar to `<Toaster />`:
6
+ *
7
+ * ```tsx
8
+ * <ModalHost />
9
+ * ```
10
+ *
11
+ * Then open modals from anywhere with `modal.open({ ... })`.
12
+ */
13
+ declare const ModalHost: () => import("react/jsx-runtime").JSX.Element;
14
+ //#endregion
15
+ export { ModalHost };
16
+ //# sourceMappingURL=ModalHost.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModalHost.d.cts","names":[],"sources":["../../src/Modal/ModalHost.tsx"],"mappings":";;;;;;AA6CC;;;;;;cA7BK,SAAA,oCAAS,GAAA,CAAA,OA6Bd"}
@@ -0,0 +1,16 @@
1
+ //#region src/Modal/ModalHost.d.ts
2
+ /**
3
+ * Renders all modals opened via the imperative `modal.open()` API.
4
+ *
5
+ * Mount once at the top level of your app, similar to `<Toaster />`:
6
+ *
7
+ * ```tsx
8
+ * <ModalHost />
9
+ * ```
10
+ *
11
+ * Then open modals from anywhere with `modal.open({ ... })`.
12
+ */
13
+ declare const ModalHost: () => import("react/jsx-runtime").JSX.Element;
14
+ //#endregion
15
+ export { ModalHost };
16
+ //# sourceMappingURL=ModalHost.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModalHost.d.ts","names":[],"sources":["../../src/Modal/ModalHost.tsx"],"mappings":";;;;;;AA6CC;;;;;;cA7BK,SAAA,oCAAS,GAAA,CAAA,OA6Bd"}
@@ -0,0 +1,39 @@
1
+ import Modal from "./Modal.js";
2
+ import { modal, useModalEntries } from "./modalStore.js";
3
+ import { Fragment, jsx } from "react/jsx-runtime";
4
+ import { useEffect } from "react";
5
+ //#region src/Modal/ModalHost.tsx
6
+ /**
7
+ * Renders all modals opened via the imperative `modal.open()` API.
8
+ *
9
+ * Mount once at the top level of your app, similar to `<Toaster />`:
10
+ *
11
+ * ```tsx
12
+ * <ModalHost />
13
+ * ```
14
+ *
15
+ * Then open modals from anywhere with `modal.open({ ... })`.
16
+ */
17
+ const ModalHost = () => {
18
+ const entries = useModalEntries();
19
+ useEffect(() => {
20
+ return () => {
21
+ modal.reset();
22
+ };
23
+ }, []);
24
+ return /* @__PURE__ */ jsx(Fragment, { children: entries.map((entry) => {
25
+ const { id, isOpen, content, onClose: _onClose, ...modalProps } = entry;
26
+ return /* @__PURE__ */ jsx(Modal, {
27
+ ...modalProps,
28
+ isOpen,
29
+ onClose: () => {
30
+ modal.close(id);
31
+ },
32
+ children: content
33
+ }, id);
34
+ }) });
35
+ };
36
+ //#endregion
37
+ export { ModalHost as default };
38
+
39
+ //# sourceMappingURL=ModalHost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModalHost.js","names":[],"sources":["../../src/Modal/ModalHost.tsx"],"sourcesContent":["import { useEffect } from 'react';\n\nimport Modal from './Modal';\nimport { modal, useModalEntries } from './modalStore';\n\n/**\n * Renders all modals opened via the imperative `modal.open()` API.\n *\n * Mount once at the top level of your app, similar to `<Toaster />`:\n *\n * ```tsx\n * <ModalHost />\n * ```\n *\n * Then open modals from anywhere with `modal.open({ ... })`.\n */\nconst ModalHost = () => {\n const entries = useModalEntries();\n\n // Clear the store when the host unmounts so any still-open\n // modal does not re-appear when a new host mounts.\n useEffect(() => {\n return () => {\n modal.reset();\n };\n }, []);\n return (\n <>\n {entries.map((entry) => {\n const { id, isOpen, content, onClose: _onClose, ...modalProps } = entry;\n return (\n <Modal\n key={id}\n {...modalProps}\n isOpen={isOpen}\n onClose={() => {\n modal.close(id);\n }}\n >\n {content}\n </Modal>\n );\n })}\n </>\n );\n};\n\nexport default ModalHost;\n"],"mappings":";;;;;;;;;;;;;;;;AAgBA,MAAM,kBAAkB;CACtB,MAAM,UAAU,gBAAgB;CAIhC,gBAAgB;EACd,aAAa;GACX,MAAM,MAAM;EACd;CACF,GAAG,CAAC,CAAC;CACL,OACE,oBAAA,UAAA,EAAA,UACG,QAAQ,KAAK,UAAU;EACtB,MAAM,EAAE,IAAI,QAAQ,SAAS,SAAS,UAAU,GAAG,eAAe;EAClE,OACE,oBAAC,OAAD;GAEE,GAAI;GACI;GACR,eAAe;IACb,MAAM,MAAM,EAAE;GAChB;aAEC;EACI,GARA,EAQA;CAEX,CAAC,EACD,CAAA;AAEN"}
@@ -3,11 +3,15 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_Modal = require("./Modal.cjs");
6
+ const require_modalStore = require("./modalStore.cjs");
7
+ const require_ModalHost = require("./ModalHost.cjs");
6
8
  //#region src/Modal/index.ts
7
9
  var Modal_default = require_Modal.default;
8
10
  //#endregion
9
11
  exports.Modal = require_Modal.default;
12
+ exports.ModalHost = require_ModalHost.default;
10
13
  exports.default = Modal_default;
14
+ exports.modal = require_modalStore.modal;
11
15
  exports.modalVariants = require_Modal.modalVariants;
12
16
 
13
17
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["Modal"],"sources":["../../src/Modal/index.ts"],"sourcesContent":["import Modal, { modalVariants } from './Modal';\n\nexport type { ModalProps } from './Modal';\n\nexport { Modal, modalVariants };\n\nexport default Modal;\n"],"mappings":";;;;;;AAMA,IAAA,gBAAeA,cAAAA"}
1
+ {"version":3,"file":"index.cjs","names":["Modal"],"sources":["../../src/Modal/index.ts"],"sourcesContent":["import Modal from './Modal';\n\nexport type { ModalProps } from './Modal';\nexport type { ModalEntry, ModalOpenOptions, ModalStoreApi } from './modalStore';\n\nexport { default as ModalHost } from './ModalHost';\nexport { modal } from './modalStore';\nexport { modalVariants } from './Modal';\nexport { Modal };\n\nexport default Modal;\n"],"mappings":";;;;;;;;AAUA,IAAA,gBAAeA,cAAAA"}
@@ -1,2 +1,4 @@
1
1
  import { Modal, ModalProps, modalVariants } from "./Modal.cjs";
2
- export { Modal, Modal as default, type ModalProps, modalVariants };
2
+ import { ModalEntry, ModalOpenOptions, ModalStoreApi, modal } from "./modalStore.cjs";
3
+ import { ModalHost } from "./ModalHost.cjs";
4
+ export { Modal, Modal as default, type ModalEntry, ModalHost, type ModalOpenOptions, type ModalProps, type ModalStoreApi, modal, modalVariants };
@@ -1,2 +1,4 @@
1
1
  import { Modal, ModalProps, modalVariants } from "./Modal.js";
2
- export { Modal, Modal as default, type ModalProps, modalVariants };
2
+ import { ModalEntry, ModalOpenOptions, ModalStoreApi, modal } from "./modalStore.js";
3
+ import { ModalHost } from "./ModalHost.js";
4
+ export { Modal, Modal as default, type ModalEntry, ModalHost, type ModalOpenOptions, type ModalProps, type ModalStoreApi, modal, modalVariants };
@@ -1,7 +1,9 @@
1
1
  import Modal, { modalVariants } from "./Modal.js";
2
+ import { modal } from "./modalStore.js";
3
+ import ModalHost from "./ModalHost.js";
2
4
  //#region src/Modal/index.ts
3
5
  var Modal_default = Modal;
4
6
  //#endregion
5
- export { Modal, Modal_default as default, modalVariants };
7
+ export { Modal, ModalHost, Modal_default as default, modal, modalVariants };
6
8
 
7
9
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/Modal/index.ts"],"sourcesContent":["import Modal, { modalVariants } from './Modal';\n\nexport type { ModalProps } from './Modal';\n\nexport { Modal, modalVariants };\n\nexport default Modal;\n"],"mappings":";;AAMA,IAAA,gBAAe"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/Modal/index.ts"],"sourcesContent":["import Modal from './Modal';\n\nexport type { ModalProps } from './Modal';\nexport type { ModalEntry, ModalOpenOptions, ModalStoreApi } from './modalStore';\n\nexport { default as ModalHost } from './ModalHost';\nexport { modal } from './modalStore';\nexport { modalVariants } from './Modal';\nexport { Modal };\n\nexport default Modal;\n"],"mappings":";;;;AAUA,IAAA,gBAAe"}
@@ -0,0 +1,80 @@
1
+ require("../_virtual/_rolldown/runtime.cjs");
2
+ let react = require("react");
3
+ //#region src/Modal/modalStore.ts
4
+ const MODAL_CLOSE_ANIMATION_MS = 300;
5
+ let nextId = 0;
6
+ let entries = [];
7
+ const listeners = /* @__PURE__ */ new Set();
8
+ const emit = () => {
9
+ listeners.forEach((listener) => {
10
+ listener();
11
+ });
12
+ };
13
+ const subscribe = (listener) => {
14
+ listeners.add(listener);
15
+ return () => {
16
+ listeners.delete(listener);
17
+ };
18
+ };
19
+ const getSnapshot = () => {
20
+ return entries;
21
+ };
22
+ /** React hook used by `ModalHost` to subscribe to the modal stack */
23
+ const useModalEntries = () => {
24
+ return (0, react.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
25
+ };
26
+ const open = (options) => {
27
+ nextId += 1;
28
+ const id = `modal-${nextId}`;
29
+ entries = [...entries, {
30
+ ...options,
31
+ id,
32
+ isOpen: true
33
+ }];
34
+ emit();
35
+ return id;
36
+ };
37
+ const close = (id) => {
38
+ const entry = entries.find((e) => {
39
+ return e.id === id;
40
+ });
41
+ if (!entry?.isOpen) return;
42
+ entries = entries.map((e) => {
43
+ return e.id === id ? {
44
+ ...e,
45
+ isOpen: false
46
+ } : e;
47
+ });
48
+ emit();
49
+ entry.onClose?.();
50
+ setTimeout(() => {
51
+ entries = entries.filter((e) => {
52
+ return e.id !== id;
53
+ });
54
+ emit();
55
+ }, MODAL_CLOSE_ANIMATION_MS);
56
+ };
57
+ const closeAll = () => {
58
+ entries.forEach((entry) => {
59
+ if (entry.isOpen) close(entry.id);
60
+ });
61
+ };
62
+ const reset = () => {
63
+ entries = [];
64
+ emit();
65
+ };
66
+ /**
67
+ * Imperative API for opening modals from anywhere (e.g. from inside a toast).
68
+ * Requires a `<ModalHost />` to be mounted somewhere in the React tree.
69
+ */
70
+ const modal = {
71
+ open,
72
+ close,
73
+ closeAll,
74
+ reset
75
+ };
76
+ //#endregion
77
+ exports.modal = modal;
78
+ exports.useModalEntries = useModalEntries;
79
+
80
+ //# sourceMappingURL=modalStore.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modalStore.cjs","names":[],"sources":["../../src/Modal/modalStore.ts"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { ModalProps } from './Modal';\n\nimport { useSyncExternalStore } from 'react';\n\n/** Options accepted by `modal.open()` */\nexport interface ModalOpenOptions extends Omit<\n ModalProps,\n 'isOpen' | 'onClose' | 'children'\n> {\n /** Modal body content */\n content?: ReactNode;\n /** Callback fired when the modal is closed (by user or programmatically) */\n onClose?: () => void;\n}\n\n/** Internal entry tracked by the store */\nexport interface ModalEntry extends ModalOpenOptions {\n id: string;\n isOpen: boolean;\n}\n\n// Duration of the HeroUI modal close animation. Entries stay in the list this\n// long after `close()` so the exit animation can play before unmounting.\nconst MODAL_CLOSE_ANIMATION_MS = 300;\n\nlet nextId = 0;\nlet entries: ModalEntry[] = [];\nconst listeners = new Set<() => void>();\n\nconst emit = () => {\n listeners.forEach((listener) => {\n listener();\n });\n};\n\nconst subscribe = (listener: () => void) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n};\n\nconst getSnapshot = () => {\n return entries;\n};\n\n/** React hook used by `ModalHost` to subscribe to the modal stack */\nexport const useModalEntries = (): ModalEntry[] => {\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n};\n\nconst open = (options: ModalOpenOptions): string => {\n nextId += 1;\n const id = `modal-${nextId}`;\n entries = [...entries, { ...options, id, isOpen: true }];\n emit();\n return id;\n};\n\nconst close = (id: string): void => {\n const entry = entries.find((e) => {\n return e.id === id;\n });\n if (!entry?.isOpen) {\n return;\n }\n entries = entries.map((e) => {\n return e.id === id ? { ...e, isOpen: false } : e;\n });\n emit();\n entry.onClose?.();\n setTimeout(() => {\n entries = entries.filter((e) => {\n return e.id !== id;\n });\n emit();\n }, MODAL_CLOSE_ANIMATION_MS);\n};\n\nconst closeAll = (): void => {\n entries.forEach((entry) => {\n if (entry.isOpen) {\n close(entry.id);\n }\n });\n};\n\n// Hard-resets the store without firing onClose callbacks or close animations.\n// Used by `ModalHost` on unmount so the store does not retain entries that\n// would re-appear when a host mounts again (e.g. switching Storybook stories).\nconst reset = (): void => {\n entries = [];\n emit();\n};\n\n/**\n * Imperative API for opening modals from anywhere (e.g. from inside a toast).\n * Requires a `<ModalHost />` to be mounted somewhere in the React tree.\n */\nexport const modal = {\n open,\n close,\n closeAll,\n reset,\n};\n\n/** Imperative modal API as exposed by the `modal` store. */\nexport type ModalStoreApi = typeof modal;\n"],"mappings":";;;AAwBA,MAAM,2BAA2B;AAEjC,IAAI,SAAS;AACb,IAAI,UAAwB,CAAC;AAC7B,MAAM,4BAAY,IAAI,IAAgB;AAEtC,MAAM,aAAa;CACjB,UAAU,SAAS,aAAa;EAC9B,SAAS;CACX,CAAC;AACH;AAEA,MAAM,aAAa,aAAyB;CAC1C,UAAU,IAAI,QAAQ;CACtB,aAAa;EACX,UAAU,OAAO,QAAQ;CAC3B;AACF;AAEA,MAAM,oBAAoB;CACxB,OAAO;AACT;;AAGA,MAAa,wBAAsC;CACjD,QAAA,GAAA,MAAA,sBAA4B,WAAW,aAAa,WAAW;AACjE;AAEA,MAAM,QAAQ,YAAsC;CAClD,UAAU;CACV,MAAM,KAAK,SAAS;CACpB,UAAU,CAAC,GAAG,SAAS;EAAE,GAAG;EAAS;EAAI,QAAQ;CAAK,CAAC;CACvD,KAAK;CACL,OAAO;AACT;AAEA,MAAM,SAAS,OAAqB;CAClC,MAAM,QAAQ,QAAQ,MAAM,MAAM;EAChC,OAAO,EAAE,OAAO;CAClB,CAAC;CACD,IAAI,CAAC,OAAO,QACV;CAEF,UAAU,QAAQ,KAAK,MAAM;EAC3B,OAAO,EAAE,OAAO,KAAK;GAAE,GAAG;GAAG,QAAQ;EAAM,IAAI;CACjD,CAAC;CACD,KAAK;CACL,MAAM,UAAU;CAChB,iBAAiB;EACf,UAAU,QAAQ,QAAQ,MAAM;GAC9B,OAAO,EAAE,OAAO;EAClB,CAAC;EACD,KAAK;CACP,GAAG,wBAAwB;AAC7B;AAEA,MAAM,iBAAuB;CAC3B,QAAQ,SAAS,UAAU;EACzB,IAAI,MAAM,QACR,MAAM,MAAM,EAAE;CAElB,CAAC;AACH;AAKA,MAAM,cAAoB;CACxB,UAAU,CAAC;CACX,KAAK;AACP;;;;;AAMA,MAAa,QAAQ;CACnB;CACA;CACA;CACA;AACF"}
@@ -0,0 +1,31 @@
1
+ import { ModalProps } from "./Modal.cjs";
2
+ import { ReactNode } from "react";
3
+
4
+ //#region src/Modal/modalStore.d.ts
5
+ /** Options accepted by `modal.open()` */
6
+ interface ModalOpenOptions extends Omit<ModalProps, 'isOpen' | 'onClose' | 'children'> {
7
+ /** Modal body content */
8
+ content?: ReactNode;
9
+ /** Callback fired when the modal is closed (by user or programmatically) */
10
+ onClose?: () => void;
11
+ }
12
+ /** Internal entry tracked by the store */
13
+ interface ModalEntry extends ModalOpenOptions {
14
+ id: string;
15
+ isOpen: boolean;
16
+ }
17
+ /**
18
+ * Imperative API for opening modals from anywhere (e.g. from inside a toast).
19
+ * Requires a `<ModalHost />` to be mounted somewhere in the React tree.
20
+ */
21
+ declare const modal: {
22
+ open: (options: ModalOpenOptions) => string;
23
+ close: (id: string) => void;
24
+ closeAll: () => void;
25
+ reset: () => void;
26
+ };
27
+ /** Imperative modal API as exposed by the `modal` store. */
28
+ type ModalStoreApi = typeof modal;
29
+ //#endregion
30
+ export { ModalEntry, ModalOpenOptions, ModalStoreApi, modal };
31
+ //# sourceMappingURL=modalStore.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modalStore.d.cts","names":[],"sources":["../../src/Modal/modalStore.ts"],"mappings":";;;;;UAMiB,gBAAA,SAAyB,IAAA,CACxC,UAAA;EADe;EAKf,OAAA,GAAU,SAAA;;EAEV,OAAA;AAAA;;UAIe,UAAA,SAAmB,gBAAgB;EAClD,EAAA;EACA,MAAA;AAAA;;;AANO;AAIT;cAmFa,KAAA;kBAhDU,gBAAgB;;;;;;KAwD3B,aAAA,UAAuB,KAAK"}
@@ -0,0 +1,31 @@
1
+ import { ModalProps } from "./Modal.js";
2
+ import { ReactNode } from "react";
3
+
4
+ //#region src/Modal/modalStore.d.ts
5
+ /** Options accepted by `modal.open()` */
6
+ interface ModalOpenOptions extends Omit<ModalProps, 'isOpen' | 'onClose' | 'children'> {
7
+ /** Modal body content */
8
+ content?: ReactNode;
9
+ /** Callback fired when the modal is closed (by user or programmatically) */
10
+ onClose?: () => void;
11
+ }
12
+ /** Internal entry tracked by the store */
13
+ interface ModalEntry extends ModalOpenOptions {
14
+ id: string;
15
+ isOpen: boolean;
16
+ }
17
+ /**
18
+ * Imperative API for opening modals from anywhere (e.g. from inside a toast).
19
+ * Requires a `<ModalHost />` to be mounted somewhere in the React tree.
20
+ */
21
+ declare const modal: {
22
+ open: (options: ModalOpenOptions) => string;
23
+ close: (id: string) => void;
24
+ closeAll: () => void;
25
+ reset: () => void;
26
+ };
27
+ /** Imperative modal API as exposed by the `modal` store. */
28
+ type ModalStoreApi = typeof modal;
29
+ //#endregion
30
+ export { ModalEntry, ModalOpenOptions, ModalStoreApi, modal };
31
+ //# sourceMappingURL=modalStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modalStore.d.ts","names":[],"sources":["../../src/Modal/modalStore.ts"],"mappings":";;;;;UAMiB,gBAAA,SAAyB,IAAA,CACxC,UAAA;EADe;EAKf,OAAA,GAAU,SAAA;;EAEV,OAAA;AAAA;;UAIe,UAAA,SAAmB,gBAAgB;EAClD,EAAA;EACA,MAAA;AAAA;;;AANO;AAIT;cAmFa,KAAA;kBAhDU,gBAAgB;;;;;;KAwD3B,aAAA,UAAuB,KAAK"}
@@ -0,0 +1,78 @@
1
+ import { useSyncExternalStore } from "react";
2
+ //#region src/Modal/modalStore.ts
3
+ const MODAL_CLOSE_ANIMATION_MS = 300;
4
+ let nextId = 0;
5
+ let entries = [];
6
+ const listeners = /* @__PURE__ */ new Set();
7
+ const emit = () => {
8
+ listeners.forEach((listener) => {
9
+ listener();
10
+ });
11
+ };
12
+ const subscribe = (listener) => {
13
+ listeners.add(listener);
14
+ return () => {
15
+ listeners.delete(listener);
16
+ };
17
+ };
18
+ const getSnapshot = () => {
19
+ return entries;
20
+ };
21
+ /** React hook used by `ModalHost` to subscribe to the modal stack */
22
+ const useModalEntries = () => {
23
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
24
+ };
25
+ const open = (options) => {
26
+ nextId += 1;
27
+ const id = `modal-${nextId}`;
28
+ entries = [...entries, {
29
+ ...options,
30
+ id,
31
+ isOpen: true
32
+ }];
33
+ emit();
34
+ return id;
35
+ };
36
+ const close = (id) => {
37
+ const entry = entries.find((e) => {
38
+ return e.id === id;
39
+ });
40
+ if (!entry?.isOpen) return;
41
+ entries = entries.map((e) => {
42
+ return e.id === id ? {
43
+ ...e,
44
+ isOpen: false
45
+ } : e;
46
+ });
47
+ emit();
48
+ entry.onClose?.();
49
+ setTimeout(() => {
50
+ entries = entries.filter((e) => {
51
+ return e.id !== id;
52
+ });
53
+ emit();
54
+ }, MODAL_CLOSE_ANIMATION_MS);
55
+ };
56
+ const closeAll = () => {
57
+ entries.forEach((entry) => {
58
+ if (entry.isOpen) close(entry.id);
59
+ });
60
+ };
61
+ const reset = () => {
62
+ entries = [];
63
+ emit();
64
+ };
65
+ /**
66
+ * Imperative API for opening modals from anywhere (e.g. from inside a toast).
67
+ * Requires a `<ModalHost />` to be mounted somewhere in the React tree.
68
+ */
69
+ const modal = {
70
+ open,
71
+ close,
72
+ closeAll,
73
+ reset
74
+ };
75
+ //#endregion
76
+ export { modal, useModalEntries };
77
+
78
+ //# sourceMappingURL=modalStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modalStore.js","names":[],"sources":["../../src/Modal/modalStore.ts"],"sourcesContent":["import type { ReactNode } from 'react';\nimport type { ModalProps } from './Modal';\n\nimport { useSyncExternalStore } from 'react';\n\n/** Options accepted by `modal.open()` */\nexport interface ModalOpenOptions extends Omit<\n ModalProps,\n 'isOpen' | 'onClose' | 'children'\n> {\n /** Modal body content */\n content?: ReactNode;\n /** Callback fired when the modal is closed (by user or programmatically) */\n onClose?: () => void;\n}\n\n/** Internal entry tracked by the store */\nexport interface ModalEntry extends ModalOpenOptions {\n id: string;\n isOpen: boolean;\n}\n\n// Duration of the HeroUI modal close animation. Entries stay in the list this\n// long after `close()` so the exit animation can play before unmounting.\nconst MODAL_CLOSE_ANIMATION_MS = 300;\n\nlet nextId = 0;\nlet entries: ModalEntry[] = [];\nconst listeners = new Set<() => void>();\n\nconst emit = () => {\n listeners.forEach((listener) => {\n listener();\n });\n};\n\nconst subscribe = (listener: () => void) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n};\n\nconst getSnapshot = () => {\n return entries;\n};\n\n/** React hook used by `ModalHost` to subscribe to the modal stack */\nexport const useModalEntries = (): ModalEntry[] => {\n return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n};\n\nconst open = (options: ModalOpenOptions): string => {\n nextId += 1;\n const id = `modal-${nextId}`;\n entries = [...entries, { ...options, id, isOpen: true }];\n emit();\n return id;\n};\n\nconst close = (id: string): void => {\n const entry = entries.find((e) => {\n return e.id === id;\n });\n if (!entry?.isOpen) {\n return;\n }\n entries = entries.map((e) => {\n return e.id === id ? { ...e, isOpen: false } : e;\n });\n emit();\n entry.onClose?.();\n setTimeout(() => {\n entries = entries.filter((e) => {\n return e.id !== id;\n });\n emit();\n }, MODAL_CLOSE_ANIMATION_MS);\n};\n\nconst closeAll = (): void => {\n entries.forEach((entry) => {\n if (entry.isOpen) {\n close(entry.id);\n }\n });\n};\n\n// Hard-resets the store without firing onClose callbacks or close animations.\n// Used by `ModalHost` on unmount so the store does not retain entries that\n// would re-appear when a host mounts again (e.g. switching Storybook stories).\nconst reset = (): void => {\n entries = [];\n emit();\n};\n\n/**\n * Imperative API for opening modals from anywhere (e.g. from inside a toast).\n * Requires a `<ModalHost />` to be mounted somewhere in the React tree.\n */\nexport const modal = {\n open,\n close,\n closeAll,\n reset,\n};\n\n/** Imperative modal API as exposed by the `modal` store. */\nexport type ModalStoreApi = typeof modal;\n"],"mappings":";;AAwBA,MAAM,2BAA2B;AAEjC,IAAI,SAAS;AACb,IAAI,UAAwB,CAAC;AAC7B,MAAM,4BAAY,IAAI,IAAgB;AAEtC,MAAM,aAAa;CACjB,UAAU,SAAS,aAAa;EAC9B,SAAS;CACX,CAAC;AACH;AAEA,MAAM,aAAa,aAAyB;CAC1C,UAAU,IAAI,QAAQ;CACtB,aAAa;EACX,UAAU,OAAO,QAAQ;CAC3B;AACF;AAEA,MAAM,oBAAoB;CACxB,OAAO;AACT;;AAGA,MAAa,wBAAsC;CACjD,OAAO,qBAAqB,WAAW,aAAa,WAAW;AACjE;AAEA,MAAM,QAAQ,YAAsC;CAClD,UAAU;CACV,MAAM,KAAK,SAAS;CACpB,UAAU,CAAC,GAAG,SAAS;EAAE,GAAG;EAAS;EAAI,QAAQ;CAAK,CAAC;CACvD,KAAK;CACL,OAAO;AACT;AAEA,MAAM,SAAS,OAAqB;CAClC,MAAM,QAAQ,QAAQ,MAAM,MAAM;EAChC,OAAO,EAAE,OAAO;CAClB,CAAC;CACD,IAAI,CAAC,OAAO,QACV;CAEF,UAAU,QAAQ,KAAK,MAAM;EAC3B,OAAO,EAAE,OAAO,KAAK;GAAE,GAAG;GAAG,QAAQ;EAAM,IAAI;CACjD,CAAC;CACD,KAAK;CACL,MAAM,UAAU;CAChB,iBAAiB;EACf,UAAU,QAAQ,QAAQ,MAAM;GAC9B,OAAO,EAAE,OAAO;EAClB,CAAC;EACD,KAAK;CACP,GAAG,wBAAwB;AAC7B;AAEA,MAAM,iBAAuB;CAC3B,QAAQ,SAAS,UAAU;EACzB,IAAI,MAAM,QACR,MAAM,MAAM,EAAE;CAElB,CAAC;AACH;AAKA,MAAM,cAAoB;CACxB,UAAU,CAAC;CACX,KAAK;AACP;;;;;AAMA,MAAa,QAAQ;CACnB;CACA;CACA;CACA;AACF"}
@@ -7,7 +7,6 @@ import { PopoverProps } from "@heroui/popover";
7
7
  declare const popoverVariants: import("tailwind-variants").TVReturnType<{
8
8
  [key: string]: {
9
9
  [key: string]: import("tailwind-merge").ClassNameValue | {
10
- trigger?: import("tailwind-merge").ClassNameValue;
11
10
  body?: import("tailwind-merge").ClassNameValue;
12
11
  footer?: import("tailwind-merge").ClassNameValue;
13
12
  header?: import("tailwind-merge").ClassNameValue;
@@ -15,12 +14,12 @@ declare const popoverVariants: import("tailwind-variants").TVReturnType<{
15
14
  divider?: import("tailwind-merge").ClassNameValue;
16
15
  footerWrapper?: import("tailwind-merge").ClassNameValue;
17
16
  headerWrapper?: import("tailwind-merge").ClassNameValue;
17
+ trigger?: import("tailwind-merge").ClassNameValue;
18
18
  };
19
19
  };
20
20
  } | {
21
21
  [x: string]: {
22
22
  [x: string]: import("tailwind-merge").ClassNameValue | {
23
- trigger?: import("tailwind-merge").ClassNameValue;
24
23
  body?: import("tailwind-merge").ClassNameValue;
25
24
  footer?: import("tailwind-merge").ClassNameValue;
26
25
  header?: import("tailwind-merge").ClassNameValue;
@@ -28,6 +27,7 @@ declare const popoverVariants: import("tailwind-variants").TVReturnType<{
28
27
  divider?: import("tailwind-merge").ClassNameValue;
29
28
  footerWrapper?: import("tailwind-merge").ClassNameValue;
30
29
  headerWrapper?: import("tailwind-merge").ClassNameValue;
30
+ trigger?: import("tailwind-merge").ClassNameValue;
31
31
  };
32
32
  };
33
33
  } | {}, {
@@ -42,7 +42,6 @@ declare const popoverVariants: import("tailwind-variants").TVReturnType<{
42
42
  }, undefined, {
43
43
  [key: string]: {
44
44
  [key: string]: import("tailwind-merge").ClassNameValue | {
45
- trigger?: import("tailwind-merge").ClassNameValue;
46
45
  body?: import("tailwind-merge").ClassNameValue;
47
46
  footer?: import("tailwind-merge").ClassNameValue;
48
47
  header?: import("tailwind-merge").ClassNameValue;
@@ -50,6 +49,7 @@ declare const popoverVariants: import("tailwind-variants").TVReturnType<{
50
49
  divider?: import("tailwind-merge").ClassNameValue;
51
50
  footerWrapper?: import("tailwind-merge").ClassNameValue;
52
51
  headerWrapper?: import("tailwind-merge").ClassNameValue;
52
+ trigger?: import("tailwind-merge").ClassNameValue;
53
53
  };
54
54
  };
55
55
  } | {}, {
@@ -7,7 +7,6 @@ import { PopoverProps } from "@heroui/popover";
7
7
  declare const popoverVariants: import("tailwind-variants").TVReturnType<{
8
8
  [key: string]: {
9
9
  [key: string]: import("tailwind-merge").ClassNameValue | {
10
- trigger?: import("tailwind-merge").ClassNameValue;
11
10
  body?: import("tailwind-merge").ClassNameValue;
12
11
  footer?: import("tailwind-merge").ClassNameValue;
13
12
  header?: import("tailwind-merge").ClassNameValue;
@@ -15,12 +14,12 @@ declare const popoverVariants: import("tailwind-variants").TVReturnType<{
15
14
  divider?: import("tailwind-merge").ClassNameValue;
16
15
  footerWrapper?: import("tailwind-merge").ClassNameValue;
17
16
  headerWrapper?: import("tailwind-merge").ClassNameValue;
17
+ trigger?: import("tailwind-merge").ClassNameValue;
18
18
  };
19
19
  };
20
20
  } | {
21
21
  [x: string]: {
22
22
  [x: string]: import("tailwind-merge").ClassNameValue | {
23
- trigger?: import("tailwind-merge").ClassNameValue;
24
23
  body?: import("tailwind-merge").ClassNameValue;
25
24
  footer?: import("tailwind-merge").ClassNameValue;
26
25
  header?: import("tailwind-merge").ClassNameValue;
@@ -28,6 +27,7 @@ declare const popoverVariants: import("tailwind-variants").TVReturnType<{
28
27
  divider?: import("tailwind-merge").ClassNameValue;
29
28
  footerWrapper?: import("tailwind-merge").ClassNameValue;
30
29
  headerWrapper?: import("tailwind-merge").ClassNameValue;
30
+ trigger?: import("tailwind-merge").ClassNameValue;
31
31
  };
32
32
  };
33
33
  } | {}, {
@@ -42,7 +42,6 @@ declare const popoverVariants: import("tailwind-variants").TVReturnType<{
42
42
  }, undefined, {
43
43
  [key: string]: {
44
44
  [key: string]: import("tailwind-merge").ClassNameValue | {
45
- trigger?: import("tailwind-merge").ClassNameValue;
46
45
  body?: import("tailwind-merge").ClassNameValue;
47
46
  footer?: import("tailwind-merge").ClassNameValue;
48
47
  header?: import("tailwind-merge").ClassNameValue;
@@ -50,6 +49,7 @@ declare const popoverVariants: import("tailwind-variants").TVReturnType<{
50
49
  divider?: import("tailwind-merge").ClassNameValue;
51
50
  footerWrapper?: import("tailwind-merge").ClassNameValue;
52
51
  headerWrapper?: import("tailwind-merge").ClassNameValue;
52
+ trigger?: import("tailwind-merge").ClassNameValue;
53
53
  };
54
54
  };
55
55
  } | {}, {
@@ -6,8 +6,8 @@ declare const inputVariants: import("tailwind-variants").TVReturnType<{
6
6
  [key: string]: {
7
7
  [key: string]: import("tailwind-merge").ClassNameValue | {
8
8
  base?: import("tailwind-merge").ClassNameValue;
9
- clearButton?: import("tailwind-merge").ClassNameValue;
10
9
  input?: import("tailwind-merge").ClassNameValue;
10
+ clearButton?: import("tailwind-merge").ClassNameValue;
11
11
  inputWrapper?: import("tailwind-merge").ClassNameValue;
12
12
  };
13
13
  };
@@ -15,8 +15,8 @@ declare const inputVariants: import("tailwind-variants").TVReturnType<{
15
15
  [x: string]: {
16
16
  [x: string]: import("tailwind-merge").ClassNameValue | {
17
17
  base?: import("tailwind-merge").ClassNameValue;
18
- clearButton?: import("tailwind-merge").ClassNameValue;
19
18
  input?: import("tailwind-merge").ClassNameValue;
19
+ clearButton?: import("tailwind-merge").ClassNameValue;
20
20
  inputWrapper?: import("tailwind-merge").ClassNameValue;
21
21
  };
22
22
  };
@@ -29,8 +29,8 @@ declare const inputVariants: import("tailwind-variants").TVReturnType<{
29
29
  [key: string]: {
30
30
  [key: string]: import("tailwind-merge").ClassNameValue | {
31
31
  base?: import("tailwind-merge").ClassNameValue;
32
- clearButton?: import("tailwind-merge").ClassNameValue;
33
32
  input?: import("tailwind-merge").ClassNameValue;
33
+ clearButton?: import("tailwind-merge").ClassNameValue;
34
34
  inputWrapper?: import("tailwind-merge").ClassNameValue;
35
35
  };
36
36
  };