@mochabug/adapt-web 1.0.0-rc43 → 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 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: 6px;
40
- --mb-adapt-drag-handle-color: #d1d5db;
41
- --mb-adapt-drag-handle-hover: #6b7280;
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: #4b5563;
74
- --mb-adapt-drag-handle-hover: #6b7280;
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(248,250,252,0.98) 100%);
232
- border: none;
233
- color: #64748b;
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: 14px;
236
- height: 48px;
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: 14px;
266
+ font-size: 16px;
267
+ font-weight: 600;
243
268
  line-height: 1;
244
269
  padding: 0;
245
270
  box-shadow:
246
- 0 2px 8px rgba(0, 0, 0, 0.12),
247
- 0 1px 3px rgba(0, 0, 0, 0.08),
248
- inset 0 1px 0 rgba(255, 255, 255, 0.8);
249
- border-radius: 4px;
250
- backdrop-filter: blur(8px);
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(241,245,249,1) 100%);
256
- color: #475569;
257
- transform: translateY(-50%) scale(1.02);
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 12px rgba(0, 0, 0, 0.15),
260
- 0 2px 4px rgba(0, 0, 0, 0.1),
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.98);
288
+ transform: translateY(-50%) scale(0.97);
266
289
  box-shadow:
267
- 0 1px 4px rgba(0, 0, 0, 0.1),
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 8px rgba(0, 0, 0, 0.12),
281
- 1px 1px 3px rgba(0, 0, 0, 0.08),
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 12px rgba(0, 0, 0, 0.15),
288
- 2px 2px 4px rgba(0, 0, 0, 0.1),
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 8px rgba(0, 0, 0, 0.12),
298
- -1px 1px 3px rgba(0, 0, 0, 0.08),
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 12px rgba(0, 0, 0, 0.15),
305
- -2px 2px 4px rgba(0, 0, 0, 0.1),
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: 56px;
314
- height: 20px;
334
+ width: 64px;
335
+ height: 24px;
315
336
  font-size: 16px;
316
- line-height: 20px;
337
+ line-height: 24px;
317
338
  vertical-align: middle;
318
339
  text-align: center;
319
- border-radius: 6px;
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 8px rgba(0, 0, 0, 0.12),
324
- 0 1px 3px rgba(0, 0, 0, 0.08),
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.02);
350
+ transform: translateX(-50%) scale(1.04);
330
351
  box-shadow:
331
- 0 5px 12px rgba(0, 0, 0, 0.15),
332
- 0 2px 4px rgba(0, 0, 0, 0.1),
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.98);
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(31,41,55,0.98) 0%, rgba(17,24,39,0.98) 100%);
342
- color: #9ca3af;
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 8px rgba(0, 0, 0, 0.3),
345
- 0 1px 3px rgba(0, 0, 0, 0.2),
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(55,65,81,1) 0%, rgba(31,41,55,1) 100%);
351
- color: #d1d5db;
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 12px rgba(0, 0, 0, 0.4),
354
- 0 2px 4px rgba(0, 0, 0, 0.3),
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: 0 0 auto;
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 {
@@ -453,6 +548,7 @@ export class AdaptWebClient {
453
548
  this.dragHandleElement = null;
454
549
  this.mainExpandButton = null;
455
550
  this.forkExpandButton = null;
551
+ this.forkToolbarElement = null;
456
552
  // Dialog elements
457
553
  this.mainContainer = null;
458
554
  this.dialogBackdrop = null;
@@ -665,6 +761,7 @@ export class AdaptWebClient {
665
761
  this.dragHandleElement = null;
666
762
  this.mainExpandButton = null;
667
763
  this.forkExpandButton = null;
764
+ this.forkToolbarElement = null;
668
765
  this.mainContainer = null;
669
766
  this.dialogBackdrop = null;
670
767
  this.dialogElement = null;
@@ -720,14 +817,10 @@ export class AdaptWebClient {
720
817
  this.dialogBackdrop.removeEventListener("click", this.backdropClickHandler);
721
818
  this.backdropClickHandler = null;
722
819
  }
723
- // Add new handler if enabled
820
+ // Add new handler if enabled (acts as minimize)
724
821
  if (enabled) {
725
822
  this.backdropClickHandler = () => {
726
- if (this.currentFork) {
727
- this.forkQueue.unshift(this.currentFork);
728
- }
729
- this.currentFork = null;
730
- this.updateDialogVisibility();
823
+ this.handleForkMinimize();
731
824
  };
732
825
  this.dialogBackdrop.addEventListener("click", this.backdropClickHandler);
733
826
  }
@@ -1021,6 +1114,7 @@ export class AdaptWebClient {
1021
1114
  this.dragHandleElement = null;
1022
1115
  this.mainExpandButton = null;
1023
1116
  this.forkExpandButton = null;
1117
+ this.forkToolbarElement = null;
1024
1118
  this.mainContainer = null;
1025
1119
  this.dialogBackdrop = null;
1026
1120
  this.dialogElement = null;
@@ -1070,23 +1164,19 @@ export class AdaptWebClient {
1070
1164
  if (!fork) {
1071
1165
  return;
1072
1166
  }
1073
- // Remove from queue
1074
- this.forkQueue = this.forkQueue.filter((item) => item.fork !== fork);
1075
- // If current fork is done, clear tracking but keep iframe mounted
1076
- // Then check if there's another fork waiting
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);
1077
1170
  if (this.currentFork?.fork === fork) {
1078
- this.currentFork = null;
1079
- // Check if there's another fork in queue to display
1080
1171
  if (this.forkQueue.length > 0) {
1172
+ // Another fork is waiting — advance to it
1173
+ this.currentFork = null;
1081
1174
  this.activateNextFork();
1082
1175
  }
1083
1176
  else {
1084
- // No more forks - update visibility (hide fork frame in side-by-side,
1085
- // or keep dialog open until user closes it)
1086
- if (this.options.forkDisplayMode === "side-by-side") {
1087
- this.updateSideBySideVisibility();
1088
- }
1089
- // For dialog mode: keep dialog open until user clicks close or backdrop
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;
1090
1180
  }
1091
1181
  }
1092
1182
  }
@@ -1148,9 +1238,10 @@ export class AdaptWebClient {
1148
1238
  this.mainToken = token;
1149
1239
  this.updateMainIframe();
1150
1240
  }
1151
- // Add to queue and activate if no current fork
1241
+ // Add to queue and activate if no current fork or current fork is completed.
1152
1242
  this.forkQueue.push(forkItem);
1153
- if (!this.currentFork) {
1243
+ if (!this.currentFork || this.currentFork.completed) {
1244
+ this.currentFork = null;
1154
1245
  this.activateNextFork();
1155
1246
  }
1156
1247
  }
@@ -1191,11 +1282,16 @@ export class AdaptWebClient {
1191
1282
  updateForkIframe() {
1192
1283
  if (!this.currentFork || !this.forkIframe)
1193
1284
  return;
1194
- // Update iframe src if changed
1195
1285
  const newSrc = getIframeSrc(this.currentFork.url, this.currentFork.token);
1196
- if (this.forkIframe.src !== newSrc) {
1197
- this.forkIframe.src = newSrc;
1198
- }
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;
1199
1295
  // Show the iframe with fade-in
1200
1296
  this.showIframe(this.forkIframe);
1201
1297
  }
@@ -1228,6 +1324,10 @@ export class AdaptWebClient {
1228
1324
  // Reset border radius in case coming from dialog mode
1229
1325
  this.forkIframe.style.borderRadius = "";
1230
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);
1231
1331
  this.forkFrameElement.appendChild(this.forkIframe);
1232
1332
  // Drag handle - initially hidden until fork arrives
1233
1333
  this.dragHandleElement = document.createElement("div");
@@ -1374,6 +1474,76 @@ export class AdaptWebClient {
1374
1474
  this.forkFrameElement.style.width = `${forkWidth}%`;
1375
1475
  this.dragHandleElement.style.left = `${this.splitPercentage}%`;
1376
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
+ }
1377
1547
  createDialogStructure() {
1378
1548
  if (this.mainContainer)
1379
1549
  return;
@@ -1401,14 +1571,10 @@ export class AdaptWebClient {
1401
1571
  this.dialogBackdrop = document.createElement("div");
1402
1572
  this.dialogBackdrop.className =
1403
1573
  this.options.classNames?.dialogBackdrop || "mb-adapt__dialog-backdrop";
1404
- // Set up backdrop click handler if enabled
1574
+ // Set up backdrop click handler if enabled (acts as minimize)
1405
1575
  if (this.options.dialogBackdropClose) {
1406
1576
  this.backdropClickHandler = () => {
1407
- if (this.currentFork) {
1408
- this.forkQueue.unshift(this.currentFork);
1409
- }
1410
- this.currentFork = null;
1411
- this.updateDialogVisibility();
1577
+ this.handleForkMinimize();
1412
1578
  };
1413
1579
  this.dialogBackdrop.addEventListener("click", this.backdropClickHandler);
1414
1580
  }
@@ -1416,28 +1582,13 @@ export class AdaptWebClient {
1416
1582
  this.dialogElement = document.createElement("div");
1417
1583
  this.dialogElement.className =
1418
1584
  this.options.classNames?.dialog || "mb-adapt__dialog";
1419
- const banner = document.createElement("div");
1420
- banner.className =
1421
- this.options.classNames?.dialogBanner || "mb-adapt__dialog-banner";
1422
- const closeBtn = document.createElement("button");
1423
- closeBtn.className =
1424
- this.options.classNames?.dialogClose || "mb-adapt__dialog-close";
1425
- closeBtn.innerHTML = "×";
1426
- closeBtn.setAttribute("aria-label", "Close dialog");
1427
- closeBtn.setAttribute("title", "Close dialog");
1428
- closeBtn.addEventListener("click", () => {
1429
- // Put current fork back in queue before closing
1430
- if (this.currentFork) {
1431
- this.forkQueue.unshift(this.currentFork);
1432
- }
1433
- this.currentFork = null;
1434
- this.updateDialogVisibility();
1435
- });
1436
- banner.appendChild(closeBtn);
1437
- this.dialogElement.appendChild(banner);
1585
+ // Same toolbar as side-by-side (minimize + exit)
1586
+ this.forkToolbarElement = this.createForkToolbar();
1587
+ this.dialogElement.appendChild(this.forkToolbarElement);
1438
1588
  const iframeContainer = document.createElement("div");
1439
1589
  iframeContainer.style.flex = "1";
1440
- iframeContainer.style.overflow = "hidden";
1590
+ iframeContainer.style.overflow = "auto";
1591
+ iframeContainer.style.minHeight = "0";
1441
1592
  // Reuse existing fork iframe or create new one
1442
1593
  if (!this.forkIframe) {
1443
1594
  this.forkIframe = this.createHiddenIframe();