@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/react.cjs CHANGED
@@ -261,21 +261,21 @@ var __webpack_modules__ = {
261
261
  module.id,
262
262
  `.toggle-bPZtik {
263
263
  border-radius: var(--c15t-radius-full, 9999px);
264
- background-color: var(--c15t-switch-track, #ccc);
264
+ background-color: var(--c15t-switch-track, #d9d9d9);
265
265
  cursor: pointer;
266
- width: 36px;
267
- height: 20px;
268
- transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
266
+ width: 2rem;
267
+ height: 1.25rem;
268
+ 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));
269
269
  border: none;
270
270
  align-items: center;
271
- padding: 0;
271
+ padding: .125rem;
272
272
  display: inline-flex;
273
273
  position: relative;
274
274
  }
275
275
 
276
276
  .toggle-bPZtik:focus-visible {
277
- outline: 2px solid var(--c15t-primary, #335cff);
278
- outline-offset: 2px;
277
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
278
+ outline: none;
279
279
  }
280
280
 
281
281
  .toggleActive-Ldlasg {
@@ -285,16 +285,16 @@ var __webpack_modules__ = {
285
285
  .toggleThumb-hjGfoX {
286
286
  border-radius: var(--c15t-radius-full, 9999px);
287
287
  background-color: var(--c15t-switch-thumb, #fff);
288
- width: 16px;
289
- height: 16px;
290
- transition: transform var(--c15t-duration-fast, .1s) var(--c15t-easing-spring, cubic-bezier(.34, 1.56, .64, 1));
288
+ width: .75rem;
289
+ height: .75rem;
290
+ box-shadow: 0 0 0 1px var(--c15t-border, #e3e3e3);
291
+ transition: transform var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
291
292
  position: absolute;
292
293
  left: 2px;
293
- box-shadow: 0 1px 2px #0003;
294
294
  }
295
295
 
296
296
  .toggleActive-Ldlasg .toggleThumb-hjGfoX {
297
- transform: translateX(16px);
297
+ transform: translateX(1rem);
298
298
  }
299
299
 
300
300
  .toggle-bPZtik:disabled, .toggleDisabled-ZcD8nZ {
@@ -307,13 +307,14 @@ var __webpack_modules__ = {
307
307
  }
308
308
 
309
309
  .badge-yA0giZ {
310
- border-radius: var(--c15t-radius-sm, .25rem);
310
+ border-radius: var(--c15t-radius-full, 9999px);
311
311
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
312
312
  font-weight: var(--c15t-font-weight-medium, 500);
313
+ line-height: var(--c15t-line-height-tight, 1.25);
313
314
  white-space: nowrap;
315
+ justify-content: center;
314
316
  align-items: center;
315
- padding: 2px 6px;
316
- line-height: 1;
317
+ padding: .1875rem .4375rem;
317
318
  display: inline-flex;
318
319
  }
319
320
 
@@ -346,38 +347,49 @@ var __webpack_modules__ = {
346
347
  justify-content: center;
347
348
  align-items: center;
348
349
  gap: var(--c15t-space-xs, .25rem);
349
- padding: var(--c15t-space-xs, .25rem) var(--c15t-space-sm, .5rem);
350
- border: 1px solid var(--c15t-border, #e3e3e3);
350
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
351
351
  border-radius: var(--c15t-radius-md, .5rem);
352
- background-color: var(--c15t-surface, #fff);
352
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
353
+ min-height: 2rem;
353
354
  color: var(--c15t-text, #171717);
354
- font-family: inherit;
355
- font-size: var(--c15t-devtools-font-size-xs, .75rem);
355
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
356
+ font-size: var(--c15t-font-size-sm, .875rem);
356
357
  font-weight: var(--c15t-font-weight-medium, 500);
358
+ line-height: var(--c15t-line-height-tight, 1.25);
359
+ box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000000d);
357
360
  cursor: pointer;
358
- 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));
361
+ 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));
362
+ padding: .375rem .625rem;
359
363
  display: inline-flex;
360
364
  }
361
365
 
362
366
  .btn-evRVlh:hover {
363
- background-color: var(--c15t-surface-hover, #f7f7f7);
367
+ background-color: var(--c15t-devtools-surface-subtle, #f7f7f7);
364
368
  border-color: var(--c15t-border-hover, #c9c9c9);
369
+ box-shadow: var(--c15t-shadow-md, 0 4px 12px #00000014);
365
370
  }
366
371
 
367
372
  .btn-evRVlh:focus-visible {
368
- outline: 2px solid var(--c15t-primary, #335cff);
369
- outline-offset: 1px;
373
+ box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000000d), 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
374
+ outline: none;
375
+ }
376
+
377
+ .btn-evRVlh:active {
378
+ box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000000d);
379
+ transform: scale(.98);
370
380
  }
371
381
 
372
382
  .btn-evRVlh:disabled {
373
383
  opacity: .5;
374
384
  cursor: not-allowed;
385
+ box-shadow: none;
375
386
  }
376
387
 
377
388
  .btnPrimary-dA6nqY {
378
389
  background-color: var(--c15t-primary, #335cff);
379
390
  border-color: var(--c15t-primary, #335cff);
380
391
  color: var(--c15t-text-on-primary, #fff);
392
+ box-shadow: none;
381
393
  }
382
394
 
383
395
  .btnPrimary-dA6nqY:hover {
@@ -389,6 +401,7 @@ var __webpack_modules__ = {
389
401
  background-color: var(--c15t-devtools-badge-error, #ef4343);
390
402
  border-color: var(--c15t-devtools-badge-error, #ef4343);
391
403
  color: var(--c15t-text-on-primary, #fff);
404
+ box-shadow: none;
392
405
  }
393
406
 
394
407
  .btnDanger-eDnqOX:hover {
@@ -397,8 +410,10 @@ var __webpack_modules__ = {
397
410
  }
398
411
 
399
412
  .btnSmall-TjXoqZ {
400
- padding: 2px var(--c15t-space-xs, .25rem);
401
- font-size: 10px;
413
+ min-height: 1.75rem;
414
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
415
+ border-radius: var(--c15t-radius-sm, .375rem);
416
+ padding: .25rem .5rem;
402
417
  }
403
418
 
404
419
  .btnIcon-fiYQAh {
@@ -408,19 +423,22 @@ var __webpack_modules__ = {
408
423
  }
409
424
 
410
425
  .input-IeTcCs {
411
- width: 100%;
412
- padding: var(--c15t-space-xs, .25rem) var(--c15t-space-sm, .5rem);
413
- border: 1px solid var(--c15t-border, #e3e3e3);
426
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
414
427
  border-radius: var(--c15t-radius-md, .5rem);
415
- background-color: var(--c15t-surface, #fff);
428
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
429
+ width: 100%;
430
+ min-height: 2rem;
416
431
  color: var(--c15t-text, #171717);
417
- font-family: inherit;
418
- font-size: var(--c15t-font-size-sm, .875rem);
419
- transition: border-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
432
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
433
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
434
+ line-height: var(--c15t-line-height-tight, 1.25);
435
+ 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));
436
+ padding: .375rem .625rem;
420
437
  }
421
438
 
422
439
  .input-IeTcCs:focus {
423
- border-color: var(--c15t-primary, #335cff);
440
+ border-color: var(--c15t-devtools-focus-ring, #335cff);
441
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--c15t-devtools-focus-ring, #335cff) 25%, transparent);
424
442
  outline: none;
425
443
  }
426
444
 
@@ -429,30 +447,35 @@ var __webpack_modules__ = {
429
447
  }
430
448
 
431
449
  .inputSmall-pJyXcL {
432
- padding: 2px var(--c15t-space-xs, .25rem);
450
+ min-height: 1.625rem;
433
451
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
452
+ padding: .25rem .4375rem;
434
453
  }
435
454
 
436
455
  .select-byJ1WM {
437
- width: 100%;
438
- padding: var(--c15t-space-xs, .25rem) var(--c15t-space-sm, .5rem);
439
- border: 1px solid var(--c15t-border, #e3e3e3);
456
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
440
457
  border-radius: var(--c15t-radius-md, .5rem);
441
- background-color: var(--c15t-surface, #fff);
458
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
459
+ width: 100%;
460
+ min-height: 2rem;
442
461
  color: var(--c15t-text, #171717);
443
- font-family: inherit;
462
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
444
463
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
464
+ line-height: var(--c15t-line-height-tight, 1.25);
445
465
  cursor: pointer;
466
+ 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));
467
+ padding: .375rem .625rem;
446
468
  }
447
469
 
448
470
  .select-byJ1WM:focus {
449
- border-color: var(--c15t-primary, #335cff);
471
+ border-color: var(--c15t-devtools-focus-ring, #335cff);
472
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--c15t-devtools-focus-ring, #335cff) 25%, transparent);
450
473
  outline: none;
451
474
  }
452
475
 
453
476
  .grid-LlrmEz {
454
477
  gap: var(--c15t-space-sm, .5rem);
455
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, 1rem);
478
+ padding: var(--c15t-space-md, 1rem);
456
479
  display: grid;
457
480
  }
458
481
 
@@ -465,42 +488,51 @@ var __webpack_modules__ = {
465
488
  }
466
489
 
467
490
  .gridCard-Qm5xxI {
468
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, .75rem);
469
- border: 1px solid var(--c15t-border, #e3e3e3);
470
- border-radius: var(--c15t-radius-md, .5rem);
471
- background-color: var(--c15t-surface, #fff);
472
- transition: border-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
473
491
  justify-content: space-between;
474
492
  align-items: center;
493
+ gap: var(--c15t-space-sm, .5rem);
494
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
495
+ border-radius: var(--c15t-radius-md, .5rem);
496
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
497
+ min-height: 2.75rem;
498
+ box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000000d);
499
+ 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));
500
+ padding: .5625rem .75rem;
475
501
  display: flex;
476
502
  }
477
503
 
478
504
  .gridCard-Qm5xxI:hover {
479
505
  border-color: var(--c15t-border-hover, #c9c9c9);
506
+ background-color: var(--c15t-devtools-surface-subtle, #fafafa);
480
507
  }
481
508
 
482
509
  .gridCardTitle-HjXETp {
483
510
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
484
511
  font-weight: var(--c15t-font-weight-medium, 500);
485
512
  color: var(--c15t-text, #171717);
513
+ line-height: var(--c15t-line-height-tight, 1.25);
486
514
  }
487
515
 
488
516
  .listItem-XUKGIo {
489
- padding: var(--c15t-space-xs, .25rem) var(--c15t-space-md, 1rem);
490
- border-bottom: 1px solid var(--c15t-border, #e3e3e3);
491
517
  justify-content: space-between;
492
518
  align-items: center;
519
+ gap: var(--c15t-space-sm, .5rem);
520
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
521
+ border-radius: var(--c15t-radius-md, .5rem);
522
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
523
+ margin-bottom: .375rem;
524
+ padding: .625rem .75rem;
493
525
  display: flex;
494
526
  }
495
527
 
496
528
  .listItem-XUKGIo:last-child {
497
- border-bottom: none;
529
+ margin-bottom: 0;
498
530
  }
499
531
 
500
532
  .listItemContent-WDBF1N {
501
533
  flex-direction: column;
502
534
  flex: 1;
503
- gap: 2px;
535
+ gap: .1875rem;
504
536
  min-width: 0;
505
537
  display: flex;
506
538
  }
@@ -514,6 +546,7 @@ var __webpack_modules__ = {
514
546
  .listItemDescription-E6JHyZ {
515
547
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
516
548
  color: var(--c15t-text-muted, #737373);
549
+ line-height: var(--c15t-line-height-tight, 1.25);
517
550
  text-overflow: ellipsis;
518
551
  white-space: nowrap;
519
552
  overflow: hidden;
@@ -527,8 +560,8 @@ var __webpack_modules__ = {
527
560
  }
528
561
 
529
562
  .section-a197cB {
530
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, 1rem);
531
- border-bottom: 1px solid var(--c15t-border, #e3e3e3);
563
+ border-bottom: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
564
+ padding: .75rem 1rem;
532
565
  }
533
566
 
534
567
  .section-a197cB:last-child {
@@ -536,9 +569,10 @@ var __webpack_modules__ = {
536
569
  }
537
570
 
538
571
  .sectionHeader-Xcljcw {
539
- margin-bottom: var(--c15t-space-sm, .5rem);
540
572
  justify-content: space-between;
541
573
  align-items: center;
574
+ gap: .5rem;
575
+ margin-bottom: .625rem;
542
576
  display: flex;
543
577
  }
544
578
 
@@ -547,13 +581,60 @@ var __webpack_modules__ = {
547
581
  font-weight: var(--c15t-font-weight-semibold, 600);
548
582
  color: var(--c15t-text-muted, #737373);
549
583
  text-transform: uppercase;
550
- letter-spacing: .5px;
584
+ letter-spacing: .04em;
585
+ }
586
+
587
+ .overrideField-keNdpJ {
588
+ flex-direction: column;
589
+ gap: .3125rem;
590
+ margin-bottom: 0;
591
+ display: flex;
592
+ }
593
+
594
+ .overrideLabel-ApMoTw {
595
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
596
+ font-weight: var(--c15t-font-weight-semibold, 600);
597
+ color: var(--c15t-text-muted, #737373);
598
+ line-height: var(--c15t-line-height-tight, 1.25);
599
+ }
600
+
601
+ .overrideHint-yCfwGt {
602
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
603
+ color: var(--c15t-text-muted, #737373);
604
+ line-height: var(--c15t-line-height-tight, 1.25);
605
+ margin-top: .5rem;
606
+ }
607
+
608
+ .overrideActions-imdcn7 {
609
+ border-top: 1px dashed var(--c15t-devtools-border-strong, #e3e3e3);
610
+ justify-content: space-between;
611
+ align-items: center;
612
+ gap: .5rem;
613
+ margin-top: .625rem;
614
+ padding-top: .625rem;
615
+ display: flex;
616
+ }
617
+
618
+ .overrideActionButtons-gYOx1e {
619
+ flex-wrap: wrap;
620
+ gap: .375rem;
621
+ display: flex;
622
+ }
623
+
624
+ .overrideStatus-sty_qS {
625
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
626
+ color: var(--c15t-text-muted, #737373);
627
+ }
628
+
629
+ .overrideStatusDirty-OUdDMw {
630
+ color: var(--c15t-devtools-badge-warning, #f59f0a);
551
631
  }
552
632
 
553
633
  .infoRow-RlB_0h {
554
- padding: var(--c15t-space-xs, .25rem) 0;
555
634
  justify-content: space-between;
556
635
  align-items: center;
636
+ gap: .5rem;
637
+ padding: .25rem 0;
557
638
  display: flex;
558
639
  }
559
640
 
@@ -566,6 +647,7 @@ var __webpack_modules__ = {
566
647
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
567
648
  font-weight: var(--c15t-font-weight-medium, 500);
568
649
  color: var(--c15t-text, #171717);
650
+ font-variant-numeric: tabular-nums;
569
651
  font-family: ui-monospace, Cascadia Code, Source Code Pro, Menlo, Consolas, DejaVu Sans Mono, monospace;
570
652
  }
571
653
 
@@ -576,18 +658,27 @@ var __webpack_modules__ = {
576
658
  flex-direction: column;
577
659
  justify-content: center;
578
660
  align-items: center;
661
+ gap: .375rem;
579
662
  display: flex;
580
663
  }
581
664
 
582
665
  .emptyStateIcon-WHFkX8 {
666
+ opacity: .55;
583
667
  width: 32px;
584
668
  height: 32px;
585
- margin-bottom: var(--c15t-space-sm, .5rem);
586
- opacity: .5;
587
669
  }
588
670
 
589
671
  .emptyStateText-TaLvAJ {
590
672
  font-size: var(--c15t-font-size-sm, .875rem);
673
+ line-height: var(--c15t-line-height-normal, 1.5);
674
+ }
675
+
676
+ .disconnectedState-dOtZBG {
677
+ padding: var(--c15t-space-xl, 2rem);
678
+ text-align: center;
679
+ font-size: var(--c15t-font-size-sm, .875rem);
680
+ color: var(--c15t-text-muted, #737373);
681
+ line-height: var(--c15t-line-height-normal, 1.5);
591
682
  }
592
683
 
593
684
  @media (prefers-reduced-motion: reduce) {
@@ -642,12 +733,20 @@ var __webpack_modules__ = {
642
733
  section: "section-a197cB",
643
734
  sectionHeader: "sectionHeader-Xcljcw",
644
735
  sectionTitle: "sectionTitle-RUiFld",
736
+ overrideField: "overrideField-keNdpJ",
737
+ overrideLabel: "overrideLabel-ApMoTw",
738
+ overrideHint: "overrideHint-yCfwGt",
739
+ overrideActions: "overrideActions-imdcn7",
740
+ overrideActionButtons: "overrideActionButtons-gYOx1e",
741
+ overrideStatus: "overrideStatus-sty_qS",
742
+ overrideStatusDirty: "overrideStatusDirty-OUdDMw",
645
743
  infoRow: "infoRow-RlB_0h",
646
744
  infoLabel: "infoLabel-_pbK33",
647
745
  infoValue: "infoValue-flMl_e",
648
746
  emptyState: "emptyState-QcmzTQ",
649
747
  emptyStateIcon: "emptyStateIcon-WHFkX8",
650
- emptyStateText: "emptyStateText-TaLvAJ"
748
+ emptyStateText: "emptyStateText-TaLvAJ",
749
+ disconnectedState: "disconnectedState-dOtZBG"
651
750
  };
652
751
  const __rspack_default_export = ___CSS_LOADER_EXPORT___;
653
752
  },
@@ -676,9 +775,9 @@ var __webpack_modules__ = {
676
775
  .floatingButton-Gw8MtJ {
677
776
  width: var(--c15t-devtools-button-size, 40px);
678
777
  height: var(--c15t-devtools-button-size, 40px);
679
- border: 1px solid var(--c15t-border, #e3e3e3);
778
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
680
779
  border-radius: var(--c15t-radius-full, 9999px);
681
- background-color: var(--c15t-surface, #fff);
780
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
682
781
  box-shadow: var(--c15t-shadow-lg, 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a);
683
782
  cursor: grab;
684
783
  z-index: var(--c15t-devtools-z-index, 99999);
@@ -706,13 +805,13 @@ var __webpack_modules__ = {
706
805
  }
707
806
 
708
807
  .floatingButton-Gw8MtJ:focus-visible {
709
- outline: 2px solid var(--c15t-primary, #335cff);
710
- outline-offset: 2px;
808
+ box-shadow: var(--c15t-shadow-lg, 0 8px 24px #0000001f), 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
809
+ outline: none;
711
810
  }
712
811
 
713
812
  .floatingButton-Gw8MtJ:active {
714
813
  cursor: grabbing;
715
- transform: scale(1.02);
814
+ transform: scale(.98);
716
815
  }
717
816
 
718
817
  .floatingButtonIcon-cHWefk {
@@ -753,6 +852,7 @@ var __webpack_modules__ = {
753
852
 
754
853
  .backdrop-LhVMB5 {
755
854
  background-color: var(--c15t-overlay, #00000080);
855
+ backdrop-filter: blur(1px);
756
856
  z-index: calc(var(--c15t-devtools-z-index, 99999) + 1);
757
857
  position: fixed;
758
858
  inset: 0;
@@ -761,10 +861,10 @@ var __webpack_modules__ = {
761
861
  .panel-jtWove {
762
862
  width: var(--c15t-devtools-panel-width, 480px);
763
863
  max-height: var(--c15t-devtools-panel-max-height, 560px);
764
- background-color: var(--c15t-surface, #fff);
765
- border: 1px solid var(--c15t-border, #e3e3e3);
864
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
865
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
766
866
  border-radius: var(--c15t-radius-lg, .75rem);
767
- box-shadow: var(--c15t-shadow-lg, 0 8px 24px #0000001f);
867
+ box-shadow: var(--c15t-shadow-lg, 0 10px 28px #00000029);
768
868
  z-index: calc(var(--c15t-devtools-z-index, 99999) + 2);
769
869
  flex-direction: column;
770
870
  display: flex;
@@ -797,11 +897,11 @@ var __webpack_modules__ = {
797
897
  }
798
898
 
799
899
  .header-xluoTr {
800
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, 1rem);
801
- border-bottom: 1px solid var(--c15t-border, #e3e3e3);
900
+ border-bottom: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
802
901
  background-color: var(--c15t-devtools-surface-muted, #f5f5f5);
803
902
  justify-content: space-between;
804
903
  align-items: center;
904
+ padding: .6875rem .875rem;
805
905
  display: flex;
806
906
  }
807
907
 
@@ -810,6 +910,7 @@ var __webpack_modules__ = {
810
910
  gap: var(--c15t-space-sm, .5rem);
811
911
  font-size: var(--c15t-font-size-sm, .875rem);
812
912
  font-weight: var(--c15t-font-weight-semibold, 600);
913
+ line-height: var(--c15t-line-height-tight, 1.25);
813
914
  color: var(--c15t-text, #171717);
814
915
  display: flex;
815
916
  }
@@ -821,9 +922,9 @@ var __webpack_modules__ = {
821
922
  }
822
923
 
823
924
  .closeButton-Yto0Nb {
824
- border-radius: var(--c15t-radius-sm, .25rem);
825
- width: 28px;
826
- height: 28px;
925
+ border-radius: var(--c15t-radius-md, .5rem);
926
+ width: 2rem;
927
+ height: 2rem;
827
928
  color: var(--c15t-text-muted, #737373);
828
929
  cursor: pointer;
829
930
  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));
@@ -836,13 +937,13 @@ var __webpack_modules__ = {
836
937
  }
837
938
 
838
939
  .closeButton-Yto0Nb:hover {
839
- background-color: var(--c15t-surface-hover, #f7f7f7);
940
+ background-color: var(--c15t-devtools-surface-subtle, #f7f7f7);
840
941
  color: var(--c15t-text, #171717);
841
942
  }
842
943
 
843
944
  .closeButton-Yto0Nb:focus-visible {
844
- outline: 2px solid var(--c15t-primary, #335cff);
845
- outline-offset: 1px;
945
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
946
+ outline: none;
846
947
  }
847
948
 
848
949
  .closeButtonIcon-fVlR1I {
@@ -850,33 +951,71 @@ var __webpack_modules__ = {
850
951
  height: 16px;
851
952
  }
852
953
 
954
+ .inlineActionButton-Ky8BmN {
955
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
956
+ border-radius: var(--c15t-radius-sm, .375rem);
957
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
958
+ min-height: 1.625rem;
959
+ color: var(--c15t-text, #171717);
960
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
961
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
962
+ font-weight: var(--c15t-font-weight-medium, 500);
963
+ line-height: var(--c15t-line-height-tight, 1.25);
964
+ cursor: pointer;
965
+ 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));
966
+ justify-content: center;
967
+ align-items: center;
968
+ padding: .25rem .5rem;
969
+ display: inline-flex;
970
+ }
971
+
972
+ .inlineActionButton-Ky8BmN:hover {
973
+ background-color: var(--c15t-devtools-surface-subtle, #f7f7f7);
974
+ border-color: var(--c15t-border-hover, #c9c9c9);
975
+ }
976
+
977
+ .inlineActionButton-Ky8BmN:focus-visible {
978
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
979
+ outline: none;
980
+ }
981
+
853
982
  .content-yDMYfG {
983
+ scrollbar-gutter: stable;
854
984
  overscroll-behavior: contain;
855
985
  -webkit-overflow-scrolling: touch;
986
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
856
987
  flex: auto;
857
988
  min-height: 200px;
858
- overflow: hidden auto;
989
+ overflow: hidden scroll;
859
990
  }
860
991
 
861
992
  .footer-ESbmwQ {
862
- padding: var(--c15t-space-xs, .25rem) var(--c15t-space-md, 1rem);
863
- border-top: 1px solid var(--c15t-border, #e3e3e3);
993
+ border-top: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
864
994
  background-color: var(--c15t-devtools-surface-muted, #f5f5f5);
865
995
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
866
996
  color: var(--c15t-text-muted, #737373);
867
997
  justify-content: space-between;
868
998
  align-items: center;
999
+ gap: .5rem;
1000
+ padding: .5rem .75rem;
869
1001
  display: flex;
870
1002
  }
871
1003
 
872
1004
  .footerStatus-rlb99A {
873
1005
  align-items: center;
874
- gap: var(--c15t-space-xs, .25rem);
1006
+ gap: .375rem;
1007
+ min-width: 0;
875
1008
  display: flex;
876
1009
  }
877
1010
 
1011
+ .footerMeta-Vdtxdk {
1012
+ opacity: .75;
1013
+ white-space: nowrap;
1014
+ }
1015
+
878
1016
  .statusDot-hYJoej {
879
1017
  border-radius: var(--c15t-radius-full, 9999px);
1018
+ flex-shrink: 0;
880
1019
  width: 6px;
881
1020
  height: 6px;
882
1021
  }
@@ -915,6 +1054,7 @@ var __webpack_modules__ = {
915
1054
  font-size: var(--c15t-font-size-sm, .875rem);
916
1055
  color: var(--c15t-text-muted, #737373);
917
1056
  max-width: 280px;
1057
+ line-height: var(--c15t-line-height-normal, 1.5);
918
1058
  }
919
1059
 
920
1060
  @media (prefers-reduced-motion: reduce) {
@@ -931,17 +1071,17 @@ var __webpack_modules__ = {
931
1071
  }
932
1072
 
933
1073
  .dropdownMenu-aKK18l {
934
- min-width: 200px;
935
- padding: var(--c15t-space-xs, .25rem);
936
- border: 1px solid var(--c15t-border, #e3e3e3);
1074
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
937
1075
  border-radius: var(--c15t-radius-lg, .75rem);
938
- background-color: var(--c15t-surface, #fff);
1076
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
1077
+ min-width: 200px;
939
1078
  box-shadow: var(--c15t-shadow-lg, 0 8px 24px #0000001f);
940
1079
  z-index: calc(var(--c15t-devtools-z-index, 99999) + 1);
941
1080
  opacity: 0;
942
1081
  transform-origin: 0 100%;
943
1082
  pointer-events: none;
944
1083
  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));
1084
+ padding: .375rem;
945
1085
  position: fixed;
946
1086
  transform: scale(.95)translateY(8px);
947
1087
  }
@@ -969,34 +1109,35 @@ var __webpack_modules__ = {
969
1109
  }
970
1110
 
971
1111
  .menuItem-kBbHRP {
972
- align-items: center;
973
- gap: var(--c15t-space-sm, .5rem);
974
- width: 100%;
975
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, .75rem);
976
1112
  border-radius: var(--c15t-radius-md, .5rem);
1113
+ width: 100%;
977
1114
  color: var(--c15t-text, #171717);
978
- font-size: var(--c15t-font-size-sm, .875rem);
1115
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
979
1116
  font-weight: var(--c15t-font-weight-medium, 500);
1117
+ line-height: var(--c15t-line-height-tight, 1.25);
980
1118
  text-align: left;
981
1119
  cursor: pointer;
982
1120
  transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
983
1121
  background: none;
984
1122
  border: none;
1123
+ align-items: center;
1124
+ gap: .625rem;
1125
+ padding: .5rem .625rem;
985
1126
  display: flex;
986
1127
  }
987
1128
 
988
1129
  .menuItem-kBbHRP:hover {
989
- background-color: var(--c15t-surface-hover, #f2f2f2);
1130
+ background-color: var(--c15t-devtools-surface-subtle, #f2f2f2);
990
1131
  }
991
1132
 
992
1133
  .menuItem-kBbHRP:focus-visible {
993
- outline: 2px solid var(--c15t-primary, #335cff);
994
- outline-offset: -2px;
1134
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
1135
+ outline: none;
995
1136
  }
996
1137
 
997
1138
  .menuItemIcon-P3pP5K {
998
- width: 20px;
999
- height: 20px;
1139
+ width: 1rem;
1140
+ height: 1rem;
1000
1141
  color: var(--c15t-text-muted, #737373);
1001
1142
  flex-shrink: 0;
1002
1143
  }
@@ -1009,6 +1150,7 @@ var __webpack_modules__ = {
1009
1150
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
1010
1151
  color: var(--c15t-text-muted, #737373);
1011
1152
  font-weight: var(--c15t-font-weight-normal, 400);
1153
+ margin-top: .125rem;
1012
1154
  }
1013
1155
 
1014
1156
  .menuItemContent-hBlruV {
@@ -1024,8 +1166,8 @@ var __webpack_modules__ = {
1024
1166
  .menuItemToggleTrack-gDp_f3 {
1025
1167
  background-color: var(--c15t-switch-track, #d9d9d9);
1026
1168
  border-radius: var(--c15t-radius-full, 9999px);
1027
- width: 36px;
1028
- height: 20px;
1169
+ width: 2rem;
1170
+ height: 1.25rem;
1029
1171
  transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
1030
1172
  position: relative;
1031
1173
  }
@@ -1033,21 +1175,22 @@ var __webpack_modules__ = {
1033
1175
  .menuItemToggleThumb-ioqqyc {
1034
1176
  background-color: var(--c15t-switch-thumb, #fff);
1035
1177
  border-radius: var(--c15t-radius-full, 9999px);
1036
- width: 16px;
1037
- height: 16px;
1038
- box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000001a);
1178
+ width: .75rem;
1179
+ height: .75rem;
1180
+ box-shadow: 0 0 0 1px var(--c15t-border, #e3e3e3);
1039
1181
  transition: transform var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
1040
1182
  position: absolute;
1041
- top: 2px;
1183
+ top: 50%;
1042
1184
  left: 2px;
1185
+ transform: translateY(-50%);
1043
1186
  }
1044
1187
 
1045
1188
  .menuItemToggleChecked-K3BPtk .menuItemToggleTrack-gDp_f3 {
1046
- background-color: var(--c15t-switch-track-checked, #335cff);
1189
+ background-color: var(--c15t-switch-track-active, #335cff);
1047
1190
  }
1048
1191
 
1049
1192
  .menuItemToggleChecked-K3BPtk .menuItemToggleThumb-ioqqyc {
1050
- transform: translateX(16px);
1193
+ transform: translate(1rem, -50%);
1051
1194
  }
1052
1195
 
1053
1196
  .menuDivider-JIBdhU {
@@ -1083,9 +1226,11 @@ var __webpack_modules__ = {
1083
1226
  headerLogo: "headerLogo-PxJ_w1",
1084
1227
  closeButton: "closeButton-Yto0Nb",
1085
1228
  closeButtonIcon: "closeButtonIcon-fVlR1I",
1229
+ inlineActionButton: "inlineActionButton-Ky8BmN",
1086
1230
  content: "content-yDMYfG",
1087
1231
  footer: "footer-ESbmwQ",
1088
1232
  footerStatus: "footerStatus-rlb99A",
1233
+ footerMeta: "footerMeta-Vdtxdk",
1089
1234
  statusDot: "statusDot-hYJoej",
1090
1235
  statusConnected: "statusConnected-hPSUgS",
1091
1236
  statusDisconnected: "statusDisconnected-HIpcee",
@@ -1124,55 +1269,63 @@ var __webpack_modules__ = {
1124
1269
  ___CSS_LOADER_EXPORT___.push([
1125
1270
  module.id,
1126
1271
  `.tabList-IyuiBE {
1127
- gap: var(--c15t-space-xs, .25rem);
1128
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, 1rem);
1129
- border-bottom: 1px solid var(--c15t-border, #e3e3e3);
1130
- background-color: var(--c15t-surface, #fff);
1131
- scrollbar-width: none;
1132
- -ms-overflow-style: none;
1272
+ border-bottom: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
1273
+ background-color: var(--c15t-devtools-surface-subtle, #fafafa);
1274
+ align-items: center;
1275
+ gap: .375rem;
1276
+ padding: .75rem;
1133
1277
  display: flex;
1134
- overflow-x: auto;
1135
1278
  }
1136
1279
 
1137
- .tabList-IyuiBE::-webkit-scrollbar {
1138
- display: none;
1280
+ .tabStrip-_KrWe4 {
1281
+ align-items: center;
1282
+ gap: var(--c15t-space-xs, .25rem);
1283
+ flex: auto;
1284
+ min-width: 0;
1285
+ display: flex;
1286
+ overflow: hidden;
1139
1287
  }
1140
1288
 
1141
1289
  .tab-yfDEqg {
1142
- align-items: center;
1143
- gap: var(--c15t-space-xs, .25rem);
1144
- padding: var(--c15t-space-xs, .25rem) var(--c15t-space-sm, .5rem);
1145
1290
  border-radius: var(--c15t-radius-md, .5rem);
1291
+ min-height: 1.875rem;
1146
1292
  color: var(--c15t-text-muted, #737373);
1147
- font-family: inherit;
1293
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
1148
1294
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
1149
1295
  font-weight: var(--c15t-font-weight-medium, 500);
1296
+ line-height: var(--c15t-line-height-tight, 1.25);
1150
1297
  cursor: pointer;
1151
1298
  white-space: nowrap;
1152
- 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));
1299
+ 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));
1153
1300
  background-color: #0000;
1154
- border: none;
1301
+ border: 1px solid #0000;
1302
+ flex-shrink: 0;
1303
+ align-items: center;
1304
+ gap: .375rem;
1305
+ padding: .25rem .625rem;
1155
1306
  display: flex;
1156
1307
  }
1157
1308
 
1158
1309
  .tab-yfDEqg:hover {
1159
- background-color: var(--c15t-surface-hover, #f7f7f7);
1310
+ background-color: var(--c15t-devtools-surface-muted, #f7f7f7);
1160
1311
  color: var(--c15t-text, #171717);
1161
1312
  }
1162
1313
 
1163
1314
  .tab-yfDEqg:focus-visible {
1164
- outline: 2px solid var(--c15t-primary, #335cff);
1165
- outline-offset: 1px;
1315
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
1316
+ outline: none;
1166
1317
  }
1167
1318
 
1168
1319
  .tabActive-r4hing {
1169
- background-color: var(--c15t-primary, #335cff);
1170
- color: var(--c15t-text-on-primary, #fff);
1320
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
1321
+ border-color: var(--c15t-devtools-border-strong, #e3e3e3);
1322
+ color: var(--c15t-text, #171717);
1323
+ box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000000d);
1171
1324
  }
1172
1325
 
1173
1326
  .tabActive-r4hing:hover {
1174
- background-color: var(--c15t-primary-hover, #03f);
1175
- color: var(--c15t-text-on-primary, #fff);
1327
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
1328
+ color: var(--c15t-text, #171717);
1176
1329
  }
1177
1330
 
1178
1331
  .tabIcon-U9tnu0 {
@@ -1181,6 +1334,131 @@ var __webpack_modules__ = {
1181
1334
  height: 14px;
1182
1335
  }
1183
1336
 
1337
+ .tabHidden-HBXYSd {
1338
+ display: none;
1339
+ }
1340
+
1341
+ .overflowContainer-TTw9DO {
1342
+ flex-shrink: 0;
1343
+ position: relative;
1344
+ }
1345
+
1346
+ .overflowContainerHidden-sQa_XZ {
1347
+ display: none;
1348
+ }
1349
+
1350
+ .overflowButton-tKq4FF {
1351
+ border-radius: var(--c15t-radius-md, .5rem);
1352
+ width: 1.875rem;
1353
+ height: 1.875rem;
1354
+ color: var(--c15t-text-muted, #737373);
1355
+ cursor: pointer;
1356
+ 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));
1357
+ background-color: #0000;
1358
+ border: 1px solid #0000;
1359
+ justify-content: center;
1360
+ align-items: center;
1361
+ padding: 0;
1362
+ display: inline-flex;
1363
+ }
1364
+
1365
+ .overflowButton-tKq4FF:hover {
1366
+ background-color: var(--c15t-devtools-surface-muted, #f7f7f7);
1367
+ color: var(--c15t-text, #171717);
1368
+ }
1369
+
1370
+ .overflowButton-tKq4FF:focus-visible {
1371
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
1372
+ outline: none;
1373
+ }
1374
+
1375
+ .overflowButtonIcon-FSurfC {
1376
+ justify-content: center;
1377
+ align-items: center;
1378
+ width: 14px;
1379
+ height: 14px;
1380
+ display: inline-flex;
1381
+ }
1382
+
1383
+ .overflowMenu-TST0eZ {
1384
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
1385
+ border-radius: var(--c15t-radius-md, .5rem);
1386
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
1387
+ min-width: 10rem;
1388
+ box-shadow: var(--c15t-shadow-md, 0 4px 12px #00000014);
1389
+ opacity: 0;
1390
+ transform-origin: 100% 0;
1391
+ pointer-events: none;
1392
+ z-index: 10;
1393
+ 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));
1394
+ flex-direction: column;
1395
+ gap: .125rem;
1396
+ padding: .3125rem;
1397
+ display: flex;
1398
+ position: absolute;
1399
+ top: calc(100% + .375rem);
1400
+ right: 0;
1401
+ transform: translateY(-4px)scale(.98);
1402
+ }
1403
+
1404
+ .overflowMenu-TST0eZ[data-state="open"] {
1405
+ opacity: 1;
1406
+ pointer-events: auto;
1407
+ transform: translateY(0)scale(1);
1408
+ }
1409
+
1410
+ .overflowItem-y5Pz7k {
1411
+ border-radius: var(--c15t-radius-sm, .375rem);
1412
+ min-height: 1.75rem;
1413
+ color: var(--c15t-text, #171717);
1414
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
1415
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
1416
+ font-weight: var(--c15t-font-weight-medium, 500);
1417
+ line-height: var(--c15t-line-height-tight, 1.25);
1418
+ text-align: left;
1419
+ cursor: pointer;
1420
+ white-space: nowrap;
1421
+ 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));
1422
+ background-color: #0000;
1423
+ border: none;
1424
+ align-items: center;
1425
+ gap: .5rem;
1426
+ padding: .3125rem .5rem;
1427
+ display: inline-flex;
1428
+ }
1429
+
1430
+ .overflowItem-y5Pz7k:hover {
1431
+ background-color: var(--c15t-devtools-surface-subtle, #fafafa);
1432
+ }
1433
+
1434
+ .overflowItem-y5Pz7k:focus-visible {
1435
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
1436
+ outline: none;
1437
+ }
1438
+
1439
+ .overflowItemActive-mzVG1T {
1440
+ background-color: var(--c15t-devtools-accent-soft, #ebefff);
1441
+ color: var(--c15t-text, #171717);
1442
+ }
1443
+
1444
+ .overflowItemDisabled-dcHX3K {
1445
+ opacity: .5;
1446
+ cursor: not-allowed;
1447
+ }
1448
+
1449
+ .overflowItemIcon-fz291V {
1450
+ flex-shrink: 0;
1451
+ justify-content: center;
1452
+ align-items: center;
1453
+ width: 14px;
1454
+ height: 14px;
1455
+ display: inline-flex;
1456
+ }
1457
+
1458
+ .overflowItemHidden-k4aawi {
1459
+ display: none;
1460
+ }
1461
+
1184
1462
  .tabDisabled-lDuv5l {
1185
1463
  opacity: .5;
1186
1464
  cursor: not-allowed;
@@ -1201,7 +1479,7 @@ var __webpack_modules__ = {
1201
1479
  }
1202
1480
 
1203
1481
  @media (prefers-reduced-motion: reduce) {
1204
- .tab-yfDEqg {
1482
+ .tab-yfDEqg, .overflowButton-tKq4FF, .overflowMenu-TST0eZ, .overflowItem-y5Pz7k {
1205
1483
  transition: none;
1206
1484
  }
1207
1485
  }
@@ -1217,9 +1495,21 @@ var __webpack_modules__ = {
1217
1495
  ]);
1218
1496
  ___CSS_LOADER_EXPORT___.locals = {
1219
1497
  tabList: "tabList-IyuiBE",
1498
+ tabStrip: "tabStrip-_KrWe4",
1220
1499
  tab: "tab-yfDEqg",
1221
1500
  tabActive: "tabActive-r4hing",
1222
1501
  tabIcon: "tabIcon-U9tnu0",
1502
+ tabHidden: "tabHidden-HBXYSd",
1503
+ overflowContainer: "overflowContainer-TTw9DO",
1504
+ overflowContainerHidden: "overflowContainerHidden-sQa_XZ",
1505
+ overflowButton: "overflowButton-tKq4FF",
1506
+ overflowButtonIcon: "overflowButtonIcon-FSurfC",
1507
+ overflowMenu: "overflowMenu-TST0eZ",
1508
+ overflowItem: "overflowItem-y5Pz7k",
1509
+ overflowItemActive: "overflowItemActive-mzVG1T",
1510
+ overflowItemDisabled: "overflowItemDisabled-dcHX3K",
1511
+ overflowItemIcon: "overflowItemIcon-fz291V",
1512
+ overflowItemHidden: "overflowItemHidden-k4aawi",
1223
1513
  tabDisabled: "tabDisabled-lDuv5l",
1224
1514
  tabPanel: "tabPanel-QKO8FX",
1225
1515
  tabPanelActive: "tabPanelActive-mrNlGE"
@@ -1243,6 +1533,15 @@ var __webpack_modules__ = {
1243
1533
  --c15t-devtools-button-size: 40px;
1244
1534
  --c15t-devtools-z-index: 99999;
1245
1535
  --c15t-devtools-surface-muted: var(--c15t-surface-hover, #f7f7f7);
1536
+ --c15t-devtools-surface-subtle: #fafafa;
1537
+ --c15t-devtools-surface-elevated: var(--c15t-surface, #fff);
1538
+ --c15t-devtools-border-strong: var(--c15t-border, #e3e3e3);
1539
+ --c15t-devtools-code-surface: #f7f7f7;
1540
+ --c15t-devtools-accent-soft: #ebefff;
1541
+ --c15t-devtools-focus-ring: var(--c15t-primary, #335cff);
1542
+ --c15t-devtools-text-muted: var(--c15t-text-muted, #737373);
1543
+ --c15t-devtools-font-size-sm: var(--c15t-font-size-sm, .875rem);
1544
+ --c15t-surface-muted: var(--c15t-devtools-surface-muted, #f7f7f7);
1246
1545
  --c15t-devtools-font-size-xs: .75rem;
1247
1546
  --c15t-devtools-badge-success: #21c45d;
1248
1547
  --c15t-devtools-badge-success-bg: #e4fbed;
@@ -1256,8 +1555,37 @@ var __webpack_modules__ = {
1256
1555
  --c15t-devtools-badge-neutral-bg: #f0f0f0;
1257
1556
  }
1258
1557
 
1558
+ :is(:global(.c15t-light), :global(.light)) {
1559
+ --c15t-devtools-surface-muted: var(--c15t-surface-hover, #f7f7f7);
1560
+ --c15t-devtools-surface-subtle: #fafafa;
1561
+ --c15t-devtools-surface-elevated: var(--c15t-surface, #fff);
1562
+ --c15t-devtools-border-strong: var(--c15t-border, #e3e3e3);
1563
+ --c15t-devtools-code-surface: #f7f7f7;
1564
+ --c15t-devtools-accent-soft: #ebefff;
1565
+ --c15t-devtools-badge-success-bg: #e4fbed;
1566
+ --c15t-devtools-badge-error-bg: #fde7e7;
1567
+ --c15t-devtools-badge-warning-bg: #fef7dc;
1568
+ --c15t-devtools-badge-info-bg: #dcebfe;
1569
+ --c15t-devtools-badge-neutral-bg: #f0f0f0;
1570
+ }
1571
+
1572
+ @supports (color: color-mix(in srgb, white, black)) {
1573
+ :root {
1574
+ --c15t-devtools-surface-muted: color-mix(in srgb, var(--c15t-surface-hover, #f7f7f7) 85%, var(--c15t-surface, #fff));
1575
+ --c15t-devtools-surface-subtle: color-mix(in srgb, var(--c15t-surface-hover, #f7f7f7) 55%, var(--c15t-surface, #fff));
1576
+ --c15t-devtools-border-strong: color-mix(in srgb, var(--c15t-border, #e3e3e3) 80%, var(--c15t-text-muted, #737373));
1577
+ --c15t-devtools-code-surface: color-mix(in srgb, var(--c15t-surface-hover, #f7f7f7) 70%, var(--c15t-surface, #fff));
1578
+ --c15t-devtools-accent-soft: color-mix(in srgb, var(--c15t-primary, #335cff) 12%, transparent);
1579
+ }
1580
+ }
1581
+
1259
1582
  :is(:global(.c15t-dark), :global(.dark)) {
1260
1583
  --c15t-devtools-surface-muted: var(--c15t-surface-hover, #292929);
1584
+ --c15t-devtools-surface-subtle: #242424;
1585
+ --c15t-devtools-surface-elevated: var(--c15t-surface, #1a1a1a);
1586
+ --c15t-devtools-border-strong: var(--c15t-border, #3d3d3d);
1587
+ --c15t-devtools-code-surface: #212121;
1588
+ --c15t-devtools-accent-soft: #335cff33;
1261
1589
  --c15t-devtools-badge-success-bg: #21c45d33;
1262
1590
  --c15t-devtools-badge-error-bg: #ef434333;
1263
1591
  --c15t-devtools-badge-warning-bg: #f59f0a33;
@@ -1266,8 +1594,13 @@ var __webpack_modules__ = {
1266
1594
  }
1267
1595
 
1268
1596
  @media (prefers-color-scheme: dark) {
1269
- :root {
1597
+ :global(:root:not(.light):not(.c15t-light)) {
1270
1598
  --c15t-devtools-surface-muted: var(--c15t-surface-hover, #292929);
1599
+ --c15t-devtools-surface-subtle: #242424;
1600
+ --c15t-devtools-surface-elevated: var(--c15t-surface, #1a1a1a);
1601
+ --c15t-devtools-border-strong: var(--c15t-border, #3d3d3d);
1602
+ --c15t-devtools-code-surface: #212121;
1603
+ --c15t-devtools-accent-soft: #335cff33;
1271
1604
  --c15t-devtools-badge-success-bg: #21c45d33;
1272
1605
  --c15t-devtools-badge-error-bg: #ef434333;
1273
1606
  --c15t-devtools-badge-warning-bg: #f59f0a33;
@@ -1793,7 +2126,7 @@ var __webpack_exports__ = {};
1793
2126
  type: options.type ?? 'button'
1794
2127
  });
1795
2128
  }
1796
- function span(options = {}) {
2129
+ function renderer_span(options = {}) {
1797
2130
  return createElement({
1798
2131
  ...options,
1799
2132
  tag: 'span'
@@ -1872,7 +2205,8 @@ var __webpack_exports__ = {};
1872
2205
  panel_module_options.insertStyleElement = insertStyleElement_default();
1873
2206
  injectStylesIntoStyleTag_default()(panel_module.A, panel_module_options);
1874
2207
  const styles_panel_module = panel_module.A && panel_module.A.locals ? panel_module.A.locals : void 0;
1875
- const PREFERENCE_TRIGGER_SELECTORS = '[data-c15t-trigger], [aria-label*="privacy settings"], [aria-label*="preference"]';
2208
+ const PREFERENCE_TRIGGER_SELECTORS = '[data-c15t-trigger], [aria-label*="privacy settings" i], [aria-label*="preference" i]';
2209
+ const PREVIOUS_DISPLAY_ATTR = 'data-c15t-devtools-prev-display';
1876
2210
  function detectPreferenceTrigger() {
1877
2211
  const triggers = document.querySelectorAll(PREFERENCE_TRIGGER_SELECTORS);
1878
2212
  return triggers.length > 0;
@@ -1882,11 +2216,23 @@ var __webpack_exports__ = {};
1882
2216
  }
1883
2217
  function setPreferenceTriggerVisibility(visible) {
1884
2218
  const elements = getPreferenceTriggerElements();
1885
- for (const el of elements)el.style.display = visible ? '' : 'none';
2219
+ for (const el of elements){
2220
+ if (visible) {
2221
+ const previousDisplay = el.getAttribute(PREVIOUS_DISPLAY_ATTR);
2222
+ if (null === previousDisplay) el.style.removeProperty('display');
2223
+ else {
2224
+ el.style.display = previousDisplay;
2225
+ el.removeAttribute(PREVIOUS_DISPLAY_ATTR);
2226
+ }
2227
+ continue;
2228
+ }
2229
+ if (!el.hasAttribute(PREVIOUS_DISPLAY_ATTR)) el.setAttribute(PREVIOUS_DISPLAY_ATTR, el.style.display);
2230
+ el.style.display = 'none';
2231
+ }
1886
2232
  }
1887
- function getPreferenceCenterOpener() {
2233
+ function getPreferenceCenterOpener(namespace = 'c15tStore') {
1888
2234
  const win = window;
1889
- const store = win.c15tStore;
2235
+ const store = win[namespace];
1890
2236
  if (store && 'function' == typeof store.getState) {
1891
2237
  const state = store.getState();
1892
2238
  if ('function' == typeof state.setActiveUI) return ()=>{
@@ -1895,6 +2241,7 @@ var __webpack_exports__ = {};
1895
2241
  }
1896
2242
  return null;
1897
2243
  }
2244
+ const version = '2.0.0-rc.4';
1898
2245
  const DEVTOOLS_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 446 445" aria-label="c15t">
1899
2246
  <path fill="currentColor" d="M223.178.313c39.064 0 70.732 31.668 70.732 70.732-.001 39.064-31.668 70.731-70.732 70.731-12.181 0-23.642-3.079-33.649-8.502l-55.689 55.689a70.267 70.267 0 0 1 5.574 13.441h167.531c8.695-29.217 35.762-50.523 67.804-50.523 39.064 0 70.731 31.668 70.731 70.732s-31.668 70.732-70.731 70.732c-32.042 0-59.108-21.306-67.803-50.523H139.413a70.417 70.417 0 0 1-7.888 17.396l54.046 54.046c10.893-6.851 23.786-10.815 37.605-10.815 39.064 0 70.732 31.669 70.732 70.733 0 39.064-31.668 70.731-70.732 70.731s-70.732-31.667-70.732-70.731c0-10.518 2.296-20.499 6.414-29.471l-57.78-57.78c-8.972 4.117-18.952 6.414-29.47 6.414-39.063 0-70.731-31.668-70.732-70.732 0-39.064 31.669-70.732 70.733-70.732 12.18 0 23.642 3.079 33.649 8.502l55.688-55.688c-5.423-10.007-8.502-21.469-8.502-33.65 0-39.064 31.668-70.733 70.732-70.733Zm0 343.555c-16.742 0-30.314 13.572-30.314 30.314 0 16.741 13.572 30.313 30.314 30.313s30.314-13.572 30.314-30.313c0-16.742-13.572-30.314-30.314-30.314ZM71.611 192.299c-16.742 0-30.315 13.572-30.315 30.314s13.573 30.314 30.315 30.314c16.741 0 30.313-13.572 30.313-30.314 0-16.741-13.572-30.314-30.313-30.314Zm303.138 0c-16.729 0-30.294 13.551-30.315 30.275l.001.039-.001.038c.021 16.725 13.586 30.276 30.315 30.276 16.741 0 30.313-13.572 30.313-30.314 0-16.741-13.572-30.314-30.313-30.314ZM223.178 40.73c-16.742 0-30.314 13.573-30.314 30.315s13.573 30.313 30.314 30.313c16.742 0 30.313-13.572 30.314-30.313 0-16.742-13.572-30.314-30.314-30.315Z"/>
1900
2247
  </svg>`;
@@ -1975,7 +2322,7 @@ var __webpack_exports__ = {};
1975
2322
  const labelContainer = renderer_div({
1976
2323
  className: styles_panel_module.menuItemContent ?? ''
1977
2324
  });
1978
- const label = span({
2325
+ const label = renderer_span({
1979
2326
  className: styles_panel_module.menuItemLabel ?? '',
1980
2327
  text: item.label
1981
2328
  });
@@ -2097,8 +2444,13 @@ var __webpack_exports__ = {};
2097
2444
  return styles_panel_module.positionTopLeft ?? '';
2098
2445
  }
2099
2446
  }
2447
+ function formatRetryDelay(delayMs) {
2448
+ if (null === delayMs) return 'n/a';
2449
+ if (delayMs < 1000) return `${delayMs}ms`;
2450
+ return `${(delayMs / 1000).toFixed(1)}s`;
2451
+ }
2100
2452
  function createPanel(options) {
2101
- const { stateManager, storeConnector, onRenderContent, enableUnifiedMode = true } = options;
2453
+ const { stateManager, storeConnector, onRenderContent, namespace = 'c15tStore', enableUnifiedMode = true } = options;
2102
2454
  let removePortal = null;
2103
2455
  let isAnimatingOut = false;
2104
2456
  let draggable = null;
@@ -2127,7 +2479,7 @@ var __webpack_exports__ = {};
2127
2479
  return;
2128
2480
  }
2129
2481
  hasPreferenceTrigger = detectPreferenceTrigger();
2130
- const preferenceCenterOpener = getPreferenceCenterOpener();
2482
+ const preferenceCenterOpener = getPreferenceCenterOpener(namespace);
2131
2483
  useUnifiedMode = hasPreferenceTrigger && null !== preferenceCenterOpener;
2132
2484
  if (useUnifiedMode && !dropdownMenu) {
2133
2485
  dropdownMenu = createDropdownMenu({
@@ -2147,7 +2499,7 @@ var __webpack_exports__ = {};
2147
2499
  description: 'Open privacy settings',
2148
2500
  icon: PREFERENCES_ICON,
2149
2501
  onClick: ()=>{
2150
- const opener = getPreferenceCenterOpener();
2502
+ const opener = getPreferenceCenterOpener(namespace);
2151
2503
  if (opener) opener();
2152
2504
  }
2153
2505
  },
@@ -2203,6 +2555,7 @@ var __webpack_exports__ = {};
2203
2555
  let panelElement = null;
2204
2556
  let backdropElement = null;
2205
2557
  let contentContainer = null;
2558
+ let footerElement = null;
2206
2559
  function createPanelElement() {
2207
2560
  const corner = draggable?.getCorner() ?? stateManager.getState().position;
2208
2561
  const positionClass = getPositionClass(corner);
@@ -2227,7 +2580,7 @@ var __webpack_exports__ = {};
2227
2580
  }));
2228
2581
  return logoWrapper;
2229
2582
  })(),
2230
- span({
2583
+ renderer_span({
2231
2584
  text: 'c15t DevTools'
2232
2585
  })
2233
2586
  ]
@@ -2254,37 +2607,60 @@ var __webpack_exports__ = {};
2254
2607
  contentContainer = renderer_div({
2255
2608
  className: styles_panel_module.content
2256
2609
  });
2257
- const isConnected = storeConnector.isConnected();
2258
- const footer = renderer_div({
2259
- className: styles_panel_module.footer,
2260
- children: [
2261
- renderer_div({
2262
- className: styles_panel_module.footerStatus,
2263
- children: [
2264
- span({
2265
- className: `${styles_panel_module.statusDot} ${isConnected ? styles_panel_module.statusConnected : styles_panel_module.statusDisconnected}`
2266
- }),
2267
- span({
2268
- text: isConnected ? 'Connected' : 'Disconnected'
2269
- })
2270
- ]
2271
- }),
2272
- span({
2273
- text: 'v1.8.3'
2274
- })
2275
- ]
2610
+ footerElement = renderer_div({
2611
+ className: styles_panel_module.footer
2276
2612
  });
2613
+ updateFooter();
2277
2614
  panel.appendChild(header);
2278
2615
  panel.appendChild(contentContainer);
2279
- panel.appendChild(footer);
2280
- if (isConnected) onRenderContent(contentContainer);
2616
+ panel.appendChild(footerElement);
2617
+ if (storeConnector.isConnected()) onRenderContent(contentContainer);
2281
2618
  else renderErrorState(contentContainer);
2282
2619
  return panel;
2283
2620
  }
2284
- function renderErrorState(container) {
2285
- clearElement(container);
2286
- const errorState = renderer_div({
2287
- className: styles_panel_module.errorState,
2621
+ function updateFooter() {
2622
+ if (!footerElement) return;
2623
+ clearElement(footerElement);
2624
+ const isConnected = storeConnector.isConnected();
2625
+ const storeState = storeConnector.getState();
2626
+ const isLoading = storeState?.isLoadingConsentInfo ?? false;
2627
+ const diagnostics = storeConnector.getDiagnostics();
2628
+ const statusChildren = [
2629
+ renderer_span({
2630
+ className: `${styles_panel_module.statusDot} ${isConnected ? styles_panel_module.statusConnected : styles_panel_module.statusDisconnected}`
2631
+ }),
2632
+ renderer_span({
2633
+ text: isConnected ? 'Connected' : 'Disconnected'
2634
+ })
2635
+ ];
2636
+ if (isLoading) statusChildren.push(renderer_span({
2637
+ className: styles_panel_module.footerMeta,
2638
+ text: '\u00b7 Fetching /init\u2026'
2639
+ }));
2640
+ else if (!isConnected) statusChildren.push(renderer_span({
2641
+ className: styles_panel_module.footerMeta,
2642
+ text: `· ${diagnostics.namespace} · retry ${diagnostics.reconnectAttempts} · next ${formatRetryDelay(diagnostics.nextRetryInMs)}`
2643
+ }));
2644
+ footerElement.appendChild(renderer_div({
2645
+ className: styles_panel_module.footerStatus,
2646
+ children: statusChildren
2647
+ }));
2648
+ if (!isConnected) footerElement.appendChild(renderer_button({
2649
+ className: styles_panel_module.inlineActionButton,
2650
+ text: 'Retry',
2651
+ onClick: ()=>{
2652
+ storeConnector.retryConnection();
2653
+ }
2654
+ }));
2655
+ footerElement.appendChild(renderer_span({
2656
+ text: `v${version}`
2657
+ }));
2658
+ }
2659
+ function renderErrorState(container) {
2660
+ clearElement(container);
2661
+ const diagnostics = storeConnector.getDiagnostics();
2662
+ const errorState = renderer_div({
2663
+ className: styles_panel_module.errorState,
2288
2664
  children: [
2289
2665
  (()=>{
2290
2666
  const iconWrap = renderer_div({
@@ -2303,6 +2679,30 @@ var __webpack_exports__ = {};
2303
2679
  renderer_div({
2304
2680
  className: styles_panel_module.errorMessage,
2305
2681
  text: 'c15t consent manager is not initialized. Make sure you have set up the ConsentManagerProvider in your app.'
2682
+ }),
2683
+ renderer_div({
2684
+ className: styles_panel_module.errorMessage,
2685
+ style: {
2686
+ marginTop: '4px',
2687
+ fontSize: 'var(--c15t-devtools-font-size-xs)'
2688
+ },
2689
+ text: `Namespace: ${diagnostics.namespace} · Retries: ${diagnostics.reconnectAttempts} · Next retry: ${formatRetryDelay(diagnostics.nextRetryInMs)}`
2690
+ }),
2691
+ diagnostics.lastError ? renderer_div({
2692
+ className: styles_panel_module.errorMessage,
2693
+ style: {
2694
+ marginTop: '4px',
2695
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
2696
+ color: 'var(--c15t-text-muted)'
2697
+ },
2698
+ text: `Last error: ${diagnostics.lastError}`
2699
+ }) : null,
2700
+ renderer_button({
2701
+ className: styles_panel_module.inlineActionButton,
2702
+ text: 'Retry Connection',
2703
+ onClick: ()=>{
2704
+ storeConnector.retryConnection();
2705
+ }
2306
2706
  })
2307
2707
  ]
2308
2708
  });
@@ -2338,6 +2738,7 @@ var __webpack_exports__ = {};
2338
2738
  panelElement = null;
2339
2739
  }
2340
2740
  contentContainer = null;
2741
+ footerElement = null;
2341
2742
  isAnimatingOut = false;
2342
2743
  floatingButton.style.display = '';
2343
2744
  stateManager.setOpen(false);
@@ -2356,9 +2757,14 @@ var __webpack_exports__ = {};
2356
2757
  update();
2357
2758
  });
2358
2759
  const unsubscribeStore = storeConnector.subscribe(()=>{
2760
+ updateFooter();
2359
2761
  if (contentContainer) if (storeConnector.isConnected()) onRenderContent(contentContainer);
2360
2762
  else renderErrorState(contentContainer);
2361
2763
  });
2764
+ const unsubscribeDiagnostics = storeConnector.subscribeDiagnostics(()=>{
2765
+ updateFooter();
2766
+ if (contentContainer && !storeConnector.isConnected()) renderErrorState(contentContainer);
2767
+ });
2362
2768
  container.appendChild(floatingButton);
2363
2769
  removePortal = createPortal(container);
2364
2770
  return {
@@ -2368,6 +2774,7 @@ var __webpack_exports__ = {};
2368
2774
  destroy: ()=>{
2369
2775
  unsubscribeState();
2370
2776
  unsubscribeStore();
2777
+ unsubscribeDiagnostics();
2371
2778
  if (dropdownMenu) {
2372
2779
  dropdownMenu.destroy();
2373
2780
  dropdownMenu = null;
@@ -2416,6 +2823,11 @@ var __webpack_exports__ = {};
2416
2823
  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">
2417
2824
  <path d="M12 20h9"></path>
2418
2825
  <path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"></path>
2826
+ </svg>`;
2827
+ const MORE_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
2828
+ <circle cx="12" cy="5" r="1.75"></circle>
2829
+ <circle cx="12" cy="12" r="1.75"></circle>
2830
+ <circle cx="12" cy="19" r="1.75"></circle>
2419
2831
  </svg>`;
2420
2832
  const TABS = [
2421
2833
  {
@@ -2452,12 +2864,56 @@ var __webpack_exports__ = {};
2452
2864
  function tabs_createTabs(options) {
2453
2865
  const { onTabChange, disabledTabs = [] } = options;
2454
2866
  let activeTab = options.activeTab;
2867
+ let isOverflowMenuOpen = false;
2868
+ let visibleTabIds = [];
2869
+ let hiddenTabIds = [];
2455
2870
  const tabButtons = new Map();
2871
+ const overflowButtons = new Map();
2456
2872
  const tabList = renderer_div({
2457
- className: styles_tabs_module.tabList,
2873
+ className: styles_tabs_module.tabList
2874
+ });
2875
+ const tabStrip = renderer_div({
2876
+ className: styles_tabs_module.tabStrip,
2458
2877
  role: 'tablist',
2459
2878
  ariaLabel: 'DevTools tabs'
2460
2879
  });
2880
+ tabList.appendChild(tabStrip);
2881
+ const overflowMenu = renderer_div({
2882
+ className: styles_tabs_module.overflowMenu,
2883
+ role: 'menu',
2884
+ ariaLabel: 'All tabs'
2885
+ });
2886
+ overflowMenu.dataset.state = 'closed';
2887
+ const overflowButton = renderer_button({
2888
+ className: styles_tabs_module.overflowButton,
2889
+ ariaLabel: 'More tabs',
2890
+ ariaExpanded: 'false',
2891
+ onClick: ()=>toggleOverflowMenu(),
2892
+ onKeyDown: (e)=>{
2893
+ if ('ArrowDown' === e.key || 'Enter' === e.key || ' ' === e.key) {
2894
+ e.preventDefault();
2895
+ openOverflowMenu();
2896
+ focusFirstEnabledOverflowItem();
2897
+ }
2898
+ }
2899
+ });
2900
+ overflowButton.setAttribute('aria-haspopup', 'menu');
2901
+ const overflowIcon = renderer_div({
2902
+ className: styles_tabs_module.overflowButtonIcon
2903
+ });
2904
+ overflowIcon.appendChild(createSvgElement(MORE_ICON, {
2905
+ width: 14,
2906
+ height: 14
2907
+ }));
2908
+ overflowButton.appendChild(overflowIcon);
2909
+ const overflowContainer = renderer_div({
2910
+ className: styles_tabs_module.overflowContainer,
2911
+ children: [
2912
+ overflowButton,
2913
+ overflowMenu
2914
+ ]
2915
+ });
2916
+ tabList.appendChild(overflowContainer);
2461
2917
  for (const tab of TABS){
2462
2918
  const isActive = tab.id === activeTab;
2463
2919
  const isDisabled = disabledTabs.includes(tab.id);
@@ -2471,6 +2927,7 @@ var __webpack_exports__ = {};
2471
2927
  disabled: isDisabled,
2472
2928
  onClick: ()=>{
2473
2929
  if (!isDisabled) {
2930
+ closeOverflowMenu();
2474
2931
  setActiveTab(tab.id);
2475
2932
  onTabChange(tab.id);
2476
2933
  }
@@ -2487,11 +2944,188 @@ var __webpack_exports__ = {};
2487
2944
  tabButton.appendChild(iconWrapper);
2488
2945
  tabButton.appendChild(document.createTextNode(tab.label));
2489
2946
  tabButtons.set(tab.id, tabButton);
2490
- tabList.appendChild(tabButton);
2947
+ tabStrip.appendChild(tabButton);
2948
+ const overflowItem = renderer_button({
2949
+ className: `${styles_tabs_module.overflowItem} ${isActive ? styles_tabs_module.overflowItemActive : ''} ${isDisabled ? styles_tabs_module.overflowItemDisabled : ''}`,
2950
+ role: 'menuitemradio',
2951
+ ariaChecked: isActive ? 'true' : 'false',
2952
+ disabled: isDisabled,
2953
+ onClick: ()=>{
2954
+ if (!isDisabled) {
2955
+ setActiveTab(tab.id);
2956
+ onTabChange(tab.id);
2957
+ closeOverflowMenu();
2958
+ tabButtons.get(tab.id)?.focus();
2959
+ }
2960
+ },
2961
+ onKeyDown: (e)=>handleOverflowKeyDown(e, tab.id)
2962
+ });
2963
+ const overflowItemIcon = renderer_div({
2964
+ className: styles_tabs_module.overflowItemIcon
2965
+ });
2966
+ overflowItemIcon.appendChild(createSvgElement(tab.icon, {
2967
+ width: 14,
2968
+ height: 14
2969
+ }));
2970
+ overflowItem.appendChild(overflowItemIcon);
2971
+ overflowItem.appendChild(document.createTextNode(tab.label));
2972
+ overflowButtons.set(tab.id, overflowItem);
2973
+ overflowMenu.appendChild(overflowItem);
2974
+ }
2975
+ function applyActiveState(tab) {
2976
+ for (const [tabId, tabButton] of tabButtons){
2977
+ const isActive = tabId === tab;
2978
+ if (styles_tabs_module.tabActive) tabButton.classList.toggle(styles_tabs_module.tabActive, isActive);
2979
+ tabButton.setAttribute('aria-selected', isActive ? 'true' : 'false');
2980
+ tabButton.tabIndex = isActive ? 0 : -1;
2981
+ }
2982
+ for (const [tabId, overflowItem] of overflowButtons){
2983
+ const isActive = tabId === tab;
2984
+ if (styles_tabs_module.overflowItemActive) overflowItem.classList.toggle(styles_tabs_module.overflowItemActive, isActive);
2985
+ overflowItem.setAttribute('aria-checked', isActive ? 'true' : 'false');
2986
+ }
2987
+ }
2988
+ function updateVisibleTabs() {
2989
+ const allTabIds = TABS.map((t)=>t.id);
2990
+ const iabEnabled = !disabledTabs.includes('iab');
2991
+ const preferredSecondTab = iabEnabled ? 'iab' : 'consents';
2992
+ const overflowSecondTab = iabEnabled ? 'consents' : 'iab';
2993
+ const showOverflowSecondTabInStrip = activeTab === overflowSecondTab;
2994
+ const stripSecondTab = showOverflowSecondTabInStrip ? overflowSecondTab : preferredSecondTab;
2995
+ const forcedOverflowTab = showOverflowSecondTabInStrip ? preferredSecondTab : overflowSecondTab;
2996
+ const layoutTabIds = [
2997
+ 'location',
2998
+ stripSecondTab,
2999
+ "scripts",
3000
+ 'actions',
3001
+ 'events',
3002
+ forcedOverflowTab
3003
+ ];
3004
+ const forcedOverflowTabIds = new Set();
3005
+ forcedOverflowTabIds.add(forcedOverflowTab);
3006
+ for (const [index, tabId] of layoutTabIds.entries()){
3007
+ const tabButton = tabButtons.get(tabId);
3008
+ if (tabButton) tabButton.style.order = String(index);
3009
+ const overflowItem = overflowButtons.get(tabId);
3010
+ if (overflowItem) overflowItem.style.order = String(index);
3011
+ }
3012
+ for (const tabId of allTabIds){
3013
+ const tabButton = tabButtons.get(tabId);
3014
+ if (tabButton && styles_tabs_module.tabHidden) tabButton.classList.remove(styles_tabs_module.tabHidden);
3015
+ }
3016
+ if (styles_tabs_module.overflowContainerHidden) overflowContainer.classList.remove(styles_tabs_module.overflowContainerHidden);
3017
+ const stripGap = Number.parseFloat(getComputedStyle(tabStrip).gap || '0');
3018
+ const calculateVisibleTabs = (availableWidth)=>{
3019
+ if (availableWidth <= 0) return [];
3020
+ const nextVisible = [];
3021
+ let usedWidth = 0;
3022
+ for (const tabId of layoutTabIds){
3023
+ if (forcedOverflowTabIds.has(tabId)) continue;
3024
+ const tabButton = tabButtons.get(tabId);
3025
+ if (!tabButton) continue;
3026
+ const width = tabButton.getBoundingClientRect().width;
3027
+ const nextUsed = 0 === nextVisible.length ? width : usedWidth + stripGap + width;
3028
+ if (nextUsed <= availableWidth) {
3029
+ nextVisible.push(tabId);
3030
+ usedWidth = nextUsed;
3031
+ } else break;
3032
+ }
3033
+ return nextVisible;
3034
+ };
3035
+ const measureStripWidth = ()=>tabStrip.getBoundingClientRect().width;
3036
+ const showOverflowContainer = ()=>{
3037
+ if (styles_tabs_module.overflowContainerHidden) overflowContainer.classList.remove(styles_tabs_module.overflowContainerHidden);
3038
+ };
3039
+ const hideOverflowContainer = ()=>{
3040
+ if (styles_tabs_module.overflowContainerHidden) overflowContainer.classList.add(styles_tabs_module.overflowContainerHidden);
3041
+ };
3042
+ const measureVisibleWidth = (tabIds)=>{
3043
+ let width = 0;
3044
+ for (const [index, tabId] of tabIds.entries()){
3045
+ const tabButton = tabButtons.get(tabId);
3046
+ if (tabButton) {
3047
+ width += tabButton.getBoundingClientRect().width;
3048
+ if (index > 0) width += stripGap;
3049
+ }
3050
+ }
3051
+ return width;
3052
+ };
3053
+ if (0 === forcedOverflowTabIds.size) {
3054
+ hideOverflowContainer();
3055
+ const visibleWithoutOverflow = calculateVisibleTabs(measureStripWidth());
3056
+ if (visibleWithoutOverflow.length === layoutTabIds.length) visibleTabIds = visibleWithoutOverflow;
3057
+ else {
3058
+ showOverflowContainer();
3059
+ visibleTabIds = calculateVisibleTabs(measureStripWidth());
3060
+ }
3061
+ } else {
3062
+ showOverflowContainer();
3063
+ const withOverflow = calculateVisibleTabs(measureStripWidth());
3064
+ visibleTabIds = withOverflow.length > 0 ? withOverflow : [
3065
+ activeTab
3066
+ ];
3067
+ }
3068
+ if (!visibleTabIds.includes(activeTab) && !disabledTabs.includes(activeTab)) if (visibleTabIds.length > 0) visibleTabIds[visibleTabIds.length - 1] = activeTab;
3069
+ else visibleTabIds = [
3070
+ activeTab
3071
+ ];
3072
+ visibleTabIds = [
3073
+ ...new Set(visibleTabIds)
3074
+ ];
3075
+ const maxStripWidth = measureStripWidth();
3076
+ while(visibleTabIds.length > 1 && measureVisibleWidth(visibleTabIds) > maxStripWidth + 0.5){
3077
+ let removeIndex = visibleTabIds.length - 1;
3078
+ if (visibleTabIds[removeIndex] === activeTab) removeIndex = Math.max(0, removeIndex - 1);
3079
+ visibleTabIds.splice(removeIndex, 1);
3080
+ }
3081
+ hiddenTabIds = layoutTabIds.filter((tabId)=>!visibleTabIds.includes(tabId) || forcedOverflowTabIds.has(tabId) && tabId !== activeTab);
3082
+ for (const tabId of allTabIds){
3083
+ const tabButton = tabButtons.get(tabId);
3084
+ if (tabButton) {
3085
+ if (styles_tabs_module.tabHidden) tabButton.classList.toggle(styles_tabs_module.tabHidden, hiddenTabIds.includes(tabId));
3086
+ }
3087
+ }
3088
+ for (const tabId of allTabIds){
3089
+ const overflowItem = overflowButtons.get(tabId);
3090
+ if (overflowItem) {
3091
+ if (styles_tabs_module.overflowItemHidden) overflowItem.classList.toggle(styles_tabs_module.overflowItemHidden, !hiddenTabIds.includes(tabId));
3092
+ }
3093
+ }
3094
+ if (styles_tabs_module.overflowContainerHidden) overflowContainer.classList.toggle(styles_tabs_module.overflowContainerHidden, 0 === hiddenTabIds.length);
3095
+ if (0 === hiddenTabIds.length) closeOverflowMenu();
3096
+ }
3097
+ function focusFirstEnabledOverflowItem() {
3098
+ const firstEnabled = hiddenTabIds.find((tabId)=>!disabledTabs.includes(tabId));
3099
+ if (firstEnabled) overflowButtons.get(firstEnabled)?.focus();
3100
+ }
3101
+ function openOverflowMenu() {
3102
+ if (isOverflowMenuOpen || 0 === hiddenTabIds.length) return;
3103
+ isOverflowMenuOpen = true;
3104
+ overflowMenu.dataset.state = 'open';
3105
+ overflowButton.setAttribute('aria-expanded', 'true');
3106
+ document.addEventListener('click', handleOutsideClick);
3107
+ document.addEventListener('keydown', handleEscapeKey);
3108
+ }
3109
+ function closeOverflowMenu() {
3110
+ if (!isOverflowMenuOpen) return;
3111
+ isOverflowMenuOpen = false;
3112
+ overflowMenu.dataset.state = 'closed';
3113
+ overflowButton.setAttribute('aria-expanded', 'false');
3114
+ document.removeEventListener('click', handleOutsideClick);
3115
+ document.removeEventListener('keydown', handleEscapeKey);
3116
+ }
3117
+ function toggleOverflowMenu() {
3118
+ if (isOverflowMenuOpen) closeOverflowMenu();
3119
+ else openOverflowMenu();
3120
+ }
3121
+ function handleOutsideClick(e) {
3122
+ if (!overflowContainer.contains(e.target)) closeOverflowMenu();
3123
+ }
3124
+ function handleEscapeKey(e) {
3125
+ if ('Escape' === e.key) closeOverflowMenu();
2491
3126
  }
2492
3127
  function handleKeyDown(e, currentTab) {
2493
- const tabIds = TABS.map((t)=>t.id);
2494
- const enabledTabIds = tabIds.filter((id)=>!disabledTabs.includes(id));
3128
+ const enabledTabIds = visibleTabIds.filter((tabId)=>!disabledTabs.includes(tabId));
2495
3129
  const currentIndex = enabledTabIds.indexOf(currentTab);
2496
3130
  let newIndex = currentIndex;
2497
3131
  switch(e.key){
@@ -2518,23 +3152,152 @@ var __webpack_exports__ = {};
2518
3152
  tabButtons.get(newTab)?.focus();
2519
3153
  }
2520
3154
  }
3155
+ function handleOverflowKeyDown(e, currentTab) {
3156
+ const enabledTabIds = hiddenTabIds.filter((tabId)=>!disabledTabs.includes(tabId));
3157
+ const currentIndex = enabledTabIds.indexOf(currentTab);
3158
+ if ('Escape' === e.key) {
3159
+ e.preventDefault();
3160
+ closeOverflowMenu();
3161
+ overflowButton.focus();
3162
+ return;
3163
+ }
3164
+ let newIndex = currentIndex;
3165
+ switch(e.key){
3166
+ case 'ArrowDown':
3167
+ newIndex = (currentIndex + 1) % enabledTabIds.length;
3168
+ break;
3169
+ case 'ArrowUp':
3170
+ newIndex = currentIndex > 0 ? currentIndex - 1 : enabledTabIds.length - 1;
3171
+ break;
3172
+ default:
3173
+ return;
3174
+ }
3175
+ e.preventDefault();
3176
+ const newTab = enabledTabIds[newIndex];
3177
+ if (newTab) overflowButtons.get(newTab)?.focus();
3178
+ }
2521
3179
  function setActiveTab(tab) {
2522
3180
  activeTab = tab;
2523
- for (const [tabId, tabButton] of tabButtons){
2524
- const isActive = tabId === tab;
2525
- if (styles_tabs_module.tabActive) tabButton.classList.toggle(styles_tabs_module.tabActive, isActive);
2526
- tabButton.setAttribute('aria-selected', isActive ? 'true' : 'false');
2527
- tabButton.tabIndex = isActive ? 0 : -1;
2528
- }
3181
+ applyActiveState(tab);
3182
+ updateVisibleTabs();
2529
3183
  }
3184
+ const handleWindowResize = ()=>{
3185
+ updateVisibleTabs();
3186
+ };
3187
+ let resizeObserver = null;
3188
+ if ('undefined' != typeof ResizeObserver) {
3189
+ resizeObserver = new ResizeObserver(()=>{
3190
+ updateVisibleTabs();
3191
+ });
3192
+ resizeObserver.observe(tabList);
3193
+ } else window.addEventListener('resize', handleWindowResize);
3194
+ applyActiveState(activeTab);
3195
+ requestAnimationFrame(()=>{
3196
+ updateVisibleTabs();
3197
+ });
2530
3198
  return {
2531
3199
  element: tabList,
2532
3200
  setActiveTab,
2533
3201
  destroy: ()=>{
3202
+ closeOverflowMenu();
3203
+ if (resizeObserver) {
3204
+ resizeObserver.disconnect();
3205
+ resizeObserver = null;
3206
+ } else window.removeEventListener('resize', handleWindowResize);
2534
3207
  tabButtons.clear();
3208
+ overflowButtons.clear();
2535
3209
  }
2536
3210
  };
2537
3211
  }
3212
+ function debug_bundle_createDebugBundle(payload) {
3213
+ const { namespace, devToolsState, connection, recentEvents, storeState } = payload;
3214
+ const bundle = {
3215
+ generatedAt: new Date().toISOString(),
3216
+ namespace,
3217
+ devToolsState,
3218
+ connection,
3219
+ recentEvents,
3220
+ storeState,
3221
+ overrides: storeState?.overrides ?? null,
3222
+ iab: storeState?.iab ? {
3223
+ tcString: (storeState?.iab).tcString ?? null,
3224
+ purposeCount: Object.keys((storeState?.iab).purposeConsents ?? {}).length,
3225
+ vendorCount: Object.keys((storeState?.iab).vendorConsents ?? {}).length
3226
+ } : null
3227
+ };
3228
+ return JSON.stringify(bundle, null, 2);
3229
+ }
3230
+ function debug_bundle_sanitizeStoreState(state) {
3231
+ if (!state) return null;
3232
+ try {
3233
+ return JSON.parse(JSON.stringify(state, (_key, value)=>'function' == typeof value ? void 0 : value));
3234
+ } catch {
3235
+ return {
3236
+ error: 'Unable to serialize store state'
3237
+ };
3238
+ }
3239
+ }
3240
+ function debug_bundle_downloadDebugBundle(content) {
3241
+ const blob = new Blob([
3242
+ content
3243
+ ], {
3244
+ type: 'application/json'
3245
+ });
3246
+ const url = URL.createObjectURL(blob);
3247
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
3248
+ const anchor = document.createElement('a');
3249
+ anchor.href = url;
3250
+ anchor.download = `c15t-debug-bundle-${timestamp}.json`;
3251
+ anchor.click();
3252
+ URL.revokeObjectURL(url);
3253
+ }
3254
+ const DEVTOOLS_OVERRIDES_STORAGE_KEY = 'c15t-devtools-overrides';
3255
+ function normalizeStringValue(value) {
3256
+ if ('string' != typeof value) return;
3257
+ const normalized = value.trim();
3258
+ return normalized.length > 0 ? normalized : void 0;
3259
+ }
3260
+ function normalizeBooleanValue(value) {
3261
+ return 'boolean' == typeof value ? value : void 0;
3262
+ }
3263
+ function normalizeOverrides(value) {
3264
+ if (!value || 'object' != typeof value) return null;
3265
+ const source = value;
3266
+ const overrides = {
3267
+ country: normalizeStringValue(source.country),
3268
+ region: normalizeStringValue(source.region),
3269
+ language: normalizeStringValue(source.language),
3270
+ gpc: normalizeBooleanValue(source.gpc)
3271
+ };
3272
+ return hasPersistedOverrides(overrides) ? overrides : null;
3273
+ }
3274
+ function hasPersistedOverrides(overrides) {
3275
+ return Boolean(overrides.country || overrides.region || overrides.language || void 0 !== overrides.gpc);
3276
+ }
3277
+ function override_storage_loadPersistedOverrides(storageKey = DEVTOOLS_OVERRIDES_STORAGE_KEY) {
3278
+ if ('undefined' == typeof window) return null;
3279
+ try {
3280
+ const stored = localStorage.getItem(storageKey);
3281
+ if (!stored) return null;
3282
+ const parsed = JSON.parse(stored);
3283
+ return normalizeOverrides(parsed);
3284
+ } catch {
3285
+ return null;
3286
+ }
3287
+ }
3288
+ function override_storage_persistOverrides(overrides, storageKey = DEVTOOLS_OVERRIDES_STORAGE_KEY) {
3289
+ if ('undefined' == typeof window) return;
3290
+ try {
3291
+ if (!hasPersistedOverrides(overrides)) return void localStorage.removeItem(storageKey);
3292
+ localStorage.setItem(storageKey, JSON.stringify(overrides));
3293
+ } catch {}
3294
+ }
3295
+ function override_storage_clearPersistedOverrides(storageKey = DEVTOOLS_OVERRIDES_STORAGE_KEY) {
3296
+ if ('undefined' == typeof window) return;
3297
+ try {
3298
+ localStorage.removeItem(storageKey);
3299
+ } catch {}
3300
+ }
2538
3301
  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");
2539
3302
  var components_module_options = {};
2540
3303
  components_module_options.styleTagTransform = styleTagTransform_default();
@@ -2571,7 +3334,7 @@ var __webpack_exports__ = {};
2571
3334
  info: styles_components_module.badgeInfo,
2572
3335
  neutral: styles_components_module.badgeNeutral
2573
3336
  }[variant];
2574
- return span({
3337
+ return renderer_span({
2575
3338
  className: `${styles_components_module.badge} ${variantClass}`,
2576
3339
  text
2577
3340
  });
@@ -2602,31 +3365,19 @@ var __webpack_exports__ = {};
2602
3365
  btn.appendChild(document.createTextNode(text));
2603
3366
  return btn;
2604
3367
  }
2605
- function createListItem(options) {
2606
- const { title, description, actions = [] } = options;
2607
- const content = renderer_div({
2608
- className: styles_components_module.listItemContent,
2609
- children: [
2610
- span({
2611
- className: styles_components_module.listItemTitle,
2612
- text: title
2613
- }),
2614
- description ? span({
2615
- className: styles_components_module.listItemDescription,
2616
- text: description
2617
- }) : null
2618
- ]
2619
- });
2620
- const actionsContainer = renderer_div({
2621
- className: styles_components_module.listItemActions,
2622
- children: actions
2623
- });
2624
- return renderer_div({
2625
- className: styles_components_module.listItem,
2626
- children: [
2627
- content,
2628
- actionsContainer
2629
- ]
3368
+ function createInput(options) {
3369
+ const { value, placeholder, ariaLabel, small = false, onInput } = options;
3370
+ const sizeClass = small ? styles_components_module.inputSmall : '';
3371
+ return input({
3372
+ className: `${styles_components_module.input} ${sizeClass}`.trim(),
3373
+ type: 'text',
3374
+ value,
3375
+ placeholder,
3376
+ ariaLabel,
3377
+ onInput: (event)=>{
3378
+ const target = event.target;
3379
+ onInput?.(target?.value ?? '');
3380
+ }
2630
3381
  });
2631
3382
  }
2632
3383
  function createSection(options) {
@@ -2634,7 +3385,7 @@ var __webpack_exports__ = {};
2634
3385
  const header = renderer_div({
2635
3386
  className: styles_components_module.sectionHeader,
2636
3387
  children: [
2637
- span({
3388
+ renderer_span({
2638
3389
  className: styles_components_module.sectionTitle,
2639
3390
  text: title
2640
3391
  }),
@@ -2654,11 +3405,11 @@ var __webpack_exports__ = {};
2654
3405
  return renderer_div({
2655
3406
  className: styles_components_module.infoRow,
2656
3407
  children: [
2657
- span({
3408
+ renderer_span({
2658
3409
  className: styles_components_module.infoLabel,
2659
3410
  text: label
2660
3411
  }),
2661
- span({
3412
+ renderer_span({
2662
3413
  className: styles_components_module.infoValue,
2663
3414
  text: value
2664
3415
  })
@@ -2678,7 +3429,7 @@ var __webpack_exports__ = {};
2678
3429
  }));
2679
3430
  children.push(iconWrapper);
2680
3431
  }
2681
- children.push(span({
3432
+ children.push(renderer_span({
2682
3433
  className: styles_components_module.emptyStateText,
2683
3434
  text
2684
3435
  }));
@@ -2698,7 +3449,7 @@ var __webpack_exports__ = {};
2698
3449
  function createGridCard(options) {
2699
3450
  const { title, action } = options;
2700
3451
  const children = [
2701
- span({
3452
+ renderer_span({
2702
3453
  className: styles_components_module.gridCardTitle,
2703
3454
  text: title
2704
3455
  })
@@ -2709,6 +3460,18 @@ var __webpack_exports__ = {};
2709
3460
  children
2710
3461
  });
2711
3462
  }
3463
+ function createDisconnectedState(message = 'Store not connected') {
3464
+ return renderer_div({
3465
+ className: styles_components_module.disconnectedState,
3466
+ style: {
3467
+ padding: '24px',
3468
+ textAlign: 'center',
3469
+ color: 'var(--c15t-text-muted)',
3470
+ fontSize: 'var(--c15t-devtools-font-size-sm)'
3471
+ },
3472
+ text: message
3473
+ });
3474
+ }
2712
3475
  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">
2713
3476
  <path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"></path>
2714
3477
  <path d="M21 3v5h-5"></path>
@@ -2736,19 +3499,11 @@ var __webpack_exports__ = {};
2736
3499
  <polyline points="4 17 10 11 4 5"></polyline>
2737
3500
  <line x1="12" y1="19" x2="20" y2="19"></line>
2738
3501
  </svg>`;
2739
- function actions_renderActionsPanel(container, options) {
2740
- const { getState, onResetConsents, onRefetchBanner, onShowBanner, onOpenPreferences, onCopyState } = options;
3502
+ function renderActionsPanel(container, options) {
3503
+ const { getState, onResetConsents, onRefetchBanner, onShowBanner, onOpenPreferences, onCopyState, onExportDebugBundle } = options;
2741
3504
  clearElement(container);
2742
3505
  const state = getState();
2743
- if (!state) return void container.appendChild(renderer_div({
2744
- style: {
2745
- padding: '24px',
2746
- textAlign: 'center',
2747
- color: 'var(--c15t-text-muted)',
2748
- fontSize: 'var(--c15t-devtools-font-size-sm)'
2749
- },
2750
- text: 'Store not connected'
2751
- }));
3506
+ if (!state) return void container.appendChild(createDisconnectedState());
2752
3507
  const actionCards = [
2753
3508
  createActionCard({
2754
3509
  icon: actions_EYE_ICON,
@@ -2769,6 +3524,12 @@ var __webpack_exports__ = {};
2769
3524
  icon: COPY_ICON,
2770
3525
  label: 'Copy State',
2771
3526
  onClick: onCopyState
3527
+ }),
3528
+ createActionCard({
3529
+ icon: REFRESH_ICON,
3530
+ label: 'Export Debug',
3531
+ onClick: ()=>onExportDebugBundle?.(),
3532
+ disabled: !onExportDebugBundle
2772
3533
  })
2773
3534
  ];
2774
3535
  const grid = createGrid({
@@ -2806,7 +3567,7 @@ var __webpack_exports__ = {};
2806
3567
  },
2807
3568
  children: [
2808
3569
  createIconWrapper(TERMINAL_ICON, 14),
2809
- span({
3570
+ renderer_span({
2810
3571
  style: {
2811
3572
  fontSize: 'var(--c15t-devtools-font-size-xs)',
2812
3573
  fontWeight: '600',
@@ -2829,10 +3590,10 @@ var __webpack_exports__ = {};
2829
3590
  color: 'var(--c15t-text-muted)'
2830
3591
  },
2831
3592
  children: [
2832
- span({
3593
+ renderer_span({
2833
3594
  text: `window.${getNamespace(state)}.getState()`
2834
3595
  }),
2835
- span({
3596
+ renderer_span({
2836
3597
  text: 'window.__c15tDevTools.open()'
2837
3598
  })
2838
3599
  ]
@@ -2842,7 +3603,7 @@ var __webpack_exports__ = {};
2842
3603
  container.appendChild(consoleSection);
2843
3604
  }
2844
3605
  function createActionCard(options) {
2845
- const { icon, label, onClick } = options;
3606
+ const { icon, label, onClick, disabled = false } = options;
2846
3607
  const card = renderer_div({
2847
3608
  className: styles_components_module.gridCard ?? '',
2848
3609
  style: {
@@ -2853,11 +3614,12 @@ var __webpack_exports__ = {};
2853
3614
  gap: '6px',
2854
3615
  padding: '16px 8px',
2855
3616
  cursor: 'pointer',
2856
- transition: 'background-color var(--c15t-duration-fast) var(--c15t-easing)'
3617
+ transition: 'background-color var(--c15t-duration-fast) var(--c15t-easing)',
3618
+ opacity: disabled ? '0.55' : '1'
2857
3619
  },
2858
3620
  children: [
2859
3621
  createIconWrapper(icon, 20),
2860
- span({
3622
+ renderer_span({
2861
3623
  style: {
2862
3624
  fontSize: 'var(--c15t-devtools-font-size-xs)',
2863
3625
  fontWeight: '500',
@@ -2868,13 +3630,15 @@ var __webpack_exports__ = {};
2868
3630
  })
2869
3631
  ]
2870
3632
  });
2871
- card.addEventListener('click', onClick);
2872
- card.addEventListener('mouseenter', ()=>{
2873
- card.style.backgroundColor = 'var(--c15t-surface-hover)';
2874
- });
2875
- card.addEventListener('mouseleave', ()=>{
2876
- card.style.backgroundColor = '';
2877
- });
3633
+ if (!disabled) {
3634
+ card.addEventListener('click', onClick);
3635
+ card.addEventListener('mouseenter', ()=>{
3636
+ card.style.backgroundColor = 'var(--c15t-surface-hover)';
3637
+ });
3638
+ card.addEventListener('mouseleave', ()=>{
3639
+ card.style.backgroundColor = '';
3640
+ });
3641
+ }
2878
3642
  return card;
2879
3643
  }
2880
3644
  function createIconWrapper(icon, size) {
@@ -2895,19 +3659,12 @@ var __webpack_exports__ = {};
2895
3659
  function getNamespace(state) {
2896
3660
  return state.config?.meta?.namespace || 'c15tStore';
2897
3661
  }
2898
- function consents_renderConsentsPanel(container, options) {
3662
+ const consentSearchByContainer = new WeakMap();
3663
+ function renderConsentsPanel(container, options) {
2899
3664
  const { getState, onConsentChange, onSave, onAcceptAll, onRejectAll, onReset } = options;
2900
3665
  clearElement(container);
2901
3666
  const state = getState();
2902
- if (!state) return void container.appendChild(renderer_div({
2903
- style: {
2904
- padding: '24px',
2905
- textAlign: 'center',
2906
- color: 'var(--c15t-text-muted)',
2907
- fontSize: 'var(--c15t-devtools-font-size-sm)'
2908
- },
2909
- text: 'Store not connected'
2910
- }));
3667
+ if (!state) return void container.appendChild(createDisconnectedState());
2911
3668
  const isIabMode = 'iab' === state.model;
2912
3669
  const savedConsents = state.consents || {};
2913
3670
  const selectedConsents = state.selectedConsents || {};
@@ -2921,15 +3678,40 @@ var __webpack_exports__ = {};
2921
3678
  ct.name,
2922
3679
  ct
2923
3680
  ]));
3681
+ const searchQuery = consentSearchByContainer.get(container) ?? '';
2924
3682
  const consentEntries = Object.entries(displayConsents);
2925
- if (0 === consentEntries.length) container.appendChild(renderer_div({
3683
+ const filteredConsentEntries = consentEntries.filter(([name])=>{
3684
+ if (!searchQuery) return true;
3685
+ const consentType = consentTypeMap.get(name);
3686
+ const displayName = consentType?.name || name;
3687
+ return `${name} ${displayName}`.toLowerCase().includes(searchQuery);
3688
+ });
3689
+ const showSearchInput = consentEntries.length > 4;
3690
+ if (showSearchInput) container.appendChild(renderer_div({
3691
+ style: {
3692
+ padding: '8px 0 10px'
3693
+ },
3694
+ children: [
3695
+ createInput({
3696
+ value: searchQuery,
3697
+ placeholder: 'Filter consents…',
3698
+ ariaLabel: 'Filter consents',
3699
+ small: true,
3700
+ onInput: (value)=>{
3701
+ consentSearchByContainer.set(container, value.trim().toLowerCase());
3702
+ renderConsentsPanel(container, options);
3703
+ }
3704
+ })
3705
+ ]
3706
+ }));
3707
+ if (0 === filteredConsentEntries.length) container.appendChild(renderer_div({
2926
3708
  style: {
2927
3709
  padding: '24px',
2928
3710
  textAlign: 'center',
2929
3711
  color: 'var(--c15t-devtools-text-muted)',
2930
3712
  fontSize: 'var(--c15t-devtools-font-size-sm)'
2931
3713
  },
2932
- text: 'No consents configured'
3714
+ text: 0 === consentEntries.length ? 'No consents configured' : 'No matching consents'
2933
3715
  }));
2934
3716
  else {
2935
3717
  if (isIabMode) {
@@ -2947,7 +3729,7 @@ var __webpack_exports__ = {};
2947
3729
  container.appendChild(iabNotice);
2948
3730
  }
2949
3731
  const gridCards = [];
2950
- for (const [name, value] of consentEntries){
3732
+ for (const [name, value] of filteredConsentEntries){
2951
3733
  const consentType = consentTypeMap.get(name);
2952
3734
  const isNecessary = 'necessary' === name;
2953
3735
  const displayName = consentType?.name || name;
@@ -3011,13 +3793,13 @@ var __webpack_exports__ = {};
3011
3793
  },
3012
3794
  children: [
3013
3795
  createButton({
3014
- text: 'All',
3796
+ text: 'Accept',
3015
3797
  variant: 'primary',
3016
3798
  small: true,
3017
3799
  onClick: onAcceptAll
3018
3800
  }),
3019
3801
  createButton({
3020
- text: 'None',
3802
+ text: 'Reject',
3021
3803
  variant: 'default',
3022
3804
  small: true,
3023
3805
  onClick: onRejectAll
@@ -3037,7 +3819,7 @@ var __webpack_exports__ = {};
3037
3819
  gap: '8px'
3038
3820
  },
3039
3821
  children: [
3040
- span({
3822
+ renderer_span({
3041
3823
  style: {
3042
3824
  fontSize: 'var(--c15t-devtools-font-size-xs)',
3043
3825
  color: 'var(--c15t-devtools-badge-warning)'
@@ -3051,7 +3833,7 @@ var __webpack_exports__ = {};
3051
3833
  onClick: onSave
3052
3834
  })
3053
3835
  ]
3054
- }) : span({
3836
+ }) : renderer_span({
3055
3837
  style: {
3056
3838
  fontSize: 'var(--c15t-devtools-font-size-xs)',
3057
3839
  color: 'var(--c15t-text-muted)'
@@ -3065,19 +3847,36 @@ var __webpack_exports__ = {};
3065
3847
  function formatConsentName(name) {
3066
3848
  return name.replace(/_/g, ' ').replace(/\b\w/g, (l)=>l.toUpperCase());
3067
3849
  }
3068
- function events_renderEventsPanel(container, options) {
3850
+ const panelStateByContainer = new WeakMap();
3851
+ function getPanelState(container) {
3852
+ const existing = panelStateByContainer.get(container);
3853
+ if (existing) return existing;
3854
+ const initialState = {
3855
+ activeFilter: 'all',
3856
+ selectedEventId: null,
3857
+ searchQuery: ''
3858
+ };
3859
+ panelStateByContainer.set(container, initialState);
3860
+ return initialState;
3861
+ }
3862
+ function renderEventsPanel(container, options) {
3069
3863
  const { getEvents, onClear } = options;
3864
+ const panelState = getPanelState(container);
3070
3865
  clearElement(container);
3071
- const events = getEvents();
3866
+ const allEvents = getEvents();
3867
+ const events = allEvents.filter((event)=>matchesFilter(event, panelState.activeFilter)).filter((event)=>matchesSearch(event, panelState.searchQuery));
3868
+ if (!events.some((event)=>event.id === panelState.selectedEventId)) panelState.selectedEventId = events[0]?.id ?? null;
3869
+ const selectedEvent = events.find((event)=>event.id === panelState.selectedEventId) ?? null;
3072
3870
  const header = renderer_div({
3073
3871
  style: {
3074
3872
  display: 'flex',
3075
3873
  alignItems: 'center',
3076
3874
  justifyContent: 'space-between',
3077
- padding: '12px 16px 8px'
3875
+ padding: '12px 16px 8px',
3876
+ gap: '8px'
3078
3877
  },
3079
3878
  children: [
3080
- span({
3879
+ renderer_span({
3081
3880
  style: {
3082
3881
  fontSize: 'var(--c15t-devtools-font-size-xs)',
3083
3882
  fontWeight: '600',
@@ -3085,66 +3884,178 @@ var __webpack_exports__ = {};
3085
3884
  textTransform: 'uppercase',
3086
3885
  letterSpacing: '0.5px'
3087
3886
  },
3088
- text: `Events (${events.length})`
3887
+ text: `Events (${events.length}/${allEvents.length})`
3089
3888
  }),
3090
- createButton({
3091
- text: 'Clear',
3092
- small: true,
3093
- onClick: onClear
3889
+ renderer_div({
3890
+ style: {
3891
+ display: 'flex',
3892
+ gap: '6px'
3893
+ },
3894
+ children: [
3895
+ createButton({
3896
+ text: 'Export',
3897
+ small: true,
3898
+ onClick: ()=>exportEvents(allEvents)
3899
+ }),
3900
+ createButton({
3901
+ text: 'Clear',
3902
+ small: true,
3903
+ onClick: ()=>{
3904
+ onClear();
3905
+ panelState.selectedEventId = null;
3906
+ renderEventsPanel(container, options);
3907
+ }
3908
+ })
3909
+ ]
3094
3910
  })
3095
3911
  ]
3096
3912
  });
3097
3913
  container.appendChild(header);
3914
+ container.appendChild(renderer_div({
3915
+ style: {
3916
+ display: 'flex',
3917
+ flexWrap: 'wrap',
3918
+ gap: '6px',
3919
+ padding: '0 16px 8px'
3920
+ },
3921
+ children: EVENT_FILTERS.map((filter)=>createFilterButton(filter, filter === panelState.activeFilter, ()=>{
3922
+ panelState.activeFilter = filter;
3923
+ panelState.selectedEventId = null;
3924
+ renderEventsPanel(container, options);
3925
+ }))
3926
+ }));
3927
+ container.appendChild(renderer_div({
3928
+ style: {
3929
+ padding: '0 16px 8px'
3930
+ },
3931
+ children: [
3932
+ createInput({
3933
+ value: panelState.searchQuery,
3934
+ placeholder: 'Search events…',
3935
+ ariaLabel: 'Search events',
3936
+ small: true,
3937
+ onInput: (value)=>{
3938
+ panelState.searchQuery = value.trim().toLowerCase();
3939
+ panelState.selectedEventId = null;
3940
+ renderEventsPanel(container, options);
3941
+ }
3942
+ })
3943
+ ]
3944
+ }));
3098
3945
  const eventList = renderer_div({
3099
3946
  style: {
3100
3947
  display: 'flex',
3101
3948
  flexDirection: 'column',
3102
3949
  gap: '4px',
3103
3950
  padding: '0 12px 12px',
3104
- maxHeight: '400px',
3951
+ maxHeight: '300px',
3105
3952
  overflowY: 'auto'
3106
3953
  }
3107
3954
  });
3108
- if (0 === events.length) {
3109
- const emptyState = renderer_div({
3110
- style: {
3111
- padding: '32px 16px',
3112
- textAlign: 'center',
3113
- color: 'var(--c15t-text-muted)',
3114
- fontSize: 'var(--c15t-devtools-font-size-sm)'
3115
- },
3116
- text: 'No events recorded yet'
3117
- });
3118
- eventList.appendChild(emptyState);
3119
- } else for (const event of events){
3120
- const eventItem = createEventItem(event);
3121
- eventList.appendChild(eventItem);
3122
- }
3955
+ if (0 === events.length) eventList.appendChild(renderer_div({
3956
+ style: {
3957
+ padding: '20px 16px',
3958
+ textAlign: 'center',
3959
+ color: 'var(--c15t-text-muted)',
3960
+ fontSize: 'var(--c15t-devtools-font-size-sm)'
3961
+ },
3962
+ text: 'No events match this filter'
3963
+ }));
3964
+ else for (const event of events)eventList.appendChild(createEventItem(event, event.id === panelState.selectedEventId, ()=>{
3965
+ panelState.selectedEventId = event.id;
3966
+ renderEventsPanel(container, options);
3967
+ }));
3123
3968
  container.appendChild(eventList);
3969
+ container.appendChild(createPayloadSection(selectedEvent));
3124
3970
  }
3125
- function createEventItem(event) {
3126
- const time = formatTime(event.timestamp);
3127
- const icon = getEventIcon(event.type);
3128
- const color = getEventColor(event.type);
3971
+ const EVENT_FILTERS = [
3972
+ 'all',
3973
+ 'error',
3974
+ 'consent',
3975
+ 'network',
3976
+ 'iab'
3977
+ ];
3978
+ function createFilterButton(filter, active, onClick) {
3979
+ return createButton({
3980
+ text: filter.toUpperCase(),
3981
+ small: true,
3982
+ variant: active ? 'primary' : 'default',
3983
+ onClick
3984
+ });
3985
+ }
3986
+ function matchesFilter(event, filter) {
3987
+ if ('all' === filter) return true;
3988
+ if ('error' === filter) return 'error' === event.type;
3989
+ if ('consent' === filter) return 'consent_set' === event.type || 'consent_save' === event.type || 'consent_reset' === event.type;
3990
+ if ('network' === filter) return 'network' === event.type;
3991
+ return 'iab' === event.type;
3992
+ }
3993
+ function matchesSearch(event, query) {
3994
+ if (!query) return true;
3995
+ const haystack = `${event.type} ${event.message} ${JSON.stringify(event.data ?? {})}`;
3996
+ return haystack.toLowerCase().includes(query);
3997
+ }
3998
+ function createPayloadSection(event) {
3999
+ const payload = event?.data ? JSON.stringify(event.data, null, 2) : null;
3129
4000
  return renderer_div({
3130
- className: styles_components_module.gridCard ?? '',
3131
4001
  style: {
3132
- display: 'flex',
3133
- alignItems: 'center',
3134
- gap: '8px',
3135
- padding: '6px 10px',
3136
- fontSize: 'var(--c15t-devtools-font-size-xs)'
4002
+ padding: '0 12px 12px'
3137
4003
  },
3138
4004
  children: [
3139
- span({
4005
+ renderer_div({
3140
4006
  style: {
3141
- color,
3142
- fontSize: '8px',
3143
- lineHeight: '1'
4007
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
4008
+ fontWeight: '600',
4009
+ color: 'var(--c15t-text-muted)',
4010
+ textTransform: 'uppercase',
4011
+ letterSpacing: '0.5px',
4012
+ marginBottom: '6px'
3144
4013
  },
3145
- text: icon
4014
+ text: 'Payload'
3146
4015
  }),
3147
- span({
4016
+ renderer_div({
4017
+ className: styles_components_module.gridCard ?? '',
4018
+ style: {
4019
+ padding: '8px',
4020
+ fontFamily: 'ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, monospace',
4021
+ fontSize: '11px',
4022
+ color: 'var(--c15t-text-muted)',
4023
+ maxHeight: '140px',
4024
+ overflowY: 'auto',
4025
+ whiteSpace: 'pre-wrap',
4026
+ wordBreak: 'break-word'
4027
+ },
4028
+ text: payload || 'Select an event with payload data'
4029
+ })
4030
+ ]
4031
+ });
4032
+ }
4033
+ function createEventItem(event, selected, onSelect) {
4034
+ const time = formatTime(event.timestamp);
4035
+ const icon = getEventIcon(event.type);
4036
+ const color = getEventColor(event.type);
4037
+ return renderer_div({
4038
+ className: styles_components_module.gridCard ?? '',
4039
+ style: {
4040
+ display: 'flex',
4041
+ alignItems: 'center',
4042
+ gap: '8px',
4043
+ padding: '6px 10px',
4044
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
4045
+ cursor: 'pointer',
4046
+ borderColor: selected ? 'var(--c15t-devtools-badge-info, #3b82f6)' : 'var(--c15t-border)'
4047
+ },
4048
+ onClick: onSelect,
4049
+ children: [
4050
+ renderer_span({
4051
+ style: {
4052
+ color,
4053
+ fontSize: '8px',
4054
+ lineHeight: '1'
4055
+ },
4056
+ text: icon
4057
+ }),
4058
+ renderer_span({
3148
4059
  style: {
3149
4060
  color: 'var(--c15t-text-muted)',
3150
4061
  fontFamily: 'monospace',
@@ -3153,7 +4064,7 @@ var __webpack_exports__ = {};
3153
4064
  },
3154
4065
  text: time
3155
4066
  }),
3156
- span({
4067
+ renderer_span({
3157
4068
  style: {
3158
4069
  color: 'var(--c15t-text)',
3159
4070
  flex: '1'
@@ -3163,6 +4074,21 @@ var __webpack_exports__ = {};
3163
4074
  ]
3164
4075
  });
3165
4076
  }
4077
+ function exportEvents(events) {
4078
+ const json = JSON.stringify(events, null, 2);
4079
+ const blob = new Blob([
4080
+ json
4081
+ ], {
4082
+ type: 'application/json'
4083
+ });
4084
+ const url = URL.createObjectURL(blob);
4085
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
4086
+ const a = document.createElement('a');
4087
+ a.href = url;
4088
+ a.download = `c15t-events-${timestamp}.json`;
4089
+ a.click();
4090
+ URL.revokeObjectURL(url);
4091
+ }
3166
4092
  function formatTime(timestamp) {
3167
4093
  const date = new Date(timestamp);
3168
4094
  return date.toLocaleTimeString('en-US', {
@@ -3181,7 +4107,10 @@ var __webpack_exports__ = {};
3181
4107
  return '○';
3182
4108
  case 'error':
3183
4109
  return '✕';
3184
- case 'info':
4110
+ case 'network':
4111
+ return '◉';
4112
+ case 'iab':
4113
+ return '◆';
3185
4114
  default:
3186
4115
  return '○';
3187
4116
  }
@@ -3195,43 +4124,23 @@ var __webpack_exports__ = {};
3195
4124
  return 'var(--c15t-devtools-badge-warning, #f59e0b)';
3196
4125
  case 'error':
3197
4126
  return 'var(--c15t-devtools-badge-error, #ef4444)';
3198
- case 'info':
4127
+ case 'network':
4128
+ return 'var(--c15t-devtools-badge-warning, #f59e0b)';
4129
+ case 'iab':
4130
+ return 'var(--c15t-devtools-badge-info, #3b82f6)';
3199
4131
  default:
3200
4132
  return 'var(--c15t-text-muted)';
3201
4133
  }
3202
4134
  }
3203
- function iab_renderIabPanel(container, options) {
3204
- const { getState, onReset } = options;
4135
+ const iabSearchByContainer = new WeakMap();
4136
+ function renderIabPanel(container, options) {
4137
+ const { getState, onSetPurposeConsent, onSetVendorConsent, onSetSpecialFeatureOptIn, onAcceptAll, onRejectAll, onSave, onReset } = options;
3205
4138
  clearElement(container);
3206
4139
  const state = getState();
3207
- if (!state) return void container.appendChild(renderer_div({
3208
- style: {
3209
- padding: '24px',
3210
- textAlign: 'center',
3211
- color: 'var(--c15t-text-muted)',
3212
- fontSize: 'var(--c15t-devtools-font-size-sm)'
3213
- },
3214
- text: 'Store not connected'
3215
- }));
3216
- if ('iab' !== state.model) return void container.appendChild(renderer_div({
3217
- style: {
3218
- padding: '24px',
3219
- textAlign: 'center',
3220
- color: 'var(--c15t-text-muted)',
3221
- fontSize: 'var(--c15t-devtools-font-size-sm)'
3222
- },
3223
- text: 'IAB TCF mode is not configured'
3224
- }));
4140
+ if (!state) return void container.appendChild(createDisconnectedState());
4141
+ if ('iab' !== state.model) return void container.appendChild(createDisconnectedState('IAB TCF mode is not configured'));
3225
4142
  const iabState = state.iab;
3226
- if (!iabState) return void container.appendChild(renderer_div({
3227
- style: {
3228
- padding: '24px',
3229
- textAlign: 'center',
3230
- color: 'var(--c15t-text-muted)',
3231
- fontSize: 'var(--c15t-devtools-font-size-sm)'
3232
- },
3233
- text: 'IAB state not available'
3234
- }));
4143
+ if (!iabState) return void container.appendChild(createDisconnectedState('IAB state not available'));
3235
4144
  const tcString = iabState.tcString;
3236
4145
  const tcStringSection = createSection({
3237
4146
  title: 'TC String',
@@ -3263,9 +4172,30 @@ var __webpack_exports__ = {};
3263
4172
  });
3264
4173
  container.appendChild(tcStringSection);
3265
4174
  const gvl = iabState.gvl;
4175
+ const searchQuery = iabSearchByContainer.get(container) ?? '';
4176
+ container.appendChild(createSection({
4177
+ title: 'Filter',
4178
+ children: [
4179
+ createInput({
4180
+ value: searchQuery,
4181
+ placeholder: 'Filter purposes or vendors…',
4182
+ ariaLabel: 'Filter IAB purposes and vendors',
4183
+ small: true,
4184
+ onInput: (value)=>{
4185
+ iabSearchByContainer.set(container, value.trim().toLowerCase());
4186
+ renderIabPanel(container, options);
4187
+ }
4188
+ })
4189
+ ]
4190
+ }));
3266
4191
  const purposeConsents = iabState.purposeConsents || {};
3267
4192
  const purposes = gvl?.purposes || {};
3268
- const purposeEntries = Object.entries(purposeConsents);
4193
+ const purposeEntries = Object.entries(purposeConsents).filter(([purposeId])=>{
4194
+ if (!searchQuery) return true;
4195
+ const purposeInfo = purposes[purposeId];
4196
+ const purposeName = purposeInfo?.name || `Purpose ${purposeId}`;
4197
+ return `${purposeId} ${purposeName}`.toLowerCase().includes(searchQuery);
4198
+ });
3269
4199
  if (purposeEntries.length > 0) {
3270
4200
  const purposeList = renderer_div({
3271
4201
  style: {
@@ -3279,7 +4209,9 @@ var __webpack_exports__ = {};
3279
4209
  for (const [purposeId, consent] of purposeEntries){
3280
4210
  const purposeInfo = purposes[purposeId];
3281
4211
  const purposeName = purposeInfo?.name || `Purpose ${purposeId}`;
3282
- purposeList.appendChild(createPurposeRow(purposeId, purposeName, Boolean(consent)));
4212
+ purposeList.appendChild(createPurposeRow(purposeId, purposeName, Boolean(consent), (value)=>{
4213
+ onSetPurposeConsent(Number(purposeId), value);
4214
+ }));
3283
4215
  }
3284
4216
  const purposesSection = createSection({
3285
4217
  title: `Purposes (${purposeEntries.length})`,
@@ -3291,7 +4223,12 @@ var __webpack_exports__ = {};
3291
4223
  }
3292
4224
  const specialFeatureOptIns = iabState.specialFeatureOptIns || {};
3293
4225
  const specialFeatures = gvl?.specialFeatures || {};
3294
- const specialFeatureEntries = Object.entries(specialFeatureOptIns);
4226
+ const specialFeatureEntries = Object.entries(specialFeatureOptIns).filter(([featureId])=>{
4227
+ if (!searchQuery) return true;
4228
+ const featureInfo = specialFeatures[featureId];
4229
+ const featureName = featureInfo?.name || `Special Feature ${featureId}`;
4230
+ return `${featureId} ${featureName}`.toLowerCase().includes(searchQuery);
4231
+ });
3295
4232
  if (specialFeatureEntries.length > 0) {
3296
4233
  const specialFeatureList = renderer_div({
3297
4234
  style: {
@@ -3305,7 +4242,9 @@ var __webpack_exports__ = {};
3305
4242
  for (const [featureId, optIn] of specialFeatureEntries){
3306
4243
  const featureInfo = specialFeatures[featureId];
3307
4244
  const featureName = featureInfo?.name || `Special Feature ${featureId}`;
3308
- specialFeatureList.appendChild(createPurposeRow(featureId, featureName, Boolean(optIn)));
4245
+ specialFeatureList.appendChild(createPurposeRow(featureId, featureName, Boolean(optIn), (value)=>{
4246
+ onSetSpecialFeatureOptIn(Number(featureId), value);
4247
+ }, 'feature'));
3309
4248
  }
3310
4249
  const specialFeaturesSection = createSection({
3311
4250
  title: `Special Features (${specialFeatureEntries.length})`,
@@ -3317,7 +4256,12 @@ var __webpack_exports__ = {};
3317
4256
  }
3318
4257
  const vendorConsents = iabState.vendorConsents || {};
3319
4258
  const vendors = gvl?.vendors || {};
3320
- const vendorEntries = Object.entries(vendorConsents);
4259
+ const vendorEntries = Object.entries(vendorConsents).filter(([vendorId])=>{
4260
+ if (!searchQuery) return true;
4261
+ const vendorInfo = vendors[vendorId];
4262
+ const vendorName = vendorInfo?.name || `Vendor ${vendorId}`;
4263
+ return `${vendorId} ${vendorName}`.toLowerCase().includes(searchQuery);
4264
+ });
3321
4265
  const iabVendors = [];
3322
4266
  const customVendors = [];
3323
4267
  for (const [vendorId, consent] of vendorEntries){
@@ -3345,7 +4289,9 @@ var __webpack_exports__ = {};
3345
4289
  overflowY: 'auto'
3346
4290
  }
3347
4291
  });
3348
- for (const [vendorId, consent, vendorName] of iabVendors)vendorList.appendChild(createVendorRow(vendorId, vendorName, consent, 'iab'));
4292
+ for (const [vendorId, consent, vendorName] of iabVendors)vendorList.appendChild(createVendorRow(vendorId, vendorName, consent, 'iab', (value)=>{
4293
+ onSetVendorConsent(Number(vendorId), value);
4294
+ }));
3349
4295
  const vendorsSection = createSection({
3350
4296
  title: `IAB Vendors (${iabVendors.length})`,
3351
4297
  children: [
@@ -3364,7 +4310,9 @@ var __webpack_exports__ = {};
3364
4310
  overflowY: 'auto'
3365
4311
  }
3366
4312
  });
3367
- for (const [vendorId, consent, vendorName] of customVendors)customVendorList.appendChild(createVendorRow(vendorId, vendorName, consent, 'custom'));
4313
+ for (const [vendorId, consent, vendorName] of customVendors)customVendorList.appendChild(createVendorRow(vendorId, vendorName, consent, 'custom', (value)=>{
4314
+ onSetVendorConsent(vendorId, value);
4315
+ }));
3368
4316
  const customVendorsSection = createSection({
3369
4317
  title: `Custom Vendors (${customVendors.length})`,
3370
4318
  children: [
@@ -3386,15 +4334,40 @@ var __webpack_exports__ = {};
3386
4334
  style: {
3387
4335
  display: 'flex',
3388
4336
  alignItems: 'center',
3389
- justifyContent: 'flex-end',
4337
+ justifyContent: 'space-between',
3390
4338
  padding: '12px 16px',
3391
4339
  marginTop: 'auto',
3392
4340
  borderTop: '1px solid var(--c15t-border)',
3393
4341
  backgroundColor: 'var(--c15t-surface)'
3394
4342
  },
3395
4343
  children: [
4344
+ renderer_div({
4345
+ style: {
4346
+ display: 'flex',
4347
+ gap: '6px'
4348
+ },
4349
+ children: [
4350
+ createButton({
4351
+ text: 'Accept All',
4352
+ variant: 'primary',
4353
+ small: true,
4354
+ onClick: onAcceptAll
4355
+ }),
4356
+ createButton({
4357
+ text: 'Reject All',
4358
+ small: true,
4359
+ onClick: onRejectAll
4360
+ }),
4361
+ createButton({
4362
+ text: 'Save',
4363
+ variant: 'primary',
4364
+ small: true,
4365
+ onClick: onSave
4366
+ })
4367
+ ]
4368
+ }),
3396
4369
  createButton({
3397
- text: 'Reset All',
4370
+ text: 'Reset',
3398
4371
  variant: 'danger',
3399
4372
  small: true,
3400
4373
  onClick: onReset
@@ -3403,7 +4376,7 @@ var __webpack_exports__ = {};
3403
4376
  });
3404
4377
  container.appendChild(footer);
3405
4378
  }
3406
- function createPurposeRow(id, name, consent) {
4379
+ function createPurposeRow(id, name, consent, onChange, ariaKind = 'purpose') {
3407
4380
  return renderer_div({
3408
4381
  style: {
3409
4382
  display: 'flex',
@@ -3414,7 +4387,7 @@ var __webpack_exports__ = {};
3414
4387
  borderBottom: '1px solid var(--c15t-border)'
3415
4388
  },
3416
4389
  children: [
3417
- span({
4390
+ renderer_span({
3418
4391
  style: {
3419
4392
  color: 'var(--c15t-text)',
3420
4393
  overflow: 'hidden',
@@ -3426,14 +4399,28 @@ var __webpack_exports__ = {};
3426
4399
  text: `${id}. ${name}`,
3427
4400
  title: name
3428
4401
  }),
3429
- createBadge({
3430
- text: consent ? '✓' : '✕',
3431
- variant: consent ? 'success' : 'error'
4402
+ renderer_div({
4403
+ style: {
4404
+ display: 'flex',
4405
+ alignItems: 'center',
4406
+ gap: '6px'
4407
+ },
4408
+ children: [
4409
+ createBadge({
4410
+ text: consent ? '✓' : '✕',
4411
+ variant: consent ? 'success' : 'error'
4412
+ }),
4413
+ createToggle({
4414
+ checked: consent,
4415
+ onChange,
4416
+ ariaLabel: `Toggle ${ariaKind} ${id}`
4417
+ })
4418
+ ]
3432
4419
  })
3433
4420
  ]
3434
4421
  });
3435
4422
  }
3436
- function createVendorRow(id, name, consent, type) {
4423
+ function createVendorRow(id, name, consent, type, onChange) {
3437
4424
  return renderer_div({
3438
4425
  style: {
3439
4426
  display: 'flex',
@@ -3454,7 +4441,7 @@ var __webpack_exports__ = {};
3454
4441
  marginRight: '8px'
3455
4442
  },
3456
4443
  children: [
3457
- 'custom' === type ? span({
4444
+ 'custom' === type ? renderer_span({
3458
4445
  style: {
3459
4446
  fontSize: '9px',
3460
4447
  padding: '1px 4px',
@@ -3465,7 +4452,7 @@ var __webpack_exports__ = {};
3465
4452
  },
3466
4453
  text: 'CUSTOM'
3467
4454
  }) : null,
3468
- span({
4455
+ renderer_span({
3469
4456
  style: {
3470
4457
  color: 'var(--c15t-text)',
3471
4458
  overflow: 'hidden',
@@ -3480,27 +4467,24 @@ var __webpack_exports__ = {};
3480
4467
  createBadge({
3481
4468
  text: consent ? '✓' : '✕',
3482
4469
  variant: consent ? 'success' : 'error'
4470
+ }),
4471
+ createToggle({
4472
+ checked: consent,
4473
+ onChange,
4474
+ ariaLabel: `Toggle vendor ${id}`
3483
4475
  })
3484
4476
  ]
3485
4477
  });
3486
4478
  }
3487
4479
  function truncateText(text, maxLength) {
3488
4480
  if (text.length <= maxLength) return text;
3489
- return text.slice(0, maxLength - 3) + '...';
4481
+ return `${text.slice(0, maxLength - 3)}...`;
3490
4482
  }
3491
- function location_renderLocationPanel(container, options) {
3492
- const { getState, onSetOverrides, onClearOverrides } = options;
4483
+ function renderLocationPanel(container, options) {
4484
+ const { getState, onApplyOverrides, onClearOverrides } = options;
3493
4485
  clearElement(container);
3494
4486
  const state = getState();
3495
- if (!state) return void container.appendChild(renderer_div({
3496
- style: {
3497
- padding: '24px',
3498
- textAlign: 'center',
3499
- color: 'var(--c15t-text-muted)',
3500
- fontSize: 'var(--c15t-devtools-font-size-sm)'
3501
- },
3502
- text: 'Store not connected'
3503
- }));
4487
+ if (!state) return void container.appendChild(createDisconnectedState());
3504
4488
  const locationInfo = state.locationInfo;
3505
4489
  const overrides = state.overrides;
3506
4490
  const translationConfig = state.translationConfig;
@@ -3510,145 +4494,230 @@ var __webpack_exports__ = {};
3510
4494
  createCompactInfoCard('Jurisdiction', locationInfo?.jurisdiction || '—'),
3511
4495
  createCompactInfoCard('Language', translationConfig?.defaultLanguage || '—')
3512
4496
  ];
4497
+ gridItems.push(createCompactInfoCard('GPC', getEffectiveGpcLabel(overrides?.gpc)));
3513
4498
  if (state.model) gridItems.push(createCompactInfoCard('Model', getModelLabel(state.model)));
3514
4499
  const locationGrid = createGrid({
3515
- columns: 2,
4500
+ columns: 3,
3516
4501
  children: gridItems
3517
4502
  });
3518
4503
  container.appendChild(locationGrid);
4504
+ const initialDraft = getDraftFromOverrides(overrides);
4505
+ let appliedOverrides = normalizeOverrideDraft(initialDraft);
4506
+ let isSubmitting = false;
4507
+ const countryField = createOverrideSelect({
4508
+ label: 'Country',
4509
+ selectOptions: COUNTRY_OPTIONS,
4510
+ value: initialDraft.country
4511
+ });
4512
+ const regionField = createOverrideInput({
4513
+ label: 'Region',
4514
+ placeholder: 'e.g., CA, NY, BE',
4515
+ value: initialDraft.region
4516
+ });
4517
+ const languageField = createOverrideInput({
4518
+ label: 'Language',
4519
+ placeholder: 'e.g., de, fr, en-US',
4520
+ value: initialDraft.language
4521
+ });
4522
+ const gpcField = createOverrideSelect({
4523
+ label: 'GPC',
4524
+ selectOptions: GPC_OPTIONS,
4525
+ value: initialDraft.gpc
4526
+ });
4527
+ const formStatus = renderer_span({
4528
+ className: styles_components_module.overrideStatus,
4529
+ text: 'In sync'
4530
+ });
4531
+ const applyButton = createButton({
4532
+ text: 'Apply',
4533
+ variant: 'primary',
4534
+ small: true,
4535
+ disabled: true,
4536
+ onClick: ()=>{
4537
+ applyDraft();
4538
+ }
4539
+ });
4540
+ const revertButton = createButton({
4541
+ text: 'Revert',
4542
+ small: true,
4543
+ disabled: true,
4544
+ onClick: ()=>{
4545
+ setDraftValues(getDraftFromOverrides(appliedOverrides));
4546
+ updateFormState();
4547
+ }
4548
+ });
4549
+ const clearButton = createButton({
4550
+ text: 'Clear',
4551
+ small: true,
4552
+ onClick: ()=>{
4553
+ clearDraftAndOverrides();
4554
+ }
4555
+ });
4556
+ const overrideFieldsGrid = renderer_div({
4557
+ style: {
4558
+ display: 'grid',
4559
+ gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
4560
+ gap: '8px 10px'
4561
+ },
4562
+ children: [
4563
+ countryField.element,
4564
+ regionField.element,
4565
+ languageField.element,
4566
+ gpcField.element
4567
+ ]
4568
+ });
3519
4569
  const overrideSection = createSection({
3520
4570
  title: 'Override Settings',
3521
- actions: [
3522
- createButton({
3523
- text: 'Clear',
3524
- small: true,
3525
- onClick: onClearOverrides
3526
- })
3527
- ],
3528
4571
  children: [
3529
- createOverrideSelect({
3530
- label: 'Country',
3531
- selectOptions: COUNTRY_OPTIONS,
3532
- value: overrides?.country || '',
3533
- onChange: (value)=>onSetOverrides({
3534
- country: value || void 0
3535
- })
3536
- }),
3537
- createOverrideInput({
3538
- label: 'Region',
3539
- placeholder: 'e.g., CA, NY, BE',
3540
- value: overrides?.region || '',
3541
- onChange: (value)=>onSetOverrides({
3542
- region: value || void 0
3543
- })
4572
+ overrideFieldsGrid,
4573
+ renderer_span({
4574
+ className: styles_components_module.overrideHint,
4575
+ text: 'GPC override only affects opt-out or unregulated jurisdictions.'
3544
4576
  }),
3545
- createOverrideInput({
3546
- label: 'Language',
3547
- placeholder: 'e.g., de, fr, en',
3548
- value: overrides?.language || '',
3549
- onChange: (value)=>onSetOverrides({
3550
- language: value || void 0
3551
- })
4577
+ renderer_div({
4578
+ className: styles_components_module.overrideActions,
4579
+ children: [
4580
+ renderer_div({
4581
+ className: styles_components_module.overrideActionButtons,
4582
+ children: [
4583
+ revertButton,
4584
+ applyButton,
4585
+ clearButton
4586
+ ]
4587
+ }),
4588
+ formStatus
4589
+ ]
3552
4590
  })
3553
4591
  ]
3554
4592
  });
3555
4593
  container.appendChild(overrideSection);
3556
- const hasOverrides = overrides && (overrides.country || overrides.region || overrides.language);
3557
- if (hasOverrides) {
3558
- const overrideBanner = renderer_div({
3559
- style: {
3560
- padding: '8px 16px',
3561
- backgroundColor: 'var(--c15t-devtools-badge-info-bg)',
3562
- color: 'var(--c15t-devtools-badge-info)',
3563
- fontSize: 'var(--c15t-devtools-font-size-xs)',
3564
- borderTop: '1px solid var(--c15t-devtools-border)'
3565
- },
3566
- text: 'Overrides are active. This may affect consent behavior.'
4594
+ countryField.control.addEventListener('change', updateFormState);
4595
+ regionField.control.addEventListener('input', updateFormState);
4596
+ languageField.control.addEventListener('input', updateFormState);
4597
+ gpcField.control.addEventListener('change', updateFormState);
4598
+ updateFormState();
4599
+ async function applyDraft() {
4600
+ if (isSubmitting) return;
4601
+ const draftOverrides = getDraftOverrides();
4602
+ if (overridesEqual(draftOverrides, appliedOverrides)) return;
4603
+ isSubmitting = true;
4604
+ updateFormState();
4605
+ try {
4606
+ await onApplyOverrides(draftOverrides);
4607
+ appliedOverrides = draftOverrides;
4608
+ } finally{
4609
+ isSubmitting = false;
4610
+ updateFormState();
4611
+ }
4612
+ }
4613
+ async function clearDraftAndOverrides() {
4614
+ if (isSubmitting) return;
4615
+ isSubmitting = true;
4616
+ updateFormState();
4617
+ try {
4618
+ await onClearOverrides();
4619
+ appliedOverrides = {};
4620
+ setDraftValues(getDraftFromOverrides(void 0));
4621
+ } finally{
4622
+ isSubmitting = false;
4623
+ updateFormState();
4624
+ }
4625
+ }
4626
+ function getDraftOverrides() {
4627
+ return normalizeOverrideDraft({
4628
+ country: countryField.control.value,
4629
+ region: regionField.control.value,
4630
+ language: languageField.control.value,
4631
+ gpc: gpcField.control.value
3567
4632
  });
3568
- container.appendChild(overrideBanner);
4633
+ }
4634
+ function setDraftValues(draft) {
4635
+ countryField.control.value = draft.country;
4636
+ regionField.control.value = draft.region;
4637
+ languageField.control.value = draft.language;
4638
+ gpcField.control.value = draft.gpc;
4639
+ }
4640
+ function updateFormState() {
4641
+ const draftOverrides = getDraftOverrides();
4642
+ const hasDraftChanges = !overridesEqual(draftOverrides, appliedOverrides);
4643
+ applyButton.disabled = !hasDraftChanges || isSubmitting;
4644
+ revertButton.disabled = !hasDraftChanges || isSubmitting;
4645
+ clearButton.disabled = isSubmitting;
4646
+ formStatus.textContent = isSubmitting ? 'Applying...' : hasDraftChanges ? 'Unsaved changes' : hasOverridesValue(appliedOverrides) ? 'Overrides active' : 'No overrides';
4647
+ if (styles_components_module.overrideStatusDirty) formStatus.classList.toggle(styles_components_module.overrideStatusDirty, !isSubmitting && hasDraftChanges);
3569
4648
  }
3570
4649
  }
3571
4650
  function createOverrideInput(options) {
3572
- const { label, placeholder, value, onChange } = options;
3573
- let debounceTimer = null;
4651
+ const { label, placeholder, value } = options;
3574
4652
  const inputField = input({
3575
4653
  className: `${styles_components_module.input ?? ''} ${styles_components_module.inputSmall ?? ''}`.trim(),
3576
4654
  placeholder,
3577
- value,
3578
- onInput: (e)=>{
3579
- const target = e.target;
3580
- if (debounceTimer) clearTimeout(debounceTimer);
3581
- debounceTimer = setTimeout(()=>{
3582
- onChange(target.value);
3583
- }, 500);
3584
- }
3585
- });
3586
- return renderer_div({
3587
- style: {
3588
- display: 'flex',
3589
- alignItems: 'center',
3590
- justifyContent: 'space-between',
3591
- gap: '8px',
3592
- marginBottom: '8px'
3593
- },
3594
- children: [
3595
- renderer_div({
3596
- style: {
3597
- fontSize: 'var(--c15t-devtools-font-size-xs)',
3598
- color: 'var(--c15t-devtools-text-muted)',
3599
- minWidth: '60px'
3600
- },
3601
- text: label
3602
- }),
3603
- renderer_div({
3604
- style: {
3605
- flex: '1'
3606
- },
3607
- children: [
3608
- inputField
3609
- ]
3610
- })
3611
- ]
4655
+ value
3612
4656
  });
4657
+ return {
4658
+ element: renderer_div({
4659
+ className: styles_components_module.overrideField,
4660
+ children: [
4661
+ renderer_span({
4662
+ className: styles_components_module.overrideLabel,
4663
+ text: label
4664
+ }),
4665
+ inputField
4666
+ ]
4667
+ }),
4668
+ control: inputField
4669
+ };
3613
4670
  }
3614
4671
  function createOverrideSelect(options) {
3615
- const { label, selectOptions, value, onChange } = options;
4672
+ const { label, selectOptions, value } = options;
3616
4673
  const selectField = renderer_select({
3617
4674
  className: `${styles_components_module.input ?? ''} ${styles_components_module.inputSmall ?? ''}`.trim(),
3618
4675
  options: selectOptions,
3619
- selectedValue: value,
3620
- onChange: (e)=>{
3621
- const target = e.target;
3622
- onChange(target.value);
3623
- }
3624
- });
3625
- return renderer_div({
3626
- style: {
3627
- display: 'flex',
3628
- alignItems: 'center',
3629
- justifyContent: 'space-between',
3630
- gap: '8px',
3631
- marginBottom: '8px'
3632
- },
3633
- children: [
3634
- renderer_div({
3635
- style: {
3636
- fontSize: 'var(--c15t-devtools-font-size-xs)',
3637
- color: 'var(--c15t-devtools-text-muted)',
3638
- minWidth: '60px'
3639
- },
3640
- text: label
3641
- }),
3642
- renderer_div({
3643
- style: {
3644
- flex: '1'
3645
- },
3646
- children: [
3647
- selectField
3648
- ]
3649
- })
3650
- ]
4676
+ selectedValue: value
3651
4677
  });
4678
+ return {
4679
+ element: renderer_div({
4680
+ className: styles_components_module.overrideField,
4681
+ children: [
4682
+ renderer_span({
4683
+ className: styles_components_module.overrideLabel,
4684
+ text: label
4685
+ }),
4686
+ selectField
4687
+ ]
4688
+ }),
4689
+ control: selectField
4690
+ };
4691
+ }
4692
+ function getDraftFromOverrides(overrides) {
4693
+ return {
4694
+ country: overrides?.country ?? '',
4695
+ region: overrides?.region ?? '',
4696
+ language: overrides?.language ?? '',
4697
+ gpc: overrides?.gpc === true ? 'true' : overrides?.gpc === false ? 'false' : ''
4698
+ };
4699
+ }
4700
+ function normalizeOverrideDraft(draft) {
4701
+ return {
4702
+ country: normalizeAlphaCode(draft.country),
4703
+ region: normalizeAlphaCode(draft.region),
4704
+ language: normalizeLanguageCode(draft.language),
4705
+ gpc: 'true' === draft.gpc ? true : 'false' === draft.gpc ? false : void 0
4706
+ };
4707
+ }
4708
+ function normalizeAlphaCode(value) {
4709
+ const normalized = value.trim().toUpperCase();
4710
+ return normalized || void 0;
4711
+ }
4712
+ function normalizeLanguageCode(value) {
4713
+ const normalized = value.trim();
4714
+ return normalized || void 0;
4715
+ }
4716
+ function overridesEqual(a, b) {
4717
+ return a.country === b.country && a.region === b.region && a.language === b.language && a.gpc === b.gpc;
4718
+ }
4719
+ function hasOverridesValue(overrides) {
4720
+ return Boolean(overrides.country || overrides.region || overrides.language || void 0 !== overrides.gpc);
3652
4721
  }
3653
4722
  const COUNTRY_OPTIONS = [
3654
4723
  {
@@ -3772,6 +4841,32 @@ var __webpack_exports__ = {};
3772
4841
  label: 'ZA - South Africa'
3773
4842
  }
3774
4843
  ];
4844
+ const GPC_OPTIONS = [
4845
+ {
4846
+ value: '',
4847
+ label: '-- Browser Default --'
4848
+ },
4849
+ {
4850
+ value: 'true',
4851
+ label: 'Force On (Simulated)'
4852
+ },
4853
+ {
4854
+ value: 'false',
4855
+ label: 'Force Off (Simulated)'
4856
+ }
4857
+ ];
4858
+ function getEffectiveGpcLabel(gpcOverride) {
4859
+ if (true === gpcOverride) return 'On (Override)';
4860
+ if (false === gpcOverride) return 'Off (Override)';
4861
+ if ('undefined' == typeof window || 'undefined' == typeof navigator) return 'Unknown';
4862
+ try {
4863
+ const nav = navigator;
4864
+ const value = nav.globalPrivacyControl;
4865
+ return true === value || '1' === value ? 'Active' : 'Inactive';
4866
+ } catch {
4867
+ return 'Unknown';
4868
+ }
4869
+ }
3775
4870
  function getModelLabel(model) {
3776
4871
  switch(model){
3777
4872
  case 'opt-in':
@@ -3788,19 +4883,21 @@ var __webpack_exports__ = {};
3788
4883
  return renderer_div({
3789
4884
  className: styles_components_module.gridCard ?? '',
3790
4885
  style: {
4886
+ padding: '6px 8px',
4887
+ minHeight: 'auto',
3791
4888
  flexDirection: 'column',
3792
4889
  alignItems: 'flex-start',
3793
- gap: '2px'
4890
+ gap: '1px'
3794
4891
  },
3795
4892
  children: [
3796
- span({
4893
+ renderer_span({
3797
4894
  style: {
3798
4895
  fontSize: 'var(--c15t-devtools-font-size-xs)',
3799
4896
  color: 'var(--c15t-text-muted)'
3800
4897
  },
3801
4898
  text: label
3802
4899
  }),
3803
- span({
4900
+ renderer_span({
3804
4901
  style: {
3805
4902
  fontSize: 'var(--c15t-font-size-sm)',
3806
4903
  fontWeight: '500',
@@ -3815,34 +4912,38 @@ var __webpack_exports__ = {};
3815
4912
  function scanDOM(state) {
3816
4913
  const results = [];
3817
4914
  const configuredScripts = state.scripts || [];
3818
- const managedDomains = new Map();
4915
+ const managedResources = [];
3819
4916
  for (const script of configuredScripts)if (script.src) try {
3820
4917
  const url = new URL(script.src, window.location.origin);
3821
- if (url.hostname !== window.location.hostname) managedDomains.set(url.hostname, script.id);
4918
+ if (url.hostname !== window.location.hostname) managedResources.push({
4919
+ scriptId: script.id,
4920
+ domain: url.hostname,
4921
+ pathPrefix: normalizePathname(url.pathname)
4922
+ });
3822
4923
  } catch {}
3823
4924
  const scriptElements = document.querySelectorAll("script[src]");
3824
4925
  for (const el of scriptElements){
3825
4926
  const src = el.getAttribute('src');
3826
4927
  if (!src) continue;
3827
- const resource = checkResource(src, "script", managedDomains);
4928
+ const resource = checkResource(src, "script", managedResources);
3828
4929
  if (resource) results.push(resource);
3829
4930
  }
3830
4931
  const iframeElements = document.querySelectorAll('iframe[src]');
3831
4932
  for (const el of iframeElements){
3832
4933
  const src = el.getAttribute('src');
3833
4934
  if (!src) continue;
3834
- const resource = checkResource(src, 'iframe', managedDomains);
4935
+ const resource = checkResource(src, 'iframe', managedResources);
3835
4936
  if (resource) results.push(resource);
3836
4937
  }
3837
4938
  return results;
3838
4939
  }
3839
- function checkResource(src, type, managedDomains) {
4940
+ function checkResource(src, type, managedResources) {
3840
4941
  try {
3841
4942
  const url = new URL(src, window.location.origin);
3842
4943
  const domain = url.hostname;
3843
4944
  if (domain === window.location.hostname) return null;
3844
4945
  if ('data:' === url.protocol || 'blob:' === url.protocol) return null;
3845
- const managedBy = managedDomains.get(domain);
4946
+ const managedBy = findManagedScriptId(url, managedResources);
3846
4947
  const isManaged = Boolean(managedBy);
3847
4948
  return {
3848
4949
  type,
@@ -3854,6 +4955,21 @@ var __webpack_exports__ = {};
3854
4955
  } catch {}
3855
4956
  return null;
3856
4957
  }
4958
+ function findManagedScriptId(url, managedResources) {
4959
+ const domain = url.hostname;
4960
+ const path = normalizePathname(url.pathname);
4961
+ let bestMatch = null;
4962
+ for (const matcher of managedResources)if (matcher.domain === domain) {
4963
+ if ('/' === matcher.pathPrefix || path.startsWith(matcher.pathPrefix)) {
4964
+ if (!bestMatch || matcher.pathPrefix.length > bestMatch.pathPrefix.length) bestMatch = matcher;
4965
+ }
4966
+ }
4967
+ return bestMatch?.scriptId;
4968
+ }
4969
+ function normalizePathname(pathname) {
4970
+ const trimmed = pathname.trim();
4971
+ return trimmed.length > 0 ? trimmed : '/';
4972
+ }
3857
4973
  function createDomScannerSection(state) {
3858
4974
  let resultsContainer = null;
3859
4975
  let lastScanResults = [];
@@ -3957,21 +5073,21 @@ var __webpack_exports__ = {};
3957
5073
  borderBottom: '1px solid var(--c15t-border)'
3958
5074
  },
3959
5075
  children: [
3960
- span({
5076
+ renderer_span({
3961
5077
  style: {
3962
5078
  color: iconColor,
3963
5079
  flexShrink: '0'
3964
5080
  },
3965
5081
  text: icon
3966
5082
  }),
3967
- span({
5083
+ renderer_span({
3968
5084
  style: {
3969
5085
  color: 'var(--c15t-text-muted)',
3970
5086
  flexShrink: '0'
3971
5087
  },
3972
5088
  text: `${resource.type}:`
3973
5089
  }),
3974
- span({
5090
+ renderer_span({
3975
5091
  style: {
3976
5092
  fontWeight: '500',
3977
5093
  color: 'var(--c15t-text)',
@@ -4017,27 +5133,42 @@ var __webpack_exports__ = {};
4017
5133
  <polyline points="16 18 22 12 16 6"></polyline>
4018
5134
  <polyline points="8 6 2 12 8 18"></polyline>
4019
5135
  </svg>`;
4020
- function scripts_renderScriptsPanel(container, options) {
4021
- const { getState } = options;
5136
+ const scriptsSearchByContainer = new WeakMap();
5137
+ function renderScriptsPanel(container, options) {
5138
+ const { getState, getEvents } = options;
4022
5139
  clearElement(container);
4023
5140
  const state = getState();
4024
- if (!state) return void container.appendChild(renderer_div({
4025
- style: {
4026
- padding: '24px',
4027
- textAlign: 'center',
4028
- color: 'var(--c15t-text-muted)',
4029
- fontSize: 'var(--c15t-devtools-font-size-sm)'
4030
- },
4031
- text: 'Store not connected'
4032
- }));
5141
+ if (!state) return void container.appendChild(createDisconnectedState());
4033
5142
  const scripts = state.scripts || [];
4034
5143
  const loadedScripts = state.loadedScripts || {};
4035
5144
  const networkBlocker = state.networkBlocker;
4036
- if (0 === scripts.length) {
4037
- const scriptsSection = createSection({
4038
- title: 'Configured Scripts',
4039
- children: [
4040
- createEmptyState({
5145
+ const events = getEvents?.() ?? [];
5146
+ const searchQuery = scriptsSearchByContainer.get(container) ?? '';
5147
+ const filteredScripts = scripts.filter((script)=>{
5148
+ if (!searchQuery) return true;
5149
+ const category = 'string' == typeof script.category ? script.category : JSON.stringify(script.category);
5150
+ return `${script.id} ${category}`.toLowerCase().includes(searchQuery);
5151
+ });
5152
+ if (scripts.length > 4) container.appendChild(createSection({
5153
+ title: 'Filter',
5154
+ children: [
5155
+ createInput({
5156
+ value: searchQuery,
5157
+ placeholder: "Filter scripts…",
5158
+ ariaLabel: "Filter scripts",
5159
+ small: true,
5160
+ onInput: (value)=>{
5161
+ scriptsSearchByContainer.set(container, value.trim().toLowerCase());
5162
+ renderScriptsPanel(container, options);
5163
+ }
5164
+ })
5165
+ ]
5166
+ }));
5167
+ if (0 === scripts.length) {
5168
+ const scriptsSection = createSection({
5169
+ title: 'Configured Scripts',
5170
+ children: [
5171
+ createEmptyState({
4041
5172
  icon: CODE_ICON,
4042
5173
  text: "No scripts configured"
4043
5174
  })
@@ -4049,10 +5180,19 @@ var __webpack_exports__ = {};
4049
5180
  style: {
4050
5181
  display: 'flex',
4051
5182
  flexDirection: 'column',
4052
- gap: '4px'
5183
+ borderTop: '1px solid var(--c15t-border)',
5184
+ borderBottom: '1px solid var(--c15t-border)'
4053
5185
  }
4054
5186
  });
4055
- for (const script of scripts){
5187
+ if (0 === filteredScripts.length) scriptsList.appendChild(renderer_div({
5188
+ style: {
5189
+ padding: '10px 0',
5190
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
5191
+ color: 'var(--c15t-text-muted)'
5192
+ },
5193
+ text: "No matching scripts"
5194
+ }));
5195
+ for (const script of filteredScripts){
4056
5196
  const scriptId = script.id;
4057
5197
  const isLoaded = true === loadedScripts[scriptId];
4058
5198
  const category = script.category;
@@ -4076,17 +5216,64 @@ var __webpack_exports__ = {};
4076
5216
  text: status.charAt(0).toUpperCase() + status.slice(1),
4077
5217
  variant: statusVariant
4078
5218
  });
4079
- const item = createListItem({
4080
- title: scriptId,
4081
- description: `Category: ${categoryDisplay}`,
4082
- actions: [
4083
- badge
5219
+ const row = renderer_div({
5220
+ style: {
5221
+ display: 'flex',
5222
+ alignItems: 'center',
5223
+ justifyContent: 'space-between',
5224
+ gap: '8px',
5225
+ padding: '8px 0',
5226
+ borderBottom: '1px solid var(--c15t-border)'
5227
+ },
5228
+ children: [
5229
+ renderer_div({
5230
+ style: {
5231
+ display: 'flex',
5232
+ flexDirection: 'column',
5233
+ gap: '2px',
5234
+ minWidth: '0',
5235
+ flex: '1'
5236
+ },
5237
+ children: [
5238
+ renderer_div({
5239
+ style: {
5240
+ fontSize: 'var(--c15t-font-size-sm)',
5241
+ fontWeight: '500',
5242
+ color: 'var(--c15t-text)',
5243
+ overflow: 'hidden',
5244
+ textOverflow: 'ellipsis',
5245
+ whiteSpace: 'nowrap'
5246
+ },
5247
+ text: scriptId
5248
+ }),
5249
+ renderer_div({
5250
+ style: {
5251
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
5252
+ color: 'var(--c15t-text-muted)',
5253
+ overflow: 'hidden',
5254
+ textOverflow: 'ellipsis',
5255
+ whiteSpace: 'nowrap'
5256
+ },
5257
+ text: `Category: ${categoryDisplay}`
5258
+ })
5259
+ ]
5260
+ }),
5261
+ renderer_div({
5262
+ style: {
5263
+ flexShrink: '0'
5264
+ },
5265
+ children: [
5266
+ badge
5267
+ ]
5268
+ })
4084
5269
  ]
4085
5270
  });
4086
- scriptsList.appendChild(item);
5271
+ scriptsList.appendChild(row);
4087
5272
  }
5273
+ const lastRow = scriptsList.lastElementChild;
5274
+ if (lastRow) lastRow.style.borderBottom = 'none';
4088
5275
  const scriptsSection = createSection({
4089
- title: `Configured Scripts (${scripts.length})`,
5276
+ title: `Configured Scripts (${filteredScripts.length}/${scripts.length})`,
4090
5277
  children: [
4091
5278
  scriptsList
4092
5279
  ]
@@ -4115,6 +5302,20 @@ var __webpack_exports__ = {};
4115
5302
  ]
4116
5303
  });
4117
5304
  container.appendChild(networkSection);
5305
+ const blockedRequestEvents = events.filter((event)=>'network' === event.type);
5306
+ const networkEventsSection = createSection({
5307
+ title: `Blocked Requests (${blockedRequestEvents.length})`,
5308
+ children: 0 === blockedRequestEvents.length ? [
5309
+ renderer_div({
5310
+ style: {
5311
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
5312
+ color: 'var(--c15t-devtools-text-muted)'
5313
+ },
5314
+ text: 'No blocked network requests recorded in this session'
5315
+ })
5316
+ ] : createBlockedRequestContent(blockedRequestEvents)
5317
+ });
5318
+ container.appendChild(networkEventsSection);
4118
5319
  const loadedCount = Object.values(loadedScripts).filter(Boolean).length;
4119
5320
  const totalCount = scripts.length;
4120
5321
  const summarySection = createSection({
@@ -4140,12 +5341,80 @@ var __webpack_exports__ = {};
4140
5341
  }
4141
5342
  function checkScriptConsent(state, category) {
4142
5343
  if (!category) return true;
5344
+ if ('function' == typeof state.has) try {
5345
+ return state.has(category);
5346
+ } catch {}
4143
5347
  if ('string' == typeof category) {
4144
5348
  const consents = state.consents || {};
4145
5349
  return true === consents[category];
4146
5350
  }
4147
5351
  return false;
4148
5352
  }
5353
+ function createBlockedRequestContent(events) {
5354
+ const stats = new Map();
5355
+ for (const event of events){
5356
+ const ruleId = getEventRuleId(event) ?? 'unknown';
5357
+ stats.set(ruleId, (stats.get(ruleId) ?? 0) + 1);
5358
+ }
5359
+ const statsList = renderer_div({
5360
+ style: {
5361
+ display: 'flex',
5362
+ flexDirection: 'column',
5363
+ gap: '4px',
5364
+ marginBottom: '8px'
5365
+ },
5366
+ children: [
5367
+ ...stats.entries()
5368
+ ].sort((a, b)=>b[1] - a[1]).map(([ruleId, count])=>createInfoRow({
5369
+ label: 'unknown' === ruleId ? 'Unknown Rule' : `Rule: ${ruleId}`,
5370
+ value: `${count}`
5371
+ }))
5372
+ });
5373
+ const latestEvents = events.slice(0, 5);
5374
+ const latestList = renderer_div({
5375
+ style: {
5376
+ display: 'flex',
5377
+ flexDirection: 'column',
5378
+ gap: '4px'
5379
+ },
5380
+ children: latestEvents.map((event)=>createInfoRow({
5381
+ label: `${formatEventTime(event.timestamp)} ${getEventMethod(event)}`,
5382
+ value: scripts_truncateText(getEventUrl(event), 38)
5383
+ }))
5384
+ });
5385
+ return [
5386
+ statsList,
5387
+ latestList
5388
+ ];
5389
+ }
5390
+ function getEventRuleId(event) {
5391
+ const data = event.data;
5392
+ const rule = data?.rule;
5393
+ const ruleId = rule?.id ?? data?.ruleId;
5394
+ return 'string' == typeof ruleId || 'number' == typeof ruleId ? String(ruleId) : void 0;
5395
+ }
5396
+ function getEventMethod(event) {
5397
+ const data = event.data;
5398
+ const method = data?.method;
5399
+ return 'string' == typeof method ? method.toUpperCase() : 'REQ';
5400
+ }
5401
+ function getEventUrl(event) {
5402
+ const data = event.data;
5403
+ const url = data?.url;
5404
+ return 'string' == typeof url ? url : event.message;
5405
+ }
5406
+ function formatEventTime(timestamp) {
5407
+ return new Date(timestamp).toLocaleTimeString('en-US', {
5408
+ hour12: false,
5409
+ hour: '2-digit',
5410
+ minute: '2-digit',
5411
+ second: '2-digit'
5412
+ });
5413
+ }
5414
+ function scripts_truncateText(text, maxLength) {
5415
+ if (text.length <= maxLength) return text;
5416
+ return `${text.slice(0, maxLength - 3)}...`;
5417
+ }
4149
5418
  const STORAGE_KEYS = {
4150
5419
  C15T: 'c15t',
4151
5420
  PENDING_SYNC: 'c15t:pending-consent-sync',
@@ -4171,7 +5440,7 @@ var __webpack_exports__ = {};
4171
5440
  localStorage.removeItem(STORAGE_KEYS.EUCONSENT);
4172
5441
  } catch {}
4173
5442
  }
4174
- async function reset_consents_resetAllConsents(store, stateManager) {
5443
+ async function resetAllConsents(store, stateManager) {
4175
5444
  const storeState = store.getState();
4176
5445
  storeState.resetConsents();
4177
5446
  clearAllCookies();
@@ -4182,7 +5451,222 @@ var __webpack_exports__ = {};
4182
5451
  message: 'All consents reset (storage cleared)'
4183
5452
  });
4184
5453
  }
5454
+ function panel_renderer_createPanelRenderer(config) {
5455
+ const { storeConnector, stateManager, enableEventLogging = true, onPersistOverrides, onClearPersistedOverrides, onCopyState, onExportDebugBundle } = config;
5456
+ const getStoreState = ()=>storeConnector.getState();
5457
+ const logEvent = (type, message, data)=>{
5458
+ if (enableEventLogging) stateManager.addEvent({
5459
+ type,
5460
+ message,
5461
+ data
5462
+ });
5463
+ };
5464
+ const resetConsents = async ()=>{
5465
+ const store = storeConnector.getStore();
5466
+ if (store) await resetAllConsents(store, enableEventLogging ? stateManager : void 0);
5467
+ };
5468
+ const renderPanel = (container, tab)=>{
5469
+ switch(tab){
5470
+ case 'consents':
5471
+ renderConsentsPanel(container, {
5472
+ getState: getStoreState,
5473
+ onConsentChange: (name, value)=>{
5474
+ const store = storeConnector.getStore();
5475
+ if (store) {
5476
+ const consentName = String(name);
5477
+ store.getState().setSelectedConsent(consentName, value);
5478
+ logEvent('info', `${consentName} toggled to ${value} (not saved)`, {
5479
+ name: consentName,
5480
+ value
5481
+ });
5482
+ }
5483
+ },
5484
+ onSave: ()=>{
5485
+ const store = storeConnector.getStore();
5486
+ if (store) {
5487
+ store.getState().saveConsents('custom');
5488
+ logEvent('consent_save', 'Saved consent preferences');
5489
+ }
5490
+ },
5491
+ onAcceptAll: ()=>{
5492
+ const store = storeConnector.getStore();
5493
+ if (store) {
5494
+ store.getState().saveConsents('all');
5495
+ logEvent('consent_save', 'Accepted all consents');
5496
+ }
5497
+ },
5498
+ onRejectAll: ()=>{
5499
+ const store = storeConnector.getStore();
5500
+ if (store) {
5501
+ store.getState().saveConsents('necessary');
5502
+ logEvent('consent_save', 'Rejected all optional consents');
5503
+ }
5504
+ },
5505
+ onReset: resetConsents
5506
+ });
5507
+ break;
5508
+ case 'location':
5509
+ renderLocationPanel(container, {
5510
+ getState: getStoreState,
5511
+ onApplyOverrides: async (overrides)=>{
5512
+ const store = storeConnector.getStore();
5513
+ if (store) {
5514
+ await store.getState().setOverrides({
5515
+ country: overrides.country,
5516
+ region: overrides.region,
5517
+ language: overrides.language,
5518
+ gpc: overrides.gpc
5519
+ });
5520
+ logEvent('info', 'Overrides updated', {
5521
+ country: overrides.country,
5522
+ region: overrides.region,
5523
+ language: overrides.language,
5524
+ gpc: overrides.gpc
5525
+ });
5526
+ onPersistOverrides?.({
5527
+ country: overrides.country,
5528
+ region: overrides.region,
5529
+ language: overrides.language,
5530
+ gpc: overrides.gpc
5531
+ });
5532
+ }
5533
+ },
5534
+ onClearOverrides: async ()=>{
5535
+ const store = storeConnector.getStore();
5536
+ if (store) {
5537
+ await store.getState().setOverrides({
5538
+ country: void 0,
5539
+ region: void 0,
5540
+ language: void 0,
5541
+ gpc: void 0
5542
+ });
5543
+ logEvent('info', 'Overrides cleared');
5544
+ onClearPersistedOverrides?.();
5545
+ }
5546
+ }
5547
+ });
5548
+ break;
5549
+ case "scripts":
5550
+ renderScriptsPanel(container, {
5551
+ getState: getStoreState,
5552
+ getEvents: ()=>stateManager.getState().eventLog
5553
+ });
5554
+ break;
5555
+ case 'iab':
5556
+ renderIabPanel(container, {
5557
+ getState: getStoreState,
5558
+ onSetPurposeConsent: (purposeId, value)=>{
5559
+ const iab = storeConnector.getStore()?.getState().iab;
5560
+ if (!iab) return;
5561
+ iab.setPurposeConsent(purposeId, value);
5562
+ logEvent('iab', `IAB purpose ${purposeId} set to ${value}`);
5563
+ },
5564
+ onSetVendorConsent: (vendorId, value)=>{
5565
+ const iab = storeConnector.getStore()?.getState().iab;
5566
+ if (!iab) return;
5567
+ iab.setVendorConsent(vendorId, value);
5568
+ logEvent('iab', `IAB vendor ${vendorId} set to ${value}`);
5569
+ },
5570
+ onSetSpecialFeatureOptIn: (featureId, value)=>{
5571
+ const iab = storeConnector.getStore()?.getState().iab;
5572
+ if (!iab) return;
5573
+ iab.setSpecialFeatureOptIn(featureId, value);
5574
+ logEvent('iab', `IAB feature ${featureId} set to ${value}`);
5575
+ },
5576
+ onAcceptAll: ()=>{
5577
+ const iab = storeConnector.getStore()?.getState().iab;
5578
+ if (!iab) return;
5579
+ iab.acceptAll();
5580
+ logEvent('iab', 'IAB accept all selected');
5581
+ },
5582
+ onRejectAll: ()=>{
5583
+ const iab = storeConnector.getStore()?.getState().iab;
5584
+ if (!iab) return;
5585
+ iab.rejectAll();
5586
+ logEvent('iab', 'IAB reject all selected');
5587
+ },
5588
+ onSave: ()=>{
5589
+ const iab = storeConnector.getStore()?.getState().iab;
5590
+ if (!iab) return;
5591
+ iab.save().then(()=>logEvent('iab', 'IAB preferences saved')).catch((error)=>{
5592
+ logEvent('error', `Failed to save IAB preferences: ${String(error)}`);
5593
+ });
5594
+ },
5595
+ onReset: resetConsents
5596
+ });
5597
+ break;
5598
+ case 'events':
5599
+ renderEventsPanel(container, {
5600
+ getEvents: ()=>stateManager.getState().eventLog,
5601
+ onClear: ()=>{
5602
+ stateManager.clearEventLog();
5603
+ logEvent('info', 'Event log cleared');
5604
+ }
5605
+ });
5606
+ break;
5607
+ case 'actions':
5608
+ renderActionsPanel(container, {
5609
+ getState: getStoreState,
5610
+ onResetConsents: resetConsents,
5611
+ onRefetchBanner: async ()=>{
5612
+ const store = storeConnector.getStore();
5613
+ if (store) {
5614
+ await store.getState().initConsentManager();
5615
+ logEvent('info', 'Banner data refetched');
5616
+ }
5617
+ },
5618
+ onShowBanner: ()=>{
5619
+ const store = storeConnector.getStore();
5620
+ if (store) {
5621
+ store.getState().setActiveUI('banner', {
5622
+ force: true
5623
+ });
5624
+ logEvent('info', 'Banner shown');
5625
+ }
5626
+ },
5627
+ onOpenPreferences: ()=>{
5628
+ const store = storeConnector.getStore();
5629
+ if (store) {
5630
+ store.getState().setActiveUI('dialog');
5631
+ logEvent('info', 'Preferences dialog opened');
5632
+ }
5633
+ },
5634
+ onCopyState: ()=>{
5635
+ const state = getStoreState();
5636
+ if (state) if (onCopyState) {
5637
+ const result = onCopyState(state);
5638
+ if (result instanceof Promise) result.then((ok)=>{
5639
+ logEvent(ok ? 'info' : 'error', ok ? 'State copied to clipboard' : 'Failed to copy state');
5640
+ }).catch(()=>{
5641
+ logEvent('error', 'Failed to copy state');
5642
+ });
5643
+ else logEvent(result ? 'info' : 'error', result ? 'State copied to clipboard' : 'Failed to copy state');
5644
+ } else navigator.clipboard.writeText(JSON.stringify(state, null, 2)).then(()=>{
5645
+ logEvent('info', 'State copied to clipboard');
5646
+ }).catch(()=>{
5647
+ logEvent('error', 'Failed to copy state');
5648
+ });
5649
+ },
5650
+ onExportDebugBundle: onExportDebugBundle ? ()=>{
5651
+ try {
5652
+ onExportDebugBundle();
5653
+ logEvent('info', 'Debug bundle exported');
5654
+ } catch {
5655
+ logEvent('error', 'Failed to export debug bundle');
5656
+ }
5657
+ } : void 0
5658
+ });
5659
+ break;
5660
+ }
5661
+ };
5662
+ return {
5663
+ renderPanel,
5664
+ getStoreState,
5665
+ resetConsents
5666
+ };
5667
+ }
4185
5668
  const STORAGE_KEY = 'c15t-devtools-events';
5669
+ const ACTIVE_TAB_STORAGE_KEY = 'c15t-devtools-active-tab';
4186
5670
  function loadPersistedEvents() {
4187
5671
  if ('undefined' == typeof window) return [];
4188
5672
  try {
@@ -4197,11 +5681,29 @@ var __webpack_exports__ = {};
4197
5681
  sessionStorage.setItem(STORAGE_KEY, JSON.stringify(events));
4198
5682
  } catch {}
4199
5683
  }
5684
+ function isDevToolsTab(value) {
5685
+ return 'consents' === value || 'location' === value || "scripts" === value || 'iab' === value || 'events' === value || 'actions' === value;
5686
+ }
5687
+ function loadPersistedActiveTab() {
5688
+ if ('undefined' == typeof window) return null;
5689
+ try {
5690
+ const stored = localStorage.getItem(ACTIVE_TAB_STORAGE_KEY);
5691
+ if (isDevToolsTab(stored)) return stored;
5692
+ } catch {}
5693
+ return null;
5694
+ }
5695
+ function persistActiveTab(tab) {
5696
+ if ('undefined' == typeof window) return;
5697
+ try {
5698
+ localStorage.setItem(ACTIVE_TAB_STORAGE_KEY, tab);
5699
+ } catch {}
5700
+ }
4200
5701
  function state_manager_createStateManager(initialState = {}) {
4201
5702
  const persistedEvents = loadPersistedEvents();
5703
+ const persistedActiveTab = loadPersistedActiveTab();
4202
5704
  let state = {
4203
5705
  isOpen: false,
4204
- activeTab: 'location',
5706
+ activeTab: persistedActiveTab ?? 'location',
4205
5707
  position: 'bottom-right',
4206
5708
  isConnected: false,
4207
5709
  eventLog: persistedEvents,
@@ -4242,6 +5744,7 @@ var __webpack_exports__ = {};
4242
5744
  setState({
4243
5745
  activeTab: tab
4244
5746
  });
5747
+ persistActiveTab(tab);
4245
5748
  },
4246
5749
  setPosition: (position)=>{
4247
5750
  setState({
@@ -4283,12 +5786,67 @@ var __webpack_exports__ = {};
4283
5786
  const { namespace = 'c15tStore', onConnect, onStateChange, onDisconnect } = options;
4284
5787
  let store = null;
4285
5788
  let unsubscribe = null;
4286
- let pollInterval = null;
5789
+ let reconnectTimeout = null;
5790
+ let reconnectAttempts = 0;
5791
+ let hasNotifiedDisconnect = false;
4287
5792
  const listeners = new Set();
5793
+ const diagnosticsListeners = new Set();
5794
+ let diagnostics = {
5795
+ namespace,
5796
+ reconnectAttempts: 0,
5797
+ nextRetryInMs: null,
5798
+ lastError: null,
5799
+ isPolling: false,
5800
+ disconnectNotified: false
5801
+ };
5802
+ const INITIAL_RETRY_DELAY_MS = 100;
5803
+ const MAX_RETRY_DELAY_MS = 2000;
5804
+ const DISCONNECT_NOTIFY_ATTEMPTS = 5;
5805
+ function updateDiagnostics(partial, notify = true) {
5806
+ diagnostics = {
5807
+ ...diagnostics,
5808
+ ...partial
5809
+ };
5810
+ if (!notify) return;
5811
+ for (const listener of diagnosticsListeners)listener(diagnostics);
5812
+ }
5813
+ function clearReconnectTimer() {
5814
+ if (reconnectTimeout) {
5815
+ clearTimeout(reconnectTimeout);
5816
+ reconnectTimeout = null;
5817
+ updateDiagnostics({
5818
+ isPolling: false,
5819
+ nextRetryInMs: null
5820
+ });
5821
+ }
5822
+ }
5823
+ function resetReconnectState() {
5824
+ reconnectAttempts = 0;
5825
+ hasNotifiedDisconnect = false;
5826
+ updateDiagnostics({
5827
+ reconnectAttempts: 0,
5828
+ nextRetryInMs: null,
5829
+ lastError: null,
5830
+ disconnectNotified: false
5831
+ });
5832
+ }
5833
+ function notifyDisconnectedOnce() {
5834
+ if (hasNotifiedDisconnect) return;
5835
+ hasNotifiedDisconnect = true;
5836
+ updateDiagnostics({
5837
+ disconnectNotified: true
5838
+ });
5839
+ onDisconnect?.();
5840
+ }
4288
5841
  function tryConnect() {
4289
5842
  if ('undefined' == typeof window) return false;
4290
5843
  const storeInstance = window[namespace];
4291
5844
  if (storeInstance && 'function' == typeof storeInstance.getState) {
5845
+ if (store === storeInstance && unsubscribe) return true;
5846
+ if (unsubscribe) {
5847
+ unsubscribe();
5848
+ unsubscribe = null;
5849
+ }
4292
5850
  store = storeInstance;
4293
5851
  unsubscribe = store.subscribe((state)=>{
4294
5852
  onStateChange?.(state);
@@ -4296,30 +5854,41 @@ var __webpack_exports__ = {};
4296
5854
  });
4297
5855
  const currentState = store.getState();
4298
5856
  onConnect?.(currentState, store);
4299
- if (pollInterval) {
4300
- clearInterval(pollInterval);
4301
- pollInterval = null;
4302
- }
5857
+ clearReconnectTimer();
5858
+ resetReconnectState();
5859
+ updateDiagnostics({
5860
+ lastError: null
5861
+ });
4303
5862
  return true;
4304
5863
  }
5864
+ updateDiagnostics({
5865
+ lastError: `Store "${namespace}" not found on window`
5866
+ });
4305
5867
  return false;
4306
5868
  }
5869
+ function scheduleReconnect(immediate = false) {
5870
+ if (store || reconnectTimeout) return;
5871
+ const delay = immediate ? 0 : Math.min(INITIAL_RETRY_DELAY_MS * 2 ** Math.min(reconnectAttempts, 5), MAX_RETRY_DELAY_MS);
5872
+ updateDiagnostics({
5873
+ isPolling: true,
5874
+ nextRetryInMs: delay,
5875
+ reconnectAttempts
5876
+ });
5877
+ reconnectTimeout = setTimeout(()=>{
5878
+ reconnectTimeout = null;
5879
+ reconnectAttempts++;
5880
+ updateDiagnostics({
5881
+ reconnectAttempts,
5882
+ nextRetryInMs: null
5883
+ });
5884
+ if (tryConnect()) return;
5885
+ if (reconnectAttempts >= DISCONNECT_NOTIFY_ATTEMPTS) notifyDisconnectedOnce();
5886
+ scheduleReconnect();
5887
+ }, delay);
5888
+ }
4307
5889
  function startPolling() {
4308
- if (pollInterval) return;
4309
5890
  if (tryConnect()) return;
4310
- let attempts = 0;
4311
- const maxAttempts = 50;
4312
- pollInterval = setInterval(()=>{
4313
- attempts++;
4314
- if (tryConnect()) return;
4315
- if (attempts >= maxAttempts) {
4316
- if (pollInterval) {
4317
- clearInterval(pollInterval);
4318
- pollInterval = null;
4319
- }
4320
- onDisconnect?.();
4321
- }
4322
- }, 100);
5891
+ scheduleReconnect(true);
4323
5892
  }
4324
5893
  startPolling();
4325
5894
  return {
@@ -4333,17 +5902,155 @@ var __webpack_exports__ = {};
4333
5902
  listeners.delete(listener);
4334
5903
  };
4335
5904
  },
5905
+ getDiagnostics: ()=>diagnostics,
5906
+ subscribeDiagnostics: (listener)=>{
5907
+ diagnosticsListeners.add(listener);
5908
+ listener(diagnostics);
5909
+ return ()=>{
5910
+ diagnosticsListeners.delete(listener);
5911
+ };
5912
+ },
5913
+ retryConnection: ()=>{
5914
+ if (store) return;
5915
+ resetReconnectState();
5916
+ scheduleReconnect(true);
5917
+ },
4336
5918
  destroy: ()=>{
4337
- if (pollInterval) {
4338
- clearInterval(pollInterval);
4339
- pollInterval = null;
4340
- }
5919
+ clearReconnectTimer();
4341
5920
  if (unsubscribe) {
4342
5921
  unsubscribe();
4343
5922
  unsubscribe = null;
4344
5923
  }
4345
5924
  store = null;
4346
5925
  listeners.clear();
5926
+ diagnosticsListeners.clear();
5927
+ }
5928
+ };
5929
+ }
5930
+ const REGISTRY_KEY = '__c15tDevToolsInstrumentationRegistry';
5931
+ let fallbackRegistry = null;
5932
+ function getRegistry() {
5933
+ if ('undefined' == typeof window) {
5934
+ if (!fallbackRegistry) fallbackRegistry = new Map();
5935
+ return fallbackRegistry;
5936
+ }
5937
+ const host = window;
5938
+ const existing = host[REGISTRY_KEY];
5939
+ if (existing) return existing;
5940
+ const registry = new Map();
5941
+ host[REGISTRY_KEY] = registry;
5942
+ return registry;
5943
+ }
5944
+ function getBlockedRequestMessage(payload) {
5945
+ const data = payload;
5946
+ const method = 'string' == typeof data?.method ? data.method.toUpperCase() : 'REQUEST';
5947
+ const url = 'string' == typeof data?.url ? data.url : 'unknown-url';
5948
+ return `Network blocked: ${method} ${url}`;
5949
+ }
5950
+ function emitEvent(entry, event) {
5951
+ for (const listener of entry.listeners)listener(event);
5952
+ }
5953
+ function ensureNetworkBlockerWrapped(entry) {
5954
+ const blocker = entry.store.getState().networkBlocker;
5955
+ if (!blocker) return;
5956
+ if (blocker.onRequestBlocked === entry.wrappedNetworkBlockedCallback) return;
5957
+ entry.originalNetworkBlockedCallback = blocker.onRequestBlocked;
5958
+ entry.wrappedNetworkBlockedCallback = (payload)=>{
5959
+ emitEvent(entry, {
5960
+ type: 'network',
5961
+ message: getBlockedRequestMessage(payload),
5962
+ data: payload
5963
+ });
5964
+ if ('function' == typeof entry.originalNetworkBlockedCallback) entry.originalNetworkBlockedCallback(payload);
5965
+ };
5966
+ entry.store.getState().setNetworkBlocker({
5967
+ ...blocker,
5968
+ onRequestBlocked: entry.wrappedNetworkBlockedCallback
5969
+ });
5970
+ }
5971
+ function restoreInstrumentation(entry) {
5972
+ entry.stopWatchingStore?.();
5973
+ entry.stopWatchingStore = null;
5974
+ const state = entry.store.getState();
5975
+ state.setCallback('onBannerFetched', entry.originalCallbacks.onBannerFetched);
5976
+ state.setCallback('onConsentSet', entry.originalCallbacks.onConsentSet);
5977
+ state.setCallback('onError', entry.originalCallbacks.onError);
5978
+ state.setCallback('onBeforeConsentRevocationReload', entry.originalCallbacks.onBeforeConsentRevocationReload);
5979
+ const blocker = state.networkBlocker;
5980
+ if (blocker && blocker.onRequestBlocked === entry.wrappedNetworkBlockedCallback) state.setNetworkBlocker({
5981
+ ...blocker,
5982
+ onRequestBlocked: entry.originalNetworkBlockedCallback
5983
+ });
5984
+ entry.wrappedNetworkBlockedCallback = null;
5985
+ }
5986
+ function createInstrumentationEntry(store) {
5987
+ const entry = {
5988
+ store,
5989
+ listeners: new Set(),
5990
+ originalCallbacks: {
5991
+ ...store.getState().callbacks
5992
+ },
5993
+ originalNetworkBlockedCallback: store.getState().networkBlocker?.onRequestBlocked,
5994
+ wrappedNetworkBlockedCallback: null,
5995
+ stopWatchingStore: null
5996
+ };
5997
+ store.getState().setCallback('onBannerFetched', (payload)=>{
5998
+ const jurisdiction = payload.jurisdiction;
5999
+ emitEvent(entry, {
6000
+ type: 'info',
6001
+ message: `Banner fetched: ${String(jurisdiction)}`,
6002
+ data: payload
6003
+ });
6004
+ if ('function' == typeof entry.originalCallbacks.onBannerFetched) entry.originalCallbacks.onBannerFetched(payload);
6005
+ });
6006
+ store.getState().setCallback('onConsentSet', (payload)=>{
6007
+ emitEvent(entry, {
6008
+ type: 'consent_set',
6009
+ message: 'Consent preferences updated',
6010
+ data: payload
6011
+ });
6012
+ if ('function' == typeof entry.originalCallbacks.onConsentSet) entry.originalCallbacks.onConsentSet(payload);
6013
+ });
6014
+ store.getState().setCallback('onError', (payload)=>{
6015
+ const errorMessage = payload.error;
6016
+ emitEvent(entry, {
6017
+ type: 'error',
6018
+ message: `Error: ${String(errorMessage)}`,
6019
+ data: payload
6020
+ });
6021
+ if ('function' == typeof entry.originalCallbacks.onError) entry.originalCallbacks.onError(payload);
6022
+ });
6023
+ store.getState().setCallback('onBeforeConsentRevocationReload', (payload)=>{
6024
+ emitEvent(entry, {
6025
+ type: 'info',
6026
+ message: 'Consent revocation - page will reload',
6027
+ data: payload
6028
+ });
6029
+ if ('function' == typeof entry.originalCallbacks.onBeforeConsentRevocationReload) entry.originalCallbacks.onBeforeConsentRevocationReload(payload);
6030
+ });
6031
+ ensureNetworkBlockerWrapped(entry);
6032
+ entry.stopWatchingStore = store.subscribe(()=>{
6033
+ ensureNetworkBlockerWrapped(entry);
6034
+ });
6035
+ return entry;
6036
+ }
6037
+ function store_instrumentation_registerStoreInstrumentation(options) {
6038
+ const { namespace, store, onEvent } = options;
6039
+ const registry = getRegistry();
6040
+ let entry = registry.get(namespace);
6041
+ if (!entry || entry.store !== store) {
6042
+ if (entry) restoreInstrumentation(entry);
6043
+ entry = createInstrumentationEntry(store);
6044
+ registry.set(namespace, entry);
6045
+ }
6046
+ entry.listeners.add(onEvent);
6047
+ return ()=>{
6048
+ const current = registry.get(namespace);
6049
+ if (!current) return;
6050
+ current.listeners.delete(onEvent);
6051
+ if (0 === current.listeners.size) {
6052
+ restoreInstrumentation(current);
6053
+ registry.delete(namespace);
4347
6054
  }
4348
6055
  };
4349
6056
  }
@@ -4356,59 +6063,148 @@ var __webpack_exports__ = {};
4356
6063
  tokens_options.insertStyleElement = insertStyleElement_default();
4357
6064
  injectStylesIntoStyleTag_default()(tokens.A, tokens_options);
4358
6065
  tokens.A && tokens.A.locals && tokens.A.locals;
6066
+ const PANEL_HEIGHT_TRANSITION = 'height var(--c15t-duration-normal, 200ms) var(--c15t-easing, cubic-bezier(0.4, 0, 0.2, 1))';
6067
+ const PANEL_HEIGHT_TRANSITION_MS = 200;
6068
+ const PANEL_HEIGHT_TRANSITION_BUFFER_MS = 80;
6069
+ function normalizeOverridesForPersistence(overrides) {
6070
+ return {
6071
+ country: overrides?.country?.trim() || void 0,
6072
+ region: overrides?.region?.trim() || void 0,
6073
+ language: overrides?.language?.trim() || void 0,
6074
+ gpc: overrides?.gpc
6075
+ };
6076
+ }
6077
+ function persistedOverridesEqual(a, b) {
6078
+ return a.country === b.country && a.region === b.region && a.language === b.language && a.gpc === b.gpc;
6079
+ }
6080
+ function prefersReducedMotion() {
6081
+ return 'undefined' != typeof window && 'function' == typeof window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
6082
+ }
6083
+ function createPanelHeightAnimator() {
6084
+ let activePanel = null;
6085
+ let frameId = null;
6086
+ let timeoutId = null;
6087
+ let removeTransitionListener = null;
6088
+ function clearAnimationState() {
6089
+ if (null !== frameId) {
6090
+ window.cancelAnimationFrame(frameId);
6091
+ frameId = null;
6092
+ }
6093
+ if (null !== timeoutId) {
6094
+ clearTimeout(timeoutId);
6095
+ timeoutId = null;
6096
+ }
6097
+ if (removeTransitionListener) {
6098
+ removeTransitionListener();
6099
+ removeTransitionListener = null;
6100
+ }
6101
+ if (activePanel) {
6102
+ activePanel.style.height = '';
6103
+ activePanel.style.transition = '';
6104
+ activePanel.style.willChange = '';
6105
+ activePanel = null;
6106
+ }
6107
+ }
6108
+ function animate(panel, previousHeight) {
6109
+ if (!Number.isFinite(previousHeight) || prefersReducedMotion()) return;
6110
+ const nextHeight = panel.getBoundingClientRect().height;
6111
+ if (!Number.isFinite(nextHeight) || Math.abs(nextHeight - previousHeight) < 1) return;
6112
+ clearAnimationState();
6113
+ activePanel = panel;
6114
+ panel.style.height = `${previousHeight}px`;
6115
+ panel.style.willChange = 'height';
6116
+ panel.getBoundingClientRect();
6117
+ const handleTransitionEnd = (event)=>{
6118
+ const transitionEvent = event;
6119
+ if ('string' == typeof transitionEvent.propertyName && transitionEvent.propertyName && 'height' !== transitionEvent.propertyName) return;
6120
+ clearAnimationState();
6121
+ };
6122
+ panel.addEventListener('transitionend', handleTransitionEnd);
6123
+ removeTransitionListener = ()=>{
6124
+ panel.removeEventListener('transitionend', handleTransitionEnd);
6125
+ };
6126
+ frameId = window.requestAnimationFrame(()=>{
6127
+ frameId = null;
6128
+ panel.style.transition = PANEL_HEIGHT_TRANSITION;
6129
+ panel.style.height = `${nextHeight}px`;
6130
+ });
6131
+ timeoutId = setTimeout(()=>{
6132
+ clearAnimationState();
6133
+ }, PANEL_HEIGHT_TRANSITION_MS + PANEL_HEIGHT_TRANSITION_BUFFER_MS);
6134
+ }
6135
+ return {
6136
+ animate,
6137
+ destroy: clearAnimationState
6138
+ };
6139
+ }
6140
+ function createStateCopy(state) {
6141
+ return {
6142
+ consents: state.consents,
6143
+ selectedConsents: state.selectedConsents,
6144
+ consentInfo: state.consentInfo,
6145
+ locationInfo: state.locationInfo,
6146
+ model: state.model,
6147
+ overrides: state.overrides,
6148
+ scripts: state.scripts?.map((script)=>({
6149
+ id: script.id
6150
+ })),
6151
+ loadedScripts: state.loadedScripts
6152
+ };
6153
+ }
4359
6154
  function createDevTools(options = {}) {
4360
6155
  const { namespace = 'c15tStore', position = 'bottom-right', defaultOpen = false } = options;
4361
6156
  const stateManager = state_manager_createStateManager({
4362
6157
  position,
4363
6158
  isOpen: defaultOpen
4364
6159
  });
4365
- let originalCallbacks = {};
6160
+ let detachInstrumentation = null;
4366
6161
  const storeConnector = store_connector_createStoreConnector({
4367
6162
  namespace,
4368
- onConnect: (state, store)=>{
6163
+ onConnect: (_state, store)=>{
6164
+ detachInstrumentation?.();
6165
+ detachInstrumentation = store_instrumentation_registerStoreInstrumentation({
6166
+ namespace,
6167
+ store,
6168
+ onEvent: (event)=>{
6169
+ stateManager.addEvent(event);
6170
+ }
6171
+ });
4369
6172
  stateManager.setConnected(true);
4370
6173
  stateManager.addEvent({
4371
6174
  type: 'info',
4372
6175
  message: 'Connected to c15tStore'
4373
6176
  });
4374
- originalCallbacks = {
4375
- ...state.callbacks
4376
- };
4377
- store.getState().setCallback('onBannerFetched', (payload)=>{
4378
- stateManager.addEvent({
4379
- type: 'info',
4380
- message: `Banner fetched: ${String(payload.jurisdiction)}`,
4381
- data: payload
4382
- });
4383
- if ('function' == typeof originalCallbacks.onBannerFetched) originalCallbacks.onBannerFetched(payload);
4384
- });
4385
- store.getState().setCallback('onConsentSet', (payload)=>{
4386
- stateManager.addEvent({
4387
- type: 'consent_set',
4388
- message: 'Consent preferences updated',
4389
- data: payload
4390
- });
4391
- if ('function' == typeof originalCallbacks.onConsentSet) originalCallbacks.onConsentSet(payload);
4392
- });
4393
- store.getState().setCallback('onError', (payload)=>{
4394
- stateManager.addEvent({
4395
- type: 'error',
4396
- message: `Error: ${payload.error}`,
4397
- data: payload
4398
- });
4399
- if ('function' == typeof originalCallbacks.onError) originalCallbacks.onError(payload);
4400
- });
4401
- store.getState().setCallback('onBeforeConsentRevocationReload', (payload)=>{
4402
- stateManager.addEvent({
4403
- type: 'info',
4404
- message: 'Consent revocation - page will reload',
4405
- data: payload
6177
+ const persistedOverrides = override_storage_loadPersistedOverrides();
6178
+ if (persistedOverrides) {
6179
+ const currentOverrides = normalizeOverridesForPersistence(store.getState().overrides);
6180
+ if (!persistedOverridesEqual(persistedOverrides, currentOverrides)) store.getState().setOverrides({
6181
+ country: persistedOverrides.country,
6182
+ region: persistedOverrides.region,
6183
+ language: persistedOverrides.language,
6184
+ gpc: persistedOverrides.gpc
6185
+ }).then(()=>{
6186
+ stateManager.addEvent({
6187
+ type: 'info',
6188
+ message: 'Applied persisted devtools overrides',
6189
+ data: {
6190
+ country: persistedOverrides.country,
6191
+ region: persistedOverrides.region,
6192
+ language: persistedOverrides.language,
6193
+ gpc: persistedOverrides.gpc
6194
+ }
6195
+ });
6196
+ }).catch(()=>{
6197
+ stateManager.addEvent({
6198
+ type: 'error',
6199
+ message: 'Failed to apply persisted devtools overrides'
6200
+ });
4406
6201
  });
4407
- if ('function' == typeof originalCallbacks.onBeforeConsentRevocationReload) originalCallbacks.onBeforeConsentRevocationReload(payload);
4408
- });
6202
+ }
4409
6203
  },
4410
6204
  onDisconnect: ()=>{
4411
6205
  stateManager.setConnected(false);
6206
+ detachInstrumentation?.();
6207
+ detachInstrumentation = null;
4412
6208
  stateManager.addEvent({
4413
6209
  type: 'error',
4414
6210
  message: 'Disconnected from c15tStore'
@@ -4416,22 +6212,56 @@ var __webpack_exports__ = {};
4416
6212
  },
4417
6213
  onStateChange: ()=>{}
4418
6214
  });
6215
+ const panelRenderer = panel_renderer_createPanelRenderer({
6216
+ storeConnector,
6217
+ stateManager,
6218
+ enableEventLogging: true,
6219
+ onPersistOverrides: override_storage_persistOverrides,
6220
+ onClearPersistedOverrides: override_storage_clearPersistedOverrides,
6221
+ onCopyState: async (state)=>{
6222
+ try {
6223
+ await navigator.clipboard.writeText(JSON.stringify(createStateCopy(state), null, 2));
6224
+ return true;
6225
+ } catch {
6226
+ return false;
6227
+ }
6228
+ },
6229
+ onExportDebugBundle: ()=>{
6230
+ const bundle = debug_bundle_createDebugBundle({
6231
+ namespace,
6232
+ devToolsState: stateManager.getState(),
6233
+ connection: storeConnector.getDiagnostics(),
6234
+ recentEvents: stateManager.getState().eventLog.slice(0, 100),
6235
+ storeState: debug_bundle_sanitizeStoreState(storeConnector.getState())
6236
+ });
6237
+ debug_bundle_downloadDebugBundle(bundle);
6238
+ }
6239
+ });
4419
6240
  let tabsInstance = null;
6241
+ const panelHeightAnimator = createPanelHeightAnimator();
4420
6242
  const panelInstance = createPanel({
4421
6243
  stateManager,
4422
6244
  storeConnector,
6245
+ namespace,
4423
6246
  onRenderContent: (container)=>{
4424
- renderContent(container, stateManager, storeConnector);
6247
+ renderContent(container);
4425
6248
  }
4426
6249
  });
4427
- function renderContent(container, stateManager, storeConnector) {
6250
+ function renderContent(container) {
6251
+ const panel = container.parentElement;
6252
+ const previousPanelHeight = panel?.getBoundingClientRect().height ?? 0;
4428
6253
  clearElement(container);
4429
6254
  const storeState = storeConnector.getState();
4430
6255
  const disabledTabs = [];
4431
6256
  if (!storeState || 'iab' !== storeState.model) disabledTabs.push('iab');
6257
+ let currentActiveTab = stateManager.getState().activeTab;
6258
+ if (disabledTabs.includes(currentActiveTab)) {
6259
+ stateManager.setActiveTab('consents');
6260
+ currentActiveTab = 'consents';
6261
+ }
4432
6262
  if (tabsInstance) tabsInstance.destroy();
4433
6263
  tabsInstance = tabs_createTabs({
4434
- activeTab: stateManager.getState().activeTab,
6264
+ activeTab: currentActiveTab,
4435
6265
  onTabChange: (tab)=>{
4436
6266
  stateManager.setActiveTab(tab);
4437
6267
  },
@@ -4446,202 +6276,9 @@ var __webpack_exports__ = {};
4446
6276
  }
4447
6277
  });
4448
6278
  container.appendChild(panelContent);
4449
- const state = stateManager.getState();
4450
- const getStoreState = ()=>storeConnector.getState();
4451
- switch(state.activeTab){
4452
- case 'consents':
4453
- consents_renderConsentsPanel(panelContent, {
4454
- getState: getStoreState,
4455
- onConsentChange: (name, value)=>{
4456
- const store = storeConnector.getStore();
4457
- if (store) {
4458
- const consentName = String(name);
4459
- store.getState().setSelectedConsent(consentName, value);
4460
- stateManager.addEvent({
4461
- type: 'info',
4462
- message: `${consentName} toggled to ${value} (not saved)`,
4463
- data: {
4464
- name: consentName,
4465
- value
4466
- }
4467
- });
4468
- }
4469
- },
4470
- onSave: ()=>{
4471
- const store = storeConnector.getStore();
4472
- if (store) {
4473
- store.getState().saveConsents('custom');
4474
- stateManager.addEvent({
4475
- type: 'consent_save',
4476
- message: 'Saved consent preferences'
4477
- });
4478
- }
4479
- },
4480
- onAcceptAll: ()=>{
4481
- const store = storeConnector.getStore();
4482
- if (store) {
4483
- store.getState().saveConsents('all');
4484
- stateManager.addEvent({
4485
- type: 'consent_save',
4486
- message: 'Accepted all consents'
4487
- });
4488
- }
4489
- },
4490
- onRejectAll: ()=>{
4491
- const store = storeConnector.getStore();
4492
- if (store) {
4493
- store.getState().saveConsents('necessary');
4494
- stateManager.addEvent({
4495
- type: 'consent_save',
4496
- message: 'Rejected all optional consents'
4497
- });
4498
- }
4499
- },
4500
- onReset: async ()=>{
4501
- const store = storeConnector.getStore();
4502
- if (store) await reset_consents_resetAllConsents(store, stateManager);
4503
- }
4504
- });
4505
- break;
4506
- case 'location':
4507
- location_renderLocationPanel(panelContent, {
4508
- getState: getStoreState,
4509
- onSetOverrides: async (overrides)=>{
4510
- const store = storeConnector.getStore();
4511
- if (store) {
4512
- const currentOverrides = store.getState().overrides || {};
4513
- await store.getState().setOverrides({
4514
- ...currentOverrides,
4515
- ...overrides
4516
- });
4517
- stateManager.addEvent({
4518
- type: 'info',
4519
- message: 'Overrides updated',
4520
- data: overrides
4521
- });
4522
- await store.getState().initConsentManager();
4523
- stateManager.addEvent({
4524
- type: 'info',
4525
- message: 'Consent manager re-initialized with new overrides'
4526
- });
4527
- }
4528
- },
4529
- onClearOverrides: async ()=>{
4530
- const store = storeConnector.getStore();
4531
- if (store) {
4532
- await store.getState().setOverrides(void 0);
4533
- stateManager.addEvent({
4534
- type: 'info',
4535
- message: 'Overrides cleared'
4536
- });
4537
- await store.getState().initConsentManager();
4538
- stateManager.addEvent({
4539
- type: 'info',
4540
- message: 'Consent manager re-initialized'
4541
- });
4542
- }
4543
- }
4544
- });
4545
- break;
4546
- case "scripts":
4547
- scripts_renderScriptsPanel(panelContent, {
4548
- getState: getStoreState
4549
- });
4550
- break;
4551
- case 'iab':
4552
- iab_renderIabPanel(panelContent, {
4553
- getState: getStoreState,
4554
- onReset: async ()=>{
4555
- const store = storeConnector.getStore();
4556
- if (store) await reset_consents_resetAllConsents(store, stateManager);
4557
- }
4558
- });
4559
- break;
4560
- case 'events':
4561
- events_renderEventsPanel(panelContent, {
4562
- getEvents: ()=>stateManager.getState().eventLog,
4563
- onClear: ()=>{
4564
- stateManager.clearEventLog();
4565
- stateManager.addEvent({
4566
- type: 'info',
4567
- message: 'Event log cleared'
4568
- });
4569
- }
4570
- });
4571
- break;
4572
- case 'actions':
4573
- actions_renderActionsPanel(panelContent, {
4574
- getState: getStoreState,
4575
- onResetConsents: async ()=>{
4576
- const store = storeConnector.getStore();
4577
- if (store) await reset_consents_resetAllConsents(store, stateManager);
4578
- },
4579
- onRefetchBanner: async ()=>{
4580
- const store = storeConnector.getStore();
4581
- if (store) {
4582
- await store.getState().initConsentManager();
4583
- stateManager.addEvent({
4584
- type: 'info',
4585
- message: 'Banner data refetched'
4586
- });
4587
- }
4588
- },
4589
- onShowBanner: ()=>{
4590
- const store = storeConnector.getStore();
4591
- if (store) {
4592
- store.getState().setActiveUI('banner', {
4593
- force: true
4594
- });
4595
- stateManager.addEvent({
4596
- type: 'info',
4597
- message: 'Banner shown'
4598
- });
4599
- }
4600
- },
4601
- onOpenPreferences: ()=>{
4602
- const store = storeConnector.getStore();
4603
- if (store) {
4604
- store.getState().setActiveUI('dialog');
4605
- stateManager.addEvent({
4606
- type: 'info',
4607
- message: 'Preference center opened'
4608
- });
4609
- }
4610
- },
4611
- onCopyState: ()=>{
4612
- const state = storeConnector.getState();
4613
- if (state) {
4614
- const stateCopy = {
4615
- consents: state.consents,
4616
- consentInfo: state.consentInfo,
4617
- locationInfo: state.locationInfo,
4618
- model: state.model,
4619
- overrides: state.overrides,
4620
- scripts: state.scripts?.map((s)=>({
4621
- id: s.id
4622
- })),
4623
- loadedScripts: state.loadedScripts
4624
- };
4625
- navigator.clipboard.writeText(JSON.stringify(stateCopy, null, 2)).then(()=>{
4626
- stateManager.addEvent({
4627
- type: 'info',
4628
- message: 'State copied to clipboard'
4629
- });
4630
- }).catch(()=>{
4631
- stateManager.addEvent({
4632
- type: 'error',
4633
- message: 'Failed to copy state'
4634
- });
4635
- });
4636
- }
4637
- }
4638
- });
4639
- break;
4640
- }
6279
+ panelRenderer.renderPanel(panelContent, currentActiveTab);
6280
+ if (panel) panelHeightAnimator.animate(panel, previousPanelHeight);
4641
6281
  }
4642
- storeConnector.subscribe(()=>{
4643
- panelInstance.update();
4644
- });
4645
6282
  const instance = {
4646
6283
  open: ()=>stateManager.setOpen(true),
4647
6284
  close: ()=>stateManager.setOpen(false),
@@ -4655,6 +6292,9 @@ var __webpack_exports__ = {};
4655
6292
  };
4656
6293
  },
4657
6294
  destroy: ()=>{
6295
+ detachInstrumentation?.();
6296
+ detachInstrumentation = null;
6297
+ panelHeightAnimator.destroy();
4658
6298
  tabsInstance?.destroy();
4659
6299
  panelInstance.destroy();
4660
6300
  storeConnector.destroy();