@c15t/dev-tools 2.0.0-rc.2 → 2.0.0-rc.4

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.
Files changed (52) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/components/panel.d.ts +1 -0
  3. package/dist/components/panel.d.ts.map +1 -1
  4. package/dist/components/tabs.d.ts.map +1 -1
  5. package/dist/components/ui.d.ts +8 -0
  6. package/dist/components/ui.d.ts.map +1 -1
  7. package/dist/core/debug-bundle.d.ts +14 -0
  8. package/dist/core/debug-bundle.d.ts.map +1 -0
  9. package/dist/core/devtools.d.ts.map +1 -1
  10. package/dist/core/override-storage.d.ts +7 -0
  11. package/dist/core/override-storage.d.ts.map +1 -0
  12. package/dist/core/panel-renderer.d.ts +5 -0
  13. package/dist/core/panel-renderer.d.ts.map +1 -1
  14. package/dist/core/state-manager.d.ts +1 -1
  15. package/dist/core/state-manager.d.ts.map +1 -1
  16. package/dist/core/store-connector.d.ts +20 -0
  17. package/dist/core/store-connector.d.ts.map +1 -1
  18. package/dist/core/store-instrumentation.d.ts +13 -0
  19. package/dist/core/store-instrumentation.d.ts.map +1 -0
  20. package/dist/index.cjs +2469 -845
  21. package/dist/index.js +2472 -848
  22. package/dist/panels/actions.d.ts +1 -0
  23. package/dist/panels/actions.d.ts.map +1 -1
  24. package/dist/panels/consents.d.ts.map +1 -1
  25. package/dist/panels/dom-scanner.d.ts.map +1 -1
  26. package/dist/panels/events.d.ts.map +1 -1
  27. package/dist/panels/iab.d.ts +6 -0
  28. package/dist/panels/iab.d.ts.map +1 -1
  29. package/dist/panels/location.d.ts +9 -6
  30. package/dist/panels/location.d.ts.map +1 -1
  31. package/dist/panels/scripts.d.ts +2 -0
  32. package/dist/panels/scripts.d.ts.map +1 -1
  33. package/dist/react.cjs +2392 -752
  34. package/dist/react.js +2376 -736
  35. package/dist/tanstack.cjs +2197 -555
  36. package/dist/tanstack.js +2195 -553
  37. package/dist/utils/preference-trigger.d.ts +2 -2
  38. package/dist/utils/preference-trigger.d.ts.map +1 -1
  39. package/dist/version.d.ts +2 -0
  40. package/dist/version.d.ts.map +1 -0
  41. package/package.json +16 -14
  42. package/tsconfig.json +9 -1
  43. package/dist/__tests__/components/ui.test.d.ts +0 -2
  44. package/dist/__tests__/components/ui.test.d.ts.map +0 -1
  45. package/dist/__tests__/core/renderer.test.d.ts +0 -2
  46. package/dist/__tests__/core/renderer.test.d.ts.map +0 -1
  47. package/dist/__tests__/core/reset-consents.test.d.ts +0 -2
  48. package/dist/__tests__/core/reset-consents.test.d.ts.map +0 -1
  49. package/dist/__tests__/core/state-manager.test.d.ts +0 -2
  50. package/dist/__tests__/core/state-manager.test.d.ts.map +0 -1
  51. package/dist/__tests__/panels/dom-scanner.test.d.ts +0 -2
  52. package/dist/__tests__/panels/dom-scanner.test.d.ts.map +0 -1
package/dist/tanstack.cjs CHANGED
@@ -260,21 +260,21 @@ var __webpack_modules__ = {
260
260
  module.id,
261
261
  `.toggle-bPZtik {
262
262
  border-radius: var(--c15t-radius-full, 9999px);
263
- background-color: var(--c15t-switch-track, #ccc);
263
+ background-color: var(--c15t-switch-track, #d9d9d9);
264
264
  cursor: pointer;
265
- width: 36px;
266
- height: 20px;
267
- transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
265
+ width: 2rem;
266
+ height: 1.25rem;
267
+ transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), box-shadow var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
268
268
  border: none;
269
269
  align-items: center;
270
- padding: 0;
270
+ padding: .125rem;
271
271
  display: inline-flex;
272
272
  position: relative;
273
273
  }
274
274
 
275
275
  .toggle-bPZtik:focus-visible {
276
- outline: 2px solid var(--c15t-primary, #335cff);
277
- outline-offset: 2px;
276
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
277
+ outline: none;
278
278
  }
279
279
 
280
280
  .toggleActive-Ldlasg {
@@ -284,16 +284,16 @@ var __webpack_modules__ = {
284
284
  .toggleThumb-hjGfoX {
285
285
  border-radius: var(--c15t-radius-full, 9999px);
286
286
  background-color: var(--c15t-switch-thumb, #fff);
287
- width: 16px;
288
- height: 16px;
289
- transition: transform var(--c15t-duration-fast, .1s) var(--c15t-easing-spring, cubic-bezier(.34, 1.56, .64, 1));
287
+ width: .75rem;
288
+ height: .75rem;
289
+ box-shadow: 0 0 0 1px var(--c15t-border, #e3e3e3);
290
+ transition: transform var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
290
291
  position: absolute;
291
292
  left: 2px;
292
- box-shadow: 0 1px 2px #0003;
293
293
  }
294
294
 
295
295
  .toggleActive-Ldlasg .toggleThumb-hjGfoX {
296
- transform: translateX(16px);
296
+ transform: translateX(1rem);
297
297
  }
298
298
 
299
299
  .toggle-bPZtik:disabled, .toggleDisabled-ZcD8nZ {
@@ -306,13 +306,14 @@ var __webpack_modules__ = {
306
306
  }
307
307
 
308
308
  .badge-yA0giZ {
309
- border-radius: var(--c15t-radius-sm, .25rem);
309
+ border-radius: var(--c15t-radius-full, 9999px);
310
310
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
311
311
  font-weight: var(--c15t-font-weight-medium, 500);
312
+ line-height: var(--c15t-line-height-tight, 1.25);
312
313
  white-space: nowrap;
314
+ justify-content: center;
313
315
  align-items: center;
314
- padding: 2px 6px;
315
- line-height: 1;
316
+ padding: .1875rem .4375rem;
316
317
  display: inline-flex;
317
318
  }
318
319
 
@@ -345,38 +346,49 @@ var __webpack_modules__ = {
345
346
  justify-content: center;
346
347
  align-items: center;
347
348
  gap: var(--c15t-space-xs, .25rem);
348
- padding: var(--c15t-space-xs, .25rem) var(--c15t-space-sm, .5rem);
349
- border: 1px solid var(--c15t-border, #e3e3e3);
349
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
350
350
  border-radius: var(--c15t-radius-md, .5rem);
351
- background-color: var(--c15t-surface, #fff);
351
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
352
+ min-height: 2rem;
352
353
  color: var(--c15t-text, #171717);
353
- font-family: inherit;
354
- font-size: var(--c15t-devtools-font-size-xs, .75rem);
354
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
355
+ font-size: var(--c15t-font-size-sm, .875rem);
355
356
  font-weight: var(--c15t-font-weight-medium, 500);
357
+ line-height: var(--c15t-line-height-tight, 1.25);
358
+ box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000000d);
356
359
  cursor: pointer;
357
- transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), border-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
360
+ transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), border-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), box-shadow var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
361
+ padding: .375rem .625rem;
358
362
  display: inline-flex;
359
363
  }
360
364
 
361
365
  .btn-evRVlh:hover {
362
- background-color: var(--c15t-surface-hover, #f7f7f7);
366
+ background-color: var(--c15t-devtools-surface-subtle, #f7f7f7);
363
367
  border-color: var(--c15t-border-hover, #c9c9c9);
368
+ box-shadow: var(--c15t-shadow-md, 0 4px 12px #00000014);
364
369
  }
365
370
 
366
371
  .btn-evRVlh:focus-visible {
367
- outline: 2px solid var(--c15t-primary, #335cff);
368
- outline-offset: 1px;
372
+ box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000000d), 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
373
+ outline: none;
374
+ }
375
+
376
+ .btn-evRVlh:active {
377
+ box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000000d);
378
+ transform: scale(.98);
369
379
  }
370
380
 
371
381
  .btn-evRVlh:disabled {
372
382
  opacity: .5;
373
383
  cursor: not-allowed;
384
+ box-shadow: none;
374
385
  }
375
386
 
376
387
  .btnPrimary-dA6nqY {
377
388
  background-color: var(--c15t-primary, #335cff);
378
389
  border-color: var(--c15t-primary, #335cff);
379
390
  color: var(--c15t-text-on-primary, #fff);
391
+ box-shadow: none;
380
392
  }
381
393
 
382
394
  .btnPrimary-dA6nqY:hover {
@@ -388,6 +400,7 @@ var __webpack_modules__ = {
388
400
  background-color: var(--c15t-devtools-badge-error, #ef4343);
389
401
  border-color: var(--c15t-devtools-badge-error, #ef4343);
390
402
  color: var(--c15t-text-on-primary, #fff);
403
+ box-shadow: none;
391
404
  }
392
405
 
393
406
  .btnDanger-eDnqOX:hover {
@@ -396,8 +409,10 @@ var __webpack_modules__ = {
396
409
  }
397
410
 
398
411
  .btnSmall-TjXoqZ {
399
- padding: 2px var(--c15t-space-xs, .25rem);
400
- font-size: 10px;
412
+ min-height: 1.75rem;
413
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
414
+ border-radius: var(--c15t-radius-sm, .375rem);
415
+ padding: .25rem .5rem;
401
416
  }
402
417
 
403
418
  .btnIcon-fiYQAh {
@@ -407,19 +422,22 @@ var __webpack_modules__ = {
407
422
  }
408
423
 
409
424
  .input-IeTcCs {
410
- width: 100%;
411
- padding: var(--c15t-space-xs, .25rem) var(--c15t-space-sm, .5rem);
412
- border: 1px solid var(--c15t-border, #e3e3e3);
425
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
413
426
  border-radius: var(--c15t-radius-md, .5rem);
414
- background-color: var(--c15t-surface, #fff);
427
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
428
+ width: 100%;
429
+ min-height: 2rem;
415
430
  color: var(--c15t-text, #171717);
416
- font-family: inherit;
417
- font-size: var(--c15t-font-size-sm, .875rem);
418
- transition: border-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
431
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
432
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
433
+ line-height: var(--c15t-line-height-tight, 1.25);
434
+ transition: border-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), box-shadow var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
435
+ padding: .375rem .625rem;
419
436
  }
420
437
 
421
438
  .input-IeTcCs:focus {
422
- border-color: var(--c15t-primary, #335cff);
439
+ border-color: var(--c15t-devtools-focus-ring, #335cff);
440
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--c15t-devtools-focus-ring, #335cff) 25%, transparent);
423
441
  outline: none;
424
442
  }
425
443
 
@@ -428,30 +446,35 @@ var __webpack_modules__ = {
428
446
  }
429
447
 
430
448
  .inputSmall-pJyXcL {
431
- padding: 2px var(--c15t-space-xs, .25rem);
449
+ min-height: 1.625rem;
432
450
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
451
+ padding: .25rem .4375rem;
433
452
  }
434
453
 
435
454
  .select-byJ1WM {
436
- width: 100%;
437
- padding: var(--c15t-space-xs, .25rem) var(--c15t-space-sm, .5rem);
438
- border: 1px solid var(--c15t-border, #e3e3e3);
455
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
439
456
  border-radius: var(--c15t-radius-md, .5rem);
440
- background-color: var(--c15t-surface, #fff);
457
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
458
+ width: 100%;
459
+ min-height: 2rem;
441
460
  color: var(--c15t-text, #171717);
442
- font-family: inherit;
461
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
443
462
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
463
+ line-height: var(--c15t-line-height-tight, 1.25);
444
464
  cursor: pointer;
465
+ transition: border-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), box-shadow var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
466
+ padding: .375rem .625rem;
445
467
  }
446
468
 
447
469
  .select-byJ1WM:focus {
448
- border-color: var(--c15t-primary, #335cff);
470
+ border-color: var(--c15t-devtools-focus-ring, #335cff);
471
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--c15t-devtools-focus-ring, #335cff) 25%, transparent);
449
472
  outline: none;
450
473
  }
451
474
 
452
475
  .grid-LlrmEz {
453
476
  gap: var(--c15t-space-sm, .5rem);
454
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, 1rem);
477
+ padding: var(--c15t-space-md, 1rem);
455
478
  display: grid;
456
479
  }
457
480
 
@@ -464,42 +487,51 @@ var __webpack_modules__ = {
464
487
  }
465
488
 
466
489
  .gridCard-Qm5xxI {
467
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, .75rem);
468
- border: 1px solid var(--c15t-border, #e3e3e3);
469
- border-radius: var(--c15t-radius-md, .5rem);
470
- background-color: var(--c15t-surface, #fff);
471
- transition: border-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
472
490
  justify-content: space-between;
473
491
  align-items: center;
492
+ gap: var(--c15t-space-sm, .5rem);
493
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
494
+ border-radius: var(--c15t-radius-md, .5rem);
495
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
496
+ min-height: 2.75rem;
497
+ box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000000d);
498
+ transition: border-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
499
+ padding: .5625rem .75rem;
474
500
  display: flex;
475
501
  }
476
502
 
477
503
  .gridCard-Qm5xxI:hover {
478
504
  border-color: var(--c15t-border-hover, #c9c9c9);
505
+ background-color: var(--c15t-devtools-surface-subtle, #fafafa);
479
506
  }
480
507
 
481
508
  .gridCardTitle-HjXETp {
482
509
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
483
510
  font-weight: var(--c15t-font-weight-medium, 500);
484
511
  color: var(--c15t-text, #171717);
512
+ line-height: var(--c15t-line-height-tight, 1.25);
485
513
  }
486
514
 
487
515
  .listItem-XUKGIo {
488
- padding: var(--c15t-space-xs, .25rem) var(--c15t-space-md, 1rem);
489
- border-bottom: 1px solid var(--c15t-border, #e3e3e3);
490
516
  justify-content: space-between;
491
517
  align-items: center;
518
+ gap: var(--c15t-space-sm, .5rem);
519
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
520
+ border-radius: var(--c15t-radius-md, .5rem);
521
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
522
+ margin-bottom: .375rem;
523
+ padding: .625rem .75rem;
492
524
  display: flex;
493
525
  }
494
526
 
495
527
  .listItem-XUKGIo:last-child {
496
- border-bottom: none;
528
+ margin-bottom: 0;
497
529
  }
498
530
 
499
531
  .listItemContent-WDBF1N {
500
532
  flex-direction: column;
501
533
  flex: 1;
502
- gap: 2px;
534
+ gap: .1875rem;
503
535
  min-width: 0;
504
536
  display: flex;
505
537
  }
@@ -513,6 +545,7 @@ var __webpack_modules__ = {
513
545
  .listItemDescription-E6JHyZ {
514
546
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
515
547
  color: var(--c15t-text-muted, #737373);
548
+ line-height: var(--c15t-line-height-tight, 1.25);
516
549
  text-overflow: ellipsis;
517
550
  white-space: nowrap;
518
551
  overflow: hidden;
@@ -526,8 +559,8 @@ var __webpack_modules__ = {
526
559
  }
527
560
 
528
561
  .section-a197cB {
529
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, 1rem);
530
- border-bottom: 1px solid var(--c15t-border, #e3e3e3);
562
+ border-bottom: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
563
+ padding: .75rem 1rem;
531
564
  }
532
565
 
533
566
  .section-a197cB:last-child {
@@ -535,9 +568,10 @@ var __webpack_modules__ = {
535
568
  }
536
569
 
537
570
  .sectionHeader-Xcljcw {
538
- margin-bottom: var(--c15t-space-sm, .5rem);
539
571
  justify-content: space-between;
540
572
  align-items: center;
573
+ gap: .5rem;
574
+ margin-bottom: .625rem;
541
575
  display: flex;
542
576
  }
543
577
 
@@ -546,13 +580,60 @@ var __webpack_modules__ = {
546
580
  font-weight: var(--c15t-font-weight-semibold, 600);
547
581
  color: var(--c15t-text-muted, #737373);
548
582
  text-transform: uppercase;
549
- letter-spacing: .5px;
583
+ letter-spacing: .04em;
584
+ }
585
+
586
+ .overrideField-keNdpJ {
587
+ flex-direction: column;
588
+ gap: .3125rem;
589
+ margin-bottom: 0;
590
+ display: flex;
591
+ }
592
+
593
+ .overrideLabel-ApMoTw {
594
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
595
+ font-weight: var(--c15t-font-weight-semibold, 600);
596
+ color: var(--c15t-text-muted, #737373);
597
+ line-height: var(--c15t-line-height-tight, 1.25);
598
+ }
599
+
600
+ .overrideHint-yCfwGt {
601
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
602
+ color: var(--c15t-text-muted, #737373);
603
+ line-height: var(--c15t-line-height-tight, 1.25);
604
+ margin-top: .5rem;
605
+ }
606
+
607
+ .overrideActions-imdcn7 {
608
+ border-top: 1px dashed var(--c15t-devtools-border-strong, #e3e3e3);
609
+ justify-content: space-between;
610
+ align-items: center;
611
+ gap: .5rem;
612
+ margin-top: .625rem;
613
+ padding-top: .625rem;
614
+ display: flex;
615
+ }
616
+
617
+ .overrideActionButtons-gYOx1e {
618
+ flex-wrap: wrap;
619
+ gap: .375rem;
620
+ display: flex;
621
+ }
622
+
623
+ .overrideStatus-sty_qS {
624
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
625
+ color: var(--c15t-text-muted, #737373);
626
+ }
627
+
628
+ .overrideStatusDirty-OUdDMw {
629
+ color: var(--c15t-devtools-badge-warning, #f59f0a);
550
630
  }
551
631
 
552
632
  .infoRow-RlB_0h {
553
- padding: var(--c15t-space-xs, .25rem) 0;
554
633
  justify-content: space-between;
555
634
  align-items: center;
635
+ gap: .5rem;
636
+ padding: .25rem 0;
556
637
  display: flex;
557
638
  }
558
639
 
@@ -565,6 +646,7 @@ var __webpack_modules__ = {
565
646
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
566
647
  font-weight: var(--c15t-font-weight-medium, 500);
567
648
  color: var(--c15t-text, #171717);
649
+ font-variant-numeric: tabular-nums;
568
650
  font-family: ui-monospace, Cascadia Code, Source Code Pro, Menlo, Consolas, DejaVu Sans Mono, monospace;
569
651
  }
570
652
 
@@ -575,18 +657,27 @@ var __webpack_modules__ = {
575
657
  flex-direction: column;
576
658
  justify-content: center;
577
659
  align-items: center;
660
+ gap: .375rem;
578
661
  display: flex;
579
662
  }
580
663
 
581
664
  .emptyStateIcon-WHFkX8 {
665
+ opacity: .55;
582
666
  width: 32px;
583
667
  height: 32px;
584
- margin-bottom: var(--c15t-space-sm, .5rem);
585
- opacity: .5;
586
668
  }
587
669
 
588
670
  .emptyStateText-TaLvAJ {
589
671
  font-size: var(--c15t-font-size-sm, .875rem);
672
+ line-height: var(--c15t-line-height-normal, 1.5);
673
+ }
674
+
675
+ .disconnectedState-dOtZBG {
676
+ padding: var(--c15t-space-xl, 2rem);
677
+ text-align: center;
678
+ font-size: var(--c15t-font-size-sm, .875rem);
679
+ color: var(--c15t-text-muted, #737373);
680
+ line-height: var(--c15t-line-height-normal, 1.5);
590
681
  }
591
682
 
592
683
  @media (prefers-reduced-motion: reduce) {
@@ -641,12 +732,20 @@ var __webpack_modules__ = {
641
732
  section: "section-a197cB",
642
733
  sectionHeader: "sectionHeader-Xcljcw",
643
734
  sectionTitle: "sectionTitle-RUiFld",
735
+ overrideField: "overrideField-keNdpJ",
736
+ overrideLabel: "overrideLabel-ApMoTw",
737
+ overrideHint: "overrideHint-yCfwGt",
738
+ overrideActions: "overrideActions-imdcn7",
739
+ overrideActionButtons: "overrideActionButtons-gYOx1e",
740
+ overrideStatus: "overrideStatus-sty_qS",
741
+ overrideStatusDirty: "overrideStatusDirty-OUdDMw",
644
742
  infoRow: "infoRow-RlB_0h",
645
743
  infoLabel: "infoLabel-_pbK33",
646
744
  infoValue: "infoValue-flMl_e",
647
745
  emptyState: "emptyState-QcmzTQ",
648
746
  emptyStateIcon: "emptyStateIcon-WHFkX8",
649
- emptyStateText: "emptyStateText-TaLvAJ"
747
+ emptyStateText: "emptyStateText-TaLvAJ",
748
+ disconnectedState: "disconnectedState-dOtZBG"
650
749
  };
651
750
  const __rspack_default_export = ___CSS_LOADER_EXPORT___;
652
751
  },
@@ -675,9 +774,9 @@ var __webpack_modules__ = {
675
774
  .floatingButton-Gw8MtJ {
676
775
  width: var(--c15t-devtools-button-size, 40px);
677
776
  height: var(--c15t-devtools-button-size, 40px);
678
- border: 1px solid var(--c15t-border, #e3e3e3);
777
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
679
778
  border-radius: var(--c15t-radius-full, 9999px);
680
- background-color: var(--c15t-surface, #fff);
779
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
681
780
  box-shadow: var(--c15t-shadow-lg, 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a);
682
781
  cursor: grab;
683
782
  z-index: var(--c15t-devtools-z-index, 99999);
@@ -705,13 +804,13 @@ var __webpack_modules__ = {
705
804
  }
706
805
 
707
806
  .floatingButton-Gw8MtJ:focus-visible {
708
- outline: 2px solid var(--c15t-primary, #335cff);
709
- outline-offset: 2px;
807
+ box-shadow: var(--c15t-shadow-lg, 0 8px 24px #0000001f), 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
808
+ outline: none;
710
809
  }
711
810
 
712
811
  .floatingButton-Gw8MtJ:active {
713
812
  cursor: grabbing;
714
- transform: scale(1.02);
813
+ transform: scale(.98);
715
814
  }
716
815
 
717
816
  .floatingButtonIcon-cHWefk {
@@ -752,6 +851,7 @@ var __webpack_modules__ = {
752
851
 
753
852
  .backdrop-LhVMB5 {
754
853
  background-color: var(--c15t-overlay, #00000080);
854
+ backdrop-filter: blur(1px);
755
855
  z-index: calc(var(--c15t-devtools-z-index, 99999) + 1);
756
856
  position: fixed;
757
857
  inset: 0;
@@ -760,10 +860,10 @@ var __webpack_modules__ = {
760
860
  .panel-jtWove {
761
861
  width: var(--c15t-devtools-panel-width, 480px);
762
862
  max-height: var(--c15t-devtools-panel-max-height, 560px);
763
- background-color: var(--c15t-surface, #fff);
764
- border: 1px solid var(--c15t-border, #e3e3e3);
863
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
864
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
765
865
  border-radius: var(--c15t-radius-lg, .75rem);
766
- box-shadow: var(--c15t-shadow-lg, 0 8px 24px #0000001f);
866
+ box-shadow: var(--c15t-shadow-lg, 0 10px 28px #00000029);
767
867
  z-index: calc(var(--c15t-devtools-z-index, 99999) + 2);
768
868
  flex-direction: column;
769
869
  display: flex;
@@ -796,11 +896,11 @@ var __webpack_modules__ = {
796
896
  }
797
897
 
798
898
  .header-xluoTr {
799
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, 1rem);
800
- border-bottom: 1px solid var(--c15t-border, #e3e3e3);
899
+ border-bottom: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
801
900
  background-color: var(--c15t-devtools-surface-muted, #f5f5f5);
802
901
  justify-content: space-between;
803
902
  align-items: center;
903
+ padding: .6875rem .875rem;
804
904
  display: flex;
805
905
  }
806
906
 
@@ -809,6 +909,7 @@ var __webpack_modules__ = {
809
909
  gap: var(--c15t-space-sm, .5rem);
810
910
  font-size: var(--c15t-font-size-sm, .875rem);
811
911
  font-weight: var(--c15t-font-weight-semibold, 600);
912
+ line-height: var(--c15t-line-height-tight, 1.25);
812
913
  color: var(--c15t-text, #171717);
813
914
  display: flex;
814
915
  }
@@ -820,9 +921,9 @@ var __webpack_modules__ = {
820
921
  }
821
922
 
822
923
  .closeButton-Yto0Nb {
823
- border-radius: var(--c15t-radius-sm, .25rem);
824
- width: 28px;
825
- height: 28px;
924
+ border-radius: var(--c15t-radius-md, .5rem);
925
+ width: 2rem;
926
+ height: 2rem;
826
927
  color: var(--c15t-text-muted, #737373);
827
928
  cursor: pointer;
828
929
  transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
@@ -835,13 +936,13 @@ var __webpack_modules__ = {
835
936
  }
836
937
 
837
938
  .closeButton-Yto0Nb:hover {
838
- background-color: var(--c15t-surface-hover, #f7f7f7);
939
+ background-color: var(--c15t-devtools-surface-subtle, #f7f7f7);
839
940
  color: var(--c15t-text, #171717);
840
941
  }
841
942
 
842
943
  .closeButton-Yto0Nb:focus-visible {
843
- outline: 2px solid var(--c15t-primary, #335cff);
844
- outline-offset: 1px;
944
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
945
+ outline: none;
845
946
  }
846
947
 
847
948
  .closeButtonIcon-fVlR1I {
@@ -849,33 +950,71 @@ var __webpack_modules__ = {
849
950
  height: 16px;
850
951
  }
851
952
 
953
+ .inlineActionButton-Ky8BmN {
954
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
955
+ border-radius: var(--c15t-radius-sm, .375rem);
956
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
957
+ min-height: 1.625rem;
958
+ color: var(--c15t-text, #171717);
959
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
960
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
961
+ font-weight: var(--c15t-font-weight-medium, 500);
962
+ line-height: var(--c15t-line-height-tight, 1.25);
963
+ cursor: pointer;
964
+ transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), border-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
965
+ justify-content: center;
966
+ align-items: center;
967
+ padding: .25rem .5rem;
968
+ display: inline-flex;
969
+ }
970
+
971
+ .inlineActionButton-Ky8BmN:hover {
972
+ background-color: var(--c15t-devtools-surface-subtle, #f7f7f7);
973
+ border-color: var(--c15t-border-hover, #c9c9c9);
974
+ }
975
+
976
+ .inlineActionButton-Ky8BmN:focus-visible {
977
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
978
+ outline: none;
979
+ }
980
+
852
981
  .content-yDMYfG {
982
+ scrollbar-gutter: stable;
853
983
  overscroll-behavior: contain;
854
984
  -webkit-overflow-scrolling: touch;
985
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
855
986
  flex: auto;
856
987
  min-height: 200px;
857
- overflow: hidden auto;
988
+ overflow: hidden scroll;
858
989
  }
859
990
 
860
991
  .footer-ESbmwQ {
861
- padding: var(--c15t-space-xs, .25rem) var(--c15t-space-md, 1rem);
862
- border-top: 1px solid var(--c15t-border, #e3e3e3);
992
+ border-top: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
863
993
  background-color: var(--c15t-devtools-surface-muted, #f5f5f5);
864
994
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
865
995
  color: var(--c15t-text-muted, #737373);
866
996
  justify-content: space-between;
867
997
  align-items: center;
998
+ gap: .5rem;
999
+ padding: .5rem .75rem;
868
1000
  display: flex;
869
1001
  }
870
1002
 
871
1003
  .footerStatus-rlb99A {
872
1004
  align-items: center;
873
- gap: var(--c15t-space-xs, .25rem);
1005
+ gap: .375rem;
1006
+ min-width: 0;
874
1007
  display: flex;
875
1008
  }
876
1009
 
1010
+ .footerMeta-Vdtxdk {
1011
+ opacity: .75;
1012
+ white-space: nowrap;
1013
+ }
1014
+
877
1015
  .statusDot-hYJoej {
878
1016
  border-radius: var(--c15t-radius-full, 9999px);
1017
+ flex-shrink: 0;
879
1018
  width: 6px;
880
1019
  height: 6px;
881
1020
  }
@@ -914,6 +1053,7 @@ var __webpack_modules__ = {
914
1053
  font-size: var(--c15t-font-size-sm, .875rem);
915
1054
  color: var(--c15t-text-muted, #737373);
916
1055
  max-width: 280px;
1056
+ line-height: var(--c15t-line-height-normal, 1.5);
917
1057
  }
918
1058
 
919
1059
  @media (prefers-reduced-motion: reduce) {
@@ -930,17 +1070,17 @@ var __webpack_modules__ = {
930
1070
  }
931
1071
 
932
1072
  .dropdownMenu-aKK18l {
933
- min-width: 200px;
934
- padding: var(--c15t-space-xs, .25rem);
935
- border: 1px solid var(--c15t-border, #e3e3e3);
1073
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
936
1074
  border-radius: var(--c15t-radius-lg, .75rem);
937
- background-color: var(--c15t-surface, #fff);
1075
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
1076
+ min-width: 200px;
938
1077
  box-shadow: var(--c15t-shadow-lg, 0 8px 24px #0000001f);
939
1078
  z-index: calc(var(--c15t-devtools-z-index, 99999) + 1);
940
1079
  opacity: 0;
941
1080
  transform-origin: 0 100%;
942
1081
  pointer-events: none;
943
1082
  transition: opacity var(--c15t-duration-fast, .1s) var(--c15t-easing-out, cubic-bezier(.215, .61, .355, 1)), transform var(--c15t-duration-fast, .1s) var(--c15t-easing-out, cubic-bezier(.215, .61, .355, 1));
1083
+ padding: .375rem;
944
1084
  position: fixed;
945
1085
  transform: scale(.95)translateY(8px);
946
1086
  }
@@ -968,34 +1108,35 @@ var __webpack_modules__ = {
968
1108
  }
969
1109
 
970
1110
  .menuItem-kBbHRP {
971
- align-items: center;
972
- gap: var(--c15t-space-sm, .5rem);
973
- width: 100%;
974
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, .75rem);
975
1111
  border-radius: var(--c15t-radius-md, .5rem);
1112
+ width: 100%;
976
1113
  color: var(--c15t-text, #171717);
977
- font-size: var(--c15t-font-size-sm, .875rem);
1114
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
978
1115
  font-weight: var(--c15t-font-weight-medium, 500);
1116
+ line-height: var(--c15t-line-height-tight, 1.25);
979
1117
  text-align: left;
980
1118
  cursor: pointer;
981
1119
  transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
982
1120
  background: none;
983
1121
  border: none;
1122
+ align-items: center;
1123
+ gap: .625rem;
1124
+ padding: .5rem .625rem;
984
1125
  display: flex;
985
1126
  }
986
1127
 
987
1128
  .menuItem-kBbHRP:hover {
988
- background-color: var(--c15t-surface-hover, #f2f2f2);
1129
+ background-color: var(--c15t-devtools-surface-subtle, #f2f2f2);
989
1130
  }
990
1131
 
991
1132
  .menuItem-kBbHRP:focus-visible {
992
- outline: 2px solid var(--c15t-primary, #335cff);
993
- outline-offset: -2px;
1133
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
1134
+ outline: none;
994
1135
  }
995
1136
 
996
1137
  .menuItemIcon-P3pP5K {
997
- width: 20px;
998
- height: 20px;
1138
+ width: 1rem;
1139
+ height: 1rem;
999
1140
  color: var(--c15t-text-muted, #737373);
1000
1141
  flex-shrink: 0;
1001
1142
  }
@@ -1008,6 +1149,7 @@ var __webpack_modules__ = {
1008
1149
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
1009
1150
  color: var(--c15t-text-muted, #737373);
1010
1151
  font-weight: var(--c15t-font-weight-normal, 400);
1152
+ margin-top: .125rem;
1011
1153
  }
1012
1154
 
1013
1155
  .menuItemContent-hBlruV {
@@ -1023,8 +1165,8 @@ var __webpack_modules__ = {
1023
1165
  .menuItemToggleTrack-gDp_f3 {
1024
1166
  background-color: var(--c15t-switch-track, #d9d9d9);
1025
1167
  border-radius: var(--c15t-radius-full, 9999px);
1026
- width: 36px;
1027
- height: 20px;
1168
+ width: 2rem;
1169
+ height: 1.25rem;
1028
1170
  transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
1029
1171
  position: relative;
1030
1172
  }
@@ -1032,21 +1174,22 @@ var __webpack_modules__ = {
1032
1174
  .menuItemToggleThumb-ioqqyc {
1033
1175
  background-color: var(--c15t-switch-thumb, #fff);
1034
1176
  border-radius: var(--c15t-radius-full, 9999px);
1035
- width: 16px;
1036
- height: 16px;
1037
- box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000001a);
1177
+ width: .75rem;
1178
+ height: .75rem;
1179
+ box-shadow: 0 0 0 1px var(--c15t-border, #e3e3e3);
1038
1180
  transition: transform var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
1039
1181
  position: absolute;
1040
- top: 2px;
1182
+ top: 50%;
1041
1183
  left: 2px;
1184
+ transform: translateY(-50%);
1042
1185
  }
1043
1186
 
1044
1187
  .menuItemToggleChecked-K3BPtk .menuItemToggleTrack-gDp_f3 {
1045
- background-color: var(--c15t-switch-track-checked, #335cff);
1188
+ background-color: var(--c15t-switch-track-active, #335cff);
1046
1189
  }
1047
1190
 
1048
1191
  .menuItemToggleChecked-K3BPtk .menuItemToggleThumb-ioqqyc {
1049
- transform: translateX(16px);
1192
+ transform: translate(1rem, -50%);
1050
1193
  }
1051
1194
 
1052
1195
  .menuDivider-JIBdhU {
@@ -1082,9 +1225,11 @@ var __webpack_modules__ = {
1082
1225
  headerLogo: "headerLogo-PxJ_w1",
1083
1226
  closeButton: "closeButton-Yto0Nb",
1084
1227
  closeButtonIcon: "closeButtonIcon-fVlR1I",
1228
+ inlineActionButton: "inlineActionButton-Ky8BmN",
1085
1229
  content: "content-yDMYfG",
1086
1230
  footer: "footer-ESbmwQ",
1087
1231
  footerStatus: "footerStatus-rlb99A",
1232
+ footerMeta: "footerMeta-Vdtxdk",
1088
1233
  statusDot: "statusDot-hYJoej",
1089
1234
  statusConnected: "statusConnected-hPSUgS",
1090
1235
  statusDisconnected: "statusDisconnected-HIpcee",
@@ -1123,55 +1268,63 @@ var __webpack_modules__ = {
1123
1268
  ___CSS_LOADER_EXPORT___.push([
1124
1269
  module.id,
1125
1270
  `.tabList-IyuiBE {
1126
- gap: var(--c15t-space-xs, .25rem);
1127
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, 1rem);
1128
- border-bottom: 1px solid var(--c15t-border, #e3e3e3);
1129
- background-color: var(--c15t-surface, #fff);
1130
- scrollbar-width: none;
1131
- -ms-overflow-style: none;
1271
+ border-bottom: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
1272
+ background-color: var(--c15t-devtools-surface-subtle, #fafafa);
1273
+ align-items: center;
1274
+ gap: .375rem;
1275
+ padding: .75rem;
1132
1276
  display: flex;
1133
- overflow-x: auto;
1134
1277
  }
1135
1278
 
1136
- .tabList-IyuiBE::-webkit-scrollbar {
1137
- display: none;
1279
+ .tabStrip-_KrWe4 {
1280
+ align-items: center;
1281
+ gap: var(--c15t-space-xs, .25rem);
1282
+ flex: auto;
1283
+ min-width: 0;
1284
+ display: flex;
1285
+ overflow: hidden;
1138
1286
  }
1139
1287
 
1140
1288
  .tab-yfDEqg {
1141
- align-items: center;
1142
- gap: var(--c15t-space-xs, .25rem);
1143
- padding: var(--c15t-space-xs, .25rem) var(--c15t-space-sm, .5rem);
1144
1289
  border-radius: var(--c15t-radius-md, .5rem);
1290
+ min-height: 1.875rem;
1145
1291
  color: var(--c15t-text-muted, #737373);
1146
- font-family: inherit;
1292
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
1147
1293
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
1148
1294
  font-weight: var(--c15t-font-weight-medium, 500);
1295
+ line-height: var(--c15t-line-height-tight, 1.25);
1149
1296
  cursor: pointer;
1150
1297
  white-space: nowrap;
1151
- transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
1298
+ transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), border-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), box-shadow var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
1152
1299
  background-color: #0000;
1153
- border: none;
1300
+ border: 1px solid #0000;
1301
+ flex-shrink: 0;
1302
+ align-items: center;
1303
+ gap: .375rem;
1304
+ padding: .25rem .625rem;
1154
1305
  display: flex;
1155
1306
  }
1156
1307
 
1157
1308
  .tab-yfDEqg:hover {
1158
- background-color: var(--c15t-surface-hover, #f7f7f7);
1309
+ background-color: var(--c15t-devtools-surface-muted, #f7f7f7);
1159
1310
  color: var(--c15t-text, #171717);
1160
1311
  }
1161
1312
 
1162
1313
  .tab-yfDEqg:focus-visible {
1163
- outline: 2px solid var(--c15t-primary, #335cff);
1164
- outline-offset: 1px;
1314
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
1315
+ outline: none;
1165
1316
  }
1166
1317
 
1167
1318
  .tabActive-r4hing {
1168
- background-color: var(--c15t-primary, #335cff);
1169
- color: var(--c15t-text-on-primary, #fff);
1319
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
1320
+ border-color: var(--c15t-devtools-border-strong, #e3e3e3);
1321
+ color: var(--c15t-text, #171717);
1322
+ box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000000d);
1170
1323
  }
1171
1324
 
1172
1325
  .tabActive-r4hing:hover {
1173
- background-color: var(--c15t-primary-hover, #03f);
1174
- color: var(--c15t-text-on-primary, #fff);
1326
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
1327
+ color: var(--c15t-text, #171717);
1175
1328
  }
1176
1329
 
1177
1330
  .tabIcon-U9tnu0 {
@@ -1180,6 +1333,131 @@ var __webpack_modules__ = {
1180
1333
  height: 14px;
1181
1334
  }
1182
1335
 
1336
+ .tabHidden-HBXYSd {
1337
+ display: none;
1338
+ }
1339
+
1340
+ .overflowContainer-TTw9DO {
1341
+ flex-shrink: 0;
1342
+ position: relative;
1343
+ }
1344
+
1345
+ .overflowContainerHidden-sQa_XZ {
1346
+ display: none;
1347
+ }
1348
+
1349
+ .overflowButton-tKq4FF {
1350
+ border-radius: var(--c15t-radius-md, .5rem);
1351
+ width: 1.875rem;
1352
+ height: 1.875rem;
1353
+ color: var(--c15t-text-muted, #737373);
1354
+ cursor: pointer;
1355
+ transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), border-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
1356
+ background-color: #0000;
1357
+ border: 1px solid #0000;
1358
+ justify-content: center;
1359
+ align-items: center;
1360
+ padding: 0;
1361
+ display: inline-flex;
1362
+ }
1363
+
1364
+ .overflowButton-tKq4FF:hover {
1365
+ background-color: var(--c15t-devtools-surface-muted, #f7f7f7);
1366
+ color: var(--c15t-text, #171717);
1367
+ }
1368
+
1369
+ .overflowButton-tKq4FF:focus-visible {
1370
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
1371
+ outline: none;
1372
+ }
1373
+
1374
+ .overflowButtonIcon-FSurfC {
1375
+ justify-content: center;
1376
+ align-items: center;
1377
+ width: 14px;
1378
+ height: 14px;
1379
+ display: inline-flex;
1380
+ }
1381
+
1382
+ .overflowMenu-TST0eZ {
1383
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
1384
+ border-radius: var(--c15t-radius-md, .5rem);
1385
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
1386
+ min-width: 10rem;
1387
+ box-shadow: var(--c15t-shadow-md, 0 4px 12px #00000014);
1388
+ opacity: 0;
1389
+ transform-origin: 100% 0;
1390
+ pointer-events: none;
1391
+ z-index: 10;
1392
+ transition: opacity var(--c15t-duration-fast, .1s) var(--c15t-easing-out, cubic-bezier(.215, .61, .355, 1)), transform var(--c15t-duration-fast, .1s) var(--c15t-easing-out, cubic-bezier(.215, .61, .355, 1));
1393
+ flex-direction: column;
1394
+ gap: .125rem;
1395
+ padding: .3125rem;
1396
+ display: flex;
1397
+ position: absolute;
1398
+ top: calc(100% + .375rem);
1399
+ right: 0;
1400
+ transform: translateY(-4px)scale(.98);
1401
+ }
1402
+
1403
+ .overflowMenu-TST0eZ[data-state="open"] {
1404
+ opacity: 1;
1405
+ pointer-events: auto;
1406
+ transform: translateY(0)scale(1);
1407
+ }
1408
+
1409
+ .overflowItem-y5Pz7k {
1410
+ border-radius: var(--c15t-radius-sm, .375rem);
1411
+ min-height: 1.75rem;
1412
+ color: var(--c15t-text, #171717);
1413
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
1414
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
1415
+ font-weight: var(--c15t-font-weight-medium, 500);
1416
+ line-height: var(--c15t-line-height-tight, 1.25);
1417
+ text-align: left;
1418
+ cursor: pointer;
1419
+ white-space: nowrap;
1420
+ transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1)), color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
1421
+ background-color: #0000;
1422
+ border: none;
1423
+ align-items: center;
1424
+ gap: .5rem;
1425
+ padding: .3125rem .5rem;
1426
+ display: inline-flex;
1427
+ }
1428
+
1429
+ .overflowItem-y5Pz7k:hover {
1430
+ background-color: var(--c15t-devtools-surface-subtle, #fafafa);
1431
+ }
1432
+
1433
+ .overflowItem-y5Pz7k:focus-visible {
1434
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
1435
+ outline: none;
1436
+ }
1437
+
1438
+ .overflowItemActive-mzVG1T {
1439
+ background-color: var(--c15t-devtools-accent-soft, #ebefff);
1440
+ color: var(--c15t-text, #171717);
1441
+ }
1442
+
1443
+ .overflowItemDisabled-dcHX3K {
1444
+ opacity: .5;
1445
+ cursor: not-allowed;
1446
+ }
1447
+
1448
+ .overflowItemIcon-fz291V {
1449
+ flex-shrink: 0;
1450
+ justify-content: center;
1451
+ align-items: center;
1452
+ width: 14px;
1453
+ height: 14px;
1454
+ display: inline-flex;
1455
+ }
1456
+
1457
+ .overflowItemHidden-k4aawi {
1458
+ display: none;
1459
+ }
1460
+
1183
1461
  .tabDisabled-lDuv5l {
1184
1462
  opacity: .5;
1185
1463
  cursor: not-allowed;
@@ -1200,7 +1478,7 @@ var __webpack_modules__ = {
1200
1478
  }
1201
1479
 
1202
1480
  @media (prefers-reduced-motion: reduce) {
1203
- .tab-yfDEqg {
1481
+ .tab-yfDEqg, .overflowButton-tKq4FF, .overflowMenu-TST0eZ, .overflowItem-y5Pz7k {
1204
1482
  transition: none;
1205
1483
  }
1206
1484
  }
@@ -1216,9 +1494,21 @@ var __webpack_modules__ = {
1216
1494
  ]);
1217
1495
  ___CSS_LOADER_EXPORT___.locals = {
1218
1496
  tabList: "tabList-IyuiBE",
1497
+ tabStrip: "tabStrip-_KrWe4",
1219
1498
  tab: "tab-yfDEqg",
1220
1499
  tabActive: "tabActive-r4hing",
1221
1500
  tabIcon: "tabIcon-U9tnu0",
1501
+ tabHidden: "tabHidden-HBXYSd",
1502
+ overflowContainer: "overflowContainer-TTw9DO",
1503
+ overflowContainerHidden: "overflowContainerHidden-sQa_XZ",
1504
+ overflowButton: "overflowButton-tKq4FF",
1505
+ overflowButtonIcon: "overflowButtonIcon-FSurfC",
1506
+ overflowMenu: "overflowMenu-TST0eZ",
1507
+ overflowItem: "overflowItem-y5Pz7k",
1508
+ overflowItemActive: "overflowItemActive-mzVG1T",
1509
+ overflowItemDisabled: "overflowItemDisabled-dcHX3K",
1510
+ overflowItemIcon: "overflowItemIcon-fz291V",
1511
+ overflowItemHidden: "overflowItemHidden-k4aawi",
1222
1512
  tabDisabled: "tabDisabled-lDuv5l",
1223
1513
  tabPanel: "tabPanel-QKO8FX",
1224
1514
  tabPanelActive: "tabPanelActive-mrNlGE"
@@ -1242,6 +1532,15 @@ var __webpack_modules__ = {
1242
1532
  --c15t-devtools-button-size: 40px;
1243
1533
  --c15t-devtools-z-index: 99999;
1244
1534
  --c15t-devtools-surface-muted: var(--c15t-surface-hover, #f7f7f7);
1535
+ --c15t-devtools-surface-subtle: #fafafa;
1536
+ --c15t-devtools-surface-elevated: var(--c15t-surface, #fff);
1537
+ --c15t-devtools-border-strong: var(--c15t-border, #e3e3e3);
1538
+ --c15t-devtools-code-surface: #f7f7f7;
1539
+ --c15t-devtools-accent-soft: #ebefff;
1540
+ --c15t-devtools-focus-ring: var(--c15t-primary, #335cff);
1541
+ --c15t-devtools-text-muted: var(--c15t-text-muted, #737373);
1542
+ --c15t-devtools-font-size-sm: var(--c15t-font-size-sm, .875rem);
1543
+ --c15t-surface-muted: var(--c15t-devtools-surface-muted, #f7f7f7);
1245
1544
  --c15t-devtools-font-size-xs: .75rem;
1246
1545
  --c15t-devtools-badge-success: #21c45d;
1247
1546
  --c15t-devtools-badge-success-bg: #e4fbed;
@@ -1255,8 +1554,37 @@ var __webpack_modules__ = {
1255
1554
  --c15t-devtools-badge-neutral-bg: #f0f0f0;
1256
1555
  }
1257
1556
 
1557
+ :is(:global(.c15t-light), :global(.light)) {
1558
+ --c15t-devtools-surface-muted: var(--c15t-surface-hover, #f7f7f7);
1559
+ --c15t-devtools-surface-subtle: #fafafa;
1560
+ --c15t-devtools-surface-elevated: var(--c15t-surface, #fff);
1561
+ --c15t-devtools-border-strong: var(--c15t-border, #e3e3e3);
1562
+ --c15t-devtools-code-surface: #f7f7f7;
1563
+ --c15t-devtools-accent-soft: #ebefff;
1564
+ --c15t-devtools-badge-success-bg: #e4fbed;
1565
+ --c15t-devtools-badge-error-bg: #fde7e7;
1566
+ --c15t-devtools-badge-warning-bg: #fef7dc;
1567
+ --c15t-devtools-badge-info-bg: #dcebfe;
1568
+ --c15t-devtools-badge-neutral-bg: #f0f0f0;
1569
+ }
1570
+
1571
+ @supports (color: color-mix(in srgb, white, black)) {
1572
+ :root {
1573
+ --c15t-devtools-surface-muted: color-mix(in srgb, var(--c15t-surface-hover, #f7f7f7) 85%, var(--c15t-surface, #fff));
1574
+ --c15t-devtools-surface-subtle: color-mix(in srgb, var(--c15t-surface-hover, #f7f7f7) 55%, var(--c15t-surface, #fff));
1575
+ --c15t-devtools-border-strong: color-mix(in srgb, var(--c15t-border, #e3e3e3) 80%, var(--c15t-text-muted, #737373));
1576
+ --c15t-devtools-code-surface: color-mix(in srgb, var(--c15t-surface-hover, #f7f7f7) 70%, var(--c15t-surface, #fff));
1577
+ --c15t-devtools-accent-soft: color-mix(in srgb, var(--c15t-primary, #335cff) 12%, transparent);
1578
+ }
1579
+ }
1580
+
1258
1581
  :is(:global(.c15t-dark), :global(.dark)) {
1259
1582
  --c15t-devtools-surface-muted: var(--c15t-surface-hover, #292929);
1583
+ --c15t-devtools-surface-subtle: #242424;
1584
+ --c15t-devtools-surface-elevated: var(--c15t-surface, #1a1a1a);
1585
+ --c15t-devtools-border-strong: var(--c15t-border, #3d3d3d);
1586
+ --c15t-devtools-code-surface: #212121;
1587
+ --c15t-devtools-accent-soft: #335cff33;
1260
1588
  --c15t-devtools-badge-success-bg: #21c45d33;
1261
1589
  --c15t-devtools-badge-error-bg: #ef434333;
1262
1590
  --c15t-devtools-badge-warning-bg: #f59f0a33;
@@ -1265,8 +1593,13 @@ var __webpack_modules__ = {
1265
1593
  }
1266
1594
 
1267
1595
  @media (prefers-color-scheme: dark) {
1268
- :root {
1596
+ :global(:root:not(.light):not(.c15t-light)) {
1269
1597
  --c15t-devtools-surface-muted: var(--c15t-surface-hover, #292929);
1598
+ --c15t-devtools-surface-subtle: #242424;
1599
+ --c15t-devtools-surface-elevated: var(--c15t-surface, #1a1a1a);
1600
+ --c15t-devtools-border-strong: var(--c15t-border, #3d3d3d);
1601
+ --c15t-devtools-code-surface: #212121;
1602
+ --c15t-devtools-accent-soft: #335cff33;
1270
1603
  --c15t-devtools-badge-success-bg: #21c45d33;
1271
1604
  --c15t-devtools-badge-error-bg: #ef434333;
1272
1605
  --c15t-devtools-badge-warning-bg: #f59f0a33;
@@ -1579,7 +1912,7 @@ var __webpack_exports__ = {};
1579
1912
  panel_module_options.insertStyleElement = insertStyleElement_default();
1580
1913
  injectStylesIntoStyleTag_default()(panel_module.A, panel_module_options);
1581
1914
  panel_module.A && panel_module.A.locals && panel_module.A.locals;
1582
- '[data-c15t-trigger], [aria-label*="privacy settings"], [aria-label*="preference"]';
1915
+ '[data-c15t-trigger], [aria-label*="privacy settings" i], [aria-label*="preference" i]';
1583
1916
  function createElement(options = {}) {
1584
1917
  const { tag = 'div', text, html, children, className, id, style, dataset, onClick, onMouseEnter, onMouseLeave, onKeyDown, onKeyUp, onFocus, onBlur, onChange, onInput, onAnimationEnd, onTransitionEnd, ...attrs } = options;
1585
1918
  const element = document.createElement(tag);
@@ -1706,6 +2039,11 @@ var __webpack_exports__ = {};
1706
2039
  const EVENTS_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1707
2040
  <path d="M12 20h9"></path>
1708
2041
  <path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"></path>
2042
+ </svg>`;
2043
+ const MORE_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
2044
+ <circle cx="12" cy="5" r="1.75"></circle>
2045
+ <circle cx="12" cy="12" r="1.75"></circle>
2046
+ <circle cx="12" cy="19" r="1.75"></circle>
1709
2047
  </svg>`;
1710
2048
  const TABS = [
1711
2049
  {
@@ -1742,12 +2080,56 @@ var __webpack_exports__ = {};
1742
2080
  function tabs_createTabs(options) {
1743
2081
  const { onTabChange, disabledTabs = [] } = options;
1744
2082
  let activeTab = options.activeTab;
2083
+ let isOverflowMenuOpen = false;
2084
+ let visibleTabIds = [];
2085
+ let hiddenTabIds = [];
1745
2086
  const tabButtons = new Map();
2087
+ const overflowButtons = new Map();
1746
2088
  const tabList = renderer_div({
1747
- className: styles_tabs_module.tabList,
2089
+ className: styles_tabs_module.tabList
2090
+ });
2091
+ const tabStrip = renderer_div({
2092
+ className: styles_tabs_module.tabStrip,
1748
2093
  role: 'tablist',
1749
2094
  ariaLabel: 'DevTools tabs'
1750
2095
  });
2096
+ tabList.appendChild(tabStrip);
2097
+ const overflowMenu = renderer_div({
2098
+ className: styles_tabs_module.overflowMenu,
2099
+ role: 'menu',
2100
+ ariaLabel: 'All tabs'
2101
+ });
2102
+ overflowMenu.dataset.state = 'closed';
2103
+ const overflowButton = renderer_button({
2104
+ className: styles_tabs_module.overflowButton,
2105
+ ariaLabel: 'More tabs',
2106
+ ariaExpanded: 'false',
2107
+ onClick: ()=>toggleOverflowMenu(),
2108
+ onKeyDown: (e)=>{
2109
+ if ('ArrowDown' === e.key || 'Enter' === e.key || ' ' === e.key) {
2110
+ e.preventDefault();
2111
+ openOverflowMenu();
2112
+ focusFirstEnabledOverflowItem();
2113
+ }
2114
+ }
2115
+ });
2116
+ overflowButton.setAttribute('aria-haspopup', 'menu');
2117
+ const overflowIcon = renderer_div({
2118
+ className: styles_tabs_module.overflowButtonIcon
2119
+ });
2120
+ overflowIcon.appendChild(renderer_createSvgElement(MORE_ICON, {
2121
+ width: 14,
2122
+ height: 14
2123
+ }));
2124
+ overflowButton.appendChild(overflowIcon);
2125
+ const overflowContainer = renderer_div({
2126
+ className: styles_tabs_module.overflowContainer,
2127
+ children: [
2128
+ overflowButton,
2129
+ overflowMenu
2130
+ ]
2131
+ });
2132
+ tabList.appendChild(overflowContainer);
1751
2133
  for (const tab of TABS){
1752
2134
  const isActive = tab.id === activeTab;
1753
2135
  const isDisabled = disabledTabs.includes(tab.id);
@@ -1761,6 +2143,7 @@ var __webpack_exports__ = {};
1761
2143
  disabled: isDisabled,
1762
2144
  onClick: ()=>{
1763
2145
  if (!isDisabled) {
2146
+ closeOverflowMenu();
1764
2147
  setActiveTab(tab.id);
1765
2148
  onTabChange(tab.id);
1766
2149
  }
@@ -1777,16 +2160,193 @@ var __webpack_exports__ = {};
1777
2160
  tabButton.appendChild(iconWrapper);
1778
2161
  tabButton.appendChild(document.createTextNode(tab.label));
1779
2162
  tabButtons.set(tab.id, tabButton);
1780
- tabList.appendChild(tabButton);
1781
- }
1782
- function handleKeyDown(e, currentTab) {
1783
- const tabIds = TABS.map((t)=>t.id);
1784
- const enabledTabIds = tabIds.filter((id)=>!disabledTabs.includes(id));
1785
- const currentIndex = enabledTabIds.indexOf(currentTab);
1786
- let newIndex = currentIndex;
1787
- switch(e.key){
1788
- case 'ArrowLeft':
1789
- newIndex = currentIndex > 0 ? currentIndex - 1 : enabledTabIds.length - 1;
2163
+ tabStrip.appendChild(tabButton);
2164
+ const overflowItem = renderer_button({
2165
+ className: `${styles_tabs_module.overflowItem} ${isActive ? styles_tabs_module.overflowItemActive : ''} ${isDisabled ? styles_tabs_module.overflowItemDisabled : ''}`,
2166
+ role: 'menuitemradio',
2167
+ ariaChecked: isActive ? 'true' : 'false',
2168
+ disabled: isDisabled,
2169
+ onClick: ()=>{
2170
+ if (!isDisabled) {
2171
+ setActiveTab(tab.id);
2172
+ onTabChange(tab.id);
2173
+ closeOverflowMenu();
2174
+ tabButtons.get(tab.id)?.focus();
2175
+ }
2176
+ },
2177
+ onKeyDown: (e)=>handleOverflowKeyDown(e, tab.id)
2178
+ });
2179
+ const overflowItemIcon = renderer_div({
2180
+ className: styles_tabs_module.overflowItemIcon
2181
+ });
2182
+ overflowItemIcon.appendChild(renderer_createSvgElement(tab.icon, {
2183
+ width: 14,
2184
+ height: 14
2185
+ }));
2186
+ overflowItem.appendChild(overflowItemIcon);
2187
+ overflowItem.appendChild(document.createTextNode(tab.label));
2188
+ overflowButtons.set(tab.id, overflowItem);
2189
+ overflowMenu.appendChild(overflowItem);
2190
+ }
2191
+ function applyActiveState(tab) {
2192
+ for (const [tabId, tabButton] of tabButtons){
2193
+ const isActive = tabId === tab;
2194
+ if (styles_tabs_module.tabActive) tabButton.classList.toggle(styles_tabs_module.tabActive, isActive);
2195
+ tabButton.setAttribute('aria-selected', isActive ? 'true' : 'false');
2196
+ tabButton.tabIndex = isActive ? 0 : -1;
2197
+ }
2198
+ for (const [tabId, overflowItem] of overflowButtons){
2199
+ const isActive = tabId === tab;
2200
+ if (styles_tabs_module.overflowItemActive) overflowItem.classList.toggle(styles_tabs_module.overflowItemActive, isActive);
2201
+ overflowItem.setAttribute('aria-checked', isActive ? 'true' : 'false');
2202
+ }
2203
+ }
2204
+ function updateVisibleTabs() {
2205
+ const allTabIds = TABS.map((t)=>t.id);
2206
+ const iabEnabled = !disabledTabs.includes('iab');
2207
+ const preferredSecondTab = iabEnabled ? 'iab' : 'consents';
2208
+ const overflowSecondTab = iabEnabled ? 'consents' : 'iab';
2209
+ const showOverflowSecondTabInStrip = activeTab === overflowSecondTab;
2210
+ const stripSecondTab = showOverflowSecondTabInStrip ? overflowSecondTab : preferredSecondTab;
2211
+ const forcedOverflowTab = showOverflowSecondTabInStrip ? preferredSecondTab : overflowSecondTab;
2212
+ const layoutTabIds = [
2213
+ 'location',
2214
+ stripSecondTab,
2215
+ "scripts",
2216
+ 'actions',
2217
+ 'events',
2218
+ forcedOverflowTab
2219
+ ];
2220
+ const forcedOverflowTabIds = new Set();
2221
+ forcedOverflowTabIds.add(forcedOverflowTab);
2222
+ for (const [index, tabId] of layoutTabIds.entries()){
2223
+ const tabButton = tabButtons.get(tabId);
2224
+ if (tabButton) tabButton.style.order = String(index);
2225
+ const overflowItem = overflowButtons.get(tabId);
2226
+ if (overflowItem) overflowItem.style.order = String(index);
2227
+ }
2228
+ for (const tabId of allTabIds){
2229
+ const tabButton = tabButtons.get(tabId);
2230
+ if (tabButton && styles_tabs_module.tabHidden) tabButton.classList.remove(styles_tabs_module.tabHidden);
2231
+ }
2232
+ if (styles_tabs_module.overflowContainerHidden) overflowContainer.classList.remove(styles_tabs_module.overflowContainerHidden);
2233
+ const stripGap = Number.parseFloat(getComputedStyle(tabStrip).gap || '0');
2234
+ const calculateVisibleTabs = (availableWidth)=>{
2235
+ if (availableWidth <= 0) return [];
2236
+ const nextVisible = [];
2237
+ let usedWidth = 0;
2238
+ for (const tabId of layoutTabIds){
2239
+ if (forcedOverflowTabIds.has(tabId)) continue;
2240
+ const tabButton = tabButtons.get(tabId);
2241
+ if (!tabButton) continue;
2242
+ const width = tabButton.getBoundingClientRect().width;
2243
+ const nextUsed = 0 === nextVisible.length ? width : usedWidth + stripGap + width;
2244
+ if (nextUsed <= availableWidth) {
2245
+ nextVisible.push(tabId);
2246
+ usedWidth = nextUsed;
2247
+ } else break;
2248
+ }
2249
+ return nextVisible;
2250
+ };
2251
+ const measureStripWidth = ()=>tabStrip.getBoundingClientRect().width;
2252
+ const showOverflowContainer = ()=>{
2253
+ if (styles_tabs_module.overflowContainerHidden) overflowContainer.classList.remove(styles_tabs_module.overflowContainerHidden);
2254
+ };
2255
+ const hideOverflowContainer = ()=>{
2256
+ if (styles_tabs_module.overflowContainerHidden) overflowContainer.classList.add(styles_tabs_module.overflowContainerHidden);
2257
+ };
2258
+ const measureVisibleWidth = (tabIds)=>{
2259
+ let width = 0;
2260
+ for (const [index, tabId] of tabIds.entries()){
2261
+ const tabButton = tabButtons.get(tabId);
2262
+ if (tabButton) {
2263
+ width += tabButton.getBoundingClientRect().width;
2264
+ if (index > 0) width += stripGap;
2265
+ }
2266
+ }
2267
+ return width;
2268
+ };
2269
+ if (0 === forcedOverflowTabIds.size) {
2270
+ hideOverflowContainer();
2271
+ const visibleWithoutOverflow = calculateVisibleTabs(measureStripWidth());
2272
+ if (visibleWithoutOverflow.length === layoutTabIds.length) visibleTabIds = visibleWithoutOverflow;
2273
+ else {
2274
+ showOverflowContainer();
2275
+ visibleTabIds = calculateVisibleTabs(measureStripWidth());
2276
+ }
2277
+ } else {
2278
+ showOverflowContainer();
2279
+ const withOverflow = calculateVisibleTabs(measureStripWidth());
2280
+ visibleTabIds = withOverflow.length > 0 ? withOverflow : [
2281
+ activeTab
2282
+ ];
2283
+ }
2284
+ if (!visibleTabIds.includes(activeTab) && !disabledTabs.includes(activeTab)) if (visibleTabIds.length > 0) visibleTabIds[visibleTabIds.length - 1] = activeTab;
2285
+ else visibleTabIds = [
2286
+ activeTab
2287
+ ];
2288
+ visibleTabIds = [
2289
+ ...new Set(visibleTabIds)
2290
+ ];
2291
+ const maxStripWidth = measureStripWidth();
2292
+ while(visibleTabIds.length > 1 && measureVisibleWidth(visibleTabIds) > maxStripWidth + 0.5){
2293
+ let removeIndex = visibleTabIds.length - 1;
2294
+ if (visibleTabIds[removeIndex] === activeTab) removeIndex = Math.max(0, removeIndex - 1);
2295
+ visibleTabIds.splice(removeIndex, 1);
2296
+ }
2297
+ hiddenTabIds = layoutTabIds.filter((tabId)=>!visibleTabIds.includes(tabId) || forcedOverflowTabIds.has(tabId) && tabId !== activeTab);
2298
+ for (const tabId of allTabIds){
2299
+ const tabButton = tabButtons.get(tabId);
2300
+ if (tabButton) {
2301
+ if (styles_tabs_module.tabHidden) tabButton.classList.toggle(styles_tabs_module.tabHidden, hiddenTabIds.includes(tabId));
2302
+ }
2303
+ }
2304
+ for (const tabId of allTabIds){
2305
+ const overflowItem = overflowButtons.get(tabId);
2306
+ if (overflowItem) {
2307
+ if (styles_tabs_module.overflowItemHidden) overflowItem.classList.toggle(styles_tabs_module.overflowItemHidden, !hiddenTabIds.includes(tabId));
2308
+ }
2309
+ }
2310
+ if (styles_tabs_module.overflowContainerHidden) overflowContainer.classList.toggle(styles_tabs_module.overflowContainerHidden, 0 === hiddenTabIds.length);
2311
+ if (0 === hiddenTabIds.length) closeOverflowMenu();
2312
+ }
2313
+ function focusFirstEnabledOverflowItem() {
2314
+ const firstEnabled = hiddenTabIds.find((tabId)=>!disabledTabs.includes(tabId));
2315
+ if (firstEnabled) overflowButtons.get(firstEnabled)?.focus();
2316
+ }
2317
+ function openOverflowMenu() {
2318
+ if (isOverflowMenuOpen || 0 === hiddenTabIds.length) return;
2319
+ isOverflowMenuOpen = true;
2320
+ overflowMenu.dataset.state = 'open';
2321
+ overflowButton.setAttribute('aria-expanded', 'true');
2322
+ document.addEventListener('click', handleOutsideClick);
2323
+ document.addEventListener('keydown', handleEscapeKey);
2324
+ }
2325
+ function closeOverflowMenu() {
2326
+ if (!isOverflowMenuOpen) return;
2327
+ isOverflowMenuOpen = false;
2328
+ overflowMenu.dataset.state = 'closed';
2329
+ overflowButton.setAttribute('aria-expanded', 'false');
2330
+ document.removeEventListener('click', handleOutsideClick);
2331
+ document.removeEventListener('keydown', handleEscapeKey);
2332
+ }
2333
+ function toggleOverflowMenu() {
2334
+ if (isOverflowMenuOpen) closeOverflowMenu();
2335
+ else openOverflowMenu();
2336
+ }
2337
+ function handleOutsideClick(e) {
2338
+ if (!overflowContainer.contains(e.target)) closeOverflowMenu();
2339
+ }
2340
+ function handleEscapeKey(e) {
2341
+ if ('Escape' === e.key) closeOverflowMenu();
2342
+ }
2343
+ function handleKeyDown(e, currentTab) {
2344
+ const enabledTabIds = visibleTabIds.filter((tabId)=>!disabledTabs.includes(tabId));
2345
+ const currentIndex = enabledTabIds.indexOf(currentTab);
2346
+ let newIndex = currentIndex;
2347
+ switch(e.key){
2348
+ case 'ArrowLeft':
2349
+ newIndex = currentIndex > 0 ? currentIndex - 1 : enabledTabIds.length - 1;
1790
2350
  break;
1791
2351
  case 'ArrowRight':
1792
2352
  newIndex = currentIndex < enabledTabIds.length - 1 ? currentIndex + 1 : 0;
@@ -1808,23 +2368,152 @@ var __webpack_exports__ = {};
1808
2368
  tabButtons.get(newTab)?.focus();
1809
2369
  }
1810
2370
  }
2371
+ function handleOverflowKeyDown(e, currentTab) {
2372
+ const enabledTabIds = hiddenTabIds.filter((tabId)=>!disabledTabs.includes(tabId));
2373
+ const currentIndex = enabledTabIds.indexOf(currentTab);
2374
+ if ('Escape' === e.key) {
2375
+ e.preventDefault();
2376
+ closeOverflowMenu();
2377
+ overflowButton.focus();
2378
+ return;
2379
+ }
2380
+ let newIndex = currentIndex;
2381
+ switch(e.key){
2382
+ case 'ArrowDown':
2383
+ newIndex = (currentIndex + 1) % enabledTabIds.length;
2384
+ break;
2385
+ case 'ArrowUp':
2386
+ newIndex = currentIndex > 0 ? currentIndex - 1 : enabledTabIds.length - 1;
2387
+ break;
2388
+ default:
2389
+ return;
2390
+ }
2391
+ e.preventDefault();
2392
+ const newTab = enabledTabIds[newIndex];
2393
+ if (newTab) overflowButtons.get(newTab)?.focus();
2394
+ }
1811
2395
  function setActiveTab(tab) {
1812
2396
  activeTab = tab;
1813
- for (const [tabId, tabButton] of tabButtons){
1814
- const isActive = tabId === tab;
1815
- if (styles_tabs_module.tabActive) tabButton.classList.toggle(styles_tabs_module.tabActive, isActive);
1816
- tabButton.setAttribute('aria-selected', isActive ? 'true' : 'false');
1817
- tabButton.tabIndex = isActive ? 0 : -1;
1818
- }
2397
+ applyActiveState(tab);
2398
+ updateVisibleTabs();
1819
2399
  }
2400
+ const handleWindowResize = ()=>{
2401
+ updateVisibleTabs();
2402
+ };
2403
+ let resizeObserver = null;
2404
+ if ('undefined' != typeof ResizeObserver) {
2405
+ resizeObserver = new ResizeObserver(()=>{
2406
+ updateVisibleTabs();
2407
+ });
2408
+ resizeObserver.observe(tabList);
2409
+ } else window.addEventListener('resize', handleWindowResize);
2410
+ applyActiveState(activeTab);
2411
+ requestAnimationFrame(()=>{
2412
+ updateVisibleTabs();
2413
+ });
1820
2414
  return {
1821
2415
  element: tabList,
1822
2416
  setActiveTab,
1823
2417
  destroy: ()=>{
2418
+ closeOverflowMenu();
2419
+ if (resizeObserver) {
2420
+ resizeObserver.disconnect();
2421
+ resizeObserver = null;
2422
+ } else window.removeEventListener('resize', handleWindowResize);
1824
2423
  tabButtons.clear();
2424
+ overflowButtons.clear();
1825
2425
  }
1826
2426
  };
1827
2427
  }
2428
+ function debug_bundle_createDebugBundle(payload) {
2429
+ const { namespace, devToolsState, connection, recentEvents, storeState } = payload;
2430
+ const bundle = {
2431
+ generatedAt: new Date().toISOString(),
2432
+ namespace,
2433
+ devToolsState,
2434
+ connection,
2435
+ recentEvents,
2436
+ storeState,
2437
+ overrides: storeState?.overrides ?? null,
2438
+ iab: storeState?.iab ? {
2439
+ tcString: (storeState?.iab).tcString ?? null,
2440
+ purposeCount: Object.keys((storeState?.iab).purposeConsents ?? {}).length,
2441
+ vendorCount: Object.keys((storeState?.iab).vendorConsents ?? {}).length
2442
+ } : null
2443
+ };
2444
+ return JSON.stringify(bundle, null, 2);
2445
+ }
2446
+ function debug_bundle_sanitizeStoreState(state) {
2447
+ if (!state) return null;
2448
+ try {
2449
+ return JSON.parse(JSON.stringify(state, (_key, value)=>'function' == typeof value ? void 0 : value));
2450
+ } catch {
2451
+ return {
2452
+ error: 'Unable to serialize store state'
2453
+ };
2454
+ }
2455
+ }
2456
+ function debug_bundle_downloadDebugBundle(content) {
2457
+ const blob = new Blob([
2458
+ content
2459
+ ], {
2460
+ type: 'application/json'
2461
+ });
2462
+ const url = URL.createObjectURL(blob);
2463
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
2464
+ const anchor = document.createElement('a');
2465
+ anchor.href = url;
2466
+ anchor.download = `c15t-debug-bundle-${timestamp}.json`;
2467
+ anchor.click();
2468
+ URL.revokeObjectURL(url);
2469
+ }
2470
+ const DEVTOOLS_OVERRIDES_STORAGE_KEY = 'c15t-devtools-overrides';
2471
+ function normalizeStringValue(value) {
2472
+ if ('string' != typeof value) return;
2473
+ const normalized = value.trim();
2474
+ return normalized.length > 0 ? normalized : void 0;
2475
+ }
2476
+ function normalizeBooleanValue(value) {
2477
+ return 'boolean' == typeof value ? value : void 0;
2478
+ }
2479
+ function normalizeOverrides(value) {
2480
+ if (!value || 'object' != typeof value) return null;
2481
+ const source = value;
2482
+ const overrides = {
2483
+ country: normalizeStringValue(source.country),
2484
+ region: normalizeStringValue(source.region),
2485
+ language: normalizeStringValue(source.language),
2486
+ gpc: normalizeBooleanValue(source.gpc)
2487
+ };
2488
+ return hasPersistedOverrides(overrides) ? overrides : null;
2489
+ }
2490
+ function hasPersistedOverrides(overrides) {
2491
+ return Boolean(overrides.country || overrides.region || overrides.language || void 0 !== overrides.gpc);
2492
+ }
2493
+ function override_storage_loadPersistedOverrides(storageKey = DEVTOOLS_OVERRIDES_STORAGE_KEY) {
2494
+ if ('undefined' == typeof window) return null;
2495
+ try {
2496
+ const stored = localStorage.getItem(storageKey);
2497
+ if (!stored) return null;
2498
+ const parsed = JSON.parse(stored);
2499
+ return normalizeOverrides(parsed);
2500
+ } catch {
2501
+ return null;
2502
+ }
2503
+ }
2504
+ function override_storage_persistOverrides(overrides, storageKey = DEVTOOLS_OVERRIDES_STORAGE_KEY) {
2505
+ if ('undefined' == typeof window) return;
2506
+ try {
2507
+ if (!hasPersistedOverrides(overrides)) return void localStorage.removeItem(storageKey);
2508
+ localStorage.setItem(storageKey, JSON.stringify(overrides));
2509
+ } catch {}
2510
+ }
2511
+ function override_storage_clearPersistedOverrides(storageKey = DEVTOOLS_OVERRIDES_STORAGE_KEY) {
2512
+ if ('undefined' == typeof window) return;
2513
+ try {
2514
+ localStorage.removeItem(storageKey);
2515
+ } catch {}
2516
+ }
1828
2517
  var components_module = __webpack_require__("../../node_modules/.bun/@rsbuild+core@1.6.12/node_modules/@rsbuild/core/compiled/css-loader/index.js??ruleSet[1].rules[1].use[1]!builtin:lightningcss-loader??ruleSet[1].rules[1].use[2]!./src/styles/components.module.css");
1829
2518
  var components_module_options = {};
1830
2519
  components_module_options.styleTagTransform = styleTagTransform_default();
@@ -1892,31 +2581,19 @@ var __webpack_exports__ = {};
1892
2581
  btn.appendChild(document.createTextNode(text));
1893
2582
  return btn;
1894
2583
  }
1895
- function createListItem(options) {
1896
- const { title, description, actions = [] } = options;
1897
- const content = renderer_div({
1898
- className: styles_components_module.listItemContent,
1899
- children: [
1900
- renderer_span({
1901
- className: styles_components_module.listItemTitle,
1902
- text: title
1903
- }),
1904
- description ? renderer_span({
1905
- className: styles_components_module.listItemDescription,
1906
- text: description
1907
- }) : null
1908
- ]
1909
- });
1910
- const actionsContainer = renderer_div({
1911
- className: styles_components_module.listItemActions,
1912
- children: actions
1913
- });
1914
- return renderer_div({
1915
- className: styles_components_module.listItem,
1916
- children: [
1917
- content,
1918
- actionsContainer
1919
- ]
2584
+ function createInput(options) {
2585
+ const { value, placeholder, ariaLabel, small = false, onInput } = options;
2586
+ const sizeClass = small ? styles_components_module.inputSmall : '';
2587
+ return input({
2588
+ className: `${styles_components_module.input} ${sizeClass}`.trim(),
2589
+ type: 'text',
2590
+ value,
2591
+ placeholder,
2592
+ ariaLabel,
2593
+ onInput: (event)=>{
2594
+ const target = event.target;
2595
+ onInput?.(target?.value ?? '');
2596
+ }
1920
2597
  });
1921
2598
  }
1922
2599
  function createSection(options) {
@@ -1999,6 +2676,18 @@ var __webpack_exports__ = {};
1999
2676
  children
2000
2677
  });
2001
2678
  }
2679
+ function createDisconnectedState(message = 'Store not connected') {
2680
+ return renderer_div({
2681
+ className: styles_components_module.disconnectedState,
2682
+ style: {
2683
+ padding: '24px',
2684
+ textAlign: 'center',
2685
+ color: 'var(--c15t-text-muted)',
2686
+ fontSize: 'var(--c15t-devtools-font-size-sm)'
2687
+ },
2688
+ text: message
2689
+ });
2690
+ }
2002
2691
  const REFRESH_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
2003
2692
  <path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"></path>
2004
2693
  <path d="M21 3v5h-5"></path>
@@ -2026,19 +2715,11 @@ var __webpack_exports__ = {};
2026
2715
  <polyline points="4 17 10 11 4 5"></polyline>
2027
2716
  <line x1="12" y1="19" x2="20" y2="19"></line>
2028
2717
  </svg>`;
2029
- function actions_renderActionsPanel(container, options) {
2030
- const { getState, onResetConsents, onRefetchBanner, onShowBanner, onOpenPreferences, onCopyState } = options;
2718
+ function renderActionsPanel(container, options) {
2719
+ const { getState, onResetConsents, onRefetchBanner, onShowBanner, onOpenPreferences, onCopyState, onExportDebugBundle } = options;
2031
2720
  renderer_clearElement(container);
2032
2721
  const state = getState();
2033
- if (!state) return void container.appendChild(renderer_div({
2034
- style: {
2035
- padding: '24px',
2036
- textAlign: 'center',
2037
- color: 'var(--c15t-text-muted)',
2038
- fontSize: 'var(--c15t-devtools-font-size-sm)'
2039
- },
2040
- text: 'Store not connected'
2041
- }));
2722
+ if (!state) return void container.appendChild(createDisconnectedState());
2042
2723
  const actionCards = [
2043
2724
  createActionCard({
2044
2725
  icon: actions_EYE_ICON,
@@ -2059,6 +2740,12 @@ var __webpack_exports__ = {};
2059
2740
  icon: COPY_ICON,
2060
2741
  label: 'Copy State',
2061
2742
  onClick: onCopyState
2743
+ }),
2744
+ createActionCard({
2745
+ icon: REFRESH_ICON,
2746
+ label: 'Export Debug',
2747
+ onClick: ()=>onExportDebugBundle?.(),
2748
+ disabled: !onExportDebugBundle
2062
2749
  })
2063
2750
  ];
2064
2751
  const grid = createGrid({
@@ -2132,7 +2819,7 @@ var __webpack_exports__ = {};
2132
2819
  container.appendChild(consoleSection);
2133
2820
  }
2134
2821
  function createActionCard(options) {
2135
- const { icon, label, onClick } = options;
2822
+ const { icon, label, onClick, disabled = false } = options;
2136
2823
  const card = renderer_div({
2137
2824
  className: styles_components_module.gridCard ?? '',
2138
2825
  style: {
@@ -2143,7 +2830,8 @@ var __webpack_exports__ = {};
2143
2830
  gap: '6px',
2144
2831
  padding: '16px 8px',
2145
2832
  cursor: 'pointer',
2146
- transition: 'background-color var(--c15t-duration-fast) var(--c15t-easing)'
2833
+ transition: 'background-color var(--c15t-duration-fast) var(--c15t-easing)',
2834
+ opacity: disabled ? '0.55' : '1'
2147
2835
  },
2148
2836
  children: [
2149
2837
  createIconWrapper(icon, 20),
@@ -2158,13 +2846,15 @@ var __webpack_exports__ = {};
2158
2846
  })
2159
2847
  ]
2160
2848
  });
2161
- card.addEventListener('click', onClick);
2162
- card.addEventListener('mouseenter', ()=>{
2163
- card.style.backgroundColor = 'var(--c15t-surface-hover)';
2164
- });
2165
- card.addEventListener('mouseleave', ()=>{
2166
- card.style.backgroundColor = '';
2167
- });
2849
+ if (!disabled) {
2850
+ card.addEventListener('click', onClick);
2851
+ card.addEventListener('mouseenter', ()=>{
2852
+ card.style.backgroundColor = 'var(--c15t-surface-hover)';
2853
+ });
2854
+ card.addEventListener('mouseleave', ()=>{
2855
+ card.style.backgroundColor = '';
2856
+ });
2857
+ }
2168
2858
  return card;
2169
2859
  }
2170
2860
  function createIconWrapper(icon, size) {
@@ -2185,19 +2875,12 @@ var __webpack_exports__ = {};
2185
2875
  function getNamespace(state) {
2186
2876
  return state.config?.meta?.namespace || 'c15tStore';
2187
2877
  }
2188
- function consents_renderConsentsPanel(container, options) {
2878
+ const consentSearchByContainer = new WeakMap();
2879
+ function renderConsentsPanel(container, options) {
2189
2880
  const { getState, onConsentChange, onSave, onAcceptAll, onRejectAll, onReset } = options;
2190
2881
  renderer_clearElement(container);
2191
2882
  const state = getState();
2192
- if (!state) return void container.appendChild(renderer_div({
2193
- style: {
2194
- padding: '24px',
2195
- textAlign: 'center',
2196
- color: 'var(--c15t-text-muted)',
2197
- fontSize: 'var(--c15t-devtools-font-size-sm)'
2198
- },
2199
- text: 'Store not connected'
2200
- }));
2883
+ if (!state) return void container.appendChild(createDisconnectedState());
2201
2884
  const isIabMode = 'iab' === state.model;
2202
2885
  const savedConsents = state.consents || {};
2203
2886
  const selectedConsents = state.selectedConsents || {};
@@ -2211,15 +2894,40 @@ var __webpack_exports__ = {};
2211
2894
  ct.name,
2212
2895
  ct
2213
2896
  ]));
2897
+ const searchQuery = consentSearchByContainer.get(container) ?? '';
2214
2898
  const consentEntries = Object.entries(displayConsents);
2215
- if (0 === consentEntries.length) container.appendChild(renderer_div({
2899
+ const filteredConsentEntries = consentEntries.filter(([name])=>{
2900
+ if (!searchQuery) return true;
2901
+ const consentType = consentTypeMap.get(name);
2902
+ const displayName = consentType?.name || name;
2903
+ return `${name} ${displayName}`.toLowerCase().includes(searchQuery);
2904
+ });
2905
+ const showSearchInput = consentEntries.length > 4;
2906
+ if (showSearchInput) container.appendChild(renderer_div({
2907
+ style: {
2908
+ padding: '8px 0 10px'
2909
+ },
2910
+ children: [
2911
+ createInput({
2912
+ value: searchQuery,
2913
+ placeholder: 'Filter consents…',
2914
+ ariaLabel: 'Filter consents',
2915
+ small: true,
2916
+ onInput: (value)=>{
2917
+ consentSearchByContainer.set(container, value.trim().toLowerCase());
2918
+ renderConsentsPanel(container, options);
2919
+ }
2920
+ })
2921
+ ]
2922
+ }));
2923
+ if (0 === filteredConsentEntries.length) container.appendChild(renderer_div({
2216
2924
  style: {
2217
2925
  padding: '24px',
2218
2926
  textAlign: 'center',
2219
2927
  color: 'var(--c15t-devtools-text-muted)',
2220
2928
  fontSize: 'var(--c15t-devtools-font-size-sm)'
2221
2929
  },
2222
- text: 'No consents configured'
2930
+ text: 0 === consentEntries.length ? 'No consents configured' : 'No matching consents'
2223
2931
  }));
2224
2932
  else {
2225
2933
  if (isIabMode) {
@@ -2237,7 +2945,7 @@ var __webpack_exports__ = {};
2237
2945
  container.appendChild(iabNotice);
2238
2946
  }
2239
2947
  const gridCards = [];
2240
- for (const [name, value] of consentEntries){
2948
+ for (const [name, value] of filteredConsentEntries){
2241
2949
  const consentType = consentTypeMap.get(name);
2242
2950
  const isNecessary = 'necessary' === name;
2243
2951
  const displayName = consentType?.name || name;
@@ -2301,13 +3009,13 @@ var __webpack_exports__ = {};
2301
3009
  },
2302
3010
  children: [
2303
3011
  createButton({
2304
- text: 'All',
3012
+ text: 'Accept',
2305
3013
  variant: 'primary',
2306
3014
  small: true,
2307
3015
  onClick: onAcceptAll
2308
3016
  }),
2309
3017
  createButton({
2310
- text: 'None',
3018
+ text: 'Reject',
2311
3019
  variant: 'default',
2312
3020
  small: true,
2313
3021
  onClick: onRejectAll
@@ -2355,16 +3063,33 @@ var __webpack_exports__ = {};
2355
3063
  function formatConsentName(name) {
2356
3064
  return name.replace(/_/g, ' ').replace(/\b\w/g, (l)=>l.toUpperCase());
2357
3065
  }
2358
- function events_renderEventsPanel(container, options) {
3066
+ const panelStateByContainer = new WeakMap();
3067
+ function getPanelState(container) {
3068
+ const existing = panelStateByContainer.get(container);
3069
+ if (existing) return existing;
3070
+ const initialState = {
3071
+ activeFilter: 'all',
3072
+ selectedEventId: null,
3073
+ searchQuery: ''
3074
+ };
3075
+ panelStateByContainer.set(container, initialState);
3076
+ return initialState;
3077
+ }
3078
+ function renderEventsPanel(container, options) {
2359
3079
  const { getEvents, onClear } = options;
3080
+ const panelState = getPanelState(container);
2360
3081
  renderer_clearElement(container);
2361
- const events = getEvents();
3082
+ const allEvents = getEvents();
3083
+ const events = allEvents.filter((event)=>matchesFilter(event, panelState.activeFilter)).filter((event)=>matchesSearch(event, panelState.searchQuery));
3084
+ if (!events.some((event)=>event.id === panelState.selectedEventId)) panelState.selectedEventId = events[0]?.id ?? null;
3085
+ const selectedEvent = events.find((event)=>event.id === panelState.selectedEventId) ?? null;
2362
3086
  const header = renderer_div({
2363
3087
  style: {
2364
3088
  display: 'flex',
2365
3089
  alignItems: 'center',
2366
3090
  justifyContent: 'space-between',
2367
- padding: '12px 16px 8px'
3091
+ padding: '12px 16px 8px',
3092
+ gap: '8px'
2368
3093
  },
2369
3094
  children: [
2370
3095
  renderer_span({
@@ -2375,44 +3100,153 @@ var __webpack_exports__ = {};
2375
3100
  textTransform: 'uppercase',
2376
3101
  letterSpacing: '0.5px'
2377
3102
  },
2378
- text: `Events (${events.length})`
3103
+ text: `Events (${events.length}/${allEvents.length})`
2379
3104
  }),
2380
- createButton({
2381
- text: 'Clear',
2382
- small: true,
2383
- onClick: onClear
3105
+ renderer_div({
3106
+ style: {
3107
+ display: 'flex',
3108
+ gap: '6px'
3109
+ },
3110
+ children: [
3111
+ createButton({
3112
+ text: 'Export',
3113
+ small: true,
3114
+ onClick: ()=>exportEvents(allEvents)
3115
+ }),
3116
+ createButton({
3117
+ text: 'Clear',
3118
+ small: true,
3119
+ onClick: ()=>{
3120
+ onClear();
3121
+ panelState.selectedEventId = null;
3122
+ renderEventsPanel(container, options);
3123
+ }
3124
+ })
3125
+ ]
2384
3126
  })
2385
3127
  ]
2386
3128
  });
2387
3129
  container.appendChild(header);
3130
+ container.appendChild(renderer_div({
3131
+ style: {
3132
+ display: 'flex',
3133
+ flexWrap: 'wrap',
3134
+ gap: '6px',
3135
+ padding: '0 16px 8px'
3136
+ },
3137
+ children: EVENT_FILTERS.map((filter)=>createFilterButton(filter, filter === panelState.activeFilter, ()=>{
3138
+ panelState.activeFilter = filter;
3139
+ panelState.selectedEventId = null;
3140
+ renderEventsPanel(container, options);
3141
+ }))
3142
+ }));
3143
+ container.appendChild(renderer_div({
3144
+ style: {
3145
+ padding: '0 16px 8px'
3146
+ },
3147
+ children: [
3148
+ createInput({
3149
+ value: panelState.searchQuery,
3150
+ placeholder: 'Search events…',
3151
+ ariaLabel: 'Search events',
3152
+ small: true,
3153
+ onInput: (value)=>{
3154
+ panelState.searchQuery = value.trim().toLowerCase();
3155
+ panelState.selectedEventId = null;
3156
+ renderEventsPanel(container, options);
3157
+ }
3158
+ })
3159
+ ]
3160
+ }));
2388
3161
  const eventList = renderer_div({
2389
3162
  style: {
2390
3163
  display: 'flex',
2391
3164
  flexDirection: 'column',
2392
3165
  gap: '4px',
2393
3166
  padding: '0 12px 12px',
2394
- maxHeight: '400px',
3167
+ maxHeight: '300px',
2395
3168
  overflowY: 'auto'
2396
3169
  }
2397
3170
  });
2398
- if (0 === events.length) {
2399
- const emptyState = renderer_div({
2400
- style: {
2401
- padding: '32px 16px',
2402
- textAlign: 'center',
2403
- color: 'var(--c15t-text-muted)',
2404
- fontSize: 'var(--c15t-devtools-font-size-sm)'
2405
- },
2406
- text: 'No events recorded yet'
2407
- });
2408
- eventList.appendChild(emptyState);
2409
- } else for (const event of events){
2410
- const eventItem = createEventItem(event);
2411
- eventList.appendChild(eventItem);
2412
- }
3171
+ if (0 === events.length) eventList.appendChild(renderer_div({
3172
+ style: {
3173
+ padding: '20px 16px',
3174
+ textAlign: 'center',
3175
+ color: 'var(--c15t-text-muted)',
3176
+ fontSize: 'var(--c15t-devtools-font-size-sm)'
3177
+ },
3178
+ text: 'No events match this filter'
3179
+ }));
3180
+ else for (const event of events)eventList.appendChild(createEventItem(event, event.id === panelState.selectedEventId, ()=>{
3181
+ panelState.selectedEventId = event.id;
3182
+ renderEventsPanel(container, options);
3183
+ }));
2413
3184
  container.appendChild(eventList);
3185
+ container.appendChild(createPayloadSection(selectedEvent));
3186
+ }
3187
+ const EVENT_FILTERS = [
3188
+ 'all',
3189
+ 'error',
3190
+ 'consent',
3191
+ 'network',
3192
+ 'iab'
3193
+ ];
3194
+ function createFilterButton(filter, active, onClick) {
3195
+ return createButton({
3196
+ text: filter.toUpperCase(),
3197
+ small: true,
3198
+ variant: active ? 'primary' : 'default',
3199
+ onClick
3200
+ });
3201
+ }
3202
+ function matchesFilter(event, filter) {
3203
+ if ('all' === filter) return true;
3204
+ if ('error' === filter) return 'error' === event.type;
3205
+ if ('consent' === filter) return 'consent_set' === event.type || 'consent_save' === event.type || 'consent_reset' === event.type;
3206
+ if ('network' === filter) return 'network' === event.type;
3207
+ return 'iab' === event.type;
3208
+ }
3209
+ function matchesSearch(event, query) {
3210
+ if (!query) return true;
3211
+ const haystack = `${event.type} ${event.message} ${JSON.stringify(event.data ?? {})}`;
3212
+ return haystack.toLowerCase().includes(query);
3213
+ }
3214
+ function createPayloadSection(event) {
3215
+ const payload = event?.data ? JSON.stringify(event.data, null, 2) : null;
3216
+ return renderer_div({
3217
+ style: {
3218
+ padding: '0 12px 12px'
3219
+ },
3220
+ children: [
3221
+ renderer_div({
3222
+ style: {
3223
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
3224
+ fontWeight: '600',
3225
+ color: 'var(--c15t-text-muted)',
3226
+ textTransform: 'uppercase',
3227
+ letterSpacing: '0.5px',
3228
+ marginBottom: '6px'
3229
+ },
3230
+ text: 'Payload'
3231
+ }),
3232
+ renderer_div({
3233
+ className: styles_components_module.gridCard ?? '',
3234
+ style: {
3235
+ padding: '8px',
3236
+ fontFamily: 'ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, monospace',
3237
+ fontSize: '11px',
3238
+ color: 'var(--c15t-text-muted)',
3239
+ maxHeight: '140px',
3240
+ overflowY: 'auto',
3241
+ whiteSpace: 'pre-wrap',
3242
+ wordBreak: 'break-word'
3243
+ },
3244
+ text: payload || 'Select an event with payload data'
3245
+ })
3246
+ ]
3247
+ });
2414
3248
  }
2415
- function createEventItem(event) {
3249
+ function createEventItem(event, selected, onSelect) {
2416
3250
  const time = formatTime(event.timestamp);
2417
3251
  const icon = getEventIcon(event.type);
2418
3252
  const color = getEventColor(event.type);
@@ -2423,8 +3257,11 @@ var __webpack_exports__ = {};
2423
3257
  alignItems: 'center',
2424
3258
  gap: '8px',
2425
3259
  padding: '6px 10px',
2426
- fontSize: 'var(--c15t-devtools-font-size-xs)'
3260
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
3261
+ cursor: 'pointer',
3262
+ borderColor: selected ? 'var(--c15t-devtools-badge-info, #3b82f6)' : 'var(--c15t-border)'
2427
3263
  },
3264
+ onClick: onSelect,
2428
3265
  children: [
2429
3266
  renderer_span({
2430
3267
  style: {
@@ -2453,6 +3290,21 @@ var __webpack_exports__ = {};
2453
3290
  ]
2454
3291
  });
2455
3292
  }
3293
+ function exportEvents(events) {
3294
+ const json = JSON.stringify(events, null, 2);
3295
+ const blob = new Blob([
3296
+ json
3297
+ ], {
3298
+ type: 'application/json'
3299
+ });
3300
+ const url = URL.createObjectURL(blob);
3301
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
3302
+ const a = document.createElement('a');
3303
+ a.href = url;
3304
+ a.download = `c15t-events-${timestamp}.json`;
3305
+ a.click();
3306
+ URL.revokeObjectURL(url);
3307
+ }
2456
3308
  function formatTime(timestamp) {
2457
3309
  const date = new Date(timestamp);
2458
3310
  return date.toLocaleTimeString('en-US', {
@@ -2471,7 +3323,10 @@ var __webpack_exports__ = {};
2471
3323
  return '○';
2472
3324
  case 'error':
2473
3325
  return '✕';
2474
- case 'info':
3326
+ case 'network':
3327
+ return '◉';
3328
+ case 'iab':
3329
+ return '◆';
2475
3330
  default:
2476
3331
  return '○';
2477
3332
  }
@@ -2485,43 +3340,23 @@ var __webpack_exports__ = {};
2485
3340
  return 'var(--c15t-devtools-badge-warning, #f59e0b)';
2486
3341
  case 'error':
2487
3342
  return 'var(--c15t-devtools-badge-error, #ef4444)';
2488
- case 'info':
3343
+ case 'network':
3344
+ return 'var(--c15t-devtools-badge-warning, #f59e0b)';
3345
+ case 'iab':
3346
+ return 'var(--c15t-devtools-badge-info, #3b82f6)';
2489
3347
  default:
2490
3348
  return 'var(--c15t-text-muted)';
2491
3349
  }
2492
3350
  }
2493
- function iab_renderIabPanel(container, options) {
2494
- const { getState, onReset } = options;
3351
+ const iabSearchByContainer = new WeakMap();
3352
+ function renderIabPanel(container, options) {
3353
+ const { getState, onSetPurposeConsent, onSetVendorConsent, onSetSpecialFeatureOptIn, onAcceptAll, onRejectAll, onSave, onReset } = options;
2495
3354
  renderer_clearElement(container);
2496
3355
  const state = getState();
2497
- if (!state) return void container.appendChild(renderer_div({
2498
- style: {
2499
- padding: '24px',
2500
- textAlign: 'center',
2501
- color: 'var(--c15t-text-muted)',
2502
- fontSize: 'var(--c15t-devtools-font-size-sm)'
2503
- },
2504
- text: 'Store not connected'
2505
- }));
2506
- if ('iab' !== state.model) return void container.appendChild(renderer_div({
2507
- style: {
2508
- padding: '24px',
2509
- textAlign: 'center',
2510
- color: 'var(--c15t-text-muted)',
2511
- fontSize: 'var(--c15t-devtools-font-size-sm)'
2512
- },
2513
- text: 'IAB TCF mode is not configured'
2514
- }));
3356
+ if (!state) return void container.appendChild(createDisconnectedState());
3357
+ if ('iab' !== state.model) return void container.appendChild(createDisconnectedState('IAB TCF mode is not configured'));
2515
3358
  const iabState = state.iab;
2516
- if (!iabState) return void container.appendChild(renderer_div({
2517
- style: {
2518
- padding: '24px',
2519
- textAlign: 'center',
2520
- color: 'var(--c15t-text-muted)',
2521
- fontSize: 'var(--c15t-devtools-font-size-sm)'
2522
- },
2523
- text: 'IAB state not available'
2524
- }));
3359
+ if (!iabState) return void container.appendChild(createDisconnectedState('IAB state not available'));
2525
3360
  const tcString = iabState.tcString;
2526
3361
  const tcStringSection = createSection({
2527
3362
  title: 'TC String',
@@ -2553,9 +3388,30 @@ var __webpack_exports__ = {};
2553
3388
  });
2554
3389
  container.appendChild(tcStringSection);
2555
3390
  const gvl = iabState.gvl;
2556
- const purposeConsents = iabState.purposeConsents || {};
2557
- const purposes = gvl?.purposes || {};
2558
- const purposeEntries = Object.entries(purposeConsents);
3391
+ const searchQuery = iabSearchByContainer.get(container) ?? '';
3392
+ container.appendChild(createSection({
3393
+ title: 'Filter',
3394
+ children: [
3395
+ createInput({
3396
+ value: searchQuery,
3397
+ placeholder: 'Filter purposes or vendors…',
3398
+ ariaLabel: 'Filter IAB purposes and vendors',
3399
+ small: true,
3400
+ onInput: (value)=>{
3401
+ iabSearchByContainer.set(container, value.trim().toLowerCase());
3402
+ renderIabPanel(container, options);
3403
+ }
3404
+ })
3405
+ ]
3406
+ }));
3407
+ const purposeConsents = iabState.purposeConsents || {};
3408
+ const purposes = gvl?.purposes || {};
3409
+ const purposeEntries = Object.entries(purposeConsents).filter(([purposeId])=>{
3410
+ if (!searchQuery) return true;
3411
+ const purposeInfo = purposes[purposeId];
3412
+ const purposeName = purposeInfo?.name || `Purpose ${purposeId}`;
3413
+ return `${purposeId} ${purposeName}`.toLowerCase().includes(searchQuery);
3414
+ });
2559
3415
  if (purposeEntries.length > 0) {
2560
3416
  const purposeList = renderer_div({
2561
3417
  style: {
@@ -2569,7 +3425,9 @@ var __webpack_exports__ = {};
2569
3425
  for (const [purposeId, consent] of purposeEntries){
2570
3426
  const purposeInfo = purposes[purposeId];
2571
3427
  const purposeName = purposeInfo?.name || `Purpose ${purposeId}`;
2572
- purposeList.appendChild(createPurposeRow(purposeId, purposeName, Boolean(consent)));
3428
+ purposeList.appendChild(createPurposeRow(purposeId, purposeName, Boolean(consent), (value)=>{
3429
+ onSetPurposeConsent(Number(purposeId), value);
3430
+ }));
2573
3431
  }
2574
3432
  const purposesSection = createSection({
2575
3433
  title: `Purposes (${purposeEntries.length})`,
@@ -2581,7 +3439,12 @@ var __webpack_exports__ = {};
2581
3439
  }
2582
3440
  const specialFeatureOptIns = iabState.specialFeatureOptIns || {};
2583
3441
  const specialFeatures = gvl?.specialFeatures || {};
2584
- const specialFeatureEntries = Object.entries(specialFeatureOptIns);
3442
+ const specialFeatureEntries = Object.entries(specialFeatureOptIns).filter(([featureId])=>{
3443
+ if (!searchQuery) return true;
3444
+ const featureInfo = specialFeatures[featureId];
3445
+ const featureName = featureInfo?.name || `Special Feature ${featureId}`;
3446
+ return `${featureId} ${featureName}`.toLowerCase().includes(searchQuery);
3447
+ });
2585
3448
  if (specialFeatureEntries.length > 0) {
2586
3449
  const specialFeatureList = renderer_div({
2587
3450
  style: {
@@ -2595,7 +3458,9 @@ var __webpack_exports__ = {};
2595
3458
  for (const [featureId, optIn] of specialFeatureEntries){
2596
3459
  const featureInfo = specialFeatures[featureId];
2597
3460
  const featureName = featureInfo?.name || `Special Feature ${featureId}`;
2598
- specialFeatureList.appendChild(createPurposeRow(featureId, featureName, Boolean(optIn)));
3461
+ specialFeatureList.appendChild(createPurposeRow(featureId, featureName, Boolean(optIn), (value)=>{
3462
+ onSetSpecialFeatureOptIn(Number(featureId), value);
3463
+ }, 'feature'));
2599
3464
  }
2600
3465
  const specialFeaturesSection = createSection({
2601
3466
  title: `Special Features (${specialFeatureEntries.length})`,
@@ -2607,7 +3472,12 @@ var __webpack_exports__ = {};
2607
3472
  }
2608
3473
  const vendorConsents = iabState.vendorConsents || {};
2609
3474
  const vendors = gvl?.vendors || {};
2610
- const vendorEntries = Object.entries(vendorConsents);
3475
+ const vendorEntries = Object.entries(vendorConsents).filter(([vendorId])=>{
3476
+ if (!searchQuery) return true;
3477
+ const vendorInfo = vendors[vendorId];
3478
+ const vendorName = vendorInfo?.name || `Vendor ${vendorId}`;
3479
+ return `${vendorId} ${vendorName}`.toLowerCase().includes(searchQuery);
3480
+ });
2611
3481
  const iabVendors = [];
2612
3482
  const customVendors = [];
2613
3483
  for (const [vendorId, consent] of vendorEntries){
@@ -2635,7 +3505,9 @@ var __webpack_exports__ = {};
2635
3505
  overflowY: 'auto'
2636
3506
  }
2637
3507
  });
2638
- for (const [vendorId, consent, vendorName] of iabVendors)vendorList.appendChild(createVendorRow(vendorId, vendorName, consent, 'iab'));
3508
+ for (const [vendorId, consent, vendorName] of iabVendors)vendorList.appendChild(createVendorRow(vendorId, vendorName, consent, 'iab', (value)=>{
3509
+ onSetVendorConsent(Number(vendorId), value);
3510
+ }));
2639
3511
  const vendorsSection = createSection({
2640
3512
  title: `IAB Vendors (${iabVendors.length})`,
2641
3513
  children: [
@@ -2654,7 +3526,9 @@ var __webpack_exports__ = {};
2654
3526
  overflowY: 'auto'
2655
3527
  }
2656
3528
  });
2657
- for (const [vendorId, consent, vendorName] of customVendors)customVendorList.appendChild(createVendorRow(vendorId, vendorName, consent, 'custom'));
3529
+ for (const [vendorId, consent, vendorName] of customVendors)customVendorList.appendChild(createVendorRow(vendorId, vendorName, consent, 'custom', (value)=>{
3530
+ onSetVendorConsent(vendorId, value);
3531
+ }));
2658
3532
  const customVendorsSection = createSection({
2659
3533
  title: `Custom Vendors (${customVendors.length})`,
2660
3534
  children: [
@@ -2676,15 +3550,40 @@ var __webpack_exports__ = {};
2676
3550
  style: {
2677
3551
  display: 'flex',
2678
3552
  alignItems: 'center',
2679
- justifyContent: 'flex-end',
3553
+ justifyContent: 'space-between',
2680
3554
  padding: '12px 16px',
2681
3555
  marginTop: 'auto',
2682
3556
  borderTop: '1px solid var(--c15t-border)',
2683
3557
  backgroundColor: 'var(--c15t-surface)'
2684
3558
  },
2685
3559
  children: [
3560
+ renderer_div({
3561
+ style: {
3562
+ display: 'flex',
3563
+ gap: '6px'
3564
+ },
3565
+ children: [
3566
+ createButton({
3567
+ text: 'Accept All',
3568
+ variant: 'primary',
3569
+ small: true,
3570
+ onClick: onAcceptAll
3571
+ }),
3572
+ createButton({
3573
+ text: 'Reject All',
3574
+ small: true,
3575
+ onClick: onRejectAll
3576
+ }),
3577
+ createButton({
3578
+ text: 'Save',
3579
+ variant: 'primary',
3580
+ small: true,
3581
+ onClick: onSave
3582
+ })
3583
+ ]
3584
+ }),
2686
3585
  createButton({
2687
- text: 'Reset All',
3586
+ text: 'Reset',
2688
3587
  variant: 'danger',
2689
3588
  small: true,
2690
3589
  onClick: onReset
@@ -2693,7 +3592,7 @@ var __webpack_exports__ = {};
2693
3592
  });
2694
3593
  container.appendChild(footer);
2695
3594
  }
2696
- function createPurposeRow(id, name, consent) {
3595
+ function createPurposeRow(id, name, consent, onChange, ariaKind = 'purpose') {
2697
3596
  return renderer_div({
2698
3597
  style: {
2699
3598
  display: 'flex',
@@ -2716,14 +3615,28 @@ var __webpack_exports__ = {};
2716
3615
  text: `${id}. ${name}`,
2717
3616
  title: name
2718
3617
  }),
2719
- createBadge({
2720
- text: consent ? '✓' : '✕',
2721
- variant: consent ? 'success' : 'error'
3618
+ renderer_div({
3619
+ style: {
3620
+ display: 'flex',
3621
+ alignItems: 'center',
3622
+ gap: '6px'
3623
+ },
3624
+ children: [
3625
+ createBadge({
3626
+ text: consent ? '✓' : '✕',
3627
+ variant: consent ? 'success' : 'error'
3628
+ }),
3629
+ createToggle({
3630
+ checked: consent,
3631
+ onChange,
3632
+ ariaLabel: `Toggle ${ariaKind} ${id}`
3633
+ })
3634
+ ]
2722
3635
  })
2723
3636
  ]
2724
3637
  });
2725
3638
  }
2726
- function createVendorRow(id, name, consent, type) {
3639
+ function createVendorRow(id, name, consent, type, onChange) {
2727
3640
  return renderer_div({
2728
3641
  style: {
2729
3642
  display: 'flex',
@@ -2770,27 +3683,24 @@ var __webpack_exports__ = {};
2770
3683
  createBadge({
2771
3684
  text: consent ? '✓' : '✕',
2772
3685
  variant: consent ? 'success' : 'error'
3686
+ }),
3687
+ createToggle({
3688
+ checked: consent,
3689
+ onChange,
3690
+ ariaLabel: `Toggle vendor ${id}`
2773
3691
  })
2774
3692
  ]
2775
3693
  });
2776
3694
  }
2777
3695
  function truncateText(text, maxLength) {
2778
3696
  if (text.length <= maxLength) return text;
2779
- return text.slice(0, maxLength - 3) + '...';
3697
+ return `${text.slice(0, maxLength - 3)}...`;
2780
3698
  }
2781
- function location_renderLocationPanel(container, options) {
2782
- const { getState, onSetOverrides, onClearOverrides } = options;
3699
+ function renderLocationPanel(container, options) {
3700
+ const { getState, onApplyOverrides, onClearOverrides } = options;
2783
3701
  renderer_clearElement(container);
2784
3702
  const state = getState();
2785
- if (!state) return void container.appendChild(renderer_div({
2786
- style: {
2787
- padding: '24px',
2788
- textAlign: 'center',
2789
- color: 'var(--c15t-text-muted)',
2790
- fontSize: 'var(--c15t-devtools-font-size-sm)'
2791
- },
2792
- text: 'Store not connected'
2793
- }));
3703
+ if (!state) return void container.appendChild(createDisconnectedState());
2794
3704
  const locationInfo = state.locationInfo;
2795
3705
  const overrides = state.overrides;
2796
3706
  const translationConfig = state.translationConfig;
@@ -2800,145 +3710,230 @@ var __webpack_exports__ = {};
2800
3710
  createCompactInfoCard('Jurisdiction', locationInfo?.jurisdiction || '—'),
2801
3711
  createCompactInfoCard('Language', translationConfig?.defaultLanguage || '—')
2802
3712
  ];
3713
+ gridItems.push(createCompactInfoCard('GPC', getEffectiveGpcLabel(overrides?.gpc)));
2803
3714
  if (state.model) gridItems.push(createCompactInfoCard('Model', getModelLabel(state.model)));
2804
3715
  const locationGrid = createGrid({
2805
- columns: 2,
3716
+ columns: 3,
2806
3717
  children: gridItems
2807
3718
  });
2808
3719
  container.appendChild(locationGrid);
3720
+ const initialDraft = getDraftFromOverrides(overrides);
3721
+ let appliedOverrides = normalizeOverrideDraft(initialDraft);
3722
+ let isSubmitting = false;
3723
+ const countryField = createOverrideSelect({
3724
+ label: 'Country',
3725
+ selectOptions: COUNTRY_OPTIONS,
3726
+ value: initialDraft.country
3727
+ });
3728
+ const regionField = createOverrideInput({
3729
+ label: 'Region',
3730
+ placeholder: 'e.g., CA, NY, BE',
3731
+ value: initialDraft.region
3732
+ });
3733
+ const languageField = createOverrideInput({
3734
+ label: 'Language',
3735
+ placeholder: 'e.g., de, fr, en-US',
3736
+ value: initialDraft.language
3737
+ });
3738
+ const gpcField = createOverrideSelect({
3739
+ label: 'GPC',
3740
+ selectOptions: GPC_OPTIONS,
3741
+ value: initialDraft.gpc
3742
+ });
3743
+ const formStatus = renderer_span({
3744
+ className: styles_components_module.overrideStatus,
3745
+ text: 'In sync'
3746
+ });
3747
+ const applyButton = createButton({
3748
+ text: 'Apply',
3749
+ variant: 'primary',
3750
+ small: true,
3751
+ disabled: true,
3752
+ onClick: ()=>{
3753
+ applyDraft();
3754
+ }
3755
+ });
3756
+ const revertButton = createButton({
3757
+ text: 'Revert',
3758
+ small: true,
3759
+ disabled: true,
3760
+ onClick: ()=>{
3761
+ setDraftValues(getDraftFromOverrides(appliedOverrides));
3762
+ updateFormState();
3763
+ }
3764
+ });
3765
+ const clearButton = createButton({
3766
+ text: 'Clear',
3767
+ small: true,
3768
+ onClick: ()=>{
3769
+ clearDraftAndOverrides();
3770
+ }
3771
+ });
3772
+ const overrideFieldsGrid = renderer_div({
3773
+ style: {
3774
+ display: 'grid',
3775
+ gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
3776
+ gap: '8px 10px'
3777
+ },
3778
+ children: [
3779
+ countryField.element,
3780
+ regionField.element,
3781
+ languageField.element,
3782
+ gpcField.element
3783
+ ]
3784
+ });
2809
3785
  const overrideSection = createSection({
2810
3786
  title: 'Override Settings',
2811
- actions: [
2812
- createButton({
2813
- text: 'Clear',
2814
- small: true,
2815
- onClick: onClearOverrides
2816
- })
2817
- ],
2818
3787
  children: [
2819
- createOverrideSelect({
2820
- label: 'Country',
2821
- selectOptions: COUNTRY_OPTIONS,
2822
- value: overrides?.country || '',
2823
- onChange: (value)=>onSetOverrides({
2824
- country: value || void 0
2825
- })
2826
- }),
2827
- createOverrideInput({
2828
- label: 'Region',
2829
- placeholder: 'e.g., CA, NY, BE',
2830
- value: overrides?.region || '',
2831
- onChange: (value)=>onSetOverrides({
2832
- region: value || void 0
2833
- })
3788
+ overrideFieldsGrid,
3789
+ renderer_span({
3790
+ className: styles_components_module.overrideHint,
3791
+ text: 'GPC override only affects opt-out or unregulated jurisdictions.'
2834
3792
  }),
2835
- createOverrideInput({
2836
- label: 'Language',
2837
- placeholder: 'e.g., de, fr, en',
2838
- value: overrides?.language || '',
2839
- onChange: (value)=>onSetOverrides({
2840
- language: value || void 0
2841
- })
3793
+ renderer_div({
3794
+ className: styles_components_module.overrideActions,
3795
+ children: [
3796
+ renderer_div({
3797
+ className: styles_components_module.overrideActionButtons,
3798
+ children: [
3799
+ revertButton,
3800
+ applyButton,
3801
+ clearButton
3802
+ ]
3803
+ }),
3804
+ formStatus
3805
+ ]
2842
3806
  })
2843
3807
  ]
2844
3808
  });
2845
3809
  container.appendChild(overrideSection);
2846
- const hasOverrides = overrides && (overrides.country || overrides.region || overrides.language);
2847
- if (hasOverrides) {
2848
- const overrideBanner = renderer_div({
2849
- style: {
2850
- padding: '8px 16px',
2851
- backgroundColor: 'var(--c15t-devtools-badge-info-bg)',
2852
- color: 'var(--c15t-devtools-badge-info)',
2853
- fontSize: 'var(--c15t-devtools-font-size-xs)',
2854
- borderTop: '1px solid var(--c15t-devtools-border)'
2855
- },
2856
- text: 'Overrides are active. This may affect consent behavior.'
3810
+ countryField.control.addEventListener('change', updateFormState);
3811
+ regionField.control.addEventListener('input', updateFormState);
3812
+ languageField.control.addEventListener('input', updateFormState);
3813
+ gpcField.control.addEventListener('change', updateFormState);
3814
+ updateFormState();
3815
+ async function applyDraft() {
3816
+ if (isSubmitting) return;
3817
+ const draftOverrides = getDraftOverrides();
3818
+ if (overridesEqual(draftOverrides, appliedOverrides)) return;
3819
+ isSubmitting = true;
3820
+ updateFormState();
3821
+ try {
3822
+ await onApplyOverrides(draftOverrides);
3823
+ appliedOverrides = draftOverrides;
3824
+ } finally{
3825
+ isSubmitting = false;
3826
+ updateFormState();
3827
+ }
3828
+ }
3829
+ async function clearDraftAndOverrides() {
3830
+ if (isSubmitting) return;
3831
+ isSubmitting = true;
3832
+ updateFormState();
3833
+ try {
3834
+ await onClearOverrides();
3835
+ appliedOverrides = {};
3836
+ setDraftValues(getDraftFromOverrides(void 0));
3837
+ } finally{
3838
+ isSubmitting = false;
3839
+ updateFormState();
3840
+ }
3841
+ }
3842
+ function getDraftOverrides() {
3843
+ return normalizeOverrideDraft({
3844
+ country: countryField.control.value,
3845
+ region: regionField.control.value,
3846
+ language: languageField.control.value,
3847
+ gpc: gpcField.control.value
2857
3848
  });
2858
- container.appendChild(overrideBanner);
3849
+ }
3850
+ function setDraftValues(draft) {
3851
+ countryField.control.value = draft.country;
3852
+ regionField.control.value = draft.region;
3853
+ languageField.control.value = draft.language;
3854
+ gpcField.control.value = draft.gpc;
3855
+ }
3856
+ function updateFormState() {
3857
+ const draftOverrides = getDraftOverrides();
3858
+ const hasDraftChanges = !overridesEqual(draftOverrides, appliedOverrides);
3859
+ applyButton.disabled = !hasDraftChanges || isSubmitting;
3860
+ revertButton.disabled = !hasDraftChanges || isSubmitting;
3861
+ clearButton.disabled = isSubmitting;
3862
+ formStatus.textContent = isSubmitting ? 'Applying...' : hasDraftChanges ? 'Unsaved changes' : hasOverridesValue(appliedOverrides) ? 'Overrides active' : 'No overrides';
3863
+ if (styles_components_module.overrideStatusDirty) formStatus.classList.toggle(styles_components_module.overrideStatusDirty, !isSubmitting && hasDraftChanges);
2859
3864
  }
2860
3865
  }
2861
3866
  function createOverrideInput(options) {
2862
- const { label, placeholder, value, onChange } = options;
2863
- let debounceTimer = null;
3867
+ const { label, placeholder, value } = options;
2864
3868
  const inputField = input({
2865
3869
  className: `${styles_components_module.input ?? ''} ${styles_components_module.inputSmall ?? ''}`.trim(),
2866
3870
  placeholder,
2867
- value,
2868
- onInput: (e)=>{
2869
- const target = e.target;
2870
- if (debounceTimer) clearTimeout(debounceTimer);
2871
- debounceTimer = setTimeout(()=>{
2872
- onChange(target.value);
2873
- }, 500);
2874
- }
2875
- });
2876
- return renderer_div({
2877
- style: {
2878
- display: 'flex',
2879
- alignItems: 'center',
2880
- justifyContent: 'space-between',
2881
- gap: '8px',
2882
- marginBottom: '8px'
2883
- },
2884
- children: [
2885
- renderer_div({
2886
- style: {
2887
- fontSize: 'var(--c15t-devtools-font-size-xs)',
2888
- color: 'var(--c15t-devtools-text-muted)',
2889
- minWidth: '60px'
2890
- },
2891
- text: label
2892
- }),
2893
- renderer_div({
2894
- style: {
2895
- flex: '1'
2896
- },
2897
- children: [
2898
- inputField
2899
- ]
2900
- })
2901
- ]
3871
+ value
2902
3872
  });
3873
+ return {
3874
+ element: renderer_div({
3875
+ className: styles_components_module.overrideField,
3876
+ children: [
3877
+ renderer_span({
3878
+ className: styles_components_module.overrideLabel,
3879
+ text: label
3880
+ }),
3881
+ inputField
3882
+ ]
3883
+ }),
3884
+ control: inputField
3885
+ };
2903
3886
  }
2904
3887
  function createOverrideSelect(options) {
2905
- const { label, selectOptions, value, onChange } = options;
3888
+ const { label, selectOptions, value } = options;
2906
3889
  const selectField = renderer_select({
2907
3890
  className: `${styles_components_module.input ?? ''} ${styles_components_module.inputSmall ?? ''}`.trim(),
2908
3891
  options: selectOptions,
2909
- selectedValue: value,
2910
- onChange: (e)=>{
2911
- const target = e.target;
2912
- onChange(target.value);
2913
- }
2914
- });
2915
- return renderer_div({
2916
- style: {
2917
- display: 'flex',
2918
- alignItems: 'center',
2919
- justifyContent: 'space-between',
2920
- gap: '8px',
2921
- marginBottom: '8px'
2922
- },
2923
- children: [
2924
- renderer_div({
2925
- style: {
2926
- fontSize: 'var(--c15t-devtools-font-size-xs)',
2927
- color: 'var(--c15t-devtools-text-muted)',
2928
- minWidth: '60px'
2929
- },
2930
- text: label
2931
- }),
2932
- renderer_div({
2933
- style: {
2934
- flex: '1'
2935
- },
2936
- children: [
2937
- selectField
2938
- ]
2939
- })
2940
- ]
3892
+ selectedValue: value
2941
3893
  });
3894
+ return {
3895
+ element: renderer_div({
3896
+ className: styles_components_module.overrideField,
3897
+ children: [
3898
+ renderer_span({
3899
+ className: styles_components_module.overrideLabel,
3900
+ text: label
3901
+ }),
3902
+ selectField
3903
+ ]
3904
+ }),
3905
+ control: selectField
3906
+ };
3907
+ }
3908
+ function getDraftFromOverrides(overrides) {
3909
+ return {
3910
+ country: overrides?.country ?? '',
3911
+ region: overrides?.region ?? '',
3912
+ language: overrides?.language ?? '',
3913
+ gpc: overrides?.gpc === true ? 'true' : overrides?.gpc === false ? 'false' : ''
3914
+ };
3915
+ }
3916
+ function normalizeOverrideDraft(draft) {
3917
+ return {
3918
+ country: normalizeAlphaCode(draft.country),
3919
+ region: normalizeAlphaCode(draft.region),
3920
+ language: normalizeLanguageCode(draft.language),
3921
+ gpc: 'true' === draft.gpc ? true : 'false' === draft.gpc ? false : void 0
3922
+ };
3923
+ }
3924
+ function normalizeAlphaCode(value) {
3925
+ const normalized = value.trim().toUpperCase();
3926
+ return normalized || void 0;
3927
+ }
3928
+ function normalizeLanguageCode(value) {
3929
+ const normalized = value.trim();
3930
+ return normalized || void 0;
3931
+ }
3932
+ function overridesEqual(a, b) {
3933
+ return a.country === b.country && a.region === b.region && a.language === b.language && a.gpc === b.gpc;
3934
+ }
3935
+ function hasOverridesValue(overrides) {
3936
+ return Boolean(overrides.country || overrides.region || overrides.language || void 0 !== overrides.gpc);
2942
3937
  }
2943
3938
  const COUNTRY_OPTIONS = [
2944
3939
  {
@@ -3062,6 +4057,32 @@ var __webpack_exports__ = {};
3062
4057
  label: 'ZA - South Africa'
3063
4058
  }
3064
4059
  ];
4060
+ const GPC_OPTIONS = [
4061
+ {
4062
+ value: '',
4063
+ label: '-- Browser Default --'
4064
+ },
4065
+ {
4066
+ value: 'true',
4067
+ label: 'Force On (Simulated)'
4068
+ },
4069
+ {
4070
+ value: 'false',
4071
+ label: 'Force Off (Simulated)'
4072
+ }
4073
+ ];
4074
+ function getEffectiveGpcLabel(gpcOverride) {
4075
+ if (true === gpcOverride) return 'On (Override)';
4076
+ if (false === gpcOverride) return 'Off (Override)';
4077
+ if ('undefined' == typeof window || 'undefined' == typeof navigator) return 'Unknown';
4078
+ try {
4079
+ const nav = navigator;
4080
+ const value = nav.globalPrivacyControl;
4081
+ return true === value || '1' === value ? 'Active' : 'Inactive';
4082
+ } catch {
4083
+ return 'Unknown';
4084
+ }
4085
+ }
3065
4086
  function getModelLabel(model) {
3066
4087
  switch(model){
3067
4088
  case 'opt-in':
@@ -3078,9 +4099,11 @@ var __webpack_exports__ = {};
3078
4099
  return renderer_div({
3079
4100
  className: styles_components_module.gridCard ?? '',
3080
4101
  style: {
4102
+ padding: '6px 8px',
4103
+ minHeight: 'auto',
3081
4104
  flexDirection: 'column',
3082
4105
  alignItems: 'flex-start',
3083
- gap: '2px'
4106
+ gap: '1px'
3084
4107
  },
3085
4108
  children: [
3086
4109
  renderer_span({
@@ -3105,34 +4128,38 @@ var __webpack_exports__ = {};
3105
4128
  function scanDOM(state) {
3106
4129
  const results = [];
3107
4130
  const configuredScripts = state.scripts || [];
3108
- const managedDomains = new Map();
4131
+ const managedResources = [];
3109
4132
  for (const script of configuredScripts)if (script.src) try {
3110
4133
  const url = new URL(script.src, window.location.origin);
3111
- if (url.hostname !== window.location.hostname) managedDomains.set(url.hostname, script.id);
4134
+ if (url.hostname !== window.location.hostname) managedResources.push({
4135
+ scriptId: script.id,
4136
+ domain: url.hostname,
4137
+ pathPrefix: normalizePathname(url.pathname)
4138
+ });
3112
4139
  } catch {}
3113
4140
  const scriptElements = document.querySelectorAll("script[src]");
3114
4141
  for (const el of scriptElements){
3115
4142
  const src = el.getAttribute('src');
3116
4143
  if (!src) continue;
3117
- const resource = checkResource(src, "script", managedDomains);
4144
+ const resource = checkResource(src, "script", managedResources);
3118
4145
  if (resource) results.push(resource);
3119
4146
  }
3120
4147
  const iframeElements = document.querySelectorAll('iframe[src]');
3121
4148
  for (const el of iframeElements){
3122
4149
  const src = el.getAttribute('src');
3123
4150
  if (!src) continue;
3124
- const resource = checkResource(src, 'iframe', managedDomains);
4151
+ const resource = checkResource(src, 'iframe', managedResources);
3125
4152
  if (resource) results.push(resource);
3126
4153
  }
3127
4154
  return results;
3128
4155
  }
3129
- function checkResource(src, type, managedDomains) {
4156
+ function checkResource(src, type, managedResources) {
3130
4157
  try {
3131
4158
  const url = new URL(src, window.location.origin);
3132
4159
  const domain = url.hostname;
3133
4160
  if (domain === window.location.hostname) return null;
3134
4161
  if ('data:' === url.protocol || 'blob:' === url.protocol) return null;
3135
- const managedBy = managedDomains.get(domain);
4162
+ const managedBy = findManagedScriptId(url, managedResources);
3136
4163
  const isManaged = Boolean(managedBy);
3137
4164
  return {
3138
4165
  type,
@@ -3144,6 +4171,21 @@ var __webpack_exports__ = {};
3144
4171
  } catch {}
3145
4172
  return null;
3146
4173
  }
4174
+ function findManagedScriptId(url, managedResources) {
4175
+ const domain = url.hostname;
4176
+ const path = normalizePathname(url.pathname);
4177
+ let bestMatch = null;
4178
+ for (const matcher of managedResources)if (matcher.domain === domain) {
4179
+ if ('/' === matcher.pathPrefix || path.startsWith(matcher.pathPrefix)) {
4180
+ if (!bestMatch || matcher.pathPrefix.length > bestMatch.pathPrefix.length) bestMatch = matcher;
4181
+ }
4182
+ }
4183
+ return bestMatch?.scriptId;
4184
+ }
4185
+ function normalizePathname(pathname) {
4186
+ const trimmed = pathname.trim();
4187
+ return trimmed.length > 0 ? trimmed : '/';
4188
+ }
3147
4189
  function createDomScannerSection(state) {
3148
4190
  let resultsContainer = null;
3149
4191
  let lastScanResults = [];
@@ -3307,22 +4349,37 @@ var __webpack_exports__ = {};
3307
4349
  <polyline points="16 18 22 12 16 6"></polyline>
3308
4350
  <polyline points="8 6 2 12 8 18"></polyline>
3309
4351
  </svg>`;
3310
- function scripts_renderScriptsPanel(container, options) {
3311
- const { getState } = options;
4352
+ const scriptsSearchByContainer = new WeakMap();
4353
+ function renderScriptsPanel(container, options) {
4354
+ const { getState, getEvents } = options;
3312
4355
  renderer_clearElement(container);
3313
4356
  const state = getState();
3314
- if (!state) return void container.appendChild(renderer_div({
3315
- style: {
3316
- padding: '24px',
3317
- textAlign: 'center',
3318
- color: 'var(--c15t-text-muted)',
3319
- fontSize: 'var(--c15t-devtools-font-size-sm)'
3320
- },
3321
- text: 'Store not connected'
3322
- }));
4357
+ if (!state) return void container.appendChild(createDisconnectedState());
3323
4358
  const scripts = state.scripts || [];
3324
4359
  const loadedScripts = state.loadedScripts || {};
3325
4360
  const networkBlocker = state.networkBlocker;
4361
+ const events = getEvents?.() ?? [];
4362
+ const searchQuery = scriptsSearchByContainer.get(container) ?? '';
4363
+ const filteredScripts = scripts.filter((script)=>{
4364
+ if (!searchQuery) return true;
4365
+ const category = 'string' == typeof script.category ? script.category : JSON.stringify(script.category);
4366
+ return `${script.id} ${category}`.toLowerCase().includes(searchQuery);
4367
+ });
4368
+ if (scripts.length > 4) container.appendChild(createSection({
4369
+ title: 'Filter',
4370
+ children: [
4371
+ createInput({
4372
+ value: searchQuery,
4373
+ placeholder: "Filter scripts…",
4374
+ ariaLabel: "Filter scripts",
4375
+ small: true,
4376
+ onInput: (value)=>{
4377
+ scriptsSearchByContainer.set(container, value.trim().toLowerCase());
4378
+ renderScriptsPanel(container, options);
4379
+ }
4380
+ })
4381
+ ]
4382
+ }));
3326
4383
  if (0 === scripts.length) {
3327
4384
  const scriptsSection = createSection({
3328
4385
  title: 'Configured Scripts',
@@ -3339,10 +4396,19 @@ var __webpack_exports__ = {};
3339
4396
  style: {
3340
4397
  display: 'flex',
3341
4398
  flexDirection: 'column',
3342
- gap: '4px'
4399
+ borderTop: '1px solid var(--c15t-border)',
4400
+ borderBottom: '1px solid var(--c15t-border)'
3343
4401
  }
3344
4402
  });
3345
- for (const script of scripts){
4403
+ if (0 === filteredScripts.length) scriptsList.appendChild(renderer_div({
4404
+ style: {
4405
+ padding: '10px 0',
4406
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
4407
+ color: 'var(--c15t-text-muted)'
4408
+ },
4409
+ text: "No matching scripts"
4410
+ }));
4411
+ for (const script of filteredScripts){
3346
4412
  const scriptId = script.id;
3347
4413
  const isLoaded = true === loadedScripts[scriptId];
3348
4414
  const category = script.category;
@@ -3366,17 +4432,64 @@ var __webpack_exports__ = {};
3366
4432
  text: status.charAt(0).toUpperCase() + status.slice(1),
3367
4433
  variant: statusVariant
3368
4434
  });
3369
- const item = createListItem({
3370
- title: scriptId,
3371
- description: `Category: ${categoryDisplay}`,
3372
- actions: [
3373
- badge
4435
+ const row = renderer_div({
4436
+ style: {
4437
+ display: 'flex',
4438
+ alignItems: 'center',
4439
+ justifyContent: 'space-between',
4440
+ gap: '8px',
4441
+ padding: '8px 0',
4442
+ borderBottom: '1px solid var(--c15t-border)'
4443
+ },
4444
+ children: [
4445
+ renderer_div({
4446
+ style: {
4447
+ display: 'flex',
4448
+ flexDirection: 'column',
4449
+ gap: '2px',
4450
+ minWidth: '0',
4451
+ flex: '1'
4452
+ },
4453
+ children: [
4454
+ renderer_div({
4455
+ style: {
4456
+ fontSize: 'var(--c15t-font-size-sm)',
4457
+ fontWeight: '500',
4458
+ color: 'var(--c15t-text)',
4459
+ overflow: 'hidden',
4460
+ textOverflow: 'ellipsis',
4461
+ whiteSpace: 'nowrap'
4462
+ },
4463
+ text: scriptId
4464
+ }),
4465
+ renderer_div({
4466
+ style: {
4467
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
4468
+ color: 'var(--c15t-text-muted)',
4469
+ overflow: 'hidden',
4470
+ textOverflow: 'ellipsis',
4471
+ whiteSpace: 'nowrap'
4472
+ },
4473
+ text: `Category: ${categoryDisplay}`
4474
+ })
4475
+ ]
4476
+ }),
4477
+ renderer_div({
4478
+ style: {
4479
+ flexShrink: '0'
4480
+ },
4481
+ children: [
4482
+ badge
4483
+ ]
4484
+ })
3374
4485
  ]
3375
4486
  });
3376
- scriptsList.appendChild(item);
4487
+ scriptsList.appendChild(row);
3377
4488
  }
4489
+ const lastRow = scriptsList.lastElementChild;
4490
+ if (lastRow) lastRow.style.borderBottom = 'none';
3378
4491
  const scriptsSection = createSection({
3379
- title: `Configured Scripts (${scripts.length})`,
4492
+ title: `Configured Scripts (${filteredScripts.length}/${scripts.length})`,
3380
4493
  children: [
3381
4494
  scriptsList
3382
4495
  ]
@@ -3405,6 +4518,20 @@ var __webpack_exports__ = {};
3405
4518
  ]
3406
4519
  });
3407
4520
  container.appendChild(networkSection);
4521
+ const blockedRequestEvents = events.filter((event)=>'network' === event.type);
4522
+ const networkEventsSection = createSection({
4523
+ title: `Blocked Requests (${blockedRequestEvents.length})`,
4524
+ children: 0 === blockedRequestEvents.length ? [
4525
+ renderer_div({
4526
+ style: {
4527
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
4528
+ color: 'var(--c15t-devtools-text-muted)'
4529
+ },
4530
+ text: 'No blocked network requests recorded in this session'
4531
+ })
4532
+ ] : createBlockedRequestContent(blockedRequestEvents)
4533
+ });
4534
+ container.appendChild(networkEventsSection);
3408
4535
  const loadedCount = Object.values(loadedScripts).filter(Boolean).length;
3409
4536
  const totalCount = scripts.length;
3410
4537
  const summarySection = createSection({
@@ -3430,12 +4557,80 @@ var __webpack_exports__ = {};
3430
4557
  }
3431
4558
  function checkScriptConsent(state, category) {
3432
4559
  if (!category) return true;
4560
+ if ('function' == typeof state.has) try {
4561
+ return state.has(category);
4562
+ } catch {}
3433
4563
  if ('string' == typeof category) {
3434
4564
  const consents = state.consents || {};
3435
4565
  return true === consents[category];
3436
4566
  }
3437
4567
  return false;
3438
4568
  }
4569
+ function createBlockedRequestContent(events) {
4570
+ const stats = new Map();
4571
+ for (const event of events){
4572
+ const ruleId = getEventRuleId(event) ?? 'unknown';
4573
+ stats.set(ruleId, (stats.get(ruleId) ?? 0) + 1);
4574
+ }
4575
+ const statsList = renderer_div({
4576
+ style: {
4577
+ display: 'flex',
4578
+ flexDirection: 'column',
4579
+ gap: '4px',
4580
+ marginBottom: '8px'
4581
+ },
4582
+ children: [
4583
+ ...stats.entries()
4584
+ ].sort((a, b)=>b[1] - a[1]).map(([ruleId, count])=>createInfoRow({
4585
+ label: 'unknown' === ruleId ? 'Unknown Rule' : `Rule: ${ruleId}`,
4586
+ value: `${count}`
4587
+ }))
4588
+ });
4589
+ const latestEvents = events.slice(0, 5);
4590
+ const latestList = renderer_div({
4591
+ style: {
4592
+ display: 'flex',
4593
+ flexDirection: 'column',
4594
+ gap: '4px'
4595
+ },
4596
+ children: latestEvents.map((event)=>createInfoRow({
4597
+ label: `${formatEventTime(event.timestamp)} ${getEventMethod(event)}`,
4598
+ value: scripts_truncateText(getEventUrl(event), 38)
4599
+ }))
4600
+ });
4601
+ return [
4602
+ statsList,
4603
+ latestList
4604
+ ];
4605
+ }
4606
+ function getEventRuleId(event) {
4607
+ const data = event.data;
4608
+ const rule = data?.rule;
4609
+ const ruleId = rule?.id ?? data?.ruleId;
4610
+ return 'string' == typeof ruleId || 'number' == typeof ruleId ? String(ruleId) : void 0;
4611
+ }
4612
+ function getEventMethod(event) {
4613
+ const data = event.data;
4614
+ const method = data?.method;
4615
+ return 'string' == typeof method ? method.toUpperCase() : 'REQ';
4616
+ }
4617
+ function getEventUrl(event) {
4618
+ const data = event.data;
4619
+ const url = data?.url;
4620
+ return 'string' == typeof url ? url : event.message;
4621
+ }
4622
+ function formatEventTime(timestamp) {
4623
+ return new Date(timestamp).toLocaleTimeString('en-US', {
4624
+ hour12: false,
4625
+ hour: '2-digit',
4626
+ minute: '2-digit',
4627
+ second: '2-digit'
4628
+ });
4629
+ }
4630
+ function scripts_truncateText(text, maxLength) {
4631
+ if (text.length <= maxLength) return text;
4632
+ return `${text.slice(0, maxLength - 3)}...`;
4633
+ }
3439
4634
  const STORAGE_KEYS = {
3440
4635
  C15T: 'c15t',
3441
4636
  PENDING_SYNC: 'c15t:pending-consent-sync',
@@ -3461,7 +4656,7 @@ var __webpack_exports__ = {};
3461
4656
  localStorage.removeItem(STORAGE_KEYS.EUCONSENT);
3462
4657
  } catch {}
3463
4658
  }
3464
- async function reset_consents_resetAllConsents(store, stateManager) {
4659
+ async function resetAllConsents(store, stateManager) {
3465
4660
  const storeState = store.getState();
3466
4661
  storeState.resetConsents();
3467
4662
  clearAllCookies();
@@ -3472,7 +4667,222 @@ var __webpack_exports__ = {};
3472
4667
  message: 'All consents reset (storage cleared)'
3473
4668
  });
3474
4669
  }
4670
+ function panel_renderer_createPanelRenderer(config) {
4671
+ const { storeConnector, stateManager, enableEventLogging = true, onPersistOverrides, onClearPersistedOverrides, onCopyState, onExportDebugBundle } = config;
4672
+ const getStoreState = ()=>storeConnector.getState();
4673
+ const logEvent = (type, message, data)=>{
4674
+ if (enableEventLogging) stateManager.addEvent({
4675
+ type,
4676
+ message,
4677
+ data
4678
+ });
4679
+ };
4680
+ const resetConsents = async ()=>{
4681
+ const store = storeConnector.getStore();
4682
+ if (store) await resetAllConsents(store, enableEventLogging ? stateManager : void 0);
4683
+ };
4684
+ const renderPanel = (container, tab)=>{
4685
+ switch(tab){
4686
+ case 'consents':
4687
+ renderConsentsPanel(container, {
4688
+ getState: getStoreState,
4689
+ onConsentChange: (name, value)=>{
4690
+ const store = storeConnector.getStore();
4691
+ if (store) {
4692
+ const consentName = String(name);
4693
+ store.getState().setSelectedConsent(consentName, value);
4694
+ logEvent('info', `${consentName} toggled to ${value} (not saved)`, {
4695
+ name: consentName,
4696
+ value
4697
+ });
4698
+ }
4699
+ },
4700
+ onSave: ()=>{
4701
+ const store = storeConnector.getStore();
4702
+ if (store) {
4703
+ store.getState().saveConsents('custom');
4704
+ logEvent('consent_save', 'Saved consent preferences');
4705
+ }
4706
+ },
4707
+ onAcceptAll: ()=>{
4708
+ const store = storeConnector.getStore();
4709
+ if (store) {
4710
+ store.getState().saveConsents('all');
4711
+ logEvent('consent_save', 'Accepted all consents');
4712
+ }
4713
+ },
4714
+ onRejectAll: ()=>{
4715
+ const store = storeConnector.getStore();
4716
+ if (store) {
4717
+ store.getState().saveConsents('necessary');
4718
+ logEvent('consent_save', 'Rejected all optional consents');
4719
+ }
4720
+ },
4721
+ onReset: resetConsents
4722
+ });
4723
+ break;
4724
+ case 'location':
4725
+ renderLocationPanel(container, {
4726
+ getState: getStoreState,
4727
+ onApplyOverrides: async (overrides)=>{
4728
+ const store = storeConnector.getStore();
4729
+ if (store) {
4730
+ await store.getState().setOverrides({
4731
+ country: overrides.country,
4732
+ region: overrides.region,
4733
+ language: overrides.language,
4734
+ gpc: overrides.gpc
4735
+ });
4736
+ logEvent('info', 'Overrides updated', {
4737
+ country: overrides.country,
4738
+ region: overrides.region,
4739
+ language: overrides.language,
4740
+ gpc: overrides.gpc
4741
+ });
4742
+ onPersistOverrides?.({
4743
+ country: overrides.country,
4744
+ region: overrides.region,
4745
+ language: overrides.language,
4746
+ gpc: overrides.gpc
4747
+ });
4748
+ }
4749
+ },
4750
+ onClearOverrides: async ()=>{
4751
+ const store = storeConnector.getStore();
4752
+ if (store) {
4753
+ await store.getState().setOverrides({
4754
+ country: void 0,
4755
+ region: void 0,
4756
+ language: void 0,
4757
+ gpc: void 0
4758
+ });
4759
+ logEvent('info', 'Overrides cleared');
4760
+ onClearPersistedOverrides?.();
4761
+ }
4762
+ }
4763
+ });
4764
+ break;
4765
+ case "scripts":
4766
+ renderScriptsPanel(container, {
4767
+ getState: getStoreState,
4768
+ getEvents: ()=>stateManager.getState().eventLog
4769
+ });
4770
+ break;
4771
+ case 'iab':
4772
+ renderIabPanel(container, {
4773
+ getState: getStoreState,
4774
+ onSetPurposeConsent: (purposeId, value)=>{
4775
+ const iab = storeConnector.getStore()?.getState().iab;
4776
+ if (!iab) return;
4777
+ iab.setPurposeConsent(purposeId, value);
4778
+ logEvent('iab', `IAB purpose ${purposeId} set to ${value}`);
4779
+ },
4780
+ onSetVendorConsent: (vendorId, value)=>{
4781
+ const iab = storeConnector.getStore()?.getState().iab;
4782
+ if (!iab) return;
4783
+ iab.setVendorConsent(vendorId, value);
4784
+ logEvent('iab', `IAB vendor ${vendorId} set to ${value}`);
4785
+ },
4786
+ onSetSpecialFeatureOptIn: (featureId, value)=>{
4787
+ const iab = storeConnector.getStore()?.getState().iab;
4788
+ if (!iab) return;
4789
+ iab.setSpecialFeatureOptIn(featureId, value);
4790
+ logEvent('iab', `IAB feature ${featureId} set to ${value}`);
4791
+ },
4792
+ onAcceptAll: ()=>{
4793
+ const iab = storeConnector.getStore()?.getState().iab;
4794
+ if (!iab) return;
4795
+ iab.acceptAll();
4796
+ logEvent('iab', 'IAB accept all selected');
4797
+ },
4798
+ onRejectAll: ()=>{
4799
+ const iab = storeConnector.getStore()?.getState().iab;
4800
+ if (!iab) return;
4801
+ iab.rejectAll();
4802
+ logEvent('iab', 'IAB reject all selected');
4803
+ },
4804
+ onSave: ()=>{
4805
+ const iab = storeConnector.getStore()?.getState().iab;
4806
+ if (!iab) return;
4807
+ iab.save().then(()=>logEvent('iab', 'IAB preferences saved')).catch((error)=>{
4808
+ logEvent('error', `Failed to save IAB preferences: ${String(error)}`);
4809
+ });
4810
+ },
4811
+ onReset: resetConsents
4812
+ });
4813
+ break;
4814
+ case 'events':
4815
+ renderEventsPanel(container, {
4816
+ getEvents: ()=>stateManager.getState().eventLog,
4817
+ onClear: ()=>{
4818
+ stateManager.clearEventLog();
4819
+ logEvent('info', 'Event log cleared');
4820
+ }
4821
+ });
4822
+ break;
4823
+ case 'actions':
4824
+ renderActionsPanel(container, {
4825
+ getState: getStoreState,
4826
+ onResetConsents: resetConsents,
4827
+ onRefetchBanner: async ()=>{
4828
+ const store = storeConnector.getStore();
4829
+ if (store) {
4830
+ await store.getState().initConsentManager();
4831
+ logEvent('info', 'Banner data refetched');
4832
+ }
4833
+ },
4834
+ onShowBanner: ()=>{
4835
+ const store = storeConnector.getStore();
4836
+ if (store) {
4837
+ store.getState().setActiveUI('banner', {
4838
+ force: true
4839
+ });
4840
+ logEvent('info', 'Banner shown');
4841
+ }
4842
+ },
4843
+ onOpenPreferences: ()=>{
4844
+ const store = storeConnector.getStore();
4845
+ if (store) {
4846
+ store.getState().setActiveUI('dialog');
4847
+ logEvent('info', 'Preferences dialog opened');
4848
+ }
4849
+ },
4850
+ onCopyState: ()=>{
4851
+ const state = getStoreState();
4852
+ if (state) if (onCopyState) {
4853
+ const result = onCopyState(state);
4854
+ if (result instanceof Promise) result.then((ok)=>{
4855
+ logEvent(ok ? 'info' : 'error', ok ? 'State copied to clipboard' : 'Failed to copy state');
4856
+ }).catch(()=>{
4857
+ logEvent('error', 'Failed to copy state');
4858
+ });
4859
+ else logEvent(result ? 'info' : 'error', result ? 'State copied to clipboard' : 'Failed to copy state');
4860
+ } else navigator.clipboard.writeText(JSON.stringify(state, null, 2)).then(()=>{
4861
+ logEvent('info', 'State copied to clipboard');
4862
+ }).catch(()=>{
4863
+ logEvent('error', 'Failed to copy state');
4864
+ });
4865
+ },
4866
+ onExportDebugBundle: onExportDebugBundle ? ()=>{
4867
+ try {
4868
+ onExportDebugBundle();
4869
+ logEvent('info', 'Debug bundle exported');
4870
+ } catch {
4871
+ logEvent('error', 'Failed to export debug bundle');
4872
+ }
4873
+ } : void 0
4874
+ });
4875
+ break;
4876
+ }
4877
+ };
4878
+ return {
4879
+ renderPanel,
4880
+ getStoreState,
4881
+ resetConsents
4882
+ };
4883
+ }
3475
4884
  const STORAGE_KEY = 'c15t-devtools-events';
4885
+ const ACTIVE_TAB_STORAGE_KEY = 'c15t-devtools-active-tab';
3476
4886
  function loadPersistedEvents() {
3477
4887
  if ('undefined' == typeof window) return [];
3478
4888
  try {
@@ -3487,11 +4897,29 @@ var __webpack_exports__ = {};
3487
4897
  sessionStorage.setItem(STORAGE_KEY, JSON.stringify(events));
3488
4898
  } catch {}
3489
4899
  }
4900
+ function isDevToolsTab(value) {
4901
+ return 'consents' === value || 'location' === value || "scripts" === value || 'iab' === value || 'events' === value || 'actions' === value;
4902
+ }
4903
+ function loadPersistedActiveTab() {
4904
+ if ('undefined' == typeof window) return null;
4905
+ try {
4906
+ const stored = localStorage.getItem(ACTIVE_TAB_STORAGE_KEY);
4907
+ if (isDevToolsTab(stored)) return stored;
4908
+ } catch {}
4909
+ return null;
4910
+ }
4911
+ function persistActiveTab(tab) {
4912
+ if ('undefined' == typeof window) return;
4913
+ try {
4914
+ localStorage.setItem(ACTIVE_TAB_STORAGE_KEY, tab);
4915
+ } catch {}
4916
+ }
3490
4917
  function state_manager_createStateManager(initialState = {}) {
3491
4918
  const persistedEvents = loadPersistedEvents();
4919
+ const persistedActiveTab = loadPersistedActiveTab();
3492
4920
  let state = {
3493
4921
  isOpen: false,
3494
- activeTab: 'location',
4922
+ activeTab: persistedActiveTab ?? 'location',
3495
4923
  position: 'bottom-right',
3496
4924
  isConnected: false,
3497
4925
  eventLog: persistedEvents,
@@ -3532,6 +4960,7 @@ var __webpack_exports__ = {};
3532
4960
  setState({
3533
4961
  activeTab: tab
3534
4962
  });
4963
+ persistActiveTab(tab);
3535
4964
  },
3536
4965
  setPosition: (position)=>{
3537
4966
  setState({
@@ -3573,12 +5002,67 @@ var __webpack_exports__ = {};
3573
5002
  const { namespace = 'c15tStore', onConnect, onStateChange, onDisconnect } = options;
3574
5003
  let store = null;
3575
5004
  let unsubscribe = null;
3576
- let pollInterval = null;
5005
+ let reconnectTimeout = null;
5006
+ let reconnectAttempts = 0;
5007
+ let hasNotifiedDisconnect = false;
3577
5008
  const listeners = new Set();
5009
+ const diagnosticsListeners = new Set();
5010
+ let diagnostics = {
5011
+ namespace,
5012
+ reconnectAttempts: 0,
5013
+ nextRetryInMs: null,
5014
+ lastError: null,
5015
+ isPolling: false,
5016
+ disconnectNotified: false
5017
+ };
5018
+ const INITIAL_RETRY_DELAY_MS = 100;
5019
+ const MAX_RETRY_DELAY_MS = 2000;
5020
+ const DISCONNECT_NOTIFY_ATTEMPTS = 5;
5021
+ function updateDiagnostics(partial, notify = true) {
5022
+ diagnostics = {
5023
+ ...diagnostics,
5024
+ ...partial
5025
+ };
5026
+ if (!notify) return;
5027
+ for (const listener of diagnosticsListeners)listener(diagnostics);
5028
+ }
5029
+ function clearReconnectTimer() {
5030
+ if (reconnectTimeout) {
5031
+ clearTimeout(reconnectTimeout);
5032
+ reconnectTimeout = null;
5033
+ updateDiagnostics({
5034
+ isPolling: false,
5035
+ nextRetryInMs: null
5036
+ });
5037
+ }
5038
+ }
5039
+ function resetReconnectState() {
5040
+ reconnectAttempts = 0;
5041
+ hasNotifiedDisconnect = false;
5042
+ updateDiagnostics({
5043
+ reconnectAttempts: 0,
5044
+ nextRetryInMs: null,
5045
+ lastError: null,
5046
+ disconnectNotified: false
5047
+ });
5048
+ }
5049
+ function notifyDisconnectedOnce() {
5050
+ if (hasNotifiedDisconnect) return;
5051
+ hasNotifiedDisconnect = true;
5052
+ updateDiagnostics({
5053
+ disconnectNotified: true
5054
+ });
5055
+ onDisconnect?.();
5056
+ }
3578
5057
  function tryConnect() {
3579
5058
  if ('undefined' == typeof window) return false;
3580
5059
  const storeInstance = window[namespace];
3581
5060
  if (storeInstance && 'function' == typeof storeInstance.getState) {
5061
+ if (store === storeInstance && unsubscribe) return true;
5062
+ if (unsubscribe) {
5063
+ unsubscribe();
5064
+ unsubscribe = null;
5065
+ }
3582
5066
  store = storeInstance;
3583
5067
  unsubscribe = store.subscribe((state)=>{
3584
5068
  onStateChange?.(state);
@@ -3586,30 +5070,41 @@ var __webpack_exports__ = {};
3586
5070
  });
3587
5071
  const currentState = store.getState();
3588
5072
  onConnect?.(currentState, store);
3589
- if (pollInterval) {
3590
- clearInterval(pollInterval);
3591
- pollInterval = null;
3592
- }
5073
+ clearReconnectTimer();
5074
+ resetReconnectState();
5075
+ updateDiagnostics({
5076
+ lastError: null
5077
+ });
3593
5078
  return true;
3594
5079
  }
5080
+ updateDiagnostics({
5081
+ lastError: `Store "${namespace}" not found on window`
5082
+ });
3595
5083
  return false;
3596
5084
  }
5085
+ function scheduleReconnect(immediate = false) {
5086
+ if (store || reconnectTimeout) return;
5087
+ const delay = immediate ? 0 : Math.min(INITIAL_RETRY_DELAY_MS * 2 ** Math.min(reconnectAttempts, 5), MAX_RETRY_DELAY_MS);
5088
+ updateDiagnostics({
5089
+ isPolling: true,
5090
+ nextRetryInMs: delay,
5091
+ reconnectAttempts
5092
+ });
5093
+ reconnectTimeout = setTimeout(()=>{
5094
+ reconnectTimeout = null;
5095
+ reconnectAttempts++;
5096
+ updateDiagnostics({
5097
+ reconnectAttempts,
5098
+ nextRetryInMs: null
5099
+ });
5100
+ if (tryConnect()) return;
5101
+ if (reconnectAttempts >= DISCONNECT_NOTIFY_ATTEMPTS) notifyDisconnectedOnce();
5102
+ scheduleReconnect();
5103
+ }, delay);
5104
+ }
3597
5105
  function startPolling() {
3598
- if (pollInterval) return;
3599
5106
  if (tryConnect()) return;
3600
- let attempts = 0;
3601
- const maxAttempts = 50;
3602
- pollInterval = setInterval(()=>{
3603
- attempts++;
3604
- if (tryConnect()) return;
3605
- if (attempts >= maxAttempts) {
3606
- if (pollInterval) {
3607
- clearInterval(pollInterval);
3608
- pollInterval = null;
3609
- }
3610
- onDisconnect?.();
3611
- }
3612
- }, 100);
5107
+ scheduleReconnect(true);
3613
5108
  }
3614
5109
  startPolling();
3615
5110
  return {
@@ -3623,17 +5118,155 @@ var __webpack_exports__ = {};
3623
5118
  listeners.delete(listener);
3624
5119
  };
3625
5120
  },
5121
+ getDiagnostics: ()=>diagnostics,
5122
+ subscribeDiagnostics: (listener)=>{
5123
+ diagnosticsListeners.add(listener);
5124
+ listener(diagnostics);
5125
+ return ()=>{
5126
+ diagnosticsListeners.delete(listener);
5127
+ };
5128
+ },
5129
+ retryConnection: ()=>{
5130
+ if (store) return;
5131
+ resetReconnectState();
5132
+ scheduleReconnect(true);
5133
+ },
3626
5134
  destroy: ()=>{
3627
- if (pollInterval) {
3628
- clearInterval(pollInterval);
3629
- pollInterval = null;
3630
- }
5135
+ clearReconnectTimer();
3631
5136
  if (unsubscribe) {
3632
5137
  unsubscribe();
3633
5138
  unsubscribe = null;
3634
5139
  }
3635
5140
  store = null;
3636
5141
  listeners.clear();
5142
+ diagnosticsListeners.clear();
5143
+ }
5144
+ };
5145
+ }
5146
+ const REGISTRY_KEY = '__c15tDevToolsInstrumentationRegistry';
5147
+ let fallbackRegistry = null;
5148
+ function getRegistry() {
5149
+ if ('undefined' == typeof window) {
5150
+ if (!fallbackRegistry) fallbackRegistry = new Map();
5151
+ return fallbackRegistry;
5152
+ }
5153
+ const host = window;
5154
+ const existing = host[REGISTRY_KEY];
5155
+ if (existing) return existing;
5156
+ const registry = new Map();
5157
+ host[REGISTRY_KEY] = registry;
5158
+ return registry;
5159
+ }
5160
+ function getBlockedRequestMessage(payload) {
5161
+ const data = payload;
5162
+ const method = 'string' == typeof data?.method ? data.method.toUpperCase() : 'REQUEST';
5163
+ const url = 'string' == typeof data?.url ? data.url : 'unknown-url';
5164
+ return `Network blocked: ${method} ${url}`;
5165
+ }
5166
+ function emitEvent(entry, event) {
5167
+ for (const listener of entry.listeners)listener(event);
5168
+ }
5169
+ function ensureNetworkBlockerWrapped(entry) {
5170
+ const blocker = entry.store.getState().networkBlocker;
5171
+ if (!blocker) return;
5172
+ if (blocker.onRequestBlocked === entry.wrappedNetworkBlockedCallback) return;
5173
+ entry.originalNetworkBlockedCallback = blocker.onRequestBlocked;
5174
+ entry.wrappedNetworkBlockedCallback = (payload)=>{
5175
+ emitEvent(entry, {
5176
+ type: 'network',
5177
+ message: getBlockedRequestMessage(payload),
5178
+ data: payload
5179
+ });
5180
+ if ('function' == typeof entry.originalNetworkBlockedCallback) entry.originalNetworkBlockedCallback(payload);
5181
+ };
5182
+ entry.store.getState().setNetworkBlocker({
5183
+ ...blocker,
5184
+ onRequestBlocked: entry.wrappedNetworkBlockedCallback
5185
+ });
5186
+ }
5187
+ function restoreInstrumentation(entry) {
5188
+ entry.stopWatchingStore?.();
5189
+ entry.stopWatchingStore = null;
5190
+ const state = entry.store.getState();
5191
+ state.setCallback('onBannerFetched', entry.originalCallbacks.onBannerFetched);
5192
+ state.setCallback('onConsentSet', entry.originalCallbacks.onConsentSet);
5193
+ state.setCallback('onError', entry.originalCallbacks.onError);
5194
+ state.setCallback('onBeforeConsentRevocationReload', entry.originalCallbacks.onBeforeConsentRevocationReload);
5195
+ const blocker = state.networkBlocker;
5196
+ if (blocker && blocker.onRequestBlocked === entry.wrappedNetworkBlockedCallback) state.setNetworkBlocker({
5197
+ ...blocker,
5198
+ onRequestBlocked: entry.originalNetworkBlockedCallback
5199
+ });
5200
+ entry.wrappedNetworkBlockedCallback = null;
5201
+ }
5202
+ function createInstrumentationEntry(store) {
5203
+ const entry = {
5204
+ store,
5205
+ listeners: new Set(),
5206
+ originalCallbacks: {
5207
+ ...store.getState().callbacks
5208
+ },
5209
+ originalNetworkBlockedCallback: store.getState().networkBlocker?.onRequestBlocked,
5210
+ wrappedNetworkBlockedCallback: null,
5211
+ stopWatchingStore: null
5212
+ };
5213
+ store.getState().setCallback('onBannerFetched', (payload)=>{
5214
+ const jurisdiction = payload.jurisdiction;
5215
+ emitEvent(entry, {
5216
+ type: 'info',
5217
+ message: `Banner fetched: ${String(jurisdiction)}`,
5218
+ data: payload
5219
+ });
5220
+ if ('function' == typeof entry.originalCallbacks.onBannerFetched) entry.originalCallbacks.onBannerFetched(payload);
5221
+ });
5222
+ store.getState().setCallback('onConsentSet', (payload)=>{
5223
+ emitEvent(entry, {
5224
+ type: 'consent_set',
5225
+ message: 'Consent preferences updated',
5226
+ data: payload
5227
+ });
5228
+ if ('function' == typeof entry.originalCallbacks.onConsentSet) entry.originalCallbacks.onConsentSet(payload);
5229
+ });
5230
+ store.getState().setCallback('onError', (payload)=>{
5231
+ const errorMessage = payload.error;
5232
+ emitEvent(entry, {
5233
+ type: 'error',
5234
+ message: `Error: ${String(errorMessage)}`,
5235
+ data: payload
5236
+ });
5237
+ if ('function' == typeof entry.originalCallbacks.onError) entry.originalCallbacks.onError(payload);
5238
+ });
5239
+ store.getState().setCallback('onBeforeConsentRevocationReload', (payload)=>{
5240
+ emitEvent(entry, {
5241
+ type: 'info',
5242
+ message: 'Consent revocation - page will reload',
5243
+ data: payload
5244
+ });
5245
+ if ('function' == typeof entry.originalCallbacks.onBeforeConsentRevocationReload) entry.originalCallbacks.onBeforeConsentRevocationReload(payload);
5246
+ });
5247
+ ensureNetworkBlockerWrapped(entry);
5248
+ entry.stopWatchingStore = store.subscribe(()=>{
5249
+ ensureNetworkBlockerWrapped(entry);
5250
+ });
5251
+ return entry;
5252
+ }
5253
+ function store_instrumentation_registerStoreInstrumentation(options) {
5254
+ const { namespace, store, onEvent } = options;
5255
+ const registry = getRegistry();
5256
+ let entry = registry.get(namespace);
5257
+ if (!entry || entry.store !== store) {
5258
+ if (entry) restoreInstrumentation(entry);
5259
+ entry = createInstrumentationEntry(store);
5260
+ registry.set(namespace, entry);
5261
+ }
5262
+ entry.listeners.add(onEvent);
5263
+ return ()=>{
5264
+ const current = registry.get(namespace);
5265
+ if (!current) return;
5266
+ current.listeners.delete(onEvent);
5267
+ if (0 === current.listeners.size) {
5268
+ restoreInstrumentation(current);
5269
+ registry.delete(namespace);
3637
5270
  }
3638
5271
  };
3639
5272
  }
@@ -3646,15 +5279,88 @@ var __webpack_exports__ = {};
3646
5279
  tokens_options.insertStyleElement = insertStyleElement_default();
3647
5280
  injectStylesIntoStyleTag_default()(tokens.A, tokens_options);
3648
5281
  tokens.A && tokens.A.locals && tokens.A.locals;
5282
+ function normalizeOverridesForPersistence(overrides) {
5283
+ return {
5284
+ country: overrides?.country?.trim() || void 0,
5285
+ region: overrides?.region?.trim() || void 0,
5286
+ language: overrides?.language?.trim() || void 0,
5287
+ gpc: overrides?.gpc
5288
+ };
5289
+ }
5290
+ function persistedOverridesEqual(a, b) {
5291
+ return a.country === b.country && a.region === b.region && a.language === b.language && a.gpc === b.gpc;
5292
+ }
5293
+ function createStateCopy(state) {
5294
+ return {
5295
+ consents: state.consents,
5296
+ selectedConsents: state.selectedConsents,
5297
+ consentInfo: state.consentInfo,
5298
+ locationInfo: state.locationInfo,
5299
+ model: state.model,
5300
+ overrides: state.overrides,
5301
+ scripts: state.scripts?.map((script)=>({
5302
+ id: script.id
5303
+ })),
5304
+ loadedScripts: state.loadedScripts
5305
+ };
5306
+ }
3649
5307
  function createDevToolsPanel(options) {
3650
5308
  const { namespace = 'c15tStore' } = options;
5309
+ let detachInstrumentation = null;
3651
5310
  const stateManager = state_manager_createStateManager({
3652
5311
  isOpen: true
3653
5312
  });
3654
5313
  const storeConnector = store_connector_createStoreConnector({
3655
5314
  namespace,
3656
- onConnect: ()=>stateManager.setConnected(true),
3657
- onDisconnect: ()=>stateManager.setConnected(false)
5315
+ onConnect: (state, store)=>{
5316
+ detachInstrumentation?.();
5317
+ detachInstrumentation = store_instrumentation_registerStoreInstrumentation({
5318
+ namespace,
5319
+ store,
5320
+ onEvent: (event)=>stateManager.addEvent(event)
5321
+ });
5322
+ stateManager.setConnected(true);
5323
+ const persistedOverrides = override_storage_loadPersistedOverrides();
5324
+ if (persistedOverrides) {
5325
+ const currentOverrides = normalizeOverridesForPersistence(state.overrides);
5326
+ if (!persistedOverridesEqual(persistedOverrides, currentOverrides)) store.getState().setOverrides({
5327
+ country: persistedOverrides.country,
5328
+ region: persistedOverrides.region,
5329
+ language: persistedOverrides.language,
5330
+ gpc: persistedOverrides.gpc
5331
+ });
5332
+ }
5333
+ },
5334
+ onDisconnect: ()=>{
5335
+ stateManager.setConnected(false);
5336
+ detachInstrumentation?.();
5337
+ detachInstrumentation = null;
5338
+ }
5339
+ });
5340
+ const panelRenderer = panel_renderer_createPanelRenderer({
5341
+ storeConnector,
5342
+ stateManager,
5343
+ enableEventLogging: false,
5344
+ onPersistOverrides: override_storage_persistOverrides,
5345
+ onClearPersistedOverrides: override_storage_clearPersistedOverrides,
5346
+ onCopyState: async (state)=>{
5347
+ try {
5348
+ await navigator.clipboard.writeText(JSON.stringify(createStateCopy(state), null, 2));
5349
+ return true;
5350
+ } catch {
5351
+ return false;
5352
+ }
5353
+ },
5354
+ onExportDebugBundle: ()=>{
5355
+ const bundle = debug_bundle_createDebugBundle({
5356
+ namespace,
5357
+ devToolsState: stateManager.getState(),
5358
+ connection: storeConnector.getDiagnostics(),
5359
+ recentEvents: stateManager.getState().eventLog.slice(0, 100),
5360
+ storeState: debug_bundle_sanitizeStoreState(storeConnector.getState())
5361
+ });
5362
+ debug_bundle_downloadDebugBundle(bundle);
5363
+ }
3658
5364
  });
3659
5365
  const container = renderer_div({
3660
5366
  style: {
@@ -3675,108 +5381,42 @@ var __webpack_exports__ = {};
3675
5381
  }
3676
5382
  });
3677
5383
  function renderActivePanel() {
3678
- const state = stateManager.getState();
3679
- const getStoreState = ()=>storeConnector.getState();
3680
- switch(state.activeTab){
3681
- case 'consents':
3682
- consents_renderConsentsPanel(contentArea, {
3683
- getState: getStoreState,
3684
- onConsentChange: (name, value)=>{
3685
- storeConnector.getStore()?.getState().setSelectedConsent(name, value);
3686
- },
3687
- onSave: ()=>{
3688
- storeConnector.getStore()?.getState().saveConsents('custom');
3689
- },
3690
- onAcceptAll: ()=>{
3691
- storeConnector.getStore()?.getState().saveConsents('all');
3692
- },
3693
- onRejectAll: ()=>{
3694
- storeConnector.getStore()?.getState().saveConsents('necessary');
3695
- },
3696
- onReset: async ()=>{
3697
- const store = storeConnector.getStore();
3698
- if (store) await reset_consents_resetAllConsents(store);
3699
- }
3700
- });
3701
- break;
3702
- case 'location':
3703
- location_renderLocationPanel(contentArea, {
3704
- getState: getStoreState,
3705
- onSetOverrides: async (overrides)=>{
3706
- const store = storeConnector.getStore();
3707
- if (store) {
3708
- const current = store.getState().overrides || {};
3709
- await store.getState().setOverrides({
3710
- ...current,
3711
- ...overrides
3712
- });
3713
- }
3714
- },
3715
- onClearOverrides: async ()=>{
3716
- await storeConnector.getStore()?.getState().setOverrides(void 0);
3717
- }
3718
- });
3719
- break;
3720
- case "scripts":
3721
- scripts_renderScriptsPanel(contentArea, {
3722
- getState: getStoreState
3723
- });
3724
- break;
3725
- case 'iab':
3726
- iab_renderIabPanel(contentArea, {
3727
- getState: getStoreState,
3728
- onReset: async ()=>{
3729
- const store = storeConnector.getStore();
3730
- if (store) await reset_consents_resetAllConsents(store);
3731
- }
3732
- });
3733
- break;
3734
- case 'events':
3735
- events_renderEventsPanel(contentArea, {
3736
- getEvents: ()=>stateManager.getState().eventLog,
3737
- onClear: ()=>{
3738
- stateManager.clearEventLog();
3739
- }
3740
- });
3741
- break;
3742
- case 'actions':
3743
- actions_renderActionsPanel(contentArea, {
3744
- getState: getStoreState,
3745
- onResetConsents: async ()=>{
3746
- const store = storeConnector.getStore();
3747
- if (store) await reset_consents_resetAllConsents(store);
3748
- },
3749
- onRefetchBanner: async ()=>{
3750
- await storeConnector.getStore()?.getState().initConsentManager();
3751
- },
3752
- onShowBanner: ()=>{
3753
- storeConnector.getStore()?.getState().setActiveUI('banner', {
3754
- force: true
3755
- });
3756
- },
3757
- onOpenPreferences: ()=>{
3758
- storeConnector.getStore()?.getState().setActiveUI('dialog');
3759
- },
3760
- onCopyState: ()=>{
3761
- const state = storeConnector.getState();
3762
- if (state) navigator.clipboard.writeText(JSON.stringify(state, null, 2));
3763
- }
3764
- });
3765
- break;
5384
+ const activeTab = syncTabs();
5385
+ panelRenderer.renderPanel(contentArea, activeTab);
5386
+ }
5387
+ let tabsInstance = null;
5388
+ let iabDisabled = true;
5389
+ function getDisabledTabs() {
5390
+ const disabledTabs = [];
5391
+ const storeState = storeConnector.getState();
5392
+ if (!storeState || 'iab' !== storeState.model) disabledTabs.push('iab');
5393
+ return disabledTabs;
5394
+ }
5395
+ function syncTabs() {
5396
+ const disabledTabs = getDisabledTabs();
5397
+ const nextIabDisabled = disabledTabs.includes('iab');
5398
+ let activeTab = stateManager.getState().activeTab;
5399
+ if (disabledTabs.includes(activeTab)) {
5400
+ activeTab = 'consents';
5401
+ stateManager.setActiveTab(activeTab);
3766
5402
  }
5403
+ if (tabsInstance && iabDisabled === nextIabDisabled) tabsInstance.setActiveTab(activeTab);
5404
+ else {
5405
+ tabsInstance?.destroy();
5406
+ tabsInstance = tabs_createTabs({
5407
+ activeTab,
5408
+ onTabChange: (tab)=>{
5409
+ stateManager.setActiveTab(tab);
5410
+ renderActivePanel();
5411
+ },
5412
+ disabledTabs
5413
+ });
5414
+ iabDisabled = nextIabDisabled;
5415
+ if (!tabsInstance.element.parentElement) container.appendChild(tabsInstance.element);
5416
+ }
5417
+ return activeTab;
3767
5418
  }
3768
- const storeState = storeConnector.getState();
3769
- const disabledTabs = [];
3770
- if (!storeState || 'iab' !== storeState.model) disabledTabs.push('iab');
3771
- const tabsInstance = tabs_createTabs({
3772
- activeTab: stateManager.getState().activeTab,
3773
- onTabChange: (tab)=>{
3774
- stateManager.setActiveTab(tab);
3775
- renderActivePanel();
3776
- },
3777
- disabledTabs
3778
- });
3779
- container.appendChild(tabsInstance.element);
5419
+ syncTabs();
3780
5420
  container.appendChild(contentArea);
3781
5421
  renderActivePanel();
3782
5422
  const unsubscribe = storeConnector.subscribe(()=>{
@@ -3785,8 +5425,10 @@ var __webpack_exports__ = {};
3785
5425
  return {
3786
5426
  element: container,
3787
5427
  destroy: ()=>{
5428
+ detachInstrumentation?.();
5429
+ detachInstrumentation = null;
3788
5430
  unsubscribe();
3789
- tabsInstance.destroy();
5431
+ tabsInstance?.destroy();
3790
5432
  storeConnector.destroy();
3791
5433
  stateManager.destroy();
3792
5434
  }