@scalemule/news-publication 0.0.11 → 0.0.13

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.
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { hasConsented, COOKIE_CONSENT_EVENT, acceptAllCookies, recordConsentToCompliance, rejectOptionalCookies } from './chunk-RNXTBN5Z.js';
2
+ import { checkUrlConsentBridge, hasConsented, isGeoConsentRequired, queryNetworkConsentHub, DEFAULT_CONSENT_HUB_URL, acceptAllCookies, rejectOptionalCookies, COOKIE_CONSENT_EVENT, recordConsentToCompliance, setNetworkConsentHub } from './chunk-L5OE6DND.js';
3
3
  import { useState, useEffect } from 'react';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
 
@@ -9,16 +9,52 @@ function CookieConsentBanner({
9
9
  settingsUrl = "/cookies",
10
10
  className = "",
11
11
  publicationSlug,
12
- complianceEndpoint = "/api/compliance/consent"
12
+ complianceEndpoint = "/api/compliance/consent",
13
+ countryCode,
14
+ forceShow = false,
15
+ consentHubUrl = DEFAULT_CONSENT_HUB_URL
13
16
  }) {
14
17
  const [mounted, setMounted] = useState(false);
15
18
  const [visible, setVisible] = useState(false);
16
19
  useEffect(() => {
17
20
  setMounted(true);
18
- if (!hasConsented()) {
19
- const timer = window.setTimeout(() => setVisible(true), 300);
20
- return () => window.clearTimeout(timer);
21
+ if (checkUrlConsentBridge()) {
22
+ setVisible(false);
23
+ return;
21
24
  }
25
+ if (hasConsented()) {
26
+ setVisible(false);
27
+ return;
28
+ }
29
+ if (!forceShow && !isGeoConsentRequired(countryCode)) {
30
+ setVisible(false);
31
+ void queryNetworkConsentHub(consentHubUrl, 1200).then((networkStatus) => {
32
+ if (networkStatus === "accepted") {
33
+ acceptAllCookies();
34
+ } else if (networkStatus === "rejected") {
35
+ rejectOptionalCookies();
36
+ }
37
+ });
38
+ return;
39
+ }
40
+ let cancelled = false;
41
+ void queryNetworkConsentHub(consentHubUrl, 1e3).then((networkStatus) => {
42
+ if (cancelled) return;
43
+ if (networkStatus === "accepted") {
44
+ acceptAllCookies();
45
+ setVisible(false);
46
+ } else if (networkStatus === "rejected") {
47
+ rejectOptionalCookies();
48
+ setVisible(false);
49
+ } else {
50
+ setVisible(true);
51
+ }
52
+ });
53
+ return () => {
54
+ cancelled = true;
55
+ };
56
+ }, [countryCode, forceShow, consentHubUrl]);
57
+ useEffect(() => {
22
58
  const onConsentChange = () => {
23
59
  if (hasConsented()) {
24
60
  setVisible(false);
@@ -35,6 +71,7 @@ function CookieConsentBanner({
35
71
  endpoint: complianceEndpoint,
36
72
  publicationSlug
37
73
  });
74
+ setNetworkConsentHub("accepted", consentHubUrl);
38
75
  };
39
76
  const handleReject = () => {
40
77
  const record = rejectOptionalCookies();
@@ -43,13 +80,14 @@ function CookieConsentBanner({
43
80
  endpoint: complianceEndpoint,
44
81
  publicationSlug
45
82
  });
83
+ setNetworkConsentHub("rejected", consentHubUrl);
46
84
  };
47
85
  const defaultText = /* @__PURE__ */ jsxs(Fragment, { children: [
48
- "We use cookies and process data from your device to analyze website performance, personalize ad content, and improve your experience. Your consent includes data transfers outside of the country you\u2019re located. View",
86
+ "We use cookies and device data to analyze performance, support local sponsors, and remember your reading preferences across our news network. View",
49
87
  " ",
50
88
  /* @__PURE__ */ jsx("a", { href: settingsUrl, className: "sm-cookie-banner-link", children: "Cookie Settings" }),
51
89
  " ",
52
- "for more information."
90
+ "for details."
53
91
  ] });
54
92
  return /* @__PURE__ */ jsx(
55
93
  "aside",
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { getCookieConsent, DEFAULT_PREFERENCES_ACCEPTED, COOKIE_CATEGORIES, setCookieConsent, recordConsentToCompliance, DEFAULT_PREFERENCES_REJECTED } from './chunk-RNXTBN5Z.js';
2
+ import { getCookieConsent, DEFAULT_PREFERENCES_ACCEPTED, COOKIE_CATEGORIES, setCookieConsent, recordConsentToCompliance, DEFAULT_PREFERENCES_REJECTED } from './chunk-L5OE6DND.js';
3
3
  import { useState, useEffect } from 'react';
4
4
  import { jsxs, jsx } from 'react/jsx-runtime';
5
5
 
@@ -3,6 +3,8 @@ var COOKIE_CONSENT_KEY = "sm_cookie_consent_v1";
3
3
  var COOKIE_CONSENT_BACKUP_KEY = "napsite_cookie_consent_v1";
4
4
  var COOKIE_CONSENT_EVENT = "scalemule-cookie-consent-change";
5
5
  var COOKIE_CONSENT_MAX_AGE_SECONDS = 365 * 24 * 60 * 60;
6
+ var DEFAULT_CONSENT_HUB_URL = "https://bayareachronicle.com/consent-bridge.html";
7
+ var NETWORK_CONSENT_STORAGE_KEY = "sm_network_consent_status";
6
8
  var DEFAULT_PREFERENCES_REJECTED = {
7
9
  essential: true,
8
10
  performance: false,
@@ -157,6 +159,248 @@ function getCookieConsent() {
157
159
  }
158
160
  return memoryConsent;
159
161
  }
162
+ var EU_EEA_UK_COUNTRIES = /* @__PURE__ */ new Set([
163
+ "AT",
164
+ "BE",
165
+ "BG",
166
+ "HR",
167
+ "CY",
168
+ "CZ",
169
+ "DK",
170
+ "EE",
171
+ "FI",
172
+ "FR",
173
+ "DE",
174
+ "GR",
175
+ "HU",
176
+ "IE",
177
+ "IT",
178
+ "LV",
179
+ "LT",
180
+ "LU",
181
+ "MT",
182
+ "NL",
183
+ "PL",
184
+ "PT",
185
+ "RO",
186
+ "SK",
187
+ "SI",
188
+ "ES",
189
+ "SE",
190
+ "IS",
191
+ "LI",
192
+ "NO",
193
+ "GB",
194
+ "CH"
195
+ ]);
196
+ function isGeoConsentRequired(countryCode) {
197
+ if (countryCode && typeof countryCode === "string") {
198
+ const code = countryCode.trim().toUpperCase();
199
+ if (code.length === 2) {
200
+ return EU_EEA_UK_COUNTRIES.has(code);
201
+ }
202
+ }
203
+ if (typeof window !== "undefined") {
204
+ try {
205
+ const cached = readCookie("sm_geo_country") || window.localStorage?.getItem("sm_geo_country");
206
+ if (cached && typeof cached === "string" && cached.length === 2) {
207
+ return EU_EEA_UK_COUNTRIES.has(cached.toUpperCase());
208
+ }
209
+ const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
210
+ if (tz) {
211
+ if (/^(America|US|Canada|Pacific)\//i.test(tz)) {
212
+ return false;
213
+ }
214
+ if (/^(Europe|Atlantic\/Reykjavik|Atlantic\/Canary|Atlantic\/Faeroe|Atlantic\/Madeira|Atlantic\/Azores|WET|CET|EET|GMT)/i.test(tz)) {
215
+ return true;
216
+ }
217
+ }
218
+ } catch {
219
+ }
220
+ }
221
+ return false;
222
+ }
223
+ function checkUrlConsentBridge() {
224
+ if (typeof window === "undefined") return false;
225
+ try {
226
+ const url = new URL(window.location.href);
227
+ const param = url.searchParams.get("sm_consent");
228
+ if (!param) return false;
229
+ if (param === "accepted" || param === "1" || param === "all") {
230
+ acceptAllCookies();
231
+ } else if (param === "rejected" || param === "0" || param === "essential") {
232
+ rejectOptionalCookies();
233
+ } else {
234
+ return false;
235
+ }
236
+ url.searchParams.delete("sm_consent");
237
+ const newSearch = url.searchParams.toString() ? `?${url.searchParams.toString()}` : "";
238
+ window.history.replaceState(null, "", `${url.pathname}${newSearch}${url.hash}`);
239
+ return true;
240
+ } catch {
241
+ return false;
242
+ }
243
+ }
244
+ function decorateNetworkUrl(targetUrl) {
245
+ const consent = getCookieConsent();
246
+ if (!consent) return targetUrl;
247
+ try {
248
+ const base = typeof window !== "undefined" ? window.location.origin : "https://localhost";
249
+ const url = new URL(targetUrl, base);
250
+ const value = consent.preferences.performance || consent.preferences.advertising ? "1" : "0";
251
+ url.searchParams.set("sm_consent", value);
252
+ return url.toString();
253
+ } catch {
254
+ return targetUrl;
255
+ }
256
+ }
257
+ function queryNetworkConsentHub(hubUrl = DEFAULT_CONSENT_HUB_URL, timeoutMs = 1e3) {
258
+ if (typeof window === "undefined") return Promise.resolve(null);
259
+ try {
260
+ const hubOrigin = new URL(hubUrl).origin;
261
+ if (window.location.origin === hubOrigin) {
262
+ try {
263
+ const direct = window.localStorage?.getItem(NETWORK_CONSENT_STORAGE_KEY);
264
+ if (direct === "accepted" || direct === "rejected") {
265
+ return Promise.resolve(direct);
266
+ }
267
+ } catch {
268
+ }
269
+ return Promise.resolve(null);
270
+ }
271
+ return new Promise((resolve) => {
272
+ let settled = false;
273
+ let iframe = null;
274
+ let timer = null;
275
+ const finish = (result) => {
276
+ if (settled) return;
277
+ settled = true;
278
+ if (timer !== null) window.clearTimeout(timer);
279
+ window.removeEventListener("message", onMessage);
280
+ if (iframe && iframe.parentNode) {
281
+ try {
282
+ iframe.parentNode.removeChild(iframe);
283
+ } catch {
284
+ }
285
+ }
286
+ resolve(result);
287
+ };
288
+ const sendGet = () => {
289
+ try {
290
+ iframe?.contentWindow?.postMessage({ type: "SM_CONSENT_GET" }, hubOrigin);
291
+ } catch {
292
+ }
293
+ };
294
+ const onMessage = (event) => {
295
+ if (event.origin !== hubOrigin) return;
296
+ const data = event.data;
297
+ if (!data || typeof data !== "object") return;
298
+ if (data.type === "SM_CONSENT_STATUS") {
299
+ const status = data.status === "accepted" || data.status === "rejected" ? data.status : null;
300
+ finish(status);
301
+ } else if (data.type === "SM_CONSENT_BRIDGE_READY") {
302
+ sendGet();
303
+ }
304
+ };
305
+ window.addEventListener("message", onMessage);
306
+ timer = window.setTimeout(() => {
307
+ finish(null);
308
+ }, timeoutMs);
309
+ try {
310
+ iframe = document.createElement("iframe");
311
+ iframe.src = hubUrl;
312
+ iframe.style.position = "absolute";
313
+ iframe.style.width = "0";
314
+ iframe.style.height = "0";
315
+ iframe.style.border = "0";
316
+ iframe.style.display = "none";
317
+ iframe.style.visibility = "hidden";
318
+ iframe.setAttribute("aria-hidden", "true");
319
+ iframe.setAttribute("tabindex", "-1");
320
+ iframe.onload = () => {
321
+ sendGet();
322
+ };
323
+ iframe.onerror = () => {
324
+ finish(null);
325
+ };
326
+ const target = document.body || document.documentElement;
327
+ target.appendChild(iframe);
328
+ } catch {
329
+ finish(null);
330
+ }
331
+ });
332
+ } catch {
333
+ return Promise.resolve(null);
334
+ }
335
+ }
336
+ function setNetworkConsentHub(status, hubUrl = DEFAULT_CONSENT_HUB_URL) {
337
+ if (typeof window === "undefined") return;
338
+ try {
339
+ const hubOrigin = new URL(hubUrl).origin;
340
+ if (window.location.origin === hubOrigin) {
341
+ try {
342
+ if (status) {
343
+ window.localStorage?.setItem(NETWORK_CONSENT_STORAGE_KEY, status);
344
+ } else {
345
+ window.localStorage?.removeItem(NETWORK_CONSENT_STORAGE_KEY);
346
+ }
347
+ } catch {
348
+ }
349
+ return;
350
+ }
351
+ let iframe = null;
352
+ let timer = null;
353
+ const cleanup = () => {
354
+ if (timer !== null) window.clearTimeout(timer);
355
+ window.removeEventListener("message", onMessage);
356
+ if (iframe && iframe.parentNode) {
357
+ try {
358
+ iframe.parentNode.removeChild(iframe);
359
+ } catch {
360
+ }
361
+ }
362
+ };
363
+ const sendSet = () => {
364
+ try {
365
+ iframe?.contentWindow?.postMessage({ type: "SM_CONSENT_SET", status }, hubOrigin);
366
+ } catch {
367
+ }
368
+ };
369
+ const onMessage = (event) => {
370
+ if (event.origin !== hubOrigin) return;
371
+ const data = event.data;
372
+ if (!data || typeof data !== "object") return;
373
+ if (data.type === "SM_CONSENT_SAVED") {
374
+ cleanup();
375
+ } else if (data.type === "SM_CONSENT_BRIDGE_READY") {
376
+ sendSet();
377
+ }
378
+ };
379
+ window.addEventListener("message", onMessage);
380
+ timer = window.setTimeout(cleanup, 2500);
381
+ try {
382
+ iframe = document.createElement("iframe");
383
+ iframe.src = hubUrl;
384
+ iframe.style.position = "absolute";
385
+ iframe.style.width = "0";
386
+ iframe.style.height = "0";
387
+ iframe.style.border = "0";
388
+ iframe.style.display = "none";
389
+ iframe.style.visibility = "hidden";
390
+ iframe.setAttribute("aria-hidden", "true");
391
+ iframe.setAttribute("tabindex", "-1");
392
+ iframe.onload = () => {
393
+ sendSet();
394
+ };
395
+ iframe.onerror = cleanup;
396
+ const target = document.body || document.documentElement;
397
+ target.appendChild(iframe);
398
+ } catch {
399
+ cleanup();
400
+ }
401
+ } catch {
402
+ }
403
+ }
160
404
  function hasConsented() {
161
405
  return getCookieConsent() !== null;
162
406
  }
@@ -204,6 +448,8 @@ function setCookieConsent(preferences, source = "settings_save") {
204
448
  window.localStorage?.setItem(COOKIE_CONSENT_KEY, serialized);
205
449
  } catch {
206
450
  }
451
+ const networkStatus = mergedPreferences.performance || mergedPreferences.advertising ? "accepted" : "rejected";
452
+ setNetworkConsentHub(networkStatus);
207
453
  window.dispatchEvent(new CustomEvent(COOKIE_CONSENT_EVENT, { detail: record }));
208
454
  }
209
455
  return record;
@@ -225,6 +471,7 @@ function clearCookieConsent() {
225
471
  window.localStorage?.removeItem(COOKIE_CONSENT_KEY);
226
472
  } catch {
227
473
  }
474
+ setNetworkConsentHub(null);
228
475
  window.dispatchEvent(new CustomEvent(COOKIE_CONSENT_EVENT, { detail: null }));
229
476
  }
230
477
  }
@@ -256,4 +503,4 @@ async function recordConsentToCompliance(record, options) {
256
503
  }
257
504
  }
258
505
 
259
- export { COOKIE_CATEGORIES, COOKIE_CONSENT_BACKUP_KEY, COOKIE_CONSENT_EVENT, COOKIE_CONSENT_KEY, COOKIE_CONSENT_MAX_AGE_SECONDS, DEFAULT_PREFERENCES_ACCEPTED, DEFAULT_PREFERENCES_REJECTED, acceptAllCookies, clearCookieConsent, getCookieConsent, hasConsented, isCategoryAllowed, recordConsentToCompliance, rejectOptionalCookies, setCookieConsent };
506
+ export { COOKIE_CATEGORIES, COOKIE_CONSENT_BACKUP_KEY, COOKIE_CONSENT_EVENT, COOKIE_CONSENT_KEY, COOKIE_CONSENT_MAX_AGE_SECONDS, DEFAULT_CONSENT_HUB_URL, DEFAULT_PREFERENCES_ACCEPTED, DEFAULT_PREFERENCES_REJECTED, EU_EEA_UK_COUNTRIES, NETWORK_CONSENT_STORAGE_KEY, acceptAllCookies, checkUrlConsentBridge, clearCookieConsent, decorateNetworkUrl, getCookieConsent, hasConsented, isCategoryAllowed, isGeoConsentRequired, queryNetworkConsentHub, recordConsentToCompliance, rejectOptionalCookies, setCookieConsent, setNetworkConsentHub };