@syntrologie/adapt-overlays 2.18.0 → 2.20.0
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/cta-navigation.d.ts +38 -0
- package/dist/cta-navigation.d.ts.map +1 -0
- package/dist/modal.d.ts.map +1 -1
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +36 -2
- package/dist/runtime.js.map +3 -3
- package/dist/schema.d.ts +52 -20
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +37 -7
- package/dist/schema.js.map +2 -2
- package/package.json +1 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CTA navigation helper.
|
|
3
|
+
*
|
|
4
|
+
* Shared between modal and tooltip executors so the rules for "should this
|
|
5
|
+
* button navigate, and how" live in one place.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Returns true if the href is safe to pass to window.location.assign or
|
|
9
|
+
* window.open.
|
|
10
|
+
*
|
|
11
|
+
* Uses the URL parser rather than string prefix matching, because browsers
|
|
12
|
+
* strip embedded control characters (\\t, \\n, \\r, etc.) from schemes before
|
|
13
|
+
* resolving — so a naive `.trim().toLowerCase().startsWith('javascript:')`
|
|
14
|
+
* check is bypassed by inputs like `"java\\tscript:alert(1)"`. Running the
|
|
15
|
+
* input through `new URL()` first canonicalizes the scheme using the same
|
|
16
|
+
* algorithm the browser uses, then we check the resolved protocol against an
|
|
17
|
+
* allowlist (http/https/mailto/tel).
|
|
18
|
+
*
|
|
19
|
+
* This is defense-in-depth — the schema layer should already have rejected
|
|
20
|
+
* unsafe values via Zod regex + refine, but SDK consumers building configs
|
|
21
|
+
* outside the parser should still be safe at runtime.
|
|
22
|
+
*/
|
|
23
|
+
export declare function isSafeNavigationHref(href: string): boolean;
|
|
24
|
+
export interface NavigateCtaInput {
|
|
25
|
+
actionId: string;
|
|
26
|
+
href?: string;
|
|
27
|
+
target?: '_self' | '_blank';
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Navigate per the CTA's href/target. Returns true if a navigation was
|
|
31
|
+
* performed (caller can use this to decide whether to also destroy the
|
|
32
|
+
* overlay). Returns false for: missing href, dismiss action, or unsafe href.
|
|
33
|
+
*
|
|
34
|
+
* Callers should publish their telemetry event BEFORE calling this so a
|
|
35
|
+
* full-page navigation doesn't drop the click event in flight.
|
|
36
|
+
*/
|
|
37
|
+
export declare function navigateForCta(input: NavigateCtaInput): boolean;
|
|
38
|
+
//# sourceMappingURL=cta-navigation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cta-navigation.d.ts","sourceRoot":"","sources":["../src/cta-navigation.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAU1D;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAW/D"}
|
package/dist/modal.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../src/modal.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../src/modal.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAkB,WAAW,EAAE,MAAM,SAAS,CAAC;AAW3E;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,WAAW,CAwOpD,CAAC"}
|
package/dist/runtime.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAGvC,OAAO,KAAK,EACV,cAAc,EACd,WAAW,EAEX,eAAe,EACf,WAAW,EACX,aAAa,EACd,MAAM,SAAS,CAAC;AAIjB,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC;AAGrC,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAMvE;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,cAAc,CAAC,eAAe,CAsE5D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,WAAW,CA0GpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,cAAc,CAAC,WAAW,CAoGpD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,aAAa,CA4FxD,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;EAQZ,CAAC;AAEX;;GAEG;AACH,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkBnB,CAAC"}
|
package/dist/runtime.js
CHANGED
|
@@ -436,6 +436,30 @@ var executeCelebrate = async (action, context) => {
|
|
|
436
436
|
};
|
|
437
437
|
};
|
|
438
438
|
|
|
439
|
+
// src/cta-navigation.ts
|
|
440
|
+
var ALLOWED_PROTOCOLS = /* @__PURE__ */ new Set(["http:", "https:", "mailto:", "tel:"]);
|
|
441
|
+
function isSafeNavigationHref(href) {
|
|
442
|
+
if (typeof href !== "string" || href.trim().length === 0) return false;
|
|
443
|
+
let parsed;
|
|
444
|
+
try {
|
|
445
|
+
parsed = new URL(href, "https://syntro.local/");
|
|
446
|
+
} catch {
|
|
447
|
+
return false;
|
|
448
|
+
}
|
|
449
|
+
return ALLOWED_PROTOCOLS.has(parsed.protocol);
|
|
450
|
+
}
|
|
451
|
+
function navigateForCta(input) {
|
|
452
|
+
if (input.actionId === "dismiss") return false;
|
|
453
|
+
if (!input.href || !isSafeNavigationHref(input.href)) return false;
|
|
454
|
+
const href = input.href;
|
|
455
|
+
if (input.target === "_blank") {
|
|
456
|
+
window.open(href, "_blank", "noopener,noreferrer");
|
|
457
|
+
} else {
|
|
458
|
+
window.location.assign(href);
|
|
459
|
+
}
|
|
460
|
+
return true;
|
|
461
|
+
}
|
|
462
|
+
|
|
439
463
|
// src/executors/tour.ts
|
|
440
464
|
var ACTIVE_TOUR_KEY = "syntro_active_tour";
|
|
441
465
|
var activeTours = /* @__PURE__ */ new Map();
|
|
@@ -1416,10 +1440,16 @@ var executeModal = async (action, context) => {
|
|
|
1416
1440
|
const actionId = btn.getAttribute("data-syntro-action");
|
|
1417
1441
|
if (actionId) {
|
|
1418
1442
|
actionClicked = actionId;
|
|
1443
|
+
const matchingBtn = ctaButtons?.find((b) => b.actionId === actionId);
|
|
1444
|
+
const href = matchingBtn?.href;
|
|
1419
1445
|
context.publishEvent("action.modal_cta_clicked", {
|
|
1420
|
-
actionId
|
|
1446
|
+
actionId,
|
|
1447
|
+
...href ? { href } : {}
|
|
1421
1448
|
});
|
|
1422
1449
|
handle.destroy();
|
|
1450
|
+
if (matchingBtn) {
|
|
1451
|
+
navigateForCta(matchingBtn);
|
|
1452
|
+
}
|
|
1423
1453
|
}
|
|
1424
1454
|
};
|
|
1425
1455
|
actionBtns.forEach((btn) => btn.addEventListener("click", actionHandler));
|
|
@@ -2594,8 +2624,12 @@ var executeTooltip = async (action, context) => {
|
|
|
2594
2624
|
context.publishEvent("action.tooltip_cta_clicked", {
|
|
2595
2625
|
anchorId: action.anchorId,
|
|
2596
2626
|
actionId,
|
|
2597
|
-
label: clickedBtn.label
|
|
2627
|
+
label: clickedBtn.label,
|
|
2628
|
+
...clickedBtn.href ? { href: clickedBtn.href } : {}
|
|
2598
2629
|
});
|
|
2630
|
+
handle.destroy();
|
|
2631
|
+
navigateForCta(clickedBtn);
|
|
2632
|
+
return;
|
|
2599
2633
|
}
|
|
2600
2634
|
}
|
|
2601
2635
|
handle.destroy();
|