@hanzo/ui 8.29.12 → 8.29.14
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/dist/consent/Consent.cjs +211 -50
- package/dist/consent/Consent.d.ts +5 -1
- package/dist/consent/Consent.d.ts.map +1 -1
- package/dist/consent/Consent.js +214 -53
- package/dist/consent/Consent.js.map +1 -1
- package/dist/gallery.html +1 -1
- package/package.json +3 -3
package/dist/consent/Consent.cjs
CHANGED
|
@@ -6,27 +6,39 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
6
6
|
/**
|
|
7
7
|
* Consent — the one cookie banner every Hanzo, Lux and Zoo site mounts.
|
|
8
8
|
*
|
|
9
|
-
* It draws the choice; @hanzo/event stores it (`hz_consent`) and acts on it:
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* It draws the choice; @hanzo/event stores it (`hz_consent`) and acts on it: no
|
|
10
|
+
* Google Analytics, no Meta pixel and no ad personalization before Accept, and
|
|
11
|
+
* Google Consent Mode v2 starts denied. The brand's own first-party analytics is
|
|
12
|
+
* strictly necessary and runs for every visitor; the choice does not govern it.
|
|
12
13
|
*
|
|
13
|
-
* - every visitor, wherever they are, is asked: a
|
|
14
|
-
*
|
|
14
|
+
* - every visitor, wherever they are, is asked: a bar with Manage preferences,
|
|
15
|
+
* Accept all and a ×, until they have chosen. Nothing optional loads first.
|
|
16
|
+
* - the bar's × is a choice, not a dismissal: it stores essential cookies only
|
|
17
|
+
* and closes, so refusing is one press, exactly as accepting is.
|
|
18
|
+
* - Manage preferences opens the Cookie Preferences sheet: a modal with one
|
|
19
|
+
* section per category, Strictly Necessary always on, the rest switches that
|
|
20
|
+
* start off until chosen, and the policy links.
|
|
15
21
|
* - Global Privacy Control or Do Not Track is the visitor's answer already: they
|
|
16
22
|
* are not asked, nothing optional runs, and the switches are locked off.
|
|
17
|
-
* - cloud serves the policy with the site's tag config; the
|
|
18
|
-
*
|
|
23
|
+
* - cloud serves the policy with the site's tag config; the bar redraws when it
|
|
24
|
+
* arrives, and asks again when the policy version changes.
|
|
19
25
|
*
|
|
20
|
-
* `Consent` mounts once near the root
|
|
21
|
-
* link
|
|
26
|
+
* `Consent` mounts once near the root. `openConsent()`, `ConsentLink` and any
|
|
27
|
+
* link to `#choices` (the footer's Privacy choices) open the sheet from anywhere.
|
|
28
|
+
* `brand` names who is asking; `cookies`, `privacy` and `terms` are the brand's
|
|
29
|
+
* own policies.
|
|
22
30
|
*/
|
|
23
31
|
const gui_1 = require("@hanzo/gui");
|
|
32
|
+
const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
|
|
24
33
|
const event_1 = require("@hanzo/event");
|
|
25
34
|
const react_1 = require("react");
|
|
26
35
|
const button_1 = require("../backends/gui/button.cjs");
|
|
36
|
+
const dir_1 = require("../backends/gui/dir.cjs");
|
|
27
37
|
const switch_1 = require("../backends/gui/switch.cjs");
|
|
28
38
|
const slot_1 = require("../backends/gui/slot.cjs");
|
|
29
39
|
const OPEN = 'hzconsent-open';
|
|
40
|
+
/** The address that opens the sheet, from any link on any page. */
|
|
41
|
+
const HASH = '#choices';
|
|
30
42
|
/** Opens the choices from anywhere. */
|
|
31
43
|
const openConsent = () => {
|
|
32
44
|
if (typeof window !== 'undefined')
|
|
@@ -34,24 +46,56 @@ const openConsent = () => {
|
|
|
34
46
|
};
|
|
35
47
|
exports.openConsent = openConsent;
|
|
36
48
|
const kinds = (brand) => [
|
|
37
|
-
{
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
{
|
|
50
|
+
id: 'necessary',
|
|
51
|
+
title: 'Strictly Necessary Cookies',
|
|
52
|
+
body: `These are needed for the site to work, so they are always on. They keep you signed in and your session secure, protect forms against cross-site request forgery, spread traffic across servers, remember the choice you make here, and keep what you have typed into a form. They include ${brand}'s own first-party analytics, which counts visits and finds what is broken for ${brand} alone and is never sold or shared.`,
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: 'analytics',
|
|
56
|
+
key: 'analytics',
|
|
57
|
+
title: 'Performance Cookies',
|
|
58
|
+
body: `Google Analytics: lets Google measure visits to ${brand} with its own cookies.`,
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: 'marketing',
|
|
62
|
+
key: 'marketing',
|
|
63
|
+
title: 'Marketing Cookies',
|
|
64
|
+
body: `The Meta pixel: lets Meta measure the sign-ups and orders ${brand}'s ads led to.`,
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: 'ads',
|
|
68
|
+
key: 'ads',
|
|
69
|
+
title: 'Sell, Share, or Use Your Data for Targeted Advertising',
|
|
70
|
+
body: 'Lets Google and Meta use your visit to choose the ads they show you on other sites and apps. Some US state privacy laws call this a “sale” or “sharing” of your personal information, or “targeted advertising”, and give you the right to opt out: it stays off unless you turn it on.',
|
|
71
|
+
},
|
|
40
72
|
];
|
|
41
|
-
/** The
|
|
73
|
+
/** The bar's and the sheet's inset from the window's edges: 16px, or the device's inset and 8px where that is wider. */
|
|
42
74
|
const EDGE = {
|
|
75
|
+
top: 'max(16px, calc(var(--safe-top, env(safe-area-inset-top, 0px)) + 8px))',
|
|
43
76
|
bottom: 'max(16px, calc(var(--safe-bottom, env(safe-area-inset-bottom, 0px)) + 8px))',
|
|
44
77
|
left: 'max(16px, calc(var(--safe-left, env(safe-area-inset-left, 0px)) + 8px))',
|
|
45
78
|
right: 'max(16px, calc(var(--safe-right, env(safe-area-inset-right, 0px)) + 8px))',
|
|
46
79
|
};
|
|
80
|
+
/** The panel both wear: the card's ground, edge, corner (`$6`, the sign-in card's) and floating shadow. */
|
|
81
|
+
const PANEL = {
|
|
82
|
+
bg: '$background',
|
|
83
|
+
borderWidth: 1,
|
|
84
|
+
borderColor: '$borderColor',
|
|
85
|
+
rounded: '$6',
|
|
86
|
+
shadowColor: 'rgba(0,0,0,0.25)',
|
|
87
|
+
shadowRadius: 24,
|
|
88
|
+
shadowOffset: { width: 0, height: 8 },
|
|
89
|
+
};
|
|
47
90
|
/**
|
|
48
|
-
* Where the
|
|
91
|
+
* Where the bar sits: fixed to the foot of the window, clear of the home
|
|
49
92
|
* indicator and the notch, centred. It stands on design's banner rung
|
|
50
93
|
* (`--z-banner`): over the page and its dock, under every overlay — a dialog, a
|
|
51
94
|
* menu, a phone drawer — and is answered once they close.
|
|
52
95
|
*/
|
|
53
96
|
const frame = {
|
|
54
97
|
...(0, slot_1.slot)('consent'),
|
|
98
|
+
...PANEL,
|
|
55
99
|
role: 'dialog',
|
|
56
100
|
'aria-label': 'Cookie preferences',
|
|
57
101
|
position: 'fixed',
|
|
@@ -60,46 +104,166 @@ const frame = {
|
|
|
60
104
|
r: EDGE.right,
|
|
61
105
|
mx: 'auto',
|
|
62
106
|
z: 'var(--z-banner, 50)',
|
|
63
|
-
py: '$
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
borderColor: '$borderColor',
|
|
68
|
-
bg: '$background',
|
|
69
|
-
shadowColor: 'rgba(0,0,0,0.25)',
|
|
70
|
-
shadowRadius: 24,
|
|
71
|
-
shadowOffset: { width: 0, height: 8 },
|
|
107
|
+
py: '$3',
|
|
108
|
+
paddingInlineStart: '$4',
|
|
109
|
+
// Clear of the × in the corner: its 32px, and 12px either side.
|
|
110
|
+
paddingInlineEnd: 56,
|
|
72
111
|
};
|
|
73
112
|
/** The bar is as wide as its line and buttons, up to the window less its inset. */
|
|
74
113
|
const FIT = { width: 'fit-content' };
|
|
75
|
-
/**
|
|
114
|
+
/** The one filled control in the bar and in the sheet: the ink, as the sign-in card's Continue. */
|
|
115
|
+
const ACT = { bg: '$ink', color: '$background', borderColor: '$ink', hoverStyle: { opacity: 0.92 } };
|
|
116
|
+
/** A link in the sheet's intro: the line's own ink, underlined, never broken across lines. */
|
|
76
117
|
const INLINE = { color: 'inherit', textDecoration: 'underline', whiteSpace: 'nowrap' };
|
|
77
|
-
|
|
118
|
+
/** The sheet covers the window, on design's modal rung, over a scrim of its own. */
|
|
119
|
+
const COVER = { position: 'fixed', t: 0, r: 0, b: 0, l: 0 };
|
|
120
|
+
/** What Tab may land on inside the sheet. */
|
|
121
|
+
const FOCUSABLE = 'a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
122
|
+
/** A section's button never submits a form the sheet sits in. gui's stack props do not name `type`. */
|
|
123
|
+
const BUTTON = { type: 'button' };
|
|
124
|
+
const Consent = ({ cookies = 'https://hanzo.ai/cookies', privacy = 'https://hanzo.ai/privacy', terms = 'https://hanzo.ai/terms', brand = 'Hanzo', }) => {
|
|
78
125
|
const [shown, setShown] = (0, react_1.useState)(false);
|
|
79
126
|
const [choosing, setChoosing] = (0, react_1.useState)(false);
|
|
80
127
|
const [draft, setDraft] = (0, react_1.useState)({ analytics: false, marketing: false, ads: false });
|
|
128
|
+
const [expanded, setExpanded] = (0, react_1.useState)({});
|
|
81
129
|
// The choices are open because the visitor asked for them. A policy that
|
|
82
130
|
// arrives after (cloud answers ~150ms into a page opened at #choices) redraws
|
|
83
|
-
// the
|
|
131
|
+
// the bar's question, and must not close what was asked for.
|
|
84
132
|
const asked = (0, react_1.useRef)(false);
|
|
85
|
-
//
|
|
86
|
-
const
|
|
133
|
+
// What had focus when the sheet opened, given it back when the sheet closes.
|
|
134
|
+
const back = (0, react_1.useRef)(null);
|
|
135
|
+
const sheet = (0, react_1.useRef)(null);
|
|
136
|
+
const manage = (0, react_1.useRef)(null);
|
|
137
|
+
const opened = (0, react_1.useRef)(false);
|
|
138
|
+
// The switches were filled from a stored choice, not left off.
|
|
139
|
+
const seeded = (0, react_1.useRef)(false);
|
|
140
|
+
const id = (0, react_1.useId)();
|
|
141
|
+
// The browser refused, as the page sees it or as cloud saw the request. State,
|
|
142
|
+
// so cloud's answer redraws an open sheet.
|
|
143
|
+
const [locked, setLocked] = (0, react_1.useState)(false);
|
|
144
|
+
const choose = () => {
|
|
145
|
+
// Already open: the visitor's unsaved switches and the focus to return stay as they are.
|
|
146
|
+
if (asked.current)
|
|
147
|
+
return;
|
|
148
|
+
const at = document.activeElement;
|
|
149
|
+
back.current = at instanceof HTMLElement && at !== document.body ? at : null;
|
|
150
|
+
asked.current = true;
|
|
151
|
+
setLocked((0, event_1.declined)());
|
|
152
|
+
seeded.current = (0, event_1.storedConsent)();
|
|
153
|
+
setDraft((0, event_1.readConsent)());
|
|
154
|
+
setChoosing(true);
|
|
155
|
+
setShown(true);
|
|
156
|
+
};
|
|
157
|
+
// Closing without a choice: a visitor who has not chosen is asked again by the bar.
|
|
158
|
+
const close = () => {
|
|
159
|
+
asked.current = false;
|
|
160
|
+
setChoosing(false);
|
|
161
|
+
setShown((0, event_1.asks)());
|
|
162
|
+
};
|
|
87
163
|
(0, react_1.useEffect)(() => {
|
|
88
|
-
const sync = () =>
|
|
164
|
+
const sync = () => {
|
|
165
|
+
setShown((0, event_1.asks)() || asked.current);
|
|
166
|
+
setLocked((0, event_1.declined)());
|
|
167
|
+
// A policy version the stored choice was not made under: the switches the
|
|
168
|
+
// sheet opened with were an old grant, and are off until chosen again.
|
|
169
|
+
if (asked.current && seeded.current && !(0, event_1.storedConsent)()) {
|
|
170
|
+
seeded.current = false;
|
|
171
|
+
setDraft((0, event_1.readConsent)());
|
|
172
|
+
}
|
|
173
|
+
};
|
|
89
174
|
sync();
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
175
|
+
// `#choices` opens the sheet: on arrival, on a hash change, and on a press of
|
|
176
|
+
// any link on this site to it, so the footer's Privacy choices and a link in
|
|
177
|
+
// a page are the same control.
|
|
178
|
+
const hash = () => {
|
|
179
|
+
if (window.location.hash !== HASH)
|
|
180
|
+
return;
|
|
181
|
+
// The router's own entry state is kept: only the address loses its hash. A
|
|
182
|
+
// microtask, so a router that wraps replaceState in its own mount effect
|
|
183
|
+
// (Next's, which runs after this child's) records the address without it.
|
|
184
|
+
queueMicrotask(() => history.replaceState(history.state, '', window.location.pathname + window.location.search));
|
|
185
|
+
choose();
|
|
186
|
+
};
|
|
187
|
+
// A plain press only: a modified one (new tab, new window) keeps the browser's
|
|
188
|
+
// meaning, and the page it opens at #choices opens the sheet on arrival.
|
|
189
|
+
const press = (e) => {
|
|
190
|
+
if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey)
|
|
191
|
+
return;
|
|
192
|
+
// The attribute, not `.href`: an SVG link's `.href` is not a string.
|
|
193
|
+
const a = e.target?.closest?.('a[href]');
|
|
194
|
+
const href = a?.getAttribute('href');
|
|
195
|
+
const target = a?.getAttribute('target');
|
|
196
|
+
if (!href || a?.hasAttribute('download') || (target && target !== '_self'))
|
|
197
|
+
return;
|
|
198
|
+
let to;
|
|
199
|
+
try {
|
|
200
|
+
to = new URL(href, document.baseURI);
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (to.hash !== HASH || to.origin !== window.location.origin)
|
|
206
|
+
return;
|
|
207
|
+
e.preventDefault();
|
|
208
|
+
choose();
|
|
95
209
|
};
|
|
96
|
-
|
|
210
|
+
hash();
|
|
211
|
+
window.addEventListener(OPEN, choose);
|
|
97
212
|
window.addEventListener(event_1.POLICY_EVENT, sync);
|
|
213
|
+
window.addEventListener('hashchange', hash);
|
|
214
|
+
document.addEventListener('click', press, { capture: true });
|
|
98
215
|
return () => {
|
|
99
|
-
window.removeEventListener(OPEN,
|
|
216
|
+
window.removeEventListener(OPEN, choose);
|
|
100
217
|
window.removeEventListener(event_1.POLICY_EVENT, sync);
|
|
218
|
+
window.removeEventListener('hashchange', hash);
|
|
219
|
+
document.removeEventListener('click', press, { capture: true });
|
|
101
220
|
};
|
|
102
221
|
}, []);
|
|
222
|
+
// Focus moves into the sheet when it opens, stays inside it while it is open,
|
|
223
|
+
// and returns to what opened it (or the bar's Manage preferences) when it closes.
|
|
224
|
+
(0, react_1.useEffect)(() => {
|
|
225
|
+
if (!choosing) {
|
|
226
|
+
if (!opened.current)
|
|
227
|
+
return;
|
|
228
|
+
opened.current = false;
|
|
229
|
+
const el = back.current;
|
|
230
|
+
back.current = null;
|
|
231
|
+
if (el?.isConnected)
|
|
232
|
+
el.focus();
|
|
233
|
+
else
|
|
234
|
+
manage.current?.focus();
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
opened.current = true;
|
|
238
|
+
const all = () => [...(sheet.current?.querySelectorAll(FOCUSABLE) ?? [])];
|
|
239
|
+
all()[0]?.focus();
|
|
240
|
+
const keys = (e) => {
|
|
241
|
+
if (e.key === 'Escape') {
|
|
242
|
+
e.preventDefault();
|
|
243
|
+
close();
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (e.key !== 'Tab')
|
|
247
|
+
return;
|
|
248
|
+
const list = all();
|
|
249
|
+
const first = list[0];
|
|
250
|
+
const last = list[list.length - 1];
|
|
251
|
+
if (!first || !last)
|
|
252
|
+
return;
|
|
253
|
+
const at = document.activeElement;
|
|
254
|
+
const inside = !!at && !!sheet.current?.contains(at);
|
|
255
|
+
if (e.shiftKey && (at === first || !inside)) {
|
|
256
|
+
e.preventDefault();
|
|
257
|
+
last.focus();
|
|
258
|
+
}
|
|
259
|
+
else if (!e.shiftKey && (at === last || !inside)) {
|
|
260
|
+
e.preventDefault();
|
|
261
|
+
first.focus();
|
|
262
|
+
}
|
|
263
|
+
};
|
|
264
|
+
document.addEventListener('keydown', keys);
|
|
265
|
+
return () => document.removeEventListener('keydown', keys);
|
|
266
|
+
}, [choosing]);
|
|
103
267
|
if (!shown)
|
|
104
268
|
return null;
|
|
105
269
|
const done = (fn) => () => {
|
|
@@ -108,21 +272,18 @@ const Consent = ({ privacy = 'https://hanzo.ai/privacy', brand = 'Hanzo' }) => {
|
|
|
108
272
|
setShown(false);
|
|
109
273
|
setChoosing(false);
|
|
110
274
|
};
|
|
111
|
-
const choose = () => {
|
|
112
|
-
asked.current = true;
|
|
113
|
-
setDraft((0, event_1.readConsent)());
|
|
114
|
-
setChoosing(true);
|
|
115
|
-
setShown(true);
|
|
116
|
-
};
|
|
117
275
|
if (choosing)
|
|
118
|
-
return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
276
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('consent-sheet'), ...COVER, z: "var(--z-modal, 600)", items: "center", justify: "center",
|
|
277
|
+
// The device's insets are physical sides, so the shorthand names them in order.
|
|
278
|
+
style: { padding: `${EDGE.top} ${EDGE.right} ${EDGE.bottom} ${EDGE.left}` }, children: [(0, jsx_runtime_1.jsx)(gui_1.YStack, { ...COVER, position: "absolute", z: 0, bg: "rgba(0,0,0,0.6)", "aria-hidden": true, onPress: close }), (0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('consent'), ...PANEL, ref: sheet, role: "dialog", "aria-modal": true, "aria-labelledby": `${id}-title`, position: "relative", width: "100%", maxW: 560, maxH: "100%", overflow: "hidden", children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", justify: "space-between", gap: "$3", pt: "$5", pb: "$3", paddingInlineStart: "$5", paddingInlineEnd: "$4", children: [(0, jsx_runtime_1.jsx)(gui_1.Text, { render: "h2", id: `${id}-title`, m: 0, fontSize: "$6", lineHeight: "$6", fontWeight: "600", color: "$ink", children: "Cookie Preferences" }), (0, jsx_runtime_1.jsx)(button_1.Button, { type: "button", size: "icon-sm", variant: "ghost", "aria-label": "Close", onClick: close, children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.X, { size: 16 }) })] }), (0, jsx_runtime_1.jsxs)(gui_1.YStack, { shrink: 1, minH: 0, overflowY: "auto", px: "$5", pb: "$2", style: { overscrollBehavior: 'contain' }, children: [(0, jsx_runtime_1.jsxs)(gui_1.Paragraph, { size: "$2", color: "$aside", m: 0, pb: "$3", children: ['We use cookies and similar technologies to provide our services, measure performance, and support advertising. Essential cookies are required for the site to work and cannot be turned off. You can allow or reject optional cookies below. Learn more in our ', (0, jsx_runtime_1.jsx)("a", { href: cookies, style: INLINE, children: "Cookie Policy" }), ', ', (0, jsx_runtime_1.jsx)("a", { href: privacy, style: INLINE, children: "Privacy Policy" }), ', and ', (0, jsx_runtime_1.jsx)("a", { href: terms, style: INLINE, children: "Terms of Service" }), "."] }), locked ? ((0, jsx_runtime_1.jsx)(gui_1.Paragraph, { size: "$2", color: "$ink", m: 0, pb: "$3", children: "Your browser asks sites not to track you, so all of these stay off." })) : null, kinds(brand).map((k) => {
|
|
279
|
+
const open = expanded[k.id] === true;
|
|
280
|
+
const body = `${id}-${k.id}`;
|
|
281
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.YStack, { ...(0, slot_1.slot)('consent-section'), borderTopWidth: 1, borderColor: "$borderColor", children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$3", minH: 52, py: "$2", children: [(0, jsx_runtime_1.jsx)(gui_1.XStack, { render: "h3", flex: 1, minW: 0, m: 0, children: (0, jsx_runtime_1.jsxs)(gui_1.XStack, { render: "button", ...BUTTON, "aria-expanded": open, "aria-controls": body, onPress: () => setExpanded({ ...expanded, [k.id]: !open }), flex: 1, minW: 0, items: "center", gap: "$2", p: 0, bg: "transparent", borderWidth: 0, cursor: "pointer", children: [(0, jsx_runtime_1.jsx)(gui_1.XStack, { shrink: 0, rotate: open ? '180deg' : '0deg', opacity: 0.7, children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronDown, { size: 16 }) }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$3", lineHeight: "$3", fontWeight: "600", color: "$ink", ...(0, dir_1.align)('start'), children: k.title })] }) }), k.key ? ((0, jsx_runtime_1.jsx)(switch_1.Switch, { "aria-label": k.title, "aria-describedby": body, disabled: locked, checked: locked ? false : draft[k.key], onCheckedChange: (v) => setDraft({ ...draft, [k.key]: v === true }) })) : ((0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", fontWeight: "600", color: "$ink", whiteSpace: "nowrap", children: "Always Active" }))] }), (0, jsx_runtime_1.jsx)(gui_1.YStack, { id: body, display: open ? 'flex' : 'none', pb: "$3", paddingInlineStart: 24, children: (0, jsx_runtime_1.jsx)(gui_1.Paragraph, { size: "$2", color: "$aside", m: 0, children: k.body }) })] }, k.id));
|
|
282
|
+
})] }), (0, jsx_runtime_1.jsxs)(gui_1.XStack, { flexWrap: "wrap", gap: "$2", px: "$5", py: "$4", borderTopWidth: 1, borderColor: "$borderColor", children: [locked ? null : ((0, jsx_runtime_1.jsx)(button_1.Button, { type: "button", variant: "secondary", grow: 1, onClick: done(event_1.acceptAll), children: "Accept all" })), (0, jsx_runtime_1.jsx)(button_1.Button, { type: "button", ...ACT, grow: 1, onClick: done(() => (0, event_1.saveConsent)(draft)), children: "Save preferences" })] })] })] }));
|
|
283
|
+
// One bar: the line, then the buttons. They share a row where the line fits
|
|
284
|
+
// beside them and the buttons drop under it where it does not, so a phone shows
|
|
285
|
+
// the line over one row of buttons and nothing breaks mid-control.
|
|
286
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { ...frame, style: FIT, maxW: 1200, flexWrap: "wrap", items: "center", columnGap: "$4", rowGap: "$3", children: [(0, jsx_runtime_1.jsx)(gui_1.YStack, { shrink: 1, minW: 0, children: (0, jsx_runtime_1.jsx)(gui_1.Paragraph, { size: "$2", color: "$ink", m: 0, children: `Essential cookies keep ${brand} running. With your OK, optional cookies help us measure performance and ads.` }) }), (0, jsx_runtime_1.jsxs)(gui_1.XStack, { gap: "$2", marginInlineStart: "auto", items: "center", flexWrap: "wrap", children: [(0, jsx_runtime_1.jsx)(button_1.Button, { ref: manage, type: "button", size: "sm", variant: "secondary", onClick: choose, children: "Manage preferences" }), (0, jsx_runtime_1.jsx)(button_1.Button, { type: "button", size: "sm", ...ACT, onClick: done(event_1.acceptAll), children: "Accept all" })] }), (0, jsx_runtime_1.jsx)(button_1.Button, { type: "button", size: "icon-sm", variant: "ghost", "aria-label": "Close and use essential cookies only", position: "absolute", t: "$3", insetInlineEnd: "$3", onClick: done(event_1.rejectAll), children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.X, { size: 16 }) })] }));
|
|
126
287
|
};
|
|
127
288
|
exports.Consent = Consent;
|
|
128
289
|
/** The footer link that reopens the choices, in every footer and every region. */
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
/** Opens the choices from anywhere. */
|
|
2
2
|
export declare const openConsent: () => void;
|
|
3
3
|
export type ConsentProps = {
|
|
4
|
+
/** Where the cookie policy lives. */
|
|
5
|
+
cookies?: string;
|
|
4
6
|
/** Where the privacy policy lives. */
|
|
5
7
|
privacy?: string;
|
|
8
|
+
/** Where the terms of service live. */
|
|
9
|
+
terms?: string;
|
|
6
10
|
/** Who is asking: the brand the visitor is on. */
|
|
7
11
|
brand?: string;
|
|
8
12
|
};
|
|
9
|
-
declare const Consent: ({ privacy, brand }: ConsentProps) => import("react").JSX.Element | null;
|
|
13
|
+
declare const Consent: ({ cookies, privacy, terms, brand, }: ConsentProps) => import("react").JSX.Element | null;
|
|
10
14
|
/** The footer link that reopens the choices, in every footer and every region. */
|
|
11
15
|
declare const ConsentLink: ({ label }: {
|
|
12
16
|
label?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Consent.d.ts","sourceRoot":"","sources":["../../src/consent/Consent.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Consent.d.ts","sourceRoot":"","sources":["../../src/consent/Consent.tsx"],"names":[],"mappings":"AA0CA,uCAAuC;AACvC,eAAO,MAAM,WAAW,QAAO,IAE9B,CAAA;AA0FD,MAAM,MAAM,YAAY,GAAG;IACzB,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAED,QAAA,MAAM,OAAO,wCAKV,YAAY,uCA4Sd,CAAA;AAED,kFAAkF;AAClF,QAAA,MAAM,WAAW,cAAmC;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,gCAIrE,CAAA;AAED,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAA"}
|
package/dist/consent/Consent.js
CHANGED
|
@@ -3,51 +3,95 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
/**
|
|
4
4
|
* Consent — the one cookie banner every Hanzo, Lux and Zoo site mounts.
|
|
5
5
|
*
|
|
6
|
-
* It draws the choice; @hanzo/event stores it (`hz_consent`) and acts on it:
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* It draws the choice; @hanzo/event stores it (`hz_consent`) and acts on it: no
|
|
7
|
+
* Google Analytics, no Meta pixel and no ad personalization before Accept, and
|
|
8
|
+
* Google Consent Mode v2 starts denied. The brand's own first-party analytics is
|
|
9
|
+
* strictly necessary and runs for every visitor; the choice does not govern it.
|
|
9
10
|
*
|
|
10
|
-
* - every visitor, wherever they are, is asked: a
|
|
11
|
-
*
|
|
11
|
+
* - every visitor, wherever they are, is asked: a bar with Manage preferences,
|
|
12
|
+
* Accept all and a ×, until they have chosen. Nothing optional loads first.
|
|
13
|
+
* - the bar's × is a choice, not a dismissal: it stores essential cookies only
|
|
14
|
+
* and closes, so refusing is one press, exactly as accepting is.
|
|
15
|
+
* - Manage preferences opens the Cookie Preferences sheet: a modal with one
|
|
16
|
+
* section per category, Strictly Necessary always on, the rest switches that
|
|
17
|
+
* start off until chosen, and the policy links.
|
|
12
18
|
* - Global Privacy Control or Do Not Track is the visitor's answer already: they
|
|
13
19
|
* are not asked, nothing optional runs, and the switches are locked off.
|
|
14
|
-
* - cloud serves the policy with the site's tag config; the
|
|
15
|
-
*
|
|
20
|
+
* - cloud serves the policy with the site's tag config; the bar redraws when it
|
|
21
|
+
* arrives, and asks again when the policy version changes.
|
|
16
22
|
*
|
|
17
|
-
* `Consent` mounts once near the root
|
|
18
|
-
* link
|
|
23
|
+
* `Consent` mounts once near the root. `openConsent()`, `ConsentLink` and any
|
|
24
|
+
* link to `#choices` (the footer's Privacy choices) open the sheet from anywhere.
|
|
25
|
+
* `brand` names who is asking; `cookies`, `privacy` and `terms` are the brand's
|
|
26
|
+
* own policies.
|
|
19
27
|
*/
|
|
20
|
-
import { Paragraph, XStack, YStack } from '@hanzo/gui';
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
28
|
+
import { Paragraph, Text, XStack, YStack } from '@hanzo/gui';
|
|
29
|
+
import { ChevronDown, X } from '@hanzogui/lucide-icons-2';
|
|
30
|
+
import { acceptAll, asks, declined, POLICY_EVENT, readConsent, rejectAll, saveConsent, storedConsent } from '@hanzo/event';
|
|
31
|
+
import { useEffect, useId, useRef, useState } from 'react';
|
|
23
32
|
import { Button } from '../backends/gui/button.js';
|
|
33
|
+
import { align } from '../backends/gui/dir.js';
|
|
24
34
|
import { Switch } from '../backends/gui/switch.js';
|
|
25
35
|
import { slot } from '../backends/gui/slot.js';
|
|
26
36
|
const OPEN = 'hzconsent-open';
|
|
37
|
+
/** The address that opens the sheet, from any link on any page. */
|
|
38
|
+
const HASH = '#choices';
|
|
27
39
|
/** Opens the choices from anywhere. */
|
|
28
40
|
export const openConsent = () => {
|
|
29
41
|
if (typeof window !== 'undefined')
|
|
30
42
|
window.dispatchEvent(new Event(OPEN));
|
|
31
43
|
};
|
|
32
44
|
const kinds = (brand) => [
|
|
33
|
-
{
|
|
34
|
-
|
|
35
|
-
|
|
45
|
+
{
|
|
46
|
+
id: 'necessary',
|
|
47
|
+
title: 'Strictly Necessary Cookies',
|
|
48
|
+
body: `These are needed for the site to work, so they are always on. They keep you signed in and your session secure, protect forms against cross-site request forgery, spread traffic across servers, remember the choice you make here, and keep what you have typed into a form. They include ${brand}'s own first-party analytics, which counts visits and finds what is broken for ${brand} alone and is never sold or shared.`,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: 'analytics',
|
|
52
|
+
key: 'analytics',
|
|
53
|
+
title: 'Performance Cookies',
|
|
54
|
+
body: `Google Analytics: lets Google measure visits to ${brand} with its own cookies.`,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: 'marketing',
|
|
58
|
+
key: 'marketing',
|
|
59
|
+
title: 'Marketing Cookies',
|
|
60
|
+
body: `The Meta pixel: lets Meta measure the sign-ups and orders ${brand}'s ads led to.`,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
id: 'ads',
|
|
64
|
+
key: 'ads',
|
|
65
|
+
title: 'Sell, Share, or Use Your Data for Targeted Advertising',
|
|
66
|
+
body: 'Lets Google and Meta use your visit to choose the ads they show you on other sites and apps. Some US state privacy laws call this a “sale” or “sharing” of your personal information, or “targeted advertising”, and give you the right to opt out: it stays off unless you turn it on.',
|
|
67
|
+
},
|
|
36
68
|
];
|
|
37
|
-
/** The
|
|
69
|
+
/** The bar's and the sheet's inset from the window's edges: 16px, or the device's inset and 8px where that is wider. */
|
|
38
70
|
const EDGE = {
|
|
71
|
+
top: 'max(16px, calc(var(--safe-top, env(safe-area-inset-top, 0px)) + 8px))',
|
|
39
72
|
bottom: 'max(16px, calc(var(--safe-bottom, env(safe-area-inset-bottom, 0px)) + 8px))',
|
|
40
73
|
left: 'max(16px, calc(var(--safe-left, env(safe-area-inset-left, 0px)) + 8px))',
|
|
41
74
|
right: 'max(16px, calc(var(--safe-right, env(safe-area-inset-right, 0px)) + 8px))',
|
|
42
75
|
};
|
|
76
|
+
/** The panel both wear: the card's ground, edge, corner (`$6`, the sign-in card's) and floating shadow. */
|
|
77
|
+
const PANEL = {
|
|
78
|
+
bg: '$background',
|
|
79
|
+
borderWidth: 1,
|
|
80
|
+
borderColor: '$borderColor',
|
|
81
|
+
rounded: '$6',
|
|
82
|
+
shadowColor: 'rgba(0,0,0,0.25)',
|
|
83
|
+
shadowRadius: 24,
|
|
84
|
+
shadowOffset: { width: 0, height: 8 },
|
|
85
|
+
};
|
|
43
86
|
/**
|
|
44
|
-
* Where the
|
|
87
|
+
* Where the bar sits: fixed to the foot of the window, clear of the home
|
|
45
88
|
* indicator and the notch, centred. It stands on design's banner rung
|
|
46
89
|
* (`--z-banner`): over the page and its dock, under every overlay — a dialog, a
|
|
47
90
|
* menu, a phone drawer — and is answered once they close.
|
|
48
91
|
*/
|
|
49
92
|
const frame = {
|
|
50
93
|
...slot('consent'),
|
|
94
|
+
...PANEL,
|
|
51
95
|
role: 'dialog',
|
|
52
96
|
'aria-label': 'Cookie preferences',
|
|
53
97
|
position: 'fixed',
|
|
@@ -56,46 +100,166 @@ const frame = {
|
|
|
56
100
|
r: EDGE.right,
|
|
57
101
|
mx: 'auto',
|
|
58
102
|
z: 'var(--z-banner, 50)',
|
|
59
|
-
py: '$
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
borderColor: '$borderColor',
|
|
64
|
-
bg: '$background',
|
|
65
|
-
shadowColor: 'rgba(0,0,0,0.25)',
|
|
66
|
-
shadowRadius: 24,
|
|
67
|
-
shadowOffset: { width: 0, height: 8 },
|
|
103
|
+
py: '$3',
|
|
104
|
+
paddingInlineStart: '$4',
|
|
105
|
+
// Clear of the × in the corner: its 32px, and 12px either side.
|
|
106
|
+
paddingInlineEnd: 56,
|
|
68
107
|
};
|
|
69
108
|
/** The bar is as wide as its line and buttons, up to the window less its inset. */
|
|
70
109
|
const FIT = { width: 'fit-content' };
|
|
71
|
-
/**
|
|
110
|
+
/** The one filled control in the bar and in the sheet: the ink, as the sign-in card's Continue. */
|
|
111
|
+
const ACT = { bg: '$ink', color: '$background', borderColor: '$ink', hoverStyle: { opacity: 0.92 } };
|
|
112
|
+
/** A link in the sheet's intro: the line's own ink, underlined, never broken across lines. */
|
|
72
113
|
const INLINE = { color: 'inherit', textDecoration: 'underline', whiteSpace: 'nowrap' };
|
|
73
|
-
|
|
114
|
+
/** The sheet covers the window, on design's modal rung, over a scrim of its own. */
|
|
115
|
+
const COVER = { position: 'fixed', t: 0, r: 0, b: 0, l: 0 };
|
|
116
|
+
/** What Tab may land on inside the sheet. */
|
|
117
|
+
const FOCUSABLE = 'a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])';
|
|
118
|
+
/** A section's button never submits a form the sheet sits in. gui's stack props do not name `type`. */
|
|
119
|
+
const BUTTON = { type: 'button' };
|
|
120
|
+
const Consent = ({ cookies = 'https://hanzo.ai/cookies', privacy = 'https://hanzo.ai/privacy', terms = 'https://hanzo.ai/terms', brand = 'Hanzo', }) => {
|
|
74
121
|
const [shown, setShown] = useState(false);
|
|
75
122
|
const [choosing, setChoosing] = useState(false);
|
|
76
123
|
const [draft, setDraft] = useState({ analytics: false, marketing: false, ads: false });
|
|
124
|
+
const [expanded, setExpanded] = useState({});
|
|
77
125
|
// The choices are open because the visitor asked for them. A policy that
|
|
78
126
|
// arrives after (cloud answers ~150ms into a page opened at #choices) redraws
|
|
79
|
-
// the
|
|
127
|
+
// the bar's question, and must not close what was asked for.
|
|
80
128
|
const asked = useRef(false);
|
|
81
|
-
//
|
|
82
|
-
const
|
|
129
|
+
// What had focus when the sheet opened, given it back when the sheet closes.
|
|
130
|
+
const back = useRef(null);
|
|
131
|
+
const sheet = useRef(null);
|
|
132
|
+
const manage = useRef(null);
|
|
133
|
+
const opened = useRef(false);
|
|
134
|
+
// The switches were filled from a stored choice, not left off.
|
|
135
|
+
const seeded = useRef(false);
|
|
136
|
+
const id = useId();
|
|
137
|
+
// The browser refused, as the page sees it or as cloud saw the request. State,
|
|
138
|
+
// so cloud's answer redraws an open sheet.
|
|
139
|
+
const [locked, setLocked] = useState(false);
|
|
140
|
+
const choose = () => {
|
|
141
|
+
// Already open: the visitor's unsaved switches and the focus to return stay as they are.
|
|
142
|
+
if (asked.current)
|
|
143
|
+
return;
|
|
144
|
+
const at = document.activeElement;
|
|
145
|
+
back.current = at instanceof HTMLElement && at !== document.body ? at : null;
|
|
146
|
+
asked.current = true;
|
|
147
|
+
setLocked(declined());
|
|
148
|
+
seeded.current = storedConsent();
|
|
149
|
+
setDraft(readConsent());
|
|
150
|
+
setChoosing(true);
|
|
151
|
+
setShown(true);
|
|
152
|
+
};
|
|
153
|
+
// Closing without a choice: a visitor who has not chosen is asked again by the bar.
|
|
154
|
+
const close = () => {
|
|
155
|
+
asked.current = false;
|
|
156
|
+
setChoosing(false);
|
|
157
|
+
setShown(asks());
|
|
158
|
+
};
|
|
83
159
|
useEffect(() => {
|
|
84
|
-
const sync = () =>
|
|
160
|
+
const sync = () => {
|
|
161
|
+
setShown(asks() || asked.current);
|
|
162
|
+
setLocked(declined());
|
|
163
|
+
// A policy version the stored choice was not made under: the switches the
|
|
164
|
+
// sheet opened with were an old grant, and are off until chosen again.
|
|
165
|
+
if (asked.current && seeded.current && !storedConsent()) {
|
|
166
|
+
seeded.current = false;
|
|
167
|
+
setDraft(readConsent());
|
|
168
|
+
}
|
|
169
|
+
};
|
|
85
170
|
sync();
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
171
|
+
// `#choices` opens the sheet: on arrival, on a hash change, and on a press of
|
|
172
|
+
// any link on this site to it, so the footer's Privacy choices and a link in
|
|
173
|
+
// a page are the same control.
|
|
174
|
+
const hash = () => {
|
|
175
|
+
if (window.location.hash !== HASH)
|
|
176
|
+
return;
|
|
177
|
+
// The router's own entry state is kept: only the address loses its hash. A
|
|
178
|
+
// microtask, so a router that wraps replaceState in its own mount effect
|
|
179
|
+
// (Next's, which runs after this child's) records the address without it.
|
|
180
|
+
queueMicrotask(() => history.replaceState(history.state, '', window.location.pathname + window.location.search));
|
|
181
|
+
choose();
|
|
182
|
+
};
|
|
183
|
+
// A plain press only: a modified one (new tab, new window) keeps the browser's
|
|
184
|
+
// meaning, and the page it opens at #choices opens the sheet on arrival.
|
|
185
|
+
const press = (e) => {
|
|
186
|
+
if (e.defaultPrevented || e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey)
|
|
187
|
+
return;
|
|
188
|
+
// The attribute, not `.href`: an SVG link's `.href` is not a string.
|
|
189
|
+
const a = e.target?.closest?.('a[href]');
|
|
190
|
+
const href = a?.getAttribute('href');
|
|
191
|
+
const target = a?.getAttribute('target');
|
|
192
|
+
if (!href || a?.hasAttribute('download') || (target && target !== '_self'))
|
|
193
|
+
return;
|
|
194
|
+
let to;
|
|
195
|
+
try {
|
|
196
|
+
to = new URL(href, document.baseURI);
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (to.hash !== HASH || to.origin !== window.location.origin)
|
|
202
|
+
return;
|
|
203
|
+
e.preventDefault();
|
|
204
|
+
choose();
|
|
91
205
|
};
|
|
92
|
-
|
|
206
|
+
hash();
|
|
207
|
+
window.addEventListener(OPEN, choose);
|
|
93
208
|
window.addEventListener(POLICY_EVENT, sync);
|
|
209
|
+
window.addEventListener('hashchange', hash);
|
|
210
|
+
document.addEventListener('click', press, { capture: true });
|
|
94
211
|
return () => {
|
|
95
|
-
window.removeEventListener(OPEN,
|
|
212
|
+
window.removeEventListener(OPEN, choose);
|
|
96
213
|
window.removeEventListener(POLICY_EVENT, sync);
|
|
214
|
+
window.removeEventListener('hashchange', hash);
|
|
215
|
+
document.removeEventListener('click', press, { capture: true });
|
|
97
216
|
};
|
|
98
217
|
}, []);
|
|
218
|
+
// Focus moves into the sheet when it opens, stays inside it while it is open,
|
|
219
|
+
// and returns to what opened it (or the bar's Manage preferences) when it closes.
|
|
220
|
+
useEffect(() => {
|
|
221
|
+
if (!choosing) {
|
|
222
|
+
if (!opened.current)
|
|
223
|
+
return;
|
|
224
|
+
opened.current = false;
|
|
225
|
+
const el = back.current;
|
|
226
|
+
back.current = null;
|
|
227
|
+
if (el?.isConnected)
|
|
228
|
+
el.focus();
|
|
229
|
+
else
|
|
230
|
+
manage.current?.focus();
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
opened.current = true;
|
|
234
|
+
const all = () => [...(sheet.current?.querySelectorAll(FOCUSABLE) ?? [])];
|
|
235
|
+
all()[0]?.focus();
|
|
236
|
+
const keys = (e) => {
|
|
237
|
+
if (e.key === 'Escape') {
|
|
238
|
+
e.preventDefault();
|
|
239
|
+
close();
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
if (e.key !== 'Tab')
|
|
243
|
+
return;
|
|
244
|
+
const list = all();
|
|
245
|
+
const first = list[0];
|
|
246
|
+
const last = list[list.length - 1];
|
|
247
|
+
if (!first || !last)
|
|
248
|
+
return;
|
|
249
|
+
const at = document.activeElement;
|
|
250
|
+
const inside = !!at && !!sheet.current?.contains(at);
|
|
251
|
+
if (e.shiftKey && (at === first || !inside)) {
|
|
252
|
+
e.preventDefault();
|
|
253
|
+
last.focus();
|
|
254
|
+
}
|
|
255
|
+
else if (!e.shiftKey && (at === last || !inside)) {
|
|
256
|
+
e.preventDefault();
|
|
257
|
+
first.focus();
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
document.addEventListener('keydown', keys);
|
|
261
|
+
return () => document.removeEventListener('keydown', keys);
|
|
262
|
+
}, [choosing]);
|
|
99
263
|
if (!shown)
|
|
100
264
|
return null;
|
|
101
265
|
const done = (fn) => () => {
|
|
@@ -104,21 +268,18 @@ const Consent = ({ privacy = 'https://hanzo.ai/privacy', brand = 'Hanzo' }) => {
|
|
|
104
268
|
setShown(false);
|
|
105
269
|
setChoosing(false);
|
|
106
270
|
};
|
|
107
|
-
const choose = () => {
|
|
108
|
-
asked.current = true;
|
|
109
|
-
setDraft(readConsent());
|
|
110
|
-
setChoosing(true);
|
|
111
|
-
setShown(true);
|
|
112
|
-
};
|
|
113
271
|
if (choosing)
|
|
114
|
-
return (_jsxs(YStack, { ...
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
272
|
+
return (_jsxs(YStack, { ...slot('consent-sheet'), ...COVER, z: "var(--z-modal, 600)", items: "center", justify: "center",
|
|
273
|
+
// The device's insets are physical sides, so the shorthand names them in order.
|
|
274
|
+
style: { padding: `${EDGE.top} ${EDGE.right} ${EDGE.bottom} ${EDGE.left}` }, children: [_jsx(YStack, { ...COVER, position: "absolute", z: 0, bg: "rgba(0,0,0,0.6)", "aria-hidden": true, onPress: close }), _jsxs(YStack, { ...slot('consent'), ...PANEL, ref: sheet, role: "dialog", "aria-modal": true, "aria-labelledby": `${id}-title`, position: "relative", width: "100%", maxW: 560, maxH: "100%", overflow: "hidden", children: [_jsxs(XStack, { items: "center", justify: "space-between", gap: "$3", pt: "$5", pb: "$3", paddingInlineStart: "$5", paddingInlineEnd: "$4", children: [_jsx(Text, { render: "h2", id: `${id}-title`, m: 0, fontSize: "$6", lineHeight: "$6", fontWeight: "600", color: "$ink", children: "Cookie Preferences" }), _jsx(Button, { type: "button", size: "icon-sm", variant: "ghost", "aria-label": "Close", onClick: close, children: _jsx(X, { size: 16 }) })] }), _jsxs(YStack, { shrink: 1, minH: 0, overflowY: "auto", px: "$5", pb: "$2", style: { overscrollBehavior: 'contain' }, children: [_jsxs(Paragraph, { size: "$2", color: "$aside", m: 0, pb: "$3", children: ['We use cookies and similar technologies to provide our services, measure performance, and support advertising. Essential cookies are required for the site to work and cannot be turned off. You can allow or reject optional cookies below. Learn more in our ', _jsx("a", { href: cookies, style: INLINE, children: "Cookie Policy" }), ', ', _jsx("a", { href: privacy, style: INLINE, children: "Privacy Policy" }), ', and ', _jsx("a", { href: terms, style: INLINE, children: "Terms of Service" }), "."] }), locked ? (_jsx(Paragraph, { size: "$2", color: "$ink", m: 0, pb: "$3", children: "Your browser asks sites not to track you, so all of these stay off." })) : null, kinds(brand).map((k) => {
|
|
275
|
+
const open = expanded[k.id] === true;
|
|
276
|
+
const body = `${id}-${k.id}`;
|
|
277
|
+
return (_jsxs(YStack, { ...slot('consent-section'), borderTopWidth: 1, borderColor: "$borderColor", children: [_jsxs(XStack, { items: "center", gap: "$3", minH: 52, py: "$2", children: [_jsx(XStack, { render: "h3", flex: 1, minW: 0, m: 0, children: _jsxs(XStack, { render: "button", ...BUTTON, "aria-expanded": open, "aria-controls": body, onPress: () => setExpanded({ ...expanded, [k.id]: !open }), flex: 1, minW: 0, items: "center", gap: "$2", p: 0, bg: "transparent", borderWidth: 0, cursor: "pointer", children: [_jsx(XStack, { shrink: 0, rotate: open ? '180deg' : '0deg', opacity: 0.7, children: _jsx(ChevronDown, { size: 16 }) }), _jsx(Text, { fontSize: "$3", lineHeight: "$3", fontWeight: "600", color: "$ink", ...align('start'), children: k.title })] }) }), k.key ? (_jsx(Switch, { "aria-label": k.title, "aria-describedby": body, disabled: locked, checked: locked ? false : draft[k.key], onCheckedChange: (v) => setDraft({ ...draft, [k.key]: v === true }) })) : (_jsx(Text, { fontSize: "$2", fontWeight: "600", color: "$ink", whiteSpace: "nowrap", children: "Always Active" }))] }), _jsx(YStack, { id: body, display: open ? 'flex' : 'none', pb: "$3", paddingInlineStart: 24, children: _jsx(Paragraph, { size: "$2", color: "$aside", m: 0, children: k.body }) })] }, k.id));
|
|
278
|
+
})] }), _jsxs(XStack, { flexWrap: "wrap", gap: "$2", px: "$5", py: "$4", borderTopWidth: 1, borderColor: "$borderColor", children: [locked ? null : (_jsx(Button, { type: "button", variant: "secondary", grow: 1, onClick: done(acceptAll), children: "Accept all" })), _jsx(Button, { type: "button", ...ACT, grow: 1, onClick: done(() => saveConsent(draft)), children: "Save preferences" })] })] })] }));
|
|
279
|
+
// One bar: the line, then the buttons. They share a row where the line fits
|
|
280
|
+
// beside them and the buttons drop under it where it does not, so a phone shows
|
|
281
|
+
// the line over one row of buttons and nothing breaks mid-control.
|
|
282
|
+
return (_jsxs(XStack, { ...frame, style: FIT, maxW: 1200, flexWrap: "wrap", items: "center", columnGap: "$4", rowGap: "$3", children: [_jsx(YStack, { shrink: 1, minW: 0, children: _jsx(Paragraph, { size: "$2", color: "$ink", m: 0, children: `Essential cookies keep ${brand} running. With your OK, optional cookies help us measure performance and ads.` }) }), _jsxs(XStack, { gap: "$2", marginInlineStart: "auto", items: "center", flexWrap: "wrap", children: [_jsx(Button, { ref: manage, type: "button", size: "sm", variant: "secondary", onClick: choose, children: "Manage preferences" }), _jsx(Button, { type: "button", size: "sm", ...ACT, onClick: done(acceptAll), children: "Accept all" })] }), _jsx(Button, { type: "button", size: "icon-sm", variant: "ghost", "aria-label": "Close and use essential cookies only", position: "absolute", t: "$3", insetInlineEnd: "$3", onClick: done(rejectAll), children: _jsx(X, { size: 16 }) })] }));
|
|
122
283
|
};
|
|
123
284
|
/** The footer link that reopens the choices, in every footer and every region. */
|
|
124
285
|
const ConsentLink = ({ label = 'Cookie settings' }) => (_jsx(Button, { ...slot('consent-link'), type: "button", variant: "link", size: "sm", px: 0, minH: 0, onClick: openConsent, children: label }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Consent.js","sourceRoot":"","sources":["../../src/consent/Consent.tsx"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Consent.js","sourceRoot":"","sources":["../../src/consent/Consent.tsx"],"names":[],"mappings":"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"}
|
package/dist/gallery.html
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!doctype html><html lang="en" class="t_dark"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>@hanzo/ui 8.29.
|
|
1
|
+
<!doctype html><html lang="en" class="t_dark"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>@hanzo/ui 8.29.14</title><style>/* @hanzo/ui — generated by scripts/gen-css.mjs. Do not edit. */
|
|
2
2
|
:root { --hanzo-ui-styles: 1; }
|
|
3
3
|
/* Hanzo Design System — the entry point. Import THIS one file.
|
|
4
4
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/ui",
|
|
3
|
-
"version": "8.29.
|
|
3
|
+
"version": "8.29.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Hanzo UI — the one canonical Hanzo component library, on @hanzo/gui + @hanzo/design. ONE substrate: every component renders through @hanzo/gui primitives, so the same import works on web, native (expo) and desktop (Tauri). Self-contained (theme.css), presentational, host-agnostic, clean-room.",
|
|
6
6
|
"exports": {
|
|
@@ -331,7 +331,7 @@
|
|
|
331
331
|
"@hanzo/canvas": ">=0.2.3",
|
|
332
332
|
"@hanzo/cd": ">=0.1.2",
|
|
333
333
|
"@hanzo/dashboard": ">=0.2.0",
|
|
334
|
-
"@hanzo/event": ">=0.3.
|
|
334
|
+
"@hanzo/event": ">=0.3.61",
|
|
335
335
|
"@hanzo/data": ">=1.2.4",
|
|
336
336
|
"@hanzo/gui": "^8.3.5",
|
|
337
337
|
"@hanzo/iam": ">=0.21.26",
|
|
@@ -388,7 +388,7 @@
|
|
|
388
388
|
},
|
|
389
389
|
"devDependencies": {
|
|
390
390
|
"@hanzo/cd": "0.1.2",
|
|
391
|
-
"@hanzo/event": "0.3.
|
|
391
|
+
"@hanzo/event": "0.3.61",
|
|
392
392
|
"@hanzo/dashboard": "0.2.0",
|
|
393
393
|
"@hanzo/data": "1.2.4",
|
|
394
394
|
"@hanzo/gui": "8.3.5",
|