@momentco-ai/moment-sdk 0.3.1-dev.20 → 0.3.3-dev.22
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 +68 -62
- package/dist/types/sdk/button.d.ts +5 -0
- package/dist/types/sdk/types.d.ts +29 -1
- package/package.json +4 -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),l=Math.round(window.screenY+(window.outerHeight-700)/2);if(this.popup=window.open(t,"moment-oauth-popup",`width=500,height=700,left=${i},top=${l},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=s=>{if(s.origin!==this.opts.liveOrigin||s.source!==this.popup)return;const r=s.data;!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())},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),e.selection&&i.set("selection",e.selection),`${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)}}function x(n,e,t=typeof window<"u"?window.location.origin:""){const i=new URLSearchParams;return i.set("teamSlug",e.teamSlug),e.momentSlug&&i.set("momentSlug",e.momentSlug),e.listSlug&&i.set("listSlug",e.listSlug),i.set("triggerType",e.triggerType),e.ids?.length&&i.set("ids",e.ids.join(",")),e.playlistSlugs?.length&&i.set("playlistSlugs",e.playlistSlugs.join(",")),e.calendar&&i.set("calendar",e.calendar),e.apiSourceId&&i.set("subscriptionId",e.apiSourceId),e.externalEventId&&i.set("externalId",e.externalEventId),e.externalEventIdPrefix&&!e.externalEventId&&i.set("externalIdPrefix",e.externalEventIdPrefix),i.set("returnOrigin",t),i.set("embed","1"),`${n}/en/embed/sync?${i.toString()}`}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 T(){if(typeof document>"u"||document.getElementById(f))return;const n=document.createElement("style");n.id=f,n.textContent=E,document.head.appendChild(n)}const S=".moment-sync-trigger",I="https://live.dev.momentco.ai";class v{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:S,...e},this.liveBaseUrl=I;try{this.liveOrigin=new URL(this.liveBaseUrl).origin}catch{throw new Error(`[MomentSdk] Invalid VITE_LIVE_BASE_URL: "${this.liveBaseUrl}"`)}T(),this.bindTriggers(),this.emitAnalytics("embed.init")}open(e){e.externalEventId&&e.externalEventIdPrefix&&console.warn("[MomentSdk] Both externalEventId and externalEventIdPrefix provided; using externalEventId only.");const t=this.scopeOpenPayload(e);this.emitAnalytics("embed.open",{teamSlug:t.teamSlug,triggerType:t.triggerType}),this.createModal(t)}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)},o=this.boundClickHandlers.get(t);o&&t.removeEventListener("click",o),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,o=e.getAttribute("data-moment-list-slug")??void 0,s=e.getAttribute("data-moment-trigger-type");let r="moment";s!=null&&s!==""&&(s==="moment"||s==="list"||s==="team"||s==="brand-playlist"?r=s:console.warn("[MomentSdk] Invalid data-moment-trigger-type, falling back to 'moment':",s));const c=e.getAttribute("data-moment-ids")??e.getAttribute("data-moment-game-id")??"",u=c?c.split(",").filter(Boolean):[],a=e.getAttribute("data-moment-calendar");let p;a!=null&&a!==""&&(a==="google"||a==="outlook"?p=a:console.warn("[MomentSdk] Invalid data-moment-calendar, ignoring value:",a));const l=e.getAttribute("data-api-source-id")??void 0,d=e.getAttribute("data-external-event-id")??void 0,m=e.getAttribute("data-external-event-id-prefix")??void 0;if(d&&m&&console.warn("[MomentSdk] Both data-external-event-id and data-external-event-id-prefix are set; using data-external-event-id only."),!t){console.warn("[MomentSdk] Missing data-moment-team-slug on trigger element");return}const h=r==="team"||r==="brand-playlist";this.emitAnalytics("embed.trigger.click",{teamSlug:t,triggerType:r,momentIds:h?[]:u}),this.open({teamSlug:t,momentSlug:i,listSlug:o,triggerType:r,ids:u,calendar:p??void 0,apiSourceId:l,externalEventId:m&&!d?void 0:d,externalEventIdPrefix:d?void 0:m})}scopeOpenPayload(e){return e.triggerType==="team"||e.triggerType==="brand-playlist"?{teamSlug:e.teamSlug,triggerType:e.triggerType,calendar:e.calendar}:e}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 o=document.createElement("div");Object.assign(o.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 r=document.createElement("button");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,{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"}),r.addEventListener("mouseenter",()=>{r.style.color="#666"}),r.addEventListener("mouseleave",()=>{r.style.color="#999"}),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,{width:"100%",border:"none",display:"block",height:"420px",overflow:"hidden",transition:"height 0.15s ease"}),s.appendChild(r),s.appendChild(this.iframe);const c=document.createElement("div");Object.assign(c.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"}),c.appendChild(u),c.appendChild(a),o.appendChild(s),o.appendChild(c),this.overlay.appendChild(o),document.body.appendChild(this.overlay);const p=l=>{if(l.key!=="Tab")return;const d=s.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');if(d.length===0){l.preventDefault(),s.focus();return}const m=d[0],h=d[d.length-1],y=document.activeElement;l.shiftKey&&y===m?(l.preventDefault(),h.focus()):!l.shiftKey&&y===h&&(l.preventDefault(),m.focus())};s.addEventListener("keydown",p),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=p}buildIframeUrl(e){return x(this.liveBaseUrl,e)}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 o=Math.round(window.innerHeight*.8);this.iframe.style.height=`${Math.min(i,o)}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 b(n){const e=document.createElement("button");return e.type="button",e.classList.add("moment-sync-trigger"),n.className&&n.className.split(" ").forEach(t=>{t&&e.classList.add(t)}),e.setAttribute("data-moment-team-slug",n.teamSlug),n.momentSlug&&e.setAttribute("data-moment-slug",n.momentSlug),n.listSlug&&e.setAttribute("data-moment-list-slug",n.listSlug),n.triggerType&&e.setAttribute("data-moment-trigger-type",n.triggerType),n.ids?.length&&e.setAttribute("data-moment-ids",n.ids.join(",")),n.calendar&&e.setAttribute("data-moment-calendar",n.calendar),n.apiSourceId&&e.setAttribute("data-api-source-id",n.apiSourceId),n.externalEventId&&e.setAttribute("data-external-event-id",n.externalEventId),n.externalEventIdPrefix&&e.setAttribute("data-external-event-id-prefix",n.externalEventIdPrefix),e.textContent=n.label??"Add to Calendar",e}if(typeof window<"u"){const n=window;n.MomentSdk=v,n.createMomentButton=b}g.MomentSdk=v,g.createMomentButton=b,Object.defineProperty(g,Symbol.toStringTag,{value:"Module"})})(this.MomentSdk=this.MomentSdk||{});
|
|
25
|
+
`;function S(){if(typeof document>"u"||document.getElementById(v))return;const n=document.createElement("style");n.id=v,n.textContent=T,document.head.appendChild(n)}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){e.externalEventId&&e.externalEventIdPrefix&&console.warn("[MomentSdk] Both externalEventId and externalEventIdPrefix provided; using externalEventId only.");const t=this.scopeOpenPayload(e);this.emitAnalytics("embed.open",{teamSlug:t.teamSlug,triggerType:t.triggerType}),this.createModal(t)}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)},l=this.boundClickHandlers.get(t);l&&t.removeEventListener("click",l),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,l=e.getAttribute("data-moment-list-slug")??void 0,s=e.getAttribute("data-moment-trigger-type");let r="moment";s!=null&&s!==""&&(s==="moment"||s==="list"||s==="team"||s==="brand-playlist"||s==="playlist"||s==="schedule"?r=s:console.warn("[MomentSdk] Invalid data-moment-trigger-type, falling back to 'moment':",s));const a=e.getAttribute("data-moment-ids")??e.getAttribute("data-moment-game-id")??"",m=a?a.split(",").filter(Boolean):[],d=e.getAttribute("data-moment-playlist-slugs")??"",g=d?d.split(",").map(A=>A.trim()).filter(Boolean):[],o=e.getAttribute("data-moment-calendar");let c;o!=null&&o!==""&&(o==="google"||o==="outlook"?c=o:console.warn("[MomentSdk] Invalid data-moment-calendar, ignoring value:",o));const h=e.getAttribute("data-api-source-id")??void 0,u=e.getAttribute("data-external-event-id")??void 0,p=e.getAttribute("data-external-event-id-prefix")??void 0;if(u&&p&&console.warn("[MomentSdk] Both data-external-event-id and data-external-event-id-prefix are set; using data-external-event-id only."),!t){console.warn("[MomentSdk] Missing data-moment-team-slug on trigger element");return}const P=r==="team"||r==="brand-playlist"||r==="playlist"||r==="schedule";this.emitAnalytics("embed.trigger.click",{teamSlug:t,triggerType:r,momentIds:P?[]:m}),this.open({teamSlug:t,momentSlug:i,listSlug:l,triggerType:r,ids:m,playlistSlugs:g,calendar:c??void 0,apiSourceId:h,externalEventId:p&&!u?void 0:u,externalEventIdPrefix:u?void 0:p})}scopeOpenPayload(e){return e.triggerType==="playlist"||e.triggerType==="schedule"?{teamSlug:e.teamSlug,triggerType:e.triggerType,playlistSlugs:e.playlistSlugs,calendar:e.calendar}:e.triggerType==="team"||e.triggerType==="brand-playlist"?{teamSlug:e.teamSlug,triggerType:e.triggerType,calendar:e.calendar}:e}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",o=>{o.target===this.overlay&&this.handleCancel()});const i=o=>{o.key==="Escape"&&this.handleCancel()};document.addEventListener("keydown",i);const l=document.createElement("div");Object.assign(l.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 r=document.createElement("button");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,{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"}),r.addEventListener("mouseenter",()=>{r.style.color="#666"}),r.addEventListener("mouseleave",()=>{r.style.color="#999"}),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,{width:"100%",border:"none",display:"block",height:"420px",overflow:"hidden",transition:"height 0.15s ease"}),s.appendChild(r),s.appendChild(this.iframe);const a=document.createElement("div");Object.assign(a.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 d=document.createElement("img");d.alt="Moment",d.src=`${this.liveBaseUrl}/brand/moment-text-white.png`,Object.assign(d.style,{height:"auto",width:"67px"}),a.appendChild(m),a.appendChild(d),l.appendChild(s),l.appendChild(a),this.overlay.appendChild(l),document.body.appendChild(this.overlay);const g=o=>{if(o.key!=="Tab")return;const c=s.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');if(c.length===0){o.preventDefault(),s.focus();return}const h=c[0],u=c[c.length-1],p=document.activeElement;o.shiftKey&&p===h?(o.preventDefault(),u.focus()):!o.shiftKey&&p===u&&(o.preventDefault(),h.focus())};s.addEventListener("keydown",g),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=g}buildIframeUrl(e){return x(this.liveBaseUrl,e)}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 l=Math.round(window.innerHeight*.8);this.iframe.style.height=`${Math.min(i,l)}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(n){const e=document.createElement("button");return e.type="button",e.classList.add("moment-sync-trigger"),n.className&&n.className.split(" ").forEach(t=>{t&&e.classList.add(t)}),e.setAttribute("data-moment-team-slug",n.teamSlug),n.momentSlug&&e.setAttribute("data-moment-slug",n.momentSlug),n.listSlug&&e.setAttribute("data-moment-list-slug",n.listSlug),n.triggerType&&e.setAttribute("data-moment-trigger-type",n.triggerType),n.ids?.length&&e.setAttribute("data-moment-ids",n.ids.join(",")),n.playlistSlugs?.length&&e.setAttribute("data-moment-playlist-slugs",n.playlistSlugs.join(",")),n.calendar&&e.setAttribute("data-moment-calendar",n.calendar),n.apiSourceId&&e.setAttribute("data-api-source-id",n.apiSourceId),n.externalEventId&&e.setAttribute("data-external-event-id",n.externalEventId),n.externalEventIdPrefix&&e.setAttribute("data-external-event-id-prefix",n.externalEventIdPrefix),e.textContent=n.label??"Add to Calendar",e}if(typeof window<"u"){const n=window;n.MomentSdk=b,n.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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class
|
|
1
|
+
class y {
|
|
2
2
|
popup = null;
|
|
3
3
|
pollTimer = null;
|
|
4
4
|
messageHandler = null;
|
|
@@ -12,11 +12,11 @@ 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), l = 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=${l},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;
|
|
@@ -46,7 +46,7 @@ class v {
|
|
|
46
46
|
triggerType: e.triggerType,
|
|
47
47
|
returnOrigin: t
|
|
48
48
|
});
|
|
49
|
-
return e.subscriptionType && i.set("subscriptionType", e.subscriptionType), `${this.opts.liveBaseUrl}/en/embed/oauth-popup?${i.toString()}`;
|
|
49
|
+
return e.subscriptionType && i.set("subscriptionType", e.subscriptionType), e.selection && i.set("selection", e.selection), `${this.opts.liveBaseUrl}/en/embed/oauth-popup?${i.toString()}`;
|
|
50
50
|
}
|
|
51
51
|
startPolling() {
|
|
52
52
|
this.pollTimer = setInterval(() => {
|
|
@@ -63,11 +63,11 @@ class v {
|
|
|
63
63
|
this.opts.iframeWindow.postMessage(t, this.opts.liveOrigin);
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
function
|
|
66
|
+
function w(n, e, t = typeof window < "u" ? window.location.origin : "") {
|
|
67
67
|
const i = new URLSearchParams();
|
|
68
|
-
return i.set("teamSlug", e.teamSlug), e.momentSlug && i.set("momentSlug", e.momentSlug), e.listSlug && i.set("listSlug", e.listSlug), i.set("triggerType", e.triggerType), e.ids?.length && i.set("ids", e.ids.join(",")), e.calendar && i.set("calendar", e.calendar), e.apiSourceId && i.set("subscriptionId", e.apiSourceId), e.externalEventId && i.set("externalId", e.externalEventId), e.externalEventIdPrefix && !e.externalEventId && i.set("externalIdPrefix", e.externalEventIdPrefix), i.set("returnOrigin", t), i.set("embed", "1"), `${n}/en/embed/sync?${i.toString()}`;
|
|
68
|
+
return i.set("teamSlug", e.teamSlug), e.momentSlug && i.set("momentSlug", e.momentSlug), e.listSlug && i.set("listSlug", e.listSlug), i.set("triggerType", e.triggerType), e.ids?.length && i.set("ids", e.ids.join(",")), e.playlistSlugs?.length && i.set("playlistSlugs", e.playlistSlugs.join(",")), e.calendar && i.set("calendar", e.calendar), e.apiSourceId && i.set("subscriptionId", e.apiSourceId), e.externalEventId && i.set("externalId", e.externalEventId), e.externalEventIdPrefix && !e.externalEventId && i.set("externalIdPrefix", e.externalEventIdPrefix), i.set("returnOrigin", t), i.set("embed", "1"), `${n}/en/embed/sync?${i.toString()}`;
|
|
69
69
|
}
|
|
70
|
-
const f = "moment-sdk-trigger-styles",
|
|
70
|
+
const f = "moment-sdk-trigger-styles", x = `
|
|
71
71
|
:where(.moment-sync-trigger) {
|
|
72
72
|
background-color: #1c1917;
|
|
73
73
|
color: #ffffff;
|
|
@@ -92,13 +92,13 @@ const f = "moment-sdk-trigger-styles", y = `
|
|
|
92
92
|
outline-offset: 2px;
|
|
93
93
|
}
|
|
94
94
|
`;
|
|
95
|
-
function
|
|
95
|
+
function T() {
|
|
96
96
|
if (typeof document > "u" || document.getElementById(f)) return;
|
|
97
97
|
const n = document.createElement("style");
|
|
98
|
-
n.id = f, n.textContent =
|
|
98
|
+
n.id = f, n.textContent = x, document.head.appendChild(n);
|
|
99
99
|
}
|
|
100
|
-
const
|
|
101
|
-
class
|
|
100
|
+
const E = ".moment-sync-trigger", S = "https://live.dev.momentco.ai";
|
|
101
|
+
class I {
|
|
102
102
|
opts;
|
|
103
103
|
liveBaseUrl;
|
|
104
104
|
liveOrigin;
|
|
@@ -114,15 +114,15 @@ class T {
|
|
|
114
114
|
closeTimer = null;
|
|
115
115
|
constructor(e) {
|
|
116
116
|
this.opts = {
|
|
117
|
-
triggerSelector:
|
|
117
|
+
triggerSelector: E,
|
|
118
118
|
...e
|
|
119
|
-
}, this.liveBaseUrl =
|
|
119
|
+
}, this.liveBaseUrl = S;
|
|
120
120
|
try {
|
|
121
121
|
this.liveOrigin = new URL(this.liveBaseUrl).origin;
|
|
122
122
|
} catch {
|
|
123
123
|
throw new Error(`[MomentSdk] Invalid VITE_LIVE_BASE_URL: "${this.liveBaseUrl}"`);
|
|
124
124
|
}
|
|
125
|
-
|
|
125
|
+
T(), this.bindTriggers(), this.emitAnalytics("embed.init");
|
|
126
126
|
}
|
|
127
127
|
/**
|
|
128
128
|
* Programmatically open the sync modal.
|
|
@@ -160,8 +160,8 @@ class T {
|
|
|
160
160
|
document.querySelectorAll(this.opts.triggerSelector).forEach((t) => {
|
|
161
161
|
const i = (s) => {
|
|
162
162
|
s.preventDefault(), this.handleTriggerClick(t);
|
|
163
|
-
},
|
|
164
|
-
|
|
163
|
+
}, l = this.boundClickHandlers.get(t);
|
|
164
|
+
l && t.removeEventListener("click", l), t.addEventListener("click", i), this.boundClickHandlers.set(t, i);
|
|
165
165
|
});
|
|
166
166
|
}
|
|
167
167
|
unbindTriggers() {
|
|
@@ -170,42 +170,48 @@ class T {
|
|
|
170
170
|
}), this.boundClickHandlers.clear();
|
|
171
171
|
}
|
|
172
172
|
handleTriggerClick(e) {
|
|
173
|
-
const t = e.getAttribute("data-moment-team-slug") ?? "", i = e.getAttribute("data-moment-slug") ?? void 0,
|
|
173
|
+
const t = e.getAttribute("data-moment-team-slug") ?? "", i = e.getAttribute("data-moment-slug") ?? void 0, l = e.getAttribute("data-moment-list-slug") ?? void 0, s = e.getAttribute("data-moment-trigger-type");
|
|
174
174
|
let r = "moment";
|
|
175
|
-
s != null && s !== "" && (s === "moment" || s === "list" || s === "team" || s === "brand-playlist" ? r = s : console.warn(
|
|
175
|
+
s != null && s !== "" && (s === "moment" || s === "list" || s === "team" || s === "brand-playlist" || s === "playlist" || s === "schedule" ? r = s : console.warn(
|
|
176
176
|
"[MomentSdk] Invalid data-moment-trigger-type, falling back to 'moment':",
|
|
177
177
|
s
|
|
178
178
|
));
|
|
179
|
-
const
|
|
180
|
-
let
|
|
181
|
-
|
|
182
|
-
const
|
|
183
|
-
if (
|
|
179
|
+
const a = e.getAttribute("data-moment-ids") ?? e.getAttribute("data-moment-game-id") ?? "", m = a ? a.split(",").filter(Boolean) : [], d = e.getAttribute("data-moment-playlist-slugs") ?? "", g = d ? d.split(",").map((b) => b.trim()).filter(Boolean) : [], o = e.getAttribute("data-moment-calendar");
|
|
180
|
+
let c;
|
|
181
|
+
o != null && o !== "" && (o === "google" || o === "outlook" ? c = o : console.warn("[MomentSdk] Invalid data-moment-calendar, ignoring value:", o));
|
|
182
|
+
const h = e.getAttribute("data-api-source-id") ?? void 0, u = e.getAttribute("data-external-event-id") ?? void 0, p = e.getAttribute("data-external-event-id-prefix") ?? void 0;
|
|
183
|
+
if (u && p && console.warn(
|
|
184
184
|
"[MomentSdk] Both data-external-event-id and data-external-event-id-prefix are set; using data-external-event-id only."
|
|
185
185
|
), !t) {
|
|
186
186
|
console.warn("[MomentSdk] Missing data-moment-team-slug on trigger element");
|
|
187
187
|
return;
|
|
188
188
|
}
|
|
189
|
-
const
|
|
189
|
+
const v = r === "team" || r === "brand-playlist" || r === "playlist" || r === "schedule";
|
|
190
190
|
this.emitAnalytics("embed.trigger.click", {
|
|
191
191
|
teamSlug: t,
|
|
192
192
|
triggerType: r,
|
|
193
|
-
momentIds:
|
|
193
|
+
momentIds: v ? [] : m
|
|
194
194
|
}), this.open({
|
|
195
195
|
teamSlug: t,
|
|
196
196
|
momentSlug: i,
|
|
197
|
-
listSlug:
|
|
197
|
+
listSlug: l,
|
|
198
198
|
triggerType: r,
|
|
199
|
-
ids:
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
199
|
+
ids: m,
|
|
200
|
+
playlistSlugs: g,
|
|
201
|
+
calendar: c ?? void 0,
|
|
202
|
+
apiSourceId: h,
|
|
203
|
+
externalEventId: p && !u ? void 0 : u,
|
|
204
|
+
externalEventIdPrefix: u ? void 0 : p
|
|
204
205
|
});
|
|
205
206
|
}
|
|
206
207
|
/** Drop moment/list/source scoping for brand-level subscription triggers. */
|
|
207
208
|
scopeOpenPayload(e) {
|
|
208
|
-
return e.triggerType === "
|
|
209
|
+
return e.triggerType === "playlist" || e.triggerType === "schedule" ? {
|
|
210
|
+
teamSlug: e.teamSlug,
|
|
211
|
+
triggerType: e.triggerType,
|
|
212
|
+
playlistSlugs: e.playlistSlugs,
|
|
213
|
+
calendar: e.calendar
|
|
214
|
+
} : e.triggerType === "team" || e.triggerType === "brand-playlist" ? {
|
|
209
215
|
teamSlug: e.teamSlug,
|
|
210
216
|
triggerType: e.triggerType,
|
|
211
217
|
calendar: e.calendar
|
|
@@ -225,15 +231,15 @@ class T {
|
|
|
225
231
|
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
226
232
|
backdropFilter: "blur(2px)",
|
|
227
233
|
padding: "16px"
|
|
228
|
-
}), this.overlay.addEventListener("click", (
|
|
229
|
-
|
|
234
|
+
}), this.overlay.addEventListener("click", (o) => {
|
|
235
|
+
o.target === this.overlay && this.handleCancel();
|
|
230
236
|
});
|
|
231
|
-
const i = (
|
|
232
|
-
|
|
237
|
+
const i = (o) => {
|
|
238
|
+
o.key === "Escape" && this.handleCancel();
|
|
233
239
|
};
|
|
234
240
|
document.addEventListener("keydown", i);
|
|
235
|
-
const
|
|
236
|
-
Object.assign(
|
|
241
|
+
const l = document.createElement("div");
|
|
242
|
+
Object.assign(l.style, {
|
|
237
243
|
position: "relative",
|
|
238
244
|
width: "100%",
|
|
239
245
|
maxWidth: "380px",
|
|
@@ -281,42 +287,42 @@ class T {
|
|
|
281
287
|
overflow: "hidden",
|
|
282
288
|
transition: "height 0.15s ease"
|
|
283
289
|
}), s.appendChild(r), s.appendChild(this.iframe);
|
|
284
|
-
const
|
|
285
|
-
Object.assign(
|
|
290
|
+
const a = document.createElement("div");
|
|
291
|
+
Object.assign(a.style, {
|
|
286
292
|
display: "flex",
|
|
287
293
|
alignItems: "center",
|
|
288
294
|
justifyContent: "center",
|
|
289
295
|
gap: "6px",
|
|
290
296
|
padding: "12px 0"
|
|
291
297
|
});
|
|
292
|
-
const
|
|
293
|
-
|
|
298
|
+
const m = document.createElement("span");
|
|
299
|
+
m.textContent = "Powered by", Object.assign(m.style, {
|
|
294
300
|
fontFamily: "Inter, system-ui, -apple-system, sans-serif",
|
|
295
301
|
fontSize: "12px",
|
|
296
302
|
lineHeight: "16px",
|
|
297
303
|
color: "#ffffff"
|
|
298
304
|
});
|
|
299
|
-
const
|
|
300
|
-
|
|
305
|
+
const d = document.createElement("img");
|
|
306
|
+
d.alt = "Moment", d.src = `${this.liveBaseUrl}/brand/moment-text-white.png`, Object.assign(d.style, {
|
|
301
307
|
height: "auto",
|
|
302
308
|
width: "67px"
|
|
303
|
-
}),
|
|
304
|
-
const
|
|
305
|
-
if (
|
|
306
|
-
const
|
|
309
|
+
}), a.appendChild(m), a.appendChild(d), l.appendChild(s), l.appendChild(a), this.overlay.appendChild(l), document.body.appendChild(this.overlay);
|
|
310
|
+
const g = (o) => {
|
|
311
|
+
if (o.key !== "Tab") return;
|
|
312
|
+
const c = s.querySelectorAll(
|
|
307
313
|
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
308
314
|
);
|
|
309
|
-
if (
|
|
310
|
-
|
|
315
|
+
if (c.length === 0) {
|
|
316
|
+
o.preventDefault(), s.focus();
|
|
311
317
|
return;
|
|
312
318
|
}
|
|
313
|
-
const
|
|
314
|
-
|
|
319
|
+
const h = c[0], u = c[c.length - 1], p = document.activeElement;
|
|
320
|
+
o.shiftKey && p === h ? (o.preventDefault(), u.focus()) : !o.shiftKey && p === u && (o.preventDefault(), h.focus());
|
|
315
321
|
};
|
|
316
|
-
s.addEventListener("keydown",
|
|
322
|
+
s.addEventListener("keydown", g), 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 = g;
|
|
317
323
|
}
|
|
318
324
|
buildIframeUrl(e) {
|
|
319
|
-
return
|
|
325
|
+
return w(this.liveBaseUrl, e);
|
|
320
326
|
}
|
|
321
327
|
// ── Private: message handling ─────────────────────────────────────
|
|
322
328
|
setupMessageListener() {
|
|
@@ -335,8 +341,8 @@ class T {
|
|
|
335
341
|
if (t.source === "moment-live-embed" && t.type === "moment.embed.resize") {
|
|
336
342
|
const i = typeof t.height == "number" ? t.height : 0;
|
|
337
343
|
if (i > 0 && this.iframe) {
|
|
338
|
-
const
|
|
339
|
-
this.iframe.style.height = `${Math.min(i,
|
|
344
|
+
const l = Math.round(window.innerHeight * 0.8);
|
|
345
|
+
this.iframe.style.height = `${Math.min(i, l)}px`;
|
|
340
346
|
}
|
|
341
347
|
return;
|
|
342
348
|
}
|
|
@@ -353,7 +359,7 @@ class T {
|
|
|
353
359
|
}, window.addEventListener("message", this.messageHandler);
|
|
354
360
|
}
|
|
355
361
|
handleOAuthStart(e) {
|
|
356
|
-
this.popupBridge && (this.popupBridge.cleanup(), this.popupBridge = null), this.popupBridge = new
|
|
362
|
+
this.popupBridge && (this.popupBridge.cleanup(), this.popupBridge = null), this.popupBridge = new y({
|
|
357
363
|
liveBaseUrl: this.liveBaseUrl,
|
|
358
364
|
liveOrigin: this.liveOrigin,
|
|
359
365
|
iframeWindow: this.iframe?.contentWindow ?? null,
|
|
@@ -419,17 +425,17 @@ class T {
|
|
|
419
425
|
});
|
|
420
426
|
}
|
|
421
427
|
}
|
|
422
|
-
function
|
|
428
|
+
function P(n) {
|
|
423
429
|
const e = document.createElement("button");
|
|
424
430
|
return e.type = "button", e.classList.add("moment-sync-trigger"), n.className && n.className.split(" ").forEach((t) => {
|
|
425
431
|
t && e.classList.add(t);
|
|
426
|
-
}), e.setAttribute("data-moment-team-slug", n.teamSlug), n.momentSlug && e.setAttribute("data-moment-slug", n.momentSlug), n.listSlug && e.setAttribute("data-moment-list-slug", n.listSlug), n.triggerType && e.setAttribute("data-moment-trigger-type", n.triggerType), n.ids?.length && e.setAttribute("data-moment-ids", n.ids.join(",")), n.calendar && e.setAttribute("data-moment-calendar", n.calendar), n.apiSourceId && e.setAttribute("data-api-source-id", n.apiSourceId), n.externalEventId && e.setAttribute("data-external-event-id", n.externalEventId), n.externalEventIdPrefix && e.setAttribute("data-external-event-id-prefix", n.externalEventIdPrefix), e.textContent = n.label ?? "Add to Calendar", e;
|
|
432
|
+
}), e.setAttribute("data-moment-team-slug", n.teamSlug), n.momentSlug && e.setAttribute("data-moment-slug", n.momentSlug), n.listSlug && e.setAttribute("data-moment-list-slug", n.listSlug), n.triggerType && e.setAttribute("data-moment-trigger-type", n.triggerType), n.ids?.length && e.setAttribute("data-moment-ids", n.ids.join(",")), n.playlistSlugs?.length && e.setAttribute("data-moment-playlist-slugs", n.playlistSlugs.join(",")), n.calendar && e.setAttribute("data-moment-calendar", n.calendar), n.apiSourceId && e.setAttribute("data-api-source-id", n.apiSourceId), n.externalEventId && e.setAttribute("data-external-event-id", n.externalEventId), n.externalEventIdPrefix && e.setAttribute("data-external-event-id-prefix", n.externalEventIdPrefix), e.textContent = n.label ?? "Add to Calendar", e;
|
|
427
433
|
}
|
|
428
434
|
if (typeof window < "u") {
|
|
429
435
|
const n = window;
|
|
430
|
-
n.MomentSdk =
|
|
436
|
+
n.MomentSdk = I, n.createMomentButton = P;
|
|
431
437
|
}
|
|
432
438
|
export {
|
|
433
|
-
|
|
434
|
-
|
|
439
|
+
I as MomentSdk,
|
|
440
|
+
P as createMomentButton
|
|
435
441
|
};
|
|
@@ -10,6 +10,11 @@ export declare function createMomentButton(options: {
|
|
|
10
10
|
listSlug?: string;
|
|
11
11
|
triggerType?: MomentTriggerType;
|
|
12
12
|
ids?: string[];
|
|
13
|
+
/**
|
|
14
|
+
* Playlist slugs offered under a `playlist` trigger (picker when >1) or the
|
|
15
|
+
* collections shown in the `schedule` trigger's multi-select modal.
|
|
16
|
+
*/
|
|
17
|
+
playlistSlugs?: string[];
|
|
13
18
|
calendar?: CalendarProvider;
|
|
14
19
|
/** Sync subscription source id; pairs with `externalEventId` for server-side resolution. */
|
|
15
20
|
apiSourceId?: string;
|
|
@@ -6,8 +6,14 @@
|
|
|
6
6
|
* - `list` → subscribe to a curated list of moments
|
|
7
7
|
* - `team` → subscribe to a team / brand schedule (all published moments)
|
|
8
8
|
* - `brand-playlist` → subscribe to the brand's default playlist
|
|
9
|
+
* - `playlist` → subscribe to one of several specific playlists. When more than
|
|
10
|
+
* one slug is supplied, Live fetches each playlist and prompts the user to
|
|
11
|
+
* pick which one to sync.
|
|
12
|
+
* - `schedule` → open the brand's schedule modal. Live fetches the supplied
|
|
13
|
+
* collection playlists and lets the fan multi-select which ones to sync in a
|
|
14
|
+
* single pass (the generic "Add to Calendar" experience).
|
|
9
15
|
*/
|
|
10
|
-
export type MomentTriggerType = 'moment' | 'list' | 'team' | 'brand-playlist';
|
|
16
|
+
export type MomentTriggerType = 'moment' | 'list' | 'team' | 'brand-playlist' | 'playlist' | 'schedule';
|
|
11
17
|
export type CalendarProvider = 'google' | 'outlook';
|
|
12
18
|
export interface MomentSdkInitOptions {
|
|
13
19
|
/** CSS selector for trigger elements. Default: ".moment-sync-trigger" */
|
|
@@ -35,6 +41,14 @@ export interface MomentSdkInitOptions {
|
|
|
35
41
|
* `externalEventId` for this trigger type.
|
|
36
42
|
* - `brand-playlist` → `teamSlug` only (Live resolves the brand's
|
|
37
43
|
* `defaultPlaylistId`). Omit the same fields as `team`.
|
|
44
|
+
* - `playlist` → `teamSlug` plus `playlistSlugs` (one or more playlist slugs).
|
|
45
|
+
* With a single slug Live syncs that playlist directly; with several it shows
|
|
46
|
+
* a picker. Omit `momentSlug`, `listSlug`, `ids`, `apiSourceId`, and
|
|
47
|
+
* `externalEventId` for this trigger type.
|
|
48
|
+
* - `schedule` → `teamSlug` plus `playlistSlugs` (the collections to surface).
|
|
49
|
+
* Live renders the schedule modal where the fan multi-selects collections and
|
|
50
|
+
* syncs them together. Omit `momentSlug`, `listSlug`, `ids`, `apiSourceId`,
|
|
51
|
+
* and `externalEventId` for this trigger type.
|
|
38
52
|
*/
|
|
39
53
|
export interface MomentSdkOpenPayload {
|
|
40
54
|
teamSlug: string;
|
|
@@ -43,6 +57,14 @@ export interface MomentSdkOpenPayload {
|
|
|
43
57
|
listSlug?: string;
|
|
44
58
|
triggerType: MomentTriggerType;
|
|
45
59
|
ids?: string[];
|
|
60
|
+
/**
|
|
61
|
+
* Playlist slugs to offer under a `playlist` or `schedule` trigger. Live
|
|
62
|
+
* fetches each playlist's details. Under `playlist`, more than one slug
|
|
63
|
+
* renders a single-choice picker; under `schedule`, the slugs become the
|
|
64
|
+
* multi-select collections in the schedule modal. Forwarded to the Live embed
|
|
65
|
+
* as the `playlistSlugs` query param (comma-separated).
|
|
66
|
+
*/
|
|
67
|
+
playlistSlugs?: string[];
|
|
46
68
|
calendar?: CalendarProvider;
|
|
47
69
|
/**
|
|
48
70
|
* Sync subscription source identifier (the publisher's sync-subscription id).
|
|
@@ -84,6 +106,12 @@ export interface MomentOAuthStartPayload {
|
|
|
84
106
|
* under a `list`/`team` trigger).
|
|
85
107
|
*/
|
|
86
108
|
subscriptionType?: MomentSubscriptionType;
|
|
109
|
+
/**
|
|
110
|
+
* Mixed-type selection encoded as `type:id,id;type:id`. Set by the `schedule`
|
|
111
|
+
* trigger when the cart mixes collections and individual events. Forwarded
|
|
112
|
+
* verbatim to the popup, which subscribes each group; opaque to the SDK.
|
|
113
|
+
*/
|
|
114
|
+
selection?: string;
|
|
87
115
|
returnOrigin: string;
|
|
88
116
|
}
|
|
89
117
|
/** Parent → Iframe: relay OAuth popup status */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@momentco-ai/moment-sdk",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3-dev.22",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Embeddable calendar sync widget for external team websites",
|
|
6
6
|
"author": "Moment Co. <support@momentco.ai> (https://momentco.ai)",
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"build": "vite build && tsc --emitDeclarationOnly --outDir dist/types",
|
|
56
56
|
"build:dev": "vite build --mode development && tsc --emitDeclarationOnly --outDir dist/types",
|
|
57
57
|
"build:prod": "vite build --mode production && tsc --emitDeclarationOnly --outDir dist/types",
|
|
58
|
+
"build:local": "VITE_LIVE_BASE_URL=http://localhost:8081 vite build && tsc --emitDeclarationOnly --outDir dist/types",
|
|
58
59
|
"type-check": "tsc --noEmit",
|
|
59
60
|
"typecheck": "pnpm run type-check",
|
|
60
61
|
"lint": "eslint .",
|
|
@@ -64,6 +65,8 @@
|
|
|
64
65
|
"quality": "pnpm run type-check && pnpm run lint && pnpm run format",
|
|
65
66
|
"test": "vitest run",
|
|
66
67
|
"examples": "pnpm build && node examples/serve.mjs",
|
|
68
|
+
"integration-test": "node integration-test/serve.mjs",
|
|
69
|
+
"integration-test:local": "INTEGRATION_USE_LOCAL_SDK=1 node integration-test/serve.mjs",
|
|
67
70
|
"prepare": "husky"
|
|
68
71
|
},
|
|
69
72
|
"devDependencies": {
|