@c15t/dev-tools 2.0.0-rc.4 → 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 (75) hide show
  1. package/README.md +12 -1
  2. package/dist/index.cjs +346 -36
  3. package/dist/index.js +346 -36
  4. package/dist/react.cjs +346 -36
  5. package/dist/react.js +346 -36
  6. package/dist/tanstack.cjs +340 -35
  7. package/dist/tanstack.js +340 -35
  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 +0 -1
  13. package/{dist → dist-types}/core/debug-bundle.d.ts +1 -2
  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 +1 -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 +1 -2
  23. package/{dist → dist-types}/core/store-instrumentation.d.ts +1 -2
  24. package/{dist → dist-types}/index.d.ts +0 -1
  25. package/{dist → dist-types}/panels/actions.d.ts +1 -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 +32 -29
  42. package/CHANGELOG.md +0 -163
  43. package/dist/components/dropdown-menu.d.ts.map +0 -1
  44. package/dist/components/index.d.ts.map +0 -1
  45. package/dist/components/panel.d.ts.map +0 -1
  46. package/dist/components/tabs.d.ts.map +0 -1
  47. package/dist/components/ui.d.ts.map +0 -1
  48. package/dist/core/debug-bundle.d.ts.map +0 -1
  49. package/dist/core/devtools.d.ts.map +0 -1
  50. package/dist/core/draggable.d.ts.map +0 -1
  51. package/dist/core/index.d.ts.map +0 -1
  52. package/dist/core/override-storage.d.ts.map +0 -1
  53. package/dist/core/panel-renderer.d.ts.map +0 -1
  54. package/dist/core/renderer.d.ts.map +0 -1
  55. package/dist/core/reset-consents.d.ts.map +0 -1
  56. package/dist/core/state-manager.d.ts.map +0 -1
  57. package/dist/core/store-connector.d.ts.map +0 -1
  58. package/dist/core/store-instrumentation.d.ts.map +0 -1
  59. package/dist/index.d.ts.map +0 -1
  60. package/dist/panels/actions.d.ts.map +0 -1
  61. package/dist/panels/consents.d.ts.map +0 -1
  62. package/dist/panels/dom-scanner.d.ts.map +0 -1
  63. package/dist/panels/events.d.ts.map +0 -1
  64. package/dist/panels/iab.d.ts.map +0 -1
  65. package/dist/panels/index.d.ts.map +0 -1
  66. package/dist/panels/location.d.ts.map +0 -1
  67. package/dist/panels/scripts.d.ts.map +0 -1
  68. package/dist/react.d.ts.map +0 -1
  69. package/dist/styles/index.d.ts.map +0 -1
  70. package/dist/tanstack.d.ts.map +0 -1
  71. package/dist/utils/index.d.ts.map +0 -1
  72. package/dist/utils/preference-trigger.d.ts.map +0 -1
  73. package/dist/version.d.ts +0 -2
  74. package/dist/version.d.ts.map +0 -1
  75. package/tsconfig.json +0 -20
package/dist/tanstack.cjs CHANGED
@@ -2023,6 +2023,11 @@ var __webpack_exports__ = {};
2023
2023
  <circle cx="12" cy="12" r="10"></circle>
2024
2024
  <line x1="2" y1="12" x2="22" y2="12"></line>
2025
2025
  <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>
2026
+ </svg>`;
2027
+ 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">
2028
+ <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path>
2029
+ <path d="M9 12h6"></path>
2030
+ <path d="M12 9v6"></path>
2026
2031
  </svg>`;
2027
2032
  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">
2028
2033
  <polyline points="16 18 22 12 16 6"></polyline>
@@ -2051,6 +2056,11 @@ var __webpack_exports__ = {};
2051
2056
  label: 'Location',
2052
2057
  icon: LOCATION_ICON
2053
2058
  },
2059
+ {
2060
+ id: 'policy',
2061
+ label: 'Policy',
2062
+ icon: POLICY_ICON
2063
+ },
2054
2064
  {
2055
2065
  id: 'consents',
2056
2066
  label: 'Consents',
@@ -2211,6 +2221,7 @@ var __webpack_exports__ = {};
2211
2221
  const forcedOverflowTab = showOverflowSecondTabInStrip ? preferredSecondTab : overflowSecondTab;
2212
2222
  const layoutTabIds = [
2213
2223
  'location',
2224
+ 'policy',
2214
2225
  stripSecondTab,
2215
2226
  "scripts",
2216
2227
  'actions',
@@ -2875,7 +2886,6 @@ var __webpack_exports__ = {};
2875
2886
  function getNamespace(state) {
2876
2887
  return state.config?.meta?.namespace || 'c15tStore';
2877
2888
  }
2878
- const consentSearchByContainer = new WeakMap();
2879
2889
  function renderConsentsPanel(container, options) {
2880
2890
  const { getState, onConsentChange, onSave, onAcceptAll, onRejectAll, onReset } = options;
2881
2891
  renderer_clearElement(container);
@@ -2894,40 +2904,15 @@ var __webpack_exports__ = {};
2894
2904
  ct.name,
2895
2905
  ct
2896
2906
  ]));
2897
- const searchQuery = consentSearchByContainer.get(container) ?? '';
2898
2907
  const consentEntries = Object.entries(displayConsents);
2899
- const filteredConsentEntries = consentEntries.filter(([name])=>{
2900
- if (!searchQuery) return true;
2901
- const consentType = consentTypeMap.get(name);
2902
- const displayName = consentType?.name || name;
2903
- return `${name} ${displayName}`.toLowerCase().includes(searchQuery);
2904
- });
2905
- const showSearchInput = consentEntries.length > 4;
2906
- if (showSearchInput) container.appendChild(renderer_div({
2907
- style: {
2908
- padding: '8px 0 10px'
2909
- },
2910
- children: [
2911
- createInput({
2912
- value: searchQuery,
2913
- placeholder: 'Filter consents…',
2914
- ariaLabel: 'Filter consents',
2915
- small: true,
2916
- onInput: (value)=>{
2917
- consentSearchByContainer.set(container, value.trim().toLowerCase());
2918
- renderConsentsPanel(container, options);
2919
- }
2920
- })
2921
- ]
2922
- }));
2923
- if (0 === filteredConsentEntries.length) container.appendChild(renderer_div({
2908
+ if (0 === consentEntries.length) container.appendChild(renderer_div({
2924
2909
  style: {
2925
2910
  padding: '24px',
2926
2911
  textAlign: 'center',
2927
2912
  color: 'var(--c15t-devtools-text-muted)',
2928
2913
  fontSize: 'var(--c15t-devtools-font-size-sm)'
2929
2914
  },
2930
- text: 0 === consentEntries.length ? 'No consents configured' : 'No matching consents'
2915
+ text: 'No consents configured'
2931
2916
  }));
2932
2917
  else {
2933
2918
  if (isIabMode) {
@@ -2945,7 +2930,7 @@ var __webpack_exports__ = {};
2945
2930
  container.appendChild(iabNotice);
2946
2931
  }
2947
2932
  const gridCards = [];
2948
- for (const [name, value] of filteredConsentEntries){
2933
+ for (const [name, value] of consentEntries){
2949
2934
  const consentType = consentTypeMap.get(name);
2950
2935
  const isNecessary = 'necessary' === name;
2951
2936
  const displayName = consentType?.name || name;
@@ -3696,6 +3681,27 @@ var __webpack_exports__ = {};
3696
3681
  if (text.length <= maxLength) return text;
3697
3682
  return `${text.slice(0, maxLength - 3)}...`;
3698
3683
  }
3684
+ function init_source_formatInitSource(source, detail) {
3685
+ const label = (()=>{
3686
+ switch(source){
3687
+ case 'ssr':
3688
+ return 'SSR Prefetch';
3689
+ case 'backend':
3690
+ return 'Backend';
3691
+ case 'backend-cache-hit':
3692
+ return 'Backend (Cache Hit)';
3693
+ case 'offline-fallback':
3694
+ return 'Offline Fallback';
3695
+ case 'offline-mode':
3696
+ return 'Offline Mode';
3697
+ case 'custom':
3698
+ return 'Custom Client';
3699
+ default:
3700
+ return '—';
3701
+ }
3702
+ })();
3703
+ return detail ? `${label} [${detail}]` : label;
3704
+ }
3699
3705
  function renderLocationPanel(container, options) {
3700
3706
  const { getState, onApplyOverrides, onClearOverrides } = options;
3701
3707
  renderer_clearElement(container);
@@ -3704,11 +3710,15 @@ var __webpack_exports__ = {};
3704
3710
  const locationInfo = state.locationInfo;
3705
3711
  const overrides = state.overrides;
3706
3712
  const translationConfig = state.translationConfig;
3713
+ const initData = state.lastBannerFetchData;
3714
+ const activePolicy = initData?.policy;
3715
+ const policyDecision = initData?.policyDecision;
3716
+ const initSource = init_source_formatInitSource(state.initDataSource, state.initDataSourceDetail);
3707
3717
  const gridItems = [
3708
3718
  createCompactInfoCard('Country', locationInfo?.countryCode || '—'),
3709
3719
  createCompactInfoCard('Region', locationInfo?.regionCode || '—'),
3710
- createCompactInfoCard('Jurisdiction', locationInfo?.jurisdiction || '—'),
3711
- createCompactInfoCard('Language', translationConfig?.defaultLanguage || '—')
3720
+ createCompactInfoCard('Language', translationConfig?.defaultLanguage || '—'),
3721
+ createCompactInfoCard('Init Source', initSource)
3712
3722
  ];
3713
3723
  gridItems.push(createCompactInfoCard('GPC', getEffectiveGpcLabel(overrides?.gpc)));
3714
3724
  if (state.model) gridItems.push(createCompactInfoCard('Model', getModelLabel(state.model)));
@@ -3716,7 +3726,6 @@ var __webpack_exports__ = {};
3716
3726
  columns: 3,
3717
3727
  children: gridItems
3718
3728
  });
3719
- container.appendChild(locationGrid);
3720
3729
  const initialDraft = getDraftFromOverrides(overrides);
3721
3730
  let appliedOverrides = normalizeOverrideDraft(initialDraft);
3722
3731
  let isSubmitting = false;
@@ -3807,6 +3816,12 @@ var __webpack_exports__ = {};
3807
3816
  ]
3808
3817
  });
3809
3818
  container.appendChild(overrideSection);
3819
+ container.appendChild(locationGrid);
3820
+ container.appendChild(createActivePolicySummarySection({
3821
+ policy: activePolicy,
3822
+ policyDecision,
3823
+ policySnapshotToken: initData?.policySnapshotToken
3824
+ }));
3810
3825
  countryField.control.addEventListener('change', updateFormState);
3811
3826
  regionField.control.addEventListener('input', updateFormState);
3812
3827
  languageField.control.addEventListener('input', updateFormState);
@@ -4095,15 +4110,53 @@ var __webpack_exports__ = {};
4095
4110
  return 'None';
4096
4111
  }
4097
4112
  }
4113
+ function createActivePolicySummarySection(options) {
4114
+ const { policy, policyDecision, policySnapshotToken } = options;
4115
+ if (!policy && !policyDecision) return createSection({
4116
+ title: 'Active Policy',
4117
+ children: [
4118
+ renderer_div({
4119
+ style: {
4120
+ padding: '10px 12px',
4121
+ fontSize: 'var(--c15t-devtools-font-size-sm)',
4122
+ color: 'var(--c15t-text-muted)'
4123
+ },
4124
+ text: 'No active policy matched.'
4125
+ })
4126
+ ]
4127
+ });
4128
+ const cards = [
4129
+ createCompactInfoCard('Policy ID', policy?.id ?? policyDecision?.policyId ?? '—'),
4130
+ createCompactInfoCard('Matched By', policyDecision?.matchedBy ?? '—'),
4131
+ createCompactInfoCard('Snapshot Token', policySnapshotToken ? 'present' : 'missing')
4132
+ ];
4133
+ return createSection({
4134
+ title: 'Active Policy',
4135
+ children: [
4136
+ renderer_div({
4137
+ style: {
4138
+ display: 'grid',
4139
+ gridTemplateColumns: 'repeat(3, minmax(0, 1fr))',
4140
+ gap: 'var(--c15t-space-sm, 0.5rem)'
4141
+ },
4142
+ children: cards
4143
+ }),
4144
+ renderer_span({
4145
+ className: styles_components_module.overrideHint,
4146
+ text: 'Open the Policy tab for full policy-pack diagnostics.'
4147
+ })
4148
+ ]
4149
+ });
4150
+ }
4098
4151
  function createCompactInfoCard(label, value) {
4099
4152
  return renderer_div({
4100
4153
  className: styles_components_module.gridCard ?? '',
4101
4154
  style: {
4102
- padding: '6px 8px',
4155
+ padding: '8px 10px',
4103
4156
  minHeight: 'auto',
4104
4157
  flexDirection: 'column',
4105
4158
  alignItems: 'flex-start',
4106
- gap: '1px'
4159
+ gap: '2px'
4107
4160
  },
4108
4161
  children: [
4109
4162
  renderer_span({
@@ -4124,6 +4177,253 @@ var __webpack_exports__ = {};
4124
4177
  ]
4125
4178
  });
4126
4179
  }
4180
+ function renderPolicyPanel(container, options) {
4181
+ const { getState } = options;
4182
+ renderer_clearElement(container);
4183
+ const state = getState();
4184
+ if (!state) return void container.appendChild(createDisconnectedState());
4185
+ const initData = state.lastBannerFetchData;
4186
+ const activePolicy = initData?.policy;
4187
+ const policyDecision = initData?.policyDecision;
4188
+ const initSource = init_source_formatInitSource(state.initDataSource, state.initDataSourceDetail);
4189
+ container.appendChild(createMatchTraceSection({
4190
+ policyDecision,
4191
+ policyId: activePolicy?.id ?? policyDecision?.policyId
4192
+ }));
4193
+ if (!activePolicy && !policyDecision) return void container.appendChild(createSection({
4194
+ title: 'Policy',
4195
+ children: [
4196
+ renderer_div({
4197
+ style: {
4198
+ padding: '10px 12px',
4199
+ fontSize: 'var(--c15t-devtools-font-size-sm)',
4200
+ color: 'var(--c15t-text-muted)'
4201
+ },
4202
+ text: 'No active policy matched for this request.'
4203
+ }),
4204
+ createHint(`Init Source: ${initSource}`)
4205
+ ]
4206
+ }));
4207
+ container.appendChild(createSection({
4208
+ title: 'Policy',
4209
+ children: [
4210
+ policy_createGrid(3, [
4211
+ createCard('ID', activePolicy?.id ?? policyDecision?.policyId ?? '—'),
4212
+ createCard('Model', policy_getModelLabel(activePolicy?.model)),
4213
+ createCard('Scope', getScopeModeLabel(activePolicy?.consent?.scopeMode ?? state.policyScopeMode)),
4214
+ createCard('Categories', formatList(state.policyCategories ?? activePolicy?.consent?.categories)),
4215
+ createCard('Preselected', formatList(activePolicy?.consent?.preselectedCategories)),
4216
+ createCard('Expiry', 'number' == typeof activePolicy?.consent?.expiryDays ? `${activePolicy.consent.expiryDays}d` : '—')
4217
+ ]),
4218
+ createHint(`${initSource} · ${formatFingerprint(policyDecision?.fingerprint)}`)
4219
+ ]
4220
+ }));
4221
+ const uiMode = activePolicy?.ui?.mode;
4222
+ if (uiMode && 'none' !== uiMode) {
4223
+ const bannerCards = buildSurfaceCards('Banner', activePolicy?.ui?.banner, state.policyBanner);
4224
+ const dialogCards = buildSurfaceCards('Dialog', activePolicy?.ui?.dialog, state.policyDialog);
4225
+ if (bannerCards.length > 0 || dialogCards.length > 0) container.appendChild(createSection({
4226
+ title: `UI · ${uiMode}`,
4227
+ children: [
4228
+ policy_createGrid(3, [
4229
+ ...bannerCards,
4230
+ ...dialogCards
4231
+ ])
4232
+ ]
4233
+ }));
4234
+ }
4235
+ const proofLabel = formatProofSummary(activePolicy?.proof);
4236
+ const snapshotLabel = initData?.policySnapshotToken ? 'present' : 'missing';
4237
+ container.appendChild(createSection({
4238
+ title: 'Proof & Snapshot',
4239
+ children: [
4240
+ policy_createGrid(3, [
4241
+ createCard('Proof', proofLabel),
4242
+ createCard('Snapshot', snapshotLabel),
4243
+ createCard('I18n', activePolicy?.i18n?.messageProfile ?? activePolicy?.i18n?.language ?? '—')
4244
+ ])
4245
+ ]
4246
+ }));
4247
+ }
4248
+ function buildSurfaceCards(prefix, policySurface, storeSurface) {
4249
+ const policyLayout = Array.isArray(policySurface?.layout) && 0 === policySurface.layout.length ? null : policySurface?.layout ?? null;
4250
+ const storeLayout = Array.isArray(storeSurface.layout) && 0 === storeSurface.layout.length ? null : storeSurface.layout ?? null;
4251
+ const actions = formatList(policySurface?.allowedActions ?? storeSurface.allowedActions);
4252
+ const primary = policySurface?.primaryAction ?? storeSurface.primaryAction ?? null;
4253
+ const layout = policyLayout ?? storeLayout;
4254
+ const direction = policySurface?.direction ?? storeSurface.direction ?? null;
4255
+ const profile = policySurface?.uiProfile ?? storeSurface.uiProfile ?? null;
4256
+ const scrollLock = policySurface?.scrollLock ?? storeSurface.scrollLock ?? null;
4257
+ if ('—' === actions && !primary && !layout && !direction && !profile && null === scrollLock) return [];
4258
+ const cards = [
4259
+ createCard(`${prefix} Actions`, actions)
4260
+ ];
4261
+ if (primary) cards.push(createCard(`${prefix} Primary`, primary));
4262
+ if (layout) cards.push(createCard(`${prefix} Layout`, Array.isArray(layout) ? layout.map((group)=>Array.isArray(group) ? `[${group.join(', ')}]` : group).join(' / ') : layout));
4263
+ if (direction) cards.push(createCard(`${prefix} Direction`, direction));
4264
+ if (profile) cards.push(createCard(`${prefix} Profile`, profile));
4265
+ if (null !== scrollLock) cards.push(createCard(`${prefix} Scroll Lock`, scrollLock ? 'on' : 'off'));
4266
+ return cards;
4267
+ }
4268
+ function createMatchTraceSection(options) {
4269
+ const { policyDecision, policyId } = options;
4270
+ const entries = buildTraceEntries(policyDecision, policyId);
4271
+ return createSection({
4272
+ title: 'Match Trace',
4273
+ children: [
4274
+ renderer_div({
4275
+ style: {
4276
+ display: 'grid',
4277
+ gridTemplateColumns: '1fr',
4278
+ gap: '4px'
4279
+ },
4280
+ children: entries.map((entry)=>renderer_div({
4281
+ className: styles_components_module.gridCard ?? '',
4282
+ style: {
4283
+ padding: '6px 10px',
4284
+ display: 'flex',
4285
+ alignItems: 'center',
4286
+ justifyContent: 'space-between',
4287
+ gap: '10px'
4288
+ },
4289
+ children: [
4290
+ renderer_span({
4291
+ style: {
4292
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
4293
+ color: 'var(--c15t-text-muted)',
4294
+ fontFamily: 'ui-monospace, monospace'
4295
+ },
4296
+ text: entry.step
4297
+ }),
4298
+ renderer_span({
4299
+ style: {
4300
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
4301
+ fontFamily: 'ui-monospace, monospace'
4302
+ },
4303
+ text: entry.result
4304
+ })
4305
+ ]
4306
+ }))
4307
+ }),
4308
+ createHint('region → country → default · fallback on geo failure · Simulate via Location tab')
4309
+ ]
4310
+ });
4311
+ }
4312
+ function buildTraceEntries(decision, policyId) {
4313
+ if (!decision) return [
4314
+ {
4315
+ step: 'decision metadata',
4316
+ result: 'UNAVAILABLE'
4317
+ }
4318
+ ];
4319
+ const country = decision.country ?? 'n/a';
4320
+ const regionKey = decision.country && decision.region ? `${decision.country}-${decision.region}` : 'n/a';
4321
+ const resolved = policyId ?? decision.policyId ?? 'unknown';
4322
+ const matched = decision.matchedBy;
4323
+ return [
4324
+ {
4325
+ step: `region(${regionKey})`,
4326
+ result: 'region' === matched ? `MATCH → ${resolved}` : 'MISS'
4327
+ },
4328
+ {
4329
+ step: `country(${country})`,
4330
+ result: 'country' === matched ? `MATCH → ${resolved}` : 'region' === matched ? 'SKIPPED' : 'MISS'
4331
+ },
4332
+ {
4333
+ step: 'fallback(geo-fail)',
4334
+ result: 'fallback' === matched ? `MATCH → ${resolved}` : 'SKIPPED'
4335
+ },
4336
+ {
4337
+ step: 'default(catch-all)',
4338
+ result: 'default' === matched ? `MATCH → ${resolved}` : 'SKIPPED'
4339
+ }
4340
+ ];
4341
+ }
4342
+ function policy_getModelLabel(model) {
4343
+ switch(model){
4344
+ case 'opt-in':
4345
+ return 'Opt-In';
4346
+ case 'opt-out':
4347
+ return 'Opt-Out';
4348
+ case 'iab':
4349
+ return 'IAB TCF';
4350
+ default:
4351
+ return 'None';
4352
+ }
4353
+ }
4354
+ function getScopeModeLabel(mode) {
4355
+ switch(mode){
4356
+ case 'strict':
4357
+ return 'Strict';
4358
+ case 'permissive':
4359
+ return 'Permissive';
4360
+ default:
4361
+ return '—';
4362
+ }
4363
+ }
4364
+ function formatList(items) {
4365
+ if (!items || 0 === items.length) return '—';
4366
+ if (items.includes('*')) return '* (all)';
4367
+ return items.join(', ');
4368
+ }
4369
+ function formatProofSummary(proof) {
4370
+ if (!proof) return '—';
4371
+ const parts = [];
4372
+ if (proof.storeIp) parts.push('IP');
4373
+ if (proof.storeUserAgent) parts.push('UA');
4374
+ if (proof.storeLanguage) parts.push('Lang');
4375
+ return parts.length > 0 ? parts.join(', ') : 'none';
4376
+ }
4377
+ function formatFingerprint(fingerprint) {
4378
+ if (!fingerprint) return 'no fingerprint';
4379
+ if (fingerprint.length <= 12) return fingerprint;
4380
+ return `${fingerprint.slice(0, 8)}…${fingerprint.slice(-4)}`;
4381
+ }
4382
+ function createCard(label, value) {
4383
+ return renderer_div({
4384
+ className: styles_components_module.gridCard ?? '',
4385
+ style: {
4386
+ padding: '8px 10px',
4387
+ minHeight: 'auto',
4388
+ flexDirection: 'column',
4389
+ alignItems: 'flex-start',
4390
+ gap: '2px'
4391
+ },
4392
+ children: [
4393
+ renderer_span({
4394
+ style: {
4395
+ fontSize: 'var(--c15t-devtools-font-size-xs)',
4396
+ color: 'var(--c15t-text-muted)'
4397
+ },
4398
+ text: label
4399
+ }),
4400
+ renderer_span({
4401
+ style: {
4402
+ fontSize: 'var(--c15t-font-size-sm)',
4403
+ fontWeight: '500',
4404
+ fontFamily: 'ui-monospace, monospace'
4405
+ },
4406
+ text: value
4407
+ })
4408
+ ]
4409
+ });
4410
+ }
4411
+ function policy_createGrid(columns, children) {
4412
+ return renderer_div({
4413
+ style: {
4414
+ display: 'grid',
4415
+ gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`,
4416
+ gap: 'var(--c15t-space-sm, 0.5rem)'
4417
+ },
4418
+ children
4419
+ });
4420
+ }
4421
+ function createHint(text) {
4422
+ return renderer_span({
4423
+ className: styles_components_module.overrideHint,
4424
+ text
4425
+ });
4426
+ }
4127
4427
  const dismissedResources = new Set();
4128
4428
  function scanDOM(state) {
4129
4429
  const results = [];
@@ -4762,6 +5062,11 @@ var __webpack_exports__ = {};
4762
5062
  }
4763
5063
  });
4764
5064
  break;
5065
+ case 'policy':
5066
+ renderPolicyPanel(container, {
5067
+ getState: getStoreState
5068
+ });
5069
+ break;
4765
5070
  case "scripts":
4766
5071
  renderScriptsPanel(container, {
4767
5072
  getState: getStoreState,
@@ -4898,7 +5203,7 @@ var __webpack_exports__ = {};
4898
5203
  } catch {}
4899
5204
  }
4900
5205
  function isDevToolsTab(value) {
4901
- return 'consents' === value || 'location' === value || "scripts" === value || 'iab' === value || 'events' === value || 'actions' === value;
5206
+ return 'consents' === value || 'location' === value || 'policy' === value || "scripts" === value || 'iab' === value || 'events' === value || 'actions' === value;
4902
5207
  }
4903
5208
  function loadPersistedActiveTab() {
4904
5209
  if ('undefined' == typeof window) return null;