@mochabug/adapt-web 1.0.0-rc53 → 1.0.0-rc54
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/esm/AdaptAutomationElement.js +28 -2
- package/dist/esm/AdaptCapElement.js +0 -1
- package/dist/esm/AdaptCapWidget.js +0 -1
- package/dist/esm/cap-adapter.js +0 -1
- package/dist/esm/elements.js +0 -1
- package/dist/esm/iframe-url.js +0 -1
- package/dist/esm/index.js +250 -3
- package/dist/esm/types.js +0 -1
- package/dist/types/AdaptAutomationElement.d.ts +8 -1
- package/dist/types/index.d.ts +21 -1
- package/dist/types/types.d.ts +21 -0
- package/dist/umd/adapt-web.js +231 -5
- package/dist/umd/adapt-web.min.js +6 -6
- package/package.json +2 -2
- package/dist/esm/AdaptAutomationElement.js.map +0 -1
- package/dist/esm/AdaptCapElement.js.map +0 -1
- package/dist/esm/AdaptCapWidget.js.map +0 -1
- package/dist/esm/cap-adapter.js.map +0 -1
- package/dist/esm/elements.js.map +0 -1
- package/dist/esm/iframe-url.js.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/types.js.map +0 -1
|
@@ -13,6 +13,7 @@ const OBSERVED_ATTRIBUTES = [
|
|
|
13
13
|
"dialog-resize-to-content",
|
|
14
14
|
"dark-mode",
|
|
15
15
|
"auto-resizing",
|
|
16
|
+
"persist",
|
|
16
17
|
];
|
|
17
18
|
/**
|
|
18
19
|
* `<adapt-automation>` custom element for embedding Adapt automations.
|
|
@@ -107,6 +108,25 @@ export class AdaptAutomationElement extends BaseElement {
|
|
|
107
108
|
this.removeAttribute("dialog-resize-to-content");
|
|
108
109
|
}
|
|
109
110
|
}
|
|
111
|
+
get persist() {
|
|
112
|
+
return this.hasAttribute("persist");
|
|
113
|
+
}
|
|
114
|
+
set persist(v) {
|
|
115
|
+
if (v) {
|
|
116
|
+
this.setAttribute("persist", "");
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
this.removeAttribute("persist");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Clear persisted state, stop current session, and reinitialize fresh.
|
|
124
|
+
*/
|
|
125
|
+
async newSession() {
|
|
126
|
+
if (this._client) {
|
|
127
|
+
await this._client.newSession();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
110
130
|
// --- Lifecycle ---
|
|
111
131
|
connectedCallback() {
|
|
112
132
|
// Defer to next microtask to avoid TDZ issues from circular imports
|
|
@@ -119,7 +139,7 @@ export class AdaptAutomationElement extends BaseElement {
|
|
|
119
139
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
120
140
|
if (oldValue === newValue)
|
|
121
141
|
return;
|
|
122
|
-
if (name === "automation-id") {
|
|
142
|
+
if (name === "automation-id" || name === "persist") {
|
|
123
143
|
this._destroyClient();
|
|
124
144
|
queueMicrotask(() => this._tryInit());
|
|
125
145
|
return;
|
|
@@ -229,6 +249,13 @@ export class AdaptAutomationElement extends BaseElement {
|
|
|
229
249
|
options.classNames = this.classNames;
|
|
230
250
|
if (this.styles !== undefined)
|
|
231
251
|
options.styles = this.styles;
|
|
252
|
+
// Persist: object options take precedence, otherwise use boolean attribute
|
|
253
|
+
if (this.persistOptions !== undefined) {
|
|
254
|
+
options.persist = this.persistOptions;
|
|
255
|
+
}
|
|
256
|
+
else if (this.persist) {
|
|
257
|
+
options.persist = true;
|
|
258
|
+
}
|
|
232
259
|
this._client = new AdaptWebClient(options);
|
|
233
260
|
}
|
|
234
261
|
_destroyClient() {
|
|
@@ -251,4 +278,3 @@ if (typeof customElements !== "undefined" &&
|
|
|
251
278
|
document.head.appendChild(s);
|
|
252
279
|
}
|
|
253
280
|
}
|
|
254
|
-
//# sourceMappingURL=AdaptAutomationElement.js.map
|
package/dist/esm/cap-adapter.js
CHANGED
package/dist/esm/elements.js
CHANGED
package/dist/esm/iframe-url.js
CHANGED
package/dist/esm/index.js
CHANGED
|
@@ -19,6 +19,22 @@ export { configure, resetConfig };
|
|
|
19
19
|
// Re-export custom elements
|
|
20
20
|
export { AdaptAutomationElement } from "./AdaptAutomationElement.js";
|
|
21
21
|
export { AdaptCapElement } from "./AdaptCapElement.js";
|
|
22
|
+
/**
|
|
23
|
+
* Clear persisted session state for a given automation ID.
|
|
24
|
+
* Use this to force a fresh session on next page load.
|
|
25
|
+
*
|
|
26
|
+
* @param automationId - The automation ID whose state to clear
|
|
27
|
+
* @param storage - Which storage to clear: 'session' (default), 'local', or 'both'
|
|
28
|
+
*/
|
|
29
|
+
export function clearPersistedState(automationId, storage = "both") {
|
|
30
|
+
const key = `mb_adapt_${automationId}`;
|
|
31
|
+
if (storage === "session" || storage === "both") {
|
|
32
|
+
sessionStorage.removeItem(key);
|
|
33
|
+
}
|
|
34
|
+
if (storage === "local" || storage === "both") {
|
|
35
|
+
localStorage.removeItem(key);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
22
38
|
/**
|
|
23
39
|
* Default CSS styles with CSS Custom Properties for theming.
|
|
24
40
|
*/
|
|
@@ -1021,6 +1037,8 @@ export class AdaptWebClient {
|
|
|
1021
1037
|
}
|
|
1022
1038
|
// Reset for next drag
|
|
1023
1039
|
unclampedSplit = this.splitPercentage;
|
|
1040
|
+
// Persist the new split position
|
|
1041
|
+
this.saveState();
|
|
1024
1042
|
};
|
|
1025
1043
|
this.mouseMoveHandler = handleMouseMove;
|
|
1026
1044
|
this.mouseUpHandler = handleMouseUp;
|
|
@@ -1098,6 +1116,13 @@ export class AdaptWebClient {
|
|
|
1098
1116
|
if (sessionJson.status === "STATUS_COMPLETED" && !sessionJson.fork) {
|
|
1099
1117
|
this.handleSessionComplete();
|
|
1100
1118
|
}
|
|
1119
|
+
// On any session-level terminal status, clear persisted state
|
|
1120
|
+
if (!sessionJson.fork &&
|
|
1121
|
+
(sessionJson.status === "STATUS_COMPLETED" ||
|
|
1122
|
+
sessionJson.status === "STATUS_STOPPED" ||
|
|
1123
|
+
sessionJson.status === "STATUS_ERRORED")) {
|
|
1124
|
+
this.clearState();
|
|
1125
|
+
}
|
|
1101
1126
|
if (this.options.onSession) {
|
|
1102
1127
|
this.options.onSession(sessionJson.status || "STATUS_UNSPECIFIED", sessionJson.fork);
|
|
1103
1128
|
}
|
|
@@ -1106,6 +1131,12 @@ export class AdaptWebClient {
|
|
|
1106
1131
|
if (this.options.onOutput) {
|
|
1107
1132
|
handlers.onOutput = this.options.onOutput;
|
|
1108
1133
|
}
|
|
1134
|
+
// Try to restore persisted session (skip when sessionToken is provided — server manages lifecycle)
|
|
1135
|
+
if (!this.options.sessionToken && this.resolvePersistOptions()) {
|
|
1136
|
+
const restored = await this.tryRestoreSession(handlers);
|
|
1137
|
+
if (restored)
|
|
1138
|
+
return;
|
|
1139
|
+
}
|
|
1109
1140
|
// Priority: sessionToken > challengeToken > inheritToken/inheritFrom > authToken
|
|
1110
1141
|
if (this.options.sessionToken) {
|
|
1111
1142
|
// Use pre-created session token directly (server-side scenario)
|
|
@@ -1154,6 +1185,8 @@ export class AdaptWebClient {
|
|
|
1154
1185
|
result = await this.client.run(runOptions);
|
|
1155
1186
|
}
|
|
1156
1187
|
this.sessionToken = result.sessionToken;
|
|
1188
|
+
this.sessionExpiresAt = result.expiresAt;
|
|
1189
|
+
this.saveState();
|
|
1157
1190
|
}
|
|
1158
1191
|
}
|
|
1159
1192
|
/**
|
|
@@ -1198,12 +1231,220 @@ export class AdaptWebClient {
|
|
|
1198
1231
|
this.capWidgetInstance = null;
|
|
1199
1232
|
}
|
|
1200
1233
|
}
|
|
1234
|
+
// --- Persistence helpers ---
|
|
1235
|
+
resolvePersistOptions() {
|
|
1236
|
+
const p = this.options.persist;
|
|
1237
|
+
if (!p)
|
|
1238
|
+
return null;
|
|
1239
|
+
if (p === true)
|
|
1240
|
+
return { storage: "session", ttl: 3600 };
|
|
1241
|
+
return { storage: p.storage ?? "session", ttl: p.ttl ?? 3600 };
|
|
1242
|
+
}
|
|
1243
|
+
getStorageKey() {
|
|
1244
|
+
return `mb_adapt_${this.options.id}`;
|
|
1245
|
+
}
|
|
1246
|
+
getStorage() {
|
|
1247
|
+
const opts = this.resolvePersistOptions();
|
|
1248
|
+
if (!opts)
|
|
1249
|
+
return null;
|
|
1250
|
+
return opts.storage === "local" ? localStorage : sessionStorage;
|
|
1251
|
+
}
|
|
1252
|
+
saveState() {
|
|
1253
|
+
const storage = this.getStorage();
|
|
1254
|
+
if (!storage || !this.sessionToken)
|
|
1255
|
+
return;
|
|
1256
|
+
const opts = this.resolvePersistOptions();
|
|
1257
|
+
const state = {
|
|
1258
|
+
v: 1,
|
|
1259
|
+
token: this.sessionToken,
|
|
1260
|
+
expiresAt: this.sessionExpiresAt
|
|
1261
|
+
? this.sessionExpiresAt.toISOString()
|
|
1262
|
+
: null,
|
|
1263
|
+
savedAt: Date.now(),
|
|
1264
|
+
ttl: opts.ttl,
|
|
1265
|
+
mainUrl: this.mainUrl,
|
|
1266
|
+
mainToken: this.mainToken,
|
|
1267
|
+
currentFork: this.currentFork
|
|
1268
|
+
? {
|
|
1269
|
+
url: this.currentFork.url,
|
|
1270
|
+
token: this.currentFork.token,
|
|
1271
|
+
fork: this.currentFork.fork,
|
|
1272
|
+
depth: this.currentFork.depth,
|
|
1273
|
+
time: this.currentFork.time,
|
|
1274
|
+
completed: this.currentFork.completed,
|
|
1275
|
+
}
|
|
1276
|
+
: null,
|
|
1277
|
+
forkQueue: this.forkQueue.map((f) => ({
|
|
1278
|
+
url: f.url,
|
|
1279
|
+
token: f.token,
|
|
1280
|
+
fork: f.fork,
|
|
1281
|
+
depth: f.depth,
|
|
1282
|
+
time: f.time,
|
|
1283
|
+
completed: f.completed,
|
|
1284
|
+
})),
|
|
1285
|
+
forkDisplayMode: this.forkDisplay.mode,
|
|
1286
|
+
splitPercentage: this.splitPercentage,
|
|
1287
|
+
};
|
|
1288
|
+
storage.setItem(this.getStorageKey(), JSON.stringify(state));
|
|
1289
|
+
}
|
|
1290
|
+
loadState() {
|
|
1291
|
+
const storage = this.getStorage();
|
|
1292
|
+
if (!storage)
|
|
1293
|
+
return null;
|
|
1294
|
+
const raw = storage.getItem(this.getStorageKey());
|
|
1295
|
+
if (!raw)
|
|
1296
|
+
return null;
|
|
1297
|
+
let state;
|
|
1298
|
+
try {
|
|
1299
|
+
state = JSON.parse(raw);
|
|
1300
|
+
}
|
|
1301
|
+
catch {
|
|
1302
|
+
this.clearState();
|
|
1303
|
+
return null;
|
|
1304
|
+
}
|
|
1305
|
+
// Version check
|
|
1306
|
+
if (state.v !== 1) {
|
|
1307
|
+
this.clearState();
|
|
1308
|
+
return null;
|
|
1309
|
+
}
|
|
1310
|
+
const now = Date.now();
|
|
1311
|
+
const leeway = 30000; // 30 seconds
|
|
1312
|
+
// TTL check
|
|
1313
|
+
if (now - state.savedAt > state.ttl * 1000 + leeway) {
|
|
1314
|
+
this.clearState();
|
|
1315
|
+
return null;
|
|
1316
|
+
}
|
|
1317
|
+
// Session expiresAt check
|
|
1318
|
+
if (state.expiresAt) {
|
|
1319
|
+
const expires = new Date(state.expiresAt).getTime();
|
|
1320
|
+
if (now > expires + leeway) {
|
|
1321
|
+
this.clearState();
|
|
1322
|
+
return null;
|
|
1323
|
+
}
|
|
1324
|
+
}
|
|
1325
|
+
return state;
|
|
1326
|
+
}
|
|
1327
|
+
clearState() {
|
|
1328
|
+
const storage = this.getStorage();
|
|
1329
|
+
if (!storage)
|
|
1330
|
+
return;
|
|
1331
|
+
storage.removeItem(this.getStorageKey());
|
|
1332
|
+
}
|
|
1333
|
+
async tryRestoreSession(handlers) {
|
|
1334
|
+
const state = this.loadState();
|
|
1335
|
+
if (!state)
|
|
1336
|
+
return false;
|
|
1337
|
+
// Restore state and show iframes IMMEDIATELY — don't wait for subscribe
|
|
1338
|
+
this.sessionToken = state.token;
|
|
1339
|
+
this.sessionExpiresAt = state.expiresAt
|
|
1340
|
+
? new Date(state.expiresAt)
|
|
1341
|
+
: undefined;
|
|
1342
|
+
this.mainUrl = state.mainUrl;
|
|
1343
|
+
this.mainToken = state.mainToken;
|
|
1344
|
+
this.forkQueue = state.forkQueue;
|
|
1345
|
+
this.currentFork = state.currentFork;
|
|
1346
|
+
// Restore UI state if fork display mode is consistent with current options
|
|
1347
|
+
if (state.forkDisplayMode === this.forkDisplay.mode) {
|
|
1348
|
+
if (this.forkDisplay.mode === "side-by-side") {
|
|
1349
|
+
this.splitPercentage = state.splitPercentage;
|
|
1350
|
+
}
|
|
1351
|
+
// Dialog collapsed state is already captured by currentFork/forkQueue
|
|
1352
|
+
}
|
|
1353
|
+
if (this.mainUrl && this.mainIframe) {
|
|
1354
|
+
const newSrc = getIframeSrc(this.mainUrl, this.mainToken);
|
|
1355
|
+
if (this.mainIframe.src !== newSrc) {
|
|
1356
|
+
this.mainIframe.src = newSrc;
|
|
1357
|
+
}
|
|
1358
|
+
this.showIframe(this.mainIframe);
|
|
1359
|
+
}
|
|
1360
|
+
if (this.currentFork && this.forkIframe) {
|
|
1361
|
+
this.updateForkIframe();
|
|
1362
|
+
}
|
|
1363
|
+
// Update visibility for the current display mode — must run even when
|
|
1364
|
+
// currentFork is null so that collapsed-state UI (expand buttons) renders
|
|
1365
|
+
if (this.forkDisplay.mode === "dialog") {
|
|
1366
|
+
this.updateDialogVisibility();
|
|
1367
|
+
}
|
|
1368
|
+
else {
|
|
1369
|
+
this.updateSideBySideVisibility();
|
|
1370
|
+
}
|
|
1371
|
+
// Now reconnect the stream — if it fails, reset everything and fall through
|
|
1372
|
+
try {
|
|
1373
|
+
await this.client.subscribe(state.token, handlers);
|
|
1374
|
+
}
|
|
1375
|
+
catch {
|
|
1376
|
+
this.clearState();
|
|
1377
|
+
this.sessionToken = null;
|
|
1378
|
+
this.sessionExpiresAt = undefined;
|
|
1379
|
+
this.mainUrl = null;
|
|
1380
|
+
this.mainToken = undefined;
|
|
1381
|
+
this.forkQueue = [];
|
|
1382
|
+
this.currentFork = null;
|
|
1383
|
+
if (this.mainIframe) {
|
|
1384
|
+
this.mainIframe.src = "about:blank";
|
|
1385
|
+
this.mainIframe.classList.remove("mb-adapt__iframe--visible");
|
|
1386
|
+
}
|
|
1387
|
+
if (this.forkIframe) {
|
|
1388
|
+
this.forkIframe.src = "about:blank";
|
|
1389
|
+
this.forkIframe.classList.remove("mb-adapt__iframe--visible");
|
|
1390
|
+
this.forkIframe.classList.add("mb-adapt__iframe--hidden");
|
|
1391
|
+
}
|
|
1392
|
+
if (this.forkDisplay.mode === "side-by-side") {
|
|
1393
|
+
this.updateSideBySideVisibility();
|
|
1394
|
+
}
|
|
1395
|
+
else {
|
|
1396
|
+
this.updateDialogVisibility();
|
|
1397
|
+
}
|
|
1398
|
+
return false;
|
|
1399
|
+
}
|
|
1400
|
+
return true;
|
|
1401
|
+
}
|
|
1402
|
+
/**
|
|
1403
|
+
* Clear persisted state, stop current session, and reinitialize fresh.
|
|
1404
|
+
*/
|
|
1405
|
+
async newSession() {
|
|
1406
|
+
this.clearState();
|
|
1407
|
+
// Stop current session best-effort
|
|
1408
|
+
if (this.sessionToken) {
|
|
1409
|
+
this.client.stop(this.sessionToken).catch(() => { });
|
|
1410
|
+
}
|
|
1411
|
+
await this.client.unsubscribe();
|
|
1412
|
+
// Reset internal state
|
|
1413
|
+
this.mainUrl = null;
|
|
1414
|
+
this.mainToken = undefined;
|
|
1415
|
+
this.forkQueue = [];
|
|
1416
|
+
this.currentFork = null;
|
|
1417
|
+
this.sessionToken = null;
|
|
1418
|
+
this.sessionExpiresAt = undefined;
|
|
1419
|
+
this.lastForkActive = null;
|
|
1420
|
+
// Reset iframes
|
|
1421
|
+
if (this.mainIframe) {
|
|
1422
|
+
this.mainIframe.src = "about:blank";
|
|
1423
|
+
this.mainIframe.classList.remove("mb-adapt__iframe--visible");
|
|
1424
|
+
}
|
|
1425
|
+
if (this.forkIframe) {
|
|
1426
|
+
this.forkIframe.src = "about:blank";
|
|
1427
|
+
this.forkIframe.classList.remove("mb-adapt__iframe--visible");
|
|
1428
|
+
this.forkIframe.classList.add("mb-adapt__iframe--hidden");
|
|
1429
|
+
}
|
|
1430
|
+
// Reset visual state
|
|
1431
|
+
this.removeStoppedPlaceholder();
|
|
1432
|
+
if (this.forkDisplay.mode === "side-by-side") {
|
|
1433
|
+
this.updateSideBySideVisibility();
|
|
1434
|
+
}
|
|
1435
|
+
else {
|
|
1436
|
+
this.updateDialogVisibility();
|
|
1437
|
+
}
|
|
1438
|
+
// Reinitialize
|
|
1439
|
+
await this.init();
|
|
1440
|
+
}
|
|
1201
1441
|
async destroy() {
|
|
1202
1442
|
this.destroyed = true;
|
|
1203
1443
|
// Clean up Cap.js widget if present
|
|
1204
1444
|
this.destroyCapWidget();
|
|
1205
|
-
//
|
|
1206
|
-
|
|
1445
|
+
// Stop session on destroy — but NOT when persist has saved state (session survives page refresh).
|
|
1446
|
+
// If persisted state was cleared (explicit stop, terminal status), stop() is still called.
|
|
1447
|
+
if (this.sessionToken && !this.loadState()) {
|
|
1207
1448
|
this.client.stop(this.sessionToken).catch(() => { });
|
|
1208
1449
|
}
|
|
1209
1450
|
await this.client.unsubscribe();
|
|
@@ -1255,10 +1496,12 @@ export class AdaptWebClient {
|
|
|
1255
1496
|
const fork = msg.fork || "";
|
|
1256
1497
|
if (msg.stopped) {
|
|
1257
1498
|
this.handleStoppedMessage(fork);
|
|
1499
|
+
this.saveState();
|
|
1258
1500
|
return;
|
|
1259
1501
|
}
|
|
1260
1502
|
if (msg.done) {
|
|
1261
1503
|
this.handleDoneMessage(fork);
|
|
1504
|
+
this.saveState();
|
|
1262
1505
|
return;
|
|
1263
1506
|
}
|
|
1264
1507
|
if (!msg.url)
|
|
@@ -1271,6 +1514,7 @@ export class AdaptWebClient {
|
|
|
1271
1514
|
// Fork URL - should open dialog
|
|
1272
1515
|
this.handleForkUrl(msg.url, msg.token, fork);
|
|
1273
1516
|
}
|
|
1517
|
+
this.saveState();
|
|
1274
1518
|
}
|
|
1275
1519
|
handleSessionComplete() {
|
|
1276
1520
|
// Clear all forks and minimize to show only main frame
|
|
@@ -1400,6 +1644,7 @@ export class AdaptWebClient {
|
|
|
1400
1644
|
else {
|
|
1401
1645
|
this.updateSideBySideVisibility();
|
|
1402
1646
|
}
|
|
1647
|
+
this.saveState();
|
|
1403
1648
|
}
|
|
1404
1649
|
updateMainIframe() {
|
|
1405
1650
|
if (!this.rootElement || !this.mainUrl || !this.mainIframe)
|
|
@@ -1510,6 +1755,7 @@ export class AdaptWebClient {
|
|
|
1510
1755
|
this.splitPercentage = 50;
|
|
1511
1756
|
}
|
|
1512
1757
|
this.updateSideBySideVisibility();
|
|
1758
|
+
this.saveState();
|
|
1513
1759
|
});
|
|
1514
1760
|
this.wrapperElement.appendChild(this.mainFrameElement);
|
|
1515
1761
|
this.wrapperElement.appendChild(this.forkFrameElement);
|
|
@@ -1682,6 +1928,7 @@ export class AdaptWebClient {
|
|
|
1682
1928
|
this.currentFork = null;
|
|
1683
1929
|
this.updateDialogVisibility();
|
|
1684
1930
|
}
|
|
1931
|
+
this.saveState();
|
|
1685
1932
|
}
|
|
1686
1933
|
handleForkExit() {
|
|
1687
1934
|
if (!this.currentFork)
|
|
@@ -1711,6 +1958,7 @@ export class AdaptWebClient {
|
|
|
1711
1958
|
this.updateDialogVisibility();
|
|
1712
1959
|
}
|
|
1713
1960
|
}
|
|
1961
|
+
this.saveState();
|
|
1714
1962
|
}
|
|
1715
1963
|
createDialogStructure() {
|
|
1716
1964
|
if (this.mainContainer)
|
|
@@ -1849,4 +2097,3 @@ export class AdaptWebClient {
|
|
|
1849
2097
|
AdaptWebClient.COLLAPSE_THRESHOLD = 15;
|
|
1850
2098
|
AdaptWebClient.RESPONSIVE_BREAKPOINT = 900; // px - below this, auto-collapse to single view
|
|
1851
2099
|
AdaptWebClient.DIALOG_FULLSCREEN_BREAKPOINT = 639; // px - at or below this, dialog is fullscreen
|
|
1852
|
-
//# sourceMappingURL=index.js.map
|
package/dist/esm/types.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AdaptWebClientOptions, CapWidgetOptions, Output, SignalValue, StatusJson } from "./types.js";
|
|
1
|
+
import type { AdaptWebClientOptions, CapWidgetOptions, Output, PersistOptions, SignalValue, StatusJson } from "./types.js";
|
|
2
2
|
/**
|
|
3
3
|
* `<adapt-automation>` custom element for embedding Adapt automations.
|
|
4
4
|
*
|
|
@@ -33,6 +33,7 @@ export declare class AdaptAutomationElement extends BaseElement {
|
|
|
33
33
|
} | undefined;
|
|
34
34
|
classNames: AdaptWebClientOptions["classNames"];
|
|
35
35
|
styles: Partial<CSSStyleDeclaration> | undefined;
|
|
36
|
+
persistOptions: PersistOptions | undefined;
|
|
36
37
|
onSessionCallback: ((status: StatusJson, fork?: string) => void) | undefined;
|
|
37
38
|
onOutputCallback: ((output: Output) => void) | undefined;
|
|
38
39
|
onForkActiveCallback: ((active: boolean) => void) | undefined;
|
|
@@ -48,6 +49,12 @@ export declare class AdaptAutomationElement extends BaseElement {
|
|
|
48
49
|
set dialogBackdropClose(v: boolean);
|
|
49
50
|
get dialogResizeToContent(): boolean;
|
|
50
51
|
set dialogResizeToContent(v: boolean);
|
|
52
|
+
get persist(): boolean;
|
|
53
|
+
set persist(v: boolean);
|
|
54
|
+
/**
|
|
55
|
+
* Clear persisted state, stop current session, and reinitialize fresh.
|
|
56
|
+
*/
|
|
57
|
+
newSession(): Promise<void>;
|
|
51
58
|
connectedCallback(): void;
|
|
52
59
|
disconnectedCallback(): void;
|
|
53
60
|
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ declare global {
|
|
|
6
6
|
import { configure, resetConfig } from "@mochabug/adapt-core";
|
|
7
7
|
import { createConnectClient } from "@mochabug/adapt-core/connect";
|
|
8
8
|
import type { AdaptWebClientOptions } from "./types.js";
|
|
9
|
-
export type { AdaptWebClientOptions, CapWidgetI18n, CapWidgetOptions, ChallengeInfo, ForkDisplay, Output, RedeemedChallenge, SignalValue, StatusJson, } from "./types.js";
|
|
9
|
+
export type { AdaptWebClientOptions, CapWidgetI18n, CapWidgetOptions, ChallengeInfo, ForkDisplay, Output, PersistOptions, RedeemedChallenge, SignalValue, StatusJson, } from "./types.js";
|
|
10
10
|
export { AdaptCapWidget, type AdaptCapWidgetOptions, } from "./AdaptCapWidget.js";
|
|
11
11
|
export { createChallenge, redeemChallenge } from "./cap-adapter.js";
|
|
12
12
|
export type { SignalData } from "@mochabug/adapt-core";
|
|
@@ -27,6 +27,14 @@ export interface AdaptAutoResizingMessage {
|
|
|
27
27
|
type: "adapt-autoResizing";
|
|
28
28
|
autoResizing: boolean;
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* Clear persisted session state for a given automation ID.
|
|
32
|
+
* Use this to force a fresh session on next page load.
|
|
33
|
+
*
|
|
34
|
+
* @param automationId - The automation ID whose state to clear
|
|
35
|
+
* @param storage - Which storage to clear: 'session' (default), 'local', or 'both'
|
|
36
|
+
*/
|
|
37
|
+
export declare function clearPersistedState(automationId: string, storage?: "session" | "local" | "both"): void;
|
|
30
38
|
/**
|
|
31
39
|
* Browser client for rendering Adapt automation sessions in iframes.
|
|
32
40
|
*
|
|
@@ -73,6 +81,7 @@ export declare class AdaptWebClient {
|
|
|
73
81
|
private forkDisplay;
|
|
74
82
|
private destroyed;
|
|
75
83
|
private lastForkActive;
|
|
84
|
+
private sessionExpiresAt;
|
|
76
85
|
private stoppedPlaceholder;
|
|
77
86
|
private capWidgetInstance;
|
|
78
87
|
constructor(options: AdaptWebClientOptions);
|
|
@@ -126,6 +135,17 @@ export declare class AdaptWebClient {
|
|
|
126
135
|
* Destroy the Cap.js widget instance if present.
|
|
127
136
|
*/
|
|
128
137
|
private destroyCapWidget;
|
|
138
|
+
private resolvePersistOptions;
|
|
139
|
+
private getStorageKey;
|
|
140
|
+
private getStorage;
|
|
141
|
+
private saveState;
|
|
142
|
+
private loadState;
|
|
143
|
+
private clearState;
|
|
144
|
+
private tryRestoreSession;
|
|
145
|
+
/**
|
|
146
|
+
* Clear persisted state, stop current session, and reinitialize fresh.
|
|
147
|
+
*/
|
|
148
|
+
newSession(): Promise<void>;
|
|
129
149
|
destroy(): Promise<void>;
|
|
130
150
|
private onUrl;
|
|
131
151
|
private handleSessionComplete;
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
import type { Output, SignalValue, StatusJson } from "@mochabug/adapt-core";
|
|
2
2
|
export type { Output, SignalValue, StatusJson } from "@mochabug/adapt-core";
|
|
3
|
+
/**
|
|
4
|
+
* Options for session persistence across page refreshes.
|
|
5
|
+
*/
|
|
6
|
+
export interface PersistOptions {
|
|
7
|
+
/** Storage type: 'session' (default) uses sessionStorage, 'local' uses localStorage. */
|
|
8
|
+
storage?: "session" | "local";
|
|
9
|
+
/** Max TTL in seconds (default: 3600). Capped by the session's own expiresAt. */
|
|
10
|
+
ttl?: number;
|
|
11
|
+
}
|
|
3
12
|
/**
|
|
4
13
|
* Discriminated union for fork display configuration.
|
|
5
14
|
*
|
|
@@ -374,4 +383,16 @@ export interface AdaptWebClientOptions {
|
|
|
374
383
|
* ```
|
|
375
384
|
*/
|
|
376
385
|
styles?: Partial<CSSStyleDeclaration>;
|
|
386
|
+
/**
|
|
387
|
+
* Enable session persistence across page refreshes.
|
|
388
|
+
*
|
|
389
|
+
* When enabled, the session token and URL state are stored in browser storage.
|
|
390
|
+
* On page load, the client reconnects to the existing session instead of creating a new one.
|
|
391
|
+
*
|
|
392
|
+
* - `true` — use sessionStorage with 3600s TTL
|
|
393
|
+
* - `PersistOptions` — customize storage type and TTL
|
|
394
|
+
*
|
|
395
|
+
* @default undefined (disabled)
|
|
396
|
+
*/
|
|
397
|
+
persist?: boolean | PersistOptions;
|
|
377
398
|
}
|