@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 CHANGED
@@ -1,3 +1,93 @@
1
- # Temporary Holding Version
1
+ # @guidelytech/guide-runtime
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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 }`.