@machinemetrics/mm-react-embeddable 1.3.1 → 1.4.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,61 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react"),C=require("prop-types"),O=require("styled-components"),q=e.createContext(null),W=({children:r})=>{const[u,d]=e.useState({}),[i,R]=e.useState({}),c=e.useRef({}),f=e.useRef({}),b=e.useRef({}),T=e.useCallback((t,s)=>{var n;return!!((n=b.current[t])!=null&&n.has(s))},[]),w=e.useCallback((t,s,n)=>{d(o=>({...o,[t]:{origin:s,frameRef:n}}))},[]),h=e.useCallback(t=>{d(s=>{const n={...s};return delete n[t],n}),R(s=>{const n={...s};return delete n[t],n}),delete b.current[t]},[]);e.useEffect(()=>{const t=(n=[],o)=>{n.forEach(a=>a(o))},s=n=>{var $,y,E,m,k;if(!(($=n==null?void 0:n.data)!=null&&$.instanceId))return;const{instanceId:o,type:a}=n.data,l=c.current;if(a==="response"){const{callbackId:I,response:_,error:H}=n.data,U=f.current[I];U&&(U(_,H),delete f.current[I]);return}if(a==="mark-registered"){const{requestType:I}=n.data;b.current[o]||(b.current[o]=new Set),b.current[o].add(I);return}a==="ready"&&R(I=>({...I,[o]:!0})),t((y=l[o])==null?void 0:y[a],n.data),t((E=l["*"])==null?void 0:E[a],n.data),t((m=l[o])==null?void 0:m["*"],n.data),t((k=l["*"])==null?void 0:k["*"],n.data)};return window.addEventListener("message",s),()=>{window.removeEventListener("message",s)}},[u]);const g=e.useCallback((t,s,n)=>{var a,l;const o=u[t];if(!o){console.warn(`Origin not set for id: ${t}. Unable to send message.`);return}(l=(a=o==null?void 0:o.frameRef)==null?void 0:a.current)!=null&&l.contentWindow&&o.frameRef.current.contentWindow.postMessage({type:s,...n,instanceId:t},o.origin)},[u]),M=e.useRef(0),P=e.useCallback(()=>`${Date.now()}-${++M.current}`,[]),F=e.useCallback(async(t,s,n={})=>new Promise((o,a)=>{const l=P(),$=(y,E)=>{delete f.current[l],E?a(E):o(y)};f.current[l]=$,g(t,"request",{callbackId:l,requestType:s,data:n})}),[g]),L=e.useCallback((t,s)=>{g(t,"load-options",s)},[g]),p=e.useCallback((t,s)=>{g(t,"validate",s)},[g]),x=e.useMemo(()=>({registerFrame:w,unregisterFrame:h,sendMessage:g,sendRequest:F,loadOptions:L,validate:p,hasHandler:T,readyFrames:i,addListener:(t,s,n)=>(c.current[t]||(c.current[t]={}),c.current[t][s]||(c.current[t][s]=[]),c.current[t][s].push(n),()=>{c.current[t][s]=c.current[t][s].filter(o=>o!==n)})}),[w,h,g,F,L,p,T,i]);return e.createElement(q.Provider,{value:x},r)},Z={},j=async r=>{try{const u=new URL(r).origin;if(Z[u]!==void 0)return Z[u];const i=await(await fetch(`${u}/mm-app-manifest.json`)).json();if(!i.version)throw new Error("Invalid manifest");return Z[u]=i,i}catch{}return Z[origin]=!1,!1},v=async r=>!!await j(r),S=(r,u,d)=>{const i=e.useContext(q);if(i===null)throw new Error("useEmbeddedEffect must be used within a MMEmbeddableZoneProvider");const R=e.useRef(d);e.useEffect(()=>{R.current=d},[d]),e.useEffect(()=>{if(!(!r||!u)){if(u.startsWith("key:")){const c=u.substring(4);return i.readyFrames[r]&&i.sendMessage(r,"subscribe-key",{keyChord:c}),i.addListener(r,`key-pressed:${c}`,(...b)=>R.current(...b))}return i.addListener(r,u,(...c)=>R.current(...c))}},[i,r,u])};W.propTypes={children:C.node.isRequired};const z=O.default||O,B=1e4,D=z.iframe`
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react"),w=require("prop-types"),q=require("styled-components"),Z=e.createContext(null),B={},_=async n=>{let i;try{if(i=new URL(n).origin,B[i]!==void 0)return B[i];const l=await(await fetch(`${i}/mm-app-manifest.json`)).json();if(!l.version)throw new Error("Invalid manifest");return B[i]=l,l}catch{}return i&&(B[i]=!1),!1},V=async n=>!!await _(n),v=e.createContext({pending:[],authorize:()=>{},dismiss:()=>{},originEpochs:{},credentials:{},unsupported:{}}),se=2e4,A=n=>{try{return new URL(n).origin}catch{return null}},K=n=>{if(!n||/^\d{1,3}(?:\.\d{1,3}){3}$/.test(n)||n.includes(":"))return n;const i=n.split(".");return i.length<=2?n:i.slice(-2).join(".")},G=(n,i)=>{try{const o=new URL(n),l=new URL(i);return o.protocol!==l.protocol?!0:K(o.hostname)!==K(l.hostname)}catch{return!0}},J=(n,{onBlocked:i,onClosed:o})=>{const l=window.open(n.authUrl,"mm-embed-auth","popup,width=600,height=700");if(!l)return i(),()=>{};const m=setInterval(()=>{l.closed&&(clearInterval(m),o())},1e3);return()=>clearInterval(m)},Q=({children:n,launcher:i})=>{const o=e.useContext(Z),[l,m]=e.useState({}),[R,g]=e.useState({}),[p,z]=e.useState({}),[$,x]=e.useState({}),y=e.useRef(p);y.current=p;const b=e.useRef(null),M=e.useRef({}),S=e.useCallback((t,r)=>{_(r).then(s=>{if(!s||!s.name)return;const f=k=>k[t]?{...k,[t]:{...k[t],name:s.name}}:k;m(f),x(f)})},[]),O=e.useCallback((t,r)=>{const s=A(t==null?void 0:t.authUrl);s&&(x(f=>f[s]?f:{...f,[s]:{origin:s,reason:r,name:null}}),S(s,t.authUrl))},[S]),L=e.useCallback((t,{v2:r=!1}={})=>{const s=A(t==null?void 0:t.authUrl);s&&(r&&y.current[s]||(m(f=>f[s]?f:{...f,[s]:{origin:s,authUrl:t.authUrl,silentUrl:t.silentUrl||null,status:r&&t.silentUrl?"silent":"interactive",v2:r,name:null,popupBlocked:!1}}),S(s,t.authUrl)))},[S]),C=e.useCallback(t=>{m(r=>{if(!r[t])return r;const s={...r};return delete s[t],s})},[]),T=e.useCallback(t=>{t&&(C(t),g(r=>({...r,[t]:(r[t]||0)+1})))},[C]),u=e.useCallback(t=>{m(r=>!r[t]||r[t].status==="interactive"?r:{...r,[t]:{...r[t],status:"interactive"}})},[]),d=e.useCallback(t=>{C(t.origin)},[C]),c=e.useCallback(t=>{const r=A(t==null?void 0:t.authUrl);if(r&&G(r,window.location.origin)){O(t,"cross-site-legacy");return}L(t)},[L,O]);e.useEffect(()=>{if(!o)return;const t=[o.addListener("*","authorize",c),o.addListener("*","login",c),o.addListener("*","credential-request",r=>L(r,{v2:!0})),o.addListener("*","authorized",r=>{r!=null&&r.accessToken||T(A(r==null?void 0:r.authUrl))})];return()=>t.forEach(r=>r())},[o,c,L,T]),e.useEffect(()=>{const t=r=>{const s=r==null?void 0:r.data;if(!s||s.type!=="authorized"&&s.type!=="authorize-failed")return;const f=A(s.authUrl);if(!(!f||r.origin!==f)){if(s.type==="authorized"&&s.accessToken){z(k=>({...k,[f]:{accessToken:s.accessToken}})),C(f);return}s.type==="authorize-failed"&&u(f)}};return window.addEventListener("message",t),()=>window.removeEventListener("message",t)},[C,u]),e.useEffect(()=>{const t=M.current;Object.values(l).forEach(r=>{r.status==="silent"&&!t[r.origin]&&(t[r.origin]=setTimeout(()=>{delete t[r.origin],u(r.origin)},se))}),Object.keys(t).forEach(r=>{(!l[r]||l[r].status!=="silent")&&(clearTimeout(t[r]),delete t[r])})},[l,u]),e.useEffect(()=>()=>{b.current&&b.current(),Object.values(M.current).forEach(clearTimeout)},[]);const a=e.useCallback(t=>{b.current&&(b.current(),b.current=null);const r=i||J;b.current=r(t,{onBlocked:()=>{m(s=>s[t.origin]?{...s,[t.origin]:{...s[t.origin],popupBlocked:!0}}:s)},onClosed:()=>{if(t.v2){m(s=>!s[t.origin]||!s[t.origin].silentUrl?s:{...s,[t.origin]:{...s[t.origin],status:"silent"}});return}T(t.origin)}})},[i,T]),h={pending:Object.values(l).filter(t=>t.status==="interactive"),authorize:a,dismiss:d,originEpochs:R,credentials:p,unsupported:$},E=Object.values(l).filter(t=>t.status==="silent"&&t.silentUrl);return e.createElement(v.Provider,{value:h},n,E.map(t=>e.createElement("iframe",{key:`mm-silent-auth-${t.origin}`,src:t.silentUrl,title:`MachineMetrics silent authorization (${t.origin})`,"aria-hidden":"true",tabIndex:-1,style:{display:"none"}})))};Q.propTypes={children:w.node,launcher:w.func};const X=()=>e.useContext(v),Y=n=>{const{originEpochs:i}=e.useContext(v),o=A(n);return o&&i[o]||0},N=n=>{const{credentials:i}=e.useContext(v),o=A(n);return o&&i[o]||null},ee=n=>{const{unsupported:i}=e.useContext(v),o=A(n);return o&&i[o]||null},te=({children:n,authorizationLauncher:i})=>{const[o,l]=e.useState({}),[m,R]=e.useState({}),g=e.useRef({}),p=e.useRef({}),z=e.useRef({}),$=e.useCallback((u,d)=>{var c;return!!((c=z.current[u])!=null&&c.has(d))},[]),x=e.useCallback((u,d,c)=>{l(a=>({...a,[u]:{origin:d,frameRef:c}}))},[]),y=e.useCallback(u=>{l(d=>{const c={...d};return delete c[u],c}),R(d=>{const c={...d};return delete c[u],c}),delete z.current[u]},[]);e.useEffect(()=>{const u=(c=[],a)=>{c.forEach(h=>h(a))},d=c=>{var t,r,s,f,k;if(!((t=c==null?void 0:c.data)!=null&&t.instanceId))return;const{instanceId:a,type:h}=c.data,E=g.current;if(h==="response"){const{callbackId:I,response:P,error:F}=c.data,U=p.current[I];U&&(U(P,F),delete p.current[I]);return}if(h==="mark-registered"){const{requestType:I}=c.data;z.current[a]||(z.current[a]=new Set),z.current[a].add(I);return}h==="ready"&&R(I=>({...I,[a]:!0})),u((r=E[a])==null?void 0:r[h],c.data),u((s=E["*"])==null?void 0:s[h],c.data),u((f=E[a])==null?void 0:f["*"],c.data),u((k=E["*"])==null?void 0:k["*"],c.data)};return window.addEventListener("message",d),()=>{window.removeEventListener("message",d)}},[o]);const b=e.useCallback((u,d,c)=>{var h,E;const a=o[u];if(!a){console.warn(`Origin not set for id: ${u}. Unable to send message.`);return}(E=(h=a==null?void 0:a.frameRef)==null?void 0:h.current)!=null&&E.contentWindow&&a.frameRef.current.contentWindow.postMessage({type:d,...c,instanceId:u},a.origin)},[o]),M=e.useRef(0),S=e.useCallback(()=>`${Date.now()}-${++M.current}`,[]),O=e.useCallback(async(u,d,c={})=>new Promise((a,h)=>{const E=S(),t=(r,s)=>{delete p.current[E],s?h(s):a(r)};p.current[E]=t,b(u,"request",{callbackId:E,requestType:d,data:c})}),[b]),L=e.useCallback((u,d)=>{b(u,"load-options",d)},[b]),C=e.useCallback((u,d)=>{b(u,"validate",d)},[b]),T=e.useMemo(()=>({registerFrame:x,unregisterFrame:y,sendMessage:b,sendRequest:O,loadOptions:L,validate:C,hasHandler:$,readyFrames:m,addListener:(u,d,c)=>(g.current[u]||(g.current[u]={}),g.current[u][d]||(g.current[u][d]=[]),g.current[u][d].push(c),()=>{g.current[u][d]=g.current[u][d].filter(a=>a!==c)})}),[x,y,b,O,L,C,$,m]);return e.createElement(Z.Provider,{value:T},e.createElement(Q,{launcher:i},n))},j=(n,i,o)=>{const l=e.useContext(Z);if(l===null)throw new Error("useEmbeddedEffect must be used within a MMEmbeddableZoneProvider");const m=e.useRef(o);e.useEffect(()=>{m.current=o},[o]),e.useEffect(()=>{if(!(!n||!i)){if(i.startsWith("key:")){const R=i.substring(4);return l.readyFrames[n]&&l.sendMessage(n,"subscribe-key",{keyChord:R}),l.addListener(n,`key-pressed:${R}`,(...p)=>m.current(...p))}return l.addListener(n,i,(...R)=>m.current(...R))}},[l,n,i])};te.propTypes={children:w.node.isRequired,authorizationLauncher:w.func};const D=q.default||q,oe=1e4,ie="credentials",W=(n,i)=>`${n}/mm-embedded-interop?id=${i}&origin=${window.location.origin}&caps=${ie}`,ue=D.iframe`
2
2
  width: 100%;
3
3
  height: 100%;
4
4
  border: none;
5
- visibility: ${r=>r.$isReady?"visible":"hidden"};
6
- `,A=({id:r,src:u,path:d,onInit:i=()=>{},onTimeout:R,context:c={},params:f={},skipManifestCheck:b=!1,...T})=>{if("isConfiguring"in T)return console.error("isConfiguring must be passed via the params prop to MMEmbeddableZone"),null;if("colorMode"in c)return console.error("colorMode must be passed via the params prop to MMEmbeddableZone"),null;if("isFullScreen"in c)return console.error("isFullScreen must be passed via the params prop to MMEmbeddableZone"),null;const w=e.useRef(),[h,g]=e.useState(),[M,P]=e.useState(0),{registerFrame:F,unregisterFrame:L,sendMessage:p}=e.useContext(q),[x,t]=e.useState(!0),[s,n]=e.useState(),o=e.useRef(),a=e.useRef(R),l=e.useRef(i),$=e.useRef(!1);e.useEffect(()=>{a.current=R},[R]),e.useEffect(()=>{l.current=i},[i]),e.useEffect(()=>{M&&p(r,"set-context",{context:{...c,colorMode:f.colorMode,isFullScreen:f.isFullScreen}})},[c,f.colorMode,f.isFullScreen,r,M]),e.useEffect(()=>{M&&(p(r,"set-params",{params:f}),p(r,"set-configuring",{isConfiguring:f.isConfiguring}))},[f,r,M]),e.useEffect(()=>{d!==void 0&&n((d==null?void 0:d.indexOf("/"))===0?d:`/${d}`)},[d]),e.useEffect(()=>{s===void 0||!M||p(r,"navigate",{path:s})},[s,M,r,p]),e.useEffect(()=>{if(!(!u||!r||!w)){if(b){const m=new URL(u);t(!0),F(r,m.origin,w),l.current(),g(`${m.origin}/mm-embedded-interop?id=${r}&origin=${window.location.origin}`)}else(async()=>{const m=await v(u);if(t(m),m){const k=new URL(u);F(r,k.origin,w),l.current(),g(`${k.origin}/mm-embedded-interop?id=${r}&origin=${window.location.origin}`)}})();return()=>{L(r)}}},[u,r,F,w,b]),e.useEffect(()=>{if(!(!b||!h||$.current))return o.current=setTimeout(()=>{a.current&&a.current()},B),()=>clearTimeout(o.current)},[h,b]);const y=e.useCallback(()=>{$.current=!0,clearTimeout(o.current)},[]);S(r,"init",y),S(r,"authorize",y),S(r,"login",y),S(r,"ready",()=>{y(),P(m=>m+1)});const E=e.useRef();return S(r,"heartbeat",()=>{E.current&&clearTimeout(E.current),E.current=setTimeout(()=>{if(w.current){const m=new URL(u);w.current.src=`${m.origin}/mm-embedded-interop?id=${r}&origin=${window.location.origin}`}},6e3)}),e.useEffect(()=>()=>{E.current&&clearTimeout(E.current)},[]),!b&&!x?null:e.createElement(D,{$isReady:M,ref:w,src:h,...T})};A.propTypes={id:C.string,src:C.string.isRequired,path:C.string,onInit:C.func,onTimeout:C.func,skipManifestCheck:C.bool};exports.MMEmbeddableZone=A;exports.MMEmbeddableZoneContext=q;exports.MMEmbeddableZoneProvider=W;exports.getAppInfo=j;exports.testIsEmbeddable=v;exports.useEmbeddedEffect=S;
5
+ visibility: ${n=>n.$isReady?"visible":"hidden"};
6
+ `,ce=D.div`
7
+ width: 100%;
8
+ height: 100%;
9
+ display: flex;
10
+ flex-direction: column;
11
+ align-items: center;
12
+ justify-content: center;
13
+ gap: 6px;
14
+ padding: 16px;
15
+ box-sizing: border-box;
16
+ text-align: center;
17
+ color: #555;
18
+ font-size: 14px;
19
+ `,ne=({entry:n})=>e.createElement(ce,null,e.createElement("div",{style:{fontWeight:600}},n&&(n.name||n.origin)||"This app"," can’t be embedded here"),e.createElement("div",{style:{fontSize:12,color:"#888"}},"It needs an update to support embedding from a different domain."));ne.propTypes={entry:w.shape({origin:w.string,name:w.string,reason:w.string})};const ae=D.div`
20
+ height: 100%;
21
+ display: flex;
22
+ flex: 1;
23
+ align-items: center;
24
+ justify-content: center;
25
+ `,re=({id:n,src:i,path:o,onInit:l=()=>{},onTimeout:m,context:R={},params:g={},skipManifestCheck:p=!1,renderUnsupported:z,...$})=>{if("isConfiguring"in $)return console.error("isConfiguring must be passed via the params prop to MMEmbeddableZone"),null;if("colorMode"in R)return console.error("colorMode must be passed via the params prop to MMEmbeddableZone"),null;if("isFullScreen"in R)return console.error("isFullScreen must be passed via the params prop to MMEmbeddableZone"),null;const x=e.useRef(),[y,b]=e.useState(),[M,S]=e.useState(0),[O,L]=e.useState(!1),C=Y(i),T=N(i),u=ee(i);e.useEffect(()=>{C>0&&S(0)},[C]);const{registerFrame:d,unregisterFrame:c,sendMessage:a}=e.useContext(Z),[h,E]=e.useState(!0),[t,r]=e.useState(),s=e.useRef(),f=e.useRef(m),k=e.useRef(l),I=e.useRef(!1);e.useEffect(()=>{f.current=m},[m]),e.useEffect(()=>{k.current=l},[l]),e.useEffect(()=>{M&&a(n,"set-context",{context:{...R,colorMode:g.colorMode,isFullScreen:g.isFullScreen}})},[R,g.colorMode,g.isFullScreen,n,M]),e.useEffect(()=>{M&&(a(n,"set-params",{params:g}),a(n,"set-configuring",{isConfiguring:g.isConfiguring}))},[g,n,M]),e.useEffect(()=>{o!==void 0&&r((o==null?void 0:o.indexOf("/"))===0?o:`/${o}`)},[o]),e.useEffect(()=>{t===void 0||!M||a(n,"navigate",{path:t})},[t,M,n,a]),e.useEffect(()=>{if(!(!i||!n||!x)){if(p){const U=new URL(i);E(!0),d(n,U.origin,x),k.current(),b(W(U.origin,n))}else(async()=>{const U=await V(i);if(E(U),U){const H=new URL(i);d(n,H.origin,x),k.current(),b(W(H.origin,n))}})();return()=>{c(n)}}},[i,n,d,x,p]),e.useEffect(()=>{if(!(!p||!y||I.current))return s.current=setTimeout(()=>{f.current&&f.current()},oe),()=>clearTimeout(s.current)},[y,p]);const P=e.useCallback(()=>{I.current=!0,clearTimeout(s.current)},[]);j(n,"init",P),j(n,"authorize",P),j(n,"login",P),j(n,"credential-request",()=>{P(),L(!0)}),e.useEffect(()=>{!O||!T||a(n,"credential",{accessToken:T.accessToken})},[O,T,n,a]),j(n,"ready",()=>{P(),S(U=>U+1)});const F=e.useRef();return j(n,"heartbeat",()=>{F.current&&clearTimeout(F.current),F.current=setTimeout(()=>{if(x.current){const U=new URL(i);x.current.src=W(U.origin,n)}},6e3)}),e.useEffect(()=>()=>{F.current&&clearTimeout(F.current)},[]),!p&&!h?e.createElement(ae,null,e.createElement("div",{style:{textAlign:"center"}},"Application must adhere to the MM App Manifest specification to be embedded.")):u?z?z(u):e.createElement(ne,{entry:u}):e.createElement(ue,{key:`auth-epoch-${C}`,$isReady:M,ref:x,src:y,...$})};re.propTypes={id:w.string,src:w.string.isRequired,path:w.string,onInit:w.func,onTimeout:w.func,skipManifestCheck:w.bool,renderUnsupported:w.func};const le=q.div`
26
+ position: fixed;
27
+ inset: 0;
28
+ background: rgba(0, 0, 0, 0.45);
29
+ display: flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ z-index: 10000;
33
+ `,de=q.div`
34
+ background: #fff;
35
+ border-radius: 8px;
36
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.2);
37
+ padding: 24px;
38
+ width: 480px;
39
+ max-width: calc(100vw - 32px);
40
+ font-family: sans-serif;
41
+ color: #222;
42
+ `,fe=q.div`
43
+ display: flex;
44
+ align-items: center;
45
+ justify-content: space-between;
46
+ padding: 10px 0;
47
+ gap: 16px;
48
+ `,me=q.button`
49
+ background: #16a500;
50
+ color: #fff;
51
+ border: none;
52
+ border-radius: 6px;
53
+ padding: 9px 18px;
54
+ font-size: 14px;
55
+ cursor: pointer;
56
+ white-space: nowrap;
57
+ `,ge=q.p`
58
+ color: #b3261e;
59
+ font-size: 13px;
60
+ margin: 4px 0 0;
61
+ `,be=()=>{const{pending:n,authorize:i}=X();return n.length===0?null:e.createElement(le,null,e.createElement(de,null,e.createElement("h3",{style:{margin:"0 0 8px"}},"Authorization Required"),e.createElement("p",{style:{margin:"0 0 12px",fontSize:14,color:"#555"}},"The following apps need you to sign in and authorize them before they can load."),n.map(o=>e.createElement("div",{key:o.origin},e.createElement(fe,null,e.createElement("div",null,e.createElement("div",{style:{fontWeight:600}},o.name||o.origin),o.name&&e.createElement("div",{style:{fontSize:12,color:"#888"}},o.origin)),e.createElement(me,{onClick:()=>i(o)},"Authorize")),o.popupBlocked&&e.createElement(ge,null,"The sign-in window was blocked. Allow popups for this site, then try again.")))))};exports.EmbeddedAuthorizationContext=v;exports.EmbeddedAuthorizationPrompt=be;exports.MMEmbeddableZone=re;exports.MMEmbeddableZoneContext=Z;exports.MMEmbeddableZoneProvider=te;exports.getAppInfo=_;exports.isCrossSite=G;exports.popupAuthorizationLauncher=J;exports.testIsEmbeddable=V;exports.useEmbeddedAuthorizations=X;exports.useEmbeddedCredential=N;exports.useEmbeddedEffect=j;exports.useEmbeddedOriginEpoch=Y;exports.useEmbeddedUnsupported=ee;
@@ -1,254 +1,579 @@
1
- import A, { createContext as B, useState as U, useRef as R, useCallback as $, useEffect as g, useMemo as D, useContext as H } from "react";
2
- import T from "prop-types";
3
- import j from "styled-components";
4
- const W = B(null), K = ({ children: e }) => {
5
- const [s, a] = U({}), [c, y] = U({}), i = R({}), l = R({}), f = R({}), x = $((r, t) => {
6
- var n;
7
- return !!((n = f.current[r]) != null && n.has(t));
8
- }, []), p = $((r, t, n) => {
9
- a((o) => ({ ...o, [r]: { origin: t, frameRef: n } }));
10
- }, []), I = $((r) => {
11
- a((t) => {
12
- const n = { ...t };
13
- return delete n[r], n;
14
- }), y((t) => {
15
- const n = { ...t };
16
- return delete n[r], n;
17
- }), delete f.current[r];
1
+ import f, { createContext as X, useContext as Z, useState as I, useRef as T, useCallback as b, useEffect as h, useMemo as te } from "react";
2
+ import R from "prop-types";
3
+ import W from "styled-components";
4
+ const K = X(null), H = {}, Y = async (t) => {
5
+ let o;
6
+ try {
7
+ if (o = new URL(t).origin, H[o] !== void 0)
8
+ return H[o];
9
+ const a = await (await fetch(`${o}/mm-app-manifest.json`)).json();
10
+ if (!a.version)
11
+ throw new Error("Invalid manifest");
12
+ return H[o] = a, a;
13
+ } catch {
14
+ }
15
+ return o && (H[o] = !1), !1;
16
+ }, ne = async (t) => !!await Y(t), D = X({
17
+ pending: [],
18
+ authorize: () => {
19
+ },
20
+ dismiss: () => {
21
+ },
22
+ originEpochs: {},
23
+ credentials: {},
24
+ unsupported: {}
25
+ }), re = 2e4, j = (t) => {
26
+ try {
27
+ return new URL(t).origin;
28
+ } catch {
29
+ return null;
30
+ }
31
+ }, Q = (t) => {
32
+ if (!t || /^\d{1,3}(?:\.\d{1,3}){3}$/.test(t) || t.includes(":"))
33
+ return t;
34
+ const o = t.split(".");
35
+ return o.length <= 2 ? t : o.slice(-2).join(".");
36
+ }, se = (t, o) => {
37
+ try {
38
+ const s = new URL(t), a = new URL(o);
39
+ return s.protocol !== a.protocol ? !0 : Q(s.hostname) !== Q(a.hostname);
40
+ } catch {
41
+ return !0;
42
+ }
43
+ }, oe = (t, { onBlocked: o, onClosed: s }) => {
44
+ const a = window.open(
45
+ t.authUrl,
46
+ "mm-embed-auth",
47
+ "popup,width=600,height=700"
48
+ );
49
+ if (!a)
50
+ return o(), () => {
51
+ };
52
+ const m = setInterval(() => {
53
+ a.closed && (clearInterval(m), s());
54
+ }, 1e3);
55
+ return () => clearInterval(m);
56
+ }, N = ({ children: t, launcher: o }) => {
57
+ const s = Z(K), [a, m] = I({}), [U, g] = I({}), [E, O] = I({}), [q, M] = I({}), $ = T(E);
58
+ $.current = E;
59
+ const p = T(null), k = T({}), C = b((e, n) => {
60
+ Y(n).then((r) => {
61
+ if (!r || !r.name)
62
+ return;
63
+ const d = (y) => y[e] ? { ...y, [e]: { ...y[e], name: r.name } } : y;
64
+ m(d), M(d);
65
+ });
66
+ }, []), P = b(
67
+ (e, n) => {
68
+ const r = j(e == null ? void 0 : e.authUrl);
69
+ r && (M((d) => d[r] ? d : {
70
+ ...d,
71
+ [r]: { origin: r, reason: n, name: null }
72
+ }), C(r, e.authUrl));
73
+ },
74
+ [C]
75
+ ), F = b(
76
+ (e, { v2: n = !1 } = {}) => {
77
+ const r = j(e == null ? void 0 : e.authUrl);
78
+ r && (n && $.current[r] || (m((d) => d[r] ? d : {
79
+ ...d,
80
+ [r]: {
81
+ origin: r,
82
+ authUrl: e.authUrl,
83
+ silentUrl: e.silentUrl || null,
84
+ // v2 entries try the invisible silent resolver first; legacy
85
+ // signals go straight to the host's interactive UI.
86
+ status: n && e.silentUrl ? "silent" : "interactive",
87
+ v2: n,
88
+ name: null,
89
+ popupBlocked: !1
90
+ }
91
+ }), C(r, e.authUrl)));
92
+ },
93
+ [C]
94
+ ), z = b((e) => {
95
+ m((n) => {
96
+ if (!n[e])
97
+ return n;
98
+ const r = { ...n };
99
+ return delete r[e], r;
100
+ });
101
+ }, []), S = b(
102
+ (e) => {
103
+ e && (z(e), g((n) => ({
104
+ ...n,
105
+ [e]: (n[e] || 0) + 1
106
+ })));
107
+ },
108
+ [z]
109
+ ), i = b((e) => {
110
+ m((n) => !n[e] || n[e].status === "interactive" ? n : {
111
+ ...n,
112
+ [e]: { ...n[e], status: "interactive" }
113
+ });
114
+ }, []), l = b(
115
+ (e) => {
116
+ z(e.origin);
117
+ },
118
+ [z]
119
+ ), c = b(
120
+ (e) => {
121
+ const n = j(e == null ? void 0 : e.authUrl);
122
+ if (n && se(n, window.location.origin)) {
123
+ P(e, "cross-site-legacy");
124
+ return;
125
+ }
126
+ F(e);
127
+ },
128
+ [F, P]
129
+ );
130
+ h(() => {
131
+ if (!s)
132
+ return;
133
+ const e = [
134
+ s.addListener("*", "authorize", c),
135
+ s.addListener("*", "login", c),
136
+ s.addListener(
137
+ "*",
138
+ "credential-request",
139
+ (n) => F(n, { v2: !0 })
140
+ ),
141
+ s.addListener("*", "authorized", (n) => {
142
+ n != null && n.accessToken || S(j(n == null ? void 0 : n.authUrl));
143
+ })
144
+ ];
145
+ return () => e.forEach((n) => n());
146
+ }, [s, c, F, S]), h(() => {
147
+ const e = (n) => {
148
+ const r = n == null ? void 0 : n.data;
149
+ if (!r || r.type !== "authorized" && r.type !== "authorize-failed")
150
+ return;
151
+ const d = j(r.authUrl);
152
+ if (!(!d || n.origin !== d)) {
153
+ if (r.type === "authorized" && r.accessToken) {
154
+ O((y) => ({
155
+ ...y,
156
+ [d]: { accessToken: r.accessToken }
157
+ })), z(d);
158
+ return;
159
+ }
160
+ r.type === "authorize-failed" && i(d);
161
+ }
162
+ };
163
+ return window.addEventListener("message", e), () => window.removeEventListener("message", e);
164
+ }, [z, i]), h(() => {
165
+ const e = k.current;
166
+ Object.values(a).forEach((n) => {
167
+ n.status === "silent" && !e[n.origin] && (e[n.origin] = setTimeout(() => {
168
+ delete e[n.origin], i(n.origin);
169
+ }, re));
170
+ }), Object.keys(e).forEach((n) => {
171
+ (!a[n] || a[n].status !== "silent") && (clearTimeout(e[n]), delete e[n]);
172
+ });
173
+ }, [a, i]), h(() => () => {
174
+ p.current && p.current(), Object.values(k.current).forEach(clearTimeout);
18
175
  }, []);
19
- g(() => {
20
- const r = (n = [], o) => {
21
- n.forEach((u) => u(o));
22
- }, t = (n) => {
23
- var F, M, w, m, C;
24
- if (!((F = n == null ? void 0 : n.data) != null && F.instanceId))
176
+ const u = b(
177
+ (e) => {
178
+ p.current && (p.current(), p.current = null);
179
+ const n = o || oe;
180
+ p.current = n(e, {
181
+ onBlocked: () => {
182
+ m((r) => r[e.origin] ? {
183
+ ...r,
184
+ [e.origin]: { ...r[e.origin], popupBlocked: !0 }
185
+ } : r);
186
+ },
187
+ onClosed: () => {
188
+ if (e.v2) {
189
+ m((r) => !r[e.origin] || !r[e.origin].silentUrl ? r : {
190
+ ...r,
191
+ [e.origin]: { ...r[e.origin], status: "silent" }
192
+ });
193
+ return;
194
+ }
195
+ S(e.origin);
196
+ }
197
+ });
198
+ },
199
+ [o, S]
200
+ ), w = {
201
+ // Hosts render UI for interactive entries only; silent resolution is
202
+ // invisible by design.
203
+ pending: Object.values(a).filter(
204
+ (e) => e.status === "interactive"
205
+ ),
206
+ authorize: u,
207
+ dismiss: l,
208
+ originEpochs: U,
209
+ credentials: E,
210
+ unsupported: q
211
+ }, x = Object.values(a).filter(
212
+ (e) => e.status === "silent" && e.silentUrl
213
+ );
214
+ return /* @__PURE__ */ f.createElement(D.Provider, { value: w }, t, x.map((e) => /* @__PURE__ */ f.createElement(
215
+ "iframe",
216
+ {
217
+ key: `mm-silent-auth-${e.origin}`,
218
+ src: e.silentUrl,
219
+ title: `MachineMetrics silent authorization (${e.origin})`,
220
+ "aria-hidden": "true",
221
+ tabIndex: -1,
222
+ style: { display: "none" }
223
+ }
224
+ )));
225
+ };
226
+ N.propTypes = {
227
+ children: R.node,
228
+ launcher: R.func
229
+ };
230
+ const ie = () => Z(D), ce = (t) => {
231
+ const { originEpochs: o } = Z(D), s = j(t);
232
+ return s && o[s] || 0;
233
+ }, ue = (t) => {
234
+ const { credentials: o } = Z(D), s = j(t);
235
+ return s && o[s] || null;
236
+ }, ae = (t) => {
237
+ const { unsupported: o } = Z(D), s = j(t);
238
+ return s && o[s] || null;
239
+ }, le = ({ children: t, authorizationLauncher: o }) => {
240
+ const [s, a] = I({}), [m, U] = I({}), g = T({}), E = T({}), O = T({}), q = b((i, l) => {
241
+ var c;
242
+ return !!((c = O.current[i]) != null && c.has(l));
243
+ }, []), M = b((i, l, c) => {
244
+ a((u) => ({ ...u, [i]: { origin: l, frameRef: c } }));
245
+ }, []), $ = b((i) => {
246
+ a((l) => {
247
+ const c = { ...l };
248
+ return delete c[i], c;
249
+ }), U((l) => {
250
+ const c = { ...l };
251
+ return delete c[i], c;
252
+ }), delete O.current[i];
253
+ }, []);
254
+ h(() => {
255
+ const i = (c = [], u) => {
256
+ c.forEach((w) => w(u));
257
+ }, l = (c) => {
258
+ var e, n, r, d, y;
259
+ if (!((e = c == null ? void 0 : c.data) != null && e.instanceId))
25
260
  return;
26
- const { instanceId: o, type: u } = n.data, d = i.current;
27
- if (u === "response") {
28
- const { callbackId: S, response: v, error: z } = n.data, _ = l.current[S];
29
- _ && (_(v, z), delete l.current[S]);
261
+ const { instanceId: u, type: w } = c.data, x = g.current;
262
+ if (w === "response") {
263
+ const { callbackId: A, response: v, error: B } = c.data, L = E.current[A];
264
+ L && (L(v, B), delete E.current[A]);
30
265
  return;
31
266
  }
32
- if (u === "mark-registered") {
33
- const { requestType: S } = n.data;
34
- f.current[o] || (f.current[o] = /* @__PURE__ */ new Set()), f.current[o].add(S);
267
+ if (w === "mark-registered") {
268
+ const { requestType: A } = c.data;
269
+ O.current[u] || (O.current[u] = /* @__PURE__ */ new Set()), O.current[u].add(A);
35
270
  return;
36
271
  }
37
- u === "ready" && y((S) => ({ ...S, [o]: !0 })), r((M = d[o]) == null ? void 0 : M[u], n.data), r((w = d["*"]) == null ? void 0 : w[u], n.data), r((m = d[o]) == null ? void 0 : m["*"], n.data), r((C = d["*"]) == null ? void 0 : C["*"], n.data);
272
+ w === "ready" && U((A) => ({ ...A, [u]: !0 })), i((n = x[u]) == null ? void 0 : n[w], c.data), i((r = x["*"]) == null ? void 0 : r[w], c.data), i((d = x[u]) == null ? void 0 : d["*"], c.data), i((y = x["*"]) == null ? void 0 : y["*"], c.data);
38
273
  };
39
- return window.addEventListener("message", t), () => {
40
- window.removeEventListener("message", t);
274
+ return window.addEventListener("message", l), () => {
275
+ window.removeEventListener("message", l);
41
276
  };
42
277
  }, [s]);
43
- const b = $(
44
- (r, t, n) => {
45
- var u, d;
46
- const o = s[r];
47
- if (!o) {
48
- console.warn(`Origin not set for id: ${r}. Unable to send message.`);
278
+ const p = b(
279
+ (i, l, c) => {
280
+ var w, x;
281
+ const u = s[i];
282
+ if (!u) {
283
+ console.warn(`Origin not set for id: ${i}. Unable to send message.`);
49
284
  return;
50
285
  }
51
- (d = (u = o == null ? void 0 : o.frameRef) == null ? void 0 : u.current) != null && d.contentWindow && o.frameRef.current.contentWindow.postMessage(
52
- { type: t, ...n, instanceId: r },
53
- o.origin
286
+ (x = (w = u == null ? void 0 : u.frameRef) == null ? void 0 : w.current) != null && x.contentWindow && u.frameRef.current.contentWindow.postMessage(
287
+ { type: l, ...c, instanceId: i },
288
+ u.origin
54
289
  );
55
290
  },
56
291
  [s]
57
- ), E = R(0), O = $(() => `${Date.now()}-${++E.current}`, []), L = $(
58
- async (r, t, n = {}) => new Promise((o, u) => {
59
- const d = O(), F = (M, w) => {
60
- delete l.current[d], w ? u(w) : o(M);
292
+ ), k = T(0), C = b(() => `${Date.now()}-${++k.current}`, []), P = b(
293
+ async (i, l, c = {}) => new Promise((u, w) => {
294
+ const x = C(), e = (n, r) => {
295
+ delete E.current[x], r ? w(r) : u(n);
61
296
  };
62
- l.current[d] = F, b(r, "request", { callbackId: d, requestType: t, data: n });
297
+ E.current[x] = e, p(i, "request", { callbackId: x, requestType: l, data: c });
63
298
  }),
64
- [b]
65
- ), Z = $(
66
- (r, t) => {
67
- b(r, "load-options", t);
299
+ [p]
300
+ ), F = b(
301
+ (i, l) => {
302
+ p(i, "load-options", l);
68
303
  },
69
- [b]
70
- ), h = $(
71
- (r, t) => {
72
- b(r, "validate", t);
304
+ [p]
305
+ ), z = b(
306
+ (i, l) => {
307
+ p(i, "validate", l);
73
308
  },
74
- [b]
75
- ), k = D(
309
+ [p]
310
+ ), S = te(
76
311
  () => ({
77
- registerFrame: p,
78
- unregisterFrame: I,
79
- sendMessage: b,
80
- sendRequest: L,
81
- loadOptions: Z,
82
- validate: h,
83
- hasHandler: x,
84
- readyFrames: c,
85
- addListener: (r, t, n) => (i.current[r] || (i.current[r] = {}), i.current[r][t] || (i.current[r][t] = []), i.current[r][t].push(n), () => {
86
- i.current[r][t] = i.current[r][t].filter((o) => o !== n);
312
+ registerFrame: M,
313
+ unregisterFrame: $,
314
+ sendMessage: p,
315
+ sendRequest: P,
316
+ loadOptions: F,
317
+ validate: z,
318
+ hasHandler: q,
319
+ readyFrames: m,
320
+ addListener: (i, l, c) => (g.current[i] || (g.current[i] = {}), g.current[i][l] || (g.current[i][l] = []), g.current[i][l].push(c), () => {
321
+ g.current[i][l] = g.current[i][l].filter((u) => u !== c);
87
322
  })
88
323
  }),
89
324
  [
325
+ M,
326
+ $,
90
327
  p,
91
- I,
92
- b,
93
- L,
94
- Z,
95
- h,
96
- x,
97
- c
328
+ P,
329
+ F,
330
+ z,
331
+ q,
332
+ m
98
333
  ]
99
334
  );
100
- return /* @__PURE__ */ A.createElement(W.Provider, { value: k }, e);
101
- }, q = {}, G = async (e) => {
102
- try {
103
- const s = new URL(e).origin;
104
- if (q[s] !== void 0)
105
- return q[s];
106
- const c = await (await fetch(`${s}/mm-app-manifest.json`)).json();
107
- if (!c.version)
108
- throw new Error("Invalid manifest");
109
- return q[s] = c, c;
110
- } catch {
111
- }
112
- return q[origin] = !1, !1;
113
- }, J = async (e) => !!await G(e), P = (e, s, a) => {
114
- const c = H(W);
115
- if (c === null)
335
+ return /* @__PURE__ */ f.createElement(K.Provider, { value: S }, /* @__PURE__ */ f.createElement(N, { launcher: o }, t));
336
+ }, _ = (t, o, s) => {
337
+ const a = Z(K);
338
+ if (a === null)
116
339
  throw new Error(
117
340
  "useEmbeddedEffect must be used within a MMEmbeddableZoneProvider"
118
341
  );
119
- const y = R(a);
120
- g(() => {
121
- y.current = a;
122
- }, [a]), g(() => {
123
- if (!(!e || !s)) {
124
- if (s.startsWith("key:")) {
125
- const i = s.substring(4);
126
- return c.readyFrames[e] && c.sendMessage(e, "subscribe-key", { keyChord: i }), c.addListener(
127
- e,
128
- `key-pressed:${i}`,
129
- (...f) => y.current(...f)
342
+ const m = T(s);
343
+ h(() => {
344
+ m.current = s;
345
+ }, [s]), h(() => {
346
+ if (!(!t || !o)) {
347
+ if (o.startsWith("key:")) {
348
+ const U = o.substring(4);
349
+ return a.readyFrames[t] && a.sendMessage(t, "subscribe-key", { keyChord: U }), a.addListener(
350
+ t,
351
+ `key-pressed:${U}`,
352
+ (...E) => m.current(...E)
130
353
  );
131
354
  }
132
- return c.addListener(
133
- e,
134
- s,
135
- (...i) => y.current(...i)
355
+ return a.addListener(
356
+ t,
357
+ o,
358
+ (...U) => m.current(...U)
136
359
  );
137
360
  }
138
- }, [c, e, s]);
361
+ }, [a, t, o]);
139
362
  };
140
- K.propTypes = {
141
- children: T.node.isRequired
363
+ le.propTypes = {
364
+ children: R.node.isRequired,
365
+ /**
366
+ * Optional interactive-step launcher for embedded authorizations,
367
+ * `(entry, { onBlocked, onClosed }) => cleanup`. Defaults to a top-level
368
+ * popup. Hosts that cannot open windows (Android WebView shells) drive
369
+ * their own UI from useEmbeddedAuthorizations() instead.
370
+ */
371
+ authorizationLauncher: R.func
142
372
  };
143
- const Q = j.default || j, V = 1e4, X = Q.iframe`
373
+ const G = W.default || W, de = 1e4, fe = "credentials", V = (t, o) => `${t}/mm-embedded-interop?id=${o}&origin=${window.location.origin}&caps=${fe}`, me = G.iframe`
144
374
  width: 100%;
145
375
  height: 100%;
146
376
  border: none;
147
- visibility: ${(e) => e.$isReady ? "visible" : "hidden"};
148
- `, Y = ({
149
- id: e,
150
- src: s,
151
- path: a,
152
- onInit: c = () => {
377
+ visibility: ${(t) => t.$isReady ? "visible" : "hidden"};
378
+ `, ge = G.div`
379
+ width: 100%;
380
+ height: 100%;
381
+ display: flex;
382
+ flex-direction: column;
383
+ align-items: center;
384
+ justify-content: center;
385
+ gap: 6px;
386
+ padding: 16px;
387
+ box-sizing: border-box;
388
+ text-align: center;
389
+ color: #555;
390
+ font-size: 14px;
391
+ `, ee = ({ entry: t }) => /* @__PURE__ */ f.createElement(ge, null, /* @__PURE__ */ f.createElement("div", { style: { fontWeight: 600 } }, t && (t.name || t.origin) || "This app", " can’t be embedded here"), /* @__PURE__ */ f.createElement("div", { style: { fontSize: 12, color: "#888" } }, "It needs an update to support embedding from a different domain."));
392
+ ee.propTypes = {
393
+ entry: R.shape({
394
+ origin: R.string,
395
+ name: R.string,
396
+ reason: R.string
397
+ })
398
+ };
399
+ const pe = G.div`
400
+ height: 100%;
401
+ display: flex;
402
+ flex: 1;
403
+ align-items: center;
404
+ justify-content: center;
405
+ `, he = ({
406
+ id: t,
407
+ src: o,
408
+ path: s,
409
+ onInit: a = () => {
153
410
  },
154
- onTimeout: y,
155
- context: i = {},
156
- params: l = {},
157
- skipManifestCheck: f = !1,
158
- ...x
411
+ onTimeout: m,
412
+ context: U = {},
413
+ params: g = {},
414
+ skipManifestCheck: E = !1,
415
+ renderUnsupported: O,
416
+ ...q
159
417
  }) => {
160
- if ("isConfiguring" in x)
418
+ if ("isConfiguring" in q)
161
419
  return console.error(
162
420
  "isConfiguring must be passed via the params prop to MMEmbeddableZone"
163
421
  ), null;
164
- if ("colorMode" in i)
422
+ if ("colorMode" in U)
165
423
  return console.error(
166
424
  "colorMode must be passed via the params prop to MMEmbeddableZone"
167
425
  ), null;
168
- if ("isFullScreen" in i)
426
+ if ("isFullScreen" in U)
169
427
  return console.error(
170
428
  "isFullScreen must be passed via the params prop to MMEmbeddableZone"
171
429
  ), null;
172
- const p = R(), [I, b] = U(), [E, O] = U(0), { registerFrame: L, unregisterFrame: Z, sendMessage: h } = H(
173
- W
174
- ), [k, r] = U(!0), [t, n] = U(), o = R(), u = R(y), d = R(c), F = R(!1);
175
- g(() => {
176
- u.current = y;
177
- }, [y]), g(() => {
178
- d.current = c;
179
- }, [c]), g(() => {
180
- E && h(e, "set-context", {
430
+ const M = T(), [$, p] = I(), [k, C] = I(0), [P, F] = I(!1), z = ce(o), S = ue(o), i = ae(o);
431
+ h(() => {
432
+ z > 0 && C(0);
433
+ }, [z]);
434
+ const { registerFrame: l, unregisterFrame: c, sendMessage: u } = Z(
435
+ K
436
+ ), [w, x] = I(!0), [e, n] = I(), r = T(), d = T(m), y = T(a), A = T(!1);
437
+ h(() => {
438
+ d.current = m;
439
+ }, [m]), h(() => {
440
+ y.current = a;
441
+ }, [a]), h(() => {
442
+ k && u(t, "set-context", {
181
443
  context: {
182
- ...i,
444
+ ...U,
183
445
  // TODO: Remove this once everything is migrated to params
184
- colorMode: l.colorMode,
185
- isFullScreen: l.isFullScreen
446
+ colorMode: g.colorMode,
447
+ isFullScreen: g.isFullScreen
186
448
  }
187
449
  });
188
- }, [i, l.colorMode, l.isFullScreen, e, E]), g(() => {
189
- E && (h(e, "set-params", { params: l }), h(e, "set-configuring", { isConfiguring: l.isConfiguring }));
190
- }, [l, e, E]), g(() => {
191
- a !== void 0 && n((a == null ? void 0 : a.indexOf("/")) === 0 ? a : `/${a}`);
192
- }, [a]), g(() => {
193
- t === void 0 || !E || h(e, "navigate", { path: t });
194
- }, [t, E, e, h]), g(() => {
195
- if (!(!s || !e || !p)) {
196
- if (f) {
197
- const m = new URL(s);
198
- r(!0), L(e, m.origin, p), d.current(), b(
199
- `${m.origin}/mm-embedded-interop?id=${e}&origin=${window.location.origin}`
200
- );
450
+ }, [U, g.colorMode, g.isFullScreen, t, k]), h(() => {
451
+ k && (u(t, "set-params", { params: g }), u(t, "set-configuring", { isConfiguring: g.isConfiguring }));
452
+ }, [g, t, k]), h(() => {
453
+ s !== void 0 && n((s == null ? void 0 : s.indexOf("/")) === 0 ? s : `/${s}`);
454
+ }, [s]), h(() => {
455
+ e === void 0 || !k || u(t, "navigate", { path: e });
456
+ }, [e, k, t, u]), h(() => {
457
+ if (!(!o || !t || !M)) {
458
+ if (E) {
459
+ const L = new URL(o);
460
+ x(!0), l(t, L.origin, M), y.current(), p(V(L.origin, t));
201
461
  } else
202
462
  (async () => {
203
- const m = await J(s);
204
- if (r(m), m) {
205
- const C = new URL(s);
206
- L(e, C.origin, p), d.current(), b(
207
- `${C.origin}/mm-embedded-interop?id=${e}&origin=${window.location.origin}`
208
- );
463
+ const L = await ne(o);
464
+ if (x(L), L) {
465
+ const J = new URL(o);
466
+ l(t, J.origin, M), y.current(), p(V(J.origin, t));
209
467
  }
210
468
  })();
211
469
  return () => {
212
- Z(e);
470
+ c(t);
213
471
  };
214
472
  }
215
- }, [s, e, L, p, f]), g(() => {
216
- if (!(!f || !I || F.current))
217
- return o.current = setTimeout(() => {
218
- u.current && u.current();
219
- }, V), () => clearTimeout(o.current);
220
- }, [I, f]);
221
- const M = $(() => {
222
- F.current = !0, clearTimeout(o.current);
473
+ }, [o, t, l, M, E]), h(() => {
474
+ if (!(!E || !$ || A.current))
475
+ return r.current = setTimeout(() => {
476
+ d.current && d.current();
477
+ }, de), () => clearTimeout(r.current);
478
+ }, [$, E]);
479
+ const v = b(() => {
480
+ A.current = !0, clearTimeout(r.current);
223
481
  }, []);
224
- P(e, "init", M), P(e, "authorize", M), P(e, "login", M), P(e, "ready", () => {
225
- M(), O((m) => m + 1);
482
+ _(t, "init", v), _(t, "authorize", v), _(t, "login", v), _(t, "credential-request", () => {
483
+ v(), F(!0);
484
+ }), h(() => {
485
+ !P || !S || u(t, "credential", { accessToken: S.accessToken });
486
+ }, [P, S, t, u]), _(t, "ready", () => {
487
+ v(), C((L) => L + 1);
226
488
  });
227
- const w = R();
228
- return P(e, "heartbeat", () => {
229
- w.current && clearTimeout(w.current), w.current = setTimeout(() => {
230
- if (p.current) {
231
- const m = new URL(s);
232
- p.current.src = `${m.origin}/mm-embedded-interop?id=${e}&origin=${window.location.origin}`;
489
+ const B = T();
490
+ return _(t, "heartbeat", () => {
491
+ B.current && clearTimeout(B.current), B.current = setTimeout(() => {
492
+ if (M.current) {
493
+ const L = new URL(o);
494
+ M.current.src = V(L.origin, t);
233
495
  }
234
496
  }, 6e3);
235
- }), g(() => () => {
236
- w.current && clearTimeout(w.current);
237
- }, []), !f && !k ? null : /* @__PURE__ */ A.createElement(X, { $isReady: E, ref: p, src: I, ...x });
497
+ }), h(() => () => {
498
+ B.current && clearTimeout(B.current);
499
+ }, []), !E && !w ? /* @__PURE__ */ f.createElement(pe, null, /* @__PURE__ */ f.createElement("div", { style: { textAlign: "center" } }, "Application must adhere to the MM App Manifest specification to be embedded.")) : i ? O ? O(i) : /* @__PURE__ */ f.createElement(ee, { entry: i }) : /* @__PURE__ */ f.createElement(
500
+ me,
501
+ {
502
+ key: `auth-epoch-${z}`,
503
+ $isReady: k,
504
+ ref: M,
505
+ src: $,
506
+ ...q
507
+ }
508
+ );
509
+ };
510
+ he.propTypes = {
511
+ id: R.string,
512
+ src: R.string.isRequired,
513
+ path: R.string,
514
+ onInit: R.func,
515
+ onTimeout: R.func,
516
+ skipManifestCheck: R.bool,
517
+ /**
518
+ * Optional host-styled renderer for the structurally-unsupported embed
519
+ * state (legacy app on a cross-site origin), `(entry) => ReactNode`. Falls
520
+ * back to a minimal built-in placeholder.
521
+ */
522
+ renderUnsupported: R.func
238
523
  };
239
- Y.propTypes = {
240
- id: T.string,
241
- src: T.string.isRequired,
242
- path: T.string,
243
- onInit: T.func,
244
- onTimeout: T.func,
245
- skipManifestCheck: T.bool
524
+ const be = W.div`
525
+ position: fixed;
526
+ inset: 0;
527
+ background: rgba(0, 0, 0, 0.45);
528
+ display: flex;
529
+ align-items: center;
530
+ justify-content: center;
531
+ z-index: 10000;
532
+ `, Ee = W.div`
533
+ background: #fff;
534
+ border-radius: 8px;
535
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.2);
536
+ padding: 24px;
537
+ width: 480px;
538
+ max-width: calc(100vw - 32px);
539
+ font-family: sans-serif;
540
+ color: #222;
541
+ `, we = W.div`
542
+ display: flex;
543
+ align-items: center;
544
+ justify-content: space-between;
545
+ padding: 10px 0;
546
+ gap: 16px;
547
+ `, xe = W.button`
548
+ background: #16a500;
549
+ color: #fff;
550
+ border: none;
551
+ border-radius: 6px;
552
+ padding: 9px 18px;
553
+ font-size: 14px;
554
+ cursor: pointer;
555
+ white-space: nowrap;
556
+ `, Re = W.p`
557
+ color: #b3261e;
558
+ font-size: 13px;
559
+ margin: 4px 0 0;
560
+ `, ze = () => {
561
+ const { pending: t, authorize: o } = ie();
562
+ return t.length === 0 ? null : /* @__PURE__ */ f.createElement(be, null, /* @__PURE__ */ f.createElement(Ee, null, /* @__PURE__ */ f.createElement("h3", { style: { margin: "0 0 8px" } }, "Authorization Required"), /* @__PURE__ */ f.createElement("p", { style: { margin: "0 0 12px", fontSize: 14, color: "#555" } }, "The following apps need you to sign in and authorize them before they can load."), t.map((s) => /* @__PURE__ */ f.createElement("div", { key: s.origin }, /* @__PURE__ */ f.createElement(we, null, /* @__PURE__ */ f.createElement("div", null, /* @__PURE__ */ f.createElement("div", { style: { fontWeight: 600 } }, s.name || s.origin), s.name && /* @__PURE__ */ f.createElement("div", { style: { fontSize: 12, color: "#888" } }, s.origin)), /* @__PURE__ */ f.createElement(xe, { onClick: () => o(s) }, "Authorize")), s.popupBlocked && /* @__PURE__ */ f.createElement(Re, null, "The sign-in window was blocked. Allow popups for this site, then try again.")))));
246
563
  };
247
564
  export {
248
- Y as MMEmbeddableZone,
249
- W as MMEmbeddableZoneContext,
250
- K as MMEmbeddableZoneProvider,
251
- G as getAppInfo,
252
- J as testIsEmbeddable,
253
- P as useEmbeddedEffect
565
+ D as EmbeddedAuthorizationContext,
566
+ ze as EmbeddedAuthorizationPrompt,
567
+ he as MMEmbeddableZone,
568
+ K as MMEmbeddableZoneContext,
569
+ le as MMEmbeddableZoneProvider,
570
+ Y as getAppInfo,
571
+ se as isCrossSite,
572
+ oe as popupAuthorizationLauncher,
573
+ ne as testIsEmbeddable,
574
+ ie as useEmbeddedAuthorizations,
575
+ ue as useEmbeddedCredential,
576
+ _ as useEmbeddedEffect,
577
+ ce as useEmbeddedOriginEpoch,
578
+ ae as useEmbeddedUnsupported
254
579
  };
@@ -1,6 +1,61 @@
1
- (function(a,e){typeof exports=="object"&&typeof module!="undefined"?e(exports,require("react"),require("prop-types"),require("styled-components")):typeof define=="function"&&define.amd?define(["exports","react","prop-types","styled-components"],e):(a=typeof globalThis!="undefined"?globalThis:a||self,e(a["mm-react-embeddable"]={},a.React,a.PropTypes,a.styled))})(this,(function(a,e,C,W){"use strict";const q=e.createContext(null),v=({children:r})=>{const[u,f]=e.useState({}),[c,M]=e.useState({}),i=e.useRef({}),m=e.useRef({}),b=e.useRef({}),L=e.useCallback((n,s)=>{var t;return!!((t=b.current[n])!=null&&t.has(s))},[]),y=e.useCallback((n,s,t)=>{f(o=>({...o,[n]:{origin:s,frameRef:t}}))},[]),S=e.useCallback(n=>{f(s=>{const t={...s};return delete t[n],t}),M(s=>{const t={...s};return delete t[n],t}),delete b.current[n]},[]);e.useEffect(()=>{const n=(t=[],o)=>{t.forEach(d=>d(o))},s=t=>{var F,h,w,g,Z;if(!((F=t==null?void 0:t.data)!=null&&F.instanceId))return;const{instanceId:o,type:d}=t.data,l=i.current;if(d==="response"){const{callbackId:T,response:_,error:G}=t.data,z=m.current[T];z&&(z(_,G),delete m.current[T]);return}if(d==="mark-registered"){const{requestType:T}=t.data;b.current[o]||(b.current[o]=new Set),b.current[o].add(T);return}d==="ready"&&M(T=>({...T,[o]:!0})),n((h=l[o])==null?void 0:h[d],t.data),n((w=l["*"])==null?void 0:w[d],t.data),n((g=l[o])==null?void 0:g["*"],t.data),n((Z=l["*"])==null?void 0:Z["*"],t.data)};return window.addEventListener("message",s),()=>{window.removeEventListener("message",s)}},[u]);const E=e.useCallback((n,s,t)=>{var d,l;const o=u[n];if(!o){console.warn(`Origin not set for id: ${n}. Unable to send message.`);return}(l=(d=o==null?void 0:o.frameRef)==null?void 0:d.current)!=null&&l.contentWindow&&o.frameRef.current.contentWindow.postMessage({type:s,...t,instanceId:n},o.origin)},[u]),p=e.useRef(0),x=e.useCallback(()=>`${Date.now()}-${++p.current}`,[]),k=e.useCallback(async(n,s,t={})=>new Promise((o,d)=>{const l=x(),F=(h,w)=>{delete m.current[l],w?d(w):o(h)};m.current[l]=F,E(n,"request",{callbackId:l,requestType:s,data:t})}),[E]),O=e.useCallback((n,s)=>{E(n,"load-options",s)},[E]),$=e.useCallback((n,s)=>{E(n,"validate",s)},[E]),j=e.useMemo(()=>({registerFrame:y,unregisterFrame:S,sendMessage:E,sendRequest:k,loadOptions:O,validate:$,hasHandler:L,readyFrames:c,addListener:(n,s,t)=>(i.current[n]||(i.current[n]={}),i.current[n][s]||(i.current[n][s]=[]),i.current[n][s].push(t),()=>{i.current[n][s]=i.current[n][s].filter(o=>o!==t)})}),[y,S,E,k,O,$,L,c]);return e.createElement(q.Provider,{value:j},r)},U={},A=async r=>{try{const u=new URL(r).origin;if(U[u]!==void 0)return U[u];const c=await(await fetch(`${u}/mm-app-manifest.json`)).json();if(!c.version)throw new Error("Invalid manifest");return U[u]=c,c}catch{}return U[origin]=!1,!1},P=async r=>!!await A(r),I=(r,u,f)=>{const c=e.useContext(q);if(c===null)throw new Error("useEmbeddedEffect must be used within a MMEmbeddableZoneProvider");const M=e.useRef(f);e.useEffect(()=>{M.current=f},[f]),e.useEffect(()=>{if(!(!r||!u)){if(u.startsWith("key:")){const i=u.substring(4);return c.readyFrames[r]&&c.sendMessage(r,"subscribe-key",{keyChord:i}),c.addListener(r,`key-pressed:${i}`,(...b)=>M.current(...b))}return c.addListener(r,u,(...i)=>M.current(...i))}},[c,r,u])};v.propTypes={children:C.node.isRequired};const B=W.default||W,D=1e4,K=B.iframe`
1
+ (function(m,e){typeof exports=="object"&&typeof module!="undefined"?e(exports,require("react"),require("prop-types"),require("styled-components")):typeof define=="function"&&define.amd?define(["exports","react","prop-types","styled-components"],e):(m=typeof globalThis!="undefined"?globalThis:m||self,e(m["mm-react-embeddable"]={},m.React,m.PropTypes,m.styled))})(this,(function(m,e,C,q){"use strict";const _=e.createContext(null),D={},H=async t=>{let o;try{if(o=new URL(t).origin,D[o]!==void 0)return D[o];const d=await(await fetch(`${o}/mm-app-manifest.json`)).json();if(!d.version)throw new Error("Invalid manifest");return D[o]=d,d}catch{}return o&&(D[o]=!1),!1},V=async t=>!!await H(t),W=e.createContext({pending:[],authorize:()=>{},dismiss:()=>{},originEpochs:{},credentials:{},unsupported:{}}),ie=2e4,F=t=>{try{return new URL(t).origin}catch{return null}},G=t=>{if(!t||/^\d{1,3}(?:\.\d{1,3}){3}$/.test(t)||t.includes(":"))return t;const o=t.split(".");return o.length<=2?t:o.slice(-2).join(".")},J=(t,o)=>{try{const i=new URL(t),d=new URL(o);return i.protocol!==d.protocol?!0:G(i.hostname)!==G(d.hostname)}catch{return!0}},Q=(t,{onBlocked:o,onClosed:i})=>{const d=window.open(t.authUrl,"mm-embed-auth","popup,width=600,height=700");if(!d)return o(),()=>{};const g=setInterval(()=>{d.closed&&(clearInterval(g),i())},1e3);return()=>clearInterval(g)},X=({children:t,launcher:o})=>{const i=e.useContext(_),[d,g]=e.useState({}),[k,b]=e.useState({}),[E,L]=e.useState({}),[v,x]=e.useState({}),I=e.useRef(E);I.current=E;const h=e.useRef(null),z=e.useRef({}),O=e.useCallback((n,r)=>{H(r).then(s=>{if(!s||!s.name)return;const f=U=>U[n]?{...U,[n]:{...U[n],name:s.name}}:U;g(f),x(f)})},[]),j=e.useCallback((n,r)=>{const s=F(n==null?void 0:n.authUrl);s&&(x(f=>f[s]?f:{...f,[s]:{origin:s,reason:r,name:null}}),O(s,n.authUrl))},[O]),A=e.useCallback((n,{v2:r=!1}={})=>{const s=F(n==null?void 0:n.authUrl);s&&(r&&I.current[s]||(g(f=>f[s]?f:{...f,[s]:{origin:s,authUrl:n.authUrl,silentUrl:n.silentUrl||null,status:r&&n.silentUrl?"silent":"interactive",v2:r,name:null,popupBlocked:!1}}),O(s,n.authUrl)))},[O]),M=e.useCallback(n=>{g(r=>{if(!r[n])return r;const s={...r};return delete s[n],s})},[]),T=e.useCallback(n=>{n&&(M(n),b(r=>({...r,[n]:(r[n]||0)+1})))},[M]),u=e.useCallback(n=>{g(r=>!r[n]||r[n].status==="interactive"?r:{...r,[n]:{...r[n],status:"interactive"}})},[]),a=e.useCallback(n=>{M(n.origin)},[M]),c=e.useCallback(n=>{const r=F(n==null?void 0:n.authUrl);if(r&&J(r,window.location.origin)){j(n,"cross-site-legacy");return}A(n)},[A,j]);e.useEffect(()=>{if(!i)return;const n=[i.addListener("*","authorize",c),i.addListener("*","login",c),i.addListener("*","credential-request",r=>A(r,{v2:!0})),i.addListener("*","authorized",r=>{r!=null&&r.accessToken||T(F(r==null?void 0:r.authUrl))})];return()=>n.forEach(r=>r())},[i,c,A,T]),e.useEffect(()=>{const n=r=>{const s=r==null?void 0:r.data;if(!s||s.type!=="authorized"&&s.type!=="authorize-failed")return;const f=F(s.authUrl);if(!(!f||r.origin!==f)){if(s.type==="authorized"&&s.accessToken){L(U=>({...U,[f]:{accessToken:s.accessToken}})),M(f);return}s.type==="authorize-failed"&&u(f)}};return window.addEventListener("message",n),()=>window.removeEventListener("message",n)},[M,u]),e.useEffect(()=>{const n=z.current;Object.values(d).forEach(r=>{r.status==="silent"&&!n[r.origin]&&(n[r.origin]=setTimeout(()=>{delete n[r.origin],u(r.origin)},ie))}),Object.keys(n).forEach(r=>{(!d[r]||d[r].status!=="silent")&&(clearTimeout(n[r]),delete n[r])})},[d,u]),e.useEffect(()=>()=>{h.current&&h.current(),Object.values(z.current).forEach(clearTimeout)},[]);const l=e.useCallback(n=>{h.current&&(h.current(),h.current=null);const r=o||Q;h.current=r(n,{onBlocked:()=>{g(s=>s[n.origin]?{...s,[n.origin]:{...s[n.origin],popupBlocked:!0}}:s)},onClosed:()=>{if(n.v2){g(s=>!s[n.origin]||!s[n.origin].silentUrl?s:{...s,[n.origin]:{...s[n.origin],status:"silent"}});return}T(n.origin)}})},[o,T]),p={pending:Object.values(d).filter(n=>n.status==="interactive"),authorize:l,dismiss:a,originEpochs:k,credentials:E,unsupported:v},w=Object.values(d).filter(n=>n.status==="silent"&&n.silentUrl);return e.createElement(W.Provider,{value:p},t,w.map(n=>e.createElement("iframe",{key:`mm-silent-auth-${n.origin}`,src:n.silentUrl,title:`MachineMetrics silent authorization (${n.origin})`,"aria-hidden":"true",tabIndex:-1,style:{display:"none"}})))};X.propTypes={children:C.node,launcher:C.func};const Y=()=>e.useContext(W),N=t=>{const{originEpochs:o}=e.useContext(W),i=F(t);return i&&o[i]||0},R=t=>{const{credentials:o}=e.useContext(W),i=F(t);return i&&o[i]||null},ee=t=>{const{unsupported:o}=e.useContext(W),i=F(t);return i&&o[i]||null},ne=({children:t,authorizationLauncher:o})=>{const[i,d]=e.useState({}),[g,k]=e.useState({}),b=e.useRef({}),E=e.useRef({}),L=e.useRef({}),v=e.useCallback((u,a)=>{var c;return!!((c=L.current[u])!=null&&c.has(a))},[]),x=e.useCallback((u,a,c)=>{d(l=>({...l,[u]:{origin:a,frameRef:c}}))},[]),I=e.useCallback(u=>{d(a=>{const c={...a};return delete c[u],c}),k(a=>{const c={...a};return delete c[u],c}),delete L.current[u]},[]);e.useEffect(()=>{const u=(c=[],l)=>{c.forEach(p=>p(l))},a=c=>{var n,r,s,f,U;if(!((n=c==null?void 0:c.data)!=null&&n.instanceId))return;const{instanceId:l,type:p}=c.data,w=b.current;if(p==="response"){const{callbackId:y,response:Z,error:B}=c.data,S=E.current[y];S&&(S(Z,B),delete E.current[y]);return}if(p==="mark-registered"){const{requestType:y}=c.data;L.current[l]||(L.current[l]=new Set),L.current[l].add(y);return}p==="ready"&&k(y=>({...y,[l]:!0})),u((r=w[l])==null?void 0:r[p],c.data),u((s=w["*"])==null?void 0:s[p],c.data),u((f=w[l])==null?void 0:f["*"],c.data),u((U=w["*"])==null?void 0:U["*"],c.data)};return window.addEventListener("message",a),()=>{window.removeEventListener("message",a)}},[i]);const h=e.useCallback((u,a,c)=>{var p,w;const l=i[u];if(!l){console.warn(`Origin not set for id: ${u}. Unable to send message.`);return}(w=(p=l==null?void 0:l.frameRef)==null?void 0:p.current)!=null&&w.contentWindow&&l.frameRef.current.contentWindow.postMessage({type:a,...c,instanceId:u},l.origin)},[i]),z=e.useRef(0),O=e.useCallback(()=>`${Date.now()}-${++z.current}`,[]),j=e.useCallback(async(u,a,c={})=>new Promise((l,p)=>{const w=O(),n=(r,s)=>{delete E.current[w],s?p(s):l(r)};E.current[w]=n,h(u,"request",{callbackId:w,requestType:a,data:c})}),[h]),A=e.useCallback((u,a)=>{h(u,"load-options",a)},[h]),M=e.useCallback((u,a)=>{h(u,"validate",a)},[h]),T=e.useMemo(()=>({registerFrame:x,unregisterFrame:I,sendMessage:h,sendRequest:j,loadOptions:A,validate:M,hasHandler:v,readyFrames:g,addListener:(u,a,c)=>(b.current[u]||(b.current[u]={}),b.current[u][a]||(b.current[u][a]=[]),b.current[u][a].push(c),()=>{b.current[u][a]=b.current[u][a].filter(l=>l!==c)})}),[x,I,h,j,A,M,v,g]);return e.createElement(_.Provider,{value:T},e.createElement(X,{launcher:o},t))},$=(t,o,i)=>{const d=e.useContext(_);if(d===null)throw new Error("useEmbeddedEffect must be used within a MMEmbeddableZoneProvider");const g=e.useRef(i);e.useEffect(()=>{g.current=i},[i]),e.useEffect(()=>{if(!(!t||!o)){if(o.startsWith("key:")){const k=o.substring(4);return d.readyFrames[t]&&d.sendMessage(t,"subscribe-key",{keyChord:k}),d.addListener(t,`key-pressed:${k}`,(...E)=>g.current(...E))}return d.addListener(t,o,(...k)=>g.current(...k))}},[d,t,o])};ne.propTypes={children:C.node.isRequired,authorizationLauncher:C.func};const P=q.default||q,oe=1e4,ue="credentials",K=(t,o)=>`${t}/mm-embedded-interop?id=${o}&origin=${window.location.origin}&caps=${ue}`,ce=P.iframe`
2
2
  width: 100%;
3
3
  height: 100%;
4
4
  border: none;
5
- visibility: ${r=>r.$isReady?"visible":"hidden"};
6
- `,H=({id:r,src:u,path:f,onInit:c=()=>{},onTimeout:M,context:i={},params:m={},skipManifestCheck:b=!1,...L})=>{if("isConfiguring"in L)return console.error("isConfiguring must be passed via the params prop to MMEmbeddableZone"),null;if("colorMode"in i)return console.error("colorMode must be passed via the params prop to MMEmbeddableZone"),null;if("isFullScreen"in i)return console.error("isFullScreen must be passed via the params prop to MMEmbeddableZone"),null;const y=e.useRef(),[S,E]=e.useState(),[p,x]=e.useState(0),{registerFrame:k,unregisterFrame:O,sendMessage:$}=e.useContext(q),[j,n]=e.useState(!0),[s,t]=e.useState(),o=e.useRef(),d=e.useRef(M),l=e.useRef(c),F=e.useRef(!1);e.useEffect(()=>{d.current=M},[M]),e.useEffect(()=>{l.current=c},[c]),e.useEffect(()=>{p&&$(r,"set-context",{context:{...i,colorMode:m.colorMode,isFullScreen:m.isFullScreen}})},[i,m.colorMode,m.isFullScreen,r,p]),e.useEffect(()=>{p&&($(r,"set-params",{params:m}),$(r,"set-configuring",{isConfiguring:m.isConfiguring}))},[m,r,p]),e.useEffect(()=>{f!==void 0&&t((f==null?void 0:f.indexOf("/"))===0?f:`/${f}`)},[f]),e.useEffect(()=>{s===void 0||!p||$(r,"navigate",{path:s})},[s,p,r,$]),e.useEffect(()=>{if(!(!u||!r||!y)){if(b){const g=new URL(u);n(!0),k(r,g.origin,y),l.current(),E(`${g.origin}/mm-embedded-interop?id=${r}&origin=${window.location.origin}`)}else(async()=>{const g=await P(u);if(n(g),g){const Z=new URL(u);k(r,Z.origin,y),l.current(),E(`${Z.origin}/mm-embedded-interop?id=${r}&origin=${window.location.origin}`)}})();return()=>{O(r)}}},[u,r,k,y,b]),e.useEffect(()=>{if(!(!b||!S||F.current))return o.current=setTimeout(()=>{d.current&&d.current()},D),()=>clearTimeout(o.current)},[S,b]);const h=e.useCallback(()=>{F.current=!0,clearTimeout(o.current)},[]);I(r,"init",h),I(r,"authorize",h),I(r,"login",h),I(r,"ready",()=>{h(),x(g=>g+1)});const w=e.useRef();return I(r,"heartbeat",()=>{w.current&&clearTimeout(w.current),w.current=setTimeout(()=>{if(y.current){const g=new URL(u);y.current.src=`${g.origin}/mm-embedded-interop?id=${r}&origin=${window.location.origin}`}},6e3)}),e.useEffect(()=>()=>{w.current&&clearTimeout(w.current)},[]),!b&&!j?null:e.createElement(K,{$isReady:p,ref:y,src:S,...L})};H.propTypes={id:C.string,src:C.string.isRequired,path:C.string,onInit:C.func,onTimeout:C.func,skipManifestCheck:C.bool},a.MMEmbeddableZone=H,a.MMEmbeddableZoneContext=q,a.MMEmbeddableZoneProvider=v,a.getAppInfo=A,a.testIsEmbeddable=P,a.useEmbeddedEffect=I,Object.defineProperty(a,Symbol.toStringTag,{value:"Module"})}));
5
+ visibility: ${t=>t.$isReady?"visible":"hidden"};
6
+ `,le=P.div`
7
+ width: 100%;
8
+ height: 100%;
9
+ display: flex;
10
+ flex-direction: column;
11
+ align-items: center;
12
+ justify-content: center;
13
+ gap: 6px;
14
+ padding: 16px;
15
+ box-sizing: border-box;
16
+ text-align: center;
17
+ color: #555;
18
+ font-size: 14px;
19
+ `,te=({entry:t})=>e.createElement(le,null,e.createElement("div",{style:{fontWeight:600}},t&&(t.name||t.origin)||"This app"," can’t be embedded here"),e.createElement("div",{style:{fontSize:12,color:"#888"}},"It needs an update to support embedding from a different domain."));te.propTypes={entry:C.shape({origin:C.string,name:C.string,reason:C.string})};const de=P.div`
20
+ height: 100%;
21
+ display: flex;
22
+ flex: 1;
23
+ align-items: center;
24
+ justify-content: center;
25
+ `,re=({id:t,src:o,path:i,onInit:d=()=>{},onTimeout:g,context:k={},params:b={},skipManifestCheck:E=!1,renderUnsupported:L,...v})=>{if("isConfiguring"in v)return console.error("isConfiguring must be passed via the params prop to MMEmbeddableZone"),null;if("colorMode"in k)return console.error("colorMode must be passed via the params prop to MMEmbeddableZone"),null;if("isFullScreen"in k)return console.error("isFullScreen must be passed via the params prop to MMEmbeddableZone"),null;const x=e.useRef(),[I,h]=e.useState(),[z,O]=e.useState(0),[j,A]=e.useState(!1),M=N(o),T=R(o),u=ee(o);e.useEffect(()=>{M>0&&O(0)},[M]);const{registerFrame:a,unregisterFrame:c,sendMessage:l}=e.useContext(_),[p,w]=e.useState(!0),[n,r]=e.useState(),s=e.useRef(),f=e.useRef(g),U=e.useRef(d),y=e.useRef(!1);e.useEffect(()=>{f.current=g},[g]),e.useEffect(()=>{U.current=d},[d]),e.useEffect(()=>{z&&l(t,"set-context",{context:{...k,colorMode:b.colorMode,isFullScreen:b.isFullScreen}})},[k,b.colorMode,b.isFullScreen,t,z]),e.useEffect(()=>{z&&(l(t,"set-params",{params:b}),l(t,"set-configuring",{isConfiguring:b.isConfiguring}))},[b,t,z]),e.useEffect(()=>{i!==void 0&&r((i==null?void 0:i.indexOf("/"))===0?i:`/${i}`)},[i]),e.useEffect(()=>{n===void 0||!z||l(t,"navigate",{path:n})},[n,z,t,l]),e.useEffect(()=>{if(!(!o||!t||!x)){if(E){const S=new URL(o);w(!0),a(t,S.origin,x),U.current(),h(K(S.origin,t))}else(async()=>{const S=await V(o);if(w(S),S){const se=new URL(o);a(t,se.origin,x),U.current(),h(K(se.origin,t))}})();return()=>{c(t)}}},[o,t,a,x,E]),e.useEffect(()=>{if(!(!E||!I||y.current))return s.current=setTimeout(()=>{f.current&&f.current()},oe),()=>clearTimeout(s.current)},[I,E]);const Z=e.useCallback(()=>{y.current=!0,clearTimeout(s.current)},[]);$(t,"init",Z),$(t,"authorize",Z),$(t,"login",Z),$(t,"credential-request",()=>{Z(),A(!0)}),e.useEffect(()=>{!j||!T||l(t,"credential",{accessToken:T.accessToken})},[j,T,t,l]),$(t,"ready",()=>{Z(),O(S=>S+1)});const B=e.useRef();return $(t,"heartbeat",()=>{B.current&&clearTimeout(B.current),B.current=setTimeout(()=>{if(x.current){const S=new URL(o);x.current.src=K(S.origin,t)}},6e3)}),e.useEffect(()=>()=>{B.current&&clearTimeout(B.current)},[]),!E&&!p?e.createElement(de,null,e.createElement("div",{style:{textAlign:"center"}},"Application must adhere to the MM App Manifest specification to be embedded.")):u?L?L(u):e.createElement(te,{entry:u}):e.createElement(ce,{key:`auth-epoch-${M}`,$isReady:z,ref:x,src:I,...v})};re.propTypes={id:C.string,src:C.string.isRequired,path:C.string,onInit:C.func,onTimeout:C.func,skipManifestCheck:C.bool,renderUnsupported:C.func};const ae=q.div`
26
+ position: fixed;
27
+ inset: 0;
28
+ background: rgba(0, 0, 0, 0.45);
29
+ display: flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ z-index: 10000;
33
+ `,fe=q.div`
34
+ background: #fff;
35
+ border-radius: 8px;
36
+ box-shadow: 0 4px 24px rgba(0, 0, 0, 0.2);
37
+ padding: 24px;
38
+ width: 480px;
39
+ max-width: calc(100vw - 32px);
40
+ font-family: sans-serif;
41
+ color: #222;
42
+ `,me=q.div`
43
+ display: flex;
44
+ align-items: center;
45
+ justify-content: space-between;
46
+ padding: 10px 0;
47
+ gap: 16px;
48
+ `,ge=q.button`
49
+ background: #16a500;
50
+ color: #fff;
51
+ border: none;
52
+ border-radius: 6px;
53
+ padding: 9px 18px;
54
+ font-size: 14px;
55
+ cursor: pointer;
56
+ white-space: nowrap;
57
+ `,be=q.p`
58
+ color: #b3261e;
59
+ font-size: 13px;
60
+ margin: 4px 0 0;
61
+ `,he=()=>{const{pending:t,authorize:o}=Y();return t.length===0?null:e.createElement(ae,null,e.createElement(fe,null,e.createElement("h3",{style:{margin:"0 0 8px"}},"Authorization Required"),e.createElement("p",{style:{margin:"0 0 12px",fontSize:14,color:"#555"}},"The following apps need you to sign in and authorize them before they can load."),t.map(i=>e.createElement("div",{key:i.origin},e.createElement(me,null,e.createElement("div",null,e.createElement("div",{style:{fontWeight:600}},i.name||i.origin),i.name&&e.createElement("div",{style:{fontSize:12,color:"#888"}},i.origin)),e.createElement(ge,{onClick:()=>o(i)},"Authorize")),i.popupBlocked&&e.createElement(be,null,"The sign-in window was blocked. Allow popups for this site, then try again.")))))};m.EmbeddedAuthorizationContext=W,m.EmbeddedAuthorizationPrompt=he,m.MMEmbeddableZone=re,m.MMEmbeddableZoneContext=_,m.MMEmbeddableZoneProvider=ne,m.getAppInfo=H,m.isCrossSite=J,m.popupAuthorizationLauncher=Q,m.testIsEmbeddable=V,m.useEmbeddedAuthorizations=Y,m.useEmbeddedCredential=R,m.useEmbeddedEffect=$,m.useEmbeddedOriginEpoch=N,m.useEmbeddedUnsupported=ee,Object.defineProperty(m,Symbol.toStringTag,{value:"Module"})}));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@machinemetrics/mm-react-embeddable",
3
- "version": "1.3.1",
3
+ "version": "1.4.0-0",
4
4
  "license": "MIT",
5
5
  "module": "dist/mm-react-embeddable.es.js",
6
6
  "main": "dist/mm-react-embeddable.cjs.js",
@@ -20,7 +20,9 @@
20
20
  "build": "vite build",
21
21
  "start": "npm install --omit=peer && npm link && vite build --watch",
22
22
  "test": "vitest run",
23
- "test:watch": "vitest"
23
+ "test:watch": "vitest",
24
+ "prepare": "node scripts/install-hooks.mjs",
25
+ "check:version": "node scripts/check-version.mjs"
24
26
  },
25
27
  "files": [
26
28
  "dist"
@@ -42,4 +44,4 @@
42
44
  "vite": "^7.2.2",
43
45
  "vitest": "^4.0.10"
44
46
  }
45
- }
47
+ }