@wireai/activation 0.12.0 → 0.12.2

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 (53) hide show
  1. package/AGENTS.md +13 -10
  2. package/CHANGELOG.md +130 -0
  3. package/INTEGRATION_PROMPT.md +14 -3
  4. package/README.md +40 -2
  5. package/dist/analytics/index.d.mts +5 -4
  6. package/dist/analytics/index.d.ts +5 -4
  7. package/dist/analytics/index.js +39 -24
  8. package/dist/analytics/index.js.map +1 -1
  9. package/dist/analytics/index.mjs +39 -24
  10. package/dist/analytics/index.mjs.map +1 -1
  11. package/dist/coachmarks/index.d.mts +16 -0
  12. package/dist/coachmarks/index.d.ts +16 -0
  13. package/dist/coachmarks/index.js +19 -13
  14. package/dist/coachmarks/index.js.map +1 -1
  15. package/dist/coachmarks/index.mjs +19 -13
  16. package/dist/coachmarks/index.mjs.map +1 -1
  17. package/dist/{currentSession-DsSDHqor.d.mts → currentSession-BlCeDP0f.d.mts} +59 -5
  18. package/dist/{currentSession-D6RiVtc8.d.ts → currentSession-BxEB37xt.d.ts} +59 -5
  19. package/dist/index.d.mts +10 -20
  20. package/dist/index.d.ts +10 -20
  21. package/dist/index.js +301 -187
  22. package/dist/index.js.map +1 -1
  23. package/dist/index.mjs +300 -188
  24. package/dist/index.mjs.map +1 -1
  25. package/dist/questionnaire/index.js +41 -19
  26. package/dist/questionnaire/index.js.map +1 -1
  27. package/dist/questionnaire/index.mjs +41 -19
  28. package/dist/questionnaire/index.mjs.map +1 -1
  29. package/dist/reviews/index.js +41 -19
  30. package/dist/reviews/index.js.map +1 -1
  31. package/dist/reviews/index.mjs +41 -19
  32. package/dist/reviews/index.mjs.map +1 -1
  33. package/dist/showcase/index.js +15 -6
  34. package/dist/showcase/index.js.map +1 -1
  35. package/dist/showcase/index.mjs +15 -6
  36. package/dist/showcase/index.mjs.map +1 -1
  37. package/llms.txt +2 -0
  38. package/package.json +1 -1
  39. package/src/WireOnboarding.tsx +140 -5
  40. package/src/activation/wireActivation.ts +8 -1
  41. package/src/analytics/analyticsFacade.ts +15 -11
  42. package/src/analytics/reportClientEvent.ts +11 -7
  43. package/src/coachmarks/runtime.ts +53 -17
  44. package/src/config/wireConfigFromEnv.ts +46 -2
  45. package/src/context/deviceId.ts +82 -18
  46. package/src/index.ts +9 -1
  47. package/src/questionnaire/runtime.ts +1 -0
  48. package/src/questionnaire/useQuestionnaireGate.ts +8 -3
  49. package/src/reviews/runtime.ts +68 -7
  50. package/src/reviews/useReviewGate.ts +8 -3
  51. package/src/session-analytics/useLifecycleEvents.ts +57 -27
  52. package/src/session-analytics/useSessionStart.ts +37 -1
  53. package/src/types.ts +41 -4
@@ -1081,14 +1081,21 @@ var styles6 = StyleSheet.create({
1081
1081
  });
1082
1082
 
1083
1083
  // src/coachmarks/runtime.ts
1084
- var storageSingleton = null;
1085
- var testing = false;
1086
- var getCoachmarkStorage = () => storageSingleton;
1087
- var isCoachmarkTesting = () => testing;
1084
+ var COACHMARK_RUNTIME_SLOT = /* @__PURE__ */ Symbol.for("@wireai/activation:coachmarkRuntime");
1085
+ var runtimeGlobal = globalThis;
1086
+ var coachmarkRuntime = () => {
1087
+ const existing = runtimeGlobal[COACHMARK_RUNTIME_SLOT];
1088
+ if (existing) return existing;
1089
+ const created = { storage: null, testing: false, coachmarksEnabled: true };
1090
+ runtimeGlobal[COACHMARK_RUNTIME_SLOT] = created;
1091
+ return created;
1092
+ };
1093
+ var getCoachmarkStorage = () => coachmarkRuntime().storage;
1094
+ var isCoachmarkTesting = () => coachmarkRuntime().testing;
1088
1095
  var SEEN_VALUE = "1";
1089
1096
  var hasSeenGate = (key, storageOverride, testingOverride) => {
1090
- if (testingOverride != null ? testingOverride : testing) return false;
1091
- const storage = storageOverride != null ? storageOverride : storageSingleton;
1097
+ if (testingOverride != null ? testingOverride : isCoachmarkTesting()) return false;
1098
+ const storage = storageOverride != null ? storageOverride : getCoachmarkStorage();
1092
1099
  if (!storage) return false;
1093
1100
  try {
1094
1101
  return storage.getItem(key) === SEEN_VALUE;
@@ -1097,8 +1104,8 @@ var hasSeenGate = (key, storageOverride, testingOverride) => {
1097
1104
  }
1098
1105
  };
1099
1106
  var markSeenGate = (key, storageOverride, testingOverride) => {
1100
- if (testingOverride != null ? testingOverride : testing) return;
1101
- const storage = storageOverride != null ? storageOverride : storageSingleton;
1107
+ if (testingOverride != null ? testingOverride : isCoachmarkTesting()) return;
1108
+ const storage = storageOverride != null ? storageOverride : getCoachmarkStorage();
1102
1109
  if (!storage) return;
1103
1110
  try {
1104
1111
  storage.setItem(key, SEEN_VALUE);
@@ -1286,6 +1293,20 @@ var reviewLastShownKey = (id) => `wire_review_${id}_last`;
1286
1293
  var reviewSessionsKey = (id) => `wire_review_${id}_sessions`;
1287
1294
  var reviewSessionOpenKey = (id) => `wire_review_${id}_open`;
1288
1295
  var resolveStorage = (override) => override != null ? override : getCoachmarkStorage();
1296
+ var NO_STORAGE_WARNED_SLOT = /* @__PURE__ */ Symbol.for(
1297
+ "@wireai/activation:gateStorageWarned"
1298
+ );
1299
+ var gateWarnGlobal = globalThis;
1300
+ var warnMissingGateStorage = (storage, gate) => {
1301
+ if (storage) return;
1302
+ if (gateWarnGlobal[NO_STORAGE_WARNED_SLOT]) return;
1303
+ if (typeof __DEV__ === "undefined" || !__DEV__) return;
1304
+ if (typeof console === "undefined" || !console.warn) return;
1305
+ gateWarnGlobal[NO_STORAGE_WARNED_SLOT] = true;
1306
+ console.warn(
1307
+ `[wireai] the ${gate} gate has no sync storage, so its app-open counter is stuck at 1 and the fail-closed minSessions rule can never be satisfied \u2014 the gate will never fire. Mount CoachmarkProvider with a sync storage adapter at your app root, or pass \`storage\` to the gate.`
1308
+ );
1309
+ };
1289
1310
  var readInt = (storage, key) => {
1290
1311
  if (!storage) return 0;
1291
1312
  try {
@@ -1315,13 +1336,12 @@ var readStr = (storage, key) => {
1315
1336
  var PROCESS_OPEN_ID_SLOT = /* @__PURE__ */ Symbol.for("@wireai/activation:processOpenId");
1316
1337
  var openIdGlobal = globalThis;
1317
1338
  var currentOpenId = () => {
1318
- const live = getCurrentSessionId();
1319
- if (live) return live;
1339
+ var _a;
1320
1340
  const existing = openIdGlobal[PROCESS_OPEN_ID_SLOT];
1321
1341
  if (existing) return existing;
1322
- const created = makeSessionId();
1323
- openIdGlobal[PROCESS_OPEN_ID_SLOT] = created;
1324
- return created;
1342
+ const resolved = (_a = getCurrentSessionId()) != null ? _a : makeSessionId();
1343
+ openIdGlobal[PROCESS_OPEN_ID_SLOT] = resolved;
1344
+ return resolved;
1325
1345
  };
1326
1346
  var bumpSessionCount = (storage, sessionsKey, openKey, openId = currentOpenId()) => {
1327
1347
  const lastOpen = readStr(storage, openKey);
@@ -1359,14 +1379,16 @@ var useReviewGate = ({
1359
1379
  (a, b) => sameDecision(a, b)
1360
1380
  );
1361
1381
  const featureEnabled = useResolvedFeatures({ flags: features, config: featuresConfig }).review.enabled;
1362
- const testing2 = isTesting != null ? isTesting : isCoachmarkTesting();
1382
+ const testing = isTesting != null ? isTesting : isCoachmarkTesting();
1363
1383
  const seenKey = reviewSeenKey(config.id, config.oncePerVersion === false ? void 0 : config.appVersion);
1364
1384
  const lastKey = reviewLastShownKey(config.id);
1365
1385
  const sessionsKey = reviewSessionsKey(config.id);
1366
1386
  const sessionOpenKey = reviewSessionOpenKey(config.id);
1367
- const sessions = useState(
1368
- () => bumpSessionCount(resolveStorage(storage), sessionsKey, sessionOpenKey)
1369
- )[0];
1387
+ const sessions = useState(() => {
1388
+ const store = resolveStorage(storage);
1389
+ warnMissingGateStorage(store, "review");
1390
+ return bumpSessionCount(store, sessionsKey, sessionOpenKey);
1391
+ })[0];
1370
1392
  const hasServerDecision = decision != null;
1371
1393
  const timeoutMs = config.timeoutFallbackMs;
1372
1394
  const waits = !hasServerDecision && timeoutMs != null && timeoutMs > 0;
@@ -1381,7 +1403,7 @@ var useReviewGate = ({
1381
1403
  }, [waits, timeoutMs]);
1382
1404
  const { visible, verdict } = useMemo(() => {
1383
1405
  if (!featureEnabled) return { visible: false, verdict: { fire: false, reason: "feature_disabled" } };
1384
- if (testing2) return { visible: true, verdict: { fire: true, reason: "testing" } };
1406
+ if (testing) return { visible: true, verdict: { fire: true, reason: "testing" } };
1385
1407
  const store = resolveStorage(storage);
1386
1408
  const local = evaluateGate(resolveRules(config), {
1387
1409
  sessions,
@@ -1394,7 +1416,7 @@ var useReviewGate = ({
1394
1416
  const alreadySeen = hasSeenGate(seenKey, storage, isTesting);
1395
1417
  const ready = hasServerDecision || elapsed;
1396
1418
  return { visible: ready && resolved.fire && !alreadySeen, verdict: resolved };
1397
- }, [featureEnabled, testing2, config, decision, events, sessions, elapsed, hasServerDecision, seenKey, lastKey, storage, isTesting]);
1419
+ }, [featureEnabled, testing, config, decision, events, sessions, elapsed, hasServerDecision, seenKey, lastKey, storage, isTesting]);
1398
1420
  const shownRef = useRef(false);
1399
1421
  const markShown = useCallback(() => {
1400
1422
  if (shownRef.current) return;