@momentco-ai/moment-sdk 0.2.1-dev.16 → 0.2.2-dev.17
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/moment-sdk.js +2 -2
- package/dist/moment-sdk.mjs +58 -54
- package/dist/types/sdk/button.d.ts +4 -0
- package/dist/types/sdk/types.d.ts +13 -0
- package/package.json +1 -1
package/dist/moment-sdk.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(
|
|
1
|
+
(function(f){"use strict";class w{popup=null;pollTimer=null;messageHandler=null;resultReceived=!1;opts;constructor(e){this.opts=e}open(e){this.cleanup(),this.resultReceived=!1;const t=this.buildPopupUrl(e),i=Math.round(window.screenX+(window.outerWidth-500)/2),r=Math.round(window.screenY+(window.outerHeight-700)/2);if(this.popup=window.open(t,"moment-oauth-popup",`width=500,height=700,left=${i},top=${r},menubar=no,toolbar=no,location=yes,status=no`),!this.popup||this.popup.closed){this.sendStatusToIframe("popup-blocked"),this.opts.onPopupBlocked();return}this.sendStatusToIframe("popup-opened"),this.startPolling(),this.messageHandler=n=>{if(n.origin!==this.opts.liveOrigin||n.source!==this.popup)return;const o=n.data;!o||typeof o!="object"||o.source!=="moment-live-embed"||o.type!=="moment.embed.result"||(this.resultReceived=!0,this.sendStatusToIframe("completed"),this.opts.iframeWindow&&this.opts.iframeWindow.postMessage(o,this.opts.liveOrigin),this.opts.onResult(o),this.cleanup())},window.addEventListener("message",this.messageHandler)}cleanup(){if(this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=null),this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null),this.popup&&!this.popup.closed)try{this.popup.close()}catch{}this.popup=null}buildPopupUrl(e){const t=window.location.origin,i=new URLSearchParams({provider:e.provider,teamSlug:e.teamSlug,ids:e.ids.join(","),triggerType:e.triggerType,returnOrigin:t});return e.subscriptionType&&i.set("subscriptionType",e.subscriptionType),`${this.opts.liveBaseUrl}/en/embed/oauth-popup?${i.toString()}`}startPolling(){this.pollTimer=setInterval(()=>{(!this.popup||this.popup.closed)&&(this.pollTimer&&(clearInterval(this.pollTimer),this.pollTimer=null),this.resultReceived||(this.sendStatusToIframe("popup-closed"),this.opts.onPopupClosed()),this.cleanup())},500)}sendStatusToIframe(e){if(!this.opts.iframeWindow)return;const t={source:"moment-sdk",type:"moment.embed.oauth.status",status:e};this.opts.iframeWindow.postMessage(t,this.opts.liveOrigin)}}const v="moment-sdk-trigger-styles",T=`
|
|
2
2
|
:where(.moment-sync-trigger) {
|
|
3
3
|
background-color: #1c1917;
|
|
4
4
|
color: #ffffff;
|
|
@@ -22,4 +22,4 @@
|
|
|
22
22
|
outline: 2px solid #1c1917;
|
|
23
23
|
outline-offset: 2px;
|
|
24
24
|
}
|
|
25
|
-
`;function S(){if(typeof document>"u"||document.getElementById(g))return;const o=document.createElement("style");o.id=g,o.textContent=T,document.head.appendChild(o)}const E=".moment-sync-trigger",k="https://live.dev.momentco.ai";class f{opts;liveBaseUrl;liveOrigin;overlay=null;iframe=null;popupBridge=null;messageHandler=null;boundClickHandlers=new Map;activePayload=null;previousFocusedElement=null;previousBodyOverflow="";didManageBodyOverflow=!1;closeTimer=null;constructor(e){this.opts={triggerSelector:E,...e},this.liveBaseUrl=k;try{this.liveOrigin=new URL(this.liveBaseUrl).origin}catch{throw new Error(`[MomentSdk] Invalid VITE_LIVE_BASE_URL: "${this.liveBaseUrl}"`)}S(),this.bindTriggers(),this.emitAnalytics("embed.init")}open(e){this.emitAnalytics("embed.open",{teamSlug:e.teamSlug,triggerType:e.triggerType}),this.createModal(e)}close(){this.handleCancel()}rebind(){this.unbindTriggers(),this.bindTriggers()}destroy(){this.cleanup(),this.unbindTriggers()}bindTriggers(){document.querySelectorAll(this.opts.triggerSelector).forEach(t=>{const i=s=>{s.preventDefault(),this.handleTriggerClick(t)},r=this.boundClickHandlers.get(t);r&&t.removeEventListener("click",r),t.addEventListener("click",i),this.boundClickHandlers.set(t,i)})}unbindTriggers(){this.boundClickHandlers.forEach((e,t)=>{t.removeEventListener("click",e)}),this.boundClickHandlers.clear()}handleTriggerClick(e){const t=e.getAttribute("data-moment-team-slug")??"",i=e.getAttribute("data-moment-slug")??void 0,r=e.getAttribute("data-moment-list-slug")??void 0,s=e.getAttribute("data-moment-trigger-type");let n="moment";s!=null&&s!==""&&(s==="moment"||s==="list"||s==="team"?n=s:console.warn("[MomentSdk] Invalid data-moment-trigger-type, falling back to 'moment':",s));const d=e.getAttribute("data-moment-ids")??e.getAttribute("data-moment-game-id")??"",m=d?d.split(",").filter(Boolean):[],a=e.getAttribute("data-moment-calendar");let u;if(a!=null&&a!==""&&(a==="google"||a==="outlook"?u=a:console.warn("[MomentSdk] Invalid data-moment-calendar, ignoring value:",a)),!t){console.warn("[MomentSdk] Missing data-moment-team-slug on trigger element");return}const l=n==="team"?void 0:i,c=n==="team"?void 0:r,p=n==="team"?[]:m;this.emitAnalytics("embed.trigger.click",{teamSlug:t,triggerType:n,momentIds:p}),this.open({teamSlug:t,momentSlug:l,listSlug:c,triggerType:n,ids:p,calendar:u??void 0})}createModal(e){this.cleanup(),this.previousFocusedElement=document.activeElement||null,this.activePayload=e;const t=this.buildIframeUrl(e);this.overlay=document.createElement("div"),this.overlay.setAttribute("role","presentation"),Object.assign(this.overlay.style,{position:"fixed",inset:"0",zIndex:"999999",display:"flex",alignItems:"center",justifyContent:"center",backgroundColor:"rgba(0, 0, 0, 0.5)",backdropFilter:"blur(2px)",padding:"16px"}),this.overlay.addEventListener("click",l=>{l.target===this.overlay&&this.handleCancel()});const i=l=>{l.key==="Escape"&&this.handleCancel()};document.addEventListener("keydown",i);const r=document.createElement("div");Object.assign(r.style,{position:"relative",width:"100%",maxWidth:"380px",borderRadius:"16px",overflow:"hidden",backgroundColor:"#000000",boxShadow:"0 25px 50px -12px rgba(0, 0, 0, 0.25)",display:"flex",flexDirection:"column"});const s=document.createElement("div");s.setAttribute("role","dialog"),s.setAttribute("aria-modal","true"),s.setAttribute("aria-label","Calendar sync modal"),s.tabIndex=-1,Object.assign(s.style,{position:"relative",width:"100%",maxHeight:"80vh",borderRadius:"12px",overflow:"auto",backgroundColor:"#ffffff"});const n=document.createElement("button");n.type="button",n.innerHTML='<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1l12 12M13 1L1 13" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>',n.setAttribute("aria-label","Close"),Object.assign(n.style,{position:"absolute",top:"10px",right:"10px",zIndex:"10",border:"none",backgroundColor:"transparent",color:"#999",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",width:"24px",height:"24px",padding:"0"}),n.addEventListener("mouseenter",()=>{n.style.color="#666"}),n.addEventListener("mouseleave",()=>{n.style.color="#999"}),n.addEventListener("click",()=>this.handleCancel()),this.iframe=document.createElement("iframe"),this.iframe.src=t,this.iframe.setAttribute("allow",""),this.iframe.setAttribute("sandbox","allow-scripts allow-same-origin allow-popups allow-forms"),this.iframe.setAttribute("scrolling","no"),Object.assign(this.iframe.style,{width:"100%",border:"none",display:"block",height:"420px",overflow:"hidden",transition:"height 0.15s ease"}),s.appendChild(n),s.appendChild(this.iframe);const d=document.createElement("div");Object.assign(d.style,{display:"flex",alignItems:"center",justifyContent:"center",gap:"6px",padding:"12px 0"});const m=document.createElement("span");m.textContent="Powered by",Object.assign(m.style,{fontFamily:"Inter, system-ui, -apple-system, sans-serif",fontSize:"12px",lineHeight:"16px",color:"#ffffff"});const a=document.createElement("img");a.alt="Moment",a.src=`${this.liveBaseUrl}/brand/moment-text-white.png`,Object.assign(a.style,{height:"auto",width:"67px"}),d.appendChild(m),d.appendChild(a),r.appendChild(s),r.appendChild(d),this.overlay.appendChild(r),document.body.appendChild(this.overlay);const u=l=>{if(l.key!=="Tab")return;const c=s.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');if(c.length===0){l.preventDefault(),s.focus();return}const p=c[0],b=c[c.length-1],y=document.activeElement;l.shiftKey&&y===p?(l.preventDefault(),b.focus()):!l.shiftKey&&y===b&&(l.preventDefault(),p.focus())};s.addEventListener("keydown",u),n.focus(),this.previousBodyOverflow=document.body.style.overflow,document.body.style.overflow="hidden",this.didManageBodyOverflow=!0,this.setupMessageListener(),this.overlay._escHandler=i,this.overlay._focusTrapHandler=u}buildIframeUrl(e){const t=new URLSearchParams;return t.set("teamSlug",e.teamSlug),e.momentSlug&&t.set("momentSlug",e.momentSlug),e.listSlug&&t.set("listSlug",e.listSlug),t.set("triggerType",e.triggerType),e.ids?.length&&t.set("ids",e.ids.join(",")),e.calendar&&t.set("calendar",e.calendar),t.set("returnOrigin",window.location.origin),t.set("embed","1"),`${this.liveBaseUrl}/en/embed/sync?${t.toString()}`}setupMessageListener(){this.messageHandler=e=>{if(e.origin!==this.liveOrigin||e.source!==this.iframe?.contentWindow)return;const t=e.data;if(!(!t||typeof t!="object")){if(t.source==="moment-live-embed"&&t.type==="moment.embed.oauth.start"){const i=t;this.emitAnalytics("oauth.start",{provider:i.provider,teamSlug:i.teamSlug}),this.handleOAuthStart(i);return}if(t.source==="moment-live-embed"&&t.type==="moment.embed.resize"){const i=typeof t.height=="number"?t.height:0;if(i>0&&this.iframe){const r=Math.round(window.innerHeight*.8);this.iframe.style.height=`${Math.min(i,r)}px`}return}if(t.source==="moment-live-embed"&&t.type==="moment.embed.open.url"){const{url:i}=t;i&&typeof i=="string"&&i.startsWith("webcal://")&&window.open(i,"_blank");return}if(t.source==="moment-live-embed"&&t.type==="moment.embed.result"){const i=t;this.handleResult(i)}}},window.addEventListener("message",this.messageHandler)}handleOAuthStart(e){this.popupBridge&&(this.popupBridge.cleanup(),this.popupBridge=null),this.popupBridge=new w({liveBaseUrl:this.liveBaseUrl,liveOrigin:this.liveOrigin,iframeWindow:this.iframe?.contentWindow??null,onResult:t=>{this.handleResult(t)},onPopupBlocked:()=>{this.emitAnalytics("oauth.popup.blocked",{provider:e.provider})},onPopupClosed:()=>{this.emitAnalytics("oauth.popup.closed",{provider:e.provider})}}),this.popupBridge.open(e)}handleResult(e){if(e.result==="success")this.emitAnalytics("subscribe.success",{provider:e.provider,triggerType:e.triggerType,momentIds:e.momentIds}),this.opts.onSuccess?.(e);else if(e.result==="error")this.emitAnalytics("subscribe.error",{provider:e.provider,triggerType:e.triggerType,momentIds:e.momentIds}),this.opts.onError?.(e);else if(e.result==="cancelled")return;this.opts.onClose?.(e),this.emitAnalytics("embed.close"),this.closeTimer=setTimeout(()=>this.cleanup(),1500)}handleCancel(){this.emitAnalytics("embed.close");const t={source:"moment-live-embed",type:"moment.embed.result",result:"cancelled",triggerType:this.activePayload?.triggerType??"moment",momentIds:this.activePayload?.ids??[]};this.opts.onClose?.(t),this.cleanup()}cleanup(){if(this.closeTimer&&(clearTimeout(this.closeTimer),this.closeTimer=null),this.popupBridge&&(this.popupBridge.cleanup(),this.popupBridge=null),this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null),this.overlay){const{_escHandler:e,_focusTrapHandler:t}=this.overlay;e&&document.removeEventListener("keydown",e);const i=this.overlay.firstElementChild;i&&t&&i.removeEventListener("keydown",t),this.overlay.remove(),this.overlay=null}this.iframe=null,this.activePayload=null,this.didManageBodyOverflow&&(document.body.style.overflow=this.previousBodyOverflow,this.didManageBodyOverflow=!1),this.previousFocusedElement&&typeof this.previousFocusedElement.focus=="function"&&this.previousFocusedElement.focus(),this.previousFocusedElement=null}emitAnalytics(e,t){this.opts.onAnalytics?.({event:e,timestamp:Date.now(),...t})}}function v(o){const e=document.createElement("button");return e.type="button",e.classList.add("moment-sync-trigger"),o.className&&o.className.split(" ").forEach(t=>{t&&e.classList.add(t)}),e.setAttribute("data-moment-team-slug",o.teamSlug),o.momentSlug&&e.setAttribute("data-moment-slug",o.momentSlug),o.listSlug&&e.setAttribute("data-moment-list-slug",o.listSlug),o.triggerType&&e.setAttribute("data-moment-trigger-type",o.triggerType),o.ids?.length&&e.setAttribute("data-moment-ids",o.ids.join(",")),o.calendar&&e.setAttribute("data-moment-calendar",o.calendar),e.textContent=o.label??"Add to Calendar",e}if(typeof window<"u"){const o=window;o.MomentSdk=f,o.createMomentButton=v}h.MomentSdk=f,h.createMomentButton=v,Object.defineProperty(h,Symbol.toStringTag,{value:"Module"})})(this.MomentSdk=this.MomentSdk||{});
|
|
25
|
+
`;function S(){if(typeof document>"u"||document.getElementById(v))return;const s=document.createElement("style");s.id=v,s.textContent=T,document.head.appendChild(s)}const E=".moment-sync-trigger",I="https://live.dev.momentco.ai";class b{opts;liveBaseUrl;liveOrigin;overlay=null;iframe=null;popupBridge=null;messageHandler=null;boundClickHandlers=new Map;activePayload=null;previousFocusedElement=null;previousBodyOverflow="";didManageBodyOverflow=!1;closeTimer=null;constructor(e){this.opts={triggerSelector:E,...e},this.liveBaseUrl=I;try{this.liveOrigin=new URL(this.liveBaseUrl).origin}catch{throw new Error(`[MomentSdk] Invalid VITE_LIVE_BASE_URL: "${this.liveBaseUrl}"`)}S(),this.bindTriggers(),this.emitAnalytics("embed.init")}open(e){this.emitAnalytics("embed.open",{teamSlug:e.teamSlug,triggerType:e.triggerType}),this.createModal(e)}close(){this.handleCancel()}rebind(){this.unbindTriggers(),this.bindTriggers()}destroy(){this.cleanup(),this.unbindTriggers()}bindTriggers(){document.querySelectorAll(this.opts.triggerSelector).forEach(t=>{const i=n=>{n.preventDefault(),this.handleTriggerClick(t)},r=this.boundClickHandlers.get(t);r&&t.removeEventListener("click",r),t.addEventListener("click",i),this.boundClickHandlers.set(t,i)})}unbindTriggers(){this.boundClickHandlers.forEach((e,t)=>{t.removeEventListener("click",e)}),this.boundClickHandlers.clear()}handleTriggerClick(e){const t=e.getAttribute("data-moment-team-slug")??"",i=e.getAttribute("data-moment-slug")??void 0,r=e.getAttribute("data-moment-list-slug")??void 0,n=e.getAttribute("data-moment-trigger-type");let o="moment";n!=null&&n!==""&&(n==="moment"||n==="list"||n==="team"?o=n:console.warn("[MomentSdk] Invalid data-moment-trigger-type, falling back to 'moment':",n));const d=e.getAttribute("data-moment-ids")??e.getAttribute("data-moment-game-id")??"",u=d?d.split(",").filter(Boolean):[],a=e.getAttribute("data-moment-calendar");let m;a!=null&&a!==""&&(a==="google"||a==="outlook"?m=a:console.warn("[MomentSdk] Invalid data-moment-calendar, ignoring value:",a));const l=e.getAttribute("data-api-source-id")??void 0,c=e.getAttribute("data-external-event-id")??void 0;if(!t){console.warn("[MomentSdk] Missing data-moment-team-slug on trigger element");return}const h=o==="team"?void 0:i,g=o==="team"?void 0:r,p=o==="team"?[]:u;this.emitAnalytics("embed.trigger.click",{teamSlug:t,triggerType:o,momentIds:p}),this.open({teamSlug:t,momentSlug:h,listSlug:g,triggerType:o,ids:p,calendar:m??void 0,apiSourceId:l,externalEventId:c})}createModal(e){this.cleanup(),this.previousFocusedElement=document.activeElement||null,this.activePayload=e;const t=this.buildIframeUrl(e);this.overlay=document.createElement("div"),this.overlay.setAttribute("role","presentation"),Object.assign(this.overlay.style,{position:"fixed",inset:"0",zIndex:"999999",display:"flex",alignItems:"center",justifyContent:"center",backgroundColor:"rgba(0, 0, 0, 0.5)",backdropFilter:"blur(2px)",padding:"16px"}),this.overlay.addEventListener("click",l=>{l.target===this.overlay&&this.handleCancel()});const i=l=>{l.key==="Escape"&&this.handleCancel()};document.addEventListener("keydown",i);const r=document.createElement("div");Object.assign(r.style,{position:"relative",width:"100%",maxWidth:"380px",borderRadius:"16px",overflow:"hidden",backgroundColor:"#000000",boxShadow:"0 25px 50px -12px rgba(0, 0, 0, 0.25)",display:"flex",flexDirection:"column"});const n=document.createElement("div");n.setAttribute("role","dialog"),n.setAttribute("aria-modal","true"),n.setAttribute("aria-label","Calendar sync modal"),n.tabIndex=-1,Object.assign(n.style,{position:"relative",width:"100%",maxHeight:"80vh",borderRadius:"12px",overflow:"auto",backgroundColor:"#ffffff"});const o=document.createElement("button");o.type="button",o.innerHTML='<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1l12 12M13 1L1 13" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>',o.setAttribute("aria-label","Close"),Object.assign(o.style,{position:"absolute",top:"10px",right:"10px",zIndex:"10",border:"none",backgroundColor:"transparent",color:"#999",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",width:"24px",height:"24px",padding:"0"}),o.addEventListener("mouseenter",()=>{o.style.color="#666"}),o.addEventListener("mouseleave",()=>{o.style.color="#999"}),o.addEventListener("click",()=>this.handleCancel()),this.iframe=document.createElement("iframe"),this.iframe.src=t,this.iframe.setAttribute("allow",""),this.iframe.setAttribute("sandbox","allow-scripts allow-same-origin allow-popups allow-forms"),this.iframe.setAttribute("scrolling","no"),Object.assign(this.iframe.style,{width:"100%",border:"none",display:"block",height:"420px",overflow:"hidden",transition:"height 0.15s ease"}),n.appendChild(o),n.appendChild(this.iframe);const d=document.createElement("div");Object.assign(d.style,{display:"flex",alignItems:"center",justifyContent:"center",gap:"6px",padding:"12px 0"});const u=document.createElement("span");u.textContent="Powered by",Object.assign(u.style,{fontFamily:"Inter, system-ui, -apple-system, sans-serif",fontSize:"12px",lineHeight:"16px",color:"#ffffff"});const a=document.createElement("img");a.alt="Moment",a.src=`${this.liveBaseUrl}/brand/moment-text-white.png`,Object.assign(a.style,{height:"auto",width:"67px"}),d.appendChild(u),d.appendChild(a),r.appendChild(n),r.appendChild(d),this.overlay.appendChild(r),document.body.appendChild(this.overlay);const m=l=>{if(l.key!=="Tab")return;const c=n.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');if(c.length===0){l.preventDefault(),n.focus();return}const h=c[0],g=c[c.length-1],p=document.activeElement;l.shiftKey&&p===h?(l.preventDefault(),g.focus()):!l.shiftKey&&p===g&&(l.preventDefault(),h.focus())};n.addEventListener("keydown",m),o.focus(),this.previousBodyOverflow=document.body.style.overflow,document.body.style.overflow="hidden",this.didManageBodyOverflow=!0,this.setupMessageListener(),this.overlay._escHandler=i,this.overlay._focusTrapHandler=m}buildIframeUrl(e){const t=new URLSearchParams;return t.set("teamSlug",e.teamSlug),e.momentSlug&&t.set("momentSlug",e.momentSlug),e.listSlug&&t.set("listSlug",e.listSlug),t.set("triggerType",e.triggerType),e.ids?.length&&t.set("ids",e.ids.join(",")),e.calendar&&t.set("calendar",e.calendar),e.apiSourceId&&t.set("subscriptionId",e.apiSourceId),e.externalEventId&&t.set("externalId",e.externalEventId),t.set("returnOrigin",window.location.origin),t.set("embed","1"),`${this.liveBaseUrl}/en/embed/sync?${t.toString()}`}setupMessageListener(){this.messageHandler=e=>{if(e.origin!==this.liveOrigin||e.source!==this.iframe?.contentWindow)return;const t=e.data;if(!(!t||typeof t!="object")){if(t.source==="moment-live-embed"&&t.type==="moment.embed.oauth.start"){const i=t;this.emitAnalytics("oauth.start",{provider:i.provider,teamSlug:i.teamSlug}),this.handleOAuthStart(i);return}if(t.source==="moment-live-embed"&&t.type==="moment.embed.resize"){const i=typeof t.height=="number"?t.height:0;if(i>0&&this.iframe){const r=Math.round(window.innerHeight*.8);this.iframe.style.height=`${Math.min(i,r)}px`}return}if(t.source==="moment-live-embed"&&t.type==="moment.embed.open.url"){const{url:i}=t;i&&typeof i=="string"&&i.startsWith("webcal://")&&window.open(i,"_blank");return}if(t.source==="moment-live-embed"&&t.type==="moment.embed.result"){const i=t;this.handleResult(i)}}},window.addEventListener("message",this.messageHandler)}handleOAuthStart(e){this.popupBridge&&(this.popupBridge.cleanup(),this.popupBridge=null),this.popupBridge=new w({liveBaseUrl:this.liveBaseUrl,liveOrigin:this.liveOrigin,iframeWindow:this.iframe?.contentWindow??null,onResult:t=>{this.handleResult(t)},onPopupBlocked:()=>{this.emitAnalytics("oauth.popup.blocked",{provider:e.provider})},onPopupClosed:()=>{this.emitAnalytics("oauth.popup.closed",{provider:e.provider})}}),this.popupBridge.open(e)}handleResult(e){if(e.result==="success")this.emitAnalytics("subscribe.success",{provider:e.provider,triggerType:e.triggerType,momentIds:e.momentIds}),this.opts.onSuccess?.(e);else if(e.result==="error")this.emitAnalytics("subscribe.error",{provider:e.provider,triggerType:e.triggerType,momentIds:e.momentIds}),this.opts.onError?.(e);else if(e.result==="cancelled")return;this.opts.onClose?.(e),this.emitAnalytics("embed.close"),this.closeTimer=setTimeout(()=>this.cleanup(),1500)}handleCancel(){this.emitAnalytics("embed.close");const t={source:"moment-live-embed",type:"moment.embed.result",result:"cancelled",triggerType:this.activePayload?.triggerType??"moment",momentIds:this.activePayload?.ids??[]};this.opts.onClose?.(t),this.cleanup()}cleanup(){if(this.closeTimer&&(clearTimeout(this.closeTimer),this.closeTimer=null),this.popupBridge&&(this.popupBridge.cleanup(),this.popupBridge=null),this.messageHandler&&(window.removeEventListener("message",this.messageHandler),this.messageHandler=null),this.overlay){const{_escHandler:e,_focusTrapHandler:t}=this.overlay;e&&document.removeEventListener("keydown",e);const i=this.overlay.firstElementChild;i&&t&&i.removeEventListener("keydown",t),this.overlay.remove(),this.overlay=null}this.iframe=null,this.activePayload=null,this.didManageBodyOverflow&&(document.body.style.overflow=this.previousBodyOverflow,this.didManageBodyOverflow=!1),this.previousFocusedElement&&typeof this.previousFocusedElement.focus=="function"&&this.previousFocusedElement.focus(),this.previousFocusedElement=null}emitAnalytics(e,t){this.opts.onAnalytics?.({event:e,timestamp:Date.now(),...t})}}function y(s){const e=document.createElement("button");return e.type="button",e.classList.add("moment-sync-trigger"),s.className&&s.className.split(" ").forEach(t=>{t&&e.classList.add(t)}),e.setAttribute("data-moment-team-slug",s.teamSlug),s.momentSlug&&e.setAttribute("data-moment-slug",s.momentSlug),s.listSlug&&e.setAttribute("data-moment-list-slug",s.listSlug),s.triggerType&&e.setAttribute("data-moment-trigger-type",s.triggerType),s.ids?.length&&e.setAttribute("data-moment-ids",s.ids.join(",")),s.calendar&&e.setAttribute("data-moment-calendar",s.calendar),s.apiSourceId&&e.setAttribute("data-api-source-id",s.apiSourceId),s.externalEventId&&e.setAttribute("data-external-event-id",s.externalEventId),e.textContent=s.label??"Add to Calendar",e}if(typeof window<"u"){const s=window;s.MomentSdk=b,s.createMomentButton=y}f.MomentSdk=b,f.createMomentButton=y,Object.defineProperty(f,Symbol.toStringTag,{value:"Module"})})(this.MomentSdk=this.MomentSdk||{});
|
package/dist/moment-sdk.mjs
CHANGED
|
@@ -12,19 +12,19 @@ class v {
|
|
|
12
12
|
*/
|
|
13
13
|
open(e) {
|
|
14
14
|
this.cleanup(), this.resultReceived = !1;
|
|
15
|
-
const t = this.buildPopupUrl(e), i = Math.round(window.screenX + (window.outerWidth - 500) / 2),
|
|
15
|
+
const t = this.buildPopupUrl(e), i = Math.round(window.screenX + (window.outerWidth - 500) / 2), o = Math.round(window.screenY + (window.outerHeight - 700) / 2);
|
|
16
16
|
if (this.popup = window.open(
|
|
17
17
|
t,
|
|
18
18
|
"moment-oauth-popup",
|
|
19
|
-
`width=500,height=700,left=${i},top=${
|
|
19
|
+
`width=500,height=700,left=${i},top=${o},menubar=no,toolbar=no,location=yes,status=no`
|
|
20
20
|
), !this.popup || this.popup.closed) {
|
|
21
21
|
this.sendStatusToIframe("popup-blocked"), this.opts.onPopupBlocked();
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
|
-
this.sendStatusToIframe("popup-opened"), this.startPolling(), this.messageHandler = (
|
|
25
|
-
if (
|
|
26
|
-
const
|
|
27
|
-
!
|
|
24
|
+
this.sendStatusToIframe("popup-opened"), this.startPolling(), this.messageHandler = (n) => {
|
|
25
|
+
if (n.origin !== this.opts.liveOrigin || n.source !== this.popup) return;
|
|
26
|
+
const r = n.data;
|
|
27
|
+
!r || typeof r != "object" || r.source !== "moment-live-embed" || r.type !== "moment.embed.result" || (this.resultReceived = !0, this.sendStatusToIframe("completed"), this.opts.iframeWindow && this.opts.iframeWindow.postMessage(r, this.opts.liveOrigin), this.opts.onResult(r), this.cleanup());
|
|
28
28
|
}, window.addEventListener("message", this.messageHandler);
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
@@ -90,8 +90,8 @@ const f = "moment-sdk-trigger-styles", b = `
|
|
|
90
90
|
`;
|
|
91
91
|
function y() {
|
|
92
92
|
if (typeof document > "u" || document.getElementById(f)) return;
|
|
93
|
-
const
|
|
94
|
-
|
|
93
|
+
const s = document.createElement("style");
|
|
94
|
+
s.id = f, s.textContent = b, document.head.appendChild(s);
|
|
95
95
|
}
|
|
96
96
|
const w = ".moment-sync-trigger", T = "https://live.dev.momentco.ai";
|
|
97
97
|
class E {
|
|
@@ -150,10 +150,10 @@ class E {
|
|
|
150
150
|
// ── Private: trigger binding ──────────────────────────────────────
|
|
151
151
|
bindTriggers() {
|
|
152
152
|
document.querySelectorAll(this.opts.triggerSelector).forEach((t) => {
|
|
153
|
-
const i = (
|
|
154
|
-
|
|
155
|
-
},
|
|
156
|
-
|
|
153
|
+
const i = (n) => {
|
|
154
|
+
n.preventDefault(), this.handleTriggerClick(t);
|
|
155
|
+
}, o = this.boundClickHandlers.get(t);
|
|
156
|
+
o && t.removeEventListener("click", o), t.addEventListener("click", i), this.boundClickHandlers.set(t, i);
|
|
157
157
|
});
|
|
158
158
|
}
|
|
159
159
|
unbindTriggers() {
|
|
@@ -162,30 +162,34 @@ class E {
|
|
|
162
162
|
}), this.boundClickHandlers.clear();
|
|
163
163
|
}
|
|
164
164
|
handleTriggerClick(e) {
|
|
165
|
-
const t = e.getAttribute("data-moment-team-slug") ?? "", i = e.getAttribute("data-moment-slug") ?? void 0,
|
|
166
|
-
let
|
|
167
|
-
|
|
165
|
+
const t = e.getAttribute("data-moment-team-slug") ?? "", i = e.getAttribute("data-moment-slug") ?? void 0, o = e.getAttribute("data-moment-list-slug") ?? void 0, n = e.getAttribute("data-moment-trigger-type");
|
|
166
|
+
let r = "moment";
|
|
167
|
+
n != null && n !== "" && (n === "moment" || n === "list" || n === "team" ? r = n : console.warn(
|
|
168
168
|
"[MomentSdk] Invalid data-moment-trigger-type, falling back to 'moment':",
|
|
169
|
-
|
|
169
|
+
n
|
|
170
170
|
));
|
|
171
|
-
const d = e.getAttribute("data-moment-ids") ?? e.getAttribute("data-moment-game-id") ?? "",
|
|
172
|
-
let
|
|
173
|
-
|
|
171
|
+
const d = e.getAttribute("data-moment-ids") ?? e.getAttribute("data-moment-game-id") ?? "", u = d ? d.split(",").filter(Boolean) : [], a = e.getAttribute("data-moment-calendar");
|
|
172
|
+
let m;
|
|
173
|
+
a != null && a !== "" && (a === "google" || a === "outlook" ? m = a : console.warn("[MomentSdk] Invalid data-moment-calendar, ignoring value:", a));
|
|
174
|
+
const l = e.getAttribute("data-api-source-id") ?? void 0, c = e.getAttribute("data-external-event-id") ?? void 0;
|
|
175
|
+
if (!t) {
|
|
174
176
|
console.warn("[MomentSdk] Missing data-moment-team-slug on trigger element");
|
|
175
177
|
return;
|
|
176
178
|
}
|
|
177
|
-
const
|
|
179
|
+
const h = r === "team" ? void 0 : i, g = r === "team" ? void 0 : o, p = r === "team" ? [] : u;
|
|
178
180
|
this.emitAnalytics("embed.trigger.click", {
|
|
179
181
|
teamSlug: t,
|
|
180
|
-
triggerType:
|
|
182
|
+
triggerType: r,
|
|
181
183
|
momentIds: p
|
|
182
184
|
}), this.open({
|
|
183
185
|
teamSlug: t,
|
|
184
|
-
momentSlug:
|
|
185
|
-
listSlug:
|
|
186
|
-
triggerType:
|
|
186
|
+
momentSlug: h,
|
|
187
|
+
listSlug: g,
|
|
188
|
+
triggerType: r,
|
|
187
189
|
ids: p,
|
|
188
|
-
calendar:
|
|
190
|
+
calendar: m ?? void 0,
|
|
191
|
+
apiSourceId: l,
|
|
192
|
+
externalEventId: c
|
|
189
193
|
});
|
|
190
194
|
}
|
|
191
195
|
// ── Private: modal creation ───────────────────────────────────────
|
|
@@ -209,8 +213,8 @@ class E {
|
|
|
209
213
|
l.key === "Escape" && this.handleCancel();
|
|
210
214
|
};
|
|
211
215
|
document.addEventListener("keydown", i);
|
|
212
|
-
const
|
|
213
|
-
Object.assign(
|
|
216
|
+
const o = document.createElement("div");
|
|
217
|
+
Object.assign(o.style, {
|
|
214
218
|
position: "relative",
|
|
215
219
|
width: "100%",
|
|
216
220
|
maxWidth: "380px",
|
|
@@ -221,8 +225,8 @@ class E {
|
|
|
221
225
|
display: "flex",
|
|
222
226
|
flexDirection: "column"
|
|
223
227
|
});
|
|
224
|
-
const
|
|
225
|
-
|
|
228
|
+
const n = document.createElement("div");
|
|
229
|
+
n.setAttribute("role", "dialog"), n.setAttribute("aria-modal", "true"), n.setAttribute("aria-label", "Calendar sync modal"), n.tabIndex = -1, Object.assign(n.style, {
|
|
226
230
|
position: "relative",
|
|
227
231
|
width: "100%",
|
|
228
232
|
maxHeight: "80vh",
|
|
@@ -230,8 +234,8 @@ class E {
|
|
|
230
234
|
overflow: "auto",
|
|
231
235
|
backgroundColor: "#ffffff"
|
|
232
236
|
});
|
|
233
|
-
const
|
|
234
|
-
|
|
237
|
+
const r = document.createElement("button");
|
|
238
|
+
r.type = "button", r.innerHTML = '<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 1l12 12M13 1L1 13" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>', r.setAttribute("aria-label", "Close"), Object.assign(r.style, {
|
|
235
239
|
position: "absolute",
|
|
236
240
|
top: "10px",
|
|
237
241
|
right: "10px",
|
|
@@ -246,18 +250,18 @@ class E {
|
|
|
246
250
|
width: "24px",
|
|
247
251
|
height: "24px",
|
|
248
252
|
padding: "0"
|
|
249
|
-
}),
|
|
250
|
-
|
|
251
|
-
}),
|
|
252
|
-
|
|
253
|
-
}),
|
|
253
|
+
}), r.addEventListener("mouseenter", () => {
|
|
254
|
+
r.style.color = "#666";
|
|
255
|
+
}), r.addEventListener("mouseleave", () => {
|
|
256
|
+
r.style.color = "#999";
|
|
257
|
+
}), r.addEventListener("click", () => this.handleCancel()), this.iframe = document.createElement("iframe"), this.iframe.src = t, this.iframe.setAttribute("allow", ""), this.iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-popups allow-forms"), this.iframe.setAttribute("scrolling", "no"), Object.assign(this.iframe.style, {
|
|
254
258
|
width: "100%",
|
|
255
259
|
border: "none",
|
|
256
260
|
display: "block",
|
|
257
261
|
height: "420px",
|
|
258
262
|
overflow: "hidden",
|
|
259
263
|
transition: "height 0.15s ease"
|
|
260
|
-
}),
|
|
264
|
+
}), n.appendChild(r), n.appendChild(this.iframe);
|
|
261
265
|
const d = document.createElement("div");
|
|
262
266
|
Object.assign(d.style, {
|
|
263
267
|
display: "flex",
|
|
@@ -266,8 +270,8 @@ class E {
|
|
|
266
270
|
gap: "6px",
|
|
267
271
|
padding: "12px 0"
|
|
268
272
|
});
|
|
269
|
-
const
|
|
270
|
-
|
|
273
|
+
const u = document.createElement("span");
|
|
274
|
+
u.textContent = "Powered by", Object.assign(u.style, {
|
|
271
275
|
fontFamily: "Inter, system-ui, -apple-system, sans-serif",
|
|
272
276
|
fontSize: "12px",
|
|
273
277
|
lineHeight: "16px",
|
|
@@ -277,24 +281,24 @@ class E {
|
|
|
277
281
|
a.alt = "Moment", a.src = `${this.liveBaseUrl}/brand/moment-text-white.png`, Object.assign(a.style, {
|
|
278
282
|
height: "auto",
|
|
279
283
|
width: "67px"
|
|
280
|
-
}), d.appendChild(
|
|
281
|
-
const
|
|
284
|
+
}), d.appendChild(u), d.appendChild(a), o.appendChild(n), o.appendChild(d), this.overlay.appendChild(o), document.body.appendChild(this.overlay);
|
|
285
|
+
const m = (l) => {
|
|
282
286
|
if (l.key !== "Tab") return;
|
|
283
|
-
const c =
|
|
287
|
+
const c = n.querySelectorAll(
|
|
284
288
|
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
285
289
|
);
|
|
286
290
|
if (c.length === 0) {
|
|
287
|
-
l.preventDefault(),
|
|
291
|
+
l.preventDefault(), n.focus();
|
|
288
292
|
return;
|
|
289
293
|
}
|
|
290
|
-
const
|
|
291
|
-
l.shiftKey &&
|
|
294
|
+
const h = c[0], g = c[c.length - 1], p = document.activeElement;
|
|
295
|
+
l.shiftKey && p === h ? (l.preventDefault(), g.focus()) : !l.shiftKey && p === g && (l.preventDefault(), h.focus());
|
|
292
296
|
};
|
|
293
|
-
|
|
297
|
+
n.addEventListener("keydown", m), r.focus(), this.previousBodyOverflow = document.body.style.overflow, document.body.style.overflow = "hidden", this.didManageBodyOverflow = !0, this.setupMessageListener(), this.overlay._escHandler = i, this.overlay._focusTrapHandler = m;
|
|
294
298
|
}
|
|
295
299
|
buildIframeUrl(e) {
|
|
296
300
|
const t = new URLSearchParams();
|
|
297
|
-
return t.set("teamSlug", e.teamSlug), e.momentSlug && t.set("momentSlug", e.momentSlug), e.listSlug && t.set("listSlug", e.listSlug), t.set("triggerType", e.triggerType), e.ids?.length && t.set("ids", e.ids.join(",")), e.calendar && t.set("calendar", e.calendar), t.set("returnOrigin", window.location.origin), t.set("embed", "1"), `${this.liveBaseUrl}/en/embed/sync?${t.toString()}`;
|
|
301
|
+
return t.set("teamSlug", e.teamSlug), e.momentSlug && t.set("momentSlug", e.momentSlug), e.listSlug && t.set("listSlug", e.listSlug), t.set("triggerType", e.triggerType), e.ids?.length && t.set("ids", e.ids.join(",")), e.calendar && t.set("calendar", e.calendar), e.apiSourceId && t.set("subscriptionId", e.apiSourceId), e.externalEventId && t.set("externalId", e.externalEventId), t.set("returnOrigin", window.location.origin), t.set("embed", "1"), `${this.liveBaseUrl}/en/embed/sync?${t.toString()}`;
|
|
298
302
|
}
|
|
299
303
|
// ── Private: message handling ─────────────────────────────────────
|
|
300
304
|
setupMessageListener() {
|
|
@@ -313,8 +317,8 @@ class E {
|
|
|
313
317
|
if (t.source === "moment-live-embed" && t.type === "moment.embed.resize") {
|
|
314
318
|
const i = typeof t.height == "number" ? t.height : 0;
|
|
315
319
|
if (i > 0 && this.iframe) {
|
|
316
|
-
const
|
|
317
|
-
this.iframe.style.height = `${Math.min(i,
|
|
320
|
+
const o = Math.round(window.innerHeight * 0.8);
|
|
321
|
+
this.iframe.style.height = `${Math.min(i, o)}px`;
|
|
318
322
|
}
|
|
319
323
|
return;
|
|
320
324
|
}
|
|
@@ -397,15 +401,15 @@ class E {
|
|
|
397
401
|
});
|
|
398
402
|
}
|
|
399
403
|
}
|
|
400
|
-
function S(
|
|
404
|
+
function S(s) {
|
|
401
405
|
const e = document.createElement("button");
|
|
402
|
-
return e.type = "button", e.classList.add("moment-sync-trigger"),
|
|
406
|
+
return e.type = "button", e.classList.add("moment-sync-trigger"), s.className && s.className.split(" ").forEach((t) => {
|
|
403
407
|
t && e.classList.add(t);
|
|
404
|
-
}), e.setAttribute("data-moment-team-slug",
|
|
408
|
+
}), e.setAttribute("data-moment-team-slug", s.teamSlug), s.momentSlug && e.setAttribute("data-moment-slug", s.momentSlug), s.listSlug && e.setAttribute("data-moment-list-slug", s.listSlug), s.triggerType && e.setAttribute("data-moment-trigger-type", s.triggerType), s.ids?.length && e.setAttribute("data-moment-ids", s.ids.join(",")), s.calendar && e.setAttribute("data-moment-calendar", s.calendar), s.apiSourceId && e.setAttribute("data-api-source-id", s.apiSourceId), s.externalEventId && e.setAttribute("data-external-event-id", s.externalEventId), e.textContent = s.label ?? "Add to Calendar", e;
|
|
405
409
|
}
|
|
406
410
|
if (typeof window < "u") {
|
|
407
|
-
const
|
|
408
|
-
|
|
411
|
+
const s = window;
|
|
412
|
+
s.MomentSdk = E, s.createMomentButton = S;
|
|
409
413
|
}
|
|
410
414
|
export {
|
|
411
415
|
E as MomentSdk,
|
|
@@ -11,6 +11,10 @@ export declare function createMomentButton(options: {
|
|
|
11
11
|
triggerType?: MomentTriggerType;
|
|
12
12
|
ids?: string[];
|
|
13
13
|
calendar?: CalendarProvider;
|
|
14
|
+
/** Sync subscription source id; pairs with `externalEventId` for server-side resolution. */
|
|
15
|
+
apiSourceId?: string;
|
|
16
|
+
/** External event identifier resolved against `apiSourceId`. */
|
|
17
|
+
externalEventId?: string;
|
|
14
18
|
label?: string;
|
|
15
19
|
className?: string;
|
|
16
20
|
}): HTMLButtonElement;
|
|
@@ -40,6 +40,19 @@ export interface MomentSdkOpenPayload {
|
|
|
40
40
|
triggerType: MomentTriggerType;
|
|
41
41
|
ids?: string[];
|
|
42
42
|
calendar?: CalendarProvider;
|
|
43
|
+
/**
|
|
44
|
+
* Sync subscription source identifier (the publisher's sync-subscription id).
|
|
45
|
+
* When provided together with `externalEventId`, the embed resolves the moment
|
|
46
|
+
* server-side from the source + external event identifier instead of a slug.
|
|
47
|
+
* Forwarded to the Live embed as the `subscriptionId` query param.
|
|
48
|
+
*/
|
|
49
|
+
apiSourceId?: string;
|
|
50
|
+
/**
|
|
51
|
+
* External event identifier emitted by the publisher's source feed (e.g. the
|
|
52
|
+
* provider's native event id). Resolved against `apiSourceId` to a moment.
|
|
53
|
+
* Forwarded to the Live embed as the `externalId` query param.
|
|
54
|
+
*/
|
|
55
|
+
externalEventId?: string;
|
|
43
56
|
}
|
|
44
57
|
/** Backend subscription resource type that the embed will create */
|
|
45
58
|
export type MomentSubscriptionType = 'moment' | 'list' | 'team';
|
package/package.json
CHANGED