@vectoriox/iox-builder 4.31.0 → 4.31.2
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.
|
@@ -1631,7 +1631,11 @@ class OverlayService {
|
|
|
1631
1631
|
if (host.classList[i].startsWith('iox-node-'))
|
|
1632
1632
|
return host;
|
|
1633
1633
|
}
|
|
1634
|
-
|
|
1634
|
+
// The node's own styled element always precedes its children in document order; for the
|
|
1635
|
+
// Dialog it sits BELOW a classless fixed stage, where firstElementChild pointed the
|
|
1636
|
+
// outline at the stage (live find 2026-10-10 — "can't select the white box").
|
|
1637
|
+
const styled = host.querySelector('[class*="iox-node-"]');
|
|
1638
|
+
return styled || host.firstElementChild || host;
|
|
1635
1639
|
}
|
|
1636
1640
|
// ── Node → Element registry ──────────────────────────────
|
|
1637
1641
|
registerNode(node, element, componentRef) {
|
|
@@ -8490,6 +8494,22 @@ class BuilderDialogComponent {
|
|
|
8490
8494
|
this.selectSub?.unsubscribe();
|
|
8491
8495
|
this.instanceRegistry.unregister(this.nodeId);
|
|
8492
8496
|
}
|
|
8497
|
+
/** A click on the stage ITSELF is the backdrop click — children swallow everything else.
|
|
8498
|
+
* Closing clicks STOP here: the same click would bubble into canvas selection, and
|
|
8499
|
+
* select$ would reopen the dialog in the same breath (live find 2026-10-10 — "the X
|
|
8500
|
+
* doesn't work"). */
|
|
8501
|
+
onStageClick(event) {
|
|
8502
|
+
if (event.target !== event.currentTarget)
|
|
8503
|
+
return;
|
|
8504
|
+
if (this.closeOnBackdrop !== false && this.closeOnBackdrop !== 'false') {
|
|
8505
|
+
event.stopPropagation();
|
|
8506
|
+
this.designOpen = false;
|
|
8507
|
+
}
|
|
8508
|
+
}
|
|
8509
|
+
onCloseClick(event) {
|
|
8510
|
+
event.stopPropagation();
|
|
8511
|
+
this.designOpen = false;
|
|
8512
|
+
}
|
|
8493
8513
|
onBackdrop() {
|
|
8494
8514
|
if (this.closeOnBackdrop !== false && this.closeOnBackdrop !== 'false')
|
|
8495
8515
|
this.designOpen = false;
|
|
@@ -8499,8 +8519,8 @@ class BuilderDialogComponent {
|
|
|
8499
8519
|
}
|
|
8500
8520
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderDialogComponent, deps: [{ token: DragEngineService }, { token: i1.ComponentInstanceRegistryService }, { token: OverlayService }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8501
8521
|
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.31", type: BuilderDialogComponent, isStandalone: false, selector: "app-builder-dialog", inputs: { children: "children", style: "style", nodeId: "nodeId", dropListId: "dropListId", closeOnBackdrop: "closeOnBackdrop", showCloseButton: "showCloseButton", placement: "placement" }, outputs: { childClick: "childClick", childMouseEnter: "childMouseEnter", childMouseLeave: "childMouseLeave" }, ngImport: i0, template: `
|
|
8502
|
-
<div *ngIf="designOpen" class="dialog-stage" [attr.data-placement]="placementValue"
|
|
8503
|
-
|
|
8522
|
+
<div *ngIf="designOpen" class="dialog-stage" [attr.data-placement]="placementValue"
|
|
8523
|
+
(click)="onStageClick($event)">
|
|
8504
8524
|
<div [ngStyle]="style"
|
|
8505
8525
|
[ngClass]="'iox-node-' + nodeId"
|
|
8506
8526
|
class="dialog-surface"
|
|
@@ -8512,7 +8532,8 @@ class BuilderDialogComponent {
|
|
|
8512
8532
|
type="button"
|
|
8513
8533
|
class="dialog-close"
|
|
8514
8534
|
aria-label="Close dialog"
|
|
8515
|
-
(
|
|
8535
|
+
(mousedown)="$event.stopPropagation()"
|
|
8536
|
+
(click)="onCloseClick($event)">
|
|
8516
8537
|
<i class="ph-thin ph-x"></i>
|
|
8517
8538
|
</button>
|
|
8518
8539
|
|
|
@@ -8530,13 +8551,13 @@ class BuilderDialogComponent {
|
|
|
8530
8551
|
</ng-container>
|
|
8531
8552
|
</div>
|
|
8532
8553
|
</div>
|
|
8533
|
-
`, isInline: true, styles: [".dialog-stage{position:fixed;inset:0;z-index:50
|
|
8554
|
+
`, isInline: true, styles: [".dialog-stage{position:fixed;inset:0;z-index:50;display:grid;place-items:center;padding:24px;box-sizing:border-box;background:#0f172a73}.dialog-stage[data-placement=top]{align-items:start}.dialog-stage[data-placement=bottom]{align-items:end}.dialog-stage[data-placement=start]{justify-items:start}.dialog-stage[data-placement=end]{justify-items:end}.dialog-surface{box-sizing:border-box;max-width:100%;max-height:100%;overflow:auto;contain:layout}.dialog-close{position:absolute;inset-inline-end:10px;top:10px;width:26px;height:26px;border:none;border-radius:999px;background:#0f172a0f;color:inherit;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.dialog-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;min-height:90px;border:1.5px dashed rgba(100,116,139,.35);border-radius:4px;color:#64748b80;font-size:12px}.dialog-placeholder i{font-size:18px}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: RenderDirective, selector: "[ioxRender]", inputs: ["ioxRender", "ioxDragSourceId"], outputs: ["onClick", "onMouseEnter", "onMouseLeave"] }, { kind: "directive", type: IoxDropzoneDirective, selector: "[ioxDropzone]", inputs: ["ioxDropzoneId", "ioxDropzoneData", "ioxDropzonePostDrop"], outputs: ["ioxDrop"] }] }); }
|
|
8534
8555
|
}
|
|
8535
8556
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImport: i0, type: BuilderDialogComponent, decorators: [{
|
|
8536
8557
|
type: Component,
|
|
8537
8558
|
args: [{ selector: 'app-builder-dialog', template: `
|
|
8538
|
-
<div *ngIf="designOpen" class="dialog-stage" [attr.data-placement]="placementValue"
|
|
8539
|
-
|
|
8559
|
+
<div *ngIf="designOpen" class="dialog-stage" [attr.data-placement]="placementValue"
|
|
8560
|
+
(click)="onStageClick($event)">
|
|
8540
8561
|
<div [ngStyle]="style"
|
|
8541
8562
|
[ngClass]="'iox-node-' + nodeId"
|
|
8542
8563
|
class="dialog-surface"
|
|
@@ -8548,7 +8569,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
|
|
|
8548
8569
|
type="button"
|
|
8549
8570
|
class="dialog-close"
|
|
8550
8571
|
aria-label="Close dialog"
|
|
8551
|
-
(
|
|
8572
|
+
(mousedown)="$event.stopPropagation()"
|
|
8573
|
+
(click)="onCloseClick($event)">
|
|
8552
8574
|
<i class="ph-thin ph-x"></i>
|
|
8553
8575
|
</button>
|
|
8554
8576
|
|
|
@@ -8566,7 +8588,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.31", ngImpo
|
|
|
8566
8588
|
</ng-container>
|
|
8567
8589
|
</div>
|
|
8568
8590
|
</div>
|
|
8569
|
-
`, standalone: false, styles: [".dialog-stage{position:fixed;inset:0;z-index:50
|
|
8591
|
+
`, standalone: false, styles: [".dialog-stage{position:fixed;inset:0;z-index:50;display:grid;place-items:center;padding:24px;box-sizing:border-box;background:#0f172a73}.dialog-stage[data-placement=top]{align-items:start}.dialog-stage[data-placement=bottom]{align-items:end}.dialog-stage[data-placement=start]{justify-items:start}.dialog-stage[data-placement=end]{justify-items:end}.dialog-surface{box-sizing:border-box;max-width:100%;max-height:100%;overflow:auto;contain:layout}.dialog-close{position:absolute;inset-inline-end:10px;top:10px;width:26px;height:26px;border:none;border-radius:999px;background:#0f172a0f;color:inherit;cursor:pointer;display:inline-flex;align-items:center;justify-content:center}.dialog-placeholder{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.5rem;min-height:90px;border:1.5px dashed rgba(100,116,139,.35);border-radius:4px;color:#64748b80;font-size:12px}.dialog-placeholder i{font-size:18px}\n"] }]
|
|
8570
8592
|
}], ctorParameters: () => [{ type: DragEngineService }, { type: i1.ComponentInstanceRegistryService }, { type: OverlayService }, { type: i0.ChangeDetectorRef }], propDecorators: { children: [{
|
|
8571
8593
|
type: Input
|
|
8572
8594
|
}], style: [{
|
|
@@ -9988,6 +10010,13 @@ function setTrait(node, name, value) {
|
|
|
9988
10010
|
trait.default = value;
|
|
9989
10011
|
}
|
|
9990
10012
|
|
|
10013
|
+
function text$1(content, styles, createConfig) {
|
|
10014
|
+
const node = textNode(content, createConfig);
|
|
10015
|
+
if (node)
|
|
10016
|
+
for (const [prop, value] of Object.entries(styles))
|
|
10017
|
+
setStyleTrait(node, prop, value);
|
|
10018
|
+
return node;
|
|
10019
|
+
}
|
|
9991
10020
|
/**
|
|
9992
10021
|
* THE CONSENT PRESET (consent plan C3) — the banner as builder elements, which is the whole bet:
|
|
9993
10022
|
* Wix ships a banner you cannot design, Webflow ships a design system and no banner; ours is a
|
|
@@ -10014,16 +10043,50 @@ const click = (actions) => ({
|
|
|
10014
10043
|
target: 'self', duration: 0, delay: 0, easing: 'ease', ...a,
|
|
10015
10044
|
})),
|
|
10016
10045
|
});
|
|
10017
|
-
|
|
10046
|
+
const TOKEN$1 = (name, fallback) => `var(--iox-${name}, ${fallback})`;
|
|
10047
|
+
function button(label, createConfig, interaction, styles = {}) {
|
|
10018
10048
|
const btn = createConfig('ButtonBlock');
|
|
10019
10049
|
const text = textNode(label, createConfig);
|
|
10020
10050
|
if (!btn || !text)
|
|
10021
10051
|
return null;
|
|
10022
10052
|
setTrait(btn, 'tag', 'button');
|
|
10053
|
+
setStyleTrait(text, 'fontSize', 'inherit');
|
|
10054
|
+
setStyleTrait(text, 'fontWeight', 'inherit');
|
|
10055
|
+
setStyleTrait(text, 'color', 'inherit');
|
|
10056
|
+
for (const [prop, value] of Object.entries(styles))
|
|
10057
|
+
setStyleTrait(btn, prop, value);
|
|
10023
10058
|
btn.children = [text];
|
|
10024
10059
|
btn.interactions = [interaction];
|
|
10025
10060
|
return btn;
|
|
10026
10061
|
}
|
|
10062
|
+
/** The C1/C2 board button voices — Swiss by fallback, the brand's the moment tokens seed. */
|
|
10063
|
+
const SOLID = {
|
|
10064
|
+
backgroundColor: TOKEN$1('brand-500', '#1f1d1b'), color: TOKEN$1('brandInk', '#ffffff'),
|
|
10065
|
+
fontSize: '12px', fontWeight: '600', padding: '9px 16px',
|
|
10066
|
+
borderRadius: TOKEN$1('radius-control', '4px'),
|
|
10067
|
+
};
|
|
10068
|
+
const OUTLINED = {
|
|
10069
|
+
backgroundColor: 'transparent', color: TOKEN$1('ink', '#1f1d1b'),
|
|
10070
|
+
borderWidth: '1px', borderStyle: 'solid', borderColor: TOKEN$1('ink', '#1f1d1b'),
|
|
10071
|
+
fontSize: '12px', fontWeight: '600', padding: '8px 16px',
|
|
10072
|
+
borderRadius: TOKEN$1('radius-control', '4px'),
|
|
10073
|
+
};
|
|
10074
|
+
const QUIET = {
|
|
10075
|
+
backgroundColor: 'transparent', color: TOKEN$1('inkMuted', '#4a453f'),
|
|
10076
|
+
fontSize: '11px', fontWeight: '400', padding: '2px 4px', textDecoration: 'underline',
|
|
10077
|
+
};
|
|
10078
|
+
const SMALL_ALLOW = {
|
|
10079
|
+
backgroundColor: 'transparent', color: TOKEN$1('ink', '#1f1d1b'),
|
|
10080
|
+
borderWidth: '1px', borderStyle: 'solid', borderColor: TOKEN$1('ink', '#1f1d1b'),
|
|
10081
|
+
fontSize: '11px', fontWeight: '600', padding: '5px 10px',
|
|
10082
|
+
borderRadius: TOKEN$1('radius-control', '4px'),
|
|
10083
|
+
};
|
|
10084
|
+
const SMALL_REFUSE = {
|
|
10085
|
+
backgroundColor: 'transparent', color: TOKEN$1('inkMuted', '#6b6560'),
|
|
10086
|
+
borderWidth: '1px', borderStyle: 'solid', borderColor: TOKEN$1('line', '#d8d4d1'),
|
|
10087
|
+
fontSize: '11px', fontWeight: '600', padding: '5px 10px',
|
|
10088
|
+
borderRadius: TOKEN$1('radius-control', '4px'),
|
|
10089
|
+
};
|
|
10027
10090
|
function row(createConfig, styles, children) {
|
|
10028
10091
|
const container = createConfig('Container');
|
|
10029
10092
|
if (!container || children.some(c => !c))
|
|
@@ -10045,57 +10108,97 @@ function buildConsentPreset(createConfig) {
|
|
|
10045
10108
|
setTrait(banner, 'closeOnBackdrop', false); // clicking away is NOT consent
|
|
10046
10109
|
setTrait(banner, 'showCloseButton', true); // the runtime records X as a "no"
|
|
10047
10110
|
setTrait(banner, 'placement', 'bottom'); // A5: placement is the Dialog's own choice
|
|
10048
|
-
|
|
10049
|
-
|
|
10050
|
-
|
|
10051
|
-
|
|
10052
|
-
|
|
10053
|
-
|
|
10111
|
+
// Board C1, Swiss column: a full-width bottom bar, hairline-ruled, surface-on-surface.
|
|
10112
|
+
setStyleTrait(banner, 'width', '100%');
|
|
10113
|
+
setStyleTrait(banner, 'borderRadius', '0px');
|
|
10114
|
+
setStyleTrait(banner, 'padding', '14px 20px');
|
|
10115
|
+
setStyleTrait(banner, 'backgroundColor', TOKEN$1('surface', '#ffffff'));
|
|
10116
|
+
setStyleTrait(banner, 'borderWidth', '1px');
|
|
10117
|
+
setStyleTrait(banner, 'borderStyle', 'solid');
|
|
10118
|
+
setStyleTrait(banner, 'borderColor', TOKEN$1('ink', '#1f1d1b'));
|
|
10119
|
+
setStyleTrait(banner, 'boxShadow', 'none');
|
|
10120
|
+
const heading = text$1('Cookies on this site', { fontSize: '13px', fontWeight: '600', color: TOKEN$1('ink', '#1f1d1b') }, createConfig);
|
|
10121
|
+
// The first layer NAMES the three categories (plan §7) — the board does it in the copy.
|
|
10122
|
+
const body = text$1('We use analytics and marketing cookies only if you allow them. Necessary ones always run.', { fontSize: '11px', color: TOKEN$1('inkMuted', '#4a453f'), lineHeight: '1.5', maxWidth: '330px' }, createConfig);
|
|
10123
|
+
const textCol = row(createConfig, { display: 'flex', flexDirection: 'column', gap: '4px', flexGrow: '1' }, [heading, body]);
|
|
10054
10124
|
const accept = button('Accept all', createConfig, click([
|
|
10055
10125
|
{ type: 'grantConsent' },
|
|
10056
10126
|
{ type: 'closeDialog', target: banner.id },
|
|
10057
|
-
]));
|
|
10127
|
+
]), SOLID);
|
|
10058
10128
|
const reject = button('Reject all', createConfig, click([
|
|
10059
10129
|
{ type: 'denyConsent' },
|
|
10060
10130
|
{ type: 'closeDialog', target: banner.id },
|
|
10061
|
-
]));
|
|
10131
|
+
]), OUTLINED);
|
|
10062
10132
|
const prefs = button('Preferences', createConfig, click([
|
|
10063
10133
|
{ type: 'openConsentPreferences', target: preferences.id },
|
|
10064
|
-
]));
|
|
10065
|
-
const
|
|
10066
|
-
|
|
10134
|
+
]), QUIET);
|
|
10135
|
+
const acceptRejectRow = row(createConfig, { display: 'flex', gap: '7px' }, [accept, reject]);
|
|
10136
|
+
const buttonsCol = row(createConfig, { display: 'flex', flexDirection: 'column', gap: '7px', alignItems: 'center' }, [acceptRejectRow, prefs]);
|
|
10137
|
+
const bannerRow = row(createConfig, { display: 'flex', gap: '18px', alignItems: 'flex-start', flexWrap: 'wrap' }, [textCol, buttonsCol]);
|
|
10138
|
+
if (!bannerRow)
|
|
10067
10139
|
return null;
|
|
10068
|
-
banner.children = [
|
|
10140
|
+
banner.children = [bannerRow];
|
|
10069
10141
|
// ── the preferences modal ────────────────────────────────────────────────
|
|
10070
10142
|
preferences.label = 'Consent preferences';
|
|
10071
10143
|
setTrait(preferences, 'closeOnBackdrop', true);
|
|
10072
10144
|
setTrait(preferences, 'showCloseButton', true);
|
|
10073
|
-
|
|
10074
|
-
|
|
10075
|
-
|
|
10076
|
-
|
|
10145
|
+
setStyleTrait(preferences, 'width', 'min(480px, calc(100vw - 48px))');
|
|
10146
|
+
setStyleTrait(preferences, 'padding', '18px 20px');
|
|
10147
|
+
setStyleTrait(preferences, 'display', 'flex');
|
|
10148
|
+
setStyleTrait(preferences, 'flexDirection', 'column');
|
|
10149
|
+
setStyleTrait(preferences, 'gap', '12px');
|
|
10150
|
+
const prefsHeading = text$1('Your privacy choices', { fontSize: '16px', fontWeight: '600', color: TOKEN$1('ink', '#1f1d1b') }, createConfig);
|
|
10151
|
+
const prefsSub = text$1('Change these any time from “Cookie settings” in the footer.', { fontSize: '12px', color: TOKEN$1('inkMuted', '#6b6560') }, createConfig);
|
|
10152
|
+
const CARD = {
|
|
10153
|
+
display: 'flex', gap: '12px', alignItems: 'flex-start',
|
|
10154
|
+
borderWidth: '1px', borderStyle: 'solid', borderColor: TOKEN$1('line', '#e6e3e1'),
|
|
10155
|
+
borderRadius: TOKEN$1('radius-surface', '8px'), padding: '12px 14px',
|
|
10156
|
+
};
|
|
10157
|
+
const nameText = (s) => text$1(s, { fontSize: '13px', fontWeight: '600', color: TOKEN$1('ink', '#1f1d1b') }, createConfig);
|
|
10158
|
+
const descText = (s) => text$1(s, { fontSize: '11px', color: TOKEN$1('inkMuted', '#6b6560'), lineHeight: '1.5' }, createConfig);
|
|
10159
|
+
const textColOf = (name, desc) => row(createConfig, { display: 'flex', flexDirection: 'column', gap: '2px', flexGrow: '1' }, [nameText(name), descText(desc)]);
|
|
10160
|
+
const alwaysOn = text$1('ALWAYS ON', {
|
|
10161
|
+
fontSize: '10px', fontWeight: '600', color: TOKEN$1('inkMuted', '#6b6560'),
|
|
10162
|
+
borderWidth: '1px', borderStyle: 'solid', borderColor: TOKEN$1('line', '#e6e3e1'),
|
|
10163
|
+
borderRadius: '999px', padding: '3px 8px',
|
|
10164
|
+
}, createConfig);
|
|
10165
|
+
const necessaryCard = row(createConfig, CARD, [
|
|
10166
|
+
textColOf('Necessary', 'Keeps the site working: your session, your language, this very choice. Always on.'),
|
|
10167
|
+
alwaysOn,
|
|
10168
|
+
]);
|
|
10169
|
+
const categoryCard = (category, name, desc) => {
|
|
10077
10170
|
const allow = button('Allow', createConfig, click([
|
|
10078
10171
|
{ type: 'setConsentCategory', params: { category, granted: true } },
|
|
10079
|
-
]));
|
|
10172
|
+
]), SMALL_ALLOW);
|
|
10080
10173
|
const refuse = button('Refuse', createConfig, click([
|
|
10081
10174
|
{ type: 'setConsentCategory', params: { category, granted: false } },
|
|
10082
|
-
]));
|
|
10083
|
-
const pair = row(createConfig, { display: 'flex', gap: '
|
|
10084
|
-
return row(createConfig,
|
|
10175
|
+
]), SMALL_REFUSE);
|
|
10176
|
+
const pair = row(createConfig, { display: 'flex', gap: '6px' }, [allow, refuse]);
|
|
10177
|
+
return row(createConfig, CARD, [textColOf(name, desc), pair]);
|
|
10085
10178
|
};
|
|
10086
|
-
const
|
|
10087
|
-
const
|
|
10088
|
-
|
|
10089
|
-
const
|
|
10179
|
+
const analyticsCard = categoryCard('analytics', 'Analytics', 'Anonymous counts of visits and pages. Off means the analytics script never loads.');
|
|
10180
|
+
const marketingCard = categoryCard('marketing', 'Marketing', 'Ads measurement and remarketing. Off means no ad cookies and no data shared.');
|
|
10181
|
+
// Board C2's footer: bulk exits live here too — Reject | (grow) | Done | Accept.
|
|
10182
|
+
const prefsReject = button('Reject all', createConfig, click([
|
|
10183
|
+
{ type: 'denyConsent' },
|
|
10184
|
+
{ type: 'closeDialog', target: preferences.id },
|
|
10185
|
+
]), OUTLINED);
|
|
10186
|
+
const prefsDone = button('Done', createConfig, click([
|
|
10187
|
+
{ type: 'closeDialog', target: preferences.id },
|
|
10188
|
+
]), { ...OUTLINED, color: TOKEN$1('inkMuted', '#3d3833'), borderColor: TOKEN$1('line', '#d8d4d1') });
|
|
10189
|
+
const prefsAccept = button('Accept all', createConfig, click([
|
|
10190
|
+
{ type: 'grantConsent' },
|
|
10090
10191
|
{ type: 'closeDialog', target: preferences.id },
|
|
10091
|
-
]));
|
|
10092
|
-
|
|
10192
|
+
]), SOLID);
|
|
10193
|
+
const spacer = row(createConfig, { flexGrow: '1' }, []);
|
|
10194
|
+
const footer = row(createConfig, { display: 'flex', gap: '8px', alignItems: 'center' }, [prefsReject, spacer, prefsDone, prefsAccept]);
|
|
10195
|
+
if (!prefsHeading || !prefsSub || !necessaryCard || !analyticsCard || !marketingCard || !footer)
|
|
10093
10196
|
return null;
|
|
10094
|
-
preferences.children = [prefsHeading,
|
|
10197
|
+
preferences.children = [prefsHeading, prefsSub, necessaryCard, analyticsCard, marketingCard, footer];
|
|
10095
10198
|
// ── the withdrawal path (§7.3) ───────────────────────────────────────────
|
|
10096
10199
|
const withdrawal = button('Cookie settings', createConfig, click([
|
|
10097
10200
|
{ type: 'openConsentPreferences', target: preferences.id },
|
|
10098
|
-
]));
|
|
10201
|
+
]), QUIET);
|
|
10099
10202
|
if (!withdrawal)
|
|
10100
10203
|
return null;
|
|
10101
10204
|
withdrawal.label = 'Cookie settings';
|