@sunboard/react 0.5.0 → 0.6.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.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ReactNode } from "react";
2
- import { RuntimeBootstrapRequest, RuntimeBootstrapResponse, RuntimeExperience, RuntimeProgress, RuntimeTrackRequest, RuntimeTrackResponse, SunboardRuntimeApiError, SunboardRuntimeClient, SunboardRuntimeClientOptions } from "@sunboard/core/runtime-api";
3
- import * as react_jsx_runtime1 from "react/jsx-runtime";
4
- import { NormalizedSunboardSpec, SunboardHotspot, SunboardStep, SunboardTourStep, SurveyQuestionType, TrackEventName } from "@sunboard/core";
2
+ import { RuntimeBootstrapRequest, RuntimeBootstrapResponse, RuntimeExperience, RuntimeProgress, RuntimeTrackRequest, RuntimeTrackResponse, SunboardRuntimeApiError, SunboardRuntimeClient, SunboardRuntimeClientOptions, TooltipDismissVia } from "@sunboard/core/runtime-api";
3
+ import * as react_jsx_runtime0 from "react/jsx-runtime";
4
+ import { NormalizedSunboardSpec, SunboardHotspot, SunboardPlacement, SunboardStep, SunboardTooltip, SunboardTourStep, SurveyQuestionType, TrackEventName } from "@sunboard/core";
5
5
 
6
6
  //#region src/adapters/navigation.d.ts
7
7
  type NavigateCallback = (url: string) => void | Promise<void>;
@@ -52,6 +52,23 @@ type TourResult = {
52
52
  ok: false;
53
53
  reason: "not-ready" | "missing-user" | "missing-tour";
54
54
  };
55
+ type TooltipResult = {
56
+ ok: true;
57
+ } | {
58
+ ok: false;
59
+ reason: "not-ready" | "missing-user" | "missing-tooltip";
60
+ };
61
+ type VisibleSunboardTooltip = {
62
+ key: string;
63
+ tooltip: SunboardTooltip;
64
+ /**
65
+ * True when the user asked for this tooltip (a checklist step's
66
+ * `openTooltip` action), false when it is showing proactively. A requested
67
+ * tooltip shows even if it was dismissed before — the user explicitly asked
68
+ * to be shown where the action happens.
69
+ */
70
+ requested: boolean;
71
+ };
55
72
  type ActiveSunboardTour = {
56
73
  key: string;
57
74
  name: string;
@@ -88,11 +105,32 @@ type SunboardContextValue = {
88
105
  }) => Promise<TourResult>;
89
106
  advanceTour: () => Promise<TourResult>;
90
107
  navigateToStep: (step: SunboardStep) => Promise<void>;
91
- startChecklistStep: (step: SunboardStep) => Promise<TourResult | void>;
108
+ startChecklistStep: (step: SunboardStep) => Promise<TourResult | TooltipResult | void>;
92
109
  visibleHotspots: Array<{
93
110
  key: string;
94
111
  hotspot: SunboardHotspot;
95
112
  }>;
113
+ dismissedTooltipKeys: ReadonlySet<string>;
114
+ /**
115
+ * Tooltips that qualify for the current route, requested-first. Renderers
116
+ * show ONE at a time: the first entry whose target resolves.
117
+ */
118
+ visibleTooltips: VisibleSunboardTooltip[];
119
+ /**
120
+ * Open a tooltip on demand (the checklist's openTooltip action). Navigates
121
+ * are the caller's job; this just marks the tooltip requested so it renders
122
+ * once its route matches and its target is present, dismissal or not.
123
+ */
124
+ openTooltip: (tooltipKey: string) => Promise<TooltipResult>;
125
+ /**
126
+ * Never show this tooltip again. `via: "close"` is the negative signal (the
127
+ * default); `via: "action"` records that the user took the tooltip's action.
128
+ */
129
+ dismissTooltip: (tooltipKey: string, options?: {
130
+ via?: TooltipDismissVia;
131
+ }) => Promise<TooltipResult>;
132
+ /** Report that a tooltip actually reached the user's eyes (deduped per session). */
133
+ markTooltipSeen: (tooltipKey: string) => void;
96
134
  };
97
135
  //#endregion
98
136
  //#region src/components/SunboardProvider.d.ts
@@ -132,21 +170,31 @@ declare function SunboardProvider({
132
170
  identities: identitiesProp,
133
171
  onTrack,
134
172
  children
135
- }: SunboardProviderProps): react_jsx_runtime1.JSX.Element;
173
+ }: SunboardProviderProps): react_jsx_runtime0.JSX.Element;
136
174
  //#endregion
137
175
  //#region src/components/SunboardHotspots.d.ts
138
- declare function SunboardHotspots(): react_jsx_runtime1.JSX.Element;
176
+ declare function SunboardHotspots(): react_jsx_runtime0.JSX.Element;
177
+ //#endregion
178
+ //#region src/components/SunboardTooltips.d.ts
179
+ /**
180
+ * Renders at most one tooltip: the first visible candidate whose target
181
+ * resolves. A candidate whose selector never appears is skipped for the rest
182
+ * of the session (without recording a dismissal — the user rejected nothing),
183
+ * so one stale selector can't block the tooltips behind it.
184
+ */
185
+ declare function SunboardTooltips(): react_jsx_runtime0.JSX.Element | null;
139
186
  //#endregion
140
187
  //#region src/components/SunboardTour.d.ts
141
- declare function SunboardTour(): react_jsx_runtime1.JSX.Element | null;
188
+ declare function SunboardTour(): react_jsx_runtime0.JSX.Element | null;
142
189
  //#endregion
143
190
  //#region src/components/Sunboard.d.ts
144
- declare function SunboardChecklist(): react_jsx_runtime1.JSX.Element | null;
145
- declare function SunboardSurvey(): react_jsx_runtime1.JSX.Element | null;
191
+ declare function SunboardChecklist(): react_jsx_runtime0.JSX.Element | null;
192
+ declare function SunboardSurvey(): react_jsx_runtime0.JSX.Element | null;
146
193
  declare const Sunboard: typeof SunboardChecklist & {
147
194
  Checklist: typeof SunboardChecklist;
148
195
  Survey: typeof SunboardSurvey;
149
196
  Hotspots: typeof SunboardHotspots;
197
+ Tooltips: typeof SunboardTooltips;
150
198
  Tour: typeof SunboardTour;
151
199
  };
152
200
  //#endregion
@@ -234,5 +282,38 @@ type UseSurveyResult = {
234
282
  };
235
283
  declare function useSurvey(): UseSurveyResult;
236
284
  //#endregion
237
- export { type ChecklistViewStep, type RuntimeBootstrapRequest, type RuntimeBootstrapResponse, type RuntimeExperience, type RuntimeProgress, type RuntimeTrackRequest, type RuntimeTrackResponse, Sunboard, SunboardChecklist, type SunboardContextValue, SunboardHotspots, SunboardProvider, type SunboardProviderProps, SunboardRuntimeApiError, SunboardRuntimeClient, type SunboardRuntimeClientOptions, SunboardSurvey, SunboardTour, type SunboardUser, type SurveyResult, type SurveyViewOption, type SurveyViewQuestion, type SurveyViewStep, type TourResult, type TrackProperties, type TrackResult, type UseChecklistResult, type UseSurveyResult, useChecklist, useSunboard, useSurvey };
285
+ //#region src/hooks/useTooltips.d.ts
286
+ type TooltipView = {
287
+ key: string;
288
+ title: string;
289
+ body?: string;
290
+ /** CSS selector of the element the tooltip points at. */
291
+ target: string;
292
+ placement: SunboardPlacement;
293
+ /** True when a tour action is attached; `engage` starts it. */
294
+ hasAction: boolean;
295
+ actionLabel?: string;
296
+ /** True when the user asked for this tooltip via a checklist step. */
297
+ requested: boolean;
298
+ };
299
+ type UseTooltipsResult = {
300
+ /**
301
+ * Tooltips that qualify for the current route (undismissed, or explicitly
302
+ * requested). Render ONE at a time — the first whose target you can anchor.
303
+ */
304
+ tooltips: TooltipView[];
305
+ /** Report that a tooltip is actually on screen (deduped per session). */
306
+ markSeen: (key: string) => void;
307
+ /** Close without acting — the tooltip never shows again. */
308
+ dismiss: (key: string) => void;
309
+ /** Take the tooltip's action: starts its tour and retires the tooltip. */
310
+ engage: (key: string) => void;
311
+ };
312
+ /**
313
+ * Headless counterpart of `<SunboardTooltips>`: the same visibility, seen,
314
+ * dismissal, and engagement semantics with rendering left to the host.
315
+ */
316
+ declare function useTooltips(): UseTooltipsResult;
317
+ //#endregion
318
+ export { type ChecklistViewStep, type RuntimeBootstrapRequest, type RuntimeBootstrapResponse, type RuntimeExperience, type RuntimeProgress, type RuntimeTrackRequest, type RuntimeTrackResponse, Sunboard, SunboardChecklist, type SunboardContextValue, SunboardHotspots, SunboardProvider, type SunboardProviderProps, SunboardRuntimeApiError, SunboardRuntimeClient, type SunboardRuntimeClientOptions, SunboardSurvey, SunboardTooltips, SunboardTour, type SunboardUser, type SurveyResult, type SurveyViewOption, type SurveyViewQuestion, type SurveyViewStep, type TooltipResult, type TooltipView, type TourResult, type TrackProperties, type TrackResult, type UseChecklistResult, type UseSurveyResult, type UseTooltipsResult, type VisibleSunboardTooltip, useChecklist, useSunboard, useSurvey, useTooltips };
238
319
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/adapters/navigation.ts","../src/lib/detect-identities.ts","../src/hooks/sunboard-context.ts","../src/components/SunboardProvider.tsx","../src/components/SunboardHotspots.tsx","../src/components/SunboardTour.tsx","../src/components/Sunboard.tsx","../src/hooks/useSunboard.ts","../src/hooks/useChecklist.ts","../src/hooks/useSurvey.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/adapters/navigation.ts","../src/lib/detect-identities.ts","../src/hooks/sunboard-context.ts","../src/components/SunboardProvider.tsx","../src/components/SunboardHotspots.tsx","../src/components/SunboardTooltips.tsx","../src/components/SunboardTour.tsx","../src/components/Sunboard.tsx","../src/hooks/useSunboard.ts","../src/hooks/useChecklist.ts","../src/hooks/useSurvey.ts","../src/hooks/useTooltips.ts"],"sourcesContent":[],"mappings":"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"}
package/dist/index.mjs CHANGED
@@ -148,28 +148,32 @@ function SunboardProvider({ spec: specProp, user, loading: loadingProp, route, n
148
148
  }, [user, ownedAttributes]);
149
149
  const [completedStepKeys, setCompletedStepKeys] = useState(() => /* @__PURE__ */ new Set());
150
150
  const [completedTourKeys, setCompletedTourKeys] = useState(() => /* @__PURE__ */ new Set());
151
+ const [dismissedTooltipKeys, setDismissedTooltipKeys] = useState(() => /* @__PURE__ */ new Set());
151
152
  const [activeTourState, setActiveTourState] = useState(null);
153
+ const [requestedTooltipKey, setRequestedTooltipKey] = useState(null);
154
+ const seenTooltipKeys = useRef(/* @__PURE__ */ new Set());
152
155
  const lastNavigatedTourStep = useRef(null);
153
156
  const storageKey = !hostedMode && resolvedSpec && user ? completedToursStorageKey(resolvedSpec.key, user.id) : null;
157
+ const tooltipStorageKey = !hostedMode && resolvedSpec && user ? dismissedTooltipsStorageKey(resolvedSpec.key, user.id) : null;
154
158
  const experienceKey = activeSurvey?.key ?? activeExperience?.key ?? resolvedSpec?.key ?? null;
155
159
  const versionId = activeSurvey?.version.id ?? activeExperience?.version.id ?? null;
156
160
  useEffect(() => {
157
161
  setCompletedStepKeys(/* @__PURE__ */ new Set());
158
162
  setActiveTourState(null);
163
+ setRequestedTooltipKey(null);
164
+ seenTooltipKeys.current = /* @__PURE__ */ new Set();
159
165
  lastNavigatedTourStep.current = null;
160
- if (!storageKey) {
161
- setCompletedTourKeys(/* @__PURE__ */ new Set());
162
- return;
163
- }
164
- setCompletedTourKeys(readCompletedTours(storageKey));
166
+ setCompletedTourKeys(storageKey ? readStoredKeys(storageKey) : /* @__PURE__ */ new Set());
167
+ setDismissedTooltipKeys(tooltipStorageKey ? readStoredKeys(tooltipStorageKey) : /* @__PURE__ */ new Set());
165
168
  }, [
166
169
  resolvedSpec?.key,
167
170
  storageKey,
171
+ tooltipStorageKey,
168
172
  user?.id
169
173
  ]);
170
174
  useEffect(() => {
171
175
  if (!hostedMode || !activeExperience) return;
172
- applyProgress(activeExperience.progress, setCompletedStepKeys, setCompletedTourKeys);
176
+ applyProgress(activeExperience.progress, setCompletedStepKeys, setCompletedTourKeys, setDismissedTooltipKeys);
173
177
  }, [activeExperience, hostedMode]);
174
178
  const effectiveCompletedStepKeys = useMemo(() => {
175
179
  if (!hostedMode || !activeExperience) return completedStepKeys;
@@ -187,6 +191,14 @@ function SunboardProvider({ spec: specProp, user, loading: loadingProp, route, n
187
191
  completedTourKeys,
188
192
  hostedMode
189
193
  ]);
194
+ const effectiveDismissedTooltipKeys = useMemo(() => {
195
+ if (!hostedMode || !activeExperience) return dismissedTooltipKeys;
196
+ return mergeKeys(dismissedTooltipKeys, activeExperience.progress.dismissedTooltipKeys);
197
+ }, [
198
+ activeExperience,
199
+ dismissedTooltipKeys,
200
+ hostedMode
201
+ ]);
190
202
  useEffect(() => {
191
203
  if (!resolvedSpec) return;
192
204
  const tourCompletedStepKeys = (resolvedSpec.checklist?.steps ?? []).filter((step) => step.completeWhen?.tour && effectiveCompletedTourKeys.has(step.completeWhen.tour)).map((step) => step.key);
@@ -243,7 +255,7 @@ function SunboardProvider({ spec: specProp, user, loading: loadingProp, route, n
243
255
  setCompletedTourKeys((current) => {
244
256
  const next = new Set(current);
245
257
  next.add(tourKey);
246
- if (storageKey) writeCompletedTours(storageKey, next);
258
+ if (storageKey) writeStoredKeys(storageKey, next);
247
259
  return next;
248
260
  });
249
261
  }, [storageKey]);
@@ -269,7 +281,7 @@ function SunboardProvider({ spec: specProp, user, loading: loadingProp, route, n
269
281
  user: toRuntimeUser(user),
270
282
  versionId: versionId ?? void 0
271
283
  });
272
- if (response.progress) applyProgress(response.progress, setCompletedStepKeys, setCompletedTourKeys);
284
+ if (response.progress) applyProgress(response.progress, setCompletedStepKeys, setCompletedTourKeys, setDismissedTooltipKeys);
273
285
  } catch {
274
286
  networkOk = false;
275
287
  }
@@ -423,7 +435,7 @@ function SunboardProvider({ spec: specProp, user, loading: loadingProp, route, n
423
435
  tourKey,
424
436
  user: toRuntimeUser(user),
425
437
  versionId: versionId ?? void 0
426
- })).progress, setCompletedStepKeys, setCompletedTourKeys);
438
+ })).progress, setCompletedStepKeys, setCompletedTourKeys, setDismissedTooltipKeys);
427
439
  } catch {}
428
440
  }, [
429
441
  client,
@@ -468,10 +480,106 @@ function SunboardProvider({ spec: specProp, user, loading: loadingProp, route, n
468
480
  resolvedSpec,
469
481
  user
470
482
  ]);
483
+ const openTooltip = useCallback(async (tooltipKey) => {
484
+ if (resolvedLoading || !resolvedSpec) return {
485
+ ok: false,
486
+ reason: "not-ready"
487
+ };
488
+ if (!user) return {
489
+ ok: false,
490
+ reason: "missing-user"
491
+ };
492
+ if (!resolvedSpec.tooltips[tooltipKey]) return {
493
+ ok: false,
494
+ reason: "missing-tooltip"
495
+ };
496
+ setRequestedTooltipKey(tooltipKey);
497
+ return { ok: true };
498
+ }, [
499
+ resolvedLoading,
500
+ resolvedSpec,
501
+ user
502
+ ]);
503
+ const dismissTooltip = useCallback(async (tooltipKey, options) => {
504
+ if (resolvedLoading || !resolvedSpec) return {
505
+ ok: false,
506
+ reason: "not-ready"
507
+ };
508
+ if (!user) return {
509
+ ok: false,
510
+ reason: "missing-user"
511
+ };
512
+ if (!resolvedSpec.tooltips[tooltipKey]) return {
513
+ ok: false,
514
+ reason: "missing-tooltip"
515
+ };
516
+ const via = options?.via ?? "close";
517
+ setRequestedTooltipKey((current) => current === tooltipKey ? null : current);
518
+ setDismissedTooltipKeys((current) => {
519
+ const next = mergeKeys(current, [tooltipKey]);
520
+ if (tooltipStorageKey && next !== current) writeStoredKeys(tooltipStorageKey, next);
521
+ return next;
522
+ });
523
+ if (hostedMode && client && experienceKey) client.dismissTooltip({
524
+ experienceKey,
525
+ origin: currentOrigin,
526
+ route: currentRoute,
527
+ tooltipKey,
528
+ user: toRuntimeUser(user),
529
+ versionId: versionId ?? void 0,
530
+ via
531
+ }).catch(() => {});
532
+ return { ok: true };
533
+ }, [
534
+ client,
535
+ currentOrigin,
536
+ currentRoute,
537
+ experienceKey,
538
+ hostedMode,
539
+ resolvedLoading,
540
+ resolvedSpec,
541
+ tooltipStorageKey,
542
+ user,
543
+ versionId
544
+ ]);
545
+ const markTooltipSeen = useCallback((tooltipKey) => {
546
+ if (!resolvedSpec?.tooltips[tooltipKey] || seenTooltipKeys.current.has(tooltipKey)) return;
547
+ seenTooltipKeys.current.add(tooltipKey);
548
+ if (hostedMode && client && experienceKey && user) client.recordTooltipSeen({
549
+ experienceKey,
550
+ origin: currentOrigin,
551
+ route: currentRoute,
552
+ tooltipKey,
553
+ user: toRuntimeUser(user),
554
+ versionId: versionId ?? void 0
555
+ }).catch(() => {});
556
+ }, [
557
+ client,
558
+ currentOrigin,
559
+ currentRoute,
560
+ experienceKey,
561
+ hostedMode,
562
+ resolvedSpec,
563
+ user,
564
+ versionId
565
+ ]);
471
566
  const startChecklistStep = useCallback(async (step) => {
472
567
  if (step.action?.type === "startTour") return startTour(step.action.tour);
568
+ if (step.action?.type === "openTooltip") {
569
+ const tooltipKey = step.action.tooltip;
570
+ const destination = resolvedSpec?.tooltips[tooltipKey]?.route ?? step.route;
571
+ if (destination && !routeMatches(destination, currentRoute)) await navigateWithFallback(destination, navigate);
572
+ return openTooltip(tooltipKey);
573
+ }
473
574
  await navigateToStep(step);
474
- }, [navigateToStep, startTour]);
575
+ }, [
576
+ currentRoute,
577
+ navigate,
578
+ navigateToStep,
579
+ openTooltip,
580
+ resolvedSpec,
581
+ startTour
582
+ ]);
475
583
  const visibleHotspots = useMemo(() => {
476
584
  if (!resolvedSpec || activeTour) return [];
477
585
  return Object.entries(resolvedSpec.hotspots).filter(([, hotspot]) => routeMatches(hotspot.route, currentRoute)).filter(([, hotspot]) => hotspot.repeatable || !effectiveCompletedTourKeys.has(hotspot.action.tour)).map(([key, hotspot]) => ({
@@ -484,6 +592,29 @@ function SunboardProvider({ spec: specProp, user, loading: loadingProp, route, n
484
592
  currentRoute,
485
593
  resolvedSpec
486
594
  ]);
595
+ const visibleTooltips = useMemo(() => {
596
+ if (!resolvedSpec || activeTour) return [];
597
+ const requestedTooltip = requestedTooltipKey ? resolvedSpec.tooltips[requestedTooltipKey] : void 0;
598
+ if (requestedTooltipKey && requestedTooltip) {
599
+ if (!routeMatches(requestedTooltip.route, currentRoute)) return [];
600
+ return [{
601
+ key: requestedTooltipKey,
602
+ requested: true,
603
+ tooltip: requestedTooltip
604
+ }];
605
+ }
606
+ return Object.entries(resolvedSpec.tooltips).filter(([key, tooltip]) => routeMatches(tooltip.route, currentRoute) && !effectiveDismissedTooltipKeys.has(key)).map(([key, tooltip]) => ({
607
+ key,
608
+ requested: false,
609
+ tooltip
610
+ }));
611
+ }, [
612
+ activeTour,
613
+ currentRoute,
614
+ effectiveDismissedTooltipKeys,
615
+ requestedTooltipKey,
616
+ resolvedSpec
617
+ ]);
487
618
  const value = useMemo(() => ({
488
619
  spec: resolvedSpec,
489
620
  user: effectiveUser,
@@ -501,7 +632,12 @@ function SunboardProvider({ spec: specProp, user, loading: loadingProp, route, n
501
632
  advanceTour,
502
633
  navigateToStep,
503
634
  startChecklistStep,
504
- visibleHotspots
635
+ visibleHotspots,
636
+ dismissedTooltipKeys: effectiveDismissedTooltipKeys,
637
+ visibleTooltips,
638
+ openTooltip,
639
+ dismissTooltip,
640
+ markTooltipSeen
505
641
  }), [
506
642
  resolvedSpec,
507
643
  effectiveUser,
@@ -519,7 +655,12 @@ function SunboardProvider({ spec: specProp, user, loading: loadingProp, route, n
519
655
  advanceTour,
520
656
  navigateToStep,
521
657
  startChecklistStep,
522
- visibleHotspots
658
+ visibleHotspots,
659
+ effectiveDismissedTooltipKeys,
660
+ visibleTooltips,
661
+ openTooltip,
662
+ dismissTooltip,
663
+ markTooltipSeen
523
664
  ]);
524
665
  return /* @__PURE__ */ jsx(SunboardContext.Provider, {
525
666
  value,
@@ -639,9 +780,10 @@ function scheduleLateIdentityCapture(options) {
639
780
  function hasUnsentIdentity(detected, sent) {
640
781
  return Object.entries(detected).some(([provider, id]) => sent?.[provider] !== id);
641
782
  }
642
- function applyProgress(progress, setSteps, setTours) {
783
+ function applyProgress(progress, setSteps, setTours, setDismissedTooltips) {
643
784
  setSteps((current) => mergeKeys(current, progress.completedStepKeys));
644
785
  setTours((current) => mergeKeys(current, progress.completedTourKeys));
786
+ setDismissedTooltips?.((current) => mergeKeys(current, progress.dismissedTooltipKeys));
645
787
  }
646
788
  function mergeKeys(current, incoming) {
647
789
  if (incoming.length === 0) return current;
@@ -665,6 +807,9 @@ function toRuntimeUser(user) {
665
807
  function completedToursStorageKey(specKey, userId) {
666
808
  return `sunboard:${specKey}:${userId}:completed-tours`;
667
809
  }
810
+ function dismissedTooltipsStorageKey(specKey, userId) {
811
+ return `sunboard:${specKey}:${userId}:dismissed-tooltips`;
812
+ }
668
813
  function getBrowserRoute() {
669
814
  if (typeof window === "undefined") return "/";
670
815
  return `${window.location.pathname}${window.location.search}`;
@@ -673,7 +818,7 @@ function getBrowserOrigin() {
673
818
  if (typeof window === "undefined") return;
674
819
  return window.location.origin;
675
820
  }
676
- function readCompletedTours(storageKey) {
821
+ function readStoredKeys(storageKey) {
677
822
  if (typeof window === "undefined") return /* @__PURE__ */ new Set();
678
823
  try {
679
824
  const rawValue = window.localStorage.getItem(storageKey);
@@ -684,10 +829,10 @@ function readCompletedTours(storageKey) {
684
829
  return /* @__PURE__ */ new Set();
685
830
  }
686
831
  }
687
- function writeCompletedTours(storageKey, tourKeys) {
832
+ function writeStoredKeys(storageKey, keys) {
688
833
  if (typeof window === "undefined") return;
689
834
  try {
690
- window.localStorage.setItem(storageKey, JSON.stringify([...tourKeys].sort()));
835
+ window.localStorage.setItem(storageKey, JSON.stringify([...keys].sort()));
691
836
  } catch {}
692
837
  }
693
838
 
@@ -740,7 +885,8 @@ function useSunboard() {
740
885
  //#region src/hooks/useChecklist.ts
741
886
  function actionLabelFor(step) {
742
887
  if (step.action?.type === "startTour") return "Start";
743
- if (step.action || step.route) return "Open";
888
+ if (step.action?.type === "openTooltip") return "Show me";
889
+ if (step.route) return "Open";
744
890
  }
745
891
  function interpolateOptional$1(text, user) {
746
892
  if (!text) return void 0;
@@ -1115,6 +1261,109 @@ function Hotspot({ hotspot, hotspotKey }) {
1115
1261
  }) });
1116
1262
  }
1117
1263
 
1264
+ //#endregion
1265
+ //#region src/components/SunboardTooltips.tsx
1266
+ /**
1267
+ * Renders at most one tooltip: the first visible candidate whose target
1268
+ * resolves. A candidate whose selector never appears is skipped for the rest
1269
+ * of the session (without recording a dismissal — the user rejected nothing),
1270
+ * so one stale selector can't block the tooltips behind it.
1271
+ */
1272
+ function SunboardTooltips() {
1273
+ const { visibleTooltips } = useSunboard();
1274
+ const [skippedKeys, setSkippedKeys] = useState(() => /* @__PURE__ */ new Set());
1275
+ const active = visibleTooltips.find(({ key }) => !skippedKeys.has(key)) ?? null;
1276
+ if (!active) return null;
1277
+ return /* @__PURE__ */ jsx(Tooltip, {
1278
+ onTargetMissing: () => setSkippedKeys((current) => new Set(current).add(active.key)),
1279
+ requested: active.requested,
1280
+ tooltip: active.tooltip,
1281
+ tooltipKey: active.key
1282
+ }, active.key);
1283
+ }
1284
+ function Tooltip({ tooltip, tooltipKey, requested, onTargetMissing }) {
1285
+ const { dismissTooltip, markTooltipSeen, startTour } = useSunboard();
1286
+ const arrowRef = useRef(null);
1287
+ const title = useInterpolated(tooltip.title);
1288
+ const body = useInterpolated(tooltip.body);
1289
+ const actionLabel = useInterpolated(tooltip.actionLabel) ?? "Show me how";
1290
+ const target = useTargetElement(tooltip.target, true);
1291
+ const { context, refs, floatingStyles, update } = useFloating({
1292
+ placement: tooltip.placement,
1293
+ middleware: [
1294
+ offset(12),
1295
+ flip(),
1296
+ shift({ padding: 12 }),
1297
+ arrow({ element: arrowRef })
1298
+ ],
1299
+ whileElementsMounted: autoUpdate
1300
+ });
1301
+ useEffect(() => {
1302
+ if (!target.timedOut) return;
1303
+ onTargetMissing();
1304
+ }, [target.timedOut]);
1305
+ useEffect(() => {
1306
+ if (!target.element) return;
1307
+ refs.setReference(target.element);
1308
+ update();
1309
+ markTooltipSeen(tooltipKey);
1310
+ }, [
1311
+ markTooltipSeen,
1312
+ refs,
1313
+ target.element,
1314
+ tooltipKey,
1315
+ update
1316
+ ]);
1317
+ if (!target.element) return null;
1318
+ return /* @__PURE__ */ jsx(FloatingPortal, { children: /* @__PURE__ */ jsxs("section", {
1319
+ "aria-label": title,
1320
+ className: "sunboard-tooltip",
1321
+ "data-sunboard-tooltip": tooltipKey,
1322
+ "data-requested": requested,
1323
+ ref: refs.setFloating,
1324
+ role: "dialog",
1325
+ style: floatingStyles,
1326
+ children: [
1327
+ /* @__PURE__ */ jsx(FloatingArrow, {
1328
+ className: "sunboard-tooltip-arrow",
1329
+ context,
1330
+ fill: "var(--sunboard-tour-background)",
1331
+ ref: arrowRef,
1332
+ stroke: "var(--sunboard-tour-border)",
1333
+ strokeWidth: 1,
1334
+ tipRadius: 2
1335
+ }),
1336
+ /* @__PURE__ */ jsx("button", {
1337
+ "aria-label": `Dismiss ${title}`,
1338
+ className: "sunboard-tooltip-close",
1339
+ onClick: () => void dismissTooltip(tooltipKey),
1340
+ type: "button",
1341
+ children: "x"
1342
+ }),
1343
+ /* @__PURE__ */ jsx("h2", {
1344
+ className: "sunboard-tooltip-title",
1345
+ children: title
1346
+ }),
1347
+ body ? /* @__PURE__ */ jsx("p", {
1348
+ className: "sunboard-tooltip-body",
1349
+ children: body
1350
+ }) : null,
1351
+ tooltip.action ? /* @__PURE__ */ jsx("div", {
1352
+ className: "sunboard-tooltip-actions",
1353
+ children: /* @__PURE__ */ jsx("button", {
1354
+ className: "sunboard-tooltip-action",
1355
+ onClick: () => {
1356
+ dismissTooltip(tooltipKey, { via: "action" });
1357
+ startTour(tooltip.action.tour);
1358
+ },
1359
+ type: "button",
1360
+ children: actionLabel
1361
+ })
1362
+ }) : null
1363
+ ]
1364
+ }) });
1365
+ }
1366
+
1118
1367
  //#endregion
1119
1368
  //#region src/components/SunboardTour.tsx
1120
1369
  function SunboardTour() {
@@ -1524,9 +1773,45 @@ const Sunboard = Object.assign(SunboardChecklist, {
1524
1773
  Checklist: SunboardChecklist,
1525
1774
  Survey: SunboardSurvey,
1526
1775
  Hotspots: SunboardHotspots,
1776
+ Tooltips: SunboardTooltips,
1527
1777
  Tour: SunboardTour
1528
1778
  });
1529
1779
 
1530
1780
  //#endregion
1531
- export { Sunboard, SunboardChecklist, SunboardHotspots, SunboardProvider, SunboardRuntimeApiError, SunboardRuntimeClient, SunboardSurvey, SunboardTour, useChecklist, useSunboard, useSurvey };
1781
+ //#region src/hooks/useTooltips.ts
1782
+ /**
1783
+ * Headless counterpart of `<SunboardTooltips>`: the same visibility, seen,
1784
+ * dismissal, and engagement semantics with rendering left to the host.
1785
+ */
1786
+ function useTooltips() {
1787
+ const { user, visibleTooltips, markTooltipSeen, dismissTooltip, startTour } = useSunboard();
1788
+ return {
1789
+ tooltips: useMemo(() => visibleTooltips.map(({ key, tooltip, requested }) => ({
1790
+ key,
1791
+ title: interpolateTokens(tooltip.title, user ?? null),
1792
+ body: tooltip.body ? interpolateTokens(tooltip.body, user ?? null) : void 0,
1793
+ target: tooltip.target,
1794
+ placement: tooltip.placement,
1795
+ hasAction: Boolean(tooltip.action),
1796
+ actionLabel: tooltip.actionLabel ? interpolateTokens(tooltip.actionLabel, user ?? null) : void 0,
1797
+ requested
1798
+ })), [user, visibleTooltips]),
1799
+ markSeen: markTooltipSeen,
1800
+ dismiss: (key) => {
1801
+ dismissTooltip(key);
1802
+ },
1803
+ engage: useCallback((key) => {
1804
+ const entry = visibleTooltips.find((candidate) => candidate.key === key);
1805
+ dismissTooltip(key, { via: "action" });
1806
+ if (entry?.tooltip.action) startTour(entry.tooltip.action.tour);
1807
+ }, [
1808
+ dismissTooltip,
1809
+ startTour,
1810
+ visibleTooltips
1811
+ ])
1812
+ };
1813
+ }
1814
+
1815
+ //#endregion
1816
+ export { Sunboard, SunboardChecklist, SunboardHotspots, SunboardProvider, SunboardRuntimeApiError, SunboardRuntimeClient, SunboardSurvey, SunboardTooltips, SunboardTour, useChecklist, useSunboard, useSurvey, useTooltips };
1532
1817
  //# sourceMappingURL=index.mjs.map