@wireai/activation 0.3.0 → 0.7.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 +1 -1
- package/CHANGELOG.md +57 -0
- package/dist/analytics/index.d.mts +15 -2
- package/dist/analytics/index.d.ts +15 -2
- package/dist/analytics/index.js +224 -14
- package/dist/analytics/index.js.map +1 -1
- package/dist/analytics/index.mjs +222 -15
- package/dist/analytics/index.mjs.map +1 -1
- package/dist/coachmarks/index.js +6 -1
- package/dist/coachmarks/index.js.map +1 -1
- package/dist/coachmarks/index.mjs +6 -1
- package/dist/coachmarks/index.mjs.map +1 -1
- package/dist/{eventQueue-CA1d8Fmn.d.mts → currentSession-BJBB7i4-.d.mts} +143 -15
- package/dist/{eventQueue-CrNB9gzH.d.ts → currentSession-CxnP7gAa.d.ts} +143 -15
- package/dist/index.d.mts +40 -39
- package/dist/index.d.ts +40 -39
- package/dist/index.js +378 -154
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +370 -156
- package/dist/index.mjs.map +1 -1
- package/dist/questionnaire/index.d.mts +1 -1
- package/dist/questionnaire/index.d.ts +1 -1
- package/dist/questionnaire/index.js +29 -5
- package/dist/questionnaire/index.js.map +1 -1
- package/dist/questionnaire/index.mjs +30 -6
- package/dist/questionnaire/index.mjs.map +1 -1
- package/dist/reviews/index.d.mts +1 -1
- package/dist/reviews/index.d.ts +1 -1
- package/dist/reviews/index.js +40 -9
- package/dist/reviews/index.js.map +1 -1
- package/dist/reviews/index.mjs +42 -11
- package/dist/reviews/index.mjs.map +1 -1
- package/dist/showcase/index.d.mts +1 -14
- package/dist/showcase/index.d.ts +1 -14
- package/dist/showcase/index.js +8 -2
- package/dist/showcase/index.js.map +1 -1
- package/dist/showcase/index.mjs +8 -2
- package/dist/showcase/index.mjs.map +1 -1
- package/package.json +3 -2
- package/src/OnboardingFlow.tsx +8 -4
- package/src/WireOnboarding.tsx +12 -6
- package/src/analytics/analyticsFacade.ts +86 -10
- package/src/analytics/contextEnvelope.ts +13 -7
- package/src/analytics/currentSession.ts +35 -0
- package/src/analytics/eventQueue.ts +5 -0
- package/src/analytics/index.ts +3 -0
- package/src/analytics/useAnalytics.ts +7 -1
- package/src/analytics/useScreenTracking.ts +23 -1
- package/src/cards/InterstitialCard.tsx +1 -1
- package/src/cards/NumberStepperCard.tsx +12 -7
- package/src/cards/StatusCard.tsx +13 -8
- package/src/cards/TextInputCard.tsx +10 -5
- package/src/components/AnimatedSparkle.tsx +20 -3
- package/src/components/Button.tsx +10 -1
- package/src/components/CardHandoff.tsx +2 -6
- package/src/components/CardLayout.tsx +16 -10
- package/src/components/Illustration.tsx +9 -5
- package/src/components/LoadingBlock.tsx +44 -29
- package/src/components/LoadingScreen.tsx +3 -2
- package/src/components/OnboardingScaffold.tsx +21 -23
- package/src/context/userContext.ts +210 -0
- package/src/device/appVersion.ts +103 -0
- package/src/device/deviceContext.ts +17 -5
- package/src/features/WireFeaturesProvider.tsx +7 -2
- package/src/identity/userIdentity.ts +5 -0
- package/src/index.ts +23 -0
- package/src/questionnaire/QuestionnaireGate.tsx +15 -3
- package/src/reviews/ReviewGate.tsx +27 -7
- package/src/reviews/ReviewModal.tsx +4 -0
- package/src/session-analytics/reportSessionStart.ts +7 -0
- package/src/session-analytics/useLifecycleEvents.ts +4 -2
- package/src/session-analytics/useSessionStart.ts +2 -1
- package/src/showcase/FeatureShowcase.tsx +2 -1
- package/src/types.ts +6 -5
- package/src/components/loaderChrome.ts +0 -28
package/dist/index.js
CHANGED
|
@@ -12,6 +12,12 @@ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
|
12
12
|
var React14__default = /*#__PURE__*/_interopDefault(React14);
|
|
13
13
|
|
|
14
14
|
var __defProp = Object.defineProperty;
|
|
15
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
16
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
17
|
+
}) : x)(function(x) {
|
|
18
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
19
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
20
|
+
});
|
|
15
21
|
var __export = (target, all) => {
|
|
16
22
|
for (var name in all)
|
|
17
23
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -85,11 +91,15 @@ var useOnboardingTheme = () => {
|
|
|
85
91
|
const ctx = React14.useContext(OnboardingThemeContext);
|
|
86
92
|
return ctx != null ? ctx : mergeTheme();
|
|
87
93
|
};
|
|
88
|
-
var
|
|
94
|
+
var EMPTY_REGISTRY = {};
|
|
95
|
+
var IllustrationContext = React14.createContext(EMPTY_REGISTRY);
|
|
89
96
|
var IllustrationProvider = ({
|
|
90
97
|
registry,
|
|
91
98
|
children
|
|
92
|
-
}) =>
|
|
99
|
+
}) => {
|
|
100
|
+
const value = React14.useMemo(() => registry != null ? registry : EMPTY_REGISTRY, [registry]);
|
|
101
|
+
return /* @__PURE__ */ jsxRuntime.jsx(IllustrationContext.Provider, { value, children });
|
|
102
|
+
};
|
|
93
103
|
var useIllustration = (name) => {
|
|
94
104
|
const registry = React14.useContext(IllustrationContext);
|
|
95
105
|
if (!name) return void 0;
|
|
@@ -380,23 +390,33 @@ var _AnimatedSparkle = ({ size = 30, color, variant = "spin" }) => {
|
|
|
380
390
|
outputRange: [1, LOADER_PULSE_MIN_OPACITY]
|
|
381
391
|
});
|
|
382
392
|
const animatedStyle = reduced ? void 0 : variant === "pulse" ? { opacity: pulse } : { transform: [{ rotate }] };
|
|
383
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: animatedStyle, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
393
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: [styles2.box, { width: size, height: size }, animatedStyle], children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
384
394
|
reactNative.Text,
|
|
385
395
|
{
|
|
386
396
|
accessibilityElementsHidden: true,
|
|
387
397
|
importantForAccessibility: "no",
|
|
388
|
-
style: [
|
|
398
|
+
style: [
|
|
399
|
+
styles2.glyph,
|
|
400
|
+
{
|
|
401
|
+
width: size,
|
|
402
|
+
fontSize: size,
|
|
403
|
+
lineHeight: size,
|
|
404
|
+
color: color != null ? color : t.colors.primary
|
|
405
|
+
}
|
|
406
|
+
],
|
|
389
407
|
children: "\u2726"
|
|
390
408
|
}
|
|
391
409
|
) });
|
|
392
410
|
};
|
|
393
411
|
var AnimatedSparkle = React14__default.default.memo(_AnimatedSparkle);
|
|
394
412
|
var styles2 = reactNative.StyleSheet.create({
|
|
395
|
-
|
|
413
|
+
box: { alignItems: "center", justifyContent: "center" },
|
|
414
|
+
glyph: {
|
|
415
|
+
textAlign: "center",
|
|
416
|
+
textAlignVertical: "center",
|
|
417
|
+
includeFontPadding: false
|
|
418
|
+
}
|
|
396
419
|
});
|
|
397
|
-
var LoaderChromeContext = React14.createContext({ offsetY: 0 });
|
|
398
|
-
var LoaderChromeProvider = LoaderChromeContext.Provider;
|
|
399
|
-
var useLoaderChrome = () => React14.useContext(LoaderChromeContext);
|
|
400
420
|
var STAGE_SIZE = 96;
|
|
401
421
|
var ORBIT_DOT = 9;
|
|
402
422
|
var OrbitDot = ({ color, reduced }) => {
|
|
@@ -460,39 +480,45 @@ var _LoadingBlock = ({
|
|
|
460
480
|
}) => {
|
|
461
481
|
const t = useOnboardingTheme();
|
|
462
482
|
const reduced = useReducedMotion();
|
|
463
|
-
const { offsetY } = useLoaderChrome();
|
|
464
483
|
const [showSkeleton, setShowSkeleton] = React14.useState(false);
|
|
465
484
|
React14.useEffect(() => {
|
|
466
485
|
const timer = setTimeout(() => setShowSkeleton(true), SKELETON_DELAY_MS);
|
|
467
486
|
return () => clearTimeout(timer);
|
|
468
487
|
}, []);
|
|
469
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
470
|
-
reactNative.View,
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
/* @__PURE__ */ jsxRuntime.
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
488
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles3.center, { padding: t.spacing.lg }], children: [
|
|
489
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles3.stage, children: [
|
|
490
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles3.ring, { borderColor: t.colors.border, borderRadius: t.radius.full }] }),
|
|
491
|
+
/* @__PURE__ */ jsxRuntime.jsx(OrbitDot, { color: t.colors.primary, reduced }),
|
|
492
|
+
/* @__PURE__ */ jsxRuntime.jsx(AnimatedSparkle, { size: 40, variant: "pulse" })
|
|
493
|
+
] }),
|
|
494
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
495
|
+
reactNative.View,
|
|
496
|
+
{
|
|
497
|
+
style: [
|
|
498
|
+
styles3.labels,
|
|
499
|
+
{ marginTop: STAGE_SIZE / 2 + t.spacing.lg, gap: t.spacing.md, paddingHorizontal: t.spacing.lg }
|
|
500
|
+
],
|
|
501
|
+
pointerEvents: "none",
|
|
502
|
+
children: [
|
|
503
|
+
title ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [headingStyle(t.fonts), { color: t.colors.text, textAlign: "center" }], children: title }) : null,
|
|
504
|
+
hint ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [bodyStyle(t.fonts), { color: t.colors.textMuted, textAlign: "center" }], children: hint }) : null,
|
|
505
|
+
showSkeleton ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles3.skeleton, { gap: t.spacing.sm, marginTop: t.spacing.sm }], children: [
|
|
506
|
+
/* @__PURE__ */ jsxRuntime.jsx(SkeletonLine, { width: "80%", delay: 0, color: t.colors.surface, reduced }),
|
|
507
|
+
/* @__PURE__ */ jsxRuntime.jsx(SkeletonLine, { width: "60%", delay: 200, color: t.colors.surface, reduced })
|
|
508
|
+
] }) : null
|
|
509
|
+
]
|
|
510
|
+
}
|
|
511
|
+
)
|
|
512
|
+
] });
|
|
492
513
|
};
|
|
493
514
|
var LoadingBlock = React14__default.default.memo(_LoadingBlock);
|
|
494
515
|
var styles3 = reactNative.StyleSheet.create({
|
|
495
516
|
center: { flex: 1, alignItems: "center", justifyContent: "center" },
|
|
517
|
+
// Absolutely-positioned label column, pinned just under the centered stage: its top
|
|
518
|
+
// edge starts at the flow center (top: 50%) and the inline marginTop (STAGE_SIZE/2 +
|
|
519
|
+
// a gap) drops it below the stage. Out of flow → it never moves the stage, so the
|
|
520
|
+
// 300ms skeleton reveal grows DOWNWARD only and the icon stays centered.
|
|
521
|
+
labels: { position: "absolute", top: "50%", left: 0, right: 0, alignItems: "center" },
|
|
496
522
|
stage: {
|
|
497
523
|
width: STAGE_SIZE,
|
|
498
524
|
height: STAGE_SIZE,
|
|
@@ -575,7 +601,6 @@ var styles5 = reactNative.StyleSheet.create({
|
|
|
575
601
|
track: { height: 6, width: "100%", overflow: "hidden" },
|
|
576
602
|
fill: { height: 6 }
|
|
577
603
|
});
|
|
578
|
-
var PROGRESS_TRACK = 6;
|
|
579
604
|
var _OnboardingScaffold = ({
|
|
580
605
|
step,
|
|
581
606
|
complete,
|
|
@@ -587,33 +612,41 @@ var _OnboardingScaffold = ({
|
|
|
587
612
|
children
|
|
588
613
|
}) => {
|
|
589
614
|
const t = useOnboardingTheme();
|
|
615
|
+
const styles16 = React14.useMemo(() => makeStyles(t), [t]);
|
|
590
616
|
const hit = { top: 12, bottom: 12, left: 12, right: 12 };
|
|
591
|
-
const topChrome = t.spacing.md + PROGRESS_TRACK + t.spacing.md;
|
|
592
|
-
const loaderOffsetY = -Math.round(topChrome / 2);
|
|
593
617
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
594
618
|
reactNativeSafeAreaContext.SafeAreaView,
|
|
595
619
|
{
|
|
596
620
|
edges: ["top", "bottom"],
|
|
597
|
-
style: [
|
|
621
|
+
style: [styles16.flex, { backgroundColor: t.colors.background }],
|
|
598
622
|
children: [
|
|
599
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [
|
|
600
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
601
|
-
onSkip ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { onPress: onSkip, hitSlop: hit, style:
|
|
623
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles16.header, { paddingHorizontal: t.spacing.md, paddingTop: t.spacing.md }], children: [
|
|
624
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles16.progressWrap, children: /* @__PURE__ */ jsxRuntime.jsx(StepProgress, { step, complete, approxScreens }) }),
|
|
625
|
+
onSkip ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { onPress: onSkip, hitSlop: hit, style: styles16.skip, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [bodyStyle(t.fonts), { color: t.colors.textMuted }], children: skipLabel }) }) : null
|
|
602
626
|
] }),
|
|
603
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
604
|
-
|
|
627
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
628
|
+
reactNative.View,
|
|
629
|
+
{
|
|
630
|
+
style: [styles16.body, { paddingHorizontal: t.spacing.md, paddingTop: t.spacing.md }],
|
|
631
|
+
children
|
|
632
|
+
}
|
|
633
|
+
),
|
|
634
|
+
onBack ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles16.footer, { paddingHorizontal: t.spacing.md, paddingBottom: t.spacing.sm }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { onPress: onBack, hitSlop: hit, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [bodyStyle(t.fonts), { color: t.colors.textMuted }], children: backLabel }) }) }) : null
|
|
605
635
|
]
|
|
606
636
|
}
|
|
607
637
|
);
|
|
608
638
|
};
|
|
609
639
|
var OnboardingScaffold = React14__default.default.memo(_OnboardingScaffold);
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
}
|
|
640
|
+
function makeStyles(t) {
|
|
641
|
+
return reactNative.StyleSheet.create({
|
|
642
|
+
flex: { flex: 1 },
|
|
643
|
+
header: { flexDirection: "row", alignItems: "center" },
|
|
644
|
+
progressWrap: { flex: 1 },
|
|
645
|
+
body: { flex: 1 },
|
|
646
|
+
footer: { flexDirection: "row", justifyContent: "flex-start" },
|
|
647
|
+
skip: { marginLeft: t.spacing.md }
|
|
648
|
+
});
|
|
649
|
+
}
|
|
617
650
|
var _Button = ({
|
|
618
651
|
title,
|
|
619
652
|
onPress,
|
|
@@ -644,6 +677,14 @@ var _Button = ({
|
|
|
644
677
|
},
|
|
645
678
|
[pressT, reduced]
|
|
646
679
|
);
|
|
680
|
+
const lastPress = React14.useRef(0);
|
|
681
|
+
const handlePress = React14.useCallback(() => {
|
|
682
|
+
if (!onPress) return;
|
|
683
|
+
const now = Date.now();
|
|
684
|
+
if (now - lastPress.current < 500) return;
|
|
685
|
+
lastPress.current = now;
|
|
686
|
+
onPress();
|
|
687
|
+
}, [onPress]);
|
|
647
688
|
const handlePressIn = React14.useCallback(() => pressTo(1), [pressTo]);
|
|
648
689
|
const handlePressOut = React14.useCallback(() => pressTo(0), [pressTo]);
|
|
649
690
|
const scale = pressT.interpolate({
|
|
@@ -657,19 +698,19 @@ var _Button = ({
|
|
|
657
698
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
658
699
|
reactNative.Pressable,
|
|
659
700
|
{
|
|
660
|
-
onPress: disabled ? void 0 :
|
|
701
|
+
onPress: disabled ? void 0 : handlePress,
|
|
661
702
|
onPressIn: disabled ? void 0 : handlePressIn,
|
|
662
703
|
onPressOut: disabled ? void 0 : handlePressOut,
|
|
663
704
|
disabled,
|
|
664
705
|
accessibilityRole: "button",
|
|
665
706
|
accessibilityState: { disabled },
|
|
666
|
-
style: fullWidth ?
|
|
707
|
+
style: fullWidth ? styles6.fill : void 0,
|
|
667
708
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
668
709
|
reactNative.Animated.View,
|
|
669
710
|
{
|
|
670
711
|
style: [
|
|
671
|
-
|
|
672
|
-
fullWidth &&
|
|
712
|
+
styles6.base,
|
|
713
|
+
fullWidth && styles6.fill,
|
|
673
714
|
{
|
|
674
715
|
borderRadius: t.button.radius,
|
|
675
716
|
minHeight: t.button.height,
|
|
@@ -697,7 +738,7 @@ var _Button = ({
|
|
|
697
738
|
);
|
|
698
739
|
};
|
|
699
740
|
var Button = React14__default.default.memo(_Button);
|
|
700
|
-
var
|
|
741
|
+
var styles6 = reactNative.StyleSheet.create({
|
|
701
742
|
base: { alignItems: "center", justifyContent: "center" },
|
|
702
743
|
fill: { width: "100%" }
|
|
703
744
|
});
|
|
@@ -708,14 +749,14 @@ var _ErrorBlock = ({
|
|
|
708
749
|
onRetry
|
|
709
750
|
}) => {
|
|
710
751
|
const t = useOnboardingTheme();
|
|
711
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [
|
|
752
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles7.center, { gap: t.spacing.md, padding: t.spacing.lg }], children: [
|
|
712
753
|
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [headingStyle(t.fonts), { color: t.colors.text, textAlign: "center" }], children: title }),
|
|
713
754
|
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [bodyStyle(t.fonts), { color: t.colors.textMuted, textAlign: "center" }], children: message }),
|
|
714
755
|
onRetry ? /* @__PURE__ */ jsxRuntime.jsx(Button, { title: retryLabel, onPress: onRetry, variant: "outline" }) : null
|
|
715
756
|
] });
|
|
716
757
|
};
|
|
717
758
|
var ErrorBlock = React14__default.default.memo(_ErrorBlock);
|
|
718
|
-
var
|
|
759
|
+
var styles7 = reactNative.StyleSheet.create({
|
|
719
760
|
center: { flex: 1, alignItems: "center", justifyContent: "center" }
|
|
720
761
|
});
|
|
721
762
|
var _CardLayout = ({
|
|
@@ -727,9 +768,10 @@ var _CardLayout = ({
|
|
|
727
768
|
titleNode
|
|
728
769
|
}) => {
|
|
729
770
|
const t = useOnboardingTheme();
|
|
771
|
+
const styles16 = React14.useMemo(() => makeStyles2(t), [t]);
|
|
730
772
|
const hasHeader = !!title || !!subtitle || !!titleNode;
|
|
731
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.KeyboardAvoidingView, { style:
|
|
732
|
-
hasHeader ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
773
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.KeyboardAvoidingView, { style: styles16.fill, behavior: "padding", children: [
|
|
774
|
+
hasHeader ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles16.header, children: [
|
|
733
775
|
titleNode != null ? titleNode : title ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [labelStyle(t.fonts), { color: t.colors.text }], children: title }) : null,
|
|
734
776
|
subtitle ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
735
777
|
reactNative.Text,
|
|
@@ -745,10 +787,10 @@ var _CardLayout = ({
|
|
|
745
787
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
746
788
|
reactNative.ScrollView,
|
|
747
789
|
{
|
|
748
|
-
style:
|
|
790
|
+
style: styles16.fill,
|
|
749
791
|
contentContainerStyle: [
|
|
750
|
-
|
|
751
|
-
align === "center" &&
|
|
792
|
+
styles16.scrollContent,
|
|
793
|
+
align === "center" && styles16.center
|
|
752
794
|
],
|
|
753
795
|
keyboardShouldPersistTaps: "handled",
|
|
754
796
|
keyboardDismissMode: "on-drag",
|
|
@@ -756,17 +798,21 @@ var _CardLayout = ({
|
|
|
756
798
|
children
|
|
757
799
|
}
|
|
758
800
|
),
|
|
759
|
-
footer ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
801
|
+
footer ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles16.footer, children: footer }) : null
|
|
760
802
|
] });
|
|
761
803
|
};
|
|
762
804
|
var CardLayout = React14__default.default.memo(_CardLayout);
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
805
|
+
function makeStyles2(t) {
|
|
806
|
+
return reactNative.StyleSheet.create({
|
|
807
|
+
fill: { flex: 1 },
|
|
808
|
+
header: { marginBottom: t.spacing.lg },
|
|
809
|
+
footer: { paddingTop: t.spacing.lg },
|
|
810
|
+
// flexGrow lets a short content block grow to fill (pinning the footer) while a
|
|
811
|
+
// tall one scrolls past the visible area.
|
|
812
|
+
scrollContent: { flexGrow: 1 },
|
|
813
|
+
center: { justifyContent: "center" }
|
|
814
|
+
});
|
|
815
|
+
}
|
|
770
816
|
var easeWire2 = reactNative.Easing.bezier(...WIRE_BEZIER);
|
|
771
817
|
var BADGE_SIZE = 64;
|
|
772
818
|
var BURST_SIZE = 104;
|
|
@@ -841,14 +887,14 @@ var _CompletionView = ({
|
|
|
841
887
|
{
|
|
842
888
|
align: "center",
|
|
843
889
|
footer: /* @__PURE__ */ jsxRuntime.jsx(Button, { title: ctaLabel, onPress: handlePress, variant: "primary", disabled: submitted }),
|
|
844
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [
|
|
845
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
890
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles8.center, { gap: t.spacing.md }], children: [
|
|
891
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles8.badgeStage, children: [
|
|
846
892
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
847
893
|
reactNative.Animated.View,
|
|
848
894
|
{
|
|
849
895
|
pointerEvents: "none",
|
|
850
896
|
style: [
|
|
851
|
-
|
|
897
|
+
styles8.burst,
|
|
852
898
|
{
|
|
853
899
|
backgroundColor: t.colors.primarySoft,
|
|
854
900
|
borderRadius: t.radius.full,
|
|
@@ -862,7 +908,7 @@ var _CompletionView = ({
|
|
|
862
908
|
reactNative.Animated.View,
|
|
863
909
|
{
|
|
864
910
|
style: [
|
|
865
|
-
|
|
911
|
+
styles8.badge,
|
|
866
912
|
{
|
|
867
913
|
backgroundColor: t.colors.primarySoft,
|
|
868
914
|
borderRadius: t.radius.full,
|
|
@@ -870,7 +916,7 @@ var _CompletionView = ({
|
|
|
870
916
|
opacity: pop
|
|
871
917
|
}
|
|
872
918
|
],
|
|
873
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [
|
|
919
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles8.check, { color: t.colors.primary }], children: "\u2713" })
|
|
874
920
|
}
|
|
875
921
|
)
|
|
876
922
|
] }),
|
|
@@ -881,7 +927,7 @@ var _CompletionView = ({
|
|
|
881
927
|
);
|
|
882
928
|
};
|
|
883
929
|
var CompletionView = React14__default.default.memo(_CompletionView);
|
|
884
|
-
var
|
|
930
|
+
var styles8 = reactNative.StyleSheet.create({
|
|
885
931
|
center: { width: "100%", alignItems: "center", justifyContent: "center" },
|
|
886
932
|
badgeStage: {
|
|
887
933
|
width: BURST_SIZE,
|
|
@@ -904,7 +950,6 @@ var _CardHandoff = ({
|
|
|
904
950
|
const enterT = React14.useRef(new reactNative.Animated.Value(0)).current;
|
|
905
951
|
const exitT = React14.useRef(new reactNative.Animated.Value(0)).current;
|
|
906
952
|
const prev = React14.useRef({ key: transitionKey, node: children, variant });
|
|
907
|
-
const [enterVariant, setEnterVariant] = React14.useState(variant);
|
|
908
953
|
const running = React14.useRef({});
|
|
909
954
|
const mounted = React14.useRef(false);
|
|
910
955
|
React14.useEffect(() => {
|
|
@@ -913,7 +958,6 @@ var _CardHandoff = ({
|
|
|
913
958
|
prev.current = { key: transitionKey, node: children, variant };
|
|
914
959
|
if (!mounted.current) {
|
|
915
960
|
mounted.current = true;
|
|
916
|
-
setEnterVariant(variant);
|
|
917
961
|
running.current.enter = startEnter(enterT, variant, reduced, 0);
|
|
918
962
|
return;
|
|
919
963
|
}
|
|
@@ -921,7 +965,6 @@ var _CardHandoff = ({
|
|
|
921
965
|
(_a = running.current.enter) == null ? void 0 : _a.stop();
|
|
922
966
|
(_b = running.current.exit) == null ? void 0 : _b.stop();
|
|
923
967
|
setLeaving(last);
|
|
924
|
-
setEnterVariant(variant);
|
|
925
968
|
enterT.setValue(0);
|
|
926
969
|
exitT.setValue(0);
|
|
927
970
|
const exitDuration = reduced ? REDUCED_FADE_MS : last.variant === "fade" ? LOADER_HANDOFF_FADE_MS : CARD_EXIT_MS;
|
|
@@ -952,7 +995,7 @@ var _CardHandoff = ({
|
|
|
952
995
|
);
|
|
953
996
|
const enterStyle = {
|
|
954
997
|
opacity: enterT,
|
|
955
|
-
transform: transformFor(
|
|
998
|
+
transform: transformFor(variant, enterT, reduced, "enter")
|
|
956
999
|
};
|
|
957
1000
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
958
1001
|
leaving ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -969,7 +1012,7 @@ var _CardHandoff = ({
|
|
|
969
1012
|
children: leaving.node
|
|
970
1013
|
}
|
|
971
1014
|
) : null,
|
|
972
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: [
|
|
1015
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: [styles9.fill, enterStyle], children }, variant)
|
|
973
1016
|
] });
|
|
974
1017
|
};
|
|
975
1018
|
var startEnter = (value, variant, reduced, delay, onDone) => {
|
|
@@ -1010,7 +1053,7 @@ var transformFor = (variant, t, reduced, direction) => {
|
|
|
1010
1053
|
];
|
|
1011
1054
|
};
|
|
1012
1055
|
var CardHandoff = React14__default.default.memo(_CardHandoff);
|
|
1013
|
-
var
|
|
1056
|
+
var styles9 = reactNative.StyleSheet.create({
|
|
1014
1057
|
fill: { flex: 1 }
|
|
1015
1058
|
});
|
|
1016
1059
|
|
|
@@ -1140,6 +1183,10 @@ var OnboardingFlow = ({
|
|
|
1140
1183
|
onEventRef.current = onEvent;
|
|
1141
1184
|
const onErrorRef = React14.useRef(onError);
|
|
1142
1185
|
onErrorRef.current = onError;
|
|
1186
|
+
const onCompleteRef = React14.useRef(onComplete);
|
|
1187
|
+
onCompleteRef.current = onComplete;
|
|
1188
|
+
const validatorsRef = React14.useRef(validators);
|
|
1189
|
+
validatorsRef.current = validators;
|
|
1143
1190
|
const reportTargetRef = React14.useRef(reportTarget);
|
|
1144
1191
|
reportTargetRef.current = reportTarget;
|
|
1145
1192
|
const sessionIdRef = React14.useRef(sessionId);
|
|
@@ -1255,8 +1302,8 @@ var OnboardingFlow = ({
|
|
|
1255
1302
|
const handleFinish = React14.useCallback(() => {
|
|
1256
1303
|
if (finished.current) return;
|
|
1257
1304
|
finished.current = true;
|
|
1258
|
-
|
|
1259
|
-
}, [messages
|
|
1305
|
+
onCompleteRef.current({ answers: deriveAnswers(messages), raw: messages });
|
|
1306
|
+
}, [messages]);
|
|
1260
1307
|
const handleRetry = React14.useCallback(() => {
|
|
1261
1308
|
attempts.current = 0;
|
|
1262
1309
|
degradedRef.current = false;
|
|
@@ -1284,9 +1331,10 @@ var OnboardingFlow = ({
|
|
|
1284
1331
|
}, []);
|
|
1285
1332
|
const wrappedActions = React14.useCallback(
|
|
1286
1333
|
(messageId) => {
|
|
1334
|
+
var _a2;
|
|
1287
1335
|
const base = makeActions(messageId);
|
|
1288
1336
|
const key = progress.key;
|
|
1289
|
-
const validator = key ?
|
|
1337
|
+
const validator = key ? (_a2 = validatorsRef.current) == null ? void 0 : _a2[key] : void 0;
|
|
1290
1338
|
if (!validator) return base;
|
|
1291
1339
|
const out = { ...base };
|
|
1292
1340
|
for (const name of ANSWER_CALLBACKS) {
|
|
@@ -1297,12 +1345,12 @@ var OnboardingFlow = ({
|
|
|
1297
1345
|
if (typeof value !== "string") return original(...args);
|
|
1298
1346
|
setValidating(true);
|
|
1299
1347
|
validator(value).then((res) => {
|
|
1300
|
-
var
|
|
1348
|
+
var _a3;
|
|
1301
1349
|
if (res.ok) {
|
|
1302
1350
|
setValidationError(void 0);
|
|
1303
1351
|
original(...args);
|
|
1304
1352
|
} else {
|
|
1305
|
-
setValidationError((
|
|
1353
|
+
setValidationError((_a3 = res.error) != null ? _a3 : "That value isn't available.");
|
|
1306
1354
|
}
|
|
1307
1355
|
}).catch(() => {
|
|
1308
1356
|
original(...args);
|
|
@@ -1311,7 +1359,7 @@ var OnboardingFlow = ({
|
|
|
1311
1359
|
}
|
|
1312
1360
|
return out;
|
|
1313
1361
|
},
|
|
1314
|
-
[makeActions, progress.key
|
|
1362
|
+
[makeActions, progress.key]
|
|
1315
1363
|
);
|
|
1316
1364
|
if (degraded) {
|
|
1317
1365
|
if (fallbackFlow !== void 0) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: fallbackFlow });
|
|
@@ -1466,7 +1514,7 @@ var _ChipItem = ({ chip, isSelected, multiSelect, onToggle }) => {
|
|
|
1466
1514
|
reactNative.Animated.View,
|
|
1467
1515
|
{
|
|
1468
1516
|
style: [
|
|
1469
|
-
|
|
1517
|
+
styles10.chip,
|
|
1470
1518
|
{
|
|
1471
1519
|
borderRadius: t.radius.full,
|
|
1472
1520
|
paddingHorizontal: t.spacing.md,
|
|
@@ -1483,7 +1531,7 @@ var _ChipItem = ({ chip, isSelected, multiSelect, onToggle }) => {
|
|
|
1483
1531
|
pointerEvents: "none",
|
|
1484
1532
|
style: [
|
|
1485
1533
|
reactNative.StyleSheet.absoluteFill,
|
|
1486
|
-
|
|
1534
|
+
styles10.fillOverlay,
|
|
1487
1535
|
{
|
|
1488
1536
|
borderRadius: t.radius.full,
|
|
1489
1537
|
borderColor: t.colors.primary,
|
|
@@ -1497,7 +1545,7 @@ var _ChipItem = ({ chip, isSelected, multiSelect, onToggle }) => {
|
|
|
1497
1545
|
reactNative.Animated.Text,
|
|
1498
1546
|
{
|
|
1499
1547
|
style: [
|
|
1500
|
-
|
|
1548
|
+
styles10.check,
|
|
1501
1549
|
{ color: t.colors.onPrimary, opacity: checkT, transform: [{ scale: checkScale }] }
|
|
1502
1550
|
],
|
|
1503
1551
|
children: "\u2713"
|
|
@@ -1508,7 +1556,7 @@ var _ChipItem = ({ chip, isSelected, multiSelect, onToggle }) => {
|
|
|
1508
1556
|
{
|
|
1509
1557
|
style: [
|
|
1510
1558
|
captionStyle(t.fonts),
|
|
1511
|
-
|
|
1559
|
+
styles10.chipLabel,
|
|
1512
1560
|
{ color: isSelected ? t.colors.onPrimary : t.colors.textMuted }
|
|
1513
1561
|
],
|
|
1514
1562
|
children: chip
|
|
@@ -1570,7 +1618,7 @@ var _ChipSelectCard = ({
|
|
|
1570
1618
|
disabled: selected.length === 0 || submitted
|
|
1571
1619
|
}
|
|
1572
1620
|
),
|
|
1573
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [
|
|
1621
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles10.chipsRow, { gap: t.spacing.sm + t.spacing.xs }], children: chips.map((chip) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1574
1622
|
ChipItem,
|
|
1575
1623
|
{
|
|
1576
1624
|
chip,
|
|
@@ -1590,7 +1638,7 @@ var ChipSelectCard = {
|
|
|
1590
1638
|
propsSchema: schema,
|
|
1591
1639
|
defaultProps: { multiSelect: true, submitLabel: "Continue" }
|
|
1592
1640
|
};
|
|
1593
|
-
var
|
|
1641
|
+
var styles10 = reactNative.StyleSheet.create({
|
|
1594
1642
|
chipsRow: { flexDirection: "row", flexWrap: "wrap" },
|
|
1595
1643
|
chip: { borderWidth: 1.5, flexDirection: "row", alignItems: "center", gap: 6, overflow: "hidden" },
|
|
1596
1644
|
fillOverlay: { borderWidth: 1.5 },
|
|
@@ -1622,6 +1670,7 @@ var _TextInputCard = ({
|
|
|
1622
1670
|
lines = 6
|
|
1623
1671
|
}) => {
|
|
1624
1672
|
const t = useOnboardingTheme();
|
|
1673
|
+
const styles16 = React14.useMemo(() => makeStyles3(t), [t]);
|
|
1625
1674
|
const { height: screenHeight } = reactNative.useWindowDimensions();
|
|
1626
1675
|
const [value, setValue] = React14.useState("");
|
|
1627
1676
|
const [submitted, setSubmitted] = React14.useState(false);
|
|
@@ -1648,7 +1697,7 @@ var _TextInputCard = ({
|
|
|
1648
1697
|
disabled: !value.trim() || locked
|
|
1649
1698
|
}
|
|
1650
1699
|
),
|
|
1651
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
1700
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles16.row, children: [
|
|
1652
1701
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1653
1702
|
reactNative.TextInput,
|
|
1654
1703
|
{
|
|
@@ -1662,7 +1711,7 @@ var _TextInputCard = ({
|
|
|
1662
1711
|
textAlignVertical: multiline ? "top" : "center",
|
|
1663
1712
|
style: [
|
|
1664
1713
|
bodyStyle(t.fonts),
|
|
1665
|
-
|
|
1714
|
+
styles16.input,
|
|
1666
1715
|
{
|
|
1667
1716
|
color: t.colors.text,
|
|
1668
1717
|
backgroundColor: t.colors.surface,
|
|
@@ -1686,9 +1735,12 @@ var TextInputCard = {
|
|
|
1686
1735
|
propsSchema: schema2,
|
|
1687
1736
|
defaultProps: { submitLabel: "Submit", multiline: true, lines: 6 }
|
|
1688
1737
|
};
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
}
|
|
1738
|
+
function makeStyles3(t) {
|
|
1739
|
+
return reactNative.StyleSheet.create({
|
|
1740
|
+
row: { gap: t.spacing.sm },
|
|
1741
|
+
input: { borderWidth: 1 }
|
|
1742
|
+
});
|
|
1743
|
+
}
|
|
1692
1744
|
var easeWire5 = reactNative.Easing.bezier(...WIRE_BEZIER);
|
|
1693
1745
|
var optionObjectSchema = zod.z.object({
|
|
1694
1746
|
value: zod.z.string().describe("Option value"),
|
|
@@ -1767,7 +1819,7 @@ var _OptionRow = ({ opt, isSelected, multiSelect, onToggle }) => {
|
|
|
1767
1819
|
reactNative.Animated.View,
|
|
1768
1820
|
{
|
|
1769
1821
|
style: [
|
|
1770
|
-
|
|
1822
|
+
styles11.option,
|
|
1771
1823
|
{
|
|
1772
1824
|
padding: t.spacing.md,
|
|
1773
1825
|
borderRadius: t.radius.md,
|
|
@@ -1784,7 +1836,7 @@ var _OptionRow = ({ opt, isSelected, multiSelect, onToggle }) => {
|
|
|
1784
1836
|
pointerEvents: "none",
|
|
1785
1837
|
style: [
|
|
1786
1838
|
reactNative.StyleSheet.absoluteFill,
|
|
1787
|
-
|
|
1839
|
+
styles11.selectedOverlay,
|
|
1788
1840
|
{
|
|
1789
1841
|
borderRadius: t.radius.md,
|
|
1790
1842
|
borderColor: t.colors.primary,
|
|
@@ -1798,7 +1850,7 @@ var _OptionRow = ({ opt, isSelected, multiSelect, onToggle }) => {
|
|
|
1798
1850
|
reactNative.View,
|
|
1799
1851
|
{
|
|
1800
1852
|
style: [
|
|
1801
|
-
|
|
1853
|
+
styles11.indicator,
|
|
1802
1854
|
{ borderRadius: t.radius.full },
|
|
1803
1855
|
isSelected ? { borderColor: t.colors.primary, backgroundColor: t.colors.primary } : { borderColor: t.colors.borderStrong, backgroundColor: "transparent" }
|
|
1804
1856
|
],
|
|
@@ -1806,7 +1858,7 @@ var _OptionRow = ({ opt, isSelected, multiSelect, onToggle }) => {
|
|
|
1806
1858
|
reactNative.Animated.Text,
|
|
1807
1859
|
{
|
|
1808
1860
|
style: [
|
|
1809
|
-
|
|
1861
|
+
styles11.check,
|
|
1810
1862
|
{ color: t.colors.onPrimary, opacity: checkT, transform: [{ scale: checkScale }] }
|
|
1811
1863
|
],
|
|
1812
1864
|
children: "\u2713"
|
|
@@ -1885,7 +1937,7 @@ var SelectionCard = {
|
|
|
1885
1937
|
propsSchema: schema3,
|
|
1886
1938
|
defaultProps: { submitLabel: "Continue", multiSelect: false }
|
|
1887
1939
|
};
|
|
1888
|
-
var
|
|
1940
|
+
var styles11 = reactNative.StyleSheet.create({
|
|
1889
1941
|
option: { borderWidth: 1.5, flexDirection: "row", alignItems: "center", overflow: "hidden" },
|
|
1890
1942
|
selectedOverlay: { borderWidth: 1.5 },
|
|
1891
1943
|
indicator: { width: 24, height: 24, borderWidth: 2, alignItems: "center", justifyContent: "center" },
|
|
@@ -1907,17 +1959,22 @@ var STATUS_ICONS = {
|
|
|
1907
1959
|
info: "\u2139"
|
|
1908
1960
|
};
|
|
1909
1961
|
var _StatusCard = ({ status, title, message, ctaLabel, onContinue, onPress, onSubmit }) => {
|
|
1910
|
-
var _a
|
|
1962
|
+
var _a;
|
|
1911
1963
|
const t = useOnboardingTheme();
|
|
1912
1964
|
const reduced = useReducedMotion();
|
|
1913
1965
|
const [submitted, setSubmitted] = React14.useState(false);
|
|
1914
|
-
const
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1966
|
+
const color = React14.useMemo(() => {
|
|
1967
|
+
switch (status) {
|
|
1968
|
+
case "success":
|
|
1969
|
+
return t.colors.success;
|
|
1970
|
+
case "warning":
|
|
1971
|
+
return t.colors.warning;
|
|
1972
|
+
case "error":
|
|
1973
|
+
return t.colors.error;
|
|
1974
|
+
default:
|
|
1975
|
+
return t.colors.info;
|
|
1976
|
+
}
|
|
1977
|
+
}, [status, t.colors]);
|
|
1921
1978
|
const popT = React14.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
|
|
1922
1979
|
const copyT = React14.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
|
|
1923
1980
|
React14.useEffect(() => {
|
|
@@ -1959,8 +2016,8 @@ var _StatusCard = ({ status, title, message, ctaLabel, onContinue, onPress, onSu
|
|
|
1959
2016
|
{
|
|
1960
2017
|
align: "center",
|
|
1961
2018
|
footer: ctaLabel ? /* @__PURE__ */ jsxRuntime.jsx(Button, { title: ctaLabel, onPress: handleContinue, variant: "primary", disabled: submitted }) : void 0,
|
|
1962
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [
|
|
1963
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [
|
|
2019
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles12.center, { gap: t.spacing.sm }], children: [
|
|
2020
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles12.titleRow, { gap: t.spacing.sm }], children: [
|
|
1964
2021
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1965
2022
|
reactNative.Animated.Text,
|
|
1966
2023
|
{
|
|
@@ -1968,7 +2025,7 @@ var _StatusCard = ({ status, title, message, ctaLabel, onContinue, onPress, onSu
|
|
|
1968
2025
|
headingStyle(t.fonts),
|
|
1969
2026
|
{ color, opacity: popT, transform: [{ scale: popScale }] }
|
|
1970
2027
|
],
|
|
1971
|
-
children: (
|
|
2028
|
+
children: (_a = STATUS_ICONS[status]) != null ? _a : "\xB7"
|
|
1972
2029
|
}
|
|
1973
2030
|
),
|
|
1974
2031
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2007,7 +2064,7 @@ var StatusCard = {
|
|
|
2007
2064
|
component: React14__default.default.memo(_StatusCard),
|
|
2008
2065
|
propsSchema: schema4
|
|
2009
2066
|
};
|
|
2010
|
-
var
|
|
2067
|
+
var styles12 = reactNative.StyleSheet.create({
|
|
2011
2068
|
center: { width: "100%", alignItems: "center", justifyContent: "center" },
|
|
2012
2069
|
titleRow: { flexDirection: "row", alignItems: "center", justifyContent: "center" }
|
|
2013
2070
|
});
|
|
@@ -2032,6 +2089,7 @@ var _NumberStepperCard = ({
|
|
|
2032
2089
|
onSubmit
|
|
2033
2090
|
}) => {
|
|
2034
2091
|
const t = useOnboardingTheme();
|
|
2092
|
+
const styles16 = React14.useMemo(() => makeStyles4(t), [t]);
|
|
2035
2093
|
const safeMin = safeNum(min, 1);
|
|
2036
2094
|
const safeMaxRaw = safeNum(max, 30);
|
|
2037
2095
|
const safeMax = safeMaxRaw < safeMin ? safeMin : safeMaxRaw;
|
|
@@ -2064,7 +2122,7 @@ var _NumberStepperCard = ({
|
|
|
2064
2122
|
title: label,
|
|
2065
2123
|
align: "center",
|
|
2066
2124
|
footer: /* @__PURE__ */ jsxRuntime.jsx(Button, { title: submitLabel, onPress: handleSubmit, variant: "primary", disabled: submitted }),
|
|
2067
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
2125
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles16.wrap, children: [
|
|
2068
2126
|
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles16.stepper, { gap: t.spacing.lg }], children: [
|
|
2069
2127
|
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { onPress: atMin || submitted ? void 0 : handleDecrement, disabled: atMin || submitted, style: stepBtnStyle(atMin), children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [headingStyle(t.fonts), { color: atMin ? t.colors.textMuted : t.colors.primary }], children: "\u2212" }) }),
|
|
2070
2128
|
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles16.valueBox, children: [
|
|
@@ -2085,11 +2143,14 @@ var NumberStepperCard = {
|
|
|
2085
2143
|
propsSchema: schema5,
|
|
2086
2144
|
defaultProps: { min: 1, max: 30, defaultValue: 1, step: 1, submitLabel: "Confirm" }
|
|
2087
2145
|
};
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
}
|
|
2146
|
+
function makeStyles4(t) {
|
|
2147
|
+
return reactNative.StyleSheet.create({
|
|
2148
|
+
wrap: { gap: t.spacing.md, alignItems: "center" },
|
|
2149
|
+
stepper: { flexDirection: "row", alignItems: "center", justifyContent: "center" },
|
|
2150
|
+
stepBtn: { width: 44, height: 44, borderWidth: 2, alignItems: "center", justifyContent: "center" },
|
|
2151
|
+
valueBox: { alignItems: "center", minWidth: 80 }
|
|
2152
|
+
});
|
|
2153
|
+
}
|
|
2093
2154
|
var easeWire7 = reactNative.Easing.bezier(...WIRE_BEZIER);
|
|
2094
2155
|
var RISE_PX = 10;
|
|
2095
2156
|
var schema6 = zod.z.object({
|
|
@@ -2151,20 +2212,20 @@ var _WorkItem = ({
|
|
|
2151
2212
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2152
2213
|
reactNative.Animated.View,
|
|
2153
2214
|
{
|
|
2154
|
-
style: [
|
|
2215
|
+
style: [styles13.itemRow, { gap: t.spacing.sm + t.spacing.xs, opacity: rowT, transform: [{ translateY: rise }] }],
|
|
2155
2216
|
children: [
|
|
2156
2217
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2157
2218
|
reactNative.View,
|
|
2158
2219
|
{
|
|
2159
2220
|
style: [
|
|
2160
|
-
|
|
2221
|
+
styles13.itemBadge,
|
|
2161
2222
|
{ backgroundColor: t.colors.primarySoft, borderRadius: t.radius.full }
|
|
2162
2223
|
],
|
|
2163
2224
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2164
2225
|
reactNative.Animated.Text,
|
|
2165
2226
|
{
|
|
2166
2227
|
style: [
|
|
2167
|
-
|
|
2228
|
+
styles13.itemCheck,
|
|
2168
2229
|
{ color: t.colors.primary, opacity: checkT, transform: [{ scale: checkScale }] }
|
|
2169
2230
|
],
|
|
2170
2231
|
children: "\u2713"
|
|
@@ -2172,7 +2233,7 @@ var _WorkItem = ({
|
|
|
2172
2233
|
)
|
|
2173
2234
|
}
|
|
2174
2235
|
),
|
|
2175
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [bodyStyle(t.fonts),
|
|
2236
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [bodyStyle(t.fonts), styles13.itemText, { color: t.colors.text }], children: text })
|
|
2176
2237
|
]
|
|
2177
2238
|
}
|
|
2178
2239
|
);
|
|
@@ -2250,18 +2311,18 @@ var _InterstitialCard = ({
|
|
|
2250
2311
|
disabled: submitted || !canAdvance
|
|
2251
2312
|
}
|
|
2252
2313
|
),
|
|
2253
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [
|
|
2254
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: [
|
|
2314
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles13.center, { gap: t.spacing.md }], children: [
|
|
2315
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: [styles13.fullWidth, riseStyle(artT)], children: showImage ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2255
2316
|
reactNative.Image,
|
|
2256
2317
|
{
|
|
2257
2318
|
source: { uri: imageUrl },
|
|
2258
|
-
style:
|
|
2319
|
+
style: styles13.image,
|
|
2259
2320
|
resizeMode: "contain",
|
|
2260
2321
|
onError: () => setImgFailed(true)
|
|
2261
2322
|
}
|
|
2262
|
-
) : art ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
2323
|
+
) : art ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles13.art, children: art }) : null }),
|
|
2263
2324
|
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: riseStyle(titleT), children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [headingStyle(t.fonts), { color: t.colors.text, textAlign: "center" }], children: title }) }),
|
|
2264
|
-
(items == null ? void 0 : items.length) ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [
|
|
2325
|
+
(items == null ? void 0 : items.length) ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles13.items, { gap: t.spacing.md, marginTop: t.spacing.sm }], children: items.map((item, i) => /* @__PURE__ */ jsxRuntime.jsx(WorkItem, { text: item, index: i, reduced }, `${item}-${i}`)) }) : body ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: riseStyle(bodyT), children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [bodyStyle(t.fonts), { color: t.colors.textMuted, textAlign: "center" }], children: body }) }) : null
|
|
2265
2326
|
] })
|
|
2266
2327
|
}
|
|
2267
2328
|
);
|
|
@@ -2273,7 +2334,7 @@ var InterstitialCard = {
|
|
|
2273
2334
|
propsSchema: schema6,
|
|
2274
2335
|
defaultProps: { ctaLabel: "Continue", illustrationFallback: "momentum" }
|
|
2275
2336
|
};
|
|
2276
|
-
var
|
|
2337
|
+
var styles13 = reactNative.StyleSheet.create({
|
|
2277
2338
|
center: { width: "100%", alignItems: "center", justifyContent: "center" },
|
|
2278
2339
|
fullWidth: { width: "100%", alignItems: "center" },
|
|
2279
2340
|
art: { alignItems: "center", justifyContent: "center" },
|
|
@@ -2294,6 +2355,57 @@ var onboardingComponents = [
|
|
|
2294
2355
|
NumberStepperCard,
|
|
2295
2356
|
InterstitialCard
|
|
2296
2357
|
];
|
|
2358
|
+
|
|
2359
|
+
// src/device/appVersion.ts
|
|
2360
|
+
var coerceVersion = (value) => {
|
|
2361
|
+
if (typeof value !== "string") return void 0;
|
|
2362
|
+
const trimmed = value.trim();
|
|
2363
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
2364
|
+
};
|
|
2365
|
+
var runtimeRequire = (moduleName) => {
|
|
2366
|
+
try {
|
|
2367
|
+
if (typeof __require !== "function") return void 0;
|
|
2368
|
+
return __require(moduleName);
|
|
2369
|
+
} catch {
|
|
2370
|
+
return void 0;
|
|
2371
|
+
}
|
|
2372
|
+
};
|
|
2373
|
+
var interop = (mod) => {
|
|
2374
|
+
if (!mod || typeof mod !== "object") return void 0;
|
|
2375
|
+
const def = mod.default;
|
|
2376
|
+
if (def && typeof def === "object") return def;
|
|
2377
|
+
return mod;
|
|
2378
|
+
};
|
|
2379
|
+
var safeInterop = (requireModule, moduleName) => {
|
|
2380
|
+
try {
|
|
2381
|
+
return interop(requireModule(moduleName));
|
|
2382
|
+
} catch {
|
|
2383
|
+
return void 0;
|
|
2384
|
+
}
|
|
2385
|
+
};
|
|
2386
|
+
var detectAppVersion = (requireModule = runtimeRequire) => {
|
|
2387
|
+
try {
|
|
2388
|
+
const constants = safeInterop(requireModule, "expo-constants");
|
|
2389
|
+
if (constants) {
|
|
2390
|
+
const expoConfig = constants.expoConfig;
|
|
2391
|
+
if (expoConfig && typeof expoConfig === "object") {
|
|
2392
|
+
const fromExpoConfig = coerceVersion(expoConfig.version);
|
|
2393
|
+
if (fromExpoConfig) return fromExpoConfig;
|
|
2394
|
+
}
|
|
2395
|
+
const fromNative = coerceVersion(constants.nativeAppVersion);
|
|
2396
|
+
if (fromNative) return fromNative;
|
|
2397
|
+
}
|
|
2398
|
+
const application = safeInterop(requireModule, "expo-application");
|
|
2399
|
+
if (application) {
|
|
2400
|
+
const fromApplication = coerceVersion(application.nativeApplicationVersion);
|
|
2401
|
+
if (fromApplication) return fromApplication;
|
|
2402
|
+
}
|
|
2403
|
+
} catch {
|
|
2404
|
+
}
|
|
2405
|
+
return void 0;
|
|
2406
|
+
};
|
|
2407
|
+
|
|
2408
|
+
// src/device/deviceContext.ts
|
|
2297
2409
|
var deriveFormFactor = (iosIdiom, width, height) => {
|
|
2298
2410
|
if (iosIdiom === "pad") return "tablet";
|
|
2299
2411
|
if (iosIdiom === "phone") return "phone";
|
|
@@ -2363,9 +2475,21 @@ var collectDeviceContext = () => {
|
|
|
2363
2475
|
if (resolved.timeZone) ctx.timeZone = resolved.timeZone;
|
|
2364
2476
|
} catch {
|
|
2365
2477
|
}
|
|
2478
|
+
const appVersion = detectAppVersion();
|
|
2479
|
+
if (appVersion) ctx.appVersion = appVersion;
|
|
2366
2480
|
return ctx;
|
|
2367
2481
|
};
|
|
2368
2482
|
|
|
2483
|
+
// src/analytics/currentSession.ts
|
|
2484
|
+
var _currentSessionId;
|
|
2485
|
+
var setCurrentSessionId = (id) => {
|
|
2486
|
+
if (typeof id === "string" && id.length > 0) _currentSessionId = id;
|
|
2487
|
+
};
|
|
2488
|
+
var getCurrentSessionId = () => _currentSessionId;
|
|
2489
|
+
var resetCurrentSessionId = () => {
|
|
2490
|
+
_currentSessionId = void 0;
|
|
2491
|
+
};
|
|
2492
|
+
|
|
2369
2493
|
// src/session/persistedSession.ts
|
|
2370
2494
|
var DEFAULT_SESSION_TTL_MS = 36e5;
|
|
2371
2495
|
var READ_TIMEOUT_MS = 1500;
|
|
@@ -2444,6 +2568,7 @@ var identifyOnboarding = async (opts) => {
|
|
|
2444
2568
|
contextId = stored == null ? void 0 : stored.id;
|
|
2445
2569
|
}
|
|
2446
2570
|
}
|
|
2571
|
+
if (!contextId) contextId = getCurrentSessionId();
|
|
2447
2572
|
if (!contextId) return false;
|
|
2448
2573
|
reportClientEvent(
|
|
2449
2574
|
{ serverUrl: opts.config.serverUrl, apiKey: opts.config.apiKey },
|
|
@@ -2511,6 +2636,10 @@ var WireOnboarding = ({
|
|
|
2511
2636
|
);
|
|
2512
2637
|
const sessionId = (_a = session == null ? void 0 : session.id) != null ? _a : "";
|
|
2513
2638
|
const startupUserIdRef = React14.useRef(boundUserId);
|
|
2639
|
+
const metadataKey = config.metadata ? JSON.stringify(config.metadata) : "";
|
|
2640
|
+
const metadataStable = React14.useMemo(() => metadataKey ? JSON.parse(metadataKey) : void 0, [metadataKey]);
|
|
2641
|
+
const componentNamesKey = (components != null ? components : onboardingComponents).map((c) => c.name).join(",");
|
|
2642
|
+
const componentsStable = React14.useMemo(() => components != null ? components : onboardingComponents, [componentNamesKey]);
|
|
2514
2643
|
const llm = React14.useMemo(() => {
|
|
2515
2644
|
const baseUrl = config.serverUrl.replace(/\/$/, "");
|
|
2516
2645
|
return {
|
|
@@ -2523,9 +2652,9 @@ var WireOnboarding = ({
|
|
|
2523
2652
|
// names of the components this device can actually render — so the backend only
|
|
2524
2653
|
// emits cards the kit knows how to draw.
|
|
2525
2654
|
metadata: {
|
|
2526
|
-
...
|
|
2655
|
+
...metadataStable,
|
|
2527
2656
|
sessionId,
|
|
2528
|
-
supportedComponents:
|
|
2657
|
+
supportedComponents: componentsStable.map((c) => c.name),
|
|
2529
2658
|
// Device snapshot + host-injected user context ride the session-start metadata so the
|
|
2530
2659
|
// backend can segment the funnel. Old servers ignore these unknown keys (backward compat).
|
|
2531
2660
|
device,
|
|
@@ -2538,7 +2667,7 @@ var WireOnboarding = ({
|
|
|
2538
2667
|
},
|
|
2539
2668
|
timeoutMs: 6e4
|
|
2540
2669
|
};
|
|
2541
|
-
}, [config.serverUrl, config.appId, config.apiKey,
|
|
2670
|
+
}, [config.serverUrl, config.appId, config.apiKey, metadataStable, sessionId, componentsStable, device, userContextStable]);
|
|
2542
2671
|
const reportTarget = React14.useMemo(
|
|
2543
2672
|
() => ({ serverUrl: config.serverUrl, apiKey: config.apiKey }),
|
|
2544
2673
|
[config.serverUrl, config.apiKey]
|
|
@@ -2603,7 +2732,7 @@ function DemoOnboarding({
|
|
|
2603
2732
|
const [open, setOpen] = React14.useState(false);
|
|
2604
2733
|
const [runId, setRunId] = React14.useState(0);
|
|
2605
2734
|
const t = React14.useMemo(() => mergeTheme(theme != null ? theme : {}), [theme]);
|
|
2606
|
-
const
|
|
2735
|
+
const styles16 = React14.useMemo(() => makeStyles5(t), [t]);
|
|
2607
2736
|
const openDemo = React14.useCallback(() => {
|
|
2608
2737
|
setRunId((n) => n + 1);
|
|
2609
2738
|
setOpen(true);
|
|
@@ -2617,7 +2746,7 @@ function DemoOnboarding({
|
|
|
2617
2746
|
[onComplete]
|
|
2618
2747
|
);
|
|
2619
2748
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2620
|
-
renderTrigger ? renderTrigger(openDemo) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { onPress: openDemo, style:
|
|
2749
|
+
renderTrigger ? renderTrigger(openDemo) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { onPress: openDemo, style: styles16.trigger, accessibilityRole: "button", children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles16.triggerText, children: label }) }),
|
|
2621
2750
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2622
2751
|
reactNative.Modal,
|
|
2623
2752
|
{
|
|
@@ -2625,7 +2754,7 @@ function DemoOnboarding({
|
|
|
2625
2754
|
animationType: "slide",
|
|
2626
2755
|
presentationStyle: "fullScreen",
|
|
2627
2756
|
onRequestClose: close,
|
|
2628
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style:
|
|
2757
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles16.modal, children: config ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2629
2758
|
WireOnboarding,
|
|
2630
2759
|
{
|
|
2631
2760
|
config,
|
|
@@ -2638,16 +2767,16 @@ function DemoOnboarding({
|
|
|
2638
2767
|
onError: close
|
|
2639
2768
|
},
|
|
2640
2769
|
runId
|
|
2641
|
-
) : /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style:
|
|
2642
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
2643
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style:
|
|
2644
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { onPress: close, style:
|
|
2770
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles16.notice, children: [
|
|
2771
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles16.noticeTitle, children: "Wire AI not configured" }),
|
|
2772
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles16.noticeBody, children: "Set the Wire AI key + server URL (e.g. via wireConfigFromEnv) to demo the AI onboarding here." }),
|
|
2773
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { onPress: close, style: styles16.trigger, accessibilityRole: "button", children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles16.triggerText, children: "Close" }) })
|
|
2645
2774
|
] }) })
|
|
2646
2775
|
}
|
|
2647
2776
|
)
|
|
2648
2777
|
] });
|
|
2649
2778
|
}
|
|
2650
|
-
function
|
|
2779
|
+
function makeStyles5(t) {
|
|
2651
2780
|
return reactNative.StyleSheet.create({
|
|
2652
2781
|
trigger: {
|
|
2653
2782
|
backgroundColor: t.colors.primary,
|
|
@@ -2720,13 +2849,13 @@ var _DoneBlock = ({
|
|
|
2720
2849
|
message = "Personalizing your experience\u2026"
|
|
2721
2850
|
}) => {
|
|
2722
2851
|
const t = useOnboardingTheme();
|
|
2723
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [
|
|
2852
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles14.center, { gap: t.spacing.sm, padding: t.spacing.lg }], children: [
|
|
2724
2853
|
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [headingStyle(t.fonts), { color: t.colors.success, textAlign: "center" }], children: title }),
|
|
2725
2854
|
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [bodyStyle(t.fonts), { color: t.colors.textMuted, textAlign: "center" }], children: message })
|
|
2726
2855
|
] });
|
|
2727
2856
|
};
|
|
2728
2857
|
var DoneBlock = React14__default.default.memo(_DoneBlock);
|
|
2729
|
-
var
|
|
2858
|
+
var styles14 = reactNative.StyleSheet.create({
|
|
2730
2859
|
center: { flex: 1, alignItems: "center", justifyContent: "center" }
|
|
2731
2860
|
});
|
|
2732
2861
|
|
|
@@ -2805,25 +2934,25 @@ var _CenteredModal = React14.forwardRef(
|
|
|
2805
2934
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2806
2935
|
reactNative.Animated.View,
|
|
2807
2936
|
{
|
|
2808
|
-
style: [
|
|
2937
|
+
style: [styles15.backdrop, { opacity: backdropOpacity }],
|
|
2809
2938
|
pointerEvents: "none"
|
|
2810
2939
|
}
|
|
2811
2940
|
),
|
|
2812
2941
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2813
2942
|
reactNative.Pressable,
|
|
2814
2943
|
{
|
|
2815
|
-
style:
|
|
2944
|
+
style: styles15.fill,
|
|
2816
2945
|
onPress: onBackdrop,
|
|
2817
2946
|
accessibilityRole: "button",
|
|
2818
2947
|
accessibilityLabel: "Dismiss",
|
|
2819
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactNativeSafeAreaContext.SafeAreaView, { style:
|
|
2820
|
-
}, style:
|
|
2948
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNativeSafeAreaContext.SafeAreaView, { style: styles15.center, pointerEvents: "box-none", children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { onPress: () => {
|
|
2949
|
+
}, style: styles15.cardWrap, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2821
2950
|
reactNative.Animated.View,
|
|
2822
2951
|
{
|
|
2823
2952
|
accessibilityViewIsModal: true,
|
|
2824
2953
|
accessibilityRole: "alert",
|
|
2825
2954
|
style: [
|
|
2826
|
-
|
|
2955
|
+
styles15.card,
|
|
2827
2956
|
{
|
|
2828
2957
|
backgroundColor: theme.colors.surface,
|
|
2829
2958
|
borderRadius: theme.radius.lg,
|
|
@@ -2845,7 +2974,7 @@ var _CenteredModal = React14.forwardRef(
|
|
|
2845
2974
|
);
|
|
2846
2975
|
_CenteredModal.displayName = "CenteredModal";
|
|
2847
2976
|
var CenteredModal = React14__default.default.memo(_CenteredModal);
|
|
2848
|
-
var
|
|
2977
|
+
var styles15 = reactNative.StyleSheet.create({
|
|
2849
2978
|
fill: { flex: 1 },
|
|
2850
2979
|
backdrop: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0, backgroundColor: "#000" },
|
|
2851
2980
|
center: { flex: 1, alignItems: "center", justifyContent: "center", padding: 24 },
|
|
@@ -2999,7 +3128,12 @@ var useWireFeatures = (config) => {
|
|
|
2999
3128
|
}, [canFetch, stableConfig]);
|
|
3000
3129
|
return flags;
|
|
3001
3130
|
};
|
|
3002
|
-
var
|
|
3131
|
+
var CONTEXT_SYMBOL = /* @__PURE__ */ Symbol.for("wireai.features.context");
|
|
3132
|
+
var globalObj = global;
|
|
3133
|
+
if (!globalObj[CONTEXT_SYMBOL]) {
|
|
3134
|
+
globalObj[CONTEXT_SYMBOL] = React14.createContext(null);
|
|
3135
|
+
}
|
|
3136
|
+
var WireFeaturesContext = globalObj[CONTEXT_SYMBOL];
|
|
3003
3137
|
var WireFeaturesProvider = ({
|
|
3004
3138
|
config,
|
|
3005
3139
|
flags,
|
|
@@ -3091,6 +3225,80 @@ var attributionMetadata = (a) => {
|
|
|
3091
3225
|
return { attribution };
|
|
3092
3226
|
};
|
|
3093
3227
|
|
|
3228
|
+
// src/context/userContext.ts
|
|
3229
|
+
var RESERVED_USER_CONTEXT_KEYS = [
|
|
3230
|
+
"device_key",
|
|
3231
|
+
"app_version",
|
|
3232
|
+
"app_build",
|
|
3233
|
+
"network_type",
|
|
3234
|
+
"session_count",
|
|
3235
|
+
"returning",
|
|
3236
|
+
"platform",
|
|
3237
|
+
"user_email",
|
|
3238
|
+
"user_email_hashed"
|
|
3239
|
+
];
|
|
3240
|
+
var EXTRA_KEY_PREFIX = "custom.";
|
|
3241
|
+
var isWireScalar = (value) => {
|
|
3242
|
+
const t = typeof value;
|
|
3243
|
+
if (t === "string" || t === "boolean") return true;
|
|
3244
|
+
if (t === "number") return Number.isFinite(value);
|
|
3245
|
+
return false;
|
|
3246
|
+
};
|
|
3247
|
+
var hashEmailFnv1a = (email) => {
|
|
3248
|
+
const normalized = email.trim().toLowerCase();
|
|
3249
|
+
let hash = 2166136261;
|
|
3250
|
+
for (let i = 0; i < normalized.length; i++) {
|
|
3251
|
+
hash ^= normalized.charCodeAt(i);
|
|
3252
|
+
hash = Math.imul(hash, 16777619);
|
|
3253
|
+
}
|
|
3254
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
3255
|
+
};
|
|
3256
|
+
var cleanString = (value) => {
|
|
3257
|
+
if (typeof value !== "string") return void 0;
|
|
3258
|
+
const trimmed = value.trim();
|
|
3259
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
3260
|
+
};
|
|
3261
|
+
var namespaceExtra = (extra) => {
|
|
3262
|
+
const out = {};
|
|
3263
|
+
if (!extra || typeof extra !== "object") return out;
|
|
3264
|
+
for (const [key, value] of Object.entries(extra)) {
|
|
3265
|
+
const cleanKey = cleanString(key);
|
|
3266
|
+
if (!cleanKey) continue;
|
|
3267
|
+
if (!isWireScalar(value)) continue;
|
|
3268
|
+
out[`${EXTRA_KEY_PREFIX}${cleanKey}`] = value;
|
|
3269
|
+
}
|
|
3270
|
+
return out;
|
|
3271
|
+
};
|
|
3272
|
+
var resolveUserContext = (ctx = {}, opts = {}) => {
|
|
3273
|
+
var _a;
|
|
3274
|
+
const result = {};
|
|
3275
|
+
const bucket = {};
|
|
3276
|
+
const userId = sanitizeUserId(ctx.userId);
|
|
3277
|
+
if (userId) result.userId = userId;
|
|
3278
|
+
const deviceKey = cleanString(ctx.deviceKey);
|
|
3279
|
+
if (deviceKey) {
|
|
3280
|
+
result.deviceKey = deviceKey;
|
|
3281
|
+
bucket.device_key = deviceKey;
|
|
3282
|
+
}
|
|
3283
|
+
const appVersion = (_a = cleanString(ctx.appVersion)) != null ? _a : cleanString(opts.autoAppVersion);
|
|
3284
|
+
if (appVersion) {
|
|
3285
|
+
result.appVersion = appVersion;
|
|
3286
|
+
bucket.app_version = appVersion;
|
|
3287
|
+
}
|
|
3288
|
+
const email = cleanString(ctx.userEmail);
|
|
3289
|
+
if (email) {
|
|
3290
|
+
if (ctx.hashEmail) {
|
|
3291
|
+
bucket.user_email = hashEmailFnv1a(email);
|
|
3292
|
+
bucket.user_email_hashed = true;
|
|
3293
|
+
} else {
|
|
3294
|
+
bucket.user_email = email;
|
|
3295
|
+
}
|
|
3296
|
+
}
|
|
3297
|
+
Object.assign(bucket, namespaceExtra(ctx.extra));
|
|
3298
|
+
if (Object.keys(bucket).length > 0) result.userContext = bucket;
|
|
3299
|
+
return result;
|
|
3300
|
+
};
|
|
3301
|
+
|
|
3094
3302
|
// src/session-analytics/reportSessionStart.ts
|
|
3095
3303
|
var SESSION_STARTED_EVENT = "app.session_started";
|
|
3096
3304
|
var _emitted = /* @__PURE__ */ new Set();
|
|
@@ -3103,6 +3311,7 @@ var reportSessionStart = (opts) => {
|
|
|
3103
3311
|
const target = opts.target;
|
|
3104
3312
|
if (!opts.sink && !(target == null ? void 0 : target.serverUrl)) return;
|
|
3105
3313
|
const sessionId = (_a = opts.sessionId) != null ? _a : makeSessionId();
|
|
3314
|
+
setCurrentSessionId(sessionId);
|
|
3106
3315
|
if (opts.once !== false) {
|
|
3107
3316
|
if (_emitted.has(sessionId)) return;
|
|
3108
3317
|
if (_emitted.size >= _GUARD_MAX) {
|
|
@@ -3159,7 +3368,7 @@ var useSessionStart = (config, options = {}) => {
|
|
|
3159
3368
|
if (opts.enabled === false) return;
|
|
3160
3369
|
const target = { serverUrl: cfg.serverUrl, apiKey: (_a = cfg.apiKey) != null ? _a : "" };
|
|
3161
3370
|
const device = collectDeviceContext();
|
|
3162
|
-
if (cfg.appVersion
|
|
3371
|
+
if (cfg.appVersion) device.appVersion = cfg.appVersion;
|
|
3163
3372
|
reportSessionStart({
|
|
3164
3373
|
target,
|
|
3165
3374
|
// A fresh per-open id each fire; the emitter's once-guard dedupes within the open.
|
|
@@ -3412,6 +3621,8 @@ var createEventQueue = (options) => {
|
|
|
3412
3621
|
})();
|
|
3413
3622
|
const postBatch = async (events) => {
|
|
3414
3623
|
if (!(target == null ? void 0 : target.serverUrl) || events.length === 0) return false;
|
|
3624
|
+
const controller = typeof AbortController !== "undefined" ? new AbortController() : void 0;
|
|
3625
|
+
const timer = setTimeout(() => controller == null ? void 0 : controller.abort(), 15e3);
|
|
3415
3626
|
try {
|
|
3416
3627
|
const url = `${target.serverUrl.replace(/\/$/, "")}/v1/events`;
|
|
3417
3628
|
const headers = { "Content-Type": "application/json" };
|
|
@@ -3419,11 +3630,14 @@ var createEventQueue = (options) => {
|
|
|
3419
3630
|
const res = await fetch(url, {
|
|
3420
3631
|
method: "POST",
|
|
3421
3632
|
headers,
|
|
3422
|
-
body: JSON.stringify({ events })
|
|
3633
|
+
body: JSON.stringify({ events }),
|
|
3634
|
+
signal: controller == null ? void 0 : controller.signal
|
|
3423
3635
|
});
|
|
3424
3636
|
return !!(res && res.ok);
|
|
3425
3637
|
} catch {
|
|
3426
3638
|
return false;
|
|
3639
|
+
} finally {
|
|
3640
|
+
clearTimeout(timer);
|
|
3427
3641
|
}
|
|
3428
3642
|
};
|
|
3429
3643
|
const clearRetry = () => {
|
|
@@ -3528,7 +3742,7 @@ var useLifecycleEvents = (config, options = {}) => {
|
|
|
3528
3742
|
const { config: cfg, options: opts } = latest.current;
|
|
3529
3743
|
if (opts.enabled !== false) {
|
|
3530
3744
|
const device = collectDeviceContext();
|
|
3531
|
-
if (
|
|
3745
|
+
if (cfg == null ? void 0 : cfg.appVersion) device.appVersion = cfg.appVersion;
|
|
3532
3746
|
reportFirstOpen({
|
|
3533
3747
|
target: targetOf(cfg),
|
|
3534
3748
|
sink: resolveSink(),
|
|
@@ -3550,7 +3764,7 @@ var useLifecycleEvents = (config, options = {}) => {
|
|
|
3550
3764
|
if (opts.enabled === false) return;
|
|
3551
3765
|
if (!(cfg == null ? void 0 : cfg.serverUrl) && !opts.sink) return;
|
|
3552
3766
|
const device = collectDeviceContext();
|
|
3553
|
-
if (
|
|
3767
|
+
if (cfg == null ? void 0 : cfg.appVersion) device.appVersion = cfg.appVersion;
|
|
3554
3768
|
reportSessionStart({
|
|
3555
3769
|
target: targetOf(cfg),
|
|
3556
3770
|
sink: resolveSink(),
|
|
@@ -3594,6 +3808,7 @@ exports.DEFAULT_FEATURES_TTL_MS = DEFAULT_FEATURES_TTL_MS;
|
|
|
3594
3808
|
exports.DEFAULT_SESSION_TTL_MS = DEFAULT_SESSION_TTL_MS;
|
|
3595
3809
|
exports.DemoOnboarding = DemoOnboarding;
|
|
3596
3810
|
exports.DoneBlock = DoneBlock;
|
|
3811
|
+
exports.EXTRA_KEY_PREFIX = EXTRA_KEY_PREFIX;
|
|
3597
3812
|
exports.ErrorBlock = ErrorBlock;
|
|
3598
3813
|
exports.FIRST_OPEN_EVENT = FIRST_OPEN_EVENT;
|
|
3599
3814
|
exports.IllustrationProvider = IllustrationProvider;
|
|
@@ -3605,6 +3820,7 @@ exports.OnboardingButton = Button;
|
|
|
3605
3820
|
exports.OnboardingFlow = OnboardingFlow;
|
|
3606
3821
|
exports.OnboardingScaffold = OnboardingScaffold;
|
|
3607
3822
|
exports.OnboardingThemeProvider = OnboardingThemeProvider;
|
|
3823
|
+
exports.RESERVED_USER_CONTEXT_KEYS = RESERVED_USER_CONTEXT_KEYS;
|
|
3608
3824
|
exports.SESSION_STARTED_EVENT = SESSION_STARTED_EVENT;
|
|
3609
3825
|
exports.SelectionCard = SelectionCard;
|
|
3610
3826
|
exports.StatusCard = StatusCard;
|
|
@@ -3621,17 +3837,22 @@ exports.defaultIllustrations = defaultIllustrations;
|
|
|
3621
3837
|
exports.defaultOnboardingTheme = defaultOnboardingTheme;
|
|
3622
3838
|
exports.defaultWireFeatures = defaultWireFeatures;
|
|
3623
3839
|
exports.deriveAnswers = deriveAnswers;
|
|
3840
|
+
exports.detectAppVersion = detectAppVersion;
|
|
3624
3841
|
exports.featuresCacheKey = featuresCacheKey;
|
|
3625
3842
|
exports.featuresEqual = featuresEqual;
|
|
3626
3843
|
exports.fetchWireFeatures = fetchWireFeatures;
|
|
3627
3844
|
exports.firstOpenStorageKey = firstOpenStorageKey;
|
|
3845
|
+
exports.getCurrentSessionId = getCurrentSessionId;
|
|
3846
|
+
exports.hashEmailFnv1a = hashEmailFnv1a;
|
|
3628
3847
|
exports.identifyOnboarding = identifyOnboarding;
|
|
3629
3848
|
exports.isFeaturesFresh = isFeaturesFresh;
|
|
3630
3849
|
exports.isOnboardingEnabled = isOnboardingEnabled;
|
|
3850
|
+
exports.isWireScalar = isWireScalar;
|
|
3631
3851
|
exports.loadPersistedSession = loadPersistedSession;
|
|
3632
3852
|
exports.makeSessionId = makeSessionId;
|
|
3633
3853
|
exports.mergeTheme = mergeTheme;
|
|
3634
3854
|
exports.motionSpec = motionSpec_exports;
|
|
3855
|
+
exports.namespaceExtra = namespaceExtra;
|
|
3635
3856
|
exports.onboardingComponents = onboardingComponents;
|
|
3636
3857
|
exports.parseWireFeatures = parseWireFeatures;
|
|
3637
3858
|
exports.peekPersistedSession = peekPersistedSession;
|
|
@@ -3641,11 +3862,14 @@ exports.reportClientEvent = reportClientEvent;
|
|
|
3641
3862
|
exports.reportClientEvents = reportClientEvents;
|
|
3642
3863
|
exports.reportFirstOpen = reportFirstOpen;
|
|
3643
3864
|
exports.reportSessionStart = reportSessionStart;
|
|
3865
|
+
exports.resetCurrentSessionId = resetCurrentSessionId;
|
|
3644
3866
|
exports.resetFirstOpenLatch = resetFirstOpenLatch;
|
|
3645
3867
|
exports.resetSessionStartGuard = resetSessionStartGuard;
|
|
3868
|
+
exports.resolveUserContext = resolveUserContext;
|
|
3646
3869
|
exports.sanitizeUserId = sanitizeUserId;
|
|
3647
3870
|
exports.savePersistedSession = savePersistedSession;
|
|
3648
3871
|
exports.sessionStorageKey = sessionStorageKey;
|
|
3872
|
+
exports.setCurrentSessionId = setCurrentSessionId;
|
|
3649
3873
|
exports.themeFromBrand = themeFromBrand;
|
|
3650
3874
|
exports.toAnalyticsEvent = toAnalyticsEvent;
|
|
3651
3875
|
exports.useIllustration = useIllustration;
|