@momentco-ai/moment-sdk 0.1.2-dev.10 → 0.2.0-dev.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -9
- package/dist/moment-sdk.js +1 -1
- package/dist/moment-sdk.mjs +60 -59
- package/dist/types/sdk/button.d.ts +2 -1
- package/dist/types/sdk/types.d.ts +33 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ npm install @momentco-ai/moment-sdk
|
|
|
29
29
|
<button
|
|
30
30
|
class="moment-sync-trigger"
|
|
31
31
|
data-moment-team-slug="your-team-slug"
|
|
32
|
-
data-
|
|
32
|
+
data-moment-slug="event-001"
|
|
33
33
|
data-moment-trigger-type="moment"
|
|
34
34
|
>
|
|
35
35
|
Add to Calendar
|
|
@@ -71,9 +71,9 @@ Place these on any element matching the trigger selector (default: `.moment-sync
|
|
|
71
71
|
| Attribute | Required | Description |
|
|
72
72
|
| -------------------------- | -------- | ------------------------------------------------------------ |
|
|
73
73
|
| `data-moment-team-slug` | ✅ | Team/brand slug |
|
|
74
|
-
| `data-
|
|
75
|
-
| `data-moment-list-slug` | No | List slug (resolved to
|
|
76
|
-
| `data-moment-trigger-type` | No | `moment` (default), `list`, or `
|
|
74
|
+
| `data-moment-slug` | No | Brand-level moment slug (resolved to real ID by Moment) |
|
|
75
|
+
| `data-moment-list-slug` | No | List slug (resolved to a list-level subscription by Moment) |
|
|
76
|
+
| `data-moment-trigger-type` | No | `moment` (default), `list`, or `team` |
|
|
77
77
|
| `data-moment-ids` | No | Comma-separated moment IDs (fallback if slugs don't resolve) |
|
|
78
78
|
| `data-moment-game-id` | No | Alias for `data-moment-ids` |
|
|
79
79
|
| `data-moment-calendar` | No | Pre-select provider: `google` or `outlook` |
|
|
@@ -93,7 +93,7 @@ You can also open the modal programmatically instead of relying on data attribut
|
|
|
93
93
|
// Open modal
|
|
94
94
|
sdk.open({
|
|
95
95
|
teamSlug: 'your-team-slug',
|
|
96
|
-
|
|
96
|
+
momentSlug: 'event-123',
|
|
97
97
|
triggerType: 'moment',
|
|
98
98
|
ids: ['moment-id-1'],
|
|
99
99
|
calendar: 'google', // optional: skip provider selection
|
|
@@ -120,7 +120,7 @@ Programmatically create a styled trigger button:
|
|
|
120
120
|
<script>
|
|
121
121
|
const btn = createMomentButton({
|
|
122
122
|
teamSlug: 'your-team-slug',
|
|
123
|
-
|
|
123
|
+
momentSlug: 'event-001',
|
|
124
124
|
triggerType: 'moment',
|
|
125
125
|
label: 'Add to Calendar',
|
|
126
126
|
});
|
|
@@ -161,7 +161,7 @@ You can customize trigger button appearance in a few ways:
|
|
|
161
161
|
<script>
|
|
162
162
|
const primaryBtn = createMomentButton({
|
|
163
163
|
teamSlug: 'your-team-slug',
|
|
164
|
-
|
|
164
|
+
momentSlug: 'event-001',
|
|
165
165
|
triggerType: 'moment',
|
|
166
166
|
label: 'Get Tickets + Calendar',
|
|
167
167
|
className: 'my-calendar-btn',
|
|
@@ -177,7 +177,7 @@ You can also create plain HTML triggers and fully own styles/text:
|
|
|
177
177
|
<button
|
|
178
178
|
class="my-calendar-btn moment-sync-trigger"
|
|
179
179
|
data-moment-team-slug="your-team-slug"
|
|
180
|
-
data-
|
|
180
|
+
data-moment-slug="event-001"
|
|
181
181
|
data-moment-trigger-type="moment"
|
|
182
182
|
>
|
|
183
183
|
Add This Match to My Calendar
|
|
@@ -221,7 +221,7 @@ All callbacks (`onSuccess`, `onError`, `onClose`) receive a result payload:
|
|
|
221
221
|
"type": "moment.embed.result",
|
|
222
222
|
"result": "success | error | cancelled",
|
|
223
223
|
"provider": "google | outlook",
|
|
224
|
-
"triggerType": "moment | list |
|
|
224
|
+
"triggerType": "moment | list | team",
|
|
225
225
|
"momentIds": ["..."],
|
|
226
226
|
"message": "optional details"
|
|
227
227
|
}
|
package/dist/moment-sdk.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(u){"use strict";class g{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),s=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=${s},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=i=>{if(i.origin!==this.opts.liveOrigin||i.source!==this.popup)return;const o=i.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,s=new URLSearchParams({provider:e.provider,teamSlug:e.teamSlug,ids:e.ids.join(","),triggerType:e.triggerType,returnOrigin:t});return`${this.opts.liveBaseUrl}/en/embed/oauth-popup?${s.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 f=".moment-sync-trigger",v="https://live.dev.momentco.ai";class m{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:f,...e},this.liveBaseUrl=v;try{this.liveOrigin=new URL(this.liveBaseUrl).origin}catch{throw new Error(`[MomentSdk] Invalid VITE_LIVE_BASE_URL: "${this.liveBaseUrl}"`)}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 s=i=>{i.preventDefault(),this.handleTriggerClick(t)},r=this.boundClickHandlers.get(t);r&&t.removeEventListener("click",r),t.addEventListener("click",s),this.boundClickHandlers.set(t,s)})}unbindTriggers(){this.boundClickHandlers.forEach((e,t)=>{t.removeEventListener("click",e)}),this.boundClickHandlers.clear()}handleTriggerClick(e){const t=e.getAttribute("data-moment-team-slug")??"",s=e.getAttribute("data-external-event-id")??void 0,r=e.getAttribute("data-moment-list-slug")??void 0,i=e.getAttribute("data-moment-trigger-type");let o="moment";i!=null&&i!==""&&(i==="moment"||i==="list"||i==="schedule"?o=i:console.warn("[MomentSdk] Invalid data-moment-trigger-type, falling back to 'moment':",i));const l=e.getAttribute("data-moment-ids")??e.getAttribute("data-moment-game-id")??"",d=l?l.split(",").filter(Boolean):[],a=e.getAttribute("data-moment-calendar");let c;if(a!=null&&a!==""&&(a==="google"||a==="outlook"?c=a:console.warn("[MomentSdk] Invalid data-moment-calendar, ignoring value:",a)),!t){console.warn("[MomentSdk] Missing data-moment-team-slug on trigger element");return}this.emitAnalytics("embed.trigger.click",{teamSlug:t,triggerType:o,momentIds:d}),this.open({teamSlug:t,externalEventId:s,listSlug:r,triggerType:o,ids:d,calendar:c??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 s=l=>{l.key==="Escape"&&this.handleCancel()};document.addEventListener("keydown",s);const r=document.createElement("div");r.setAttribute("role","dialog"),r.setAttribute("aria-modal","true"),r.setAttribute("aria-label","Calendar sync modal"),r.tabIndex=-1,Object.assign(r.style,{position:"relative",width:"100%",maxWidth:"420px",maxHeight:"90vh",borderRadius:"16px",overflow:"hidden",backgroundColor:"#ffffff",boxShadow:"0 25px 50px -12px rgba(0, 0, 0, 0.25)"});const i=document.createElement("button");i.type="button",i.textContent="ⓧ",i.setAttribute("aria-label","Close"),Object.assign(i.style,{position:"absolute",top:"8px",right:"8px",zIndex:"10",border:"none",backgroundColor:"transparent",color:"#999",fontSize:"20px",lineHeight:"1",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center"}),i.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"),Object.assign(this.iframe.style,{width:"100%",height:"480px",border:"none",display:"block"}),r.appendChild(i),r.appendChild(this.iframe),this.overlay.appendChild(r),document.body.appendChild(this.overlay);const o=l=>{if(l.key!=="Tab")return;const d=r.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');if(d.length===0){l.preventDefault(),r.focus();return}const a=d[0],c=d[d.length-1],h=document.activeElement;l.shiftKey&&h===a?(l.preventDefault(),c.focus()):!l.shiftKey&&h===c&&(l.preventDefault(),a.focus())};r.addEventListener("keydown",o),i.focus(),this.previousBodyOverflow=document.body.style.overflow,document.body.style.overflow="hidden",this.didManageBodyOverflow=!0,this.setupMessageListener(),this.overlay._escHandler=s,this.overlay._focusTrapHandler=o}buildIframeUrl(e){const t=new URLSearchParams;return t.set("teamSlug",e.teamSlug),e.externalEventId&&t.set("momentSlug",e.externalEventId),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 s=t;this.emitAnalytics("oauth.start",{provider:s.provider,teamSlug:s.teamSlug}),this.handleOAuthStart(s);return}if(t.source==="moment-live-embed"&&t.type==="moment.embed.result"){const s=t;this.handleResult(s)}}},window.addEventListener("message",this.messageHandler)}handleOAuthStart(e){this.popupBridge&&(this.popupBridge.cleanup(),this.popupBridge=null),this.popupBridge=new g({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 s=this.overlay.firstElementChild;s&&t&&s.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 p(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)}),Object.assign(e.style,{backgroundColor:"#1c1917",color:"#ffffff",border:"1px solid #292524",borderRadius:"4px",padding:"8px 16px",fontSize:"14px",fontWeight:"500",cursor:"pointer",lineHeight:"1.4"}),e.setAttribute("data-moment-team-slug",n.teamSlug),n.externalEventId&&e.setAttribute("data-external-event-id",n.externalEventId),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),e.textContent=n.label??"Add to Calendar",e}if(typeof window<"u"){const n=window;n.MomentSdk=m,n.createMomentButton=p}u.MomentSdk=m,u.createMomentButton=p,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})})(this.MomentSdk=this.MomentSdk||{});
|
|
1
|
+
(function(m){"use strict";class f{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),o=Math.round(window.screenY+(window.outerHeight-700)/2);if(this.popup=window.open(t,"moment-oauth-popup",`width=500,height=700,left=${i},top=${o},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),`${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-sync-trigger",b="https://live.dev.momentco.ai";class p{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:v,...e},this.liveBaseUrl=b;try{this.liveOrigin=new URL(this.liveBaseUrl).origin}catch{throw new Error(`[MomentSdk] Invalid VITE_LIVE_BASE_URL: "${this.liveBaseUrl}"`)}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)},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"?r=s:console.warn("[MomentSdk] Invalid data-moment-trigger-type, falling back to 'moment':",s));const l=e.getAttribute("data-moment-ids")??e.getAttribute("data-moment-game-id")??"",d=l?l.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 c=r==="team"?void 0:i,y=r==="team"?void 0:o,g=r==="team"?[]:d;this.emitAnalytics("embed.trigger.click",{teamSlug:t,triggerType:r,momentIds:g}),this.open({teamSlug:t,momentSlug:c,listSlug:y,triggerType:r,ids:g,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 o=document.createElement("div");o.setAttribute("role","dialog"),o.setAttribute("aria-modal","true"),o.setAttribute("aria-label","Calendar sync modal"),o.tabIndex=-1,Object.assign(o.style,{position:"relative",width:"100%",maxWidth:"420px",maxHeight:"90vh",borderRadius:"16px",overflow:"hidden",backgroundColor:"#ffffff",boxShadow:"0 25px 50px -12px rgba(0, 0, 0, 0.25)"});const s=document.createElement("button");s.type="button",s.textContent="ⓧ",s.setAttribute("aria-label","Close"),Object.assign(s.style,{position:"absolute",top:"8px",right:"8px",zIndex:"10",border:"none",backgroundColor:"transparent",color:"#999",fontSize:"20px",lineHeight:"1",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center"}),s.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"),Object.assign(this.iframe.style,{width:"100%",height:"480px",border:"none",display:"block"}),o.appendChild(s),o.appendChild(this.iframe),this.overlay.appendChild(o),document.body.appendChild(this.overlay);const r=l=>{if(l.key!=="Tab")return;const d=o.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');if(d.length===0){l.preventDefault(),o.focus();return}const a=d[0],u=d[d.length-1],c=document.activeElement;l.shiftKey&&c===a?(l.preventDefault(),u.focus()):!l.shiftKey&&c===u&&(l.preventDefault(),a.focus())};o.addEventListener("keydown",r),s.focus(),this.previousBodyOverflow=document.body.style.overflow,document.body.style.overflow="hidden",this.didManageBodyOverflow=!0,this.setupMessageListener(),this.overlay._escHandler=i,this.overlay._focusTrapHandler=r}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.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 f({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 h(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)}),Object.assign(e.style,{backgroundColor:"#1c1917",color:"#ffffff",border:"1px solid #292524",borderRadius:"4px",padding:"8px 16px",fontSize:"14px",fontWeight:"500",cursor:"pointer",lineHeight:"1.4"}),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),e.textContent=n.label??"Add to Calendar",e}if(typeof window<"u"){const n=window;n.MomentSdk=p,n.createMomentButton=h}m.MomentSdk=p,m.createMomentButton=h,Object.defineProperty(m,Symbol.toStringTag,{value:"Module"})})(this.MomentSdk=this.MomentSdk||{});
|
package/dist/moment-sdk.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
class
|
|
1
|
+
class h {
|
|
2
2
|
popup = null;
|
|
3
3
|
pollTimer = null;
|
|
4
4
|
messageHandler = null;
|
|
@@ -12,19 +12,19 @@ class m {
|
|
|
12
12
|
*/
|
|
13
13
|
open(e) {
|
|
14
14
|
this.cleanup(), this.resultReceived = !1;
|
|
15
|
-
const t = this.buildPopupUrl(e),
|
|
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=${
|
|
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 = (s) => {
|
|
25
|
+
if (s.origin !== this.opts.liveOrigin || s.source !== this.popup) return;
|
|
26
|
+
const r = s.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
|
/**
|
|
@@ -39,14 +39,14 @@ class m {
|
|
|
39
39
|
this.popup = null;
|
|
40
40
|
}
|
|
41
41
|
buildPopupUrl(e) {
|
|
42
|
-
const t = window.location.origin,
|
|
42
|
+
const t = window.location.origin, i = new URLSearchParams({
|
|
43
43
|
provider: e.provider,
|
|
44
44
|
teamSlug: e.teamSlug,
|
|
45
45
|
ids: e.ids.join(","),
|
|
46
46
|
triggerType: e.triggerType,
|
|
47
47
|
returnOrigin: t
|
|
48
48
|
});
|
|
49
|
-
return `${this.opts.liveBaseUrl}/en/embed/oauth-popup?${
|
|
49
|
+
return e.subscriptionType && i.set("subscriptionType", e.subscriptionType), `${this.opts.liveBaseUrl}/en/embed/oauth-popup?${i.toString()}`;
|
|
50
50
|
}
|
|
51
51
|
startPolling() {
|
|
52
52
|
this.pollTimer = setInterval(() => {
|
|
@@ -63,8 +63,8 @@ class m {
|
|
|
63
63
|
this.opts.iframeWindow.postMessage(t, this.opts.liveOrigin);
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
-
const
|
|
67
|
-
class
|
|
66
|
+
const g = ".moment-sync-trigger", f = "https://live.dev.momentco.ai";
|
|
67
|
+
class v {
|
|
68
68
|
opts;
|
|
69
69
|
liveBaseUrl;
|
|
70
70
|
liveOrigin;
|
|
@@ -80,9 +80,9 @@ class g {
|
|
|
80
80
|
closeTimer = null;
|
|
81
81
|
constructor(e) {
|
|
82
82
|
this.opts = {
|
|
83
|
-
triggerSelector:
|
|
83
|
+
triggerSelector: g,
|
|
84
84
|
...e
|
|
85
|
-
}, this.liveBaseUrl =
|
|
85
|
+
}, this.liveBaseUrl = f;
|
|
86
86
|
try {
|
|
87
87
|
this.liveOrigin = new URL(this.liveBaseUrl).origin;
|
|
88
88
|
} catch {
|
|
@@ -120,10 +120,10 @@ class g {
|
|
|
120
120
|
// ── Private: trigger binding ──────────────────────────────────────
|
|
121
121
|
bindTriggers() {
|
|
122
122
|
document.querySelectorAll(this.opts.triggerSelector).forEach((t) => {
|
|
123
|
-
const
|
|
124
|
-
|
|
125
|
-
},
|
|
126
|
-
|
|
123
|
+
const i = (s) => {
|
|
124
|
+
s.preventDefault(), this.handleTriggerClick(t);
|
|
125
|
+
}, o = this.boundClickHandlers.get(t);
|
|
126
|
+
o && t.removeEventListener("click", o), t.addEventListener("click", i), this.boundClickHandlers.set(t, i);
|
|
127
127
|
});
|
|
128
128
|
}
|
|
129
129
|
unbindTriggers() {
|
|
@@ -132,29 +132,30 @@ class g {
|
|
|
132
132
|
}), this.boundClickHandlers.clear();
|
|
133
133
|
}
|
|
134
134
|
handleTriggerClick(e) {
|
|
135
|
-
const t = e.getAttribute("data-moment-team-slug") ?? "",
|
|
136
|
-
let
|
|
137
|
-
|
|
135
|
+
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");
|
|
136
|
+
let r = "moment";
|
|
137
|
+
s != null && s !== "" && (s === "moment" || s === "list" || s === "team" ? r = s : console.warn(
|
|
138
138
|
"[MomentSdk] Invalid data-moment-trigger-type, falling back to 'moment':",
|
|
139
|
-
|
|
139
|
+
s
|
|
140
140
|
));
|
|
141
141
|
const l = e.getAttribute("data-moment-ids") ?? e.getAttribute("data-moment-game-id") ?? "", d = l ? l.split(",").filter(Boolean) : [], a = e.getAttribute("data-moment-calendar");
|
|
142
|
-
let
|
|
143
|
-
if (a != null && a !== "" && (a === "google" || a === "outlook" ?
|
|
142
|
+
let u;
|
|
143
|
+
if (a != null && a !== "" && (a === "google" || a === "outlook" ? u = a : console.warn("[MomentSdk] Invalid data-moment-calendar, ignoring value:", a)), !t) {
|
|
144
144
|
console.warn("[MomentSdk] Missing data-moment-team-slug on trigger element");
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
147
|
+
const c = r === "team" ? void 0 : i, p = r === "team" ? void 0 : o, m = r === "team" ? [] : d;
|
|
147
148
|
this.emitAnalytics("embed.trigger.click", {
|
|
148
149
|
teamSlug: t,
|
|
149
|
-
triggerType:
|
|
150
|
-
momentIds:
|
|
150
|
+
triggerType: r,
|
|
151
|
+
momentIds: m
|
|
151
152
|
}), this.open({
|
|
152
153
|
teamSlug: t,
|
|
153
|
-
|
|
154
|
-
listSlug:
|
|
155
|
-
triggerType:
|
|
156
|
-
ids:
|
|
157
|
-
calendar:
|
|
154
|
+
momentSlug: c,
|
|
155
|
+
listSlug: p,
|
|
156
|
+
triggerType: r,
|
|
157
|
+
ids: m,
|
|
158
|
+
calendar: u ?? void 0
|
|
158
159
|
});
|
|
159
160
|
}
|
|
160
161
|
// ── Private: modal creation ───────────────────────────────────────
|
|
@@ -174,12 +175,12 @@ class g {
|
|
|
174
175
|
}), this.overlay.addEventListener("click", (l) => {
|
|
175
176
|
l.target === this.overlay && this.handleCancel();
|
|
176
177
|
});
|
|
177
|
-
const
|
|
178
|
+
const i = (l) => {
|
|
178
179
|
l.key === "Escape" && this.handleCancel();
|
|
179
180
|
};
|
|
180
|
-
document.addEventListener("keydown",
|
|
181
|
-
const
|
|
182
|
-
|
|
181
|
+
document.addEventListener("keydown", i);
|
|
182
|
+
const o = document.createElement("div");
|
|
183
|
+
o.setAttribute("role", "dialog"), o.setAttribute("aria-modal", "true"), o.setAttribute("aria-label", "Calendar sync modal"), o.tabIndex = -1, Object.assign(o.style, {
|
|
183
184
|
position: "relative",
|
|
184
185
|
width: "100%",
|
|
185
186
|
maxWidth: "420px",
|
|
@@ -189,8 +190,8 @@ class g {
|
|
|
189
190
|
backgroundColor: "#ffffff",
|
|
190
191
|
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)"
|
|
191
192
|
});
|
|
192
|
-
const
|
|
193
|
-
|
|
193
|
+
const s = document.createElement("button");
|
|
194
|
+
s.type = "button", s.textContent = "ⓧ", s.setAttribute("aria-label", "Close"), Object.assign(s.style, {
|
|
194
195
|
position: "absolute",
|
|
195
196
|
top: "8px",
|
|
196
197
|
right: "8px",
|
|
@@ -204,29 +205,29 @@ class g {
|
|
|
204
205
|
display: "flex",
|
|
205
206
|
alignItems: "center",
|
|
206
207
|
justifyContent: "center"
|
|
207
|
-
}),
|
|
208
|
+
}), s.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"), Object.assign(this.iframe.style, {
|
|
208
209
|
width: "100%",
|
|
209
210
|
height: "480px",
|
|
210
211
|
border: "none",
|
|
211
212
|
display: "block"
|
|
212
|
-
}),
|
|
213
|
-
const
|
|
213
|
+
}), o.appendChild(s), o.appendChild(this.iframe), this.overlay.appendChild(o), document.body.appendChild(this.overlay);
|
|
214
|
+
const r = (l) => {
|
|
214
215
|
if (l.key !== "Tab") return;
|
|
215
|
-
const d =
|
|
216
|
+
const d = o.querySelectorAll(
|
|
216
217
|
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
|
|
217
218
|
);
|
|
218
219
|
if (d.length === 0) {
|
|
219
|
-
l.preventDefault(),
|
|
220
|
+
l.preventDefault(), o.focus();
|
|
220
221
|
return;
|
|
221
222
|
}
|
|
222
|
-
const a = d[0],
|
|
223
|
-
l.shiftKey &&
|
|
223
|
+
const a = d[0], u = d[d.length - 1], c = document.activeElement;
|
|
224
|
+
l.shiftKey && c === a ? (l.preventDefault(), u.focus()) : !l.shiftKey && c === u && (l.preventDefault(), a.focus());
|
|
224
225
|
};
|
|
225
|
-
|
|
226
|
+
o.addEventListener("keydown", r), s.focus(), this.previousBodyOverflow = document.body.style.overflow, document.body.style.overflow = "hidden", this.didManageBodyOverflow = !0, this.setupMessageListener(), this.overlay._escHandler = i, this.overlay._focusTrapHandler = r;
|
|
226
227
|
}
|
|
227
228
|
buildIframeUrl(e) {
|
|
228
229
|
const t = new URLSearchParams();
|
|
229
|
-
return t.set("teamSlug", e.teamSlug), e.
|
|
230
|
+
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()}`;
|
|
230
231
|
}
|
|
231
232
|
// ── Private: message handling ─────────────────────────────────────
|
|
232
233
|
setupMessageListener() {
|
|
@@ -235,22 +236,22 @@ class g {
|
|
|
235
236
|
const t = e.data;
|
|
236
237
|
if (!(!t || typeof t != "object")) {
|
|
237
238
|
if (t.source === "moment-live-embed" && t.type === "moment.embed.oauth.start") {
|
|
238
|
-
const
|
|
239
|
+
const i = t;
|
|
239
240
|
this.emitAnalytics("oauth.start", {
|
|
240
|
-
provider:
|
|
241
|
-
teamSlug:
|
|
242
|
-
}), this.handleOAuthStart(
|
|
241
|
+
provider: i.provider,
|
|
242
|
+
teamSlug: i.teamSlug
|
|
243
|
+
}), this.handleOAuthStart(i);
|
|
243
244
|
return;
|
|
244
245
|
}
|
|
245
246
|
if (t.source === "moment-live-embed" && t.type === "moment.embed.result") {
|
|
246
|
-
const
|
|
247
|
-
this.handleResult(
|
|
247
|
+
const i = t;
|
|
248
|
+
this.handleResult(i);
|
|
248
249
|
}
|
|
249
250
|
}
|
|
250
251
|
}, window.addEventListener("message", this.messageHandler);
|
|
251
252
|
}
|
|
252
253
|
handleOAuthStart(e) {
|
|
253
|
-
this.popupBridge && (this.popupBridge.cleanup(), this.popupBridge = null), this.popupBridge = new
|
|
254
|
+
this.popupBridge && (this.popupBridge.cleanup(), this.popupBridge = null), this.popupBridge = new h({
|
|
254
255
|
liveBaseUrl: this.liveBaseUrl,
|
|
255
256
|
liveOrigin: this.liveOrigin,
|
|
256
257
|
iframeWindow: this.iframe?.contentWindow ?? null,
|
|
@@ -302,8 +303,8 @@ class g {
|
|
|
302
303
|
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) {
|
|
303
304
|
const { _escHandler: e, _focusTrapHandler: t } = this.overlay;
|
|
304
305
|
e && document.removeEventListener("keydown", e);
|
|
305
|
-
const
|
|
306
|
-
|
|
306
|
+
const i = this.overlay.firstElementChild;
|
|
307
|
+
i && t && i.removeEventListener("keydown", t), this.overlay.remove(), this.overlay = null;
|
|
307
308
|
}
|
|
308
309
|
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;
|
|
309
310
|
}
|
|
@@ -316,7 +317,7 @@ class g {
|
|
|
316
317
|
});
|
|
317
318
|
}
|
|
318
319
|
}
|
|
319
|
-
function
|
|
320
|
+
function b(n) {
|
|
320
321
|
const e = document.createElement("button");
|
|
321
322
|
return e.type = "button", e.classList.add("moment-sync-trigger"), n.className && n.className.split(" ").forEach((t) => {
|
|
322
323
|
t && e.classList.add(t);
|
|
@@ -330,13 +331,13 @@ function f(n) {
|
|
|
330
331
|
fontWeight: "500",
|
|
331
332
|
cursor: "pointer",
|
|
332
333
|
lineHeight: "1.4"
|
|
333
|
-
}), e.setAttribute("data-moment-team-slug", n.teamSlug), n.
|
|
334
|
+
}), 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), e.textContent = n.label ?? "Add to Calendar", e;
|
|
334
335
|
}
|
|
335
336
|
if (typeof window < "u") {
|
|
336
337
|
const n = window;
|
|
337
|
-
n.MomentSdk =
|
|
338
|
+
n.MomentSdk = v, n.createMomentButton = b;
|
|
338
339
|
}
|
|
339
340
|
export {
|
|
340
|
-
|
|
341
|
-
|
|
341
|
+
v as MomentSdk,
|
|
342
|
+
b as createMomentButton
|
|
342
343
|
};
|
|
@@ -5,7 +5,8 @@ import type { MomentTriggerType, CalendarProvider } from './types';
|
|
|
5
5
|
*/
|
|
6
6
|
export declare function createMomentButton(options: {
|
|
7
7
|
teamSlug: string;
|
|
8
|
-
|
|
8
|
+
/** Brand-level moment slug. */
|
|
9
|
+
momentSlug?: string;
|
|
9
10
|
listSlug?: string;
|
|
10
11
|
triggerType?: MomentTriggerType;
|
|
11
12
|
ids?: string[];
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Subscription target type forwarded to the Live embed and ultimately mapped
|
|
3
|
+
* to the backend `subscriptionType`.
|
|
4
|
+
*
|
|
5
|
+
* - `moment` → subscribe to one or more specific moments
|
|
6
|
+
* - `list` → subscribe to a curated list of moments
|
|
7
|
+
* - `team` → subscribe to a team / brand schedule (all published moments)
|
|
8
|
+
*/
|
|
9
|
+
export type MomentTriggerType = 'moment' | 'list' | 'team';
|
|
2
10
|
export type CalendarProvider = 'google' | 'outlook';
|
|
3
11
|
export interface MomentSdkInitOptions {
|
|
4
12
|
/** CSS selector for trigger elements. Default: ".moment-sync-trigger" */
|
|
@@ -12,14 +20,29 @@ export interface MomentSdkInitOptions {
|
|
|
12
20
|
/** Optional analytics callback for tracking embed events. */
|
|
13
21
|
onAnalytics?: (event: MomentAnalyticsEvent) => void;
|
|
14
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Payload accepted by `MomentSdk.open()` and parsed from trigger element
|
|
25
|
+
* `data-moment-*` attributes.
|
|
26
|
+
*
|
|
27
|
+
* Required fields by `triggerType`:
|
|
28
|
+
* - `moment` → `teamSlug` plus EITHER `momentSlug` (brand-level moment slug)
|
|
29
|
+
* OR `ids`
|
|
30
|
+
* - `list` → `teamSlug` plus `listSlug` (`ids` not required — list resolves
|
|
31
|
+
* to a single list-level subscription)
|
|
32
|
+
* - `team` → `teamSlug` only (resolves to the brand's team-level
|
|
33
|
+
* subscription; `listSlug`, `momentSlug`, and `ids` are ignored)
|
|
34
|
+
*/
|
|
15
35
|
export interface MomentSdkOpenPayload {
|
|
16
36
|
teamSlug: string;
|
|
17
|
-
|
|
37
|
+
/** Brand-level moment slug. */
|
|
38
|
+
momentSlug?: string;
|
|
18
39
|
listSlug?: string;
|
|
19
40
|
triggerType: MomentTriggerType;
|
|
20
41
|
ids?: string[];
|
|
21
42
|
calendar?: CalendarProvider;
|
|
22
43
|
}
|
|
44
|
+
/** Backend subscription resource type that the embed will create */
|
|
45
|
+
export type MomentSubscriptionType = 'moment' | 'list' | 'team';
|
|
23
46
|
/** Iframe → Parent: request to start OAuth via popup */
|
|
24
47
|
export interface MomentOAuthStartPayload {
|
|
25
48
|
source: 'moment-live-embed';
|
|
@@ -28,6 +51,14 @@ export interface MomentOAuthStartPayload {
|
|
|
28
51
|
teamSlug: string;
|
|
29
52
|
ids: string[];
|
|
30
53
|
triggerType: MomentTriggerType;
|
|
54
|
+
/**
|
|
55
|
+
* Authoritative backend subscription type for `ids`.
|
|
56
|
+
* The iframe is the single source of truth: when present this should be
|
|
57
|
+
* forwarded verbatim to the popup so the popup does not need to re-derive
|
|
58
|
+
* it from `triggerType` (which would mis-handle cherry-picked moment IDs
|
|
59
|
+
* under a `list`/`team` trigger).
|
|
60
|
+
*/
|
|
61
|
+
subscriptionType?: MomentSubscriptionType;
|
|
31
62
|
returnOrigin: string;
|
|
32
63
|
}
|
|
33
64
|
/** Parent → Iframe: relay OAuth popup status */
|
package/package.json
CHANGED