@guidelytech/guide-runtime 0.10.0 → 0.12.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 +31 -0
- package/dist/capture.cjs.map +1 -1
- package/dist/capture.js +2 -2
- package/dist/chunk-H3CROHPR.js +585 -0
- package/dist/chunk-H3CROHPR.js.map +1 -0
- package/dist/chunk-VJSQM23R.js +359 -0
- package/dist/chunk-VJSQM23R.js.map +1 -0
- package/dist/chunk-VQJ7MZ2K.js +463 -0
- package/dist/chunk-VQJ7MZ2K.js.map +1 -0
- package/dist/index.cjs +282 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +19 -3
- package/dist/index.d.ts +19 -3
- package/dist/index.js +116 -11
- package/dist/index.js.map +1 -1
- package/dist/messenger.cjs +1326 -172
- package/dist/messenger.cjs.map +1 -1
- package/dist/messenger.d.cts +67 -5
- package/dist/messenger.d.ts +67 -5
- package/dist/messenger.js +1182 -100
- package/dist/messenger.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -44,9 +44,10 @@ __export(src_exports, {
|
|
|
44
44
|
generateSelectors: () => generateSelectors,
|
|
45
45
|
highlightSelectors: () => highlightSelectors,
|
|
46
46
|
isAnchoredStep: () => isAnchoredStep,
|
|
47
|
-
isChecklistComplete: () =>
|
|
47
|
+
isChecklistComplete: () => import_runtime7.isChecklistComplete,
|
|
48
48
|
isGuidelyElement: () => isGuidelyElement,
|
|
49
|
-
isQuestionVisible: () =>
|
|
49
|
+
isQuestionVisible: () => import_runtime8.isQuestionVisible,
|
|
50
|
+
isStableClass: () => isStableClass,
|
|
50
51
|
isStableId: () => isStableId,
|
|
51
52
|
isVisible: () => isVisible,
|
|
52
53
|
normalizeText: () => normalizeText,
|
|
@@ -619,6 +620,9 @@ function setSanitizedHtml(el2, html) {
|
|
|
619
620
|
}
|
|
620
621
|
|
|
621
622
|
// src/pdf-viewer.ts
|
|
623
|
+
var import_runtime5 = require("@guidelytech/shared/runtime");
|
|
624
|
+
|
|
625
|
+
// src/host.ts
|
|
622
626
|
var import_runtime4 = require("@guidelytech/shared/runtime");
|
|
623
627
|
|
|
624
628
|
// src/styles.ts
|
|
@@ -804,6 +808,21 @@ var STYLES = `
|
|
|
804
808
|
.g-auth-outline.g-picked .g-auth-label{background:#16a34a}
|
|
805
809
|
.g-highlight{position:fixed;z-index:calc(var(--g-z) + 8);pointer-events:none;border:2px dashed #f59e0b;background:rgba(245,158,11,.12);border-radius:4px}
|
|
806
810
|
@media (max-width:480px){.g-card.g-modal,.g-panel{width:calc(100vw - 32px)}.g-inner{padding:16px}}
|
|
811
|
+
/* resource center: unread badge + "What's new" */
|
|
812
|
+
.g-launcher-badge{position:absolute;top:-4px;right:-4px;min-width:20px;height:20px;padding:0 6px;border-radius:999px;background:#dc2626;color:#fff;font-size:11px;font-weight:700;line-height:20px;text-align:center;box-shadow:0 0 0 2px var(--g-bg)}
|
|
813
|
+
.g-rc-news{padding:10px 20px 12px;border-bottom:1px solid var(--g-border)}
|
|
814
|
+
.g-rc-news:last-of-type{border-bottom:0}
|
|
815
|
+
.g-rc-news-head{display:flex;align-items:baseline;gap:8px}
|
|
816
|
+
.g-rc-news-title{margin:0;font-size:14px;font-weight:600;line-height:1.35;flex:1}
|
|
817
|
+
.g-rc-news-new{flex:none;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--g-primary-text);background:var(--g-primary);border-radius:999px;padding:2px 7px}
|
|
818
|
+
.g-rc-news-date{display:block;font-size:12px;color:var(--g-muted);margin:2px 0 6px}
|
|
819
|
+
.g-rc-news-body{font-size:13px}
|
|
820
|
+
.g-rc-news-actions{display:flex;flex-wrap:wrap;gap:8px;margin-top:8px}
|
|
821
|
+
.g-rc-news-actions .g-btn{min-height:32px;padding:6px 12px;font-size:13px}
|
|
822
|
+
/* accessibility */
|
|
823
|
+
.g-sr-only{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
|
|
824
|
+
.g-hotspot:focus-visible,.g-custom:focus-visible,.g-card:focus-visible{outline:2px solid var(--g-primary);outline-offset:2px}
|
|
825
|
+
@media (forced-colors:active){.g-card,.g-panel,.g-banner{border:1px solid CanvasText}.g-btn{border:1px solid ButtonText}}
|
|
807
826
|
`;
|
|
808
827
|
|
|
809
828
|
// src/host.ts
|
|
@@ -898,6 +917,7 @@ function resolveTheme(theme, appearance) {
|
|
|
898
917
|
}
|
|
899
918
|
function applyTheme(el2, vars) {
|
|
900
919
|
el2.style.setProperty("--g-primary", vars.primary);
|
|
920
|
+
if (/^#[0-9a-f]{3}([0-9a-f]{3})?$/i.test(vars.primary)) el2.style.setProperty("--g-primary-text", (0, import_runtime4.readableTextOn)(vars.primary));
|
|
901
921
|
el2.style.setProperty("--g-bg", vars.bg);
|
|
902
922
|
el2.style.setProperty("--g-text", vars.text);
|
|
903
923
|
el2.style.setProperty("--g-radius", `${vars.radius}px`);
|
|
@@ -914,6 +934,16 @@ function createScope(theme, appearance, doc = document) {
|
|
|
914
934
|
const vars = resolveTheme(theme, appearance);
|
|
915
935
|
applyTheme(el2, vars);
|
|
916
936
|
handle.shadow.appendChild(el2);
|
|
937
|
+
const css = [appearance ? theme?.customCss : void 0, appearance?.customCss].filter((c) => !!c && !!c.trim());
|
|
938
|
+
let style = null;
|
|
939
|
+
if (css.length) {
|
|
940
|
+
const id = `c${++cssScopeSeq}`;
|
|
941
|
+
el2.setAttribute("data-g-css", id);
|
|
942
|
+
style = doc.createElement("style");
|
|
943
|
+
style.setAttribute("data-g-custom", id);
|
|
944
|
+
style.textContent = css.map((c) => (0, import_runtime4.scopeCustomCss)(c, `.g-scope[data-g-css="${id}"]`)).join("\n");
|
|
945
|
+
handle.shadow.insertBefore(style, el2);
|
|
946
|
+
}
|
|
917
947
|
let mq = null;
|
|
918
948
|
const onChange = () => applyTheme(el2, resolveTheme(theme, appearance));
|
|
919
949
|
if ((appearance?.theme ?? "auto") === "auto" && typeof window !== "undefined" && typeof window.matchMedia === "function") {
|
|
@@ -929,16 +959,18 @@ function createScope(theme, appearance, doc = document) {
|
|
|
929
959
|
vars,
|
|
930
960
|
destroy() {
|
|
931
961
|
mq?.removeEventListener?.("change", onChange);
|
|
962
|
+
style?.remove();
|
|
932
963
|
el2.remove();
|
|
933
964
|
}
|
|
934
965
|
};
|
|
935
966
|
}
|
|
967
|
+
var cssScopeSeq = 0;
|
|
936
968
|
|
|
937
969
|
// src/pdf-viewer.ts
|
|
938
970
|
function enhancePdfViewers(root, doc = root.ownerDocument) {
|
|
939
|
-
for (const block of Array.from(root.querySelectorAll(`div.${
|
|
940
|
-
const link = block.querySelector(`a.${
|
|
941
|
-
const strip = block.querySelector(`.${
|
|
971
|
+
for (const block of Array.from(root.querySelectorAll(`div.${import_runtime5.PDF_BLOCK_CLASS}`))) {
|
|
972
|
+
const link = block.querySelector(`a.${import_runtime5.FILE_LINK_CLASS}`);
|
|
973
|
+
const strip = block.querySelector(`.${import_runtime5.PDF_PAGES_CLASS}`);
|
|
942
974
|
if (!link || !strip || block.hasAttribute("data-g-ready")) continue;
|
|
943
975
|
for (const img of Array.from(strip.querySelectorAll("img:not([src])"))) img.remove();
|
|
944
976
|
const pages = Array.from(strip.querySelectorAll("img"));
|
|
@@ -1191,7 +1223,7 @@ function buildCard(doc, opts, extraClass) {
|
|
|
1191
1223
|
if (step.imageUrl) {
|
|
1192
1224
|
const img = h(doc, "img", "g-image");
|
|
1193
1225
|
img.src = step.imageUrl;
|
|
1194
|
-
img.alt = "";
|
|
1226
|
+
img.alt = step.imageAlt ?? "";
|
|
1195
1227
|
card.appendChild(img);
|
|
1196
1228
|
}
|
|
1197
1229
|
const inner = h(doc, "div", "g-inner");
|
|
@@ -1219,18 +1251,29 @@ function buildCard(doc, opts, extraClass) {
|
|
|
1219
1251
|
const buttons = buildButtons(doc, step, opts.canGoBack ?? opts.index > 0, opts.onButton);
|
|
1220
1252
|
if (buttons.length || step.showProgress && opts.total > 1) {
|
|
1221
1253
|
const footer = h(doc, "div", "g-footer");
|
|
1222
|
-
if (step.showProgress && opts.total > 1)
|
|
1254
|
+
if (step.showProgress && opts.total > 1) {
|
|
1255
|
+
const progress = h(doc, "span", "g-progress", `${opts.index + 1} of ${opts.total}`);
|
|
1256
|
+
progress.setAttribute("aria-label", `Step ${opts.index + 1} of ${opts.total}`);
|
|
1257
|
+
footer.appendChild(progress);
|
|
1258
|
+
}
|
|
1223
1259
|
buttons.forEach((b) => footer.appendChild(b));
|
|
1224
1260
|
inner.appendChild(footer);
|
|
1225
1261
|
}
|
|
1226
1262
|
card.appendChild(inner);
|
|
1227
1263
|
if (step.title) card.setAttribute("aria-labelledby", titleId);
|
|
1264
|
+
else card.setAttribute("aria-label", opts.total > 1 ? `Step ${opts.index + 1} of ${opts.total}` : "Guide");
|
|
1228
1265
|
if (step.body) card.setAttribute("aria-describedby", bodyId);
|
|
1229
1266
|
return { card, inner, titleId, bodyId };
|
|
1230
1267
|
}
|
|
1231
1268
|
function focusables(root) {
|
|
1232
1269
|
return Array.from(root.querySelectorAll(FOCUSABLE));
|
|
1233
1270
|
}
|
|
1271
|
+
function isTextEntry(el2) {
|
|
1272
|
+
const t = el2;
|
|
1273
|
+
if (!t || !t.tagName) return false;
|
|
1274
|
+
const tag = t.tagName.toLowerCase();
|
|
1275
|
+
return tag === "input" || tag === "textarea" || tag === "select" || t.isContentEditable === true;
|
|
1276
|
+
}
|
|
1234
1277
|
function installKeyboard(card, step, trap, onClose) {
|
|
1235
1278
|
const onKey = (e) => {
|
|
1236
1279
|
if (e.key === "Escape" && step.showClose) {
|
|
@@ -1238,6 +1281,16 @@ function installKeyboard(card, step, trap, onClose) {
|
|
|
1238
1281
|
onClose();
|
|
1239
1282
|
return;
|
|
1240
1283
|
}
|
|
1284
|
+
if ((e.key === "ArrowRight" || e.key === "ArrowLeft") && !e.altKey && !e.ctrlKey && !e.metaKey && !isTextEntry(e.target)) {
|
|
1285
|
+
const actions = e.key === "ArrowRight" ? ["next", "complete"] : ["back"];
|
|
1286
|
+
const btn = actions.map((a) => card.querySelector(`button[data-action="${a}"]`)).find(Boolean);
|
|
1287
|
+
if (btn) {
|
|
1288
|
+
e.preventDefault();
|
|
1289
|
+
e.stopPropagation();
|
|
1290
|
+
btn.click();
|
|
1291
|
+
}
|
|
1292
|
+
return;
|
|
1293
|
+
}
|
|
1241
1294
|
if (trap && e.key === "Tab") {
|
|
1242
1295
|
const items = focusables(card);
|
|
1243
1296
|
if (!items.length) {
|
|
@@ -1262,7 +1315,8 @@ function installKeyboard(card, step, trap, onClose) {
|
|
|
1262
1315
|
}
|
|
1263
1316
|
function focusInto(card) {
|
|
1264
1317
|
const doc = card.ownerDocument;
|
|
1265
|
-
const
|
|
1318
|
+
const active = doc.activeElement;
|
|
1319
|
+
const previous = active && active.id !== "guidely-root" ? active : null;
|
|
1266
1320
|
const primary = card.querySelector(".g-btn-primary") || focusables(card)[0] || card;
|
|
1267
1321
|
try {
|
|
1268
1322
|
primary.focus({ preventScroll: true });
|
|
@@ -1410,23 +1464,32 @@ function renderHotspot(doc, opts) {
|
|
|
1410
1464
|
let card = null;
|
|
1411
1465
|
let stopAnchor = null;
|
|
1412
1466
|
let stopKeys = null;
|
|
1413
|
-
const close = () => {
|
|
1467
|
+
const close = (returnFocus = false) => {
|
|
1468
|
+
const hadFocus = !!card && card.getRootNode().activeElement !== null && card.contains(card.getRootNode().activeElement);
|
|
1414
1469
|
stopAnchor?.();
|
|
1415
1470
|
stopKeys?.();
|
|
1416
1471
|
card?.remove();
|
|
1417
1472
|
card = null;
|
|
1418
1473
|
dot.setAttribute("aria-expanded", "false");
|
|
1474
|
+
if (returnFocus || hadFocus) {
|
|
1475
|
+
try {
|
|
1476
|
+
dot.focus({ preventScroll: true });
|
|
1477
|
+
} catch {
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1419
1480
|
};
|
|
1420
1481
|
const open = () => {
|
|
1421
1482
|
if (card) return;
|
|
1422
1483
|
const built = buildCard(doc, { ...opts, onClose: () => opts.onClose() }, "g-hotspot-card");
|
|
1423
1484
|
card = built.card;
|
|
1424
1485
|
card.setAttribute("role", "dialog");
|
|
1486
|
+
card.id = nextId("hotspot");
|
|
1487
|
+
dot.setAttribute("aria-controls", card.id);
|
|
1425
1488
|
const arrowEl = h(doc, "div", "g-arrow");
|
|
1426
1489
|
card.appendChild(arrowEl);
|
|
1427
1490
|
wrapper.appendChild(card);
|
|
1428
1491
|
stopAnchor = anchor(target, card, { placement: opts.step.placement, offset: opts.step.offset, arrowEl });
|
|
1429
|
-
stopKeys = installKeyboard(card, opts.step, false, close);
|
|
1492
|
+
stopKeys = installKeyboard(card, opts.step, false, () => close(true));
|
|
1430
1493
|
dot.setAttribute("aria-expanded", "true");
|
|
1431
1494
|
opts.onOpen?.();
|
|
1432
1495
|
if (cfg.openOn === "click") focusInto(card);
|
|
@@ -1448,7 +1511,8 @@ function renderBanner(doc, opts) {
|
|
|
1448
1511
|
const cleanups = [];
|
|
1449
1512
|
const pos = step.position === "top" || step.placement === "top" || step.position.startsWith("top") ? "top" : "bottom";
|
|
1450
1513
|
const banner = h(doc, "div", `g-banner g-pos-${pos}`);
|
|
1451
|
-
banner.setAttribute("role", "
|
|
1514
|
+
banner.setAttribute("role", "region");
|
|
1515
|
+
banner.setAttribute("aria-label", step.title || "Announcement");
|
|
1452
1516
|
banner.setAttribute("data-step-id", step.id);
|
|
1453
1517
|
const body = h(doc, "div", "g-body");
|
|
1454
1518
|
if (step.title) body.appendChild(h(doc, "strong", "", `${step.title} `));
|
|
@@ -1481,6 +1545,27 @@ function renderSlideout(doc, opts) {
|
|
|
1481
1545
|
cleanups.push(focusInto(card));
|
|
1482
1546
|
return { el: wrapper, card, destroy: () => cleanupAll(cleanups, wrapper) };
|
|
1483
1547
|
}
|
|
1548
|
+
function runCodeBlock(code, container, opts) {
|
|
1549
|
+
const act = (action) => () => opts.onButton({ id: `code-${action}`, label: action, action, variant: "primary" });
|
|
1550
|
+
const api = Object.freeze({ next: act("next"), back: act("back"), complete: act("complete"), skip: act("skip"), dismiss: () => opts.onClose(), stepId: opts.step.id });
|
|
1551
|
+
try {
|
|
1552
|
+
const fn = new Function("guidely", "container", `"use strict";
|
|
1553
|
+
${code}`);
|
|
1554
|
+
const result = fn(api, container);
|
|
1555
|
+
return typeof result === "function" ? () => {
|
|
1556
|
+
try {
|
|
1557
|
+
result();
|
|
1558
|
+
} catch (err) {
|
|
1559
|
+
opts.onError?.(err);
|
|
1560
|
+
}
|
|
1561
|
+
} : () => {
|
|
1562
|
+
};
|
|
1563
|
+
} catch (err) {
|
|
1564
|
+
opts.onError?.(err);
|
|
1565
|
+
return () => {
|
|
1566
|
+
};
|
|
1567
|
+
}
|
|
1568
|
+
}
|
|
1484
1569
|
function renderCustom(doc, opts) {
|
|
1485
1570
|
const cleanups = [];
|
|
1486
1571
|
const wrapper = h(doc, "div", "g-step");
|
|
@@ -1489,6 +1574,9 @@ function renderCustom(doc, opts) {
|
|
|
1489
1574
|
el2.tabIndex = -1;
|
|
1490
1575
|
el2.setAttribute("data-step-id", opts.step.id);
|
|
1491
1576
|
setSanitizedHtml(el2, opts.step.customHtml || opts.step.body || "");
|
|
1577
|
+
el2.setAttribute("role", opts.step.showOverlay ? "dialog" : "group");
|
|
1578
|
+
el2.setAttribute("aria-label", opts.step.title || "Guide");
|
|
1579
|
+
if (opts.step.showOverlay) el2.setAttribute("aria-modal", "true");
|
|
1492
1580
|
const onClick = (e) => {
|
|
1493
1581
|
const t = e.target?.closest?.("[data-g-action]");
|
|
1494
1582
|
const action = t?.getAttribute("data-g-action");
|
|
@@ -1502,6 +1590,7 @@ function renderCustom(doc, opts) {
|
|
|
1502
1590
|
opts.scope.appendChild(wrapper);
|
|
1503
1591
|
cleanups.push(installKeyboard(el2, opts.step, false, opts.onClose));
|
|
1504
1592
|
cleanups.push(focusInto(el2));
|
|
1593
|
+
if (opts.runCode && opts.step.code) cleanups.push(runCodeBlock(opts.step.code, el2, opts));
|
|
1505
1594
|
return { el: wrapper, card: el2, destroy: () => cleanupAll(cleanups, wrapper) };
|
|
1506
1595
|
}
|
|
1507
1596
|
function renderStep(opts) {
|
|
@@ -1534,7 +1623,7 @@ function isAnchoredStep(step) {
|
|
|
1534
1623
|
}
|
|
1535
1624
|
|
|
1536
1625
|
// src/controller.ts
|
|
1537
|
-
var
|
|
1626
|
+
var import_runtime6 = require("@guidelytech/shared/runtime");
|
|
1538
1627
|
function noop() {
|
|
1539
1628
|
}
|
|
1540
1629
|
var escapeHtml = (s) => s.replace(/[&<>"']/g, (c) => `&#${c.charCodeAt(0)};`);
|
|
@@ -1599,6 +1688,17 @@ function runGuide(guide, options = {}) {
|
|
|
1599
1688
|
view = null;
|
|
1600
1689
|
stepDone = false;
|
|
1601
1690
|
};
|
|
1691
|
+
let returnFocusTo = null;
|
|
1692
|
+
const restoreFocus = () => {
|
|
1693
|
+
const el2 = returnFocusTo;
|
|
1694
|
+
returnFocusTo = null;
|
|
1695
|
+
try {
|
|
1696
|
+
const now = doc.activeElement;
|
|
1697
|
+
const lost = !now || now === doc.body || now.id === "guidely-root";
|
|
1698
|
+
if (el2 && lost && el2.isConnected && typeof el2.focus === "function") el2.focus({ preventScroll: true });
|
|
1699
|
+
} catch {
|
|
1700
|
+
}
|
|
1701
|
+
};
|
|
1602
1702
|
const end = (reason) => {
|
|
1603
1703
|
if (ended) return;
|
|
1604
1704
|
ended = true;
|
|
@@ -1610,6 +1710,7 @@ function runGuide(guide, options = {}) {
|
|
|
1610
1710
|
else if (reason === "skipped") emit("guide_skipped", step, index);
|
|
1611
1711
|
scope?.destroy();
|
|
1612
1712
|
scope = null;
|
|
1713
|
+
restoreFocus();
|
|
1613
1714
|
try {
|
|
1614
1715
|
options.onEnd?.(reason);
|
|
1615
1716
|
} catch (err) {
|
|
@@ -1627,7 +1728,7 @@ function runGuide(guide, options = {}) {
|
|
|
1627
1728
|
const ctx = getCtx();
|
|
1628
1729
|
if (step && ctx) {
|
|
1629
1730
|
for (const branch of step.branches) {
|
|
1630
|
-
if ((0,
|
|
1731
|
+
if ((0, import_runtime6.evaluateRules)(branch.when, ctx)) {
|
|
1631
1732
|
target = steps.findIndex((s) => s.id === branch.goTo);
|
|
1632
1733
|
if (target >= 0) break;
|
|
1633
1734
|
}
|
|
@@ -1748,7 +1849,9 @@ function runGuide(guide, options = {}) {
|
|
|
1748
1849
|
asModal,
|
|
1749
1850
|
onButton: handleButton,
|
|
1750
1851
|
onClose: () => end("dismissed"),
|
|
1751
|
-
announce
|
|
1852
|
+
announce,
|
|
1853
|
+
runCode: options.runCode,
|
|
1854
|
+
onError
|
|
1752
1855
|
});
|
|
1753
1856
|
} catch (err) {
|
|
1754
1857
|
onError(err);
|
|
@@ -1818,7 +1921,7 @@ function runGuide(guide, options = {}) {
|
|
|
1818
1921
|
index = i;
|
|
1819
1922
|
const step = steps[i];
|
|
1820
1923
|
const ctx = getCtx();
|
|
1821
|
-
if (step.targeting && step.targeting.rules.length && ctx && !(0,
|
|
1924
|
+
if (step.targeting && step.targeting.rules.length && ctx && !(0, import_runtime6.evaluateRules)(step.targeting, ctx)) {
|
|
1822
1925
|
const nextIndex = i + direction;
|
|
1823
1926
|
if (nextIndex >= total) return end("completed");
|
|
1824
1927
|
if (nextIndex < 0) return;
|
|
@@ -1860,6 +1963,8 @@ function runGuide(guide, options = {}) {
|
|
|
1860
1963
|
guide,
|
|
1861
1964
|
start() {
|
|
1862
1965
|
if (status !== "idle") return;
|
|
1966
|
+
const focused = doc.activeElement;
|
|
1967
|
+
if (focused && focused !== doc.body && focused.id !== "guidely-root") returnFocusTo = focused;
|
|
1863
1968
|
emit("guide_viewed");
|
|
1864
1969
|
if (total === 0) return end("completed");
|
|
1865
1970
|
let startIndex = options.startAtStep ? steps.findIndex((s) => s.id === options.startAtStep) : 0;
|
|
@@ -1921,7 +2026,7 @@ function runGuide(guide, options = {}) {
|
|
|
1921
2026
|
}
|
|
1922
2027
|
|
|
1923
2028
|
// src/checklist.ts
|
|
1924
|
-
var
|
|
2029
|
+
var import_runtime7 = require("@guidelytech/shared/runtime");
|
|
1925
2030
|
function renderChecklist(options) {
|
|
1926
2031
|
const { scope, config } = options;
|
|
1927
2032
|
const doc = scope.ownerDocument;
|
|
@@ -1996,7 +2101,7 @@ function renderChecklist(options) {
|
|
|
1996
2101
|
bar.setAttribute("aria-valuemax", "100");
|
|
1997
2102
|
body.textContent = "";
|
|
1998
2103
|
foot.textContent = "";
|
|
1999
|
-
const complete = (0,
|
|
2104
|
+
const complete = (0, import_runtime7.isChecklistComplete)(config, progress);
|
|
2000
2105
|
if (complete) {
|
|
2001
2106
|
const wrap = doc.createElement("div");
|
|
2002
2107
|
wrap.className = "g-complete";
|
|
@@ -2084,7 +2189,7 @@ function renderChecklist(options) {
|
|
|
2084
2189
|
}
|
|
2085
2190
|
|
|
2086
2191
|
// src/survey.ts
|
|
2087
|
-
var
|
|
2192
|
+
var import_runtime8 = require("@guidelytech/shared/runtime");
|
|
2088
2193
|
function renderSurvey(options) {
|
|
2089
2194
|
const { scope, config } = options;
|
|
2090
2195
|
const doc = scope.ownerDocument;
|
|
@@ -2276,14 +2381,14 @@ function renderSurvey(options) {
|
|
|
2276
2381
|
config.questions.forEach((q) => {
|
|
2277
2382
|
const el2 = questionEls.get(q.id);
|
|
2278
2383
|
if (!el2) return;
|
|
2279
|
-
const visible = (0,
|
|
2384
|
+
const visible = (0, import_runtime8.isQuestionVisible)(q, answers);
|
|
2280
2385
|
el2.hidden = !visible;
|
|
2281
2386
|
if (!visible && answers[q.id] !== void 0) delete answers[q.id];
|
|
2282
2387
|
});
|
|
2283
2388
|
}
|
|
2284
2389
|
form.addEventListener("submit", (e) => {
|
|
2285
2390
|
e.preventDefault();
|
|
2286
|
-
const missing = config.questions.filter((q) => q.required && (0,
|
|
2391
|
+
const missing = config.questions.filter((q) => q.required && (0, import_runtime8.isQuestionVisible)(q, answers) && answers[q.id] === void 0);
|
|
2287
2392
|
if (missing.length) {
|
|
2288
2393
|
errorEl.textContent = `Please answer: ${missing.map((q) => q.title).join(", ")}`;
|
|
2289
2394
|
questionEls.get(missing[0].id)?.querySelector("button,textarea")?.focus();
|
|
@@ -2331,8 +2436,11 @@ function renderSurvey(options) {
|
|
|
2331
2436
|
};
|
|
2332
2437
|
}
|
|
2333
2438
|
|
|
2439
|
+
// src/resource-center.ts
|
|
2440
|
+
var import_runtime10 = require("@guidelytech/shared/runtime");
|
|
2441
|
+
|
|
2334
2442
|
// src/help-view.ts
|
|
2335
|
-
var
|
|
2443
|
+
var import_runtime9 = require("@guidelytech/shared/runtime");
|
|
2336
2444
|
var SHOW_ME_KINDS = /* @__PURE__ */ new Set(["flow", "modal", "tooltip", "announcement"]);
|
|
2337
2445
|
function startableGuide(guides, keyOrId) {
|
|
2338
2446
|
if (!keyOrId || !guides) return null;
|
|
@@ -2351,8 +2459,8 @@ function resultRow(doc, icon, title, summary, onOpen, showMe) {
|
|
|
2351
2459
|
return row;
|
|
2352
2460
|
}
|
|
2353
2461
|
function enhanceShowMe(root, doc, canStart, start) {
|
|
2354
|
-
for (const a of Array.from(root.querySelectorAll(`a[href^="${
|
|
2355
|
-
const key = (0,
|
|
2462
|
+
for (const a of Array.from(root.querySelectorAll(`a[href^="${import_runtime9.SHOW_ME_HREF_PREFIX}"]`))) {
|
|
2463
|
+
const key = (0, import_runtime9.showMeKeyFromHref)(a.getAttribute("href"));
|
|
2356
2464
|
const holder = a.closest("p.gd-show-me") ?? a;
|
|
2357
2465
|
if (!key || !canStart(key)) {
|
|
2358
2466
|
if (holder !== a) holder.remove();
|
|
@@ -2467,10 +2575,11 @@ function createHelpView(options) {
|
|
|
2467
2575
|
if (active) return renderArticle(active);
|
|
2468
2576
|
const data = options.data();
|
|
2469
2577
|
const member = options.audienceIds?.() ?? [];
|
|
2470
|
-
|
|
2578
|
+
searchWrap.hidden = !!data.modules && !data.modules.includes("search");
|
|
2579
|
+
const sections = (0, import_runtime9.resourceCenterSections)(data.collections, data.articles, member);
|
|
2471
2580
|
const q = query.trim().toLowerCase();
|
|
2472
2581
|
if (q) {
|
|
2473
|
-
const walkthroughs = (data.recommended ?? []).filter((g) => (0,
|
|
2582
|
+
const walkthroughs = (data.recommended ?? []).filter((g) => (0, import_runtime9.matchesHelpQuery)(g.name, q) && startableGuide(options.guides?.() ?? data.recommended, g.id));
|
|
2474
2583
|
if (walkthroughs.length) {
|
|
2475
2584
|
section(`Walkthroughs (${walkthroughs.length})`);
|
|
2476
2585
|
for (const g of walkthroughs) body.appendChild(resultRow(doc, "\u25B6", g.name, "Show me, step by step", () => options.onStartGuide?.(g.id)));
|
|
@@ -2479,10 +2588,10 @@ function createHelpView(options) {
|
|
|
2479
2588
|
body.append(...options.extra?.(q) ?? []);
|
|
2480
2589
|
if (q) {
|
|
2481
2590
|
const visible = sections.flatMap((s) => s.articles);
|
|
2482
|
-
const local = visible.filter((a) => (0,
|
|
2591
|
+
const local = visible.filter((a) => (0, import_runtime9.matchesHelpQuery)(`${a.title} ${a.summary}`, q));
|
|
2483
2592
|
const seen = new Set(local.map((a) => a.id));
|
|
2484
2593
|
const hidden = new Set(data.articles.map((a) => a.id).filter((id) => !visible.some((v) => v.id === id)));
|
|
2485
|
-
const merged = [...local, ...serverResults.filter((a) => !seen.has(a.id) && !hidden.has(a.id) && (0,
|
|
2594
|
+
const merged = [...local, ...serverResults.filter((a) => !seen.has(a.id) && !hidden.has(a.id) && (0, import_runtime9.isArticleListed)(data.collections, a, member))];
|
|
2486
2595
|
section(`Results (${merged.length})`);
|
|
2487
2596
|
if (!merged.length) body.appendChild(el(doc, "div", "g-rc-empty", "No articles match your search."));
|
|
2488
2597
|
merged.forEach(articleButton);
|
|
@@ -2497,55 +2606,124 @@ function createHelpView(options) {
|
|
|
2497
2606
|
body.appendChild(b);
|
|
2498
2607
|
});
|
|
2499
2608
|
}
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
for (const s of sections) {
|
|
2517
|
-
section(s.collection ? s.path.join(" \u203A ") : "Articles", s.depth);
|
|
2518
|
-
s.articles.forEach(articleButton);
|
|
2519
|
-
}
|
|
2520
|
-
if (data.faqs?.length) {
|
|
2521
|
-
section("FAQ");
|
|
2522
|
-
data.faqs.forEach((f) => {
|
|
2523
|
-
const b = listItem(doc, "?", f.question);
|
|
2524
|
-
b.setAttribute("aria-expanded", "false");
|
|
2525
|
-
const a = el(doc, "div", "g-faq-a");
|
|
2526
|
-
setSanitizedHtml(a, f.answer);
|
|
2527
|
-
a.hidden = true;
|
|
2528
|
-
b.addEventListener("click", () => {
|
|
2529
|
-
a.hidden = !a.hidden;
|
|
2530
|
-
b.setAttribute("aria-expanded", String(!a.hidden));
|
|
2609
|
+
const renderers = {
|
|
2610
|
+
search: () => {
|
|
2611
|
+
},
|
|
2612
|
+
announcements: () => {
|
|
2613
|
+
if (!data.announcements?.length) return;
|
|
2614
|
+
section(import_runtime9.RC_MODULE_LABELS.announcements);
|
|
2615
|
+
const seen = data.announcementsSeenAt ? Date.parse(data.announcementsSeenAt) : NaN;
|
|
2616
|
+
data.announcements.slice(0, 20).forEach((n) => body.appendChild(announcementItem(n, Number.isNaN(seen) || Date.parse(n.publishedAt) > seen)));
|
|
2617
|
+
},
|
|
2618
|
+
guides: () => {
|
|
2619
|
+
if (!data.recommended?.length) return;
|
|
2620
|
+
section("Recommended");
|
|
2621
|
+
data.recommended.forEach((g) => {
|
|
2622
|
+
const b = listItem(doc, "\u25B6", g.name, "Start guide");
|
|
2623
|
+
b.addEventListener("click", () => options.onStartGuide?.(g.id));
|
|
2624
|
+
body.appendChild(b);
|
|
2531
2625
|
});
|
|
2532
|
-
|
|
2533
|
-
|
|
2626
|
+
},
|
|
2627
|
+
checklists: () => {
|
|
2628
|
+
if (!data.checklists?.length) return;
|
|
2629
|
+
section("Checklists");
|
|
2630
|
+
data.checklists.forEach((g) => {
|
|
2631
|
+
const b = listItem(doc, "\u2611", g.name, "Open checklist");
|
|
2632
|
+
b.addEventListener("click", () => options.onOpenChecklist?.(g.id));
|
|
2633
|
+
body.appendChild(b);
|
|
2634
|
+
});
|
|
2635
|
+
},
|
|
2636
|
+
articles: () => {
|
|
2637
|
+
for (const s of sections) {
|
|
2638
|
+
section(s.collection ? s.path.join(" \u203A ") : "Articles", s.depth);
|
|
2639
|
+
s.articles.forEach(articleButton);
|
|
2640
|
+
}
|
|
2641
|
+
},
|
|
2642
|
+
faqs: () => {
|
|
2643
|
+
if (!data.faqs?.length) return;
|
|
2644
|
+
section("FAQ");
|
|
2645
|
+
data.faqs.forEach((f) => {
|
|
2646
|
+
const b = listItem(doc, "?", f.question);
|
|
2647
|
+
b.setAttribute("aria-expanded", "false");
|
|
2648
|
+
const a = el(doc, "div", "g-faq-a");
|
|
2649
|
+
a.id = `g-faq-${f.id}`;
|
|
2650
|
+
b.setAttribute("aria-controls", a.id);
|
|
2651
|
+
setSanitizedHtml(a, f.answer);
|
|
2652
|
+
a.hidden = true;
|
|
2653
|
+
b.addEventListener("click", () => {
|
|
2654
|
+
a.hidden = !a.hidden;
|
|
2655
|
+
b.setAttribute("aria-expanded", String(!a.hidden));
|
|
2656
|
+
});
|
|
2657
|
+
body.append(b, a);
|
|
2658
|
+
});
|
|
2659
|
+
},
|
|
2660
|
+
links: () => {
|
|
2661
|
+
if (!data.links?.length) return;
|
|
2662
|
+
section("Links");
|
|
2663
|
+
data.links.forEach((l) => {
|
|
2664
|
+
const a = el(doc, "a", "g-rc-item");
|
|
2665
|
+
a.href = l.url;
|
|
2666
|
+
a.target = "_blank";
|
|
2667
|
+
a.rel = "noopener noreferrer";
|
|
2668
|
+
const i = el(doc, "span", "g-rc-icon", "\u2197");
|
|
2669
|
+
i.setAttribute("aria-hidden", "true");
|
|
2670
|
+
a.append(i, el(doc, "span", "g-rc-title", l.label));
|
|
2671
|
+
a.setAttribute("aria-label", `${l.label} (opens in a new tab)`);
|
|
2672
|
+
body.appendChild(a);
|
|
2673
|
+
});
|
|
2674
|
+
}
|
|
2675
|
+
};
|
|
2676
|
+
for (const id of data.modules ?? import_runtime9.RC_MODULE_IDS) renderers[id]?.();
|
|
2677
|
+
if (!body.childNodes.length) body.appendChild(el(doc, "div", "g-rc-empty", "Nothing here yet."));
|
|
2678
|
+
}
|
|
2679
|
+
function announcementItem(n, unread) {
|
|
2680
|
+
const item = el(doc, "article", `g-rc-news${unread ? " g-rc-news-unread" : ""}`);
|
|
2681
|
+
const head = el(doc, "div", "g-rc-news-head");
|
|
2682
|
+
const title = el(doc, "h3", "g-rc-news-title", n.title);
|
|
2683
|
+
head.appendChild(title);
|
|
2684
|
+
if (unread) {
|
|
2685
|
+
const dot = el(doc, "span", "g-rc-news-new", "New");
|
|
2686
|
+
head.appendChild(dot);
|
|
2687
|
+
}
|
|
2688
|
+
const date = el(doc, "time", "g-rc-news-date");
|
|
2689
|
+
date.dateTime = n.publishedAt;
|
|
2690
|
+
try {
|
|
2691
|
+
date.textContent = new Date(n.publishedAt).toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
|
|
2692
|
+
} catch {
|
|
2693
|
+
date.textContent = n.publishedAt.slice(0, 10);
|
|
2694
|
+
}
|
|
2695
|
+
item.append(head, date);
|
|
2696
|
+
if (n.body) {
|
|
2697
|
+
const b = el(doc, "div", "g-body g-rc-news-body");
|
|
2698
|
+
setSanitizedHtml(b, n.body);
|
|
2699
|
+
item.appendChild(b);
|
|
2700
|
+
}
|
|
2701
|
+
const actions = el(doc, "div", "g-rc-news-actions");
|
|
2702
|
+
const guide = n.guideId ? startableGuide(options.guides?.(), n.guideId) : null;
|
|
2703
|
+
if (guide) {
|
|
2704
|
+
const b = el(doc, "button", "g-btn g-btn-primary", n.linkLabel || "Show me");
|
|
2705
|
+
b.type = "button";
|
|
2706
|
+
b.addEventListener("click", () => options.onShowMe ? options.onShowMe(guide.key) : options.onStartGuide?.(guide.id));
|
|
2707
|
+
actions.appendChild(b);
|
|
2708
|
+
}
|
|
2709
|
+
if (n.articleId) {
|
|
2710
|
+
const listed = options.data().articles.find((a) => a.id === n.articleId);
|
|
2711
|
+
if (listed) {
|
|
2712
|
+
const b = el(doc, "button", "g-btn g-btn-secondary", guide ? "Read more" : n.linkLabel || "Read more");
|
|
2713
|
+
b.type = "button";
|
|
2714
|
+
b.addEventListener("click", () => openArticle(listed));
|
|
2715
|
+
actions.appendChild(b);
|
|
2716
|
+
}
|
|
2534
2717
|
}
|
|
2535
|
-
if (
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
a.rel = "noopener noreferrer";
|
|
2542
|
-
const i = el(doc, "span", "g-rc-icon", "\u2197");
|
|
2543
|
-
i.setAttribute("aria-hidden", "true");
|
|
2544
|
-
a.append(i, el(doc, "span", "g-rc-title", l.label));
|
|
2545
|
-
body.appendChild(a);
|
|
2546
|
-
});
|
|
2718
|
+
if (n.url && /^https?:\/\//i.test(n.url)) {
|
|
2719
|
+
const a = el(doc, "a", "g-btn g-btn-link", !guide && !n.articleId && n.linkLabel ? n.linkLabel : "Learn more");
|
|
2720
|
+
a.href = n.url;
|
|
2721
|
+
a.target = "_blank";
|
|
2722
|
+
a.rel = "noopener noreferrer";
|
|
2723
|
+
actions.appendChild(a);
|
|
2547
2724
|
}
|
|
2548
|
-
if (
|
|
2725
|
+
if (actions.childNodes.length) item.appendChild(actions);
|
|
2726
|
+
return item;
|
|
2549
2727
|
}
|
|
2550
2728
|
let debounce = null;
|
|
2551
2729
|
const onInput = () => {
|
|
@@ -2617,6 +2795,19 @@ function renderResourceCenter(options) {
|
|
|
2617
2795
|
launcher.appendChild(el(doc, "span", "", config.launcher.label || config.title));
|
|
2618
2796
|
launcher.setAttribute("aria-label", config.launcher.label || config.title);
|
|
2619
2797
|
if (options.hideLauncher) launcher.hidden = true;
|
|
2798
|
+
const badge = el(doc, "span", "g-launcher-badge");
|
|
2799
|
+
badge.hidden = true;
|
|
2800
|
+
launcher.appendChild(badge);
|
|
2801
|
+
const modules = () => (0, import_runtime10.orderedModules)(config.modules).filter((m) => m.enabled && (!("targeting" in m) || !m.targeting || !options.evaluate || options.evaluate(m.targeting))).map((m) => m.id);
|
|
2802
|
+
const announcements = () => modules().includes("announcements") ? (0, import_runtime10.visibleAnnouncements)(config.announcements, options.audienceIds?.() ?? []) : [];
|
|
2803
|
+
const updateBadge = () => {
|
|
2804
|
+
const unread = (0, import_runtime10.unreadAnnouncements)(announcements(), options.announcementsSeenAt?.());
|
|
2805
|
+
badge.hidden = unread === 0;
|
|
2806
|
+
badge.textContent = unread > 9 ? "9+" : String(unread);
|
|
2807
|
+
const label = config.launcher.label || config.title;
|
|
2808
|
+
launcher.setAttribute("aria-label", unread ? `${label} (${unread} new update${unread === 1 ? "" : "s"})` : label);
|
|
2809
|
+
};
|
|
2810
|
+
updateBadge();
|
|
2620
2811
|
const panel = el(doc, "div", `g-panel ${pos}`);
|
|
2621
2812
|
panel.setAttribute("role", "dialog");
|
|
2622
2813
|
panel.setAttribute("aria-label", config.title);
|
|
@@ -2627,9 +2818,20 @@ function renderResourceCenter(options) {
|
|
|
2627
2818
|
close.type = "button";
|
|
2628
2819
|
close.setAttribute("aria-label", "Close");
|
|
2629
2820
|
head.appendChild(close);
|
|
2821
|
+
let seenAtOpen = options.announcementsSeenAt?.() ?? null;
|
|
2630
2822
|
const help = createHelpView({
|
|
2631
2823
|
doc,
|
|
2632
|
-
data: () => ({
|
|
2824
|
+
data: () => ({
|
|
2825
|
+
collections: config.collections,
|
|
2826
|
+
articles: config.articles,
|
|
2827
|
+
recommended: byId(config.recommendedGuideIds),
|
|
2828
|
+
checklists: byId(config.checklistGuideIds),
|
|
2829
|
+
faqs: config.faqs,
|
|
2830
|
+
links: config.links,
|
|
2831
|
+
announcements: announcements(),
|
|
2832
|
+
announcementsSeenAt: seenAtOpen,
|
|
2833
|
+
modules: modules()
|
|
2834
|
+
}),
|
|
2633
2835
|
search: options.search,
|
|
2634
2836
|
audienceIds: options.audienceIds,
|
|
2635
2837
|
loadArticle: options.loadArticle,
|
|
@@ -2653,8 +2855,13 @@ function renderResourceCenter(options) {
|
|
|
2653
2855
|
panel.hidden = !v;
|
|
2654
2856
|
launcher.setAttribute("aria-expanded", String(v));
|
|
2655
2857
|
if (v) {
|
|
2858
|
+
seenAtOpen = options.announcementsSeenAt?.() ?? null;
|
|
2656
2859
|
help.render();
|
|
2657
2860
|
help.focusSearch();
|
|
2861
|
+
if (announcements().length) {
|
|
2862
|
+
options.onAnnouncementsSeen?.();
|
|
2863
|
+
updateBadge();
|
|
2864
|
+
}
|
|
2658
2865
|
options.onOpen?.();
|
|
2659
2866
|
} else {
|
|
2660
2867
|
help.reset();
|
|
@@ -2892,6 +3099,7 @@ function highlightSelectors(selectors, options = {}) {
|
|
|
2892
3099
|
isChecklistComplete,
|
|
2893
3100
|
isGuidelyElement,
|
|
2894
3101
|
isQuestionVisible,
|
|
3102
|
+
isStableClass,
|
|
2895
3103
|
isStableId,
|
|
2896
3104
|
isVisible,
|
|
2897
3105
|
normalizeText,
|