@wireai/activation 0.7.0 → 0.9.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.
Files changed (94) hide show
  1. package/AGENTS.md +29 -5
  2. package/CHANGELOG.md +198 -6
  3. package/README.md +105 -10
  4. package/dist/analytics/index.d.mts +12 -8
  5. package/dist/analytics/index.d.ts +12 -8
  6. package/dist/analytics/index.js +525 -55
  7. package/dist/analytics/index.js.map +1 -1
  8. package/dist/analytics/index.mjs +525 -55
  9. package/dist/analytics/index.mjs.map +1 -1
  10. package/dist/coachmarks/index.d.mts +2 -2
  11. package/dist/coachmarks/index.d.ts +2 -2
  12. package/dist/coachmarks/index.js.map +1 -1
  13. package/dist/coachmarks/index.mjs.map +1 -1
  14. package/dist/{currentSession-CxnP7gAa.d.ts → currentSession-61dcm3V-.d.ts} +19 -3
  15. package/dist/{currentSession-BJBB7i4-.d.mts → currentSession-Bs2JfTJ8.d.mts} +19 -3
  16. package/dist/{decision-BzbiKwk3.d.mts → decision-Bl_M2y3r.d.mts} +1 -1
  17. package/dist/{decision-plDEOCkt.d.ts → decision-Cau5KmP6.d.ts} +1 -1
  18. package/dist/index.d.mts +620 -13
  19. package/dist/index.d.ts +620 -13
  20. package/dist/index.js +1194 -369
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mjs +1015 -201
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/questionnaire/index.d.mts +69 -23
  25. package/dist/questionnaire/index.d.ts +69 -23
  26. package/dist/questionnaire/index.js +643 -172
  27. package/dist/questionnaire/index.js.map +1 -1
  28. package/dist/questionnaire/index.mjs +608 -137
  29. package/dist/questionnaire/index.mjs.map +1 -1
  30. package/dist/reviews/index.d.mts +24 -12
  31. package/dist/reviews/index.d.ts +24 -12
  32. package/dist/reviews/index.js +507 -173
  33. package/dist/reviews/index.js.map +1 -1
  34. package/dist/reviews/index.mjs +462 -129
  35. package/dist/reviews/index.mjs.map +1 -1
  36. package/dist/showcase/index.d.mts +2 -2
  37. package/dist/showcase/index.d.ts +2 -2
  38. package/dist/showcase/index.js.map +1 -1
  39. package/dist/showcase/index.mjs.map +1 -1
  40. package/dist/transport-DzU-TqZz.d.ts +86 -0
  41. package/dist/transport-f5VVB5hH.d.mts +86 -0
  42. package/dist/{types-GL_hQ0TN.d.mts → types-BcmagF6K.d.mts} +1 -1
  43. package/dist/{types-GL_hQ0TN.d.ts → types-BcmagF6K.d.ts} +1 -1
  44. package/dist/{types-BhpXJGlg.d.ts → types-Buj9Lw9t.d.ts} +15 -3
  45. package/dist/{types-CMuOexw0.d.mts → types-CKFhyrMu.d.mts} +1 -1
  46. package/dist/{types-CMuOexw0.d.ts → types-CKFhyrMu.d.ts} +1 -1
  47. package/dist/{types-A6pTxIZV.d.mts → types-CNUqMK0D.d.mts} +15 -3
  48. package/metro/index.d.ts +18 -1
  49. package/metro/index.js +80 -0
  50. package/package.json +9 -1
  51. package/src/WireOnboarding.tsx +4 -0
  52. package/src/analytics/analyticsFacade.ts +55 -10
  53. package/src/analytics/currentSession.ts +1 -1
  54. package/src/cards/CardGridSelectCard.tsx +253 -0
  55. package/src/cards/ChipSelectCard.tsx +1 -1
  56. package/src/cards/SelectionCard.tsx +15 -19
  57. package/src/cards/index.ts +13 -1
  58. package/src/cards/optionSchema.ts +65 -0
  59. package/src/coachmarks/types.ts +1 -1
  60. package/src/components/CardHandoff.tsx +39 -7
  61. package/src/components/DoneCheck.tsx +94 -0
  62. package/src/components/ModalPaneHost.tsx +141 -0
  63. package/src/components/StepDots.tsx +112 -0
  64. package/src/context/deviceId.ts +43 -0
  65. package/src/device/appVersion.ts +29 -8
  66. package/src/device/deviceContext.ts +14 -1
  67. package/src/device/deviceModel.ts +106 -0
  68. package/src/features/cache.ts +1 -1
  69. package/src/haptics/expo-haptics.d.ts +31 -0
  70. package/src/haptics/haptics.ts +58 -0
  71. package/src/icons/IconRegistry.tsx +53 -0
  72. package/src/icons/WireIcon.tsx +85 -0
  73. package/src/icons/expoIcons.ts +165 -0
  74. package/src/icons/index.ts +18 -0
  75. package/src/icons/vocabulary.ts +154 -0
  76. package/src/index.ts +22 -0
  77. package/src/questionnaire/QuestionnaireGate.tsx +315 -164
  78. package/src/questionnaire/decision.ts +4 -2
  79. package/src/questionnaire/index.ts +3 -2
  80. package/src/questionnaire/steps.ts +261 -0
  81. package/src/questionnaire/types.ts +33 -12
  82. package/src/reviews/ReviewGate.tsx +250 -152
  83. package/src/reviews/index.ts +7 -3
  84. package/src/reviews/transport.ts +77 -3
  85. package/src/reviews/types.ts +13 -0
  86. package/src/session/persistedSession.ts +1 -1
  87. package/src/session-analytics/lifecycle.ts +1 -1
  88. package/src/session-analytics/useSessionStart.ts +2 -2
  89. package/src/showcase/FeatureShowcase.tsx +1 -1
  90. package/src/showcase/showcaseColors.ts +1 -1
  91. package/src/theme/mergeThemeOver.ts +27 -0
  92. package/src/types.ts +8 -0
  93. package/dist/transport-BeO_Brcu.d.mts +0 -40
  94. package/dist/transport-DLpd1v5_.d.ts +0 -40
package/dist/index.js CHANGED
@@ -1,27 +1,412 @@
1
1
  'use strict';
2
2
 
3
- var React14 = require('react');
3
+ var reactNative = require('react-native');
4
+ var React18 = require('react');
4
5
  var wireaiRn = require('wireai-rn');
5
6
  var jsxRuntime = require('react/jsx-runtime');
6
- var reactNative = require('react-native');
7
7
  var reactNativeSafeAreaContext = require('react-native-safe-area-context');
8
8
  var zod = require('zod');
9
9
 
10
10
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
11
 
12
- var React14__default = /*#__PURE__*/_interopDefault(React14);
12
+ var React18__default = /*#__PURE__*/_interopDefault(React18);
13
13
 
14
14
  var __defProp = Object.defineProperty;
15
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
16
+ var __getOwnPropNames = Object.getOwnPropertyNames;
17
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
15
18
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
16
19
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
17
20
  }) : x)(function(x) {
18
21
  if (typeof require !== "undefined") return require.apply(this, arguments);
19
22
  throw Error('Dynamic require of "' + x + '" is not supported');
20
23
  });
24
+ var __esm = (fn, res) => function __init() {
25
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
26
+ };
21
27
  var __export = (target, all) => {
22
- for (var name in all)
23
- __defProp(target, name, { get: all[name], enumerable: true });
28
+ for (var name2 in all)
29
+ __defProp(target, name2, { get: all[name2], enumerable: true });
24
30
  };
31
+ var __copyProps = (to, from, except, desc) => {
32
+ if (from && typeof from === "object" || typeof from === "function") {
33
+ for (let key of __getOwnPropNames(from))
34
+ if (!__hasOwnProp.call(to, key) && key !== except)
35
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
36
+ }
37
+ return to;
38
+ };
39
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
40
+
41
+ // node_modules/expo-modules-core/src/errors/CodedError.ts
42
+ var CodedError;
43
+ var init_CodedError = __esm({
44
+ "node_modules/expo-modules-core/src/errors/CodedError.ts"() {
45
+ CodedError = class extends Error {
46
+ constructor(code, message) {
47
+ super(message);
48
+ this.code = code;
49
+ }
50
+ };
51
+ }
52
+ });
53
+
54
+ // node_modules/expo-modules-core/src/NativeModulesProxy.ts
55
+ var NativeModulesProxy_default;
56
+ var init_NativeModulesProxy = __esm({
57
+ "node_modules/expo-modules-core/src/NativeModulesProxy.ts"() {
58
+ NativeModulesProxy_default = {};
59
+ }
60
+ });
61
+
62
+ // node_modules/expo-modules-core/src/TurboModuleToExpoModuleProxy.ts
63
+ function createTurboModuleToExpoProxy(turboModule, name2) {
64
+ return null;
65
+ }
66
+ var init_TurboModuleToExpoModuleProxy = __esm({
67
+ "node_modules/expo-modules-core/src/TurboModuleToExpoModuleProxy.ts"() {
68
+ }
69
+ });
70
+ var init_ensureNativeModulesAreInstalled = __esm({
71
+ "node_modules/expo-modules-core/src/ensureNativeModulesAreInstalled.ts"() {
72
+ }
73
+ });
74
+ function requireOptionalNativeModule(moduleName) {
75
+ var _a2, _b, _c, _d, _e;
76
+ try {
77
+ return (_e = (_d = (_c = (_b = (_a2 = globalThis.expo) == null ? void 0 : _a2.modules) == null ? void 0 : _b[moduleName]) != null ? _c : NativeModulesProxy_default[moduleName]) != null ? _d : createTurboModuleToExpoProxy(reactNative.TurboModuleRegistry.get(moduleName), moduleName)) != null ? _e : null;
78
+ } catch (e) {
79
+ const error = e;
80
+ console.warn(`An error occurred while requiring the '${moduleName}' module: ${error.message}`);
81
+ return null;
82
+ }
83
+ }
84
+ var init_requireNativeModule = __esm({
85
+ "node_modules/expo-modules-core/src/requireNativeModule.ts"() {
86
+ init_NativeModulesProxy();
87
+ init_TurboModuleToExpoModuleProxy();
88
+ init_ensureNativeModulesAreInstalled();
89
+ }
90
+ });
91
+
92
+ // node_modules/expo-modules-core/src/sweet/setUpJsLogger.fx.ts
93
+ var init_setUpJsLogger_fx = __esm({
94
+ "node_modules/expo-modules-core/src/sweet/setUpJsLogger.fx.ts"() {
95
+ init_CodedError();
96
+ init_requireNativeModule();
97
+ if (__DEV__ && typeof window !== "undefined" && (process.env.EXPO_OS === "android" || process.env.EXPO_OS === "ios")) {
98
+ const NativeJSLogger = requireOptionalNativeModule("ExpoModulesCoreJSLogger");
99
+ if (NativeJSLogger) {
100
+ const onNewException = {
101
+ eventName: "ExpoModulesCoreJSLogger.onNewError",
102
+ action: console.error
103
+ };
104
+ const onNewWarning = {
105
+ eventName: "ExpoModulesCoreJSLogger.onNewWarning",
106
+ action: console.warn
107
+ };
108
+ const onNewDebug = {
109
+ eventName: "ExpoModulesCoreJSLogger.onNewDebug",
110
+ action: console.debug
111
+ };
112
+ const onNewInfo = {
113
+ eventName: "ExpoModulesCoreJSLogger.onNewInfo",
114
+ action: console.info
115
+ };
116
+ const onNewTrace = {
117
+ eventName: "ExpoModulesCoreJSLogger.onNewTrace",
118
+ action: console.trace
119
+ };
120
+ const listeners = [
121
+ onNewException,
122
+ onNewWarning,
123
+ onNewDebug,
124
+ onNewInfo,
125
+ onNewTrace
126
+ ];
127
+ for (const listener of listeners) {
128
+ NativeJSLogger.addListener(listener.eventName, ({ message }) => {
129
+ listener.action(message);
130
+ });
131
+ }
132
+ }
133
+ }
134
+ globalThis.ExpoModulesCore_CodedError = CodedError;
135
+ }
136
+ });
137
+
138
+ // node_modules/expo-modules-core/src/registerWebModule.ts
139
+ var init_registerWebModule = __esm({
140
+ "node_modules/expo-modules-core/src/registerWebModule.ts"() {
141
+ }
142
+ });
143
+
144
+ // node_modules/expo-modules-core/src/TypedArrays.types.ts
145
+ var init_TypedArrays_types = __esm({
146
+ "node_modules/expo-modules-core/src/TypedArrays.types.ts"() {
147
+ }
148
+ });
149
+
150
+ // node_modules/expo-modules-core/src/PermissionsInterface.ts
151
+ var init_PermissionsInterface = __esm({
152
+ "node_modules/expo-modules-core/src/PermissionsInterface.ts"() {
153
+ }
154
+ });
155
+ var init_PermissionsHook = __esm({
156
+ "node_modules/expo-modules-core/src/PermissionsHook.ts"() {
157
+ "use client";
158
+ }
159
+ });
160
+ var init_Refs = __esm({
161
+ "node_modules/expo-modules-core/src/Refs.ts"() {
162
+ }
163
+ });
164
+ var init_useReleasingSharedObject = __esm({
165
+ "node_modules/expo-modules-core/src/hooks/useReleasingSharedObject.ts"() {
166
+ "use client";
167
+ }
168
+ });
169
+
170
+ // node_modules/expo-modules-core/src/reload.ts
171
+ var init_reload = __esm({
172
+ "node_modules/expo-modules-core/src/reload.ts"() {
173
+ }
174
+ });
175
+
176
+ // node_modules/expo-modules-core/src/index.ts
177
+ var init_src = __esm({
178
+ "node_modules/expo-modules-core/src/index.ts"() {
179
+ init_setUpJsLogger_fx();
180
+ init_requireNativeModule();
181
+ init_registerWebModule();
182
+ init_TypedArrays_types();
183
+ init_PermissionsInterface();
184
+ init_PermissionsHook();
185
+ init_Refs();
186
+ init_useReleasingSharedObject();
187
+ init_reload();
188
+ init_CodedError();
189
+ }
190
+ });
191
+
192
+ // node_modules/expo-constants/build/Constants.types.js
193
+ var AppOwnership, ExecutionEnvironment, UserInterfaceIdiom;
194
+ var init_Constants_types = __esm({
195
+ "node_modules/expo-constants/build/Constants.types.js"() {
196
+ (function(AppOwnership2) {
197
+ AppOwnership2["Expo"] = "expo";
198
+ })(AppOwnership || (AppOwnership = {}));
199
+ (function(ExecutionEnvironment2) {
200
+ ExecutionEnvironment2["Bare"] = "bare";
201
+ ExecutionEnvironment2["Standalone"] = "standalone";
202
+ ExecutionEnvironment2["StoreClient"] = "storeClient";
203
+ })(ExecutionEnvironment || (ExecutionEnvironment = {}));
204
+ (function(UserInterfaceIdiom2) {
205
+ UserInterfaceIdiom2["Handset"] = "handset";
206
+ UserInterfaceIdiom2["Tablet"] = "tablet";
207
+ UserInterfaceIdiom2["Desktop"] = "desktop";
208
+ UserInterfaceIdiom2["TV"] = "tv";
209
+ UserInterfaceIdiom2["Unsupported"] = "unsupported";
210
+ })(UserInterfaceIdiom || (UserInterfaceIdiom = {}));
211
+ }
212
+ });
213
+
214
+ // node_modules/expo-constants/build/ExponentConstants.js
215
+ var ExponentConstants_default;
216
+ var init_ExponentConstants = __esm({
217
+ "node_modules/expo-constants/build/ExponentConstants.js"() {
218
+ init_src();
219
+ ExponentConstants_default = requireOptionalNativeModule("ExponentConstants");
220
+ }
221
+ });
222
+
223
+ // node_modules/expo-constants/build/Constants.js
224
+ var Constants_exports = {};
225
+ __export(Constants_exports, {
226
+ AppOwnership: () => AppOwnership,
227
+ ExecutionEnvironment: () => ExecutionEnvironment,
228
+ UserInterfaceIdiom: () => UserInterfaceIdiom,
229
+ default: () => Constants_default
230
+ });
231
+ function isEmbeddedManifest(manifest) {
232
+ return !isExpoUpdatesManifest(manifest);
233
+ }
234
+ function isExpoUpdatesManifest(manifest) {
235
+ return "metadata" in manifest;
236
+ }
237
+ function getManifest(suppressWarning = false) {
238
+ if (!rawManifest) {
239
+ const invalidManifestType = rawManifest === null ? "null" : "undefined";
240
+ if (nativeConstants.executionEnvironment === ExecutionEnvironment.Bare && reactNative.Platform.OS !== "web") {
241
+ if (!suppressWarning) {
242
+ console.warn(`Constants.manifest is ${invalidManifestType} because the embedded app.config could not be read. Ensure that you have installed the expo-constants build scripts if you need to read from Constants.manifest.`);
243
+ }
244
+ } else if (nativeConstants.executionEnvironment === ExecutionEnvironment.StoreClient || nativeConstants.executionEnvironment === ExecutionEnvironment.Standalone) {
245
+ throw new CodedError("ERR_CONSTANTS_MANIFEST_UNAVAILABLE", `Constants.manifest is ${invalidManifestType}, must be an object.`);
246
+ }
247
+ }
248
+ return rawManifest;
249
+ }
250
+ var ExpoUpdates, rawUpdatesManifest, rawDevLauncherManifest, rawAppConfig, _a, rawManifest, name, appOwnership, nativeConstants, constants, Constants_default;
251
+ var init_Constants = __esm({
252
+ "node_modules/expo-constants/build/Constants.js"() {
253
+ init_src();
254
+ init_Constants_types();
255
+ init_ExponentConstants();
256
+ init_Constants_types();
257
+ if (!ExponentConstants_default) {
258
+ console.warn("No native ExponentConstants module found, are you sure the expo-constants's module is linked properly?");
259
+ }
260
+ ExpoUpdates = requireOptionalNativeModule("ExpoUpdates");
261
+ rawUpdatesManifest = null;
262
+ if (ExpoUpdates) {
263
+ let updatesManifest;
264
+ if (ExpoUpdates.manifest) {
265
+ updatesManifest = ExpoUpdates.manifest;
266
+ } else if (ExpoUpdates.manifestString) {
267
+ updatesManifest = JSON.parse(ExpoUpdates.manifestString);
268
+ }
269
+ if (updatesManifest && Object.keys(updatesManifest).length > 0) {
270
+ rawUpdatesManifest = updatesManifest;
271
+ }
272
+ }
273
+ rawDevLauncherManifest = null;
274
+ if (reactNative.NativeModules.EXDevLauncher) {
275
+ let devLauncherManifest;
276
+ if (reactNative.NativeModules.EXDevLauncher.manifestString) {
277
+ devLauncherManifest = JSON.parse(reactNative.NativeModules.EXDevLauncher.manifestString);
278
+ }
279
+ if (devLauncherManifest && Object.keys(devLauncherManifest).length > 0) {
280
+ rawDevLauncherManifest = devLauncherManifest;
281
+ }
282
+ }
283
+ rawAppConfig = null;
284
+ if (ExponentConstants_default && ExponentConstants_default.manifest) {
285
+ const appConfig = ExponentConstants_default.manifest;
286
+ if (typeof appConfig === "string") {
287
+ rawAppConfig = JSON.parse(appConfig);
288
+ } else {
289
+ rawAppConfig = appConfig;
290
+ }
291
+ }
292
+ rawManifest = (_a = rawUpdatesManifest != null ? rawUpdatesManifest : rawDevLauncherManifest) != null ? _a : rawAppConfig;
293
+ ({ name, appOwnership, ...nativeConstants } = ExponentConstants_default || {});
294
+ constants = {
295
+ ...nativeConstants,
296
+ // Ensure this is null in bare workflow
297
+ appOwnership: appOwnership != null ? appOwnership : null
298
+ };
299
+ Object.defineProperties(constants, {
300
+ /**
301
+ * Use `manifest` property by default.
302
+ * This property is only used for internal purposes.
303
+ * It behaves similarly to the original one, but suppresses warning upon no manifest available.
304
+ * `expo-asset` uses it to prevent users from seeing mentioned warning.
305
+ */
306
+ __unsafeNoWarnManifest: {
307
+ get() {
308
+ const maybeManifest = getManifest(true);
309
+ if (!maybeManifest || !isEmbeddedManifest(maybeManifest)) {
310
+ return null;
311
+ }
312
+ return maybeManifest;
313
+ },
314
+ enumerable: false
315
+ },
316
+ __unsafeNoWarnManifest2: {
317
+ get() {
318
+ const maybeManifest = getManifest(true);
319
+ if (!maybeManifest || !isExpoUpdatesManifest(maybeManifest)) {
320
+ return null;
321
+ }
322
+ return maybeManifest;
323
+ },
324
+ enumerable: false
325
+ },
326
+ manifest: {
327
+ get() {
328
+ const maybeManifest = getManifest();
329
+ if (!maybeManifest || !isEmbeddedManifest(maybeManifest)) {
330
+ return null;
331
+ }
332
+ return maybeManifest;
333
+ },
334
+ enumerable: true
335
+ },
336
+ manifest2: {
337
+ get() {
338
+ const maybeManifest = getManifest();
339
+ if (!maybeManifest || !isExpoUpdatesManifest(maybeManifest)) {
340
+ return null;
341
+ }
342
+ return maybeManifest;
343
+ },
344
+ enumerable: true
345
+ },
346
+ expoConfig: {
347
+ get() {
348
+ var _a2, _b;
349
+ const maybeManifest = getManifest(true);
350
+ if (!maybeManifest) {
351
+ return null;
352
+ }
353
+ if (ExpoUpdates && ExpoUpdates.isEmbeddedLaunch) {
354
+ return rawAppConfig;
355
+ }
356
+ if (isExpoUpdatesManifest(maybeManifest)) {
357
+ return (_b = (_a2 = maybeManifest.extra) == null ? void 0 : _a2.expoClient) != null ? _b : null;
358
+ } else if (isEmbeddedManifest(maybeManifest)) {
359
+ return maybeManifest;
360
+ }
361
+ return null;
362
+ },
363
+ enumerable: true
364
+ },
365
+ expoGoConfig: {
366
+ get() {
367
+ var _a2, _b;
368
+ const maybeManifest = getManifest(true);
369
+ if (!maybeManifest) {
370
+ return null;
371
+ }
372
+ if (isExpoUpdatesManifest(maybeManifest)) {
373
+ return (_b = (_a2 = maybeManifest.extra) == null ? void 0 : _a2.expoGo) != null ? _b : null;
374
+ } else if (isEmbeddedManifest(maybeManifest)) {
375
+ return maybeManifest;
376
+ }
377
+ return null;
378
+ },
379
+ enumerable: true
380
+ },
381
+ easConfig: {
382
+ get() {
383
+ var _a2, _b;
384
+ const maybeManifest = getManifest(true);
385
+ if (!maybeManifest) {
386
+ return null;
387
+ }
388
+ if (isExpoUpdatesManifest(maybeManifest)) {
389
+ return (_b = (_a2 = maybeManifest.extra) == null ? void 0 : _a2.eas) != null ? _b : null;
390
+ } else if (isEmbeddedManifest(maybeManifest)) {
391
+ return maybeManifest;
392
+ }
393
+ return null;
394
+ },
395
+ enumerable: true
396
+ },
397
+ __rawManifest_TEST: {
398
+ get() {
399
+ return rawManifest;
400
+ },
401
+ set(value) {
402
+ rawManifest = value;
403
+ },
404
+ enumerable: false
405
+ }
406
+ });
407
+ Constants_default = constants;
408
+ }
409
+ });
25
410
 
26
411
  // src/theme/defaultTheme.ts
27
412
  var defaultOnboardingTheme = {
@@ -79,31 +464,31 @@ var mergeTheme = (override) => {
79
464
  button: { ...defaultOnboardingTheme.button, ...override.button }
80
465
  };
81
466
  };
82
- var OnboardingThemeContext = React14.createContext(null);
467
+ var OnboardingThemeContext = React18.createContext(null);
83
468
  var OnboardingThemeProvider = ({
84
469
  theme,
85
470
  children
86
471
  }) => {
87
- const resolved = React14.useMemo(() => mergeTheme(theme), [theme]);
472
+ const resolved = React18.useMemo(() => mergeTheme(theme), [theme]);
88
473
  return /* @__PURE__ */ jsxRuntime.jsx(OnboardingThemeContext.Provider, { value: resolved, children });
89
474
  };
90
475
  var useOnboardingTheme = () => {
91
- const ctx = React14.useContext(OnboardingThemeContext);
476
+ const ctx = React18.useContext(OnboardingThemeContext);
92
477
  return ctx != null ? ctx : mergeTheme();
93
478
  };
94
479
  var EMPTY_REGISTRY = {};
95
- var IllustrationContext = React14.createContext(EMPTY_REGISTRY);
480
+ var IllustrationContext = React18.createContext(EMPTY_REGISTRY);
96
481
  var IllustrationProvider = ({
97
482
  registry,
98
483
  children
99
484
  }) => {
100
- const value = React14.useMemo(() => registry != null ? registry : EMPTY_REGISTRY, [registry]);
485
+ const value = React18.useMemo(() => registry != null ? registry : EMPTY_REGISTRY, [registry]);
101
486
  return /* @__PURE__ */ jsxRuntime.jsx(IllustrationContext.Provider, { value, children });
102
487
  };
103
- var useIllustration = (name) => {
104
- const registry = React14.useContext(IllustrationContext);
105
- if (!name) return void 0;
106
- return registry[name];
488
+ var useIllustration = (name2) => {
489
+ const registry = React18.useContext(IllustrationContext);
490
+ if (!name2) return void 0;
491
+ return registry[name2];
107
492
  };
108
493
  var Glyph = ({ children }) => {
109
494
  const t = useOnboardingTheme();
@@ -175,6 +560,21 @@ var styles = reactNative.StyleSheet.create({
175
560
  fontWeight: "700"
176
561
  }
177
562
  });
563
+ var EMPTY_REGISTRY2 = {};
564
+ var IconContext = React18.createContext(EMPTY_REGISTRY2);
565
+ var IconRegistryProvider = ({
566
+ registry,
567
+ children
568
+ }) => {
569
+ const value = React18.useMemo(() => registry != null ? registry : EMPTY_REGISTRY2, [registry]);
570
+ return /* @__PURE__ */ jsxRuntime.jsx(IconContext.Provider, { value, children });
571
+ };
572
+ var useHostIcon = (name2) => {
573
+ const registry = React18.useContext(IconContext);
574
+ if (!name2) return void 0;
575
+ if (!Object.prototype.hasOwnProperty.call(registry, name2)) return void 0;
576
+ return registry[name2];
577
+ };
178
578
 
179
579
  // src/theme/typography.ts
180
580
  var round = (n) => Math.round(n);
@@ -189,9 +589,9 @@ var captionStyle = (f) => ({
189
589
  lineHeight: round(f.baseSize * 0.8125 * f.scale * 1.5)
190
590
  });
191
591
  var labelStyle = (f) => {
192
- var _a;
592
+ var _a2;
193
593
  return {
194
- fontFamily: (_a = f.medium) != null ? _a : f.bold,
594
+ fontFamily: (_a2 = f.medium) != null ? _a2 : f.bold,
195
595
  fontSize: round(f.baseSize * f.scale),
196
596
  lineHeight: round(f.baseSize * f.scale * 1.4),
197
597
  fontWeight: f.medium ? void 0 : "600"
@@ -204,9 +604,9 @@ var headingStyle = (f) => ({
204
604
  fontWeight: f.bold ? void 0 : "700"
205
605
  });
206
606
  var buttonLabelStyle = (f) => {
207
- var _a;
607
+ var _a2;
208
608
  return {
209
- fontFamily: (_a = f.bold) != null ? _a : f.medium,
609
+ fontFamily: (_a2 = f.bold) != null ? _a2 : f.medium,
210
610
  fontSize: round(f.baseSize * f.scale),
211
611
  fontWeight: f.bold ? void 0 : "600"
212
612
  };
@@ -329,8 +729,8 @@ var stateChangeDuration = (reduced, durationMs) => reduced ? 0 : durationMs;
329
729
  var loopEnabled = (reduced) => !reduced;
330
730
  var lastKnown = false;
331
731
  var useReducedMotion = () => {
332
- const [reduced, setReduced] = React14.useState(lastKnown);
333
- React14.useEffect(() => {
732
+ const [reduced, setReduced] = React18.useState(lastKnown);
733
+ React18.useEffect(() => {
334
734
  let mounted = true;
335
735
  reactNative.AccessibilityInfo.isReduceMotionEnabled().then((value) => {
336
736
  lastKnown = value;
@@ -352,8 +752,8 @@ var ROTATION_MS = 1800;
352
752
  var _AnimatedSparkle = ({ size = 30, color, variant = "spin" }) => {
353
753
  const t = useOnboardingTheme();
354
754
  const reduced = useReducedMotion();
355
- const progress = React14.useRef(new reactNative.Animated.Value(0)).current;
356
- React14.useEffect(() => {
755
+ const progress = React18.useRef(new reactNative.Animated.Value(0)).current;
756
+ React18.useEffect(() => {
357
757
  if (!loopEnabled(reduced)) {
358
758
  progress.setValue(0);
359
759
  return;
@@ -408,7 +808,7 @@ var _AnimatedSparkle = ({ size = 30, color, variant = "spin" }) => {
408
808
  }
409
809
  ) });
410
810
  };
411
- var AnimatedSparkle = React14__default.default.memo(_AnimatedSparkle);
811
+ var AnimatedSparkle = React18__default.default.memo(_AnimatedSparkle);
412
812
  var styles2 = reactNative.StyleSheet.create({
413
813
  box: { alignItems: "center", justifyContent: "center" },
414
814
  glyph: {
@@ -420,8 +820,8 @@ var styles2 = reactNative.StyleSheet.create({
420
820
  var STAGE_SIZE = 96;
421
821
  var ORBIT_DOT = 9;
422
822
  var OrbitDot = ({ color, reduced }) => {
423
- const spin = React14.useRef(new reactNative.Animated.Value(0)).current;
424
- React14.useEffect(() => {
823
+ const spin = React18.useRef(new reactNative.Animated.Value(0)).current;
824
+ React18.useEffect(() => {
425
825
  if (!loopEnabled(reduced)) return;
426
826
  const loop = reactNative.Animated.loop(
427
827
  reactNative.Animated.timing(spin, {
@@ -444,8 +844,8 @@ var SkeletonLine = ({
444
844
  color,
445
845
  reduced
446
846
  }) => {
447
- const pulse = React14.useRef(new reactNative.Animated.Value(1)).current;
448
- React14.useEffect(() => {
847
+ const pulse = React18.useRef(new reactNative.Animated.Value(1)).current;
848
+ React18.useEffect(() => {
449
849
  if (!loopEnabled(reduced)) return;
450
850
  const loop = reactNative.Animated.loop(
451
851
  reactNative.Animated.sequence([
@@ -480,8 +880,8 @@ var _LoadingBlock = ({
480
880
  }) => {
481
881
  const t = useOnboardingTheme();
482
882
  const reduced = useReducedMotion();
483
- const [showSkeleton, setShowSkeleton] = React14.useState(false);
484
- React14.useEffect(() => {
883
+ const [showSkeleton, setShowSkeleton] = React18.useState(false);
884
+ React18.useEffect(() => {
485
885
  const timer = setTimeout(() => setShowSkeleton(true), SKELETON_DELAY_MS);
486
886
  return () => clearTimeout(timer);
487
887
  }, []);
@@ -511,7 +911,7 @@ var _LoadingBlock = ({
511
911
  )
512
912
  ] });
513
913
  };
514
- var LoadingBlock = React14__default.default.memo(_LoadingBlock);
914
+ var LoadingBlock = React18__default.default.memo(_LoadingBlock);
515
915
  var styles3 = reactNative.StyleSheet.create({
516
916
  center: { flex: 1, alignItems: "center", justifyContent: "center" },
517
917
  // Absolutely-positioned label column, pinned just under the centered stage: its top
@@ -556,7 +956,7 @@ var _LoadingScreen = ({ title, hint }) => {
556
956
  }
557
957
  );
558
958
  };
559
- var LoadingScreen = React14__default.default.memo(_LoadingScreen);
959
+ var LoadingScreen = React18__default.default.memo(_LoadingScreen);
560
960
  var styles4 = reactNative.StyleSheet.create({
561
961
  flex: { flex: 1 }
562
962
  });
@@ -575,8 +975,8 @@ var targetFor = (step, complete, approxScreens) => {
575
975
  var _StepProgress = ({ step, complete, approxScreens }) => {
576
976
  const t = useOnboardingTheme();
577
977
  const reduced = useReducedMotion();
578
- const fill = React14.useRef(new reactNative.Animated.Value(targetFor(step, complete, approxScreens))).current;
579
- React14.useEffect(() => {
978
+ const fill = React18.useRef(new reactNative.Animated.Value(targetFor(step, complete, approxScreens))).current;
979
+ React18.useEffect(() => {
580
980
  reactNative.Animated.timing(fill, {
581
981
  toValue: targetFor(step, complete, approxScreens),
582
982
  duration: scaledMs(stateChangeDuration(reduced, PROGRESS_MS)),
@@ -596,7 +996,7 @@ var _StepProgress = ({ step, complete, approxScreens }) => {
596
996
  }
597
997
  ) });
598
998
  };
599
- var StepProgress = React14__default.default.memo(_StepProgress);
999
+ var StepProgress = React18__default.default.memo(_StepProgress);
600
1000
  var styles5 = reactNative.StyleSheet.create({
601
1001
  track: { height: 6, width: "100%", overflow: "hidden" },
602
1002
  fill: { height: 6 }
@@ -612,31 +1012,31 @@ var _OnboardingScaffold = ({
612
1012
  children
613
1013
  }) => {
614
1014
  const t = useOnboardingTheme();
615
- const styles16 = React14.useMemo(() => makeStyles(t), [t]);
1015
+ const styles18 = React18.useMemo(() => makeStyles(t), [t]);
616
1016
  const hit = { top: 12, bottom: 12, left: 12, right: 12 };
617
1017
  return /* @__PURE__ */ jsxRuntime.jsxs(
618
1018
  reactNativeSafeAreaContext.SafeAreaView,
619
1019
  {
620
1020
  edges: ["top", "bottom"],
621
- style: [styles16.flex, { backgroundColor: t.colors.background }],
1021
+ style: [styles18.flex, { backgroundColor: t.colors.background }],
622
1022
  children: [
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
1023
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles18.header, { paddingHorizontal: t.spacing.md, paddingTop: t.spacing.md }], children: [
1024
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles18.progressWrap, children: /* @__PURE__ */ jsxRuntime.jsx(StepProgress, { step, complete, approxScreens }) }),
1025
+ onSkip ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.TouchableOpacity, { onPress: onSkip, hitSlop: hit, style: styles18.skip, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [bodyStyle(t.fonts), { color: t.colors.textMuted }], children: skipLabel }) }) : null
626
1026
  ] }),
627
1027
  /* @__PURE__ */ jsxRuntime.jsx(
628
1028
  reactNative.View,
629
1029
  {
630
- style: [styles16.body, { paddingHorizontal: t.spacing.md, paddingTop: t.spacing.md }],
1030
+ style: [styles18.body, { paddingHorizontal: t.spacing.md, paddingTop: t.spacing.md }],
631
1031
  children
632
1032
  }
633
1033
  ),
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
1034
+ onBack ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles18.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
635
1035
  ]
636
1036
  }
637
1037
  );
638
1038
  };
639
- var OnboardingScaffold = React14__default.default.memo(_OnboardingScaffold);
1039
+ var OnboardingScaffold = React18__default.default.memo(_OnboardingScaffold);
640
1040
  function makeStyles(t) {
641
1041
  return reactNative.StyleSheet.create({
642
1042
  flex: { flex: 1 },
@@ -657,8 +1057,8 @@ var _Button = ({
657
1057
  const t = useOnboardingTheme();
658
1058
  const reduced = useReducedMotion();
659
1059
  const isPrimary = variant === "primary";
660
- const pressT = React14.useRef(new reactNative.Animated.Value(0)).current;
661
- const pressTo = React14.useCallback(
1060
+ const pressT = React18.useRef(new reactNative.Animated.Value(0)).current;
1061
+ const pressTo = React18.useCallback(
662
1062
  (to) => {
663
1063
  if (reduced) {
664
1064
  reactNative.Animated.timing(pressT, {
@@ -677,16 +1077,16 @@ var _Button = ({
677
1077
  },
678
1078
  [pressT, reduced]
679
1079
  );
680
- const lastPress = React14.useRef(0);
681
- const handlePress = React14.useCallback(() => {
1080
+ const lastPress = React18.useRef(0);
1081
+ const handlePress = React18.useCallback(() => {
682
1082
  if (!onPress) return;
683
1083
  const now = Date.now();
684
1084
  if (now - lastPress.current < 500) return;
685
1085
  lastPress.current = now;
686
1086
  onPress();
687
1087
  }, [onPress]);
688
- const handlePressIn = React14.useCallback(() => pressTo(1), [pressTo]);
689
- const handlePressOut = React14.useCallback(() => pressTo(0), [pressTo]);
1088
+ const handlePressIn = React18.useCallback(() => pressTo(1), [pressTo]);
1089
+ const handlePressOut = React18.useCallback(() => pressTo(0), [pressTo]);
690
1090
  const scale = pressT.interpolate({
691
1091
  inputRange: [0, 1],
692
1092
  outputRange: [1, reduced ? 1 : BUTTON_PRESS_SCALE]
@@ -737,7 +1137,7 @@ var _Button = ({
737
1137
  }
738
1138
  );
739
1139
  };
740
- var Button = React14__default.default.memo(_Button);
1140
+ var Button = React18__default.default.memo(_Button);
741
1141
  var styles6 = reactNative.StyleSheet.create({
742
1142
  base: { alignItems: "center", justifyContent: "center" },
743
1143
  fill: { width: "100%" }
@@ -755,7 +1155,7 @@ var _ErrorBlock = ({
755
1155
  onRetry ? /* @__PURE__ */ jsxRuntime.jsx(Button, { title: retryLabel, onPress: onRetry, variant: "outline" }) : null
756
1156
  ] });
757
1157
  };
758
- var ErrorBlock = React14__default.default.memo(_ErrorBlock);
1158
+ var ErrorBlock = React18__default.default.memo(_ErrorBlock);
759
1159
  var styles7 = reactNative.StyleSheet.create({
760
1160
  center: { flex: 1, alignItems: "center", justifyContent: "center" }
761
1161
  });
@@ -768,10 +1168,10 @@ var _CardLayout = ({
768
1168
  titleNode
769
1169
  }) => {
770
1170
  const t = useOnboardingTheme();
771
- const styles16 = React14.useMemo(() => makeStyles2(t), [t]);
1171
+ const styles18 = React18.useMemo(() => makeStyles2(t), [t]);
772
1172
  const hasHeader = !!title || !!subtitle || !!titleNode;
773
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.KeyboardAvoidingView, { style: styles16.fill, behavior: "padding", children: [
774
- hasHeader ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles16.header, children: [
1173
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.KeyboardAvoidingView, { style: styles18.fill, behavior: "padding", children: [
1174
+ hasHeader ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles18.header, children: [
775
1175
  titleNode != null ? titleNode : title ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [labelStyle(t.fonts), { color: t.colors.text }], children: title }) : null,
776
1176
  subtitle ? /* @__PURE__ */ jsxRuntime.jsx(
777
1177
  reactNative.Text,
@@ -787,10 +1187,10 @@ var _CardLayout = ({
787
1187
  /* @__PURE__ */ jsxRuntime.jsx(
788
1188
  reactNative.ScrollView,
789
1189
  {
790
- style: styles16.fill,
1190
+ style: styles18.fill,
791
1191
  contentContainerStyle: [
792
- styles16.scrollContent,
793
- align === "center" && styles16.center
1192
+ styles18.scrollContent,
1193
+ align === "center" && styles18.center
794
1194
  ],
795
1195
  keyboardShouldPersistTaps: "handled",
796
1196
  keyboardDismissMode: "on-drag",
@@ -798,10 +1198,10 @@ var _CardLayout = ({
798
1198
  children
799
1199
  }
800
1200
  ),
801
- footer ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles16.footer, children: footer }) : null
1201
+ footer ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles18.footer, children: footer }) : null
802
1202
  ] });
803
1203
  };
804
- var CardLayout = React14__default.default.memo(_CardLayout);
1204
+ var CardLayout = React18__default.default.memo(_CardLayout);
805
1205
  function makeStyles2(t) {
806
1206
  return reactNative.StyleSheet.create({
807
1207
  fill: { flex: 1 },
@@ -824,12 +1224,12 @@ var _CompletionView = ({
824
1224
  }) => {
825
1225
  const t = useOnboardingTheme();
826
1226
  const reduced = useReducedMotion();
827
- const [submitted, setSubmitted] = React14.useState(false);
828
- const pop = React14.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
829
- const burst = React14.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
830
- const titleT = React14.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
831
- const messageT = React14.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
832
- React14.useEffect(() => {
1227
+ const [submitted, setSubmitted] = React18.useState(false);
1228
+ const pop = React18.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
1229
+ const burst = React18.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
1230
+ const titleT = React18.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
1231
+ const messageT = React18.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
1232
+ React18.useEffect(() => {
833
1233
  if (reduced) {
834
1234
  pop.setValue(1);
835
1235
  burst.setValue(1);
@@ -864,7 +1264,7 @@ var _CompletionView = ({
864
1264
  anims.forEach((a) => a.start());
865
1265
  return () => anims.forEach((a) => a.stop());
866
1266
  }, [reduced, pop, burst, titleT, messageT]);
867
- const handlePress = React14.useCallback(() => {
1267
+ const handlePress = React18.useCallback(() => {
868
1268
  if (submitted) return;
869
1269
  setSubmitted(true);
870
1270
  onContinue();
@@ -926,7 +1326,7 @@ var _CompletionView = ({
926
1326
  }
927
1327
  );
928
1328
  };
929
- var CompletionView = React14__default.default.memo(_CompletionView);
1329
+ var CompletionView = React18__default.default.memo(_CompletionView);
930
1330
  var styles8 = reactNative.StyleSheet.create({
931
1331
  center: { width: "100%", alignItems: "center", justifyContent: "center" },
932
1332
  badgeStage: {
@@ -943,17 +1343,19 @@ var easeWire3 = reactNative.Easing.bezier(...WIRE_BEZIER);
943
1343
  var _CardHandoff = ({
944
1344
  transitionKey,
945
1345
  variant = "slide",
1346
+ direction = "forward",
1347
+ layout = "fill",
946
1348
  children
947
1349
  }) => {
948
1350
  const reduced = useReducedMotion();
949
- const [leaving, setLeaving] = React14.useState(null);
950
- const enterT = React14.useRef(new reactNative.Animated.Value(0)).current;
951
- const exitT = React14.useRef(new reactNative.Animated.Value(0)).current;
952
- const prev = React14.useRef({ key: transitionKey, node: children, variant });
953
- const running = React14.useRef({});
954
- const mounted = React14.useRef(false);
955
- React14.useEffect(() => {
956
- var _a, _b;
1351
+ const [leaving, setLeaving] = React18.useState(null);
1352
+ const enterT = React18.useRef(new reactNative.Animated.Value(0)).current;
1353
+ const exitT = React18.useRef(new reactNative.Animated.Value(0)).current;
1354
+ const prev = React18.useRef({ key: transitionKey, node: children, variant });
1355
+ const running = React18.useRef({});
1356
+ const mounted = React18.useRef(false);
1357
+ React18.useEffect(() => {
1358
+ var _a2, _b;
957
1359
  const last = prev.current;
958
1360
  prev.current = { key: transitionKey, node: children, variant };
959
1361
  if (!mounted.current) {
@@ -962,7 +1364,7 @@ var _CardHandoff = ({
962
1364
  return;
963
1365
  }
964
1366
  if (last.key === transitionKey) return;
965
- (_a = running.current.enter) == null ? void 0 : _a.stop();
1367
+ (_a2 = running.current.enter) == null ? void 0 : _a2.stop();
966
1368
  (_b = running.current.exit) == null ? void 0 : _b.stop();
967
1369
  setLeaving(last);
968
1370
  enterT.setValue(0);
@@ -985,17 +1387,17 @@ var _CardHandoff = ({
985
1387
  );
986
1388
  running.current.enter = enter;
987
1389
  });
988
- React14.useEffect(
1390
+ React18.useEffect(
989
1391
  () => () => {
990
- var _a, _b;
991
- (_a = running.current.enter) == null ? void 0 : _a.stop();
1392
+ var _a2, _b;
1393
+ (_a2 = running.current.enter) == null ? void 0 : _a2.stop();
992
1394
  (_b = running.current.exit) == null ? void 0 : _b.stop();
993
1395
  },
994
1396
  []
995
1397
  );
996
1398
  const enterStyle = {
997
1399
  opacity: enterT,
998
- transform: transformFor(variant, enterT, reduced, "enter")
1400
+ transform: transformFor(variant, enterT, reduced, "enter", direction)
999
1401
  };
1000
1402
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1001
1403
  leaving ? /* @__PURE__ */ jsxRuntime.jsx(
@@ -1006,13 +1408,14 @@ var _CardHandoff = ({
1006
1408
  reactNative.StyleSheet.absoluteFill,
1007
1409
  {
1008
1410
  opacity: exitT.interpolate({ inputRange: [0, 1], outputRange: [1, 0] }),
1009
- transform: transformFor(leaving.variant, exitT, reduced, "exit")
1411
+ // The CURRENT direction drives BOTH layers: one transition, one geography.
1412
+ transform: transformFor(leaving.variant, exitT, reduced, "exit", direction)
1010
1413
  }
1011
1414
  ],
1012
1415
  children: leaving.node
1013
1416
  }
1014
1417
  ) : null,
1015
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: [styles9.fill, enterStyle], children }, variant)
1418
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: [layout === "fill" ? styles9.fill : null, enterStyle], children }, variant)
1016
1419
  ] });
1017
1420
  };
1018
1421
  var startEnter = (value, variant, reduced, delay, onDone) => {
@@ -1038,21 +1441,22 @@ var startEnter = (value, variant, reduced, delay, onDone) => {
1038
1441
  });
1039
1442
  return anim;
1040
1443
  };
1041
- var transformFor = (variant, t, reduced, direction) => {
1444
+ var transformFor = (variant, t, reduced, layer, travel) => {
1042
1445
  if (reduced || variant === "fade") return [];
1043
- if (variant === "spring" && direction === "enter") {
1446
+ if (variant === "spring" && layer === "enter") {
1044
1447
  return [{ scale: t.interpolate({ inputRange: [0, 1], outputRange: [CARD_ENTER_SCALE_FROM, 1] }) }];
1045
1448
  }
1449
+ const slide = travel === "forward" ? CARD_SLIDE_PX : -CARD_SLIDE_PX;
1046
1450
  return [
1047
1451
  {
1048
1452
  translateX: t.interpolate({
1049
1453
  inputRange: [0, 1],
1050
- outputRange: direction === "enter" ? [CARD_SLIDE_PX, 0] : [0, -CARD_SLIDE_PX]
1454
+ outputRange: layer === "enter" ? [slide, 0] : [0, -slide]
1051
1455
  })
1052
1456
  }
1053
1457
  ];
1054
1458
  };
1055
- var CardHandoff = React14__default.default.memo(_CardHandoff);
1459
+ var CardHandoff = React18__default.default.memo(_CardHandoff);
1056
1460
  var styles9 = reactNative.StyleSheet.create({
1057
1461
  fill: { flex: 1 }
1058
1462
  });
@@ -1067,13 +1471,13 @@ var tryParse = (s) => {
1067
1471
  }
1068
1472
  };
1069
1473
  var deriveAnswers = (messages) => {
1070
- var _a, _b, _c;
1474
+ var _a2, _b, _c;
1071
1475
  const out = {};
1072
1476
  for (let i = 0; i < messages.length; i++) {
1073
1477
  const m = messages[i];
1074
1478
  const r = m == null ? void 0 : m.response;
1075
1479
  if (!m || m.role !== "assistant" || !r || r.action !== "render") continue;
1076
- const props = (_a = r.props) != null ? _a : {};
1480
+ const props = (_a2 = r.props) != null ? _a2 : {};
1077
1481
  const progress = props.progress;
1078
1482
  const questionText = (_c = (_b = props.title) != null ? _b : props.label) != null ? _c : props.question;
1079
1483
  const key = (progress == null ? void 0 : progress.key) || questionText;
@@ -1087,9 +1491,9 @@ var deriveAnswers = (messages) => {
1087
1491
 
1088
1492
  // src/utils/readProgress.ts
1089
1493
  var readProgress = (response) => {
1090
- var _a;
1494
+ var _a2;
1091
1495
  if (!response || response.action !== "render") return {};
1092
- const props = (_a = response.props) != null ? _a : {};
1496
+ const props = (_a2 = response.props) != null ? _a2 : {};
1093
1497
  const raw = props.progress;
1094
1498
  if (!raw || typeof raw !== "object") return {};
1095
1499
  const p = raw;
@@ -1175,70 +1579,70 @@ var OnboardingFlow = ({
1175
1579
  resumed = false,
1176
1580
  clientContext
1177
1581
  }) => {
1178
- var _a, _b, _c, _d, _e, _f;
1582
+ var _a2, _b, _c, _d, _e, _f;
1179
1583
  const { messages, error, isLoading, sendMessage, reset } = wireaiRn.useWireAIThread();
1180
1584
  const makeActions = wireaiRn.useWireAIAction(sendMessage);
1181
- const c = React14.useMemo(() => ({ ...DEFAULT_COPY, ...copy }), [copy]);
1182
- const onEventRef = React14.useRef(onEvent);
1585
+ const c = React18.useMemo(() => ({ ...DEFAULT_COPY, ...copy }), [copy]);
1586
+ const onEventRef = React18.useRef(onEvent);
1183
1587
  onEventRef.current = onEvent;
1184
- const onErrorRef = React14.useRef(onError);
1588
+ const onErrorRef = React18.useRef(onError);
1185
1589
  onErrorRef.current = onError;
1186
- const onCompleteRef = React14.useRef(onComplete);
1590
+ const onCompleteRef = React18.useRef(onComplete);
1187
1591
  onCompleteRef.current = onComplete;
1188
- const validatorsRef = React14.useRef(validators);
1592
+ const validatorsRef = React18.useRef(validators);
1189
1593
  validatorsRef.current = validators;
1190
- const reportTargetRef = React14.useRef(reportTarget);
1594
+ const reportTargetRef = React18.useRef(reportTarget);
1191
1595
  reportTargetRef.current = reportTarget;
1192
- const sessionIdRef = React14.useRef(sessionId);
1596
+ const sessionIdRef = React18.useRef(sessionId);
1193
1597
  sessionIdRef.current = sessionId;
1194
- const clientContextRef = React14.useRef(clientContext);
1598
+ const clientContextRef = React18.useRef(clientContext);
1195
1599
  clientContextRef.current = clientContext;
1196
- const lastScreenIndexRef = React14.useRef(-1);
1197
- const previewTimer = React14.useRef(null);
1198
- const started = React14.useRef(false);
1199
- const finished = React14.useRef(false);
1200
- const errored = React14.useRef(false);
1201
- const attempts = React14.useRef(0);
1202
- const degradedRef = React14.useRef(false);
1203
- const [degraded, setDegraded] = React14.useState(false);
1204
- const [timedOut, setTimedOut] = React14.useState(false);
1205
- const [validationError, setValidationError] = React14.useState();
1206
- const [validating, setValidating] = React14.useState(false);
1207
- const lastCard = React14.useMemo(
1600
+ const lastScreenIndexRef = React18.useRef(-1);
1601
+ const previewTimer = React18.useRef(null);
1602
+ const started = React18.useRef(false);
1603
+ const finished = React18.useRef(false);
1604
+ const errored = React18.useRef(false);
1605
+ const attempts = React18.useRef(0);
1606
+ const degradedRef = React18.useRef(false);
1607
+ const [degraded, setDegraded] = React18.useState(false);
1608
+ const [timedOut, setTimedOut] = React18.useState(false);
1609
+ const [validationError, setValidationError] = React18.useState();
1610
+ const [validating, setValidating] = React18.useState(false);
1611
+ const lastCard = React18.useMemo(
1208
1612
  () => [...messages].reverse().find((m) => {
1209
- var _a2;
1210
- return m.role === "assistant" && ((_a2 = m.response) == null ? void 0 : _a2.action) === "render";
1613
+ var _a3;
1614
+ return m.role === "assistant" && ((_a3 = m.response) == null ? void 0 : _a3.action) === "render";
1211
1615
  }),
1212
1616
  [messages]
1213
1617
  );
1214
- const renderedCount = React14.useMemo(
1618
+ const renderedCount = React18.useMemo(
1215
1619
  () => messages.filter((m) => {
1216
- var _a2;
1217
- return m.role === "assistant" && ((_a2 = m.response) == null ? void 0 : _a2.action) === "render";
1620
+ var _a3;
1621
+ return m.role === "assistant" && ((_a3 = m.response) == null ? void 0 : _a3.action) === "render";
1218
1622
  }).length,
1219
1623
  [messages]
1220
1624
  );
1221
- const progress = React14.useMemo(() => readProgress(lastCard == null ? void 0 : lastCard.response), [lastCard]);
1222
- React14.useEffect(() => {
1223
- var _a2;
1625
+ const progress = React18.useMemo(() => readProgress(lastCard == null ? void 0 : lastCard.response), [lastCard]);
1626
+ React18.useEffect(() => {
1627
+ var _a3;
1224
1628
  if (started.current) return;
1225
1629
  started.current = true;
1226
1630
  sendMessage(resumed ? SKIP_ONE_SENTINEL : startMessage);
1227
- (_a2 = onEventRef.current) == null ? void 0 : _a2.call(
1631
+ (_a3 = onEventRef.current) == null ? void 0 : _a3.call(
1228
1632
  onEventRef,
1229
1633
  resumed ? { type: "resumed", contextId: sessionId } : { type: "started", contextId: sessionId }
1230
1634
  );
1231
1635
  }, [sendMessage, startMessage, resumed, sessionId]);
1232
- React14.useEffect(() => {
1636
+ React18.useEffect(() => {
1233
1637
  if (lastCard) return;
1234
1638
  const timer = setTimeout(() => setTimedOut(true), startTimeoutMs);
1235
1639
  return () => clearTimeout(timer);
1236
1640
  }, [lastCard, startTimeoutMs]);
1237
- React14.useEffect(() => {
1238
- var _a2, _b2, _c2, _d2;
1641
+ React18.useEffect(() => {
1642
+ var _a3, _b2, _c2, _d2;
1239
1643
  setValidationError(void 0);
1240
1644
  if (!(lastCard == null ? void 0 : lastCard.id)) return;
1241
- const step2 = (_a2 = progress.step) != null ? _a2 : renderedCount;
1645
+ const step2 = (_a3 = progress.step) != null ? _a3 : renderedCount;
1242
1646
  lastScreenIndexRef.current = Math.max(0, step2 - 1);
1243
1647
  (_c2 = onEventRef.current) == null ? void 0 : _c2.call(onEventRef, {
1244
1648
  type: "turn",
@@ -1252,33 +1656,33 @@ var OnboardingFlow = ({
1252
1656
  });
1253
1657
  }
1254
1658
  }, [lastCard == null ? void 0 : lastCard.id]);
1255
- React14.useEffect(() => {
1659
+ React18.useEffect(() => {
1256
1660
  return () => {
1257
- var _a2, _b2, _c2;
1661
+ var _a3, _b2, _c2;
1258
1662
  if (finished.current || degradedRef.current) return;
1259
1663
  reportClientEvent(reportTargetRef.current, {
1260
1664
  event_type: "dropped",
1261
1665
  session_id: sessionIdRef.current,
1262
1666
  screen_index: lastScreenIndexRef.current >= 0 ? lastScreenIndexRef.current : void 0,
1263
- device: (_a2 = clientContextRef.current) == null ? void 0 : _a2.device,
1667
+ device: (_a3 = clientContextRef.current) == null ? void 0 : _a3.device,
1264
1668
  user_context: (_b2 = clientContextRef.current) == null ? void 0 : _b2.userContext,
1265
1669
  user_id: (_c2 = clientContextRef.current) == null ? void 0 : _c2.userId
1266
1670
  });
1267
1671
  };
1268
1672
  }, []);
1269
- const restartThread = React14.useCallback(() => {
1673
+ const restartThread = React18.useCallback(() => {
1270
1674
  setTimedOut(false);
1271
1675
  started.current = false;
1272
1676
  errored.current = false;
1273
1677
  reset();
1274
1678
  }, [reset]);
1275
- React14.useEffect(() => {
1276
- var _a2, _b2, _c2, _d2, _e2, _f2, _g;
1679
+ React18.useEffect(() => {
1680
+ var _a3, _b2, _c2, _d2, _e2, _f2, _g;
1277
1681
  if (errored.current) return;
1278
1682
  if (!error && !timedOut) return;
1279
1683
  errored.current = true;
1280
1684
  const reason = error ? "backend" : "timeout";
1281
- (_a2 = onEventRef.current) == null ? void 0 : _a2.call(onEventRef, { type: "error", reason });
1685
+ (_a3 = onEventRef.current) == null ? void 0 : _a3.call(onEventRef, { type: "error", reason });
1282
1686
  attempts.current += 1;
1283
1687
  if (attempts.current <= maxRetries) {
1284
1688
  (_b2 = onEventRef.current) == null ? void 0 : _b2.call(onEventRef, { type: "retry", reason, attempt: attempts.current });
@@ -1299,22 +1703,22 @@ var OnboardingFlow = ({
1299
1703
  (_g = onErrorRef.current) == null ? void 0 : _g.call(onErrorRef, error != null ? error : new Error("Onboarding timed out"));
1300
1704
  }
1301
1705
  }, [error, timedOut, maxRetries]);
1302
- const handleFinish = React14.useCallback(() => {
1706
+ const handleFinish = React18.useCallback(() => {
1303
1707
  if (finished.current) return;
1304
1708
  finished.current = true;
1305
1709
  onCompleteRef.current({ answers: deriveAnswers(messages), raw: messages });
1306
1710
  }, [messages]);
1307
- const handleRetry = React14.useCallback(() => {
1711
+ const handleRetry = React18.useCallback(() => {
1308
1712
  attempts.current = 0;
1309
1713
  degradedRef.current = false;
1310
1714
  setDegraded(false);
1311
1715
  restartThread();
1312
1716
  }, [restartThread]);
1313
- const skipQuestion = React14.useCallback(() => {
1717
+ const skipQuestion = React18.useCallback(() => {
1314
1718
  if (isLoading) return;
1315
1719
  sendMessage(SKIP_ONE_SENTINEL);
1316
1720
  }, [isLoading, sendMessage]);
1317
- const previewOnSelect = React14.useCallback((value) => {
1721
+ const previewOnSelect = React18.useCallback((value) => {
1318
1722
  const target = reportTargetRef.current;
1319
1723
  if (!(target == null ? void 0 : target.serverUrl)) return;
1320
1724
  if (Array.isArray(value) ? value.length === 0 : !value) return;
@@ -1326,31 +1730,31 @@ var OnboardingFlow = ({
1326
1730
  });
1327
1731
  }, 300);
1328
1732
  }, []);
1329
- React14.useEffect(() => () => {
1733
+ React18.useEffect(() => () => {
1330
1734
  if (previewTimer.current) clearTimeout(previewTimer.current);
1331
1735
  }, []);
1332
- const wrappedActions = React14.useCallback(
1736
+ const wrappedActions = React18.useCallback(
1333
1737
  (messageId) => {
1334
- var _a2;
1738
+ var _a3;
1335
1739
  const base = makeActions(messageId);
1336
1740
  const key = progress.key;
1337
- const validator = key ? (_a2 = validatorsRef.current) == null ? void 0 : _a2[key] : void 0;
1741
+ const validator = key ? (_a3 = validatorsRef.current) == null ? void 0 : _a3[key] : void 0;
1338
1742
  if (!validator) return base;
1339
1743
  const out = { ...base };
1340
- for (const name of ANSWER_CALLBACKS) {
1341
- const original = base[name];
1744
+ for (const name2 of ANSWER_CALLBACKS) {
1745
+ const original = base[name2];
1342
1746
  if (!original) continue;
1343
- out[name] = (...args) => {
1747
+ out[name2] = (...args) => {
1344
1748
  const value = args[0];
1345
1749
  if (typeof value !== "string") return original(...args);
1346
1750
  setValidating(true);
1347
1751
  validator(value).then((res) => {
1348
- var _a3;
1752
+ var _a4;
1349
1753
  if (res.ok) {
1350
1754
  setValidationError(void 0);
1351
1755
  original(...args);
1352
1756
  } else {
1353
- setValidationError((_a3 = res.error) != null ? _a3 : "That value isn't available.");
1757
+ setValidationError((_a4 = res.error) != null ? _a4 : "That value isn't available.");
1354
1758
  }
1355
1759
  }).catch(() => {
1356
1760
  original(...args);
@@ -1381,7 +1785,7 @@ var OnboardingFlow = ({
1381
1785
  if (!lastCard || !response) {
1382
1786
  return /* @__PURE__ */ jsxRuntime.jsx(LoadingScreen, { title: c.startingTitle, hint: c.startingHint });
1383
1787
  }
1384
- const step = (_a = progress.step) != null ? _a : renderedCount;
1788
+ const step = (_a2 = progress.step) != null ? _a2 : renderedCount;
1385
1789
  const total = (_b = progress.total) != null ? _b : approxScreens;
1386
1790
  const isTerminal = response.action === "render" && response.component === "StatusCard";
1387
1791
  if (isTerminal) {
@@ -1453,9 +1857,9 @@ var schema = zod.z.object({
1453
1857
  var _ChipItem = ({ chip, isSelected, multiSelect, onToggle }) => {
1454
1858
  const t = useOnboardingTheme();
1455
1859
  const reduced = useReducedMotion();
1456
- const handlePress = React14.useCallback(() => onToggle(chip), [chip, onToggle]);
1457
- const pressScale = React14.useRef(new reactNative.Animated.Value(1)).current;
1458
- const pressTo = React14.useCallback(
1860
+ const handlePress = React18.useCallback(() => onToggle(chip), [chip, onToggle]);
1861
+ const pressScale = React18.useRef(new reactNative.Animated.Value(1)).current;
1862
+ const pressTo = React18.useCallback(
1459
1863
  (to) => {
1460
1864
  if (reduced) return;
1461
1865
  reactNative.Animated.spring(pressScale, {
@@ -1467,10 +1871,10 @@ var _ChipItem = ({ chip, isSelected, multiSelect, onToggle }) => {
1467
1871
  },
1468
1872
  [pressScale, reduced]
1469
1873
  );
1470
- const handlePressIn = React14.useCallback(() => pressTo(CHIP_PRESS_SCALE), [pressTo]);
1471
- const handlePressOut = React14.useCallback(() => pressTo(1), [pressTo]);
1472
- const fillT = React14.useRef(new reactNative.Animated.Value(isSelected ? 1 : 0)).current;
1473
- React14.useEffect(() => {
1874
+ const handlePressIn = React18.useCallback(() => pressTo(CHIP_PRESS_SCALE), [pressTo]);
1875
+ const handlePressOut = React18.useCallback(() => pressTo(1), [pressTo]);
1876
+ const fillT = React18.useRef(new reactNative.Animated.Value(isSelected ? 1 : 0)).current;
1877
+ React18.useEffect(() => {
1474
1878
  const anim = reactNative.Animated.timing(fillT, {
1475
1879
  toValue: isSelected ? 1 : 0,
1476
1880
  duration: scaledMs(stateChangeDuration(reduced, CHIP_FILL_MS)),
@@ -1480,8 +1884,8 @@ var _ChipItem = ({ chip, isSelected, multiSelect, onToggle }) => {
1480
1884
  anim.start();
1481
1885
  return () => anim.stop();
1482
1886
  }, [isSelected, reduced, fillT]);
1483
- const checkT = React14.useRef(new reactNative.Animated.Value(isSelected ? 1 : 0)).current;
1484
- React14.useEffect(() => {
1887
+ const checkT = React18.useRef(new reactNative.Animated.Value(isSelected ? 1 : 0)).current;
1888
+ React18.useEffect(() => {
1485
1889
  if (!isSelected) {
1486
1890
  checkT.setValue(0);
1487
1891
  return;
@@ -1568,7 +1972,7 @@ var _ChipItem = ({ chip, isSelected, multiSelect, onToggle }) => {
1568
1972
  }
1569
1973
  );
1570
1974
  };
1571
- var ChipItem = React14__default.default.memo(_ChipItem);
1975
+ var ChipItem = React18__default.default.memo(_ChipItem);
1572
1976
  var _ChipSelectCard = ({
1573
1977
  title,
1574
1978
  chips,
@@ -1579,12 +1983,12 @@ var _ChipSelectCard = ({
1579
1983
  onSelectionChange
1580
1984
  }) => {
1581
1985
  const t = useOnboardingTheme();
1582
- const [selected, setSelected] = React14.useState([]);
1583
- const [submitted, setSubmitted] = React14.useState(false);
1584
- React14.useEffect(() => {
1986
+ const [selected, setSelected] = React18.useState([]);
1987
+ const [submitted, setSubmitted] = React18.useState(false);
1988
+ React18.useEffect(() => {
1585
1989
  if (!submitted && selected.length) onSelectionChange == null ? void 0 : onSelectionChange(multiSelect ? selected : selected[0]);
1586
1990
  }, [selected, submitted, multiSelect, onSelectionChange]);
1587
- const toggle = React14.useCallback(
1991
+ const toggle = React18.useCallback(
1588
1992
  (chip) => {
1589
1993
  if (submitted) return;
1590
1994
  if (multiSelect) {
@@ -1599,7 +2003,7 @@ var _ChipSelectCard = ({
1599
2003
  },
1600
2004
  [submitted, multiSelect, maxSelections]
1601
2005
  );
1602
- const handleSubmit = React14.useCallback(() => {
2006
+ const handleSubmit = React18.useCallback(() => {
1603
2007
  if (!selected.length || !onSelect || submitted) return;
1604
2008
  setSubmitted(true);
1605
2009
  onSelect(multiSelect ? selected : selected[0]);
@@ -1633,8 +2037,8 @@ var _ChipSelectCard = ({
1633
2037
  };
1634
2038
  var ChipSelectCard = {
1635
2039
  name: "ChipSelectCard",
1636
- description: "Use for compact short labels: seasons, activities, travel styles, moods, categories. Ideal for 4\u201312 single-word or two-word options. Use SelectionCard instead when options need descriptions.",
1637
- component: React14__default.default.memo(_ChipSelectCard),
2040
+ description: "Use for compact short labels: seasons, activities, travel styles, moods, categories. Ideal for 4\u201312 single-word or two-word options. Use SelectionCard instead when options need descriptions; use CardGridSelectCard for a smaller set (2\u20136) of visual choices that each deserve an icon.",
2041
+ component: React18__default.default.memo(_ChipSelectCard),
1638
2042
  propsSchema: schema,
1639
2043
  defaultProps: { multiSelect: true, submitLabel: "Continue" }
1640
2044
  };
@@ -1670,14 +2074,14 @@ var _TextInputCard = ({
1670
2074
  lines = 6
1671
2075
  }) => {
1672
2076
  const t = useOnboardingTheme();
1673
- const styles16 = React14.useMemo(() => makeStyles3(t), [t]);
2077
+ const styles18 = React18.useMemo(() => makeStyles3(t), [t]);
1674
2078
  const { height: screenHeight } = reactNative.useWindowDimensions();
1675
- const [value, setValue] = React14.useState("");
1676
- const [submitted, setSubmitted] = React14.useState(false);
2079
+ const [value, setValue] = React18.useState("");
2080
+ const [submitted, setSubmitted] = React18.useState(false);
1677
2081
  const locked = submitted && !validationError;
1678
2082
  const APPROX_ROW_HEIGHT = 26;
1679
2083
  const minHeight = multiline ? Math.min(Math.max(lines, 4) * APPROX_ROW_HEIGHT + t.spacing.md * 2, screenHeight * 0.4) : 52;
1680
- const handleSubmit = React14.useCallback(() => {
2084
+ const handleSubmit = React18.useCallback(() => {
1681
2085
  if (value.trim() && onSubmit && !locked) {
1682
2086
  setSubmitted(true);
1683
2087
  onSubmit(value.trim());
@@ -1697,7 +2101,7 @@ var _TextInputCard = ({
1697
2101
  disabled: !value.trim() || locked
1698
2102
  }
1699
2103
  ),
1700
- children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles16.row, children: [
2104
+ children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles18.row, children: [
1701
2105
  /* @__PURE__ */ jsxRuntime.jsx(
1702
2106
  reactNative.TextInput,
1703
2107
  {
@@ -1711,7 +2115,7 @@ var _TextInputCard = ({
1711
2115
  textAlignVertical: multiline ? "top" : "center",
1712
2116
  style: [
1713
2117
  bodyStyle(t.fonts),
1714
- styles16.input,
2118
+ styles18.input,
1715
2119
  {
1716
2120
  color: t.colors.text,
1717
2121
  backgroundColor: t.colors.surface,
@@ -1731,7 +2135,7 @@ var _TextInputCard = ({
1731
2135
  var TextInputCard = {
1732
2136
  name: "TextInputCard",
1733
2137
  description: "Use when the user needs to type a free-text answer: an open-ended goal, notes, feedback, a name, a destination, a search query. Multi-line by default (great for open-ended goals); set multiline:false for a short single-line field like a name. Use NumberStepperCard for numeric ranges with known bounds.",
1734
- component: React14__default.default.memo(_TextInputCard),
2138
+ component: React18__default.default.memo(_TextInputCard),
1735
2139
  propsSchema: schema2,
1736
2140
  defaultProps: { submitLabel: "Submit", multiline: true, lines: 6 }
1737
2141
  };
@@ -1741,26 +2145,210 @@ function makeStyles3(t) {
1741
2145
  input: { borderWidth: 1 }
1742
2146
  });
1743
2147
  }
1744
- var easeWire5 = reactNative.Easing.bezier(...WIRE_BEZIER);
2148
+
2149
+ // src/icons/expoIcons.ts
2150
+ var runtimeRequire = (moduleName) => {
2151
+ if (moduleName !== "@expo/vector-icons") return void 0;
2152
+ if (typeof __require !== "function") return void 0;
2153
+ try {
2154
+ return __require("@expo/vector-icons");
2155
+ } catch {
2156
+ return void 0;
2157
+ }
2158
+ };
2159
+ var interop = (mod) => {
2160
+ if (!mod || typeof mod !== "object") return void 0;
2161
+ const def = mod.default;
2162
+ const ns = mod;
2163
+ if (ns.MaterialCommunityIcons || ns.Ionicons) return ns;
2164
+ if (def && typeof def === "object") return def;
2165
+ return ns;
2166
+ };
2167
+ var asComponent = (value) => {
2168
+ if (typeof value === "function") return value;
2169
+ if (value && typeof value === "object" && "$$typeof" in value) {
2170
+ return value;
2171
+ }
2172
+ return void 0;
2173
+ };
2174
+ var cached;
2175
+ var resolveIconFamily = (family, requireModule = runtimeRequire) => {
2176
+ try {
2177
+ if (cached === void 0 || requireModule !== runtimeRequire) {
2178
+ const resolved = interop(requireModule("@expo/vector-icons"));
2179
+ if (requireModule === runtimeRequire) cached = resolved != null ? resolved : null;
2180
+ if (!resolved) return void 0;
2181
+ return asComponent(resolved[family]);
2182
+ }
2183
+ if (cached === null) return void 0;
2184
+ return asComponent(cached[family]);
2185
+ } catch {
2186
+ return void 0;
2187
+ }
2188
+ };
2189
+
2190
+ // src/icons/vocabulary.ts
2191
+ var WIRE_ICON_GLYPHS = {
2192
+ // ── Acquisition channels ("where did you hear about us?") ──────────────────
2193
+ instagram: { family: "MaterialCommunityIcons", name: "instagram" },
2194
+ tiktok: { family: "Ionicons", name: "logo-tiktok" },
2195
+ youtube: { family: "MaterialCommunityIcons", name: "youtube" },
2196
+ facebook: { family: "MaterialCommunityIcons", name: "facebook" },
2197
+ twitter: { family: "MaterialCommunityIcons", name: "twitter" },
2198
+ reddit: { family: "MaterialCommunityIcons", name: "reddit" },
2199
+ linkedin: { family: "MaterialCommunityIcons", name: "linkedin" },
2200
+ discord: { family: "Ionicons", name: "logo-discord" },
2201
+ whatsapp: { family: "MaterialCommunityIcons", name: "whatsapp" },
2202
+ twitch: { family: "MaterialCommunityIcons", name: "twitch" },
2203
+ snapchat: { family: "MaterialCommunityIcons", name: "snapchat" },
2204
+ pinterest: { family: "MaterialCommunityIcons", name: "pinterest" },
2205
+ google: { family: "MaterialCommunityIcons", name: "google" },
2206
+ search: { family: "MaterialCommunityIcons", name: "magnify" },
2207
+ friend: { family: "MaterialCommunityIcons", name: "account-heart" },
2208
+ podcast: { family: "MaterialCommunityIcons", name: "podcast" },
2209
+ blog: { family: "MaterialCommunityIcons", name: "post" },
2210
+ newsletter: { family: "MaterialCommunityIcons", name: "email-outline" },
2211
+ news: { family: "MaterialCommunityIcons", name: "newspaper" },
2212
+ "app-store": { family: "MaterialCommunityIcons", name: "apple" },
2213
+ ad: { family: "MaterialCommunityIcons", name: "bullhorn" },
2214
+ // ── Intent / occasion ("what brings you here?") ────────────────────────────
2215
+ wedding: { family: "MaterialCommunityIcons", name: "ring" },
2216
+ birthday: { family: "MaterialCommunityIcons", name: "cake-variant" },
2217
+ baby: { family: "MaterialCommunityIcons", name: "baby-carriage" },
2218
+ travel: { family: "MaterialCommunityIcons", name: "airplane" },
2219
+ work: { family: "MaterialCommunityIcons", name: "briefcase" },
2220
+ celebration: { family: "MaterialCommunityIcons", name: "party-popper" },
2221
+ store: { family: "MaterialCommunityIcons", name: "storefront" },
2222
+ school: { family: "MaterialCommunityIcons", name: "school" },
2223
+ team: { family: "MaterialCommunityIcons", name: "account-multiple" },
2224
+ growth: { family: "MaterialCommunityIcons", name: "trending-up" },
2225
+ // ── General purpose ────────────────────────────────────────────────────────
2226
+ sparkle: { family: "MaterialCommunityIcons", name: "star-four-points" },
2227
+ heart: { family: "MaterialCommunityIcons", name: "heart" },
2228
+ star: { family: "MaterialCommunityIcons", name: "star" },
2229
+ fire: { family: "MaterialCommunityIcons", name: "fire" },
2230
+ target: { family: "MaterialCommunityIcons", name: "target" },
2231
+ trophy: { family: "MaterialCommunityIcons", name: "trophy" },
2232
+ rocket: { family: "MaterialCommunityIcons", name: "rocket-launch" },
2233
+ clock: { family: "MaterialCommunityIcons", name: "clock-outline" },
2234
+ calendar: { family: "MaterialCommunityIcons", name: "calendar-star" },
2235
+ camera: { family: "MaterialCommunityIcons", name: "camera" },
2236
+ image: { family: "MaterialCommunityIcons", name: "image" },
2237
+ video: { family: "MaterialCommunityIcons", name: "video" },
2238
+ mic: { family: "MaterialCommunityIcons", name: "microphone" },
2239
+ music: { family: "MaterialCommunityIcons", name: "music" },
2240
+ book: { family: "MaterialCommunityIcons", name: "book-open-variant" },
2241
+ food: { family: "MaterialCommunityIcons", name: "silverware-fork-knife" },
2242
+ coffee: { family: "MaterialCommunityIcons", name: "coffee" },
2243
+ fitness: { family: "MaterialCommunityIcons", name: "dumbbell" },
2244
+ health: { family: "MaterialCommunityIcons", name: "heart-pulse" },
2245
+ meditation: { family: "MaterialCommunityIcons", name: "meditation" },
2246
+ sleep: { family: "MaterialCommunityIcons", name: "sleep" },
2247
+ brain: { family: "MaterialCommunityIcons", name: "brain" },
2248
+ idea: { family: "MaterialCommunityIcons", name: "lightbulb-on" },
2249
+ money: { family: "MaterialCommunityIcons", name: "cash" },
2250
+ shopping: { family: "MaterialCommunityIcons", name: "cart" },
2251
+ gift: { family: "MaterialCommunityIcons", name: "gift" },
2252
+ home: { family: "MaterialCommunityIcons", name: "home" },
2253
+ car: { family: "MaterialCommunityIcons", name: "car" },
2254
+ pet: { family: "MaterialCommunityIcons", name: "paw" },
2255
+ plant: { family: "MaterialCommunityIcons", name: "sprout" },
2256
+ sun: { family: "MaterialCommunityIcons", name: "white-balance-sunny" },
2257
+ moon: { family: "MaterialCommunityIcons", name: "weather-night" },
2258
+ globe: { family: "MaterialCommunityIcons", name: "earth" },
2259
+ "map-pin": { family: "MaterialCommunityIcons", name: "map-marker" },
2260
+ compass: { family: "MaterialCommunityIcons", name: "compass" },
2261
+ flag: { family: "MaterialCommunityIcons", name: "flag" },
2262
+ bookmark: { family: "MaterialCommunityIcons", name: "bookmark" },
2263
+ bell: { family: "MaterialCommunityIcons", name: "bell" },
2264
+ mail: { family: "MaterialCommunityIcons", name: "email" },
2265
+ phone: { family: "MaterialCommunityIcons", name: "phone" },
2266
+ chat: { family: "MaterialCommunityIcons", name: "chat" },
2267
+ user: { family: "MaterialCommunityIcons", name: "account" },
2268
+ users: { family: "MaterialCommunityIcons", name: "account-group" },
2269
+ settings: { family: "MaterialCommunityIcons", name: "cog" },
2270
+ tools: { family: "MaterialCommunityIcons", name: "tools" },
2271
+ puzzle: { family: "MaterialCommunityIcons", name: "puzzle" },
2272
+ chart: { family: "MaterialCommunityIcons", name: "chart-line" },
2273
+ shield: { family: "MaterialCommunityIcons", name: "shield-check" },
2274
+ lock: { family: "MaterialCommunityIcons", name: "lock" },
2275
+ cloud: { family: "MaterialCommunityIcons", name: "cloud" },
2276
+ pencil: { family: "MaterialCommunityIcons", name: "pencil" },
2277
+ check: { family: "MaterialCommunityIcons", name: "check-circle" },
2278
+ plus: { family: "MaterialCommunityIcons", name: "plus-circle" },
2279
+ question: { family: "MaterialCommunityIcons", name: "help-circle" },
2280
+ other: { family: "MaterialCommunityIcons", name: "dots-horizontal-circle" }
2281
+ };
2282
+ var WIRE_ICON_NAMES = Object.keys(WIRE_ICON_GLYPHS).sort();
2283
+ var lookupIconGlyph = (name2) => {
2284
+ if (!name2) return void 0;
2285
+ if (!Object.prototype.hasOwnProperty.call(WIRE_ICON_GLYPHS, name2)) return void 0;
2286
+ return WIRE_ICON_GLYPHS[name2];
2287
+ };
2288
+ var _WireIcon = ({ name: name2, size = 20, color, requireModule }) => {
2289
+ const hostIcon = useHostIcon(name2);
2290
+ if (hostIcon) {
2291
+ return /* @__PURE__ */ jsxRuntime.jsx(
2292
+ reactNative.View,
2293
+ {
2294
+ style: styles11.decorative,
2295
+ accessible: false,
2296
+ importantForAccessibility: "no-hide-descendants",
2297
+ children: hostIcon
2298
+ }
2299
+ );
2300
+ }
2301
+ const glyph = lookupIconGlyph(name2);
2302
+ if (!glyph) return null;
2303
+ const Family = resolveIconFamily(glyph.family, requireModule);
2304
+ if (!Family) return null;
2305
+ return /* @__PURE__ */ jsxRuntime.jsx(
2306
+ reactNative.View,
2307
+ {
2308
+ style: styles11.decorative,
2309
+ accessible: false,
2310
+ importantForAccessibility: "no-hide-descendants",
2311
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2312
+ Family,
2313
+ {
2314
+ name: glyph.name,
2315
+ size,
2316
+ color,
2317
+ allowFontScaling: false
2318
+ }
2319
+ )
2320
+ }
2321
+ );
2322
+ };
2323
+ var WireIcon = React18__default.default.memo(_WireIcon);
2324
+ WireIcon.displayName = "WireIcon";
2325
+ var styles11 = reactNative.StyleSheet.create({
2326
+ // No size/margin of its own: the glyph decides its footprint, so an absent icon and a
2327
+ // present one differ by exactly the glyph — never by a wrapper.
2328
+ decorative: {}
2329
+ });
2330
+ var ICON_FIELD_DESCRIPTION = `Optional icon for this option, making the choice scannable at a glance. Pick the ONE name whose meaning matches the option (e.g. 'instagram' for an Instagram answer, 'friend' for 'A friend told me', 'wedding' for a wedding). Omit it when no name fits \u2014 a wrong icon is worse than none. Allowed values: ${WIRE_ICON_NAMES.join(", ")}.`;
1745
2331
  var optionObjectSchema = zod.z.object({
1746
2332
  value: zod.z.string().describe("Option value"),
1747
- label: zod.z.string().describe("Option display label")
2333
+ label: zod.z.string().describe("Option display label"),
2334
+ icon: zod.z.string().optional().describe(ICON_FIELD_DESCRIPTION)
1748
2335
  });
2336
+ var coerceOptions = (arr) => Array.isArray(arr) ? arr.map((item) => typeof item === "string" ? { value: item, label: item } : item) : arr;
2337
+ var optionsField = (description) => zod.z.preprocess(coerceOptions, zod.z.array(optionObjectSchema).min(1)).describe(description);
2338
+ var normalizeOptions = (options) => options.map((opt) => typeof opt === "string" ? { value: opt, label: opt } : opt);
2339
+ var easeWire5 = reactNative.Easing.bezier(...WIRE_BEZIER);
1749
2340
  var schema3 = zod.z.object({
1750
2341
  title: zod.z.string().describe("Question or prompt for the user"),
1751
- options: zod.z.preprocess(
1752
- (arr) => Array.isArray(arr) ? arr.map((item) => typeof item === "string" ? { value: item, label: item } : item) : arr,
1753
- zod.z.array(optionObjectSchema).min(1)
1754
- ).describe("List of choices"),
2342
+ options: optionsField("List of choices"),
1755
2343
  submitLabel: zod.z.string().optional().describe("Submit button label, default: Continue"),
1756
2344
  multiSelect: zod.z.boolean().optional().describe("Allow multiple selections")
1757
2345
  });
1758
2346
  var _OptionRow = ({ opt, isSelected, multiSelect, onToggle }) => {
1759
2347
  const t = useOnboardingTheme();
1760
2348
  const reduced = useReducedMotion();
1761
- const handlePress = React14.useCallback(() => onToggle(opt.value), [opt.value, onToggle]);
1762
- const pressScale = React14.useRef(new reactNative.Animated.Value(1)).current;
1763
- const pressTo = React14.useCallback(
2349
+ const handlePress = React18.useCallback(() => onToggle(opt.value), [opt.value, onToggle]);
2350
+ const pressScale = React18.useRef(new reactNative.Animated.Value(1)).current;
2351
+ const pressTo = React18.useCallback(
1764
2352
  (to) => {
1765
2353
  if (reduced) return;
1766
2354
  reactNative.Animated.spring(pressScale, {
@@ -1772,10 +2360,10 @@ var _OptionRow = ({ opt, isSelected, multiSelect, onToggle }) => {
1772
2360
  },
1773
2361
  [pressScale, reduced]
1774
2362
  );
1775
- const handlePressIn = React14.useCallback(() => pressTo(ROW_PRESS_SCALE), [pressTo]);
1776
- const handlePressOut = React14.useCallback(() => pressTo(1), [pressTo]);
1777
- const selectT = React14.useRef(new reactNative.Animated.Value(isSelected ? 1 : 0)).current;
1778
- React14.useEffect(() => {
2363
+ const handlePressIn = React18.useCallback(() => pressTo(ROW_PRESS_SCALE), [pressTo]);
2364
+ const handlePressOut = React18.useCallback(() => pressTo(1), [pressTo]);
2365
+ const selectT = React18.useRef(new reactNative.Animated.Value(isSelected ? 1 : 0)).current;
2366
+ React18.useEffect(() => {
1779
2367
  const anim = reactNative.Animated.timing(selectT, {
1780
2368
  toValue: isSelected ? 1 : 0,
1781
2369
  duration: scaledMs(stateChangeDuration(reduced, SELECT_FILL_MS)),
@@ -1785,8 +2373,8 @@ var _OptionRow = ({ opt, isSelected, multiSelect, onToggle }) => {
1785
2373
  anim.start();
1786
2374
  return () => anim.stop();
1787
2375
  }, [isSelected, reduced, selectT]);
1788
- const checkT = React14.useRef(new reactNative.Animated.Value(isSelected ? 1 : 0)).current;
1789
- React14.useEffect(() => {
2376
+ const checkT = React18.useRef(new reactNative.Animated.Value(isSelected ? 1 : 0)).current;
2377
+ React18.useEffect(() => {
1790
2378
  if (!isSelected) {
1791
2379
  checkT.setValue(0);
1792
2380
  return;
@@ -1819,7 +2407,7 @@ var _OptionRow = ({ opt, isSelected, multiSelect, onToggle }) => {
1819
2407
  reactNative.Animated.View,
1820
2408
  {
1821
2409
  style: [
1822
- styles11.option,
2410
+ styles12.option,
1823
2411
  {
1824
2412
  padding: t.spacing.md,
1825
2413
  borderRadius: t.radius.md,
@@ -1836,7 +2424,7 @@ var _OptionRow = ({ opt, isSelected, multiSelect, onToggle }) => {
1836
2424
  pointerEvents: "none",
1837
2425
  style: [
1838
2426
  reactNative.StyleSheet.absoluteFill,
1839
- styles11.selectedOverlay,
2427
+ styles12.selectedOverlay,
1840
2428
  {
1841
2429
  borderRadius: t.radius.md,
1842
2430
  borderColor: t.colors.primary,
@@ -1850,7 +2438,7 @@ var _OptionRow = ({ opt, isSelected, multiSelect, onToggle }) => {
1850
2438
  reactNative.View,
1851
2439
  {
1852
2440
  style: [
1853
- styles11.indicator,
2441
+ styles12.indicator,
1854
2442
  { borderRadius: t.radius.full },
1855
2443
  isSelected ? { borderColor: t.colors.primary, backgroundColor: t.colors.primary } : { borderColor: t.colors.borderStrong, backgroundColor: "transparent" }
1856
2444
  ],
@@ -1858,7 +2446,7 @@ var _OptionRow = ({ opt, isSelected, multiSelect, onToggle }) => {
1858
2446
  reactNative.Animated.Text,
1859
2447
  {
1860
2448
  style: [
1861
- styles11.check,
2449
+ styles12.check,
1862
2450
  { color: t.colors.onPrimary, opacity: checkT, transform: [{ scale: checkScale }] }
1863
2451
  ],
1864
2452
  children: "\u2713"
@@ -1866,6 +2454,7 @@ var _OptionRow = ({ opt, isSelected, multiSelect, onToggle }) => {
1866
2454
  ) : null
1867
2455
  }
1868
2456
  ),
2457
+ /* @__PURE__ */ jsxRuntime.jsx(WireIcon, { name: opt.icon, size: 20, color: t.colors.text }),
1869
2458
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [labelStyle(t.fonts), { color: t.colors.text }], children: opt.label })
1870
2459
  ]
1871
2460
  }
@@ -1873,7 +2462,7 @@ var _OptionRow = ({ opt, isSelected, multiSelect, onToggle }) => {
1873
2462
  }
1874
2463
  );
1875
2464
  };
1876
- var OptionRow = React14__default.default.memo(_OptionRow);
2465
+ var OptionRow = React18__default.default.memo(_OptionRow);
1877
2466
  var _SelectionCard = ({
1878
2467
  title,
1879
2468
  options,
@@ -1883,12 +2472,13 @@ var _SelectionCard = ({
1883
2472
  onSelectionChange
1884
2473
  }) => {
1885
2474
  const t = useOnboardingTheme();
1886
- const [selected, setSelected] = React14.useState([]);
1887
- const [submitted, setSubmitted] = React14.useState(false);
1888
- React14.useEffect(() => {
2475
+ const opts = React18__default.default.useMemo(() => normalizeOptions(options), [options]);
2476
+ const [selected, setSelected] = React18.useState([]);
2477
+ const [submitted, setSubmitted] = React18.useState(false);
2478
+ React18.useEffect(() => {
1889
2479
  if (!submitted && selected.length) onSelectionChange == null ? void 0 : onSelectionChange(multiSelect ? selected : selected[0]);
1890
2480
  }, [selected, submitted, multiSelect, onSelectionChange]);
1891
- const toggle = React14.useCallback(
2481
+ const toggle = React18.useCallback(
1892
2482
  (value) => {
1893
2483
  if (submitted) return;
1894
2484
  if (multiSelect) {
@@ -1899,7 +2489,7 @@ var _SelectionCard = ({
1899
2489
  },
1900
2490
  [submitted, multiSelect]
1901
2491
  );
1902
- const handleSubmit = React14.useCallback(() => {
2492
+ const handleSubmit = React18.useCallback(() => {
1903
2493
  if (!selected.length || !onSelect || submitted) return;
1904
2494
  setSubmitted(true);
1905
2495
  onSelect(multiSelect ? selected : selected[0]);
@@ -1917,7 +2507,7 @@ var _SelectionCard = ({
1917
2507
  disabled: selected.length === 0 || submitted
1918
2508
  }
1919
2509
  ),
1920
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: { gap: t.spacing.sm + t.spacing.xs }, children: options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(
2510
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: { gap: t.spacing.sm + t.spacing.xs }, children: opts.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(
1921
2511
  OptionRow,
1922
2512
  {
1923
2513
  opt,
@@ -1932,12 +2522,12 @@ var _SelectionCard = ({
1932
2522
  };
1933
2523
  var SelectionCard = {
1934
2524
  name: "SelectionCard",
1935
- description: "Use for mutually exclusive (radio) or multi-select (checkbox) choices from 2\u20138 options. Use ChipSelectCard instead when options are short single words.",
1936
- component: React14__default.default.memo(_SelectionCard),
2525
+ description: "Use for mutually exclusive (radio) or multi-select (checkbox) choices from 2\u20138 options, as a vertical list of rows. Best when options are wordy or need reading. Options may carry an optional `icon` from the vocabulary to make the list scannable. Use ChipSelectCard instead when options are short single words; use CardGridSelectCard when the options are visual and each has an obvious icon (occasions, channels, categories).",
2526
+ component: React18__default.default.memo(_SelectionCard),
1937
2527
  propsSchema: schema3,
1938
2528
  defaultProps: { submitLabel: "Continue", multiSelect: false }
1939
2529
  };
1940
- var styles11 = reactNative.StyleSheet.create({
2530
+ var styles12 = reactNative.StyleSheet.create({
1941
2531
  option: { borderWidth: 1.5, flexDirection: "row", alignItems: "center", overflow: "hidden" },
1942
2532
  selectedOverlay: { borderWidth: 1.5 },
1943
2533
  indicator: { width: 24, height: 24, borderWidth: 2, alignItems: "center", justifyContent: "center" },
@@ -1945,6 +2535,168 @@ var styles11 = reactNative.StyleSheet.create({
1945
2535
  });
1946
2536
  var easeWire6 = reactNative.Easing.bezier(...WIRE_BEZIER);
1947
2537
  var schema4 = zod.z.object({
2538
+ title: zod.z.string().describe("Question or prompt for the user, e.g. 'What brings you here?'"),
2539
+ options: optionsField(
2540
+ "The choices, 2-6 of them. Give EVERY option an `icon` from the vocabulary \u2014 the icon is the point of this card, and an option without one renders as a bare label next to icon-bearing neighbours. Keep labels short (1-3 words) so they fit a half-width card."
2541
+ ),
2542
+ submitLabel: zod.z.string().optional().describe("Submit button label, default: Continue"),
2543
+ multiSelect: zod.z.boolean().optional().describe("Allow multiple cards selected at once, default true")
2544
+ });
2545
+ var _OptionCard = ({ opt, isSelected, multiSelect, onToggle }) => {
2546
+ const t = useOnboardingTheme();
2547
+ const reduced = useReducedMotion();
2548
+ const handlePress = React18.useCallback(() => onToggle(opt.value), [opt.value, onToggle]);
2549
+ const pressScale = React18.useRef(new reactNative.Animated.Value(1)).current;
2550
+ const pressTo = React18.useCallback(
2551
+ (to) => {
2552
+ if (reduced) return;
2553
+ reactNative.Animated.spring(pressScale, {
2554
+ toValue: to,
2555
+ friction: PRESS_SPRING.friction,
2556
+ tension: PRESS_SPRING.tension,
2557
+ useNativeDriver: true
2558
+ }).start();
2559
+ },
2560
+ [pressScale, reduced]
2561
+ );
2562
+ const handlePressIn = React18.useCallback(() => pressTo(ROW_PRESS_SCALE), [pressTo]);
2563
+ const handlePressOut = React18.useCallback(() => pressTo(1), [pressTo]);
2564
+ const selectT = React18.useRef(new reactNative.Animated.Value(isSelected ? 1 : 0)).current;
2565
+ React18.useEffect(() => {
2566
+ const anim = reactNative.Animated.timing(selectT, {
2567
+ toValue: isSelected ? 1 : 0,
2568
+ duration: scaledMs(stateChangeDuration(reduced, SELECT_FILL_MS)),
2569
+ easing: easeWire6,
2570
+ useNativeDriver: true
2571
+ });
2572
+ anim.start();
2573
+ return () => anim.stop();
2574
+ }, [isSelected, reduced, selectT]);
2575
+ return /* @__PURE__ */ jsxRuntime.jsx(
2576
+ reactNative.Pressable,
2577
+ {
2578
+ onPress: handlePress,
2579
+ onPressIn: handlePressIn,
2580
+ onPressOut: handlePressOut,
2581
+ accessibilityRole: multiSelect ? "checkbox" : "radio",
2582
+ accessibilityState: multiSelect ? { checked: isSelected } : { selected: isSelected },
2583
+ accessibilityLabel: opt.label,
2584
+ style: styles13.cell,
2585
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
2586
+ reactNative.Animated.View,
2587
+ {
2588
+ style: [
2589
+ styles13.card,
2590
+ {
2591
+ padding: t.spacing.md,
2592
+ borderRadius: t.radius.lg,
2593
+ gap: t.spacing.sm,
2594
+ borderColor: t.colors.border,
2595
+ backgroundColor: t.colors.surface,
2596
+ transform: [{ scale: pressScale }]
2597
+ }
2598
+ ],
2599
+ children: [
2600
+ /* @__PURE__ */ jsxRuntime.jsx(
2601
+ reactNative.Animated.View,
2602
+ {
2603
+ pointerEvents: "none",
2604
+ style: [
2605
+ reactNative.StyleSheet.absoluteFill,
2606
+ styles13.selectedOverlay,
2607
+ {
2608
+ borderRadius: t.radius.lg,
2609
+ borderColor: t.colors.primary,
2610
+ backgroundColor: t.colors.primarySoft,
2611
+ opacity: selectT
2612
+ }
2613
+ ]
2614
+ }
2615
+ ),
2616
+ /* @__PURE__ */ jsxRuntime.jsx(WireIcon, { name: opt.icon, size: 24, color: t.colors.text }),
2617
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [labelStyle(t.fonts), { color: t.colors.text }], children: opt.label })
2618
+ ]
2619
+ }
2620
+ )
2621
+ }
2622
+ );
2623
+ };
2624
+ var OptionCard = React18__default.default.memo(_OptionCard);
2625
+ var _CardGridSelectCard = ({
2626
+ title,
2627
+ options,
2628
+ submitLabel = "Continue",
2629
+ multiSelect = true,
2630
+ onSelect,
2631
+ onSelectionChange
2632
+ }) => {
2633
+ const t = useOnboardingTheme();
2634
+ const opts = React18__default.default.useMemo(() => normalizeOptions(options), [options]);
2635
+ const [selected, setSelected] = React18.useState([]);
2636
+ const [submitted, setSubmitted] = React18.useState(false);
2637
+ React18.useEffect(() => {
2638
+ if (!submitted && selected.length) onSelectionChange == null ? void 0 : onSelectionChange(multiSelect ? selected : selected[0]);
2639
+ }, [selected, submitted, multiSelect, onSelectionChange]);
2640
+ const toggle = React18.useCallback(
2641
+ (value) => {
2642
+ if (submitted) return;
2643
+ if (multiSelect) {
2644
+ setSelected(
2645
+ (prev) => prev.includes(value) ? prev.filter((v) => v !== value) : [...prev, value]
2646
+ );
2647
+ } else {
2648
+ setSelected([value]);
2649
+ }
2650
+ },
2651
+ [submitted, multiSelect]
2652
+ );
2653
+ const handleSubmit = React18.useCallback(() => {
2654
+ if (!selected.length || !onSelect || submitted) return;
2655
+ setSubmitted(true);
2656
+ onSelect(multiSelect ? selected : selected[0]);
2657
+ }, [selected, onSelect, submitted, multiSelect]);
2658
+ return /* @__PURE__ */ jsxRuntime.jsx(
2659
+ CardLayout,
2660
+ {
2661
+ title,
2662
+ footer: /* @__PURE__ */ jsxRuntime.jsx(
2663
+ Button,
2664
+ {
2665
+ title: submitLabel,
2666
+ onPress: handleSubmit,
2667
+ variant: "primary",
2668
+ disabled: selected.length === 0 || submitted
2669
+ }
2670
+ ),
2671
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles13.grid, { gap: t.spacing.sm }], children: opts.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(
2672
+ OptionCard,
2673
+ {
2674
+ opt,
2675
+ isSelected: selected.includes(opt.value),
2676
+ multiSelect,
2677
+ onToggle: toggle
2678
+ },
2679
+ opt.value
2680
+ )) })
2681
+ }
2682
+ );
2683
+ };
2684
+ var CardGridSelectCard = {
2685
+ name: "CardGridSelectCard",
2686
+ description: "Use for VISUAL, icon-led choices shown as a 2-column grid of tappable cards (icon on top, short label beneath). Ideal for 2\u20136 concrete options that each have an obvious icon \u2014 occasions, channels, goals, categories \u2014 e.g. 'What brings you here?' or 'Where did you hear about us?'. Multi-select by default. Every option should carry an `icon`. Use SelectionCard instead when options need descriptions or have no natural icon; use ChipSelectCard for many short word-like tags.",
2687
+ component: React18__default.default.memo(_CardGridSelectCard),
2688
+ propsSchema: schema4,
2689
+ defaultProps: { submitLabel: "Continue", multiSelect: true }
2690
+ };
2691
+ var styles13 = reactNative.StyleSheet.create({
2692
+ grid: { flexDirection: "row", flexWrap: "wrap" },
2693
+ // Two per row: ~47% basis leaves room for the gap, flexGrow fills the remainder exactly.
2694
+ cell: { flexBasis: "47%", flexGrow: 1 },
2695
+ card: { borderWidth: 1.5, alignItems: "flex-start", overflow: "hidden" },
2696
+ selectedOverlay: { borderWidth: 1.5 }
2697
+ });
2698
+ var easeWire7 = reactNative.Easing.bezier(...WIRE_BEZIER);
2699
+ var schema5 = zod.z.object({
1948
2700
  status: zod.z.enum(["success", "warning", "error", "info"]).describe("Status type"),
1949
2701
  title: zod.z.string().describe("Status title"),
1950
2702
  message: zod.z.string().optional().describe("Supporting message"),
@@ -1959,11 +2711,11 @@ var STATUS_ICONS = {
1959
2711
  info: "\u2139"
1960
2712
  };
1961
2713
  var _StatusCard = ({ status, title, message, ctaLabel, onContinue, onPress, onSubmit }) => {
1962
- var _a;
2714
+ var _a2;
1963
2715
  const t = useOnboardingTheme();
1964
2716
  const reduced = useReducedMotion();
1965
- const [submitted, setSubmitted] = React14.useState(false);
1966
- const color = React14.useMemo(() => {
2717
+ const [submitted, setSubmitted] = React18.useState(false);
2718
+ const color = React18.useMemo(() => {
1967
2719
  switch (status) {
1968
2720
  case "success":
1969
2721
  return t.colors.success;
@@ -1975,9 +2727,9 @@ var _StatusCard = ({ status, title, message, ctaLabel, onContinue, onPress, onSu
1975
2727
  return t.colors.info;
1976
2728
  }
1977
2729
  }, [status, t.colors]);
1978
- const popT = React14.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
1979
- const copyT = React14.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
1980
- React14.useEffect(() => {
2730
+ const popT = React18.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
2731
+ const copyT = React18.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
2732
+ React18.useEffect(() => {
1981
2733
  if (reduced) {
1982
2734
  popT.setValue(1);
1983
2735
  copyT.setValue(1);
@@ -1994,7 +2746,7 @@ var _StatusCard = ({ status, title, message, ctaLabel, onContinue, onPress, onSu
1994
2746
  toValue: 1,
1995
2747
  duration: scaledMs(STATUS_COPY_MS),
1996
2748
  delay: scaledMs(STATUS_COPY_STAGGER_MS),
1997
- easing: easeWire6,
2749
+ easing: easeWire7,
1998
2750
  useNativeDriver: true
1999
2751
  })
2000
2752
  ];
@@ -2003,7 +2755,7 @@ var _StatusCard = ({ status, title, message, ctaLabel, onContinue, onPress, onSu
2003
2755
  }, [reduced, popT, copyT]);
2004
2756
  const popScale = popT.interpolate({ inputRange: [0, 1], outputRange: [STATUS_POP_SCALE_FROM, 1] });
2005
2757
  const copyRise = copyT.interpolate({ inputRange: [0, 1], outputRange: [10, 0] });
2006
- const handleContinue = React14.useCallback(() => {
2758
+ const handleContinue = React18.useCallback(() => {
2007
2759
  if (!submitted) {
2008
2760
  setSubmitted(true);
2009
2761
  if (onContinue) onContinue();
@@ -2016,8 +2768,8 @@ var _StatusCard = ({ status, title, message, ctaLabel, onContinue, onPress, onSu
2016
2768
  {
2017
2769
  align: "center",
2018
2770
  footer: ctaLabel ? /* @__PURE__ */ jsxRuntime.jsx(Button, { title: ctaLabel, onPress: handleContinue, variant: "primary", disabled: submitted }) : void 0,
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: [
2771
+ children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles14.center, { gap: t.spacing.sm }], children: [
2772
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles14.titleRow, { gap: t.spacing.sm }], children: [
2021
2773
  /* @__PURE__ */ jsxRuntime.jsx(
2022
2774
  reactNative.Animated.Text,
2023
2775
  {
@@ -2025,7 +2777,7 @@ var _StatusCard = ({ status, title, message, ctaLabel, onContinue, onPress, onSu
2025
2777
  headingStyle(t.fonts),
2026
2778
  { color, opacity: popT, transform: [{ scale: popScale }] }
2027
2779
  ],
2028
- children: (_a = STATUS_ICONS[status]) != null ? _a : "\xB7"
2780
+ children: (_a2 = STATUS_ICONS[status]) != null ? _a2 : "\xB7"
2029
2781
  }
2030
2782
  ),
2031
2783
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -2061,14 +2813,14 @@ var _StatusCard = ({ status, title, message, ctaLabel, onContinue, onPress, onSu
2061
2813
  var StatusCard = {
2062
2814
  name: "StatusCard",
2063
2815
  description: "Use ONLY for real outcomes: booking confirmed, data saved, action completed. NEVER for 'you just viewed X' acknowledgments. Always include ctaLabel so the user can continue after seeing the status.",
2064
- component: React14__default.default.memo(_StatusCard),
2065
- propsSchema: schema4
2816
+ component: React18__default.default.memo(_StatusCard),
2817
+ propsSchema: schema5
2066
2818
  };
2067
- var styles12 = reactNative.StyleSheet.create({
2819
+ var styles14 = reactNative.StyleSheet.create({
2068
2820
  center: { width: "100%", alignItems: "center", justifyContent: "center" },
2069
2821
  titleRow: { flexDirection: "row", alignItems: "center", justifyContent: "center" }
2070
2822
  });
2071
- var schema5 = zod.z.object({
2823
+ var schema6 = zod.z.object({
2072
2824
  label: zod.z.string().describe("What is being counted, e.g. 'Number of days' or 'Travellers'"),
2073
2825
  min: zod.z.number().optional().describe("Minimum value, default 1"),
2074
2826
  max: zod.z.number().optional().describe("Maximum value, default 30"),
@@ -2089,22 +2841,22 @@ var _NumberStepperCard = ({
2089
2841
  onSubmit
2090
2842
  }) => {
2091
2843
  const t = useOnboardingTheme();
2092
- const styles16 = React14.useMemo(() => makeStyles4(t), [t]);
2844
+ const styles18 = React18.useMemo(() => makeStyles4(t), [t]);
2093
2845
  const safeMin = safeNum(min, 1);
2094
2846
  const safeMaxRaw = safeNum(max, 30);
2095
2847
  const safeMax = safeMaxRaw < safeMin ? safeMin : safeMaxRaw;
2096
2848
  const safeStepRaw = safeNum(step, 1);
2097
2849
  const safeStep = safeStepRaw > 0 ? safeStepRaw : 1;
2098
2850
  const safeDefault = safeNum(defaultValue, safeMin);
2099
- const [value, setValue] = React14.useState(Math.min(Math.max(safeDefault, safeMin), safeMax));
2100
- const [submitted, setSubmitted] = React14.useState(false);
2101
- const handleDecrement = React14.useCallback(() => {
2851
+ const [value, setValue] = React18.useState(Math.min(Math.max(safeDefault, safeMin), safeMax));
2852
+ const [submitted, setSubmitted] = React18.useState(false);
2853
+ const handleDecrement = React18.useCallback(() => {
2102
2854
  if (!submitted) setValue((v) => Math.max(v - safeStep, safeMin));
2103
2855
  }, [submitted, safeStep, safeMin]);
2104
- const handleIncrement = React14.useCallback(() => {
2856
+ const handleIncrement = React18.useCallback(() => {
2105
2857
  if (!submitted) setValue((v) => Math.min(v + safeStep, safeMax));
2106
2858
  }, [submitted, safeStep, safeMax]);
2107
- const handleSubmit = React14.useCallback(() => {
2859
+ const handleSubmit = React18.useCallback(() => {
2108
2860
  if (!submitted) {
2109
2861
  setSubmitted(true);
2110
2862
  onSubmit == null ? void 0 : onSubmit(value);
@@ -2113,7 +2865,7 @@ var _NumberStepperCard = ({
2113
2865
  const atMin = value <= safeMin;
2114
2866
  const atMax = value >= safeMax;
2115
2867
  const stepBtnStyle = (disabled) => [
2116
- styles16.stepBtn,
2868
+ styles18.stepBtn,
2117
2869
  { borderRadius: t.radius.full, backgroundColor: t.colors.background, borderColor: disabled ? t.colors.border : t.colors.primary }
2118
2870
  ];
2119
2871
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -2122,10 +2874,10 @@ var _NumberStepperCard = ({
2122
2874
  title: label,
2123
2875
  align: "center",
2124
2876
  footer: /* @__PURE__ */ jsxRuntime.jsx(Button, { title: submitLabel, onPress: handleSubmit, variant: "primary", disabled: submitted }),
2125
- children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles16.wrap, children: [
2126
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles16.stepper, { gap: t.spacing.lg }], children: [
2877
+ children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles18.wrap, children: [
2878
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles18.stepper, { gap: t.spacing.lg }], children: [
2127
2879
  /* @__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" }) }),
2128
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles16.valueBox, children: [
2880
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles18.valueBox, children: [
2129
2881
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [headingStyle(t.fonts), { color: t.colors.primary }], children: String(value) }),
2130
2882
  unit ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [captionStyle(t.fonts), { color: t.colors.textMuted }], children: unit }) : null
2131
2883
  ] }),
@@ -2139,8 +2891,8 @@ var _NumberStepperCard = ({
2139
2891
  var NumberStepperCard = {
2140
2892
  name: "NumberStepperCard",
2141
2893
  description: "Use for any bounded numeric input: days, people, portions, budget tiers, ratings. Best for ranges 1\u201399. Set unit (e.g. 'days', 'people') for clarity.",
2142
- component: React14__default.default.memo(_NumberStepperCard),
2143
- propsSchema: schema5,
2894
+ component: React18__default.default.memo(_NumberStepperCard),
2895
+ propsSchema: schema6,
2144
2896
  defaultProps: { min: 1, max: 30, defaultValue: 1, step: 1, submitLabel: "Confirm" }
2145
2897
  };
2146
2898
  function makeStyles4(t) {
@@ -2151,9 +2903,9 @@ function makeStyles4(t) {
2151
2903
  valueBox: { alignItems: "center", minWidth: 80 }
2152
2904
  });
2153
2905
  }
2154
- var easeWire7 = reactNative.Easing.bezier(...WIRE_BEZIER);
2906
+ var easeWire8 = reactNative.Easing.bezier(...WIRE_BEZIER);
2155
2907
  var RISE_PX = 10;
2156
- var schema6 = zod.z.object({
2908
+ var schema7 = zod.z.object({
2157
2909
  title: zod.z.string().describe("Short, warm headline for the value/momentum moment"),
2158
2910
  body: zod.z.string().optional().describe("One or two supporting lines that reflect the user's answers back and build momentum"),
2159
2911
  items: zod.z.array(zod.z.string()).max(4).optional().describe(
@@ -2177,9 +2929,9 @@ var _WorkItem = ({
2177
2929
  reduced
2178
2930
  }) => {
2179
2931
  const t = useOnboardingTheme();
2180
- const rowT = React14.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
2181
- const checkT = React14.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
2182
- React14.useEffect(() => {
2932
+ const rowT = React18.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
2933
+ const checkT = React18.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
2934
+ React18.useEffect(() => {
2183
2935
  if (reduced) {
2184
2936
  rowT.setValue(1);
2185
2937
  checkT.setValue(1);
@@ -2190,7 +2942,7 @@ var _WorkItem = ({
2190
2942
  toValue: 1,
2191
2943
  duration: scaledMs(INTERSTITIAL_ITEM_MS),
2192
2944
  delay: scaledMs(interstitialItemDelay(index)),
2193
- easing: easeWire7,
2945
+ easing: easeWire8,
2194
2946
  useNativeDriver: true
2195
2947
  }),
2196
2948
  reactNative.Animated.spring(checkT, {
@@ -2212,20 +2964,20 @@ var _WorkItem = ({
2212
2964
  return /* @__PURE__ */ jsxRuntime.jsxs(
2213
2965
  reactNative.Animated.View,
2214
2966
  {
2215
- style: [styles13.itemRow, { gap: t.spacing.sm + t.spacing.xs, opacity: rowT, transform: [{ translateY: rise }] }],
2967
+ style: [styles15.itemRow, { gap: t.spacing.sm + t.spacing.xs, opacity: rowT, transform: [{ translateY: rise }] }],
2216
2968
  children: [
2217
2969
  /* @__PURE__ */ jsxRuntime.jsx(
2218
2970
  reactNative.View,
2219
2971
  {
2220
2972
  style: [
2221
- styles13.itemBadge,
2973
+ styles15.itemBadge,
2222
2974
  { backgroundColor: t.colors.primarySoft, borderRadius: t.radius.full }
2223
2975
  ],
2224
2976
  children: /* @__PURE__ */ jsxRuntime.jsx(
2225
2977
  reactNative.Animated.Text,
2226
2978
  {
2227
2979
  style: [
2228
- styles13.itemCheck,
2980
+ styles15.itemCheck,
2229
2981
  { color: t.colors.primary, opacity: checkT, transform: [{ scale: checkScale }] }
2230
2982
  ],
2231
2983
  children: "\u2713"
@@ -2233,12 +2985,12 @@ var _WorkItem = ({
2233
2985
  )
2234
2986
  }
2235
2987
  ),
2236
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [bodyStyle(t.fonts), styles13.itemText, { color: t.colors.text }], children: text })
2988
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [bodyStyle(t.fonts), styles15.itemText, { color: t.colors.text }], children: text })
2237
2989
  ]
2238
2990
  }
2239
2991
  );
2240
2992
  };
2241
- var WorkItem = React14__default.default.memo(_WorkItem);
2993
+ var WorkItem = React18__default.default.memo(_WorkItem);
2242
2994
  var _InterstitialCard = ({
2243
2995
  title,
2244
2996
  body,
@@ -2254,17 +3006,17 @@ var _InterstitialCard = ({
2254
3006
  const reduced = useReducedMotion();
2255
3007
  const node = useIllustration(illustration);
2256
3008
  const fallbackNode = useIllustration(illustrationFallback);
2257
- const [submitted, setSubmitted] = React14.useState(false);
2258
- const [imgFailed, setImgFailed] = React14.useState(false);
2259
- const [canAdvance, setCanAdvance] = React14.useState(false);
2260
- React14.useEffect(() => {
3009
+ const [submitted, setSubmitted] = React18.useState(false);
3010
+ const [imgFailed, setImgFailed] = React18.useState(false);
3011
+ const [canAdvance, setCanAdvance] = React18.useState(false);
3012
+ React18.useEffect(() => {
2261
3013
  const timer = setTimeout(() => setCanAdvance(true), MIN_DISPLAY_MS);
2262
3014
  return () => clearTimeout(timer);
2263
3015
  }, []);
2264
- const artT = React14.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
2265
- const titleT = React14.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
2266
- const bodyT = React14.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
2267
- React14.useEffect(() => {
3016
+ const artT = React18.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
3017
+ const titleT = React18.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
3018
+ const bodyT = React18.useRef(new reactNative.Animated.Value(reduced ? 1 : 0)).current;
3019
+ React18.useEffect(() => {
2268
3020
  if (reduced) {
2269
3021
  artT.setValue(1);
2270
3022
  titleT.setValue(1);
@@ -2275,7 +3027,7 @@ var _InterstitialCard = ({
2275
3027
  toValue: 1,
2276
3028
  duration: scaledMs(INTERSTITIAL_HEAD_MS),
2277
3029
  delay,
2278
- easing: easeWire7,
3030
+ easing: easeWire8,
2279
3031
  useNativeDriver: true
2280
3032
  });
2281
3033
  const anims = [
@@ -2290,7 +3042,7 @@ var _InterstitialCard = ({
2290
3042
  opacity: value,
2291
3043
  transform: [{ translateY: value.interpolate({ inputRange: [0, 1], outputRange: [RISE_PX, 0] }) }]
2292
3044
  });
2293
- const handleContinue = React14.useCallback(() => {
3045
+ const handleContinue = React18.useCallback(() => {
2294
3046
  if (submitted || !canAdvance) return;
2295
3047
  setSubmitted(true);
2296
3048
  if (onSubmit) onSubmit("continue");
@@ -2311,18 +3063,18 @@ var _InterstitialCard = ({
2311
3063
  disabled: submitted || !canAdvance
2312
3064
  }
2313
3065
  ),
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(
3066
+ children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles15.center, { gap: t.spacing.md }], children: [
3067
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: [styles15.fullWidth, riseStyle(artT)], children: showImage ? /* @__PURE__ */ jsxRuntime.jsx(
2316
3068
  reactNative.Image,
2317
3069
  {
2318
3070
  source: { uri: imageUrl },
2319
- style: styles13.image,
3071
+ style: styles15.image,
2320
3072
  resizeMode: "contain",
2321
3073
  onError: () => setImgFailed(true)
2322
3074
  }
2323
- ) : art ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles13.art, children: art }) : null }),
3075
+ ) : art ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles15.art, children: art }) : null }),
2324
3076
  /* @__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 }) }),
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
3077
+ (items == null ? void 0 : items.length) ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles15.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
2326
3078
  ] })
2327
3079
  }
2328
3080
  );
@@ -2330,11 +3082,11 @@ var _InterstitialCard = ({
2330
3082
  var InterstitialCard = {
2331
3083
  name: "InterstitialCard",
2332
3084
  description: "Use ONCE mid-flow (never first, never last) as a momentum/value screen between questions \u2014 an illustration + a warm line that reflects answers back, like Duolingo/Cal-AI. NOT a question; the user just taps Continue. Set `illustration` to an app-registered artwork name. Prefer `items` (2-3 short ticked lines, each reflecting a real answer) when you have the signal. Skip it if you don't have enough signal to make the line specific.",
2333
- component: React14__default.default.memo(_InterstitialCard),
2334
- propsSchema: schema6,
3085
+ component: React18__default.default.memo(_InterstitialCard),
3086
+ propsSchema: schema7,
2335
3087
  defaultProps: { ctaLabel: "Continue", illustrationFallback: "momentum" }
2336
3088
  };
2337
- var styles13 = reactNative.StyleSheet.create({
3089
+ var styles15 = reactNative.StyleSheet.create({
2338
3090
  center: { width: "100%", alignItems: "center", justifyContent: "center" },
2339
3091
  fullWidth: { width: "100%", alignItems: "center" },
2340
3092
  art: { alignItems: "center", justifyContent: "center" },
@@ -2351,6 +3103,7 @@ var onboardingComponents = [
2351
3103
  ChipSelectCard,
2352
3104
  TextInputCard,
2353
3105
  SelectionCard,
3106
+ CardGridSelectCard,
2354
3107
  StatusCard,
2355
3108
  NumberStepperCard,
2356
3109
  InterstitialCard
@@ -2362,15 +3115,22 @@ var coerceVersion = (value) => {
2362
3115
  const trimmed = value.trim();
2363
3116
  return trimmed.length > 0 ? trimmed : void 0;
2364
3117
  };
2365
- var runtimeRequire = (moduleName) => {
3118
+ var runtimeRequire2 = (moduleName) => {
3119
+ if (typeof __require !== "function") return void 0;
2366
3120
  try {
2367
- if (typeof __require !== "function") return void 0;
2368
- return __require(moduleName);
3121
+ switch (moduleName) {
3122
+ case "expo-constants":
3123
+ return init_Constants(), __toCommonJS(Constants_exports);
3124
+ case "expo-application":
3125
+ return __require("expo-application");
3126
+ default:
3127
+ return void 0;
3128
+ }
2369
3129
  } catch {
2370
3130
  return void 0;
2371
3131
  }
2372
3132
  };
2373
- var interop = (mod) => {
3133
+ var interop2 = (mod) => {
2374
3134
  if (!mod || typeof mod !== "object") return void 0;
2375
3135
  const def = mod.default;
2376
3136
  if (def && typeof def === "object") return def;
@@ -2378,21 +3138,21 @@ var interop = (mod) => {
2378
3138
  };
2379
3139
  var safeInterop = (requireModule, moduleName) => {
2380
3140
  try {
2381
- return interop(requireModule(moduleName));
3141
+ return interop2(requireModule(moduleName));
2382
3142
  } catch {
2383
3143
  return void 0;
2384
3144
  }
2385
3145
  };
2386
- var detectAppVersion = (requireModule = runtimeRequire) => {
3146
+ var detectAppVersion = (requireModule = runtimeRequire2) => {
2387
3147
  try {
2388
- const constants = safeInterop(requireModule, "expo-constants");
2389
- if (constants) {
2390
- const expoConfig = constants.expoConfig;
3148
+ const constants2 = safeInterop(requireModule, "expo-constants");
3149
+ if (constants2) {
3150
+ const expoConfig = constants2.expoConfig;
2391
3151
  if (expoConfig && typeof expoConfig === "object") {
2392
3152
  const fromExpoConfig = coerceVersion(expoConfig.version);
2393
3153
  if (fromExpoConfig) return fromExpoConfig;
2394
3154
  }
2395
- const fromNative = coerceVersion(constants.nativeAppVersion);
3155
+ const fromNative = coerceVersion(constants2.nativeAppVersion);
2396
3156
  if (fromNative) return fromNative;
2397
3157
  }
2398
3158
  const application = safeInterop(requireModule, "expo-application");
@@ -2405,6 +3165,48 @@ var detectAppVersion = (requireModule = runtimeRequire) => {
2405
3165
  return void 0;
2406
3166
  };
2407
3167
 
3168
+ // src/device/deviceModel.ts
3169
+ var coerceModel = (value) => {
3170
+ if (typeof value !== "string") return void 0;
3171
+ const trimmed = value.trim();
3172
+ return trimmed.length > 0 ? trimmed : void 0;
3173
+ };
3174
+ var runtimeRequire3 = (moduleName) => {
3175
+ if (moduleName !== "expo-device") return void 0;
3176
+ if (typeof __require !== "function") return void 0;
3177
+ try {
3178
+ return __require("expo-device");
3179
+ } catch {
3180
+ return void 0;
3181
+ }
3182
+ };
3183
+ var interop3 = (mod) => {
3184
+ if (!mod || typeof mod !== "object") return void 0;
3185
+ const def = mod.default;
3186
+ if (def && typeof def === "object") return def;
3187
+ return mod;
3188
+ };
3189
+ var safeInterop2 = (requireModule, moduleName) => {
3190
+ try {
3191
+ return interop3(requireModule(moduleName));
3192
+ } catch {
3193
+ return void 0;
3194
+ }
3195
+ };
3196
+ var detectNativeModel = (requireModule = runtimeRequire3) => {
3197
+ try {
3198
+ const device = safeInterop2(requireModule, "expo-device");
3199
+ if (device) {
3200
+ const modelName = coerceModel(device.modelName);
3201
+ if (modelName) return modelName;
3202
+ const modelId = coerceModel(device.modelId);
3203
+ if (modelId) return modelId;
3204
+ }
3205
+ } catch {
3206
+ }
3207
+ return void 0;
3208
+ };
3209
+
2408
3210
  // src/device/deviceContext.ts
2409
3211
  var deriveFormFactor = (iosIdiom, width, height) => {
2410
3212
  if (iosIdiom === "pad") return "tablet";
@@ -2415,7 +3217,7 @@ var deriveFormFactor = (iosIdiom, width, height) => {
2415
3217
  return void 0;
2416
3218
  };
2417
3219
  var collectDeviceContext = () => {
2418
- var _a;
3220
+ var _a2;
2419
3221
  const ctx = { platform: reactNative.Platform.OS };
2420
3222
  try {
2421
3223
  const version = reactNative.Platform.Version;
@@ -2424,26 +3226,26 @@ var collectDeviceContext = () => {
2424
3226
  }
2425
3227
  } catch {
2426
3228
  }
2427
- let constants = {};
3229
+ let constants2 = {};
2428
3230
  try {
2429
- constants = (_a = reactNative.Platform.constants) != null ? _a : {};
3231
+ constants2 = (_a2 = reactNative.Platform.constants) != null ? _a2 : {};
2430
3232
  } catch {
2431
- constants = {};
3233
+ constants2 = {};
2432
3234
  }
2433
3235
  let iosIdiom;
2434
3236
  try {
2435
3237
  if (reactNative.Platform.OS === "android") {
2436
- const brand = constants.Brand;
2437
- const model = constants.Model;
2438
- const release = constants.Release;
3238
+ const brand = constants2.Brand;
3239
+ const model = constants2.Model;
3240
+ const release = constants2.Release;
2439
3241
  if (typeof brand === "string" && brand) ctx.brand = brand;
2440
3242
  if (typeof model === "string" && model) ctx.model = model;
2441
3243
  if (release !== void 0 && release !== null && String(release)) {
2442
3244
  ctx.osVersion = String(release);
2443
3245
  }
2444
3246
  } else if (reactNative.Platform.OS === "ios") {
2445
- const osVersion = constants.osVersion;
2446
- const idiom = constants.interfaceIdiom;
3247
+ const osVersion = constants2.osVersion;
3248
+ const idiom = constants2.interfaceIdiom;
2447
3249
  if (osVersion !== void 0 && osVersion !== null && String(osVersion)) {
2448
3250
  ctx.osVersion = String(osVersion);
2449
3251
  }
@@ -2451,6 +3253,8 @@ var collectDeviceContext = () => {
2451
3253
  ctx.interfaceIdiom = idiom;
2452
3254
  iosIdiom = idiom;
2453
3255
  }
3256
+ const iosModel = detectNativeModel();
3257
+ if (iosModel) ctx.model = iosModel;
2454
3258
  }
2455
3259
  } catch {
2456
3260
  }
@@ -2557,9 +3361,9 @@ var sanitizeUserId = (raw) => {
2557
3361
  return trimmed.length > USER_ID_MAX_LENGTH ? trimmed.slice(0, USER_ID_MAX_LENGTH) : trimmed;
2558
3362
  };
2559
3363
  var identifyOnboarding = async (opts) => {
2560
- var _a, _b, _c;
3364
+ var _a2, _b, _c;
2561
3365
  const userId = sanitizeUserId(opts.userId);
2562
- if (!userId || !((_a = opts.config) == null ? void 0 : _a.serverUrl)) return false;
3366
+ if (!userId || !((_a2 = opts.config) == null ? void 0 : _a2.serverUrl)) return false;
2563
3367
  let contextId = ((_b = opts.contextId) == null ? void 0 : _b.trim()) || void 0;
2564
3368
  if (!contextId && opts.storage) {
2565
3369
  const key = (_c = opts.persistKey) != null ? _c : opts.appId ? sessionStorageKey(opts.appId) : void 0;
@@ -2581,6 +3385,7 @@ var WireOnboarding = ({
2581
3385
  theme,
2582
3386
  components,
2583
3387
  illustrations,
3388
+ icons,
2584
3389
  validators,
2585
3390
  onComplete,
2586
3391
  onSkip,
@@ -2598,26 +3403,26 @@ var WireOnboarding = ({
2598
3403
  userContext,
2599
3404
  userId
2600
3405
  }) => {
2601
- var _a, _b, _c;
2602
- const boundUserId = React14.useMemo(() => sanitizeUserId(userId), [userId]);
2603
- const device = React14.useMemo(() => {
3406
+ var _a2, _b, _c;
3407
+ const boundUserId = React18.useMemo(() => sanitizeUserId(userId), [userId]);
3408
+ const device = React18.useMemo(() => {
2604
3409
  const collected = collectDeviceContext();
2605
3410
  return config.appVersion ? { ...collected, appVersion: config.appVersion } : collected;
2606
3411
  }, [config.appVersion]);
2607
3412
  const userContextKey = userContext ? JSON.stringify(userContext) : "";
2608
- const userContextStable = React14.useMemo(
3413
+ const userContextStable = React18.useMemo(
2609
3414
  () => userContextKey ? JSON.parse(userContextKey) : void 0,
2610
3415
  [userContextKey]
2611
3416
  );
2612
- const clientContext = React14.useMemo(
3417
+ const clientContext = React18.useMemo(
2613
3418
  () => ({ device, userContext: userContextStable, userId: boundUserId }),
2614
3419
  [device, userContextStable, boundUserId]
2615
3420
  );
2616
- const [session, setSession] = React14.useState(
3421
+ const [session, setSession] = React18.useState(
2617
3422
  () => storage ? null : { id: makeSessionId(), resumed: false }
2618
3423
  );
2619
3424
  const storageKey = persistKey != null ? persistKey : sessionStorageKey(config.appId);
2620
- React14.useEffect(() => {
3425
+ React18.useEffect(() => {
2621
3426
  if (!storage || session) return;
2622
3427
  let cancelled = false;
2623
3428
  void loadPersistedSession(storage, storageKey, sessionTtlMs).then((loaded) => {
@@ -2627,20 +3432,20 @@ var WireOnboarding = ({
2627
3432
  cancelled = true;
2628
3433
  };
2629
3434
  }, [storage, storageKey, sessionTtlMs, session]);
2630
- const handleComplete = React14.useCallback(
3435
+ const handleComplete = React18.useCallback(
2631
3436
  (result) => {
2632
3437
  if (storage) clearPersistedSession(storage, storageKey);
2633
3438
  onComplete(result);
2634
3439
  },
2635
3440
  [storage, storageKey, onComplete]
2636
3441
  );
2637
- const sessionId = (_a = session == null ? void 0 : session.id) != null ? _a : "";
2638
- const startupUserIdRef = React14.useRef(boundUserId);
3442
+ const sessionId = (_a2 = session == null ? void 0 : session.id) != null ? _a2 : "";
3443
+ const startupUserIdRef = React18.useRef(boundUserId);
2639
3444
  const metadataKey = config.metadata ? JSON.stringify(config.metadata) : "";
2640
- const metadataStable = React14.useMemo(() => metadataKey ? JSON.parse(metadataKey) : void 0, [metadataKey]);
3445
+ const metadataStable = React18.useMemo(() => metadataKey ? JSON.parse(metadataKey) : void 0, [metadataKey]);
2641
3446
  const componentNamesKey = (components != null ? components : onboardingComponents).map((c) => c.name).join(",");
2642
- const componentsStable = React14.useMemo(() => components != null ? components : onboardingComponents, [componentNamesKey]);
2643
- const llm = React14.useMemo(() => {
3447
+ const componentsStable = React18.useMemo(() => components != null ? components : onboardingComponents, [componentNamesKey]);
3448
+ const llm = React18.useMemo(() => {
2644
3449
  const baseUrl = config.serverUrl.replace(/\/$/, "");
2645
3450
  return {
2646
3451
  provider: "a2a",
@@ -2668,13 +3473,13 @@ var WireOnboarding = ({
2668
3473
  timeoutMs: 6e4
2669
3474
  };
2670
3475
  }, [config.serverUrl, config.appId, config.apiKey, metadataStable, sessionId, componentsStable, device, userContextStable]);
2671
- const reportTarget = React14.useMemo(
3476
+ const reportTarget = React18.useMemo(
2672
3477
  () => ({ serverUrl: config.serverUrl, apiKey: config.apiKey }),
2673
3478
  [config.serverUrl, config.apiKey]
2674
3479
  );
2675
- const identifiedRef = React14.useRef(void 0);
2676
- const identifySeededRef = React14.useRef(false);
2677
- React14.useEffect(() => {
3480
+ const identifiedRef = React18.useRef(void 0);
3481
+ const identifySeededRef = React18.useRef(false);
3482
+ React18.useEffect(() => {
2678
3483
  if (!session || !sessionId) return;
2679
3484
  if (!identifySeededRef.current) {
2680
3485
  identifySeededRef.current = true;
@@ -2698,7 +3503,7 @@ var WireOnboarding = ({
2698
3503
  }
2699
3504
  ) });
2700
3505
  }
2701
- return /* @__PURE__ */ jsxRuntime.jsx(OnboardingThemeProvider, { theme, children: /* @__PURE__ */ jsxRuntime.jsx(IllustrationProvider, { registry: { ...defaultIllustrations, ...illustrations }, children: /* @__PURE__ */ jsxRuntime.jsx(wireaiRn.WireAIProvider, { llm, components: cards, children: /* @__PURE__ */ jsxRuntime.jsx(
3506
+ return /* @__PURE__ */ jsxRuntime.jsx(OnboardingThemeProvider, { theme, children: /* @__PURE__ */ jsxRuntime.jsx(IllustrationProvider, { registry: { ...defaultIllustrations, ...illustrations }, children: /* @__PURE__ */ jsxRuntime.jsx(IconRegistryProvider, { registry: icons, children: /* @__PURE__ */ jsxRuntime.jsx(wireaiRn.WireAIProvider, { llm, components: cards, children: /* @__PURE__ */ jsxRuntime.jsx(
2702
3507
  OnboardingFlow,
2703
3508
  {
2704
3509
  validators,
@@ -2717,7 +3522,7 @@ var WireOnboarding = ({
2717
3522
  resumed: session.resumed,
2718
3523
  clientContext
2719
3524
  }
2720
- ) }) }) });
3525
+ ) }) }) }) });
2721
3526
  };
2722
3527
  function DemoOnboarding({
2723
3528
  config,
@@ -2729,16 +3534,16 @@ function DemoOnboarding({
2729
3534
  onComplete,
2730
3535
  renderTrigger
2731
3536
  }) {
2732
- const [open, setOpen] = React14.useState(false);
2733
- const [runId, setRunId] = React14.useState(0);
2734
- const t = React14.useMemo(() => mergeTheme(theme != null ? theme : {}), [theme]);
2735
- const styles16 = React14.useMemo(() => makeStyles5(t), [t]);
2736
- const openDemo = React14.useCallback(() => {
3537
+ const [open, setOpen] = React18.useState(false);
3538
+ const [runId, setRunId] = React18.useState(0);
3539
+ const t = React18.useMemo(() => mergeTheme(theme != null ? theme : {}), [theme]);
3540
+ const styles18 = React18.useMemo(() => makeStyles5(t), [t]);
3541
+ const openDemo = React18.useCallback(() => {
2737
3542
  setRunId((n) => n + 1);
2738
3543
  setOpen(true);
2739
3544
  }, []);
2740
- const close = React14.useCallback(() => setOpen(false), []);
2741
- const finish = React14.useCallback(
3545
+ const close = React18.useCallback(() => setOpen(false), []);
3546
+ const finish = React18.useCallback(
2742
3547
  (result) => {
2743
3548
  onComplete == null ? void 0 : onComplete(result);
2744
3549
  setOpen(false);
@@ -2746,7 +3551,7 @@ function DemoOnboarding({
2746
3551
  [onComplete]
2747
3552
  );
2748
3553
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
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 }) }),
3554
+ renderTrigger ? renderTrigger(openDemo) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { onPress: openDemo, style: styles18.trigger, accessibilityRole: "button", children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles18.triggerText, children: label }) }),
2750
3555
  /* @__PURE__ */ jsxRuntime.jsx(
2751
3556
  reactNative.Modal,
2752
3557
  {
@@ -2754,7 +3559,7 @@ function DemoOnboarding({
2754
3559
  animationType: "slide",
2755
3560
  presentationStyle: "fullScreen",
2756
3561
  onRequestClose: close,
2757
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles16.modal, children: config ? /* @__PURE__ */ jsxRuntime.jsx(
3562
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles18.modal, children: config ? /* @__PURE__ */ jsxRuntime.jsx(
2758
3563
  WireOnboarding,
2759
3564
  {
2760
3565
  config,
@@ -2767,10 +3572,10 @@ function DemoOnboarding({
2767
3572
  onError: close
2768
3573
  },
2769
3574
  runId
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" }) })
3575
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles18.notice, children: [
3576
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles18.noticeTitle, children: "Wire AI not configured" }),
3577
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles18.noticeBody, children: "Set the Wire AI key + server URL (e.g. via wireConfigFromEnv) to demo the AI onboarding here." }),
3578
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { onPress: close, style: styles18.trigger, accessibilityRole: "button", children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles18.triggerText, children: "Close" }) })
2774
3579
  ] }) })
2775
3580
  }
2776
3581
  )
@@ -2849,13 +3654,13 @@ var _DoneBlock = ({
2849
3654
  message = "Personalizing your experience\u2026"
2850
3655
  }) => {
2851
3656
  const t = useOnboardingTheme();
2852
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles14.center, { gap: t.spacing.sm, padding: t.spacing.lg }], children: [
3657
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [styles16.center, { gap: t.spacing.sm, padding: t.spacing.lg }], children: [
2853
3658
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [headingStyle(t.fonts), { color: t.colors.success, textAlign: "center" }], children: title }),
2854
3659
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [bodyStyle(t.fonts), { color: t.colors.textMuted, textAlign: "center" }], children: message })
2855
3660
  ] });
2856
3661
  };
2857
- var DoneBlock = React14__default.default.memo(_DoneBlock);
2858
- var styles14 = reactNative.StyleSheet.create({
3662
+ var DoneBlock = React18__default.default.memo(_DoneBlock);
3663
+ var styles16 = reactNative.StyleSheet.create({
2859
3664
  center: { flex: 1, alignItems: "center", justifyContent: "center" }
2860
3665
  });
2861
3666
 
@@ -2870,13 +3675,13 @@ var CENTERED_MODAL_ANIM = {
2870
3675
  /** Peak dim of the backdrop at progress 1. */
2871
3676
  backdropOpacity: 0.55
2872
3677
  };
2873
- var _CenteredModal = React14.forwardRef(
3678
+ var _CenteredModal = React18.forwardRef(
2874
3679
  ({ theme, dismissible = true, onDismiss, children }, ref) => {
2875
- const progress = React14.useRef(new reactNative.Animated.Value(0)).current;
2876
- const [open, setOpen] = React14.useState(true);
2877
- const closingRef = React14.useRef(false);
3680
+ const progress = React18.useRef(new reactNative.Animated.Value(0)).current;
3681
+ const [open, setOpen] = React18.useState(true);
3682
+ const closingRef = React18.useRef(false);
2878
3683
  const reduced = useReducedMotion();
2879
- React14.useEffect(() => {
3684
+ React18.useEffect(() => {
2880
3685
  const anim = reduced ? reactNative.Animated.timing(progress, {
2881
3686
  toValue: 1,
2882
3687
  duration: REDUCED_FADE_MS,
@@ -2890,7 +3695,7 @@ var _CenteredModal = React14.forwardRef(
2890
3695
  anim.start();
2891
3696
  return () => anim.stop();
2892
3697
  }, [progress, reduced]);
2893
- const close = React14.useCallback(() => {
3698
+ const close = React18.useCallback(() => {
2894
3699
  if (closingRef.current) return;
2895
3700
  closingRef.current = true;
2896
3701
  reactNative.Animated.timing(progress, {
@@ -2903,15 +3708,15 @@ var _CenteredModal = React14.forwardRef(
2903
3708
  onDismiss();
2904
3709
  });
2905
3710
  }, [progress, onDismiss, reduced]);
2906
- React14.useImperativeHandle(ref, () => ({ close }), [close]);
2907
- React14.useEffect(() => {
3711
+ React18.useImperativeHandle(ref, () => ({ close }), [close]);
3712
+ React18.useEffect(() => {
2908
3713
  const sub = reactNative.BackHandler.addEventListener("hardwareBackPress", () => {
2909
3714
  if (dismissible) close();
2910
3715
  return true;
2911
3716
  });
2912
3717
  return () => sub.remove();
2913
3718
  }, [dismissible, close]);
2914
- const onBackdrop = React14.useCallback(() => {
3719
+ const onBackdrop = React18.useCallback(() => {
2915
3720
  if (dismissible) close();
2916
3721
  }, [dismissible, close]);
2917
3722
  const backdropOpacity = progress.interpolate({
@@ -2934,25 +3739,25 @@ var _CenteredModal = React14.forwardRef(
2934
3739
  /* @__PURE__ */ jsxRuntime.jsx(
2935
3740
  reactNative.Animated.View,
2936
3741
  {
2937
- style: [styles15.backdrop, { opacity: backdropOpacity }],
3742
+ style: [styles17.backdrop, { opacity: backdropOpacity }],
2938
3743
  pointerEvents: "none"
2939
3744
  }
2940
3745
  ),
2941
3746
  /* @__PURE__ */ jsxRuntime.jsx(
2942
3747
  reactNative.Pressable,
2943
3748
  {
2944
- style: styles15.fill,
3749
+ style: styles17.fill,
2945
3750
  onPress: onBackdrop,
2946
3751
  accessibilityRole: "button",
2947
3752
  accessibilityLabel: "Dismiss",
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(
3753
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNativeSafeAreaContext.SafeAreaView, { style: styles17.center, pointerEvents: "box-none", children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { onPress: () => {
3754
+ }, style: styles17.cardWrap, children: /* @__PURE__ */ jsxRuntime.jsx(
2950
3755
  reactNative.Animated.View,
2951
3756
  {
2952
3757
  accessibilityViewIsModal: true,
2953
3758
  accessibilityRole: "alert",
2954
3759
  style: [
2955
- styles15.card,
3760
+ styles17.card,
2956
3761
  {
2957
3762
  backgroundColor: theme.colors.surface,
2958
3763
  borderRadius: theme.radius.lg,
@@ -2973,8 +3778,8 @@ var _CenteredModal = React14.forwardRef(
2973
3778
  }
2974
3779
  );
2975
3780
  _CenteredModal.displayName = "CenteredModal";
2976
- var CenteredModal = React14__default.default.memo(_CenteredModal);
2977
- var styles15 = reactNative.StyleSheet.create({
3781
+ var CenteredModal = React18__default.default.memo(_CenteredModal);
3782
+ var styles17 = reactNative.StyleSheet.create({
2978
3783
  fill: { flex: 1 },
2979
3784
  backdrop: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0, backgroundColor: "#000" },
2980
3785
  center: { flex: 1, alignItems: "center", justifyContent: "center", padding: 24 },
@@ -3007,10 +3812,10 @@ var readEnabled = (raw) => {
3007
3812
  return { enabled: true };
3008
3813
  };
3009
3814
  var parseWireFeatures = (raw) => {
3010
- var _a;
3815
+ var _a2;
3011
3816
  if (!raw || typeof raw !== "object" || Array.isArray(raw)) return defaultWireFeatures;
3012
3817
  const src = raw;
3013
- const modeRaw = (_a = src.onboarding) == null ? void 0 : _a.mode;
3818
+ const modeRaw = (_a2 = src.onboarding) == null ? void 0 : _a2.mode;
3014
3819
  const mode = typeof modeRaw === "string" && VALID_MODES.includes(modeRaw) ? modeRaw : "ai";
3015
3820
  return {
3016
3821
  coachmarks: readEnabled(src.coachmarks),
@@ -3067,10 +3872,10 @@ var writeCachedFeatures = (storage, key, features) => {
3067
3872
  // src/features/fetchWireFeatures.ts
3068
3873
  var DEFAULT_TIMEOUT_MS = 4e3;
3069
3874
  var failOpen = async (storage, key) => {
3070
- var _a;
3875
+ var _a2;
3071
3876
  if (!storage) return defaultWireFeatures;
3072
- const cached = await readCachedFeatures(storage, key);
3073
- return (_a = cached == null ? void 0 : cached.features) != null ? _a : defaultWireFeatures;
3877
+ const cached2 = await readCachedFeatures(storage, key);
3878
+ return (_a2 = cached2 == null ? void 0 : cached2.features) != null ? _a2 : defaultWireFeatures;
3074
3879
  };
3075
3880
  var fetchWithTimeout = async (url, apiKey, timeoutMs) => {
3076
3881
  const controller = typeof AbortController !== "undefined" ? new AbortController() : void 0;
@@ -3103,16 +3908,16 @@ var fetchWireFeatures = async (config) => {
3103
3908
  }
3104
3909
  };
3105
3910
  var useStableValue = (value, isEqual) => {
3106
- const ref = React14.useRef(value);
3911
+ const ref = React18.useRef(value);
3107
3912
  if (!isEqual(ref.current, value)) ref.current = value;
3108
3913
  return ref.current;
3109
3914
  };
3110
3915
  var sameFetchKey = (a, b) => (a == null ? void 0 : a.serverUrl) === (b == null ? void 0 : b.serverUrl) && (a == null ? void 0 : a.apiKey) === (b == null ? void 0 : b.apiKey) && (a == null ? void 0 : a.appId) === (b == null ? void 0 : b.appId);
3111
3916
  var useWireFeatures = (config) => {
3112
3917
  const stableConfig = useStableValue(config, sameFetchKey);
3113
- const [flags, setFlags] = React14.useState(defaultWireFeatures);
3918
+ const [flags, setFlags] = React18.useState(defaultWireFeatures);
3114
3919
  const canFetch = !!(stableConfig == null ? void 0 : stableConfig.serverUrl) && !!(stableConfig == null ? void 0 : stableConfig.apiKey);
3115
- React14.useEffect(() => {
3920
+ React18.useEffect(() => {
3116
3921
  if (!canFetch) {
3117
3922
  setFlags((prev) => featuresEqual(prev, defaultWireFeatures) ? prev : defaultWireFeatures);
3118
3923
  return;
@@ -3131,7 +3936,7 @@ var useWireFeatures = (config) => {
3131
3936
  var CONTEXT_SYMBOL = /* @__PURE__ */ Symbol.for("wireai.features.context");
3132
3937
  var globalObj = global;
3133
3938
  if (!globalObj[CONTEXT_SYMBOL]) {
3134
- globalObj[CONTEXT_SYMBOL] = React14.createContext(null);
3939
+ globalObj[CONTEXT_SYMBOL] = React18.createContext(null);
3135
3940
  }
3136
3941
  var WireFeaturesContext = globalObj[CONTEXT_SYMBOL];
3137
3942
  var WireFeaturesProvider = ({
@@ -3141,23 +3946,23 @@ var WireFeaturesProvider = ({
3141
3946
  }) => {
3142
3947
  const fetched = useWireFeatures(flags ? void 0 : config);
3143
3948
  const value = flags != null ? flags : fetched;
3144
- const stable = React14.useMemo(() => value, [value]);
3949
+ const stable = React18.useMemo(() => value, [value]);
3145
3950
  return /* @__PURE__ */ jsxRuntime.jsx(WireFeaturesContext.Provider, { value: stable, children });
3146
3951
  };
3147
3952
  WireFeaturesProvider.displayName = "WireFeaturesProvider";
3148
- var useWireFeaturesContext = () => React14.useContext(WireFeaturesContext);
3953
+ var useWireFeaturesContext = () => React18.useContext(WireFeaturesContext);
3149
3954
  var useResolvedFeatures = (options) => {
3150
- var _a, _b, _c;
3955
+ var _a2, _b, _c;
3151
3956
  const ctx = useWireFeaturesContext();
3152
3957
  const shouldFetch = !(options == null ? void 0 : options.flags) && ctx == null;
3153
3958
  const fetched = useWireFeatures(shouldFetch ? options == null ? void 0 : options.config : void 0);
3154
- return (_c = (_b = (_a = options == null ? void 0 : options.flags) != null ? _a : ctx) != null ? _b : fetched) != null ? _c : defaultWireFeatures;
3959
+ return (_c = (_b = (_a2 = options == null ? void 0 : options.flags) != null ? _a2 : ctx) != null ? _b : fetched) != null ? _c : defaultWireFeatures;
3155
3960
  };
3156
3961
 
3157
3962
  // src/config/wireConfigFromEnv.ts
3158
3963
  var wireConfigFromEnv = (overrides) => {
3159
- var _a, _b, _c, _d;
3160
- const apiKey = (_a = overrides == null ? void 0 : overrides.apiKey) != null ? _a : process.env.EXPO_PUBLIC_WIREAI_API_KEY;
3964
+ var _a2, _b, _c, _d;
3965
+ const apiKey = (_a2 = overrides == null ? void 0 : overrides.apiKey) != null ? _a2 : process.env.EXPO_PUBLIC_WIREAI_API_KEY;
3161
3966
  const serverUrl = (_b = overrides == null ? void 0 : overrides.serverUrl) != null ? _b : process.env.EXPO_PUBLIC_WIREAI_SERVER_URL;
3162
3967
  const appId = (_d = (_c = overrides == null ? void 0 : overrides.appId) != null ? _c : process.env.EXPO_PUBLIC_WIREAI_APP_ID) != null ? _d : "default";
3163
3968
  if (!apiKey || !serverUrl) return null;
@@ -3171,10 +3976,10 @@ var wireConfigFromEnv = (overrides) => {
3171
3976
 
3172
3977
  // src/config/onboardingFlag.ts
3173
3978
  var isOnboardingEnabled = (opts) => {
3174
- var _a;
3979
+ var _a2;
3175
3980
  const transportPresent = wireConfigFromEnv(opts == null ? void 0 : opts.config) !== null;
3176
3981
  if (!transportPresent) return false;
3177
- return (_a = opts == null ? void 0 : opts.remote) != null ? _a : true;
3982
+ return (_a2 = opts == null ? void 0 : opts.remote) != null ? _a2 : true;
3178
3983
  };
3179
3984
 
3180
3985
  // src/analytics/analyticsEvent.ts
@@ -3270,7 +4075,7 @@ var namespaceExtra = (extra) => {
3270
4075
  return out;
3271
4076
  };
3272
4077
  var resolveUserContext = (ctx = {}, opts = {}) => {
3273
- var _a;
4078
+ var _a2;
3274
4079
  const result = {};
3275
4080
  const bucket = {};
3276
4081
  const userId = sanitizeUserId(ctx.userId);
@@ -3280,7 +4085,7 @@ var resolveUserContext = (ctx = {}, opts = {}) => {
3280
4085
  result.deviceKey = deviceKey;
3281
4086
  bucket.device_key = deviceKey;
3282
4087
  }
3283
- const appVersion = (_a = cleanString(ctx.appVersion)) != null ? _a : cleanString(opts.autoAppVersion);
4088
+ const appVersion = (_a2 = cleanString(ctx.appVersion)) != null ? _a2 : cleanString(opts.autoAppVersion);
3284
4089
  if (appVersion) {
3285
4090
  result.appVersion = appVersion;
3286
4091
  bucket.app_version = appVersion;
@@ -3299,6 +4104,15 @@ var resolveUserContext = (ctx = {}, opts = {}) => {
3299
4104
  return result;
3300
4105
  };
3301
4106
 
4107
+ // src/context/deviceId.ts
4108
+ var AUTO_DEVICE_ID_PREFIX = "wdev_";
4109
+ var deviceIdStorageKey = (appId) => `wireai:analytics:deviceKey:${appId != null ? appId : "default"}`;
4110
+ var randomChunk = () => Math.floor(Math.random() * 4294967296).toString(36).padStart(6, "0");
4111
+ var mintDeviceId = () => {
4112
+ const time = Date.now().toString(36);
4113
+ return `${AUTO_DEVICE_ID_PREFIX}${time}_${randomChunk()}${randomChunk()}`;
4114
+ };
4115
+
3302
4116
  // src/session-analytics/reportSessionStart.ts
3303
4117
  var SESSION_STARTED_EVENT = "app.session_started";
3304
4118
  var _emitted = /* @__PURE__ */ new Set();
@@ -3307,10 +4121,10 @@ var resetSessionStartGuard = () => {
3307
4121
  _emitted.clear();
3308
4122
  };
3309
4123
  var reportSessionStart = (opts) => {
3310
- var _a;
4124
+ var _a2;
3311
4125
  const target = opts.target;
3312
4126
  if (!opts.sink && !(target == null ? void 0 : target.serverUrl)) return;
3313
- const sessionId = (_a = opts.sessionId) != null ? _a : makeSessionId();
4127
+ const sessionId = (_a2 = opts.sessionId) != null ? _a2 : makeSessionId();
3314
4128
  setCurrentSessionId(sessionId);
3315
4129
  if (opts.once !== false) {
3316
4130
  if (_emitted.has(sessionId)) return;
@@ -3358,15 +4172,15 @@ var reportSessionStart = (opts) => {
3358
4172
  };
3359
4173
  var BACKGROUND_SESSION_MS = 30 * 60 * 1e3;
3360
4174
  var useSessionStart = (config, options = {}) => {
3361
- const latest = React14.useRef({ config, options });
4175
+ const latest = React18.useRef({ config, options });
3362
4176
  latest.current = { config, options };
3363
- React14.useEffect(() => {
4177
+ React18.useEffect(() => {
3364
4178
  const fire = () => {
3365
- var _a, _b;
4179
+ var _a2, _b;
3366
4180
  const { config: cfg, options: opts } = latest.current;
3367
4181
  if (!(cfg == null ? void 0 : cfg.serverUrl)) return;
3368
4182
  if (opts.enabled === false) return;
3369
- const target = { serverUrl: cfg.serverUrl, apiKey: (_a = cfg.apiKey) != null ? _a : "" };
4183
+ const target = { serverUrl: cfg.serverUrl, apiKey: (_a2 = cfg.apiKey) != null ? _a2 : "" };
3370
4184
  const device = collectDeviceContext();
3371
4185
  if (cfg.appVersion) device.appVersion = cfg.appVersion;
3372
4186
  reportSessionStart({
@@ -3417,7 +4231,7 @@ var resetFirstOpenLatch = () => {
3417
4231
  _firstOpenLatched.clear();
3418
4232
  };
3419
4233
  var buildLifecycleEvent = (questionKey, opts) => {
3420
- var _a;
4234
+ var _a2;
3421
4235
  const userContext = {};
3422
4236
  if (opts.deviceKey) userContext.device_key = opts.deviceKey;
3423
4237
  if (typeof opts.sessionCount === "number" && Number.isFinite(opts.sessionCount)) {
@@ -3429,7 +4243,7 @@ var buildLifecycleEvent = (questionKey, opts) => {
3429
4243
  const event = {
3430
4244
  event_type: "app_event",
3431
4245
  question_key: questionKey,
3432
- session_id: (_a = opts.sessionId) != null ? _a : makeSessionId()
4246
+ session_id: (_a2 = opts.sessionId) != null ? _a2 : makeSessionId()
3433
4247
  };
3434
4248
  const userId = sanitizeUserId(opts.userId);
3435
4249
  if (userId) event.user_id = userId;
@@ -3462,8 +4276,8 @@ var emitFirstOpen = (opts) => {
3462
4276
  routeLifecycleEvent(buildLifecycleEvent(FIRST_OPEN_EVENT, opts), opts);
3463
4277
  };
3464
4278
  var reportFirstOpen = (opts) => {
3465
- var _a;
3466
- const appId = (_a = opts.appId) != null ? _a : "default";
4279
+ var _a2;
4280
+ const appId = (_a2 = opts.appId) != null ? _a2 : "default";
3467
4281
  if (_firstOpenLatched.has(appId)) return;
3468
4282
  _firstOpenLatched.add(appId);
3469
4283
  const storage = opts.storage;
@@ -3540,10 +4354,10 @@ var parsePersisted2 = (raw) => {
3540
4354
  }
3541
4355
  };
3542
4356
  var createEventQueue = (options) => {
3543
- var _a, _b, _c, _d, _e, _f, _g;
4357
+ var _a2, _b, _c, _d, _e, _f, _g;
3544
4358
  const target = options.target;
3545
4359
  const storage = options.storage;
3546
- const key = (_b = options.storageKey) != null ? _b : `wireai:evtq:${(_a = options.appId) != null ? _a : "default"}`;
4360
+ const key = (_b = options.storageKey) != null ? _b : `wireai:evtq:${(_a2 = options.appId) != null ? _a2 : "default"}`;
3547
4361
  const maxSize = (_c = options.maxSize) != null ? _c : DEFAULTS.maxSize;
3548
4362
  const batchSize = (_d = options.batchSize) != null ? _d : DEFAULTS.batchSize;
3549
4363
  const baseBackoffMs = (_e = options.baseBackoffMs) != null ? _e : DEFAULTS.baseBackoffMs;
@@ -3562,13 +4376,13 @@ var createEventQueue = (options) => {
3562
4376
  }
3563
4377
  };
3564
4378
  const stamp = (event) => {
3565
- var _a2;
4379
+ var _a3;
3566
4380
  const env = resolveEnvelope();
3567
4381
  const stamped = { ...event };
3568
4382
  if (!env) return stamped;
3569
4383
  if (!stamped.device && env.device) stamped.device = env.device;
3570
4384
  if (!stamped.session_id && env.sessionId) stamped.session_id = env.sessionId;
3571
- const uc = { ...(_a2 = stamped.user_context) != null ? _a2 : {} };
4385
+ const uc = { ...(_a3 = stamped.user_context) != null ? _a3 : {} };
3572
4386
  if (env.appVersion && uc.app_version === void 0) uc.app_version = env.appVersion;
3573
4387
  if (env.appBuild && uc.app_build === void 0) uc.app_build = env.appBuild;
3574
4388
  if (env.networkType && uc.network_type === void 0) uc.network_type = env.networkType;
@@ -3713,19 +4527,19 @@ var createEventQueue = (options) => {
3713
4527
 
3714
4528
  // src/session-analytics/useLifecycleEvents.ts
3715
4529
  var useLifecycleEvents = (config, options = {}) => {
3716
- const latest = React14.useRef({ config, options });
4530
+ const latest = React18.useRef({ config, options });
3717
4531
  latest.current = { config, options };
3718
- const queueRef = React14.useRef(void 0);
3719
- React14.useEffect(() => {
3720
- var _a;
4532
+ const queueRef = React18.useRef(void 0);
4533
+ React18.useEffect(() => {
4534
+ var _a2;
3721
4535
  const resolveSink = () => {
3722
- var _a2, _b;
4536
+ var _a3, _b;
3723
4537
  const { config: cfg, options: opts } = latest.current;
3724
4538
  if (opts.sink) return opts.sink;
3725
4539
  if (!(cfg == null ? void 0 : cfg.serverUrl)) return void 0;
3726
4540
  if (!queueRef.current) {
3727
4541
  queueRef.current = createEventQueue({
3728
- target: { serverUrl: cfg.serverUrl, apiKey: (_a2 = cfg.apiKey) != null ? _a2 : "" },
4542
+ target: { serverUrl: cfg.serverUrl, apiKey: (_a3 = cfg.apiKey) != null ? _a3 : "" },
3729
4543
  storage: cfg.storage,
3730
4544
  // Dedicated key so the hook's internal queue never collides with a host's main queue.
3731
4545
  storageKey: `wireai:evtq:lifecycle:${(_b = cfg.appId) != null ? _b : "default"}`,
@@ -3735,8 +4549,8 @@ var useLifecycleEvents = (config, options = {}) => {
3735
4549
  return queueRef.current.enqueue;
3736
4550
  };
3737
4551
  const targetOf = (cfg) => {
3738
- var _a2;
3739
- return (cfg == null ? void 0 : cfg.serverUrl) ? { serverUrl: cfg.serverUrl, apiKey: (_a2 = cfg.apiKey) != null ? _a2 : "" } : void 0;
4552
+ var _a3;
4553
+ return (cfg == null ? void 0 : cfg.serverUrl) ? { serverUrl: cfg.serverUrl, apiKey: (_a3 = cfg.apiKey) != null ? _a3 : "" } : void 0;
3740
4554
  };
3741
4555
  {
3742
4556
  const { config: cfg, options: opts } = latest.current;
@@ -3751,7 +4565,7 @@ var useLifecycleEvents = (config, options = {}) => {
3751
4565
  userId: opts.userId,
3752
4566
  deviceKey: opts.deviceKey,
3753
4567
  sessionCount: opts.sessionCount,
3754
- appVersion: (_a = cfg == null ? void 0 : cfg.appVersion) != null ? _a : device.appVersion,
4568
+ appVersion: (_a2 = cfg == null ? void 0 : cfg.appVersion) != null ? _a2 : device.appVersion,
3755
4569
  platform: reactNative.Platform.OS,
3756
4570
  device,
3757
4571
  meta: opts.meta
@@ -3759,7 +4573,7 @@ var useLifecycleEvents = (config, options = {}) => {
3759
4573
  }
3760
4574
  }
3761
4575
  const fireSession = () => {
3762
- var _a2;
4576
+ var _a3;
3763
4577
  const { config: cfg, options: opts } = latest.current;
3764
4578
  if (opts.enabled === false) return;
3765
4579
  if (!(cfg == null ? void 0 : cfg.serverUrl) && !opts.sink) return;
@@ -3772,7 +4586,7 @@ var useLifecycleEvents = (config, options = {}) => {
3772
4586
  userId: opts.userId,
3773
4587
  deviceKey: opts.deviceKey,
3774
4588
  sessionCount: opts.sessionCount,
3775
- appVersion: (_a2 = cfg == null ? void 0 : cfg.appVersion) != null ? _a2 : device.appVersion,
4589
+ appVersion: (_a3 = cfg == null ? void 0 : cfg.appVersion) != null ? _a3 : device.appVersion,
3776
4590
  platform: reactNative.Platform.OS,
3777
4591
  device,
3778
4592
  meta: opts.meta
@@ -3798,8 +4612,10 @@ var useLifecycleEvents = (config, options = {}) => {
3798
4612
  }, []);
3799
4613
  };
3800
4614
 
4615
+ exports.AUTO_DEVICE_ID_PREFIX = AUTO_DEVICE_ID_PREFIX;
3801
4616
  exports.AnimatedSparkle = AnimatedSparkle;
3802
4617
  exports.BACKGROUND_SESSION_MS = BACKGROUND_SESSION_MS;
4618
+ exports.CardGridSelectCard = CardGridSelectCard;
3803
4619
  exports.CardHandoff = CardHandoff;
3804
4620
  exports.CenteredModal = CenteredModal;
3805
4621
  exports.ChipSelectCard = ChipSelectCard;
@@ -3811,6 +4627,7 @@ exports.DoneBlock = DoneBlock;
3811
4627
  exports.EXTRA_KEY_PREFIX = EXTRA_KEY_PREFIX;
3812
4628
  exports.ErrorBlock = ErrorBlock;
3813
4629
  exports.FIRST_OPEN_EVENT = FIRST_OPEN_EVENT;
4630
+ exports.IconRegistryProvider = IconRegistryProvider;
3814
4631
  exports.IllustrationProvider = IllustrationProvider;
3815
4632
  exports.InterstitialCard = InterstitialCard;
3816
4633
  exports.LoadingBlock = LoadingBlock;
@@ -3827,8 +4644,11 @@ exports.StatusCard = StatusCard;
3827
4644
  exports.StepProgress = StepProgress;
3828
4645
  exports.TextInputCard = TextInputCard;
3829
4646
  exports.USER_ID_MAX_LENGTH = USER_ID_MAX_LENGTH;
4647
+ exports.WIRE_ICON_GLYPHS = WIRE_ICON_GLYPHS;
4648
+ exports.WIRE_ICON_NAMES = WIRE_ICON_NAMES;
3830
4649
  exports.WIRE_ONBOARDING_EVENTS = WIRE_ONBOARDING_EVENTS;
3831
4650
  exports.WireFeaturesProvider = WireFeaturesProvider;
4651
+ exports.WireIcon = WireIcon;
3832
4652
  exports.WireOnboarding = WireOnboarding;
3833
4653
  exports.attributionMetadata = attributionMetadata;
3834
4654
  exports.clearPersistedSession = clearPersistedSession;
@@ -3838,6 +4658,8 @@ exports.defaultOnboardingTheme = defaultOnboardingTheme;
3838
4658
  exports.defaultWireFeatures = defaultWireFeatures;
3839
4659
  exports.deriveAnswers = deriveAnswers;
3840
4660
  exports.detectAppVersion = detectAppVersion;
4661
+ exports.detectNativeModel = detectNativeModel;
4662
+ exports.deviceIdStorageKey = deviceIdStorageKey;
3841
4663
  exports.featuresCacheKey = featuresCacheKey;
3842
4664
  exports.featuresEqual = featuresEqual;
3843
4665
  exports.fetchWireFeatures = fetchWireFeatures;
@@ -3849,8 +4671,10 @@ exports.isFeaturesFresh = isFeaturesFresh;
3849
4671
  exports.isOnboardingEnabled = isOnboardingEnabled;
3850
4672
  exports.isWireScalar = isWireScalar;
3851
4673
  exports.loadPersistedSession = loadPersistedSession;
4674
+ exports.lookupIconGlyph = lookupIconGlyph;
3852
4675
  exports.makeSessionId = makeSessionId;
3853
4676
  exports.mergeTheme = mergeTheme;
4677
+ exports.mintDeviceId = mintDeviceId;
3854
4678
  exports.motionSpec = motionSpec_exports;
3855
4679
  exports.namespaceExtra = namespaceExtra;
3856
4680
  exports.onboardingComponents = onboardingComponents;
@@ -3872,6 +4696,7 @@ exports.sessionStorageKey = sessionStorageKey;
3872
4696
  exports.setCurrentSessionId = setCurrentSessionId;
3873
4697
  exports.themeFromBrand = themeFromBrand;
3874
4698
  exports.toAnalyticsEvent = toAnalyticsEvent;
4699
+ exports.useHostIcon = useHostIcon;
3875
4700
  exports.useIllustration = useIllustration;
3876
4701
  exports.useLifecycleEvents = useLifecycleEvents;
3877
4702
  exports.useOnboardingTheme = useOnboardingTheme;