@guidelytech/guide-runtime 0.0.0-stage → 0.1.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/README.md +92 -2
- package/dist/index.cjs +2381 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +390 -0
- package/dist/index.d.ts +390 -0
- package/dist/index.js +2312 -0
- package/dist/index.js.map +1 -0
- package/package.json +59 -3
package/README.md
CHANGED
|
@@ -1,3 +1,93 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @guidelytech/guide-runtime
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Framework-free DOM engine used by the Guidely SDK and the dashboard editor: element resolution,
|
|
4
|
+
Shadow-DOM host and theming, step renderers (floating-ui positioning), the guide controller,
|
|
5
|
+
checklist / survey / resource-center widgets, an allowlist HTML sanitizer and the authoring picker.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @guidelytech/guide-runtime
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { runGuide } from "@guidelytech/guide-runtime";
|
|
13
|
+
|
|
14
|
+
const controller = runGuide(publishedGuide, {
|
|
15
|
+
theme: config.theme,
|
|
16
|
+
ctx: () => targetingContext,
|
|
17
|
+
onEvent: (e) => console.log(e.name, e.stepId),
|
|
18
|
+
onNavigate: (url) => router.push(url),
|
|
19
|
+
});
|
|
20
|
+
controller.start();
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Selectors
|
|
24
|
+
|
|
25
|
+
| Export | Description |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `resolveTarget(target \| selectors, root?)` | Tries strategies in order (`id`, `data-attr`, `aria`, `css`, `text`, `xpath`); a strategy wins only when it matches exactly one visible element. |
|
|
28
|
+
| `waitForTarget(target, { timeoutMs, signal, root, pollMs })` | MutationObserver + ≤250ms polling; rejects with `TargetTimeoutError` / `AbortError`. `timeoutMs: 0` waits forever. |
|
|
29
|
+
| `generateSelectors(el)` | Robust-first strategies for the picker: stable id (generated ids like `:r1:`, `radix-…`, long digit runs are skipped), `data-testid`/`data-tour`/`data-*`, `aria-label`, `name`/`role`, short unique CSS path (`nth-of-type` only when needed), `text` fallback for buttons/links/headings. |
|
|
30
|
+
| `describeElement(el)` | `{ selectors, textSnapshot, rect, tag }`. |
|
|
31
|
+
| `textSnapshotOf(el)`, `isVisible(el)`, `isStableId(id)`, `isGuidelyElement(el)`, `querySelectorStrategy(strategy, root)`, `normalizeText(text)`, `urlMatches(pattern, url)` | Helpers. |
|
|
32
|
+
|
|
33
|
+
## Host and theme
|
|
34
|
+
|
|
35
|
+
`ensureHost()` appends a single `<div id="guidely-root">` with an open shadow root containing all
|
|
36
|
+
styles (`:host{all:initial}`) and a polite live region. `createScope(theme, appearance)` creates a
|
|
37
|
+
themed container (`--g-primary`, `--g-bg`, `--g-text`, `--g-radius`, `--g-font`, `--g-z`,
|
|
38
|
+
`--g-overlay`; `data-theme="light|dark"`, `data-anim`). `auto` follows `prefers-color-scheme`;
|
|
39
|
+
`prefers-reduced-motion` disables animations. `resolveTheme`, `applyTheme`, `destroyHost`,
|
|
40
|
+
`DEFAULT_THEME`, `HOST_ID`, `STYLES` are also exported.
|
|
41
|
+
|
|
42
|
+
## Rendering
|
|
43
|
+
|
|
44
|
+
`renderStep({ scope, step, index, total, target, asModal, onButton, onClose, onOpen })` renders any
|
|
45
|
+
step type and returns `{ el, card, destroy }`:
|
|
46
|
+
|
|
47
|
+
* `modal` — centered card, optional overlay, `role="dialog" aria-modal`, Tab focus trap.
|
|
48
|
+
* `tooltip` / `popover` — anchored with floating-ui (`offset`, `flip`/`autoPlacement`, `shift`, `arrow`, `autoUpdate`), `role="tooltip"`, `aria-describedby` set on the target.
|
|
49
|
+
* `spotlight` — four-rect overlay with a cut-out around the target (target stays clickable) + ring + anchored card.
|
|
50
|
+
* `hotspot` — pulsing dot at the target's corner, opens the card on click or hover.
|
|
51
|
+
* `banner` — fixed top/bottom bar, `role="status"`.
|
|
52
|
+
* `slideout` — corner card. `custom` — sanitized `customHtml` only; elements with `data-g-action="next|back|dismiss|complete|skip"` act as buttons.
|
|
53
|
+
|
|
54
|
+
Chrome: close button (Escape when `showClose`), image, title, sanitized body, progress
|
|
55
|
+
("2 of 4"), buttons with `variant`s, focus moved into the card and restored on close, screen-reader
|
|
56
|
+
announcements, cards clamped to `100vw - 32px`, ≥40px touch targets.
|
|
57
|
+
|
|
58
|
+
`anchor(reference, floating, options)` and `trackRect(el, cb)` expose the positioning primitives.
|
|
59
|
+
|
|
60
|
+
## Controller
|
|
61
|
+
|
|
62
|
+
`runGuide(guide, options): GuideController` — options: `theme`, `ctx`, `onEvent`, `onNavigate`,
|
|
63
|
+
`onAction` (`start_guide` / `event` / `open_resource_center`), `onError`, `onEnd`, `eventBus`
|
|
64
|
+
(for `advanceOn: "event"`), `startAtStep`, `currentUrl`, `container`, `doc`.
|
|
65
|
+
|
|
66
|
+
Controller: `start()`, `next()`, `back()`, `goTo(stepId)`, `dismiss()`, `complete()`, `skip()`,
|
|
67
|
+
`resume()` (re-check a step waiting for its URL), `destroy()`, `getState()`.
|
|
68
|
+
|
|
69
|
+
Handles `advanceOn` (`button`, `element_click`, `element_visible`, `event`, `delay`, `any`),
|
|
70
|
+
branches (`evaluateRules(branch.when, ctx)` when leaving a step), step-level targeting, multi-page
|
|
71
|
+
steps (`step.url`), target waits with `skip` / `show_as_modal` / `end_guide` / `wait` fallbacks,
|
|
72
|
+
and emits `guide_viewed`, `guide_started`, `step_viewed`, `step_completed`, `guide_completed`,
|
|
73
|
+
`guide_skipped`, `guide_dismissed`. Rendering is wrapped in try/catch and reported via `onError`.
|
|
74
|
+
|
|
75
|
+
## Widgets
|
|
76
|
+
|
|
77
|
+
* `renderChecklist({ scope, config, progress, open, onTaskClick, onDismiss, onOpen, onClose })` → `{ open, close, toggle, isOpen, setProgress, destroy }`; `isChecklistComplete(config, progress)`.
|
|
78
|
+
* `renderSurvey({ scope, config, title, onSubmit, onDismiss, onChange })` → `{ getAnswers, showThankYou, destroy }`; `isQuestionVisible(question, answers)` evaluates `showWhen`.
|
|
79
|
+
* `renderResourceCenter({ scope, config, guides, search, onStartGuide, onOpenChecklist, onArticleView, onOpen, onClose, hideLauncher })` → `{ open, close, toggle, isOpen, destroy }`.
|
|
80
|
+
|
|
81
|
+
## Sanitizer
|
|
82
|
+
|
|
83
|
+
`sanitizeHtml(html)`, `sanitizeToFragment(html)`, `setSanitizedHtml(el, html)` — allowlist of
|
|
84
|
+
`p br strong b em i u a ul ol li img h1-h4 code pre blockquote span div hr button`, attributes
|
|
85
|
+
`href src alt title target rel class` (+ `data-g-action`/`data-g-value`), drops
|
|
86
|
+
`script/style/iframe/object/embed/form/input`, `on*` handlers, `javascript:`/`data:` URLs (except
|
|
87
|
+
`data:image/*` on `img`), forces `rel="noopener noreferrer"` on `target="_blank"`.
|
|
88
|
+
|
|
89
|
+
## Authoring
|
|
90
|
+
|
|
91
|
+
* `startAuthoring({ onPick, onExit, dashboardOrigin, message })` → `{ setStatus, setPicking, stop }` — toolbar, hover outline, capture-phase click-to-pick calling `onPick({ selectors, textSnapshot, rect, url, element })`.
|
|
92
|
+
* `previewStep(step, theme, { appearance, onEnd })` → `{ controller, destroy }`.
|
|
93
|
+
* `highlightSelectors(selectors, { durationMs })` → `{ counts, resolved, destroy }`.
|