@userflow-tech/react-native 0.3.0 → 0.3.1
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/README.md +325 -63
- package/docs/anchoring.md +58 -42
- package/docs/troubleshooting.md +63 -27
- package/expo-plugin/hostDependencyWarnings.d.ts +18 -0
- package/expo-plugin/hostDependencyWarnings.d.ts.map +1 -0
- package/expo-plugin/hostDependencyWarnings.js +91 -0
- package/expo-plugin/hostDependencyWarnings.js.map +1 -0
- package/expo-plugin/withUserflow.d.ts.map +1 -1
- package/expo-plugin/withUserflow.js +16 -0
- package/expo-plugin/withUserflow.js.map +1 -1
- package/lib/commonjs/anchors/AnchorRegistry.js +7 -0
- package/lib/commonjs/anchors/AnchorRegistry.js.map +1 -1
- package/lib/commonjs/anchors/elementConditionEvaluator.js +189 -55
- package/lib/commonjs/anchors/elementConditionEvaluator.js.map +1 -1
- package/lib/commonjs/anchors/elementTapMonitor.js +92 -0
- package/lib/commonjs/anchors/elementTapMonitor.js.map +1 -0
- package/lib/commonjs/anchors/elementTargetMatch.js +85 -0
- package/lib/commonjs/anchors/elementTargetMatch.js.map +1 -0
- package/lib/commonjs/anchors/fiber/findAnchorFiber.js +64 -39
- package/lib/commonjs/anchors/fiber/findAnchorFiber.js.map +1 -1
- package/lib/commonjs/anchors/fiber/touchTargetFiber.js +105 -0
- package/lib/commonjs/anchors/fiber/touchTargetFiber.js.map +1 -0
- package/lib/commonjs/anchors/resolveAnchorHost.js +2 -1
- package/lib/commonjs/anchors/resolveAnchorHost.js.map +1 -1
- package/lib/commonjs/anchors/resolveAutoAnchorHost.js +4 -2
- package/lib/commonjs/anchors/resolveAutoAnchorHost.js.map +1 -1
- package/lib/commonjs/anchors/resolveElementTargets.js +158 -0
- package/lib/commonjs/anchors/resolveElementTargets.js.map +1 -0
- package/lib/commonjs/anchors/targetPressMonitor.js +9 -3
- package/lib/commonjs/anchors/targetPressMonitor.js.map +1 -1
- package/lib/commonjs/anchors/useUserflowAnchor.js +1 -0
- package/lib/commonjs/anchors/useUserflowAnchor.js.map +1 -1
- package/lib/commonjs/anonymousId.js +16 -7
- package/lib/commonjs/anonymousId.js.map +1 -1
- package/lib/commonjs/index.js +5 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/installCheck.js +151 -0
- package/lib/commonjs/installCheck.js.map +1 -0
- package/lib/commonjs/pairing/deviceId.js +14 -11
- package/lib/commonjs/pairing/deviceId.js.map +1 -1
- package/lib/commonjs/runtime/TargetPressBridge.js +12 -1
- package/lib/commonjs/runtime/TargetPressBridge.js.map +1 -1
- package/lib/commonjs/runtime/UserflowProvider.js +6 -3
- package/lib/commonjs/runtime/UserflowProvider.js.map +1 -1
- package/lib/commonjs/storage/asyncStorage.js +67 -0
- package/lib/commonjs/storage/asyncStorage.js.map +1 -0
- package/lib/commonjs/surfaces/safeArea.js +68 -28
- package/lib/commonjs/surfaces/safeArea.js.map +1 -1
- package/lib/commonjs/version.js +1 -1
- package/lib/module/anchors/AnchorRegistry.js +7 -0
- package/lib/module/anchors/AnchorRegistry.js.map +1 -1
- package/lib/module/anchors/elementConditionEvaluator.js +189 -55
- package/lib/module/anchors/elementConditionEvaluator.js.map +1 -1
- package/lib/module/anchors/elementTapMonitor.js +87 -0
- package/lib/module/anchors/elementTapMonitor.js.map +1 -0
- package/lib/module/anchors/elementTargetMatch.js +78 -0
- package/lib/module/anchors/elementTargetMatch.js.map +1 -0
- package/lib/module/anchors/fiber/findAnchorFiber.js +62 -39
- package/lib/module/anchors/fiber/findAnchorFiber.js.map +1 -1
- package/lib/module/anchors/fiber/touchTargetFiber.js +100 -0
- package/lib/module/anchors/fiber/touchTargetFiber.js.map +1 -0
- package/lib/module/anchors/resolveAnchorHost.js +2 -1
- package/lib/module/anchors/resolveAnchorHost.js.map +1 -1
- package/lib/module/anchors/resolveAutoAnchorHost.js +3 -3
- package/lib/module/anchors/resolveAutoAnchorHost.js.map +1 -1
- package/lib/module/anchors/resolveElementTargets.js +152 -0
- package/lib/module/anchors/resolveElementTargets.js.map +1 -0
- package/lib/module/anchors/targetPressMonitor.js +8 -3
- package/lib/module/anchors/targetPressMonitor.js.map +1 -1
- package/lib/module/anchors/useUserflowAnchor.js +1 -0
- package/lib/module/anchors/useUserflowAnchor.js.map +1 -1
- package/lib/module/anonymousId.js +15 -5
- package/lib/module/anonymousId.js.map +1 -1
- package/lib/module/index.js +5 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/installCheck.js +139 -0
- package/lib/module/installCheck.js.map +1 -0
- package/lib/module/pairing/deviceId.js +14 -10
- package/lib/module/pairing/deviceId.js.map +1 -1
- package/lib/module/runtime/TargetPressBridge.js +12 -1
- package/lib/module/runtime/TargetPressBridge.js.map +1 -1
- package/lib/module/runtime/UserflowProvider.js +7 -4
- package/lib/module/runtime/UserflowProvider.js.map +1 -1
- package/lib/module/storage/asyncStorage.js +61 -0
- package/lib/module/storage/asyncStorage.js.map +1 -0
- package/lib/module/surfaces/safeArea.js +65 -28
- package/lib/module/surfaces/safeArea.js.map +1 -1
- package/lib/module/version.js +1 -1
- package/lib/typescript/commonjs/src/anchors/AnchorRegistry.d.ts +7 -0
- package/lib/typescript/commonjs/src/anchors/AnchorRegistry.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/elementConditionEvaluator.d.ts +12 -16
- package/lib/typescript/commonjs/src/anchors/elementConditionEvaluator.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/elementTapMonitor.d.ts +36 -0
- package/lib/typescript/commonjs/src/anchors/elementTapMonitor.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/anchors/elementTargetMatch.d.ts +20 -0
- package/lib/typescript/commonjs/src/anchors/elementTargetMatch.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/anchors/fiber/findAnchorFiber.d.ts +17 -5
- package/lib/typescript/commonjs/src/anchors/fiber/findAnchorFiber.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/fiber/touchTargetFiber.d.ts +24 -0
- package/lib/typescript/commonjs/src/anchors/fiber/touchTargetFiber.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/anchors/resolveAnchorHost.d.ts +2 -1
- package/lib/typescript/commonjs/src/anchors/resolveAnchorHost.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/resolveAutoAnchorHost.d.ts +10 -1
- package/lib/typescript/commonjs/src/anchors/resolveAutoAnchorHost.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/resolveElementTargets.d.ts +39 -0
- package/lib/typescript/commonjs/src/anchors/resolveElementTargets.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/anchors/targetPressMonitor.d.ts +2 -0
- package/lib/typescript/commonjs/src/anchors/targetPressMonitor.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anchors/useUserflowAnchor.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/anonymousId.d.ts +2 -0
- package/lib/typescript/commonjs/src/anonymousId.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/installCheck.d.ts +33 -0
- package/lib/typescript/commonjs/src/installCheck.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/pairing/deviceId.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/runtime/TargetPressBridge.d.ts +2 -1
- package/lib/typescript/commonjs/src/runtime/TargetPressBridge.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/runtime/UserflowProvider.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/storage/asyncStorage.d.ts +15 -0
- package/lib/typescript/commonjs/src/storage/asyncStorage.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/surfaces/safeArea.d.ts +4 -2
- package/lib/typescript/commonjs/src/surfaces/safeArea.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/version.d.ts +1 -1
- package/lib/typescript/module/src/anchors/AnchorRegistry.d.ts +7 -0
- package/lib/typescript/module/src/anchors/AnchorRegistry.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/elementConditionEvaluator.d.ts +12 -16
- package/lib/typescript/module/src/anchors/elementConditionEvaluator.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/elementTapMonitor.d.ts +36 -0
- package/lib/typescript/module/src/anchors/elementTapMonitor.d.ts.map +1 -0
- package/lib/typescript/module/src/anchors/elementTargetMatch.d.ts +20 -0
- package/lib/typescript/module/src/anchors/elementTargetMatch.d.ts.map +1 -0
- package/lib/typescript/module/src/anchors/fiber/findAnchorFiber.d.ts +17 -5
- package/lib/typescript/module/src/anchors/fiber/findAnchorFiber.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/fiber/touchTargetFiber.d.ts +24 -0
- package/lib/typescript/module/src/anchors/fiber/touchTargetFiber.d.ts.map +1 -0
- package/lib/typescript/module/src/anchors/resolveAnchorHost.d.ts +2 -1
- package/lib/typescript/module/src/anchors/resolveAnchorHost.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/resolveAutoAnchorHost.d.ts +10 -1
- package/lib/typescript/module/src/anchors/resolveAutoAnchorHost.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/resolveElementTargets.d.ts +39 -0
- package/lib/typescript/module/src/anchors/resolveElementTargets.d.ts.map +1 -0
- package/lib/typescript/module/src/anchors/targetPressMonitor.d.ts +2 -0
- package/lib/typescript/module/src/anchors/targetPressMonitor.d.ts.map +1 -1
- package/lib/typescript/module/src/anchors/useUserflowAnchor.d.ts.map +1 -1
- package/lib/typescript/module/src/anonymousId.d.ts +2 -0
- package/lib/typescript/module/src/anonymousId.d.ts.map +1 -1
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/installCheck.d.ts +33 -0
- package/lib/typescript/module/src/installCheck.d.ts.map +1 -0
- package/lib/typescript/module/src/pairing/deviceId.d.ts.map +1 -1
- package/lib/typescript/module/src/runtime/TargetPressBridge.d.ts +2 -1
- package/lib/typescript/module/src/runtime/TargetPressBridge.d.ts.map +1 -1
- package/lib/typescript/module/src/runtime/UserflowProvider.d.ts.map +1 -1
- package/lib/typescript/module/src/storage/asyncStorage.d.ts +15 -0
- package/lib/typescript/module/src/storage/asyncStorage.d.ts.map +1 -0
- package/lib/typescript/module/src/surfaces/safeArea.d.ts +4 -2
- package/lib/typescript/module/src/surfaces/safeArea.d.ts.map +1 -1
- package/lib/typescript/module/src/version.d.ts +1 -1
- package/package.json +13 -1
- package/src/anchors/AnchorRegistry.ts +12 -0
- package/src/anchors/elementConditionEvaluator.ts +235 -70
- package/src/anchors/elementTapMonitor.ts +95 -0
- package/src/anchors/elementTargetMatch.ts +90 -0
- package/src/anchors/fiber/findAnchorFiber.ts +66 -35
- package/src/anchors/fiber/touchTargetFiber.ts +125 -0
- package/src/anchors/resolveAnchorHost.ts +2 -1
- package/src/anchors/resolveAutoAnchorHost.ts +3 -3
- package/src/anchors/resolveElementTargets.ts +165 -0
- package/src/anchors/targetPressMonitor.ts +12 -3
- package/src/anchors/useUserflowAnchor.ts +1 -0
- package/src/anonymousId.ts +19 -8
- package/src/index.ts +10 -0
- package/src/installCheck.ts +191 -0
- package/src/pairing/deviceId.ts +14 -11
- package/src/runtime/TargetPressBridge.tsx +17 -1
- package/src/runtime/UserflowProvider.tsx +11 -4
- package/src/storage/asyncStorage.ts +88 -0
- package/src/surfaces/safeArea.ts +80 -40
- package/src/version.ts +1 -1
- package/vendor/core/dist/constants.d.ts +2 -0
- package/vendor/core/dist/constants.d.ts.map +1 -1
- package/vendor/core/dist/constants.js +2 -0
- package/vendor/core/dist/constants.js.map +1 -1
- package/vendor/core/dist/engine/ClientConditionEngine.d.ts +20 -1
- package/vendor/core/dist/engine/ClientConditionEngine.d.ts.map +1 -1
- package/vendor/core/dist/engine/ClientConditionEngine.js +13 -10
- package/vendor/core/dist/engine/ClientConditionEngine.js.map +1 -1
- package/vendor/core/dist/engine/UserflowCore.d.ts.map +1 -1
- package/vendor/core/dist/engine/UserflowCore.js +21 -2
- package/vendor/core/dist/engine/UserflowCore.js.map +1 -1
- package/vendor/core/dist/index.d.ts +1 -1
- package/vendor/core/dist/index.d.ts.map +1 -1
- package/vendor/core/dist/index.js.map +1 -1
- package/vendor/core/dist/version.d.ts +1 -1
- package/vendor/core/dist/version.js +1 -1
- package/vendor/core/package.json +1 -1
- package/vendor/protocol/package.json +1 -1
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/** Matches the web SDK's `userflow:anonymousId` localStorage key. */
|
|
2
2
|
export declare const ANONYMOUS_ID_STORAGE_KEY = "userflow:anonymousId";
|
|
3
|
+
export declare const ANONYMOUS_STORAGE_UNAVAILABLE = "Userflow.identifyAnonymous() is not supported when persistent storage is unavailable.";
|
|
4
|
+
export declare const ANONYMOUS_STORAGE_NOT_LINKED: string;
|
|
3
5
|
export declare function uuid(): string;
|
|
4
6
|
export declare function getOrCreateAnonymousId(): Promise<string>;
|
|
5
7
|
export declare function clearAnonymousId(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"anonymousId.d.ts","sourceRoot":"","sources":["../../../../src/anonymousId.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"anonymousId.d.ts","sourceRoot":"","sources":["../../../../src/anonymousId.ts"],"names":[],"mappings":"AAIA,qEAAqE;AACrE,eAAO,MAAM,wBAAwB,yBAAyB,CAAC;AAE/D,eAAO,MAAM,6BAA6B,0FAC+C,CAAC;AAE1F,eAAO,MAAM,4BAA4B,QAEwD,CAAC;AAElG,wBAAgB,IAAI,IAAI,MAAM,CAQ7B;AAED,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,MAAM,CAAC,CAe9D;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAQtD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EACV,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,uBAAuB,EACvB,oBAAoB,EACpB,uBAAuB,EACvB,mBAAmB,EACnB,oBAAoB,EACpB,0BAA0B,EAC3B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,sBAAsB,CAAC;AAG9B,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,aAAa,EACnB,MAAM,wBAAwB,CAAC;AAQhC,OAAO,EAKL,KAAK,aAAa,EACnB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAKL,KAAK,cAAc,EACpB,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export declare const INSTALL_CHECK_HEADER = "[Userflow] Native setup is incomplete. Flows may not run until you fix the following, then rebuild the app (a Metro reload is not enough):";
|
|
2
|
+
export declare const INSTALL_ASYNC_STORAGE_LINE = "- @react-native-async-storage/async-storage is not linked. Anonymous users and Builder pairing will not persist. Add it to the app package.json (npx expo install @react-native-async-storage/async-storage), run pod install on iOS, and rebuild.";
|
|
3
|
+
export declare const INSTALL_VIEW_SHOT_LINE = "- react-native-view-shot is not linked, so Builder element selection gets no screenshot. Install react-native-view-shot@^5.0.0 and rebuild. On Expo SDK 54, pin ^5.0.0; an unpinned npx expo install resolves 4.0.3.";
|
|
4
|
+
export declare const INSTALL_WEBVIEW_LINE = "- react-native-webview is not linked. Evaluate JavaScript and WebView banners will not run. Install it (npx expo install react-native-webview) and rebuild.";
|
|
5
|
+
export declare const INSTALL_DEVICE_INFO_LINE = "- react-native-device-info is not linked, so app_version and app_build are not sent. npm install react-native-device-info, then rebuild.";
|
|
6
|
+
export declare const INSTALL_CHECK_FOOTER = "See docs/troubleshooting.md.";
|
|
7
|
+
export declare const EXPO_GO_WARNING = "[Userflow] This app is running in Expo Go, which cannot load the SDK native modules. Builder preview links will not open the app. Use a development build (npx expo run:ios / npx expo run:android).";
|
|
8
|
+
export declare const INIT_OPTIONS_IGNORED_WARNING = "[Userflow] Userflow.init() already ran with different options. The new clientToken, serverEndpoint, and pairingEndpoint are ignored because init runs once per process. Userflow.reset() does not apply new credentials. Restart the app to change them.";
|
|
9
|
+
/** Lines for missing native modules. Empty when the build looks complete. */
|
|
10
|
+
export declare function collectInstallFindings(): string[];
|
|
11
|
+
export declare function expoGoWarning(): string | null;
|
|
12
|
+
export declare function formatInstallWarning(findings: readonly string[]): string;
|
|
13
|
+
/**
|
|
14
|
+
* One development warning for missing native modules, plus a separate warning
|
|
15
|
+
* when the host is Expo Go. Release builds stay quiet.
|
|
16
|
+
*/
|
|
17
|
+
export declare function warnIfInstallIncomplete(): void;
|
|
18
|
+
/** @internal */
|
|
19
|
+
export declare function resetInstallCheckForTests(): void;
|
|
20
|
+
export declare function warnIfInitOptionsIgnored(config: {
|
|
21
|
+
clientToken: string;
|
|
22
|
+
serverEndpoint?: string;
|
|
23
|
+
pairingEndpoint?: string;
|
|
24
|
+
}): void;
|
|
25
|
+
/** The in-flight `init` resolved, so later calls really are ignored. */
|
|
26
|
+
export declare function commitInitOptions(): void;
|
|
27
|
+
/**
|
|
28
|
+
* The in-flight `init` rejected. Core drops its cached promise and will run
|
|
29
|
+
* the next call, so a corrected token or endpoint must not warn.
|
|
30
|
+
* A rejection after a successful init does not forget that success.
|
|
31
|
+
*/
|
|
32
|
+
export declare function releaseFailedInitOptions(): void;
|
|
33
|
+
//# sourceMappingURL=installCheck.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"installCheck.d.ts","sourceRoot":"","sources":["../../../../src/installCheck.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,oBAAoB,+IAC6G,CAAC;AAE/I,eAAO,MAAM,0BAA0B,uPAC+M,CAAC;AAEvP,eAAO,MAAM,sBAAsB,yNACqL,CAAC;AAEzN,eAAO,MAAM,oBAAoB,gKAC8H,CAAC;AAEhK,eAAO,MAAM,wBAAwB,6IACuG,CAAC;AAE7I,eAAO,MAAM,oBAAoB,iCAAiC,CAAC;AAEnE,eAAO,MAAM,eAAe,yMAC4K,CAAC;AAEzM,eAAO,MAAM,4BAA4B,6PACmN,CAAC;AAyD7P,6EAA6E;AAC7E,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAWjD;AAED,wBAAgB,aAAa,IAAI,MAAM,GAAG,IAAI,CAI7C;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAExE;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAe9C;AAED,gBAAgB;AAChB,wBAAgB,yBAAyB,IAAI,IAAI,CAIhD;AAwBD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GAAG,IAAI,CAgBP;AAED,wEAAwE;AACxE,wBAAgB,iBAAiB,IAAI,IAAI,CAExC;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAG/C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deviceId.d.ts","sourceRoot":"","sources":["../../../../../src/pairing/deviceId.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"deviceId.d.ts","sourceRoot":"","sources":["../../../../../src/pairing/deviceId.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,6BAA6B,CAAC;AAIxE,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,MAAM,CAAC,CA0BlE;AAED,4EAA4E;AAC5E,wBAAgB,4BAA4B,IAAI,IAAI,CAEnD"}
|
|
@@ -9,7 +9,8 @@ export interface TargetPressBridgeProps {
|
|
|
9
9
|
*
|
|
10
10
|
* The Userflow overlay is a sibling above the app, so hole Pressables would
|
|
11
11
|
* intercept presses. Instead we hit-test bubbled `onTouchStart` / `onTouchEnd`
|
|
12
|
-
* against the rect registered by {@link TooltipSurface}
|
|
12
|
+
* against the rect registered by {@link TooltipSurface}, and — while an
|
|
13
|
+
* element click condition is tracked — against the fiber under the finger.
|
|
13
14
|
*
|
|
14
15
|
* Preview-chrome double taps are observed by `DoubleTapBridge` around the
|
|
15
16
|
* whole provider tree — this bridge never sees overlay touches.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TargetPressBridge.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/TargetPressBridge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"TargetPressBridge.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/TargetPressBridge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,QAAQ,EAAE,EAAE,sBAAsB,GAAG,KAAK,CAAC,YAAY,CAuD1F"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UserflowProvider.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/UserflowProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAClF,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"UserflowProvider.d.ts","sourceRoot":"","sources":["../../../../../src/runtime/UserflowProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAClF,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AA2B/B,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,iBAAiB,CAAC;CAC3B;AAID,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,yDAAyD;IACzD,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B,2DAA2D;IAC3D,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AA0CD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,gBAAgB,GAC/B,EAAE,qBAAqB,GAAG,KAAK,CAAC,YAAY,CAoF5C;AAoBD,2EAA2E;AAC3E,wBAAgB,WAAW,IAAI,oBAAoB,CAMlD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface AsyncStorageLike {
|
|
2
|
+
getItem(key: string): Promise<string | null>;
|
|
3
|
+
setItem(key: string, value: string): Promise<void>;
|
|
4
|
+
removeItem(key: string): Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
/** True when some AsyncStorage native binary is in this build. */
|
|
7
|
+
export declare function isAsyncStorageLinked(): boolean;
|
|
8
|
+
/**
|
|
9
|
+
* The AsyncStorage JS API, or `null` when the package or its native module is
|
|
10
|
+
* missing. Never requires the package until the native module is registered.
|
|
11
|
+
*/
|
|
12
|
+
export declare function getAsyncStorage(): AsyncStorageLike | null;
|
|
13
|
+
/** @internal */
|
|
14
|
+
export declare function resetAsyncStorageCacheForTests(): void;
|
|
15
|
+
//# sourceMappingURL=asyncStorage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asyncStorage.d.ts","sourceRoot":"","sources":["../../../../../src/storage/asyncStorage.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnD,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxC;AA6BD,kEAAkE;AAClE,wBAAgB,oBAAoB,IAAI,OAAO,CAI9C;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,gBAAgB,GAAG,IAAI,CAyBzD;AAED,gBAAgB;AAChB,wBAAgB,8BAA8B,IAAI,IAAI,CAErD"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Context } from 'react';
|
|
2
2
|
export interface EdgeInsets {
|
|
3
3
|
top: number;
|
|
4
4
|
right: number;
|
|
5
5
|
bottom: number;
|
|
6
6
|
left: number;
|
|
7
7
|
}
|
|
8
|
-
|
|
8
|
+
export declare const MISSING_SAFE_AREA_PROVIDER_WARNING: string;
|
|
9
|
+
/** Value from the nearest provider, or `null` when the peer or provider is absent. */
|
|
10
|
+
export declare function useParentSafeAreaInsets(): EdgeInsets | null;
|
|
9
11
|
export declare function useUserflowSafeAreaInsets(): EdgeInsets;
|
|
10
12
|
/**
|
|
11
13
|
* `SafeAreaInsetsContext` from the optional peer, or `null` when it is not installed.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safeArea.d.ts","sourceRoot":"","sources":["../../../../../src/surfaces/safeArea.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"safeArea.d.ts","sourceRoot":"","sources":["../../../../../src/surfaces/safeArea.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,OAAO,EAAE,MAAM,OAAO,CAAC;AAE5C,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAUD,eAAO,MAAM,kCAAkC,QAGZ,CAAC;AAuEpC,sFAAsF;AACtF,wBAAgB,uBAAuB,IAAI,UAAU,GAAG,IAAI,CAE3D;AAED,wBAAgB,yBAAyB,IAAI,UAAU,CAMtD;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,IAAI,CAE5E;AAED,gBAAgB;AAChB,wBAAgB,gCAAgC,IAAI,IAAI,CAGvD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@userflow-tech/react-native",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Userflow SDK for React Native — onboarding flows, tooltips, and modals.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"main": "./lib/commonjs/index.js",
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
"source": "src/index.ts",
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
|
+
"types": {
|
|
14
|
+
"import": "./lib/typescript/module/src/index.d.ts",
|
|
15
|
+
"require": "./lib/typescript/commonjs/src/index.d.ts"
|
|
16
|
+
},
|
|
13
17
|
"react-native": "./src/index.ts",
|
|
14
18
|
"import": {
|
|
15
19
|
"types": "./lib/typescript/module/src/index.d.ts",
|
|
@@ -21,6 +25,10 @@
|
|
|
21
25
|
}
|
|
22
26
|
},
|
|
23
27
|
"./navigation": {
|
|
28
|
+
"types": {
|
|
29
|
+
"import": "./lib/typescript/module/src/navigation/index.d.ts",
|
|
30
|
+
"require": "./lib/typescript/commonjs/src/navigation/index.d.ts"
|
|
31
|
+
},
|
|
24
32
|
"react-native": "./src/navigation/index.ts",
|
|
25
33
|
"import": {
|
|
26
34
|
"types": "./lib/typescript/module/src/navigation/index.d.ts",
|
|
@@ -32,6 +40,10 @@
|
|
|
32
40
|
}
|
|
33
41
|
},
|
|
34
42
|
"./expo-router": {
|
|
43
|
+
"types": {
|
|
44
|
+
"import": "./lib/typescript/module/src/expo-router/index.d.ts",
|
|
45
|
+
"require": "./lib/typescript/commonjs/src/expo-router/index.d.ts"
|
|
46
|
+
},
|
|
35
47
|
"react-native": "./src/expo-router/index.ts",
|
|
36
48
|
"import": {
|
|
37
49
|
"types": "./lib/typescript/module/src/expo-router/index.d.ts",
|
|
@@ -8,6 +8,11 @@ export interface AnchorHost {
|
|
|
8
8
|
* Called when the measured rect is not fully visible (bounded retries per step).
|
|
9
9
|
*/
|
|
10
10
|
scrollIntoView?: () => void;
|
|
11
|
+
/**
|
|
12
|
+
* Public instance this host was registered from, when known. Element click
|
|
13
|
+
* conditions use it to match a tap to this anchor.
|
|
14
|
+
*/
|
|
15
|
+
node?: object | null;
|
|
11
16
|
}
|
|
12
17
|
|
|
13
18
|
type Listener = () => void;
|
|
@@ -52,6 +57,13 @@ export class AnchorRegistry {
|
|
|
52
57
|
return last;
|
|
53
58
|
}
|
|
54
59
|
|
|
60
|
+
/** Every host registered for `id`, in registration order. */
|
|
61
|
+
getAll(id: string): AnchorHost[] {
|
|
62
|
+
const set = this.anchors.get(id);
|
|
63
|
+
if (!set || set.size === 0) return [];
|
|
64
|
+
return [...set];
|
|
65
|
+
}
|
|
66
|
+
|
|
55
67
|
/** True when more than one host is registered for the same id. */
|
|
56
68
|
isAmbiguous(id: string): boolean {
|
|
57
69
|
return (this.anchors.get(id)?.size ?? 0) > 1;
|
|
@@ -1,35 +1,43 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
1
|
+
import type {
|
|
2
|
+
ConditionEvaluator,
|
|
3
|
+
ConditionEvaluatorContext,
|
|
4
|
+
ConditionReport,
|
|
5
|
+
} from '@userflow-tech/core';
|
|
6
|
+
import { decodeMobileAutoData, type FlowConditionFragment } from '@userflow-tech/protocol';
|
|
3
7
|
|
|
4
8
|
import { anchorChangeTicker } from './anchorChangeTicker';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
9
|
+
import { elementTapMonitor } from './elementTapMonitor';
|
|
10
|
+
import { fiberIsUnder, tapPathDisabled } from './elementTargetMatch';
|
|
11
|
+
import {
|
|
12
|
+
resolveElementTargets,
|
|
13
|
+
tapMayHitSelector,
|
|
14
|
+
type ElementTarget,
|
|
15
|
+
} from './resolveElementTargets';
|
|
7
16
|
import { resolveManualAnchorId } from './resolveManualAnchorId';
|
|
8
17
|
|
|
9
|
-
/**
|
|
10
|
-
const
|
|
18
|
+
/** How many hosts to measure before giving up on a crowded duplicate id. */
|
|
19
|
+
const MAX_MEASURED_HOSTS = 8;
|
|
20
|
+
|
|
21
|
+
/** Same bound tooltip measurement uses. A host that never calls back is unknown. */
|
|
22
|
+
const MEASURE_TIMEOUT_MS = 400;
|
|
11
23
|
|
|
12
24
|
/**
|
|
13
25
|
* Evaluate ELEMENT client conditions against manual anchors, fiber-resolved
|
|
14
|
-
* `testID` / `nativeID` / `accessibilityLabel` targets, and AUTO
|
|
15
|
-
* selectors.
|
|
26
|
+
* `userflowId` / `testID` / `nativeID` / `accessibilityLabel` targets, and AUTO
|
|
27
|
+
* (codeless) selectors.
|
|
16
28
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* just because the auto-anchor registry is empty. Web-interaction states
|
|
21
|
-
* (CLICK, DISABLED, …) still report unknown.
|
|
29
|
+
* PRESENT / NOT_PRESENT: any uniquely-or-not host on a visible navigator screen
|
|
30
|
+
* counts (web parity — duplicates are present). A measured 0×0 host counts as
|
|
31
|
+
* absent. AUTO `unknown` / `ambiguous` stay `null`.
|
|
22
32
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* ScrollView, opacity 0, etc.) would need async `measureInWindow` and is out
|
|
28
|
-
* of scope.
|
|
33
|
+
* CLICK / NOT_CLICK: latch from the first matching tap, including a tap on a
|
|
34
|
+
* descendant. The latch survives re-attach via `previousIsTrue` and is cleared
|
|
35
|
+
* when the server untracks. Disabled hosts are ignored. Until it latches, an
|
|
36
|
+
* AUTO selector that does not resolve reports `null`, like presence.
|
|
29
37
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
38
|
+
* Element states are compared as string literals rather than protocol enums so
|
|
39
|
+
* the wire values stay obvious next to the branches. They match
|
|
40
|
+
* `FlowConditionElementState`.
|
|
33
41
|
*/
|
|
34
42
|
export function createElementConditionEvaluator(
|
|
35
43
|
warn: (message: string) => void = (message) => {
|
|
@@ -47,75 +55,232 @@ export function createElementConditionEvaluator(
|
|
|
47
55
|
warn(message);
|
|
48
56
|
};
|
|
49
57
|
|
|
50
|
-
return (condition, report) => {
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
report
|
|
54
|
-
}
|
|
58
|
+
return (condition, report, context) => {
|
|
59
|
+
const elementState = condition.elementState as string | null;
|
|
60
|
+
if (elementState === 'PRESENT' || elementState === 'NOT_PRESENT') {
|
|
61
|
+
return trackPresence(condition, elementState, report, warnOnce);
|
|
62
|
+
}
|
|
63
|
+
if (elementState === 'CLICK' || elementState === 'NOT_CLICK') {
|
|
64
|
+
return trackClick(condition, elementState, report, context, warnOnce);
|
|
65
|
+
}
|
|
55
66
|
|
|
56
|
-
|
|
57
|
-
|
|
67
|
+
warnOnce(
|
|
68
|
+
condition.id,
|
|
69
|
+
`[Userflow] ELEMENT condition ${condition.id} uses unsupported elementState ` +
|
|
70
|
+
`"${elementState ?? 'null'}" (supported: PRESENT, NOT_PRESENT, CLICK, NOT_CLICK); ` +
|
|
71
|
+
'leaving unknown',
|
|
72
|
+
);
|
|
73
|
+
report(null);
|
|
74
|
+
return () => {};
|
|
58
75
|
};
|
|
59
76
|
}
|
|
60
77
|
|
|
61
|
-
function
|
|
78
|
+
function trackPresence(
|
|
62
79
|
condition: FlowConditionFragment,
|
|
80
|
+
elementState: 'PRESENT' | 'NOT_PRESENT',
|
|
81
|
+
report: ConditionReport,
|
|
63
82
|
warnOnce: (conditionId: string, message: string) => void,
|
|
64
|
-
):
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
83
|
+
): () => void {
|
|
84
|
+
// A synchronous result supersedes any older measurement. Only one
|
|
85
|
+
// measurement runs at a time, and a change during it re-runs once it settles
|
|
86
|
+
// instead of discarding it, so steady anchor churn cannot hold the condition
|
|
87
|
+
// at unknown.
|
|
88
|
+
let generation = 0;
|
|
89
|
+
let reportedGeneration = 0;
|
|
90
|
+
let measuring = false;
|
|
91
|
+
let changedWhileMeasuring = false;
|
|
92
|
+
let disposed = false;
|
|
93
|
+
|
|
94
|
+
const evaluate = (): void => {
|
|
95
|
+
if (disposed) return;
|
|
96
|
+
const gen = ++generation;
|
|
97
|
+
const resolution = resolveElementTargets(condition.selector);
|
|
98
|
+
|
|
99
|
+
if (resolution.status === 'unknown') {
|
|
100
|
+
if (!resolution.silent) warnUnknown(condition, warnOnce);
|
|
101
|
+
reportedGeneration = gen;
|
|
102
|
+
report(null);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (resolution.status === 'absent') {
|
|
106
|
+
reportedGeneration = gen;
|
|
107
|
+
report(elementState === 'PRESENT' ? false : true);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
if (measuring) {
|
|
111
|
+
changedWhileMeasuring = true;
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
measuring = true;
|
|
116
|
+
void measureVisibility(resolution.targets)
|
|
117
|
+
.catch((): HostVisibility => 'unknown')
|
|
118
|
+
.then((visibility) => {
|
|
119
|
+
measuring = false;
|
|
120
|
+
if (disposed) return;
|
|
121
|
+
if (gen > reportedGeneration) {
|
|
122
|
+
reportedGeneration = gen;
|
|
123
|
+
if (visibility === 'unknown') {
|
|
124
|
+
report(null);
|
|
125
|
+
} else {
|
|
126
|
+
const present = visibility === 'present';
|
|
127
|
+
report(elementState === 'PRESENT' ? present : !present);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (changedWhileMeasuring) {
|
|
131
|
+
changedWhileMeasuring = false;
|
|
132
|
+
evaluate();
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
evaluate();
|
|
138
|
+
const unsubscribe = anchorChangeTicker.subscribe(evaluate);
|
|
139
|
+
return () => {
|
|
140
|
+
disposed = true;
|
|
141
|
+
unsubscribe();
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function trackClick(
|
|
146
|
+
condition: FlowConditionFragment,
|
|
147
|
+
elementState: 'CLICK' | 'NOT_CLICK',
|
|
148
|
+
report: ConditionReport,
|
|
149
|
+
context: ConditionEvaluatorContext | undefined,
|
|
150
|
+
warnOnce: (conditionId: string, message: string) => void,
|
|
151
|
+
): () => void {
|
|
152
|
+
if (!clickSelectorUsable(condition)) {
|
|
153
|
+
warnUnknown(condition, warnOnce);
|
|
154
|
+
report(null);
|
|
155
|
+
return () => {};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// CLICK starts false and latches true. NOT_CLICK starts true and latches false.
|
|
159
|
+
const valueWhenOccurred = elementState === 'CLICK';
|
|
160
|
+
if (context?.previousIsTrue === valueWhenOccurred) {
|
|
161
|
+
report(valueWhenOccurred);
|
|
162
|
+
return () => {};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
let latched = false;
|
|
166
|
+
let stopWatchingResolution = (): void => {};
|
|
167
|
+
if ((condition.selector?.type as string | null) === 'AUTO') {
|
|
168
|
+
// An AUTO selector can stay unresolvable (empty auto-anchor registry, a
|
|
169
|
+
// tie between look-alikes), and then no tap can latch. Report unknown
|
|
170
|
+
// until it resolves, as presence does, rather than an unclicked value
|
|
171
|
+
// nothing could clear.
|
|
172
|
+
const reportUnclickedOnceResolvable = (): void => {
|
|
173
|
+
if (latched) return;
|
|
174
|
+
const resolution = resolveElementTargets(condition.selector);
|
|
175
|
+
if (resolution.status === 'unknown') {
|
|
176
|
+
if (!resolution.silent) warnUnknown(condition, warnOnce);
|
|
177
|
+
report(null);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
report(!valueWhenOccurred);
|
|
181
|
+
};
|
|
182
|
+
reportUnclickedOnceResolvable();
|
|
183
|
+
stopWatchingResolution = anchorChangeTicker.subscribe(reportUnclickedOnceResolvable);
|
|
184
|
+
} else {
|
|
185
|
+
report(!valueWhenOccurred);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const subscription = {
|
|
189
|
+
unsubscribe: (): void => {},
|
|
190
|
+
};
|
|
191
|
+
subscription.unsubscribe = elementTapMonitor.subscribe((tap) => {
|
|
192
|
+
if (latched) return;
|
|
193
|
+
if (!tapMayHitSelector(condition.selector, tap)) return;
|
|
194
|
+
const resolution = resolveElementTargets(condition.selector);
|
|
195
|
+
if (resolution.status !== 'found') return;
|
|
196
|
+
|
|
197
|
+
const matched = resolution.targets.find(
|
|
198
|
+
(target) => target.fiber != null && fiberIsUnder(tap.targetFiber, target.fiber),
|
|
72
199
|
);
|
|
73
|
-
return
|
|
200
|
+
if (!matched?.fiber) return;
|
|
201
|
+
if (tapPathDisabled(tap.targetFiber, matched.fiber)) return;
|
|
202
|
+
|
|
203
|
+
latched = true;
|
|
204
|
+
report(valueWhenOccurred, { immediate: true });
|
|
205
|
+
subscription.unsubscribe();
|
|
206
|
+
stopWatchingResolution();
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
return () => {
|
|
210
|
+
subscription.unsubscribe();
|
|
211
|
+
stopWatchingResolution();
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function clickSelectorUsable(condition: FlowConditionFragment): boolean {
|
|
216
|
+
const selector = condition.selector;
|
|
217
|
+
if (selector == null) return false;
|
|
218
|
+
if ((selector.type as string | null) === 'AUTO') {
|
|
219
|
+
// Without a fingerprint the selector can never resolve, so a definite
|
|
220
|
+
// NOT_CLICK true would start the flow on a target nobody can tap.
|
|
221
|
+
return decodeMobileAutoData(selector.autoData)?.fingerprint != null;
|
|
74
222
|
}
|
|
223
|
+
return resolveManualAnchorId(selector.css) != null;
|
|
224
|
+
}
|
|
75
225
|
|
|
226
|
+
function warnUnknown(
|
|
227
|
+
condition: FlowConditionFragment,
|
|
228
|
+
warnOnce: (conditionId: string, message: string) => void,
|
|
229
|
+
): void {
|
|
76
230
|
const selector = condition.selector;
|
|
77
231
|
if (selector == null) {
|
|
78
232
|
warnOnce(
|
|
79
233
|
condition.id,
|
|
80
234
|
`[Userflow] ELEMENT condition ${condition.id} has no selector; leaving unknown`,
|
|
81
235
|
);
|
|
82
|
-
return
|
|
236
|
+
return;
|
|
83
237
|
}
|
|
84
|
-
|
|
85
238
|
if ((selector.type as string | null) === 'AUTO') {
|
|
86
|
-
const resolution = resolveAutoAnchorHost(selector.autoData);
|
|
87
|
-
if (resolution.status === 'unknown') {
|
|
88
|
-
warnOnce(
|
|
89
|
-
condition.id,
|
|
90
|
-
`[Userflow] ELEMENT condition ${condition.id} uses an AUTO (codeless) selector ` +
|
|
91
|
-
'that could not be resolved; leaving unknown',
|
|
92
|
-
);
|
|
93
|
-
return null;
|
|
94
|
-
}
|
|
95
|
-
if (resolution.status === 'ambiguous') {
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
const present = resolution.status === 'found';
|
|
99
|
-
return elementState === 'PRESENT' ? present : !present;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const anchorId = resolveManualAnchorId(selector.css);
|
|
103
|
-
if (anchorId == null) {
|
|
104
239
|
warnOnce(
|
|
105
240
|
condition.id,
|
|
106
|
-
`[Userflow] ELEMENT condition ${condition.id}
|
|
107
|
-
'leaving unknown',
|
|
241
|
+
`[Userflow] ELEMENT condition ${condition.id} uses an AUTO (codeless) selector ` +
|
|
242
|
+
'that could not be resolved; leaving unknown',
|
|
108
243
|
);
|
|
109
|
-
return
|
|
244
|
+
return;
|
|
110
245
|
}
|
|
246
|
+
warnOnce(
|
|
247
|
+
condition.id,
|
|
248
|
+
`[Userflow] ELEMENT condition ${condition.id} has no resolvable manual anchor id; ` +
|
|
249
|
+
'leaving unknown',
|
|
250
|
+
);
|
|
251
|
+
}
|
|
111
252
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
253
|
+
type HostVisibility = 'present' | 'absent' | 'unknown';
|
|
254
|
+
|
|
255
|
+
/** Measures hosts in parallel so duplicates cost one timeout, not one each. */
|
|
256
|
+
async function measureVisibility(targets: ElementTarget[]): Promise<HostVisibility> {
|
|
257
|
+
const slice = targets.slice(0, MAX_MEASURED_HOSTS);
|
|
258
|
+
const measured = await Promise.all(slice.map(measureHost));
|
|
259
|
+
if (measured.some((size) => size !== 'timeout' && size.width > 0 && size.height > 0)) {
|
|
260
|
+
return 'present';
|
|
118
261
|
}
|
|
119
|
-
|
|
120
|
-
return
|
|
262
|
+
if (measured.includes('timeout') || targets.length > slice.length) return 'unknown';
|
|
263
|
+
return 'absent';
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
function measureHost(
|
|
267
|
+
target: ElementTarget,
|
|
268
|
+
): Promise<{ width: number; height: number } | 'timeout'> {
|
|
269
|
+
return new Promise((resolve) => {
|
|
270
|
+
let settled = false;
|
|
271
|
+
const finish = (value: { width: number; height: number } | 'timeout'): void => {
|
|
272
|
+
if (settled) return;
|
|
273
|
+
settled = true;
|
|
274
|
+
clearTimeout(timer);
|
|
275
|
+
resolve(value);
|
|
276
|
+
};
|
|
277
|
+
const timer = setTimeout(() => finish('timeout'), MEASURE_TIMEOUT_MS);
|
|
278
|
+
try {
|
|
279
|
+
target.host.measureInWindow((_x, _y, width, height) => {
|
|
280
|
+
finish({ width, height });
|
|
281
|
+
});
|
|
282
|
+
} catch {
|
|
283
|
+
finish('timeout');
|
|
284
|
+
}
|
|
285
|
+
});
|
|
121
286
|
}
|