@rehers/rehers-roleplay-sdk 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +4 -2
- package/package.json +1 -1
- package/roleplay-sdk.js +216 -137
package/index.d.ts
CHANGED
|
@@ -82,9 +82,11 @@ export interface SeamlessRoleplaySDK {
|
|
|
82
82
|
mount(container: HTMLElement, data?: SeamlessRoleplayOpenData): void;
|
|
83
83
|
/** Open the add-to-scenario dialog for bulk contact import. */
|
|
84
84
|
addToScenario(options: AddToScenarioOptions): void;
|
|
85
|
-
/** Close the
|
|
85
|
+
/** Close the active dialog. Does not affect mount. */
|
|
86
86
|
close(): void;
|
|
87
|
-
/**
|
|
87
|
+
/** Unmount the mounted embed. Does not affect dialogs. */
|
|
88
|
+
unmount(): void;
|
|
89
|
+
/** Destroy the SDK — clears state, timers, and DOM (both mount and dialogs). */
|
|
88
90
|
destroy(): void;
|
|
89
91
|
}
|
|
90
92
|
|
package/package.json
CHANGED
package/roleplay-sdk.js
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
var SESSION_TIMEOUT_MS = 15000;
|
|
16
16
|
var SDK_LOG_PREFIX = "[SeamlessRoleplay]";
|
|
17
17
|
|
|
18
|
-
// ──
|
|
18
|
+
// ── Auth state ────────────────────────────────────────────────────
|
|
19
19
|
var publishableKey = null;
|
|
20
20
|
var userId = null;
|
|
21
21
|
var userEmail = null;
|
|
@@ -30,18 +30,25 @@
|
|
|
30
30
|
var fetchingSession = null; // single-flight Promise
|
|
31
31
|
|
|
32
32
|
var initCallbacks = { onReady: null, onError: null };
|
|
33
|
-
var
|
|
34
|
-
var addToScenarioCallbacks = { onComplete: null, onClose: null, onError: null };
|
|
35
|
-
var addToScenarioPendingContacts = null;
|
|
33
|
+
var initCalled = false;
|
|
36
34
|
|
|
37
|
-
|
|
38
|
-
var
|
|
35
|
+
// ── Mount state (persistent embed — survives dialog open/close) ───
|
|
36
|
+
var mountIframe = null;
|
|
39
37
|
var mountContainer = null;
|
|
40
|
-
var
|
|
41
|
-
var
|
|
42
|
-
var
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
var mountContactData = null;
|
|
39
|
+
var mountCallbacks = { onCallStarted: null, onCallEnded: null, onClose: null, onError: null };
|
|
40
|
+
var mountListener = null;
|
|
41
|
+
|
|
42
|
+
// ── Dialog state (overlay — dialog or add-to-scenario) ────────────
|
|
43
|
+
var dialogOverlay = null;
|
|
44
|
+
var dialogIframe = null;
|
|
45
|
+
var dialogMode = null; // "dialog" | "add-to-scenario"
|
|
46
|
+
var dialogContactData = null;
|
|
47
|
+
var dialogCallbacks = { onCallStarted: null, onCallEnded: null, onClose: null, onError: null };
|
|
48
|
+
var dialogAddToScenarioCallbacks = { onComplete: null, onClose: null, onError: null };
|
|
49
|
+
var dialogAddToScenarioPendingContacts = null;
|
|
50
|
+
var dialogListener = null;
|
|
51
|
+
var dialogCloseTeardownTimer = null;
|
|
45
52
|
|
|
46
53
|
// ── Safe logging ──────────────────────────────────────────────────
|
|
47
54
|
|
|
@@ -65,17 +72,17 @@
|
|
|
65
72
|
return DEFAULT_API_ORIGIN;
|
|
66
73
|
}
|
|
67
74
|
|
|
68
|
-
function
|
|
75
|
+
function sendMsg(iframeEl, msg) {
|
|
69
76
|
try {
|
|
70
|
-
if (
|
|
71
|
-
|
|
77
|
+
if (iframeEl && iframeEl.contentWindow) {
|
|
78
|
+
iframeEl.contentWindow.postMessage(msg, getOrigin());
|
|
72
79
|
}
|
|
73
80
|
} catch (e) {
|
|
74
|
-
logError("
|
|
81
|
+
logError("sendMsg", e);
|
|
75
82
|
}
|
|
76
83
|
}
|
|
77
84
|
|
|
78
|
-
// ── Session management
|
|
85
|
+
// ── Session management ────────────────────────────────────────────
|
|
79
86
|
|
|
80
87
|
function fetchSession() {
|
|
81
88
|
if (fetchingSession) return fetchingSession;
|
|
@@ -167,80 +174,90 @@
|
|
|
167
174
|
}, delay);
|
|
168
175
|
}
|
|
169
176
|
|
|
170
|
-
// ── Teardown
|
|
177
|
+
// ── Teardown (dialog only — mount is independent) ─────────────────
|
|
171
178
|
|
|
172
|
-
function
|
|
179
|
+
function teardownDialog() {
|
|
173
180
|
try {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
closeTeardownTimer = null;
|
|
181
|
+
if (dialogCloseTeardownTimer) {
|
|
182
|
+
clearTimeout(dialogCloseTeardownTimer);
|
|
183
|
+
dialogCloseTeardownTimer = null;
|
|
178
184
|
}
|
|
179
185
|
|
|
180
|
-
if (
|
|
181
|
-
|
|
182
|
-
overlay.parentNode.removeChild(overlay);
|
|
183
|
-
}
|
|
184
|
-
overlay = null;
|
|
185
|
-
} else if (mode === "mount") {
|
|
186
|
-
if (iframe && iframe.parentNode) {
|
|
187
|
-
iframe.parentNode.removeChild(iframe);
|
|
188
|
-
}
|
|
189
|
-
mountContainer = null;
|
|
186
|
+
if (dialogOverlay && dialogOverlay.parentNode) {
|
|
187
|
+
dialogOverlay.parentNode.removeChild(dialogOverlay);
|
|
190
188
|
}
|
|
189
|
+
dialogOverlay = null;
|
|
190
|
+
|
|
191
|
+
if (dialogListener) {
|
|
192
|
+
window.removeEventListener("message", dialogListener);
|
|
193
|
+
dialogListener = null;
|
|
194
|
+
}
|
|
195
|
+
} catch (e) {
|
|
196
|
+
logError("teardownDialog", e);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
dialogIframe = null;
|
|
200
|
+
dialogContactData = null;
|
|
201
|
+
dialogAddToScenarioPendingContacts = null;
|
|
202
|
+
dialogMode = null;
|
|
203
|
+
dialogCallbacks = { onCallStarted: null, onCallEnded: null, onClose: null, onError: null };
|
|
204
|
+
dialogAddToScenarioCallbacks = { onComplete: null, onClose: null, onError: null };
|
|
205
|
+
}
|
|
191
206
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
207
|
+
function teardownMount() {
|
|
208
|
+
try {
|
|
209
|
+
if (mountIframe && mountIframe.parentNode) {
|
|
210
|
+
mountIframe.parentNode.removeChild(mountIframe);
|
|
211
|
+
}
|
|
212
|
+
if (mountListener) {
|
|
213
|
+
window.removeEventListener("message", mountListener);
|
|
214
|
+
mountListener = null;
|
|
195
215
|
}
|
|
196
216
|
} catch (e) {
|
|
197
|
-
logError("
|
|
217
|
+
logError("teardownMount", e);
|
|
198
218
|
}
|
|
199
219
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
mode = null;
|
|
205
|
-
callbacks = { onCallStarted: null, onCallEnded: null, onClose: null, onError: null };
|
|
206
|
-
addToScenarioCallbacks = { onComplete: null, onClose: null, onError: null };
|
|
220
|
+
mountIframe = null;
|
|
221
|
+
mountContainer = null;
|
|
222
|
+
mountContactData = null;
|
|
223
|
+
mountCallbacks = { onCallStarted: null, onCallEnded: null, onClose: null, onError: null };
|
|
207
224
|
}
|
|
208
225
|
|
|
209
|
-
// ── Message
|
|
226
|
+
// ── Message dispatch ──────────────────────────────────────────────
|
|
210
227
|
|
|
211
|
-
function
|
|
212
|
-
if (
|
|
228
|
+
function dispatchInitToTarget(targetIframe, contactData, atsContacts) {
|
|
229
|
+
if (atsContacts) {
|
|
213
230
|
var msg = {
|
|
214
231
|
type: "seamless-add-to-scenario-init",
|
|
215
|
-
sessionToken:
|
|
232
|
+
sessionToken: sessionToken,
|
|
216
233
|
publishableKey: publishableKey,
|
|
217
234
|
userId: userId,
|
|
218
|
-
contacts:
|
|
235
|
+
contacts: atsContacts,
|
|
219
236
|
};
|
|
220
237
|
if (paymentLink) msg.paymentLink = paymentLink;
|
|
221
|
-
|
|
222
|
-
} else if (
|
|
238
|
+
sendMsg(targetIframe, msg);
|
|
239
|
+
} else if (sessionToken) {
|
|
223
240
|
var msg = {
|
|
224
241
|
type: "seamless-session-init",
|
|
225
|
-
sessionToken:
|
|
226
|
-
contact:
|
|
227
|
-
name:
|
|
228
|
-
domain:
|
|
229
|
-
company:
|
|
230
|
-
title:
|
|
231
|
-
companyDescription:
|
|
232
|
-
liUrl:
|
|
242
|
+
sessionToken: sessionToken,
|
|
243
|
+
contact: contactData ? {
|
|
244
|
+
name: contactData.name,
|
|
245
|
+
domain: contactData.domain,
|
|
246
|
+
company: contactData.company,
|
|
247
|
+
title: contactData.title,
|
|
248
|
+
companyDescription: contactData.companyDescription || undefined,
|
|
249
|
+
liUrl: contactData.liUrl || undefined,
|
|
233
250
|
} : null,
|
|
234
251
|
};
|
|
235
|
-
|
|
252
|
+
sendMsg(targetIframe, msg);
|
|
236
253
|
} else if (paymentLink) {
|
|
237
|
-
|
|
254
|
+
sendMsg(targetIframe, {
|
|
238
255
|
type: "seamless-session-init",
|
|
239
256
|
paymentLink: paymentLink,
|
|
240
257
|
contact: null,
|
|
241
258
|
});
|
|
242
259
|
} else {
|
|
243
|
-
|
|
260
|
+
sendMsg(targetIframe, {
|
|
244
261
|
type: "seamless-session-init",
|
|
245
262
|
paymentLink: null,
|
|
246
263
|
contact: null,
|
|
@@ -248,53 +265,104 @@
|
|
|
248
265
|
}
|
|
249
266
|
}
|
|
250
267
|
|
|
251
|
-
|
|
268
|
+
// ── Mount message handler ─────────────────────────────────────────
|
|
269
|
+
|
|
270
|
+
function handleMountMessage(event) {
|
|
271
|
+
try {
|
|
272
|
+
if (event.origin !== getOrigin()) return;
|
|
273
|
+
if (!mountIframe || !event.source || event.source !== mountIframe.contentWindow) return;
|
|
274
|
+
|
|
275
|
+
var data = event.data;
|
|
276
|
+
if (!data || typeof data.type !== "string") return;
|
|
277
|
+
|
|
278
|
+
switch (data.type) {
|
|
279
|
+
case "ROLEPLAY_READY":
|
|
280
|
+
getSessionToken()
|
|
281
|
+
.then(function (token) {
|
|
282
|
+
dispatchInitToTarget(mountIframe, mountContactData, null);
|
|
283
|
+
})
|
|
284
|
+
.catch(function () {
|
|
285
|
+
dispatchInitToTarget(mountIframe, mountContactData, null);
|
|
286
|
+
});
|
|
287
|
+
break;
|
|
288
|
+
|
|
289
|
+
case "ROLEPLAY_CALL_STARTED":
|
|
290
|
+
if (mountCallbacks.onCallStarted) {
|
|
291
|
+
mountCallbacks.onCallStarted({ callId: data.callId });
|
|
292
|
+
}
|
|
293
|
+
break;
|
|
294
|
+
|
|
295
|
+
case "ROLEPLAY_CALL_ENDED":
|
|
296
|
+
if (mountCallbacks.onCallEnded) {
|
|
297
|
+
mountCallbacks.onCallEnded({ callId: data.callId, duration: data.duration });
|
|
298
|
+
}
|
|
299
|
+
break;
|
|
300
|
+
|
|
301
|
+
case "ROLEPLAY_ERROR":
|
|
302
|
+
if (mountCallbacks.onError) {
|
|
303
|
+
mountCallbacks.onError({ code: data.code, message: data.message });
|
|
304
|
+
}
|
|
305
|
+
break;
|
|
306
|
+
|
|
307
|
+
case "ROLEPLAY_CLOSED":
|
|
308
|
+
var onClose = mountCallbacks.onClose;
|
|
309
|
+
teardownMount();
|
|
310
|
+
if (onClose) onClose();
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
} catch (e) {
|
|
314
|
+
logError("handleMountMessage", e);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// ── Dialog message handler ────────────────────────────────────────
|
|
319
|
+
|
|
320
|
+
function handleDialogMessage(event) {
|
|
252
321
|
try {
|
|
253
322
|
if (event.origin !== getOrigin()) return;
|
|
323
|
+
if (!dialogIframe || !event.source || event.source !== dialogIframe.contentWindow) return;
|
|
254
324
|
|
|
255
325
|
var data = event.data;
|
|
256
326
|
if (!data || typeof data.type !== "string") return;
|
|
257
327
|
|
|
258
328
|
switch (data.type) {
|
|
259
329
|
case "ROLEPLAY_READY":
|
|
260
|
-
// Ensure we have a fresh token before sending init to iframe
|
|
261
330
|
getSessionToken()
|
|
262
331
|
.then(function (token) {
|
|
263
|
-
|
|
332
|
+
dispatchInitToTarget(dialogIframe, dialogContactData, dialogAddToScenarioPendingContacts);
|
|
264
333
|
})
|
|
265
334
|
.catch(function () {
|
|
266
|
-
|
|
267
|
-
dispatchInitToIframe(sessionToken);
|
|
335
|
+
dispatchInitToTarget(dialogIframe, dialogContactData, dialogAddToScenarioPendingContacts);
|
|
268
336
|
});
|
|
269
337
|
break;
|
|
270
338
|
|
|
271
339
|
case "ROLEPLAY_CALL_STARTED":
|
|
272
|
-
if (
|
|
273
|
-
|
|
340
|
+
if (dialogCallbacks.onCallStarted) {
|
|
341
|
+
dialogCallbacks.onCallStarted({ callId: data.callId });
|
|
274
342
|
}
|
|
275
343
|
break;
|
|
276
344
|
|
|
277
345
|
case "ROLEPLAY_CALL_ENDED":
|
|
278
|
-
if (
|
|
279
|
-
|
|
346
|
+
if (dialogCallbacks.onCallEnded) {
|
|
347
|
+
dialogCallbacks.onCallEnded({ callId: data.callId, duration: data.duration });
|
|
280
348
|
}
|
|
281
349
|
break;
|
|
282
350
|
|
|
283
351
|
case "ROLEPLAY_ERROR":
|
|
284
|
-
if (
|
|
285
|
-
|
|
352
|
+
if (dialogCallbacks.onError) {
|
|
353
|
+
dialogCallbacks.onError({ code: data.code, message: data.message });
|
|
286
354
|
}
|
|
287
355
|
break;
|
|
288
356
|
|
|
289
357
|
case "ROLEPLAY_CLOSED":
|
|
290
|
-
var onClose =
|
|
291
|
-
|
|
358
|
+
var onClose = dialogCallbacks.onClose;
|
|
359
|
+
teardownDialog();
|
|
292
360
|
if (onClose) onClose();
|
|
293
361
|
break;
|
|
294
362
|
|
|
295
363
|
case "ADD_TO_SCENARIO_COMPLETE":
|
|
296
|
-
var atsOnComplete =
|
|
297
|
-
|
|
364
|
+
var atsOnComplete = dialogAddToScenarioCallbacks.onComplete;
|
|
365
|
+
teardownDialog();
|
|
298
366
|
if (atsOnComplete) {
|
|
299
367
|
atsOnComplete({
|
|
300
368
|
scenarioId: data.scenarioId,
|
|
@@ -306,36 +374,36 @@
|
|
|
306
374
|
break;
|
|
307
375
|
|
|
308
376
|
case "ADD_TO_SCENARIO_ERROR":
|
|
309
|
-
if (
|
|
310
|
-
|
|
377
|
+
if (dialogAddToScenarioCallbacks.onError) {
|
|
378
|
+
dialogAddToScenarioCallbacks.onError({ code: data.code, message: data.message });
|
|
311
379
|
}
|
|
312
380
|
break;
|
|
313
381
|
|
|
314
382
|
case "ADD_TO_SCENARIO_CLOSED":
|
|
315
|
-
var atsOnClose =
|
|
316
|
-
|
|
383
|
+
var atsOnClose = dialogAddToScenarioCallbacks.onClose;
|
|
384
|
+
teardownDialog();
|
|
317
385
|
if (atsOnClose) atsOnClose();
|
|
318
386
|
break;
|
|
319
387
|
}
|
|
320
388
|
} catch (e) {
|
|
321
|
-
logError("
|
|
389
|
+
logError("handleDialogMessage", e);
|
|
322
390
|
}
|
|
323
391
|
}
|
|
324
392
|
|
|
325
|
-
// ── Close
|
|
393
|
+
// ── Close (dialog only) ───────────────────────────────────────────
|
|
326
394
|
|
|
327
|
-
function
|
|
395
|
+
function closeDialog() {
|
|
328
396
|
try {
|
|
329
|
-
|
|
330
|
-
if (
|
|
331
|
-
|
|
397
|
+
sendMsg(dialogIframe, { type: "roleplay-close" });
|
|
398
|
+
if (dialogCloseTeardownTimer) clearTimeout(dialogCloseTeardownTimer);
|
|
399
|
+
dialogCloseTeardownTimer = setTimeout(teardownDialog, 300);
|
|
332
400
|
} catch (e) {
|
|
333
401
|
logError("close", e);
|
|
334
|
-
|
|
402
|
+
teardownDialog();
|
|
335
403
|
}
|
|
336
404
|
}
|
|
337
405
|
|
|
338
|
-
// ── Create iframe
|
|
406
|
+
// ── Create iframe ─────────────────────────────────────────────────
|
|
339
407
|
|
|
340
408
|
function createIframe(path) {
|
|
341
409
|
var iframeEl = document.createElement("iframe");
|
|
@@ -348,7 +416,7 @@
|
|
|
348
416
|
return iframeEl;
|
|
349
417
|
}
|
|
350
418
|
|
|
351
|
-
// ── SDK API
|
|
419
|
+
// ── SDK API ───────────────────────────────────────────────────────
|
|
352
420
|
|
|
353
421
|
var SeamlessRoleplay = {
|
|
354
422
|
/**
|
|
@@ -416,19 +484,19 @@
|
|
|
416
484
|
return;
|
|
417
485
|
}
|
|
418
486
|
|
|
419
|
-
//
|
|
420
|
-
if (
|
|
487
|
+
// Tear down any existing dialog (NOT the mount)
|
|
488
|
+
if (dialogOverlay || dialogIframe) teardownDialog();
|
|
421
489
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
490
|
+
dialogContactData = data;
|
|
491
|
+
dialogCallbacks.onCallStarted = data.onCallStarted || null;
|
|
492
|
+
dialogCallbacks.onCallEnded = data.onCallEnded || null;
|
|
493
|
+
dialogCallbacks.onClose = data.onClose || null;
|
|
494
|
+
dialogCallbacks.onError = data.onError || null;
|
|
495
|
+
dialogMode = "dialog";
|
|
428
496
|
|
|
429
497
|
// Listen for messages
|
|
430
|
-
|
|
431
|
-
window.addEventListener("message",
|
|
498
|
+
dialogListener = handleDialogMessage;
|
|
499
|
+
window.addEventListener("message", dialogListener);
|
|
432
500
|
|
|
433
501
|
// Build overlay
|
|
434
502
|
var el = document.createElement("div");
|
|
@@ -478,7 +546,7 @@
|
|
|
478
546
|
cbs.alignItems = "center";
|
|
479
547
|
cbs.justifyContent = "center";
|
|
480
548
|
cbs.lineHeight = "1";
|
|
481
|
-
closeBtn.addEventListener("click",
|
|
549
|
+
closeBtn.addEventListener("click", closeDialog);
|
|
482
550
|
|
|
483
551
|
var iframeEl = createIframe();
|
|
484
552
|
|
|
@@ -487,15 +555,15 @@
|
|
|
487
555
|
el.appendChild(container);
|
|
488
556
|
|
|
489
557
|
el.addEventListener("click", function (e) {
|
|
490
|
-
if (e.target === el)
|
|
558
|
+
if (e.target === el) closeDialog();
|
|
491
559
|
});
|
|
492
560
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
document.body.appendChild(
|
|
561
|
+
dialogOverlay = el;
|
|
562
|
+
dialogIframe = iframeEl;
|
|
563
|
+
document.body.appendChild(dialogOverlay);
|
|
496
564
|
} catch (e) {
|
|
497
565
|
logError("open", e);
|
|
498
|
-
|
|
566
|
+
teardownDialog();
|
|
499
567
|
if (data && typeof data.onError === "function") {
|
|
500
568
|
try { data.onError({ code: "SDK_ERROR", message: e.message || "Unexpected error during open" }); } catch (_) {}
|
|
501
569
|
}
|
|
@@ -527,28 +595,27 @@
|
|
|
527
595
|
return;
|
|
528
596
|
}
|
|
529
597
|
|
|
530
|
-
//
|
|
531
|
-
if (
|
|
598
|
+
// Tear down any existing mount (re-mount)
|
|
599
|
+
if (mountIframe) teardownMount();
|
|
532
600
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
mode = "mount";
|
|
601
|
+
mountContactData = hasContactData ? data : null;
|
|
602
|
+
mountCallbacks.onCallStarted = (data && data.onCallStarted) || null;
|
|
603
|
+
mountCallbacks.onCallEnded = (data && data.onCallEnded) || null;
|
|
604
|
+
mountCallbacks.onClose = (data && data.onClose) || null;
|
|
605
|
+
mountCallbacks.onError = (data && data.onError) || null;
|
|
539
606
|
mountContainer = container;
|
|
540
607
|
|
|
541
608
|
// Listen for messages
|
|
542
|
-
|
|
543
|
-
window.addEventListener("message",
|
|
609
|
+
mountListener = handleMountMessage;
|
|
610
|
+
window.addEventListener("message", mountListener);
|
|
544
611
|
|
|
545
612
|
// No contact data → full app embed at root; with contact → /embed/roleplay-call
|
|
546
613
|
var iframeEl = createIframe(hasContactData ? "/embed/roleplay-call" : "/");
|
|
547
|
-
|
|
614
|
+
mountIframe = iframeEl;
|
|
548
615
|
container.appendChild(iframeEl);
|
|
549
616
|
} catch (e) {
|
|
550
617
|
logError("mount", e);
|
|
551
|
-
|
|
618
|
+
teardownMount();
|
|
552
619
|
if (data && typeof data.onError === "function") {
|
|
553
620
|
try { data.onError({ code: "SDK_ERROR", message: e.message || "Unexpected error during mount" }); } catch (_) {}
|
|
554
621
|
}
|
|
@@ -588,18 +655,18 @@
|
|
|
588
655
|
}
|
|
589
656
|
}
|
|
590
657
|
|
|
591
|
-
// Tear down any existing dialog (
|
|
592
|
-
if (
|
|
658
|
+
// Tear down any existing dialog (NOT the mount)
|
|
659
|
+
if (dialogOverlay || dialogIframe) teardownDialog();
|
|
593
660
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
661
|
+
dialogAddToScenarioPendingContacts = opts.contacts;
|
|
662
|
+
dialogAddToScenarioCallbacks.onComplete = opts.onComplete || null;
|
|
663
|
+
dialogAddToScenarioCallbacks.onClose = opts.onClose || null;
|
|
664
|
+
dialogAddToScenarioCallbacks.onError = opts.onError || null;
|
|
665
|
+
dialogMode = "add-to-scenario";
|
|
599
666
|
|
|
600
667
|
// Listen for messages
|
|
601
|
-
|
|
602
|
-
window.addEventListener("message",
|
|
668
|
+
dialogListener = handleDialogMessage;
|
|
669
|
+
window.addEventListener("message", dialogListener);
|
|
603
670
|
|
|
604
671
|
// Build overlay — wide, compact dialog
|
|
605
672
|
var el = document.createElement("div");
|
|
@@ -663,22 +730,22 @@
|
|
|
663
730
|
cbs.transition = "background 0.15s";
|
|
664
731
|
closeBtn.addEventListener("mouseenter", function () { cbs.background = "rgba(0,0,0,0.15)"; });
|
|
665
732
|
closeBtn.addEventListener("mouseleave", function () { cbs.background = "rgba(0,0,0,0.08)"; });
|
|
666
|
-
closeBtn.addEventListener("click",
|
|
733
|
+
closeBtn.addEventListener("click", closeDialog);
|
|
667
734
|
|
|
668
735
|
container.appendChild(iframeEl);
|
|
669
736
|
container.appendChild(closeBtn);
|
|
670
737
|
el.appendChild(container);
|
|
671
738
|
|
|
672
739
|
el.addEventListener("click", function (e) {
|
|
673
|
-
if (e.target === el)
|
|
740
|
+
if (e.target === el) closeDialog();
|
|
674
741
|
});
|
|
675
742
|
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
document.body.appendChild(
|
|
743
|
+
dialogOverlay = el;
|
|
744
|
+
dialogIframe = iframeEl;
|
|
745
|
+
document.body.appendChild(dialogOverlay);
|
|
679
746
|
} catch (e) {
|
|
680
747
|
logError("addToScenario", e);
|
|
681
|
-
|
|
748
|
+
teardownDialog();
|
|
682
749
|
if (opts && typeof opts.onError === "function") {
|
|
683
750
|
try { opts.onError({ code: "SDK_ERROR", message: e.message || "Unexpected error during addToScenario" }); } catch (_) {}
|
|
684
751
|
}
|
|
@@ -686,19 +753,30 @@
|
|
|
686
753
|
},
|
|
687
754
|
|
|
688
755
|
/**
|
|
689
|
-
* Close the
|
|
756
|
+
* Close the active dialog. Does not affect mount.
|
|
690
757
|
*/
|
|
691
758
|
close: function () {
|
|
692
759
|
try {
|
|
693
|
-
|
|
760
|
+
closeDialog();
|
|
694
761
|
} catch (e) {
|
|
695
762
|
logError("close", e);
|
|
696
|
-
|
|
763
|
+
teardownDialog();
|
|
764
|
+
}
|
|
765
|
+
},
|
|
766
|
+
|
|
767
|
+
/**
|
|
768
|
+
* Unmount the mounted embed. Does not affect dialogs.
|
|
769
|
+
*/
|
|
770
|
+
unmount: function () {
|
|
771
|
+
try {
|
|
772
|
+
teardownMount();
|
|
773
|
+
} catch (e) {
|
|
774
|
+
logError("unmount", e);
|
|
697
775
|
}
|
|
698
776
|
},
|
|
699
777
|
|
|
700
778
|
/**
|
|
701
|
-
* Destroy the SDK — clears state, timers, and DOM.
|
|
779
|
+
* Destroy the SDK — clears state, timers, and DOM (both mount and dialogs).
|
|
702
780
|
*/
|
|
703
781
|
destroy: function () {
|
|
704
782
|
try {
|
|
@@ -706,7 +784,8 @@
|
|
|
706
784
|
clearTimeout(refreshTimer);
|
|
707
785
|
refreshTimer = null;
|
|
708
786
|
}
|
|
709
|
-
|
|
787
|
+
teardownDialog();
|
|
788
|
+
teardownMount();
|
|
710
789
|
publishableKey = null;
|
|
711
790
|
userId = null;
|
|
712
791
|
userEmail = null;
|