@c15t/dev-tools 2.0.0-rc.3 → 2.0.0-rc.5

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 (95) hide show
  1. package/README.md +12 -1
  2. package/dist/index.cjs +2039 -953
  3. package/dist/index.js +2042 -956
  4. package/dist/react.cjs +1975 -803
  5. package/dist/react.js +1978 -806
  6. package/dist/tanstack.cjs +1862 -524
  7. package/dist/tanstack.js +1865 -527
  8. package/{dist → dist-types}/components/dropdown-menu.d.ts +0 -1
  9. package/{dist → dist-types}/components/index.d.ts +0 -1
  10. package/{dist → dist-types}/components/panel.d.ts +0 -1
  11. package/{dist → dist-types}/components/tabs.d.ts +0 -1
  12. package/{dist → dist-types}/components/ui.d.ts +8 -1
  13. package/dist-types/core/debug-bundle.d.ts +13 -0
  14. package/{dist → dist-types}/core/devtools.d.ts +0 -1
  15. package/{dist → dist-types}/core/draggable.d.ts +0 -1
  16. package/{dist → dist-types}/core/index.d.ts +0 -1
  17. package/{dist → dist-types}/core/override-storage.d.ts +1 -2
  18. package/{dist → dist-types}/core/panel-renderer.d.ts +6 -2
  19. package/{dist → dist-types}/core/renderer.d.ts +0 -1
  20. package/{dist → dist-types}/core/reset-consents.d.ts +1 -2
  21. package/{dist → dist-types}/core/state-manager.d.ts +1 -2
  22. package/{dist → dist-types}/core/store-connector.d.ts +17 -2
  23. package/dist-types/core/store-instrumentation.d.ts +12 -0
  24. package/{dist → dist-types}/index.d.ts +0 -1
  25. package/{dist → dist-types}/panels/actions.d.ts +2 -2
  26. package/{dist → dist-types}/panels/consents.d.ts +1 -2
  27. package/{dist → dist-types}/panels/dom-scanner.d.ts +1 -2
  28. package/{dist → dist-types}/panels/events.d.ts +0 -1
  29. package/{dist → dist-types}/panels/iab.d.ts +1 -2
  30. package/{dist → dist-types}/panels/index.d.ts +1 -1
  31. package/{dist → dist-types}/panels/location.d.ts +1 -2
  32. package/dist-types/panels/policy.d.ts +12 -0
  33. package/{dist → dist-types}/panels/scripts.d.ts +1 -2
  34. package/{dist → dist-types}/react.d.ts +0 -1
  35. package/{dist → dist-types}/styles/index.d.ts +0 -1
  36. package/{dist → dist-types}/tanstack.d.ts +0 -1
  37. package/{dist → dist-types}/utils/index.d.ts +1 -1
  38. package/dist-types/utils/init-source.d.ts +2 -0
  39. package/{dist → dist-types}/utils/preference-trigger.d.ts +0 -1
  40. package/dist-types/version.d.ts +1 -0
  41. package/package.json +35 -32
  42. package/CHANGELOG.md +0 -154
  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/override-storage.test.d.ts +0 -2
  46. package/dist/__tests__/core/override-storage.test.d.ts.map +0 -1
  47. package/dist/__tests__/core/renderer.test.d.ts +0 -2
  48. package/dist/__tests__/core/renderer.test.d.ts.map +0 -1
  49. package/dist/__tests__/core/reset-consents.test.d.ts +0 -2
  50. package/dist/__tests__/core/reset-consents.test.d.ts.map +0 -1
  51. package/dist/__tests__/core/state-manager.test.d.ts +0 -2
  52. package/dist/__tests__/core/state-manager.test.d.ts.map +0 -1
  53. package/dist/__tests__/core/store-connector.test.d.ts +0 -2
  54. package/dist/__tests__/core/store-connector.test.d.ts.map +0 -1
  55. package/dist/__tests__/panels/dom-scanner.test.d.ts +0 -2
  56. package/dist/__tests__/panels/dom-scanner.test.d.ts.map +0 -1
  57. package/dist/__tests__/panels/events.test.d.ts +0 -2
  58. package/dist/__tests__/panels/events.test.d.ts.map +0 -1
  59. package/dist/__tests__/panels/iab.test.d.ts +0 -2
  60. package/dist/__tests__/panels/iab.test.d.ts.map +0 -1
  61. package/dist/__tests__/panels/scripts.test.d.ts +0 -2
  62. package/dist/__tests__/panels/scripts.test.d.ts.map +0 -1
  63. package/dist/__tests__/utils/preference-trigger.test.d.ts +0 -2
  64. package/dist/__tests__/utils/preference-trigger.test.d.ts.map +0 -1
  65. package/dist/components/dropdown-menu.d.ts.map +0 -1
  66. package/dist/components/index.d.ts.map +0 -1
  67. package/dist/components/panel.d.ts.map +0 -1
  68. package/dist/components/tabs.d.ts.map +0 -1
  69. package/dist/components/ui.d.ts.map +0 -1
  70. package/dist/core/devtools.d.ts.map +0 -1
  71. package/dist/core/draggable.d.ts.map +0 -1
  72. package/dist/core/index.d.ts.map +0 -1
  73. package/dist/core/override-storage.d.ts.map +0 -1
  74. package/dist/core/panel-renderer.d.ts.map +0 -1
  75. package/dist/core/renderer.d.ts.map +0 -1
  76. package/dist/core/reset-consents.d.ts.map +0 -1
  77. package/dist/core/state-manager.d.ts.map +0 -1
  78. package/dist/core/store-connector.d.ts.map +0 -1
  79. package/dist/index.d.ts.map +0 -1
  80. package/dist/panels/actions.d.ts.map +0 -1
  81. package/dist/panels/consents.d.ts.map +0 -1
  82. package/dist/panels/dom-scanner.d.ts.map +0 -1
  83. package/dist/panels/events.d.ts.map +0 -1
  84. package/dist/panels/iab.d.ts.map +0 -1
  85. package/dist/panels/index.d.ts.map +0 -1
  86. package/dist/panels/location.d.ts.map +0 -1
  87. package/dist/panels/scripts.d.ts.map +0 -1
  88. package/dist/react.d.ts.map +0 -1
  89. package/dist/styles/index.d.ts.map +0 -1
  90. package/dist/tanstack.d.ts.map +0 -1
  91. package/dist/utils/index.d.ts.map +0 -1
  92. package/dist/utils/preference-trigger.d.ts.map +0 -1
  93. package/dist/version.d.ts +0 -2
  94. package/dist/version.d.ts.map +0 -1
  95. package/tsconfig.json +0 -12
package/dist/tanstack.js CHANGED
@@ -259,21 +259,21 @@ var __webpack_modules__ = {
259
259
  module.id,
260
260
  `.toggle-bPZtik {
261
261
  border-radius: var(--c15t-radius-full, 9999px);
262
- background-color: var(--c15t-switch-track, #ccc);
262
+ background-color: var(--c15t-switch-track, #d9d9d9);
263
263
  cursor: pointer;
264
- width: 36px;
265
- height: 20px;
266
- transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
264
+ width: 2rem;
265
+ height: 1.25rem;
266
+ 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));
267
267
  border: none;
268
268
  align-items: center;
269
- padding: 0;
269
+ padding: .125rem;
270
270
  display: inline-flex;
271
271
  position: relative;
272
272
  }
273
273
 
274
274
  .toggle-bPZtik:focus-visible {
275
- outline: 2px solid var(--c15t-primary, #335cff);
276
- outline-offset: 2px;
275
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
276
+ outline: none;
277
277
  }
278
278
 
279
279
  .toggleActive-Ldlasg {
@@ -283,16 +283,16 @@ var __webpack_modules__ = {
283
283
  .toggleThumb-hjGfoX {
284
284
  border-radius: var(--c15t-radius-full, 9999px);
285
285
  background-color: var(--c15t-switch-thumb, #fff);
286
- width: 16px;
287
- height: 16px;
288
- transition: transform var(--c15t-duration-fast, .1s) var(--c15t-easing-spring, cubic-bezier(.34, 1.56, .64, 1));
286
+ width: .75rem;
287
+ height: .75rem;
288
+ box-shadow: 0 0 0 1px var(--c15t-border, #e3e3e3);
289
+ transition: transform var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
289
290
  position: absolute;
290
291
  left: 2px;
291
- box-shadow: 0 1px 2px #0003;
292
292
  }
293
293
 
294
294
  .toggleActive-Ldlasg .toggleThumb-hjGfoX {
295
- transform: translateX(16px);
295
+ transform: translateX(1rem);
296
296
  }
297
297
 
298
298
  .toggle-bPZtik:disabled, .toggleDisabled-ZcD8nZ {
@@ -305,13 +305,14 @@ var __webpack_modules__ = {
305
305
  }
306
306
 
307
307
  .badge-yA0giZ {
308
- border-radius: var(--c15t-radius-sm, .25rem);
308
+ border-radius: var(--c15t-radius-full, 9999px);
309
309
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
310
310
  font-weight: var(--c15t-font-weight-medium, 500);
311
+ line-height: var(--c15t-line-height-tight, 1.25);
311
312
  white-space: nowrap;
313
+ justify-content: center;
312
314
  align-items: center;
313
- padding: 2px 6px;
314
- line-height: 1;
315
+ padding: .1875rem .4375rem;
315
316
  display: inline-flex;
316
317
  }
317
318
 
@@ -344,35 +345,36 @@ var __webpack_modules__ = {
344
345
  justify-content: center;
345
346
  align-items: center;
346
347
  gap: var(--c15t-space-xs, .25rem);
347
- border: 1px solid var(--c15t-border, #e3e3e3);
348
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
348
349
  border-radius: var(--c15t-radius-md, .5rem);
349
- background-color: var(--c15t-surface, #fff);
350
- min-height: 30px;
350
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
351
+ min-height: 2rem;
351
352
  color: var(--c15t-text, #171717);
352
- font-family: inherit;
353
- font-size: 12px;
353
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
354
+ font-size: var(--c15t-font-size-sm, .875rem);
354
355
  font-weight: var(--c15t-font-weight-medium, 500);
356
+ line-height: var(--c15t-line-height-tight, 1.25);
357
+ box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000000d);
355
358
  cursor: pointer;
356
359
  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));
357
- padding: 5px 10px;
358
- line-height: 1;
360
+ padding: .375rem .625rem;
359
361
  display: inline-flex;
360
- box-shadow: 0 1px 1px #0000000a;
361
362
  }
362
363
 
363
364
  .btn-evRVlh:hover {
364
- background-color: var(--c15t-surface-hover, #f7f7f7);
365
+ background-color: var(--c15t-devtools-surface-subtle, #f7f7f7);
365
366
  border-color: var(--c15t-border-hover, #c9c9c9);
366
- box-shadow: 0 2px 6px #00000014;
367
+ box-shadow: var(--c15t-shadow-md, 0 4px 12px #00000014);
367
368
  }
368
369
 
369
370
  .btn-evRVlh:focus-visible {
370
- outline: 2px solid var(--c15t-primary, #335cff);
371
- outline-offset: 1px;
371
+ box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000000d), 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
372
+ outline: none;
372
373
  }
373
374
 
374
375
  .btn-evRVlh:active {
375
- box-shadow: 0 1px 2px #00000014;
376
+ box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000000d);
377
+ transform: scale(.98);
376
378
  }
377
379
 
378
380
  .btn-evRVlh:disabled {
@@ -385,6 +387,7 @@ var __webpack_modules__ = {
385
387
  background-color: var(--c15t-primary, #335cff);
386
388
  border-color: var(--c15t-primary, #335cff);
387
389
  color: var(--c15t-text-on-primary, #fff);
390
+ box-shadow: none;
388
391
  }
389
392
 
390
393
  .btnPrimary-dA6nqY:hover {
@@ -396,6 +399,7 @@ var __webpack_modules__ = {
396
399
  background-color: var(--c15t-devtools-badge-error, #ef4343);
397
400
  border-color: var(--c15t-devtools-badge-error, #ef4343);
398
401
  color: var(--c15t-text-on-primary, #fff);
402
+ box-shadow: none;
399
403
  }
400
404
 
401
405
  .btnDanger-eDnqOX:hover {
@@ -404,10 +408,10 @@ var __webpack_modules__ = {
404
408
  }
405
409
 
406
410
  .btnSmall-TjXoqZ {
411
+ min-height: 1.75rem;
412
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
407
413
  border-radius: var(--c15t-radius-sm, .375rem);
408
- min-height: 26px;
409
- padding: 3px 8px;
410
- font-size: 11px;
414
+ padding: .25rem .5rem;
411
415
  }
412
416
 
413
417
  .btnIcon-fiYQAh {
@@ -417,19 +421,22 @@ var __webpack_modules__ = {
417
421
  }
418
422
 
419
423
  .input-IeTcCs {
420
- width: 100%;
421
- padding: var(--c15t-space-xs, .25rem) var(--c15t-space-sm, .5rem);
422
- border: 1px solid var(--c15t-border, #e3e3e3);
424
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
423
425
  border-radius: var(--c15t-radius-md, .5rem);
424
- background-color: var(--c15t-surface, #fff);
426
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
427
+ width: 100%;
428
+ min-height: 2rem;
425
429
  color: var(--c15t-text, #171717);
426
- font-family: inherit;
427
- font-size: var(--c15t-font-size-sm, .875rem);
428
- transition: border-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
430
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
431
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
432
+ line-height: var(--c15t-line-height-tight, 1.25);
433
+ 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));
434
+ padding: .375rem .625rem;
429
435
  }
430
436
 
431
437
  .input-IeTcCs:focus {
432
- border-color: var(--c15t-primary, #335cff);
438
+ border-color: var(--c15t-devtools-focus-ring, #335cff);
439
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--c15t-devtools-focus-ring, #335cff) 25%, transparent);
433
440
  outline: none;
434
441
  }
435
442
 
@@ -438,30 +445,35 @@ var __webpack_modules__ = {
438
445
  }
439
446
 
440
447
  .inputSmall-pJyXcL {
441
- padding: 2px var(--c15t-space-xs, .25rem);
448
+ min-height: 1.625rem;
442
449
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
450
+ padding: .25rem .4375rem;
443
451
  }
444
452
 
445
453
  .select-byJ1WM {
446
- width: 100%;
447
- padding: var(--c15t-space-xs, .25rem) var(--c15t-space-sm, .5rem);
448
- border: 1px solid var(--c15t-border, #e3e3e3);
454
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
449
455
  border-radius: var(--c15t-radius-md, .5rem);
450
- background-color: var(--c15t-surface, #fff);
456
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
457
+ width: 100%;
458
+ min-height: 2rem;
451
459
  color: var(--c15t-text, #171717);
452
- font-family: inherit;
460
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
453
461
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
462
+ line-height: var(--c15t-line-height-tight, 1.25);
454
463
  cursor: pointer;
464
+ 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));
465
+ padding: .375rem .625rem;
455
466
  }
456
467
 
457
468
  .select-byJ1WM:focus {
458
- border-color: var(--c15t-primary, #335cff);
469
+ border-color: var(--c15t-devtools-focus-ring, #335cff);
470
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--c15t-devtools-focus-ring, #335cff) 25%, transparent);
459
471
  outline: none;
460
472
  }
461
473
 
462
474
  .grid-LlrmEz {
463
475
  gap: var(--c15t-space-sm, .5rem);
464
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, 1rem);
476
+ padding: var(--c15t-space-md, 1rem);
465
477
  display: grid;
466
478
  }
467
479
 
@@ -474,42 +486,51 @@ var __webpack_modules__ = {
474
486
  }
475
487
 
476
488
  .gridCard-Qm5xxI {
477
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, .75rem);
478
- border: 1px solid var(--c15t-border, #e3e3e3);
479
- border-radius: var(--c15t-radius-md, .5rem);
480
- background-color: var(--c15t-surface, #fff);
481
- transition: border-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
482
489
  justify-content: space-between;
483
490
  align-items: center;
491
+ gap: var(--c15t-space-sm, .5rem);
492
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
493
+ border-radius: var(--c15t-radius-md, .5rem);
494
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
495
+ min-height: 2.75rem;
496
+ box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000000d);
497
+ 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));
498
+ padding: .5625rem .75rem;
484
499
  display: flex;
485
500
  }
486
501
 
487
502
  .gridCard-Qm5xxI:hover {
488
503
  border-color: var(--c15t-border-hover, #c9c9c9);
504
+ background-color: var(--c15t-devtools-surface-subtle, #fafafa);
489
505
  }
490
506
 
491
507
  .gridCardTitle-HjXETp {
492
508
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
493
509
  font-weight: var(--c15t-font-weight-medium, 500);
494
510
  color: var(--c15t-text, #171717);
511
+ line-height: var(--c15t-line-height-tight, 1.25);
495
512
  }
496
513
 
497
514
  .listItem-XUKGIo {
498
- padding: var(--c15t-space-xs, .25rem) var(--c15t-space-md, 1rem);
499
- border-bottom: 1px solid var(--c15t-border, #e3e3e3);
500
515
  justify-content: space-between;
501
516
  align-items: center;
517
+ gap: var(--c15t-space-sm, .5rem);
518
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
519
+ border-radius: var(--c15t-radius-md, .5rem);
520
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
521
+ margin-bottom: .375rem;
522
+ padding: .625rem .75rem;
502
523
  display: flex;
503
524
  }
504
525
 
505
526
  .listItem-XUKGIo:last-child {
506
- border-bottom: none;
527
+ margin-bottom: 0;
507
528
  }
508
529
 
509
530
  .listItemContent-WDBF1N {
510
531
  flex-direction: column;
511
532
  flex: 1;
512
- gap: 2px;
533
+ gap: .1875rem;
513
534
  min-width: 0;
514
535
  display: flex;
515
536
  }
@@ -523,6 +544,7 @@ var __webpack_modules__ = {
523
544
  .listItemDescription-E6JHyZ {
524
545
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
525
546
  color: var(--c15t-text-muted, #737373);
547
+ line-height: var(--c15t-line-height-tight, 1.25);
526
548
  text-overflow: ellipsis;
527
549
  white-space: nowrap;
528
550
  overflow: hidden;
@@ -536,8 +558,8 @@ var __webpack_modules__ = {
536
558
  }
537
559
 
538
560
  .section-a197cB {
539
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, 1rem);
540
- border-bottom: 1px solid var(--c15t-border, #e3e3e3);
561
+ border-bottom: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
562
+ padding: .75rem 1rem;
541
563
  }
542
564
 
543
565
  .section-a197cB:last-child {
@@ -545,9 +567,10 @@ var __webpack_modules__ = {
545
567
  }
546
568
 
547
569
  .sectionHeader-Xcljcw {
548
- margin-bottom: var(--c15t-space-sm, .5rem);
549
570
  justify-content: space-between;
550
571
  align-items: center;
572
+ gap: .5rem;
573
+ margin-bottom: .625rem;
551
574
  display: flex;
552
575
  }
553
576
 
@@ -556,47 +579,49 @@ var __webpack_modules__ = {
556
579
  font-weight: var(--c15t-font-weight-semibold, 600);
557
580
  color: var(--c15t-text-muted, #737373);
558
581
  text-transform: uppercase;
559
- letter-spacing: .5px;
582
+ letter-spacing: .04em;
560
583
  }
561
584
 
562
585
  .overrideField-keNdpJ {
563
586
  flex-direction: column;
564
- gap: 3px;
587
+ gap: .3125rem;
565
588
  margin-bottom: 0;
566
589
  display: flex;
567
590
  }
568
591
 
569
592
  .overrideLabel-ApMoTw {
593
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
594
+ font-weight: var(--c15t-font-weight-semibold, 600);
570
595
  color: var(--c15t-text-muted, #737373);
571
- font-size: 11px;
572
- font-weight: 600;
596
+ line-height: var(--c15t-line-height-tight, 1.25);
573
597
  }
574
598
 
575
599
  .overrideHint-yCfwGt {
576
- color: var(--c15t-devtools-text-muted, #737373);
577
- margin-top: 6px;
578
- font-size: 11px;
600
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
601
+ color: var(--c15t-text-muted, #737373);
602
+ line-height: var(--c15t-line-height-tight, 1.25);
603
+ margin-top: .5rem;
579
604
  }
580
605
 
581
606
  .overrideActions-imdcn7 {
582
- border-top: 1px dashed var(--c15t-border, #e3e3e3);
607
+ border-top: 1px dashed var(--c15t-devtools-border-strong, #e3e3e3);
583
608
  justify-content: space-between;
584
609
  align-items: center;
585
- gap: 8px;
586
- margin-top: 8px;
587
- padding-top: 8px;
610
+ gap: .5rem;
611
+ margin-top: .625rem;
612
+ padding-top: .625rem;
588
613
  display: flex;
589
614
  }
590
615
 
591
616
  .overrideActionButtons-gYOx1e {
592
617
  flex-wrap: wrap;
593
- gap: 6px;
618
+ gap: .375rem;
594
619
  display: flex;
595
620
  }
596
621
 
597
622
  .overrideStatus-sty_qS {
623
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
598
624
  color: var(--c15t-text-muted, #737373);
599
- font-size: 11px;
600
625
  }
601
626
 
602
627
  .overrideStatusDirty-OUdDMw {
@@ -604,9 +629,10 @@ var __webpack_modules__ = {
604
629
  }
605
630
 
606
631
  .infoRow-RlB_0h {
607
- padding: var(--c15t-space-xs, .25rem) 0;
608
632
  justify-content: space-between;
609
633
  align-items: center;
634
+ gap: .5rem;
635
+ padding: .25rem 0;
610
636
  display: flex;
611
637
  }
612
638
 
@@ -619,6 +645,7 @@ var __webpack_modules__ = {
619
645
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
620
646
  font-weight: var(--c15t-font-weight-medium, 500);
621
647
  color: var(--c15t-text, #171717);
648
+ font-variant-numeric: tabular-nums;
622
649
  font-family: ui-monospace, Cascadia Code, Source Code Pro, Menlo, Consolas, DejaVu Sans Mono, monospace;
623
650
  }
624
651
 
@@ -629,18 +656,27 @@ var __webpack_modules__ = {
629
656
  flex-direction: column;
630
657
  justify-content: center;
631
658
  align-items: center;
659
+ gap: .375rem;
632
660
  display: flex;
633
661
  }
634
662
 
635
663
  .emptyStateIcon-WHFkX8 {
664
+ opacity: .55;
636
665
  width: 32px;
637
666
  height: 32px;
638
- margin-bottom: var(--c15t-space-sm, .5rem);
639
- opacity: .5;
640
667
  }
641
668
 
642
669
  .emptyStateText-TaLvAJ {
643
670
  font-size: var(--c15t-font-size-sm, .875rem);
671
+ line-height: var(--c15t-line-height-normal, 1.5);
672
+ }
673
+
674
+ .disconnectedState-dOtZBG {
675
+ padding: var(--c15t-space-xl, 2rem);
676
+ text-align: center;
677
+ font-size: var(--c15t-font-size-sm, .875rem);
678
+ color: var(--c15t-text-muted, #737373);
679
+ line-height: var(--c15t-line-height-normal, 1.5);
644
680
  }
645
681
 
646
682
  @media (prefers-reduced-motion: reduce) {
@@ -707,7 +743,8 @@ var __webpack_modules__ = {
707
743
  infoValue: "infoValue-flMl_e",
708
744
  emptyState: "emptyState-QcmzTQ",
709
745
  emptyStateIcon: "emptyStateIcon-WHFkX8",
710
- emptyStateText: "emptyStateText-TaLvAJ"
746
+ emptyStateText: "emptyStateText-TaLvAJ",
747
+ disconnectedState: "disconnectedState-dOtZBG"
711
748
  };
712
749
  const __rspack_default_export = ___CSS_LOADER_EXPORT___;
713
750
  },
@@ -736,9 +773,9 @@ var __webpack_modules__ = {
736
773
  .floatingButton-Gw8MtJ {
737
774
  width: var(--c15t-devtools-button-size, 40px);
738
775
  height: var(--c15t-devtools-button-size, 40px);
739
- border: 1px solid var(--c15t-border, #e3e3e3);
776
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
740
777
  border-radius: var(--c15t-radius-full, 9999px);
741
- background-color: var(--c15t-surface, #fff);
778
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
742
779
  box-shadow: var(--c15t-shadow-lg, 0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a);
743
780
  cursor: grab;
744
781
  z-index: var(--c15t-devtools-z-index, 99999);
@@ -766,13 +803,13 @@ var __webpack_modules__ = {
766
803
  }
767
804
 
768
805
  .floatingButton-Gw8MtJ:focus-visible {
769
- outline: 2px solid var(--c15t-primary, #335cff);
770
- outline-offset: 2px;
806
+ box-shadow: var(--c15t-shadow-lg, 0 8px 24px #0000001f), 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
807
+ outline: none;
771
808
  }
772
809
 
773
810
  .floatingButton-Gw8MtJ:active {
774
811
  cursor: grabbing;
775
- transform: scale(1.02);
812
+ transform: scale(.98);
776
813
  }
777
814
 
778
815
  .floatingButtonIcon-cHWefk {
@@ -813,6 +850,7 @@ var __webpack_modules__ = {
813
850
 
814
851
  .backdrop-LhVMB5 {
815
852
  background-color: var(--c15t-overlay, #00000080);
853
+ backdrop-filter: blur(1px);
816
854
  z-index: calc(var(--c15t-devtools-z-index, 99999) + 1);
817
855
  position: fixed;
818
856
  inset: 0;
@@ -821,10 +859,10 @@ var __webpack_modules__ = {
821
859
  .panel-jtWove {
822
860
  width: var(--c15t-devtools-panel-width, 480px);
823
861
  max-height: var(--c15t-devtools-panel-max-height, 560px);
824
- background-color: var(--c15t-surface, #fff);
825
- border: 1px solid var(--c15t-border, #e3e3e3);
862
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
863
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
826
864
  border-radius: var(--c15t-radius-lg, .75rem);
827
- box-shadow: var(--c15t-shadow-lg, 0 8px 24px #0000001f);
865
+ box-shadow: var(--c15t-shadow-lg, 0 10px 28px #00000029);
828
866
  z-index: calc(var(--c15t-devtools-z-index, 99999) + 2);
829
867
  flex-direction: column;
830
868
  display: flex;
@@ -857,11 +895,11 @@ var __webpack_modules__ = {
857
895
  }
858
896
 
859
897
  .header-xluoTr {
860
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, 1rem);
861
- border-bottom: 1px solid var(--c15t-border, #e3e3e3);
898
+ border-bottom: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
862
899
  background-color: var(--c15t-devtools-surface-muted, #f5f5f5);
863
900
  justify-content: space-between;
864
901
  align-items: center;
902
+ padding: .6875rem .875rem;
865
903
  display: flex;
866
904
  }
867
905
 
@@ -870,6 +908,7 @@ var __webpack_modules__ = {
870
908
  gap: var(--c15t-space-sm, .5rem);
871
909
  font-size: var(--c15t-font-size-sm, .875rem);
872
910
  font-weight: var(--c15t-font-weight-semibold, 600);
911
+ line-height: var(--c15t-line-height-tight, 1.25);
873
912
  color: var(--c15t-text, #171717);
874
913
  display: flex;
875
914
  }
@@ -881,9 +920,9 @@ var __webpack_modules__ = {
881
920
  }
882
921
 
883
922
  .closeButton-Yto0Nb {
884
- border-radius: var(--c15t-radius-sm, .25rem);
885
- width: 28px;
886
- height: 28px;
923
+ border-radius: var(--c15t-radius-md, .5rem);
924
+ width: 2rem;
925
+ height: 2rem;
887
926
  color: var(--c15t-text-muted, #737373);
888
927
  cursor: pointer;
889
928
  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));
@@ -896,13 +935,13 @@ var __webpack_modules__ = {
896
935
  }
897
936
 
898
937
  .closeButton-Yto0Nb:hover {
899
- background-color: var(--c15t-surface-hover, #f7f7f7);
938
+ background-color: var(--c15t-devtools-surface-subtle, #f7f7f7);
900
939
  color: var(--c15t-text, #171717);
901
940
  }
902
941
 
903
942
  .closeButton-Yto0Nb:focus-visible {
904
- outline: 2px solid var(--c15t-primary, #335cff);
905
- outline-offset: 1px;
943
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
944
+ outline: none;
906
945
  }
907
946
 
908
947
  .closeButtonIcon-fVlR1I {
@@ -910,33 +949,71 @@ var __webpack_modules__ = {
910
949
  height: 16px;
911
950
  }
912
951
 
952
+ .inlineActionButton-Ky8BmN {
953
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
954
+ border-radius: var(--c15t-radius-sm, .375rem);
955
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
956
+ min-height: 1.625rem;
957
+ color: var(--c15t-text, #171717);
958
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
959
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
960
+ font-weight: var(--c15t-font-weight-medium, 500);
961
+ line-height: var(--c15t-line-height-tight, 1.25);
962
+ cursor: pointer;
963
+ 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));
964
+ justify-content: center;
965
+ align-items: center;
966
+ padding: .25rem .5rem;
967
+ display: inline-flex;
968
+ }
969
+
970
+ .inlineActionButton-Ky8BmN:hover {
971
+ background-color: var(--c15t-devtools-surface-subtle, #f7f7f7);
972
+ border-color: var(--c15t-border-hover, #c9c9c9);
973
+ }
974
+
975
+ .inlineActionButton-Ky8BmN:focus-visible {
976
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
977
+ outline: none;
978
+ }
979
+
913
980
  .content-yDMYfG {
981
+ scrollbar-gutter: stable;
914
982
  overscroll-behavior: contain;
915
983
  -webkit-overflow-scrolling: touch;
984
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
916
985
  flex: auto;
917
986
  min-height: 200px;
918
- overflow: hidden auto;
987
+ overflow: hidden scroll;
919
988
  }
920
989
 
921
990
  .footer-ESbmwQ {
922
- padding: var(--c15t-space-xs, .25rem) var(--c15t-space-md, 1rem);
923
- border-top: 1px solid var(--c15t-border, #e3e3e3);
991
+ border-top: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
924
992
  background-color: var(--c15t-devtools-surface-muted, #f5f5f5);
925
993
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
926
994
  color: var(--c15t-text-muted, #737373);
927
995
  justify-content: space-between;
928
996
  align-items: center;
997
+ gap: .5rem;
998
+ padding: .5rem .75rem;
929
999
  display: flex;
930
1000
  }
931
1001
 
932
1002
  .footerStatus-rlb99A {
933
1003
  align-items: center;
934
- gap: var(--c15t-space-xs, .25rem);
1004
+ gap: .375rem;
1005
+ min-width: 0;
935
1006
  display: flex;
936
1007
  }
937
1008
 
1009
+ .footerMeta-Vdtxdk {
1010
+ opacity: .75;
1011
+ white-space: nowrap;
1012
+ }
1013
+
938
1014
  .statusDot-hYJoej {
939
1015
  border-radius: var(--c15t-radius-full, 9999px);
1016
+ flex-shrink: 0;
940
1017
  width: 6px;
941
1018
  height: 6px;
942
1019
  }
@@ -975,6 +1052,7 @@ var __webpack_modules__ = {
975
1052
  font-size: var(--c15t-font-size-sm, .875rem);
976
1053
  color: var(--c15t-text-muted, #737373);
977
1054
  max-width: 280px;
1055
+ line-height: var(--c15t-line-height-normal, 1.5);
978
1056
  }
979
1057
 
980
1058
  @media (prefers-reduced-motion: reduce) {
@@ -991,17 +1069,17 @@ var __webpack_modules__ = {
991
1069
  }
992
1070
 
993
1071
  .dropdownMenu-aKK18l {
994
- min-width: 200px;
995
- padding: var(--c15t-space-xs, .25rem);
996
- border: 1px solid var(--c15t-border, #e3e3e3);
1072
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
997
1073
  border-radius: var(--c15t-radius-lg, .75rem);
998
- background-color: var(--c15t-surface, #fff);
1074
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
1075
+ min-width: 200px;
999
1076
  box-shadow: var(--c15t-shadow-lg, 0 8px 24px #0000001f);
1000
1077
  z-index: calc(var(--c15t-devtools-z-index, 99999) + 1);
1001
1078
  opacity: 0;
1002
1079
  transform-origin: 0 100%;
1003
1080
  pointer-events: none;
1004
1081
  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));
1082
+ padding: .375rem;
1005
1083
  position: fixed;
1006
1084
  transform: scale(.95)translateY(8px);
1007
1085
  }
@@ -1029,34 +1107,35 @@ var __webpack_modules__ = {
1029
1107
  }
1030
1108
 
1031
1109
  .menuItem-kBbHRP {
1032
- align-items: center;
1033
- gap: var(--c15t-space-sm, .5rem);
1034
- width: 100%;
1035
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-md, .75rem);
1036
1110
  border-radius: var(--c15t-radius-md, .5rem);
1111
+ width: 100%;
1037
1112
  color: var(--c15t-text, #171717);
1038
- font-size: var(--c15t-font-size-sm, .875rem);
1113
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
1039
1114
  font-weight: var(--c15t-font-weight-medium, 500);
1115
+ line-height: var(--c15t-line-height-tight, 1.25);
1040
1116
  text-align: left;
1041
1117
  cursor: pointer;
1042
1118
  transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
1043
1119
  background: none;
1044
1120
  border: none;
1121
+ align-items: center;
1122
+ gap: .625rem;
1123
+ padding: .5rem .625rem;
1045
1124
  display: flex;
1046
1125
  }
1047
1126
 
1048
1127
  .menuItem-kBbHRP:hover {
1049
- background-color: var(--c15t-surface-hover, #f2f2f2);
1128
+ background-color: var(--c15t-devtools-surface-subtle, #f2f2f2);
1050
1129
  }
1051
1130
 
1052
1131
  .menuItem-kBbHRP:focus-visible {
1053
- outline: 2px solid var(--c15t-primary, #335cff);
1054
- outline-offset: -2px;
1132
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
1133
+ outline: none;
1055
1134
  }
1056
1135
 
1057
1136
  .menuItemIcon-P3pP5K {
1058
- width: 20px;
1059
- height: 20px;
1137
+ width: 1rem;
1138
+ height: 1rem;
1060
1139
  color: var(--c15t-text-muted, #737373);
1061
1140
  flex-shrink: 0;
1062
1141
  }
@@ -1069,6 +1148,7 @@ var __webpack_modules__ = {
1069
1148
  font-size: var(--c15t-devtools-font-size-xs, .75rem);
1070
1149
  color: var(--c15t-text-muted, #737373);
1071
1150
  font-weight: var(--c15t-font-weight-normal, 400);
1151
+ margin-top: .125rem;
1072
1152
  }
1073
1153
 
1074
1154
  .menuItemContent-hBlruV {
@@ -1084,8 +1164,8 @@ var __webpack_modules__ = {
1084
1164
  .menuItemToggleTrack-gDp_f3 {
1085
1165
  background-color: var(--c15t-switch-track, #d9d9d9);
1086
1166
  border-radius: var(--c15t-radius-full, 9999px);
1087
- width: 36px;
1088
- height: 20px;
1167
+ width: 2rem;
1168
+ height: 1.25rem;
1089
1169
  transition: background-color var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
1090
1170
  position: relative;
1091
1171
  }
@@ -1093,21 +1173,22 @@ var __webpack_modules__ = {
1093
1173
  .menuItemToggleThumb-ioqqyc {
1094
1174
  background-color: var(--c15t-switch-thumb, #fff);
1095
1175
  border-radius: var(--c15t-radius-full, 9999px);
1096
- width: 16px;
1097
- height: 16px;
1098
- box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000001a);
1176
+ width: .75rem;
1177
+ height: .75rem;
1178
+ box-shadow: 0 0 0 1px var(--c15t-border, #e3e3e3);
1099
1179
  transition: transform var(--c15t-duration-fast, .1s) var(--c15t-easing, cubic-bezier(.4, 0, .2, 1));
1100
1180
  position: absolute;
1101
- top: 2px;
1181
+ top: 50%;
1102
1182
  left: 2px;
1183
+ transform: translateY(-50%);
1103
1184
  }
1104
1185
 
1105
1186
  .menuItemToggleChecked-K3BPtk .menuItemToggleTrack-gDp_f3 {
1106
- background-color: var(--c15t-switch-track-checked, #335cff);
1187
+ background-color: var(--c15t-switch-track-active, #335cff);
1107
1188
  }
1108
1189
 
1109
1190
  .menuItemToggleChecked-K3BPtk .menuItemToggleThumb-ioqqyc {
1110
- transform: translateX(16px);
1191
+ transform: translate(1rem, -50%);
1111
1192
  }
1112
1193
 
1113
1194
  .menuDivider-JIBdhU {
@@ -1143,9 +1224,11 @@ var __webpack_modules__ = {
1143
1224
  headerLogo: "headerLogo-PxJ_w1",
1144
1225
  closeButton: "closeButton-Yto0Nb",
1145
1226
  closeButtonIcon: "closeButtonIcon-fVlR1I",
1227
+ inlineActionButton: "inlineActionButton-Ky8BmN",
1146
1228
  content: "content-yDMYfG",
1147
1229
  footer: "footer-ESbmwQ",
1148
1230
  footerStatus: "footerStatus-rlb99A",
1231
+ footerMeta: "footerMeta-Vdtxdk",
1149
1232
  statusDot: "statusDot-hYJoej",
1150
1233
  statusConnected: "statusConnected-hPSUgS",
1151
1234
  statusDisconnected: "statusDisconnected-HIpcee",
@@ -1184,62 +1267,63 @@ var __webpack_modules__ = {
1184
1267
  ___CSS_LOADER_EXPORT___.push([
1185
1268
  module.id,
1186
1269
  `.tabList-IyuiBE {
1270
+ border-bottom: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
1271
+ background-color: var(--c15t-devtools-surface-subtle, #fafafa);
1187
1272
  align-items: center;
1188
- gap: var(--c15t-space-xs, .25rem);
1189
- padding: var(--c15t-space-sm, .5rem) var(--c15t-space-sm, .5rem);
1190
- border-bottom: 1px solid var(--c15t-border, #e3e3e3);
1191
- background-color: var(--c15t-surface, #fff);
1192
- scrollbar-width: none;
1193
- -ms-overflow-style: none;
1194
- scroll-padding-inline-end: var(--c15t-space-sm, .5rem);
1273
+ gap: .375rem;
1274
+ padding: .75rem;
1195
1275
  display: flex;
1196
- overflow-x: auto;
1197
1276
  }
1198
1277
 
1199
- .tabList-IyuiBE:after {
1200
- content: "";
1201
- flex: 0 0 var(--c15t-space-sm, .5rem);
1202
- }
1203
-
1204
- .tabList-IyuiBE::-webkit-scrollbar {
1205
- display: none;
1278
+ .tabStrip-_KrWe4 {
1279
+ align-items: center;
1280
+ gap: var(--c15t-space-xs, .25rem);
1281
+ flex: auto;
1282
+ min-width: 0;
1283
+ display: flex;
1284
+ overflow: hidden;
1206
1285
  }
1207
1286
 
1208
1287
  .tab-yfDEqg {
1209
- align-items: center;
1210
- gap: var(--c15t-space-xs, .25rem);
1211
1288
  border-radius: var(--c15t-radius-md, .5rem);
1289
+ min-height: 1.875rem;
1212
1290
  color: var(--c15t-text-muted, #737373);
1213
- font-family: inherit;
1214
- font-size: 11px;
1291
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
1292
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
1215
1293
  font-weight: var(--c15t-font-weight-medium, 500);
1294
+ line-height: var(--c15t-line-height-tight, 1.25);
1216
1295
  cursor: pointer;
1217
1296
  white-space: nowrap;
1218
- 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));
1297
+ 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));
1219
1298
  background-color: #0000;
1220
- border: none;
1221
- padding: 3px 7px;
1299
+ border: 1px solid #0000;
1300
+ flex-shrink: 0;
1301
+ align-items: center;
1302
+ gap: .375rem;
1303
+ padding: .25rem .625rem;
1222
1304
  display: flex;
1223
1305
  }
1224
1306
 
1225
1307
  .tab-yfDEqg:hover {
1226
- background-color: var(--c15t-surface-hover, #f7f7f7);
1308
+ background-color: var(--c15t-devtools-surface-muted, #f7f7f7);
1227
1309
  color: var(--c15t-text, #171717);
1228
1310
  }
1229
1311
 
1230
1312
  .tab-yfDEqg:focus-visible {
1231
- outline: 2px solid var(--c15t-primary, #335cff);
1232
- outline-offset: 1px;
1313
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
1314
+ outline: none;
1233
1315
  }
1234
1316
 
1235
1317
  .tabActive-r4hing {
1236
- background-color: var(--c15t-primary, #335cff);
1237
- color: var(--c15t-text-on-primary, #fff);
1318
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
1319
+ border-color: var(--c15t-devtools-border-strong, #e3e3e3);
1320
+ color: var(--c15t-text, #171717);
1321
+ box-shadow: var(--c15t-shadow-sm, 0 1px 2px #0000000d);
1238
1322
  }
1239
1323
 
1240
1324
  .tabActive-r4hing:hover {
1241
- background-color: var(--c15t-primary-hover, #03f);
1242
- color: var(--c15t-text-on-primary, #fff);
1325
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
1326
+ color: var(--c15t-text, #171717);
1243
1327
  }
1244
1328
 
1245
1329
  .tabIcon-U9tnu0 {
@@ -1248,6 +1332,131 @@ var __webpack_modules__ = {
1248
1332
  height: 14px;
1249
1333
  }
1250
1334
 
1335
+ .tabHidden-HBXYSd {
1336
+ display: none;
1337
+ }
1338
+
1339
+ .overflowContainer-TTw9DO {
1340
+ flex-shrink: 0;
1341
+ position: relative;
1342
+ }
1343
+
1344
+ .overflowContainerHidden-sQa_XZ {
1345
+ display: none;
1346
+ }
1347
+
1348
+ .overflowButton-tKq4FF {
1349
+ border-radius: var(--c15t-radius-md, .5rem);
1350
+ width: 1.875rem;
1351
+ height: 1.875rem;
1352
+ color: var(--c15t-text-muted, #737373);
1353
+ cursor: pointer;
1354
+ 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));
1355
+ background-color: #0000;
1356
+ border: 1px solid #0000;
1357
+ justify-content: center;
1358
+ align-items: center;
1359
+ padding: 0;
1360
+ display: inline-flex;
1361
+ }
1362
+
1363
+ .overflowButton-tKq4FF:hover {
1364
+ background-color: var(--c15t-devtools-surface-muted, #f7f7f7);
1365
+ color: var(--c15t-text, #171717);
1366
+ }
1367
+
1368
+ .overflowButton-tKq4FF:focus-visible {
1369
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
1370
+ outline: none;
1371
+ }
1372
+
1373
+ .overflowButtonIcon-FSurfC {
1374
+ justify-content: center;
1375
+ align-items: center;
1376
+ width: 14px;
1377
+ height: 14px;
1378
+ display: inline-flex;
1379
+ }
1380
+
1381
+ .overflowMenu-TST0eZ {
1382
+ border: 1px solid var(--c15t-devtools-border-strong, #e3e3e3);
1383
+ border-radius: var(--c15t-radius-md, .5rem);
1384
+ background-color: var(--c15t-devtools-surface-elevated, #fff);
1385
+ min-width: 10rem;
1386
+ box-shadow: var(--c15t-shadow-md, 0 4px 12px #00000014);
1387
+ opacity: 0;
1388
+ transform-origin: 100% 0;
1389
+ pointer-events: none;
1390
+ z-index: 10;
1391
+ 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));
1392
+ flex-direction: column;
1393
+ gap: .125rem;
1394
+ padding: .3125rem;
1395
+ display: flex;
1396
+ position: absolute;
1397
+ top: calc(100% + .375rem);
1398
+ right: 0;
1399
+ transform: translateY(-4px)scale(.98);
1400
+ }
1401
+
1402
+ .overflowMenu-TST0eZ[data-state="open"] {
1403
+ opacity: 1;
1404
+ pointer-events: auto;
1405
+ transform: translateY(0)scale(1);
1406
+ }
1407
+
1408
+ .overflowItem-y5Pz7k {
1409
+ border-radius: var(--c15t-radius-sm, .375rem);
1410
+ min-height: 1.75rem;
1411
+ color: var(--c15t-text, #171717);
1412
+ font-family: var(--c15t-font-family, system-ui, -apple-system, sans-serif);
1413
+ font-size: var(--c15t-devtools-font-size-xs, .75rem);
1414
+ font-weight: var(--c15t-font-weight-medium, 500);
1415
+ line-height: var(--c15t-line-height-tight, 1.25);
1416
+ text-align: left;
1417
+ cursor: pointer;
1418
+ white-space: nowrap;
1419
+ 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));
1420
+ background-color: #0000;
1421
+ border: none;
1422
+ align-items: center;
1423
+ gap: .5rem;
1424
+ padding: .3125rem .5rem;
1425
+ display: inline-flex;
1426
+ }
1427
+
1428
+ .overflowItem-y5Pz7k:hover {
1429
+ background-color: var(--c15t-devtools-surface-subtle, #fafafa);
1430
+ }
1431
+
1432
+ .overflowItem-y5Pz7k:focus-visible {
1433
+ box-shadow: 0 0 0 2px var(--c15t-devtools-focus-ring, #335cff);
1434
+ outline: none;
1435
+ }
1436
+
1437
+ .overflowItemActive-mzVG1T {
1438
+ background-color: var(--c15t-devtools-accent-soft, #ebefff);
1439
+ color: var(--c15t-text, #171717);
1440
+ }
1441
+
1442
+ .overflowItemDisabled-dcHX3K {
1443
+ opacity: .5;
1444
+ cursor: not-allowed;
1445
+ }
1446
+
1447
+ .overflowItemIcon-fz291V {
1448
+ flex-shrink: 0;
1449
+ justify-content: center;
1450
+ align-items: center;
1451
+ width: 14px;
1452
+ height: 14px;
1453
+ display: inline-flex;
1454
+ }
1455
+
1456
+ .overflowItemHidden-k4aawi {
1457
+ display: none;
1458
+ }
1459
+
1251
1460
  .tabDisabled-lDuv5l {
1252
1461
  opacity: .5;
1253
1462
  cursor: not-allowed;
@@ -1268,7 +1477,7 @@ var __webpack_modules__ = {
1268
1477
  }
1269
1478
 
1270
1479
  @media (prefers-reduced-motion: reduce) {
1271
- .tab-yfDEqg {
1480
+ .tab-yfDEqg, .overflowButton-tKq4FF, .overflowMenu-TST0eZ, .overflowItem-y5Pz7k {
1272
1481
  transition: none;
1273
1482
  }
1274
1483
  }
@@ -1284,9 +1493,21 @@ var __webpack_modules__ = {
1284
1493
  ]);
1285
1494
  ___CSS_LOADER_EXPORT___.locals = {
1286
1495
  tabList: "tabList-IyuiBE",
1496
+ tabStrip: "tabStrip-_KrWe4",
1287
1497
  tab: "tab-yfDEqg",
1288
1498
  tabActive: "tabActive-r4hing",
1289
1499
  tabIcon: "tabIcon-U9tnu0",
1500
+ tabHidden: "tabHidden-HBXYSd",
1501
+ overflowContainer: "overflowContainer-TTw9DO",
1502
+ overflowContainerHidden: "overflowContainerHidden-sQa_XZ",
1503
+ overflowButton: "overflowButton-tKq4FF",
1504
+ overflowButtonIcon: "overflowButtonIcon-FSurfC",
1505
+ overflowMenu: "overflowMenu-TST0eZ",
1506
+ overflowItem: "overflowItem-y5Pz7k",
1507
+ overflowItemActive: "overflowItemActive-mzVG1T",
1508
+ overflowItemDisabled: "overflowItemDisabled-dcHX3K",
1509
+ overflowItemIcon: "overflowItemIcon-fz291V",
1510
+ overflowItemHidden: "overflowItemHidden-k4aawi",
1290
1511
  tabDisabled: "tabDisabled-lDuv5l",
1291
1512
  tabPanel: "tabPanel-QKO8FX",
1292
1513
  tabPanelActive: "tabPanelActive-mrNlGE"
@@ -1310,6 +1531,15 @@ var __webpack_modules__ = {
1310
1531
  --c15t-devtools-button-size: 40px;
1311
1532
  --c15t-devtools-z-index: 99999;
1312
1533
  --c15t-devtools-surface-muted: var(--c15t-surface-hover, #f7f7f7);
1534
+ --c15t-devtools-surface-subtle: #fafafa;
1535
+ --c15t-devtools-surface-elevated: var(--c15t-surface, #fff);
1536
+ --c15t-devtools-border-strong: var(--c15t-border, #e3e3e3);
1537
+ --c15t-devtools-code-surface: #f7f7f7;
1538
+ --c15t-devtools-accent-soft: #ebefff;
1539
+ --c15t-devtools-focus-ring: var(--c15t-primary, #335cff);
1540
+ --c15t-devtools-text-muted: var(--c15t-text-muted, #737373);
1541
+ --c15t-devtools-font-size-sm: var(--c15t-font-size-sm, .875rem);
1542
+ --c15t-surface-muted: var(--c15t-devtools-surface-muted, #f7f7f7);
1313
1543
  --c15t-devtools-font-size-xs: .75rem;
1314
1544
  --c15t-devtools-badge-success: #21c45d;
1315
1545
  --c15t-devtools-badge-success-bg: #e4fbed;
@@ -1323,8 +1553,37 @@ var __webpack_modules__ = {
1323
1553
  --c15t-devtools-badge-neutral-bg: #f0f0f0;
1324
1554
  }
1325
1555
 
1556
+ :is(:global(.c15t-light), :global(.light)) {
1557
+ --c15t-devtools-surface-muted: var(--c15t-surface-hover, #f7f7f7);
1558
+ --c15t-devtools-surface-subtle: #fafafa;
1559
+ --c15t-devtools-surface-elevated: var(--c15t-surface, #fff);
1560
+ --c15t-devtools-border-strong: var(--c15t-border, #e3e3e3);
1561
+ --c15t-devtools-code-surface: #f7f7f7;
1562
+ --c15t-devtools-accent-soft: #ebefff;
1563
+ --c15t-devtools-badge-success-bg: #e4fbed;
1564
+ --c15t-devtools-badge-error-bg: #fde7e7;
1565
+ --c15t-devtools-badge-warning-bg: #fef7dc;
1566
+ --c15t-devtools-badge-info-bg: #dcebfe;
1567
+ --c15t-devtools-badge-neutral-bg: #f0f0f0;
1568
+ }
1569
+
1570
+ @supports (color: color-mix(in srgb, white, black)) {
1571
+ :root {
1572
+ --c15t-devtools-surface-muted: color-mix(in srgb, var(--c15t-surface-hover, #f7f7f7) 85%, var(--c15t-surface, #fff));
1573
+ --c15t-devtools-surface-subtle: color-mix(in srgb, var(--c15t-surface-hover, #f7f7f7) 55%, var(--c15t-surface, #fff));
1574
+ --c15t-devtools-border-strong: color-mix(in srgb, var(--c15t-border, #e3e3e3) 80%, var(--c15t-text-muted, #737373));
1575
+ --c15t-devtools-code-surface: color-mix(in srgb, var(--c15t-surface-hover, #f7f7f7) 70%, var(--c15t-surface, #fff));
1576
+ --c15t-devtools-accent-soft: color-mix(in srgb, var(--c15t-primary, #335cff) 12%, transparent);
1577
+ }
1578
+ }
1579
+
1326
1580
  :is(:global(.c15t-dark), :global(.dark)) {
1327
1581
  --c15t-devtools-surface-muted: var(--c15t-surface-hover, #292929);
1582
+ --c15t-devtools-surface-subtle: #242424;
1583
+ --c15t-devtools-surface-elevated: var(--c15t-surface, #1a1a1a);
1584
+ --c15t-devtools-border-strong: var(--c15t-border, #3d3d3d);
1585
+ --c15t-devtools-code-surface: #212121;
1586
+ --c15t-devtools-accent-soft: #335cff33;
1328
1587
  --c15t-devtools-badge-success-bg: #21c45d33;
1329
1588
  --c15t-devtools-badge-error-bg: #ef434333;
1330
1589
  --c15t-devtools-badge-warning-bg: #f59f0a33;
@@ -1333,8 +1592,13 @@ var __webpack_modules__ = {
1333
1592
  }
1334
1593
 
1335
1594
  @media (prefers-color-scheme: dark) {
1336
- :root {
1595
+ :global(:root:not(.light):not(.c15t-light)) {
1337
1596
  --c15t-devtools-surface-muted: var(--c15t-surface-hover, #292929);
1597
+ --c15t-devtools-surface-subtle: #242424;
1598
+ --c15t-devtools-surface-elevated: var(--c15t-surface, #1a1a1a);
1599
+ --c15t-devtools-border-strong: var(--c15t-border, #3d3d3d);
1600
+ --c15t-devtools-code-surface: #212121;
1601
+ --c15t-devtools-accent-soft: #335cff33;
1338
1602
  --c15t-devtools-badge-success-bg: #21c45d33;
1339
1603
  --c15t-devtools-badge-error-bg: #ef434333;
1340
1604
  --c15t-devtools-badge-warning-bg: #f59f0a33;
@@ -1724,7 +1988,28 @@ panel_module_options.domAPI = styleDomAPI_default();
1724
1988
  panel_module_options.insertStyleElement = insertStyleElement_default();
1725
1989
  injectStylesIntoStyleTag_default()(panel_module.A, panel_module_options);
1726
1990
  panel_module.A && panel_module.A.locals && panel_module.A.locals;
1727
- '[data-c15t-trigger], [aria-label*="privacy settings"], [aria-label*="preference"]';
1991
+ function init_source_formatInitSource(source, detail) {
1992
+ const label = (()=>{
1993
+ switch(source){
1994
+ case 'ssr':
1995
+ return 'SSR Prefetch';
1996
+ case 'backend':
1997
+ return 'Backend';
1998
+ case 'backend-cache-hit':
1999
+ return 'Backend (Cache Hit)';
2000
+ case 'offline-fallback':
2001
+ return 'Offline Fallback';
2002
+ case 'offline-mode':
2003
+ return 'Offline Mode';
2004
+ case 'custom':
2005
+ return 'Custom Client';
2006
+ default:
2007
+ return '—';
2008
+ }
2009
+ })();
2010
+ return detail ? `${label} [${detail}]` : label;
2011
+ }
2012
+ '[data-c15t-trigger], [aria-label*="privacy settings" i], [aria-label*="preference" i]';
1728
2013
  var tabs_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/tabs.module.css");
1729
2014
  var tabs_module_options = {};
1730
2015
  tabs_module_options.styleTagTransform = styleTagTransform_default();
@@ -1743,6 +2028,11 @@ const LOCATION_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 2
1743
2028
  <line x1="2" y1="12" x2="22" y2="12"></line>
1744
2029
  <path d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"></path>
1745
2030
  </svg>`;
2031
+ const POLICY_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">
2032
+ <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
2033
+ <path d="M9 12h6"></path>
2034
+ <path d="M12 9v6"></path>
2035
+ </svg>`;
1746
2036
  const SCRIPTS_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">
1747
2037
  <polyline points="16 18 22 12 16 6"></polyline>
1748
2038
  <polyline points="8 6 2 12 8 18"></polyline>
@@ -1759,12 +2049,22 @@ const EVENTS_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
1759
2049
  <path d="M12 20h9"></path>
1760
2050
  <path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"></path>
1761
2051
  </svg>`;
2052
+ const MORE_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
2053
+ <circle cx="12" cy="5" r="1.75"></circle>
2054
+ <circle cx="12" cy="12" r="1.75"></circle>
2055
+ <circle cx="12" cy="19" r="1.75"></circle>
2056
+ </svg>`;
1762
2057
  const TABS = [
1763
2058
  {
1764
2059
  id: 'location',
1765
2060
  label: 'Location',
1766
2061
  icon: LOCATION_ICON
1767
2062
  },
2063
+ {
2064
+ id: 'policy',
2065
+ label: 'Policy',
2066
+ icon: POLICY_ICON
2067
+ },
1768
2068
  {
1769
2069
  id: 'consents',
1770
2070
  label: 'Consents',
@@ -1794,12 +2094,56 @@ const TABS = [
1794
2094
  function tabs_createTabs(options) {
1795
2095
  const { onTabChange, disabledTabs = [] } = options;
1796
2096
  let activeTab = options.activeTab;
2097
+ let isOverflowMenuOpen = false;
2098
+ let visibleTabIds = [];
2099
+ let hiddenTabIds = [];
1797
2100
  const tabButtons = new Map();
2101
+ const overflowButtons = new Map();
1798
2102
  const tabList = renderer_div({
1799
- className: styles_tabs_module.tabList,
2103
+ className: styles_tabs_module.tabList
2104
+ });
2105
+ const tabStrip = renderer_div({
2106
+ className: styles_tabs_module.tabStrip,
1800
2107
  role: 'tablist',
1801
2108
  ariaLabel: 'DevTools tabs'
1802
2109
  });
2110
+ tabList.appendChild(tabStrip);
2111
+ const overflowMenu = renderer_div({
2112
+ className: styles_tabs_module.overflowMenu,
2113
+ role: 'menu',
2114
+ ariaLabel: 'All tabs'
2115
+ });
2116
+ overflowMenu.dataset.state = 'closed';
2117
+ const overflowButton = renderer_button({
2118
+ className: styles_tabs_module.overflowButton,
2119
+ ariaLabel: 'More tabs',
2120
+ ariaExpanded: 'false',
2121
+ onClick: ()=>toggleOverflowMenu(),
2122
+ onKeyDown: (e)=>{
2123
+ if ('ArrowDown' === e.key || 'Enter' === e.key || ' ' === e.key) {
2124
+ e.preventDefault();
2125
+ openOverflowMenu();
2126
+ focusFirstEnabledOverflowItem();
2127
+ }
2128
+ }
2129
+ });
2130
+ overflowButton.setAttribute('aria-haspopup', 'menu');
2131
+ const overflowIcon = renderer_div({
2132
+ className: styles_tabs_module.overflowButtonIcon
2133
+ });
2134
+ overflowIcon.appendChild(renderer_createSvgElement(MORE_ICON, {
2135
+ width: 14,
2136
+ height: 14
2137
+ }));
2138
+ overflowButton.appendChild(overflowIcon);
2139
+ const overflowContainer = renderer_div({
2140
+ className: styles_tabs_module.overflowContainer,
2141
+ children: [
2142
+ overflowButton,
2143
+ overflowMenu
2144
+ ]
2145
+ });
2146
+ tabList.appendChild(overflowContainer);
1803
2147
  for (const tab of TABS){
1804
2148
  const isActive = tab.id === activeTab;
1805
2149
  const isDisabled = disabledTabs.includes(tab.id);
@@ -1813,6 +2157,7 @@ function tabs_createTabs(options) {
1813
2157
  disabled: isDisabled,
1814
2158
  onClick: ()=>{
1815
2159
  if (!isDisabled) {
2160
+ closeOverflowMenu();
1816
2161
  setActiveTab(tab.id);
1817
2162
  onTabChange(tab.id);
1818
2163
  }
@@ -1829,22 +2174,200 @@ function tabs_createTabs(options) {
1829
2174
  tabButton.appendChild(iconWrapper);
1830
2175
  tabButton.appendChild(document.createTextNode(tab.label));
1831
2176
  tabButtons.set(tab.id, tabButton);
1832
- tabList.appendChild(tabButton);
2177
+ tabStrip.appendChild(tabButton);
2178
+ const overflowItem = renderer_button({
2179
+ className: `${styles_tabs_module.overflowItem} ${isActive ? styles_tabs_module.overflowItemActive : ''} ${isDisabled ? styles_tabs_module.overflowItemDisabled : ''}`,
2180
+ role: 'menuitemradio',
2181
+ ariaChecked: isActive ? 'true' : 'false',
2182
+ disabled: isDisabled,
2183
+ onClick: ()=>{
2184
+ if (!isDisabled) {
2185
+ setActiveTab(tab.id);
2186
+ onTabChange(tab.id);
2187
+ closeOverflowMenu();
2188
+ tabButtons.get(tab.id)?.focus();
2189
+ }
2190
+ },
2191
+ onKeyDown: (e)=>handleOverflowKeyDown(e, tab.id)
2192
+ });
2193
+ const overflowItemIcon = renderer_div({
2194
+ className: styles_tabs_module.overflowItemIcon
2195
+ });
2196
+ overflowItemIcon.appendChild(renderer_createSvgElement(tab.icon, {
2197
+ width: 14,
2198
+ height: 14
2199
+ }));
2200
+ overflowItem.appendChild(overflowItemIcon);
2201
+ overflowItem.appendChild(document.createTextNode(tab.label));
2202
+ overflowButtons.set(tab.id, overflowItem);
2203
+ overflowMenu.appendChild(overflowItem);
1833
2204
  }
1834
- function handleKeyDown(e, currentTab) {
1835
- const tabIds = TABS.map((t)=>t.id);
1836
- const enabledTabIds = tabIds.filter((id)=>!disabledTabs.includes(id));
1837
- const currentIndex = enabledTabIds.indexOf(currentTab);
1838
- let newIndex = currentIndex;
1839
- switch(e.key){
1840
- case 'ArrowLeft':
1841
- newIndex = currentIndex > 0 ? currentIndex - 1 : enabledTabIds.length - 1;
1842
- break;
1843
- case 'ArrowRight':
1844
- newIndex = currentIndex < enabledTabIds.length - 1 ? currentIndex + 1 : 0;
1845
- break;
1846
- case 'Home':
1847
- newIndex = 0;
2205
+ function applyActiveState(tab) {
2206
+ for (const [tabId, tabButton] of tabButtons){
2207
+ const isActive = tabId === tab;
2208
+ if (styles_tabs_module.tabActive) tabButton.classList.toggle(styles_tabs_module.tabActive, isActive);
2209
+ tabButton.setAttribute('aria-selected', isActive ? 'true' : 'false');
2210
+ tabButton.tabIndex = isActive ? 0 : -1;
2211
+ }
2212
+ for (const [tabId, overflowItem] of overflowButtons){
2213
+ const isActive = tabId === tab;
2214
+ if (styles_tabs_module.overflowItemActive) overflowItem.classList.toggle(styles_tabs_module.overflowItemActive, isActive);
2215
+ overflowItem.setAttribute('aria-checked', isActive ? 'true' : 'false');
2216
+ }
2217
+ }
2218
+ function updateVisibleTabs() {
2219
+ const allTabIds = TABS.map((t)=>t.id);
2220
+ const iabEnabled = !disabledTabs.includes('iab');
2221
+ const preferredSecondTab = iabEnabled ? 'iab' : 'consents';
2222
+ const overflowSecondTab = iabEnabled ? 'consents' : 'iab';
2223
+ const showOverflowSecondTabInStrip = activeTab === overflowSecondTab;
2224
+ const stripSecondTab = showOverflowSecondTabInStrip ? overflowSecondTab : preferredSecondTab;
2225
+ const forcedOverflowTab = showOverflowSecondTabInStrip ? preferredSecondTab : overflowSecondTab;
2226
+ const layoutTabIds = [
2227
+ 'location',
2228
+ 'policy',
2229
+ stripSecondTab,
2230
+ "scripts",
2231
+ 'actions',
2232
+ 'events',
2233
+ forcedOverflowTab
2234
+ ];
2235
+ const forcedOverflowTabIds = new Set();
2236
+ forcedOverflowTabIds.add(forcedOverflowTab);
2237
+ for (const [index, tabId] of layoutTabIds.entries()){
2238
+ const tabButton = tabButtons.get(tabId);
2239
+ if (tabButton) tabButton.style.order = String(index);
2240
+ const overflowItem = overflowButtons.get(tabId);
2241
+ if (overflowItem) overflowItem.style.order = String(index);
2242
+ }
2243
+ for (const tabId of allTabIds){
2244
+ const tabButton = tabButtons.get(tabId);
2245
+ if (tabButton && styles_tabs_module.tabHidden) tabButton.classList.remove(styles_tabs_module.tabHidden);
2246
+ }
2247
+ if (styles_tabs_module.overflowContainerHidden) overflowContainer.classList.remove(styles_tabs_module.overflowContainerHidden);
2248
+ const stripGap = Number.parseFloat(getComputedStyle(tabStrip).gap || '0');
2249
+ const calculateVisibleTabs = (availableWidth)=>{
2250
+ if (availableWidth <= 0) return [];
2251
+ const nextVisible = [];
2252
+ let usedWidth = 0;
2253
+ for (const tabId of layoutTabIds){
2254
+ if (forcedOverflowTabIds.has(tabId)) continue;
2255
+ const tabButton = tabButtons.get(tabId);
2256
+ if (!tabButton) continue;
2257
+ const width = tabButton.getBoundingClientRect().width;
2258
+ const nextUsed = 0 === nextVisible.length ? width : usedWidth + stripGap + width;
2259
+ if (nextUsed <= availableWidth) {
2260
+ nextVisible.push(tabId);
2261
+ usedWidth = nextUsed;
2262
+ } else break;
2263
+ }
2264
+ return nextVisible;
2265
+ };
2266
+ const measureStripWidth = ()=>tabStrip.getBoundingClientRect().width;
2267
+ const showOverflowContainer = ()=>{
2268
+ if (styles_tabs_module.overflowContainerHidden) overflowContainer.classList.remove(styles_tabs_module.overflowContainerHidden);
2269
+ };
2270
+ const hideOverflowContainer = ()=>{
2271
+ if (styles_tabs_module.overflowContainerHidden) overflowContainer.classList.add(styles_tabs_module.overflowContainerHidden);
2272
+ };
2273
+ const measureVisibleWidth = (tabIds)=>{
2274
+ let width = 0;
2275
+ for (const [index, tabId] of tabIds.entries()){
2276
+ const tabButton = tabButtons.get(tabId);
2277
+ if (tabButton) {
2278
+ width += tabButton.getBoundingClientRect().width;
2279
+ if (index > 0) width += stripGap;
2280
+ }
2281
+ }
2282
+ return width;
2283
+ };
2284
+ if (0 === forcedOverflowTabIds.size) {
2285
+ hideOverflowContainer();
2286
+ const visibleWithoutOverflow = calculateVisibleTabs(measureStripWidth());
2287
+ if (visibleWithoutOverflow.length === layoutTabIds.length) visibleTabIds = visibleWithoutOverflow;
2288
+ else {
2289
+ showOverflowContainer();
2290
+ visibleTabIds = calculateVisibleTabs(measureStripWidth());
2291
+ }
2292
+ } else {
2293
+ showOverflowContainer();
2294
+ const withOverflow = calculateVisibleTabs(measureStripWidth());
2295
+ visibleTabIds = withOverflow.length > 0 ? withOverflow : [
2296
+ activeTab
2297
+ ];
2298
+ }
2299
+ if (!visibleTabIds.includes(activeTab) && !disabledTabs.includes(activeTab)) if (visibleTabIds.length > 0) visibleTabIds[visibleTabIds.length - 1] = activeTab;
2300
+ else visibleTabIds = [
2301
+ activeTab
2302
+ ];
2303
+ visibleTabIds = [
2304
+ ...new Set(visibleTabIds)
2305
+ ];
2306
+ const maxStripWidth = measureStripWidth();
2307
+ while(visibleTabIds.length > 1 && measureVisibleWidth(visibleTabIds) > maxStripWidth + 0.5){
2308
+ let removeIndex = visibleTabIds.length - 1;
2309
+ if (visibleTabIds[removeIndex] === activeTab) removeIndex = Math.max(0, removeIndex - 1);
2310
+ visibleTabIds.splice(removeIndex, 1);
2311
+ }
2312
+ hiddenTabIds = layoutTabIds.filter((tabId)=>!visibleTabIds.includes(tabId) || forcedOverflowTabIds.has(tabId) && tabId !== activeTab);
2313
+ for (const tabId of allTabIds){
2314
+ const tabButton = tabButtons.get(tabId);
2315
+ if (tabButton) {
2316
+ if (styles_tabs_module.tabHidden) tabButton.classList.toggle(styles_tabs_module.tabHidden, hiddenTabIds.includes(tabId));
2317
+ }
2318
+ }
2319
+ for (const tabId of allTabIds){
2320
+ const overflowItem = overflowButtons.get(tabId);
2321
+ if (overflowItem) {
2322
+ if (styles_tabs_module.overflowItemHidden) overflowItem.classList.toggle(styles_tabs_module.overflowItemHidden, !hiddenTabIds.includes(tabId));
2323
+ }
2324
+ }
2325
+ if (styles_tabs_module.overflowContainerHidden) overflowContainer.classList.toggle(styles_tabs_module.overflowContainerHidden, 0 === hiddenTabIds.length);
2326
+ if (0 === hiddenTabIds.length) closeOverflowMenu();
2327
+ }
2328
+ function focusFirstEnabledOverflowItem() {
2329
+ const firstEnabled = hiddenTabIds.find((tabId)=>!disabledTabs.includes(tabId));
2330
+ if (firstEnabled) overflowButtons.get(firstEnabled)?.focus();
2331
+ }
2332
+ function openOverflowMenu() {
2333
+ if (isOverflowMenuOpen || 0 === hiddenTabIds.length) return;
2334
+ isOverflowMenuOpen = true;
2335
+ overflowMenu.dataset.state = 'open';
2336
+ overflowButton.setAttribute('aria-expanded', 'true');
2337
+ document.addEventListener('click', handleOutsideClick);
2338
+ document.addEventListener('keydown', handleEscapeKey);
2339
+ }
2340
+ function closeOverflowMenu() {
2341
+ if (!isOverflowMenuOpen) return;
2342
+ isOverflowMenuOpen = false;
2343
+ overflowMenu.dataset.state = 'closed';
2344
+ overflowButton.setAttribute('aria-expanded', 'false');
2345
+ document.removeEventListener('click', handleOutsideClick);
2346
+ document.removeEventListener('keydown', handleEscapeKey);
2347
+ }
2348
+ function toggleOverflowMenu() {
2349
+ if (isOverflowMenuOpen) closeOverflowMenu();
2350
+ else openOverflowMenu();
2351
+ }
2352
+ function handleOutsideClick(e) {
2353
+ if (!overflowContainer.contains(e.target)) closeOverflowMenu();
2354
+ }
2355
+ function handleEscapeKey(e) {
2356
+ if ('Escape' === e.key) closeOverflowMenu();
2357
+ }
2358
+ function handleKeyDown(e, currentTab) {
2359
+ const enabledTabIds = visibleTabIds.filter((tabId)=>!disabledTabs.includes(tabId));
2360
+ const currentIndex = enabledTabIds.indexOf(currentTab);
2361
+ let newIndex = currentIndex;
2362
+ switch(e.key){
2363
+ case 'ArrowLeft':
2364
+ newIndex = currentIndex > 0 ? currentIndex - 1 : enabledTabIds.length - 1;
2365
+ break;
2366
+ case 'ArrowRight':
2367
+ newIndex = currentIndex < enabledTabIds.length - 1 ? currentIndex + 1 : 0;
2368
+ break;
2369
+ case 'Home':
2370
+ newIndex = 0;
1848
2371
  break;
1849
2372
  case 'End':
1850
2373
  newIndex = enabledTabIds.length - 1;
@@ -1860,23 +2383,152 @@ function tabs_createTabs(options) {
1860
2383
  tabButtons.get(newTab)?.focus();
1861
2384
  }
1862
2385
  }
2386
+ function handleOverflowKeyDown(e, currentTab) {
2387
+ const enabledTabIds = hiddenTabIds.filter((tabId)=>!disabledTabs.includes(tabId));
2388
+ const currentIndex = enabledTabIds.indexOf(currentTab);
2389
+ if ('Escape' === e.key) {
2390
+ e.preventDefault();
2391
+ closeOverflowMenu();
2392
+ overflowButton.focus();
2393
+ return;
2394
+ }
2395
+ let newIndex = currentIndex;
2396
+ switch(e.key){
2397
+ case 'ArrowDown':
2398
+ newIndex = (currentIndex + 1) % enabledTabIds.length;
2399
+ break;
2400
+ case 'ArrowUp':
2401
+ newIndex = currentIndex > 0 ? currentIndex - 1 : enabledTabIds.length - 1;
2402
+ break;
2403
+ default:
2404
+ return;
2405
+ }
2406
+ e.preventDefault();
2407
+ const newTab = enabledTabIds[newIndex];
2408
+ if (newTab) overflowButtons.get(newTab)?.focus();
2409
+ }
1863
2410
  function setActiveTab(tab) {
1864
2411
  activeTab = tab;
1865
- for (const [tabId, tabButton] of tabButtons){
1866
- const isActive = tabId === tab;
1867
- if (styles_tabs_module.tabActive) tabButton.classList.toggle(styles_tabs_module.tabActive, isActive);
1868
- tabButton.setAttribute('aria-selected', isActive ? 'true' : 'false');
1869
- tabButton.tabIndex = isActive ? 0 : -1;
1870
- }
2412
+ applyActiveState(tab);
2413
+ updateVisibleTabs();
1871
2414
  }
2415
+ const handleWindowResize = ()=>{
2416
+ updateVisibleTabs();
2417
+ };
2418
+ let resizeObserver = null;
2419
+ if ('undefined' != typeof ResizeObserver) {
2420
+ resizeObserver = new ResizeObserver(()=>{
2421
+ updateVisibleTabs();
2422
+ });
2423
+ resizeObserver.observe(tabList);
2424
+ } else window.addEventListener('resize', handleWindowResize);
2425
+ applyActiveState(activeTab);
2426
+ requestAnimationFrame(()=>{
2427
+ updateVisibleTabs();
2428
+ });
1872
2429
  return {
1873
2430
  element: tabList,
1874
2431
  setActiveTab,
1875
2432
  destroy: ()=>{
2433
+ closeOverflowMenu();
2434
+ if (resizeObserver) {
2435
+ resizeObserver.disconnect();
2436
+ resizeObserver = null;
2437
+ } else window.removeEventListener('resize', handleWindowResize);
1876
2438
  tabButtons.clear();
2439
+ overflowButtons.clear();
1877
2440
  }
1878
2441
  };
1879
2442
  }
2443
+ function debug_bundle_createDebugBundle(payload) {
2444
+ const { namespace, devToolsState, connection, recentEvents, storeState } = payload;
2445
+ const bundle = {
2446
+ generatedAt: new Date().toISOString(),
2447
+ namespace,
2448
+ devToolsState,
2449
+ connection,
2450
+ recentEvents,
2451
+ storeState,
2452
+ overrides: storeState?.overrides ?? null,
2453
+ iab: storeState?.iab ? {
2454
+ tcString: (storeState?.iab).tcString ?? null,
2455
+ purposeCount: Object.keys((storeState?.iab).purposeConsents ?? {}).length,
2456
+ vendorCount: Object.keys((storeState?.iab).vendorConsents ?? {}).length
2457
+ } : null
2458
+ };
2459
+ return JSON.stringify(bundle, null, 2);
2460
+ }
2461
+ function debug_bundle_sanitizeStoreState(state) {
2462
+ if (!state) return null;
2463
+ try {
2464
+ return JSON.parse(JSON.stringify(state, (_key, value)=>'function' == typeof value ? void 0 : value));
2465
+ } catch {
2466
+ return {
2467
+ error: 'Unable to serialize store state'
2468
+ };
2469
+ }
2470
+ }
2471
+ function debug_bundle_downloadDebugBundle(content) {
2472
+ const blob = new Blob([
2473
+ content
2474
+ ], {
2475
+ type: 'application/json'
2476
+ });
2477
+ const url = URL.createObjectURL(blob);
2478
+ const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
2479
+ const anchor = document.createElement('a');
2480
+ anchor.href = url;
2481
+ anchor.download = `c15t-debug-bundle-${timestamp}.json`;
2482
+ anchor.click();
2483
+ URL.revokeObjectURL(url);
2484
+ }
2485
+ const DEVTOOLS_OVERRIDES_STORAGE_KEY = 'c15t-devtools-overrides';
2486
+ function normalizeStringValue(value) {
2487
+ if ('string' != typeof value) return;
2488
+ const normalized = value.trim();
2489
+ return normalized.length > 0 ? normalized : void 0;
2490
+ }
2491
+ function normalizeBooleanValue(value) {
2492
+ return 'boolean' == typeof value ? value : void 0;
2493
+ }
2494
+ function normalizeOverrides(value) {
2495
+ if (!value || 'object' != typeof value) return null;
2496
+ const source = value;
2497
+ const overrides = {
2498
+ country: normalizeStringValue(source.country),
2499
+ region: normalizeStringValue(source.region),
2500
+ language: normalizeStringValue(source.language),
2501
+ gpc: normalizeBooleanValue(source.gpc)
2502
+ };
2503
+ return hasPersistedOverrides(overrides) ? overrides : null;
2504
+ }
2505
+ function hasPersistedOverrides(overrides) {
2506
+ return Boolean(overrides.country || overrides.region || overrides.language || void 0 !== overrides.gpc);
2507
+ }
2508
+ function override_storage_loadPersistedOverrides(storageKey = DEVTOOLS_OVERRIDES_STORAGE_KEY) {
2509
+ if ('undefined' == typeof window) return null;
2510
+ try {
2511
+ const stored = localStorage.getItem(storageKey);
2512
+ if (!stored) return null;
2513
+ const parsed = JSON.parse(stored);
2514
+ return normalizeOverrides(parsed);
2515
+ } catch {
2516
+ return null;
2517
+ }
2518
+ }
2519
+ function override_storage_persistOverrides(overrides, storageKey = DEVTOOLS_OVERRIDES_STORAGE_KEY) {
2520
+ if ('undefined' == typeof window) return;
2521
+ try {
2522
+ if (!hasPersistedOverrides(overrides)) return void localStorage.removeItem(storageKey);
2523
+ localStorage.setItem(storageKey, JSON.stringify(overrides));
2524
+ } catch {}
2525
+ }
2526
+ function override_storage_clearPersistedOverrides(storageKey = DEVTOOLS_OVERRIDES_STORAGE_KEY) {
2527
+ if ('undefined' == typeof window) return;
2528
+ try {
2529
+ localStorage.removeItem(storageKey);
2530
+ } catch {}
2531
+ }
1880
2532
  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");
1881
2533
  var components_module_options = {};
1882
2534
  components_module_options.styleTagTransform = styleTagTransform_default();
@@ -1944,31 +2596,19 @@ function createButton(options) {
1944
2596
  btn.appendChild(document.createTextNode(text));
1945
2597
  return btn;
1946
2598
  }
1947
- function createListItem(options) {
1948
- const { title, description, actions = [] } = options;
1949
- const content = renderer_div({
1950
- className: styles_components_module.listItemContent,
1951
- children: [
1952
- renderer_span({
1953
- className: styles_components_module.listItemTitle,
1954
- text: title
1955
- }),
1956
- description ? renderer_span({
1957
- className: styles_components_module.listItemDescription,
1958
- text: description
1959
- }) : null
1960
- ]
1961
- });
1962
- const actionsContainer = renderer_div({
1963
- className: styles_components_module.listItemActions,
1964
- children: actions
1965
- });
1966
- return renderer_div({
1967
- className: styles_components_module.listItem,
1968
- children: [
1969
- content,
1970
- actionsContainer
1971
- ]
2599
+ function createInput(options) {
2600
+ const { value, placeholder, ariaLabel, small = false, onInput } = options;
2601
+ const sizeClass = small ? styles_components_module.inputSmall : '';
2602
+ return input({
2603
+ className: `${styles_components_module.input} ${sizeClass}`.trim(),
2604
+ type: 'text',
2605
+ value,
2606
+ placeholder,
2607
+ ariaLabel,
2608
+ onInput: (event)=>{
2609
+ const target = event.target;
2610
+ onInput?.(target?.value ?? '');
2611
+ }
1972
2612
  });
1973
2613
  }
1974
2614
  function createSection(options) {
@@ -2051,6 +2691,18 @@ function createGridCard(options) {
2051
2691
  children
2052
2692
  });
2053
2693
  }
2694
+ function createDisconnectedState(message = 'Store not connected') {
2695
+ return renderer_div({
2696
+ className: styles_components_module.disconnectedState,
2697
+ style: {
2698
+ padding: '24px',
2699
+ textAlign: 'center',
2700
+ color: 'var(--c15t-text-muted)',
2701
+ fontSize: 'var(--c15t-devtools-font-size-sm)'
2702
+ },
2703
+ text: message
2704
+ });
2705
+ }
2054
2706
  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">
2055
2707
  <path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"></path>
2056
2708
  <path d="M21 3v5h-5"></path>
@@ -2078,19 +2730,11 @@ const TERMINAL_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 2
2078
2730
  <polyline points="4 17 10 11 4 5"></polyline>
2079
2731
  <line x1="12" y1="19" x2="20" y2="19"></line>
2080
2732
  </svg>`;
2081
- function actions_renderActionsPanel(container, options) {
2082
- const { getState, onResetConsents, onRefetchBanner, onShowBanner, onOpenPreferences, onCopyState } = options;
2733
+ function renderActionsPanel(container, options) {
2734
+ const { getState, onResetConsents, onRefetchBanner, onShowBanner, onOpenPreferences, onCopyState, onExportDebugBundle } = options;
2083
2735
  renderer_clearElement(container);
2084
2736
  const state = getState();
2085
- if (!state) return void container.appendChild(renderer_div({
2086
- style: {
2087
- padding: '24px',
2088
- textAlign: 'center',
2089
- color: 'var(--c15t-text-muted)',
2090
- fontSize: 'var(--c15t-devtools-font-size-sm)'
2091
- },
2092
- text: 'Store not connected'
2093
- }));
2737
+ if (!state) return void container.appendChild(createDisconnectedState());
2094
2738
  const actionCards = [
2095
2739
  createActionCard({
2096
2740
  icon: actions_EYE_ICON,
@@ -2111,6 +2755,12 @@ function actions_renderActionsPanel(container, options) {
2111
2755
  icon: COPY_ICON,
2112
2756
  label: 'Copy State',
2113
2757
  onClick: onCopyState
2758
+ }),
2759
+ createActionCard({
2760
+ icon: REFRESH_ICON,
2761
+ label: 'Export Debug',
2762
+ onClick: ()=>onExportDebugBundle?.(),
2763
+ disabled: !onExportDebugBundle
2114
2764
  })
2115
2765
  ];
2116
2766
  const grid = createGrid({
@@ -2184,7 +2834,7 @@ function actions_renderActionsPanel(container, options) {
2184
2834
  container.appendChild(consoleSection);
2185
2835
  }
2186
2836
  function createActionCard(options) {
2187
- const { icon, label, onClick } = options;
2837
+ const { icon, label, onClick, disabled = false } = options;
2188
2838
  const card = renderer_div({
2189
2839
  className: styles_components_module.gridCard ?? '',
2190
2840
  style: {
@@ -2195,7 +2845,8 @@ function createActionCard(options) {
2195
2845
  gap: '6px',
2196
2846
  padding: '16px 8px',
2197
2847
  cursor: 'pointer',
2198
- transition: 'background-color var(--c15t-duration-fast) var(--c15t-easing)'
2848
+ transition: 'background-color var(--c15t-duration-fast) var(--c15t-easing)',
2849
+ opacity: disabled ? '0.55' : '1'
2199
2850
  },
2200
2851
  children: [
2201
2852
  createIconWrapper(icon, 20),
@@ -2210,13 +2861,15 @@ function createActionCard(options) {
2210
2861
  })
2211
2862
  ]
2212
2863
  });
2213
- card.addEventListener('click', onClick);
2214
- card.addEventListener('mouseenter', ()=>{
2215
- card.style.backgroundColor = 'var(--c15t-surface-hover)';
2216
- });
2217
- card.addEventListener('mouseleave', ()=>{
2218
- card.style.backgroundColor = '';
2219
- });
2864
+ if (!disabled) {
2865
+ card.addEventListener('click', onClick);
2866
+ card.addEventListener('mouseenter', ()=>{
2867
+ card.style.backgroundColor = 'var(--c15t-surface-hover)';
2868
+ });
2869
+ card.addEventListener('mouseleave', ()=>{
2870
+ card.style.backgroundColor = '';
2871
+ });
2872
+ }
2220
2873
  return card;
2221
2874
  }
2222
2875
  function createIconWrapper(icon, size) {
@@ -2237,19 +2890,11 @@ function createIconWrapper(icon, size) {
2237
2890
  function getNamespace(state) {
2238
2891
  return state.config?.meta?.namespace || 'c15tStore';
2239
2892
  }
2240
- function consents_renderConsentsPanel(container, options) {
2893
+ function renderConsentsPanel(container, options) {
2241
2894
  const { getState, onConsentChange, onSave, onAcceptAll, onRejectAll, onReset } = options;
2242
2895
  renderer_clearElement(container);
2243
2896
  const state = getState();
2244
- if (!state) return void container.appendChild(renderer_div({
2245
- style: {
2246
- padding: '24px',
2247
- textAlign: 'center',
2248
- color: 'var(--c15t-text-muted)',
2249
- fontSize: 'var(--c15t-devtools-font-size-sm)'
2250
- },
2251
- text: 'Store not connected'
2252
- }));
2897
+ if (!state) return void container.appendChild(createDisconnectedState());
2253
2898
  const isIabMode = 'iab' === state.model;
2254
2899
  const savedConsents = state.consents || {};
2255
2900
  const selectedConsents = state.selectedConsents || {};
@@ -2407,15 +3052,26 @@ function consents_renderConsentsPanel(container, options) {
2407
3052
  function formatConsentName(name) {
2408
3053
  return name.replace(/_/g, ' ').replace(/\b\w/g, (l)=>l.toUpperCase());
2409
3054
  }
2410
- let activeFilter = 'all';
2411
- let selectedEventId = null;
2412
- function events_renderEventsPanel(container, options) {
3055
+ const panelStateByContainer = new WeakMap();
3056
+ function getPanelState(container) {
3057
+ const existing = panelStateByContainer.get(container);
3058
+ if (existing) return existing;
3059
+ const initialState = {
3060
+ activeFilter: 'all',
3061
+ selectedEventId: null,
3062
+ searchQuery: ''
3063
+ };
3064
+ panelStateByContainer.set(container, initialState);
3065
+ return initialState;
3066
+ }
3067
+ function renderEventsPanel(container, options) {
2413
3068
  const { getEvents, onClear } = options;
3069
+ const panelState = getPanelState(container);
2414
3070
  renderer_clearElement(container);
2415
3071
  const allEvents = getEvents();
2416
- const events = allEvents.filter((event)=>matchesFilter(event, activeFilter));
2417
- if (!events.some((event)=>event.id === selectedEventId)) selectedEventId = events[0]?.id ?? null;
2418
- const selectedEvent = events.find((event)=>event.id === selectedEventId) ?? null;
3072
+ const events = allEvents.filter((event)=>matchesFilter(event, panelState.activeFilter)).filter((event)=>matchesSearch(event, panelState.searchQuery));
3073
+ if (!events.some((event)=>event.id === panelState.selectedEventId)) panelState.selectedEventId = events[0]?.id ?? null;
3074
+ const selectedEvent = events.find((event)=>event.id === panelState.selectedEventId) ?? null;
2419
3075
  const header = renderer_div({
2420
3076
  style: {
2421
3077
  display: 'flex',
@@ -2451,8 +3107,8 @@ function events_renderEventsPanel(container, options) {
2451
3107
  small: true,
2452
3108
  onClick: ()=>{
2453
3109
  onClear();
2454
- selectedEventId = null;
2455
- events_renderEventsPanel(container, options);
3110
+ panelState.selectedEventId = null;
3111
+ renderEventsPanel(container, options);
2456
3112
  }
2457
3113
  })
2458
3114
  ]
@@ -2467,12 +3123,30 @@ function events_renderEventsPanel(container, options) {
2467
3123
  gap: '6px',
2468
3124
  padding: '0 16px 8px'
2469
3125
  },
2470
- children: EVENT_FILTERS.map((filter)=>createFilterButton(filter, filter === activeFilter, ()=>{
2471
- activeFilter = filter;
2472
- selectedEventId = null;
2473
- events_renderEventsPanel(container, options);
3126
+ children: EVENT_FILTERS.map((filter)=>createFilterButton(filter, filter === panelState.activeFilter, ()=>{
3127
+ panelState.activeFilter = filter;
3128
+ panelState.selectedEventId = null;
3129
+ renderEventsPanel(container, options);
2474
3130
  }))
2475
3131
  }));
3132
+ container.appendChild(renderer_div({
3133
+ style: {
3134
+ padding: '0 16px 8px'
3135
+ },
3136
+ children: [
3137
+ createInput({
3138
+ value: panelState.searchQuery,
3139
+ placeholder: 'Search events…',
3140
+ ariaLabel: 'Search events',
3141
+ small: true,
3142
+ onInput: (value)=>{
3143
+ panelState.searchQuery = value.trim().toLowerCase();
3144
+ panelState.selectedEventId = null;
3145
+ renderEventsPanel(container, options);
3146
+ }
3147
+ })
3148
+ ]
3149
+ }));
2476
3150
  const eventList = renderer_div({
2477
3151
  style: {
2478
3152
  display: 'flex',
@@ -2492,9 +3166,9 @@ function events_renderEventsPanel(container, options) {
2492
3166
  },
2493
3167
  text: 'No events match this filter'
2494
3168
  }));
2495
- else for (const event of events)eventList.appendChild(createEventItem(event, event.id === selectedEventId, ()=>{
2496
- selectedEventId = event.id;
2497
- events_renderEventsPanel(container, options);
3169
+ else for (const event of events)eventList.appendChild(createEventItem(event, event.id === panelState.selectedEventId, ()=>{
3170
+ panelState.selectedEventId = event.id;
3171
+ renderEventsPanel(container, options);
2498
3172
  }));
2499
3173
  container.appendChild(eventList);
2500
3174
  container.appendChild(createPayloadSection(selectedEvent));
@@ -2521,6 +3195,11 @@ function matchesFilter(event, filter) {
2521
3195
  if ('network' === filter) return 'network' === event.type;
2522
3196
  return 'iab' === event.type;
2523
3197
  }
3198
+ function matchesSearch(event, query) {
3199
+ if (!query) return true;
3200
+ const haystack = `${event.type} ${event.message} ${JSON.stringify(event.data ?? {})}`;
3201
+ return haystack.toLowerCase().includes(query);
3202
+ }
2524
3203
  function createPayloadSection(event) {
2525
3204
  const payload = event?.data ? JSON.stringify(event.data, null, 2) : null;
2526
3205
  return renderer_div({
@@ -2658,38 +3337,15 @@ function getEventColor(type) {
2658
3337
  return 'var(--c15t-text-muted)';
2659
3338
  }
2660
3339
  }
2661
- function iab_renderIabPanel(container, options) {
3340
+ const iabSearchByContainer = new WeakMap();
3341
+ function renderIabPanel(container, options) {
2662
3342
  const { getState, onSetPurposeConsent, onSetVendorConsent, onSetSpecialFeatureOptIn, onAcceptAll, onRejectAll, onSave, onReset } = options;
2663
3343
  renderer_clearElement(container);
2664
3344
  const state = getState();
2665
- if (!state) return void container.appendChild(renderer_div({
2666
- style: {
2667
- padding: '24px',
2668
- textAlign: 'center',
2669
- color: 'var(--c15t-text-muted)',
2670
- fontSize: 'var(--c15t-devtools-font-size-sm)'
2671
- },
2672
- text: 'Store not connected'
2673
- }));
2674
- if ('iab' !== state.model) return void container.appendChild(renderer_div({
2675
- style: {
2676
- padding: '24px',
2677
- textAlign: 'center',
2678
- color: 'var(--c15t-text-muted)',
2679
- fontSize: 'var(--c15t-devtools-font-size-sm)'
2680
- },
2681
- text: 'IAB TCF mode is not configured'
2682
- }));
3345
+ if (!state) return void container.appendChild(createDisconnectedState());
3346
+ if ('iab' !== state.model) return void container.appendChild(createDisconnectedState('IAB TCF mode is not configured'));
2683
3347
  const iabState = state.iab;
2684
- if (!iabState) return void container.appendChild(renderer_div({
2685
- style: {
2686
- padding: '24px',
2687
- textAlign: 'center',
2688
- color: 'var(--c15t-text-muted)',
2689
- fontSize: 'var(--c15t-devtools-font-size-sm)'
2690
- },
2691
- text: 'IAB state not available'
2692
- }));
3348
+ if (!iabState) return void container.appendChild(createDisconnectedState('IAB state not available'));
2693
3349
  const tcString = iabState.tcString;
2694
3350
  const tcStringSection = createSection({
2695
3351
  title: 'TC String',
@@ -2721,9 +3377,30 @@ function iab_renderIabPanel(container, options) {
2721
3377
  });
2722
3378
  container.appendChild(tcStringSection);
2723
3379
  const gvl = iabState.gvl;
3380
+ const searchQuery = iabSearchByContainer.get(container) ?? '';
3381
+ container.appendChild(createSection({
3382
+ title: 'Filter',
3383
+ children: [
3384
+ createInput({
3385
+ value: searchQuery,
3386
+ placeholder: 'Filter purposes or vendors…',
3387
+ ariaLabel: 'Filter IAB purposes and vendors',
3388
+ small: true,
3389
+ onInput: (value)=>{
3390
+ iabSearchByContainer.set(container, value.trim().toLowerCase());
3391
+ renderIabPanel(container, options);
3392
+ }
3393
+ })
3394
+ ]
3395
+ }));
2724
3396
  const purposeConsents = iabState.purposeConsents || {};
2725
3397
  const purposes = gvl?.purposes || {};
2726
- const purposeEntries = Object.entries(purposeConsents);
3398
+ const purposeEntries = Object.entries(purposeConsents).filter(([purposeId])=>{
3399
+ if (!searchQuery) return true;
3400
+ const purposeInfo = purposes[purposeId];
3401
+ const purposeName = purposeInfo?.name || `Purpose ${purposeId}`;
3402
+ return `${purposeId} ${purposeName}`.toLowerCase().includes(searchQuery);
3403
+ });
2727
3404
  if (purposeEntries.length > 0) {
2728
3405
  const purposeList = renderer_div({
2729
3406
  style: {
@@ -2751,7 +3428,12 @@ function iab_renderIabPanel(container, options) {
2751
3428
  }
2752
3429
  const specialFeatureOptIns = iabState.specialFeatureOptIns || {};
2753
3430
  const specialFeatures = gvl?.specialFeatures || {};
2754
- const specialFeatureEntries = Object.entries(specialFeatureOptIns);
3431
+ const specialFeatureEntries = Object.entries(specialFeatureOptIns).filter(([featureId])=>{
3432
+ if (!searchQuery) return true;
3433
+ const featureInfo = specialFeatures[featureId];
3434
+ const featureName = featureInfo?.name || `Special Feature ${featureId}`;
3435
+ return `${featureId} ${featureName}`.toLowerCase().includes(searchQuery);
3436
+ });
2755
3437
  if (specialFeatureEntries.length > 0) {
2756
3438
  const specialFeatureList = renderer_div({
2757
3439
  style: {
@@ -2779,7 +3461,12 @@ function iab_renderIabPanel(container, options) {
2779
3461
  }
2780
3462
  const vendorConsents = iabState.vendorConsents || {};
2781
3463
  const vendors = gvl?.vendors || {};
2782
- const vendorEntries = Object.entries(vendorConsents);
3464
+ const vendorEntries = Object.entries(vendorConsents).filter(([vendorId])=>{
3465
+ if (!searchQuery) return true;
3466
+ const vendorInfo = vendors[vendorId];
3467
+ const vendorName = vendorInfo?.name || `Vendor ${vendorId}`;
3468
+ return `${vendorId} ${vendorName}`.toLowerCase().includes(searchQuery);
3469
+ });
2783
3470
  const iabVendors = [];
2784
3471
  const customVendors = [];
2785
3472
  for (const [vendorId, consent] of vendorEntries){
@@ -2998,27 +3685,23 @@ function truncateText(text, maxLength) {
2998
3685
  if (text.length <= maxLength) return text;
2999
3686
  return `${text.slice(0, maxLength - 3)}...`;
3000
3687
  }
3001
- function location_renderLocationPanel(container, options) {
3688
+ function renderLocationPanel(container, options) {
3002
3689
  const { getState, onApplyOverrides, onClearOverrides } = options;
3003
3690
  renderer_clearElement(container);
3004
3691
  const state = getState();
3005
- if (!state) return void container.appendChild(renderer_div({
3006
- style: {
3007
- padding: '24px',
3008
- textAlign: 'center',
3009
- color: 'var(--c15t-text-muted)',
3010
- fontSize: 'var(--c15t-devtools-font-size-sm)'
3011
- },
3012
- text: 'Store not connected'
3013
- }));
3692
+ if (!state) return void container.appendChild(createDisconnectedState());
3014
3693
  const locationInfo = state.locationInfo;
3015
3694
  const overrides = state.overrides;
3016
3695
  const translationConfig = state.translationConfig;
3696
+ const initData = state.lastBannerFetchData;
3697
+ const activePolicy = initData?.policy;
3698
+ const policyDecision = initData?.policyDecision;
3699
+ const initSource = init_source_formatInitSource(state.initDataSource, state.initDataSourceDetail);
3017
3700
  const gridItems = [
3018
3701
  createCompactInfoCard('Country', locationInfo?.countryCode || '—'),
3019
3702
  createCompactInfoCard('Region', locationInfo?.regionCode || '—'),
3020
- createCompactInfoCard('Jurisdiction', locationInfo?.jurisdiction || '—'),
3021
- createCompactInfoCard('Language', translationConfig?.defaultLanguage || '—')
3703
+ createCompactInfoCard('Language', translationConfig?.defaultLanguage || '—'),
3704
+ createCompactInfoCard('Init Source', initSource)
3022
3705
  ];
3023
3706
  gridItems.push(createCompactInfoCard('GPC', getEffectiveGpcLabel(overrides?.gpc)));
3024
3707
  if (state.model) gridItems.push(createCompactInfoCard('Model', getModelLabel(state.model)));
@@ -3026,7 +3709,6 @@ function location_renderLocationPanel(container, options) {
3026
3709
  columns: 3,
3027
3710
  children: gridItems
3028
3711
  });
3029
- container.appendChild(locationGrid);
3030
3712
  const initialDraft = getDraftFromOverrides(overrides);
3031
3713
  let appliedOverrides = normalizeOverrideDraft(initialDraft);
3032
3714
  let isSubmitting = false;
@@ -3117,6 +3799,12 @@ function location_renderLocationPanel(container, options) {
3117
3799
  ]
3118
3800
  });
3119
3801
  container.appendChild(overrideSection);
3802
+ container.appendChild(locationGrid);
3803
+ container.appendChild(createActivePolicySummarySection({
3804
+ policy: activePolicy,
3805
+ policyDecision,
3806
+ policySnapshotToken: initData?.policySnapshotToken
3807
+ }));
3120
3808
  countryField.control.addEventListener('change', updateFormState);
3121
3809
  regionField.control.addEventListener('input', updateFormState);
3122
3810
  languageField.control.addEventListener('input', updateFormState);
@@ -3405,15 +4093,53 @@ function getModelLabel(model) {
3405
4093
  return 'None';
3406
4094
  }
3407
4095
  }
4096
+ function createActivePolicySummarySection(options) {
4097
+ const { policy, policyDecision, policySnapshotToken } = options;
4098
+ if (!policy && !policyDecision) return createSection({
4099
+ title: 'Active Policy',
4100
+ children: [
4101
+ renderer_div({
4102
+ style: {
4103
+ padding: '10px 12px',
4104
+ fontSize: 'var(--c15t-devtools-font-size-sm)',
4105
+ color: 'var(--c15t-text-muted)'
4106
+ },
4107
+ text: 'No active policy matched.'
4108
+ })
4109
+ ]
4110
+ });
4111
+ const cards = [
4112
+ createCompactInfoCard('Policy ID', policy?.id ?? policyDecision?.policyId ?? '—'),
4113
+ createCompactInfoCard('Matched By', policyDecision?.matchedBy ?? '—'),
4114
+ createCompactInfoCard('Snapshot Token', policySnapshotToken ? 'present' : 'missing')
4115
+ ];
4116
+ return createSection({
4117
+ title: 'Active Policy',
4118
+ children: [
4119
+ renderer_div({
4120
+ style: {
4121
+ display: 'grid',
4122
+ gridTemplateColumns: 'repeat(3, minmax(0, 1fr))',
4123
+ gap: 'var(--c15t-space-sm, 0.5rem)'
4124
+ },
4125
+ children: cards
4126
+ }),
4127
+ renderer_span({
4128
+ className: styles_components_module.overrideHint,
4129
+ text: 'Open the Policy tab for full policy-pack diagnostics.'
4130
+ })
4131
+ ]
4132
+ });
4133
+ }
3408
4134
  function createCompactInfoCard(label, value) {
3409
4135
  return renderer_div({
3410
4136
  className: styles_components_module.gridCard ?? '',
3411
4137
  style: {
3412
- padding: '6px 8px',
4138
+ padding: '8px 10px',
3413
4139
  minHeight: 'auto',
3414
4140
  flexDirection: 'column',
3415
4141
  alignItems: 'flex-start',
3416
- gap: '1px'
4142
+ gap: '2px'
3417
4143
  },
3418
4144
  children: [
3419
4145
  renderer_span({
@@ -3434,12 +4160,259 @@ function createCompactInfoCard(label, value) {
3434
4160
  ]
3435
4161
  });
3436
4162
  }
3437
- const dismissedResources = new Set();
3438
- function scanDOM(state) {
3439
- const results = [];
3440
- const configuredScripts = state.scripts || [];
3441
- const managedResources = [];
3442
- for (const script of configuredScripts)if (script.src) try {
4163
+ function renderPolicyPanel(container, options) {
4164
+ const { getState } = options;
4165
+ renderer_clearElement(container);
4166
+ const state = getState();
4167
+ if (!state) return void container.appendChild(createDisconnectedState());
4168
+ const initData = state.lastBannerFetchData;
4169
+ const activePolicy = initData?.policy;
4170
+ const policyDecision = initData?.policyDecision;
4171
+ const initSource = init_source_formatInitSource(state.initDataSource, state.initDataSourceDetail);
4172
+ container.appendChild(createMatchTraceSection({
4173
+ policyDecision,
4174
+ policyId: activePolicy?.id ?? policyDecision?.policyId
4175
+ }));
4176
+ if (!activePolicy && !policyDecision) return void container.appendChild(createSection({
4177
+ title: 'Policy',
4178
+ children: [
4179
+ renderer_div({
4180
+ style: {
4181
+ padding: '10px 12px',
4182
+ fontSize: 'var(--c15t-devtools-font-size-sm)',
4183
+ color: 'var(--c15t-text-muted)'
4184
+ },
4185
+ text: 'No active policy matched for this request.'
4186
+ }),
4187
+ createHint(`Init Source: ${initSource}`)
4188
+ ]
4189
+ }));
4190
+ container.appendChild(createSection({
4191
+ title: 'Policy',
4192
+ children: [
4193
+ policy_createGrid(3, [
4194
+ createCard('ID', activePolicy?.id ?? policyDecision?.policyId ?? '—'),
4195
+ createCard('Model', policy_getModelLabel(activePolicy?.model)),
4196
+ createCard('Scope', getScopeModeLabel(activePolicy?.consent?.scopeMode ?? state.policyScopeMode)),
4197
+ createCard('Categories', formatList(state.policyCategories ?? activePolicy?.consent?.categories)),
4198
+ createCard('Preselected', formatList(activePolicy?.consent?.preselectedCategories)),
4199
+ createCard('Expiry', 'number' == typeof activePolicy?.consent?.expiryDays ? `${activePolicy.consent.expiryDays}d` : '—')
4200
+ ]),
4201
+ createHint(`${initSource} · ${formatFingerprint(policyDecision?.fingerprint)}`)
4202
+ ]
4203
+ }));
4204
+ const uiMode = activePolicy?.ui?.mode;
4205
+ if (uiMode && 'none' !== uiMode) {
4206
+ const bannerCards = buildSurfaceCards('Banner', activePolicy?.ui?.banner, state.policyBanner);
4207
+ const dialogCards = buildSurfaceCards('Dialog', activePolicy?.ui?.dialog, state.policyDialog);
4208
+ if (bannerCards.length > 0 || dialogCards.length > 0) container.appendChild(createSection({
4209
+ title: `UI · ${uiMode}`,
4210
+ children: [
4211
+ policy_createGrid(3, [
4212
+ ...bannerCards,
4213
+ ...dialogCards
4214
+ ])
4215
+ ]
4216
+ }));
4217
+ }
4218
+ const proofLabel = formatProofSummary(activePolicy?.proof);
4219
+ const snapshotLabel = initData?.policySnapshotToken ? 'present' : 'missing';
4220
+ container.appendChild(createSection({
4221
+ title: 'Proof & Snapshot',
4222
+ children: [
4223
+ policy_createGrid(3, [
4224
+ createCard('Proof', proofLabel),
4225
+ createCard('Snapshot', snapshotLabel),
4226
+ createCard('I18n', activePolicy?.i18n?.messageProfile ?? activePolicy?.i18n?.language ?? '—')
4227
+ ])
4228
+ ]
4229
+ }));
4230
+ }
4231
+ function buildSurfaceCards(prefix, policySurface, storeSurface) {
4232
+ const policyLayout = Array.isArray(policySurface?.layout) && 0 === policySurface.layout.length ? null : policySurface?.layout ?? null;
4233
+ const storeLayout = Array.isArray(storeSurface.layout) && 0 === storeSurface.layout.length ? null : storeSurface.layout ?? null;
4234
+ const actions = formatList(policySurface?.allowedActions ?? storeSurface.allowedActions);
4235
+ const primary = policySurface?.primaryAction ?? storeSurface.primaryAction ?? null;
4236
+ const layout = policyLayout ?? storeLayout;
4237
+ const direction = policySurface?.direction ?? storeSurface.direction ?? null;
4238
+ const profile = policySurface?.uiProfile ?? storeSurface.uiProfile ?? null;
4239
+ const scrollLock = policySurface?.scrollLock ?? storeSurface.scrollLock ?? null;
4240
+ if ('—' === actions && !primary && !layout && !direction && !profile && null === scrollLock) return [];
4241
+ const cards = [
4242
+ createCard(`${prefix} Actions`, actions)
4243
+ ];
4244
+ if (primary) cards.push(createCard(`${prefix} Primary`, primary));
4245
+ if (layout) cards.push(createCard(`${prefix} Layout`, Array.isArray(layout) ? layout.map((group)=>Array.isArray(group) ? `[${group.join(', ')}]` : group).join(' / ') : layout));
4246
+ if (direction) cards.push(createCard(`${prefix} Direction`, direction));
4247
+ if (profile) cards.push(createCard(`${prefix} Profile`, profile));
4248
+ if (null !== scrollLock) cards.push(createCard(`${prefix} Scroll Lock`, scrollLock ? 'on' : 'off'));
4249
+ return cards;
4250
+ }
4251
+ function createMatchTraceSection(options) {
4252
+ const { policyDecision, policyId } = options;
4253
+ const entries = buildTraceEntries(policyDecision, policyId);
4254
+ return createSection({
4255
+ title: 'Match Trace',
4256
+ children: [
4257
+ renderer_div({
4258
+ style: {
4259
+ display: 'grid',
4260
+ gridTemplateColumns: '1fr',
4261
+ gap: '4px'
4262
+ },
4263
+ children: entries.map((entry)=>renderer_div({
4264
+ className: styles_components_module.gridCard ?? '',
4265
+ style: {
4266
+ padding: '6px 10px',
4267
+ display: 'flex',
4268
+ alignItems: 'center',
4269
+ justifyContent: 'space-between',
4270
+ gap: '10px'
4271
+ },
4272
+ children: [
4273
+ renderer_span({
4274
+ style: {
4275
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
4276
+ color: 'var(--c15t-text-muted)',
4277
+ fontFamily: 'ui-monospace, monospace'
4278
+ },
4279
+ text: entry.step
4280
+ }),
4281
+ renderer_span({
4282
+ style: {
4283
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
4284
+ fontFamily: 'ui-monospace, monospace'
4285
+ },
4286
+ text: entry.result
4287
+ })
4288
+ ]
4289
+ }))
4290
+ }),
4291
+ createHint('region → country → default · fallback on geo failure · Simulate via Location tab')
4292
+ ]
4293
+ });
4294
+ }
4295
+ function buildTraceEntries(decision, policyId) {
4296
+ if (!decision) return [
4297
+ {
4298
+ step: 'decision metadata',
4299
+ result: 'UNAVAILABLE'
4300
+ }
4301
+ ];
4302
+ const country = decision.country ?? 'n/a';
4303
+ const regionKey = decision.country && decision.region ? `${decision.country}-${decision.region}` : 'n/a';
4304
+ const resolved = policyId ?? decision.policyId ?? 'unknown';
4305
+ const matched = decision.matchedBy;
4306
+ return [
4307
+ {
4308
+ step: `region(${regionKey})`,
4309
+ result: 'region' === matched ? `MATCH → ${resolved}` : 'MISS'
4310
+ },
4311
+ {
4312
+ step: `country(${country})`,
4313
+ result: 'country' === matched ? `MATCH → ${resolved}` : 'region' === matched ? 'SKIPPED' : 'MISS'
4314
+ },
4315
+ {
4316
+ step: 'fallback(geo-fail)',
4317
+ result: 'fallback' === matched ? `MATCH → ${resolved}` : 'SKIPPED'
4318
+ },
4319
+ {
4320
+ step: 'default(catch-all)',
4321
+ result: 'default' === matched ? `MATCH → ${resolved}` : 'SKIPPED'
4322
+ }
4323
+ ];
4324
+ }
4325
+ function policy_getModelLabel(model) {
4326
+ switch(model){
4327
+ case 'opt-in':
4328
+ return 'Opt-In';
4329
+ case 'opt-out':
4330
+ return 'Opt-Out';
4331
+ case 'iab':
4332
+ return 'IAB TCF';
4333
+ default:
4334
+ return 'None';
4335
+ }
4336
+ }
4337
+ function getScopeModeLabel(mode) {
4338
+ switch(mode){
4339
+ case 'strict':
4340
+ return 'Strict';
4341
+ case 'permissive':
4342
+ return 'Permissive';
4343
+ default:
4344
+ return '—';
4345
+ }
4346
+ }
4347
+ function formatList(items) {
4348
+ if (!items || 0 === items.length) return '—';
4349
+ if (items.includes('*')) return '* (all)';
4350
+ return items.join(', ');
4351
+ }
4352
+ function formatProofSummary(proof) {
4353
+ if (!proof) return '—';
4354
+ const parts = [];
4355
+ if (proof.storeIp) parts.push('IP');
4356
+ if (proof.storeUserAgent) parts.push('UA');
4357
+ if (proof.storeLanguage) parts.push('Lang');
4358
+ return parts.length > 0 ? parts.join(', ') : 'none';
4359
+ }
4360
+ function formatFingerprint(fingerprint) {
4361
+ if (!fingerprint) return 'no fingerprint';
4362
+ if (fingerprint.length <= 12) return fingerprint;
4363
+ return `${fingerprint.slice(0, 8)}…${fingerprint.slice(-4)}`;
4364
+ }
4365
+ function createCard(label, value) {
4366
+ return renderer_div({
4367
+ className: styles_components_module.gridCard ?? '',
4368
+ style: {
4369
+ padding: '8px 10px',
4370
+ minHeight: 'auto',
4371
+ flexDirection: 'column',
4372
+ alignItems: 'flex-start',
4373
+ gap: '2px'
4374
+ },
4375
+ children: [
4376
+ renderer_span({
4377
+ style: {
4378
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
4379
+ color: 'var(--c15t-text-muted)'
4380
+ },
4381
+ text: label
4382
+ }),
4383
+ renderer_span({
4384
+ style: {
4385
+ fontSize: 'var(--c15t-font-size-sm)',
4386
+ fontWeight: '500',
4387
+ fontFamily: 'ui-monospace, monospace'
4388
+ },
4389
+ text: value
4390
+ })
4391
+ ]
4392
+ });
4393
+ }
4394
+ function policy_createGrid(columns, children) {
4395
+ return renderer_div({
4396
+ style: {
4397
+ display: 'grid',
4398
+ gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
4399
+ gap: 'var(--c15t-space-sm, 0.5rem)'
4400
+ },
4401
+ children
4402
+ });
4403
+ }
4404
+ function createHint(text) {
4405
+ return renderer_span({
4406
+ className: styles_components_module.overrideHint,
4407
+ text
4408
+ });
4409
+ }
4410
+ const dismissedResources = new Set();
4411
+ function scanDOM(state) {
4412
+ const results = [];
4413
+ const configuredScripts = state.scripts || [];
4414
+ const managedResources = [];
4415
+ for (const script of configuredScripts)if (script.src) try {
3443
4416
  const url = new URL(script.src, window.location.origin);
3444
4417
  if (url.hostname !== window.location.hostname) managedResources.push({
3445
4418
  scriptId: script.id,
@@ -3659,23 +4632,37 @@ const CODE_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" f
3659
4632
  <polyline points="16 18 22 12 16 6"></polyline>
3660
4633
  <polyline points="8 6 2 12 8 18"></polyline>
3661
4634
  </svg>`;
3662
- function scripts_renderScriptsPanel(container, options) {
4635
+ const scriptsSearchByContainer = new WeakMap();
4636
+ function renderScriptsPanel(container, options) {
3663
4637
  const { getState, getEvents } = options;
3664
4638
  renderer_clearElement(container);
3665
4639
  const state = getState();
3666
- if (!state) return void container.appendChild(renderer_div({
3667
- style: {
3668
- padding: '24px',
3669
- textAlign: 'center',
3670
- color: 'var(--c15t-text-muted)',
3671
- fontSize: 'var(--c15t-devtools-font-size-sm)'
3672
- },
3673
- text: 'Store not connected'
3674
- }));
4640
+ if (!state) return void container.appendChild(createDisconnectedState());
3675
4641
  const scripts = state.scripts || [];
3676
4642
  const loadedScripts = state.loadedScripts || {};
3677
4643
  const networkBlocker = state.networkBlocker;
3678
4644
  const events = getEvents?.() ?? [];
4645
+ const searchQuery = scriptsSearchByContainer.get(container) ?? '';
4646
+ const filteredScripts = scripts.filter((script)=>{
4647
+ if (!searchQuery) return true;
4648
+ const category = 'string' == typeof script.category ? script.category : JSON.stringify(script.category);
4649
+ return `${script.id} ${category}`.toLowerCase().includes(searchQuery);
4650
+ });
4651
+ if (scripts.length > 4) container.appendChild(createSection({
4652
+ title: 'Filter',
4653
+ children: [
4654
+ createInput({
4655
+ value: searchQuery,
4656
+ placeholder: "Filter scripts…",
4657
+ ariaLabel: "Filter scripts",
4658
+ small: true,
4659
+ onInput: (value)=>{
4660
+ scriptsSearchByContainer.set(container, value.trim().toLowerCase());
4661
+ renderScriptsPanel(container, options);
4662
+ }
4663
+ })
4664
+ ]
4665
+ }));
3679
4666
  if (0 === scripts.length) {
3680
4667
  const scriptsSection = createSection({
3681
4668
  title: 'Configured Scripts',
@@ -3692,10 +4679,19 @@ function scripts_renderScriptsPanel(container, options) {
3692
4679
  style: {
3693
4680
  display: 'flex',
3694
4681
  flexDirection: 'column',
3695
- gap: '4px'
4682
+ borderTop: '1px solid var(--c15t-border)',
4683
+ borderBottom: '1px solid var(--c15t-border)'
3696
4684
  }
3697
4685
  });
3698
- for (const script of scripts){
4686
+ if (0 === filteredScripts.length) scriptsList.appendChild(renderer_div({
4687
+ style: {
4688
+ padding: '10px 0',
4689
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
4690
+ color: 'var(--c15t-text-muted)'
4691
+ },
4692
+ text: "No matching scripts"
4693
+ }));
4694
+ for (const script of filteredScripts){
3699
4695
  const scriptId = script.id;
3700
4696
  const isLoaded = true === loadedScripts[scriptId];
3701
4697
  const category = script.category;
@@ -3719,17 +4715,64 @@ function scripts_renderScriptsPanel(container, options) {
3719
4715
  text: status.charAt(0).toUpperCase() + status.slice(1),
3720
4716
  variant: statusVariant
3721
4717
  });
3722
- const item = createListItem({
3723
- title: scriptId,
3724
- description: `Category: ${categoryDisplay}`,
3725
- actions: [
3726
- badge
4718
+ const row = renderer_div({
4719
+ style: {
4720
+ display: 'flex',
4721
+ alignItems: 'center',
4722
+ justifyContent: 'space-between',
4723
+ gap: '8px',
4724
+ padding: '8px 0',
4725
+ borderBottom: '1px solid var(--c15t-border)'
4726
+ },
4727
+ children: [
4728
+ renderer_div({
4729
+ style: {
4730
+ display: 'flex',
4731
+ flexDirection: 'column',
4732
+ gap: '2px',
4733
+ minWidth: '0',
4734
+ flex: '1'
4735
+ },
4736
+ children: [
4737
+ renderer_div({
4738
+ style: {
4739
+ fontSize: 'var(--c15t-font-size-sm)',
4740
+ fontWeight: '500',
4741
+ color: 'var(--c15t-text)',
4742
+ overflow: 'hidden',
4743
+ textOverflow: 'ellipsis',
4744
+ whiteSpace: 'nowrap'
4745
+ },
4746
+ text: scriptId
4747
+ }),
4748
+ renderer_div({
4749
+ style: {
4750
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
4751
+ color: 'var(--c15t-text-muted)',
4752
+ overflow: 'hidden',
4753
+ textOverflow: 'ellipsis',
4754
+ whiteSpace: 'nowrap'
4755
+ },
4756
+ text: `Category: ${categoryDisplay}`
4757
+ })
4758
+ ]
4759
+ }),
4760
+ renderer_div({
4761
+ style: {
4762
+ flexShrink: '0'
4763
+ },
4764
+ children: [
4765
+ badge
4766
+ ]
4767
+ })
3727
4768
  ]
3728
4769
  });
3729
- scriptsList.appendChild(item);
4770
+ scriptsList.appendChild(row);
3730
4771
  }
4772
+ const lastRow = scriptsList.lastElementChild;
4773
+ if (lastRow) lastRow.style.borderBottom = 'none';
3731
4774
  const scriptsSection = createSection({
3732
- title: `Configured Scripts (${scripts.length})`,
4775
+ title: `Configured Scripts (${filteredScripts.length}/${scripts.length})`,
3733
4776
  children: [
3734
4777
  scriptsList
3735
4778
  ]
@@ -3871,53 +4914,6 @@ function scripts_truncateText(text, maxLength) {
3871
4914
  if (text.length <= maxLength) return text;
3872
4915
  return `${text.slice(0, maxLength - 3)}...`;
3873
4916
  }
3874
- const DEVTOOLS_OVERRIDES_STORAGE_KEY = 'c15t-devtools-overrides';
3875
- function normalizeStringValue(value) {
3876
- if ('string' != typeof value) return;
3877
- const normalized = value.trim();
3878
- return normalized.length > 0 ? normalized : void 0;
3879
- }
3880
- function normalizeBooleanValue(value) {
3881
- return 'boolean' == typeof value ? value : void 0;
3882
- }
3883
- function normalizeOverrides(value) {
3884
- if (!value || 'object' != typeof value) return null;
3885
- const source = value;
3886
- const overrides = {
3887
- country: normalizeStringValue(source.country),
3888
- region: normalizeStringValue(source.region),
3889
- language: normalizeStringValue(source.language),
3890
- gpc: normalizeBooleanValue(source.gpc)
3891
- };
3892
- return hasPersistedOverrides(overrides) ? overrides : null;
3893
- }
3894
- function hasPersistedOverrides(overrides) {
3895
- return Boolean(overrides.country || overrides.region || overrides.language || void 0 !== overrides.gpc);
3896
- }
3897
- function override_storage_loadPersistedOverrides(storageKey = DEVTOOLS_OVERRIDES_STORAGE_KEY) {
3898
- if ('undefined' == typeof window) return null;
3899
- try {
3900
- const stored = localStorage.getItem(storageKey);
3901
- if (!stored) return null;
3902
- const parsed = JSON.parse(stored);
3903
- return normalizeOverrides(parsed);
3904
- } catch {
3905
- return null;
3906
- }
3907
- }
3908
- function override_storage_persistOverrides(overrides, storageKey = DEVTOOLS_OVERRIDES_STORAGE_KEY) {
3909
- if ('undefined' == typeof window) return;
3910
- try {
3911
- if (!hasPersistedOverrides(overrides)) return void localStorage.removeItem(storageKey);
3912
- localStorage.setItem(storageKey, JSON.stringify(overrides));
3913
- } catch {}
3914
- }
3915
- function override_storage_clearPersistedOverrides(storageKey = DEVTOOLS_OVERRIDES_STORAGE_KEY) {
3916
- if ('undefined' == typeof window) return;
3917
- try {
3918
- localStorage.removeItem(storageKey);
3919
- } catch {}
3920
- }
3921
4917
  const STORAGE_KEYS = {
3922
4918
  C15T: 'c15t',
3923
4919
  PENDING_SYNC: 'c15t:pending-consent-sync',
@@ -3943,7 +4939,7 @@ function clearAllLocalStorage() {
3943
4939
  localStorage.removeItem(STORAGE_KEYS.EUCONSENT);
3944
4940
  } catch {}
3945
4941
  }
3946
- async function reset_consents_resetAllConsents(store, stateManager) {
4942
+ async function resetAllConsents(store, stateManager) {
3947
4943
  const storeState = store.getState();
3948
4944
  storeState.resetConsents();
3949
4945
  clearAllCookies();
@@ -3954,7 +4950,227 @@ async function reset_consents_resetAllConsents(store, stateManager) {
3954
4950
  message: 'All consents reset (storage cleared)'
3955
4951
  });
3956
4952
  }
4953
+ function panel_renderer_createPanelRenderer(config) {
4954
+ const { storeConnector, stateManager, enableEventLogging = true, onPersistOverrides, onClearPersistedOverrides, onCopyState, onExportDebugBundle } = config;
4955
+ const getStoreState = ()=>storeConnector.getState();
4956
+ const logEvent = (type, message, data)=>{
4957
+ if (enableEventLogging) stateManager.addEvent({
4958
+ type,
4959
+ message,
4960
+ data
4961
+ });
4962
+ };
4963
+ const resetConsents = async ()=>{
4964
+ const store = storeConnector.getStore();
4965
+ if (store) await resetAllConsents(store, enableEventLogging ? stateManager : void 0);
4966
+ };
4967
+ const renderPanel = (container, tab)=>{
4968
+ switch(tab){
4969
+ case 'consents':
4970
+ renderConsentsPanel(container, {
4971
+ getState: getStoreState,
4972
+ onConsentChange: (name, value)=>{
4973
+ const store = storeConnector.getStore();
4974
+ if (store) {
4975
+ const consentName = String(name);
4976
+ store.getState().setSelectedConsent(consentName, value);
4977
+ logEvent('info', `${consentName} toggled to ${value} (not saved)`, {
4978
+ name: consentName,
4979
+ value
4980
+ });
4981
+ }
4982
+ },
4983
+ onSave: ()=>{
4984
+ const store = storeConnector.getStore();
4985
+ if (store) {
4986
+ store.getState().saveConsents('custom');
4987
+ logEvent('consent_save', 'Saved consent preferences');
4988
+ }
4989
+ },
4990
+ onAcceptAll: ()=>{
4991
+ const store = storeConnector.getStore();
4992
+ if (store) {
4993
+ store.getState().saveConsents('all');
4994
+ logEvent('consent_save', 'Accepted all consents');
4995
+ }
4996
+ },
4997
+ onRejectAll: ()=>{
4998
+ const store = storeConnector.getStore();
4999
+ if (store) {
5000
+ store.getState().saveConsents('necessary');
5001
+ logEvent('consent_save', 'Rejected all optional consents');
5002
+ }
5003
+ },
5004
+ onReset: resetConsents
5005
+ });
5006
+ break;
5007
+ case 'location':
5008
+ renderLocationPanel(container, {
5009
+ getState: getStoreState,
5010
+ onApplyOverrides: async (overrides)=>{
5011
+ const store = storeConnector.getStore();
5012
+ if (store) {
5013
+ await store.getState().setOverrides({
5014
+ country: overrides.country,
5015
+ region: overrides.region,
5016
+ language: overrides.language,
5017
+ gpc: overrides.gpc
5018
+ });
5019
+ logEvent('info', 'Overrides updated', {
5020
+ country: overrides.country,
5021
+ region: overrides.region,
5022
+ language: overrides.language,
5023
+ gpc: overrides.gpc
5024
+ });
5025
+ onPersistOverrides?.({
5026
+ country: overrides.country,
5027
+ region: overrides.region,
5028
+ language: overrides.language,
5029
+ gpc: overrides.gpc
5030
+ });
5031
+ }
5032
+ },
5033
+ onClearOverrides: async ()=>{
5034
+ const store = storeConnector.getStore();
5035
+ if (store) {
5036
+ await store.getState().setOverrides({
5037
+ country: void 0,
5038
+ region: void 0,
5039
+ language: void 0,
5040
+ gpc: void 0
5041
+ });
5042
+ logEvent('info', 'Overrides cleared');
5043
+ onClearPersistedOverrides?.();
5044
+ }
5045
+ }
5046
+ });
5047
+ break;
5048
+ case 'policy':
5049
+ renderPolicyPanel(container, {
5050
+ getState: getStoreState
5051
+ });
5052
+ break;
5053
+ case "scripts":
5054
+ renderScriptsPanel(container, {
5055
+ getState: getStoreState,
5056
+ getEvents: ()=>stateManager.getState().eventLog
5057
+ });
5058
+ break;
5059
+ case 'iab':
5060
+ renderIabPanel(container, {
5061
+ getState: getStoreState,
5062
+ onSetPurposeConsent: (purposeId, value)=>{
5063
+ const iab = storeConnector.getStore()?.getState().iab;
5064
+ if (!iab) return;
5065
+ iab.setPurposeConsent(purposeId, value);
5066
+ logEvent('iab', `IAB purpose ${purposeId} set to ${value}`);
5067
+ },
5068
+ onSetVendorConsent: (vendorId, value)=>{
5069
+ const iab = storeConnector.getStore()?.getState().iab;
5070
+ if (!iab) return;
5071
+ iab.setVendorConsent(vendorId, value);
5072
+ logEvent('iab', `IAB vendor ${vendorId} set to ${value}`);
5073
+ },
5074
+ onSetSpecialFeatureOptIn: (featureId, value)=>{
5075
+ const iab = storeConnector.getStore()?.getState().iab;
5076
+ if (!iab) return;
5077
+ iab.setSpecialFeatureOptIn(featureId, value);
5078
+ logEvent('iab', `IAB feature ${featureId} set to ${value}`);
5079
+ },
5080
+ onAcceptAll: ()=>{
5081
+ const iab = storeConnector.getStore()?.getState().iab;
5082
+ if (!iab) return;
5083
+ iab.acceptAll();
5084
+ logEvent('iab', 'IAB accept all selected');
5085
+ },
5086
+ onRejectAll: ()=>{
5087
+ const iab = storeConnector.getStore()?.getState().iab;
5088
+ if (!iab) return;
5089
+ iab.rejectAll();
5090
+ logEvent('iab', 'IAB reject all selected');
5091
+ },
5092
+ onSave: ()=>{
5093
+ const iab = storeConnector.getStore()?.getState().iab;
5094
+ if (!iab) return;
5095
+ iab.save().then(()=>logEvent('iab', 'IAB preferences saved')).catch((error)=>{
5096
+ logEvent('error', `Failed to save IAB preferences: ${String(error)}`);
5097
+ });
5098
+ },
5099
+ onReset: resetConsents
5100
+ });
5101
+ break;
5102
+ case 'events':
5103
+ renderEventsPanel(container, {
5104
+ getEvents: ()=>stateManager.getState().eventLog,
5105
+ onClear: ()=>{
5106
+ stateManager.clearEventLog();
5107
+ logEvent('info', 'Event log cleared');
5108
+ }
5109
+ });
5110
+ break;
5111
+ case 'actions':
5112
+ renderActionsPanel(container, {
5113
+ getState: getStoreState,
5114
+ onResetConsents: resetConsents,
5115
+ onRefetchBanner: async ()=>{
5116
+ const store = storeConnector.getStore();
5117
+ if (store) {
5118
+ await store.getState().initConsentManager();
5119
+ logEvent('info', 'Banner data refetched');
5120
+ }
5121
+ },
5122
+ onShowBanner: ()=>{
5123
+ const store = storeConnector.getStore();
5124
+ if (store) {
5125
+ store.getState().setActiveUI('banner', {
5126
+ force: true
5127
+ });
5128
+ logEvent('info', 'Banner shown');
5129
+ }
5130
+ },
5131
+ onOpenPreferences: ()=>{
5132
+ const store = storeConnector.getStore();
5133
+ if (store) {
5134
+ store.getState().setActiveUI('dialog');
5135
+ logEvent('info', 'Preferences dialog opened');
5136
+ }
5137
+ },
5138
+ onCopyState: ()=>{
5139
+ const state = getStoreState();
5140
+ if (state) if (onCopyState) {
5141
+ const result = onCopyState(state);
5142
+ if (result instanceof Promise) result.then((ok)=>{
5143
+ logEvent(ok ? 'info' : 'error', ok ? 'State copied to clipboard' : 'Failed to copy state');
5144
+ }).catch(()=>{
5145
+ logEvent('error', 'Failed to copy state');
5146
+ });
5147
+ else logEvent(result ? 'info' : 'error', result ? 'State copied to clipboard' : 'Failed to copy state');
5148
+ } else navigator.clipboard.writeText(JSON.stringify(state, null, 2)).then(()=>{
5149
+ logEvent('info', 'State copied to clipboard');
5150
+ }).catch(()=>{
5151
+ logEvent('error', 'Failed to copy state');
5152
+ });
5153
+ },
5154
+ onExportDebugBundle: onExportDebugBundle ? ()=>{
5155
+ try {
5156
+ onExportDebugBundle();
5157
+ logEvent('info', 'Debug bundle exported');
5158
+ } catch {
5159
+ logEvent('error', 'Failed to export debug bundle');
5160
+ }
5161
+ } : void 0
5162
+ });
5163
+ break;
5164
+ }
5165
+ };
5166
+ return {
5167
+ renderPanel,
5168
+ getStoreState,
5169
+ resetConsents
5170
+ };
5171
+ }
3957
5172
  const STORAGE_KEY = 'c15t-devtools-events';
5173
+ const ACTIVE_TAB_STORAGE_KEY = 'c15t-devtools-active-tab';
3958
5174
  function loadPersistedEvents() {
3959
5175
  if ('undefined' == typeof window) return [];
3960
5176
  try {
@@ -3969,11 +5185,29 @@ function persistEvents(events) {
3969
5185
  sessionStorage.setItem(STORAGE_KEY, JSON.stringify(events));
3970
5186
  } catch {}
3971
5187
  }
5188
+ function isDevToolsTab(value) {
5189
+ return 'consents' === value || 'location' === value || 'policy' === value || "scripts" === value || 'iab' === value || 'events' === value || 'actions' === value;
5190
+ }
5191
+ function loadPersistedActiveTab() {
5192
+ if ('undefined' == typeof window) return null;
5193
+ try {
5194
+ const stored = localStorage.getItem(ACTIVE_TAB_STORAGE_KEY);
5195
+ if (isDevToolsTab(stored)) return stored;
5196
+ } catch {}
5197
+ return null;
5198
+ }
5199
+ function persistActiveTab(tab) {
5200
+ if ('undefined' == typeof window) return;
5201
+ try {
5202
+ localStorage.setItem(ACTIVE_TAB_STORAGE_KEY, tab);
5203
+ } catch {}
5204
+ }
3972
5205
  function state_manager_createStateManager(initialState = {}) {
3973
5206
  const persistedEvents = loadPersistedEvents();
5207
+ const persistedActiveTab = loadPersistedActiveTab();
3974
5208
  let state = {
3975
5209
  isOpen: false,
3976
- activeTab: 'location',
5210
+ activeTab: persistedActiveTab ?? 'location',
3977
5211
  position: 'bottom-right',
3978
5212
  isConnected: false,
3979
5213
  eventLog: persistedEvents,
@@ -4014,6 +5248,7 @@ function state_manager_createStateManager(initialState = {}) {
4014
5248
  setState({
4015
5249
  activeTab: tab
4016
5250
  });
5251
+ persistActiveTab(tab);
4017
5252
  },
4018
5253
  setPosition: (position)=>{
4019
5254
  setState({
@@ -4059,22 +5294,52 @@ function store_connector_createStoreConnector(options = {}) {
4059
5294
  let reconnectAttempts = 0;
4060
5295
  let hasNotifiedDisconnect = false;
4061
5296
  const listeners = new Set();
5297
+ const diagnosticsListeners = new Set();
5298
+ let diagnostics = {
5299
+ namespace,
5300
+ reconnectAttempts: 0,
5301
+ nextRetryInMs: null,
5302
+ lastError: null,
5303
+ isPolling: false,
5304
+ disconnectNotified: false
5305
+ };
4062
5306
  const INITIAL_RETRY_DELAY_MS = 100;
4063
5307
  const MAX_RETRY_DELAY_MS = 2000;
4064
5308
  const DISCONNECT_NOTIFY_ATTEMPTS = 5;
5309
+ function updateDiagnostics(partial, notify = true) {
5310
+ diagnostics = {
5311
+ ...diagnostics,
5312
+ ...partial
5313
+ };
5314
+ if (!notify) return;
5315
+ for (const listener of diagnosticsListeners)listener(diagnostics);
5316
+ }
4065
5317
  function clearReconnectTimer() {
4066
5318
  if (reconnectTimeout) {
4067
5319
  clearTimeout(reconnectTimeout);
4068
5320
  reconnectTimeout = null;
5321
+ updateDiagnostics({
5322
+ isPolling: false,
5323
+ nextRetryInMs: null
5324
+ });
4069
5325
  }
4070
5326
  }
4071
5327
  function resetReconnectState() {
4072
5328
  reconnectAttempts = 0;
4073
5329
  hasNotifiedDisconnect = false;
5330
+ updateDiagnostics({
5331
+ reconnectAttempts: 0,
5332
+ nextRetryInMs: null,
5333
+ lastError: null,
5334
+ disconnectNotified: false
5335
+ });
4074
5336
  }
4075
5337
  function notifyDisconnectedOnce() {
4076
5338
  if (hasNotifiedDisconnect) return;
4077
5339
  hasNotifiedDisconnect = true;
5340
+ updateDiagnostics({
5341
+ disconnectNotified: true
5342
+ });
4078
5343
  onDisconnect?.();
4079
5344
  }
4080
5345
  function tryConnect() {
@@ -4095,16 +5360,31 @@ function store_connector_createStoreConnector(options = {}) {
4095
5360
  onConnect?.(currentState, store);
4096
5361
  clearReconnectTimer();
4097
5362
  resetReconnectState();
5363
+ updateDiagnostics({
5364
+ lastError: null
5365
+ });
4098
5366
  return true;
4099
5367
  }
5368
+ updateDiagnostics({
5369
+ lastError: `Store "${namespace}" not found on window`
5370
+ });
4100
5371
  return false;
4101
5372
  }
4102
5373
  function scheduleReconnect(immediate = false) {
4103
5374
  if (store || reconnectTimeout) return;
4104
5375
  const delay = immediate ? 0 : Math.min(INITIAL_RETRY_DELAY_MS * 2 ** Math.min(reconnectAttempts, 5), MAX_RETRY_DELAY_MS);
5376
+ updateDiagnostics({
5377
+ isPolling: true,
5378
+ nextRetryInMs: delay,
5379
+ reconnectAttempts
5380
+ });
4105
5381
  reconnectTimeout = setTimeout(()=>{
4106
5382
  reconnectTimeout = null;
4107
5383
  reconnectAttempts++;
5384
+ updateDiagnostics({
5385
+ reconnectAttempts,
5386
+ nextRetryInMs: null
5387
+ });
4108
5388
  if (tryConnect()) return;
4109
5389
  if (reconnectAttempts >= DISCONNECT_NOTIFY_ATTEMPTS) notifyDisconnectedOnce();
4110
5390
  scheduleReconnect();
@@ -4126,6 +5406,14 @@ function store_connector_createStoreConnector(options = {}) {
4126
5406
  listeners.delete(listener);
4127
5407
  };
4128
5408
  },
5409
+ getDiagnostics: ()=>diagnostics,
5410
+ subscribeDiagnostics: (listener)=>{
5411
+ diagnosticsListeners.add(listener);
5412
+ listener(diagnostics);
5413
+ return ()=>{
5414
+ diagnosticsListeners.delete(listener);
5415
+ };
5416
+ },
4129
5417
  retryConnection: ()=>{
4130
5418
  if (store) return;
4131
5419
  resetReconnectState();
@@ -4139,6 +5427,134 @@ function store_connector_createStoreConnector(options = {}) {
4139
5427
  }
4140
5428
  store = null;
4141
5429
  listeners.clear();
5430
+ diagnosticsListeners.clear();
5431
+ }
5432
+ };
5433
+ }
5434
+ const REGISTRY_KEY = '__c15tDevToolsInstrumentationRegistry';
5435
+ let fallbackRegistry = null;
5436
+ function getRegistry() {
5437
+ if ('undefined' == typeof window) {
5438
+ if (!fallbackRegistry) fallbackRegistry = new Map();
5439
+ return fallbackRegistry;
5440
+ }
5441
+ const host = window;
5442
+ const existing = host[REGISTRY_KEY];
5443
+ if (existing) return existing;
5444
+ const registry = new Map();
5445
+ host[REGISTRY_KEY] = registry;
5446
+ return registry;
5447
+ }
5448
+ function getBlockedRequestMessage(payload) {
5449
+ const data = payload;
5450
+ const method = 'string' == typeof data?.method ? data.method.toUpperCase() : 'REQUEST';
5451
+ const url = 'string' == typeof data?.url ? data.url : 'unknown-url';
5452
+ return `Network blocked: ${method} ${url}`;
5453
+ }
5454
+ function emitEvent(entry, event) {
5455
+ for (const listener of entry.listeners)listener(event);
5456
+ }
5457
+ function ensureNetworkBlockerWrapped(entry) {
5458
+ const blocker = entry.store.getState().networkBlocker;
5459
+ if (!blocker) return;
5460
+ if (blocker.onRequestBlocked === entry.wrappedNetworkBlockedCallback) return;
5461
+ entry.originalNetworkBlockedCallback = blocker.onRequestBlocked;
5462
+ entry.wrappedNetworkBlockedCallback = (payload)=>{
5463
+ emitEvent(entry, {
5464
+ type: 'network',
5465
+ message: getBlockedRequestMessage(payload),
5466
+ data: payload
5467
+ });
5468
+ if ('function' == typeof entry.originalNetworkBlockedCallback) entry.originalNetworkBlockedCallback(payload);
5469
+ };
5470
+ entry.store.getState().setNetworkBlocker({
5471
+ ...blocker,
5472
+ onRequestBlocked: entry.wrappedNetworkBlockedCallback
5473
+ });
5474
+ }
5475
+ function restoreInstrumentation(entry) {
5476
+ entry.stopWatchingStore?.();
5477
+ entry.stopWatchingStore = null;
5478
+ const state = entry.store.getState();
5479
+ state.setCallback('onBannerFetched', entry.originalCallbacks.onBannerFetched);
5480
+ state.setCallback('onConsentSet', entry.originalCallbacks.onConsentSet);
5481
+ state.setCallback('onError', entry.originalCallbacks.onError);
5482
+ state.setCallback('onBeforeConsentRevocationReload', entry.originalCallbacks.onBeforeConsentRevocationReload);
5483
+ const blocker = state.networkBlocker;
5484
+ if (blocker && blocker.onRequestBlocked === entry.wrappedNetworkBlockedCallback) state.setNetworkBlocker({
5485
+ ...blocker,
5486
+ onRequestBlocked: entry.originalNetworkBlockedCallback
5487
+ });
5488
+ entry.wrappedNetworkBlockedCallback = null;
5489
+ }
5490
+ function createInstrumentationEntry(store) {
5491
+ const entry = {
5492
+ store,
5493
+ listeners: new Set(),
5494
+ originalCallbacks: {
5495
+ ...store.getState().callbacks
5496
+ },
5497
+ originalNetworkBlockedCallback: store.getState().networkBlocker?.onRequestBlocked,
5498
+ wrappedNetworkBlockedCallback: null,
5499
+ stopWatchingStore: null
5500
+ };
5501
+ store.getState().setCallback('onBannerFetched', (payload)=>{
5502
+ const jurisdiction = payload.jurisdiction;
5503
+ emitEvent(entry, {
5504
+ type: 'info',
5505
+ message: `Banner fetched: ${String(jurisdiction)}`,
5506
+ data: payload
5507
+ });
5508
+ if ('function' == typeof entry.originalCallbacks.onBannerFetched) entry.originalCallbacks.onBannerFetched(payload);
5509
+ });
5510
+ store.getState().setCallback('onConsentSet', (payload)=>{
5511
+ emitEvent(entry, {
5512
+ type: 'consent_set',
5513
+ message: 'Consent preferences updated',
5514
+ data: payload
5515
+ });
5516
+ if ('function' == typeof entry.originalCallbacks.onConsentSet) entry.originalCallbacks.onConsentSet(payload);
5517
+ });
5518
+ store.getState().setCallback('onError', (payload)=>{
5519
+ const errorMessage = payload.error;
5520
+ emitEvent(entry, {
5521
+ type: 'error',
5522
+ message: `Error: ${String(errorMessage)}`,
5523
+ data: payload
5524
+ });
5525
+ if ('function' == typeof entry.originalCallbacks.onError) entry.originalCallbacks.onError(payload);
5526
+ });
5527
+ store.getState().setCallback('onBeforeConsentRevocationReload', (payload)=>{
5528
+ emitEvent(entry, {
5529
+ type: 'info',
5530
+ message: 'Consent revocation - page will reload',
5531
+ data: payload
5532
+ });
5533
+ if ('function' == typeof entry.originalCallbacks.onBeforeConsentRevocationReload) entry.originalCallbacks.onBeforeConsentRevocationReload(payload);
5534
+ });
5535
+ ensureNetworkBlockerWrapped(entry);
5536
+ entry.stopWatchingStore = store.subscribe(()=>{
5537
+ ensureNetworkBlockerWrapped(entry);
5538
+ });
5539
+ return entry;
5540
+ }
5541
+ function store_instrumentation_registerStoreInstrumentation(options) {
5542
+ const { namespace, store, onEvent } = options;
5543
+ const registry = getRegistry();
5544
+ let entry = registry.get(namespace);
5545
+ if (!entry || entry.store !== store) {
5546
+ if (entry) restoreInstrumentation(entry);
5547
+ entry = createInstrumentationEntry(store);
5548
+ registry.set(namespace, entry);
5549
+ }
5550
+ entry.listeners.add(onEvent);
5551
+ return ()=>{
5552
+ const current = registry.get(namespace);
5553
+ if (!current) return;
5554
+ current.listeners.delete(onEvent);
5555
+ if (0 === current.listeners.size) {
5556
+ restoreInstrumentation(current);
5557
+ registry.delete(namespace);
4142
5558
  }
4143
5559
  };
4144
5560
  }
@@ -4162,39 +5578,36 @@ function normalizeOverridesForPersistence(overrides) {
4162
5578
  function persistedOverridesEqual(a, b) {
4163
5579
  return a.country === b.country && a.region === b.region && a.language === b.language && a.gpc === b.gpc;
4164
5580
  }
4165
- function getBlockedRequestMessage(payload) {
4166
- const data = payload;
4167
- const method = 'string' == typeof data?.method ? data.method.toUpperCase() : 'REQUEST';
4168
- const url = 'string' == typeof data?.url ? data.url : 'unknown-url';
4169
- return `Network blocked: ${method} ${url}`;
5581
+ function createStateCopy(state) {
5582
+ return {
5583
+ consents: state.consents,
5584
+ selectedConsents: state.selectedConsents,
5585
+ consentInfo: state.consentInfo,
5586
+ locationInfo: state.locationInfo,
5587
+ model: state.model,
5588
+ overrides: state.overrides,
5589
+ scripts: state.scripts?.map((script)=>({
5590
+ id: script.id
5591
+ })),
5592
+ loadedScripts: state.loadedScripts
5593
+ };
4170
5594
  }
4171
5595
  function createDevToolsPanel(options) {
4172
5596
  const { namespace = 'c15tStore' } = options;
4173
- let originalEmbeddedNetworkBlockedCallback;
4174
- let hasWrappedEmbeddedNetworkBlocker = false;
5597
+ let detachInstrumentation = null;
4175
5598
  const stateManager = state_manager_createStateManager({
4176
5599
  isOpen: true
4177
5600
  });
4178
5601
  const storeConnector = store_connector_createStoreConnector({
4179
5602
  namespace,
4180
5603
  onConnect: (state, store)=>{
5604
+ detachInstrumentation?.();
5605
+ detachInstrumentation = store_instrumentation_registerStoreInstrumentation({
5606
+ namespace,
5607
+ store,
5608
+ onEvent: (event)=>stateManager.addEvent(event)
5609
+ });
4181
5610
  stateManager.setConnected(true);
4182
- const currentNetworkBlocker = state.networkBlocker;
4183
- if (currentNetworkBlocker && !hasWrappedEmbeddedNetworkBlocker) {
4184
- originalEmbeddedNetworkBlockedCallback = currentNetworkBlocker.onRequestBlocked;
4185
- hasWrappedEmbeddedNetworkBlocker = true;
4186
- store.getState().setNetworkBlocker({
4187
- ...currentNetworkBlocker,
4188
- onRequestBlocked: (payload)=>{
4189
- stateManager.addEvent({
4190
- type: 'network',
4191
- message: getBlockedRequestMessage(payload),
4192
- data: payload
4193
- });
4194
- if ('function' == typeof originalEmbeddedNetworkBlockedCallback) originalEmbeddedNetworkBlockedCallback(payload);
4195
- }
4196
- });
4197
- }
4198
5611
  const persistedOverrides = override_storage_loadPersistedOverrides();
4199
5612
  if (persistedOverrides) {
4200
5613
  const currentOverrides = normalizeOverridesForPersistence(state.overrides);
@@ -4206,7 +5619,36 @@ function createDevToolsPanel(options) {
4206
5619
  });
4207
5620
  }
4208
5621
  },
4209
- onDisconnect: ()=>stateManager.setConnected(false)
5622
+ onDisconnect: ()=>{
5623
+ stateManager.setConnected(false);
5624
+ detachInstrumentation?.();
5625
+ detachInstrumentation = null;
5626
+ }
5627
+ });
5628
+ const panelRenderer = panel_renderer_createPanelRenderer({
5629
+ storeConnector,
5630
+ stateManager,
5631
+ enableEventLogging: false,
5632
+ onPersistOverrides: override_storage_persistOverrides,
5633
+ onClearPersistedOverrides: override_storage_clearPersistedOverrides,
5634
+ onCopyState: async (state)=>{
5635
+ try {
5636
+ await navigator.clipboard.writeText(JSON.stringify(createStateCopy(state), null, 2));
5637
+ return true;
5638
+ } catch {
5639
+ return false;
5640
+ }
5641
+ },
5642
+ onExportDebugBundle: ()=>{
5643
+ const bundle = debug_bundle_createDebugBundle({
5644
+ namespace,
5645
+ devToolsState: stateManager.getState(),
5646
+ connection: storeConnector.getDiagnostics(),
5647
+ recentEvents: stateManager.getState().eventLog.slice(0, 100),
5648
+ storeState: debug_bundle_sanitizeStoreState(storeConnector.getState())
5649
+ });
5650
+ debug_bundle_downloadDebugBundle(bundle);
5651
+ }
4210
5652
  });
4211
5653
  const container = renderer_div({
4212
5654
  style: {
@@ -4227,140 +5669,42 @@ function createDevToolsPanel(options) {
4227
5669
  }
4228
5670
  });
4229
5671
  function renderActivePanel() {
4230
- const state = stateManager.getState();
4231
- const getStoreState = ()=>storeConnector.getState();
4232
- switch(state.activeTab){
4233
- case 'consents':
4234
- consents_renderConsentsPanel(contentArea, {
4235
- getState: getStoreState,
4236
- onConsentChange: (name, value)=>{
4237
- storeConnector.getStore()?.getState().setSelectedConsent(name, value);
4238
- },
4239
- onSave: ()=>{
4240
- storeConnector.getStore()?.getState().saveConsents('custom');
4241
- },
4242
- onAcceptAll: ()=>{
4243
- storeConnector.getStore()?.getState().saveConsents('all');
4244
- },
4245
- onRejectAll: ()=>{
4246
- storeConnector.getStore()?.getState().saveConsents('necessary');
4247
- },
4248
- onReset: async ()=>{
4249
- const store = storeConnector.getStore();
4250
- if (store) await reset_consents_resetAllConsents(store);
4251
- }
4252
- });
4253
- break;
4254
- case 'location':
4255
- location_renderLocationPanel(contentArea, {
4256
- getState: getStoreState,
4257
- onApplyOverrides: async (overrides)=>{
4258
- const store = storeConnector.getStore();
4259
- if (store) {
4260
- await store.getState().setOverrides({
4261
- country: overrides.country,
4262
- region: overrides.region,
4263
- language: overrides.language,
4264
- gpc: overrides.gpc
4265
- });
4266
- override_storage_persistOverrides({
4267
- country: overrides.country,
4268
- region: overrides.region,
4269
- language: overrides.language,
4270
- gpc: overrides.gpc
4271
- });
4272
- }
4273
- },
4274
- onClearOverrides: async ()=>{
4275
- await storeConnector.getStore()?.getState().setOverrides({
4276
- country: void 0,
4277
- region: void 0,
4278
- language: void 0,
4279
- gpc: void 0
4280
- });
4281
- override_storage_clearPersistedOverrides();
4282
- }
4283
- });
4284
- break;
4285
- case "scripts":
4286
- scripts_renderScriptsPanel(contentArea, {
4287
- getState: getStoreState,
4288
- getEvents: ()=>stateManager.getState().eventLog
4289
- });
4290
- break;
4291
- case 'iab':
4292
- iab_renderIabPanel(contentArea, {
4293
- getState: getStoreState,
4294
- onSetPurposeConsent: (purposeId, value)=>{
4295
- storeConnector.getStore()?.getState().iab?.setPurposeConsent(purposeId, value);
4296
- },
4297
- onSetVendorConsent: (vendorId, value)=>{
4298
- storeConnector.getStore()?.getState().iab?.setVendorConsent(vendorId, value);
4299
- },
4300
- onSetSpecialFeatureOptIn: (featureId, value)=>{
4301
- storeConnector.getStore()?.getState().iab?.setSpecialFeatureOptIn(featureId, value);
4302
- },
4303
- onAcceptAll: ()=>{
4304
- storeConnector.getStore()?.getState().iab?.acceptAll();
4305
- },
4306
- onRejectAll: ()=>{
4307
- storeConnector.getStore()?.getState().iab?.rejectAll();
4308
- },
4309
- onSave: ()=>{
4310
- storeConnector.getStore()?.getState().iab?.save();
4311
- },
4312
- onReset: async ()=>{
4313
- const store = storeConnector.getStore();
4314
- if (store) await reset_consents_resetAllConsents(store);
4315
- }
4316
- });
4317
- break;
4318
- case 'events':
4319
- events_renderEventsPanel(contentArea, {
4320
- getEvents: ()=>stateManager.getState().eventLog,
4321
- onClear: ()=>{
4322
- stateManager.clearEventLog();
4323
- }
4324
- });
4325
- break;
4326
- case 'actions':
4327
- actions_renderActionsPanel(contentArea, {
4328
- getState: getStoreState,
4329
- onResetConsents: async ()=>{
4330
- const store = storeConnector.getStore();
4331
- if (store) await reset_consents_resetAllConsents(store);
4332
- },
4333
- onRefetchBanner: async ()=>{
4334
- await storeConnector.getStore()?.getState().initConsentManager();
4335
- },
4336
- onShowBanner: ()=>{
4337
- storeConnector.getStore()?.getState().setActiveUI('banner', {
4338
- force: true
4339
- });
4340
- },
4341
- onOpenPreferences: ()=>{
4342
- storeConnector.getStore()?.getState().setActiveUI('dialog');
4343
- },
4344
- onCopyState: ()=>{
4345
- const state = storeConnector.getState();
4346
- if (state) navigator.clipboard.writeText(JSON.stringify(state, null, 2));
4347
- }
4348
- });
4349
- break;
5672
+ const activeTab = syncTabs();
5673
+ panelRenderer.renderPanel(contentArea, activeTab);
5674
+ }
5675
+ let tabsInstance = null;
5676
+ let iabDisabled = true;
5677
+ function getDisabledTabs() {
5678
+ const disabledTabs = [];
5679
+ const storeState = storeConnector.getState();
5680
+ if (!storeState || 'iab' !== storeState.model) disabledTabs.push('iab');
5681
+ return disabledTabs;
5682
+ }
5683
+ function syncTabs() {
5684
+ const disabledTabs = getDisabledTabs();
5685
+ const nextIabDisabled = disabledTabs.includes('iab');
5686
+ let activeTab = stateManager.getState().activeTab;
5687
+ if (disabledTabs.includes(activeTab)) {
5688
+ activeTab = 'consents';
5689
+ stateManager.setActiveTab(activeTab);
4350
5690
  }
5691
+ if (tabsInstance && iabDisabled === nextIabDisabled) tabsInstance.setActiveTab(activeTab);
5692
+ else {
5693
+ tabsInstance?.destroy();
5694
+ tabsInstance = tabs_createTabs({
5695
+ activeTab,
5696
+ onTabChange: (tab)=>{
5697
+ stateManager.setActiveTab(tab);
5698
+ renderActivePanel();
5699
+ },
5700
+ disabledTabs
5701
+ });
5702
+ iabDisabled = nextIabDisabled;
5703
+ if (!tabsInstance.element.parentElement) container.appendChild(tabsInstance.element);
5704
+ }
5705
+ return activeTab;
4351
5706
  }
4352
- const storeState = storeConnector.getState();
4353
- const disabledTabs = [];
4354
- if (!storeState || 'iab' !== storeState.model) disabledTabs.push('iab');
4355
- const tabsInstance = tabs_createTabs({
4356
- activeTab: stateManager.getState().activeTab,
4357
- onTabChange: (tab)=>{
4358
- stateManager.setActiveTab(tab);
4359
- renderActivePanel();
4360
- },
4361
- disabledTabs
4362
- });
4363
- container.appendChild(tabsInstance.element);
5707
+ syncTabs();
4364
5708
  container.appendChild(contentArea);
4365
5709
  renderActivePanel();
4366
5710
  const unsubscribe = storeConnector.subscribe(()=>{
@@ -4369,16 +5713,10 @@ function createDevToolsPanel(options) {
4369
5713
  return {
4370
5714
  element: container,
4371
5715
  destroy: ()=>{
4372
- const store = storeConnector.getStore();
4373
- if (store && hasWrappedEmbeddedNetworkBlocker) {
4374
- const currentNetworkBlocker = store.getState().networkBlocker;
4375
- if (currentNetworkBlocker) store.getState().setNetworkBlocker({
4376
- ...currentNetworkBlocker,
4377
- onRequestBlocked: originalEmbeddedNetworkBlockedCallback
4378
- });
4379
- }
5716
+ detachInstrumentation?.();
5717
+ detachInstrumentation = null;
4380
5718
  unsubscribe();
4381
- tabsInstance.destroy();
5719
+ tabsInstance?.destroy();
4382
5720
  storeConnector.destroy();
4383
5721
  stateManager.destroy();
4384
5722
  }