react-modal-registry 0.1.1 → 0.1.2

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/README.md CHANGED
@@ -14,6 +14,7 @@ Managing dialogs in React often leads to **modal sprawl**—scattering `useState
14
14
  - **Promise-Based Dialogs**: Open modals imperatively (`await modal.open()`) and await user responses inline without local boolean states.
15
15
  - **End-to-End Type Safety**: Autocomplete modal IDs, input payloads, and return values via TypeScript declaration merging.
16
16
  - **URL Deep-Linking**: Synchronize modal visibility with the URL hash (`#modal=<id>`) or query params with native browser Back button dismissal.
17
+ - **Automatic Focus Restoration**: Tracks and restores focus back to the trigger element on the page upon modal dismissal, following WAI-ARIA accessibility standards.
17
18
  - **Zero Re-Render Penalty**: Split-context architecture ensures caller components never re-render when modals open or close.
18
19
  - **Headless & UI Agnostic**: Works out of the box with shadcn/ui, Radix UI, Tailwind CSS, or native HTML `<dialog>`.
19
20
 
package/dist/index.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";"use client";var E=Object.defineProperty;var Q=Object.getOwnPropertyDescriptor;var W=Object.getOwnPropertyNames;var X=Object.prototype.hasOwnProperty;var Z=(t,e)=>{for(var s in e)E(t,s,{get:e[s],enumerable:!0})},ee=(t,e,s,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let l of W(e))!X.call(t,l)&&l!==s&&E(t,l,{get:()=>e[l],enumerable:!(a=Q(e,l))||a.enumerable});return t};var te=t=>ee(E({},"__esModule",{value:!0}),t);var Me={};Z(Me,{ModalProvider:()=>de,ModalRegistry:()=>ie,isBrowser:()=>O,useCloseAll:()=>pe,useIsModalOpen:()=>ce,useModal:()=>ue,useRegisterModal:()=>G});module.exports=te(Me);var r=require("react"),m=require("react/jsx-runtime"),k={strategy:"hash",param:"modal",historyMode:"push"},O=()=>typeof window<"u",ne=200,_=(0,r.createContext)(null),B=(0,r.createContext)(new Map);function oe(t,e){if(Object.is(t,e))return!0;if(typeof t!="object"||t===null||typeof e!="object"||e===null)return!1;if(t instanceof Date&&e instanceof Date)return t.getTime()===e.getTime();if(t instanceof RegExp&&e instanceof RegExp)return t.source===e.source&&t.flags===e.flags;if(t instanceof Map||t instanceof Set||e instanceof Map||e instanceof Set)return!1;let s=Object.keys(t),a=Object.keys(e);return s.length!==a.length?!1:s.every(l=>Object.prototype.hasOwnProperty.call(e,l)&&t[l]===e[l])}function re(t){let e=(0,r.useRef)(t);return Array.isArray(t)&&Array.isArray(e.current)&&e.current.length===t.length&&e.current.every((s,a)=>s.id===t[a].id&&s.component===t[a].component)?e.current:(e.current=t,t)}function z(t){let e=t.replace(/^#/,""),[s,a]=e.includes("?")?e.split("?",2):e.includes("=")?["",e]:[e,""];return{anchor:s,params:new URLSearchParams(a)}}function ae(t,e){let s=e.toString();return s?`#${t?`${t}?`:""}${s}`:t?`#${t}`:""}function D(t){if(!O()||!t||t.enabled===!1)return null;let e=t.param??k.param;return(t.strategy??k.strategy)==="query"?new URLSearchParams(window.location.search).get(e):z(window.location.hash).params.get(e)}function U(t,e,s){if(!O()||!e||e.enabled===!1||D(e)===t)return;let a=s??e.historyMode??k.historyMode,l=e.param??k.param,M=new URL(window.location.href),x=g=>t?g.set(l,t):g.delete(l);if((e.strategy??k.strategy)==="query")x(M.searchParams);else{let{anchor:g,params:f}=z(window.location.hash);x(f),M.hash=ae(g,f)}window.history[a==="push"?"pushState":"replaceState"](window.history.state,"",M.pathname+M.search+M.hash)}function F(t,e){if(t)return typeof t=="function"?t(e):Object.prototype.hasOwnProperty.call(t,e)?t[e]:void 0}function de({children:t,unmountDelay:e=ne,fallback:s=null,routing:a}){let l=(0,r.useRef)(new Map),[M,x]=(0,r.useState)(new Map),g=(0,r.useRef)(M),f=(0,r.useCallback)(n=>{let o=n(g.current);return g.current=o,x(o),o},[]),R=(0,r.useRef)(new Map),y=(0,r.useRef)(new Map),Y=(0,r.useRef)(0),C=(0,r.useMemo)(()=>a?{...k,...a,enabled:a.enabled!==!1}:null,[a?.enabled,a?.strategy,a?.param,a?.historyMode,a?.defaultData]),p=(0,r.useRef)(C);p.current=C,(0,r.useEffect)(()=>()=>{y.current.forEach(clearTimeout),y.current.clear(),R.current.forEach(n=>n.resolve(void 0)),R.current.clear()},[]);let b=(0,r.useCallback)(n=>{let o=l.current.get(n);return o?.[o.length-1]},[]),P=(0,r.useCallback)((n,o)=>{let c=y.current.get(n);c&&clearTimeout(c);let d;d=setTimeout(()=>{y.current.get(n)===d&&y.current.delete(n),f(i=>{let u=i.get(n);if(!u||u.isOpen||u.invocationId!==o)return i;let T=new Map(i);return T.delete(n),T})},e),y.current.set(n,d)},[e,f]),A=(0,r.useCallback)((n,o,c,d=!0)=>{let i=g.current.get(n);if(!i||!i.isOpen||o!==void 0&&i.invocationId!==o)return;let u=R.current.get(n);u&&(o===void 0||u.invocationId===o)&&(R.current.delete(n),u.resolve(c)),d&&p.current?.enabled&&D(p.current)===String(n)&&U(null,p.current,"replace");let T=!1;f(I=>{let v=I.get(n);if(!v||!v.isOpen||o!==void 0&&v.invocationId!==o)return I;T=!0;let h=new Map(I);return e<=0?h.delete(n):h.set(n,{...v,isOpen:!1}),h}),T&&e>0&&P(n,i.invocationId)},[P,e,f]),w=(0,r.useCallback)((n,o,c=!0)=>{let d=b(n);if(!d)return Promise.reject(new Error(`[react-modal-registry] Modal "${String(n)}" is not registered.`));let i=g.current.get(n),u=R.current.get(n);if(i?.isOpen&&i.component===d&&oe(i.data,o)&&u)return u.promise;c&&p.current?.enabled&&U(String(n),p.current),u&&(R.current.delete(n),u.resolve(void 0));let T=y.current.get(n);T&&(clearTimeout(T),y.current.delete(n));let I=++Y.current,v,h=new Promise(S=>{v=S});return R.current.set(n,{promise:h,resolve:v,invocationId:I}),f(S=>{let K=new Map(S);return K.set(n,{id:n,component:d,isOpen:!0,data:o,invocationId:I}),K}),h},[b,f]),N=(0,r.useCallback)((n,...o)=>w(n,o[0],!0),[w]),j=(0,r.useCallback)((n,o)=>{A(n,void 0,o,!0)},[A]),$=(0,r.useCallback)(()=>{let n=Array.from(R.current.values());if(R.current.clear(),p.current?.enabled&&U(null,p.current,"replace"),e<=0){for(let o of y.current.values())clearTimeout(o);y.current.clear(),f(()=>new Map)}else{for(let[o,c]of g.current)c.isOpen&&P(o,c.invocationId);f(o=>{let c=!1,d=new Map(o);for(let[i,u]of o)u.isOpen&&(d.set(i,{...u,isOpen:!1}),c=!0);return c?d:o})}n.forEach(o=>o.resolve(void 0))},[P,e,f]),q=(0,r.useCallback)(n=>g.current.get(n)?.isOpen??!1,[]),V=(0,r.useCallback)(((n,o)=>{let c=Array.isArray(n)?n:o?[{id:n,component:o}]:[],d=p.current?.enabled?D(p.current):null;for(let i of c){let u=l.current.get(i.id);if(u||(u=[],l.current.set(i.id,u)),u.push(i.component),d&&d===String(i.id)&&!g.current.get(i.id)?.isOpen){let T=F(p.current?.defaultData,i.id);w(i.id,T,!1)}}}),[w]),H=(0,r.useCallback)((n,o)=>{let c=Array.isArray(n)?n:[n];for(let d of c){let i=l.current.get(d);if(!i)continue;if(o){let I=i.lastIndexOf(o);if(I!==-1&&i.splice(I,1),i.length>0)continue}l.current.delete(d);let u=y.current.get(d);u&&(clearTimeout(u),y.current.delete(d));let T=R.current.get(d);T&&(R.current.delete(d),T.resolve(void 0)),p.current?.enabled&&D(p.current)===String(d)&&U(null,p.current,"replace"),f(I=>{if(!I.has(d))return I;let v=new Map(I);return v.delete(d),v})}},[f]);(0,r.useEffect)(()=>{if(!C||!C.enabled||!O())return;let n=()=>{let o=D(p.current),c=g.current;for(let[d,i]of c)String(d)!==o&&i.isOpen&&A(d,void 0,void 0,!1);if(o){let d=o;!c.get(d)?.isOpen&&b(d)&&w(d,F(p.current?.defaultData,d),!1)}};return n(),window.addEventListener("popstate",n),window.addEventListener("hashchange",n),()=>{window.removeEventListener("popstate",n),window.removeEventListener("hashchange",n)}},[C,b,w,A]);let J=(0,r.useMemo)(()=>({register:V,unregister:H,open:N,close:j,closeAll:$,isOpen:q}),[V,H,N,j,$,q]);return(0,m.jsx)(_.Provider,{value:J,children:(0,m.jsxs)(B.Provider,{value:M,children:[t,(0,m.jsx)(se,{activeModals:M,close:A,fallback:s})]})})}function se({activeModals:t,close:e,fallback:s}){return t.size===0?null:(0,m.jsx)(m.Fragment,{children:Array.from(t.values(),a=>(0,m.jsx)(le,{active:a,onClose:e,fallback:s},`${String(a.id)}:${a.invocationId}`))})}var le=(0,r.memo)(function({active:e,onClose:s,fallback:a}){let l=(0,r.useCallback)(x=>s(e.id,e.invocationId,x,!0),[s,e.id,e.invocationId]),M=e.component;return(0,m.jsx)(r.Suspense,{fallback:a??null,children:(0,m.jsx)(M,{isOpen:e.isOpen,data:e.data,close:l})})});function G(t,e){let{register:s,unregister:a}=L(),l=re(t);(0,r.useEffect)(()=>{if(Array.isArray(l))return s(l),()=>{for(let M of l)a(M.id,M.component)};if(e)return s(l,e),()=>{a(l,e)}},[l,e,s,a])}function ie({modals:t}){return G(t),null}function ue(t){let{open:e,close:s,isOpen:a}=L();return(0,r.useMemo)(()=>({open:(...l)=>e(t,...l),close:l=>s(t,l),isOpen:()=>a(t)}),[e,s,a,t])}function ce(t){return(0,r.useContext)(B).get(t)?.isOpen??!1}function pe(){return L().closeAll}function L(){let t=(0,r.useContext)(_);if(!t)throw new Error("useModalContext must be used within <ModalProvider>");return t}0&&(module.exports={ModalProvider,ModalRegistry,isBrowser,useCloseAll,useIsModalOpen,useModal,useRegisterModal});
1
+ "use strict";"use client";var E=Object.defineProperty;var W=Object.getOwnPropertyDescriptor;var X=Object.getOwnPropertyNames;var Z=Object.prototype.hasOwnProperty;var ee=(t,e)=>{for(var s in e)E(t,s,{get:e[s],enumerable:!0})},te=(t,e,s,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let l of X(e))!Z.call(t,l)&&l!==s&&E(t,l,{get:()=>e[l],enumerable:!(a=W(e,l))||a.enumerable});return t};var ne=t=>te(E({},"__esModule",{value:!0}),t);var fe={};ee(fe,{ModalProvider:()=>se,ModalRegistry:()=>ue,isBrowser:()=>D,useCloseAll:()=>Me,useIsModalOpen:()=>pe,useModal:()=>ce,useRegisterModal:()=>G});module.exports=ne(fe);var r=require("react"),R=require("react/jsx-runtime"),k={strategy:"hash",param:"modal",historyMode:"push"},D=()=>typeof window<"u",oe=200,_=(0,r.createContext)(null),B=(0,r.createContext)(new Map);function re(t,e){if(Object.is(t,e))return!0;if(typeof t!="object"||t===null||typeof e!="object"||e===null)return!1;if(t instanceof Date&&e instanceof Date)return t.getTime()===e.getTime();if(t instanceof RegExp&&e instanceof RegExp)return t.source===e.source&&t.flags===e.flags;if(t instanceof Map||t instanceof Set||e instanceof Map||e instanceof Set)return!1;let s=Object.keys(t),a=Object.keys(e);return s.length!==a.length?!1:s.every(l=>Object.prototype.hasOwnProperty.call(e,l)&&t[l]===e[l])}function ae(t){let e=(0,r.useRef)(t);return Array.isArray(t)&&Array.isArray(e.current)&&e.current.length===t.length&&e.current.every((s,a)=>s.id===t[a].id&&s.component===t[a].component)?e.current:(e.current=t,t)}function z(t){let e=t.replace(/^#/,""),[s,a]=e.includes("?")?e.split("?",2):e.includes("=")?["",e]:[e,""];return{anchor:s,params:new URLSearchParams(a)}}function de(t,e){let s=e.toString();return s?`#${t?`${t}?`:""}${s}`:t?`#${t}`:""}function b(t){if(!D()||!t||t.enabled===!1)return null;let e=t.param??k.param;return(t.strategy??k.strategy)==="query"?new URLSearchParams(window.location.search).get(e):z(window.location.hash).params.get(e)}function O(t,e,s){if(!D()||!e||e.enabled===!1||b(e)===t)return;let a=s??e.historyMode??k.historyMode,l=e.param??k.param,M=new URL(window.location.href),x=f=>t?f.set(l,t):f.delete(l);if((e.strategy??k.strategy)==="query")x(M.searchParams);else{let{anchor:f,params:I}=z(window.location.hash);x(I),M.hash=de(f,I)}window.history[a==="push"?"pushState":"replaceState"](window.history.state,"",M.pathname+M.search+M.hash)}function K(t,e){if(t)return typeof t=="function"?t(e):Object.prototype.hasOwnProperty.call(t,e)?t[e]:void 0}function se({children:t,unmountDelay:e=oe,fallback:s=null,routing:a}){let l=(0,r.useRef)(new Map),[M,x]=(0,r.useState)(new Map),f=(0,r.useRef)(M),I=(0,r.useCallback)(n=>{let o=n(f.current);return f.current=o,x(o),o},[]),m=(0,r.useRef)(new Map),y=(0,r.useRef)(new Map),Y=(0,r.useRef)(0),C=(0,r.useMemo)(()=>a?{...k,...a,enabled:a.enabled!==!1}:null,[a?.enabled,a?.strategy,a?.param,a?.historyMode,a?.defaultData]),p=(0,r.useRef)(C);p.current=C,(0,r.useEffect)(()=>()=>{y.current.forEach(clearTimeout),y.current.clear(),m.current.forEach(n=>n.resolve(void 0)),m.current.clear()},[]);let P=(0,r.useCallback)(n=>{let o=l.current.get(n);return o?.[o.length-1]},[]),U=(0,r.useCallback)((n,o)=>{let c=y.current.get(n);c&&clearTimeout(c);let d;d=setTimeout(()=>{y.current.get(n)===d&&y.current.delete(n),I(i=>{let u=i.get(n);if(!u||u.isOpen||u.invocationId!==o)return i;let g=new Map(i);return g.delete(n),g})},e),y.current.set(n,d)},[e,I]),A=(0,r.useCallback)((n,o,c,d=!0)=>{let i=f.current.get(n);if(!i||!i.isOpen||o!==void 0&&i.invocationId!==o)return;let u=m.current.get(n);u&&(o===void 0||u.invocationId===o)&&(m.current.delete(n),u.resolve(c)),d&&p.current?.enabled&&b(p.current)===String(n)&&O(null,p.current,"replace"),i.prevFocus?.focus();let g=!1;I(T=>{let v=T.get(n);if(!v||!v.isOpen||o!==void 0&&v.invocationId!==o)return T;g=!0;let h=new Map(T);return e<=0?h.delete(n):h.set(n,{...v,isOpen:!1}),h}),g&&e>0&&U(n,i.invocationId)},[U,e,I]),w=(0,r.useCallback)((n,o,c=!0)=>{let d=P(n);if(!d)return Promise.reject(new Error(`[react-modal-registry] Modal "${String(n)}" is not registered.`));let i=f.current.get(n),u=m.current.get(n);if(i?.isOpen&&i.component===d&&re(i.data,o)&&u)return u.promise;c&&p.current?.enabled&&O(String(n),p.current),u&&(m.current.delete(n),u.resolve(void 0));let g=y.current.get(n);g&&(clearTimeout(g),y.current.delete(n));let T=++Y.current,v,h=new Promise(S=>{v=S});m.current.set(n,{promise:h,resolve:v,invocationId:T});let Q=i?.prevFocus??(D()&&document.activeElement instanceof HTMLElement&&document.activeElement!==document.body?document.activeElement:null);return I(S=>{let V=new Map(S);return V.set(n,{id:n,component:d,isOpen:!0,data:o,invocationId:T,prevFocus:Q}),V}),h},[P,I]),F=(0,r.useCallback)((n,...o)=>w(n,o[0],!0),[w]),N=(0,r.useCallback)((n,o)=>{A(n,void 0,o,!0)},[A]),j=(0,r.useCallback)(()=>{let n=Array.from(m.current.values());if(m.current.clear(),p.current?.enabled&&O(null,p.current,"replace"),e<=0){for(let o of y.current.values())clearTimeout(o);y.current.clear(),I(()=>new Map)}else{for(let[o,c]of f.current)c.isOpen&&U(o,c.invocationId);I(o=>{let c=!1,d=new Map(o);for(let[i,u]of o)u.isOpen&&(d.set(i,{...u,isOpen:!1}),c=!0);return c?d:o})}for(let o of f.current.values())if(o.isOpen&&o.prevFocus){o.prevFocus.focus();break}n.forEach(o=>o.resolve(void 0))},[U,e,I]),H=(0,r.useCallback)(n=>f.current.get(n)?.isOpen??!1,[]),$=(0,r.useCallback)(((n,o)=>{let c=Array.isArray(n)?n:o?[{id:n,component:o}]:[],d=p.current?.enabled?b(p.current):null;for(let i of c){let u=l.current.get(i.id);if(u||(u=[],l.current.set(i.id,u)),u.push(i.component),d&&d===String(i.id)&&!f.current.get(i.id)?.isOpen){let g=K(p.current?.defaultData,i.id);w(i.id,g,!1)}}}),[w]),q=(0,r.useCallback)((n,o)=>{let c=Array.isArray(n)?n:[n];for(let d of c){let i=l.current.get(d);if(!i)continue;if(o){let T=i.lastIndexOf(o);if(T!==-1&&i.splice(T,1),i.length>0)continue}l.current.delete(d);let u=y.current.get(d);u&&(clearTimeout(u),y.current.delete(d));let g=m.current.get(d);g&&(m.current.delete(d),g.resolve(void 0)),p.current?.enabled&&b(p.current)===String(d)&&O(null,p.current,"replace"),I(T=>{if(!T.has(d))return T;let v=new Map(T);return v.delete(d),v})}},[I]);(0,r.useEffect)(()=>{if(!C||!C.enabled||!D())return;let n=()=>{let o=b(p.current),c=f.current;for(let[d,i]of c)String(d)!==o&&i.isOpen&&A(d,void 0,void 0,!1);if(o){let d=o;!c.get(d)?.isOpen&&P(d)&&w(d,K(p.current?.defaultData,d),!1)}};return n(),window.addEventListener("popstate",n),window.addEventListener("hashchange",n),()=>{window.removeEventListener("popstate",n),window.removeEventListener("hashchange",n)}},[C,P,w,A]);let J=(0,r.useMemo)(()=>({register:$,unregister:q,open:F,close:N,closeAll:j,isOpen:H}),[$,q,F,N,j,H]);return(0,R.jsx)(_.Provider,{value:J,children:(0,R.jsxs)(B.Provider,{value:M,children:[t,(0,R.jsx)(le,{activeModals:M,close:A,fallback:s})]})})}function le({activeModals:t,close:e,fallback:s}){return t.size===0?null:(0,R.jsx)(R.Fragment,{children:Array.from(t.values(),a=>(0,R.jsx)(ie,{active:a,onClose:e,fallback:s},`${String(a.id)}:${a.invocationId}`))})}var ie=(0,r.memo)(function({active:e,onClose:s,fallback:a}){let l=(0,r.useCallback)(x=>s(e.id,e.invocationId,x,!0),[s,e.id,e.invocationId]),M=e.component;return(0,R.jsx)(r.Suspense,{fallback:a??null,children:(0,R.jsx)(M,{isOpen:e.isOpen,data:e.data,close:l})})});function G(t,e){let{register:s,unregister:a}=L(),l=ae(t);(0,r.useEffect)(()=>{if(Array.isArray(l))return s(l),()=>{for(let M of l)a(M.id,M.component)};if(e)return s(l,e),()=>{a(l,e)}},[l,e,s,a])}function ue({modals:t}){return G(t),null}function ce(t){let{open:e,close:s,isOpen:a}=L();return(0,r.useMemo)(()=>({open:(...l)=>e(t,...l),close:l=>s(t,l),isOpen:()=>a(t)}),[e,s,a,t])}function pe(t){return(0,r.useContext)(B).get(t)?.isOpen??!1}function Me(){return L().closeAll}function L(){let t=(0,r.useContext)(_);if(!t)throw new Error("useModalContext must be used within <ModalProvider>");return t}0&&(module.exports={ModalProvider,ModalRegistry,isBrowser,useCloseAll,useIsModalOpen,useModal,useRegisterModal});
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["'use client'\n\nimport {\n createContext,\n memo,\n Suspense,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentType,\n type ReactNode\n} from 'react'\n\n/**\n * Canonical registry for modal payloads and return types via module augmentation (e.g., `env.d.ts` or `modals.d.ts`).\n *\n * @example\n * ```ts\n * declare module 'react-modal-registry' {\n * interface ModalRegistry {\n * confirmAction: { data: { itemId: string }; result: boolean }\n * simpleAlert: void\n * }\n * }\n * ```\n */\nexport interface ModalRegistry { }\n\nexport type RegisteredModalId = keyof ModalRegistry\nexport type ModalId = [RegisteredModalId] extends [never] ? string : RegisteredModalId\n\nexport type ModalData<TId extends ModalId> = TId extends keyof ModalRegistry\n ? 'data' extends keyof ModalRegistry[TId]\n ? ModalRegistry[TId]['data']\n : void\n : unknown\n\nexport type ModalResult<TId extends ModalId> = TId extends keyof ModalRegistry\n ? 'result' extends keyof ModalRegistry[TId]\n ? ModalRegistry[TId]['result']\n : void\n : unknown\n\n/**\n * Derives optional vs. required payload arguments based on `TData`.\n */\nexport type ModalDataArg<TData> = [TData] extends [never]\n ? []\n : [unknown] extends [TData]\n ? [data?: TData]\n : [TData] extends [void] | [undefined]\n ? [data?: TData]\n : undefined extends TData\n ? [data?: TData]\n : [data: TData]\n\nexport type ModalClose<TResult = void> = [TResult] extends [void]\n ? () => void\n : (result?: TResult) => void\n\n/**\n * Standard props passed to registered modal components.\n */\nexport interface ModalProps<TData = unknown, TResult = void> {\n isOpen: boolean\n data: TData\n close: ModalClose<TResult>\n}\n\nexport type ModalComponent<TData = unknown, TResult = void> = ComponentType<\n ModalProps<TData, TResult>\n>\n\nexport type UntypedModalComponent = ComponentType<ModalProps<never, unknown>>\n\nexport type RegisteredComponent<TId extends ModalId> =\n [RegisteredModalId] extends [never]\n ? ComponentType<ModalProps<never, unknown>>\n : ModalComponent<ModalData<TId>, ModalResult<TId>>\n\nexport interface ModalRegistration<TId extends ModalId = ModalId> {\n id: TId\n component: RegisteredComponent<TId>\n}\n\n/**\n * Imperative modal controller returned by `useModal(id)`.\n */\nexport interface UseModalReturn<TData = unknown, TResult = unknown> {\n open(...args: ModalDataArg<TData>): Promise<TResult | undefined>\n close(result?: TResult): void\n isOpen(): boolean\n}\n\nexport type CanonicalResult<TId extends ModalId, TResult = ModalResult<TId>> =\n [RegisteredModalId] extends [never] ? TResult : ModalResult<TId>\n\nexport interface ModalActionsValue {\n register<TId extends ModalId>(\n id: TId,\n component: RegisteredComponent<TId>\n ): void\n register(modals: readonly ModalRegistration[]): void\n unregister(idOrIds: ModalId | readonly ModalId[], targetComponent?: UntypedModalComponent): void\n open<TId extends ModalId, TResult = ModalResult<TId>>(\n id: TId,\n ...args: ModalDataArg<ModalData<TId>>\n ): Promise<CanonicalResult<TId, TResult> | undefined>\n close<TId extends ModalId>(id: TId, result?: ModalResult<TId>): void\n closeAll(): void\n isOpen(id: ModalId): boolean\n}\n\nexport type ModalDefaultData =\n | Record<string, unknown>\n | ((id: ModalId) => unknown)\n\nexport type ModalRoutingStrategy = 'hash' | 'query'\nexport type ModalHistoryMode = 'push' | 'replace'\n\nexport interface ModalRoutingConfig {\n enabled?: boolean\n strategy?: ModalRoutingStrategy\n param?: string\n historyMode?: ModalHistoryMode\n defaultData?: ModalDefaultData\n}\n\nexport interface ModalProviderProps {\n children: ReactNode\n unmountDelay?: number\n fallback?: ReactNode\n routing?: ModalRoutingConfig\n}\n\ninterface ActiveModal {\n id: ModalId\n component: UntypedModalComponent\n isOpen: boolean\n data: unknown\n invocationId: number\n}\n\nconst DEFAULT_ROUTING = {\n strategy: 'hash',\n param: 'modal',\n historyMode: 'push'\n} as const\n\nexport const isBrowser = (): boolean => typeof window !== 'undefined'\n\nconst DEFAULT_UNMOUNT_DELAY = 200\n\nconst ModalActionsContext = createContext<ModalActionsValue | null>(null)\nconst ModalActiveContext = createContext<ReadonlyMap<ModalId, ActiveModal>>(new Map())\n\nfunction isShallowEqual(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true\n if (typeof a !== 'object' || a === null || typeof b !== 'object' || b === null) return false\n if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime()\n if (a instanceof RegExp && b instanceof RegExp) return a.source === b.source && a.flags === b.flags\n if (a instanceof Map || a instanceof Set || b instanceof Map || b instanceof Set) return false\n const keysA = Object.keys(a)\n const keysB = Object.keys(b)\n if (keysA.length !== keysB.length) return false\n return keysA.every(\n k =>\n Object.prototype.hasOwnProperty.call(b, k) &&\n (a as Record<string, unknown>)[k] === (b as Record<string, unknown>)[k]\n )\n}\n\nfunction useStableRegistrations<T extends ModalId | readonly ModalRegistration[]>(\n idOrModals: T\n): T {\n const ref = useRef(idOrModals)\n if (\n Array.isArray(idOrModals) &&\n Array.isArray(ref.current) &&\n ref.current.length === idOrModals.length &&\n ref.current.every((item, i) => item.id === idOrModals[i].id && item.component === idOrModals[i].component)\n ) {\n return ref.current as T\n }\n ref.current = idOrModals\n return idOrModals\n}\n\nfunction getHashParts(rawHash: string): { anchor: string; params: URLSearchParams } {\n const hash = rawHash.replace(/^#/, '')\n const [anchor, query] = hash.includes('?')\n ? hash.split('?', 2)\n : hash.includes('=')\n ? ['', hash]\n : [hash, '']\n return { anchor, params: new URLSearchParams(query) }\n}\n\nfunction formatHash(anchor: string, params: URLSearchParams): string {\n const qs = params.toString()\n return qs ? `#${anchor ? `${anchor}?` : ''}${qs}` : (anchor ? `#${anchor}` : '')\n}\n\nfunction getUrlModalId(config?: ModalRoutingConfig | null): string | null {\n if (!isBrowser() || !config || config.enabled === false) return null\n const param = config.param ?? DEFAULT_ROUTING.param\n return (config.strategy ?? DEFAULT_ROUTING.strategy) === 'query'\n ? new URLSearchParams(window.location.search).get(param)\n : getHashParts(window.location.hash).params.get(param)\n}\n\nfunction setUrlModalId(\n id: string | null,\n config?: ModalRoutingConfig | null,\n forceMode?: ModalHistoryMode\n) {\n if (!isBrowser() || !config || config.enabled === false) return\n if (getUrlModalId(config) === id) return\n\n const mode = forceMode ?? config.historyMode ?? DEFAULT_ROUTING.historyMode\n const param = config.param ?? DEFAULT_ROUTING.param\n const url = new URL(window.location.href)\n const updateParams = (sp: URLSearchParams) => (id ? sp.set(param, id) : sp.delete(param))\n\n if ((config.strategy ?? DEFAULT_ROUTING.strategy) === 'query') {\n updateParams(url.searchParams)\n } else {\n const { anchor, params } = getHashParts(window.location.hash)\n updateParams(params)\n url.hash = formatHash(anchor, params)\n }\n\n window.history[mode === 'push' ? 'pushState' : 'replaceState'](\n window.history.state,\n '',\n url.pathname + url.search + url.hash\n )\n}\n\nfunction getDefaultData(defaultData: ModalDefaultData | undefined, id: ModalId): unknown {\n if (!defaultData) return undefined\n return typeof defaultData === 'function'\n ? defaultData(id)\n : Object.prototype.hasOwnProperty.call(defaultData, id)\n ? (defaultData as Record<string, unknown>)[id]\n : undefined\n}\n\n/**\n * Root provider hosting the modal registry, URL routing, lifecycle actions, and slot renderer.\n */\nexport function ModalProvider({\n children,\n unmountDelay = DEFAULT_UNMOUNT_DELAY,\n fallback = null,\n routing\n}: ModalProviderProps) {\n // Registry stack allows multiple components to register the same modal ID safely\n const registryRef = useRef<Map<ModalId, UntypedModalComponent[]>>(new Map())\n\n // Active modals currently open or animating out\n const [activeModals, setActiveModals] = useState<ReadonlyMap<ModalId, ActiveModal>>(new Map())\n const activeModalsRef = useRef(activeModals)\n\n const updateActiveModals = useCallback(\n (updater: (prev: ReadonlyMap<ModalId, ActiveModal>) => ReadonlyMap<ModalId, ActiveModal>) => {\n const next = updater(activeModalsRef.current)\n activeModalsRef.current = next\n setActiveModals(next)\n return next\n },\n []\n )\n\n const pendingRef = useRef<\n Map<ModalId, { promise: Promise<unknown>; resolve: (value: unknown) => void; invocationId: number }>\n >(new Map())\n const timersRef = useRef<Map<ModalId, ReturnType<typeof setTimeout>>>(new Map())\n const invocationCounterRef = useRef(0)\n\n const resolvedRouting = useMemo(\n () =>\n routing\n ? {\n ...DEFAULT_ROUTING,\n ...routing,\n enabled: routing.enabled !== false\n }\n : null,\n [\n routing?.enabled,\n routing?.strategy,\n routing?.param,\n routing?.historyMode,\n routing?.defaultData\n ]\n )\n const routingRef = useRef(resolvedRouting)\n routingRef.current = resolvedRouting\n\n useEffect(() => {\n return () => {\n timersRef.current.forEach(clearTimeout)\n timersRef.current.clear()\n pendingRef.current.forEach(p => p.resolve(undefined))\n pendingRef.current.clear()\n }\n }, [])\n\n const getComponent = useCallback((id: ModalId) => {\n const stack = registryRef.current.get(id)\n return stack?.[stack.length - 1]\n }, [])\n\n const scheduleUnmount = useCallback(\n (id: ModalId, invocationId: number) => {\n const existing = timersRef.current.get(id)\n if (existing) clearTimeout(existing)\n\n let timer: ReturnType<typeof setTimeout>\n timer = setTimeout(() => {\n if (timersRef.current.get(id) === timer) {\n timersRef.current.delete(id)\n }\n updateActiveModals(prev => {\n const item = prev.get(id)\n if (!item || item.isOpen || item.invocationId !== invocationId) return prev\n const next = new Map(prev)\n next.delete(id)\n return next\n })\n }, unmountDelay)\n timersRef.current.set(id, timer)\n },\n [unmountDelay, updateActiveModals]\n )\n\n const closeModal = useCallback(\n (id: ModalId, invocationId?: number, result?: unknown, syncUrl = true) => {\n const active = activeModalsRef.current.get(id)\n if (!active || !active.isOpen) return\n if (invocationId !== undefined && active.invocationId !== invocationId) return\n\n const pending = pendingRef.current.get(id)\n if (pending && (invocationId === undefined || pending.invocationId === invocationId)) {\n pendingRef.current.delete(id)\n pending.resolve(result)\n }\n\n if (syncUrl && routingRef.current?.enabled) {\n if (getUrlModalId(routingRef.current) === String(id)) {\n setUrlModalId(null, routingRef.current, 'replace')\n }\n }\n\n let didClose = false\n updateActiveModals(prev => {\n const current = prev.get(id)\n if (!current || !current.isOpen) return prev\n if (invocationId !== undefined && current.invocationId !== invocationId) return prev\n didClose = true\n const next = new Map(prev)\n if (unmountDelay <= 0) {\n next.delete(id)\n } else {\n next.set(id, { ...current, isOpen: false })\n }\n return next\n })\n\n if (didClose && unmountDelay > 0) {\n scheduleUnmount(id, active.invocationId)\n }\n },\n [scheduleUnmount, unmountDelay, updateActiveModals]\n )\n\n const openModal = useCallback(\n (id: ModalId, data?: unknown, syncUrl = true): Promise<unknown> => {\n const comp = getComponent(id)\n if (!comp) {\n return Promise.reject(\n new Error(`[react-modal-registry] Modal \"${String(id)}\" is not registered.`)\n )\n }\n\n const current = activeModalsRef.current.get(id)\n const existing = pendingRef.current.get(id)\n\n if (\n current?.isOpen &&\n current.component === comp &&\n isShallowEqual(current.data, data) &&\n existing\n ) {\n return existing.promise\n }\n\n if (syncUrl && routingRef.current?.enabled) {\n setUrlModalId(String(id), routingRef.current)\n }\n\n if (existing) {\n pendingRef.current.delete(id)\n existing.resolve(undefined)\n }\n\n const timer = timersRef.current.get(id)\n if (timer) {\n clearTimeout(timer)\n timersRef.current.delete(id)\n }\n\n const invocationId = ++invocationCounterRef.current\n let resolver!: (val: unknown) => void\n const promise = new Promise<unknown>(resolve => {\n resolver = resolve\n })\n\n pendingRef.current.set(id, { promise, resolve: resolver, invocationId })\n\n updateActiveModals(prev => {\n const next = new Map(prev)\n next.set(id, { id, component: comp, isOpen: true, data, invocationId })\n return next\n })\n\n return promise\n },\n [getComponent, updateActiveModals]\n )\n\n const open = useCallback(\n <TId extends ModalId, TResult = ModalResult<TId>>(\n id: TId,\n ...args: ModalDataArg<ModalData<TId>>\n ): Promise<CanonicalResult<TId, TResult> | undefined> => {\n return openModal(id, args[0], true) as Promise<CanonicalResult<TId, TResult> | undefined>\n },\n [openModal]\n )\n\n const close = useCallback(\n <TId extends ModalId>(id: TId, result?: ModalResult<TId>) => {\n closeModal(id, undefined, result, true)\n },\n [closeModal]\n )\n\n const closeAll = useCallback(() => {\n const pendings = Array.from(pendingRef.current.values())\n pendingRef.current.clear()\n\n if (routingRef.current?.enabled) {\n setUrlModalId(null, routingRef.current, 'replace')\n }\n\n if (unmountDelay <= 0) {\n for (const timer of timersRef.current.values()) clearTimeout(timer)\n timersRef.current.clear()\n updateActiveModals(() => new Map())\n } else {\n for (const [id, active] of activeModalsRef.current) {\n if (active.isOpen) {\n scheduleUnmount(id, active.invocationId)\n }\n }\n\n updateActiveModals(prev => {\n let changed = false\n const next = new Map(prev)\n for (const [id, active] of prev) {\n if (active.isOpen) {\n next.set(id, { ...active, isOpen: false })\n changed = true\n }\n }\n return changed ? next : prev\n })\n }\n\n pendings.forEach(p => p.resolve(undefined))\n }, [scheduleUnmount, unmountDelay, updateActiveModals])\n\n const isOpen = useCallback(\n (id: ModalId) => activeModalsRef.current.get(id)?.isOpen ?? false,\n []\n )\n\n const register: ModalActionsValue['register'] = useCallback(\n ((\n idOrModals: ModalId | readonly ModalRegistration[],\n component?: UntypedModalComponent\n ) => {\n const items: readonly { id: ModalId; component: UntypedModalComponent }[] =\n Array.isArray(idOrModals)\n ? (idOrModals as unknown as readonly { id: ModalId; component: UntypedModalComponent }[])\n : component\n ? [{ id: idOrModals as ModalId, component }]\n : []\n\n const urlId = routingRef.current?.enabled ? getUrlModalId(routingRef.current) : null\n\n for (const item of items) {\n let stack = registryRef.current.get(item.id)\n if (!stack) {\n stack = []\n registryRef.current.set(item.id, stack)\n }\n stack.push(item.component)\n\n // If URL routing is active and specifies this modal, open it immediately\n if (urlId && urlId === String(item.id) && !activeModalsRef.current.get(item.id)?.isOpen) {\n const data = getDefaultData(routingRef.current?.defaultData, item.id)\n openModal(item.id, data, false)\n }\n }\n }) as ModalActionsValue['register'],\n [openModal]\n )\n\n const unregister = useCallback(\n (idOrIds: ModalId | readonly ModalId[], targetComponent?: UntypedModalComponent) => {\n const ids = Array.isArray(idOrIds) ? idOrIds : [idOrIds]\n\n for (const id of ids) {\n const stack = registryRef.current.get(id)\n if (!stack) continue\n\n if (targetComponent) {\n const idx = stack.lastIndexOf(targetComponent)\n if (idx !== -1) {\n stack.splice(idx, 1)\n }\n if (stack.length > 0) {\n continue\n }\n }\n\n registryRef.current.delete(id)\n\n const timer = timersRef.current.get(id)\n if (timer) {\n clearTimeout(timer)\n timersRef.current.delete(id)\n }\n\n const pending = pendingRef.current.get(id)\n if (pending) {\n pendingRef.current.delete(id)\n pending.resolve(undefined)\n }\n\n if (routingRef.current?.enabled && getUrlModalId(routingRef.current) === String(id)) {\n setUrlModalId(null, routingRef.current, 'replace')\n }\n\n updateActiveModals(prev => {\n if (!prev.has(id)) return prev\n const next = new Map(prev)\n next.delete(id)\n return next\n })\n }\n },\n [updateActiveModals]\n )\n\n // Two-way URL synchronization listener\n useEffect(() => {\n if (!resolvedRouting || !resolvedRouting.enabled || !isBrowser()) return\n\n const syncFromUrl = () => {\n const urlId = getUrlModalId(routingRef.current)\n const currentActive = activeModalsRef.current\n\n // Dismiss active modal that does not match urlId\n for (const [id, active] of currentActive) {\n if (String(id) !== urlId && active.isOpen) {\n closeModal(id, undefined, undefined, false)\n }\n }\n\n if (urlId) {\n const modalId = urlId as ModalId\n if (!currentActive.get(modalId)?.isOpen && getComponent(modalId)) {\n openModal(modalId, getDefaultData(routingRef.current?.defaultData, modalId), false)\n }\n }\n }\n\n syncFromUrl()\n\n window.addEventListener('popstate', syncFromUrl)\n window.addEventListener('hashchange', syncFromUrl)\n\n return () => {\n window.removeEventListener('popstate', syncFromUrl)\n window.removeEventListener('hashchange', syncFromUrl)\n }\n }, [\n resolvedRouting,\n getComponent,\n openModal,\n closeModal\n ])\n\n const actions = useMemo<ModalActionsValue>(\n () => ({\n register,\n unregister,\n open,\n close,\n closeAll,\n isOpen\n }),\n [register, unregister, open, close, closeAll, isOpen]\n )\n\n return (\n <ModalActionsContext.Provider value={actions}>\n <ModalActiveContext.Provider value={activeModals}>\n {children}\n <ModalRenderer\n activeModals={activeModals}\n close={closeModal}\n fallback={fallback}\n />\n </ModalActiveContext.Provider>\n </ModalActionsContext.Provider>\n )\n}\n\nfunction ModalRenderer({\n activeModals,\n close,\n fallback\n}: {\n activeModals: ReadonlyMap<ModalId, ActiveModal>\n close: (id: ModalId, invocationId: number, result?: unknown, syncUrl?: boolean) => void\n fallback?: ReactNode\n}) {\n if (activeModals.size === 0) return null\n\n return (\n <>\n {Array.from(activeModals.values(), active => (\n <ModalSlotItem\n key={`${String(active.id)}:${active.invocationId}`}\n active={active}\n onClose={close}\n fallback={fallback}\n />\n ))}\n </>\n )\n}\n\nconst ModalSlotItem = memo(function ModalSlotItem({\n active,\n onClose,\n fallback\n}: {\n active: ActiveModal\n onClose: (id: ModalId, invocationId: number, result?: unknown, syncUrl?: boolean) => void\n fallback?: ReactNode\n}) {\n const handleClose = useCallback(\n (result?: unknown) => onClose(active.id, active.invocationId, result, true),\n [onClose, active.id, active.invocationId]\n )\n\n const Component = active.component\n\n return (\n <Suspense fallback={fallback ?? null}>\n <Component\n isOpen={active.isOpen}\n data={active.data as never}\n close={handleClose}\n />\n </Suspense>\n )\n})\n\n/**\n * Registers one or more modals for the lifetime of the calling component.\n */\nexport function useRegisterModal<TId extends ModalId>(\n id: TId,\n component: RegisteredComponent<TId>\n): void\nexport function useRegisterModal<const TIds extends readonly ModalId[]>(modals: {\n [K in keyof TIds]: ModalRegistration<TIds[K]>\n} | readonly ModalRegistration[]): void\nexport function useRegisterModal<TId extends ModalId>(\n idOrModals: TId | readonly ModalRegistration[],\n component?: RegisteredComponent<TId>\n): void {\n const { register, unregister } = useModalContext()\n const stableIdOrModals = useStableRegistrations(idOrModals)\n\n useEffect(() => {\n if (Array.isArray(stableIdOrModals)) {\n register(stableIdOrModals)\n return () => {\n for (const item of stableIdOrModals) {\n unregister(item.id, item.component as unknown as UntypedModalComponent)\n }\n }\n }\n\n if (component) {\n register(stableIdOrModals as TId, component)\n return () => {\n unregister(stableIdOrModals as TId, component as unknown as UntypedModalComponent)\n }\n }\n\n return undefined\n }, [stableIdOrModals, component, register, unregister])\n}\n\n/**\n * Declarative component for mounting static modal batches at application roots.\n */\nexport function ModalRegistry<const TIds extends readonly ModalId[]>({\n modals\n}: {\n modals: {\n [K in keyof TIds]: ModalRegistration<TIds[K]>\n } | readonly ModalRegistration[]\n}) {\n useRegisterModal(modals)\n return null\n}\n\n/**\n * Returns typed controls (`open`, `close`, `isOpen`) for a modal ID.\n */\nexport function useModal<\n TId extends ModalId,\n TResult = ModalResult<TId>\n>(\n id: TId\n): UseModalReturn<ModalData<TId>, CanonicalResult<TId, TResult>> {\n const { open, close, isOpen } = useModalContext()\n\n return useMemo<UseModalReturn<ModalData<TId>, CanonicalResult<TId, TResult>>>(\n () => ({\n open: (...args: ModalDataArg<ModalData<TId>>) =>\n open<TId, TResult>(id, ...args),\n close: (result?: CanonicalResult<TId, TResult>) =>\n close(id, result as ModalResult<TId>),\n isOpen: () => isOpen(id)\n }),\n [open, close, isOpen, id]\n )\n}\n\n/**\n * Reactively subscribes to whether a modal is currently open.\n */\nexport function useIsModalOpen(id: ModalId): boolean {\n const active = useContext(ModalActiveContext)\n return active.get(id)?.isOpen ?? false\n}\n\nexport function useCloseAll(): () => void {\n return useModalContext().closeAll\n}\n\nfunction useModalContext(): ModalActionsValue {\n const context = useContext(ModalActionsContext)\n if (!context) {\n throw new Error('useModalContext must be used within <ModalProvider>')\n }\n return context\n}\n"],"mappings":"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","names":["index_exports","__export","ModalProvider","ModalRegistry","isBrowser","useCloseAll","useIsModalOpen","useModal","useRegisterModal","__toCommonJS","import_react","import_jsx_runtime","DEFAULT_ROUTING","DEFAULT_UNMOUNT_DELAY","ModalActionsContext","ModalActiveContext","isShallowEqual","a","b","keysA","keysB","k","useStableRegistrations","idOrModals","ref","item","i","getHashParts","rawHash","hash","anchor","query","formatHash","params","qs","getUrlModalId","config","param","setUrlModalId","id","forceMode","mode","url","updateParams","sp","getDefaultData","defaultData","children","unmountDelay","fallback","routing","registryRef","activeModals","setActiveModals","activeModalsRef","updateActiveModals","updater","next","pendingRef","timersRef","invocationCounterRef","resolvedRouting","routingRef","p","getComponent","stack","scheduleUnmount","invocationId","existing","timer","prev","closeModal","result","syncUrl","active","pending","didClose","current","openModal","data","comp","resolver","promise","resolve","open","args","close","closeAll","pendings","changed","isOpen","register","component","items","urlId","unregister","idOrIds","targetComponent","ids","idx","syncFromUrl","currentActive","modalId","actions","ModalRenderer","ModalSlotItem","onClose","handleClose","Component","useModalContext","stableIdOrModals","modals","context"]}
1
+ {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["'use client'\n\nimport {\n createContext,\n memo,\n Suspense,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentType,\n type ReactNode\n} from 'react'\n\n/**\n * Canonical registry for modal payloads and return types via module augmentation (e.g., `env.d.ts` or `modals.d.ts`).\n *\n * @example\n * ```ts\n * declare module 'react-modal-registry' {\n * interface ModalRegistry {\n * confirmAction: { data: { itemId: string }; result: boolean }\n * simpleAlert: void\n * }\n * }\n * ```\n */\nexport interface ModalRegistry { }\n\nexport type RegisteredModalId = keyof ModalRegistry\nexport type ModalId = [RegisteredModalId] extends [never] ? string : RegisteredModalId\n\nexport type ModalData<TId extends ModalId> = TId extends keyof ModalRegistry\n ? 'data' extends keyof ModalRegistry[TId]\n ? ModalRegistry[TId]['data']\n : void\n : unknown\n\nexport type ModalResult<TId extends ModalId> = TId extends keyof ModalRegistry\n ? 'result' extends keyof ModalRegistry[TId]\n ? ModalRegistry[TId]['result']\n : void\n : unknown\n\n/**\n * Derives optional vs. required payload arguments based on `TData`.\n */\nexport type ModalDataArg<TData> = [TData] extends [never]\n ? []\n : [unknown] extends [TData]\n ? [data?: TData]\n : [TData] extends [void] | [undefined]\n ? [data?: TData]\n : undefined extends TData\n ? [data?: TData]\n : [data: TData]\n\nexport type ModalClose<TResult = void> = [TResult] extends [void]\n ? () => void\n : (result?: TResult) => void\n\n/**\n * Standard props passed to registered modal components.\n */\nexport interface ModalProps<TData = unknown, TResult = void> {\n isOpen: boolean\n data: TData\n close: ModalClose<TResult>\n}\n\nexport type ModalComponent<TData = unknown, TResult = void> = ComponentType<\n ModalProps<TData, TResult>\n>\n\nexport type UntypedModalComponent = ComponentType<ModalProps<never, unknown>>\n\nexport type RegisteredComponent<TId extends ModalId> =\n [RegisteredModalId] extends [never]\n ? ComponentType<ModalProps<never, unknown>>\n : ModalComponent<ModalData<TId>, ModalResult<TId>>\n\nexport interface ModalRegistration<TId extends ModalId = ModalId> {\n id: TId\n component: RegisteredComponent<TId>\n}\n\n/**\n * Imperative modal controller returned by `useModal(id)`.\n */\nexport interface UseModalReturn<TData = unknown, TResult = unknown> {\n open(...args: ModalDataArg<TData>): Promise<TResult | undefined>\n close(result?: TResult): void\n isOpen(): boolean\n}\n\nexport type CanonicalResult<TId extends ModalId, TResult = ModalResult<TId>> =\n [RegisteredModalId] extends [never] ? TResult : ModalResult<TId>\n\nexport interface ModalActionsValue {\n register<TId extends ModalId>(\n id: TId,\n component: RegisteredComponent<TId>\n ): void\n register(modals: readonly ModalRegistration[]): void\n unregister(idOrIds: ModalId | readonly ModalId[], targetComponent?: UntypedModalComponent): void\n open<TId extends ModalId, TResult = ModalResult<TId>>(\n id: TId,\n ...args: ModalDataArg<ModalData<TId>>\n ): Promise<CanonicalResult<TId, TResult> | undefined>\n close<TId extends ModalId>(id: TId, result?: ModalResult<TId>): void\n closeAll(): void\n isOpen(id: ModalId): boolean\n}\n\nexport type ModalDefaultData =\n | Record<string, unknown>\n | ((id: ModalId) => unknown)\n\nexport type ModalRoutingStrategy = 'hash' | 'query'\nexport type ModalHistoryMode = 'push' | 'replace'\n\nexport interface ModalRoutingConfig {\n enabled?: boolean\n strategy?: ModalRoutingStrategy\n param?: string\n historyMode?: ModalHistoryMode\n defaultData?: ModalDefaultData\n}\n\nexport interface ModalProviderProps {\n children: ReactNode\n unmountDelay?: number\n fallback?: ReactNode\n routing?: ModalRoutingConfig\n}\n\ninterface ActiveModal {\n id: ModalId\n component: UntypedModalComponent\n isOpen: boolean\n data: unknown\n invocationId: number\n prevFocus?: HTMLElement | null\n}\n\nconst DEFAULT_ROUTING = {\n strategy: 'hash',\n param: 'modal',\n historyMode: 'push'\n} as const\n\nexport const isBrowser = (): boolean => typeof window !== 'undefined'\n\nconst DEFAULT_UNMOUNT_DELAY = 200\n\nconst ModalActionsContext = createContext<ModalActionsValue | null>(null)\nconst ModalActiveContext = createContext<ReadonlyMap<ModalId, ActiveModal>>(new Map())\n\nfunction isShallowEqual(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true\n if (typeof a !== 'object' || a === null || typeof b !== 'object' || b === null) return false\n if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime()\n if (a instanceof RegExp && b instanceof RegExp) return a.source === b.source && a.flags === b.flags\n if (a instanceof Map || a instanceof Set || b instanceof Map || b instanceof Set) return false\n const keysA = Object.keys(a)\n const keysB = Object.keys(b)\n if (keysA.length !== keysB.length) return false\n return keysA.every(\n k =>\n Object.prototype.hasOwnProperty.call(b, k) &&\n (a as Record<string, unknown>)[k] === (b as Record<string, unknown>)[k]\n )\n}\n\nfunction useStableRegistrations<T extends ModalId | readonly ModalRegistration[]>(\n idOrModals: T\n): T {\n const ref = useRef(idOrModals)\n if (\n Array.isArray(idOrModals) &&\n Array.isArray(ref.current) &&\n ref.current.length === idOrModals.length &&\n ref.current.every((item, i) => item.id === idOrModals[i].id && item.component === idOrModals[i].component)\n ) {\n return ref.current as T\n }\n ref.current = idOrModals\n return idOrModals\n}\n\nfunction getHashParts(rawHash: string): { anchor: string; params: URLSearchParams } {\n const hash = rawHash.replace(/^#/, '')\n const [anchor, query] = hash.includes('?')\n ? hash.split('?', 2)\n : hash.includes('=')\n ? ['', hash]\n : [hash, '']\n return { anchor, params: new URLSearchParams(query) }\n}\n\nfunction formatHash(anchor: string, params: URLSearchParams): string {\n const qs = params.toString()\n return qs ? `#${anchor ? `${anchor}?` : ''}${qs}` : (anchor ? `#${anchor}` : '')\n}\n\nfunction getUrlModalId(config?: ModalRoutingConfig | null): string | null {\n if (!isBrowser() || !config || config.enabled === false) return null\n const param = config.param ?? DEFAULT_ROUTING.param\n return (config.strategy ?? DEFAULT_ROUTING.strategy) === 'query'\n ? new URLSearchParams(window.location.search).get(param)\n : getHashParts(window.location.hash).params.get(param)\n}\n\nfunction setUrlModalId(\n id: string | null,\n config?: ModalRoutingConfig | null,\n forceMode?: ModalHistoryMode\n) {\n if (!isBrowser() || !config || config.enabled === false) return\n if (getUrlModalId(config) === id) return\n\n const mode = forceMode ?? config.historyMode ?? DEFAULT_ROUTING.historyMode\n const param = config.param ?? DEFAULT_ROUTING.param\n const url = new URL(window.location.href)\n const updateParams = (sp: URLSearchParams) => (id ? sp.set(param, id) : sp.delete(param))\n\n if ((config.strategy ?? DEFAULT_ROUTING.strategy) === 'query') {\n updateParams(url.searchParams)\n } else {\n const { anchor, params } = getHashParts(window.location.hash)\n updateParams(params)\n url.hash = formatHash(anchor, params)\n }\n\n window.history[mode === 'push' ? 'pushState' : 'replaceState'](\n window.history.state,\n '',\n url.pathname + url.search + url.hash\n )\n}\n\nfunction getDefaultData(defaultData: ModalDefaultData | undefined, id: ModalId): unknown {\n if (!defaultData) return undefined\n return typeof defaultData === 'function'\n ? defaultData(id)\n : Object.prototype.hasOwnProperty.call(defaultData, id)\n ? (defaultData as Record<string, unknown>)[id]\n : undefined\n}\n\n/**\n * Root provider hosting the modal registry, URL routing, lifecycle actions, and slot renderer.\n */\nexport function ModalProvider({\n children,\n unmountDelay = DEFAULT_UNMOUNT_DELAY,\n fallback = null,\n routing\n}: ModalProviderProps) {\n // Registry stack allows multiple components to register the same modal ID safely\n const registryRef = useRef<Map<ModalId, UntypedModalComponent[]>>(new Map())\n\n // Active modals currently open or animating out\n const [activeModals, setActiveModals] = useState<ReadonlyMap<ModalId, ActiveModal>>(new Map())\n const activeModalsRef = useRef(activeModals)\n\n const updateActiveModals = useCallback(\n (updater: (prev: ReadonlyMap<ModalId, ActiveModal>) => ReadonlyMap<ModalId, ActiveModal>) => {\n const next = updater(activeModalsRef.current)\n activeModalsRef.current = next\n setActiveModals(next)\n return next\n },\n []\n )\n\n const pendingRef = useRef<\n Map<ModalId, { promise: Promise<unknown>; resolve: (value: unknown) => void; invocationId: number }>\n >(new Map())\n const timersRef = useRef<Map<ModalId, ReturnType<typeof setTimeout>>>(new Map())\n const invocationCounterRef = useRef(0)\n\n const resolvedRouting = useMemo(\n () =>\n routing\n ? {\n ...DEFAULT_ROUTING,\n ...routing,\n enabled: routing.enabled !== false\n }\n : null,\n [\n routing?.enabled,\n routing?.strategy,\n routing?.param,\n routing?.historyMode,\n routing?.defaultData\n ]\n )\n const routingRef = useRef(resolvedRouting)\n routingRef.current = resolvedRouting\n\n useEffect(() => {\n return () => {\n timersRef.current.forEach(clearTimeout)\n timersRef.current.clear()\n pendingRef.current.forEach(p => p.resolve(undefined))\n pendingRef.current.clear()\n }\n }, [])\n\n const getComponent = useCallback((id: ModalId) => {\n const stack = registryRef.current.get(id)\n return stack?.[stack.length - 1]\n }, [])\n\n const scheduleUnmount = useCallback(\n (id: ModalId, invocationId: number) => {\n const existing = timersRef.current.get(id)\n if (existing) clearTimeout(existing)\n\n let timer: ReturnType<typeof setTimeout>\n timer = setTimeout(() => {\n if (timersRef.current.get(id) === timer) {\n timersRef.current.delete(id)\n }\n updateActiveModals(prev => {\n const item = prev.get(id)\n if (!item || item.isOpen || item.invocationId !== invocationId) return prev\n const next = new Map(prev)\n next.delete(id)\n return next\n })\n }, unmountDelay)\n timersRef.current.set(id, timer)\n },\n [unmountDelay, updateActiveModals]\n )\n\n const closeModal = useCallback(\n (id: ModalId, invocationId?: number, result?: unknown, syncUrl = true) => {\n const active = activeModalsRef.current.get(id)\n if (!active || !active.isOpen) return\n if (invocationId !== undefined && active.invocationId !== invocationId) return\n\n const pending = pendingRef.current.get(id)\n if (pending && (invocationId === undefined || pending.invocationId === invocationId)) {\n pendingRef.current.delete(id)\n pending.resolve(result)\n }\n\n if (syncUrl && routingRef.current?.enabled) {\n if (getUrlModalId(routingRef.current) === String(id)) {\n setUrlModalId(null, routingRef.current, 'replace')\n }\n }\n\n active.prevFocus?.focus()\n\n let didClose = false\n updateActiveModals(prev => {\n const current = prev.get(id)\n if (!current || !current.isOpen) return prev\n if (invocationId !== undefined && current.invocationId !== invocationId) return prev\n didClose = true\n const next = new Map(prev)\n if (unmountDelay <= 0) {\n next.delete(id)\n } else {\n next.set(id, { ...current, isOpen: false })\n }\n return next\n })\n\n if (didClose && unmountDelay > 0) {\n scheduleUnmount(id, active.invocationId)\n }\n },\n [scheduleUnmount, unmountDelay, updateActiveModals]\n )\n\n const openModal = useCallback(\n (id: ModalId, data?: unknown, syncUrl = true): Promise<unknown> => {\n const comp = getComponent(id)\n if (!comp) {\n return Promise.reject(\n new Error(`[react-modal-registry] Modal \"${String(id)}\" is not registered.`)\n )\n }\n\n const current = activeModalsRef.current.get(id)\n const existing = pendingRef.current.get(id)\n\n if (\n current?.isOpen &&\n current.component === comp &&\n isShallowEqual(current.data, data) &&\n existing\n ) {\n return existing.promise\n }\n\n if (syncUrl && routingRef.current?.enabled) {\n setUrlModalId(String(id), routingRef.current)\n }\n\n if (existing) {\n pendingRef.current.delete(id)\n existing.resolve(undefined)\n }\n\n const timer = timersRef.current.get(id)\n if (timer) {\n clearTimeout(timer)\n timersRef.current.delete(id)\n }\n\n const invocationId = ++invocationCounterRef.current\n let resolver!: (val: unknown) => void\n const promise = new Promise<unknown>(resolve => {\n resolver = resolve\n })\n\n pendingRef.current.set(id, { promise, resolve: resolver, invocationId })\n\n const prevFocus =\n current?.prevFocus ??\n (isBrowser() && document.activeElement instanceof HTMLElement && document.activeElement !== document.body\n ? document.activeElement\n : null)\n\n updateActiveModals(prev => {\n const next = new Map(prev)\n next.set(id, { id, component: comp, isOpen: true, data, invocationId, prevFocus })\n return next\n })\n\n return promise\n },\n [getComponent, updateActiveModals]\n )\n\n const open = useCallback(\n <TId extends ModalId, TResult = ModalResult<TId>>(\n id: TId,\n ...args: ModalDataArg<ModalData<TId>>\n ): Promise<CanonicalResult<TId, TResult> | undefined> => {\n return openModal(id, args[0], true) as Promise<CanonicalResult<TId, TResult> | undefined>\n },\n [openModal]\n )\n\n const close = useCallback(\n <TId extends ModalId>(id: TId, result?: ModalResult<TId>) => {\n closeModal(id, undefined, result, true)\n },\n [closeModal]\n )\n\n const closeAll = useCallback(() => {\n const pendings = Array.from(pendingRef.current.values())\n pendingRef.current.clear()\n\n if (routingRef.current?.enabled) {\n setUrlModalId(null, routingRef.current, 'replace')\n }\n\n if (unmountDelay <= 0) {\n for (const timer of timersRef.current.values()) clearTimeout(timer)\n timersRef.current.clear()\n updateActiveModals(() => new Map())\n } else {\n for (const [id, active] of activeModalsRef.current) {\n if (active.isOpen) {\n scheduleUnmount(id, active.invocationId)\n }\n }\n\n updateActiveModals(prev => {\n let changed = false\n const next = new Map(prev)\n for (const [id, active] of prev) {\n if (active.isOpen) {\n next.set(id, { ...active, isOpen: false })\n changed = true\n }\n }\n return changed ? next : prev\n })\n }\n\n for (const a of activeModalsRef.current.values()) {\n if (a.isOpen && a.prevFocus) {\n a.prevFocus.focus()\n break\n }\n }\n\n pendings.forEach(p => p.resolve(undefined))\n }, [scheduleUnmount, unmountDelay, updateActiveModals])\n\n const isOpen = useCallback(\n (id: ModalId) => activeModalsRef.current.get(id)?.isOpen ?? false,\n []\n )\n\n const register: ModalActionsValue['register'] = useCallback(\n ((\n idOrModals: ModalId | readonly ModalRegistration[],\n component?: UntypedModalComponent\n ) => {\n const items: readonly { id: ModalId; component: UntypedModalComponent }[] =\n Array.isArray(idOrModals)\n ? (idOrModals as unknown as readonly { id: ModalId; component: UntypedModalComponent }[])\n : component\n ? [{ id: idOrModals as ModalId, component }]\n : []\n\n const urlId = routingRef.current?.enabled ? getUrlModalId(routingRef.current) : null\n\n for (const item of items) {\n let stack = registryRef.current.get(item.id)\n if (!stack) {\n stack = []\n registryRef.current.set(item.id, stack)\n }\n stack.push(item.component)\n\n // If URL routing is active and specifies this modal, open it immediately\n if (urlId && urlId === String(item.id) && !activeModalsRef.current.get(item.id)?.isOpen) {\n const data = getDefaultData(routingRef.current?.defaultData, item.id)\n openModal(item.id, data, false)\n }\n }\n }) as ModalActionsValue['register'],\n [openModal]\n )\n\n const unregister = useCallback(\n (idOrIds: ModalId | readonly ModalId[], targetComponent?: UntypedModalComponent) => {\n const ids = Array.isArray(idOrIds) ? idOrIds : [idOrIds]\n\n for (const id of ids) {\n const stack = registryRef.current.get(id)\n if (!stack) continue\n\n if (targetComponent) {\n const idx = stack.lastIndexOf(targetComponent)\n if (idx !== -1) {\n stack.splice(idx, 1)\n }\n if (stack.length > 0) {\n continue\n }\n }\n\n registryRef.current.delete(id)\n\n const timer = timersRef.current.get(id)\n if (timer) {\n clearTimeout(timer)\n timersRef.current.delete(id)\n }\n\n const pending = pendingRef.current.get(id)\n if (pending) {\n pendingRef.current.delete(id)\n pending.resolve(undefined)\n }\n\n if (routingRef.current?.enabled && getUrlModalId(routingRef.current) === String(id)) {\n setUrlModalId(null, routingRef.current, 'replace')\n }\n\n updateActiveModals(prev => {\n if (!prev.has(id)) return prev\n const next = new Map(prev)\n next.delete(id)\n return next\n })\n }\n },\n [updateActiveModals]\n )\n\n // Two-way URL synchronization listener\n useEffect(() => {\n if (!resolvedRouting || !resolvedRouting.enabled || !isBrowser()) return\n\n const syncFromUrl = () => {\n const urlId = getUrlModalId(routingRef.current)\n const currentActive = activeModalsRef.current\n\n // Dismiss active modal that does not match urlId\n for (const [id, active] of currentActive) {\n if (String(id) !== urlId && active.isOpen) {\n closeModal(id, undefined, undefined, false)\n }\n }\n\n if (urlId) {\n const modalId = urlId as ModalId\n if (!currentActive.get(modalId)?.isOpen && getComponent(modalId)) {\n openModal(modalId, getDefaultData(routingRef.current?.defaultData, modalId), false)\n }\n }\n }\n\n syncFromUrl()\n\n window.addEventListener('popstate', syncFromUrl)\n window.addEventListener('hashchange', syncFromUrl)\n\n return () => {\n window.removeEventListener('popstate', syncFromUrl)\n window.removeEventListener('hashchange', syncFromUrl)\n }\n }, [\n resolvedRouting,\n getComponent,\n openModal,\n closeModal\n ])\n\n const actions = useMemo<ModalActionsValue>(\n () => ({\n register,\n unregister,\n open,\n close,\n closeAll,\n isOpen\n }),\n [register, unregister, open, close, closeAll, isOpen]\n )\n\n return (\n <ModalActionsContext.Provider value={actions}>\n <ModalActiveContext.Provider value={activeModals}>\n {children}\n <ModalRenderer\n activeModals={activeModals}\n close={closeModal}\n fallback={fallback}\n />\n </ModalActiveContext.Provider>\n </ModalActionsContext.Provider>\n )\n}\n\nfunction ModalRenderer({\n activeModals,\n close,\n fallback\n}: {\n activeModals: ReadonlyMap<ModalId, ActiveModal>\n close: (id: ModalId, invocationId: number, result?: unknown, syncUrl?: boolean) => void\n fallback?: ReactNode\n}) {\n if (activeModals.size === 0) return null\n\n return (\n <>\n {Array.from(activeModals.values(), active => (\n <ModalSlotItem\n key={`${String(active.id)}:${active.invocationId}`}\n active={active}\n onClose={close}\n fallback={fallback}\n />\n ))}\n </>\n )\n}\n\nconst ModalSlotItem = memo(function ModalSlotItem({\n active,\n onClose,\n fallback\n}: {\n active: ActiveModal\n onClose: (id: ModalId, invocationId: number, result?: unknown, syncUrl?: boolean) => void\n fallback?: ReactNode\n}) {\n const handleClose = useCallback(\n (result?: unknown) => onClose(active.id, active.invocationId, result, true),\n [onClose, active.id, active.invocationId]\n )\n\n const Component = active.component\n\n return (\n <Suspense fallback={fallback ?? null}>\n <Component\n isOpen={active.isOpen}\n data={active.data as never}\n close={handleClose}\n />\n </Suspense>\n )\n})\n\n/**\n * Registers one or more modals for the lifetime of the calling component.\n */\nexport function useRegisterModal<TId extends ModalId>(\n id: TId,\n component: RegisteredComponent<TId>\n): void\nexport function useRegisterModal<const TIds extends readonly ModalId[]>(modals: {\n [K in keyof TIds]: ModalRegistration<TIds[K]>\n} | readonly ModalRegistration[]): void\nexport function useRegisterModal<TId extends ModalId>(\n idOrModals: TId | readonly ModalRegistration[],\n component?: RegisteredComponent<TId>\n): void {\n const { register, unregister } = useModalContext()\n const stableIdOrModals = useStableRegistrations(idOrModals)\n\n useEffect(() => {\n if (Array.isArray(stableIdOrModals)) {\n register(stableIdOrModals)\n return () => {\n for (const item of stableIdOrModals) {\n unregister(item.id, item.component as unknown as UntypedModalComponent)\n }\n }\n }\n\n if (component) {\n register(stableIdOrModals as TId, component)\n return () => {\n unregister(stableIdOrModals as TId, component as unknown as UntypedModalComponent)\n }\n }\n\n return undefined\n }, [stableIdOrModals, component, register, unregister])\n}\n\n/**\n * Declarative component for mounting static modal batches at application roots.\n */\nexport function ModalRegistry<const TIds extends readonly ModalId[]>({\n modals\n}: {\n modals: {\n [K in keyof TIds]: ModalRegistration<TIds[K]>\n } | readonly ModalRegistration[]\n}) {\n useRegisterModal(modals)\n return null\n}\n\n/**\n * Returns typed controls (`open`, `close`, `isOpen`) for a modal ID.\n */\nexport function useModal<\n TId extends ModalId,\n TResult = ModalResult<TId>\n>(\n id: TId\n): UseModalReturn<ModalData<TId>, CanonicalResult<TId, TResult>> {\n const { open, close, isOpen } = useModalContext()\n\n return useMemo<UseModalReturn<ModalData<TId>, CanonicalResult<TId, TResult>>>(\n () => ({\n open: (...args: ModalDataArg<ModalData<TId>>) =>\n open<TId, TResult>(id, ...args),\n close: (result?: CanonicalResult<TId, TResult>) =>\n close(id, result as ModalResult<TId>),\n isOpen: () => isOpen(id)\n }),\n [open, close, isOpen, id]\n )\n}\n\n/**\n * Reactively subscribes to whether a modal is currently open.\n */\nexport function useIsModalOpen(id: ModalId): boolean {\n const active = useContext(ModalActiveContext)\n return active.get(id)?.isOpen ?? false\n}\n\nexport function useCloseAll(): () => void {\n return useModalContext().closeAll\n}\n\nfunction useModalContext(): ModalActionsValue {\n const context = useContext(ModalActionsContext)\n if (!context) {\n throw new Error('useModalContext must be used within <ModalProvider>')\n }\n return context\n}\n"],"mappings":"0bAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,mBAAAE,GAAA,kBAAAC,GAAA,cAAAC,EAAA,gBAAAC,GAAA,mBAAAC,GAAA,aAAAC,GAAA,qBAAAC,IAAA,eAAAC,GAAAT,IAEA,IAAAU,EAYO,iBAknBDC,EAAA,6BA7eAC,EAAkB,CACtB,SAAU,OACV,MAAO,QACP,YAAa,MACf,EAEaR,EAAY,IAAe,OAAO,OAAW,IAEpDS,GAAwB,IAExBC,KAAsB,iBAAwC,IAAI,EAClEC,KAAqB,iBAAiD,IAAI,GAAK,EAErF,SAASC,GAAeC,EAAYC,EAAqB,CACvD,GAAI,OAAO,GAAGD,EAAGC,CAAC,EAAG,MAAO,GAC5B,GAAI,OAAOD,GAAM,UAAYA,IAAM,MAAQ,OAAOC,GAAM,UAAYA,IAAM,KAAM,MAAO,GACvF,GAAID,aAAa,MAAQC,aAAa,KAAM,OAAOD,EAAE,QAAQ,IAAMC,EAAE,QAAQ,EAC7E,GAAID,aAAa,QAAUC,aAAa,OAAQ,OAAOD,EAAE,SAAWC,EAAE,QAAUD,EAAE,QAAUC,EAAE,MAC9F,GAAID,aAAa,KAAOA,aAAa,KAAOC,aAAa,KAAOA,aAAa,IAAK,MAAO,GACzF,IAAMC,EAAQ,OAAO,KAAKF,CAAC,EACrBG,EAAQ,OAAO,KAAKF,CAAC,EAC3B,OAAIC,EAAM,SAAWC,EAAM,OAAe,GACnCD,EAAM,MACXE,GACE,OAAO,UAAU,eAAe,KAAKH,EAAGG,CAAC,GACxCJ,EAA8BI,CAAC,IAAOH,EAA8BG,CAAC,CAC1E,CACF,CAEA,SAASC,GACPC,EACG,CACH,IAAMC,KAAM,UAAOD,CAAU,EAC7B,OACE,MAAM,QAAQA,CAAU,GACxB,MAAM,QAAQC,EAAI,OAAO,GACzBA,EAAI,QAAQ,SAAWD,EAAW,QAClCC,EAAI,QAAQ,MAAM,CAACC,EAAMC,IAAMD,EAAK,KAAOF,EAAWG,CAAC,EAAE,IAAMD,EAAK,YAAcF,EAAWG,CAAC,EAAE,SAAS,EAElGF,EAAI,SAEbA,EAAI,QAAUD,EACPA,EACT,CAEA,SAASI,EAAaC,EAA8D,CAClF,IAAMC,EAAOD,EAAQ,QAAQ,KAAM,EAAE,EAC/B,CAACE,EAAQC,CAAK,EAAIF,EAAK,SAAS,GAAG,EACrCA,EAAK,MAAM,IAAK,CAAC,EACjBA,EAAK,SAAS,GAAG,EACjB,CAAC,GAAIA,CAAI,EACT,CAACA,EAAM,EAAE,EACb,MAAO,CAAE,OAAAC,EAAQ,OAAQ,IAAI,gBAAgBC,CAAK,CAAE,CACtD,CAEA,SAASC,GAAWF,EAAgBG,EAAiC,CACnE,IAAMC,EAAKD,EAAO,SAAS,EAC3B,OAAOC,EAAK,IAAIJ,EAAS,GAAGA,CAAM,IAAM,EAAE,GAAGI,CAAE,GAAMJ,EAAS,IAAIA,CAAM,GAAK,EAC/E,CAEA,SAASK,EAAcC,EAAmD,CACxE,GAAI,CAAChC,EAAU,GAAK,CAACgC,GAAUA,EAAO,UAAY,GAAO,OAAO,KAChE,IAAMC,EAAQD,EAAO,OAASxB,EAAgB,MAC9C,OAAQwB,EAAO,UAAYxB,EAAgB,YAAc,QACrD,IAAI,gBAAgB,OAAO,SAAS,MAAM,EAAE,IAAIyB,CAAK,EACrDV,EAAa,OAAO,SAAS,IAAI,EAAE,OAAO,IAAIU,CAAK,CACzD,CAEA,SAASC,EACPC,EACAH,EACAI,EACA,CAEA,GADI,CAACpC,EAAU,GAAK,CAACgC,GAAUA,EAAO,UAAY,IAC9CD,EAAcC,CAAM,IAAMG,EAAI,OAElC,IAAME,EAAOD,GAAaJ,EAAO,aAAexB,EAAgB,YAC1DyB,EAAQD,EAAO,OAASxB,EAAgB,MACxC8B,EAAM,IAAI,IAAI,OAAO,SAAS,IAAI,EAClCC,EAAgBC,GAAyBL,EAAKK,EAAG,IAAIP,EAAOE,CAAE,EAAIK,EAAG,OAAOP,CAAK,EAEvF,IAAKD,EAAO,UAAYxB,EAAgB,YAAc,QACpD+B,EAAaD,EAAI,YAAY,MACxB,CACL,GAAM,CAAE,OAAAZ,EAAQ,OAAAG,CAAO,EAAIN,EAAa,OAAO,SAAS,IAAI,EAC5DgB,EAAaV,CAAM,EACnBS,EAAI,KAAOV,GAAWF,EAAQG,CAAM,CACtC,CAEA,OAAO,QAAQQ,IAAS,OAAS,YAAc,cAAc,EAC3D,OAAO,QAAQ,MACf,GACAC,EAAI,SAAWA,EAAI,OAASA,EAAI,IAClC,CACF,CAEA,SAASG,EAAeC,EAA2CP,EAAsB,CACvF,GAAKO,EACL,OAAO,OAAOA,GAAgB,WAC1BA,EAAYP,CAAE,EACd,OAAO,UAAU,eAAe,KAAKO,EAAaP,CAAE,EACnDO,EAAwCP,CAAE,EAC3C,MACN,CAKO,SAASrC,GAAc,CAC5B,SAAA6C,EACA,aAAAC,EAAenC,GACf,SAAAoC,EAAW,KACX,QAAAC,CACF,EAAuB,CAErB,IAAMC,KAAc,UAA8C,IAAI,GAAK,EAGrE,CAACC,EAAcC,CAAe,KAAI,YAA4C,IAAI,GAAK,EACvFC,KAAkB,UAAOF,CAAY,EAErCG,KAAqB,eACxBC,GAA4F,CAC3F,IAAMC,EAAOD,EAAQF,EAAgB,OAAO,EAC5C,OAAAA,EAAgB,QAAUG,EAC1BJ,EAAgBI,CAAI,EACbA,CACT,EACA,CAAC,CACH,EAEMC,KAAa,UAEjB,IAAI,GAAK,EACLC,KAAY,UAAoD,IAAI,GAAK,EACzEC,KAAuB,UAAO,CAAC,EAE/BC,KAAkB,WACtB,IACEX,EACI,CACE,GAAGtC,EACH,GAAGsC,EACH,QAASA,EAAQ,UAAY,EAC/B,EACA,KACN,CACEA,GAAS,QACTA,GAAS,SACTA,GAAS,MACTA,GAAS,YACTA,GAAS,WACX,CACF,EACMY,KAAa,UAAOD,CAAe,EACzCC,EAAW,QAAUD,KAErB,aAAU,IACD,IAAM,CACXF,EAAU,QAAQ,QAAQ,YAAY,EACtCA,EAAU,QAAQ,MAAM,EACxBD,EAAW,QAAQ,QAAQK,GAAKA,EAAE,QAAQ,MAAS,CAAC,EACpDL,EAAW,QAAQ,MAAM,CAC3B,EACC,CAAC,CAAC,EAEL,IAAMM,KAAe,eAAazB,GAAgB,CAChD,IAAM0B,EAAQd,EAAY,QAAQ,IAAIZ,CAAE,EACxC,OAAO0B,IAAQA,EAAM,OAAS,CAAC,CACjC,EAAG,CAAC,CAAC,EAECC,KAAkB,eACtB,CAAC3B,EAAa4B,IAAyB,CACrC,IAAMC,EAAWT,EAAU,QAAQ,IAAIpB,CAAE,EACrC6B,GAAU,aAAaA,CAAQ,EAEnC,IAAIC,EACJA,EAAQ,WAAW,IAAM,CACnBV,EAAU,QAAQ,IAAIpB,CAAE,IAAM8B,GAChCV,EAAU,QAAQ,OAAOpB,CAAE,EAE7BgB,EAAmBe,GAAQ,CACzB,IAAM7C,EAAO6C,EAAK,IAAI/B,CAAE,EACxB,GAAI,CAACd,GAAQA,EAAK,QAAUA,EAAK,eAAiB0C,EAAc,OAAOG,EACvE,IAAMb,EAAO,IAAI,IAAIa,CAAI,EACzB,OAAAb,EAAK,OAAOlB,CAAE,EACPkB,CACT,CAAC,CACH,EAAGT,CAAY,EACfW,EAAU,QAAQ,IAAIpB,EAAI8B,CAAK,CACjC,EACA,CAACrB,EAAcO,CAAkB,CACnC,EAEMgB,KAAa,eACjB,CAAChC,EAAa4B,EAAuBK,EAAkBC,EAAU,KAAS,CACxE,IAAMC,EAASpB,EAAgB,QAAQ,IAAIf,CAAE,EAE7C,GADI,CAACmC,GAAU,CAACA,EAAO,QACnBP,IAAiB,QAAaO,EAAO,eAAiBP,EAAc,OAExE,IAAMQ,EAAUjB,EAAW,QAAQ,IAAInB,CAAE,EACrCoC,IAAYR,IAAiB,QAAaQ,EAAQ,eAAiBR,KACrET,EAAW,QAAQ,OAAOnB,CAAE,EAC5BoC,EAAQ,QAAQH,CAAM,GAGpBC,GAAWX,EAAW,SAAS,SAC7B3B,EAAc2B,EAAW,OAAO,IAAM,OAAOvB,CAAE,GACjDD,EAAc,KAAMwB,EAAW,QAAS,SAAS,EAIrDY,EAAO,WAAW,MAAM,EAExB,IAAIE,EAAW,GACfrB,EAAmBe,GAAQ,CACzB,IAAMO,EAAUP,EAAK,IAAI/B,CAAE,EAE3B,GADI,CAACsC,GAAW,CAACA,EAAQ,QACrBV,IAAiB,QAAaU,EAAQ,eAAiBV,EAAc,OAAOG,EAChFM,EAAW,GACX,IAAMnB,EAAO,IAAI,IAAIa,CAAI,EACzB,OAAItB,GAAgB,EAClBS,EAAK,OAAOlB,CAAE,EAEdkB,EAAK,IAAIlB,EAAI,CAAE,GAAGsC,EAAS,OAAQ,EAAM,CAAC,EAErCpB,CACT,CAAC,EAEGmB,GAAY5B,EAAe,GAC7BkB,EAAgB3B,EAAImC,EAAO,YAAY,CAE3C,EACA,CAACR,EAAiBlB,EAAcO,CAAkB,CACpD,EAEMuB,KAAY,eAChB,CAACvC,EAAawC,EAAgBN,EAAU,KAA2B,CACjE,IAAMO,EAAOhB,EAAazB,CAAE,EAC5B,GAAI,CAACyC,EACH,OAAO,QAAQ,OACb,IAAI,MAAM,iCAAiC,OAAOzC,CAAE,CAAC,sBAAsB,CAC7E,EAGF,IAAMsC,EAAUvB,EAAgB,QAAQ,IAAIf,CAAE,EACxC6B,EAAWV,EAAW,QAAQ,IAAInB,CAAE,EAE1C,GACEsC,GAAS,QACTA,EAAQ,YAAcG,GACtBhE,GAAe6D,EAAQ,KAAME,CAAI,GACjCX,EAEA,OAAOA,EAAS,QAGdK,GAAWX,EAAW,SAAS,SACjCxB,EAAc,OAAOC,CAAE,EAAGuB,EAAW,OAAO,EAG1CM,IACFV,EAAW,QAAQ,OAAOnB,CAAE,EAC5B6B,EAAS,QAAQ,MAAS,GAG5B,IAAMC,EAAQV,EAAU,QAAQ,IAAIpB,CAAE,EAClC8B,IACF,aAAaA,CAAK,EAClBV,EAAU,QAAQ,OAAOpB,CAAE,GAG7B,IAAM4B,EAAe,EAAEP,EAAqB,QACxCqB,EACEC,EAAU,IAAI,QAAiBC,GAAW,CAC9CF,EAAWE,CACb,CAAC,EAEDzB,EAAW,QAAQ,IAAInB,EAAI,CAAE,QAAA2C,EAAS,QAASD,EAAU,aAAAd,CAAa,CAAC,EAEvE,IAAMiB,EACJP,GAAS,YACRzE,EAAU,GAAK,SAAS,yBAAyB,aAAe,SAAS,gBAAkB,SAAS,KACjG,SAAS,cACT,MAEN,OAAAmD,EAAmBe,GAAQ,CACzB,IAAMb,EAAO,IAAI,IAAIa,CAAI,EACzB,OAAAb,EAAK,IAAIlB,EAAI,CAAE,GAAAA,EAAI,UAAWyC,EAAM,OAAQ,GAAM,KAAAD,EAAM,aAAAZ,EAAc,UAAAiB,CAAU,CAAC,EAC1E3B,CACT,CAAC,EAEMyB,CACT,EACA,CAAClB,EAAcT,CAAkB,CACnC,EAEM8B,KAAO,eACX,CACE9C,KACG+C,IAEIR,EAAUvC,EAAI+C,EAAK,CAAC,EAAG,EAAI,EAEpC,CAACR,CAAS,CACZ,EAEMS,KAAQ,eACZ,CAAsBhD,EAASiC,IAA8B,CAC3DD,EAAWhC,EAAI,OAAWiC,EAAQ,EAAI,CACxC,EACA,CAACD,CAAU,CACb,EAEMiB,KAAW,eAAY,IAAM,CACjC,IAAMC,EAAW,MAAM,KAAK/B,EAAW,QAAQ,OAAO,CAAC,EAOvD,GANAA,EAAW,QAAQ,MAAM,EAErBI,EAAW,SAAS,SACtBxB,EAAc,KAAMwB,EAAW,QAAS,SAAS,EAG/Cd,GAAgB,EAAG,CACrB,QAAWqB,KAASV,EAAU,QAAQ,OAAO,EAAG,aAAaU,CAAK,EAClEV,EAAU,QAAQ,MAAM,EACxBJ,EAAmB,IAAM,IAAI,GAAK,CACpC,KAAO,CACL,OAAW,CAAChB,EAAImC,CAAM,IAAKpB,EAAgB,QACrCoB,EAAO,QACTR,EAAgB3B,EAAImC,EAAO,YAAY,EAI3CnB,EAAmBe,GAAQ,CACzB,IAAIoB,EAAU,GACRjC,EAAO,IAAI,IAAIa,CAAI,EACzB,OAAW,CAAC/B,EAAImC,CAAM,IAAKJ,EACrBI,EAAO,SACTjB,EAAK,IAAIlB,EAAI,CAAE,GAAGmC,EAAQ,OAAQ,EAAM,CAAC,EACzCgB,EAAU,IAGd,OAAOA,EAAUjC,EAAOa,CAC1B,CAAC,CACH,CAEA,QAAWrD,KAAKqC,EAAgB,QAAQ,OAAO,EAC7C,GAAIrC,EAAE,QAAUA,EAAE,UAAW,CAC3BA,EAAE,UAAU,MAAM,EAClB,KACF,CAGFwE,EAAS,QAAQ1B,GAAKA,EAAE,QAAQ,MAAS,CAAC,CAC5C,EAAG,CAACG,EAAiBlB,EAAcO,CAAkB,CAAC,EAEhDoC,KAAS,eACZpD,GAAgBe,EAAgB,QAAQ,IAAIf,CAAE,GAAG,QAAU,GAC5D,CAAC,CACH,EAEMqD,KAA0C,gBAC7C,CACCrE,EACAsE,IACG,CACH,IAAMC,EACJ,MAAM,QAAQvE,CAAU,EACnBA,EACDsE,EACA,CAAC,CAAE,GAAItE,EAAuB,UAAAsE,CAAU,CAAC,EACzC,CAAC,EAEDE,EAAQjC,EAAW,SAAS,QAAU3B,EAAc2B,EAAW,OAAO,EAAI,KAEhF,QAAWrC,KAAQqE,EAAO,CACxB,IAAI7B,EAAQd,EAAY,QAAQ,IAAI1B,EAAK,EAAE,EAQ3C,GAPKwC,IACHA,EAAQ,CAAC,EACTd,EAAY,QAAQ,IAAI1B,EAAK,GAAIwC,CAAK,GAExCA,EAAM,KAAKxC,EAAK,SAAS,EAGrBsE,GAASA,IAAU,OAAOtE,EAAK,EAAE,GAAK,CAAC6B,EAAgB,QAAQ,IAAI7B,EAAK,EAAE,GAAG,OAAQ,CACvF,IAAMsD,EAAOlC,EAAeiB,EAAW,SAAS,YAAarC,EAAK,EAAE,EACpEqD,EAAUrD,EAAK,GAAIsD,EAAM,EAAK,CAChC,CACF,CACF,GACA,CAACD,CAAS,CACZ,EAEMkB,KAAa,eACjB,CAACC,EAAuCC,IAA4C,CAClF,IAAMC,EAAM,MAAM,QAAQF,CAAO,EAAIA,EAAU,CAACA,CAAO,EAEvD,QAAW1D,KAAM4D,EAAK,CACpB,IAAMlC,EAAQd,EAAY,QAAQ,IAAIZ,CAAE,EACxC,GAAI,CAAC0B,EAAO,SAEZ,GAAIiC,EAAiB,CACnB,IAAME,EAAMnC,EAAM,YAAYiC,CAAe,EAI7C,GAHIE,IAAQ,IACVnC,EAAM,OAAOmC,EAAK,CAAC,EAEjBnC,EAAM,OAAS,EACjB,QAEJ,CAEAd,EAAY,QAAQ,OAAOZ,CAAE,EAE7B,IAAM8B,EAAQV,EAAU,QAAQ,IAAIpB,CAAE,EAClC8B,IACF,aAAaA,CAAK,EAClBV,EAAU,QAAQ,OAAOpB,CAAE,GAG7B,IAAMoC,EAAUjB,EAAW,QAAQ,IAAInB,CAAE,EACrCoC,IACFjB,EAAW,QAAQ,OAAOnB,CAAE,EAC5BoC,EAAQ,QAAQ,MAAS,GAGvBb,EAAW,SAAS,SAAW3B,EAAc2B,EAAW,OAAO,IAAM,OAAOvB,CAAE,GAChFD,EAAc,KAAMwB,EAAW,QAAS,SAAS,EAGnDP,EAAmBe,GAAQ,CACzB,GAAI,CAACA,EAAK,IAAI/B,CAAE,EAAG,OAAO+B,EAC1B,IAAMb,EAAO,IAAI,IAAIa,CAAI,EACzB,OAAAb,EAAK,OAAOlB,CAAE,EACPkB,CACT,CAAC,CACH,CACF,EACA,CAACF,CAAkB,CACrB,KAGA,aAAU,IAAM,CACd,GAAI,CAACM,GAAmB,CAACA,EAAgB,SAAW,CAACzD,EAAU,EAAG,OAElE,IAAMiG,EAAc,IAAM,CACxB,IAAMN,EAAQ5D,EAAc2B,EAAW,OAAO,EACxCwC,EAAgBhD,EAAgB,QAGtC,OAAW,CAACf,EAAImC,CAAM,IAAK4B,EACrB,OAAO/D,CAAE,IAAMwD,GAASrB,EAAO,QACjCH,EAAWhC,EAAI,OAAW,OAAW,EAAK,EAI9C,GAAIwD,EAAO,CACT,IAAMQ,EAAUR,EACZ,CAACO,EAAc,IAAIC,CAAO,GAAG,QAAUvC,EAAauC,CAAO,GAC7DzB,EAAUyB,EAAS1D,EAAeiB,EAAW,SAAS,YAAayC,CAAO,EAAG,EAAK,CAEtF,CACF,EAEA,OAAAF,EAAY,EAEZ,OAAO,iBAAiB,WAAYA,CAAW,EAC/C,OAAO,iBAAiB,aAAcA,CAAW,EAE1C,IAAM,CACX,OAAO,oBAAoB,WAAYA,CAAW,EAClD,OAAO,oBAAoB,aAAcA,CAAW,CACtD,CACF,EAAG,CACDxC,EACAG,EACAc,EACAP,CACF,CAAC,EAED,IAAMiC,KAAU,WACd,KAAO,CACL,SAAAZ,EACA,WAAAI,EACA,KAAAX,EACA,MAAAE,EACA,SAAAC,EACA,OAAAG,CACF,GACA,CAACC,EAAUI,EAAYX,EAAME,EAAOC,EAAUG,CAAM,CACtD,EAEA,SACE,OAAC7E,EAAoB,SAApB,CAA6B,MAAO0F,EACnC,oBAACzF,EAAmB,SAAnB,CAA4B,MAAOqC,EACjC,UAAAL,KACD,OAAC0D,GAAA,CACC,aAAcrD,EACd,MAAOmB,EACP,SAAUtB,EACZ,GACF,EACF,CAEJ,CAEA,SAASwD,GAAc,CACrB,aAAArD,EACA,MAAAmC,EACA,SAAAtC,CACF,EAIG,CACD,OAAIG,EAAa,OAAS,EAAU,QAGlC,mBACG,eAAM,KAAKA,EAAa,OAAO,EAAGsB,MACjC,OAACgC,GAAA,CAEC,OAAQhC,EACR,QAASa,EACT,SAAUtC,GAHL,GAAG,OAAOyB,EAAO,EAAE,CAAC,IAAIA,EAAO,YAAY,EAIlD,CACD,EACH,CAEJ,CAEA,IAAMgC,MAAgB,QAAK,SAAuB,CAChD,OAAAhC,EACA,QAAAiC,EACA,SAAA1D,CACF,EAIG,CACD,IAAM2D,KAAc,eACjBpC,GAAqBmC,EAAQjC,EAAO,GAAIA,EAAO,aAAcF,EAAQ,EAAI,EAC1E,CAACmC,EAASjC,EAAO,GAAIA,EAAO,YAAY,CAC1C,EAEMmC,EAAYnC,EAAO,UAEzB,SACE,OAAC,YAAS,SAAUzB,GAAY,KAC9B,mBAAC4D,EAAA,CACC,OAAQnC,EAAO,OACf,KAAMA,EAAO,KACb,MAAOkC,EACT,EACF,CAEJ,CAAC,EAYM,SAASpG,EACde,EACAsE,EACM,CACN,GAAM,CAAE,SAAAD,EAAU,WAAAI,CAAW,EAAIc,EAAgB,EAC3CC,EAAmBzF,GAAuBC,CAAU,KAE1D,aAAU,IAAM,CACd,GAAI,MAAM,QAAQwF,CAAgB,EAChC,OAAAnB,EAASmB,CAAgB,EAClB,IAAM,CACX,QAAWtF,KAAQsF,EACjBf,EAAWvE,EAAK,GAAIA,EAAK,SAA6C,CAE1E,EAGF,GAAIoE,EACF,OAAAD,EAASmB,EAAyBlB,CAAS,EACpC,IAAM,CACXG,EAAWe,EAAyBlB,CAA6C,CACnF,CAIJ,EAAG,CAACkB,EAAkBlB,EAAWD,EAAUI,CAAU,CAAC,CACxD,CAKO,SAAS7F,GAAqD,CACnE,OAAA6G,CACF,EAIG,CACD,OAAAxG,EAAiBwG,CAAM,EAChB,IACT,CAKO,SAASzG,GAIdgC,EAC+D,CAC/D,GAAM,CAAE,KAAA8C,EAAM,MAAAE,EAAO,OAAAI,CAAO,EAAImB,EAAgB,EAEhD,SAAO,WACL,KAAO,CACL,KAAM,IAAIxB,IACRD,EAAmB9C,EAAI,GAAG+C,CAAI,EAChC,MAAQd,GACNe,EAAMhD,EAAIiC,CAA0B,EACtC,OAAQ,IAAMmB,EAAOpD,CAAE,CACzB,GACA,CAAC8C,EAAME,EAAOI,EAAQpD,CAAE,CAC1B,CACF,CAKO,SAASjC,GAAeiC,EAAsB,CAEnD,SADe,cAAWxB,CAAkB,EAC9B,IAAIwB,CAAE,GAAG,QAAU,EACnC,CAEO,SAASlC,IAA0B,CACxC,OAAOyG,EAAgB,EAAE,QAC3B,CAEA,SAASA,GAAqC,CAC5C,IAAMG,KAAU,cAAWnG,CAAmB,EAC9C,GAAI,CAACmG,EACH,MAAM,IAAI,MAAM,qDAAqD,EAEvE,OAAOA,CACT","names":["index_exports","__export","ModalProvider","ModalRegistry","isBrowser","useCloseAll","useIsModalOpen","useModal","useRegisterModal","__toCommonJS","import_react","import_jsx_runtime","DEFAULT_ROUTING","DEFAULT_UNMOUNT_DELAY","ModalActionsContext","ModalActiveContext","isShallowEqual","a","b","keysA","keysB","k","useStableRegistrations","idOrModals","ref","item","i","getHashParts","rawHash","hash","anchor","query","formatHash","params","qs","getUrlModalId","config","param","setUrlModalId","id","forceMode","mode","url","updateParams","sp","getDefaultData","defaultData","children","unmountDelay","fallback","routing","registryRef","activeModals","setActiveModals","activeModalsRef","updateActiveModals","updater","next","pendingRef","timersRef","invocationCounterRef","resolvedRouting","routingRef","p","getComponent","stack","scheduleUnmount","invocationId","existing","timer","prev","closeModal","result","syncUrl","active","pending","didClose","current","openModal","data","comp","resolver","promise","resolve","prevFocus","open","args","close","closeAll","pendings","changed","isOpen","register","component","items","urlId","unregister","idOrIds","targetComponent","ids","idx","syncFromUrl","currentActive","modalId","actions","ModalRenderer","ModalSlotItem","onClose","handleClose","Component","useModalContext","stableIdOrModals","modals","context"]}
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use client";import{createContext as z,memo as Z,Suspense as ee,useCallback as y,useContext as G,useEffect as E,useMemo as L,useRef as v,useState as te}from"react";import{Fragment as ue,jsx as C,jsxs as ie}from"react/jsx-runtime";var k={strategy:"hash",param:"modal",historyMode:"push"},N=()=>typeof window<"u",ne=200,Y=z(null),J=z(new Map);function oe(t,e){if(Object.is(t,e))return!0;if(typeof t!="object"||t===null||typeof e!="object"||e===null)return!1;if(t instanceof Date&&e instanceof Date)return t.getTime()===e.getTime();if(t instanceof RegExp&&e instanceof RegExp)return t.source===e.source&&t.flags===e.flags;if(t instanceof Map||t instanceof Set||e instanceof Map||e instanceof Set)return!1;let s=Object.keys(t),a=Object.keys(e);return s.length!==a.length?!1:s.every(l=>Object.prototype.hasOwnProperty.call(e,l)&&t[l]===e[l])}function re(t){let e=v(t);return Array.isArray(t)&&Array.isArray(e.current)&&e.current.length===t.length&&e.current.every((s,a)=>s.id===t[a].id&&s.component===t[a].component)?e.current:(e.current=t,t)}function Q(t){let e=t.replace(/^#/,""),[s,a]=e.includes("?")?e.split("?",2):e.includes("=")?["",e]:[e,""];return{anchor:s,params:new URLSearchParams(a)}}function ae(t,e){let s=e.toString();return s?`#${t?`${t}?`:""}${s}`:t?`#${t}`:""}function b(t){if(!N()||!t||t.enabled===!1)return null;let e=t.param??k.param;return(t.strategy??k.strategy)==="query"?new URLSearchParams(window.location.search).get(e):Q(window.location.hash).params.get(e)}function O(t,e,s){if(!N()||!e||e.enabled===!1||b(e)===t)return;let a=s??e.historyMode??k.historyMode,l=e.param??k.param,p=new URL(window.location.href),x=I=>t?I.set(l,t):I.delete(l);if((e.strategy??k.strategy)==="query")x(p.searchParams);else{let{anchor:I,params:M}=Q(window.location.hash);x(M),p.hash=ae(I,M)}window.history[a==="push"?"pushState":"replaceState"](window.history.state,"",p.pathname+p.search+p.hash)}function B(t,e){if(t)return typeof t=="function"?t(e):Object.prototype.hasOwnProperty.call(t,e)?t[e]:void 0}function pe({children:t,unmountDelay:e=ne,fallback:s=null,routing:a}){let l=v(new Map),[p,x]=te(new Map),I=v(p),M=y(n=>{let o=n(I.current);return I.current=o,x(o),o},[]),R=v(new Map),T=v(new Map),W=v(0),A=L(()=>a?{...k,...a,enabled:a.enabled!==!1}:null,[a?.enabled,a?.strategy,a?.param,a?.historyMode,a?.defaultData]),c=v(A);c.current=A,E(()=>()=>{T.current.forEach(clearTimeout),T.current.clear(),R.current.forEach(n=>n.resolve(void 0)),R.current.clear()},[]);let P=y(n=>{let o=l.current.get(n);return o?.[o.length-1]},[]),U=y((n,o)=>{let u=T.current.get(n);u&&clearTimeout(u);let r;r=setTimeout(()=>{T.current.get(n)===r&&T.current.delete(n),M(d=>{let i=d.get(n);if(!i||i.isOpen||i.invocationId!==o)return d;let g=new Map(d);return g.delete(n),g})},e),T.current.set(n,r)},[e,M]),D=y((n,o,u,r=!0)=>{let d=I.current.get(n);if(!d||!d.isOpen||o!==void 0&&d.invocationId!==o)return;let i=R.current.get(n);i&&(o===void 0||i.invocationId===o)&&(R.current.delete(n),i.resolve(u)),r&&c.current?.enabled&&b(c.current)===String(n)&&O(null,c.current,"replace");let g=!1;M(f=>{let m=f.get(n);if(!m||!m.isOpen||o!==void 0&&m.invocationId!==o)return f;g=!0;let h=new Map(f);return e<=0?h.delete(n):h.set(n,{...m,isOpen:!1}),h}),g&&e>0&&U(n,d.invocationId)},[U,e,M]),w=y((n,o,u=!0)=>{let r=P(n);if(!r)return Promise.reject(new Error(`[react-modal-registry] Modal "${String(n)}" is not registered.`));let d=I.current.get(n),i=R.current.get(n);if(d?.isOpen&&d.component===r&&oe(d.data,o)&&i)return i.promise;u&&c.current?.enabled&&O(String(n),c.current),i&&(R.current.delete(n),i.resolve(void 0));let g=T.current.get(n);g&&(clearTimeout(g),T.current.delete(n));let f=++W.current,m,h=new Promise(S=>{m=S});return R.current.set(n,{promise:h,resolve:m,invocationId:f}),M(S=>{let _=new Map(S);return _.set(n,{id:n,component:r,isOpen:!0,data:o,invocationId:f}),_}),h},[P,M]),$=y((n,...o)=>w(n,o[0],!0),[w]),q=y((n,o)=>{D(n,void 0,o,!0)},[D]),V=y(()=>{let n=Array.from(R.current.values());if(R.current.clear(),c.current?.enabled&&O(null,c.current,"replace"),e<=0){for(let o of T.current.values())clearTimeout(o);T.current.clear(),M(()=>new Map)}else{for(let[o,u]of I.current)u.isOpen&&U(o,u.invocationId);M(o=>{let u=!1,r=new Map(o);for(let[d,i]of o)i.isOpen&&(r.set(d,{...i,isOpen:!1}),u=!0);return u?r:o})}n.forEach(o=>o.resolve(void 0))},[U,e,M]),H=y(n=>I.current.get(n)?.isOpen??!1,[]),K=y(((n,o)=>{let u=Array.isArray(n)?n:o?[{id:n,component:o}]:[],r=c.current?.enabled?b(c.current):null;for(let d of u){let i=l.current.get(d.id);if(i||(i=[],l.current.set(d.id,i)),i.push(d.component),r&&r===String(d.id)&&!I.current.get(d.id)?.isOpen){let g=B(c.current?.defaultData,d.id);w(d.id,g,!1)}}}),[w]),F=y((n,o)=>{let u=Array.isArray(n)?n:[n];for(let r of u){let d=l.current.get(r);if(!d)continue;if(o){let f=d.lastIndexOf(o);if(f!==-1&&d.splice(f,1),d.length>0)continue}l.current.delete(r);let i=T.current.get(r);i&&(clearTimeout(i),T.current.delete(r));let g=R.current.get(r);g&&(R.current.delete(r),g.resolve(void 0)),c.current?.enabled&&b(c.current)===String(r)&&O(null,c.current,"replace"),M(f=>{if(!f.has(r))return f;let m=new Map(f);return m.delete(r),m})}},[M]);E(()=>{if(!A||!A.enabled||!N())return;let n=()=>{let o=b(c.current),u=I.current;for(let[r,d]of u)String(r)!==o&&d.isOpen&&D(r,void 0,void 0,!1);if(o){let r=o;!u.get(r)?.isOpen&&P(r)&&w(r,B(c.current?.defaultData,r),!1)}};return n(),window.addEventListener("popstate",n),window.addEventListener("hashchange",n),()=>{window.removeEventListener("popstate",n),window.removeEventListener("hashchange",n)}},[A,P,w,D]);let X=L(()=>({register:K,unregister:F,open:$,close:q,closeAll:V,isOpen:H}),[K,F,$,q,V,H]);return C(Y.Provider,{value:X,children:ie(J.Provider,{value:p,children:[t,C(de,{activeModals:p,close:D,fallback:s})]})})}function de({activeModals:t,close:e,fallback:s}){return t.size===0?null:C(ue,{children:Array.from(t.values(),a=>C(se,{active:a,onClose:e,fallback:s},`${String(a.id)}:${a.invocationId}`))})}var se=Z(function({active:e,onClose:s,fallback:a}){let l=y(x=>s(e.id,e.invocationId,x,!0),[s,e.id,e.invocationId]),p=e.component;return C(ee,{fallback:a??null,children:C(p,{isOpen:e.isOpen,data:e.data,close:l})})});function le(t,e){let{register:s,unregister:a}=j(),l=re(t);E(()=>{if(Array.isArray(l))return s(l),()=>{for(let p of l)a(p.id,p.component)};if(e)return s(l,e),()=>{a(l,e)}},[l,e,s,a])}function Me({modals:t}){return le(t),null}function fe(t){let{open:e,close:s,isOpen:a}=j();return L(()=>({open:(...l)=>e(t,...l),close:l=>s(t,l),isOpen:()=>a(t)}),[e,s,a,t])}function Ie(t){return G(J).get(t)?.isOpen??!1}function ge(){return j().closeAll}function j(){let t=G(Y);if(!t)throw new Error("useModalContext must be used within <ModalProvider>");return t}export{pe as ModalProvider,Me as ModalRegistry,N as isBrowser,ge as useCloseAll,Ie as useIsModalOpen,fe as useModal,le as useRegisterModal};
1
+ "use client";import{createContext as z,memo as ee,Suspense as te,useCallback as y,useContext as G,useEffect as L,useMemo as F,useRef as v,useState as ne}from"react";import{Fragment as ce,jsx as C,jsxs as ue}from"react/jsx-runtime";var k={strategy:"hash",param:"modal",historyMode:"push"},S=()=>typeof window<"u",oe=200,Y=z(null),J=z(new Map);function re(t,e){if(Object.is(t,e))return!0;if(typeof t!="object"||t===null||typeof e!="object"||e===null)return!1;if(t instanceof Date&&e instanceof Date)return t.getTime()===e.getTime();if(t instanceof RegExp&&e instanceof RegExp)return t.source===e.source&&t.flags===e.flags;if(t instanceof Map||t instanceof Set||e instanceof Map||e instanceof Set)return!1;let s=Object.keys(t),d=Object.keys(e);return s.length!==d.length?!1:s.every(l=>Object.prototype.hasOwnProperty.call(e,l)&&t[l]===e[l])}function ae(t){let e=v(t);return Array.isArray(t)&&Array.isArray(e.current)&&e.current.length===t.length&&e.current.every((s,d)=>s.id===t[d].id&&s.component===t[d].component)?e.current:(e.current=t,t)}function Q(t){let e=t.replace(/^#/,""),[s,d]=e.includes("?")?e.split("?",2):e.includes("=")?["",e]:[e,""];return{anchor:s,params:new URLSearchParams(d)}}function de(t,e){let s=e.toString();return s?`#${t?`${t}?`:""}${s}`:t?`#${t}`:""}function D(t){if(!S()||!t||t.enabled===!1)return null;let e=t.param??k.param;return(t.strategy??k.strategy)==="query"?new URLSearchParams(window.location.search).get(e):Q(window.location.hash).params.get(e)}function O(t,e,s){if(!S()||!e||e.enabled===!1||D(e)===t)return;let d=s??e.historyMode??k.historyMode,l=e.param??k.param,p=new URL(window.location.href),x=M=>t?M.set(l,t):M.delete(l);if((e.strategy??k.strategy)==="query")x(p.searchParams);else{let{anchor:M,params:f}=Q(window.location.hash);x(f),p.hash=de(M,f)}window.history[d==="push"?"pushState":"replaceState"](window.history.state,"",p.pathname+p.search+p.hash)}function B(t,e){if(t)return typeof t=="function"?t(e):Object.prototype.hasOwnProperty.call(t,e)?t[e]:void 0}function Me({children:t,unmountDelay:e=oe,fallback:s=null,routing:d}){let l=v(new Map),[p,x]=ne(new Map),M=v(p),f=y(n=>{let o=n(M.current);return M.current=o,x(o),o},[]),m=v(new Map),g=v(new Map),W=v(0),A=F(()=>d?{...k,...d,enabled:d.enabled!==!1}:null,[d?.enabled,d?.strategy,d?.param,d?.historyMode,d?.defaultData]),c=v(A);c.current=A,L(()=>()=>{g.current.forEach(clearTimeout),g.current.clear(),m.current.forEach(n=>n.resolve(void 0)),m.current.clear()},[]);let P=y(n=>{let o=l.current.get(n);return o?.[o.length-1]},[]),U=y((n,o)=>{let u=g.current.get(n);u&&clearTimeout(u);let r;r=setTimeout(()=>{g.current.get(n)===r&&g.current.delete(n),f(a=>{let i=a.get(n);if(!i||i.isOpen||i.invocationId!==o)return a;let T=new Map(a);return T.delete(n),T})},e),g.current.set(n,r)},[e,f]),b=y((n,o,u,r=!0)=>{let a=M.current.get(n);if(!a||!a.isOpen||o!==void 0&&a.invocationId!==o)return;let i=m.current.get(n);i&&(o===void 0||i.invocationId===o)&&(m.current.delete(n),i.resolve(u)),r&&c.current?.enabled&&D(c.current)===String(n)&&O(null,c.current,"replace"),a.prevFocus?.focus();let T=!1;f(I=>{let R=I.get(n);if(!R||!R.isOpen||o!==void 0&&R.invocationId!==o)return I;T=!0;let h=new Map(I);return e<=0?h.delete(n):h.set(n,{...R,isOpen:!1}),h}),T&&e>0&&U(n,a.invocationId)},[U,e,f]),w=y((n,o,u=!0)=>{let r=P(n);if(!r)return Promise.reject(new Error(`[react-modal-registry] Modal "${String(n)}" is not registered.`));let a=M.current.get(n),i=m.current.get(n);if(a?.isOpen&&a.component===r&&re(a.data,o)&&i)return i.promise;u&&c.current?.enabled&&O(String(n),c.current),i&&(m.current.delete(n),i.resolve(void 0));let T=g.current.get(n);T&&(clearTimeout(T),g.current.delete(n));let I=++W.current,R,h=new Promise(E=>{R=E});m.current.set(n,{promise:h,resolve:R,invocationId:I});let Z=a?.prevFocus??(S()&&document.activeElement instanceof HTMLElement&&document.activeElement!==document.body?document.activeElement:null);return f(E=>{let _=new Map(E);return _.set(n,{id:n,component:r,isOpen:!0,data:o,invocationId:I,prevFocus:Z}),_}),h},[P,f]),j=y((n,...o)=>w(n,o[0],!0),[w]),H=y((n,o)=>{b(n,void 0,o,!0)},[b]),$=y(()=>{let n=Array.from(m.current.values());if(m.current.clear(),c.current?.enabled&&O(null,c.current,"replace"),e<=0){for(let o of g.current.values())clearTimeout(o);g.current.clear(),f(()=>new Map)}else{for(let[o,u]of M.current)u.isOpen&&U(o,u.invocationId);f(o=>{let u=!1,r=new Map(o);for(let[a,i]of o)i.isOpen&&(r.set(a,{...i,isOpen:!1}),u=!0);return u?r:o})}for(let o of M.current.values())if(o.isOpen&&o.prevFocus){o.prevFocus.focus();break}n.forEach(o=>o.resolve(void 0))},[U,e,f]),q=y(n=>M.current.get(n)?.isOpen??!1,[]),V=y(((n,o)=>{let u=Array.isArray(n)?n:o?[{id:n,component:o}]:[],r=c.current?.enabled?D(c.current):null;for(let a of u){let i=l.current.get(a.id);if(i||(i=[],l.current.set(a.id,i)),i.push(a.component),r&&r===String(a.id)&&!M.current.get(a.id)?.isOpen){let T=B(c.current?.defaultData,a.id);w(a.id,T,!1)}}}),[w]),K=y((n,o)=>{let u=Array.isArray(n)?n:[n];for(let r of u){let a=l.current.get(r);if(!a)continue;if(o){let I=a.lastIndexOf(o);if(I!==-1&&a.splice(I,1),a.length>0)continue}l.current.delete(r);let i=g.current.get(r);i&&(clearTimeout(i),g.current.delete(r));let T=m.current.get(r);T&&(m.current.delete(r),T.resolve(void 0)),c.current?.enabled&&D(c.current)===String(r)&&O(null,c.current,"replace"),f(I=>{if(!I.has(r))return I;let R=new Map(I);return R.delete(r),R})}},[f]);L(()=>{if(!A||!A.enabled||!S())return;let n=()=>{let o=D(c.current),u=M.current;for(let[r,a]of u)String(r)!==o&&a.isOpen&&b(r,void 0,void 0,!1);if(o){let r=o;!u.get(r)?.isOpen&&P(r)&&w(r,B(c.current?.defaultData,r),!1)}};return n(),window.addEventListener("popstate",n),window.addEventListener("hashchange",n),()=>{window.removeEventListener("popstate",n),window.removeEventListener("hashchange",n)}},[A,P,w,b]);let X=F(()=>({register:V,unregister:K,open:j,close:H,closeAll:$,isOpen:q}),[V,K,j,H,$,q]);return C(Y.Provider,{value:X,children:ue(J.Provider,{value:p,children:[t,C(se,{activeModals:p,close:b,fallback:s})]})})}function se({activeModals:t,close:e,fallback:s}){return t.size===0?null:C(ce,{children:Array.from(t.values(),d=>C(le,{active:d,onClose:e,fallback:s},`${String(d.id)}:${d.invocationId}`))})}var le=ee(function({active:e,onClose:s,fallback:d}){let l=y(x=>s(e.id,e.invocationId,x,!0),[s,e.id,e.invocationId]),p=e.component;return C(te,{fallback:d??null,children:C(p,{isOpen:e.isOpen,data:e.data,close:l})})});function ie(t,e){let{register:s,unregister:d}=N(),l=ae(t);L(()=>{if(Array.isArray(l))return s(l),()=>{for(let p of l)d(p.id,p.component)};if(e)return s(l,e),()=>{d(l,e)}},[l,e,s,d])}function fe({modals:t}){return ie(t),null}function Ie(t){let{open:e,close:s,isOpen:d}=N();return F(()=>({open:(...l)=>e(t,...l),close:l=>s(t,l),isOpen:()=>d(t)}),[e,s,d,t])}function Te(t){return G(J).get(t)?.isOpen??!1}function ge(){return N().closeAll}function N(){let t=G(Y);if(!t)throw new Error("useModalContext must be used within <ModalProvider>");return t}export{Me as ModalProvider,fe as ModalRegistry,S as isBrowser,ge as useCloseAll,Te as useIsModalOpen,Ie as useModal,ie as useRegisterModal};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["'use client'\n\nimport {\n createContext,\n memo,\n Suspense,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentType,\n type ReactNode\n} from 'react'\n\n/**\n * Canonical registry for modal payloads and return types via module augmentation (e.g., `env.d.ts` or `modals.d.ts`).\n *\n * @example\n * ```ts\n * declare module 'react-modal-registry' {\n * interface ModalRegistry {\n * confirmAction: { data: { itemId: string }; result: boolean }\n * simpleAlert: void\n * }\n * }\n * ```\n */\nexport interface ModalRegistry { }\n\nexport type RegisteredModalId = keyof ModalRegistry\nexport type ModalId = [RegisteredModalId] extends [never] ? string : RegisteredModalId\n\nexport type ModalData<TId extends ModalId> = TId extends keyof ModalRegistry\n ? 'data' extends keyof ModalRegistry[TId]\n ? ModalRegistry[TId]['data']\n : void\n : unknown\n\nexport type ModalResult<TId extends ModalId> = TId extends keyof ModalRegistry\n ? 'result' extends keyof ModalRegistry[TId]\n ? ModalRegistry[TId]['result']\n : void\n : unknown\n\n/**\n * Derives optional vs. required payload arguments based on `TData`.\n */\nexport type ModalDataArg<TData> = [TData] extends [never]\n ? []\n : [unknown] extends [TData]\n ? [data?: TData]\n : [TData] extends [void] | [undefined]\n ? [data?: TData]\n : undefined extends TData\n ? [data?: TData]\n : [data: TData]\n\nexport type ModalClose<TResult = void> = [TResult] extends [void]\n ? () => void\n : (result?: TResult) => void\n\n/**\n * Standard props passed to registered modal components.\n */\nexport interface ModalProps<TData = unknown, TResult = void> {\n isOpen: boolean\n data: TData\n close: ModalClose<TResult>\n}\n\nexport type ModalComponent<TData = unknown, TResult = void> = ComponentType<\n ModalProps<TData, TResult>\n>\n\nexport type UntypedModalComponent = ComponentType<ModalProps<never, unknown>>\n\nexport type RegisteredComponent<TId extends ModalId> =\n [RegisteredModalId] extends [never]\n ? ComponentType<ModalProps<never, unknown>>\n : ModalComponent<ModalData<TId>, ModalResult<TId>>\n\nexport interface ModalRegistration<TId extends ModalId = ModalId> {\n id: TId\n component: RegisteredComponent<TId>\n}\n\n/**\n * Imperative modal controller returned by `useModal(id)`.\n */\nexport interface UseModalReturn<TData = unknown, TResult = unknown> {\n open(...args: ModalDataArg<TData>): Promise<TResult | undefined>\n close(result?: TResult): void\n isOpen(): boolean\n}\n\nexport type CanonicalResult<TId extends ModalId, TResult = ModalResult<TId>> =\n [RegisteredModalId] extends [never] ? TResult : ModalResult<TId>\n\nexport interface ModalActionsValue {\n register<TId extends ModalId>(\n id: TId,\n component: RegisteredComponent<TId>\n ): void\n register(modals: readonly ModalRegistration[]): void\n unregister(idOrIds: ModalId | readonly ModalId[], targetComponent?: UntypedModalComponent): void\n open<TId extends ModalId, TResult = ModalResult<TId>>(\n id: TId,\n ...args: ModalDataArg<ModalData<TId>>\n ): Promise<CanonicalResult<TId, TResult> | undefined>\n close<TId extends ModalId>(id: TId, result?: ModalResult<TId>): void\n closeAll(): void\n isOpen(id: ModalId): boolean\n}\n\nexport type ModalDefaultData =\n | Record<string, unknown>\n | ((id: ModalId) => unknown)\n\nexport type ModalRoutingStrategy = 'hash' | 'query'\nexport type ModalHistoryMode = 'push' | 'replace'\n\nexport interface ModalRoutingConfig {\n enabled?: boolean\n strategy?: ModalRoutingStrategy\n param?: string\n historyMode?: ModalHistoryMode\n defaultData?: ModalDefaultData\n}\n\nexport interface ModalProviderProps {\n children: ReactNode\n unmountDelay?: number\n fallback?: ReactNode\n routing?: ModalRoutingConfig\n}\n\ninterface ActiveModal {\n id: ModalId\n component: UntypedModalComponent\n isOpen: boolean\n data: unknown\n invocationId: number\n}\n\nconst DEFAULT_ROUTING = {\n strategy: 'hash',\n param: 'modal',\n historyMode: 'push'\n} as const\n\nexport const isBrowser = (): boolean => typeof window !== 'undefined'\n\nconst DEFAULT_UNMOUNT_DELAY = 200\n\nconst ModalActionsContext = createContext<ModalActionsValue | null>(null)\nconst ModalActiveContext = createContext<ReadonlyMap<ModalId, ActiveModal>>(new Map())\n\nfunction isShallowEqual(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true\n if (typeof a !== 'object' || a === null || typeof b !== 'object' || b === null) return false\n if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime()\n if (a instanceof RegExp && b instanceof RegExp) return a.source === b.source && a.flags === b.flags\n if (a instanceof Map || a instanceof Set || b instanceof Map || b instanceof Set) return false\n const keysA = Object.keys(a)\n const keysB = Object.keys(b)\n if (keysA.length !== keysB.length) return false\n return keysA.every(\n k =>\n Object.prototype.hasOwnProperty.call(b, k) &&\n (a as Record<string, unknown>)[k] === (b as Record<string, unknown>)[k]\n )\n}\n\nfunction useStableRegistrations<T extends ModalId | readonly ModalRegistration[]>(\n idOrModals: T\n): T {\n const ref = useRef(idOrModals)\n if (\n Array.isArray(idOrModals) &&\n Array.isArray(ref.current) &&\n ref.current.length === idOrModals.length &&\n ref.current.every((item, i) => item.id === idOrModals[i].id && item.component === idOrModals[i].component)\n ) {\n return ref.current as T\n }\n ref.current = idOrModals\n return idOrModals\n}\n\nfunction getHashParts(rawHash: string): { anchor: string; params: URLSearchParams } {\n const hash = rawHash.replace(/^#/, '')\n const [anchor, query] = hash.includes('?')\n ? hash.split('?', 2)\n : hash.includes('=')\n ? ['', hash]\n : [hash, '']\n return { anchor, params: new URLSearchParams(query) }\n}\n\nfunction formatHash(anchor: string, params: URLSearchParams): string {\n const qs = params.toString()\n return qs ? `#${anchor ? `${anchor}?` : ''}${qs}` : (anchor ? `#${anchor}` : '')\n}\n\nfunction getUrlModalId(config?: ModalRoutingConfig | null): string | null {\n if (!isBrowser() || !config || config.enabled === false) return null\n const param = config.param ?? DEFAULT_ROUTING.param\n return (config.strategy ?? DEFAULT_ROUTING.strategy) === 'query'\n ? new URLSearchParams(window.location.search).get(param)\n : getHashParts(window.location.hash).params.get(param)\n}\n\nfunction setUrlModalId(\n id: string | null,\n config?: ModalRoutingConfig | null,\n forceMode?: ModalHistoryMode\n) {\n if (!isBrowser() || !config || config.enabled === false) return\n if (getUrlModalId(config) === id) return\n\n const mode = forceMode ?? config.historyMode ?? DEFAULT_ROUTING.historyMode\n const param = config.param ?? DEFAULT_ROUTING.param\n const url = new URL(window.location.href)\n const updateParams = (sp: URLSearchParams) => (id ? sp.set(param, id) : sp.delete(param))\n\n if ((config.strategy ?? DEFAULT_ROUTING.strategy) === 'query') {\n updateParams(url.searchParams)\n } else {\n const { anchor, params } = getHashParts(window.location.hash)\n updateParams(params)\n url.hash = formatHash(anchor, params)\n }\n\n window.history[mode === 'push' ? 'pushState' : 'replaceState'](\n window.history.state,\n '',\n url.pathname + url.search + url.hash\n )\n}\n\nfunction getDefaultData(defaultData: ModalDefaultData | undefined, id: ModalId): unknown {\n if (!defaultData) return undefined\n return typeof defaultData === 'function'\n ? defaultData(id)\n : Object.prototype.hasOwnProperty.call(defaultData, id)\n ? (defaultData as Record<string, unknown>)[id]\n : undefined\n}\n\n/**\n * Root provider hosting the modal registry, URL routing, lifecycle actions, and slot renderer.\n */\nexport function ModalProvider({\n children,\n unmountDelay = DEFAULT_UNMOUNT_DELAY,\n fallback = null,\n routing\n}: ModalProviderProps) {\n // Registry stack allows multiple components to register the same modal ID safely\n const registryRef = useRef<Map<ModalId, UntypedModalComponent[]>>(new Map())\n\n // Active modals currently open or animating out\n const [activeModals, setActiveModals] = useState<ReadonlyMap<ModalId, ActiveModal>>(new Map())\n const activeModalsRef = useRef(activeModals)\n\n const updateActiveModals = useCallback(\n (updater: (prev: ReadonlyMap<ModalId, ActiveModal>) => ReadonlyMap<ModalId, ActiveModal>) => {\n const next = updater(activeModalsRef.current)\n activeModalsRef.current = next\n setActiveModals(next)\n return next\n },\n []\n )\n\n const pendingRef = useRef<\n Map<ModalId, { promise: Promise<unknown>; resolve: (value: unknown) => void; invocationId: number }>\n >(new Map())\n const timersRef = useRef<Map<ModalId, ReturnType<typeof setTimeout>>>(new Map())\n const invocationCounterRef = useRef(0)\n\n const resolvedRouting = useMemo(\n () =>\n routing\n ? {\n ...DEFAULT_ROUTING,\n ...routing,\n enabled: routing.enabled !== false\n }\n : null,\n [\n routing?.enabled,\n routing?.strategy,\n routing?.param,\n routing?.historyMode,\n routing?.defaultData\n ]\n )\n const routingRef = useRef(resolvedRouting)\n routingRef.current = resolvedRouting\n\n useEffect(() => {\n return () => {\n timersRef.current.forEach(clearTimeout)\n timersRef.current.clear()\n pendingRef.current.forEach(p => p.resolve(undefined))\n pendingRef.current.clear()\n }\n }, [])\n\n const getComponent = useCallback((id: ModalId) => {\n const stack = registryRef.current.get(id)\n return stack?.[stack.length - 1]\n }, [])\n\n const scheduleUnmount = useCallback(\n (id: ModalId, invocationId: number) => {\n const existing = timersRef.current.get(id)\n if (existing) clearTimeout(existing)\n\n let timer: ReturnType<typeof setTimeout>\n timer = setTimeout(() => {\n if (timersRef.current.get(id) === timer) {\n timersRef.current.delete(id)\n }\n updateActiveModals(prev => {\n const item = prev.get(id)\n if (!item || item.isOpen || item.invocationId !== invocationId) return prev\n const next = new Map(prev)\n next.delete(id)\n return next\n })\n }, unmountDelay)\n timersRef.current.set(id, timer)\n },\n [unmountDelay, updateActiveModals]\n )\n\n const closeModal = useCallback(\n (id: ModalId, invocationId?: number, result?: unknown, syncUrl = true) => {\n const active = activeModalsRef.current.get(id)\n if (!active || !active.isOpen) return\n if (invocationId !== undefined && active.invocationId !== invocationId) return\n\n const pending = pendingRef.current.get(id)\n if (pending && (invocationId === undefined || pending.invocationId === invocationId)) {\n pendingRef.current.delete(id)\n pending.resolve(result)\n }\n\n if (syncUrl && routingRef.current?.enabled) {\n if (getUrlModalId(routingRef.current) === String(id)) {\n setUrlModalId(null, routingRef.current, 'replace')\n }\n }\n\n let didClose = false\n updateActiveModals(prev => {\n const current = prev.get(id)\n if (!current || !current.isOpen) return prev\n if (invocationId !== undefined && current.invocationId !== invocationId) return prev\n didClose = true\n const next = new Map(prev)\n if (unmountDelay <= 0) {\n next.delete(id)\n } else {\n next.set(id, { ...current, isOpen: false })\n }\n return next\n })\n\n if (didClose && unmountDelay > 0) {\n scheduleUnmount(id, active.invocationId)\n }\n },\n [scheduleUnmount, unmountDelay, updateActiveModals]\n )\n\n const openModal = useCallback(\n (id: ModalId, data?: unknown, syncUrl = true): Promise<unknown> => {\n const comp = getComponent(id)\n if (!comp) {\n return Promise.reject(\n new Error(`[react-modal-registry] Modal \"${String(id)}\" is not registered.`)\n )\n }\n\n const current = activeModalsRef.current.get(id)\n const existing = pendingRef.current.get(id)\n\n if (\n current?.isOpen &&\n current.component === comp &&\n isShallowEqual(current.data, data) &&\n existing\n ) {\n return existing.promise\n }\n\n if (syncUrl && routingRef.current?.enabled) {\n setUrlModalId(String(id), routingRef.current)\n }\n\n if (existing) {\n pendingRef.current.delete(id)\n existing.resolve(undefined)\n }\n\n const timer = timersRef.current.get(id)\n if (timer) {\n clearTimeout(timer)\n timersRef.current.delete(id)\n }\n\n const invocationId = ++invocationCounterRef.current\n let resolver!: (val: unknown) => void\n const promise = new Promise<unknown>(resolve => {\n resolver = resolve\n })\n\n pendingRef.current.set(id, { promise, resolve: resolver, invocationId })\n\n updateActiveModals(prev => {\n const next = new Map(prev)\n next.set(id, { id, component: comp, isOpen: true, data, invocationId })\n return next\n })\n\n return promise\n },\n [getComponent, updateActiveModals]\n )\n\n const open = useCallback(\n <TId extends ModalId, TResult = ModalResult<TId>>(\n id: TId,\n ...args: ModalDataArg<ModalData<TId>>\n ): Promise<CanonicalResult<TId, TResult> | undefined> => {\n return openModal(id, args[0], true) as Promise<CanonicalResult<TId, TResult> | undefined>\n },\n [openModal]\n )\n\n const close = useCallback(\n <TId extends ModalId>(id: TId, result?: ModalResult<TId>) => {\n closeModal(id, undefined, result, true)\n },\n [closeModal]\n )\n\n const closeAll = useCallback(() => {\n const pendings = Array.from(pendingRef.current.values())\n pendingRef.current.clear()\n\n if (routingRef.current?.enabled) {\n setUrlModalId(null, routingRef.current, 'replace')\n }\n\n if (unmountDelay <= 0) {\n for (const timer of timersRef.current.values()) clearTimeout(timer)\n timersRef.current.clear()\n updateActiveModals(() => new Map())\n } else {\n for (const [id, active] of activeModalsRef.current) {\n if (active.isOpen) {\n scheduleUnmount(id, active.invocationId)\n }\n }\n\n updateActiveModals(prev => {\n let changed = false\n const next = new Map(prev)\n for (const [id, active] of prev) {\n if (active.isOpen) {\n next.set(id, { ...active, isOpen: false })\n changed = true\n }\n }\n return changed ? next : prev\n })\n }\n\n pendings.forEach(p => p.resolve(undefined))\n }, [scheduleUnmount, unmountDelay, updateActiveModals])\n\n const isOpen = useCallback(\n (id: ModalId) => activeModalsRef.current.get(id)?.isOpen ?? false,\n []\n )\n\n const register: ModalActionsValue['register'] = useCallback(\n ((\n idOrModals: ModalId | readonly ModalRegistration[],\n component?: UntypedModalComponent\n ) => {\n const items: readonly { id: ModalId; component: UntypedModalComponent }[] =\n Array.isArray(idOrModals)\n ? (idOrModals as unknown as readonly { id: ModalId; component: UntypedModalComponent }[])\n : component\n ? [{ id: idOrModals as ModalId, component }]\n : []\n\n const urlId = routingRef.current?.enabled ? getUrlModalId(routingRef.current) : null\n\n for (const item of items) {\n let stack = registryRef.current.get(item.id)\n if (!stack) {\n stack = []\n registryRef.current.set(item.id, stack)\n }\n stack.push(item.component)\n\n // If URL routing is active and specifies this modal, open it immediately\n if (urlId && urlId === String(item.id) && !activeModalsRef.current.get(item.id)?.isOpen) {\n const data = getDefaultData(routingRef.current?.defaultData, item.id)\n openModal(item.id, data, false)\n }\n }\n }) as ModalActionsValue['register'],\n [openModal]\n )\n\n const unregister = useCallback(\n (idOrIds: ModalId | readonly ModalId[], targetComponent?: UntypedModalComponent) => {\n const ids = Array.isArray(idOrIds) ? idOrIds : [idOrIds]\n\n for (const id of ids) {\n const stack = registryRef.current.get(id)\n if (!stack) continue\n\n if (targetComponent) {\n const idx = stack.lastIndexOf(targetComponent)\n if (idx !== -1) {\n stack.splice(idx, 1)\n }\n if (stack.length > 0) {\n continue\n }\n }\n\n registryRef.current.delete(id)\n\n const timer = timersRef.current.get(id)\n if (timer) {\n clearTimeout(timer)\n timersRef.current.delete(id)\n }\n\n const pending = pendingRef.current.get(id)\n if (pending) {\n pendingRef.current.delete(id)\n pending.resolve(undefined)\n }\n\n if (routingRef.current?.enabled && getUrlModalId(routingRef.current) === String(id)) {\n setUrlModalId(null, routingRef.current, 'replace')\n }\n\n updateActiveModals(prev => {\n if (!prev.has(id)) return prev\n const next = new Map(prev)\n next.delete(id)\n return next\n })\n }\n },\n [updateActiveModals]\n )\n\n // Two-way URL synchronization listener\n useEffect(() => {\n if (!resolvedRouting || !resolvedRouting.enabled || !isBrowser()) return\n\n const syncFromUrl = () => {\n const urlId = getUrlModalId(routingRef.current)\n const currentActive = activeModalsRef.current\n\n // Dismiss active modal that does not match urlId\n for (const [id, active] of currentActive) {\n if (String(id) !== urlId && active.isOpen) {\n closeModal(id, undefined, undefined, false)\n }\n }\n\n if (urlId) {\n const modalId = urlId as ModalId\n if (!currentActive.get(modalId)?.isOpen && getComponent(modalId)) {\n openModal(modalId, getDefaultData(routingRef.current?.defaultData, modalId), false)\n }\n }\n }\n\n syncFromUrl()\n\n window.addEventListener('popstate', syncFromUrl)\n window.addEventListener('hashchange', syncFromUrl)\n\n return () => {\n window.removeEventListener('popstate', syncFromUrl)\n window.removeEventListener('hashchange', syncFromUrl)\n }\n }, [\n resolvedRouting,\n getComponent,\n openModal,\n closeModal\n ])\n\n const actions = useMemo<ModalActionsValue>(\n () => ({\n register,\n unregister,\n open,\n close,\n closeAll,\n isOpen\n }),\n [register, unregister, open, close, closeAll, isOpen]\n )\n\n return (\n <ModalActionsContext.Provider value={actions}>\n <ModalActiveContext.Provider value={activeModals}>\n {children}\n <ModalRenderer\n activeModals={activeModals}\n close={closeModal}\n fallback={fallback}\n />\n </ModalActiveContext.Provider>\n </ModalActionsContext.Provider>\n )\n}\n\nfunction ModalRenderer({\n activeModals,\n close,\n fallback\n}: {\n activeModals: ReadonlyMap<ModalId, ActiveModal>\n close: (id: ModalId, invocationId: number, result?: unknown, syncUrl?: boolean) => void\n fallback?: ReactNode\n}) {\n if (activeModals.size === 0) return null\n\n return (\n <>\n {Array.from(activeModals.values(), active => (\n <ModalSlotItem\n key={`${String(active.id)}:${active.invocationId}`}\n active={active}\n onClose={close}\n fallback={fallback}\n />\n ))}\n </>\n )\n}\n\nconst ModalSlotItem = memo(function ModalSlotItem({\n active,\n onClose,\n fallback\n}: {\n active: ActiveModal\n onClose: (id: ModalId, invocationId: number, result?: unknown, syncUrl?: boolean) => void\n fallback?: ReactNode\n}) {\n const handleClose = useCallback(\n (result?: unknown) => onClose(active.id, active.invocationId, result, true),\n [onClose, active.id, active.invocationId]\n )\n\n const Component = active.component\n\n return (\n <Suspense fallback={fallback ?? null}>\n <Component\n isOpen={active.isOpen}\n data={active.data as never}\n close={handleClose}\n />\n </Suspense>\n )\n})\n\n/**\n * Registers one or more modals for the lifetime of the calling component.\n */\nexport function useRegisterModal<TId extends ModalId>(\n id: TId,\n component: RegisteredComponent<TId>\n): void\nexport function useRegisterModal<const TIds extends readonly ModalId[]>(modals: {\n [K in keyof TIds]: ModalRegistration<TIds[K]>\n} | readonly ModalRegistration[]): void\nexport function useRegisterModal<TId extends ModalId>(\n idOrModals: TId | readonly ModalRegistration[],\n component?: RegisteredComponent<TId>\n): void {\n const { register, unregister } = useModalContext()\n const stableIdOrModals = useStableRegistrations(idOrModals)\n\n useEffect(() => {\n if (Array.isArray(stableIdOrModals)) {\n register(stableIdOrModals)\n return () => {\n for (const item of stableIdOrModals) {\n unregister(item.id, item.component as unknown as UntypedModalComponent)\n }\n }\n }\n\n if (component) {\n register(stableIdOrModals as TId, component)\n return () => {\n unregister(stableIdOrModals as TId, component as unknown as UntypedModalComponent)\n }\n }\n\n return undefined\n }, [stableIdOrModals, component, register, unregister])\n}\n\n/**\n * Declarative component for mounting static modal batches at application roots.\n */\nexport function ModalRegistry<const TIds extends readonly ModalId[]>({\n modals\n}: {\n modals: {\n [K in keyof TIds]: ModalRegistration<TIds[K]>\n } | readonly ModalRegistration[]\n}) {\n useRegisterModal(modals)\n return null\n}\n\n/**\n * Returns typed controls (`open`, `close`, `isOpen`) for a modal ID.\n */\nexport function useModal<\n TId extends ModalId,\n TResult = ModalResult<TId>\n>(\n id: TId\n): UseModalReturn<ModalData<TId>, CanonicalResult<TId, TResult>> {\n const { open, close, isOpen } = useModalContext()\n\n return useMemo<UseModalReturn<ModalData<TId>, CanonicalResult<TId, TResult>>>(\n () => ({\n open: (...args: ModalDataArg<ModalData<TId>>) =>\n open<TId, TResult>(id, ...args),\n close: (result?: CanonicalResult<TId, TResult>) =>\n close(id, result as ModalResult<TId>),\n isOpen: () => isOpen(id)\n }),\n [open, close, isOpen, id]\n )\n}\n\n/**\n * Reactively subscribes to whether a modal is currently open.\n */\nexport function useIsModalOpen(id: ModalId): boolean {\n const active = useContext(ModalActiveContext)\n return active.get(id)?.isOpen ?? false\n}\n\nexport function useCloseAll(): () => void {\n return useModalContext().closeAll\n}\n\nfunction useModalContext(): ModalActionsValue {\n const context = useContext(ModalActionsContext)\n if (!context) {\n throw new Error('useModalContext must be used within <ModalProvider>')\n }\n return context\n}\n"],"mappings":"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","names":["createContext","memo","Suspense","useCallback","useContext","useEffect","useMemo","useRef","useState","Fragment","jsx","jsxs","DEFAULT_ROUTING","isBrowser","DEFAULT_UNMOUNT_DELAY","ModalActionsContext","ModalActiveContext","isShallowEqual","a","b","keysA","keysB","k","useStableRegistrations","idOrModals","ref","item","i","getHashParts","rawHash","hash","anchor","query","formatHash","params","qs","getUrlModalId","config","param","setUrlModalId","id","forceMode","mode","url","updateParams","sp","getDefaultData","defaultData","ModalProvider","children","unmountDelay","fallback","routing","registryRef","activeModals","setActiveModals","activeModalsRef","updateActiveModals","updater","next","pendingRef","timersRef","invocationCounterRef","resolvedRouting","routingRef","p","getComponent","stack","scheduleUnmount","invocationId","existing","timer","prev","closeModal","result","syncUrl","active","pending","didClose","current","openModal","data","comp","resolver","promise","resolve","open","args","close","closeAll","pendings","changed","isOpen","register","component","items","urlId","unregister","idOrIds","targetComponent","ids","idx","syncFromUrl","currentActive","modalId","actions","ModalRenderer","ModalSlotItem","onClose","handleClose","Component","useRegisterModal","useModalContext","stableIdOrModals","ModalRegistry","modals","useModal","useIsModalOpen","useCloseAll","context"]}
1
+ {"version":3,"sources":["../src/index.tsx"],"sourcesContent":["'use client'\n\nimport {\n createContext,\n memo,\n Suspense,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ComponentType,\n type ReactNode\n} from 'react'\n\n/**\n * Canonical registry for modal payloads and return types via module augmentation (e.g., `env.d.ts` or `modals.d.ts`).\n *\n * @example\n * ```ts\n * declare module 'react-modal-registry' {\n * interface ModalRegistry {\n * confirmAction: { data: { itemId: string }; result: boolean }\n * simpleAlert: void\n * }\n * }\n * ```\n */\nexport interface ModalRegistry { }\n\nexport type RegisteredModalId = keyof ModalRegistry\nexport type ModalId = [RegisteredModalId] extends [never] ? string : RegisteredModalId\n\nexport type ModalData<TId extends ModalId> = TId extends keyof ModalRegistry\n ? 'data' extends keyof ModalRegistry[TId]\n ? ModalRegistry[TId]['data']\n : void\n : unknown\n\nexport type ModalResult<TId extends ModalId> = TId extends keyof ModalRegistry\n ? 'result' extends keyof ModalRegistry[TId]\n ? ModalRegistry[TId]['result']\n : void\n : unknown\n\n/**\n * Derives optional vs. required payload arguments based on `TData`.\n */\nexport type ModalDataArg<TData> = [TData] extends [never]\n ? []\n : [unknown] extends [TData]\n ? [data?: TData]\n : [TData] extends [void] | [undefined]\n ? [data?: TData]\n : undefined extends TData\n ? [data?: TData]\n : [data: TData]\n\nexport type ModalClose<TResult = void> = [TResult] extends [void]\n ? () => void\n : (result?: TResult) => void\n\n/**\n * Standard props passed to registered modal components.\n */\nexport interface ModalProps<TData = unknown, TResult = void> {\n isOpen: boolean\n data: TData\n close: ModalClose<TResult>\n}\n\nexport type ModalComponent<TData = unknown, TResult = void> = ComponentType<\n ModalProps<TData, TResult>\n>\n\nexport type UntypedModalComponent = ComponentType<ModalProps<never, unknown>>\n\nexport type RegisteredComponent<TId extends ModalId> =\n [RegisteredModalId] extends [never]\n ? ComponentType<ModalProps<never, unknown>>\n : ModalComponent<ModalData<TId>, ModalResult<TId>>\n\nexport interface ModalRegistration<TId extends ModalId = ModalId> {\n id: TId\n component: RegisteredComponent<TId>\n}\n\n/**\n * Imperative modal controller returned by `useModal(id)`.\n */\nexport interface UseModalReturn<TData = unknown, TResult = unknown> {\n open(...args: ModalDataArg<TData>): Promise<TResult | undefined>\n close(result?: TResult): void\n isOpen(): boolean\n}\n\nexport type CanonicalResult<TId extends ModalId, TResult = ModalResult<TId>> =\n [RegisteredModalId] extends [never] ? TResult : ModalResult<TId>\n\nexport interface ModalActionsValue {\n register<TId extends ModalId>(\n id: TId,\n component: RegisteredComponent<TId>\n ): void\n register(modals: readonly ModalRegistration[]): void\n unregister(idOrIds: ModalId | readonly ModalId[], targetComponent?: UntypedModalComponent): void\n open<TId extends ModalId, TResult = ModalResult<TId>>(\n id: TId,\n ...args: ModalDataArg<ModalData<TId>>\n ): Promise<CanonicalResult<TId, TResult> | undefined>\n close<TId extends ModalId>(id: TId, result?: ModalResult<TId>): void\n closeAll(): void\n isOpen(id: ModalId): boolean\n}\n\nexport type ModalDefaultData =\n | Record<string, unknown>\n | ((id: ModalId) => unknown)\n\nexport type ModalRoutingStrategy = 'hash' | 'query'\nexport type ModalHistoryMode = 'push' | 'replace'\n\nexport interface ModalRoutingConfig {\n enabled?: boolean\n strategy?: ModalRoutingStrategy\n param?: string\n historyMode?: ModalHistoryMode\n defaultData?: ModalDefaultData\n}\n\nexport interface ModalProviderProps {\n children: ReactNode\n unmountDelay?: number\n fallback?: ReactNode\n routing?: ModalRoutingConfig\n}\n\ninterface ActiveModal {\n id: ModalId\n component: UntypedModalComponent\n isOpen: boolean\n data: unknown\n invocationId: number\n prevFocus?: HTMLElement | null\n}\n\nconst DEFAULT_ROUTING = {\n strategy: 'hash',\n param: 'modal',\n historyMode: 'push'\n} as const\n\nexport const isBrowser = (): boolean => typeof window !== 'undefined'\n\nconst DEFAULT_UNMOUNT_DELAY = 200\n\nconst ModalActionsContext = createContext<ModalActionsValue | null>(null)\nconst ModalActiveContext = createContext<ReadonlyMap<ModalId, ActiveModal>>(new Map())\n\nfunction isShallowEqual(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true\n if (typeof a !== 'object' || a === null || typeof b !== 'object' || b === null) return false\n if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime()\n if (a instanceof RegExp && b instanceof RegExp) return a.source === b.source && a.flags === b.flags\n if (a instanceof Map || a instanceof Set || b instanceof Map || b instanceof Set) return false\n const keysA = Object.keys(a)\n const keysB = Object.keys(b)\n if (keysA.length !== keysB.length) return false\n return keysA.every(\n k =>\n Object.prototype.hasOwnProperty.call(b, k) &&\n (a as Record<string, unknown>)[k] === (b as Record<string, unknown>)[k]\n )\n}\n\nfunction useStableRegistrations<T extends ModalId | readonly ModalRegistration[]>(\n idOrModals: T\n): T {\n const ref = useRef(idOrModals)\n if (\n Array.isArray(idOrModals) &&\n Array.isArray(ref.current) &&\n ref.current.length === idOrModals.length &&\n ref.current.every((item, i) => item.id === idOrModals[i].id && item.component === idOrModals[i].component)\n ) {\n return ref.current as T\n }\n ref.current = idOrModals\n return idOrModals\n}\n\nfunction getHashParts(rawHash: string): { anchor: string; params: URLSearchParams } {\n const hash = rawHash.replace(/^#/, '')\n const [anchor, query] = hash.includes('?')\n ? hash.split('?', 2)\n : hash.includes('=')\n ? ['', hash]\n : [hash, '']\n return { anchor, params: new URLSearchParams(query) }\n}\n\nfunction formatHash(anchor: string, params: URLSearchParams): string {\n const qs = params.toString()\n return qs ? `#${anchor ? `${anchor}?` : ''}${qs}` : (anchor ? `#${anchor}` : '')\n}\n\nfunction getUrlModalId(config?: ModalRoutingConfig | null): string | null {\n if (!isBrowser() || !config || config.enabled === false) return null\n const param = config.param ?? DEFAULT_ROUTING.param\n return (config.strategy ?? DEFAULT_ROUTING.strategy) === 'query'\n ? new URLSearchParams(window.location.search).get(param)\n : getHashParts(window.location.hash).params.get(param)\n}\n\nfunction setUrlModalId(\n id: string | null,\n config?: ModalRoutingConfig | null,\n forceMode?: ModalHistoryMode\n) {\n if (!isBrowser() || !config || config.enabled === false) return\n if (getUrlModalId(config) === id) return\n\n const mode = forceMode ?? config.historyMode ?? DEFAULT_ROUTING.historyMode\n const param = config.param ?? DEFAULT_ROUTING.param\n const url = new URL(window.location.href)\n const updateParams = (sp: URLSearchParams) => (id ? sp.set(param, id) : sp.delete(param))\n\n if ((config.strategy ?? DEFAULT_ROUTING.strategy) === 'query') {\n updateParams(url.searchParams)\n } else {\n const { anchor, params } = getHashParts(window.location.hash)\n updateParams(params)\n url.hash = formatHash(anchor, params)\n }\n\n window.history[mode === 'push' ? 'pushState' : 'replaceState'](\n window.history.state,\n '',\n url.pathname + url.search + url.hash\n )\n}\n\nfunction getDefaultData(defaultData: ModalDefaultData | undefined, id: ModalId): unknown {\n if (!defaultData) return undefined\n return typeof defaultData === 'function'\n ? defaultData(id)\n : Object.prototype.hasOwnProperty.call(defaultData, id)\n ? (defaultData as Record<string, unknown>)[id]\n : undefined\n}\n\n/**\n * Root provider hosting the modal registry, URL routing, lifecycle actions, and slot renderer.\n */\nexport function ModalProvider({\n children,\n unmountDelay = DEFAULT_UNMOUNT_DELAY,\n fallback = null,\n routing\n}: ModalProviderProps) {\n // Registry stack allows multiple components to register the same modal ID safely\n const registryRef = useRef<Map<ModalId, UntypedModalComponent[]>>(new Map())\n\n // Active modals currently open or animating out\n const [activeModals, setActiveModals] = useState<ReadonlyMap<ModalId, ActiveModal>>(new Map())\n const activeModalsRef = useRef(activeModals)\n\n const updateActiveModals = useCallback(\n (updater: (prev: ReadonlyMap<ModalId, ActiveModal>) => ReadonlyMap<ModalId, ActiveModal>) => {\n const next = updater(activeModalsRef.current)\n activeModalsRef.current = next\n setActiveModals(next)\n return next\n },\n []\n )\n\n const pendingRef = useRef<\n Map<ModalId, { promise: Promise<unknown>; resolve: (value: unknown) => void; invocationId: number }>\n >(new Map())\n const timersRef = useRef<Map<ModalId, ReturnType<typeof setTimeout>>>(new Map())\n const invocationCounterRef = useRef(0)\n\n const resolvedRouting = useMemo(\n () =>\n routing\n ? {\n ...DEFAULT_ROUTING,\n ...routing,\n enabled: routing.enabled !== false\n }\n : null,\n [\n routing?.enabled,\n routing?.strategy,\n routing?.param,\n routing?.historyMode,\n routing?.defaultData\n ]\n )\n const routingRef = useRef(resolvedRouting)\n routingRef.current = resolvedRouting\n\n useEffect(() => {\n return () => {\n timersRef.current.forEach(clearTimeout)\n timersRef.current.clear()\n pendingRef.current.forEach(p => p.resolve(undefined))\n pendingRef.current.clear()\n }\n }, [])\n\n const getComponent = useCallback((id: ModalId) => {\n const stack = registryRef.current.get(id)\n return stack?.[stack.length - 1]\n }, [])\n\n const scheduleUnmount = useCallback(\n (id: ModalId, invocationId: number) => {\n const existing = timersRef.current.get(id)\n if (existing) clearTimeout(existing)\n\n let timer: ReturnType<typeof setTimeout>\n timer = setTimeout(() => {\n if (timersRef.current.get(id) === timer) {\n timersRef.current.delete(id)\n }\n updateActiveModals(prev => {\n const item = prev.get(id)\n if (!item || item.isOpen || item.invocationId !== invocationId) return prev\n const next = new Map(prev)\n next.delete(id)\n return next\n })\n }, unmountDelay)\n timersRef.current.set(id, timer)\n },\n [unmountDelay, updateActiveModals]\n )\n\n const closeModal = useCallback(\n (id: ModalId, invocationId?: number, result?: unknown, syncUrl = true) => {\n const active = activeModalsRef.current.get(id)\n if (!active || !active.isOpen) return\n if (invocationId !== undefined && active.invocationId !== invocationId) return\n\n const pending = pendingRef.current.get(id)\n if (pending && (invocationId === undefined || pending.invocationId === invocationId)) {\n pendingRef.current.delete(id)\n pending.resolve(result)\n }\n\n if (syncUrl && routingRef.current?.enabled) {\n if (getUrlModalId(routingRef.current) === String(id)) {\n setUrlModalId(null, routingRef.current, 'replace')\n }\n }\n\n active.prevFocus?.focus()\n\n let didClose = false\n updateActiveModals(prev => {\n const current = prev.get(id)\n if (!current || !current.isOpen) return prev\n if (invocationId !== undefined && current.invocationId !== invocationId) return prev\n didClose = true\n const next = new Map(prev)\n if (unmountDelay <= 0) {\n next.delete(id)\n } else {\n next.set(id, { ...current, isOpen: false })\n }\n return next\n })\n\n if (didClose && unmountDelay > 0) {\n scheduleUnmount(id, active.invocationId)\n }\n },\n [scheduleUnmount, unmountDelay, updateActiveModals]\n )\n\n const openModal = useCallback(\n (id: ModalId, data?: unknown, syncUrl = true): Promise<unknown> => {\n const comp = getComponent(id)\n if (!comp) {\n return Promise.reject(\n new Error(`[react-modal-registry] Modal \"${String(id)}\" is not registered.`)\n )\n }\n\n const current = activeModalsRef.current.get(id)\n const existing = pendingRef.current.get(id)\n\n if (\n current?.isOpen &&\n current.component === comp &&\n isShallowEqual(current.data, data) &&\n existing\n ) {\n return existing.promise\n }\n\n if (syncUrl && routingRef.current?.enabled) {\n setUrlModalId(String(id), routingRef.current)\n }\n\n if (existing) {\n pendingRef.current.delete(id)\n existing.resolve(undefined)\n }\n\n const timer = timersRef.current.get(id)\n if (timer) {\n clearTimeout(timer)\n timersRef.current.delete(id)\n }\n\n const invocationId = ++invocationCounterRef.current\n let resolver!: (val: unknown) => void\n const promise = new Promise<unknown>(resolve => {\n resolver = resolve\n })\n\n pendingRef.current.set(id, { promise, resolve: resolver, invocationId })\n\n const prevFocus =\n current?.prevFocus ??\n (isBrowser() && document.activeElement instanceof HTMLElement && document.activeElement !== document.body\n ? document.activeElement\n : null)\n\n updateActiveModals(prev => {\n const next = new Map(prev)\n next.set(id, { id, component: comp, isOpen: true, data, invocationId, prevFocus })\n return next\n })\n\n return promise\n },\n [getComponent, updateActiveModals]\n )\n\n const open = useCallback(\n <TId extends ModalId, TResult = ModalResult<TId>>(\n id: TId,\n ...args: ModalDataArg<ModalData<TId>>\n ): Promise<CanonicalResult<TId, TResult> | undefined> => {\n return openModal(id, args[0], true) as Promise<CanonicalResult<TId, TResult> | undefined>\n },\n [openModal]\n )\n\n const close = useCallback(\n <TId extends ModalId>(id: TId, result?: ModalResult<TId>) => {\n closeModal(id, undefined, result, true)\n },\n [closeModal]\n )\n\n const closeAll = useCallback(() => {\n const pendings = Array.from(pendingRef.current.values())\n pendingRef.current.clear()\n\n if (routingRef.current?.enabled) {\n setUrlModalId(null, routingRef.current, 'replace')\n }\n\n if (unmountDelay <= 0) {\n for (const timer of timersRef.current.values()) clearTimeout(timer)\n timersRef.current.clear()\n updateActiveModals(() => new Map())\n } else {\n for (const [id, active] of activeModalsRef.current) {\n if (active.isOpen) {\n scheduleUnmount(id, active.invocationId)\n }\n }\n\n updateActiveModals(prev => {\n let changed = false\n const next = new Map(prev)\n for (const [id, active] of prev) {\n if (active.isOpen) {\n next.set(id, { ...active, isOpen: false })\n changed = true\n }\n }\n return changed ? next : prev\n })\n }\n\n for (const a of activeModalsRef.current.values()) {\n if (a.isOpen && a.prevFocus) {\n a.prevFocus.focus()\n break\n }\n }\n\n pendings.forEach(p => p.resolve(undefined))\n }, [scheduleUnmount, unmountDelay, updateActiveModals])\n\n const isOpen = useCallback(\n (id: ModalId) => activeModalsRef.current.get(id)?.isOpen ?? false,\n []\n )\n\n const register: ModalActionsValue['register'] = useCallback(\n ((\n idOrModals: ModalId | readonly ModalRegistration[],\n component?: UntypedModalComponent\n ) => {\n const items: readonly { id: ModalId; component: UntypedModalComponent }[] =\n Array.isArray(idOrModals)\n ? (idOrModals as unknown as readonly { id: ModalId; component: UntypedModalComponent }[])\n : component\n ? [{ id: idOrModals as ModalId, component }]\n : []\n\n const urlId = routingRef.current?.enabled ? getUrlModalId(routingRef.current) : null\n\n for (const item of items) {\n let stack = registryRef.current.get(item.id)\n if (!stack) {\n stack = []\n registryRef.current.set(item.id, stack)\n }\n stack.push(item.component)\n\n // If URL routing is active and specifies this modal, open it immediately\n if (urlId && urlId === String(item.id) && !activeModalsRef.current.get(item.id)?.isOpen) {\n const data = getDefaultData(routingRef.current?.defaultData, item.id)\n openModal(item.id, data, false)\n }\n }\n }) as ModalActionsValue['register'],\n [openModal]\n )\n\n const unregister = useCallback(\n (idOrIds: ModalId | readonly ModalId[], targetComponent?: UntypedModalComponent) => {\n const ids = Array.isArray(idOrIds) ? idOrIds : [idOrIds]\n\n for (const id of ids) {\n const stack = registryRef.current.get(id)\n if (!stack) continue\n\n if (targetComponent) {\n const idx = stack.lastIndexOf(targetComponent)\n if (idx !== -1) {\n stack.splice(idx, 1)\n }\n if (stack.length > 0) {\n continue\n }\n }\n\n registryRef.current.delete(id)\n\n const timer = timersRef.current.get(id)\n if (timer) {\n clearTimeout(timer)\n timersRef.current.delete(id)\n }\n\n const pending = pendingRef.current.get(id)\n if (pending) {\n pendingRef.current.delete(id)\n pending.resolve(undefined)\n }\n\n if (routingRef.current?.enabled && getUrlModalId(routingRef.current) === String(id)) {\n setUrlModalId(null, routingRef.current, 'replace')\n }\n\n updateActiveModals(prev => {\n if (!prev.has(id)) return prev\n const next = new Map(prev)\n next.delete(id)\n return next\n })\n }\n },\n [updateActiveModals]\n )\n\n // Two-way URL synchronization listener\n useEffect(() => {\n if (!resolvedRouting || !resolvedRouting.enabled || !isBrowser()) return\n\n const syncFromUrl = () => {\n const urlId = getUrlModalId(routingRef.current)\n const currentActive = activeModalsRef.current\n\n // Dismiss active modal that does not match urlId\n for (const [id, active] of currentActive) {\n if (String(id) !== urlId && active.isOpen) {\n closeModal(id, undefined, undefined, false)\n }\n }\n\n if (urlId) {\n const modalId = urlId as ModalId\n if (!currentActive.get(modalId)?.isOpen && getComponent(modalId)) {\n openModal(modalId, getDefaultData(routingRef.current?.defaultData, modalId), false)\n }\n }\n }\n\n syncFromUrl()\n\n window.addEventListener('popstate', syncFromUrl)\n window.addEventListener('hashchange', syncFromUrl)\n\n return () => {\n window.removeEventListener('popstate', syncFromUrl)\n window.removeEventListener('hashchange', syncFromUrl)\n }\n }, [\n resolvedRouting,\n getComponent,\n openModal,\n closeModal\n ])\n\n const actions = useMemo<ModalActionsValue>(\n () => ({\n register,\n unregister,\n open,\n close,\n closeAll,\n isOpen\n }),\n [register, unregister, open, close, closeAll, isOpen]\n )\n\n return (\n <ModalActionsContext.Provider value={actions}>\n <ModalActiveContext.Provider value={activeModals}>\n {children}\n <ModalRenderer\n activeModals={activeModals}\n close={closeModal}\n fallback={fallback}\n />\n </ModalActiveContext.Provider>\n </ModalActionsContext.Provider>\n )\n}\n\nfunction ModalRenderer({\n activeModals,\n close,\n fallback\n}: {\n activeModals: ReadonlyMap<ModalId, ActiveModal>\n close: (id: ModalId, invocationId: number, result?: unknown, syncUrl?: boolean) => void\n fallback?: ReactNode\n}) {\n if (activeModals.size === 0) return null\n\n return (\n <>\n {Array.from(activeModals.values(), active => (\n <ModalSlotItem\n key={`${String(active.id)}:${active.invocationId}`}\n active={active}\n onClose={close}\n fallback={fallback}\n />\n ))}\n </>\n )\n}\n\nconst ModalSlotItem = memo(function ModalSlotItem({\n active,\n onClose,\n fallback\n}: {\n active: ActiveModal\n onClose: (id: ModalId, invocationId: number, result?: unknown, syncUrl?: boolean) => void\n fallback?: ReactNode\n}) {\n const handleClose = useCallback(\n (result?: unknown) => onClose(active.id, active.invocationId, result, true),\n [onClose, active.id, active.invocationId]\n )\n\n const Component = active.component\n\n return (\n <Suspense fallback={fallback ?? null}>\n <Component\n isOpen={active.isOpen}\n data={active.data as never}\n close={handleClose}\n />\n </Suspense>\n )\n})\n\n/**\n * Registers one or more modals for the lifetime of the calling component.\n */\nexport function useRegisterModal<TId extends ModalId>(\n id: TId,\n component: RegisteredComponent<TId>\n): void\nexport function useRegisterModal<const TIds extends readonly ModalId[]>(modals: {\n [K in keyof TIds]: ModalRegistration<TIds[K]>\n} | readonly ModalRegistration[]): void\nexport function useRegisterModal<TId extends ModalId>(\n idOrModals: TId | readonly ModalRegistration[],\n component?: RegisteredComponent<TId>\n): void {\n const { register, unregister } = useModalContext()\n const stableIdOrModals = useStableRegistrations(idOrModals)\n\n useEffect(() => {\n if (Array.isArray(stableIdOrModals)) {\n register(stableIdOrModals)\n return () => {\n for (const item of stableIdOrModals) {\n unregister(item.id, item.component as unknown as UntypedModalComponent)\n }\n }\n }\n\n if (component) {\n register(stableIdOrModals as TId, component)\n return () => {\n unregister(stableIdOrModals as TId, component as unknown as UntypedModalComponent)\n }\n }\n\n return undefined\n }, [stableIdOrModals, component, register, unregister])\n}\n\n/**\n * Declarative component for mounting static modal batches at application roots.\n */\nexport function ModalRegistry<const TIds extends readonly ModalId[]>({\n modals\n}: {\n modals: {\n [K in keyof TIds]: ModalRegistration<TIds[K]>\n } | readonly ModalRegistration[]\n}) {\n useRegisterModal(modals)\n return null\n}\n\n/**\n * Returns typed controls (`open`, `close`, `isOpen`) for a modal ID.\n */\nexport function useModal<\n TId extends ModalId,\n TResult = ModalResult<TId>\n>(\n id: TId\n): UseModalReturn<ModalData<TId>, CanonicalResult<TId, TResult>> {\n const { open, close, isOpen } = useModalContext()\n\n return useMemo<UseModalReturn<ModalData<TId>, CanonicalResult<TId, TResult>>>(\n () => ({\n open: (...args: ModalDataArg<ModalData<TId>>) =>\n open<TId, TResult>(id, ...args),\n close: (result?: CanonicalResult<TId, TResult>) =>\n close(id, result as ModalResult<TId>),\n isOpen: () => isOpen(id)\n }),\n [open, close, isOpen, id]\n )\n}\n\n/**\n * Reactively subscribes to whether a modal is currently open.\n */\nexport function useIsModalOpen(id: ModalId): boolean {\n const active = useContext(ModalActiveContext)\n return active.get(id)?.isOpen ?? false\n}\n\nexport function useCloseAll(): () => void {\n return useModalContext().closeAll\n}\n\nfunction useModalContext(): ModalActionsValue {\n const context = useContext(ModalActionsContext)\n if (!context) {\n throw new Error('useModalContext must be used within <ModalProvider>')\n }\n return context\n}\n"],"mappings":"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","names":["createContext","memo","Suspense","useCallback","useContext","useEffect","useMemo","useRef","useState","Fragment","jsx","jsxs","DEFAULT_ROUTING","isBrowser","DEFAULT_UNMOUNT_DELAY","ModalActionsContext","ModalActiveContext","isShallowEqual","a","b","keysA","keysB","k","useStableRegistrations","idOrModals","ref","item","i","getHashParts","rawHash","hash","anchor","query","formatHash","params","qs","getUrlModalId","config","param","setUrlModalId","id","forceMode","mode","url","updateParams","sp","getDefaultData","defaultData","ModalProvider","children","unmountDelay","fallback","routing","registryRef","activeModals","setActiveModals","activeModalsRef","updateActiveModals","updater","next","pendingRef","timersRef","invocationCounterRef","resolvedRouting","routingRef","p","getComponent","stack","scheduleUnmount","invocationId","existing","timer","prev","closeModal","result","syncUrl","active","pending","didClose","current","openModal","data","comp","resolver","promise","resolve","prevFocus","open","args","close","closeAll","pendings","changed","isOpen","register","component","items","urlId","unregister","idOrIds","targetComponent","ids","idx","syncFromUrl","currentActive","modalId","actions","ModalRenderer","ModalSlotItem","onClose","handleClose","Component","useRegisterModal","useModalContext","stableIdOrModals","ModalRegistry","modals","useModal","useIsModalOpen","useCloseAll","context"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-modal-registry",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Type-safe modal registry and promise-based dialog manager for React",
5
5
  "keywords": [
6
6
  "react-modal",