@wireai/activation 0.15.0 → 0.16.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/AGENTS.md +95 -20
- package/CHANGELOG.md +707 -0
- package/INTEGRATION_PROMPT.md +61 -23
- package/README.md +100 -25
- package/dist/analytics/index.d.mts +32 -10
- package/dist/analytics/index.d.ts +32 -10
- package/dist/analytics/index.js +288 -127
- package/dist/analytics/index.js.map +1 -1
- package/dist/analytics/index.mjs +288 -127
- package/dist/analytics/index.mjs.map +1 -1
- package/dist/coachmarks/index.d.mts +14 -0
- package/dist/coachmarks/index.d.ts +14 -0
- package/dist/coachmarks/index.js +73 -20
- package/dist/coachmarks/index.js.map +1 -1
- package/dist/coachmarks/index.mjs +73 -20
- package/dist/coachmarks/index.mjs.map +1 -1
- package/dist/{currentSession-orZy5p1e.d.mts → currentSession-Bz7G6lno.d.mts} +25 -35
- package/dist/{currentSession-CFSRZ2wg.d.ts → currentSession-z-CZ55ad.d.ts} +25 -35
- package/dist/index.d.mts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +125 -36
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +125 -36
- package/dist/index.mjs.map +1 -1
- package/dist/questionnaire/index.d.mts +0 -13
- package/dist/questionnaire/index.d.ts +0 -13
- package/dist/questionnaire/index.js +154 -43
- package/dist/questionnaire/index.js.map +1 -1
- package/dist/questionnaire/index.mjs +155 -44
- package/dist/questionnaire/index.mjs.map +1 -1
- package/dist/reviews/index.js +159 -91
- package/dist/reviews/index.js.map +1 -1
- package/dist/reviews/index.mjs +160 -92
- package/dist/reviews/index.mjs.map +1 -1
- package/dist/showcase/index.js +59 -18
- package/dist/showcase/index.js.map +1 -1
- package/dist/showcase/index.mjs +60 -19
- package/dist/showcase/index.mjs.map +1 -1
- package/llms.txt +9 -9
- package/package.json +6 -9
- package/src/analytics/currentSession.ts +141 -4
- package/src/analytics/index.ts +6 -1
- package/src/analytics/reportClientEvent.ts +19 -10
- package/src/analytics/useAnalytics.ts +74 -15
- package/src/analytics/wireDoctor.ts +152 -7
- package/src/coachmarks/CoachmarkProvider.tsx +26 -5
- package/src/coachmarks/runtime.ts +53 -0
- package/src/coachmarks/useCoachmarkTour.ts +51 -1
- package/src/context/deviceId.ts +49 -15
- package/src/features/WireFeaturesProvider.tsx +72 -12
- package/src/features/fetchWireFeatures.ts +49 -11
- package/src/features/useWireFeatures.ts +39 -3
- package/src/identity/identityRecord.ts +15 -2
- package/src/questionnaire/QuestionnaireGate.tsx +40 -1
- package/src/questionnaire/transport.ts +22 -8
- package/src/questionnaire/useQuestionnaireGate.ts +58 -7
- package/src/reviews/ReviewGate.tsx +39 -0
- package/src/reviews/idempotency.ts +38 -0
- package/src/reviews/runtime.ts +39 -10
- package/src/reviews/transport.ts +22 -8
- package/src/reviews/useReviewGate.ts +57 -7
- package/src/session-analytics/lifecycle.ts +16 -0
- package/src/session-analytics/useLifecycleEvents.ts +30 -2
- package/src/session-analytics/useSessionStart.ts +22 -2
- package/src/showcase/FeatureShowcase.tsx +50 -3
- package/src/types.ts +5 -4
- package/src/utils/withDeadline.ts +70 -0
package/dist/showcase/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { forwardRef, createElement, createContext, useEffect, useMemo, useRef, useCallback,
|
|
1
|
+
import React, { forwardRef, createElement, createContext, useEffect, useMemo, useState, useRef, useCallback, useContext, useReducer } from 'react';
|
|
2
2
|
import { View, StyleSheet, AccessibilityInfo } from 'react-native';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
|
|
@@ -528,17 +528,31 @@ var failOpen = async (storage, key) => {
|
|
|
528
528
|
const cached3 = await readCachedFeatures(storage, key);
|
|
529
529
|
return (_a = cached3 == null ? void 0 : cached3.features) != null ? _a : defaultWireFeatures;
|
|
530
530
|
};
|
|
531
|
-
var
|
|
531
|
+
var NO_ANSWER = /* @__PURE__ */ Symbol("wire-features-no-answer");
|
|
532
|
+
var fetchFeaturesJson = async (url, apiKey, timeoutMs) => {
|
|
532
533
|
const controller = typeof AbortController !== "undefined" ? new AbortController() : void 0;
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
534
|
+
let timer;
|
|
535
|
+
const expired = new Promise((resolve) => {
|
|
536
|
+
timer = setTimeout(() => {
|
|
537
|
+
controller == null ? void 0 : controller.abort();
|
|
538
|
+
resolve(NO_ANSWER);
|
|
539
|
+
}, timeoutMs);
|
|
540
|
+
});
|
|
541
|
+
const exchange = (async () => {
|
|
542
|
+
const res = await fetch(url, {
|
|
536
543
|
method: "GET",
|
|
537
544
|
headers: { Accept: "application/json", Authorization: `Bearer ${apiKey}` },
|
|
538
545
|
signal: controller == null ? void 0 : controller.signal
|
|
539
546
|
});
|
|
547
|
+
if (!res || !res.ok) return NO_ANSWER;
|
|
548
|
+
return await res.json();
|
|
549
|
+
})();
|
|
550
|
+
try {
|
|
551
|
+
return await Promise.race([exchange, expired]);
|
|
540
552
|
} finally {
|
|
541
553
|
clearTimeout(timer);
|
|
554
|
+
void exchange.catch(() => {
|
|
555
|
+
});
|
|
542
556
|
}
|
|
543
557
|
};
|
|
544
558
|
var fetchWireFeatures = async (config) => {
|
|
@@ -548,9 +562,8 @@ var fetchWireFeatures = async (config) => {
|
|
|
548
562
|
const url = `${config.serverUrl.replace(/\/$/, "")}/v1/features`;
|
|
549
563
|
const timeoutMs = config.timeoutMs && config.timeoutMs > 0 ? config.timeoutMs : DEFAULT_TIMEOUT_MS;
|
|
550
564
|
try {
|
|
551
|
-
const
|
|
552
|
-
if (
|
|
553
|
-
const json = await res.json();
|
|
565
|
+
const json = await fetchFeaturesJson(url, config.apiKey, timeoutMs);
|
|
566
|
+
if (json === NO_ANSWER) return failOpen(storage, key);
|
|
554
567
|
const features = parseWireFeatures(json);
|
|
555
568
|
if (storage) writeCachedFeatures(storage, key, features);
|
|
556
569
|
return features;
|
|
@@ -566,41 +579,56 @@ var useStableValue = (value, isEqual) => {
|
|
|
566
579
|
return ref.current;
|
|
567
580
|
};
|
|
568
581
|
var sameFetchKey = (a, b) => (a == null ? void 0 : a.serverUrl) === (b == null ? void 0 : b.serverUrl) && (a == null ? void 0 : a.apiKey) === (b == null ? void 0 : b.apiKey) && (a == null ? void 0 : a.appId) === (b == null ? void 0 : b.appId);
|
|
569
|
-
var
|
|
582
|
+
var useWireFeaturesState = (config) => {
|
|
570
583
|
const stableConfig = useStableValue(config, sameFetchKey);
|
|
571
584
|
const [flags, setFlags] = useState(defaultWireFeatures);
|
|
572
585
|
const canFetch = !!(stableConfig == null ? void 0 : stableConfig.serverUrl) && !!(stableConfig == null ? void 0 : stableConfig.apiKey);
|
|
586
|
+
const [settled, setSettled] = useState(!canFetch);
|
|
573
587
|
useEffect(() => {
|
|
574
588
|
if (!canFetch) {
|
|
575
589
|
setFlags((prev) => featuresEqual(prev, defaultWireFeatures) ? prev : defaultWireFeatures);
|
|
590
|
+
setSettled(true);
|
|
576
591
|
return;
|
|
577
592
|
}
|
|
578
593
|
let alive = true;
|
|
579
594
|
void fetchWireFeatures(stableConfig).then((next) => {
|
|
580
595
|
if (!alive) return;
|
|
581
596
|
setFlags((prev) => featuresEqual(prev, next) ? prev : next);
|
|
597
|
+
setSettled(true);
|
|
582
598
|
});
|
|
583
599
|
return () => {
|
|
584
600
|
alive = false;
|
|
585
601
|
};
|
|
586
602
|
}, [canFetch, stableConfig]);
|
|
587
|
-
return flags;
|
|
603
|
+
return useMemo(() => ({ flags, settled }), [flags, settled]);
|
|
588
604
|
};
|
|
589
605
|
var CONTEXT_SYMBOL = /* @__PURE__ */ Symbol.for("wireai.features.context");
|
|
590
|
-
var
|
|
591
|
-
if (!
|
|
592
|
-
|
|
606
|
+
var featuresContextGlobal = globalThis;
|
|
607
|
+
if (!featuresContextGlobal[CONTEXT_SYMBOL]) {
|
|
608
|
+
featuresContextGlobal[CONTEXT_SYMBOL] = createContext(null);
|
|
593
609
|
}
|
|
594
|
-
var WireFeaturesContext =
|
|
610
|
+
var WireFeaturesContext = featuresContextGlobal[CONTEXT_SYMBOL];
|
|
611
|
+
var SETTLED_SYMBOL = /* @__PURE__ */ Symbol.for("wireai.features.settled.context");
|
|
612
|
+
var settledContextGlobal = globalThis;
|
|
613
|
+
if (!settledContextGlobal[SETTLED_SYMBOL]) {
|
|
614
|
+
settledContextGlobal[SETTLED_SYMBOL] = createContext(true);
|
|
615
|
+
}
|
|
616
|
+
var WireFeaturesSettledContext = settledContextGlobal[SETTLED_SYMBOL];
|
|
595
617
|
var useWireFeaturesContext = () => useContext(WireFeaturesContext);
|
|
596
|
-
var
|
|
618
|
+
var useResolvedFeaturesState = (options) => {
|
|
597
619
|
var _a, _b, _c;
|
|
598
620
|
const ctx = useWireFeaturesContext();
|
|
621
|
+
const ctxSettled = useContext(WireFeaturesSettledContext);
|
|
599
622
|
const shouldFetch = !(options == null ? void 0 : options.flags) && ctx == null;
|
|
600
|
-
const fetched =
|
|
601
|
-
|
|
623
|
+
const fetched = useWireFeaturesState(shouldFetch ? options == null ? void 0 : options.config : void 0);
|
|
624
|
+
const flags = (_c = (_b = (_a = options == null ? void 0 : options.flags) != null ? _a : ctx) != null ? _b : fetched.flags) != null ? _c : defaultWireFeatures;
|
|
625
|
+
const settled = (options == null ? void 0 : options.flags) ? true : ctx != null ? ctxSettled : fetched.settled;
|
|
626
|
+
return useMemo(() => ({ flags, settled }), [flags, settled]);
|
|
602
627
|
};
|
|
603
628
|
|
|
629
|
+
// src/session/persistedSession.ts
|
|
630
|
+
var READ_TIMEOUT_MS2 = 1500;
|
|
631
|
+
|
|
604
632
|
// src/theme/defaultTheme.ts
|
|
605
633
|
var defaultOnboardingTheme = {
|
|
606
634
|
colors: {
|
|
@@ -760,7 +788,10 @@ var _FeatureShowcase = ({
|
|
|
760
788
|
[active, themeOverride]
|
|
761
789
|
);
|
|
762
790
|
const accent = accentColor != null ? accentColor : t.colors.primary;
|
|
763
|
-
const
|
|
791
|
+
const { flags, settled } = useResolvedFeaturesState({
|
|
792
|
+
flags: features,
|
|
793
|
+
config: featuresConfig
|
|
794
|
+
});
|
|
764
795
|
const disabled = !flags.showcase.enabled;
|
|
765
796
|
const Onboarding = useMemo(() => resolveShowcaseOnboarding(), []);
|
|
766
797
|
const gateKey = showcaseGateKey(config.id);
|
|
@@ -769,6 +800,14 @@ var _FeatureShowcase = ({
|
|
|
769
800
|
[gateKey, storage, isTesting]
|
|
770
801
|
);
|
|
771
802
|
const skip = seen || disabled || !Onboarding;
|
|
803
|
+
const flagsCouldMatter = !seen && !!Onboarding;
|
|
804
|
+
const [holdExpired, setHoldExpired] = useState(false);
|
|
805
|
+
useEffect(() => {
|
|
806
|
+
if (settled || holdExpired || !flagsCouldMatter) return void 0;
|
|
807
|
+
const timer = setTimeout(() => setHoldExpired(true), READ_TIMEOUT_MS2);
|
|
808
|
+
return () => clearTimeout(timer);
|
|
809
|
+
}, [settled, holdExpired, flagsCouldMatter]);
|
|
810
|
+
const holding = flagsCouldMatter && !settled && !holdExpired;
|
|
772
811
|
const doneRef = useRef(false);
|
|
773
812
|
const finish = useCallback(() => {
|
|
774
813
|
if (doneRef.current) return;
|
|
@@ -777,11 +816,12 @@ var _FeatureShowcase = ({
|
|
|
777
816
|
onDone();
|
|
778
817
|
}, [gateKey, storage, isTesting, onDone]);
|
|
779
818
|
useEffect(() => {
|
|
819
|
+
if (holding) return;
|
|
780
820
|
if (skip && !doneRef.current) {
|
|
781
821
|
doneRef.current = true;
|
|
782
822
|
onDone();
|
|
783
823
|
}
|
|
784
|
-
}, [skip, onDone]);
|
|
824
|
+
}, [holding, skip, onDone]);
|
|
785
825
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
786
826
|
const steps = useMemo(
|
|
787
827
|
() => config.slides.map((slide) => {
|
|
@@ -848,6 +888,7 @@ var _FeatureShowcase = ({
|
|
|
848
888
|
}),
|
|
849
889
|
[t]
|
|
850
890
|
);
|
|
891
|
+
if (holding) return null;
|
|
851
892
|
if (skip || !Onboarding) return null;
|
|
852
893
|
const activeGesture = (_a = config.slides[activeIndex]) == null ? void 0 : _a.gesture;
|
|
853
894
|
const showGesture = !!activeGesture && activeGesture !== "none" && activeGesture !== "tap" && activeGesture !== "double_tap";
|