@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.
- package/dist/Alert/Alert.cjs +18 -6
- package/dist/Alert/Alert.cjs.map +1 -1
- package/dist/Alert/Alert.d.cts +12 -0
- package/dist/Alert/Alert.d.cts.map +1 -1
- package/dist/Alert/Alert.d.ts +12 -0
- package/dist/Alert/Alert.d.ts.map +1 -1
- package/dist/Alert/Alert.js +18 -6
- package/dist/Alert/Alert.js.map +1 -1
- package/dist/Avatar/Avatar.d.cts +6 -6
- package/dist/Avatar/Avatar.d.ts +6 -6
- package/dist/Breadcrumb/Breadcrumb.d.cts +3 -3
- package/dist/Breadcrumb/Breadcrumb.d.ts +3 -3
- package/dist/Drawer/Drawer.d.cts +6 -6
- package/dist/Drawer/Drawer.d.ts +6 -6
- package/dist/Menu/Menu.d.cts +3 -3
- package/dist/Menu/Menu.d.ts +3 -3
- package/dist/Modal/Modal.cjs +1 -1
- package/dist/Modal/Modal.cjs.map +1 -1
- package/dist/Modal/Modal.d.cts +5 -1
- package/dist/Modal/Modal.d.cts.map +1 -1
- package/dist/Modal/Modal.d.ts +5 -1
- package/dist/Modal/Modal.d.ts.map +1 -1
- package/dist/Modal/Modal.js +2 -2
- package/dist/Modal/Modal.js.map +1 -1
- package/dist/Modal/ModalHost.cjs +40 -0
- package/dist/Modal/ModalHost.cjs.map +1 -0
- package/dist/Modal/ModalHost.d.cts +16 -0
- package/dist/Modal/ModalHost.d.cts.map +1 -0
- package/dist/Modal/ModalHost.d.ts +16 -0
- package/dist/Modal/ModalHost.d.ts.map +1 -0
- package/dist/Modal/ModalHost.js +39 -0
- package/dist/Modal/ModalHost.js.map +1 -0
- package/dist/Modal/index.cjs +4 -0
- package/dist/Modal/index.cjs.map +1 -1
- package/dist/Modal/index.d.cts +3 -1
- package/dist/Modal/index.d.ts +3 -1
- package/dist/Modal/index.js +3 -1
- package/dist/Modal/index.js.map +1 -1
- package/dist/Modal/modalStore.cjs +80 -0
- package/dist/Modal/modalStore.cjs.map +1 -0
- package/dist/Modal/modalStore.d.cts +31 -0
- package/dist/Modal/modalStore.d.cts.map +1 -0
- package/dist/Modal/modalStore.d.ts +31 -0
- package/dist/Modal/modalStore.d.ts.map +1 -0
- package/dist/Modal/modalStore.js +78 -0
- package/dist/Modal/modalStore.js.map +1 -0
- package/dist/Popover/Popover.d.cts +3 -3
- package/dist/Popover/Popover.d.ts +3 -3
- package/dist/SearchInput/SearchInput.d.cts +3 -3
- package/dist/SearchInput/SearchInput.d.ts +3 -3
- package/dist/Toast/Toaster.cjs +10 -2
- package/dist/Toast/Toaster.cjs.map +1 -1
- package/dist/Toast/Toaster.d.cts +5 -2
- package/dist/Toast/Toaster.d.cts.map +1 -1
- package/dist/Toast/Toaster.d.ts +5 -2
- package/dist/Toast/Toaster.d.ts.map +1 -1
- package/dist/Toast/Toaster.js +10 -2
- package/dist/Toast/Toaster.js.map +1 -1
- package/dist/Toast/index.cjs +3 -3
- package/dist/Toast/index.cjs.map +1 -1
- package/dist/Toast/index.d.cts +1 -1
- package/dist/Toast/index.d.ts +1 -1
- package/dist/Toast/index.js +1 -1
- package/dist/Toast/index.js.map +1 -1
- package/dist/Toast/{Toast.cjs → toast.cjs} +2 -2
- package/dist/Toast/{Toast.cjs.map → toast.cjs.map} +1 -1
- package/dist/Toast/{Toast.d.cts → toast.d.cts} +2 -2
- package/dist/Toast/{Toast.d.cts.map → toast.d.cts.map} +1 -1
- package/dist/Toast/{Toast.d.ts → toast.d.ts} +2 -2
- package/dist/Toast/{Toast.d.ts.map → toast.d.ts.map} +1 -1
- package/dist/Toast/{Toast.js → toast.js} +2 -2
- package/dist/Toast/{Toast.js.map → toast.js.map} +1 -1
- package/dist/index.cjs +6 -2
- package/dist/index.d.cts +4 -2
- package/dist/index.d.ts +4 -2
- package/dist/index.js +4 -2
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Modal.d.cts","names":[],"sources":["../../src/Modal/Modal.tsx"],"mappings":";;;;;
|
|
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"}
|
package/dist/Modal/Modal.d.ts
CHANGED
|
@@ -89,7 +89,11 @@ interface ModalProps$1 extends VariantProps {
|
|
|
89
89
|
children?: ReactNode;
|
|
90
90
|
/** CSS class name */
|
|
91
91
|
className?: ClassName;
|
|
92
|
-
/**
|
|
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":";;;;;
|
|
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"}
|
package/dist/Modal/Modal.js
CHANGED
|
@@ -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 =
|
|
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"),
|
package/dist/Modal/Modal.js.map
CHANGED
|
@@ -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 {
|
|
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"}
|
package/dist/Modal/index.cjs
CHANGED
|
@@ -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
|
package/dist/Modal/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["Modal"],"sources":["../../src/Modal/index.ts"],"sourcesContent":["import Modal
|
|
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"}
|
package/dist/Modal/index.d.cts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import { Modal, ModalProps, modalVariants } from "./Modal.cjs";
|
|
2
|
-
|
|
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 };
|
package/dist/Modal/index.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
1
|
import { Modal, ModalProps, modalVariants } from "./Modal.js";
|
|
2
|
-
|
|
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 };
|
package/dist/Modal/index.js
CHANGED
|
@@ -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
|
package/dist/Modal/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/Modal/index.ts"],"sourcesContent":["import Modal
|
|
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
|
};
|