@c15t/dev-tools 2.0.0-rc.1 → 2.0.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/README.md +3 -3
- package/dist/__tests__/core/override-storage.test.d.ts +2 -0
- package/dist/__tests__/core/override-storage.test.d.ts.map +1 -0
- package/dist/__tests__/core/store-connector.test.d.ts +2 -0
- package/dist/__tests__/core/store-connector.test.d.ts.map +1 -0
- package/dist/__tests__/panels/events.test.d.ts +2 -0
- package/dist/__tests__/panels/events.test.d.ts.map +1 -0
- package/dist/__tests__/panels/iab.test.d.ts +2 -0
- package/dist/__tests__/panels/iab.test.d.ts.map +1 -0
- package/dist/__tests__/panels/scripts.test.d.ts +2 -0
- package/dist/__tests__/panels/scripts.test.d.ts.map +1 -0
- package/dist/__tests__/utils/preference-trigger.test.d.ts +2 -0
- package/dist/__tests__/utils/preference-trigger.test.d.ts.map +1 -0
- package/dist/components/panel.d.ts +1 -0
- package/dist/components/panel.d.ts.map +1 -1
- package/dist/core/devtools.d.ts.map +1 -1
- package/dist/core/override-storage.d.ts +7 -0
- package/dist/core/override-storage.d.ts.map +1 -0
- package/dist/core/panel-renderer.d.ts.map +1 -1
- package/dist/core/state-manager.d.ts +1 -1
- package/dist/core/state-manager.d.ts.map +1 -1
- package/dist/core/store-connector.d.ts +4 -0
- package/dist/core/store-connector.d.ts.map +1 -1
- package/dist/index.cjs +1092 -244
- package/dist/index.js +1092 -244
- package/dist/panels/dom-scanner.d.ts.map +1 -1
- package/dist/panels/events.d.ts.map +1 -1
- package/dist/panels/iab.d.ts +6 -0
- package/dist/panels/iab.d.ts.map +1 -1
- package/dist/panels/location.d.ts +9 -6
- package/dist/panels/location.d.ts.map +1 -1
- package/dist/panels/scripts.d.ts +2 -0
- package/dist/panels/scripts.d.ts.map +1 -1
- package/dist/react.cjs +1020 -239
- package/dist/react.d.ts +8 -7
- package/dist/react.d.ts.map +1 -1
- package/dist/react.js +1016 -238
- package/dist/tanstack.cjs +810 -201
- package/dist/tanstack.js +810 -201
- package/dist/utils/preference-trigger.d.ts +2 -2
- package/dist/utils/preference-trigger.d.ts.map +1 -1
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/package.json +10 -8
package/dist/index.js
CHANGED
|
@@ -344,22 +344,26 @@ var __webpack_modules__ = {
|
|
|
344
344
|
justify-content: center;
|
|
345
345
|
align-items: center;
|
|
346
346
|
gap: var(--c15t-space-xs, .25rem);
|
|
347
|
-
padding: var(--c15t-space-xs, .25rem) var(--c15t-space-sm, .5rem);
|
|
348
347
|
border: 1px solid var(--c15t-border, #e3e3e3);
|
|
349
348
|
border-radius: var(--c15t-radius-md, .5rem);
|
|
350
349
|
background-color: var(--c15t-surface, #fff);
|
|
350
|
+
min-height: 30px;
|
|
351
351
|
color: var(--c15t-text, #171717);
|
|
352
352
|
font-family: inherit;
|
|
353
|
-
font-size:
|
|
353
|
+
font-size: 12px;
|
|
354
354
|
font-weight: var(--c15t-font-weight-medium, 500);
|
|
355
355
|
cursor: pointer;
|
|
356
|
-
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));
|
|
356
|
+
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;
|
|
357
359
|
display: inline-flex;
|
|
360
|
+
box-shadow: 0 1px 1px #0000000a;
|
|
358
361
|
}
|
|
359
362
|
|
|
360
363
|
.btn-evRVlh:hover {
|
|
361
364
|
background-color: var(--c15t-surface-hover, #f7f7f7);
|
|
362
365
|
border-color: var(--c15t-border-hover, #c9c9c9);
|
|
366
|
+
box-shadow: 0 2px 6px #00000014;
|
|
363
367
|
}
|
|
364
368
|
|
|
365
369
|
.btn-evRVlh:focus-visible {
|
|
@@ -367,9 +371,14 @@ var __webpack_modules__ = {
|
|
|
367
371
|
outline-offset: 1px;
|
|
368
372
|
}
|
|
369
373
|
|
|
374
|
+
.btn-evRVlh:active {
|
|
375
|
+
box-shadow: 0 1px 2px #00000014;
|
|
376
|
+
}
|
|
377
|
+
|
|
370
378
|
.btn-evRVlh:disabled {
|
|
371
379
|
opacity: .5;
|
|
372
380
|
cursor: not-allowed;
|
|
381
|
+
box-shadow: none;
|
|
373
382
|
}
|
|
374
383
|
|
|
375
384
|
.btnPrimary-dA6nqY {
|
|
@@ -395,8 +404,10 @@ var __webpack_modules__ = {
|
|
|
395
404
|
}
|
|
396
405
|
|
|
397
406
|
.btnSmall-TjXoqZ {
|
|
398
|
-
|
|
399
|
-
|
|
407
|
+
border-radius: var(--c15t-radius-sm, .375rem);
|
|
408
|
+
min-height: 26px;
|
|
409
|
+
padding: 3px 8px;
|
|
410
|
+
font-size: 11px;
|
|
400
411
|
}
|
|
401
412
|
|
|
402
413
|
.btnIcon-fiYQAh {
|
|
@@ -548,6 +559,50 @@ var __webpack_modules__ = {
|
|
|
548
559
|
letter-spacing: .5px;
|
|
549
560
|
}
|
|
550
561
|
|
|
562
|
+
.overrideField-keNdpJ {
|
|
563
|
+
flex-direction: column;
|
|
564
|
+
gap: 3px;
|
|
565
|
+
margin-bottom: 0;
|
|
566
|
+
display: flex;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
.overrideLabel-ApMoTw {
|
|
570
|
+
color: var(--c15t-text-muted, #737373);
|
|
571
|
+
font-size: 11px;
|
|
572
|
+
font-weight: 600;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
.overrideHint-yCfwGt {
|
|
576
|
+
color: var(--c15t-devtools-text-muted, #737373);
|
|
577
|
+
margin-top: 6px;
|
|
578
|
+
font-size: 11px;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
.overrideActions-imdcn7 {
|
|
582
|
+
border-top: 1px dashed var(--c15t-border, #e3e3e3);
|
|
583
|
+
justify-content: space-between;
|
|
584
|
+
align-items: center;
|
|
585
|
+
gap: 8px;
|
|
586
|
+
margin-top: 8px;
|
|
587
|
+
padding-top: 8px;
|
|
588
|
+
display: flex;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
.overrideActionButtons-gYOx1e {
|
|
592
|
+
flex-wrap: wrap;
|
|
593
|
+
gap: 6px;
|
|
594
|
+
display: flex;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
.overrideStatus-sty_qS {
|
|
598
|
+
color: var(--c15t-text-muted, #737373);
|
|
599
|
+
font-size: 11px;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
.overrideStatusDirty-OUdDMw {
|
|
603
|
+
color: var(--c15t-devtools-badge-warning, #f59f0a);
|
|
604
|
+
}
|
|
605
|
+
|
|
551
606
|
.infoRow-RlB_0h {
|
|
552
607
|
padding: var(--c15t-space-xs, .25rem) 0;
|
|
553
608
|
justify-content: space-between;
|
|
@@ -640,6 +695,13 @@ var __webpack_modules__ = {
|
|
|
640
695
|
section: "section-a197cB",
|
|
641
696
|
sectionHeader: "sectionHeader-Xcljcw",
|
|
642
697
|
sectionTitle: "sectionTitle-RUiFld",
|
|
698
|
+
overrideField: "overrideField-keNdpJ",
|
|
699
|
+
overrideLabel: "overrideLabel-ApMoTw",
|
|
700
|
+
overrideHint: "overrideHint-yCfwGt",
|
|
701
|
+
overrideActions: "overrideActions-imdcn7",
|
|
702
|
+
overrideActionButtons: "overrideActionButtons-gYOx1e",
|
|
703
|
+
overrideStatus: "overrideStatus-sty_qS",
|
|
704
|
+
overrideStatusDirty: "overrideStatusDirty-OUdDMw",
|
|
643
705
|
infoRow: "infoRow-RlB_0h",
|
|
644
706
|
infoLabel: "infoLabel-_pbK33",
|
|
645
707
|
infoValue: "infoValue-flMl_e",
|
|
@@ -1122,16 +1184,23 @@ var __webpack_modules__ = {
|
|
|
1122
1184
|
___CSS_LOADER_EXPORT___.push([
|
|
1123
1185
|
module.id,
|
|
1124
1186
|
`.tabList-IyuiBE {
|
|
1187
|
+
align-items: center;
|
|
1125
1188
|
gap: var(--c15t-space-xs, .25rem);
|
|
1126
|
-
padding: var(--c15t-space-sm, .5rem) var(--c15t-space-
|
|
1189
|
+
padding: var(--c15t-space-sm, .5rem) var(--c15t-space-sm, .5rem);
|
|
1127
1190
|
border-bottom: 1px solid var(--c15t-border, #e3e3e3);
|
|
1128
1191
|
background-color: var(--c15t-surface, #fff);
|
|
1129
1192
|
scrollbar-width: none;
|
|
1130
1193
|
-ms-overflow-style: none;
|
|
1194
|
+
scroll-padding-inline-end: var(--c15t-space-sm, .5rem);
|
|
1131
1195
|
display: flex;
|
|
1132
1196
|
overflow-x: auto;
|
|
1133
1197
|
}
|
|
1134
1198
|
|
|
1199
|
+
.tabList-IyuiBE:after {
|
|
1200
|
+
content: "";
|
|
1201
|
+
flex: 0 0 var(--c15t-space-sm, .5rem);
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1135
1204
|
.tabList-IyuiBE::-webkit-scrollbar {
|
|
1136
1205
|
display: none;
|
|
1137
1206
|
}
|
|
@@ -1139,17 +1208,17 @@ var __webpack_modules__ = {
|
|
|
1139
1208
|
.tab-yfDEqg {
|
|
1140
1209
|
align-items: center;
|
|
1141
1210
|
gap: var(--c15t-space-xs, .25rem);
|
|
1142
|
-
padding: var(--c15t-space-xs, .25rem) var(--c15t-space-sm, .5rem);
|
|
1143
1211
|
border-radius: var(--c15t-radius-md, .5rem);
|
|
1144
1212
|
color: var(--c15t-text-muted, #737373);
|
|
1145
1213
|
font-family: inherit;
|
|
1146
|
-
font-size:
|
|
1214
|
+
font-size: 11px;
|
|
1147
1215
|
font-weight: var(--c15t-font-weight-medium, 500);
|
|
1148
1216
|
cursor: pointer;
|
|
1149
1217
|
white-space: nowrap;
|
|
1150
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));
|
|
1151
1219
|
background-color: #0000;
|
|
1152
1220
|
border: none;
|
|
1221
|
+
padding: 3px 7px;
|
|
1153
1222
|
display: flex;
|
|
1154
1223
|
}
|
|
1155
1224
|
|
|
@@ -1864,9 +1933,9 @@ function setPreferenceTriggerVisibility(visible) {
|
|
|
1864
1933
|
const elements = getPreferenceTriggerElements();
|
|
1865
1934
|
for (const el of elements)el.style.display = visible ? '' : 'none';
|
|
1866
1935
|
}
|
|
1867
|
-
function getPreferenceCenterOpener() {
|
|
1936
|
+
function getPreferenceCenterOpener(namespace = 'c15tStore') {
|
|
1868
1937
|
const win = window;
|
|
1869
|
-
const store = win
|
|
1938
|
+
const store = win[namespace];
|
|
1870
1939
|
if (store && 'function' == typeof store.getState) {
|
|
1871
1940
|
const state = store.getState();
|
|
1872
1941
|
if ('function' == typeof state.setActiveUI) return ()=>{
|
|
@@ -1875,6 +1944,7 @@ function getPreferenceCenterOpener() {
|
|
|
1875
1944
|
}
|
|
1876
1945
|
return null;
|
|
1877
1946
|
}
|
|
1947
|
+
const version = '2.0.0-rc.3';
|
|
1878
1948
|
const DEVTOOLS_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 446 445" aria-label="c15t">
|
|
1879
1949
|
<path fill="currentColor" d="M223.178.313c39.064 0 70.732 31.668 70.732 70.732-.001 39.064-31.668 70.731-70.732 70.731-12.181 0-23.642-3.079-33.649-8.502l-55.689 55.689a70.267 70.267 0 0 1 5.574 13.441h167.531c8.695-29.217 35.762-50.523 67.804-50.523 39.064 0 70.731 31.668 70.731 70.732s-31.668 70.732-70.731 70.732c-32.042 0-59.108-21.306-67.803-50.523H139.413a70.417 70.417 0 0 1-7.888 17.396l54.046 54.046c10.893-6.851 23.786-10.815 37.605-10.815 39.064 0 70.732 31.669 70.732 70.733 0 39.064-31.668 70.731-70.732 70.731s-70.732-31.667-70.732-70.731c0-10.518 2.296-20.499 6.414-29.471l-57.78-57.78c-8.972 4.117-18.952 6.414-29.47 6.414-39.063 0-70.731-31.668-70.732-70.732 0-39.064 31.669-70.732 70.733-70.732 12.18 0 23.642 3.079 33.649 8.502l55.688-55.688c-5.423-10.007-8.502-21.469-8.502-33.65 0-39.064 31.668-70.733 70.732-70.733Zm0 343.555c-16.742 0-30.314 13.572-30.314 30.314 0 16.741 13.572 30.313 30.314 30.313s30.314-13.572 30.314-30.313c0-16.742-13.572-30.314-30.314-30.314ZM71.611 192.299c-16.742 0-30.315 13.572-30.315 30.314s13.573 30.314 30.315 30.314c16.741 0 30.313-13.572 30.313-30.314 0-16.741-13.572-30.314-30.313-30.314Zm303.138 0c-16.729 0-30.294 13.551-30.315 30.275l.001.039-.001.038c.021 16.725 13.586 30.276 30.315 30.276 16.741 0 30.313-13.572 30.313-30.314 0-16.741-13.572-30.314-30.313-30.314ZM223.178 40.73c-16.742 0-30.314 13.573-30.314 30.315s13.573 30.313 30.314 30.313c16.742 0 30.313-13.572 30.314-30.313 0-16.742-13.572-30.314-30.314-30.315Z"/>
|
|
1880
1950
|
</svg>`;
|
|
@@ -2078,7 +2148,7 @@ function getPositionClass(position) {
|
|
|
2078
2148
|
}
|
|
2079
2149
|
}
|
|
2080
2150
|
function createPanel(options) {
|
|
2081
|
-
const { stateManager, storeConnector, onRenderContent, enableUnifiedMode = true } = options;
|
|
2151
|
+
const { stateManager, storeConnector, onRenderContent, namespace = 'c15tStore', enableUnifiedMode = true } = options;
|
|
2082
2152
|
let removePortal = null;
|
|
2083
2153
|
let isAnimatingOut = false;
|
|
2084
2154
|
let draggable = null;
|
|
@@ -2107,7 +2177,7 @@ function createPanel(options) {
|
|
|
2107
2177
|
return;
|
|
2108
2178
|
}
|
|
2109
2179
|
hasPreferenceTrigger = detectPreferenceTrigger();
|
|
2110
|
-
const preferenceCenterOpener = getPreferenceCenterOpener();
|
|
2180
|
+
const preferenceCenterOpener = getPreferenceCenterOpener(namespace);
|
|
2111
2181
|
useUnifiedMode = hasPreferenceTrigger && null !== preferenceCenterOpener;
|
|
2112
2182
|
if (useUnifiedMode && !dropdownMenu) {
|
|
2113
2183
|
dropdownMenu = createDropdownMenu({
|
|
@@ -2127,7 +2197,7 @@ function createPanel(options) {
|
|
|
2127
2197
|
description: 'Open privacy settings',
|
|
2128
2198
|
icon: PREFERENCES_ICON,
|
|
2129
2199
|
onClick: ()=>{
|
|
2130
|
-
const opener = getPreferenceCenterOpener();
|
|
2200
|
+
const opener = getPreferenceCenterOpener(namespace);
|
|
2131
2201
|
if (opener) opener();
|
|
2132
2202
|
}
|
|
2133
2203
|
},
|
|
@@ -2183,6 +2253,7 @@ function createPanel(options) {
|
|
|
2183
2253
|
let panelElement = null;
|
|
2184
2254
|
let backdropElement = null;
|
|
2185
2255
|
let contentContainer = null;
|
|
2256
|
+
let footerElement = null;
|
|
2186
2257
|
function createPanelElement() {
|
|
2187
2258
|
const corner = draggable?.getCorner() ?? stateManager.getState().position;
|
|
2188
2259
|
const positionClass = getPositionClass(corner);
|
|
@@ -2234,33 +2305,53 @@ function createPanel(options) {
|
|
|
2234
2305
|
contentContainer = renderer_div({
|
|
2235
2306
|
className: styles_panel_module.content
|
|
2236
2307
|
});
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
className: styles_panel_module.footer,
|
|
2240
|
-
children: [
|
|
2241
|
-
renderer_div({
|
|
2242
|
-
className: styles_panel_module.footerStatus,
|
|
2243
|
-
children: [
|
|
2244
|
-
span({
|
|
2245
|
-
className: `${styles_panel_module.statusDot} ${isConnected ? styles_panel_module.statusConnected : styles_panel_module.statusDisconnected}`
|
|
2246
|
-
}),
|
|
2247
|
-
span({
|
|
2248
|
-
text: isConnected ? 'Connected' : 'Disconnected'
|
|
2249
|
-
})
|
|
2250
|
-
]
|
|
2251
|
-
}),
|
|
2252
|
-
span({
|
|
2253
|
-
text: 'v1.8.3'
|
|
2254
|
-
})
|
|
2255
|
-
]
|
|
2308
|
+
footerElement = renderer_div({
|
|
2309
|
+
className: styles_panel_module.footer
|
|
2256
2310
|
});
|
|
2311
|
+
updateFooter();
|
|
2257
2312
|
panel.appendChild(header);
|
|
2258
2313
|
panel.appendChild(contentContainer);
|
|
2259
|
-
panel.appendChild(
|
|
2260
|
-
if (isConnected) onRenderContent(contentContainer);
|
|
2314
|
+
panel.appendChild(footerElement);
|
|
2315
|
+
if (storeConnector.isConnected()) onRenderContent(contentContainer);
|
|
2261
2316
|
else renderErrorState(contentContainer);
|
|
2262
2317
|
return panel;
|
|
2263
2318
|
}
|
|
2319
|
+
function updateFooter() {
|
|
2320
|
+
if (!footerElement) return;
|
|
2321
|
+
clearElement(footerElement);
|
|
2322
|
+
const isConnected = storeConnector.isConnected();
|
|
2323
|
+
const storeState = storeConnector.getState();
|
|
2324
|
+
const isLoading = storeState?.isLoadingConsentInfo ?? false;
|
|
2325
|
+
const statusChildren = [
|
|
2326
|
+
span({
|
|
2327
|
+
className: `${styles_panel_module.statusDot} ${isConnected ? styles_panel_module.statusConnected : styles_panel_module.statusDisconnected}`
|
|
2328
|
+
}),
|
|
2329
|
+
span({
|
|
2330
|
+
text: isConnected ? 'Connected' : 'Disconnected'
|
|
2331
|
+
})
|
|
2332
|
+
];
|
|
2333
|
+
if (isLoading) statusChildren.push(span({
|
|
2334
|
+
style: {
|
|
2335
|
+
marginLeft: '4px',
|
|
2336
|
+
opacity: '0.7'
|
|
2337
|
+
},
|
|
2338
|
+
text: '\u00b7 Fetching /init\u2026'
|
|
2339
|
+
}));
|
|
2340
|
+
footerElement.appendChild(renderer_div({
|
|
2341
|
+
className: styles_panel_module.footerStatus,
|
|
2342
|
+
children: statusChildren
|
|
2343
|
+
}));
|
|
2344
|
+
if (!isConnected) footerElement.appendChild(renderer_button({
|
|
2345
|
+
className: styles_panel_module.closeButton,
|
|
2346
|
+
text: 'Retry',
|
|
2347
|
+
onClick: ()=>{
|
|
2348
|
+
storeConnector.retryConnection();
|
|
2349
|
+
}
|
|
2350
|
+
}));
|
|
2351
|
+
footerElement.appendChild(span({
|
|
2352
|
+
text: `v${version}`
|
|
2353
|
+
}));
|
|
2354
|
+
}
|
|
2264
2355
|
function renderErrorState(container) {
|
|
2265
2356
|
clearElement(container);
|
|
2266
2357
|
const errorState = renderer_div({
|
|
@@ -2283,6 +2374,13 @@ function createPanel(options) {
|
|
|
2283
2374
|
renderer_div({
|
|
2284
2375
|
className: styles_panel_module.errorMessage,
|
|
2285
2376
|
text: 'c15t consent manager is not initialized. Make sure you have set up the ConsentManagerProvider in your app.'
|
|
2377
|
+
}),
|
|
2378
|
+
renderer_button({
|
|
2379
|
+
className: styles_panel_module.closeButton,
|
|
2380
|
+
text: 'Retry Connection',
|
|
2381
|
+
onClick: ()=>{
|
|
2382
|
+
storeConnector.retryConnection();
|
|
2383
|
+
}
|
|
2286
2384
|
})
|
|
2287
2385
|
]
|
|
2288
2386
|
});
|
|
@@ -2318,6 +2416,7 @@ function createPanel(options) {
|
|
|
2318
2416
|
panelElement = null;
|
|
2319
2417
|
}
|
|
2320
2418
|
contentContainer = null;
|
|
2419
|
+
footerElement = null;
|
|
2321
2420
|
isAnimatingOut = false;
|
|
2322
2421
|
floatingButton.style.display = '';
|
|
2323
2422
|
stateManager.setOpen(false);
|
|
@@ -2336,6 +2435,7 @@ function createPanel(options) {
|
|
|
2336
2435
|
update();
|
|
2337
2436
|
});
|
|
2338
2437
|
const unsubscribeStore = storeConnector.subscribe(()=>{
|
|
2438
|
+
updateFooter();
|
|
2339
2439
|
if (contentContainer) if (storeConnector.isConnected()) onRenderContent(contentContainer);
|
|
2340
2440
|
else renderErrorState(contentContainer);
|
|
2341
2441
|
});
|
|
@@ -2991,13 +3091,13 @@ function renderConsentsPanel(container, options) {
|
|
|
2991
3091
|
},
|
|
2992
3092
|
children: [
|
|
2993
3093
|
createButton({
|
|
2994
|
-
text: '
|
|
3094
|
+
text: 'Accept',
|
|
2995
3095
|
variant: 'primary',
|
|
2996
3096
|
small: true,
|
|
2997
3097
|
onClick: onAcceptAll
|
|
2998
3098
|
}),
|
|
2999
3099
|
createButton({
|
|
3000
|
-
text: '
|
|
3100
|
+
text: 'Reject',
|
|
3001
3101
|
variant: 'default',
|
|
3002
3102
|
small: true,
|
|
3003
3103
|
onClick: onRejectAll
|
|
@@ -3045,16 +3145,22 @@ function renderConsentsPanel(container, options) {
|
|
|
3045
3145
|
function formatConsentName(name) {
|
|
3046
3146
|
return name.replace(/_/g, ' ').replace(/\b\w/g, (l)=>l.toUpperCase());
|
|
3047
3147
|
}
|
|
3148
|
+
let activeFilter = 'all';
|
|
3149
|
+
let selectedEventId = null;
|
|
3048
3150
|
function renderEventsPanel(container, options) {
|
|
3049
3151
|
const { getEvents, onClear } = options;
|
|
3050
3152
|
clearElement(container);
|
|
3051
|
-
const
|
|
3153
|
+
const allEvents = getEvents();
|
|
3154
|
+
const events = allEvents.filter((event)=>matchesFilter(event, activeFilter));
|
|
3155
|
+
if (!events.some((event)=>event.id === selectedEventId)) selectedEventId = events[0]?.id ?? null;
|
|
3156
|
+
const selectedEvent = events.find((event)=>event.id === selectedEventId) ?? null;
|
|
3052
3157
|
const header = renderer_div({
|
|
3053
3158
|
style: {
|
|
3054
3159
|
display: 'flex',
|
|
3055
3160
|
alignItems: 'center',
|
|
3056
3161
|
justifyContent: 'space-between',
|
|
3057
|
-
padding: '12px 16px 8px'
|
|
3162
|
+
padding: '12px 16px 8px',
|
|
3163
|
+
gap: '8px'
|
|
3058
3164
|
},
|
|
3059
3165
|
children: [
|
|
3060
3166
|
span({
|
|
@@ -3065,44 +3171,130 @@ function renderEventsPanel(container, options) {
|
|
|
3065
3171
|
textTransform: 'uppercase',
|
|
3066
3172
|
letterSpacing: '0.5px'
|
|
3067
3173
|
},
|
|
3068
|
-
text: `Events (${events.length})`
|
|
3174
|
+
text: `Events (${events.length}/${allEvents.length})`
|
|
3069
3175
|
}),
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3176
|
+
renderer_div({
|
|
3177
|
+
style: {
|
|
3178
|
+
display: 'flex',
|
|
3179
|
+
gap: '6px'
|
|
3180
|
+
},
|
|
3181
|
+
children: [
|
|
3182
|
+
createButton({
|
|
3183
|
+
text: 'Export',
|
|
3184
|
+
small: true,
|
|
3185
|
+
onClick: ()=>exportEvents(allEvents)
|
|
3186
|
+
}),
|
|
3187
|
+
createButton({
|
|
3188
|
+
text: 'Clear',
|
|
3189
|
+
small: true,
|
|
3190
|
+
onClick: ()=>{
|
|
3191
|
+
onClear();
|
|
3192
|
+
selectedEventId = null;
|
|
3193
|
+
renderEventsPanel(container, options);
|
|
3194
|
+
}
|
|
3195
|
+
})
|
|
3196
|
+
]
|
|
3074
3197
|
})
|
|
3075
3198
|
]
|
|
3076
3199
|
});
|
|
3077
3200
|
container.appendChild(header);
|
|
3201
|
+
container.appendChild(renderer_div({
|
|
3202
|
+
style: {
|
|
3203
|
+
display: 'flex',
|
|
3204
|
+
flexWrap: 'wrap',
|
|
3205
|
+
gap: '6px',
|
|
3206
|
+
padding: '0 16px 8px'
|
|
3207
|
+
},
|
|
3208
|
+
children: EVENT_FILTERS.map((filter)=>createFilterButton(filter, filter === activeFilter, ()=>{
|
|
3209
|
+
activeFilter = filter;
|
|
3210
|
+
selectedEventId = null;
|
|
3211
|
+
renderEventsPanel(container, options);
|
|
3212
|
+
}))
|
|
3213
|
+
}));
|
|
3078
3214
|
const eventList = renderer_div({
|
|
3079
3215
|
style: {
|
|
3080
3216
|
display: 'flex',
|
|
3081
3217
|
flexDirection: 'column',
|
|
3082
3218
|
gap: '4px',
|
|
3083
3219
|
padding: '0 12px 12px',
|
|
3084
|
-
maxHeight: '
|
|
3220
|
+
maxHeight: '300px',
|
|
3085
3221
|
overflowY: 'auto'
|
|
3086
3222
|
}
|
|
3087
3223
|
});
|
|
3088
|
-
if (0 === events.length) {
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
eventList.appendChild(eventItem);
|
|
3102
|
-
}
|
|
3224
|
+
if (0 === events.length) eventList.appendChild(renderer_div({
|
|
3225
|
+
style: {
|
|
3226
|
+
padding: '20px 16px',
|
|
3227
|
+
textAlign: 'center',
|
|
3228
|
+
color: 'var(--c15t-text-muted)',
|
|
3229
|
+
fontSize: 'var(--c15t-devtools-font-size-sm)'
|
|
3230
|
+
},
|
|
3231
|
+
text: 'No events match this filter'
|
|
3232
|
+
}));
|
|
3233
|
+
else for (const event of events)eventList.appendChild(createEventItem(event, event.id === selectedEventId, ()=>{
|
|
3234
|
+
selectedEventId = event.id;
|
|
3235
|
+
renderEventsPanel(container, options);
|
|
3236
|
+
}));
|
|
3103
3237
|
container.appendChild(eventList);
|
|
3238
|
+
container.appendChild(createPayloadSection(selectedEvent));
|
|
3239
|
+
}
|
|
3240
|
+
const EVENT_FILTERS = [
|
|
3241
|
+
'all',
|
|
3242
|
+
'error',
|
|
3243
|
+
'consent',
|
|
3244
|
+
'network',
|
|
3245
|
+
'iab'
|
|
3246
|
+
];
|
|
3247
|
+
function createFilterButton(filter, active, onClick) {
|
|
3248
|
+
return createButton({
|
|
3249
|
+
text: filter.toUpperCase(),
|
|
3250
|
+
small: true,
|
|
3251
|
+
variant: active ? 'primary' : 'default',
|
|
3252
|
+
onClick
|
|
3253
|
+
});
|
|
3254
|
+
}
|
|
3255
|
+
function matchesFilter(event, filter) {
|
|
3256
|
+
if ('all' === filter) return true;
|
|
3257
|
+
if ('error' === filter) return 'error' === event.type;
|
|
3258
|
+
if ('consent' === filter) return 'consent_set' === event.type || 'consent_save' === event.type || 'consent_reset' === event.type;
|
|
3259
|
+
if ('network' === filter) return 'network' === event.type;
|
|
3260
|
+
return 'iab' === event.type;
|
|
3104
3261
|
}
|
|
3105
|
-
function
|
|
3262
|
+
function createPayloadSection(event) {
|
|
3263
|
+
const payload = event?.data ? JSON.stringify(event.data, null, 2) : null;
|
|
3264
|
+
return renderer_div({
|
|
3265
|
+
style: {
|
|
3266
|
+
padding: '0 12px 12px'
|
|
3267
|
+
},
|
|
3268
|
+
children: [
|
|
3269
|
+
renderer_div({
|
|
3270
|
+
style: {
|
|
3271
|
+
fontSize: 'var(--c15t-devtools-font-size-xs)',
|
|
3272
|
+
fontWeight: '600',
|
|
3273
|
+
color: 'var(--c15t-text-muted)',
|
|
3274
|
+
textTransform: 'uppercase',
|
|
3275
|
+
letterSpacing: '0.5px',
|
|
3276
|
+
marginBottom: '6px'
|
|
3277
|
+
},
|
|
3278
|
+
text: 'Payload'
|
|
3279
|
+
}),
|
|
3280
|
+
renderer_div({
|
|
3281
|
+
className: styles_components_module.gridCard ?? '',
|
|
3282
|
+
style: {
|
|
3283
|
+
padding: '8px',
|
|
3284
|
+
fontFamily: 'ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, monospace',
|
|
3285
|
+
fontSize: '11px',
|
|
3286
|
+
color: 'var(--c15t-text-muted)',
|
|
3287
|
+
maxHeight: '140px',
|
|
3288
|
+
overflowY: 'auto',
|
|
3289
|
+
whiteSpace: 'pre-wrap',
|
|
3290
|
+
wordBreak: 'break-word'
|
|
3291
|
+
},
|
|
3292
|
+
text: payload || 'Select an event with payload data'
|
|
3293
|
+
})
|
|
3294
|
+
]
|
|
3295
|
+
});
|
|
3296
|
+
}
|
|
3297
|
+
function createEventItem(event, selected, onSelect) {
|
|
3106
3298
|
const time = formatTime(event.timestamp);
|
|
3107
3299
|
const icon = getEventIcon(event.type);
|
|
3108
3300
|
const color = getEventColor(event.type);
|
|
@@ -3113,8 +3305,11 @@ function createEventItem(event) {
|
|
|
3113
3305
|
alignItems: 'center',
|
|
3114
3306
|
gap: '8px',
|
|
3115
3307
|
padding: '6px 10px',
|
|
3116
|
-
fontSize: 'var(--c15t-devtools-font-size-xs)'
|
|
3308
|
+
fontSize: 'var(--c15t-devtools-font-size-xs)',
|
|
3309
|
+
cursor: 'pointer',
|
|
3310
|
+
borderColor: selected ? 'var(--c15t-devtools-badge-info, #3b82f6)' : 'var(--c15t-border)'
|
|
3117
3311
|
},
|
|
3312
|
+
onClick: onSelect,
|
|
3118
3313
|
children: [
|
|
3119
3314
|
span({
|
|
3120
3315
|
style: {
|
|
@@ -3143,6 +3338,21 @@ function createEventItem(event) {
|
|
|
3143
3338
|
]
|
|
3144
3339
|
});
|
|
3145
3340
|
}
|
|
3341
|
+
function exportEvents(events) {
|
|
3342
|
+
const json = JSON.stringify(events, null, 2);
|
|
3343
|
+
const blob = new Blob([
|
|
3344
|
+
json
|
|
3345
|
+
], {
|
|
3346
|
+
type: 'application/json'
|
|
3347
|
+
});
|
|
3348
|
+
const url = URL.createObjectURL(blob);
|
|
3349
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
3350
|
+
const a = document.createElement('a');
|
|
3351
|
+
a.href = url;
|
|
3352
|
+
a.download = `c15t-events-${timestamp}.json`;
|
|
3353
|
+
a.click();
|
|
3354
|
+
URL.revokeObjectURL(url);
|
|
3355
|
+
}
|
|
3146
3356
|
function formatTime(timestamp) {
|
|
3147
3357
|
const date = new Date(timestamp);
|
|
3148
3358
|
return date.toLocaleTimeString('en-US', {
|
|
@@ -3161,7 +3371,10 @@ function getEventIcon(type) {
|
|
|
3161
3371
|
return '○';
|
|
3162
3372
|
case 'error':
|
|
3163
3373
|
return '✕';
|
|
3164
|
-
case '
|
|
3374
|
+
case 'network':
|
|
3375
|
+
return '◉';
|
|
3376
|
+
case 'iab':
|
|
3377
|
+
return '◆';
|
|
3165
3378
|
default:
|
|
3166
3379
|
return '○';
|
|
3167
3380
|
}
|
|
@@ -3175,13 +3388,16 @@ function getEventColor(type) {
|
|
|
3175
3388
|
return 'var(--c15t-devtools-badge-warning, #f59e0b)';
|
|
3176
3389
|
case 'error':
|
|
3177
3390
|
return 'var(--c15t-devtools-badge-error, #ef4444)';
|
|
3178
|
-
case '
|
|
3391
|
+
case 'network':
|
|
3392
|
+
return 'var(--c15t-devtools-badge-warning, #f59e0b)';
|
|
3393
|
+
case 'iab':
|
|
3394
|
+
return 'var(--c15t-devtools-badge-info, #3b82f6)';
|
|
3179
3395
|
default:
|
|
3180
3396
|
return 'var(--c15t-text-muted)';
|
|
3181
3397
|
}
|
|
3182
3398
|
}
|
|
3183
3399
|
function renderIabPanel(container, options) {
|
|
3184
|
-
const { getState, onReset } = options;
|
|
3400
|
+
const { getState, onSetPurposeConsent, onSetVendorConsent, onSetSpecialFeatureOptIn, onAcceptAll, onRejectAll, onSave, onReset } = options;
|
|
3185
3401
|
clearElement(container);
|
|
3186
3402
|
const state = getState();
|
|
3187
3403
|
if (!state) return void container.appendChild(renderer_div({
|
|
@@ -3259,7 +3475,9 @@ function renderIabPanel(container, options) {
|
|
|
3259
3475
|
for (const [purposeId, consent] of purposeEntries){
|
|
3260
3476
|
const purposeInfo = purposes[purposeId];
|
|
3261
3477
|
const purposeName = purposeInfo?.name || `Purpose ${purposeId}`;
|
|
3262
|
-
purposeList.appendChild(createPurposeRow(purposeId, purposeName, Boolean(consent))
|
|
3478
|
+
purposeList.appendChild(createPurposeRow(purposeId, purposeName, Boolean(consent), (value)=>{
|
|
3479
|
+
onSetPurposeConsent(Number(purposeId), value);
|
|
3480
|
+
}));
|
|
3263
3481
|
}
|
|
3264
3482
|
const purposesSection = createSection({
|
|
3265
3483
|
title: `Purposes (${purposeEntries.length})`,
|
|
@@ -3285,7 +3503,9 @@ function renderIabPanel(container, options) {
|
|
|
3285
3503
|
for (const [featureId, optIn] of specialFeatureEntries){
|
|
3286
3504
|
const featureInfo = specialFeatures[featureId];
|
|
3287
3505
|
const featureName = featureInfo?.name || `Special Feature ${featureId}`;
|
|
3288
|
-
specialFeatureList.appendChild(createPurposeRow(featureId, featureName, Boolean(optIn))
|
|
3506
|
+
specialFeatureList.appendChild(createPurposeRow(featureId, featureName, Boolean(optIn), (value)=>{
|
|
3507
|
+
onSetSpecialFeatureOptIn(Number(featureId), value);
|
|
3508
|
+
}, 'feature'));
|
|
3289
3509
|
}
|
|
3290
3510
|
const specialFeaturesSection = createSection({
|
|
3291
3511
|
title: `Special Features (${specialFeatureEntries.length})`,
|
|
@@ -3325,7 +3545,9 @@ function renderIabPanel(container, options) {
|
|
|
3325
3545
|
overflowY: 'auto'
|
|
3326
3546
|
}
|
|
3327
3547
|
});
|
|
3328
|
-
for (const [vendorId, consent, vendorName] of iabVendors)vendorList.appendChild(createVendorRow(vendorId, vendorName, consent, 'iab')
|
|
3548
|
+
for (const [vendorId, consent, vendorName] of iabVendors)vendorList.appendChild(createVendorRow(vendorId, vendorName, consent, 'iab', (value)=>{
|
|
3549
|
+
onSetVendorConsent(Number(vendorId), value);
|
|
3550
|
+
}));
|
|
3329
3551
|
const vendorsSection = createSection({
|
|
3330
3552
|
title: `IAB Vendors (${iabVendors.length})`,
|
|
3331
3553
|
children: [
|
|
@@ -3344,7 +3566,9 @@ function renderIabPanel(container, options) {
|
|
|
3344
3566
|
overflowY: 'auto'
|
|
3345
3567
|
}
|
|
3346
3568
|
});
|
|
3347
|
-
for (const [vendorId, consent, vendorName] of customVendors)customVendorList.appendChild(createVendorRow(vendorId, vendorName, consent, 'custom')
|
|
3569
|
+
for (const [vendorId, consent, vendorName] of customVendors)customVendorList.appendChild(createVendorRow(vendorId, vendorName, consent, 'custom', (value)=>{
|
|
3570
|
+
onSetVendorConsent(vendorId, value);
|
|
3571
|
+
}));
|
|
3348
3572
|
const customVendorsSection = createSection({
|
|
3349
3573
|
title: `Custom Vendors (${customVendors.length})`,
|
|
3350
3574
|
children: [
|
|
@@ -3366,15 +3590,40 @@ function renderIabPanel(container, options) {
|
|
|
3366
3590
|
style: {
|
|
3367
3591
|
display: 'flex',
|
|
3368
3592
|
alignItems: 'center',
|
|
3369
|
-
justifyContent: '
|
|
3593
|
+
justifyContent: 'space-between',
|
|
3370
3594
|
padding: '12px 16px',
|
|
3371
3595
|
marginTop: 'auto',
|
|
3372
3596
|
borderTop: '1px solid var(--c15t-border)',
|
|
3373
3597
|
backgroundColor: 'var(--c15t-surface)'
|
|
3374
3598
|
},
|
|
3375
3599
|
children: [
|
|
3600
|
+
renderer_div({
|
|
3601
|
+
style: {
|
|
3602
|
+
display: 'flex',
|
|
3603
|
+
gap: '6px'
|
|
3604
|
+
},
|
|
3605
|
+
children: [
|
|
3606
|
+
createButton({
|
|
3607
|
+
text: 'Accept All',
|
|
3608
|
+
variant: 'primary',
|
|
3609
|
+
small: true,
|
|
3610
|
+
onClick: onAcceptAll
|
|
3611
|
+
}),
|
|
3612
|
+
createButton({
|
|
3613
|
+
text: 'Reject All',
|
|
3614
|
+
small: true,
|
|
3615
|
+
onClick: onRejectAll
|
|
3616
|
+
}),
|
|
3617
|
+
createButton({
|
|
3618
|
+
text: 'Save',
|
|
3619
|
+
variant: 'primary',
|
|
3620
|
+
small: true,
|
|
3621
|
+
onClick: onSave
|
|
3622
|
+
})
|
|
3623
|
+
]
|
|
3624
|
+
}),
|
|
3376
3625
|
createButton({
|
|
3377
|
-
text: 'Reset
|
|
3626
|
+
text: 'Reset',
|
|
3378
3627
|
variant: 'danger',
|
|
3379
3628
|
small: true,
|
|
3380
3629
|
onClick: onReset
|
|
@@ -3383,7 +3632,7 @@ function renderIabPanel(container, options) {
|
|
|
3383
3632
|
});
|
|
3384
3633
|
container.appendChild(footer);
|
|
3385
3634
|
}
|
|
3386
|
-
function createPurposeRow(id, name, consent) {
|
|
3635
|
+
function createPurposeRow(id, name, consent, onChange, ariaKind = 'purpose') {
|
|
3387
3636
|
return renderer_div({
|
|
3388
3637
|
style: {
|
|
3389
3638
|
display: 'flex',
|
|
@@ -3406,14 +3655,28 @@ function createPurposeRow(id, name, consent) {
|
|
|
3406
3655
|
text: `${id}. ${name}`,
|
|
3407
3656
|
title: name
|
|
3408
3657
|
}),
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3658
|
+
renderer_div({
|
|
3659
|
+
style: {
|
|
3660
|
+
display: 'flex',
|
|
3661
|
+
alignItems: 'center',
|
|
3662
|
+
gap: '6px'
|
|
3663
|
+
},
|
|
3664
|
+
children: [
|
|
3665
|
+
createBadge({
|
|
3666
|
+
text: consent ? '✓' : '✕',
|
|
3667
|
+
variant: consent ? 'success' : 'error'
|
|
3668
|
+
}),
|
|
3669
|
+
createToggle({
|
|
3670
|
+
checked: consent,
|
|
3671
|
+
onChange,
|
|
3672
|
+
ariaLabel: `Toggle ${ariaKind} ${id}`
|
|
3673
|
+
})
|
|
3674
|
+
]
|
|
3412
3675
|
})
|
|
3413
3676
|
]
|
|
3414
3677
|
});
|
|
3415
3678
|
}
|
|
3416
|
-
function createVendorRow(id, name, consent, type) {
|
|
3679
|
+
function createVendorRow(id, name, consent, type, onChange) {
|
|
3417
3680
|
return renderer_div({
|
|
3418
3681
|
style: {
|
|
3419
3682
|
display: 'flex',
|
|
@@ -3460,16 +3723,21 @@ function createVendorRow(id, name, consent, type) {
|
|
|
3460
3723
|
createBadge({
|
|
3461
3724
|
text: consent ? '✓' : '✕',
|
|
3462
3725
|
variant: consent ? 'success' : 'error'
|
|
3726
|
+
}),
|
|
3727
|
+
createToggle({
|
|
3728
|
+
checked: consent,
|
|
3729
|
+
onChange,
|
|
3730
|
+
ariaLabel: `Toggle vendor ${id}`
|
|
3463
3731
|
})
|
|
3464
3732
|
]
|
|
3465
3733
|
});
|
|
3466
3734
|
}
|
|
3467
3735
|
function truncateText(text, maxLength) {
|
|
3468
3736
|
if (text.length <= maxLength) return text;
|
|
3469
|
-
return text.slice(0, maxLength - 3)
|
|
3737
|
+
return `${text.slice(0, maxLength - 3)}...`;
|
|
3470
3738
|
}
|
|
3471
3739
|
function renderLocationPanel(container, options) {
|
|
3472
|
-
const { getState,
|
|
3740
|
+
const { getState, onApplyOverrides, onClearOverrides } = options;
|
|
3473
3741
|
clearElement(container);
|
|
3474
3742
|
const state = getState();
|
|
3475
3743
|
if (!state) return void container.appendChild(renderer_div({
|
|
@@ -3490,145 +3758,230 @@ function renderLocationPanel(container, options) {
|
|
|
3490
3758
|
createCompactInfoCard('Jurisdiction', locationInfo?.jurisdiction || '—'),
|
|
3491
3759
|
createCompactInfoCard('Language', translationConfig?.defaultLanguage || '—')
|
|
3492
3760
|
];
|
|
3761
|
+
gridItems.push(createCompactInfoCard('GPC', getEffectiveGpcLabel(overrides?.gpc)));
|
|
3493
3762
|
if (state.model) gridItems.push(createCompactInfoCard('Model', getModelLabel(state.model)));
|
|
3494
3763
|
const locationGrid = createGrid({
|
|
3495
|
-
columns:
|
|
3764
|
+
columns: 3,
|
|
3496
3765
|
children: gridItems
|
|
3497
3766
|
});
|
|
3498
3767
|
container.appendChild(locationGrid);
|
|
3768
|
+
const initialDraft = getDraftFromOverrides(overrides);
|
|
3769
|
+
let appliedOverrides = normalizeOverrideDraft(initialDraft);
|
|
3770
|
+
let isSubmitting = false;
|
|
3771
|
+
const countryField = createOverrideSelect({
|
|
3772
|
+
label: 'Country',
|
|
3773
|
+
selectOptions: COUNTRY_OPTIONS,
|
|
3774
|
+
value: initialDraft.country
|
|
3775
|
+
});
|
|
3776
|
+
const regionField = createOverrideInput({
|
|
3777
|
+
label: 'Region',
|
|
3778
|
+
placeholder: 'e.g., CA, NY, BE',
|
|
3779
|
+
value: initialDraft.region
|
|
3780
|
+
});
|
|
3781
|
+
const languageField = createOverrideInput({
|
|
3782
|
+
label: 'Language',
|
|
3783
|
+
placeholder: 'e.g., de, fr, en-US',
|
|
3784
|
+
value: initialDraft.language
|
|
3785
|
+
});
|
|
3786
|
+
const gpcField = createOverrideSelect({
|
|
3787
|
+
label: 'GPC',
|
|
3788
|
+
selectOptions: GPC_OPTIONS,
|
|
3789
|
+
value: initialDraft.gpc
|
|
3790
|
+
});
|
|
3791
|
+
const formStatus = span({
|
|
3792
|
+
className: styles_components_module.overrideStatus,
|
|
3793
|
+
text: 'In sync'
|
|
3794
|
+
});
|
|
3795
|
+
const applyButton = createButton({
|
|
3796
|
+
text: 'Apply',
|
|
3797
|
+
variant: 'primary',
|
|
3798
|
+
small: true,
|
|
3799
|
+
disabled: true,
|
|
3800
|
+
onClick: ()=>{
|
|
3801
|
+
applyDraft();
|
|
3802
|
+
}
|
|
3803
|
+
});
|
|
3804
|
+
const revertButton = createButton({
|
|
3805
|
+
text: 'Revert',
|
|
3806
|
+
small: true,
|
|
3807
|
+
disabled: true,
|
|
3808
|
+
onClick: ()=>{
|
|
3809
|
+
setDraftValues(getDraftFromOverrides(appliedOverrides));
|
|
3810
|
+
updateFormState();
|
|
3811
|
+
}
|
|
3812
|
+
});
|
|
3813
|
+
const clearButton = createButton({
|
|
3814
|
+
text: 'Clear',
|
|
3815
|
+
small: true,
|
|
3816
|
+
onClick: ()=>{
|
|
3817
|
+
clearDraftAndOverrides();
|
|
3818
|
+
}
|
|
3819
|
+
});
|
|
3820
|
+
const overrideFieldsGrid = renderer_div({
|
|
3821
|
+
style: {
|
|
3822
|
+
display: 'grid',
|
|
3823
|
+
gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
|
|
3824
|
+
gap: '8px 10px'
|
|
3825
|
+
},
|
|
3826
|
+
children: [
|
|
3827
|
+
countryField.element,
|
|
3828
|
+
regionField.element,
|
|
3829
|
+
languageField.element,
|
|
3830
|
+
gpcField.element
|
|
3831
|
+
]
|
|
3832
|
+
});
|
|
3499
3833
|
const overrideSection = createSection({
|
|
3500
3834
|
title: 'Override Settings',
|
|
3501
|
-
actions: [
|
|
3502
|
-
createButton({
|
|
3503
|
-
text: 'Clear',
|
|
3504
|
-
small: true,
|
|
3505
|
-
onClick: onClearOverrides
|
|
3506
|
-
})
|
|
3507
|
-
],
|
|
3508
3835
|
children: [
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
onChange: (value)=>onSetOverrides({
|
|
3514
|
-
country: value || void 0
|
|
3515
|
-
})
|
|
3516
|
-
}),
|
|
3517
|
-
createOverrideInput({
|
|
3518
|
-
label: 'Region',
|
|
3519
|
-
placeholder: 'e.g., CA, NY, BE',
|
|
3520
|
-
value: overrides?.region || '',
|
|
3521
|
-
onChange: (value)=>onSetOverrides({
|
|
3522
|
-
region: value || void 0
|
|
3523
|
-
})
|
|
3836
|
+
overrideFieldsGrid,
|
|
3837
|
+
span({
|
|
3838
|
+
className: styles_components_module.overrideHint,
|
|
3839
|
+
text: 'GPC override only affects opt-out or unregulated jurisdictions.'
|
|
3524
3840
|
}),
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3841
|
+
renderer_div({
|
|
3842
|
+
className: styles_components_module.overrideActions,
|
|
3843
|
+
children: [
|
|
3844
|
+
renderer_div({
|
|
3845
|
+
className: styles_components_module.overrideActionButtons,
|
|
3846
|
+
children: [
|
|
3847
|
+
revertButton,
|
|
3848
|
+
applyButton,
|
|
3849
|
+
clearButton
|
|
3850
|
+
]
|
|
3851
|
+
}),
|
|
3852
|
+
formStatus
|
|
3853
|
+
]
|
|
3532
3854
|
})
|
|
3533
3855
|
]
|
|
3534
3856
|
});
|
|
3535
3857
|
container.appendChild(overrideSection);
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3858
|
+
countryField.control.addEventListener('change', updateFormState);
|
|
3859
|
+
regionField.control.addEventListener('input', updateFormState);
|
|
3860
|
+
languageField.control.addEventListener('input', updateFormState);
|
|
3861
|
+
gpcField.control.addEventListener('change', updateFormState);
|
|
3862
|
+
updateFormState();
|
|
3863
|
+
async function applyDraft() {
|
|
3864
|
+
if (isSubmitting) return;
|
|
3865
|
+
const draftOverrides = getDraftOverrides();
|
|
3866
|
+
if (overridesEqual(draftOverrides, appliedOverrides)) return;
|
|
3867
|
+
isSubmitting = true;
|
|
3868
|
+
updateFormState();
|
|
3869
|
+
try {
|
|
3870
|
+
await onApplyOverrides(draftOverrides);
|
|
3871
|
+
appliedOverrides = draftOverrides;
|
|
3872
|
+
} finally{
|
|
3873
|
+
isSubmitting = false;
|
|
3874
|
+
updateFormState();
|
|
3875
|
+
}
|
|
3876
|
+
}
|
|
3877
|
+
async function clearDraftAndOverrides() {
|
|
3878
|
+
if (isSubmitting) return;
|
|
3879
|
+
isSubmitting = true;
|
|
3880
|
+
updateFormState();
|
|
3881
|
+
try {
|
|
3882
|
+
await onClearOverrides();
|
|
3883
|
+
appliedOverrides = {};
|
|
3884
|
+
setDraftValues(getDraftFromOverrides(void 0));
|
|
3885
|
+
} finally{
|
|
3886
|
+
isSubmitting = false;
|
|
3887
|
+
updateFormState();
|
|
3888
|
+
}
|
|
3889
|
+
}
|
|
3890
|
+
function getDraftOverrides() {
|
|
3891
|
+
return normalizeOverrideDraft({
|
|
3892
|
+
country: countryField.control.value,
|
|
3893
|
+
region: regionField.control.value,
|
|
3894
|
+
language: languageField.control.value,
|
|
3895
|
+
gpc: gpcField.control.value
|
|
3547
3896
|
});
|
|
3548
|
-
|
|
3897
|
+
}
|
|
3898
|
+
function setDraftValues(draft) {
|
|
3899
|
+
countryField.control.value = draft.country;
|
|
3900
|
+
regionField.control.value = draft.region;
|
|
3901
|
+
languageField.control.value = draft.language;
|
|
3902
|
+
gpcField.control.value = draft.gpc;
|
|
3903
|
+
}
|
|
3904
|
+
function updateFormState() {
|
|
3905
|
+
const draftOverrides = getDraftOverrides();
|
|
3906
|
+
const hasDraftChanges = !overridesEqual(draftOverrides, appliedOverrides);
|
|
3907
|
+
applyButton.disabled = !hasDraftChanges || isSubmitting;
|
|
3908
|
+
revertButton.disabled = !hasDraftChanges || isSubmitting;
|
|
3909
|
+
clearButton.disabled = isSubmitting;
|
|
3910
|
+
formStatus.textContent = isSubmitting ? 'Applying...' : hasDraftChanges ? 'Unsaved changes' : hasOverridesValue(appliedOverrides) ? 'Overrides active' : 'No overrides';
|
|
3911
|
+
if (styles_components_module.overrideStatusDirty) formStatus.classList.toggle(styles_components_module.overrideStatusDirty, !isSubmitting && hasDraftChanges);
|
|
3549
3912
|
}
|
|
3550
3913
|
}
|
|
3551
3914
|
function createOverrideInput(options) {
|
|
3552
|
-
const { label, placeholder, value
|
|
3553
|
-
let debounceTimer = null;
|
|
3915
|
+
const { label, placeholder, value } = options;
|
|
3554
3916
|
const inputField = input({
|
|
3555
3917
|
className: `${styles_components_module.input ?? ''} ${styles_components_module.inputSmall ?? ''}`.trim(),
|
|
3556
3918
|
placeholder,
|
|
3557
|
-
value
|
|
3558
|
-
onInput: (e)=>{
|
|
3559
|
-
const target = e.target;
|
|
3560
|
-
if (debounceTimer) clearTimeout(debounceTimer);
|
|
3561
|
-
debounceTimer = setTimeout(()=>{
|
|
3562
|
-
onChange(target.value);
|
|
3563
|
-
}, 500);
|
|
3564
|
-
}
|
|
3565
|
-
});
|
|
3566
|
-
return renderer_div({
|
|
3567
|
-
style: {
|
|
3568
|
-
display: 'flex',
|
|
3569
|
-
alignItems: 'center',
|
|
3570
|
-
justifyContent: 'space-between',
|
|
3571
|
-
gap: '8px',
|
|
3572
|
-
marginBottom: '8px'
|
|
3573
|
-
},
|
|
3574
|
-
children: [
|
|
3575
|
-
renderer_div({
|
|
3576
|
-
style: {
|
|
3577
|
-
fontSize: 'var(--c15t-devtools-font-size-xs)',
|
|
3578
|
-
color: 'var(--c15t-devtools-text-muted)',
|
|
3579
|
-
minWidth: '60px'
|
|
3580
|
-
},
|
|
3581
|
-
text: label
|
|
3582
|
-
}),
|
|
3583
|
-
renderer_div({
|
|
3584
|
-
style: {
|
|
3585
|
-
flex: '1'
|
|
3586
|
-
},
|
|
3587
|
-
children: [
|
|
3588
|
-
inputField
|
|
3589
|
-
]
|
|
3590
|
-
})
|
|
3591
|
-
]
|
|
3919
|
+
value
|
|
3592
3920
|
});
|
|
3921
|
+
return {
|
|
3922
|
+
element: renderer_div({
|
|
3923
|
+
className: styles_components_module.overrideField,
|
|
3924
|
+
children: [
|
|
3925
|
+
span({
|
|
3926
|
+
className: styles_components_module.overrideLabel,
|
|
3927
|
+
text: label
|
|
3928
|
+
}),
|
|
3929
|
+
inputField
|
|
3930
|
+
]
|
|
3931
|
+
}),
|
|
3932
|
+
control: inputField
|
|
3933
|
+
};
|
|
3593
3934
|
}
|
|
3594
3935
|
function createOverrideSelect(options) {
|
|
3595
|
-
const { label, selectOptions, value
|
|
3936
|
+
const { label, selectOptions, value } = options;
|
|
3596
3937
|
const selectField = renderer_select({
|
|
3597
3938
|
className: `${styles_components_module.input ?? ''} ${styles_components_module.inputSmall ?? ''}`.trim(),
|
|
3598
3939
|
options: selectOptions,
|
|
3599
|
-
selectedValue: value
|
|
3600
|
-
onChange: (e)=>{
|
|
3601
|
-
const target = e.target;
|
|
3602
|
-
onChange(target.value);
|
|
3603
|
-
}
|
|
3604
|
-
});
|
|
3605
|
-
return renderer_div({
|
|
3606
|
-
style: {
|
|
3607
|
-
display: 'flex',
|
|
3608
|
-
alignItems: 'center',
|
|
3609
|
-
justifyContent: 'space-between',
|
|
3610
|
-
gap: '8px',
|
|
3611
|
-
marginBottom: '8px'
|
|
3612
|
-
},
|
|
3613
|
-
children: [
|
|
3614
|
-
renderer_div({
|
|
3615
|
-
style: {
|
|
3616
|
-
fontSize: 'var(--c15t-devtools-font-size-xs)',
|
|
3617
|
-
color: 'var(--c15t-devtools-text-muted)',
|
|
3618
|
-
minWidth: '60px'
|
|
3619
|
-
},
|
|
3620
|
-
text: label
|
|
3621
|
-
}),
|
|
3622
|
-
renderer_div({
|
|
3623
|
-
style: {
|
|
3624
|
-
flex: '1'
|
|
3625
|
-
},
|
|
3626
|
-
children: [
|
|
3627
|
-
selectField
|
|
3628
|
-
]
|
|
3629
|
-
})
|
|
3630
|
-
]
|
|
3940
|
+
selectedValue: value
|
|
3631
3941
|
});
|
|
3942
|
+
return {
|
|
3943
|
+
element: renderer_div({
|
|
3944
|
+
className: styles_components_module.overrideField,
|
|
3945
|
+
children: [
|
|
3946
|
+
span({
|
|
3947
|
+
className: styles_components_module.overrideLabel,
|
|
3948
|
+
text: label
|
|
3949
|
+
}),
|
|
3950
|
+
selectField
|
|
3951
|
+
]
|
|
3952
|
+
}),
|
|
3953
|
+
control: selectField
|
|
3954
|
+
};
|
|
3955
|
+
}
|
|
3956
|
+
function getDraftFromOverrides(overrides) {
|
|
3957
|
+
return {
|
|
3958
|
+
country: overrides?.country ?? '',
|
|
3959
|
+
region: overrides?.region ?? '',
|
|
3960
|
+
language: overrides?.language ?? '',
|
|
3961
|
+
gpc: overrides?.gpc === true ? 'true' : overrides?.gpc === false ? 'false' : ''
|
|
3962
|
+
};
|
|
3963
|
+
}
|
|
3964
|
+
function normalizeOverrideDraft(draft) {
|
|
3965
|
+
return {
|
|
3966
|
+
country: normalizeAlphaCode(draft.country),
|
|
3967
|
+
region: normalizeAlphaCode(draft.region),
|
|
3968
|
+
language: normalizeLanguageCode(draft.language),
|
|
3969
|
+
gpc: 'true' === draft.gpc ? true : 'false' === draft.gpc ? false : void 0
|
|
3970
|
+
};
|
|
3971
|
+
}
|
|
3972
|
+
function normalizeAlphaCode(value) {
|
|
3973
|
+
const normalized = value.trim().toUpperCase();
|
|
3974
|
+
return normalized || void 0;
|
|
3975
|
+
}
|
|
3976
|
+
function normalizeLanguageCode(value) {
|
|
3977
|
+
const normalized = value.trim();
|
|
3978
|
+
return normalized || void 0;
|
|
3979
|
+
}
|
|
3980
|
+
function overridesEqual(a, b) {
|
|
3981
|
+
return a.country === b.country && a.region === b.region && a.language === b.language && a.gpc === b.gpc;
|
|
3982
|
+
}
|
|
3983
|
+
function hasOverridesValue(overrides) {
|
|
3984
|
+
return Boolean(overrides.country || overrides.region || overrides.language || void 0 !== overrides.gpc);
|
|
3632
3985
|
}
|
|
3633
3986
|
const COUNTRY_OPTIONS = [
|
|
3634
3987
|
{
|
|
@@ -3752,6 +4105,32 @@ const COUNTRY_OPTIONS = [
|
|
|
3752
4105
|
label: 'ZA - South Africa'
|
|
3753
4106
|
}
|
|
3754
4107
|
];
|
|
4108
|
+
const GPC_OPTIONS = [
|
|
4109
|
+
{
|
|
4110
|
+
value: '',
|
|
4111
|
+
label: '-- Browser Default --'
|
|
4112
|
+
},
|
|
4113
|
+
{
|
|
4114
|
+
value: 'true',
|
|
4115
|
+
label: 'Force On (Simulated)'
|
|
4116
|
+
},
|
|
4117
|
+
{
|
|
4118
|
+
value: 'false',
|
|
4119
|
+
label: 'Force Off (Simulated)'
|
|
4120
|
+
}
|
|
4121
|
+
];
|
|
4122
|
+
function getEffectiveGpcLabel(gpcOverride) {
|
|
4123
|
+
if (true === gpcOverride) return 'On (Override)';
|
|
4124
|
+
if (false === gpcOverride) return 'Off (Override)';
|
|
4125
|
+
if ('undefined' == typeof window || 'undefined' == typeof navigator) return 'Unknown';
|
|
4126
|
+
try {
|
|
4127
|
+
const nav = navigator;
|
|
4128
|
+
const value = nav.globalPrivacyControl;
|
|
4129
|
+
return true === value || '1' === value ? 'Active' : 'Inactive';
|
|
4130
|
+
} catch {
|
|
4131
|
+
return 'Unknown';
|
|
4132
|
+
}
|
|
4133
|
+
}
|
|
3755
4134
|
function getModelLabel(model) {
|
|
3756
4135
|
switch(model){
|
|
3757
4136
|
case 'opt-in':
|
|
@@ -3768,9 +4147,11 @@ function createCompactInfoCard(label, value) {
|
|
|
3768
4147
|
return renderer_div({
|
|
3769
4148
|
className: styles_components_module.gridCard ?? '',
|
|
3770
4149
|
style: {
|
|
4150
|
+
padding: '6px 8px',
|
|
4151
|
+
minHeight: 'auto',
|
|
3771
4152
|
flexDirection: 'column',
|
|
3772
4153
|
alignItems: 'flex-start',
|
|
3773
|
-
gap: '
|
|
4154
|
+
gap: '1px'
|
|
3774
4155
|
},
|
|
3775
4156
|
children: [
|
|
3776
4157
|
span({
|
|
@@ -3795,34 +4176,38 @@ const dismissedResources = new Set();
|
|
|
3795
4176
|
function scanDOM(state) {
|
|
3796
4177
|
const results = [];
|
|
3797
4178
|
const configuredScripts = state.scripts || [];
|
|
3798
|
-
const
|
|
4179
|
+
const managedResources = [];
|
|
3799
4180
|
for (const script of configuredScripts)if (script.src) try {
|
|
3800
4181
|
const url = new URL(script.src, window.location.origin);
|
|
3801
|
-
if (url.hostname !== window.location.hostname)
|
|
4182
|
+
if (url.hostname !== window.location.hostname) managedResources.push({
|
|
4183
|
+
scriptId: script.id,
|
|
4184
|
+
domain: url.hostname,
|
|
4185
|
+
pathPrefix: normalizePathname(url.pathname)
|
|
4186
|
+
});
|
|
3802
4187
|
} catch {}
|
|
3803
4188
|
const scriptElements = document.querySelectorAll("script[src]");
|
|
3804
4189
|
for (const el of scriptElements){
|
|
3805
4190
|
const src = el.getAttribute('src');
|
|
3806
4191
|
if (!src) continue;
|
|
3807
|
-
const resource = checkResource(src, "script",
|
|
4192
|
+
const resource = checkResource(src, "script", managedResources);
|
|
3808
4193
|
if (resource) results.push(resource);
|
|
3809
4194
|
}
|
|
3810
4195
|
const iframeElements = document.querySelectorAll('iframe[src]');
|
|
3811
4196
|
for (const el of iframeElements){
|
|
3812
4197
|
const src = el.getAttribute('src');
|
|
3813
4198
|
if (!src) continue;
|
|
3814
|
-
const resource = checkResource(src, 'iframe',
|
|
4199
|
+
const resource = checkResource(src, 'iframe', managedResources);
|
|
3815
4200
|
if (resource) results.push(resource);
|
|
3816
4201
|
}
|
|
3817
4202
|
return results;
|
|
3818
4203
|
}
|
|
3819
|
-
function checkResource(src, type,
|
|
4204
|
+
function checkResource(src, type, managedResources) {
|
|
3820
4205
|
try {
|
|
3821
4206
|
const url = new URL(src, window.location.origin);
|
|
3822
4207
|
const domain = url.hostname;
|
|
3823
4208
|
if (domain === window.location.hostname) return null;
|
|
3824
4209
|
if ('data:' === url.protocol || 'blob:' === url.protocol) return null;
|
|
3825
|
-
const managedBy =
|
|
4210
|
+
const managedBy = findManagedScriptId(url, managedResources);
|
|
3826
4211
|
const isManaged = Boolean(managedBy);
|
|
3827
4212
|
return {
|
|
3828
4213
|
type,
|
|
@@ -3834,6 +4219,21 @@ function checkResource(src, type, managedDomains) {
|
|
|
3834
4219
|
} catch {}
|
|
3835
4220
|
return null;
|
|
3836
4221
|
}
|
|
4222
|
+
function findManagedScriptId(url, managedResources) {
|
|
4223
|
+
const domain = url.hostname;
|
|
4224
|
+
const path = normalizePathname(url.pathname);
|
|
4225
|
+
let bestMatch = null;
|
|
4226
|
+
for (const matcher of managedResources)if (matcher.domain === domain) {
|
|
4227
|
+
if ('/' === matcher.pathPrefix || path.startsWith(matcher.pathPrefix)) {
|
|
4228
|
+
if (!bestMatch || matcher.pathPrefix.length > bestMatch.pathPrefix.length) bestMatch = matcher;
|
|
4229
|
+
}
|
|
4230
|
+
}
|
|
4231
|
+
return bestMatch?.scriptId;
|
|
4232
|
+
}
|
|
4233
|
+
function normalizePathname(pathname) {
|
|
4234
|
+
const trimmed = pathname.trim();
|
|
4235
|
+
return trimmed.length > 0 ? trimmed : '/';
|
|
4236
|
+
}
|
|
3837
4237
|
function createDomScannerSection(state) {
|
|
3838
4238
|
let resultsContainer = null;
|
|
3839
4239
|
let lastScanResults = [];
|
|
@@ -3998,7 +4398,7 @@ const CODE_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" f
|
|
|
3998
4398
|
<polyline points="8 6 2 12 8 18"></polyline>
|
|
3999
4399
|
</svg>`;
|
|
4000
4400
|
function renderScriptsPanel(container, options) {
|
|
4001
|
-
const { getState } = options;
|
|
4401
|
+
const { getState, getEvents } = options;
|
|
4002
4402
|
clearElement(container);
|
|
4003
4403
|
const state = getState();
|
|
4004
4404
|
if (!state) return void container.appendChild(renderer_div({
|
|
@@ -4013,6 +4413,7 @@ function renderScriptsPanel(container, options) {
|
|
|
4013
4413
|
const scripts = state.scripts || [];
|
|
4014
4414
|
const loadedScripts = state.loadedScripts || {};
|
|
4015
4415
|
const networkBlocker = state.networkBlocker;
|
|
4416
|
+
const events = getEvents?.() ?? [];
|
|
4016
4417
|
if (0 === scripts.length) {
|
|
4017
4418
|
const scriptsSection = createSection({
|
|
4018
4419
|
title: 'Configured Scripts',
|
|
@@ -4095,6 +4496,20 @@ function renderScriptsPanel(container, options) {
|
|
|
4095
4496
|
]
|
|
4096
4497
|
});
|
|
4097
4498
|
container.appendChild(networkSection);
|
|
4499
|
+
const blockedRequestEvents = events.filter((event)=>'network' === event.type);
|
|
4500
|
+
const networkEventsSection = createSection({
|
|
4501
|
+
title: `Blocked Requests (${blockedRequestEvents.length})`,
|
|
4502
|
+
children: 0 === blockedRequestEvents.length ? [
|
|
4503
|
+
renderer_div({
|
|
4504
|
+
style: {
|
|
4505
|
+
fontSize: 'var(--c15t-devtools-font-size-xs)',
|
|
4506
|
+
color: 'var(--c15t-devtools-text-muted)'
|
|
4507
|
+
},
|
|
4508
|
+
text: 'No blocked network requests recorded in this session'
|
|
4509
|
+
})
|
|
4510
|
+
] : createBlockedRequestContent(blockedRequestEvents)
|
|
4511
|
+
});
|
|
4512
|
+
container.appendChild(networkEventsSection);
|
|
4098
4513
|
const loadedCount = Object.values(loadedScripts).filter(Boolean).length;
|
|
4099
4514
|
const totalCount = scripts.length;
|
|
4100
4515
|
const summarySection = createSection({
|
|
@@ -4120,12 +4535,127 @@ function renderScriptsPanel(container, options) {
|
|
|
4120
4535
|
}
|
|
4121
4536
|
function checkScriptConsent(state, category) {
|
|
4122
4537
|
if (!category) return true;
|
|
4538
|
+
if ('function' == typeof state.has) try {
|
|
4539
|
+
return state.has(category);
|
|
4540
|
+
} catch {}
|
|
4123
4541
|
if ('string' == typeof category) {
|
|
4124
4542
|
const consents = state.consents || {};
|
|
4125
4543
|
return true === consents[category];
|
|
4126
4544
|
}
|
|
4127
4545
|
return false;
|
|
4128
4546
|
}
|
|
4547
|
+
function createBlockedRequestContent(events) {
|
|
4548
|
+
const stats = new Map();
|
|
4549
|
+
for (const event of events){
|
|
4550
|
+
const ruleId = getEventRuleId(event) ?? 'unknown';
|
|
4551
|
+
stats.set(ruleId, (stats.get(ruleId) ?? 0) + 1);
|
|
4552
|
+
}
|
|
4553
|
+
const statsList = renderer_div({
|
|
4554
|
+
style: {
|
|
4555
|
+
display: 'flex',
|
|
4556
|
+
flexDirection: 'column',
|
|
4557
|
+
gap: '4px',
|
|
4558
|
+
marginBottom: '8px'
|
|
4559
|
+
},
|
|
4560
|
+
children: [
|
|
4561
|
+
...stats.entries()
|
|
4562
|
+
].sort((a, b)=>b[1] - a[1]).map(([ruleId, count])=>createInfoRow({
|
|
4563
|
+
label: 'unknown' === ruleId ? 'Unknown Rule' : `Rule: ${ruleId}`,
|
|
4564
|
+
value: `${count}`
|
|
4565
|
+
}))
|
|
4566
|
+
});
|
|
4567
|
+
const latestEvents = events.slice(0, 5);
|
|
4568
|
+
const latestList = renderer_div({
|
|
4569
|
+
style: {
|
|
4570
|
+
display: 'flex',
|
|
4571
|
+
flexDirection: 'column',
|
|
4572
|
+
gap: '4px'
|
|
4573
|
+
},
|
|
4574
|
+
children: latestEvents.map((event)=>createInfoRow({
|
|
4575
|
+
label: `${formatEventTime(event.timestamp)} ${getEventMethod(event)}`,
|
|
4576
|
+
value: scripts_truncateText(getEventUrl(event), 38)
|
|
4577
|
+
}))
|
|
4578
|
+
});
|
|
4579
|
+
return [
|
|
4580
|
+
statsList,
|
|
4581
|
+
latestList
|
|
4582
|
+
];
|
|
4583
|
+
}
|
|
4584
|
+
function getEventRuleId(event) {
|
|
4585
|
+
const data = event.data;
|
|
4586
|
+
const rule = data?.rule;
|
|
4587
|
+
const ruleId = rule?.id ?? data?.ruleId;
|
|
4588
|
+
return 'string' == typeof ruleId || 'number' == typeof ruleId ? String(ruleId) : void 0;
|
|
4589
|
+
}
|
|
4590
|
+
function getEventMethod(event) {
|
|
4591
|
+
const data = event.data;
|
|
4592
|
+
const method = data?.method;
|
|
4593
|
+
return 'string' == typeof method ? method.toUpperCase() : 'REQ';
|
|
4594
|
+
}
|
|
4595
|
+
function getEventUrl(event) {
|
|
4596
|
+
const data = event.data;
|
|
4597
|
+
const url = data?.url;
|
|
4598
|
+
return 'string' == typeof url ? url : event.message;
|
|
4599
|
+
}
|
|
4600
|
+
function formatEventTime(timestamp) {
|
|
4601
|
+
return new Date(timestamp).toLocaleTimeString('en-US', {
|
|
4602
|
+
hour12: false,
|
|
4603
|
+
hour: '2-digit',
|
|
4604
|
+
minute: '2-digit',
|
|
4605
|
+
second: '2-digit'
|
|
4606
|
+
});
|
|
4607
|
+
}
|
|
4608
|
+
function scripts_truncateText(text, maxLength) {
|
|
4609
|
+
if (text.length <= maxLength) return text;
|
|
4610
|
+
return `${text.slice(0, maxLength - 3)}...`;
|
|
4611
|
+
}
|
|
4612
|
+
const DEVTOOLS_OVERRIDES_STORAGE_KEY = 'c15t-devtools-overrides';
|
|
4613
|
+
function normalizeStringValue(value) {
|
|
4614
|
+
if ('string' != typeof value) return;
|
|
4615
|
+
const normalized = value.trim();
|
|
4616
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
4617
|
+
}
|
|
4618
|
+
function normalizeBooleanValue(value) {
|
|
4619
|
+
return 'boolean' == typeof value ? value : void 0;
|
|
4620
|
+
}
|
|
4621
|
+
function normalizeOverrides(value) {
|
|
4622
|
+
if (!value || 'object' != typeof value) return null;
|
|
4623
|
+
const source = value;
|
|
4624
|
+
const overrides = {
|
|
4625
|
+
country: normalizeStringValue(source.country),
|
|
4626
|
+
region: normalizeStringValue(source.region),
|
|
4627
|
+
language: normalizeStringValue(source.language),
|
|
4628
|
+
gpc: normalizeBooleanValue(source.gpc)
|
|
4629
|
+
};
|
|
4630
|
+
return hasPersistedOverrides(overrides) ? overrides : null;
|
|
4631
|
+
}
|
|
4632
|
+
function hasPersistedOverrides(overrides) {
|
|
4633
|
+
return Boolean(overrides.country || overrides.region || overrides.language || void 0 !== overrides.gpc);
|
|
4634
|
+
}
|
|
4635
|
+
function loadPersistedOverrides(storageKey = DEVTOOLS_OVERRIDES_STORAGE_KEY) {
|
|
4636
|
+
if ('undefined' == typeof window) return null;
|
|
4637
|
+
try {
|
|
4638
|
+
const stored = localStorage.getItem(storageKey);
|
|
4639
|
+
if (!stored) return null;
|
|
4640
|
+
const parsed = JSON.parse(stored);
|
|
4641
|
+
return normalizeOverrides(parsed);
|
|
4642
|
+
} catch {
|
|
4643
|
+
return null;
|
|
4644
|
+
}
|
|
4645
|
+
}
|
|
4646
|
+
function persistOverrides(overrides, storageKey = DEVTOOLS_OVERRIDES_STORAGE_KEY) {
|
|
4647
|
+
if ('undefined' == typeof window) return;
|
|
4648
|
+
try {
|
|
4649
|
+
if (!hasPersistedOverrides(overrides)) return void localStorage.removeItem(storageKey);
|
|
4650
|
+
localStorage.setItem(storageKey, JSON.stringify(overrides));
|
|
4651
|
+
} catch {}
|
|
4652
|
+
}
|
|
4653
|
+
function clearPersistedOverrides(storageKey = DEVTOOLS_OVERRIDES_STORAGE_KEY) {
|
|
4654
|
+
if ('undefined' == typeof window) return;
|
|
4655
|
+
try {
|
|
4656
|
+
localStorage.removeItem(storageKey);
|
|
4657
|
+
} catch {}
|
|
4658
|
+
}
|
|
4129
4659
|
const STORAGE_KEYS = {
|
|
4130
4660
|
C15T: 'c15t',
|
|
4131
4661
|
PENDING_SYNC: 'c15t:pending-consent-sync',
|
|
@@ -4263,12 +4793,37 @@ function createStoreConnector(options = {}) {
|
|
|
4263
4793
|
const { namespace = 'c15tStore', onConnect, onStateChange, onDisconnect } = options;
|
|
4264
4794
|
let store = null;
|
|
4265
4795
|
let unsubscribe = null;
|
|
4266
|
-
let
|
|
4796
|
+
let reconnectTimeout = null;
|
|
4797
|
+
let reconnectAttempts = 0;
|
|
4798
|
+
let hasNotifiedDisconnect = false;
|
|
4267
4799
|
const listeners = new Set();
|
|
4800
|
+
const INITIAL_RETRY_DELAY_MS = 100;
|
|
4801
|
+
const MAX_RETRY_DELAY_MS = 2000;
|
|
4802
|
+
const DISCONNECT_NOTIFY_ATTEMPTS = 5;
|
|
4803
|
+
function clearReconnectTimer() {
|
|
4804
|
+
if (reconnectTimeout) {
|
|
4805
|
+
clearTimeout(reconnectTimeout);
|
|
4806
|
+
reconnectTimeout = null;
|
|
4807
|
+
}
|
|
4808
|
+
}
|
|
4809
|
+
function resetReconnectState() {
|
|
4810
|
+
reconnectAttempts = 0;
|
|
4811
|
+
hasNotifiedDisconnect = false;
|
|
4812
|
+
}
|
|
4813
|
+
function notifyDisconnectedOnce() {
|
|
4814
|
+
if (hasNotifiedDisconnect) return;
|
|
4815
|
+
hasNotifiedDisconnect = true;
|
|
4816
|
+
onDisconnect?.();
|
|
4817
|
+
}
|
|
4268
4818
|
function tryConnect() {
|
|
4269
4819
|
if ('undefined' == typeof window) return false;
|
|
4270
4820
|
const storeInstance = window[namespace];
|
|
4271
4821
|
if (storeInstance && 'function' == typeof storeInstance.getState) {
|
|
4822
|
+
if (store === storeInstance && unsubscribe) return true;
|
|
4823
|
+
if (unsubscribe) {
|
|
4824
|
+
unsubscribe();
|
|
4825
|
+
unsubscribe = null;
|
|
4826
|
+
}
|
|
4272
4827
|
store = storeInstance;
|
|
4273
4828
|
unsubscribe = store.subscribe((state)=>{
|
|
4274
4829
|
onStateChange?.(state);
|
|
@@ -4276,30 +4831,26 @@ function createStoreConnector(options = {}) {
|
|
|
4276
4831
|
});
|
|
4277
4832
|
const currentState = store.getState();
|
|
4278
4833
|
onConnect?.(currentState, store);
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
pollInterval = null;
|
|
4282
|
-
}
|
|
4834
|
+
clearReconnectTimer();
|
|
4835
|
+
resetReconnectState();
|
|
4283
4836
|
return true;
|
|
4284
4837
|
}
|
|
4285
4838
|
return false;
|
|
4286
4839
|
}
|
|
4840
|
+
function scheduleReconnect(immediate = false) {
|
|
4841
|
+
if (store || reconnectTimeout) return;
|
|
4842
|
+
const delay = immediate ? 0 : Math.min(INITIAL_RETRY_DELAY_MS * 2 ** Math.min(reconnectAttempts, 5), MAX_RETRY_DELAY_MS);
|
|
4843
|
+
reconnectTimeout = setTimeout(()=>{
|
|
4844
|
+
reconnectTimeout = null;
|
|
4845
|
+
reconnectAttempts++;
|
|
4846
|
+
if (tryConnect()) return;
|
|
4847
|
+
if (reconnectAttempts >= DISCONNECT_NOTIFY_ATTEMPTS) notifyDisconnectedOnce();
|
|
4848
|
+
scheduleReconnect();
|
|
4849
|
+
}, delay);
|
|
4850
|
+
}
|
|
4287
4851
|
function startPolling() {
|
|
4288
|
-
if (pollInterval) return;
|
|
4289
4852
|
if (tryConnect()) return;
|
|
4290
|
-
|
|
4291
|
-
const maxAttempts = 50;
|
|
4292
|
-
pollInterval = setInterval(()=>{
|
|
4293
|
-
attempts++;
|
|
4294
|
-
if (tryConnect()) return;
|
|
4295
|
-
if (attempts >= maxAttempts) {
|
|
4296
|
-
if (pollInterval) {
|
|
4297
|
-
clearInterval(pollInterval);
|
|
4298
|
-
pollInterval = null;
|
|
4299
|
-
}
|
|
4300
|
-
onDisconnect?.();
|
|
4301
|
-
}
|
|
4302
|
-
}, 100);
|
|
4853
|
+
scheduleReconnect(true);
|
|
4303
4854
|
}
|
|
4304
4855
|
startPolling();
|
|
4305
4856
|
return {
|
|
@@ -4313,11 +4864,13 @@ function createStoreConnector(options = {}) {
|
|
|
4313
4864
|
listeners.delete(listener);
|
|
4314
4865
|
};
|
|
4315
4866
|
},
|
|
4867
|
+
retryConnection: ()=>{
|
|
4868
|
+
if (store) return;
|
|
4869
|
+
resetReconnectState();
|
|
4870
|
+
scheduleReconnect(true);
|
|
4871
|
+
},
|
|
4316
4872
|
destroy: ()=>{
|
|
4317
|
-
|
|
4318
|
-
clearInterval(pollInterval);
|
|
4319
|
-
pollInterval = null;
|
|
4320
|
-
}
|
|
4873
|
+
clearReconnectTimer();
|
|
4321
4874
|
if (unsubscribe) {
|
|
4322
4875
|
unsubscribe();
|
|
4323
4876
|
unsubscribe = null;
|
|
@@ -4345,6 +4898,86 @@ tokens_options.domAPI = styleDomAPI_default();
|
|
|
4345
4898
|
tokens_options.insertStyleElement = insertStyleElement_default();
|
|
4346
4899
|
injectStylesIntoStyleTag_default()(tokens.A, tokens_options);
|
|
4347
4900
|
tokens.A && tokens.A.locals && tokens.A.locals;
|
|
4901
|
+
const PANEL_HEIGHT_TRANSITION = 'height var(--c15t-duration-normal, 200ms) var(--c15t-easing, cubic-bezier(0.4, 0, 0.2, 1))';
|
|
4902
|
+
const PANEL_HEIGHT_TRANSITION_MS = 200;
|
|
4903
|
+
const PANEL_HEIGHT_TRANSITION_BUFFER_MS = 80;
|
|
4904
|
+
function normalizeOverridesForPersistence(overrides) {
|
|
4905
|
+
return {
|
|
4906
|
+
country: overrides?.country?.trim() || void 0,
|
|
4907
|
+
region: overrides?.region?.trim() || void 0,
|
|
4908
|
+
language: overrides?.language?.trim() || void 0,
|
|
4909
|
+
gpc: overrides?.gpc
|
|
4910
|
+
};
|
|
4911
|
+
}
|
|
4912
|
+
function persistedOverridesEqual(a, b) {
|
|
4913
|
+
return a.country === b.country && a.region === b.region && a.language === b.language && a.gpc === b.gpc;
|
|
4914
|
+
}
|
|
4915
|
+
function getBlockedRequestMessage(payload) {
|
|
4916
|
+
const data = payload;
|
|
4917
|
+
const method = 'string' == typeof data?.method ? data.method.toUpperCase() : 'REQUEST';
|
|
4918
|
+
const url = 'string' == typeof data?.url ? data.url : 'unknown-url';
|
|
4919
|
+
return `Network blocked: ${method} ${url}`;
|
|
4920
|
+
}
|
|
4921
|
+
function prefersReducedMotion() {
|
|
4922
|
+
return 'undefined' != typeof window && 'function' == typeof window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
4923
|
+
}
|
|
4924
|
+
function createPanelHeightAnimator() {
|
|
4925
|
+
let activePanel = null;
|
|
4926
|
+
let frameId = null;
|
|
4927
|
+
let timeoutId = null;
|
|
4928
|
+
let removeTransitionListener = null;
|
|
4929
|
+
function clearAnimationState() {
|
|
4930
|
+
if (null !== frameId) {
|
|
4931
|
+
window.cancelAnimationFrame(frameId);
|
|
4932
|
+
frameId = null;
|
|
4933
|
+
}
|
|
4934
|
+
if (null !== timeoutId) {
|
|
4935
|
+
clearTimeout(timeoutId);
|
|
4936
|
+
timeoutId = null;
|
|
4937
|
+
}
|
|
4938
|
+
if (removeTransitionListener) {
|
|
4939
|
+
removeTransitionListener();
|
|
4940
|
+
removeTransitionListener = null;
|
|
4941
|
+
}
|
|
4942
|
+
if (activePanel) {
|
|
4943
|
+
activePanel.style.height = '';
|
|
4944
|
+
activePanel.style.transition = '';
|
|
4945
|
+
activePanel.style.willChange = '';
|
|
4946
|
+
activePanel = null;
|
|
4947
|
+
}
|
|
4948
|
+
}
|
|
4949
|
+
function animate(panel, previousHeight) {
|
|
4950
|
+
if (!Number.isFinite(previousHeight) || prefersReducedMotion()) return;
|
|
4951
|
+
const nextHeight = panel.getBoundingClientRect().height;
|
|
4952
|
+
if (!Number.isFinite(nextHeight) || Math.abs(nextHeight - previousHeight) < 1) return;
|
|
4953
|
+
clearAnimationState();
|
|
4954
|
+
activePanel = panel;
|
|
4955
|
+
panel.style.height = `${previousHeight}px`;
|
|
4956
|
+
panel.style.willChange = 'height';
|
|
4957
|
+
panel.getBoundingClientRect();
|
|
4958
|
+
const handleTransitionEnd = (event)=>{
|
|
4959
|
+
const transitionEvent = event;
|
|
4960
|
+
if ('string' == typeof transitionEvent.propertyName && transitionEvent.propertyName && 'height' !== transitionEvent.propertyName) return;
|
|
4961
|
+
clearAnimationState();
|
|
4962
|
+
};
|
|
4963
|
+
panel.addEventListener('transitionend', handleTransitionEnd);
|
|
4964
|
+
removeTransitionListener = ()=>{
|
|
4965
|
+
panel.removeEventListener('transitionend', handleTransitionEnd);
|
|
4966
|
+
};
|
|
4967
|
+
frameId = window.requestAnimationFrame(()=>{
|
|
4968
|
+
frameId = null;
|
|
4969
|
+
panel.style.transition = PANEL_HEIGHT_TRANSITION;
|
|
4970
|
+
panel.style.height = `${nextHeight}px`;
|
|
4971
|
+
});
|
|
4972
|
+
timeoutId = setTimeout(()=>{
|
|
4973
|
+
clearAnimationState();
|
|
4974
|
+
}, PANEL_HEIGHT_TRANSITION_MS + PANEL_HEIGHT_TRANSITION_BUFFER_MS);
|
|
4975
|
+
}
|
|
4976
|
+
return {
|
|
4977
|
+
animate,
|
|
4978
|
+
destroy: clearAnimationState
|
|
4979
|
+
};
|
|
4980
|
+
}
|
|
4348
4981
|
function createDevTools(options = {}) {
|
|
4349
4982
|
const { namespace = 'c15tStore', position = 'bottom-right', defaultOpen = false } = options;
|
|
4350
4983
|
const stateManager = createStateManager({
|
|
@@ -4352,6 +4985,8 @@ function createDevTools(options = {}) {
|
|
|
4352
4985
|
isOpen: defaultOpen
|
|
4353
4986
|
});
|
|
4354
4987
|
let originalCallbacks = {};
|
|
4988
|
+
let originalNetworkBlockedCallback;
|
|
4989
|
+
let hasWrappedNetworkBlockerCallback = false;
|
|
4355
4990
|
const storeConnector = createStoreConnector({
|
|
4356
4991
|
namespace,
|
|
4357
4992
|
onConnect: (state, store)=>{
|
|
@@ -4395,6 +5030,48 @@ function createDevTools(options = {}) {
|
|
|
4395
5030
|
});
|
|
4396
5031
|
if ('function' == typeof originalCallbacks.onBeforeConsentRevocationReload) originalCallbacks.onBeforeConsentRevocationReload(payload);
|
|
4397
5032
|
});
|
|
5033
|
+
const currentNetworkBlocker = store.getState().networkBlocker;
|
|
5034
|
+
if (currentNetworkBlocker && !hasWrappedNetworkBlockerCallback) {
|
|
5035
|
+
originalNetworkBlockedCallback = currentNetworkBlocker.onRequestBlocked;
|
|
5036
|
+
hasWrappedNetworkBlockerCallback = true;
|
|
5037
|
+
store.getState().setNetworkBlocker({
|
|
5038
|
+
...currentNetworkBlocker,
|
|
5039
|
+
onRequestBlocked: (payload)=>{
|
|
5040
|
+
stateManager.addEvent({
|
|
5041
|
+
type: 'network',
|
|
5042
|
+
message: getBlockedRequestMessage(payload),
|
|
5043
|
+
data: payload
|
|
5044
|
+
});
|
|
5045
|
+
if ('function' == typeof originalNetworkBlockedCallback) originalNetworkBlockedCallback(payload);
|
|
5046
|
+
}
|
|
5047
|
+
});
|
|
5048
|
+
}
|
|
5049
|
+
const persistedOverrides = loadPersistedOverrides();
|
|
5050
|
+
if (persistedOverrides) {
|
|
5051
|
+
const currentOverrides = normalizeOverridesForPersistence(store.getState().overrides);
|
|
5052
|
+
if (!persistedOverridesEqual(persistedOverrides, currentOverrides)) store.getState().setOverrides({
|
|
5053
|
+
country: persistedOverrides.country,
|
|
5054
|
+
region: persistedOverrides.region,
|
|
5055
|
+
language: persistedOverrides.language,
|
|
5056
|
+
gpc: persistedOverrides.gpc
|
|
5057
|
+
}).then(()=>{
|
|
5058
|
+
stateManager.addEvent({
|
|
5059
|
+
type: 'info',
|
|
5060
|
+
message: 'Applied persisted devtools overrides',
|
|
5061
|
+
data: {
|
|
5062
|
+
country: persistedOverrides.country,
|
|
5063
|
+
region: persistedOverrides.region,
|
|
5064
|
+
language: persistedOverrides.language,
|
|
5065
|
+
gpc: persistedOverrides.gpc
|
|
5066
|
+
}
|
|
5067
|
+
});
|
|
5068
|
+
}).catch(()=>{
|
|
5069
|
+
stateManager.addEvent({
|
|
5070
|
+
type: 'error',
|
|
5071
|
+
message: 'Failed to apply persisted devtools overrides'
|
|
5072
|
+
});
|
|
5073
|
+
});
|
|
5074
|
+
}
|
|
4398
5075
|
},
|
|
4399
5076
|
onDisconnect: ()=>{
|
|
4400
5077
|
stateManager.setConnected(false);
|
|
@@ -4406,14 +5083,18 @@ function createDevTools(options = {}) {
|
|
|
4406
5083
|
onStateChange: ()=>{}
|
|
4407
5084
|
});
|
|
4408
5085
|
let tabsInstance = null;
|
|
5086
|
+
const panelHeightAnimator = createPanelHeightAnimator();
|
|
4409
5087
|
const panelInstance = createPanel({
|
|
4410
5088
|
stateManager,
|
|
4411
5089
|
storeConnector,
|
|
5090
|
+
namespace,
|
|
4412
5091
|
onRenderContent: (container)=>{
|
|
4413
5092
|
renderContent(container, stateManager, storeConnector);
|
|
4414
5093
|
}
|
|
4415
5094
|
});
|
|
4416
5095
|
function renderContent(container, stateManager, storeConnector) {
|
|
5096
|
+
const panel = container.parentElement;
|
|
5097
|
+
const previousPanelHeight = panel?.getBoundingClientRect().height ?? 0;
|
|
4417
5098
|
clearElement(container);
|
|
4418
5099
|
const storeState = storeConnector.getState();
|
|
4419
5100
|
const disabledTabs = [];
|
|
@@ -4495,38 +5176,46 @@ function createDevTools(options = {}) {
|
|
|
4495
5176
|
case 'location':
|
|
4496
5177
|
renderLocationPanel(panelContent, {
|
|
4497
5178
|
getState: getStoreState,
|
|
4498
|
-
|
|
5179
|
+
onApplyOverrides: async (overrides)=>{
|
|
4499
5180
|
const store = storeConnector.getStore();
|
|
4500
5181
|
if (store) {
|
|
4501
|
-
const currentOverrides = store.getState().overrides || {};
|
|
4502
5182
|
await store.getState().setOverrides({
|
|
4503
|
-
|
|
4504
|
-
|
|
5183
|
+
country: overrides.country,
|
|
5184
|
+
region: overrides.region,
|
|
5185
|
+
language: overrides.language,
|
|
5186
|
+
gpc: overrides.gpc
|
|
4505
5187
|
});
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
5188
|
+
persistOverrides({
|
|
5189
|
+
country: overrides.country,
|
|
5190
|
+
region: overrides.region,
|
|
5191
|
+
language: overrides.language,
|
|
5192
|
+
gpc: overrides.gpc
|
|
4510
5193
|
});
|
|
4511
|
-
await store.getState().initConsentManager();
|
|
4512
5194
|
stateManager.addEvent({
|
|
4513
5195
|
type: 'info',
|
|
4514
|
-
message: '
|
|
5196
|
+
message: 'Overrides updated',
|
|
5197
|
+
data: {
|
|
5198
|
+
country: overrides.country,
|
|
5199
|
+
region: overrides.region,
|
|
5200
|
+
language: overrides.language,
|
|
5201
|
+
gpc: overrides.gpc
|
|
5202
|
+
}
|
|
4515
5203
|
});
|
|
4516
5204
|
}
|
|
4517
5205
|
},
|
|
4518
5206
|
onClearOverrides: async ()=>{
|
|
4519
5207
|
const store = storeConnector.getStore();
|
|
4520
5208
|
if (store) {
|
|
4521
|
-
await store.getState().setOverrides(
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
5209
|
+
await store.getState().setOverrides({
|
|
5210
|
+
country: void 0,
|
|
5211
|
+
region: void 0,
|
|
5212
|
+
language: void 0,
|
|
5213
|
+
gpc: void 0
|
|
4525
5214
|
});
|
|
4526
|
-
|
|
5215
|
+
clearPersistedOverrides();
|
|
4527
5216
|
stateManager.addEvent({
|
|
4528
5217
|
type: 'info',
|
|
4529
|
-
message: '
|
|
5218
|
+
message: 'Overrides cleared'
|
|
4530
5219
|
});
|
|
4531
5220
|
}
|
|
4532
5221
|
}
|
|
@@ -4534,12 +5223,85 @@ function createDevTools(options = {}) {
|
|
|
4534
5223
|
break;
|
|
4535
5224
|
case "scripts":
|
|
4536
5225
|
renderScriptsPanel(panelContent, {
|
|
4537
|
-
getState: getStoreState
|
|
5226
|
+
getState: getStoreState,
|
|
5227
|
+
getEvents: ()=>stateManager.getState().eventLog
|
|
4538
5228
|
});
|
|
4539
5229
|
break;
|
|
4540
5230
|
case 'iab':
|
|
4541
5231
|
renderIabPanel(panelContent, {
|
|
4542
5232
|
getState: getStoreState,
|
|
5233
|
+
onSetPurposeConsent: (purposeId, value)=>{
|
|
5234
|
+
const iab = storeConnector.getStore()?.getState().iab;
|
|
5235
|
+
if (!iab) return;
|
|
5236
|
+
iab.setPurposeConsent(purposeId, value);
|
|
5237
|
+
stateManager.addEvent({
|
|
5238
|
+
type: 'iab',
|
|
5239
|
+
message: `IAB purpose ${purposeId} set to ${value}`,
|
|
5240
|
+
data: {
|
|
5241
|
+
purposeId,
|
|
5242
|
+
value
|
|
5243
|
+
}
|
|
5244
|
+
});
|
|
5245
|
+
},
|
|
5246
|
+
onSetVendorConsent: (vendorId, value)=>{
|
|
5247
|
+
const iab = storeConnector.getStore()?.getState().iab;
|
|
5248
|
+
if (!iab) return;
|
|
5249
|
+
iab.setVendorConsent(vendorId, value);
|
|
5250
|
+
stateManager.addEvent({
|
|
5251
|
+
type: 'iab',
|
|
5252
|
+
message: `IAB vendor ${vendorId} set to ${value}`,
|
|
5253
|
+
data: {
|
|
5254
|
+
vendorId,
|
|
5255
|
+
value
|
|
5256
|
+
}
|
|
5257
|
+
});
|
|
5258
|
+
},
|
|
5259
|
+
onSetSpecialFeatureOptIn: (featureId, value)=>{
|
|
5260
|
+
const iab = storeConnector.getStore()?.getState().iab;
|
|
5261
|
+
if (!iab) return;
|
|
5262
|
+
iab.setSpecialFeatureOptIn(featureId, value);
|
|
5263
|
+
stateManager.addEvent({
|
|
5264
|
+
type: 'iab',
|
|
5265
|
+
message: `IAB feature ${featureId} set to ${value}`,
|
|
5266
|
+
data: {
|
|
5267
|
+
featureId,
|
|
5268
|
+
value
|
|
5269
|
+
}
|
|
5270
|
+
});
|
|
5271
|
+
},
|
|
5272
|
+
onAcceptAll: ()=>{
|
|
5273
|
+
const iab = storeConnector.getStore()?.getState().iab;
|
|
5274
|
+
if (!iab) return;
|
|
5275
|
+
iab.acceptAll();
|
|
5276
|
+
stateManager.addEvent({
|
|
5277
|
+
type: 'iab',
|
|
5278
|
+
message: 'IAB accept all selected'
|
|
5279
|
+
});
|
|
5280
|
+
},
|
|
5281
|
+
onRejectAll: ()=>{
|
|
5282
|
+
const iab = storeConnector.getStore()?.getState().iab;
|
|
5283
|
+
if (!iab) return;
|
|
5284
|
+
iab.rejectAll();
|
|
5285
|
+
stateManager.addEvent({
|
|
5286
|
+
type: 'iab',
|
|
5287
|
+
message: 'IAB reject all selected'
|
|
5288
|
+
});
|
|
5289
|
+
},
|
|
5290
|
+
onSave: ()=>{
|
|
5291
|
+
const iab = storeConnector.getStore()?.getState().iab;
|
|
5292
|
+
if (!iab) return;
|
|
5293
|
+
iab.save().then(()=>{
|
|
5294
|
+
stateManager.addEvent({
|
|
5295
|
+
type: 'iab',
|
|
5296
|
+
message: 'IAB preferences saved'
|
|
5297
|
+
});
|
|
5298
|
+
}).catch((error)=>{
|
|
5299
|
+
stateManager.addEvent({
|
|
5300
|
+
type: 'error',
|
|
5301
|
+
message: `Failed to save IAB preferences: ${String(error)}`
|
|
5302
|
+
});
|
|
5303
|
+
});
|
|
5304
|
+
},
|
|
4543
5305
|
onReset: async ()=>{
|
|
4544
5306
|
const store = storeConnector.getStore();
|
|
4545
5307
|
if (store) await resetAllConsents(store, stateManager);
|
|
@@ -4627,6 +5389,7 @@ function createDevTools(options = {}) {
|
|
|
4627
5389
|
});
|
|
4628
5390
|
break;
|
|
4629
5391
|
}
|
|
5392
|
+
if (panel) panelHeightAnimator.animate(panel, previousPanelHeight);
|
|
4630
5393
|
}
|
|
4631
5394
|
storeConnector.subscribe(()=>{
|
|
4632
5395
|
panelInstance.update();
|
|
@@ -4644,6 +5407,21 @@ function createDevTools(options = {}) {
|
|
|
4644
5407
|
};
|
|
4645
5408
|
},
|
|
4646
5409
|
destroy: ()=>{
|
|
5410
|
+
const store = storeConnector.getStore();
|
|
5411
|
+
if (store) {
|
|
5412
|
+
store.getState().setCallback('onBannerFetched', originalCallbacks.onBannerFetched);
|
|
5413
|
+
store.getState().setCallback('onConsentSet', originalCallbacks.onConsentSet);
|
|
5414
|
+
store.getState().setCallback('onError', originalCallbacks.onError);
|
|
5415
|
+
store.getState().setCallback('onBeforeConsentRevocationReload', originalCallbacks.onBeforeConsentRevocationReload);
|
|
5416
|
+
if (hasWrappedNetworkBlockerCallback) {
|
|
5417
|
+
const currentNetworkBlocker = store.getState().networkBlocker;
|
|
5418
|
+
if (currentNetworkBlocker) store.getState().setNetworkBlocker({
|
|
5419
|
+
...currentNetworkBlocker,
|
|
5420
|
+
onRequestBlocked: originalNetworkBlockedCallback
|
|
5421
|
+
});
|
|
5422
|
+
}
|
|
5423
|
+
}
|
|
5424
|
+
panelHeightAnimator.destroy();
|
|
4647
5425
|
tabsInstance?.destroy();
|
|
4648
5426
|
panelInstance.destroy();
|
|
4649
5427
|
storeConnector.destroy();
|
|
@@ -4656,12 +5434,42 @@ function createDevTools(options = {}) {
|
|
|
4656
5434
|
}
|
|
4657
5435
|
function createDevToolsPanel(options) {
|
|
4658
5436
|
const { namespace = 'c15tStore' } = options;
|
|
5437
|
+
let originalEmbeddedNetworkBlockedCallback;
|
|
5438
|
+
let hasWrappedEmbeddedNetworkBlocker = false;
|
|
4659
5439
|
const stateManager = createStateManager({
|
|
4660
5440
|
isOpen: true
|
|
4661
5441
|
});
|
|
4662
5442
|
const storeConnector = createStoreConnector({
|
|
4663
5443
|
namespace,
|
|
4664
|
-
onConnect: ()=>
|
|
5444
|
+
onConnect: (state, store)=>{
|
|
5445
|
+
stateManager.setConnected(true);
|
|
5446
|
+
const currentNetworkBlocker = state.networkBlocker;
|
|
5447
|
+
if (currentNetworkBlocker && !hasWrappedEmbeddedNetworkBlocker) {
|
|
5448
|
+
originalEmbeddedNetworkBlockedCallback = currentNetworkBlocker.onRequestBlocked;
|
|
5449
|
+
hasWrappedEmbeddedNetworkBlocker = true;
|
|
5450
|
+
store.getState().setNetworkBlocker({
|
|
5451
|
+
...currentNetworkBlocker,
|
|
5452
|
+
onRequestBlocked: (payload)=>{
|
|
5453
|
+
stateManager.addEvent({
|
|
5454
|
+
type: 'network',
|
|
5455
|
+
message: getBlockedRequestMessage(payload),
|
|
5456
|
+
data: payload
|
|
5457
|
+
});
|
|
5458
|
+
if ('function' == typeof originalEmbeddedNetworkBlockedCallback) originalEmbeddedNetworkBlockedCallback(payload);
|
|
5459
|
+
}
|
|
5460
|
+
});
|
|
5461
|
+
}
|
|
5462
|
+
const persistedOverrides = loadPersistedOverrides();
|
|
5463
|
+
if (persistedOverrides) {
|
|
5464
|
+
const currentOverrides = normalizeOverridesForPersistence(state.overrides);
|
|
5465
|
+
if (!persistedOverridesEqual(persistedOverrides, currentOverrides)) store.getState().setOverrides({
|
|
5466
|
+
country: persistedOverrides.country,
|
|
5467
|
+
region: persistedOverrides.region,
|
|
5468
|
+
language: persistedOverrides.language,
|
|
5469
|
+
gpc: persistedOverrides.gpc
|
|
5470
|
+
});
|
|
5471
|
+
}
|
|
5472
|
+
},
|
|
4665
5473
|
onDisconnect: ()=>stateManager.setConnected(false)
|
|
4666
5474
|
});
|
|
4667
5475
|
const container = renderer_div({
|
|
@@ -4710,29 +5518,61 @@ function createDevToolsPanel(options) {
|
|
|
4710
5518
|
case 'location':
|
|
4711
5519
|
renderLocationPanel(contentArea, {
|
|
4712
5520
|
getState: getStoreState,
|
|
4713
|
-
|
|
5521
|
+
onApplyOverrides: async (overrides)=>{
|
|
4714
5522
|
const store = storeConnector.getStore();
|
|
4715
5523
|
if (store) {
|
|
4716
|
-
const current = store.getState().overrides || {};
|
|
4717
5524
|
await store.getState().setOverrides({
|
|
4718
|
-
|
|
4719
|
-
|
|
5525
|
+
country: overrides.country,
|
|
5526
|
+
region: overrides.region,
|
|
5527
|
+
language: overrides.language,
|
|
5528
|
+
gpc: overrides.gpc
|
|
5529
|
+
});
|
|
5530
|
+
persistOverrides({
|
|
5531
|
+
country: overrides.country,
|
|
5532
|
+
region: overrides.region,
|
|
5533
|
+
language: overrides.language,
|
|
5534
|
+
gpc: overrides.gpc
|
|
4720
5535
|
});
|
|
4721
5536
|
}
|
|
4722
5537
|
},
|
|
4723
5538
|
onClearOverrides: async ()=>{
|
|
4724
|
-
await storeConnector.getStore()?.getState().setOverrides(
|
|
5539
|
+
await storeConnector.getStore()?.getState().setOverrides({
|
|
5540
|
+
country: void 0,
|
|
5541
|
+
region: void 0,
|
|
5542
|
+
language: void 0,
|
|
5543
|
+
gpc: void 0
|
|
5544
|
+
});
|
|
5545
|
+
clearPersistedOverrides();
|
|
4725
5546
|
}
|
|
4726
5547
|
});
|
|
4727
5548
|
break;
|
|
4728
5549
|
case "scripts":
|
|
4729
5550
|
renderScriptsPanel(contentArea, {
|
|
4730
|
-
getState: getStoreState
|
|
5551
|
+
getState: getStoreState,
|
|
5552
|
+
getEvents: ()=>stateManager.getState().eventLog
|
|
4731
5553
|
});
|
|
4732
5554
|
break;
|
|
4733
5555
|
case 'iab':
|
|
4734
5556
|
renderIabPanel(contentArea, {
|
|
4735
5557
|
getState: getStoreState,
|
|
5558
|
+
onSetPurposeConsent: (purposeId, value)=>{
|
|
5559
|
+
storeConnector.getStore()?.getState().iab?.setPurposeConsent(purposeId, value);
|
|
5560
|
+
},
|
|
5561
|
+
onSetVendorConsent: (vendorId, value)=>{
|
|
5562
|
+
storeConnector.getStore()?.getState().iab?.setVendorConsent(vendorId, value);
|
|
5563
|
+
},
|
|
5564
|
+
onSetSpecialFeatureOptIn: (featureId, value)=>{
|
|
5565
|
+
storeConnector.getStore()?.getState().iab?.setSpecialFeatureOptIn(featureId, value);
|
|
5566
|
+
},
|
|
5567
|
+
onAcceptAll: ()=>{
|
|
5568
|
+
storeConnector.getStore()?.getState().iab?.acceptAll();
|
|
5569
|
+
},
|
|
5570
|
+
onRejectAll: ()=>{
|
|
5571
|
+
storeConnector.getStore()?.getState().iab?.rejectAll();
|
|
5572
|
+
},
|
|
5573
|
+
onSave: ()=>{
|
|
5574
|
+
storeConnector.getStore()?.getState().iab?.save();
|
|
5575
|
+
},
|
|
4736
5576
|
onReset: async ()=>{
|
|
4737
5577
|
const store = storeConnector.getStore();
|
|
4738
5578
|
if (store) await resetAllConsents(store);
|
|
@@ -4793,6 +5633,14 @@ function createDevToolsPanel(options) {
|
|
|
4793
5633
|
return {
|
|
4794
5634
|
element: container,
|
|
4795
5635
|
destroy: ()=>{
|
|
5636
|
+
const store = storeConnector.getStore();
|
|
5637
|
+
if (store && hasWrappedEmbeddedNetworkBlocker) {
|
|
5638
|
+
const currentNetworkBlocker = store.getState().networkBlocker;
|
|
5639
|
+
if (currentNetworkBlocker) store.getState().setNetworkBlocker({
|
|
5640
|
+
...currentNetworkBlocker,
|
|
5641
|
+
onRequestBlocked: originalEmbeddedNetworkBlockedCallback
|
|
5642
|
+
});
|
|
5643
|
+
}
|
|
4796
5644
|
unsubscribe();
|
|
4797
5645
|
tabsInstance.destroy();
|
|
4798
5646
|
storeConnector.destroy();
|