@guidelytech/guide-runtime 0.8.0 → 0.10.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/capture.cjs +160 -34
- package/dist/capture.cjs.map +1 -1
- package/dist/capture.js +9 -14
- package/dist/capture.js.map +1 -1
- package/dist/chunk-GUH2PQJ7.js +462 -0
- package/dist/chunk-GUH2PQJ7.js.map +1 -0
- package/dist/chunk-KJRXCITD.js +515 -0
- package/dist/chunk-KJRXCITD.js.map +1 -0
- package/dist/chunk-PG7CMBHD.js +330 -0
- package/dist/chunk-PG7CMBHD.js.map +1 -0
- package/dist/chunk-VNJPNGZ4.js +301 -0
- package/dist/chunk-VNJPNGZ4.js.map +1 -0
- package/dist/index.cjs +356 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +62 -8
- package/dist/index.d.ts +62 -8
- package/dist/index.js +107 -23
- package/dist/index.js.map +1 -1
- package/dist/messenger.cjs +586 -35
- package/dist/messenger.cjs.map +1 -1
- package/dist/messenger.d.cts +21 -1
- package/dist/messenger.d.ts +21 -1
- package/dist/messenger.js +527 -23
- package/dist/messenger.js.map +1 -1
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -5,9 +5,16 @@ import {
|
|
|
5
5
|
sanitizeHtml,
|
|
6
6
|
sanitizeToFragment,
|
|
7
7
|
setSanitizedHtml
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-KJRXCITD.js";
|
|
9
9
|
import {
|
|
10
|
+
SHADOW_SEPARATOR,
|
|
10
11
|
TargetTimeoutError,
|
|
12
|
+
closestComposed,
|
|
13
|
+
componentAnchor,
|
|
14
|
+
composedParent,
|
|
15
|
+
composedTarget,
|
|
16
|
+
containsComposed,
|
|
17
|
+
deepElementFromPoint,
|
|
11
18
|
describeElement,
|
|
12
19
|
generateSelectors,
|
|
13
20
|
isGuidelyElement,
|
|
@@ -16,10 +23,12 @@ import {
|
|
|
16
23
|
normalizeText,
|
|
17
24
|
querySelectorStrategy,
|
|
18
25
|
resolveTarget,
|
|
26
|
+
shadowHostChain,
|
|
19
27
|
textSnapshotOf,
|
|
20
28
|
urlMatches,
|
|
29
|
+
visualRect,
|
|
21
30
|
waitForTarget
|
|
22
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-GUH2PQJ7.js";
|
|
23
32
|
import {
|
|
24
33
|
DEFAULT_THEME,
|
|
25
34
|
HOST_ID,
|
|
@@ -30,11 +39,12 @@ import {
|
|
|
30
39
|
ensureHost,
|
|
31
40
|
prefersReducedMotion,
|
|
32
41
|
resolveTheme
|
|
33
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-PG7CMBHD.js";
|
|
34
43
|
|
|
35
44
|
// src/position.ts
|
|
36
45
|
import { arrow, autoPlacement, autoUpdate, computePosition, flip, offset, shift } from "@floating-ui/dom";
|
|
37
|
-
function anchor(
|
|
46
|
+
function anchor(target, floating, options = {}) {
|
|
47
|
+
const reference = target.shadowRoot ? { getBoundingClientRect: () => visualRect(target), contextElement: target } : target;
|
|
38
48
|
const placement = options.placement ?? "auto";
|
|
39
49
|
const gap = options.offset ?? 10;
|
|
40
50
|
const middleware = [offset(gap + (options.arrowEl ? 4 : 0))];
|
|
@@ -87,7 +97,7 @@ function trackRect(el2, cb) {
|
|
|
87
97
|
let stopped = false;
|
|
88
98
|
const run = () => {
|
|
89
99
|
if (stopped) return;
|
|
90
|
-
cb(el2
|
|
100
|
+
cb(visualRect(el2));
|
|
91
101
|
};
|
|
92
102
|
const schedule = () => {
|
|
93
103
|
if (stopped) return;
|
|
@@ -100,6 +110,9 @@ function trackRect(el2, cb) {
|
|
|
100
110
|
const win = el2.ownerDocument.defaultView;
|
|
101
111
|
win?.addEventListener("scroll", schedule, true);
|
|
102
112
|
win?.addEventListener("resize", schedule);
|
|
113
|
+
const shadowRoots = [];
|
|
114
|
+
for (let root = el2.getRootNode(); root.nodeType === 11 && root.host; root = root.host.getRootNode()) shadowRoots.push(root);
|
|
115
|
+
for (const root of shadowRoots) root.addEventListener("scroll", schedule, true);
|
|
103
116
|
let ro = null;
|
|
104
117
|
if (typeof ResizeObserver !== "undefined") {
|
|
105
118
|
try {
|
|
@@ -115,6 +128,7 @@ function trackRect(el2, cb) {
|
|
|
115
128
|
stopped = true;
|
|
116
129
|
win?.removeEventListener("scroll", schedule, true);
|
|
117
130
|
win?.removeEventListener("resize", schedule);
|
|
131
|
+
for (const root of shadowRoots) root.removeEventListener("scroll", schedule, true);
|
|
118
132
|
ro?.disconnect();
|
|
119
133
|
clearInterval(interval);
|
|
120
134
|
if (typeof cancelAnimationFrame === "function") cancelAnimationFrame(raf);
|
|
@@ -501,6 +515,17 @@ function isAnchoredStep(step) {
|
|
|
501
515
|
import { evaluateRules } from "@guidelytech/shared/runtime";
|
|
502
516
|
function noop() {
|
|
503
517
|
}
|
|
518
|
+
var escapeHtml = (s) => s.replace(/[&<>"']/g, (c) => `&#${c.charCodeAt(0)};`);
|
|
519
|
+
function navigableUrl(pattern) {
|
|
520
|
+
if (!pattern || /[*?#\s]/.test(pattern) || pattern.includes("/:")) return null;
|
|
521
|
+
if (pattern.startsWith("/") && !pattern.startsWith("//")) return pattern;
|
|
522
|
+
try {
|
|
523
|
+
const u = new URL(pattern);
|
|
524
|
+
if (typeof location !== "undefined" && u.origin === location.origin) return u.pathname;
|
|
525
|
+
} catch {
|
|
526
|
+
}
|
|
527
|
+
return null;
|
|
528
|
+
}
|
|
504
529
|
function runGuide(guide, options = {}) {
|
|
505
530
|
const doc = options.doc ?? (options.container?.ownerDocument || document);
|
|
506
531
|
const steps = guide.config.steps;
|
|
@@ -645,15 +670,15 @@ function runGuide(guide, options = {}) {
|
|
|
645
670
|
onError(err);
|
|
646
671
|
}
|
|
647
672
|
};
|
|
648
|
-
const setupAdvance = (step) => {
|
|
673
|
+
const setupAdvance = (step, target) => {
|
|
649
674
|
const modes = step.advanceOn === "any" ? ["element_click", "element_visible", "event", "delay"] : [step.advanceOn];
|
|
650
675
|
for (const mode of modes) {
|
|
651
|
-
if (mode === "element_click" && step.advanceValue) {
|
|
676
|
+
if (mode === "element_click" && (step.advanceValue || target)) {
|
|
652
677
|
const selector = step.advanceValue;
|
|
653
678
|
const handler = (e) => {
|
|
654
|
-
const t = e
|
|
679
|
+
const t = composedTarget(e);
|
|
655
680
|
try {
|
|
656
|
-
if (t &&
|
|
681
|
+
if (selector ? t && closestComposed(t, selector) : t && target && containsComposed(target, t)) advance();
|
|
657
682
|
} catch {
|
|
658
683
|
}
|
|
659
684
|
};
|
|
@@ -689,10 +714,11 @@ function runGuide(guide, options = {}) {
|
|
|
689
714
|
const render = (step, target, asModal = false) => {
|
|
690
715
|
if (ended) return;
|
|
691
716
|
status = "running";
|
|
717
|
+
const shown = !target && step.advanceOn === "element_click" && !step.advanceValue && !step.buttons.length ? { ...step, buttons: [{ id: "g-next", label: index + 1 >= total ? "Done" : "Next", action: index + 1 >= total ? "complete" : "next", variant: "primary" }] } : step;
|
|
692
718
|
try {
|
|
693
719
|
view = renderStep({
|
|
694
720
|
scope: getScope(),
|
|
695
|
-
step,
|
|
721
|
+
step: shown,
|
|
696
722
|
index,
|
|
697
723
|
total,
|
|
698
724
|
canGoBack: history.length > 0 || index > 0,
|
|
@@ -714,7 +740,43 @@ function runGuide(guide, options = {}) {
|
|
|
714
740
|
}
|
|
715
741
|
emit("step_viewed", step, index, asModal ? { fallback: "show_as_modal" } : void 0);
|
|
716
742
|
announce(step.title ? `${step.title}. Step ${index + 1} of ${total}` : `Step ${index + 1} of ${total}`);
|
|
717
|
-
setupAdvance(step);
|
|
743
|
+
setupAdvance(step, target);
|
|
744
|
+
};
|
|
745
|
+
const showUrlPrompt = (step) => {
|
|
746
|
+
if (ended || status !== "waiting_url" || view) return;
|
|
747
|
+
const href = navigableUrl(step.url);
|
|
748
|
+
const where = (step.url ?? "").replace(/^https?:\/\/[^/]+/i, "") || "another page";
|
|
749
|
+
const prompt = {
|
|
750
|
+
...step,
|
|
751
|
+
type: "modal",
|
|
752
|
+
title: "Continue on another page",
|
|
753
|
+
body: `<p>The next step${step.title ? `, <strong>${escapeHtml(step.title)}</strong>,` : ""} is on <code>${escapeHtml(where)}</code>.</p>`,
|
|
754
|
+
imageUrl: "",
|
|
755
|
+
buttons: [
|
|
756
|
+
...href ? [{ id: "g-go", label: "Take me there", action: "url", value: href, variant: "primary" }] : [],
|
|
757
|
+
{ id: "g-exit", label: "Exit", action: "dismiss", variant: href ? "secondary" : "primary" }
|
|
758
|
+
]
|
|
759
|
+
};
|
|
760
|
+
try {
|
|
761
|
+
view = renderStep({
|
|
762
|
+
scope: getScope(),
|
|
763
|
+
step: prompt,
|
|
764
|
+
index,
|
|
765
|
+
total,
|
|
766
|
+
canGoBack: false,
|
|
767
|
+
target: null,
|
|
768
|
+
asModal: true,
|
|
769
|
+
onButton: (b) => {
|
|
770
|
+
if (b.action !== "url" || !b.value) return end("dismissed");
|
|
771
|
+
if (options.onNavigate) options.onNavigate(b.value);
|
|
772
|
+
else location.assign(b.value);
|
|
773
|
+
},
|
|
774
|
+
onClose: () => end("dismissed"),
|
|
775
|
+
announce
|
|
776
|
+
});
|
|
777
|
+
} catch (err) {
|
|
778
|
+
onError(err);
|
|
779
|
+
}
|
|
718
780
|
};
|
|
719
781
|
const applyFallback = (step, direction) => {
|
|
720
782
|
const fallback = step.target?.fallback ?? "skip";
|
|
@@ -740,9 +802,18 @@ function runGuide(guide, options = {}) {
|
|
|
740
802
|
if (nextIndex < 0) return;
|
|
741
803
|
return showStep(nextIndex, direction);
|
|
742
804
|
}
|
|
805
|
+
try {
|
|
806
|
+
options.onPosition?.(step.id);
|
|
807
|
+
} catch (err) {
|
|
808
|
+
onError(err);
|
|
809
|
+
}
|
|
743
810
|
if (step.url && !urlMatches(step.url, currentUrl())) {
|
|
744
811
|
status = "waiting_url";
|
|
745
812
|
pendingIndex = i;
|
|
813
|
+
if (options.promptForUrl) {
|
|
814
|
+
const t = setTimeout(() => showUrlPrompt(step), options.urlPromptDelayMs ?? 1200);
|
|
815
|
+
stepCleanups.push(() => clearTimeout(t));
|
|
816
|
+
}
|
|
746
817
|
return;
|
|
747
818
|
}
|
|
748
819
|
pendingIndex = -1;
|
|
@@ -1276,7 +1347,14 @@ function renderResourceCenter(options) {
|
|
|
1276
1347
|
loadArticle: options.loadArticle,
|
|
1277
1348
|
onStartGuide: options.onStartGuide,
|
|
1278
1349
|
onOpenChecklist: options.onOpenChecklist,
|
|
1279
|
-
onArticleView: options.onArticleView
|
|
1350
|
+
onArticleView: options.onArticleView,
|
|
1351
|
+
guides: () => guides,
|
|
1352
|
+
onShowMe: (key) => {
|
|
1353
|
+
setOpen(false);
|
|
1354
|
+
options.onStartGuide?.(key);
|
|
1355
|
+
},
|
|
1356
|
+
// Articles read in a larger panel.
|
|
1357
|
+
onArticleChange: (reading) => panel.classList.toggle("g-panel-reading", reading)
|
|
1280
1358
|
});
|
|
1281
1359
|
panel.append(head, help.el);
|
|
1282
1360
|
root.append(launcher, panel);
|
|
@@ -1365,7 +1443,7 @@ function startAuthoring(options) {
|
|
|
1365
1443
|
outline.hidden = true;
|
|
1366
1444
|
return;
|
|
1367
1445
|
}
|
|
1368
|
-
const r = el2
|
|
1446
|
+
const r = visualRect(el2);
|
|
1369
1447
|
outline.hidden = false;
|
|
1370
1448
|
outline.classList.toggle("g-picked", picked);
|
|
1371
1449
|
Object.assign(outline.style, { left: `${r.left}px`, top: `${r.top}px`, width: `${r.width}px`, height: `${r.height}px` });
|
|
@@ -1373,9 +1451,9 @@ function startAuthoring(options) {
|
|
|
1373
1451
|
label.style.top = r.top < 30 ? "100%" : "-24px";
|
|
1374
1452
|
};
|
|
1375
1453
|
const elementAt = (x, y) => {
|
|
1376
|
-
const el2 = doc
|
|
1454
|
+
const el2 = deepElementFromPoint(doc, x, y);
|
|
1377
1455
|
if (!el2 || isGuidelyElement(el2) || el2 === doc.documentElement || el2 === doc.body) return null;
|
|
1378
|
-
return el2;
|
|
1456
|
+
return componentAnchor(el2);
|
|
1379
1457
|
};
|
|
1380
1458
|
const onMove = (e) => {
|
|
1381
1459
|
if (!picking || stopped) return;
|
|
@@ -1390,7 +1468,7 @@ function startAuthoring(options) {
|
|
|
1390
1468
|
};
|
|
1391
1469
|
const onClick = (e) => {
|
|
1392
1470
|
if (!picking || stopped) return;
|
|
1393
|
-
if (
|
|
1471
|
+
if (isGuidelyElement(composedTarget(e))) return;
|
|
1394
1472
|
const el2 = elementAt(e.clientX, e.clientY) ?? hovered;
|
|
1395
1473
|
if (!el2) return;
|
|
1396
1474
|
e.preventDefault();
|
|
@@ -1403,8 +1481,7 @@ function startAuthoring(options) {
|
|
|
1403
1481
|
};
|
|
1404
1482
|
const swallow = (e) => {
|
|
1405
1483
|
if (!picking || stopped) return;
|
|
1406
|
-
|
|
1407
|
-
if (t && isGuidelyElement(t)) return;
|
|
1484
|
+
if (isGuidelyElement(composedTarget(e))) return;
|
|
1408
1485
|
e.preventDefault();
|
|
1409
1486
|
e.stopPropagation();
|
|
1410
1487
|
};
|
|
@@ -1462,7 +1539,7 @@ function previewStep(step, theme, options = {}) {
|
|
|
1462
1539
|
name: "Preview",
|
|
1463
1540
|
kind: "flow",
|
|
1464
1541
|
version: 0,
|
|
1465
|
-
config: { steps: [previewStepConfig], targeting: { id: "root", op: "and", rules: [] }, trigger: { type: "manual", delayMs: 0 }, frequency: { mode: "every_time", cooldownHours: 0, priority: 0, mutuallyExclusiveWith: [], reshowAfterDismiss: true }, appearance: options.appearance ?? { theme: "auto", animation: "fade" }, urlPatterns: [], platforms: ["web"] }
|
|
1542
|
+
config: { steps: [previewStepConfig], visibility: "everyone", targeting: { id: "root", op: "and", rules: [] }, trigger: { type: "manual", delayMs: 0 }, frequency: { mode: "every_time", cooldownHours: 0, priority: 0, mutuallyExclusiveWith: [], reshowAfterDismiss: true }, appearance: options.appearance ?? { theme: "auto", animation: "fade" }, urlPatterns: [], platforms: ["web"] }
|
|
1466
1543
|
};
|
|
1467
1544
|
const controller = runGuide(guide, { theme, doc: options.doc, onEnd: () => options.onEnd?.(), onNavigate: () => {
|
|
1468
1545
|
}, onAction: () => {
|
|
@@ -1475,17 +1552,15 @@ function highlightSelectors(selectors, options = {}) {
|
|
|
1475
1552
|
const scope = createScope(null, { theme: "light", animation: "none" }, doc);
|
|
1476
1553
|
const boxes = [];
|
|
1477
1554
|
const counts = [];
|
|
1478
|
-
|
|
1555
|
+
const resolved = resolveTarget(selectors, doc);
|
|
1479
1556
|
const matched = /* @__PURE__ */ new Set();
|
|
1480
1557
|
selectors.forEach((s) => {
|
|
1481
1558
|
const els = querySelectorStrategy(s, doc).filter((el2) => !isGuidelyElement(el2));
|
|
1482
|
-
const visible = els.filter(isVisible);
|
|
1483
1559
|
counts.push(els.length);
|
|
1484
|
-
if (!resolved && visible.length === 1) resolved = visible[0];
|
|
1485
1560
|
els.forEach((el2) => matched.add(el2));
|
|
1486
1561
|
});
|
|
1487
1562
|
matched.forEach((el2) => {
|
|
1488
|
-
const r = el2
|
|
1563
|
+
const r = visualRect(el2);
|
|
1489
1564
|
const box = doc.createElement("div");
|
|
1490
1565
|
box.className = "g-highlight";
|
|
1491
1566
|
Object.assign(box.style, { left: `${r.left}px`, top: `${r.top}px`, width: `${r.width}px`, height: `${r.height}px` });
|
|
@@ -1505,12 +1580,19 @@ function highlightSelectors(selectors, options = {}) {
|
|
|
1505
1580
|
export {
|
|
1506
1581
|
DEFAULT_THEME,
|
|
1507
1582
|
HOST_ID,
|
|
1583
|
+
SHADOW_SEPARATOR,
|
|
1508
1584
|
STYLES,
|
|
1509
1585
|
TargetTimeoutError,
|
|
1510
1586
|
anchor,
|
|
1511
1587
|
applyTheme,
|
|
1512
1588
|
buildCard,
|
|
1589
|
+
closestComposed,
|
|
1590
|
+
componentAnchor,
|
|
1591
|
+
composedParent,
|
|
1592
|
+
composedTarget,
|
|
1593
|
+
containsComposed,
|
|
1513
1594
|
createScope,
|
|
1595
|
+
deepElementFromPoint,
|
|
1514
1596
|
describeElement,
|
|
1515
1597
|
destroyHost,
|
|
1516
1598
|
enhancePdfViewers,
|
|
@@ -1544,10 +1626,12 @@ export {
|
|
|
1544
1626
|
sanitizeHtml,
|
|
1545
1627
|
sanitizeToFragment,
|
|
1546
1628
|
setSanitizedHtml,
|
|
1629
|
+
shadowHostChain,
|
|
1547
1630
|
startAuthoring,
|
|
1548
1631
|
textSnapshotOf,
|
|
1549
1632
|
trackRect,
|
|
1550
1633
|
urlMatches,
|
|
1634
|
+
visualRect,
|
|
1551
1635
|
waitForTarget
|
|
1552
1636
|
};
|
|
1553
1637
|
//# sourceMappingURL=index.js.map
|