@apollovisionlabs/guide-core 0.1.1 → 0.3.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/index.d.ts CHANGED
@@ -19,6 +19,11 @@ interface Step {
19
19
  placement?: Placement;
20
20
  /** Lets the user interact with the page during the step. */
21
21
  interactive?: boolean;
22
+ /**
23
+ * Advances the tour when the user clicks the target. Implies `interactive`: a step that
24
+ * waits for a click has to let the click through.
25
+ */
26
+ advanceOn?: 'click';
22
27
  title?: string;
23
28
  titleKey?: string;
24
29
  body?: string;
@@ -35,9 +40,64 @@ interface TourProgress {
35
40
  status: 'in-progress' | 'completed';
36
41
  stepIndex: number;
37
42
  }
43
+ interface ChecklistItem {
44
+ id: string;
45
+ title?: string;
46
+ titleKey?: string;
47
+ body?: string;
48
+ bodyKey?: string;
49
+ /** Tour launched when the item is activated. Completing it completes the item. */
50
+ tourId?: string;
51
+ /** Path navigated to when the item is activated and carries no tour. */
52
+ href?: string;
53
+ }
54
+ interface Checklist {
55
+ id: string;
56
+ items: ChecklistItem[];
57
+ }
58
+ interface ChecklistProgress {
59
+ completed: string[];
60
+ dismissed: boolean;
61
+ }
62
+ interface ResolvedChecklistItem {
63
+ id: string;
64
+ title: string;
65
+ body: string;
66
+ completed: boolean;
67
+ tourId?: string;
68
+ href?: string;
69
+ }
70
+ interface Hotspot {
71
+ id: string;
72
+ /** Logical key carried by the data-guide attribute on the element. */
73
+ target: string;
74
+ title?: string;
75
+ titleKey?: string;
76
+ body?: string;
77
+ bodyKey?: string;
78
+ /** Tour started from the hotspot's bubble. */
79
+ tourId?: string;
80
+ placement?: Placement;
81
+ }
82
+ interface ResolvedHotspot {
83
+ id: string;
84
+ target: string;
85
+ title: string;
86
+ body: string;
87
+ seen: boolean;
88
+ tourId?: string;
89
+ placement?: Placement;
90
+ }
91
+ interface HotspotsProgress {
92
+ seen: string[];
93
+ }
38
94
  interface GuideStorage {
39
- read(tourId: string): Promise<TourProgress | null>;
40
- write(tourId: string, progress: TourProgress): Promise<void>;
95
+ /**
96
+ * Reads a previously written value. The key is namespaced by the caller,
97
+ * `tour:<id>`, `checklist:<id>`, or `hotspots:seen`, so one storage serves them all.
98
+ */
99
+ read<T>(key: string): Promise<T | null>;
100
+ write<T>(key: string, value: T): Promise<void>;
41
101
  }
42
102
  type GuideEvent = {
43
103
  type: 'tour:start';
@@ -60,11 +120,42 @@ type GuideEvent = {
60
120
  tourId: string;
61
121
  stepIndex: number;
62
122
  target: string;
123
+ } | {
124
+ type: 'checklist:item-complete';
125
+ checklistId: string;
126
+ itemId: string;
127
+ } | {
128
+ type: 'checklist:complete';
129
+ checklistId: string;
130
+ } | {
131
+ type: 'checklist:dismiss';
132
+ checklistId: string;
133
+ } | {
134
+ type: 'hotspot:show';
135
+ hotspotId: string;
136
+ } | {
137
+ type: 'hotspot:open';
138
+ hotspotId: string;
63
139
  };
64
140
  type Translate = (key: string) => string;
65
141
 
66
- declare function createMemoryStorage(initial?: Record<string, TourProgress>): GuideStorage;
142
+ declare function createMemoryStorage(initial?: Record<string, unknown>): GuideStorage;
67
143
  declare function createBrowserStorage(namespace?: string): GuideStorage;
144
+ /**
145
+ * A stored value survives code changes, browser extensions and hand editing,
146
+ * so nothing read back is trusted until its shape is checked.
147
+ */
148
+ declare function isTourProgress(value: unknown): value is TourProgress;
149
+ /**
150
+ * Same defensive posture as isTourProgress: a stored checklist value is
151
+ * never trusted until its shape is checked.
152
+ */
153
+ declare function isChecklistProgress(value: unknown): value is ChecklistProgress;
154
+ /**
155
+ * Same defensive posture as the two guards above: a stored hotspot value is never trusted
156
+ * until its shape is checked.
157
+ */
158
+ declare function isHotspotsProgress(value: unknown): value is HotspotsProgress;
68
159
 
69
160
  declare function isLiteralRoute(pattern: string): boolean;
70
161
  declare function matchRoute(pattern: string, pathname: string): boolean;
@@ -122,6 +213,14 @@ interface ActiveStep {
122
213
  stepCount: number;
123
214
  element: HTMLElement | null;
124
215
  rect: Rect | null;
216
+ /**
217
+ * Whether the page stays reachable during the step. True when the step declares
218
+ * `interactive`, and also when it declares `advanceOn`, whose click has to reach the
219
+ * element. Renderers read this instead of `step.interactive`, so the rule lives here.
220
+ */
221
+ interactive: boolean;
222
+ /** True when the step advances on a user action rather than on a button. */
223
+ awaitsAction: boolean;
125
224
  title: string;
126
225
  body: string;
127
226
  isFirst: boolean;
@@ -172,4 +271,103 @@ declare function findMissingTargets(tour: Tour, location: string | undefined, at
172
271
 
173
272
  declare function useGuideStep(): ActiveStep | null;
174
273
 
175
- export { type ActiveStep, GuideContext, type GuideContextValue, type GuideEvent, GuideProvider, type GuideProviderProps, type GuideStorage, type MissingTargetPolicy, type Placement, type Rect, type Step, type Tour, type TourAction, type TourProgress, type TourState, type TourStatus, type Translate, type UseFocusTrapOptions, type UseTargetElementOptions, type UseTourResult, createBrowserStorage, createMemoryStorage, findMissingTargets, initialTourState, isLiteralRoute, matchRoute, tourReducer, useAnnouncer, useElementRect, useFocusTrap, useGuideStep, usePrefersReducedMotion, useTargetElement, useTour };
274
+ declare function resolveText(value: string | undefined, key: string | undefined, translate: Translate | undefined): string;
275
+
276
+ interface ChecklistContextValue {
277
+ checklists: Checklist[];
278
+ progress: Record<string, ChecklistProgress>;
279
+ translate?: Translate;
280
+ /**
281
+ * Whether each checklist's initial restore from storage has settled, keyed by checklist id:
282
+ * true immediately for a checklist when no `storage` prop was given (there is nothing to
283
+ * wait for), and true once that checklist's own read has resolved or rejected. Settled
284
+ * independently per checklist, so a slow or hung read for one checklist never holds another
285
+ * checklist's rendering hostage, and a renderer can wait for its own entry without a broken
286
+ * backend hiding it forever.
287
+ */
288
+ restored: Record<string, boolean>;
289
+ activate: (checklistId: string, itemId: string) => void;
290
+ toggle: (checklistId: string, itemId: string) => void;
291
+ complete: (checklistId: string, itemId: string) => void;
292
+ dismiss: (checklistId: string) => void;
293
+ reset: (checklistId: string) => void;
294
+ }
295
+ declare const ChecklistContext: react.Context<ChecklistContextValue | null>;
296
+ interface ChecklistProviderProps {
297
+ checklists: Checklist[];
298
+ children: ReactNode;
299
+ storage?: GuideStorage;
300
+ translate?: Translate;
301
+ navigate?: (path: string) => void;
302
+ onEvent?: (event: GuideEvent) => void;
303
+ }
304
+ declare function ChecklistProvider({ checklists, children, storage, translate, navigate, onEvent, }: ChecklistProviderProps): react.JSX.Element;
305
+
306
+ interface UseChecklistResult {
307
+ items: ResolvedChecklistItem[];
308
+ completedCount: number;
309
+ total: number;
310
+ isComplete: boolean;
311
+ dismissed: boolean;
312
+ /**
313
+ * Whether this checklist's own initial restore from storage has settled. A renderer should
314
+ * wait for this before drawing anything, or a checklist already dismissed or partly
315
+ * completed in storage can flash its empty initial state on screen once before the restore
316
+ * lands. Settled per checklist: a slow or hung read for a different checklist on the same
317
+ * provider never holds this one false.
318
+ */
319
+ restored: boolean;
320
+ activate: (itemId: string) => void;
321
+ toggle: (itemId: string) => void;
322
+ complete: (itemId: string) => void;
323
+ dismiss: () => void;
324
+ reset: () => void;
325
+ }
326
+ declare function useChecklist(checklistId: string): UseChecklistResult;
327
+
328
+ interface HotspotContextValue {
329
+ hotspots: Hotspot[];
330
+ seen: string[];
331
+ translate?: Translate;
332
+ /**
333
+ * Whether the initial restore from storage has settled: true immediately when no `storage`
334
+ * prop was given (there is nothing to wait for), and true once the read resolves or
335
+ * rejects, so a renderer can wait for it without a broken backend hiding hotspots forever.
336
+ */
337
+ restored: boolean;
338
+ open: (hotspotId: string) => void;
339
+ startTour: (hotspotId: string) => void;
340
+ reset: () => void;
341
+ notifyShown: (hotspotId: string) => void;
342
+ }
343
+ declare const HotspotContext: react.Context<HotspotContextValue | null>;
344
+ interface HotspotProviderProps {
345
+ hotspots: Hotspot[];
346
+ children: ReactNode;
347
+ storage?: GuideStorage;
348
+ translate?: Translate;
349
+ onEvent?: (event: GuideEvent) => void;
350
+ }
351
+ declare function HotspotProvider({ hotspots, children, storage, translate, onEvent, }: HotspotProviderProps): react.JSX.Element;
352
+
353
+ interface UseHotspotsResult {
354
+ /**
355
+ * Every hotspot, each carrying its own `seen`, rather than the unseen ones alone. A
356
+ * renderer has to keep a marker mounted while its own bubble closes, so it needs the seen
357
+ * one too; filtering is one line at the call site.
358
+ */
359
+ hotspots: ResolvedHotspot[];
360
+ /**
361
+ * Whether the initial restore from storage has settled. A renderer should wait for this
362
+ * before drawing any marker, or a hotspot already seen in storage can flash on screen once
363
+ * before the restore lands.
364
+ */
365
+ restored: boolean;
366
+ open: (hotspotId: string) => void;
367
+ startTour: (hotspotId: string) => void;
368
+ reset: () => void;
369
+ notifyShown: (hotspotId: string) => void;
370
+ }
371
+ declare function useHotspots(): UseHotspotsResult;
372
+
373
+ export { type ActiveStep, type Checklist, ChecklistContext, type ChecklistContextValue, type ChecklistItem, type ChecklistProgress, ChecklistProvider, type ChecklistProviderProps, GuideContext, type GuideContextValue, type GuideEvent, GuideProvider, type GuideProviderProps, type GuideStorage, type Hotspot, HotspotContext, type HotspotContextValue, HotspotProvider, type HotspotProviderProps, type HotspotsProgress, type MissingTargetPolicy, type Placement, type Rect, type ResolvedChecklistItem, type ResolvedHotspot, type Step, type Tour, type TourAction, type TourProgress, type TourState, type TourStatus, type Translate, type UseChecklistResult, type UseFocusTrapOptions, type UseHotspotsResult, type UseTargetElementOptions, type UseTourResult, createBrowserStorage, createMemoryStorage, findMissingTargets, initialTourState, isChecklistProgress, isHotspotsProgress, isLiteralRoute, isTourProgress, matchRoute, resolveText, tourReducer, useAnnouncer, useChecklist, useElementRect, useFocusTrap, useGuideStep, useHotspots, usePrefersReducedMotion, useTargetElement, useTour };