@lerx/promise-modal 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/ModalManager.d.ts +0 -1
- package/dist/app/constant.d.ts +0 -1
- package/dist/bootstrap/BootstrapProvider/BootstrapProvider.d.ts +0 -1
- package/dist/bootstrap/BootstrapProvider/helpers/bootstrap.d.ts +0 -1
- package/dist/bootstrap/BootstrapProvider/hooks/useInitialize.d.ts +0 -1
- package/dist/bootstrap/BootstrapProvider/index.d.ts +0 -1
- package/dist/bootstrap/BootstrapProvider/type.d.ts +0 -1
- package/dist/bootstrap/BootstrapProvider/useBootstrap.d.ts +0 -1
- package/dist/bootstrap/index.d.ts +0 -1
- package/dist/components/Anchor/Anchor.d.ts +0 -1
- package/dist/components/Anchor/classNames.emotion.d.ts +0 -1
- package/dist/components/Anchor/index.d.ts +0 -1
- package/dist/components/Background/Background.d.ts +0 -1
- package/dist/components/Background/classNames.emotion.d.ts +0 -1
- package/dist/components/Background/index.d.ts +0 -1
- package/dist/components/FallbackComponents/FallbackContent.d.ts +0 -1
- package/dist/components/FallbackComponents/FallbackFooter.d.ts +0 -1
- package/dist/components/FallbackComponents/FallbackForegroundFrame.d.ts +0 -1
- package/dist/components/FallbackComponents/FallbackSubtitle.d.ts +0 -1
- package/dist/components/FallbackComponents/FallbackTitle.d.ts +0 -1
- package/dist/components/FallbackComponents/classNames.emotion.d.ts +0 -1
- package/dist/components/FallbackComponents/index.d.ts +0 -1
- package/dist/components/Foreground/Foreground.d.ts +0 -1
- package/dist/components/Foreground/classNames.emotion.d.ts +0 -1
- package/dist/components/Foreground/components/AlertInner.d.ts +0 -1
- package/dist/components/Foreground/components/ConfirmInner.d.ts +0 -1
- package/dist/components/Foreground/components/PromptInner.d.ts +0 -1
- package/dist/components/Foreground/components/index.d.ts +0 -1
- package/dist/components/Foreground/index.d.ts +0 -1
- package/dist/components/Presenter/Presenter.d.ts +0 -1
- package/dist/components/Presenter/classNames.emotion.d.ts +0 -1
- package/dist/components/Presenter/index.d.ts +0 -1
- package/dist/core/handle/alert.d.ts +0 -1
- package/dist/core/handle/confirm.d.ts +0 -1
- package/dist/core/handle/index.d.ts +0 -1
- package/dist/core/handle/prompt.d.ts +0 -1
- package/dist/core/index.d.ts +0 -1
- package/dist/core/node/ModalNode/AbstractNode.d.ts +0 -1
- package/dist/core/node/ModalNode/AlertNode.d.ts +0 -1
- package/dist/core/node/ModalNode/ConfirmNode.d.ts +0 -1
- package/dist/core/node/ModalNode/PromptNode.d.ts +0 -1
- package/dist/core/node/ModalNode/index.d.ts +0 -1
- package/dist/core/node/index.d.ts +0 -1
- package/dist/core/node/nodeFactory.d.ts +0 -1
- package/dist/core/node/type.d.ts +0 -1
- package/dist/hooks/useActiveModalCount.d.ts +0 -1
- package/dist/hooks/useDefaultPathname.d.ts +0 -1
- package/dist/hooks/useDestroyAfter.d.ts +0 -1
- package/dist/hooks/useModalAnimation.d.ts +0 -1
- package/dist/hooks/useSubscribeModal.d.ts +0 -1
- package/dist/index.cjs +966 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.mjs +953 -2
- package/dist/providers/ConfigurationContext/ConfigurationContext.d.ts +0 -1
- package/dist/providers/ConfigurationContext/ConfigurationContextProvider.d.ts +4 -1
- package/dist/providers/ConfigurationContext/index.d.ts +0 -1
- package/dist/providers/ConfigurationContext/useConfigurationContext.d.ts +0 -1
- package/dist/providers/ModalManagerContext/ModalManagerContext.d.ts +0 -1
- package/dist/providers/ModalManagerContext/ModalManagerContextProvider.d.ts +0 -1
- package/dist/providers/ModalManagerContext/index.d.ts +0 -1
- package/dist/providers/ModalManagerContext/useModalManagerContext.d.ts +0 -1
- package/dist/providers/UserDefinedContext/UserDefinedContext.d.ts +0 -1
- package/dist/providers/UserDefinedContext/UserDefinedContextProvider.d.ts +2 -2
- package/dist/providers/UserDefinedContext/index.d.ts +0 -1
- package/dist/providers/UserDefinedContext/useUserDefinedContext.d.ts +0 -1
- package/dist/providers/index.d.ts +0 -1
- package/dist/types/alert.d.ts +0 -1
- package/dist/types/background.d.ts +0 -1
- package/dist/types/base.d.ts +0 -1
- package/dist/types/confirm.d.ts +0 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/modal.d.ts +0 -1
- package/dist/types/prompt.d.ts +0 -1
- package/package.json +34 -27
- package/dist/app/ModalManager.d.ts.map +0 -1
- package/dist/app/constant.d.ts.map +0 -1
- package/dist/bootstrap/BootstrapProvider/BootstrapProvider.d.ts.map +0 -1
- package/dist/bootstrap/BootstrapProvider/helpers/bootstrap.d.ts.map +0 -1
- package/dist/bootstrap/BootstrapProvider/hooks/useInitialize.d.ts.map +0 -1
- package/dist/bootstrap/BootstrapProvider/index.d.ts.map +0 -1
- package/dist/bootstrap/BootstrapProvider/type.d.ts.map +0 -1
- package/dist/bootstrap/BootstrapProvider/useBootstrap.d.ts.map +0 -1
- package/dist/bootstrap/index.d.ts.map +0 -1
- package/dist/components/Anchor/Anchor.d.ts.map +0 -1
- package/dist/components/Anchor/classNames.emotion.d.ts.map +0 -1
- package/dist/components/Anchor/index.d.ts.map +0 -1
- package/dist/components/Background/Background.d.ts.map +0 -1
- package/dist/components/Background/classNames.emotion.d.ts.map +0 -1
- package/dist/components/Background/index.d.ts.map +0 -1
- package/dist/components/FallbackComponents/FallbackContent.d.ts.map +0 -1
- package/dist/components/FallbackComponents/FallbackFooter.d.ts.map +0 -1
- package/dist/components/FallbackComponents/FallbackForegroundFrame.d.ts.map +0 -1
- package/dist/components/FallbackComponents/FallbackSubtitle.d.ts.map +0 -1
- package/dist/components/FallbackComponents/FallbackTitle.d.ts.map +0 -1
- package/dist/components/FallbackComponents/classNames.emotion.d.ts.map +0 -1
- package/dist/components/FallbackComponents/index.d.ts.map +0 -1
- package/dist/components/Foreground/Foreground.d.ts.map +0 -1
- package/dist/components/Foreground/classNames.emotion.d.ts.map +0 -1
- package/dist/components/Foreground/components/AlertInner.d.ts.map +0 -1
- package/dist/components/Foreground/components/ConfirmInner.d.ts.map +0 -1
- package/dist/components/Foreground/components/PromptInner.d.ts.map +0 -1
- package/dist/components/Foreground/components/index.d.ts.map +0 -1
- package/dist/components/Foreground/index.d.ts.map +0 -1
- package/dist/components/Presenter/Presenter.d.ts.map +0 -1
- package/dist/components/Presenter/classNames.emotion.d.ts.map +0 -1
- package/dist/components/Presenter/index.d.ts.map +0 -1
- package/dist/core/handle/alert.d.ts.map +0 -1
- package/dist/core/handle/confirm.d.ts.map +0 -1
- package/dist/core/handle/index.d.ts.map +0 -1
- package/dist/core/handle/prompt.d.ts.map +0 -1
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/node/ModalNode/AbstractNode.d.ts.map +0 -1
- package/dist/core/node/ModalNode/AlertNode.d.ts.map +0 -1
- package/dist/core/node/ModalNode/ConfirmNode.d.ts.map +0 -1
- package/dist/core/node/ModalNode/PromptNode.d.ts.map +0 -1
- package/dist/core/node/ModalNode/index.d.ts.map +0 -1
- package/dist/core/node/index.d.ts.map +0 -1
- package/dist/core/node/nodeFactory.d.ts.map +0 -1
- package/dist/core/node/type.d.ts.map +0 -1
- package/dist/hooks/useActiveModalCount.d.ts.map +0 -1
- package/dist/hooks/useDefaultPathname.d.ts.map +0 -1
- package/dist/hooks/useDestroyAfter.d.ts.map +0 -1
- package/dist/hooks/useModalAnimation.d.ts.map +0 -1
- package/dist/hooks/useSubscribeModal.d.ts.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/providers/ConfigurationContext/ConfigurationContext.d.ts.map +0 -1
- package/dist/providers/ConfigurationContext/ConfigurationContextProvider.d.ts.map +0 -1
- package/dist/providers/ConfigurationContext/index.d.ts.map +0 -1
- package/dist/providers/ConfigurationContext/useConfigurationContext.d.ts.map +0 -1
- package/dist/providers/ModalManagerContext/ModalManagerContext.d.ts.map +0 -1
- package/dist/providers/ModalManagerContext/ModalManagerContextProvider.d.ts.map +0 -1
- package/dist/providers/ModalManagerContext/index.d.ts.map +0 -1
- package/dist/providers/ModalManagerContext/useModalManagerContext.d.ts.map +0 -1
- package/dist/providers/UserDefinedContext/UserDefinedContext.d.ts.map +0 -1
- package/dist/providers/UserDefinedContext/UserDefinedContextProvider.d.ts.map +0 -1
- package/dist/providers/UserDefinedContext/index.d.ts.map +0 -1
- package/dist/providers/UserDefinedContext/useUserDefinedContext.d.ts.map +0 -1
- package/dist/providers/index.d.ts.map +0 -1
- package/dist/types/alert.d.ts.map +0 -1
- package/dist/types/background.d.ts.map +0 -1
- package/dist/types/base.d.ts.map +0 -1
- package/dist/types/confirm.d.ts.map +0 -1
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/modal.d.ts.map +0 -1
- package/dist/types/prompt.d.ts.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,966 @@
|
|
|
1
|
-
function _EMOTION_STRINGIFIED_CSS_ERROR__$4(){return"You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."}function _EMOTION_STRINGIFIED_CSS_ERROR__$3(){return"You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."}function _EMOTION_STRINGIFIED_CSS_ERROR__$2(){return"You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."}var e=require("react/jsx-runtime"),n=require("react"),o=require("@winglet/common-utils/convert"),t=require("@winglet/react-utils/hook"),r=require("@winglet/common-utils/lib"),i=require("@emotion/css"),s=require("react-dom"),a=require("@winglet/common-utils/array"),l=require("@winglet/react-utils/hoc"),c=require("@winglet/common-utils/filter"),d=require("@winglet/react-utils/render"),u=require("@winglet/common-utils/console");class ModalManager{static#e=0;static activate(){return ModalManager.#e?0:ModalManager.#e=1}static#n=null;static anchor(e){if(ModalManager.#n){const e=document.getElementById(ModalManager.#n.id);if(e)return e}const{tag:n="div",prefix:o="promise-modal",root:t=document.body}=e||{},i=document.createElement(n);return i.setAttribute("id",`${o}-${r.getRandomString(36)}`),t.appendChild(i),ModalManager.#n=i,i}static#o=[];static get prerender(){return ModalManager.#o}static#t=e=>ModalManager.#o.push(e);static set openHandler(e){ModalManager.#t=e,ModalManager.#o=[]}static get unanchored(){return!ModalManager.#n}static reset(){ModalManager.#e=0,ModalManager.#n=null,ModalManager.#o=[],ModalManager.#t=e=>ModalManager.#o.push(e)}static open(e){ModalManager.#t(e)}}class AbstractNode{id;initiator;title;subtitle;background;manualDestroy;closeOnBackdropClick;dimmed;ForegroundComponent;BackgroundComponent;#r;get alive(){return this.#r}#i;get visible(){return this.#i}#s;#a=new Set;constructor({id:e,initiator:n,title:o,subtitle:t,background:r,dimmed:i=1,manualDestroy:s=0,closeOnBackdropClick:a=1,resolve:l,ForegroundComponent:c,BackgroundComponent:d}){this.id=e,this.initiator=n,this.title=o,this.subtitle=t,this.background=r,this.dimmed=i,this.manualDestroy=s,this.closeOnBackdropClick=a,this.ForegroundComponent=c,this.BackgroundComponent=d,this.#r=1,this.#i=1,this.#s=l}subscribe(e){return this.#a.add(e),()=>{this.#a.delete(e)}}publish(){for(const e of this.#a)e()}resolve(e){this.#s(e)}onDestroy(){const e=1==this.#r;this.#r=0,this.manualDestroy&&e&&this.publish()}onShow(){const e=0==this.#i;this.#i=1,e&&this.publish()}onHide(){const e=1==this.#i;this.#i=0,e&&this.publish()}}class AlertNode extends AbstractNode{type;subtype;content;footer;constructor({id:e,initiator:n,type:o,subtype:t,title:r,subtitle:i,content:s,footer:a,background:l,dimmed:c,manualDestroy:d,closeOnBackdropClick:u,resolve:m,ForegroundComponent:p,BackgroundComponent:C}){super({id:e,initiator:n,title:r,subtitle:i,background:l,dimmed:c,manualDestroy:d,closeOnBackdropClick:u,resolve:m,ForegroundComponent:p,BackgroundComponent:C}),this.type=o,this.subtype=t,this.content=s,this.footer=a}onClose(){this.resolve(null)}onConfirm(){this.resolve(null)}}class ConfirmNode extends AbstractNode{type;subtype;content;footer;constructor({id:e,initiator:n,type:o,subtype:t,title:r,subtitle:i,content:s,footer:a,background:l,dimmed:c,manualDestroy:d,closeOnBackdropClick:u,resolve:m,ForegroundComponent:p,BackgroundComponent:C}){super({id:e,initiator:n,title:r,subtitle:i,background:l,dimmed:c,manualDestroy:d,closeOnBackdropClick:u,resolve:m,ForegroundComponent:p,BackgroundComponent:C}),this.type=o,this.subtype=t,this.content=s,this.footer=a}onClose(){this.resolve(0)}onConfirm(){this.resolve(1)}}class PromptNode extends AbstractNode{type;content;defaultValue;Input;disabled;returnOnCancel;footer;#l;constructor({id:e,initiator:n,type:o,title:t,subtitle:r,content:i,defaultValue:s,Input:a,disabled:l,returnOnCancel:c,footer:d,background:u,dimmed:m,manualDestroy:p,closeOnBackdropClick:C,resolve:h,ForegroundComponent:g,BackgroundComponent:f}){super({id:e,initiator:n,title:t,subtitle:r,background:u,dimmed:m,manualDestroy:p,closeOnBackdropClick:C,resolve:h,ForegroundComponent:g,BackgroundComponent:f}),this.type=o,this.content=i,this.Input=a,this.defaultValue=s,this.#l=s,this.disabled=l,this.returnOnCancel=c,this.footer=d}onChange(e){this.#l=e}onConfirm(){this.resolve(this.#l??null)}onClose(){this.returnOnCancel?this.resolve(this.#l??null):this.resolve(null)}}const nodeFactory=e=>{switch(e.type){case"alert":return new AlertNode(e);case"confirm":return new ConfirmNode(e);case"prompt":return new PromptNode(e)}throw new Error(`Unknown modal: ${e.type}`,{modal:e})},m=n.createContext({}),p=n.memo((({usePathname:r,children:i})=>{const s=n.useRef(new Map),[a,l]=n.useState([]),c=t.useReference(a),{pathname:d}=r(),u=n.useRef(d),p=n.useRef(0),C=useConfigurationOptions(),h=n.useMemo((()=>o.convertMsFromDuration(C.duration)),[C]);t.useOnMountLayout((()=>{const{manualDestroy:e,closeOnBackdropClick:n}=C;for(const o of ModalManager.prerender){const t=nodeFactory({...o,id:p.current++,initiator:u.current,manualDestroy:void 0!==o.manualDestroy?o.manualDestroy:e,closeOnBackdropClick:void 0!==o.closeOnBackdropClick?o.closeOnBackdropClick:n});s.current.set(t.id,t),l((e=>[...e,t.id]))}return ModalManager.openHandler=o=>{const t=nodeFactory({...o,id:p.current++,initiator:u.current,manualDestroy:void 0!==o.manualDestroy?o.manualDestroy:e,closeOnBackdropClick:void 0!==o.closeOnBackdropClick?o.closeOnBackdropClick:n});s.current.set(t.id,t),l((e=>{const n=[];for(let o=0;o<e.length;o++){const t=e[o];s.current.get(t)?.alive?n.push(t):s.current.delete(t)}return[...n,t.id]}))},()=>{ModalManager.reset()}})),n.useLayoutEffect((()=>{for(const e of c.current){const n=s.current.get(e);n?.alive&&(n.initiator===d?n.onShow():n.onHide())}u.current=d}),[d]);const g=n.useCallback((e=>s.current.get(e)),[]),f=n.useCallback((e=>{const n=s.current.get(e);n&&(n.onDestroy(),b.current?.())}),[]),b=n.useRef(void 0),v=n.useCallback((e=>{const n=s.current.get(e);n&&(n.onHide(),b.current?.(),n.manualDestroy||setTimeout((()=>{n.onDestroy()}),h))}),[h]),y=n.useCallback(((e,n)=>{const o=s.current.get(e);o&&"prompt"===o.type&&o.onChange(n)}),[]),x=n.useCallback((e=>{const n=s.current.get(e);n&&(n.onConfirm(),v(e))}),[v]),k=n.useCallback((e=>{const n=s.current.get(e);n&&(n.onClose(),v(e))}),[v]),M=n.useCallback((e=>({modal:g(e),onConfirm:()=>x(e),onClose:()=>k(e),onChange:n=>y(e,n),onDestroy:()=>f(e)})),[g,x,k,y,f]),O=n.useMemo((()=>({modalIds:a,getModalNode:g,onChange:y,onConfirm:x,onClose:k,onDestroy:f,getModal:M,setUpdater:e=>{b.current=e}})),[a,M,g,y,x,k,f]);return e.jsx(m.Provider,{value:O,children:i})})),useModalManagerContext=()=>n.useContext(m),useModal=e=>{const{getModal:o}=useModalManagerContext();return n.useMemo((()=>o(e)),[e,o])},C=i.css("production"===process.env.NODE_ENV?{name:"131j9g2",styles:"margin:unset"}:{name:"1w3kbco-fallback",styles:"margin:unset;label:fallback;",toString:_EMOTION_STRINGIFIED_CSS_ERROR__$4}),h=i.css("production"===process.env.NODE_ENV?{name:"1kuk3a3",styles:"display:flex;flex-direction:column;justify-content:center;align-items:center;background-color:white;padding:20px 80px;gap:10px;border:1px solid black"}:{name:"16dbbea-frame",styles:"display:flex;flex-direction:column;justify-content:center;align-items:center;background-color:white;padding:20px 80px;gap:10px;border:1px solid black;label:frame;",toString:_EMOTION_STRINGIFIED_CSS_ERROR__$4}),FallbackTitle=({children:n})=>e.jsx("h2",{className:C,children:n}),FallbackSubtitle=({children:n})=>e.jsx("h3",{className:C,children:n}),FallbackContent=({children:n})=>e.jsx("div",{className:C,children:n}),FallbackFooter=({confirmLabel:n,hideConfirm:o=0,cancelLabel:t,hideCancel:r=0,disabled:i,onConfirm:s,onCancel:a})=>e.jsxs("div",{children:[!o&&e.jsx("button",{onClick:s,disabled:i,children:n||"Confirm"}),!r&&"function"==typeof a&&e.jsx("button",{onClick:a,children:t||"Cancel"})]}),defaultValidate=e=>e?.visible,useActiveModalCount=(e=defaultValidate,o=0)=>{const{modalIds:t,getModalNode:r}=useModalManagerContext();return n.useMemo((()=>{let n=0;for(const o of t)e(r(o))&&n++;return n}),[r,t,o])},g=n.forwardRef((({id:o,onChangeOrder:t,children:r},i)=>{const s=useActiveModalCount(),[a,l]=n.useMemo((()=>{const e=s>1;return[e?Math.floor(o/5)%3*100:0,e?o%5*35:0]}),[s,o]);return e.jsx("div",{ref:i,className:h,onClick:t,style:{marginBottom:`calc(25vh + ${a}px)`,marginLeft:`${a}px`,transform:`translate(${l}px, ${l}px)`},children:r})})),f=n.createContext({}),b=n.memo((({ForegroundComponent:o,BackgroundComponent:t,TitleComponent:r,SubtitleComponent:i,ContentComponent:s,FooterComponent:a,options:l,children:c})=>{const d=n.useMemo((()=>({BackgroundComponent:t,ForegroundComponent:o||g,TitleComponent:r||FallbackTitle,SubtitleComponent:i||FallbackSubtitle,ContentComponent:n.memo(s||FallbackContent),FooterComponent:n.memo(a||FallbackFooter),options:{duration:"300ms",backdrop:"rgba(0, 0, 0, 0.5)",closeOnBackdropClick:1,manualDestroy:0,...l}})),[o,t,s,a,i,r,l]);return e.jsx(f.Provider,{value:d,children:c})})),useConfigurationContext=()=>n.useContext(f),useConfigurationOptions=()=>n.useContext(f).options,v=n.createContext({}),UserDefinedContextProvider=({context:o,children:t})=>{const r=n.useMemo((()=>({context:o||{}})),[o]);return e.jsx(v.Provider,{value:r,children:t})},useUserDefinedContext=()=>n.useContext(v),usePathname=()=>{const[e,o]=n.useState(window.location.pathname);return n.useLayoutEffect((()=>{let n;const checkPathname=()=>{n&&cancelAnimationFrame(n),e!==window.location.pathname?o(window.location.pathname):n=requestAnimationFrame(checkPathname)};return n=requestAnimationFrame(checkPathname),()=>{n&&cancelAnimationFrame(n)}}),[e]),{pathname:e}},y=i.css("production"===process.env.NODE_ENV?{name:"u7uu4v",styles:"display:none;position:fixed;inset:0;z-index:-999;pointer-events:none;>*{pointer-events:none;}"}:{name:"coymdj-background",styles:"display:none;position:fixed;inset:0;z-index:-999;pointer-events:none;>*{pointer-events:none;};label:background;",toString:_EMOTION_STRINGIFIED_CSS_ERROR__$3}),x=i.css("production"===process.env.NODE_ENV?{name:"n07k1x",styles:"pointer-events:all"}:{name:"1hektcs-active",styles:"pointer-events:all;label:active;",toString:_EMOTION_STRINGIFIED_CSS_ERROR__$3}),k=i.css("production"===process.env.NODE_ENV?{name:"1wnowod",styles:"display:flex;align-items:center;justify-content:center"}:{name:"xppew7-visible",styles:"display:flex;align-items:center;justify-content:center;label:visible;",toString:_EMOTION_STRINGIFIED_CSS_ERROR__$3}),BackgroundFrame=({modalId:o,onChangeOrder:t})=>{const{BackgroundComponent:r}=useConfigurationContext(),{context:s}=useUserDefinedContext(),{modal:a,onClose:l,onChange:c,onConfirm:d,onDestroy:u}=useModal(o),m=n.useCallback((e=>{a&&a.closeOnBackdropClick&&a.visible&&l(),e.stopPropagation()}),[a,l]),p=n.useMemo((()=>a?.BackgroundComponent||r),[r,a]);return a?e.jsx("div",{className:i.cx(y,{[k]:a.manualDestroy?a.alive:a.visible,[x]:a.closeOnBackdropClick&&a.visible}),onClick:m,children:p&&e.jsx(p,{id:a.id,type:a.type,alive:a.alive,visible:a.visible,initiator:a.initiator,manualDestroy:a.manualDestroy,closeOnBackdropClick:a.closeOnBackdropClick,background:a.background,onChange:c,onConfirm:d,onClose:l,onDestroy:u,onChangeOrder:t,context:s})}):null},M=i.css("production"===process.env.NODE_ENV?{name:"12g0hx0",styles:"pointer-events:none;display:none;position:fixed;inset:0;z-index:1"}:{name:"1hcczik-foreground",styles:"pointer-events:none;display:none;position:fixed;inset:0;z-index:1;label:foreground;",toString:_EMOTION_STRINGIFIED_CSS_ERROR__$2}),O=i.css("production"===process.env.NODE_ENV?{name:"1g95xyq",styles:">*{pointer-events:all;}"}:{name:"123csva-active",styles:">*{pointer-events:all;};label:active;",toString:_EMOTION_STRINGIFIED_CSS_ERROR__$2}),_=i.css("production"===process.env.NODE_ENV?{name:"1fmljv2",styles:"display:flex!important;justify-content:center;align-items:center"}:{name:"1p4unab-visible",styles:"display:flex!important;justify-content:center;align-items:center;label:visible;",toString:_EMOTION_STRINGIFIED_CSS_ERROR__$2}),I=n.memo((({modal:o,handlers:r})=>{const{title:i,subtitle:s,content:a,footer:l}=n.useMemo((()=>o),[o]),{context:u}=useUserDefinedContext(),{onConfirm:m}=n.useMemo((()=>r),[r]),p=t.useHandle(m),{TitleComponent:C,SubtitleComponent:h,ContentComponent:g,FooterComponent:f}=useConfigurationContext();return e.jsxs(n.Fragment,{children:[i&&(c.isString(i)?e.jsx(C,{context:u,children:i}):i),s&&(c.isString(s)?e.jsx(h,{context:u,children:s}):s),a&&(c.isString(a)?e.jsx(g,{context:u,children:a}):d.renderComponent(a,{onConfirm:p})),0!=l&&("function"==typeof l?l({onConfirm:p,context:u}):e.jsx(f,{onConfirm:p,confirmLabel:l?.confirm,hideConfirm:l?.hideConfirm,context:u}))]})})),S=n.memo((({modal:o,handlers:r})=>{const{title:i,subtitle:s,content:a,footer:l}=n.useMemo((()=>o),[o]),{context:u}=useUserDefinedContext(),{onConfirm:m,onClose:p}=n.useMemo((()=>r),[r]),C=t.useHandle(m),h=t.useHandle(p),{TitleComponent:g,SubtitleComponent:f,ContentComponent:b,FooterComponent:v}=useConfigurationContext();return e.jsxs(n.Fragment,{children:[i&&(c.isString(i)?e.jsx(g,{context:u,children:i}):i),s&&(c.isString(s)?e.jsx(f,{context:u,children:s}):s),a&&(c.isString(a)?e.jsx(b,{context:u,children:a}):d.renderComponent(a,{onConfirm:C,onCancel:h,context:u})),0!=l&&("function"==typeof l?l({onConfirm:C,onCancel:h,context:u}):e.jsx(v,{onConfirm:C,onCancel:h,confirmLabel:l?.confirm,cancelLabel:l?.cancel,hideConfirm:l?.hideConfirm,hideCancel:l?.hideCancel,context:u}))]})})),D=n.memo((({modal:o,handlers:r})=>{const{Input:i,defaultValue:s,disabled:a,title:u,subtitle:m,content:p,footer:C}=n.useMemo((()=>({...o,Input:n.memo(l.withErrorBoundary(o.Input))})),[o]),{context:h}=useUserDefinedContext(),[g,f]=n.useState(s),{onChange:b,onClose:v,onConfirm:y}=n.useMemo((()=>r),[r]),x=t.useHandle(v),k=t.useHandle((e=>{const n=c.isFunction(e)?e(g):e;f(n),b(n)})),M=n.useCallback((()=>{requestAnimationFrame(y)}),[y]),O=n.useMemo((()=>g?!!a?.(g):0),[a,g]),{TitleComponent:_,SubtitleComponent:I,ContentComponent:S,FooterComponent:D}=useConfigurationContext();return e.jsxs(n.Fragment,{children:[u&&(c.isString(u)?e.jsx(_,{context:h,children:u}):u),m&&(c.isString(m)?e.jsx(I,{context:h,children:m}):m),p&&(c.isString(p)?e.jsx(S,{context:h,children:p}):d.renderComponent(p,{onConfirm:M,onCancel:x,context:h})),i&&e.jsx(i,{defaultValue:s,value:g,onChange:k,onConfirm:M,onCancel:x,context:h}),0!=C&&("function"==typeof C?C({value:g,disabled:O,onChange:k,onConfirm:M,onCancel:x,context:h}):e.jsx(D,{disabled:O,onConfirm:M,onCancel:x,confirmLabel:C?.confirm,cancelLabel:C?.cancel,hideConfirm:C?.hideConfirm,hideCancel:C?.hideCancel,context:h}))]})})),ForegroundFrame=({modalId:o,onChangeOrder:t})=>{const{ForegroundComponent:r}=useConfigurationContext(),{context:s}=useUserDefinedContext(),{modal:a,onChange:l,onConfirm:c,onClose:d,onDestroy:u}=useModal(o),m=n.useMemo((()=>a?.ForegroundComponent||r),[r,a]);return a?e.jsx("div",{className:i.cx(M,{[_]:a.manualDestroy?a.alive:a.visible,[O]:a.visible}),children:e.jsxs(m,{id:a.id,type:a.type,alive:a.alive,visible:a.visible,initiator:a.initiator,manualDestroy:a.manualDestroy,closeOnBackdropClick:a.closeOnBackdropClick,background:a.background,onChange:l,onConfirm:c,onClose:d,onDestroy:u,onChangeOrder:t,context:s,children:["alert"===a.type&&e.jsx(I,{modal:a,handlers:{onConfirm:c}}),"confirm"===a.type&&e.jsx(S,{modal:a,handlers:{onConfirm:c,onClose:d}}),"prompt"===a.type&&e.jsx(D,{modal:a,handlers:{onChange:l,onConfirm:c,onClose:d}})]})}):null},useSubscribeModal=e=>{const[o,r]=t.useVersion();return n.useEffect((()=>{if(e)return e.subscribe(r)}),[e,r]),o},N=i.css("production"===process.env.NODE_ENV?{name:"13dmkf4",styles:"position:fixed;inset:0;pointer-events:none;overflow:hidden"}:{name:"yjeu12-presenter",styles:"position:fixed;inset:0;pointer-events:none;overflow:hidden;label:presenter;",toString:function _EMOTION_STRINGIFIED_CSS_ERROR__$1(){return"You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."}}),{increment:E}=r.counterFactory(1),R=n.memo((({modalId:o})=>{const r=n.useRef(null),{modal:i}=useModal(o);useSubscribeModal(i);const s=t.useHandle((()=>{r.current&&(r.current.style.zIndex=`${E()}`)}));return e.jsxs("div",{ref:r,className:N,children:[e.jsx(BackgroundFrame,{modalId:o,onChangeOrder:s}),e.jsx(ForegroundFrame,{modalId:o,onChangeOrder:s})]})})),F=i.css("production"===process.env.NODE_ENV?{name:"2hpasy",styles:"display:flex;align-items:center;justify-content:center;position:fixed;inset:0;pointer-events:none;z-index:1000;transition:background-color ease-in-out"}:{name:"lhj8co-anchor",styles:"display:flex;align-items:center;justify-content:center;position:fixed;inset:0;pointer-events:none;z-index:1000;transition:background-color ease-in-out;label:anchor;",toString:function _EMOTION_STRINGIFIED_CSS_ERROR__(){return"You have tried to stringify object returned from `css` function. It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop)."}}),validateDimmable=e=>e?.visible&&e.dimmed,j=n.memo(l.withErrorBoundary((()=>{const[o,r]=t.useVersion(),{modalIds:i,setUpdater:s}=useModalManagerContext();n.useEffect((()=>{s(r)}),[s,r]);const l=useConfigurationOptions(),c=useActiveModalCount(validateDimmable,o);return e.jsx("div",{className:F,style:{transitionDuration:l.duration,backgroundColor:c?l.backdrop:"transparent"},children:a.map(i,(n=>e.jsx(R,{modalId:n},n)))})}))),bootstrap=({ForegroundComponent:n,BackgroundComponent:o,TitleComponent:t,SubtitleComponent:r,ContentComponent:i,FooterComponent:a,usePathname:l,options:c,context:d,anchor:u})=>s.createPortal(e.jsx(UserDefinedContextProvider,{context:d,children:e.jsx(b,{ForegroundComponent:n,BackgroundComponent:o,TitleComponent:t,SubtitleComponent:r,ContentComponent:i,FooterComponent:a,options:c,children:e.jsx(p,{usePathname:l,children:e.jsx(j,{})})})}),u),useInitialize=()=>{const e=n.useRef(ModalManager.activate()),o=n.useRef(null),[,r]=t.useVersion(),i=n.useCallback((n=>{e.current?(o.current=ModalManager.anchor({root:n}),r()):u.printError("ModalProvider is already initialized",["ModalProvider can only be initialized once.","Nesting ModalProvider will be ignored..."],{info:"Something is wrong with the ModalProvider initialization..."})}),[r]);return{anchorRef:o,handleInitialize:i}},B=n.forwardRef((({usePathname:o,ForegroundComponent:r,BackgroundComponent:i,TitleComponent:s,SubtitleComponent:a,ContentComponent:l,FooterComponent:c,options:d,context:u,children:m},p)=>{const C=n.useMemo((()=>o||usePathname),[o]),{anchorRef:h,handleInitialize:g}=useInitialize();return n.useImperativeHandle(p,(()=>({initialize:g})),[g]),t.useOnMount((()=>(null===p&&g(),()=>{h.current&&h.current.remove()}))),e.jsxs(n.Fragment,{children:[m,h.current&&bootstrap({ForegroundComponent:r,BackgroundComponent:i,TitleComponent:s,SubtitleComponent:a,ContentComponent:l,FooterComponent:c,usePathname:C,options:d,context:u,anchor:h.current})]})}));exports.ModalProvider=B,exports.alert=({subtype:e,title:n,subtitle:o,content:t,background:r,footer:i,dimmed:s,manualDestroy:a,closeOnBackdropClick:l,ForegroundComponent:c,BackgroundComponent:d})=>new Promise(((u,m)=>{try{ModalManager.open({type:"alert",subtype:e,resolve:()=>u(),title:n,subtitle:o,content:t,background:r,footer:i,dimmed:s,manualDestroy:a,closeOnBackdropClick:l,ForegroundComponent:c,BackgroundComponent:d})}catch(e){m(e)}})),exports.confirm=({subtype:e,title:n,subtitle:o,content:t,background:r,footer:i,dimmed:s,manualDestroy:a,closeOnBackdropClick:l,ForegroundComponent:c,BackgroundComponent:d})=>new Promise(((u,m)=>{try{ModalManager.open({type:"confirm",subtype:e,resolve:e=>u(e??0),title:n,subtitle:o,content:t,background:r,footer:i,dimmed:s,manualDestroy:a,closeOnBackdropClick:l,ForegroundComponent:c,BackgroundComponent:d})}catch(e){m(e)}})),exports.prompt=({defaultValue:e,title:n,subtitle:o,content:t,Input:r,disabled:i,returnOnCancel:s,background:a,footer:l,dimmed:c,manualDestroy:d,closeOnBackdropClick:u,ForegroundComponent:m,BackgroundComponent:p})=>new Promise(((C,h)=>{try{ModalManager.open({type:"prompt",resolve:e=>C(e),title:n,subtitle:o,content:t,Input:r,defaultValue:e,disabled:i,returnOnCancel:s,background:a,footer:l,dimmed:c,manualDestroy:d,closeOnBackdropClick:u,ForegroundComponent:m,BackgroundComponent:p})}catch(e){h(e)}})),exports.useActiveModalCount=useActiveModalCount,exports.useDestroyAfter=(e,t)=>{const{modal:r,onDestroy:i}=useModal(e),s=useSubscribeModal(r),a=n.useRef({modal:r,onDestroy:i,milliseconds:c.isString(t)?o.convertMsFromDuration(t):t});n.useEffect((()=>{const{modal:e,onDestroy:n,milliseconds:o}=a.current;if(!e||e.visible||!e.alive)return;const t=setTimeout((()=>{n()}),o);return()=>{t&&clearTimeout(t)}}),[s])},exports.useInitializeModal=({usePathname:e,ForegroundComponent:o,BackgroundComponent:r,TitleComponent:i,SubtitleComponent:s,ContentComponent:a,FooterComponent:l,options:c,context:d,mode:u="auto"}={})=>{const m=n.useMemo((()=>e||usePathname),[e]),{anchorRef:p,handleInitialize:C}=useInitialize();t.useOnMount((()=>("auto"===u&&C(),()=>{p.current&&p.current.remove()})));const h=n.useCallback((e=>{"manual"===u&&C(e)}),[u,C]);return{portal:p.current&&bootstrap({usePathname:m,ForegroundComponent:o,BackgroundComponent:r,TitleComponent:i,SubtitleComponent:s,ContentComponent:a,FooterComponent:l,options:c,context:d,anchor:p.current}),initialize:h}},exports.useModalAnimation=(e,o)=>{const t=n.useRef(o);t.current=o,n.useLayoutEffect((()=>{if(!t.current)return;let n;return n=e?requestAnimationFrame((()=>t.current.onVisible?.())):requestAnimationFrame((()=>t.current.onHidden?.())),()=>{n&&cancelAnimationFrame(n)}}),[e])},exports.useModalBackdrop=()=>useConfigurationOptions().backdrop,exports.useModalDuration=()=>{const e=useConfigurationOptions();return{duration:e.duration,milliseconds:o.convertMsFromDuration(e.duration)}},exports.useModalOptions=useConfigurationOptions,exports.useSubscribeModal=useSubscribeModal;
|
|
2
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
const react = require('react');
|
|
5
|
+
const convert = require('@winglet/common-utils/convert');
|
|
6
|
+
const hook = require('@winglet/react-utils/hook');
|
|
7
|
+
const lib = require('@winglet/common-utils/lib');
|
|
8
|
+
const css = require('@emotion/css');
|
|
9
|
+
const reactDom = require('react-dom');
|
|
10
|
+
const array = require('@winglet/common-utils/array');
|
|
11
|
+
const hoc = require('@winglet/react-utils/hoc');
|
|
12
|
+
const filter = require('@winglet/common-utils/filter');
|
|
13
|
+
const render = require('@winglet/react-utils/render');
|
|
14
|
+
const console = require('@winglet/common-utils/console');
|
|
15
|
+
|
|
16
|
+
class ModalManager {
|
|
17
|
+
static #active = false;
|
|
18
|
+
static activate() {
|
|
19
|
+
if (ModalManager.#active)
|
|
20
|
+
return false;
|
|
21
|
+
return (ModalManager.#active = true);
|
|
22
|
+
}
|
|
23
|
+
static #anchor = null;
|
|
24
|
+
static anchor(options) {
|
|
25
|
+
if (ModalManager.#anchor) {
|
|
26
|
+
const anchor = document.getElementById(ModalManager.#anchor.id);
|
|
27
|
+
if (anchor)
|
|
28
|
+
return anchor;
|
|
29
|
+
}
|
|
30
|
+
const { tag = 'div', prefix = 'promise-modal', root = document.body, } = options || {};
|
|
31
|
+
const node = document.createElement(tag);
|
|
32
|
+
node.setAttribute('id', `${prefix}-${lib.getRandomString(36)}`);
|
|
33
|
+
root.appendChild(node);
|
|
34
|
+
ModalManager.#anchor = node;
|
|
35
|
+
return node;
|
|
36
|
+
}
|
|
37
|
+
static #prerenderList = [];
|
|
38
|
+
static get prerender() {
|
|
39
|
+
return ModalManager.#prerenderList;
|
|
40
|
+
}
|
|
41
|
+
static #openHandler = (modal) => ModalManager.#prerenderList.push(modal);
|
|
42
|
+
static set openHandler(handler) {
|
|
43
|
+
ModalManager.#openHandler = handler;
|
|
44
|
+
ModalManager.#prerenderList = [];
|
|
45
|
+
}
|
|
46
|
+
static get unanchored() {
|
|
47
|
+
return !ModalManager.#anchor;
|
|
48
|
+
}
|
|
49
|
+
static reset() {
|
|
50
|
+
ModalManager.#active = false;
|
|
51
|
+
ModalManager.#anchor = null;
|
|
52
|
+
ModalManager.#prerenderList = [];
|
|
53
|
+
ModalManager.#openHandler = (modal) => ModalManager.#prerenderList.push(modal);
|
|
54
|
+
}
|
|
55
|
+
static open(modal) {
|
|
56
|
+
ModalManager.#openHandler(modal);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const alert = ({ subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
|
|
61
|
+
return new Promise((resolve, reject) => {
|
|
62
|
+
try {
|
|
63
|
+
ModalManager.open({
|
|
64
|
+
type: 'alert',
|
|
65
|
+
subtype,
|
|
66
|
+
resolve: () => resolve(),
|
|
67
|
+
title,
|
|
68
|
+
subtitle,
|
|
69
|
+
content,
|
|
70
|
+
background,
|
|
71
|
+
footer,
|
|
72
|
+
dimmed,
|
|
73
|
+
manualDestroy,
|
|
74
|
+
closeOnBackdropClick,
|
|
75
|
+
ForegroundComponent,
|
|
76
|
+
BackgroundComponent,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
reject(error);
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const confirm = ({ subtype, title, subtitle, content, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
|
|
86
|
+
return new Promise((resolve, reject) => {
|
|
87
|
+
try {
|
|
88
|
+
ModalManager.open({
|
|
89
|
+
type: 'confirm',
|
|
90
|
+
subtype,
|
|
91
|
+
resolve: (result) => resolve(result ?? false),
|
|
92
|
+
title,
|
|
93
|
+
subtitle,
|
|
94
|
+
content,
|
|
95
|
+
background,
|
|
96
|
+
footer,
|
|
97
|
+
dimmed,
|
|
98
|
+
manualDestroy,
|
|
99
|
+
closeOnBackdropClick,
|
|
100
|
+
ForegroundComponent,
|
|
101
|
+
BackgroundComponent,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
reject(error);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const prompt = ({ defaultValue, title, subtitle, content, Input, disabled, returnOnCancel, background, footer, dimmed, manualDestroy, closeOnBackdropClick, ForegroundComponent, BackgroundComponent, }) => {
|
|
111
|
+
return new Promise((resolve, reject) => {
|
|
112
|
+
try {
|
|
113
|
+
ModalManager.open({
|
|
114
|
+
type: 'prompt',
|
|
115
|
+
resolve: (result) => resolve(result),
|
|
116
|
+
title,
|
|
117
|
+
subtitle,
|
|
118
|
+
content,
|
|
119
|
+
Input,
|
|
120
|
+
defaultValue,
|
|
121
|
+
disabled,
|
|
122
|
+
returnOnCancel,
|
|
123
|
+
background,
|
|
124
|
+
footer,
|
|
125
|
+
dimmed,
|
|
126
|
+
manualDestroy,
|
|
127
|
+
closeOnBackdropClick,
|
|
128
|
+
ForegroundComponent,
|
|
129
|
+
BackgroundComponent,
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
reject(error);
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
class AbstractNode {
|
|
139
|
+
id;
|
|
140
|
+
initiator;
|
|
141
|
+
title;
|
|
142
|
+
subtitle;
|
|
143
|
+
background;
|
|
144
|
+
manualDestroy;
|
|
145
|
+
closeOnBackdropClick;
|
|
146
|
+
dimmed;
|
|
147
|
+
ForegroundComponent;
|
|
148
|
+
BackgroundComponent;
|
|
149
|
+
#alive;
|
|
150
|
+
get alive() {
|
|
151
|
+
return this.#alive;
|
|
152
|
+
}
|
|
153
|
+
#visible;
|
|
154
|
+
get visible() {
|
|
155
|
+
return this.#visible;
|
|
156
|
+
}
|
|
157
|
+
#resolve;
|
|
158
|
+
#listeners = new Set();
|
|
159
|
+
constructor({ id, initiator, title, subtitle, background, dimmed = true, manualDestroy = false, closeOnBackdropClick = true, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
160
|
+
this.id = id;
|
|
161
|
+
this.initiator = initiator;
|
|
162
|
+
this.title = title;
|
|
163
|
+
this.subtitle = subtitle;
|
|
164
|
+
this.background = background;
|
|
165
|
+
this.dimmed = dimmed;
|
|
166
|
+
this.manualDestroy = manualDestroy;
|
|
167
|
+
this.closeOnBackdropClick = closeOnBackdropClick;
|
|
168
|
+
this.ForegroundComponent = ForegroundComponent;
|
|
169
|
+
this.BackgroundComponent = BackgroundComponent;
|
|
170
|
+
this.#alive = true;
|
|
171
|
+
this.#visible = true;
|
|
172
|
+
this.#resolve = resolve;
|
|
173
|
+
}
|
|
174
|
+
subscribe(listener) {
|
|
175
|
+
this.#listeners.add(listener);
|
|
176
|
+
return () => {
|
|
177
|
+
this.#listeners.delete(listener);
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
publish() {
|
|
181
|
+
for (const listener of this.#listeners)
|
|
182
|
+
listener();
|
|
183
|
+
}
|
|
184
|
+
resolve(result) {
|
|
185
|
+
this.#resolve(result);
|
|
186
|
+
}
|
|
187
|
+
onDestroy() {
|
|
188
|
+
const needPublish = this.#alive === true;
|
|
189
|
+
this.#alive = false;
|
|
190
|
+
if (this.manualDestroy && needPublish)
|
|
191
|
+
this.publish();
|
|
192
|
+
}
|
|
193
|
+
onShow() {
|
|
194
|
+
const needPublish = this.#visible === false;
|
|
195
|
+
this.#visible = true;
|
|
196
|
+
if (needPublish)
|
|
197
|
+
this.publish();
|
|
198
|
+
}
|
|
199
|
+
onHide() {
|
|
200
|
+
const needPublish = this.#visible === true;
|
|
201
|
+
this.#visible = false;
|
|
202
|
+
if (needPublish)
|
|
203
|
+
this.publish();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
class AlertNode extends AbstractNode {
|
|
208
|
+
type;
|
|
209
|
+
subtype;
|
|
210
|
+
content;
|
|
211
|
+
footer;
|
|
212
|
+
constructor({ id, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
213
|
+
super({
|
|
214
|
+
id,
|
|
215
|
+
initiator,
|
|
216
|
+
title,
|
|
217
|
+
subtitle,
|
|
218
|
+
background,
|
|
219
|
+
dimmed,
|
|
220
|
+
manualDestroy,
|
|
221
|
+
closeOnBackdropClick,
|
|
222
|
+
resolve,
|
|
223
|
+
ForegroundComponent,
|
|
224
|
+
BackgroundComponent,
|
|
225
|
+
});
|
|
226
|
+
this.type = type;
|
|
227
|
+
this.subtype = subtype;
|
|
228
|
+
this.content = content;
|
|
229
|
+
this.footer = footer;
|
|
230
|
+
}
|
|
231
|
+
onClose() {
|
|
232
|
+
this.resolve(null);
|
|
233
|
+
}
|
|
234
|
+
onConfirm() {
|
|
235
|
+
this.resolve(null);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
class ConfirmNode extends AbstractNode {
|
|
240
|
+
type;
|
|
241
|
+
subtype;
|
|
242
|
+
content;
|
|
243
|
+
footer;
|
|
244
|
+
constructor({ id, initiator, type, subtype, title, subtitle, content, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
245
|
+
super({
|
|
246
|
+
id,
|
|
247
|
+
initiator,
|
|
248
|
+
title,
|
|
249
|
+
subtitle,
|
|
250
|
+
background,
|
|
251
|
+
dimmed,
|
|
252
|
+
manualDestroy,
|
|
253
|
+
closeOnBackdropClick,
|
|
254
|
+
resolve,
|
|
255
|
+
ForegroundComponent,
|
|
256
|
+
BackgroundComponent,
|
|
257
|
+
});
|
|
258
|
+
this.type = type;
|
|
259
|
+
this.subtype = subtype;
|
|
260
|
+
this.content = content;
|
|
261
|
+
this.footer = footer;
|
|
262
|
+
}
|
|
263
|
+
onClose() {
|
|
264
|
+
this.resolve(false);
|
|
265
|
+
}
|
|
266
|
+
onConfirm() {
|
|
267
|
+
this.resolve(true);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
class PromptNode extends AbstractNode {
|
|
272
|
+
type;
|
|
273
|
+
content;
|
|
274
|
+
defaultValue;
|
|
275
|
+
Input;
|
|
276
|
+
disabled;
|
|
277
|
+
returnOnCancel;
|
|
278
|
+
footer;
|
|
279
|
+
#value;
|
|
280
|
+
constructor({ id, initiator, type, title, subtitle, content, defaultValue, Input, disabled, returnOnCancel, footer, background, dimmed, manualDestroy, closeOnBackdropClick, resolve, ForegroundComponent, BackgroundComponent, }) {
|
|
281
|
+
super({
|
|
282
|
+
id,
|
|
283
|
+
initiator,
|
|
284
|
+
title,
|
|
285
|
+
subtitle,
|
|
286
|
+
background,
|
|
287
|
+
dimmed,
|
|
288
|
+
manualDestroy,
|
|
289
|
+
closeOnBackdropClick,
|
|
290
|
+
resolve,
|
|
291
|
+
ForegroundComponent,
|
|
292
|
+
BackgroundComponent,
|
|
293
|
+
});
|
|
294
|
+
this.type = type;
|
|
295
|
+
this.content = content;
|
|
296
|
+
this.Input = Input;
|
|
297
|
+
this.defaultValue = defaultValue;
|
|
298
|
+
this.#value = defaultValue;
|
|
299
|
+
this.disabled = disabled;
|
|
300
|
+
this.returnOnCancel = returnOnCancel;
|
|
301
|
+
this.footer = footer;
|
|
302
|
+
}
|
|
303
|
+
onChange(value) {
|
|
304
|
+
this.#value = value;
|
|
305
|
+
}
|
|
306
|
+
onConfirm() {
|
|
307
|
+
this.resolve(this.#value ?? null);
|
|
308
|
+
}
|
|
309
|
+
onClose() {
|
|
310
|
+
if (this.returnOnCancel)
|
|
311
|
+
this.resolve(this.#value ?? null);
|
|
312
|
+
else
|
|
313
|
+
this.resolve(null);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
const nodeFactory = (modal) => {
|
|
318
|
+
switch (modal.type) {
|
|
319
|
+
case 'alert':
|
|
320
|
+
return new AlertNode(modal);
|
|
321
|
+
case 'confirm':
|
|
322
|
+
return new ConfirmNode(modal);
|
|
323
|
+
case 'prompt':
|
|
324
|
+
return new PromptNode(modal);
|
|
325
|
+
}
|
|
326
|
+
throw new Error(`Unknown modal: ${modal.type}`, { modal });
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const DEFAULT_ANIMATION_DURATION = '300ms';
|
|
330
|
+
const DEFAULT_BACKDROP_COLOR = 'rgba(0, 0, 0, 0.5)';
|
|
331
|
+
|
|
332
|
+
const fallback = css.css `
|
|
333
|
+
margin: unset;
|
|
334
|
+
`;
|
|
335
|
+
const frame = css.css `
|
|
336
|
+
display: flex;
|
|
337
|
+
flex-direction: column;
|
|
338
|
+
justify-content: center;
|
|
339
|
+
align-items: center;
|
|
340
|
+
background-color: white;
|
|
341
|
+
padding: 20px 80px;
|
|
342
|
+
gap: 10px;
|
|
343
|
+
border: 1px solid black;
|
|
344
|
+
`;
|
|
345
|
+
|
|
346
|
+
const FallbackTitle = ({ children }) => {
|
|
347
|
+
return jsxRuntime.jsx("h2", { className: fallback, children: children });
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
const FallbackSubtitle = ({ children }) => {
|
|
351
|
+
return jsxRuntime.jsx("h3", { className: fallback, children: children });
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
const FallbackContent = ({ children }) => {
|
|
355
|
+
return jsxRuntime.jsx("div", { className: fallback, children: children });
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
const FallbackFooter = ({ confirmLabel, hideConfirm = false, cancelLabel, hideCancel = false, disabled, onConfirm, onCancel, }) => {
|
|
359
|
+
return (jsxRuntime.jsxs("div", { children: [!hideConfirm && (jsxRuntime.jsx("button", { onClick: onConfirm, disabled: disabled, children: confirmLabel || 'Confirm' })), !hideCancel && typeof onCancel === 'function' && (jsxRuntime.jsx("button", { onClick: onCancel, children: cancelLabel || 'Cancel' }))] }));
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
const ModalManagerContext = react.createContext({});
|
|
363
|
+
|
|
364
|
+
const useModalManagerContext = () => react.useContext(ModalManagerContext);
|
|
365
|
+
const useModal = (id) => {
|
|
366
|
+
const { getModal } = useModalManagerContext();
|
|
367
|
+
return react.useMemo(() => getModal(id), [id, getModal]);
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
const defaultValidate = (modal) => modal?.visible;
|
|
371
|
+
const useActiveModalCount = (validate = defaultValidate, refreshKey = 0) => {
|
|
372
|
+
const { modalIds, getModalNode } = useModalManagerContext();
|
|
373
|
+
return react.useMemo(() => {
|
|
374
|
+
let count = 0;
|
|
375
|
+
for (const id of modalIds) {
|
|
376
|
+
if (validate(getModalNode(id)))
|
|
377
|
+
count++;
|
|
378
|
+
}
|
|
379
|
+
return count;
|
|
380
|
+
}, [getModalNode, modalIds, refreshKey]);
|
|
381
|
+
};
|
|
382
|
+
|
|
383
|
+
const MAX_MODAL_COUNT = 5;
|
|
384
|
+
const MAX_MODAL_LEVEL = 3;
|
|
385
|
+
const FallbackForegroundFrame = react.forwardRef(({ id, onChangeOrder, children }, ref) => {
|
|
386
|
+
const activeCount = useActiveModalCount();
|
|
387
|
+
const [level, offset] = react.useMemo(() => {
|
|
388
|
+
const stacked = activeCount > 1;
|
|
389
|
+
const level = stacked
|
|
390
|
+
? (Math.floor(id / MAX_MODAL_COUNT) % MAX_MODAL_LEVEL) * 100
|
|
391
|
+
: 0;
|
|
392
|
+
const offset = stacked ? (id % MAX_MODAL_COUNT) * 35 : 0;
|
|
393
|
+
return [level, offset];
|
|
394
|
+
}, [activeCount, id]);
|
|
395
|
+
return (jsxRuntime.jsx("div", { ref: ref, className: frame, onClick: onChangeOrder, style: {
|
|
396
|
+
marginBottom: `calc(25vh + ${level}px)`,
|
|
397
|
+
marginLeft: `${level}px`,
|
|
398
|
+
transform: `translate(${offset}px, ${offset}px)`,
|
|
399
|
+
}, children: children }));
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
const ConfigurationContext = react.createContext({});
|
|
403
|
+
|
|
404
|
+
const ConfigurationContextProvider = react.memo(({ ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, options, children, }) => {
|
|
405
|
+
const value = react.useMemo(() => ({
|
|
406
|
+
BackgroundComponent,
|
|
407
|
+
ForegroundComponent: ForegroundComponent || FallbackForegroundFrame,
|
|
408
|
+
TitleComponent: TitleComponent || FallbackTitle,
|
|
409
|
+
SubtitleComponent: SubtitleComponent || FallbackSubtitle,
|
|
410
|
+
ContentComponent: react.memo(ContentComponent || FallbackContent),
|
|
411
|
+
FooterComponent: react.memo(FooterComponent || FallbackFooter),
|
|
412
|
+
options: {
|
|
413
|
+
duration: DEFAULT_ANIMATION_DURATION,
|
|
414
|
+
backdrop: DEFAULT_BACKDROP_COLOR,
|
|
415
|
+
closeOnBackdropClick: true,
|
|
416
|
+
manualDestroy: false,
|
|
417
|
+
...options,
|
|
418
|
+
},
|
|
419
|
+
}), [
|
|
420
|
+
ForegroundComponent,
|
|
421
|
+
BackgroundComponent,
|
|
422
|
+
ContentComponent,
|
|
423
|
+
FooterComponent,
|
|
424
|
+
SubtitleComponent,
|
|
425
|
+
TitleComponent,
|
|
426
|
+
options,
|
|
427
|
+
]);
|
|
428
|
+
return (jsxRuntime.jsx(ConfigurationContext.Provider, { value: value, children: children }));
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
const useConfigurationContext = () => react.useContext(ConfigurationContext);
|
|
432
|
+
const useConfigurationOptions = () => {
|
|
433
|
+
const context = react.useContext(ConfigurationContext);
|
|
434
|
+
return context.options;
|
|
435
|
+
};
|
|
436
|
+
const useConfigurationDuration = () => {
|
|
437
|
+
const context = useConfigurationOptions();
|
|
438
|
+
return {
|
|
439
|
+
duration: context.duration,
|
|
440
|
+
milliseconds: convert.convertMsFromDuration(context.duration),
|
|
441
|
+
};
|
|
442
|
+
};
|
|
443
|
+
const useConfigurationBackdrop = () => {
|
|
444
|
+
const context = useConfigurationOptions();
|
|
445
|
+
return context.backdrop;
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
const ModalManagerContextProvider = react.memo(({ usePathname, children, }) => {
|
|
449
|
+
const modalDictionary = react.useRef(new Map());
|
|
450
|
+
const [modalIds, setModalIds] = react.useState([]);
|
|
451
|
+
const modalIdsRef = hook.useReference(modalIds);
|
|
452
|
+
const { pathname } = usePathname();
|
|
453
|
+
const initiator = react.useRef(pathname);
|
|
454
|
+
const modalIdSequence = react.useRef(0);
|
|
455
|
+
const options = useConfigurationOptions();
|
|
456
|
+
const duration = react.useMemo(() => convert.convertMsFromDuration(options.duration), [options]);
|
|
457
|
+
hook.useOnMountLayout(() => {
|
|
458
|
+
const { manualDestroy, closeOnBackdropClick } = options;
|
|
459
|
+
for (const data of ModalManager.prerender) {
|
|
460
|
+
const modal = nodeFactory({
|
|
461
|
+
...data,
|
|
462
|
+
id: modalIdSequence.current++,
|
|
463
|
+
initiator: initiator.current,
|
|
464
|
+
manualDestroy: data.manualDestroy !== undefined
|
|
465
|
+
? data.manualDestroy
|
|
466
|
+
: manualDestroy,
|
|
467
|
+
closeOnBackdropClick: data.closeOnBackdropClick !== undefined
|
|
468
|
+
? data.closeOnBackdropClick
|
|
469
|
+
: closeOnBackdropClick,
|
|
470
|
+
});
|
|
471
|
+
modalDictionary.current.set(modal.id, modal);
|
|
472
|
+
setModalIds((ids) => [...ids, modal.id]);
|
|
473
|
+
}
|
|
474
|
+
ModalManager.openHandler = (data) => {
|
|
475
|
+
const modal = nodeFactory({
|
|
476
|
+
...data,
|
|
477
|
+
id: modalIdSequence.current++,
|
|
478
|
+
initiator: initiator.current,
|
|
479
|
+
manualDestroy: data.manualDestroy !== undefined
|
|
480
|
+
? data.manualDestroy
|
|
481
|
+
: manualDestroy,
|
|
482
|
+
closeOnBackdropClick: data.closeOnBackdropClick !== undefined
|
|
483
|
+
? data.closeOnBackdropClick
|
|
484
|
+
: closeOnBackdropClick,
|
|
485
|
+
});
|
|
486
|
+
modalDictionary.current.set(modal.id, modal);
|
|
487
|
+
setModalIds((ids) => {
|
|
488
|
+
const aliveIds = [];
|
|
489
|
+
for (let index = 0; index < ids.length; index++) {
|
|
490
|
+
const id = ids[index];
|
|
491
|
+
const destroyed = !modalDictionary.current.get(id)?.alive;
|
|
492
|
+
if (destroyed)
|
|
493
|
+
modalDictionary.current.delete(id);
|
|
494
|
+
else
|
|
495
|
+
aliveIds.push(id);
|
|
496
|
+
}
|
|
497
|
+
return [...aliveIds, modal.id];
|
|
498
|
+
});
|
|
499
|
+
};
|
|
500
|
+
return () => {
|
|
501
|
+
ModalManager.reset();
|
|
502
|
+
};
|
|
503
|
+
});
|
|
504
|
+
react.useLayoutEffect(() => {
|
|
505
|
+
for (const id of modalIdsRef.current) {
|
|
506
|
+
const modal = modalDictionary.current.get(id);
|
|
507
|
+
if (!modal?.alive)
|
|
508
|
+
continue;
|
|
509
|
+
if (modal.initiator === pathname)
|
|
510
|
+
modal.onShow();
|
|
511
|
+
else
|
|
512
|
+
modal.onHide();
|
|
513
|
+
}
|
|
514
|
+
initiator.current = pathname;
|
|
515
|
+
}, [pathname]);
|
|
516
|
+
const getModalNode = react.useCallback((modalId) => {
|
|
517
|
+
return modalDictionary.current.get(modalId);
|
|
518
|
+
}, []);
|
|
519
|
+
const onDestroy = react.useCallback((modalId) => {
|
|
520
|
+
const modal = modalDictionary.current.get(modalId);
|
|
521
|
+
if (!modal)
|
|
522
|
+
return;
|
|
523
|
+
modal.onDestroy();
|
|
524
|
+
updaterRef.current?.();
|
|
525
|
+
}, []);
|
|
526
|
+
const updaterRef = react.useRef(undefined);
|
|
527
|
+
const hideModal = react.useCallback((modalId) => {
|
|
528
|
+
const modal = modalDictionary.current.get(modalId);
|
|
529
|
+
if (!modal)
|
|
530
|
+
return;
|
|
531
|
+
modal.onHide();
|
|
532
|
+
updaterRef.current?.();
|
|
533
|
+
if (!modal.manualDestroy)
|
|
534
|
+
setTimeout(() => {
|
|
535
|
+
modal.onDestroy();
|
|
536
|
+
}, duration);
|
|
537
|
+
}, [duration]);
|
|
538
|
+
const onChange = react.useCallback((modalId, value) => {
|
|
539
|
+
const modal = modalDictionary.current.get(modalId);
|
|
540
|
+
if (!modal)
|
|
541
|
+
return;
|
|
542
|
+
if (modal.type === 'prompt')
|
|
543
|
+
modal.onChange(value);
|
|
544
|
+
}, []);
|
|
545
|
+
const onConfirm = react.useCallback((modalId) => {
|
|
546
|
+
const modal = modalDictionary.current.get(modalId);
|
|
547
|
+
if (!modal)
|
|
548
|
+
return;
|
|
549
|
+
modal.onConfirm();
|
|
550
|
+
hideModal(modalId);
|
|
551
|
+
}, [hideModal]);
|
|
552
|
+
const onClose = react.useCallback((modalId) => {
|
|
553
|
+
const modal = modalDictionary.current.get(modalId);
|
|
554
|
+
if (!modal)
|
|
555
|
+
return;
|
|
556
|
+
modal.onClose();
|
|
557
|
+
hideModal(modalId);
|
|
558
|
+
}, [hideModal]);
|
|
559
|
+
const getModal = react.useCallback((modalId) => ({
|
|
560
|
+
modal: getModalNode(modalId),
|
|
561
|
+
onConfirm: () => onConfirm(modalId),
|
|
562
|
+
onClose: () => onClose(modalId),
|
|
563
|
+
onChange: (value) => onChange(modalId, value),
|
|
564
|
+
onDestroy: () => onDestroy(modalId),
|
|
565
|
+
}), [getModalNode, onConfirm, onClose, onChange, onDestroy]);
|
|
566
|
+
const value = react.useMemo(() => {
|
|
567
|
+
return {
|
|
568
|
+
modalIds,
|
|
569
|
+
getModalNode,
|
|
570
|
+
onChange,
|
|
571
|
+
onConfirm,
|
|
572
|
+
onClose,
|
|
573
|
+
onDestroy,
|
|
574
|
+
getModal,
|
|
575
|
+
setUpdater: (updater) => {
|
|
576
|
+
updaterRef.current = updater;
|
|
577
|
+
},
|
|
578
|
+
};
|
|
579
|
+
}, [
|
|
580
|
+
modalIds,
|
|
581
|
+
getModal,
|
|
582
|
+
getModalNode,
|
|
583
|
+
onChange,
|
|
584
|
+
onConfirm,
|
|
585
|
+
onClose,
|
|
586
|
+
onDestroy,
|
|
587
|
+
]);
|
|
588
|
+
return (jsxRuntime.jsx(ModalManagerContext.Provider, { value: value, children: children }));
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
const UserDefinedContext = react.createContext({});
|
|
592
|
+
|
|
593
|
+
const UserDefinedContextProvider = ({ context, children, }) => {
|
|
594
|
+
const contextValue = react.useMemo(() => ({ context: context || {} }), [context]);
|
|
595
|
+
return (jsxRuntime.jsx(UserDefinedContext.Provider, { value: contextValue, children: children }));
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
const useUserDefinedContext = () => {
|
|
599
|
+
return react.useContext(UserDefinedContext);
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
const usePathname = () => {
|
|
603
|
+
const [pathname, setPathname] = react.useState(window.location.pathname);
|
|
604
|
+
react.useLayoutEffect(() => {
|
|
605
|
+
let requestId;
|
|
606
|
+
const checkPathname = () => {
|
|
607
|
+
if (requestId)
|
|
608
|
+
cancelAnimationFrame(requestId);
|
|
609
|
+
if (pathname !== window.location.pathname) {
|
|
610
|
+
setPathname(window.location.pathname);
|
|
611
|
+
}
|
|
612
|
+
else {
|
|
613
|
+
requestId = requestAnimationFrame(checkPathname);
|
|
614
|
+
}
|
|
615
|
+
};
|
|
616
|
+
requestId = requestAnimationFrame(checkPathname);
|
|
617
|
+
return () => {
|
|
618
|
+
if (requestId)
|
|
619
|
+
cancelAnimationFrame(requestId);
|
|
620
|
+
};
|
|
621
|
+
}, [pathname]);
|
|
622
|
+
return { pathname };
|
|
623
|
+
};
|
|
624
|
+
|
|
625
|
+
const background = css.css `
|
|
626
|
+
display: none;
|
|
627
|
+
position: fixed;
|
|
628
|
+
inset: 0;
|
|
629
|
+
z-index: -999;
|
|
630
|
+
pointer-events: none;
|
|
631
|
+
> * {
|
|
632
|
+
pointer-events: none;
|
|
633
|
+
}
|
|
634
|
+
`;
|
|
635
|
+
const active$1 = css.css `
|
|
636
|
+
pointer-events: all;
|
|
637
|
+
`;
|
|
638
|
+
const visible$1 = css.css `
|
|
639
|
+
display: flex;
|
|
640
|
+
align-items: center;
|
|
641
|
+
justify-content: center;
|
|
642
|
+
`;
|
|
643
|
+
|
|
644
|
+
const BackgroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
645
|
+
const { BackgroundComponent } = useConfigurationContext();
|
|
646
|
+
const { context: userDefinedContext } = useUserDefinedContext();
|
|
647
|
+
const { modal, onClose, onChange, onConfirm, onDestroy } = useModal(modalId);
|
|
648
|
+
const handleClose = react.useCallback((event) => {
|
|
649
|
+
if (modal && modal.closeOnBackdropClick && modal.visible)
|
|
650
|
+
onClose();
|
|
651
|
+
event.stopPropagation();
|
|
652
|
+
}, [modal, onClose]);
|
|
653
|
+
const Background = react.useMemo(() => modal?.BackgroundComponent || BackgroundComponent, [BackgroundComponent, modal]);
|
|
654
|
+
if (!modal)
|
|
655
|
+
return null;
|
|
656
|
+
return (jsxRuntime.jsx("div", { className: css.cx(background, {
|
|
657
|
+
[visible$1]: modal.manualDestroy ? modal.alive : modal.visible,
|
|
658
|
+
[active$1]: modal.closeOnBackdropClick && modal.visible,
|
|
659
|
+
}), onClick: handleClose, children: Background && (jsxRuntime.jsx(Background, { id: modal.id, type: modal.type, alive: modal.alive, visible: modal.visible, initiator: modal.initiator, manualDestroy: modal.manualDestroy, closeOnBackdropClick: modal.closeOnBackdropClick, background: modal.background, onChange: onChange, onConfirm: onConfirm, onClose: onClose, onDestroy: onDestroy, onChangeOrder: onChangeOrder, context: userDefinedContext })) }));
|
|
660
|
+
};
|
|
661
|
+
|
|
662
|
+
const foreground = css.css `
|
|
663
|
+
pointer-events: none;
|
|
664
|
+
display: none;
|
|
665
|
+
position: fixed;
|
|
666
|
+
inset: 0;
|
|
667
|
+
z-index: 1;
|
|
668
|
+
`;
|
|
669
|
+
const active = css.css `
|
|
670
|
+
> * {
|
|
671
|
+
pointer-events: all;
|
|
672
|
+
}
|
|
673
|
+
`;
|
|
674
|
+
const visible = css.css `
|
|
675
|
+
display: flex !important;
|
|
676
|
+
justify-content: center;
|
|
677
|
+
align-items: center;
|
|
678
|
+
`;
|
|
679
|
+
|
|
680
|
+
const AlertInner = react.memo(({ modal, handlers }) => {
|
|
681
|
+
const { title, subtitle, content, footer } = react.useMemo(() => modal, [modal]);
|
|
682
|
+
const { context: userDefinedContext } = useUserDefinedContext();
|
|
683
|
+
const { onConfirm } = react.useMemo(() => handlers, [handlers]);
|
|
684
|
+
const handleConfirm = hook.useHandle(onConfirm);
|
|
685
|
+
const { TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, } = useConfigurationContext();
|
|
686
|
+
return (jsxRuntime.jsxs(react.Fragment, { children: [title &&
|
|
687
|
+
(filter.isString(title) ? (jsxRuntime.jsx(TitleComponent, { context: userDefinedContext, children: title })) : (title)), subtitle &&
|
|
688
|
+
(filter.isString(subtitle) ? (jsxRuntime.jsx(SubtitleComponent, { context: userDefinedContext, children: subtitle })) : (subtitle)), content &&
|
|
689
|
+
(filter.isString(content) ? (jsxRuntime.jsx(ContentComponent, { context: userDefinedContext, children: content })) : (render.renderComponent(content, {
|
|
690
|
+
onConfirm: handleConfirm,
|
|
691
|
+
}))), footer !== false &&
|
|
692
|
+
(typeof footer === 'function' ? (footer({
|
|
693
|
+
onConfirm: handleConfirm,
|
|
694
|
+
context: userDefinedContext,
|
|
695
|
+
})) : (jsxRuntime.jsx(FooterComponent, { onConfirm: handleConfirm, confirmLabel: footer?.confirm, hideConfirm: footer?.hideConfirm, context: userDefinedContext })))] }));
|
|
696
|
+
});
|
|
697
|
+
|
|
698
|
+
const ConfirmInner = react.memo(({ modal, handlers }) => {
|
|
699
|
+
const { title, subtitle, content, footer } = react.useMemo(() => modal, [modal]);
|
|
700
|
+
const { context: userDefinedContext } = useUserDefinedContext();
|
|
701
|
+
const { onConfirm, onClose } = react.useMemo(() => handlers, [handlers]);
|
|
702
|
+
const handleConfirm = hook.useHandle(onConfirm);
|
|
703
|
+
const handleClose = hook.useHandle(onClose);
|
|
704
|
+
const { TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, } = useConfigurationContext();
|
|
705
|
+
return (jsxRuntime.jsxs(react.Fragment, { children: [title &&
|
|
706
|
+
(filter.isString(title) ? (jsxRuntime.jsx(TitleComponent, { context: userDefinedContext, children: title })) : (title)), subtitle &&
|
|
707
|
+
(filter.isString(subtitle) ? (jsxRuntime.jsx(SubtitleComponent, { context: userDefinedContext, children: subtitle })) : (subtitle)), content &&
|
|
708
|
+
(filter.isString(content) ? (jsxRuntime.jsx(ContentComponent, { context: userDefinedContext, children: content })) : (render.renderComponent(content, {
|
|
709
|
+
onConfirm: handleConfirm,
|
|
710
|
+
onCancel: handleClose,
|
|
711
|
+
context: userDefinedContext,
|
|
712
|
+
}))), footer !== false &&
|
|
713
|
+
(typeof footer === 'function' ? (footer({
|
|
714
|
+
onConfirm: handleConfirm,
|
|
715
|
+
onCancel: handleClose,
|
|
716
|
+
context: userDefinedContext,
|
|
717
|
+
})) : (jsxRuntime.jsx(FooterComponent, { onConfirm: handleConfirm, onCancel: handleClose, confirmLabel: footer?.confirm, cancelLabel: footer?.cancel, hideConfirm: footer?.hideConfirm, hideCancel: footer?.hideCancel, context: userDefinedContext })))] }));
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
const PromptInner = react.memo(({ modal, handlers }) => {
|
|
721
|
+
const { Input, defaultValue, disabled: checkDisabled, title, subtitle, content, footer, } = react.useMemo(() => ({
|
|
722
|
+
...modal,
|
|
723
|
+
Input: react.memo(hoc.withErrorBoundary(modal.Input)),
|
|
724
|
+
}), [modal]);
|
|
725
|
+
const { context: userDefinedContext } = useUserDefinedContext();
|
|
726
|
+
const [value, setValue] = react.useState(defaultValue);
|
|
727
|
+
const { onChange, onClose, onConfirm } = react.useMemo(() => handlers, [handlers]);
|
|
728
|
+
const handleClose = hook.useHandle(onClose);
|
|
729
|
+
const handleChange = hook.useHandle((inputValue) => {
|
|
730
|
+
const input = filter.isFunction(inputValue) ? inputValue(value) : inputValue;
|
|
731
|
+
setValue(input);
|
|
732
|
+
onChange(input);
|
|
733
|
+
});
|
|
734
|
+
const handleConfirm = react.useCallback(() => {
|
|
735
|
+
requestAnimationFrame(onConfirm);
|
|
736
|
+
}, [onConfirm]);
|
|
737
|
+
const disabled = react.useMemo(() => (value ? !!checkDisabled?.(value) : false), [checkDisabled, value]);
|
|
738
|
+
const { TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, } = useConfigurationContext();
|
|
739
|
+
return (jsxRuntime.jsxs(react.Fragment, { children: [title &&
|
|
740
|
+
(filter.isString(title) ? (jsxRuntime.jsx(TitleComponent, { context: userDefinedContext, children: title })) : (title)), subtitle &&
|
|
741
|
+
(filter.isString(subtitle) ? (jsxRuntime.jsx(SubtitleComponent, { context: userDefinedContext, children: subtitle })) : (subtitle)), content &&
|
|
742
|
+
(filter.isString(content) ? (jsxRuntime.jsx(ContentComponent, { context: userDefinedContext, children: content })) : (render.renderComponent(content, {
|
|
743
|
+
onConfirm: handleConfirm,
|
|
744
|
+
onCancel: handleClose,
|
|
745
|
+
context: userDefinedContext,
|
|
746
|
+
}))), Input && (jsxRuntime.jsx(Input, { defaultValue: defaultValue, value: value, onChange: handleChange, onConfirm: handleConfirm, onCancel: handleClose, context: userDefinedContext })), footer !== false &&
|
|
747
|
+
(typeof footer === 'function' ? (footer({
|
|
748
|
+
value,
|
|
749
|
+
disabled,
|
|
750
|
+
onChange: handleChange,
|
|
751
|
+
onConfirm: handleConfirm,
|
|
752
|
+
onCancel: handleClose,
|
|
753
|
+
context: userDefinedContext,
|
|
754
|
+
})) : (jsxRuntime.jsx(FooterComponent, { disabled: disabled, onConfirm: handleConfirm, onCancel: handleClose, confirmLabel: footer?.confirm, cancelLabel: footer?.cancel, hideConfirm: footer?.hideConfirm, hideCancel: footer?.hideCancel, context: userDefinedContext })))] }));
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
const ForegroundFrame = ({ modalId, onChangeOrder, }) => {
|
|
758
|
+
const { ForegroundComponent } = useConfigurationContext();
|
|
759
|
+
const { context: userDefinedContext } = useUserDefinedContext();
|
|
760
|
+
const { modal, onChange, onConfirm, onClose, onDestroy } = useModal(modalId);
|
|
761
|
+
const Foreground = react.useMemo(() => modal?.ForegroundComponent || ForegroundComponent, [ForegroundComponent, modal]);
|
|
762
|
+
if (!modal)
|
|
763
|
+
return null;
|
|
764
|
+
return (jsxRuntime.jsx("div", { className: css.cx(foreground, {
|
|
765
|
+
[visible]: modal.manualDestroy ? modal.alive : modal.visible,
|
|
766
|
+
[active]: modal.visible,
|
|
767
|
+
}), children: jsxRuntime.jsxs(Foreground, { id: modal.id, type: modal.type, alive: modal.alive, visible: modal.visible, initiator: modal.initiator, manualDestroy: modal.manualDestroy, closeOnBackdropClick: modal.closeOnBackdropClick, background: modal.background, onChange: onChange, onConfirm: onConfirm, onClose: onClose, onDestroy: onDestroy, onChangeOrder: onChangeOrder, context: userDefinedContext, children: [modal.type === 'alert' && (jsxRuntime.jsx(AlertInner, { modal: modal, handlers: { onConfirm } })), modal.type === 'confirm' && (jsxRuntime.jsx(ConfirmInner, { modal: modal, handlers: { onConfirm, onClose } })), modal.type === 'prompt' && (jsxRuntime.jsx(PromptInner, { modal: modal, handlers: { onChange, onConfirm, onClose } }))] }) }));
|
|
768
|
+
};
|
|
769
|
+
|
|
770
|
+
const useSubscribeModal = (modal) => {
|
|
771
|
+
const [version, update] = hook.useVersion();
|
|
772
|
+
react.useEffect(() => {
|
|
773
|
+
if (!modal)
|
|
774
|
+
return;
|
|
775
|
+
const unsubscribe = modal.subscribe(update);
|
|
776
|
+
return unsubscribe;
|
|
777
|
+
}, [modal, update]);
|
|
778
|
+
return version;
|
|
779
|
+
};
|
|
780
|
+
|
|
781
|
+
const presenter = css.css `
|
|
782
|
+
position: fixed;
|
|
783
|
+
inset: 0;
|
|
784
|
+
pointer-events: none;
|
|
785
|
+
overflow: hidden;
|
|
786
|
+
`;
|
|
787
|
+
|
|
788
|
+
const { increment } = lib.counterFactory(1);
|
|
789
|
+
const Presenter = react.memo(({ modalId }) => {
|
|
790
|
+
const ref = react.useRef(null);
|
|
791
|
+
const { modal } = useModal(modalId);
|
|
792
|
+
useSubscribeModal(modal);
|
|
793
|
+
const handleChangeOrder = hook.useHandle(() => {
|
|
794
|
+
if (ref.current) {
|
|
795
|
+
ref.current.style.zIndex = `${increment()}`;
|
|
796
|
+
}
|
|
797
|
+
});
|
|
798
|
+
return (jsxRuntime.jsxs("div", { ref: ref, className: presenter, children: [jsxRuntime.jsx(BackgroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder }), jsxRuntime.jsx(ForegroundFrame, { modalId: modalId, onChangeOrder: handleChangeOrder })] }));
|
|
799
|
+
});
|
|
800
|
+
|
|
801
|
+
const anchor = css.css `
|
|
802
|
+
display: flex;
|
|
803
|
+
align-items: center;
|
|
804
|
+
justify-content: center;
|
|
805
|
+
position: fixed;
|
|
806
|
+
inset: 0;
|
|
807
|
+
pointer-events: none;
|
|
808
|
+
z-index: 1000;
|
|
809
|
+
transition: background-color ease-in-out;
|
|
810
|
+
`;
|
|
811
|
+
|
|
812
|
+
const AnchorInner = () => {
|
|
813
|
+
const [version, update] = hook.useVersion();
|
|
814
|
+
const { modalIds, setUpdater } = useModalManagerContext();
|
|
815
|
+
react.useEffect(() => {
|
|
816
|
+
setUpdater(update);
|
|
817
|
+
}, [setUpdater, update]);
|
|
818
|
+
const options = useConfigurationOptions();
|
|
819
|
+
const dimmed = useActiveModalCount(validateDimmable, version);
|
|
820
|
+
return (jsxRuntime.jsx("div", { className: anchor, style: {
|
|
821
|
+
transitionDuration: options.duration,
|
|
822
|
+
backgroundColor: dimmed ? options.backdrop : 'transparent',
|
|
823
|
+
}, children: array.map(modalIds, (id) => (jsxRuntime.jsx(Presenter, { modalId: id }, id))) }));
|
|
824
|
+
};
|
|
825
|
+
const validateDimmable = (modal) => modal?.visible && modal.dimmed;
|
|
826
|
+
const Anchor = react.memo(hoc.withErrorBoundary(AnchorInner));
|
|
827
|
+
|
|
828
|
+
const bootstrap = ({ ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, usePathname, options, context, anchor, }) => reactDom.createPortal(jsxRuntime.jsx(UserDefinedContextProvider, { context: context, children: jsxRuntime.jsx(ConfigurationContextProvider, { ForegroundComponent: ForegroundComponent, BackgroundComponent: BackgroundComponent, TitleComponent: TitleComponent, SubtitleComponent: SubtitleComponent, ContentComponent: ContentComponent, FooterComponent: FooterComponent, options: options, children: jsxRuntime.jsx(ModalManagerContextProvider, { usePathname: usePathname, children: jsxRuntime.jsx(Anchor, {}) }) }) }), anchor);
|
|
829
|
+
|
|
830
|
+
const useInitialize = () => {
|
|
831
|
+
const permitted = react.useRef(ModalManager.activate());
|
|
832
|
+
const anchorRef = react.useRef(null);
|
|
833
|
+
const [, update] = hook.useVersion();
|
|
834
|
+
const handleInitialize = react.useCallback((root) => {
|
|
835
|
+
if (permitted.current) {
|
|
836
|
+
anchorRef.current = ModalManager.anchor({ root });
|
|
837
|
+
update();
|
|
838
|
+
}
|
|
839
|
+
else
|
|
840
|
+
console.printError('ModalProvider is already initialized', [
|
|
841
|
+
'ModalProvider can only be initialized once.',
|
|
842
|
+
'Nesting ModalProvider will be ignored...',
|
|
843
|
+
], {
|
|
844
|
+
info: 'Something is wrong with the ModalProvider initialization...',
|
|
845
|
+
});
|
|
846
|
+
}, [update]);
|
|
847
|
+
return {
|
|
848
|
+
anchorRef,
|
|
849
|
+
handleInitialize,
|
|
850
|
+
};
|
|
851
|
+
};
|
|
852
|
+
|
|
853
|
+
const BootstrapProvider = react.forwardRef(({ usePathname: useExternalPathname, ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, options, context, children, }, handleRef) => {
|
|
854
|
+
const usePathname$1 = react.useMemo(() => useExternalPathname || usePathname, [useExternalPathname]);
|
|
855
|
+
const { anchorRef, handleInitialize } = useInitialize();
|
|
856
|
+
react.useImperativeHandle(handleRef, () => ({
|
|
857
|
+
initialize: handleInitialize,
|
|
858
|
+
}), [handleInitialize]);
|
|
859
|
+
hook.useOnMount(() => {
|
|
860
|
+
if (handleRef === null)
|
|
861
|
+
handleInitialize();
|
|
862
|
+
return () => {
|
|
863
|
+
if (anchorRef.current)
|
|
864
|
+
anchorRef.current.remove();
|
|
865
|
+
};
|
|
866
|
+
});
|
|
867
|
+
return (jsxRuntime.jsxs(react.Fragment, { children: [children, anchorRef.current &&
|
|
868
|
+
bootstrap({
|
|
869
|
+
ForegroundComponent,
|
|
870
|
+
BackgroundComponent,
|
|
871
|
+
TitleComponent,
|
|
872
|
+
SubtitleComponent,
|
|
873
|
+
ContentComponent,
|
|
874
|
+
FooterComponent,
|
|
875
|
+
usePathname: usePathname$1,
|
|
876
|
+
options,
|
|
877
|
+
context,
|
|
878
|
+
anchor: anchorRef.current,
|
|
879
|
+
})] }));
|
|
880
|
+
});
|
|
881
|
+
|
|
882
|
+
const useBootstrap = ({ usePathname: useExternalPathname, ForegroundComponent, BackgroundComponent, TitleComponent, SubtitleComponent, ContentComponent, FooterComponent, options, context, mode = 'auto', } = {}) => {
|
|
883
|
+
const usePathname$1 = react.useMemo(() => useExternalPathname || usePathname, [useExternalPathname]);
|
|
884
|
+
const { anchorRef, handleInitialize } = useInitialize();
|
|
885
|
+
hook.useOnMount(() => {
|
|
886
|
+
if (mode === 'auto')
|
|
887
|
+
handleInitialize();
|
|
888
|
+
return () => {
|
|
889
|
+
if (anchorRef.current)
|
|
890
|
+
anchorRef.current.remove();
|
|
891
|
+
};
|
|
892
|
+
});
|
|
893
|
+
const initialize = react.useCallback((element) => {
|
|
894
|
+
if (mode === 'manual')
|
|
895
|
+
handleInitialize(element);
|
|
896
|
+
}, [mode, handleInitialize]);
|
|
897
|
+
const portal = anchorRef.current &&
|
|
898
|
+
bootstrap({
|
|
899
|
+
usePathname: usePathname$1,
|
|
900
|
+
ForegroundComponent,
|
|
901
|
+
BackgroundComponent,
|
|
902
|
+
TitleComponent,
|
|
903
|
+
SubtitleComponent,
|
|
904
|
+
ContentComponent,
|
|
905
|
+
FooterComponent,
|
|
906
|
+
options,
|
|
907
|
+
context,
|
|
908
|
+
anchor: anchorRef.current,
|
|
909
|
+
});
|
|
910
|
+
return { portal, initialize };
|
|
911
|
+
};
|
|
912
|
+
|
|
913
|
+
const useDestroyAfter = (modalId, duration) => {
|
|
914
|
+
const { modal, onDestroy } = useModal(modalId);
|
|
915
|
+
const tick = useSubscribeModal(modal);
|
|
916
|
+
const reference = react.useRef({
|
|
917
|
+
modal,
|
|
918
|
+
onDestroy,
|
|
919
|
+
milliseconds: filter.isString(duration)
|
|
920
|
+
? convert.convertMsFromDuration(duration)
|
|
921
|
+
: duration,
|
|
922
|
+
});
|
|
923
|
+
react.useEffect(() => {
|
|
924
|
+
const { modal, onDestroy, milliseconds } = reference.current;
|
|
925
|
+
if (!modal || modal.visible || !modal.alive)
|
|
926
|
+
return;
|
|
927
|
+
const timer = setTimeout(() => {
|
|
928
|
+
onDestroy();
|
|
929
|
+
}, milliseconds);
|
|
930
|
+
return () => {
|
|
931
|
+
if (timer)
|
|
932
|
+
clearTimeout(timer);
|
|
933
|
+
};
|
|
934
|
+
}, [tick]);
|
|
935
|
+
};
|
|
936
|
+
|
|
937
|
+
const useModalAnimation = (visible, handler) => {
|
|
938
|
+
const handlerRef = react.useRef(handler);
|
|
939
|
+
handlerRef.current = handler;
|
|
940
|
+
react.useLayoutEffect(() => {
|
|
941
|
+
if (!handlerRef.current)
|
|
942
|
+
return;
|
|
943
|
+
let frame;
|
|
944
|
+
if (visible)
|
|
945
|
+
frame = requestAnimationFrame(() => handlerRef.current.onVisible?.());
|
|
946
|
+
else
|
|
947
|
+
frame = requestAnimationFrame(() => handlerRef.current.onHidden?.());
|
|
948
|
+
return () => {
|
|
949
|
+
if (frame)
|
|
950
|
+
cancelAnimationFrame(frame);
|
|
951
|
+
};
|
|
952
|
+
}, [visible]);
|
|
953
|
+
};
|
|
954
|
+
|
|
955
|
+
exports.ModalProvider = BootstrapProvider;
|
|
956
|
+
exports.alert = alert;
|
|
957
|
+
exports.confirm = confirm;
|
|
958
|
+
exports.prompt = prompt;
|
|
959
|
+
exports.useActiveModalCount = useActiveModalCount;
|
|
960
|
+
exports.useDestroyAfter = useDestroyAfter;
|
|
961
|
+
exports.useInitializeModal = useBootstrap;
|
|
962
|
+
exports.useModalAnimation = useModalAnimation;
|
|
963
|
+
exports.useModalBackdrop = useConfigurationBackdrop;
|
|
964
|
+
exports.useModalDuration = useConfigurationDuration;
|
|
965
|
+
exports.useModalOptions = useConfigurationOptions;
|
|
966
|
+
exports.useSubscribeModal = useSubscribeModal;
|