@userflow-tech/react-native 0.3.1 → 0.4.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 +160 -126
- package/docs/anchoring.md +3 -4
- package/docs/troubleshooting.md +27 -24
- package/expo-plugin/hostDependencyWarnings.d.ts +5 -2
- package/expo-plugin/hostDependencyWarnings.d.ts.map +1 -1
- package/expo-plugin/hostDependencyWarnings.js +12 -2
- package/expo-plugin/hostDependencyWarnings.js.map +1 -1
- package/lib/commonjs/authoring/capturePickerScreenshot.js +9 -1
- package/lib/commonjs/authoring/capturePickerScreenshot.js.map +1 -1
- package/lib/commonjs/evalJs/getWebView.js +5 -13
- package/lib/commonjs/evalJs/getWebView.js.map +1 -1
- package/lib/commonjs/hostAppVersion.js +6 -1
- package/lib/commonjs/hostAppVersion.js.map +1 -1
- package/lib/commonjs/installCheck.js +61 -29
- package/lib/commonjs/installCheck.js.map +1 -1
- package/lib/commonjs/nativeModules.js +44 -0
- package/lib/commonjs/nativeModules.js.map +1 -0
- package/lib/commonjs/network.js +20 -7
- package/lib/commonjs/network.js.map +1 -1
- package/lib/commonjs/pairing/tokenStorage.js +17 -4
- package/lib/commonjs/pairing/tokenStorage.js.map +1 -1
- package/lib/commonjs/surfaces/BannerSurface.js +3 -1
- package/lib/commonjs/surfaces/BannerSurface.js.map +1 -1
- package/lib/commonjs/surfaces/safeArea.js +6 -0
- package/lib/commonjs/surfaces/safeArea.js.map +1 -1
- package/lib/commonjs/version.js +1 -1
- package/lib/module/authoring/capturePickerScreenshot.js +9 -1
- package/lib/module/authoring/capturePickerScreenshot.js.map +1 -1
- package/lib/module/evalJs/getWebView.js +5 -13
- package/lib/module/evalJs/getWebView.js.map +1 -1
- package/lib/module/hostAppVersion.js +6 -1
- package/lib/module/hostAppVersion.js.map +1 -1
- package/lib/module/installCheck.js +56 -26
- package/lib/module/installCheck.js.map +1 -1
- package/lib/module/nativeModules.js +40 -0
- package/lib/module/nativeModules.js.map +1 -0
- package/lib/module/network.js +20 -7
- package/lib/module/network.js.map +1 -1
- package/lib/module/pairing/tokenStorage.js +17 -4
- package/lib/module/pairing/tokenStorage.js.map +1 -1
- package/lib/module/surfaces/BannerSurface.js +3 -1
- package/lib/module/surfaces/BannerSurface.js.map +1 -1
- package/lib/module/surfaces/safeArea.js +5 -0
- package/lib/module/surfaces/safeArea.js.map +1 -1
- package/lib/module/version.js +1 -1
- package/lib/typescript/commonjs/src/authoring/capturePickerScreenshot.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/evalJs/getWebView.d.ts +2 -1
- package/lib/typescript/commonjs/src/evalJs/getWebView.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/hostAppVersion.d.ts +1 -1
- package/lib/typescript/commonjs/src/hostAppVersion.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/installCheck.d.ts +18 -3
- package/lib/typescript/commonjs/src/installCheck.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/nativeModules.d.ts +13 -0
- package/lib/typescript/commonjs/src/nativeModules.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/network.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/pairing/tokenStorage.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/surfaces/BannerSurface.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/surfaces/safeArea.d.ts +2 -0
- 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/authoring/capturePickerScreenshot.d.ts.map +1 -1
- package/lib/typescript/module/src/evalJs/getWebView.d.ts +2 -1
- package/lib/typescript/module/src/evalJs/getWebView.d.ts.map +1 -1
- package/lib/typescript/module/src/hostAppVersion.d.ts +1 -1
- package/lib/typescript/module/src/hostAppVersion.d.ts.map +1 -1
- package/lib/typescript/module/src/installCheck.d.ts +18 -3
- package/lib/typescript/module/src/installCheck.d.ts.map +1 -1
- package/lib/typescript/module/src/nativeModules.d.ts +13 -0
- package/lib/typescript/module/src/nativeModules.d.ts.map +1 -0
- package/lib/typescript/module/src/network.d.ts.map +1 -1
- package/lib/typescript/module/src/pairing/tokenStorage.d.ts.map +1 -1
- package/lib/typescript/module/src/surfaces/BannerSurface.d.ts.map +1 -1
- package/lib/typescript/module/src/surfaces/safeArea.d.ts +2 -0
- 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 -8
- package/src/authoring/capturePickerScreenshot.ts +10 -1
- package/src/evalJs/getWebView.ts +6 -13
- package/src/hostAppVersion.ts +7 -1
- package/src/installCheck.ts +67 -33
- package/src/nativeModules.ts +48 -0
- package/src/network.ts +27 -11
- package/src/pairing/tokenStorage.ts +23 -7
- package/src/surfaces/BannerSurface.tsx +7 -5
- package/src/surfaces/safeArea.ts +5 -0
- package/src/version.ts +1 -1
- package/vendor/core/package.json +1 -1
- package/vendor/protocol/package.json +1 -1
- package/docs/theme-mapping.md +0 -130
- package/docs/webview-custom-banner-poc.md +0 -64
package/README.md
CHANGED
|
@@ -1,40 +1,53 @@
|
|
|
1
1
|
# `@userflow-tech/react-native`
|
|
2
2
|
|
|
3
3
|
Official Userflow SDK for React Native and Expo. Deliver guided flows, tooltips,
|
|
4
|
-
and
|
|
5
|
-
release for every content change.
|
|
4
|
+
modals, and banners authored in the Userflow dashboard — without shipping a new
|
|
5
|
+
app release for every content change.
|
|
6
6
|
|
|
7
|
-
> Early development. APIs may change.
|
|
8
|
-
> (`publishConfig.access: restricted`).
|
|
7
|
+
> Early development. APIs may change.
|
|
9
8
|
|
|
10
9
|
## Requirements
|
|
11
10
|
|
|
12
|
-
Declared minimums: React `>=18.2.0`, React Native `>=0.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
| `
|
|
11
|
+
Declared minimums: React `>=18.2.0`, React Native `>=0.76.0`. React Native
|
|
12
|
+
0.74 and 0.75 cannot install this SDK: `react-native-view-shot` 5.x, which
|
|
13
|
+
Builder element selection needs, requires React Native 0.76 or later. The SDK
|
|
14
|
+
is tested on React Native 0.81 / React 19.1 and on Expo SDK 57 / React Native
|
|
15
|
+
0.86. Expo Go is not supported.
|
|
16
|
+
|
|
17
|
+
`@react-native-async-storage/async-storage` is the only native module this
|
|
18
|
+
package depends on, so npm installs it. `react-native-webview` and
|
|
19
|
+
`react-native-view-shot` are required peers. npm 7+ and pnpm install required
|
|
20
|
+
peers. Yarn 1 and `npm install --legacy-peer-deps` do not, which is why the
|
|
21
|
+
install commands list WebView and view-shot explicitly.
|
|
22
|
+
`react-native-device-info` is an optional peer for bare React Native.
|
|
23
|
+
|
|
24
|
+
Install those packages in the **app** as well. Expo SDK 54 and later autolink
|
|
25
|
+
native modules found anywhere in the tree. Bare React Native, and Expo SDK 53
|
|
26
|
+
and older, only autolink packages listed in the app's own `package.json`. A
|
|
27
|
+
direct install also picks a version that matches the app's React Native, inside
|
|
28
|
+
the ranges below.
|
|
29
|
+
|
|
30
|
+
| Package | Kind | Why | If missing |
|
|
31
|
+
| ------------------------------------------------------- | -------------------------------- | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
32
|
+
| `react`, `react-native` `>=0.76.0` | Required peers | Host runtime. | The app cannot load the SDK. React Native older than 0.76 fails install (`ERESOLVE`) because view-shot 5.x requires it. |
|
|
33
|
+
| `@react-native-async-storage/async-storage` `>=1.23 <3` | Dependency | Anonymous user id and the pairing device id. | `identifyAnonymous()` throws. Pairing keeps a device id in memory for the session. A dev-only warning is logged from `Userflow.init`. |
|
|
34
|
+
| `react-native-device-info` `>=11 <16` | Optional peer, bare React Native | Host app `app_version` / `app_build`. Expo reads `expo-application` / `expo-constants` instead. | Those attributes are omitted. A dev-only warning is logged on bare React Native. |
|
|
35
|
+
| `react-native-view-shot` `^5.0.0` | Required peer | Builder element-selection screenshots. | The picker has no screenshot. A dev-only warning is logged from `Userflow.init`. Version 6.x is outside the tested range and requires React Native 0.80 or later. |
|
|
36
|
+
| `react-native-webview` `>=13.8.0 <14` | Required peer | Evaluate JavaScript and WebView banners. | Those surfaces do not run. A dev-only warning is logged from `Userflow.init`. |
|
|
37
|
+
| `react-native-safe-area-context` `>=4 <6` | Optional peer | Insets for banners, flow cards, and Builder bars. | In development, `Userflow.init` warns once. Those surfaces draw under the status bar and home indicator. With the package installed but no `<SafeAreaProvider>`, cards use the device's initial insets and log a separate warning. |
|
|
38
|
+
| `@react-navigation/native` | Optional peer | Screen tracking and NAVIGATE routing (React Navigation). | Report screens yourself with `updateScreen` / `useUserflowScreen`. |
|
|
39
|
+
| `expo-router` | Optional peer | Screen tracking and NAVIGATE routing (Expo Router). | Report screens yourself with `updateScreen` / `useUserflowScreen`. |
|
|
40
|
+
| `@react-native-community/netinfo` `>=11 <13` | Optional peer | Instant offline→online reconnect. | Recovery still runs on the heartbeat and when the app returns to the foreground. If the JavaScript package is installed but `RNCNetInfo` is not in the binary, the SDK skips it instead of showing a red screen. |
|
|
41
|
+
| `expo-secure-store` | Optional peer | Persist the Builder pairing JWT in Keychain/Keystore. | The pairing token stays in memory and is lost when the process ends. The SDK loads it only when the `ExpoSecureStore` native module is registered. |
|
|
34
42
|
|
|
35
43
|
Optional peers are declared `optional: true` in `peerDependenciesMeta`, so
|
|
36
|
-
package managers
|
|
37
|
-
|
|
44
|
+
package managers do not warn if you skip them.
|
|
45
|
+
|
|
46
|
+
A clean npm install prints no warning about optional peers, so install
|
|
47
|
+
`react-native-safe-area-context` and NetInfo yourself when you want the behavior
|
|
48
|
+
in the table. An app that already depends
|
|
49
|
+
on an older major (view-shot 4.0.3, NetInfo 9.x, safe-area 3.x, WebView 13.6.x
|
|
50
|
+
or 14.x) fails install with `ERESOLVE`.
|
|
38
51
|
|
|
39
52
|
### Expo Go is not supported
|
|
40
53
|
|
|
@@ -47,35 +60,8 @@ Use an **Expo development build** (or bare React Native). In development,
|
|
|
47
60
|
|
|
48
61
|
## Install
|
|
49
62
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
Packages publish to the private `@userflow-tech` npm org. Userflow adds the
|
|
53
|
-
client's npm user or organization to a **read-only team** on that org. The
|
|
54
|
-
client then creates a **granular access token** on npm (Read-only, limited to
|
|
55
|
-
`@userflow-tech`). A `404` from `npm install` or `npm view @userflow-tech/react-native`
|
|
56
|
-
means the token is missing, or that user or org is not on the team. npm uses
|
|
57
|
-
404 for a private package the caller cannot see.
|
|
58
|
-
|
|
59
|
-
### npm, Yarn, and CI
|
|
60
|
-
|
|
61
|
-
npm and Yarn 1 read `.npmrc`. Do not commit the token:
|
|
62
|
-
|
|
63
|
-
```ini
|
|
64
|
-
@userflow-tech:registry=https://registry.npmjs.org/
|
|
65
|
-
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Yarn 2 and later ignore `.npmrc`. Add this to `.yarnrc.yml` instead:
|
|
69
|
-
|
|
70
|
-
```yaml
|
|
71
|
-
npmScopes:
|
|
72
|
-
userflow-tech:
|
|
73
|
-
npmRegistryServer: 'https://registry.npmjs.org'
|
|
74
|
-
npmAuthToken: '${NPM_TOKEN}'
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
Set `NPM_TOKEN` in the environment that installs dependencies: a local shell,
|
|
78
|
-
CI, and EAS (an EAS secret named `NPM_TOKEN`, available to the install step).
|
|
63
|
+
The package is public on npm. No token, `.npmrc`, or `.yarnrc.yml` setup is
|
|
64
|
+
needed with any package manager.
|
|
79
65
|
|
|
80
66
|
### Packages
|
|
81
67
|
|
|
@@ -88,11 +74,25 @@ npm install @userflow-tech/react-native @react-native-async-storage/async-storag
|
|
|
88
74
|
cd ios && pod install
|
|
89
75
|
```
|
|
90
76
|
|
|
91
|
-
`react-native-view-shot`
|
|
92
|
-
|
|
77
|
+
`react-native-webview` and `react-native-view-shot` (`^5.0.0`) are **required
|
|
78
|
+
peers**. npm 7+ and pnpm install them. Yarn 1 and
|
|
79
|
+
`npm install --legacy-peer-deps` do not, so the commands above install them in
|
|
80
|
+
the app. Both are native modules — rebuild after install (a Metro reload is not
|
|
81
|
+
enough). On Expo SDK 54,
|
|
93
82
|
unpinned `npx expo install react-native-view-shot` resolves **4.0.3**, which
|
|
94
|
-
does not satisfy the peer. Pin `^5.0.0` as in the command above. If
|
|
95
|
-
|
|
83
|
+
does not satisfy the peer. Pin `^5.0.0` as in the command above. If the app
|
|
84
|
+
already depends on 4.0.3, that same command is what fixes it: installing the
|
|
85
|
+
SDK alone fails with
|
|
86
|
+
|
|
87
|
+
```text
|
|
88
|
+
npm error Found: react-native-view-shot@4.0.3
|
|
89
|
+
npm error peer react-native-view-shot@"^5.0.0" from @userflow-tech/react-native
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Do not retry with `--force` or `--legacy-peer-deps`. That installs the SDK and
|
|
93
|
+
leaves 4.0.3 in place. If that already happened, `Userflow.init` warns in
|
|
94
|
+
development and names the installed version. If `expo doctor`
|
|
95
|
+
reports the `^5.0.0` pin, exclude it from Expo's version check:
|
|
96
96
|
|
|
97
97
|
```json
|
|
98
98
|
{
|
|
@@ -114,10 +114,6 @@ npx expo install react-native-safe-area-context @react-native-community/netinfo
|
|
|
114
114
|
# and either expo-router or @react-navigation/native, depending on your router
|
|
115
115
|
```
|
|
116
116
|
|
|
117
|
-
For local tarball installs from this monorepo, pack with `pnpm pack:all` at the
|
|
118
|
-
repo root and install the single `@userflow-tech/react-native` tarball. Steps:
|
|
119
|
-
`docs/local-testing.md` in the monorepo.
|
|
120
|
-
|
|
121
117
|
### Install with an AI agent
|
|
122
118
|
|
|
123
119
|
Cursor, Claude Code, and other agents that read Agent Skills can do this
|
|
@@ -143,7 +139,7 @@ Claude Code loads it from the plugin:
|
|
|
143
139
|
import { Userflow, UserflowProvider } from '@userflow-tech/react-native';
|
|
144
140
|
|
|
145
141
|
await Userflow.init({
|
|
146
|
-
clientToken: 'ct_...', // from the Userflow dashboard
|
|
142
|
+
clientToken: 'ct_...', // from Settings → Environments in the Userflow dashboard. Never an esk_ secret key.
|
|
147
143
|
// serverEndpoint: 'https://e.userflow.com', // default (US). EU: 'https://e.eu.userflow.com'
|
|
148
144
|
// pairingEndpoint: 'https://e.userflow.com', // default; pairing stays on the US host
|
|
149
145
|
});
|
|
@@ -162,6 +158,17 @@ NetInfo subscriptions). Call `Userflow.reset()` on logout to clear identity and
|
|
|
162
158
|
disconnect. `reset()` does not apply a new `clientToken` or endpoint; restart
|
|
163
159
|
the app to change those.
|
|
164
160
|
|
|
161
|
+
### `init` options
|
|
162
|
+
|
|
163
|
+
| Option | Default | Description |
|
|
164
|
+
| ----------------- | ------------------------ | ------------------------------------------------------------------------------------------------------------ |
|
|
165
|
+
| `clientToken` | — | **Required.** The `ct_…` client token from Settings → Environments. |
|
|
166
|
+
| `serverEndpoint` | `https://e.userflow.com` | Userflow host. EU environments use `https://e.eu.userflow.com`. |
|
|
167
|
+
| `pairingEndpoint` | `https://e.userflow.com` | Builder pairing host. Stays on the US host for EU environments too. |
|
|
168
|
+
| `onNavigate` | — | Handler for flow NAVIGATE actions. Wins over React Navigation, Expo Router, and Linking. See NAVIGATE below. |
|
|
169
|
+
| `appVersion` | Read from the native app | Override the host app version sent as `app_version`. |
|
|
170
|
+
| `appBuild` | Read from the native app | Build number sent as `app_build`, paired with `appVersion`. |
|
|
171
|
+
|
|
165
172
|
### Where to put `init`, `identify`, and `UserflowProvider`
|
|
166
173
|
|
|
167
174
|
Call `Userflow.init` once, as early as you can, from the root component
|
|
@@ -231,14 +238,14 @@ to the device's initial insets:
|
|
|
231
238
|
|
|
232
239
|
### Call order
|
|
233
240
|
|
|
234
|
-
| Call | Before `init()` resolves | Before `identify()`
|
|
235
|
-
| -------------------------------- | ------------------------------------------------------ |
|
|
236
|
-
| `identify` / `identifyAnonymous` | **Throws** `Call Userflow.init() before identify()` | —
|
|
237
|
-
| `group` | **Throws** `Call Userflow.init() before group()` | **Throws** `Call Userflow.identify() before group()`
|
|
238
|
-
| `updateUser` | **Throws** `Call Userflow.init() before updateUser()` | **Throws** `Call Userflow.identify() before updateUser()`
|
|
239
|
-
| `updateGroup` | **Throws** `Call Userflow.init() before updateGroup()` | **Throws** `Call Userflow.identify() before updateGroup()`; also requires a prior `group()`
|
|
240
|
-
| `track` | **Throws** `Call Userflow.init() before track()` | **Throws** `Call Userflow.identify() before track()`. Network, rate-limit, and unexpected SDK errors are isolated (the promise resolves; see [isolation.md](docs/isolation.md)) |
|
|
241
|
-
| `updateScreen` | Silently buffers; included on the next channel join | Silently buffers
|
|
241
|
+
| Call | Before `init()` resolves | Before `identify()` |
|
|
242
|
+
| -------------------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
243
|
+
| `identify` / `identifyAnonymous` | **Throws** `Call Userflow.init() before identify()` | — |
|
|
244
|
+
| `group` | **Throws** `Call Userflow.init() before group()` | **Throws** `Call Userflow.identify() before group()` |
|
|
245
|
+
| `updateUser` | **Throws** `Call Userflow.init() before updateUser()` | **Throws** `Call Userflow.identify() before updateUser()` |
|
|
246
|
+
| `updateGroup` | **Throws** `Call Userflow.init() before updateGroup()` | **Throws** `Call Userflow.identify() before updateGroup()`; also requires a prior `group()` |
|
|
247
|
+
| `track` | **Throws** `Call Userflow.init() before track()` | **Throws** `Call Userflow.identify() before track()`. Network, rate-limit, and unexpected SDK errors are isolated (the promise resolves; see [isolation.md](https://unpkg.com/@userflow-tech/react-native/docs/isolation.md)) |
|
|
248
|
+
| `updateScreen` | Silently buffers; included on the next channel join | Silently buffers |
|
|
242
249
|
|
|
243
250
|
Other rules:
|
|
244
251
|
|
|
@@ -255,7 +262,7 @@ Other rules:
|
|
|
255
262
|
Same-id re-identify merges attributes.
|
|
256
263
|
- Identity verification `signature` is optional in the type, but **required by
|
|
257
264
|
the server** when the environment has identity verification enabled. See
|
|
258
|
-
[docs/identity-verification.md](docs/identity-verification.md).
|
|
265
|
+
[docs/identity-verification.md](https://unpkg.com/@userflow-tech/react-native/docs/identity-verification.md).
|
|
259
266
|
|
|
260
267
|
## Localization
|
|
261
268
|
|
|
@@ -288,7 +295,7 @@ unmount or crash the host tree. `init` / `identify` still throw — a swallowed
|
|
|
288
295
|
identify would look like success. Native crashes and errors in **your** children
|
|
289
296
|
of `UserflowProvider` are out of scope.
|
|
290
297
|
|
|
291
|
-
Details: [docs/isolation.md](docs/isolation.md).
|
|
298
|
+
Details: [docs/isolation.md](https://unpkg.com/@userflow-tech/react-native/docs/isolation.md).
|
|
292
299
|
|
|
293
300
|
## Screen tracking
|
|
294
301
|
|
|
@@ -381,13 +388,13 @@ function InviteScreen() {
|
|
|
381
388
|
|
|
382
389
|
Targets inside a `ScrollView` / `FlatList` are scrolled into view automatically.
|
|
383
390
|
`useUserflowScrollContainer` is only needed as an override for scroll libraries
|
|
384
|
-
the fiber walk cannot drive — see [docs/anchoring.md](docs/anchoring.md).
|
|
391
|
+
the fiber walk cannot drive — see [docs/anchoring.md](https://unpkg.com/@userflow-tech/react-native/docs/anchoring.md).
|
|
385
392
|
|
|
386
393
|
In the Userflow builder, set the MANUAL step selector CSS to `#invite-teammates`
|
|
387
394
|
(or `invite-teammates`). Use `useUserflowAnchor(id)` only when you need an
|
|
388
395
|
explicit override (e.g. a third-party component that does not accept `testID`).
|
|
389
396
|
Full contract, prop priority, missing-target behavior, and duplicate-id rules:
|
|
390
|
-
[docs/anchoring.md](docs/anchoring.md).
|
|
397
|
+
[docs/anchoring.md](https://unpkg.com/@userflow-tech/react-native/docs/anchoring.md).
|
|
391
398
|
|
|
392
399
|
## Builder preview & pairing
|
|
393
400
|
|
|
@@ -432,8 +439,8 @@ Deep-link / pairing helpers:
|
|
|
432
439
|
| `PreviewModeBanner` | Mounted by `UserflowProvider` while paired. The top bar shows at once for a preview link, stays hidden for an element-selection link and after any pick until the next preview, and waits briefly on a link with no purpose. |
|
|
433
440
|
|
|
434
441
|
Full scheme registration, Linking ownership, and verify commands:
|
|
435
|
-
[docs/deep-linking.md](docs/deep-linking.md). Symptom table:
|
|
436
|
-
[docs/troubleshooting.md](docs/troubleshooting.md
|
|
442
|
+
[docs/deep-linking.md](https://unpkg.com/@userflow-tech/react-native/docs/deep-linking.md). Symptom table: the "Builder preview / pairing" section of
|
|
443
|
+
[docs/troubleshooting.md](https://unpkg.com/@userflow-tech/react-native/docs/troubleshooting.md).
|
|
437
444
|
|
|
438
445
|
## Connection resilience
|
|
439
446
|
|
|
@@ -464,33 +471,35 @@ Screen tracking ≠ action routing. React Navigation apps need
|
|
|
464
471
|
|
|
465
472
|
### `Userflow`
|
|
466
473
|
|
|
467
|
-
| Member
|
|
468
|
-
|
|
|
469
|
-
| `init(config)`
|
|
470
|
-
| `identify(userId, attributes?, options?)`
|
|
471
|
-
| `identifyAnonymous(attributes?, options?)`
|
|
472
|
-
| `group(groupId, attributes?, options?)`
|
|
473
|
-
| `updateUser(attributes?)`
|
|
474
|
-
| `updateGroup(attributes?, options?)`
|
|
475
|
-
| `track(name, attributes?, options?)`
|
|
476
|
-
| `reset()`
|
|
477
|
-
| `teardown()`
|
|
478
|
-
| `updateScreen(name)`
|
|
479
|
-
| `setOnNavigate(handler)`
|
|
480
|
-
| `reportActivity()`
|
|
481
|
-
| `didHandleURL(url)`
|
|
482
|
-
| `handlePairingUrl(url)`
|
|
483
|
-
| `exitPreview()`
|
|
484
|
-
| `
|
|
485
|
-
| `
|
|
486
|
-
| `
|
|
487
|
-
| `
|
|
488
|
-
| `
|
|
489
|
-
| `
|
|
490
|
-
| `
|
|
491
|
-
| `
|
|
492
|
-
| `
|
|
493
|
-
| `
|
|
474
|
+
| Member | Description |
|
|
475
|
+
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
476
|
+
| `init(config)` | Validate credentials, store config, start lifecycle + network controllers. |
|
|
477
|
+
| `identify(userId, attributes?, options?)` | Identify a user; auto-sets `sdk` / `device_os` / `device_type` and `app_version` / `app_build` from init; `options.signature` for identity verification. |
|
|
478
|
+
| `identifyAnonymous(attributes?, options?)` | Stable anonymous id via AsyncStorage; auto-sets `sdk` / `device_os` / `device_type` and `app_version` / `app_build`. |
|
|
479
|
+
| `group(groupId, attributes?, options?)` | Associate the current user with a group. |
|
|
480
|
+
| `updateUser(attributes?)` | Upsert attributes for the current user without re-identifying. |
|
|
481
|
+
| `updateGroup(attributes?, options?)` | Upsert group / membership attributes without re-grouping. |
|
|
482
|
+
| `track(name, attributes?, options?)` | Record a custom event (literal attribute values only); `userOnly` skips group. Misuse (`UserflowAuthError`) rejects; network / rate-limit / SDK bugs are isolated. |
|
|
483
|
+
| `reset()` | Clear identity, the stored anonymous id, client conditions, and flow and banner sessions; disconnect. |
|
|
484
|
+
| `teardown()` | Stop AppState / NetInfo / screen-tracking subscriptions. |
|
|
485
|
+
| `updateScreen(name)` | Report the active screen (prefer hooks when possible). |
|
|
486
|
+
| `setOnNavigate(handler)` | Override or clear the host NAVIGATE handler. |
|
|
487
|
+
| `reportActivity()` | Reset the idle timer; reconnect an idle-suspended socket. |
|
|
488
|
+
| `didHandleURL(url)` | Handle a Userflow preview deep link (`…://?token=…`). |
|
|
489
|
+
| `handlePairingUrl(url)` | Handle a Builder pairing deep link (`…://?pairing_token=…`). Works in every build; the signed JWT gates the session. |
|
|
490
|
+
| `exitPreview()` | Leave Builder preview mode; disconnect the pairing websocket. Works in every build. |
|
|
491
|
+
| `setScrollPadding(padding)` | Sticky header/footer insets used when scrolling tooltip targets into view. |
|
|
492
|
+
| `setCustomScrollIntoView(fn)` | Replace scroll-into-view (e.g. unsupported scroll libraries). Pass `null` to restore the default. |
|
|
493
|
+
| `setSurfaceInteractionBlocking(enabled)` | `true` (default) blocks taps on the app under tooltip backdrops. `false` lets them through. Modals always block. |
|
|
494
|
+
| `setEvalJsContext(values)` | Values exposed to Evaluate JavaScript as `window.userflowContext.host`. Replaces the previous values. |
|
|
495
|
+
| `getUserId()` | Current user id, or `null` before identify. |
|
|
496
|
+
| `getAttributes()` | Copy of attributes for the current user. |
|
|
497
|
+
| `getFlowSessionEngine()` | Mid-flow session engine (created lazily; attach runs after identify). |
|
|
498
|
+
| `getBannerSessionEngine()` | Banner session engine (created lazily; attach runs after identify). |
|
|
499
|
+
| `getHostAppVersion()` | Host app native version cached at init, or `null` before init / when unavailable. |
|
|
500
|
+
| `getDeviceContext()` | Platform metadata cached during `init` (`sdk`, `deviceOs`, `deviceType`), or `null` before init. |
|
|
501
|
+
| `logHostAppVersion()` | Log the host app's native version (not `SDK_VERSION`) and platform OS. Uses bundled device-info on bare RN. |
|
|
502
|
+
| `logDeviceContext()` | Log cached user-attribute values (`sdk` / `device_os` / `device_type`). Requires `init`. |
|
|
494
503
|
|
|
495
504
|
### Hooks and components
|
|
496
505
|
|
|
@@ -503,8 +512,19 @@ Screen tracking ≠ action routing. React Navigation apps need
|
|
|
503
512
|
| `useUserflowScreen(name)` | Report the active screen from a React tree. |
|
|
504
513
|
| `useUserflowAnchor(id)` | Optional override: register a view as a MANUAL target (beats `userflowId` / `testID`). |
|
|
505
514
|
| `useUserflowScrollContainer(onScroll?)` | Optional override: register a `ScrollView` for tooltip scroll-into-view. |
|
|
506
|
-
| `
|
|
507
|
-
|
|
515
|
+
| `EmbedBannerPlaceholder` | Slot for a banner placed on an element (`<EmbedBannerPlaceholder id="welcome-banner" />` matches the selector `#welcome-banner`). Renders nothing until a matching banner is active. Top and bottom banners ignore it. |
|
|
516
|
+
|
|
517
|
+
### Pairing helpers
|
|
518
|
+
|
|
519
|
+
Named exports, not members of `Userflow`. Use them when your app owns `Linking`
|
|
520
|
+
and forwards URLs itself.
|
|
521
|
+
|
|
522
|
+
| Export | Description |
|
|
523
|
+
| ----------------------------- | ------------------------------------------------------------------------- |
|
|
524
|
+
| `inspectPairingDeepLink(url)` | Classify a URL as pairing without consuming it; reports rejection reason. |
|
|
525
|
+
| `isPairingAttempt(reason)` | True when a rejection was a recognisable pairing attempt worth reporting. |
|
|
526
|
+
| `parsePairingDeepLink(url)` | Parse a pairing deep link. |
|
|
527
|
+
| `isUserflowPairingUrl(url)` | Detect a pairing deep link. |
|
|
508
528
|
|
|
509
529
|
### Subpath exports
|
|
510
530
|
|
|
@@ -524,20 +544,22 @@ Screen tracking ≠ action routing. React Navigation apps need
|
|
|
524
544
|
|
|
525
545
|
## Guides in this package
|
|
526
546
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
|
531
|
-
|
|
|
532
|
-
| [docs/
|
|
533
|
-
| [docs/
|
|
534
|
-
| [docs/
|
|
547
|
+
These guides also ship in the package, under
|
|
548
|
+
`node_modules/@userflow-tech/react-native/docs/`.
|
|
549
|
+
|
|
550
|
+
| Doc | Topic |
|
|
551
|
+
| ------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------- |
|
|
552
|
+
| [docs/anchoring.md](https://unpkg.com/@userflow-tech/react-native/docs/anchoring.md) | Manual targets, scroll containers, missing-target behavior |
|
|
553
|
+
| [docs/isolation.md](https://unpkg.com/@userflow-tech/react-native/docs/isolation.md) | What “isolated as possible” means; overlay + `track` guards |
|
|
554
|
+
| [docs/deep-linking.md](https://unpkg.com/@userflow-tech/react-native/docs/deep-linking.md) | Builder preview URLs and pairing sessions |
|
|
555
|
+
| [docs/identity-verification.md](https://unpkg.com/@userflow-tech/react-native/docs/identity-verification.md) | HMAC signature on your backend |
|
|
556
|
+
| [docs/troubleshooting.md](https://unpkg.com/@userflow-tech/react-native/docs/troubleshooting.md) | Symptom → cause for common integration failures |
|
|
535
557
|
|
|
536
558
|
## Experimental
|
|
537
559
|
|
|
538
560
|
- AUTO / codeless element targeting (exact-id fast path + scored matcher;
|
|
539
561
|
scored path needs Babel full mode to populate the auto-anchor registry).
|
|
540
|
-
See [docs/anchoring.md](docs/anchoring.md).
|
|
562
|
+
See [docs/anchoring.md](https://unpkg.com/@userflow-tech/react-native/docs/anchoring.md).
|
|
541
563
|
- Build-time stamping with `@userflow-tech/react-native/babel-plugin`. Jest
|
|
542
564
|
runs the plugin too, which changes snapshots. Read
|
|
543
565
|
[Babel plugin and snapshot tests](#babel-plugin-and-snapshot-tests) before
|
|
@@ -546,10 +568,14 @@ Screen tracking ≠ action routing. React Navigation apps need
|
|
|
546
568
|
## Install diagnostics
|
|
547
569
|
|
|
548
570
|
In development, the first `Userflow.init` checks native module registration and
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
571
|
+
whether `react-native-safe-area-context` is installed. Missing native modules
|
|
572
|
+
share one warning. A missing safe-area package gets its own warning, because
|
|
573
|
+
flows still run and draw under the status bar. It does not `require` an
|
|
574
|
+
unlinked package (including NetInfo, whose import throws when `RNCNetInfo` is
|
|
575
|
+
absent). Rebuild the native app after fixing a native-module line; a Metro
|
|
576
|
+
reload is not enough. Installing safe-area-context also needs a rebuild, then a
|
|
577
|
+
`<SafeAreaProvider>` around the app. The warnings look like this (only the
|
|
578
|
+
missing lines are included):
|
|
553
579
|
|
|
554
580
|
```text
|
|
555
581
|
[Userflow] Native setup is incomplete. Flows may not run until you fix the following, then rebuild the app (a Metro reload is not enough):
|
|
@@ -557,7 +583,12 @@ are included):
|
|
|
557
583
|
- 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.
|
|
558
584
|
- react-native-webview is not linked. Evaluate JavaScript and WebView banners will not run. Install it (npx expo install react-native-webview) and rebuild.
|
|
559
585
|
- react-native-device-info is not linked, so app_version and app_build are not sent. npm install react-native-device-info, then rebuild.
|
|
560
|
-
See docs/troubleshooting.md.
|
|
586
|
+
See node_modules/@userflow-tech/react-native/docs/troubleshooting.md.
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
```text
|
|
590
|
+
[Userflow] react-native-safe-area-context is not installed, so banners, flow cards, and Builder bars draw under the status bar and home indicator. Install it (npx expo install react-native-safe-area-context) and wrap the app in <SafeAreaProvider>.
|
|
591
|
+
See node_modules/@userflow-tech/react-native/docs/troubleshooting.md.
|
|
561
592
|
```
|
|
562
593
|
|
|
563
594
|
Passing an environment secret key as `clientToken` throws:
|
|
@@ -572,8 +603,11 @@ Pairing stays on `https://e.userflow.com`.
|
|
|
572
603
|
|
|
573
604
|
`expo prebuild` warns when the config plugin has no `schemeId`, when
|
|
574
605
|
`react-native-view-shot` is missing or older than 5, and (on Expo SDK 53 and
|
|
575
|
-
older) when AsyncStorage or
|
|
576
|
-
|
|
606
|
+
older) when AsyncStorage, WebView, or safe-area-context is not a direct
|
|
607
|
+
dependency. Expo SDK 54 and later autolink safe-area-context when another
|
|
608
|
+
package such as Expo Router brought it in, so prebuild stays quiet in that
|
|
609
|
+
case. `Userflow.init` still warns when the package itself cannot be loaded.
|
|
610
|
+
Passing an environment UUID as `schemeId` fails the prebuild:
|
|
577
611
|
|
|
578
612
|
```text
|
|
579
613
|
[@userflow-tech/react-native] schemeId "550e8400-e29b-41d4-a716-446655440000" looks like an environment id. Pass the scheme_id value that starts with userflow- (an opaque id from the dashboard), not the environment UUID.
|
|
@@ -681,4 +715,4 @@ the files it lists, not the components a test renders.
|
|
|
681
715
|
- `INPUT_VALUE` / `FILLED_IN_INPUT` client conditions
|
|
682
716
|
|
|
683
717
|
Flows gated on unsupported client conditions stay unknown and **never start**.
|
|
684
|
-
See [docs/troubleshooting.md](docs/troubleshooting.md).
|
|
718
|
+
See [docs/troubleshooting.md](https://unpkg.com/@userflow-tech/react-native/docs/troubleshooting.md).
|
package/docs/anchoring.md
CHANGED
|
@@ -16,7 +16,7 @@ Dashboard MANUAL selectors store a CSS-like string on `step.selector.css` (or
|
|
|
16
16
|
`condition.selector.css`). The SDK resolves it with:
|
|
17
17
|
|
|
18
18
|
```typescript
|
|
19
|
-
//
|
|
19
|
+
// src/anchors/resolveManualAnchorId.ts
|
|
20
20
|
return trimmed.startsWith('#') ? trimmed.slice(1) : trimmed;
|
|
21
21
|
```
|
|
22
22
|
|
|
@@ -318,7 +318,7 @@ Modals always block — the full-screen backdrop is a `Pressable` hit target.
|
|
|
318
318
|
Pass `Userflow.setSurfaceInteractionBlocking(false)` to restore the legacy
|
|
319
319
|
pass-through tooltip backdrop (`pointerEvents="none"` on dim bands) so the
|
|
320
320
|
host screen stays scrollable and tappable underneath. The `tooltipTargetBlocked`
|
|
321
|
-
hole seal is unchanged
|
|
321
|
+
hole seal is unchanged.
|
|
322
322
|
|
|
323
323
|
When a tooltip step has `backdrop: false`, the cutout still mounts with dim
|
|
324
324
|
opacity `0` so interaction blocking applies without a visible dim.
|
|
@@ -341,7 +341,7 @@ rect** via a pass-through bridge around app content (`TargetPressBridge` in
|
|
|
341
341
|
ELEMENT `CLICK` / `NOT_CLICK` auto-start conditions use the same bridge
|
|
342
342
|
(`elementTapMonitor`) and do not steal the press either. `MOUSEDOWN` and
|
|
343
343
|
`DISABLED` conditions are still unsupported — see
|
|
344
|
-
[
|
|
344
|
+
[troubleshooting.md](troubleshooting.md).
|
|
345
345
|
|
|
346
346
|
## Missing-target behavior
|
|
347
347
|
|
|
@@ -405,4 +405,3 @@ The Userflow overlay is a _sibling_ of the scan root, so SDK-owned `testID`s
|
|
|
405
405
|
|
|
406
406
|
- [troubleshooting.md](troubleshooting.md) — “flow never appeared” checklist
|
|
407
407
|
- [theme-mapping.md](theme-mapping.md) — chrome tokens that affect tooltip UI
|
|
408
|
-
- Repo `docs/client-conditions.md` (monorepo only) — track / toggle protocol internals
|