@wireai/activation 0.13.2 → 0.13.5

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.
Files changed (82) hide show
  1. package/AGENTS.md +6 -3
  2. package/CHANGELOG.md +291 -4
  3. package/INTEGRATION_PROMPT.md +7 -1
  4. package/README.md +68 -2
  5. package/dist/analytics/index.d.mts +86 -6
  6. package/dist/analytics/index.d.ts +86 -6
  7. package/dist/analytics/index.js +271 -472
  8. package/dist/analytics/index.js.map +1 -1
  9. package/dist/analytics/index.mjs +269 -471
  10. package/dist/analytics/index.mjs.map +1 -1
  11. package/dist/coachmarks/index.d.mts +15 -2
  12. package/dist/coachmarks/index.d.ts +15 -2
  13. package/dist/coachmarks/index.js +58 -14
  14. package/dist/coachmarks/index.js.map +1 -1
  15. package/dist/coachmarks/index.mjs +58 -14
  16. package/dist/coachmarks/index.mjs.map +1 -1
  17. package/dist/{currentSession-ClkLjcJ0.d.mts → currentSession-DgJf0fRz.d.mts} +4 -4
  18. package/dist/{currentSession-DOVZEWJl.d.ts → currentSession-EOHU64QD.d.ts} +4 -4
  19. package/dist/{decision-Bl_M2y3r.d.mts → decision-Bgo17oH7.d.mts} +1 -1
  20. package/dist/{decision-Cau5KmP6.d.ts → decision-Bkh_LigV.d.ts} +1 -1
  21. package/dist/index.d.mts +27 -4
  22. package/dist/index.d.ts +27 -4
  23. package/dist/index.js +224 -575
  24. package/dist/index.js.map +1 -1
  25. package/dist/index.mjs +221 -572
  26. package/dist/index.mjs.map +1 -1
  27. package/dist/questionnaire/index.d.mts +43 -11
  28. package/dist/questionnaire/index.d.ts +43 -11
  29. package/dist/questionnaire/index.js +45 -13
  30. package/dist/questionnaire/index.js.map +1 -1
  31. package/dist/questionnaire/index.mjs +45 -13
  32. package/dist/questionnaire/index.mjs.map +1 -1
  33. package/dist/reviews/index.d.mts +5 -5
  34. package/dist/reviews/index.d.ts +5 -5
  35. package/dist/reviews/index.js +31 -9
  36. package/dist/reviews/index.js.map +1 -1
  37. package/dist/reviews/index.mjs +31 -9
  38. package/dist/reviews/index.mjs.map +1 -1
  39. package/dist/showcase/index.d.mts +1 -1
  40. package/dist/showcase/index.d.ts +1 -1
  41. package/dist/showcase/index.js +7 -2
  42. package/dist/showcase/index.js.map +1 -1
  43. package/dist/showcase/index.mjs +7 -2
  44. package/dist/showcase/index.mjs.map +1 -1
  45. package/dist/{transport-CF_eHwzC.d.mts → transport-B_0SgCBe.d.ts} +44 -5
  46. package/dist/{transport-DsRe4epC.d.ts → transport-j5gFfJhK.d.mts} +44 -5
  47. package/dist/{types-CKFhyrMu.d.mts → types-BpwiRpA8.d.mts} +1 -1
  48. package/dist/{types-CKFhyrMu.d.ts → types-BpwiRpA8.d.ts} +1 -1
  49. package/dist/{types-CNUqMK0D.d.mts → types-Cju-1_jT.d.mts} +42 -2
  50. package/dist/{types-Buj9Lw9t.d.ts → types-h2BZvl1t.d.ts} +42 -2
  51. package/llms.txt +1 -1
  52. package/package.json +6 -1
  53. package/src/OnboardingFlow.tsx +44 -15
  54. package/src/WireOnboarding.tsx +7 -6
  55. package/src/activation/revalidation.ts +9 -1
  56. package/src/activation/wireActivation.ts +3 -3
  57. package/src/analytics/analyticsFacade.ts +2 -2
  58. package/src/analytics/currentSession.ts +10 -0
  59. package/src/analytics/eventQueue.ts +88 -20
  60. package/src/analytics/index.ts +6 -0
  61. package/src/analytics/reportClientEvent.ts +29 -7
  62. package/src/analytics/wireDoctor.ts +330 -0
  63. package/src/cards/CardGridSelectCard.tsx +1 -1
  64. package/src/cards/ChipSelectCard.tsx +2 -2
  65. package/src/cards/SelectionCard.tsx +1 -1
  66. package/src/coachmarks/runtime.ts +72 -3
  67. package/src/coachmarks/useCoachmarkTour.ts +62 -14
  68. package/src/context/deviceId.ts +14 -5
  69. package/src/features/WireFeaturesProvider.tsx +12 -1
  70. package/src/identity/identityRecord.ts +9 -1
  71. package/src/identity/userIdentity.ts +1 -1
  72. package/src/questionnaire/QuestionnaireGate.tsx +90 -10
  73. package/src/questionnaire/index.ts +9 -1
  74. package/src/questionnaire/transport.ts +46 -11
  75. package/src/reviews/ReviewGate.tsx +61 -6
  76. package/src/reviews/index.ts +10 -1
  77. package/src/reviews/runtime.ts +11 -1
  78. package/src/reviews/transport.ts +58 -12
  79. package/src/session-analytics/useLifecycleEvents.ts +1 -1
  80. package/src/theme/ThemeContext.tsx +49 -1
  81. package/src/types.ts +1 -1
  82. package/src/utils/submitResult.ts +39 -0
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { ReactNode } from 'react';
3
- import { W as WireFeatures, a as WireFeaturesConfig } from '../types-CKFhyrMu.mjs';
3
+ import { a as WireFeatures, b as WireFeaturesConfig } from '../types-BpwiRpA8.mjs';
4
4
  import { C as CoachmarkStorage, a as CoachmarkStep, G as GestureKind, T as TargetRect, P as Placement } from '../types-BcmagF6K.mjs';
5
5
  import { View } from 'react-native';
6
6
 
@@ -121,6 +121,15 @@ interface UseCoachmarkTourOptions {
121
121
  * target is picked up. `onStepShown` is suppressed on that resume (last-shown
122
122
  * step id is tracked in a ref) so a pause/resume never double-counts a step.
123
123
  *
124
+ * KILL SWITCH vs PAUSE — two different gates, two different endings. `enabled` is the host's
125
+ * domain gate and PAUSES (position kept, gate unwritten, resumes on the same step). The tenant's
126
+ * coachmarks feature flag (`setCoachmarksEnabled`, from GET /v1/features) is TERMINAL: flipped off
127
+ * mid-tour it ends the tour and fires `onComplete`, but does NOT write the once-gate, so the tour
128
+ * replays on the next mount once the flag is back on. It is read through a subscription rather
129
+ * than sampled, because the flip has to reach a tour that is already in flight: the overlay's
130
+ * `show()` is a no-op while the flag is off, so a tour that carried on would paint nothing, could
131
+ * not be tapped to advance, and would never reach a terminal state.
132
+ *
124
133
  * IMPORTANT: `steps` MUST be a stable (memoized) array. If a new array identity
125
134
  * is passed on every render the drive effect re-runs and re-shows the current
126
135
  * step (wasteful anchor re-resolves / overlay churn), and analytics can
@@ -164,7 +173,11 @@ steps: CoachmarkStep[], { tourId, showOnce, enabled, startDelayMs, onComplete, o
164
173
 
165
174
  /**
166
175
  * Set the coachmarks master switch (from the resolved feature flags). Default true (fail-open).
167
- * Written by CoachmarkProvider; read imperatively by the tour arm + the overlay store.
176
+ * Written by CoachmarkProvider; read imperatively by the tour arm + the overlay store, and
177
+ * SUBSCRIBED to by `useCoachmarkTour` (see `subscribeCoachmarksEnabled`).
178
+ *
179
+ * No-ops when the value is unchanged, which matters because the provider writes it on every
180
+ * render — without that guard every render would fan out a notification.
168
181
  */
169
182
  declare const setCoachmarksEnabled: (value: boolean) => void;
170
183
  /** Whether the coachmarks module is enabled. False → tours/overlays are silently skipped. */
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import React__default, { ReactNode } from 'react';
3
- import { W as WireFeatures, a as WireFeaturesConfig } from '../types-CKFhyrMu.js';
3
+ import { a as WireFeatures, b as WireFeaturesConfig } from '../types-BpwiRpA8.js';
4
4
  import { C as CoachmarkStorage, a as CoachmarkStep, G as GestureKind, T as TargetRect, P as Placement } from '../types-BcmagF6K.js';
5
5
  import { View } from 'react-native';
6
6
 
@@ -121,6 +121,15 @@ interface UseCoachmarkTourOptions {
121
121
  * target is picked up. `onStepShown` is suppressed on that resume (last-shown
122
122
  * step id is tracked in a ref) so a pause/resume never double-counts a step.
123
123
  *
124
+ * KILL SWITCH vs PAUSE — two different gates, two different endings. `enabled` is the host's
125
+ * domain gate and PAUSES (position kept, gate unwritten, resumes on the same step). The tenant's
126
+ * coachmarks feature flag (`setCoachmarksEnabled`, from GET /v1/features) is TERMINAL: flipped off
127
+ * mid-tour it ends the tour and fires `onComplete`, but does NOT write the once-gate, so the tour
128
+ * replays on the next mount once the flag is back on. It is read through a subscription rather
129
+ * than sampled, because the flip has to reach a tour that is already in flight: the overlay's
130
+ * `show()` is a no-op while the flag is off, so a tour that carried on would paint nothing, could
131
+ * not be tapped to advance, and would never reach a terminal state.
132
+ *
124
133
  * IMPORTANT: `steps` MUST be a stable (memoized) array. If a new array identity
125
134
  * is passed on every render the drive effect re-runs and re-shows the current
126
135
  * step (wasteful anchor re-resolves / overlay churn), and analytics can
@@ -164,7 +173,11 @@ steps: CoachmarkStep[], { tourId, showOnce, enabled, startDelayMs, onComplete, o
164
173
 
165
174
  /**
166
175
  * Set the coachmarks master switch (from the resolved feature flags). Default true (fail-open).
167
- * Written by CoachmarkProvider; read imperatively by the tour arm + the overlay store.
176
+ * Written by CoachmarkProvider; read imperatively by the tour arm + the overlay store, and
177
+ * SUBSCRIBED to by `useCoachmarkTour` (see `subscribeCoachmarksEnabled`).
178
+ *
179
+ * No-ops when the value is unchanged, which matters because the provider writes it on every
180
+ * render — without that guard every render would fan out a notification.
168
181
  */
169
182
  declare const setCoachmarksEnabled: (value: boolean) => void;
170
183
  /** Whether the coachmarks module is enabled. False → tours/overlays are silently skipped. */
@@ -152,7 +152,7 @@ var useWireFeatures = (config) => {
152
152
  return flags;
153
153
  };
154
154
  var CONTEXT_SYMBOL = /* @__PURE__ */ Symbol.for("wireai.features.context");
155
- var globalObj = global;
155
+ var globalObj = globalThis;
156
156
  if (!globalObj[CONTEXT_SYMBOL]) {
157
157
  globalObj[CONTEXT_SYMBOL] = React3.createContext(null);
158
158
  }
@@ -176,10 +176,36 @@ var coachmarkRuntime = () => {
176
176
  runtimeGlobal[COACHMARK_RUNTIME_SLOT] = created;
177
177
  return created;
178
178
  };
179
+ var enabledListeners = () => {
180
+ const runtime = coachmarkRuntime();
181
+ if (!runtime.listeners) runtime.listeners = /* @__PURE__ */ new Set();
182
+ return runtime.listeners;
183
+ };
184
+ var notifyCoachmarksEnabled = () => {
185
+ if (enabledListeners().size === 0) return;
186
+ void Promise.resolve().then(() => {
187
+ for (const listener of [...enabledListeners()]) {
188
+ try {
189
+ listener();
190
+ } catch {
191
+ }
192
+ }
193
+ });
194
+ };
179
195
  var setCoachmarksEnabled = (value) => {
180
- coachmarkRuntime().coachmarksEnabled = value;
196
+ const runtime = coachmarkRuntime();
197
+ if (runtime.coachmarksEnabled === value) return;
198
+ runtime.coachmarksEnabled = value;
199
+ notifyCoachmarksEnabled();
181
200
  };
182
201
  var areCoachmarksEnabled = () => coachmarkRuntime().coachmarksEnabled;
202
+ var subscribeCoachmarksEnabled = (listener) => {
203
+ const listeners2 = enabledListeners();
204
+ listeners2.add(listener);
205
+ return () => {
206
+ listeners2.delete(listener);
207
+ };
208
+ };
183
209
  var setCoachmarkStorage = (storage) => {
184
210
  coachmarkRuntime().storage = storage;
185
211
  };
@@ -293,7 +319,12 @@ var defaultOnboardingTheme = {
293
319
  var mergeTheme = (override) => {
294
320
  return defaultOnboardingTheme;
295
321
  };
296
- var OnboardingThemeContext = React3.createContext(null);
322
+ var THEME_CONTEXT_SLOT = /* @__PURE__ */ Symbol.for("@wireai/activation:themeContext");
323
+ var themeGlobal = globalThis;
324
+ if (!themeGlobal[THEME_CONTEXT_SLOT]) {
325
+ themeGlobal[THEME_CONTEXT_SLOT] = React3.createContext(null);
326
+ }
327
+ var OnboardingThemeContext = themeGlobal[THEME_CONTEXT_SLOT];
297
328
  var useOnboardingTheme = () => {
298
329
  const ctx = React3.useContext(OnboardingThemeContext);
299
330
  return ctx != null ? ctx : mergeTheme();
@@ -838,26 +869,39 @@ var useCoachmarkTour = (steps, {
838
869
  const lastShownStepIdRef = React3.useRef(null);
839
870
  const callbacksRef = React3.useRef({ onStepShown, onStepEngaged, onStepDismissed });
840
871
  callbacksRef.current = { onStepShown, onStepEngaged, onStepDismissed };
841
- const finish = React3.useCallback(() => {
842
- if (finishedRef.current) return;
843
- finishedRef.current = true;
844
- if (showOnce) markSeenGate(coachmarkGateKey(tourId));
845
- coachmarkOverlay.hide();
846
- setActiveIndex(null);
847
- onComplete == null ? void 0 : onComplete();
848
- }, [onComplete, showOnce, tourId]);
872
+ const coachmarksOn = React3.useSyncExternalStore(
873
+ subscribeCoachmarksEnabled,
874
+ areCoachmarksEnabled,
875
+ areCoachmarksEnabled
876
+ );
877
+ const exit = React3.useCallback(
878
+ (writeGate) => {
879
+ if (finishedRef.current) return;
880
+ finishedRef.current = true;
881
+ if (writeGate && showOnce) markSeenGate(coachmarkGateKey(tourId));
882
+ coachmarkOverlay.hide();
883
+ setActiveIndex(null);
884
+ onComplete == null ? void 0 : onComplete();
885
+ },
886
+ [onComplete, showOnce, tourId]
887
+ );
888
+ const finish = React3.useCallback(() => exit(true), [exit]);
849
889
  React3.useEffect(() => {
850
890
  if (!enabled || startedRef.current) return void 0;
851
- if (!areCoachmarksEnabled()) return void 0;
891
+ if (!coachmarksOn) return void 0;
852
892
  if (showOnce && hasSeenGate(coachmarkGateKey(tourId))) return void 0;
853
893
  const timer = setTimeout(() => {
854
894
  startedRef.current = true;
855
895
  setActiveIndex(0);
856
896
  }, startDelayMs);
857
897
  return () => clearTimeout(timer);
858
- }, [enabled, startDelayMs, showOnce, tourId]);
898
+ }, [enabled, coachmarksOn, startDelayMs, showOnce, tourId]);
859
899
  React3.useEffect(() => {
860
900
  if (activeIndex === null) return void 0;
901
+ if (!coachmarksOn) {
902
+ exit(false);
903
+ return void 0;
904
+ }
861
905
  if (!enabled) {
862
906
  if (startedRef.current && !finishedRef.current) coachmarkOverlay.hide();
863
907
  return void 0;
@@ -907,7 +951,7 @@ var useCoachmarkTour = (steps, {
907
951
  return () => {
908
952
  cancelled = true;
909
953
  };
910
- }, [activeIndex, steps, finish, enabled]);
954
+ }, [activeIndex, steps, finish, exit, enabled, coachmarksOn]);
911
955
  React3.useEffect(
912
956
  () => () => {
913
957
  if (!finishedRef.current) coachmarkOverlay.hide();