@mochabug/adapt-web 1.0.0-rc42 → 1.0.0-rc44
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/index.js +339 -112
- package/dist/esm/index.js.map +1 -1
- package/dist/types/index.d.ts +8 -0
- package/dist/types/types.d.ts +6 -0
- package/dist/umd/adapt-web.js +713 -219
- package/dist/umd/adapt-web.min.js +183 -72
- package/package.json +3 -3
package/dist/esm/index.js
CHANGED
|
@@ -36,9 +36,14 @@ const DEFAULT_STYLES = `
|
|
|
36
36
|
--mb-adapt-dialog-z: 1000;
|
|
37
37
|
--mb-adapt-dialog-width: 80%;
|
|
38
38
|
--mb-adapt-dialog-height: 80%;
|
|
39
|
-
--mb-adapt-drag-handle-width:
|
|
40
|
-
--mb-adapt-drag-handle-color: #
|
|
41
|
-
--mb-adapt-drag-handle-hover: #
|
|
39
|
+
--mb-adapt-drag-handle-width: 8px;
|
|
40
|
+
--mb-adapt-drag-handle-color: #cbd5e1;
|
|
41
|
+
--mb-adapt-drag-handle-hover: #94a3b8;
|
|
42
|
+
--mb-adapt-toolbar-height: 32px;
|
|
43
|
+
--mb-adapt-toolbar-bg: rgba(249, 250, 251, 0.85);
|
|
44
|
+
--mb-adapt-toolbar-border: #e5e7eb;
|
|
45
|
+
--mb-adapt-toolbar-color: #6b7280;
|
|
46
|
+
--mb-adapt-toolbar-btn-hover: #e5e7eb;
|
|
42
47
|
--mb-adapt-banner-height: 40px;
|
|
43
48
|
--mb-adapt-banner-bg: #f9fafb;
|
|
44
49
|
--mb-adapt-banner-border: #e5e7eb;
|
|
@@ -70,8 +75,12 @@ const DEFAULT_STYLES = `
|
|
|
70
75
|
--mb-adapt-dialog-bg: #1f2937;
|
|
71
76
|
--mb-adapt-banner-bg: #111827;
|
|
72
77
|
--mb-adapt-banner-border: #374151;
|
|
73
|
-
--mb-adapt-drag-handle-color: #
|
|
74
|
-
--mb-adapt-drag-handle-hover: #
|
|
78
|
+
--mb-adapt-drag-handle-color: #475569;
|
|
79
|
+
--mb-adapt-drag-handle-hover: #64748b;
|
|
80
|
+
--mb-adapt-toolbar-bg: rgba(17, 24, 39, 0.85);
|
|
81
|
+
--mb-adapt-toolbar-border: #374151;
|
|
82
|
+
--mb-adapt-toolbar-color: #9ca3af;
|
|
83
|
+
--mb-adapt-toolbar-btn-hover: #374151;
|
|
75
84
|
--mb-adapt-button-color: #e5e7eb;
|
|
76
85
|
--mb-adapt-button-hover-bg: #374151;
|
|
77
86
|
|
|
@@ -121,12 +130,6 @@ const DEFAULT_STYLES = `
|
|
|
121
130
|
transition: opacity 0.1s ease-out;
|
|
122
131
|
}
|
|
123
132
|
|
|
124
|
-
/* When inside main-container (dialog mode), allow iframe to size itself */
|
|
125
|
-
.mb-adapt__main-container .mb-adapt__iframe {
|
|
126
|
-
height: auto;
|
|
127
|
-
min-height: 300px;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
133
|
.mb-adapt__iframe--visible {
|
|
131
134
|
opacity: 1;
|
|
132
135
|
}
|
|
@@ -143,11 +146,32 @@ const DEFAULT_STYLES = `
|
|
|
143
146
|
background-color: var(--mb-adapt-drag-handle-color);
|
|
144
147
|
cursor: ew-resize;
|
|
145
148
|
z-index: 10;
|
|
146
|
-
transition: background-color 0.2s, left 0.15s ease-out;
|
|
149
|
+
transition: background-color 0.2s, left 0.15s ease-out, box-shadow 0.2s;
|
|
150
|
+
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.04);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.mb-adapt__drag-handle::after {
|
|
154
|
+
content: '';
|
|
155
|
+
position: absolute;
|
|
156
|
+
top: 50%;
|
|
157
|
+
left: 50%;
|
|
158
|
+
transform: translate(-50%, -50%);
|
|
159
|
+
width: 4px;
|
|
160
|
+
height: 24px;
|
|
161
|
+
background-image: radial-gradient(circle, currentColor 1px, transparent 1px);
|
|
162
|
+
background-size: 4px 6px;
|
|
163
|
+
background-position: center;
|
|
164
|
+
opacity: 0.5;
|
|
165
|
+
color: var(--mb-adapt-drag-handle-hover);
|
|
147
166
|
}
|
|
148
167
|
|
|
149
168
|
.mb-adapt__drag-handle:hover {
|
|
150
169
|
background-color: var(--mb-adapt-drag-handle-hover);
|
|
170
|
+
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.mb-adapt__drag-handle:hover::after {
|
|
174
|
+
opacity: 0.8;
|
|
151
175
|
}
|
|
152
176
|
|
|
153
177
|
.mb-adapt__drag-overlay {
|
|
@@ -228,43 +252,42 @@ const DEFAULT_STYLES = `
|
|
|
228
252
|
position: absolute;
|
|
229
253
|
top: 50%;
|
|
230
254
|
transform: translateY(-50%);
|
|
231
|
-
background: linear-gradient(180deg, rgba(255,255,255,0.98) 0%, rgba(
|
|
232
|
-
border:
|
|
233
|
-
color: #
|
|
255
|
+
background: linear-gradient(180deg, rgba(255,255,255,0.98) 0%, rgba(241,245,249,0.98) 100%);
|
|
256
|
+
border: 1px solid rgba(0, 0, 0, 0.08);
|
|
257
|
+
color: #475569;
|
|
234
258
|
cursor: pointer;
|
|
235
|
-
width:
|
|
236
|
-
height:
|
|
259
|
+
width: 22px;
|
|
260
|
+
height: 64px;
|
|
237
261
|
display: none;
|
|
238
262
|
align-items: center;
|
|
239
263
|
justify-content: center;
|
|
240
264
|
z-index: 100;
|
|
241
265
|
transition: all 0.2s ease-out;
|
|
242
|
-
font-size:
|
|
266
|
+
font-size: 16px;
|
|
267
|
+
font-weight: 600;
|
|
243
268
|
line-height: 1;
|
|
244
269
|
padding: 0;
|
|
245
270
|
box-shadow:
|
|
246
|
-
0 2px
|
|
247
|
-
0 1px
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
backdrop-filter: blur(
|
|
251
|
-
-webkit-backdrop-filter: blur(8px);
|
|
271
|
+
0 2px 12px rgba(0, 0, 0, 0.14),
|
|
272
|
+
0 1px 4px rgba(0, 0, 0, 0.10);
|
|
273
|
+
border-radius: 6px;
|
|
274
|
+
backdrop-filter: blur(12px);
|
|
275
|
+
-webkit-backdrop-filter: blur(12px);
|
|
252
276
|
}
|
|
253
277
|
|
|
254
278
|
.mb-adapt__expand-button:hover {
|
|
255
|
-
background: linear-gradient(180deg, rgba(255,255,255,1) 0%, rgba(
|
|
256
|
-
color: #
|
|
257
|
-
transform: translateY(-50%) scale(1.
|
|
279
|
+
background: linear-gradient(180deg, rgba(255,255,255,1) 0%, rgba(226,232,240,1) 100%);
|
|
280
|
+
color: #1e293b;
|
|
281
|
+
transform: translateY(-50%) scale(1.04);
|
|
258
282
|
box-shadow:
|
|
259
|
-
0 4px
|
|
260
|
-
0 2px
|
|
261
|
-
inset 0 1px 0 rgba(255, 255, 255, 1);
|
|
283
|
+
0 4px 16px rgba(0, 0, 0, 0.18),
|
|
284
|
+
0 2px 6px rgba(0, 0, 0, 0.12);
|
|
262
285
|
}
|
|
263
286
|
|
|
264
287
|
.mb-adapt__expand-button:active {
|
|
265
|
-
transform: translateY(-50%) scale(0.
|
|
288
|
+
transform: translateY(-50%) scale(0.97);
|
|
266
289
|
box-shadow:
|
|
267
|
-
0 1px 4px rgba(0, 0, 0, 0.
|
|
290
|
+
0 1px 4px rgba(0, 0, 0, 0.10),
|
|
268
291
|
0 1px 2px rgba(0, 0, 0, 0.06);
|
|
269
292
|
}
|
|
270
293
|
|
|
@@ -276,83 +299,79 @@ const DEFAULT_STYLES = `
|
|
|
276
299
|
left: 0;
|
|
277
300
|
border-top-left-radius: 0;
|
|
278
301
|
border-bottom-left-radius: 0;
|
|
302
|
+
border-left: none;
|
|
279
303
|
box-shadow:
|
|
280
|
-
2px 2px
|
|
281
|
-
1px 1px
|
|
282
|
-
inset 0 1px 0 rgba(255, 255, 255, 0.8);
|
|
304
|
+
2px 2px 12px rgba(0, 0, 0, 0.14),
|
|
305
|
+
1px 1px 4px rgba(0, 0, 0, 0.10);
|
|
283
306
|
}
|
|
284
307
|
|
|
285
308
|
.mb-adapt__expand-button--left:hover {
|
|
286
309
|
box-shadow:
|
|
287
|
-
3px 4px
|
|
288
|
-
2px 2px
|
|
289
|
-
inset 0 1px 0 rgba(255, 255, 255, 1);
|
|
310
|
+
3px 4px 16px rgba(0, 0, 0, 0.18),
|
|
311
|
+
2px 2px 6px rgba(0, 0, 0, 0.12);
|
|
290
312
|
}
|
|
291
313
|
|
|
292
314
|
.mb-adapt__expand-button--right {
|
|
293
315
|
right: 0;
|
|
294
316
|
border-top-right-radius: 0;
|
|
295
317
|
border-bottom-right-radius: 0;
|
|
318
|
+
border-right: none;
|
|
296
319
|
box-shadow:
|
|
297
|
-
-2px 2px
|
|
298
|
-
-1px 1px
|
|
299
|
-
inset 0 1px 0 rgba(255, 255, 255, 0.8);
|
|
320
|
+
-2px 2px 12px rgba(0, 0, 0, 0.14),
|
|
321
|
+
-1px 1px 4px rgba(0, 0, 0, 0.10);
|
|
300
322
|
}
|
|
301
323
|
|
|
302
324
|
.mb-adapt__expand-button--right:hover {
|
|
303
325
|
box-shadow:
|
|
304
|
-
-3px 4px
|
|
305
|
-
-2px 2px
|
|
306
|
-
inset 0 1px 0 rgba(255, 255, 255, 1);
|
|
326
|
+
-3px 4px 16px rgba(0, 0, 0, 0.18),
|
|
327
|
+
-2px 2px 6px rgba(0, 0, 0, 0.12);
|
|
307
328
|
}
|
|
308
329
|
|
|
309
330
|
.mb-adapt__expand-button--dialog {
|
|
310
331
|
left: 50%;
|
|
311
332
|
top: 0;
|
|
312
333
|
transform: translateX(-50%);
|
|
313
|
-
width:
|
|
314
|
-
height:
|
|
334
|
+
width: 64px;
|
|
335
|
+
height: 24px;
|
|
315
336
|
font-size: 16px;
|
|
316
|
-
line-height:
|
|
337
|
+
line-height: 24px;
|
|
317
338
|
vertical-align: middle;
|
|
318
339
|
text-align: center;
|
|
319
|
-
border-radius:
|
|
340
|
+
border-radius: 8px;
|
|
320
341
|
border-top-left-radius: 0;
|
|
321
342
|
border-top-right-radius: 0;
|
|
343
|
+
border-top: none;
|
|
322
344
|
box-shadow:
|
|
323
|
-
0 3px
|
|
324
|
-
0 1px
|
|
325
|
-
inset 0 1px 0 rgba(255, 255, 255, 0.8);
|
|
345
|
+
0 3px 12px rgba(0, 0, 0, 0.14),
|
|
346
|
+
0 1px 4px rgba(0, 0, 0, 0.10);
|
|
326
347
|
}
|
|
327
348
|
|
|
328
349
|
.mb-adapt__expand-button--dialog:hover {
|
|
329
|
-
transform: translateX(-50%) scale(1.
|
|
350
|
+
transform: translateX(-50%) scale(1.04);
|
|
330
351
|
box-shadow:
|
|
331
|
-
0 5px
|
|
332
|
-
0 2px
|
|
333
|
-
inset 0 1px 0 rgba(255, 255, 255, 1);
|
|
352
|
+
0 5px 16px rgba(0, 0, 0, 0.18),
|
|
353
|
+
0 2px 6px rgba(0, 0, 0, 0.12);
|
|
334
354
|
}
|
|
335
355
|
|
|
336
356
|
.mb-adapt__expand-button--dialog:active {
|
|
337
|
-
transform: translateX(-50%) scale(0.
|
|
357
|
+
transform: translateX(-50%) scale(0.97);
|
|
338
358
|
}
|
|
339
359
|
|
|
340
360
|
.mb-adapt--dark .mb-adapt__expand-button {
|
|
341
|
-
background: linear-gradient(180deg, rgba(
|
|
342
|
-
color:
|
|
361
|
+
background: linear-gradient(180deg, rgba(51,65,85,0.98) 0%, rgba(30,41,59,0.98) 100%);
|
|
362
|
+
border-color: rgba(255, 255, 255, 0.1);
|
|
363
|
+
color: #cbd5e1;
|
|
343
364
|
box-shadow:
|
|
344
|
-
0 2px
|
|
345
|
-
0 1px
|
|
346
|
-
inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
|
365
|
+
0 2px 12px rgba(0, 0, 0, 0.35),
|
|
366
|
+
0 1px 4px rgba(0, 0, 0, 0.25);
|
|
347
367
|
}
|
|
348
368
|
|
|
349
369
|
.mb-adapt--dark .mb-adapt__expand-button:hover {
|
|
350
|
-
background: linear-gradient(180deg, rgba(
|
|
351
|
-
color: #
|
|
370
|
+
background: linear-gradient(180deg, rgba(71,85,105,1) 0%, rgba(51,65,85,1) 100%);
|
|
371
|
+
color: #f1f5f9;
|
|
352
372
|
box-shadow:
|
|
353
|
-
0 4px
|
|
354
|
-
0 2px
|
|
355
|
-
inset 0 1px 0 rgba(255, 255, 255, 0.15);
|
|
373
|
+
0 4px 16px rgba(0, 0, 0, 0.45),
|
|
374
|
+
0 2px 6px rgba(0, 0, 0, 0.35);
|
|
356
375
|
}
|
|
357
376
|
|
|
358
377
|
.mb-adapt__drag-handle--disabled {
|
|
@@ -360,14 +379,90 @@ const DEFAULT_STYLES = `
|
|
|
360
379
|
opacity: 0.3;
|
|
361
380
|
}
|
|
362
381
|
|
|
382
|
+
.mb-adapt__frame--has-toolbar {
|
|
383
|
+
display: flex;
|
|
384
|
+
flex-direction: column;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
.mb-adapt__frame--has-toolbar.mb-adapt__frame--hidden {
|
|
388
|
+
display: none;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.mb-adapt__frame--has-toolbar .mb-adapt__iframe {
|
|
392
|
+
flex: 1;
|
|
393
|
+
height: auto;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.mb-adapt__toolbar {
|
|
397
|
+
display: flex;
|
|
398
|
+
align-items: center;
|
|
399
|
+
justify-content: flex-end;
|
|
400
|
+
height: var(--mb-adapt-toolbar-height);
|
|
401
|
+
background: var(--mb-adapt-toolbar-bg);
|
|
402
|
+
border-bottom: 1px solid var(--mb-adapt-toolbar-border);
|
|
403
|
+
padding: 0 4px;
|
|
404
|
+
flex-shrink: 0;
|
|
405
|
+
backdrop-filter: blur(12px);
|
|
406
|
+
-webkit-backdrop-filter: blur(12px);
|
|
407
|
+
gap: 2px;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
.mb-adapt__toolbar-btn {
|
|
411
|
+
display: flex;
|
|
412
|
+
align-items: center;
|
|
413
|
+
justify-content: center;
|
|
414
|
+
width: 26px;
|
|
415
|
+
height: 26px;
|
|
416
|
+
border: none;
|
|
417
|
+
border-radius: 6px;
|
|
418
|
+
background: transparent;
|
|
419
|
+
color: var(--mb-adapt-toolbar-color);
|
|
420
|
+
cursor: pointer;
|
|
421
|
+
padding: 0;
|
|
422
|
+
transition: background-color 0.15s, color 0.15s;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
.mb-adapt__toolbar-btn:hover {
|
|
426
|
+
background: var(--mb-adapt-toolbar-btn-hover);
|
|
427
|
+
color: var(--mb-adapt-button-color);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
.mb-adapt__toolbar-btn svg {
|
|
431
|
+
width: 14px;
|
|
432
|
+
height: 14px;
|
|
433
|
+
stroke: currentColor;
|
|
434
|
+
stroke-width: 2;
|
|
435
|
+
fill: none;
|
|
436
|
+
stroke-linecap: round;
|
|
437
|
+
stroke-linejoin: round;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
.mb-adapt__toolbar-btn--exit:hover {
|
|
441
|
+
background: #fecaca;
|
|
442
|
+
color: #dc2626;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
.mb-adapt--dark .mb-adapt__toolbar-btn--exit:hover {
|
|
446
|
+
background: rgba(220, 38, 38, 0.2);
|
|
447
|
+
color: #fca5a5;
|
|
448
|
+
}
|
|
449
|
+
|
|
363
450
|
.mb-adapt__main-container {
|
|
364
451
|
position: relative;
|
|
452
|
+
display: flex;
|
|
453
|
+
flex-direction: column;
|
|
365
454
|
width: 100%;
|
|
366
|
-
flex:
|
|
455
|
+
flex: 1;
|
|
456
|
+
min-height: 0;
|
|
367
457
|
overflow: visible;
|
|
368
458
|
background: transparent;
|
|
369
459
|
}
|
|
370
460
|
|
|
461
|
+
.mb-adapt__main-container .mb-adapt__iframe {
|
|
462
|
+
flex: 1;
|
|
463
|
+
min-height: 0;
|
|
464
|
+
}
|
|
465
|
+
|
|
371
466
|
/* Responsive dialog - full screen on small viewports */
|
|
372
467
|
@media (max-width: 600px) {
|
|
373
468
|
.mb-adapt__dialog {
|
|
@@ -412,6 +507,21 @@ const DEFAULT_STYLES = `
|
|
|
412
507
|
cap-widget::part(attribution) {
|
|
413
508
|
display: none;
|
|
414
509
|
}
|
|
510
|
+
|
|
511
|
+
.mb-adapt__stopped-placeholder {
|
|
512
|
+
display: flex;
|
|
513
|
+
align-items: center;
|
|
514
|
+
justify-content: center;
|
|
515
|
+
width: 100%;
|
|
516
|
+
height: 100%;
|
|
517
|
+
min-height: 200px;
|
|
518
|
+
color: #6b7280;
|
|
519
|
+
font-family: system-ui, -apple-system, sans-serif;
|
|
520
|
+
font-size: 16px;
|
|
521
|
+
border-radius: var(--mb-adapt-border-radius);
|
|
522
|
+
background: var(--mb-adapt-banner-bg);
|
|
523
|
+
border: 1px solid var(--mb-adapt-banner-border);
|
|
524
|
+
}
|
|
415
525
|
`;
|
|
416
526
|
/**
|
|
417
527
|
* Browser client for rendering Adapt automation sessions in iframes.
|
|
@@ -438,6 +548,7 @@ export class AdaptWebClient {
|
|
|
438
548
|
this.dragHandleElement = null;
|
|
439
549
|
this.mainExpandButton = null;
|
|
440
550
|
this.forkExpandButton = null;
|
|
551
|
+
this.forkToolbarElement = null;
|
|
441
552
|
// Dialog elements
|
|
442
553
|
this.mainContainer = null;
|
|
443
554
|
this.dialogBackdrop = null;
|
|
@@ -450,6 +561,8 @@ export class AdaptWebClient {
|
|
|
450
561
|
this.messageHandler = null;
|
|
451
562
|
this.backdropClickHandler = null;
|
|
452
563
|
this.destroyed = false;
|
|
564
|
+
// Stopped placeholder element
|
|
565
|
+
this.stoppedPlaceholder = null;
|
|
453
566
|
// Cap.js widget instance (for PoW challenges)
|
|
454
567
|
this.capWidgetInstance = null;
|
|
455
568
|
this.options = {
|
|
@@ -648,6 +761,7 @@ export class AdaptWebClient {
|
|
|
648
761
|
this.dragHandleElement = null;
|
|
649
762
|
this.mainExpandButton = null;
|
|
650
763
|
this.forkExpandButton = null;
|
|
764
|
+
this.forkToolbarElement = null;
|
|
651
765
|
this.mainContainer = null;
|
|
652
766
|
this.dialogBackdrop = null;
|
|
653
767
|
this.dialogElement = null;
|
|
@@ -703,14 +817,10 @@ export class AdaptWebClient {
|
|
|
703
817
|
this.dialogBackdrop.removeEventListener("click", this.backdropClickHandler);
|
|
704
818
|
this.backdropClickHandler = null;
|
|
705
819
|
}
|
|
706
|
-
// Add new handler if enabled
|
|
820
|
+
// Add new handler if enabled (acts as minimize)
|
|
707
821
|
if (enabled) {
|
|
708
822
|
this.backdropClickHandler = () => {
|
|
709
|
-
|
|
710
|
-
this.forkQueue.unshift(this.currentFork);
|
|
711
|
-
}
|
|
712
|
-
this.currentFork = null;
|
|
713
|
-
this.updateDialogVisibility();
|
|
823
|
+
this.handleForkMinimize();
|
|
714
824
|
};
|
|
715
825
|
this.dialogBackdrop.addEventListener("click", this.backdropClickHandler);
|
|
716
826
|
}
|
|
@@ -1004,6 +1114,7 @@ export class AdaptWebClient {
|
|
|
1004
1114
|
this.dragHandleElement = null;
|
|
1005
1115
|
this.mainExpandButton = null;
|
|
1006
1116
|
this.forkExpandButton = null;
|
|
1117
|
+
this.forkToolbarElement = null;
|
|
1007
1118
|
this.mainContainer = null;
|
|
1008
1119
|
this.dialogBackdrop = null;
|
|
1009
1120
|
this.dialogElement = null;
|
|
@@ -1013,11 +1124,16 @@ export class AdaptWebClient {
|
|
|
1013
1124
|
this.resizeObserver = null;
|
|
1014
1125
|
this.messageHandler = null;
|
|
1015
1126
|
this.backdropClickHandler = null;
|
|
1127
|
+
this.stoppedPlaceholder = null;
|
|
1016
1128
|
}
|
|
1017
1129
|
onUrl(msg) {
|
|
1018
1130
|
if (this.destroyed)
|
|
1019
1131
|
return;
|
|
1020
1132
|
const fork = msg.fork || "";
|
|
1133
|
+
if (msg.stopped) {
|
|
1134
|
+
this.handleStoppedMessage(fork);
|
|
1135
|
+
return;
|
|
1136
|
+
}
|
|
1021
1137
|
if (msg.done) {
|
|
1022
1138
|
this.handleDoneMessage(fork);
|
|
1023
1139
|
return;
|
|
@@ -1048,27 +1164,60 @@ export class AdaptWebClient {
|
|
|
1048
1164
|
if (!fork) {
|
|
1049
1165
|
return;
|
|
1050
1166
|
}
|
|
1051
|
-
// Remove from queue
|
|
1167
|
+
// Remove from queue (but not the current fork — it's tracked separately).
|
|
1168
|
+
// Also discard any previously-completed (stale) forks from the queue.
|
|
1169
|
+
this.forkQueue = this.forkQueue.filter((item) => item.fork !== fork && !item.completed);
|
|
1170
|
+
if (this.currentFork?.fork === fork) {
|
|
1171
|
+
if (this.forkQueue.length > 0) {
|
|
1172
|
+
// Another fork is waiting — advance to it
|
|
1173
|
+
this.currentFork = null;
|
|
1174
|
+
this.activateNextFork();
|
|
1175
|
+
}
|
|
1176
|
+
else {
|
|
1177
|
+
// No active forks remain — keep this fork visible (graceful completion)
|
|
1178
|
+
// but mark it so it gets evicted when a new fork arrives.
|
|
1179
|
+
this.currentFork.completed = true;
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
handleStoppedMessage(fork) {
|
|
1184
|
+
if (!fork) {
|
|
1185
|
+
// Main URL stopped — clear iframe and show placeholder
|
|
1186
|
+
this.mainUrl = null;
|
|
1187
|
+
this.mainToken = undefined;
|
|
1188
|
+
if (this.mainIframe) {
|
|
1189
|
+
this.mainIframe.src = "about:blank";
|
|
1190
|
+
this.mainIframe.classList.remove("mb-adapt__iframe--visible");
|
|
1191
|
+
this.mainIframe.classList.add("mb-adapt__iframe--hidden");
|
|
1192
|
+
}
|
|
1193
|
+
this.showStoppedPlaceholder();
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
// Fork stopped — remove from queue
|
|
1052
1197
|
this.forkQueue = this.forkQueue.filter((item) => item.fork !== fork);
|
|
1053
|
-
// If current fork is done, clear tracking but keep iframe mounted
|
|
1054
|
-
// Then check if there's another fork waiting
|
|
1055
1198
|
if (this.currentFork?.fork === fork) {
|
|
1056
1199
|
this.currentFork = null;
|
|
1057
|
-
// Check if there's another fork in queue to display
|
|
1058
1200
|
if (this.forkQueue.length > 0) {
|
|
1059
1201
|
this.activateNextFork();
|
|
1060
1202
|
}
|
|
1061
1203
|
else {
|
|
1062
|
-
// No more forks
|
|
1063
|
-
|
|
1204
|
+
// No more forks — clear the fork iframe
|
|
1205
|
+
if (this.forkIframe) {
|
|
1206
|
+
this.forkIframe.src = "about:blank";
|
|
1207
|
+
this.forkIframe.classList.remove("mb-adapt__iframe--visible");
|
|
1208
|
+
this.forkIframe.classList.add("mb-adapt__iframe--hidden");
|
|
1209
|
+
}
|
|
1064
1210
|
if (this.options.forkDisplayMode === "side-by-side") {
|
|
1065
1211
|
this.updateSideBySideVisibility();
|
|
1066
1212
|
}
|
|
1067
|
-
|
|
1213
|
+
else {
|
|
1214
|
+
this.updateDialogVisibility();
|
|
1215
|
+
}
|
|
1068
1216
|
}
|
|
1069
1217
|
}
|
|
1070
1218
|
}
|
|
1071
1219
|
handleMainUrl(url, token) {
|
|
1220
|
+
this.removeStoppedPlaceholder();
|
|
1072
1221
|
this.mainUrl = url;
|
|
1073
1222
|
this.mainToken = token;
|
|
1074
1223
|
// Update main iframe only - never touch dialog state
|
|
@@ -1089,9 +1238,10 @@ export class AdaptWebClient {
|
|
|
1089
1238
|
this.mainToken = token;
|
|
1090
1239
|
this.updateMainIframe();
|
|
1091
1240
|
}
|
|
1092
|
-
// Add to queue and activate if no current fork
|
|
1241
|
+
// Add to queue and activate if no current fork or current fork is completed.
|
|
1093
1242
|
this.forkQueue.push(forkItem);
|
|
1094
|
-
if (!this.currentFork) {
|
|
1243
|
+
if (!this.currentFork || this.currentFork.completed) {
|
|
1244
|
+
this.currentFork = null;
|
|
1095
1245
|
this.activateNextFork();
|
|
1096
1246
|
}
|
|
1097
1247
|
}
|
|
@@ -1132,11 +1282,16 @@ export class AdaptWebClient {
|
|
|
1132
1282
|
updateForkIframe() {
|
|
1133
1283
|
if (!this.currentFork || !this.forkIframe)
|
|
1134
1284
|
return;
|
|
1135
|
-
// Update iframe src if changed
|
|
1136
1285
|
const newSrc = getIframeSrc(this.currentFork.url, this.currentFork.token);
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1286
|
+
// Replace iframe to force a fresh load — browsers don't reload when only
|
|
1287
|
+
// the hash fragment changes (same plugin URL, different fork token).
|
|
1288
|
+
const parent = this.forkIframe.parentElement;
|
|
1289
|
+
if (parent) {
|
|
1290
|
+
const fresh = this.createHiddenIframe();
|
|
1291
|
+
parent.replaceChild(fresh, this.forkIframe);
|
|
1292
|
+
this.forkIframe = fresh;
|
|
1293
|
+
}
|
|
1294
|
+
this.forkIframe.src = newSrc;
|
|
1140
1295
|
// Show the iframe with fade-in
|
|
1141
1296
|
this.showIframe(this.forkIframe);
|
|
1142
1297
|
}
|
|
@@ -1169,6 +1324,10 @@ export class AdaptWebClient {
|
|
|
1169
1324
|
// Reset border radius in case coming from dialog mode
|
|
1170
1325
|
this.forkIframe.style.borderRadius = "";
|
|
1171
1326
|
this.mainFrameElement.appendChild(this.mainIframe);
|
|
1327
|
+
// Fork toolbar with minimize + exit
|
|
1328
|
+
this.forkToolbarElement = this.createForkToolbar();
|
|
1329
|
+
this.forkFrameElement.classList.add("mb-adapt__frame--has-toolbar");
|
|
1330
|
+
this.forkFrameElement.appendChild(this.forkToolbarElement);
|
|
1172
1331
|
this.forkFrameElement.appendChild(this.forkIframe);
|
|
1173
1332
|
// Drag handle - initially hidden until fork arrives
|
|
1174
1333
|
this.dragHandleElement = document.createElement("div");
|
|
@@ -1315,6 +1474,76 @@ export class AdaptWebClient {
|
|
|
1315
1474
|
this.forkFrameElement.style.width = `${forkWidth}%`;
|
|
1316
1475
|
this.dragHandleElement.style.left = `${this.splitPercentage}%`;
|
|
1317
1476
|
}
|
|
1477
|
+
createForkToolbar() {
|
|
1478
|
+
const toolbar = document.createElement("div");
|
|
1479
|
+
toolbar.className =
|
|
1480
|
+
this.options.classNames?.toolbar || "mb-adapt__toolbar";
|
|
1481
|
+
// Minimize button (horizontal line icon)
|
|
1482
|
+
const minimizeBtn = document.createElement("button");
|
|
1483
|
+
minimizeBtn.className =
|
|
1484
|
+
this.options.classNames?.toolbarButton || "mb-adapt__toolbar-btn";
|
|
1485
|
+
minimizeBtn.setAttribute("aria-label", "Minimize fork");
|
|
1486
|
+
minimizeBtn.setAttribute("title", "Minimize");
|
|
1487
|
+
minimizeBtn.innerHTML = `<svg viewBox="0 0 16 16"><line x1="3" y1="8" x2="13" y2="8"/></svg>`;
|
|
1488
|
+
minimizeBtn.addEventListener("click", () => {
|
|
1489
|
+
this.handleForkMinimize();
|
|
1490
|
+
});
|
|
1491
|
+
// Exit button (X icon) — stops the fork via the API
|
|
1492
|
+
const exitBtn = document.createElement("button");
|
|
1493
|
+
exitBtn.className = `${this.options.classNames?.toolbarButton || "mb-adapt__toolbar-btn"} mb-adapt__toolbar-btn--exit`;
|
|
1494
|
+
exitBtn.setAttribute("aria-label", "Close fork");
|
|
1495
|
+
exitBtn.setAttribute("title", "Close");
|
|
1496
|
+
exitBtn.innerHTML = `<svg viewBox="0 0 16 16"><line x1="4" y1="4" x2="12" y2="12"/><line x1="12" y1="4" x2="4" y2="12"/></svg>`;
|
|
1497
|
+
exitBtn.addEventListener("click", () => {
|
|
1498
|
+
this.handleForkExit();
|
|
1499
|
+
});
|
|
1500
|
+
toolbar.appendChild(minimizeBtn);
|
|
1501
|
+
toolbar.appendChild(exitBtn);
|
|
1502
|
+
return toolbar;
|
|
1503
|
+
}
|
|
1504
|
+
handleForkMinimize() {
|
|
1505
|
+
if (!this.currentFork)
|
|
1506
|
+
return;
|
|
1507
|
+
if (this.options.forkDisplayMode === "side-by-side") {
|
|
1508
|
+
this.splitPercentage = 100;
|
|
1509
|
+
this.updateSideBySideVisibility();
|
|
1510
|
+
}
|
|
1511
|
+
else {
|
|
1512
|
+
// Dialog mode: hide dialog, put fork back in queue so expand button shows
|
|
1513
|
+
this.forkQueue.unshift(this.currentFork);
|
|
1514
|
+
this.currentFork = null;
|
|
1515
|
+
this.updateDialogVisibility();
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
handleForkExit() {
|
|
1519
|
+
if (!this.currentFork)
|
|
1520
|
+
return;
|
|
1521
|
+
const fork = this.currentFork.fork;
|
|
1522
|
+
// Stop the fork via the API (best-effort, just like Run.tsx/ClientWindow.tsx)
|
|
1523
|
+
if (this.sessionToken) {
|
|
1524
|
+
this.client.stop(this.sessionToken, fork).catch(() => { });
|
|
1525
|
+
}
|
|
1526
|
+
// Remove from queue immediately (user-dismissable, same as ClientWindow.tsx)
|
|
1527
|
+
this.forkQueue = this.forkQueue.filter((item) => item.fork !== fork);
|
|
1528
|
+
this.currentFork = null;
|
|
1529
|
+
if (this.forkQueue.length > 0) {
|
|
1530
|
+
this.activateNextFork();
|
|
1531
|
+
}
|
|
1532
|
+
else {
|
|
1533
|
+
// Clear the fork iframe
|
|
1534
|
+
if (this.forkIframe) {
|
|
1535
|
+
this.forkIframe.src = "about:blank";
|
|
1536
|
+
this.forkIframe.classList.remove("mb-adapt__iframe--visible");
|
|
1537
|
+
this.forkIframe.classList.add("mb-adapt__iframe--hidden");
|
|
1538
|
+
}
|
|
1539
|
+
if (this.options.forkDisplayMode === "side-by-side") {
|
|
1540
|
+
this.updateSideBySideVisibility();
|
|
1541
|
+
}
|
|
1542
|
+
else {
|
|
1543
|
+
this.updateDialogVisibility();
|
|
1544
|
+
}
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1318
1547
|
createDialogStructure() {
|
|
1319
1548
|
if (this.mainContainer)
|
|
1320
1549
|
return;
|
|
@@ -1342,14 +1571,10 @@ export class AdaptWebClient {
|
|
|
1342
1571
|
this.dialogBackdrop = document.createElement("div");
|
|
1343
1572
|
this.dialogBackdrop.className =
|
|
1344
1573
|
this.options.classNames?.dialogBackdrop || "mb-adapt__dialog-backdrop";
|
|
1345
|
-
// Set up backdrop click handler if enabled
|
|
1574
|
+
// Set up backdrop click handler if enabled (acts as minimize)
|
|
1346
1575
|
if (this.options.dialogBackdropClose) {
|
|
1347
1576
|
this.backdropClickHandler = () => {
|
|
1348
|
-
|
|
1349
|
-
this.forkQueue.unshift(this.currentFork);
|
|
1350
|
-
}
|
|
1351
|
-
this.currentFork = null;
|
|
1352
|
-
this.updateDialogVisibility();
|
|
1577
|
+
this.handleForkMinimize();
|
|
1353
1578
|
};
|
|
1354
1579
|
this.dialogBackdrop.addEventListener("click", this.backdropClickHandler);
|
|
1355
1580
|
}
|
|
@@ -1357,28 +1582,13 @@ export class AdaptWebClient {
|
|
|
1357
1582
|
this.dialogElement = document.createElement("div");
|
|
1358
1583
|
this.dialogElement.className =
|
|
1359
1584
|
this.options.classNames?.dialog || "mb-adapt__dialog";
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
const closeBtn = document.createElement("button");
|
|
1364
|
-
closeBtn.className =
|
|
1365
|
-
this.options.classNames?.dialogClose || "mb-adapt__dialog-close";
|
|
1366
|
-
closeBtn.innerHTML = "×";
|
|
1367
|
-
closeBtn.setAttribute("aria-label", "Close dialog");
|
|
1368
|
-
closeBtn.setAttribute("title", "Close dialog");
|
|
1369
|
-
closeBtn.addEventListener("click", () => {
|
|
1370
|
-
// Put current fork back in queue before closing
|
|
1371
|
-
if (this.currentFork) {
|
|
1372
|
-
this.forkQueue.unshift(this.currentFork);
|
|
1373
|
-
}
|
|
1374
|
-
this.currentFork = null;
|
|
1375
|
-
this.updateDialogVisibility();
|
|
1376
|
-
});
|
|
1377
|
-
banner.appendChild(closeBtn);
|
|
1378
|
-
this.dialogElement.appendChild(banner);
|
|
1585
|
+
// Same toolbar as side-by-side (minimize + exit)
|
|
1586
|
+
this.forkToolbarElement = this.createForkToolbar();
|
|
1587
|
+
this.dialogElement.appendChild(this.forkToolbarElement);
|
|
1379
1588
|
const iframeContainer = document.createElement("div");
|
|
1380
1589
|
iframeContainer.style.flex = "1";
|
|
1381
|
-
iframeContainer.style.overflow = "
|
|
1590
|
+
iframeContainer.style.overflow = "auto";
|
|
1591
|
+
iframeContainer.style.minHeight = "0";
|
|
1382
1592
|
// Reuse existing fork iframe or create new one
|
|
1383
1593
|
if (!this.forkIframe) {
|
|
1384
1594
|
this.forkIframe = this.createHiddenIframe();
|
|
@@ -1430,6 +1640,23 @@ export class AdaptWebClient {
|
|
|
1430
1640
|
});
|
|
1431
1641
|
return iframe;
|
|
1432
1642
|
}
|
|
1643
|
+
showStoppedPlaceholder() {
|
|
1644
|
+
if (!this.mainFrameElement && !this.mainContainer)
|
|
1645
|
+
return;
|
|
1646
|
+
// Remove existing placeholder if any
|
|
1647
|
+
this.removeStoppedPlaceholder();
|
|
1648
|
+
this.stoppedPlaceholder = document.createElement("div");
|
|
1649
|
+
this.stoppedPlaceholder.className = "mb-adapt__stopped-placeholder";
|
|
1650
|
+
this.stoppedPlaceholder.textContent = "This session has been stopped";
|
|
1651
|
+
const parent = this.mainFrameElement || this.mainContainer;
|
|
1652
|
+
parent.appendChild(this.stoppedPlaceholder);
|
|
1653
|
+
}
|
|
1654
|
+
removeStoppedPlaceholder() {
|
|
1655
|
+
if (this.stoppedPlaceholder) {
|
|
1656
|
+
this.stoppedPlaceholder.remove();
|
|
1657
|
+
this.stoppedPlaceholder = null;
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1433
1660
|
showIframe(iframe) {
|
|
1434
1661
|
iframe.classList.remove("mb-adapt__iframe--hidden");
|
|
1435
1662
|
// Trigger reflow to ensure transition works
|