@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/dist/index.d.cts
ADDED
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
import { SelectorStrategy, StepTarget, ProjectTheme, Appearance, Placement, GuideStep, StepButton, GuideKind, GuideConfig, TargetingContext, EventName, ChecklistConfig, ChecklistTask, SurveyConfig, SurveyQuestion, ResourceCenterConfig, ResourceCenterArticle, AuthoringPick } from '@guidelytech/shared';
|
|
2
|
+
import { Placement as Placement$1 } from '@floating-ui/dom';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* URL matching used for `step.url`, `urlPatterns` and `trigger.urlPattern`: a pattern matches the
|
|
6
|
+
* full URL, the path+query+hash, or the bare path (so `/deals` also matches `/deals?x=1`).
|
|
7
|
+
*/
|
|
8
|
+
declare function urlMatches(pattern: string | undefined | null, url: string): boolean;
|
|
9
|
+
type QueryRoot = Document | DocumentFragment | Element;
|
|
10
|
+
/** Normalises whitespace in a text snippet. */
|
|
11
|
+
declare function normalizeText(text: string | null | undefined): string;
|
|
12
|
+
/** Is the element rendered (not hidden by `hidden`, `display:none`, `visibility:hidden`, or zero size)? */
|
|
13
|
+
declare function isVisible(el: Element): boolean;
|
|
14
|
+
/** Elements that belong to Guidely's own UI are never valid targets. */
|
|
15
|
+
declare function isGuidelyElement(el: Element | null): boolean;
|
|
16
|
+
/** Resolves every element matching one strategy (visible or not). */
|
|
17
|
+
declare function querySelectorStrategy(strategy: SelectorStrategy, root: QueryRoot): Element[];
|
|
18
|
+
/**
|
|
19
|
+
* Resolves a step target by trying each strategy in order. A strategy wins only when it
|
|
20
|
+
* resolves to exactly one *visible* element; otherwise the next strategy is tried.
|
|
21
|
+
*/
|
|
22
|
+
declare function resolveTarget(target: Pick<StepTarget, "selectors"> | SelectorStrategy[], root?: QueryRoot): Element | null;
|
|
23
|
+
interface WaitForTargetOptions {
|
|
24
|
+
/** Give up after this many milliseconds (default 5000). */
|
|
25
|
+
timeoutMs?: number;
|
|
26
|
+
/** Abort early. */
|
|
27
|
+
signal?: AbortSignal;
|
|
28
|
+
root?: QueryRoot;
|
|
29
|
+
/** Polling fallback interval (default 250ms, which is also the maximum). */
|
|
30
|
+
pollMs?: number;
|
|
31
|
+
}
|
|
32
|
+
declare class TargetTimeoutError extends Error {
|
|
33
|
+
name: string;
|
|
34
|
+
constructor(message?: string);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Waits until `resolveTarget` finds an element. Uses a MutationObserver plus a polling fallback
|
|
38
|
+
* (at most every 250ms) so visibility changes without DOM mutations are also detected.
|
|
39
|
+
*/
|
|
40
|
+
declare function waitForTarget(target: Pick<StepTarget, "selectors"> | SelectorStrategy[], options?: WaitForTargetOptions): Promise<Element>;
|
|
41
|
+
/** Is this id stable enough to be used as a selector (not generated by a framework)? */
|
|
42
|
+
declare function isStableId(id: string): boolean;
|
|
43
|
+
/** Short human-readable text for an element, trimmed to 200 characters. */
|
|
44
|
+
declare function textSnapshotOf(el: Element): string;
|
|
45
|
+
/**
|
|
46
|
+
* Generates an ordered list of selector strategies for an element, most robust first:
|
|
47
|
+
* stable id → data-* attributes → aria-label → role/name → short unique CSS path → visible text.
|
|
48
|
+
*/
|
|
49
|
+
declare function generateSelectors(el: Element): SelectorStrategy[];
|
|
50
|
+
interface ElementDescription {
|
|
51
|
+
selectors: SelectorStrategy[];
|
|
52
|
+
textSnapshot: string;
|
|
53
|
+
rect: {
|
|
54
|
+
x: number;
|
|
55
|
+
y: number;
|
|
56
|
+
width: number;
|
|
57
|
+
height: number;
|
|
58
|
+
};
|
|
59
|
+
tag: string;
|
|
60
|
+
}
|
|
61
|
+
/** Everything the authoring picker needs for one element. */
|
|
62
|
+
declare function describeElement(el: Element): ElementDescription;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Parses HTML into a sanitized DocumentFragment using a strict allowlist. No external
|
|
66
|
+
* dependency: a `<template>` element parses inertly and the tree is walked element by element.
|
|
67
|
+
*/
|
|
68
|
+
declare function sanitizeToFragment(html: string, doc?: Document): DocumentFragment;
|
|
69
|
+
/** Returns sanitized HTML as a string. */
|
|
70
|
+
declare function sanitizeHtml(html: string, doc?: Document): string;
|
|
71
|
+
/** Replaces the content of `el` with the sanitized HTML. */
|
|
72
|
+
declare function setSanitizedHtml(el: Element, html: string): void;
|
|
73
|
+
|
|
74
|
+
declare const HOST_ID = "guidely-root";
|
|
75
|
+
interface HostHandle {
|
|
76
|
+
host: HTMLElement;
|
|
77
|
+
shadow: ShadowRoot;
|
|
78
|
+
/** Polite live region for screen-reader announcements. */
|
|
79
|
+
live: HTMLElement;
|
|
80
|
+
announce(text: string): void;
|
|
81
|
+
destroy(): void;
|
|
82
|
+
}
|
|
83
|
+
/** Default project theme used when the config has not loaded yet. */
|
|
84
|
+
declare const DEFAULT_THEME: ProjectTheme;
|
|
85
|
+
/** Returns (creating when needed) the single Shadow-DOM host appended to `document.body`. */
|
|
86
|
+
declare function ensureHost(doc?: Document): HostHandle;
|
|
87
|
+
/** Removes the host from the document (all overlays with it). */
|
|
88
|
+
declare function destroyHost(): void;
|
|
89
|
+
type ResolvedThemeMode = "light" | "dark";
|
|
90
|
+
declare function prefersReducedMotion(): boolean;
|
|
91
|
+
interface ThemeVars {
|
|
92
|
+
primary: string;
|
|
93
|
+
bg: string;
|
|
94
|
+
text: string;
|
|
95
|
+
radius: number;
|
|
96
|
+
font: string;
|
|
97
|
+
z: number;
|
|
98
|
+
overlay: number;
|
|
99
|
+
mode: ResolvedThemeMode;
|
|
100
|
+
animation: Appearance["animation"];
|
|
101
|
+
}
|
|
102
|
+
/** Merges project theme + guide appearance into CSS custom property values. */
|
|
103
|
+
declare function resolveTheme(theme: Partial<ProjectTheme> | null | undefined, appearance?: Partial<Appearance> | null): ThemeVars;
|
|
104
|
+
/** Applies theme variables to a scope element. */
|
|
105
|
+
declare function applyTheme(el: HTMLElement, vars: ThemeVars): void;
|
|
106
|
+
/**
|
|
107
|
+
* Creates a themed scope container inside the shadow root. Each guide/widget renders inside its
|
|
108
|
+
* own scope so appearance settings never leak between guides.
|
|
109
|
+
*/
|
|
110
|
+
declare function createScope(theme?: Partial<ProjectTheme> | null, appearance?: Partial<Appearance> | null, doc?: Document): {
|
|
111
|
+
el: HTMLElement;
|
|
112
|
+
vars: ThemeVars;
|
|
113
|
+
destroy(): void;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
interface AnchorOptions {
|
|
117
|
+
placement?: Placement;
|
|
118
|
+
offset?: number;
|
|
119
|
+
arrowEl?: HTMLElement | null;
|
|
120
|
+
/** Called after every position update. */
|
|
121
|
+
onUpdate?: (placement: Placement$1) => void;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Anchors `floating` next to `reference` using floating-ui (`flip`, `shift`, `offset`, `arrow`).
|
|
125
|
+
* `placement: "auto"` uses `autoPlacement`. Returns a cleanup function that stops `autoUpdate`.
|
|
126
|
+
*/
|
|
127
|
+
declare function anchor(reference: Element, floating: HTMLElement, options?: AnchorOptions): () => void;
|
|
128
|
+
/** Tracks the bounding rect of an element and calls `cb` on scroll/resize/mutation. */
|
|
129
|
+
declare function trackRect(el: Element, cb: (rect: DOMRect) => void): () => void;
|
|
130
|
+
|
|
131
|
+
interface RenderStepOptions {
|
|
132
|
+
/** Themed scope element inside the shadow root. */
|
|
133
|
+
scope: HTMLElement;
|
|
134
|
+
step: GuideStep;
|
|
135
|
+
index: number;
|
|
136
|
+
total: number;
|
|
137
|
+
target?: Element | null;
|
|
138
|
+
/** Render anchored steps as a centered modal (target fallback). */
|
|
139
|
+
asModal?: boolean;
|
|
140
|
+
onButton: (button: StepButton) => void;
|
|
141
|
+
/** Close button / Escape / outside click. */
|
|
142
|
+
onClose: () => void;
|
|
143
|
+
/** Called when a hotspot is expanded. */
|
|
144
|
+
onOpen?: () => void;
|
|
145
|
+
announce?: (text: string) => void;
|
|
146
|
+
}
|
|
147
|
+
interface StepView {
|
|
148
|
+
/** Root element of the rendered step (card, banner, hotspot...). */
|
|
149
|
+
el: HTMLElement;
|
|
150
|
+
/** Element that received focus (card), when any. */
|
|
151
|
+
card: HTMLElement | null;
|
|
152
|
+
destroy(): void;
|
|
153
|
+
}
|
|
154
|
+
/** Builds the shared chrome: close, image, title, body, progress and buttons. */
|
|
155
|
+
declare function buildCard(doc: Document, opts: RenderStepOptions, extraClass: string): {
|
|
156
|
+
card: HTMLElement;
|
|
157
|
+
inner: HTMLElement;
|
|
158
|
+
titleId: string;
|
|
159
|
+
bodyId: string;
|
|
160
|
+
};
|
|
161
|
+
declare function renderModal(doc: Document, opts: RenderStepOptions): StepView;
|
|
162
|
+
declare function renderTooltip(doc: Document, opts: RenderStepOptions, kind: "tooltip" | "popover"): StepView;
|
|
163
|
+
/** Overlay with a cut-out around the target (4 rects), so the target itself stays clickable. */
|
|
164
|
+
declare function renderSpotlight(doc: Document, opts: RenderStepOptions): StepView;
|
|
165
|
+
/** Pulsing dot at the target; opens an anchored card on click/hover. */
|
|
166
|
+
declare function renderHotspot(doc: Document, opts: RenderStepOptions): StepView;
|
|
167
|
+
declare function renderBanner(doc: Document, opts: RenderStepOptions): StepView;
|
|
168
|
+
declare function renderSlideout(doc: Document, opts: RenderStepOptions): StepView;
|
|
169
|
+
/** Sanitized custom HTML with no chrome. Elements with `data-g-action="next|back|dismiss|complete|skip"` act as buttons. */
|
|
170
|
+
declare function renderCustom(doc: Document, opts: RenderStepOptions): StepView;
|
|
171
|
+
/**
|
|
172
|
+
* Renders a step of any type into the scope. Checklist and survey steps are rendered by the
|
|
173
|
+
* dedicated widgets (`renderChecklist`, `renderSurvey`) and fall back to a modal here.
|
|
174
|
+
*/
|
|
175
|
+
declare function renderStep(opts: RenderStepOptions): StepView;
|
|
176
|
+
/** Does the step type anchor to a target element? */
|
|
177
|
+
declare function isAnchoredStep(step: GuideStep): boolean;
|
|
178
|
+
|
|
179
|
+
/** Minimal guide shape the runtime needs (a `PublishedGuide` or an authoring draft). */
|
|
180
|
+
interface RunnableGuide {
|
|
181
|
+
id: string;
|
|
182
|
+
key: string;
|
|
183
|
+
name: string;
|
|
184
|
+
kind: GuideKind | string;
|
|
185
|
+
version: number;
|
|
186
|
+
config: GuideConfig;
|
|
187
|
+
}
|
|
188
|
+
interface RuntimeEvent {
|
|
189
|
+
name: EventName;
|
|
190
|
+
guideId: string;
|
|
191
|
+
guideKey: string;
|
|
192
|
+
guideVersion: number;
|
|
193
|
+
stepId?: string;
|
|
194
|
+
stepIndex?: number;
|
|
195
|
+
properties?: Record<string, unknown>;
|
|
196
|
+
}
|
|
197
|
+
type GuideEndReason = "completed" | "dismissed" | "skipped" | "destroyed";
|
|
198
|
+
type GuideStatus = "idle" | "running" | "waiting_url" | "waiting_target" | "ended";
|
|
199
|
+
interface RunGuideOptions {
|
|
200
|
+
/** Project theme (merged with the guide's appearance). */
|
|
201
|
+
theme?: Partial<ProjectTheme> | null;
|
|
202
|
+
/** Targeting context used for branches and step-level targeting. */
|
|
203
|
+
ctx?: TargetingContext | (() => TargetingContext);
|
|
204
|
+
/** Receives lifecycle events (`guide_viewed`, `guide_started`, `step_viewed`, ...). */
|
|
205
|
+
onEvent?: (event: RuntimeEvent) => void;
|
|
206
|
+
/** Called for `url` button actions. Defaults to `location.assign` / `window.open`. */
|
|
207
|
+
onNavigate?: (url: string, newTab?: boolean) => void;
|
|
208
|
+
/** Called for `start_guide`, `event` and `open_resource_center` button actions. */
|
|
209
|
+
onAction?: (action: "start_guide" | "event" | "open_resource_center", value?: string, button?: StepButton) => void;
|
|
210
|
+
/** Rendering errors are reported here instead of being thrown into the host app. */
|
|
211
|
+
onError?: (error: unknown) => void;
|
|
212
|
+
/** Called exactly once when the guide ends for any reason. */
|
|
213
|
+
onEnd?: (reason: GuideEndReason) => void;
|
|
214
|
+
/** Event bus used by `advanceOn: "event"` steps. */
|
|
215
|
+
eventBus?: {
|
|
216
|
+
on(name: string, cb: () => void): () => void;
|
|
217
|
+
};
|
|
218
|
+
/** Start at this step id instead of the first step. */
|
|
219
|
+
startAtStep?: string;
|
|
220
|
+
/** Returns the current URL (defaults to `location.href`). */
|
|
221
|
+
currentUrl?: () => string;
|
|
222
|
+
/** Render into this element instead of creating a scope in the Shadow-DOM host. */
|
|
223
|
+
container?: HTMLElement;
|
|
224
|
+
doc?: Document;
|
|
225
|
+
}
|
|
226
|
+
interface GuideController {
|
|
227
|
+
readonly guide: RunnableGuide;
|
|
228
|
+
start(): void;
|
|
229
|
+
next(): void;
|
|
230
|
+
back(): void;
|
|
231
|
+
goTo(stepId: string): void;
|
|
232
|
+
dismiss(): void;
|
|
233
|
+
complete(): void;
|
|
234
|
+
skip(): void;
|
|
235
|
+
/** Re-evaluate a step waiting for a URL (call after SPA navigation). */
|
|
236
|
+
resume(): void;
|
|
237
|
+
destroy(): void;
|
|
238
|
+
getState(): {
|
|
239
|
+
status: GuideStatus;
|
|
240
|
+
stepId: string | null;
|
|
241
|
+
stepIndex: number;
|
|
242
|
+
total: number;
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Runs a guide: walks steps, waits for targets, handles advancement, branches, multi-page steps,
|
|
247
|
+
* buttons and cleanup. Rendering is wrapped in try/catch so the host app can never crash.
|
|
248
|
+
*/
|
|
249
|
+
declare function runGuide(guide: RunnableGuide, options?: RunGuideOptions): GuideController;
|
|
250
|
+
|
|
251
|
+
interface ChecklistProgress {
|
|
252
|
+
completedTaskIds: string[];
|
|
253
|
+
completedAt?: string | null;
|
|
254
|
+
dismissedAt?: string | null;
|
|
255
|
+
}
|
|
256
|
+
interface ChecklistWidgetOptions {
|
|
257
|
+
scope: HTMLElement;
|
|
258
|
+
config: ChecklistConfig;
|
|
259
|
+
progress?: ChecklistProgress;
|
|
260
|
+
/** Initially open? Defaults to `config.autoOpen`. */
|
|
261
|
+
open?: boolean;
|
|
262
|
+
onTaskClick?: (task: ChecklistTask) => void;
|
|
263
|
+
onDismiss?: () => void;
|
|
264
|
+
onOpen?: () => void;
|
|
265
|
+
onClose?: () => void;
|
|
266
|
+
}
|
|
267
|
+
interface ChecklistWidget {
|
|
268
|
+
el: HTMLElement;
|
|
269
|
+
open(): void;
|
|
270
|
+
close(): void;
|
|
271
|
+
toggle(): void;
|
|
272
|
+
isOpen(): boolean;
|
|
273
|
+
setProgress(progress: ChecklistProgress): void;
|
|
274
|
+
destroy(): void;
|
|
275
|
+
}
|
|
276
|
+
/** Are all required tasks done? */
|
|
277
|
+
declare function isChecklistComplete(config: ChecklistConfig, progress: ChecklistProgress): boolean;
|
|
278
|
+
/** Launcher pill + expandable panel listing tasks with checkmarks and a progress bar. */
|
|
279
|
+
declare function renderChecklist(options: ChecklistWidgetOptions): ChecklistWidget;
|
|
280
|
+
|
|
281
|
+
type SurveyAnswer = string | number | boolean | string[];
|
|
282
|
+
type SurveyAnswers = Record<string, SurveyAnswer>;
|
|
283
|
+
interface SurveyWidgetOptions {
|
|
284
|
+
scope: HTMLElement;
|
|
285
|
+
config: SurveyConfig;
|
|
286
|
+
title?: string;
|
|
287
|
+
onSubmit: (answers: SurveyAnswers) => void;
|
|
288
|
+
onDismiss?: () => void;
|
|
289
|
+
onChange?: (answers: SurveyAnswers) => void;
|
|
290
|
+
}
|
|
291
|
+
interface SurveyWidget {
|
|
292
|
+
el: HTMLElement;
|
|
293
|
+
getAnswers(): SurveyAnswers;
|
|
294
|
+
showThankYou(): void;
|
|
295
|
+
destroy(): void;
|
|
296
|
+
}
|
|
297
|
+
/** Evaluates a question's `showWhen` condition against current answers. */
|
|
298
|
+
declare function isQuestionVisible(q: SurveyQuestion, answers: SurveyAnswers): boolean;
|
|
299
|
+
/** Survey card: NPS/CSAT/thumbs/choice/text/rating questions with conditional follow-ups and a thank-you state. */
|
|
300
|
+
declare function renderSurvey(options: SurveyWidgetOptions): SurveyWidget;
|
|
301
|
+
|
|
302
|
+
interface ResourceCenterGuideRef {
|
|
303
|
+
id: string;
|
|
304
|
+
key: string;
|
|
305
|
+
name: string;
|
|
306
|
+
kind: string;
|
|
307
|
+
}
|
|
308
|
+
interface ResourceCenterOptions {
|
|
309
|
+
scope: HTMLElement;
|
|
310
|
+
config: ResourceCenterConfig;
|
|
311
|
+
/** Published guides (used to display recommended guides and checklists by id/key). */
|
|
312
|
+
guides?: ResourceCenterGuideRef[];
|
|
313
|
+
/** Server search. Results are merged with the client-side title/summary filter. */
|
|
314
|
+
search?: (q: string) => Promise<ResourceCenterArticle[]>;
|
|
315
|
+
onStartGuide?: (guideId: string) => void;
|
|
316
|
+
onOpenChecklist?: (guideId: string) => void;
|
|
317
|
+
onArticleView?: (article: ResourceCenterArticle) => void;
|
|
318
|
+
onOpen?: () => void;
|
|
319
|
+
onClose?: () => void;
|
|
320
|
+
/** Hide the launcher (when the host app provides its own trigger). */
|
|
321
|
+
hideLauncher?: boolean;
|
|
322
|
+
}
|
|
323
|
+
interface ResourceCenterWidget {
|
|
324
|
+
el: HTMLElement;
|
|
325
|
+
open(): void;
|
|
326
|
+
close(): void;
|
|
327
|
+
toggle(): void;
|
|
328
|
+
isOpen(): boolean;
|
|
329
|
+
destroy(): void;
|
|
330
|
+
}
|
|
331
|
+
/** Launcher + panel with search, collections, articles, recommended guides, checklists, FAQs and links. */
|
|
332
|
+
declare function renderResourceCenter(options: ResourceCenterOptions): ResourceCenterWidget;
|
|
333
|
+
|
|
334
|
+
interface AuthoringOptions {
|
|
335
|
+
/** Called with the pick for each clicked element. */
|
|
336
|
+
onPick: (pick: AuthoringPick & {
|
|
337
|
+
element: Element;
|
|
338
|
+
}) => void;
|
|
339
|
+
/** Called when the user exits authoring mode (Done / Exit / Esc with nothing hovered). */
|
|
340
|
+
onExit: () => void;
|
|
341
|
+
dashboardOrigin?: string;
|
|
342
|
+
/** Text shown in the toolbar. */
|
|
343
|
+
message?: string;
|
|
344
|
+
doc?: Document;
|
|
345
|
+
}
|
|
346
|
+
interface AuthoringSession {
|
|
347
|
+
/** Replace the toolbar status text. */
|
|
348
|
+
setStatus(text: string): void;
|
|
349
|
+
/** Pause/resume picking (e.g. while a preview is shown). */
|
|
350
|
+
setPicking(enabled: boolean): void;
|
|
351
|
+
stop(): void;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Enters authoring mode: Shadow-DOM toolbar, hover outline following `elementFromPoint`, and
|
|
355
|
+
* click-to-pick (captured in the capture phase so the host app never receives the click).
|
|
356
|
+
*/
|
|
357
|
+
declare function startAuthoring(options: AuthoringOptions): AuthoringSession;
|
|
358
|
+
interface PreviewHandle {
|
|
359
|
+
controller: GuideController;
|
|
360
|
+
destroy(): void;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Renders a single draft step on the current page (used by the dashboard editor's "preview in
|
|
364
|
+
* app" and by the simulated preview). Anchored steps resolve their target; when it cannot be
|
|
365
|
+
* found the step is shown as a modal so authors always see something.
|
|
366
|
+
*/
|
|
367
|
+
declare function previewStep(step: GuideStep, theme?: Partial<ProjectTheme> | null, options?: {
|
|
368
|
+
appearance?: RunnableGuide["config"]["appearance"];
|
|
369
|
+
onEnd?: () => void;
|
|
370
|
+
doc?: Document;
|
|
371
|
+
index?: number;
|
|
372
|
+
total?: number;
|
|
373
|
+
}): PreviewHandle;
|
|
374
|
+
interface HighlightHandle {
|
|
375
|
+
/** Number of matched elements per strategy. */
|
|
376
|
+
counts: number[];
|
|
377
|
+
/** Element resolved as the step target (first strategy with exactly one visible match). */
|
|
378
|
+
resolved: Element | null;
|
|
379
|
+
destroy(): void;
|
|
380
|
+
}
|
|
381
|
+
/** Draws dashed boxes around every element matched by the selectors, for testing selectors while authoring. */
|
|
382
|
+
declare function highlightSelectors(selectors: SelectorStrategy[], options?: {
|
|
383
|
+
durationMs?: number;
|
|
384
|
+
doc?: Document;
|
|
385
|
+
}): HighlightHandle;
|
|
386
|
+
|
|
387
|
+
/** All runtime CSS, injected once into the Shadow DOM host. Tokens are CSS custom properties. */
|
|
388
|
+
declare const STYLES = "\n:host{all:initial;position:static;display:block;contain:none}\n*,*::before,*::after{box-sizing:border-box}\n.g-scope [hidden]{display:none!important}\n.g-scope{\n --g-primary:#4f46e5;--g-bg:#ffffff;--g-text:#111827;--g-radius:12px;--g-font:Inter,system-ui,-apple-system,sans-serif;--g-z:2147483000;--g-overlay:.5;\n --g-muted:color-mix(in srgb,var(--g-text) 62%,transparent);--g-border:color-mix(in srgb,var(--g-text) 12%,transparent);\n --g-subtle:color-mix(in srgb,var(--g-text) 5%,transparent);--g-shadow:0 10px 40px rgba(0,0,0,.18),0 2px 8px rgba(0,0,0,.08);\n --g-primary-text:#ffffff;\n font-family:var(--g-font);font-size:14px;line-height:1.5;color:var(--g-text);-webkit-font-smoothing:antialiased;\n}\n.g-scope[data-theme=\"dark\"]{--g-shadow:0 10px 40px rgba(0,0,0,.5),0 2px 8px rgba(0,0,0,.3)}\n.g-live{position:fixed;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n.g-layer{position:fixed;inset:0;z-index:var(--g-z);pointer-events:none}\n.g-overlay{position:fixed;inset:0;background:rgba(0,0,0,var(--g-overlay));z-index:calc(var(--g-z) + 3);pointer-events:auto}\n.g-overlay.g-transparent{background:transparent}\n.g-spot-rect{position:fixed;background:rgba(0,0,0,var(--g-overlay));z-index:calc(var(--g-z) + 3);pointer-events:auto}\n.g-spot-ring{position:fixed;z-index:calc(var(--g-z) + 3);pointer-events:none;border-radius:6px;box-shadow:0 0 0 2px var(--g-primary),0 0 0 6px color-mix(in srgb,var(--g-primary) 30%,transparent)}\n.g-card{\n position:fixed;z-index:calc(var(--g-z) + 4);pointer-events:auto;background:var(--g-bg);color:var(--g-text);border-radius:var(--g-radius);\n box-shadow:var(--g-shadow);border:1px solid var(--g-border);width:min(360px,calc(100vw - 32px));max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);overflow:auto;outline:none;\n}\n.g-card.g-modal{left:50%;top:50%;transform:translate(-50%,-50%);width:min(480px,calc(100vw - 32px))}\n.g-card.g-tooltip,.g-card.g-popover,.g-card.g-spotlight-card,.g-card.g-hotspot-card{top:0;left:0;width:min(320px,calc(100vw - 32px))}\n.g-card.g-slideout{width:min(360px,calc(100vw - 32px));margin:16px}\n.g-pos-bottom-right{right:0;bottom:0}.g-pos-bottom-left{left:0;bottom:0}.g-pos-top-right{right:0;top:0}.g-pos-top-left{left:0;top:0}\n.g-pos-center{left:50%;top:50%;transform:translate(-50%,-50%)}\n.g-pos-top{top:0;left:0;right:0}.g-pos-bottom{bottom:0;left:0;right:0}\n.g-banner{position:fixed;left:0;right:0;z-index:calc(var(--g-z) + 1);pointer-events:auto;background:var(--g-primary);color:var(--g-primary-text);padding:10px 48px 10px 16px;display:flex;align-items:center;gap:12px;font-size:14px;box-shadow:0 2px 10px rgba(0,0,0,.15);max-width:100vw}\n.g-banner .g-body{flex:1;min-width:0}\n.g-banner .g-body a{color:inherit;text-decoration:underline}\n.g-banner .g-close{color:inherit;right:8px;top:50%;transform:translateY(-50%)}\n.g-banner .g-btn{background:rgba(255,255,255,.18);color:inherit;border-color:transparent;min-height:36px}\n.g-banner.g-pos-top{top:0}.g-banner.g-pos-bottom{bottom:0}\n.g-inner{padding:20px}\n.g-close{position:absolute;top:8px;right:8px;width:40px;height:40px;display:inline-flex;align-items:center;justify-content:center;border:0;background:transparent;color:var(--g-muted);border-radius:999px;cursor:pointer;font:inherit;font-size:20px;line-height:1}\n.g-close:hover,.g-close:focus-visible{background:var(--g-subtle);color:var(--g-text);outline:none}\n.g-close:focus-visible,.g-btn:focus-visible,.g-task:focus-visible,.g-choice:focus-visible,.g-scale button:focus-visible,.g-launcher:focus-visible,.g-input:focus-visible,.g-rc-item:focus-visible{outline:2px solid var(--g-primary);outline-offset:2px}\n.g-image{display:block;width:100%;max-height:220px;object-fit:cover;border-radius:var(--g-radius) var(--g-radius) 0 0}\n.g-title{margin:0 28px 6px 0;font-size:16px;font-weight:600;line-height:1.3}\n.g-body{font-size:14px;color:var(--g-text)}\n.g-body p{margin:0 0 8px}.g-body p:last-child{margin-bottom:0}\n.g-body ul,.g-body ol{margin:6px 0;padding-left:20px}\n.g-body a{color:var(--g-primary)}\n.g-body img{max-width:100%;height:auto;border-radius:6px}\n.g-body code{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;background:var(--g-subtle);padding:1px 4px;border-radius:4px}\n.g-body pre{background:var(--g-subtle);padding:10px;border-radius:6px;overflow:auto}\n.g-body blockquote{margin:6px 0;padding-left:10px;border-left:3px solid var(--g-border);color:var(--g-muted)}\n.g-footer{display:flex;align-items:center;gap:8px;margin-top:14px;flex-wrap:wrap}\n.g-progress{font-size:12px;color:var(--g-muted);margin-right:auto}\n.g-btn{display:inline-flex;align-items:center;justify-content:center;gap:6px;min-height:40px;padding:8px 14px;border-radius:calc(var(--g-radius) * .66);border:1px solid transparent;font:inherit;font-size:14px;font-weight:500;cursor:pointer;text-decoration:none;transition:background .15s,color .15s,border-color .15s}\n.g-btn-primary{background:var(--g-primary);color:var(--g-primary-text)}\n.g-btn-primary:hover{filter:brightness(1.08)}\n.g-btn-secondary{background:var(--g-subtle);color:var(--g-text);border-color:var(--g-border)}\n.g-btn-secondary:hover{background:color-mix(in srgb,var(--g-text) 10%,transparent)}\n.g-btn-ghost{background:transparent;color:var(--g-muted)}\n.g-btn-ghost:hover{background:var(--g-subtle);color:var(--g-text)}\n.g-btn-link{background:transparent;color:var(--g-primary);padding-left:4px;padding-right:4px}\n.g-btn-link:hover{text-decoration:underline}\n.g-btn:disabled{opacity:.5;cursor:not-allowed}\n.g-arrow{position:absolute;width:12px;height:12px;background:var(--g-bg);transform:rotate(45deg);border:1px solid var(--g-border);z-index:-1}\n.g-hotspot{position:fixed;z-index:calc(var(--g-z) + 1);pointer-events:auto;border-radius:999px;background:var(--g-primary);border:2px solid #fff;box-shadow:0 0 0 2px color-mix(in srgb,var(--g-primary) 40%,transparent);cursor:pointer;padding:0;margin:0}\n.g-hotspot::after{content:\"\";position:absolute;inset:-4px;border-radius:999px;border:2px solid var(--g-primary);opacity:0}\n.g-hotspot.g-pulse::after{animation:g-pulse 1.8s ease-out infinite}\n.g-hotspot-hit{position:absolute;inset:-14px}\n.g-custom{position:fixed;z-index:calc(var(--g-z) + 4);pointer-events:auto;left:50%;top:50%;transform:translate(-50%,-50%);max-width:calc(100vw - 32px);max-height:calc(100vh - 32px);overflow:auto}\n/* animations */\n.g-scope[data-anim=\"fade\"] .g-card,.g-scope[data-anim=\"fade\"] .g-banner,.g-scope[data-anim=\"fade\"] .g-panel{animation:g-fade .18s ease-out}\n.g-scope[data-anim=\"slide\"] .g-card,.g-scope[data-anim=\"slide\"] .g-panel{animation:g-slide .22s ease-out}\n.g-scope[data-anim=\"none\"] *{animation:none!important;transition:none!important}\n@keyframes g-fade{from{opacity:0}to{opacity:1}}\n@keyframes g-slide{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}\n@keyframes g-pulse{0%{transform:scale(.6);opacity:.9}100%{transform:scale(2.2);opacity:0}}\n@media (prefers-reduced-motion:reduce){.g-scope *{animation:none!important;transition:none!important}}\n/* launcher + panel (checklist / resource center) */\n.g-launcher{position:fixed;z-index:calc(var(--g-z) + 1);pointer-events:auto;display:inline-flex;align-items:center;gap:8px;min-height:44px;padding:10px 16px;border-radius:999px;border:0;background:var(--g-primary);color:var(--g-primary-text);font:inherit;font-size:14px;font-weight:600;cursor:pointer;box-shadow:var(--g-shadow);margin:16px}\n.g-launcher .g-ring{width:22px;height:22px;border-radius:999px;background:conic-gradient(#fff var(--g-pct,0%),rgba(255,255,255,.3) 0);display:inline-flex;align-items:center;justify-content:center;font-size:10px;position:relative}\n.g-launcher .g-ring::after{content:\"\";position:absolute;inset:3px;border-radius:999px;background:var(--g-primary)}\n.g-launcher .g-count{position:relative;z-index:1}\n.g-panel{position:fixed;z-index:calc(var(--g-z) + 2);pointer-events:auto;width:min(380px,calc(100vw - 32px));max-height:min(620px,calc(100vh - 100px));display:flex;flex-direction:column;background:var(--g-bg);color:var(--g-text);border-radius:var(--g-radius);box-shadow:var(--g-shadow);border:1px solid var(--g-border);margin:16px;bottom:60px;overflow:hidden}\n.g-panel-head{padding:16px 48px 12px 20px;border-bottom:1px solid var(--g-border);position:relative}\n.g-panel-title{margin:0;font-size:16px;font-weight:600}\n.g-panel-sub{margin:4px 0 0;font-size:12px;color:var(--g-muted)}\n.g-panel-body{overflow:auto;padding:8px 0;flex:1}\n.g-bar{height:6px;border-radius:999px;background:var(--g-subtle);overflow:hidden;margin-top:10px}\n.g-bar > span{display:block;height:100%;background:var(--g-primary);transition:width .3s}\n.g-task{display:flex;gap:12px;align-items:flex-start;width:100%;padding:12px 20px;border:0;background:transparent;text-align:left;font:inherit;color:inherit;cursor:pointer;min-height:44px}\n.g-task:hover{background:var(--g-subtle)}\n.g-task[disabled]{cursor:not-allowed;opacity:.55}\n.g-task .g-check{flex:none;width:22px;height:22px;border-radius:999px;border:2px solid var(--g-border);display:inline-flex;align-items:center;justify-content:center;font-size:13px;margin-top:1px;color:#fff}\n.g-task.g-done .g-check{background:var(--g-primary);border-color:var(--g-primary)}\n.g-task.g-done .g-task-title{text-decoration:line-through;color:var(--g-muted)}\n.g-task-title{font-weight:500}\n.g-task-desc{font-size:12px;color:var(--g-muted);margin-top:2px}\n.g-panel-foot{padding:10px 20px;border-top:1px solid var(--g-border);display:flex;justify-content:flex-end;gap:8px}\n.g-complete{padding:28px 20px;text-align:center}\n.g-complete .g-title{margin-right:0;font-size:18px}\n/* survey */\n.g-question{margin-bottom:16px}\n.g-q-title{font-weight:600;margin:0 0 4px}\n.g-q-desc{font-size:12px;color:var(--g-muted);margin:0 0 8px}\n.g-scale{display:flex;gap:4px;flex-wrap:wrap}\n.g-scale button{min-width:34px;height:40px;flex:1;padding:0 4px;border-radius:6px;border:1px solid var(--g-border);background:var(--g-subtle);color:var(--g-text);font:inherit;cursor:pointer}\n.g-scale button[aria-pressed=\"true\"],.g-scale button:hover{background:var(--g-primary);color:var(--g-primary-text);border-color:var(--g-primary)}\n.g-scale-labels{display:flex;justify-content:space-between;font-size:11px;color:var(--g-muted);margin-top:4px}\n.g-stars button,.g-thumbs button{font-size:22px;background:transparent;border:0;cursor:pointer;color:var(--g-muted);min-width:40px;height:40px;font:inherit}\n.g-stars button[aria-pressed=\"true\"],.g-stars button.g-on{color:#f59e0b}\n.g-thumbs button[aria-pressed=\"true\"]{color:var(--g-primary)}\n.g-choice{display:flex;align-items:center;gap:10px;padding:8px 10px;border:1px solid var(--g-border);border-radius:8px;margin-bottom:6px;cursor:pointer;min-height:40px;font:inherit;background:transparent;color:inherit;width:100%;text-align:left}\n.g-choice[aria-checked=\"true\"]{border-color:var(--g-primary);background:color-mix(in srgb,var(--g-primary) 8%,transparent)}\n.g-choice .g-dot{width:16px;height:16px;border-radius:999px;border:2px solid var(--g-border);flex:none}\n.g-choice.g-multi .g-dot{border-radius:4px}\n.g-choice[aria-checked=\"true\"] .g-dot{background:var(--g-primary);border-color:var(--g-primary)}\n.g-input{width:100%;min-height:40px;padding:8px 10px;border:1px solid var(--g-border);border-radius:8px;background:var(--g-bg);color:var(--g-text);font:inherit;resize:vertical}\n.g-error{color:#dc2626;font-size:12px;margin-top:4px}\n/* resource center */\n.g-rc-search{padding:12px 20px 4px}\n.g-rc-section{padding:8px 20px 4px;font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--g-muted);font-weight:600}\n.g-rc-item{display:flex;align-items:flex-start;gap:10px;width:100%;padding:10px 20px;border:0;background:transparent;font:inherit;color:inherit;text-align:left;cursor:pointer;min-height:44px;text-decoration:none}\n.g-rc-item:hover{background:var(--g-subtle)}\n.g-rc-item .g-rc-title{font-weight:500}\n.g-rc-item .g-rc-sum{font-size:12px;color:var(--g-muted);margin-top:2px}\n.g-rc-item .g-rc-icon{flex:none;width:20px;text-align:center;color:var(--g-primary)}\n.g-rc-article{padding:16px 20px}\n.g-rc-back{margin-bottom:8px}\n.g-rc-empty{padding:24px 20px;color:var(--g-muted);text-align:center}\n.g-faq-a{padding:0 20px 12px 50px;font-size:13px;color:var(--g-muted)}\n.g-faq-a[hidden]{display:none}\n/* authoring */\n.g-auth-bar{position:fixed;top:0;left:0;right:0;z-index:calc(var(--g-z) + 10);pointer-events:auto;display:flex;align-items:center;gap:12px;padding:8px 16px;background:#111827;color:#fff;font:500 13px/1.4 var(--g-font);box-shadow:0 2px 10px rgba(0,0,0,.3)}\n.g-auth-bar .g-dot-live{width:8px;height:8px;border-radius:999px;background:#22c55e;box-shadow:0 0 0 3px rgba(34,197,94,.3)}\n.g-auth-bar .g-spacer{flex:1}\n.g-auth-bar .g-btn{min-height:32px;padding:4px 12px;font-size:13px}\n.g-auth-bar .g-btn-secondary{background:rgba(255,255,255,.12);color:#fff;border-color:transparent}\n.g-auth-outline{position:fixed;z-index:calc(var(--g-z) + 9);pointer-events:none;border:2px solid var(--g-primary);background:color-mix(in srgb,var(--g-primary) 12%,transparent);border-radius:4px;transition:all .06s linear}\n.g-auth-label{position:absolute;left:-2px;top:-24px;background:var(--g-primary);color:#fff;font:600 11px/1 var(--g-font);padding:5px 7px;border-radius:4px;white-space:nowrap;max-width:320px;overflow:hidden;text-overflow:ellipsis}\n.g-auth-outline.g-picked{border-style:dashed;border-color:#22c55e;background:rgba(34,197,94,.12)}\n.g-auth-outline.g-picked .g-auth-label{background:#16a34a}\n.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}\n@media (max-width:480px){.g-card.g-modal,.g-panel{width:calc(100vw - 32px)}.g-inner{padding:16px}}\n";
|
|
389
|
+
|
|
390
|
+
export { type AnchorOptions, type AuthoringOptions, type AuthoringSession, type ChecklistProgress, type ChecklistWidget, type ChecklistWidgetOptions, DEFAULT_THEME, type ElementDescription, type GuideController, type GuideEndReason, type GuideStatus, HOST_ID, type HighlightHandle, type HostHandle, type PreviewHandle, type QueryRoot, type RenderStepOptions, type ResolvedThemeMode, type ResourceCenterGuideRef, type ResourceCenterOptions, type ResourceCenterWidget, type RunGuideOptions, type RunnableGuide, type RuntimeEvent, STYLES, type StepView, type SurveyAnswer, type SurveyAnswers, type SurveyWidget, type SurveyWidgetOptions, TargetTimeoutError, type ThemeVars, type WaitForTargetOptions, anchor, applyTheme, buildCard, createScope, describeElement, destroyHost, ensureHost, generateSelectors, highlightSelectors, isAnchoredStep, isChecklistComplete, isGuidelyElement, isQuestionVisible, isStableId, isVisible, normalizeText, prefersReducedMotion, previewStep, querySelectorStrategy, renderBanner, renderChecklist, renderCustom, renderHotspot, renderModal, renderResourceCenter, renderSlideout, renderSpotlight, renderStep, renderSurvey, renderTooltip, resolveTarget, resolveTheme, runGuide, sanitizeHtml, sanitizeToFragment, setSanitizedHtml, startAuthoring, textSnapshotOf, trackRect, urlMatches, waitForTarget };
|