@paymanai/payman-ask-sdk 2.0.4 → 2.0.5

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.
@@ -1,17 +1,20 @@
1
1
  'use strict';
2
2
 
3
- var react = require('react');
3
+ var React = require('react');
4
4
  var reactNative = require('react-native');
5
+ var paymanTypescriptAskSdk = require('@paymanai/payman-typescript-ask-sdk');
6
+ var lucideReactNative = require('lucide-react-native');
5
7
  var jsxRuntime = require('react/jsx-runtime');
8
+ var Markdown = require('react-native-markdown-display');
6
9
  var lucideReact = require('lucide-react');
7
10
  var framerMotion = require('framer-motion');
8
11
  var reactDom = require('react-dom');
9
12
  var clsx = require('clsx');
10
13
  var tailwindMerge = require('tailwind-merge');
11
- var paymanTypescriptAskSdk = require('@paymanai/payman-typescript-ask-sdk');
12
- var lucideReactNative = require('lucide-react-native');
13
14
  var Sentry = require('@sentry/react');
14
15
 
16
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
17
+
15
18
  function _interopNamespace(e) {
16
19
  if (e && e.__esModule) return e;
17
20
  var n = Object.create(null);
@@ -24,39 +27,2916 @@ function _interopNamespace(e) {
24
27
  get: function () { return e[k]; }
25
28
  });
26
29
  }
27
- });
30
+ });
31
+ }
32
+ n.default = e;
33
+ return Object.freeze(n);
34
+ }
35
+
36
+ var React__default = /*#__PURE__*/_interopDefault(React);
37
+ var Markdown__default = /*#__PURE__*/_interopDefault(Markdown);
38
+ var Sentry__namespace = /*#__PURE__*/_interopNamespace(Sentry);
39
+
40
+ // src/components/PaymanChat/index.native.tsx
41
+ var PAYMAN_TEAL = "#00858d";
42
+ var SEND_BUTTON_COLOR = "#15687d";
43
+ var SEND_BUTTON_DISABLED_COLOR = "#d1d5db";
44
+ var INPUT_BOTTOM_MARGIN = reactNative.Platform.OS === "ios" ? 18 : 8;
45
+ var LIGHT_PALETTE = {
46
+ surface: "#ffffff",
47
+ soft: "#f4f4f5",
48
+ border: "rgba(15,23,42,0.08)",
49
+ borderFocused: "rgba(15,23,42,0.16)",
50
+ textPrimary: "#0f172a",
51
+ textTertiary: "#94a3b8",
52
+ iconGrey: "#64748b",
53
+ disclaimer: "#94a3b8"
54
+ };
55
+ var DARK_PALETTE = {
56
+ surface: "#0d1719",
57
+ soft: "#162022",
58
+ border: "rgba(255,255,255,0.08)",
59
+ borderFocused: "rgba(255,255,255,0.18)",
60
+ textPrimary: "#f0f9fa",
61
+ textTertiary: "rgba(240,249,250,0.40)",
62
+ iconGrey: "rgba(240,249,250,0.55)",
63
+ disclaimer: "rgba(240,249,250,0.38)"
64
+ };
65
+ var INPUT_FONT_SIZE = 15;
66
+ var INPUT_LINE_HEIGHT = 22;
67
+ var INPUT_MAX_HEIGHT = INPUT_LINE_HEIGHT * 8;
68
+ var ANDROID_RIPPLE_DARK = { color: "rgba(15,23,42,0.10)", borderless: false };
69
+ var ANDROID_RIPPLE_LIGHT = { color: "rgba(255,255,255,0.20)", borderless: false };
70
+ var ChatInputV2 = React.forwardRef(
71
+ function ChatInputV22({
72
+ onSend,
73
+ disabled = false,
74
+ isStreaming = false,
75
+ placeholder = "Type your message\u2026",
76
+ enableVoice = false,
77
+ voiceAvailable = false,
78
+ isRecording = false,
79
+ onVoicePress,
80
+ showResetSession = false,
81
+ onResetSession,
82
+ hideSendButton = false,
83
+ showAttachmentButton,
84
+ showUploadImageButton = true,
85
+ showAttachFileButton = true,
86
+ onUploadImageClick,
87
+ onAttachFileClick,
88
+ hideDisclaimer = false,
89
+ theme = "light",
90
+ topAccessory
91
+ }, ref) {
92
+ const p = theme === "dark" ? DARK_PALETTE : LIGHT_PALETTE;
93
+ const [value, setValue] = React.useState("");
94
+ const [isFocused, setIsFocused] = React.useState(false);
95
+ const [isKeyboardVisible, setIsKeyboardVisible] = React.useState(false);
96
+ const [sheetOpen, setSheetOpen] = React.useState(false);
97
+ const textInputRef = React.useRef(null);
98
+ const hasAttachmentOptions = !!onUploadImageClick && showUploadImageButton || !!onAttachFileClick && showAttachFileButton;
99
+ const showAttachmentMenuButton = (showAttachmentButton ?? true) && hasAttachmentOptions;
100
+ React.useImperativeHandle(
101
+ ref,
102
+ () => ({
103
+ setDraft: (text) => {
104
+ setValue(text);
105
+ requestAnimationFrame(() => textInputRef.current?.focus());
106
+ },
107
+ focus: () => textInputRef.current?.focus()
108
+ }),
109
+ []
110
+ );
111
+ const handleSend = React.useCallback(() => {
112
+ const trimmed = value.trim();
113
+ if (!trimmed || disabled) return;
114
+ onSend(trimmed);
115
+ setValue("");
116
+ }, [value, disabled, onSend]);
117
+ const canSend = value.trim().length > 0 && !disabled;
118
+ const sendDisabled = !canSend || isStreaming;
119
+ const showVoiceButton = enableVoice && !!onVoicePress;
120
+ const isVoiceButtonDisabled = disabled || !voiceAvailable;
121
+ const hasTopAccessory = topAccessory != null;
122
+ const sendScale = React.useRef(new reactNative.Animated.Value(1)).current;
123
+ React.useEffect(() => {
124
+ reactNative.Animated.spring(sendScale, {
125
+ toValue: canSend && !isStreaming ? 1 : 0.94,
126
+ useNativeDriver: true,
127
+ friction: 6,
128
+ tension: 180
129
+ }).start();
130
+ }, [canSend, isStreaming, sendScale]);
131
+ const handleAttachmentPress = React.useCallback(() => {
132
+ if (disabled || isRecording) return;
133
+ setSheetOpen(true);
134
+ }, [disabled, isRecording]);
135
+ const closeSheet = React.useCallback(() => setSheetOpen(false), []);
136
+ React.useEffect(() => {
137
+ const showEvent = reactNative.Platform.OS === "ios" ? "keyboardWillShow" : "keyboardDidShow";
138
+ const hideEvent = reactNative.Platform.OS === "ios" ? "keyboardWillHide" : "keyboardDidHide";
139
+ const showSub = reactNative.Keyboard.addListener(showEvent, () => {
140
+ setIsKeyboardVisible(true);
141
+ });
142
+ const hideSub = reactNative.Keyboard.addListener(hideEvent, () => {
143
+ setIsKeyboardVisible(false);
144
+ });
145
+ return () => {
146
+ showSub.remove();
147
+ hideSub.remove();
148
+ };
149
+ }, []);
150
+ const handlePickImage = React.useCallback(() => {
151
+ closeSheet();
152
+ onUploadImageClick?.();
153
+ }, [closeSheet, onUploadImageClick]);
154
+ const handlePickFile = React.useCallback(() => {
155
+ closeSheet();
156
+ onAttachFileClick?.();
157
+ }, [closeSheet, onAttachFileClick]);
158
+ return /* @__PURE__ */ jsxRuntime.jsxs(
159
+ reactNative.View,
160
+ {
161
+ style: [
162
+ s.outer,
163
+ {
164
+ backgroundColor: p.surface,
165
+ marginBottom: isKeyboardVisible ? 0 : INPUT_BOTTOM_MARGIN
166
+ }
167
+ ],
168
+ children: [
169
+ hasTopAccessory ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: s.topAccessory, children: topAccessory }) : null,
170
+ /* @__PURE__ */ jsxRuntime.jsxs(
171
+ reactNative.View,
172
+ {
173
+ style: [
174
+ s.wrapper,
175
+ hasTopAccessory && s.wrapperWithTopAccessory,
176
+ { backgroundColor: p.soft, borderColor: p.border },
177
+ (isFocused || isRecording) && { borderColor: p.borderFocused },
178
+ disabled && s.wrapperDisabled
179
+ ],
180
+ children: [
181
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: s.inputRow, children: /* @__PURE__ */ jsxRuntime.jsx(
182
+ reactNative.TextInput,
183
+ {
184
+ ref: textInputRef,
185
+ style: [s.input, { color: p.textPrimary }],
186
+ value,
187
+ onChangeText: (t) => {
188
+ if (isRecording) return;
189
+ setValue(t);
190
+ },
191
+ onFocus: () => setIsFocused(true),
192
+ onBlur: () => setIsFocused(false),
193
+ placeholder: isRecording ? "Listening\u2026" : placeholder,
194
+ placeholderTextColor: p.textTertiary,
195
+ multiline: true,
196
+ editable: !disabled && !isRecording,
197
+ returnKeyType: "default",
198
+ blurOnSubmit: false,
199
+ scrollEnabled: true
200
+ }
201
+ ) }),
202
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s.controls, children: [
203
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s.leftControls, children: [
204
+ showResetSession && onResetSession ? /* @__PURE__ */ jsxRuntime.jsx(
205
+ reactNative.Pressable,
206
+ {
207
+ onPress: onResetSession,
208
+ disabled: isStreaming || isRecording,
209
+ style: [
210
+ s.iconBtn,
211
+ (isStreaming || isRecording) && s.iconBtnDisabled
212
+ ],
213
+ android_ripple: ANDROID_RIPPLE_DARK,
214
+ hitSlop: 6,
215
+ accessibilityLabel: "New session",
216
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.RotateCcw, { size: 18, color: p.iconGrey, strokeWidth: 2 })
217
+ }
218
+ ) : null,
219
+ showAttachmentMenuButton ? /* @__PURE__ */ jsxRuntime.jsx(
220
+ reactNative.Pressable,
221
+ {
222
+ onPress: handleAttachmentPress,
223
+ disabled: disabled || isRecording,
224
+ style: [
225
+ s.iconBtn,
226
+ (disabled || isRecording) && s.iconBtnDisabled
227
+ ],
228
+ android_ripple: ANDROID_RIPPLE_DARK,
229
+ hitSlop: 6,
230
+ accessibilityLabel: "Attach",
231
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.Plus, { size: 20, color: p.iconGrey, strokeWidth: 2 })
232
+ }
233
+ ) : null
234
+ ] }),
235
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s.rightControls, children: [
236
+ showVoiceButton ? /* @__PURE__ */ jsxRuntime.jsx(
237
+ reactNative.Pressable,
238
+ {
239
+ onPress: onVoicePress,
240
+ disabled: isVoiceButtonDisabled,
241
+ style: [
242
+ s.iconBtn,
243
+ isRecording && s.iconBtnRecording,
244
+ isVoiceButtonDisabled && s.iconBtnDisabled
245
+ ],
246
+ android_ripple: ANDROID_RIPPLE_DARK,
247
+ hitSlop: 6,
248
+ accessibilityLabel: isRecording ? "Stop recording" : "Voice input",
249
+ children: /* @__PURE__ */ jsxRuntime.jsx(
250
+ lucideReactNative.Mic,
251
+ {
252
+ size: 18,
253
+ color: isRecording ? PAYMAN_TEAL : p.iconGrey,
254
+ strokeWidth: 2
255
+ }
256
+ )
257
+ }
258
+ ) : null,
259
+ !hideSendButton ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: { transform: [{ scale: sendScale }] }, children: /* @__PURE__ */ jsxRuntime.jsx(
260
+ reactNative.Pressable,
261
+ {
262
+ onPress: handleSend,
263
+ disabled: sendDisabled,
264
+ style: [s.sendBtn, sendDisabled && s.sendBtnIdle],
265
+ android_ripple: ANDROID_RIPPLE_LIGHT,
266
+ hitSlop: 4,
267
+ accessibilityLabel: "Send",
268
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.ArrowUp, { size: 18, color: "#fff", strokeWidth: 2.75 })
269
+ }
270
+ ) }) : null
271
+ ] })
272
+ ] })
273
+ ]
274
+ }
275
+ ),
276
+ !hideDisclaimer ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [s.disclaimer, { color: p.disclaimer }], children: "AI can make mistakes. Please double-check responses." }) : null,
277
+ /* @__PURE__ */ jsxRuntime.jsx(
278
+ AttachmentSheet,
279
+ {
280
+ visible: sheetOpen,
281
+ onClose: closeSheet,
282
+ showImage: !!onUploadImageClick && showUploadImageButton,
283
+ showFile: !!onAttachFileClick && showAttachFileButton,
284
+ onPickImage: handlePickImage,
285
+ onPickFile: handlePickFile
286
+ }
287
+ )
288
+ ]
289
+ }
290
+ );
291
+ }
292
+ );
293
+ function AttachmentSheet({
294
+ visible,
295
+ onClose,
296
+ showImage,
297
+ showFile,
298
+ onPickImage,
299
+ onPickFile
300
+ }) {
301
+ const translateY = React.useRef(new reactNative.Animated.Value(80)).current;
302
+ const opacity = React.useRef(new reactNative.Animated.Value(0)).current;
303
+ React.useEffect(() => {
304
+ if (visible) {
305
+ reactNative.Animated.parallel([
306
+ reactNative.Animated.timing(opacity, {
307
+ toValue: 1,
308
+ duration: 180,
309
+ useNativeDriver: true
310
+ }),
311
+ reactNative.Animated.spring(translateY, {
312
+ toValue: 0,
313
+ useNativeDriver: true,
314
+ friction: 9,
315
+ tension: 90
316
+ })
317
+ ]).start();
318
+ } else {
319
+ translateY.setValue(80);
320
+ opacity.setValue(0);
321
+ }
322
+ }, [visible, opacity, translateY]);
323
+ return /* @__PURE__ */ jsxRuntime.jsxs(
324
+ reactNative.Modal,
325
+ {
326
+ visible,
327
+ transparent: true,
328
+ animationType: "none",
329
+ onRequestClose: onClose,
330
+ children: [
331
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: [sheet.backdrop, { opacity }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { style: sheet.backdropPressable, onPress: onClose }) }),
332
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: sheet.sheetWrap, pointerEvents: "box-none", children: /* @__PURE__ */ jsxRuntime.jsxs(
333
+ reactNative.Animated.View,
334
+ {
335
+ style: [
336
+ sheet.sheet,
337
+ { transform: [{ translateY }], opacity }
338
+ ],
339
+ children: [
340
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: sheet.handle }),
341
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: sheet.headerRow, children: [
342
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: sheet.title, children: "Add to message" }),
343
+ /* @__PURE__ */ jsxRuntime.jsx(
344
+ reactNative.Pressable,
345
+ {
346
+ onPress: onClose,
347
+ hitSlop: 8,
348
+ style: sheet.closeBtn,
349
+ android_ripple: ANDROID_RIPPLE_DARK,
350
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.X, { size: 18, color: "#6b6b67", strokeWidth: 2.25 })
351
+ }
352
+ )
353
+ ] }),
354
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: sheet.options, children: [
355
+ showImage ? /* @__PURE__ */ jsxRuntime.jsxs(
356
+ reactNative.Pressable,
357
+ {
358
+ onPress: onPickImage,
359
+ style: sheet.option,
360
+ android_ripple: ANDROID_RIPPLE_DARK,
361
+ children: [
362
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: sheet.optionIconWrap, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.ImagePlus, { size: 20, color: PAYMAN_TEAL, strokeWidth: 2 }) }),
363
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: { flex: 1 }, children: [
364
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: sheet.optionTitle, children: "Upload image" }),
365
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: sheet.optionSubtitle, children: "From your camera roll" })
366
+ ] })
367
+ ]
368
+ }
369
+ ) : null,
370
+ showFile ? /* @__PURE__ */ jsxRuntime.jsxs(
371
+ reactNative.Pressable,
372
+ {
373
+ onPress: onPickFile,
374
+ style: sheet.option,
375
+ android_ripple: ANDROID_RIPPLE_DARK,
376
+ children: [
377
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: sheet.optionIconWrap, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.Paperclip, { size: 20, color: PAYMAN_TEAL, strokeWidth: 2 }) }),
378
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: { flex: 1 }, children: [
379
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: sheet.optionTitle, children: "Attach file" }),
380
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: sheet.optionSubtitle, children: "PDFs, documents and more" })
381
+ ] })
382
+ ]
383
+ }
384
+ ) : null
385
+ ] })
386
+ ]
387
+ }
388
+ ) })
389
+ ]
390
+ }
391
+ );
392
+ }
393
+ var s = reactNative.StyleSheet.create({
394
+ outer: {
395
+ paddingHorizontal: 12,
396
+ paddingTop: 6,
397
+ paddingBottom: 6
398
+ },
399
+ topAccessory: {
400
+ marginBottom: -1,
401
+ zIndex: 1
402
+ },
403
+ wrapper: {
404
+ borderRadius: 24,
405
+ borderWidth: 1,
406
+ paddingHorizontal: 6,
407
+ paddingTop: 2,
408
+ paddingBottom: 6
409
+ },
410
+ wrapperWithTopAccessory: {
411
+ borderTopLeftRadius: 0,
412
+ borderTopRightRadius: 0
413
+ },
414
+ wrapperFocused: {
415
+ ...reactNative.Platform.select({
416
+ ios: {
417
+ shadowColor: "#000",
418
+ shadowOpacity: 0.04,
419
+ shadowRadius: 10,
420
+ shadowOffset: { width: 0, height: 2 }
421
+ },
422
+ android: { elevation: 0 }
423
+ })
424
+ },
425
+ wrapperDisabled: { opacity: 0.6 },
426
+ inputRow: {
427
+ maxHeight: INPUT_MAX_HEIGHT,
428
+ paddingHorizontal: 12,
429
+ paddingTop: 10,
430
+ paddingBottom: 4
431
+ },
432
+ input: {
433
+ fontSize: INPUT_FONT_SIZE,
434
+ lineHeight: INPUT_LINE_HEIGHT,
435
+ includeFontPadding: false,
436
+ textAlignVertical: "top",
437
+ padding: 0,
438
+ margin: 0
439
+ },
440
+ controls: {
441
+ flexDirection: "row",
442
+ alignItems: "center",
443
+ justifyContent: "space-between",
444
+ paddingHorizontal: 2,
445
+ paddingTop: 2
446
+ },
447
+ leftControls: {
448
+ flexDirection: "row",
449
+ alignItems: "center",
450
+ gap: 2
451
+ },
452
+ rightControls: {
453
+ flexDirection: "row",
454
+ alignItems: "center",
455
+ gap: 2
456
+ },
457
+ iconBtn: {
458
+ width: 32,
459
+ height: 32,
460
+ borderRadius: 16,
461
+ alignItems: "center",
462
+ justifyContent: "center"
463
+ },
464
+ iconBtnDisabled: { opacity: 0.4 },
465
+ iconBtnRecording: { backgroundColor: "rgba(0,133,141,0.10)" },
466
+ sendBtn: {
467
+ width: 34,
468
+ height: 34,
469
+ borderRadius: 17,
470
+ backgroundColor: SEND_BUTTON_COLOR,
471
+ alignItems: "center",
472
+ justifyContent: "center",
473
+ marginLeft: 2,
474
+ ...reactNative.Platform.select({
475
+ ios: {
476
+ shadowColor: SEND_BUTTON_COLOR,
477
+ shadowOpacity: 0.32,
478
+ shadowRadius: 10,
479
+ shadowOffset: { width: 0, height: 4 }
480
+ },
481
+ android: { elevation: 3 }
482
+ })
483
+ },
484
+ sendBtnIdle: {
485
+ backgroundColor: SEND_BUTTON_DISABLED_COLOR,
486
+ opacity: 1,
487
+ shadowOpacity: 0
488
+ },
489
+ disclaimer: {
490
+ fontSize: 11,
491
+ textAlign: "center",
492
+ marginTop: 8,
493
+ paddingHorizontal: 16
494
+ }
495
+ });
496
+ var sheet = reactNative.StyleSheet.create({
497
+ backdrop: {
498
+ ...reactNative.StyleSheet.absoluteFillObject,
499
+ backgroundColor: "rgba(15,23,42,0.35)"
500
+ },
501
+ backdropPressable: { flex: 1 },
502
+ sheetWrap: {
503
+ ...reactNative.StyleSheet.absoluteFillObject,
504
+ justifyContent: "flex-end"
505
+ },
506
+ sheet: {
507
+ backgroundColor: "#ffffff",
508
+ borderTopLeftRadius: 24,
509
+ borderTopRightRadius: 24,
510
+ paddingHorizontal: 20,
511
+ paddingTop: 8,
512
+ paddingBottom: 36,
513
+ ...reactNative.Platform.select({
514
+ ios: {
515
+ shadowColor: "#000",
516
+ shadowOpacity: 0.18,
517
+ shadowRadius: 24,
518
+ shadowOffset: { width: 0, height: -4 }
519
+ },
520
+ android: { elevation: 16 }
521
+ })
522
+ },
523
+ handle: {
524
+ alignSelf: "center",
525
+ width: 44,
526
+ height: 4,
527
+ borderRadius: 2,
528
+ backgroundColor: "rgba(15,23,42,0.12)",
529
+ marginBottom: 12
530
+ },
531
+ headerRow: {
532
+ flexDirection: "row",
533
+ alignItems: "center",
534
+ justifyContent: "space-between",
535
+ marginBottom: 12
536
+ },
537
+ title: {
538
+ fontSize: 16,
539
+ fontWeight: "600",
540
+ color: "#1d1d1f"
541
+ },
542
+ closeBtn: {
543
+ width: 30,
544
+ height: 30,
545
+ borderRadius: 15,
546
+ alignItems: "center",
547
+ justifyContent: "center",
548
+ backgroundColor: "rgba(15,23,42,0.04)"
549
+ },
550
+ options: { gap: 8 },
551
+ option: {
552
+ flexDirection: "row",
553
+ alignItems: "center",
554
+ gap: 12,
555
+ paddingHorizontal: 12,
556
+ paddingVertical: 14,
557
+ borderRadius: 14,
558
+ backgroundColor: "#f8fafc",
559
+ borderWidth: reactNative.StyleSheet.hairlineWidth,
560
+ borderColor: "rgba(15,23,42,0.06)"
561
+ },
562
+ optionIconWrap: {
563
+ width: 38,
564
+ height: 38,
565
+ borderRadius: 19,
566
+ backgroundColor: "rgba(0,133,141,0.10)",
567
+ alignItems: "center",
568
+ justifyContent: "center"
569
+ },
570
+ optionTitle: {
571
+ fontSize: 15,
572
+ fontWeight: "600",
573
+ color: "#1d1d1f"
574
+ },
575
+ optionSubtitle: {
576
+ fontSize: 12,
577
+ color: "#6b6b67",
578
+ marginTop: 2
579
+ }
580
+ });
581
+ var DEFAULT_MAX_LENGTH = 6;
582
+ var MAX_SUPPORTED_LENGTH = 12;
583
+ var OTP_ERROR_BORDER = "#ef4444";
584
+ var COMPLETE_PULSE_MS = 350;
585
+ var SHAKE_MS = 400;
586
+ function OtpInput({
587
+ value,
588
+ onChange,
589
+ maxLength,
590
+ disabled = false,
591
+ error = false
592
+ }) {
593
+ const inputRefs = React.useRef([]);
594
+ const shakeAnim = React.useRef(new reactNative.Animated.Value(0)).current;
595
+ const scaleAnim = React.useRef(new reactNative.Animated.Value(1)).current;
596
+ const prevLenRef = React.useRef(0);
597
+ const [internalError, setInternalError] = React.useState(false);
598
+ const safeMaxLength = Number.isInteger(maxLength) && maxLength > 0 ? Math.min(maxLength, MAX_SUPPORTED_LENGTH) : DEFAULT_MAX_LENGTH;
599
+ const digits = value.split("").concat(Array(safeMaxLength).fill("")).slice(0, safeMaxLength);
600
+ const isFull = value.length === safeMaxLength && /^\d+$/.test(value);
601
+ React.useEffect(() => {
602
+ if (!disabled) {
603
+ inputRefs.current[0]?.focus();
604
+ }
605
+ }, [disabled]);
606
+ React.useEffect(() => {
607
+ if (!error) {
608
+ setInternalError(false);
609
+ return;
610
+ }
611
+ setInternalError(true);
612
+ reactNative.Animated.sequence([
613
+ reactNative.Animated.timing(shakeAnim, { toValue: 1, duration: SHAKE_MS, useNativeDriver: true }),
614
+ reactNative.Animated.timing(shakeAnim, { toValue: 0, duration: 0, useNativeDriver: true })
615
+ ]).start();
616
+ }, [error, shakeAnim]);
617
+ React.useEffect(() => {
618
+ if (isFull && prevLenRef.current < safeMaxLength) {
619
+ reactNative.Animated.sequence([
620
+ reactNative.Animated.timing(scaleAnim, { toValue: 1.04, duration: COMPLETE_PULSE_MS * 0.4, useNativeDriver: true }),
621
+ reactNative.Animated.timing(scaleAnim, { toValue: 1, duration: COMPLETE_PULSE_MS * 0.6, useNativeDriver: true })
622
+ ]).start();
623
+ }
624
+ prevLenRef.current = value.length;
625
+ }, [isFull, value.length, safeMaxLength, scaleAnim]);
626
+ const shakeTranslate = shakeAnim.interpolate({
627
+ inputRange: [0, 0.15, 0.3, 0.45, 0.6, 0.75, 0.9, 1],
628
+ outputRange: [0, -6, 5, -4, 3, -2, 1, 0]
629
+ });
630
+ const focusInput = (index) => {
631
+ if (index >= 0 && index < safeMaxLength) {
632
+ inputRefs.current[index]?.focus();
633
+ }
634
+ };
635
+ const updateValue = (newDigits) => {
636
+ onChange(newDigits.join("").slice(0, safeMaxLength));
637
+ };
638
+ const handleChange = (index, text) => {
639
+ const cleaned = text.replace(/\D/g, "");
640
+ if (cleaned.length > 1) {
641
+ const pasted = cleaned.slice(0, safeMaxLength);
642
+ const newDigits2 = pasted.split("").concat(Array(safeMaxLength).fill("")).slice(0, safeMaxLength);
643
+ updateValue(newDigits2);
644
+ focusInput(Math.min(pasted.length, safeMaxLength - 1));
645
+ return;
646
+ }
647
+ const char = cleaned.slice(-1);
648
+ const newDigits = [...digits];
649
+ newDigits[index] = char;
650
+ updateValue(newDigits);
651
+ if (char && index < safeMaxLength - 1) {
652
+ focusInput(index + 1);
653
+ }
654
+ };
655
+ const handleKeyPress = (index, key) => {
656
+ if (key === "Backspace") {
657
+ if (digits[index]) {
658
+ const newDigits = [...digits];
659
+ newDigits[index] = "";
660
+ updateValue(newDigits);
661
+ } else if (index > 0) {
662
+ const newDigits = [...digits];
663
+ newDigits[index - 1] = "";
664
+ updateValue(newDigits);
665
+ focusInput(index - 1);
666
+ }
667
+ }
668
+ };
669
+ return /* @__PURE__ */ jsxRuntime.jsx(
670
+ reactNative.Animated.View,
671
+ {
672
+ style: [
673
+ s2.container,
674
+ { transform: [{ translateX: shakeTranslate }, { scale: scaleAnim }] }
675
+ ],
676
+ children: digits.map((digit, i) => /* @__PURE__ */ jsxRuntime.jsx(
677
+ reactNative.TextInput,
678
+ {
679
+ ref: (el) => {
680
+ inputRefs.current[i] = el;
681
+ },
682
+ value: digit,
683
+ editable: !disabled,
684
+ keyboardType: "number-pad",
685
+ maxLength: 1,
686
+ onChangeText: (text) => handleChange(i, text),
687
+ onKeyPress: ({ nativeEvent }) => handleKeyPress(i, nativeEvent.key),
688
+ onFocus: () => inputRefs.current[i]?.setNativeProps({ selection: { start: 0, end: 1 } }),
689
+ style: [
690
+ s2.input,
691
+ disabled && s2.inputDisabled,
692
+ internalError && s2.inputError
693
+ ],
694
+ accessibilityLabel: `Digit ${i + 1}`
695
+ },
696
+ i
697
+ ))
698
+ }
699
+ );
700
+ }
701
+ var PAYMAN_OTP = {
702
+ bg: "#FFFFFF",
703
+ border: "rgba(0,0,0,0.1)",
704
+ fg: "#18181b",
705
+ disabledBg: "rgba(0,0,0,0.03)"
706
+ };
707
+ var s2 = reactNative.StyleSheet.create({
708
+ container: { flexDirection: "row", gap: 8, justifyContent: "center" },
709
+ input: {
710
+ width: 44,
711
+ height: 50,
712
+ textAlign: "center",
713
+ fontSize: 20,
714
+ fontWeight: "600",
715
+ borderWidth: 1,
716
+ borderColor: PAYMAN_OTP.border,
717
+ borderRadius: 10,
718
+ color: PAYMAN_OTP.fg,
719
+ backgroundColor: PAYMAN_OTP.bg
720
+ },
721
+ inputDisabled: { backgroundColor: PAYMAN_OTP.disabledBg, opacity: 0.5 },
722
+ inputError: {
723
+ borderColor: OTP_ERROR_BORDER,
724
+ borderWidth: 1.5
725
+ }
726
+ });
727
+
728
+ // src/components/UserActionModal/constants.ts
729
+ var BUTTON_LABELS = {
730
+ /** Link-style actions (new layout) */
731
+ RESEND_CODE: "Resend OTP",
732
+ CANCEL_TRANSFER: "Cancel Payment",
733
+ /** Short cancel label for payee approval flows */
734
+ CANCEL: "Cancel"
735
+ };
736
+ var RESEND_OTP_COOLDOWN_SECONDS = 30;
737
+ var DEFAULT_OTP_MAX_LENGTH = 6;
738
+ var MIN_OTP_MAX_LENGTH = 1;
739
+ var MAX_OTP_MAX_LENGTH = 12;
740
+ var ACTION_PENDING_TIMEOUT_MS = 15e3;
741
+ var MODAL_CONTENT = {
742
+ LOADING_APPROVE: "Verifying...",
743
+ LOADING_REJECT: "Rejecting...",
744
+ LOADING_RESEND: "Resending...",
745
+ RESEND_AVAILABLE_IN: "Resend OTP in",
746
+ SECURED_BY_PREFIX: "Secured by",
747
+ SECURED_BY_BRAND: "Payman"
748
+ };
749
+
750
+ // src/components/UserActionModal/utils.ts
751
+ function getOtpSchemaFromRequest(schema) {
752
+ const properties = schema?.properties;
753
+ const otp = properties?.otp;
754
+ const maxLengthRaw = otp?.maxLength;
755
+ const parsedMaxLength = Number.isInteger(maxLengthRaw) ? Number(maxLengthRaw) : DEFAULT_OTP_MAX_LENGTH;
756
+ const clampedMaxLength = Math.min(
757
+ MAX_OTP_MAX_LENGTH,
758
+ Math.max(MIN_OTP_MAX_LENGTH, parsedMaxLength)
759
+ );
760
+ return {
761
+ maxLength: clampedMaxLength
762
+ };
763
+ }
764
+ function formatAmountForDisplay(amount) {
765
+ const normalized = amount.replace(/,/g, "").trim();
766
+ const n = Number(normalized);
767
+ if (!Number.isFinite(n)) {
768
+ return amount.startsWith("$") ? amount : `$${amount}`;
769
+ }
770
+ return new Intl.NumberFormat("en-US", {
771
+ style: "currency",
772
+ currency: "USD"
773
+ }).format(n);
774
+ }
775
+ var BRAND = "#15687d";
776
+ var TEXT_PRIMARY = "#111827";
777
+ var TEXT_SECONDARY = "#64748b";
778
+ var BORDER = "rgba(15,23,42,0.10)";
779
+ var OTP_ERROR_FLASH_MS = 600;
780
+ function InlineVerificationPanel({
781
+ userActionRequest,
782
+ clearOtpTrigger,
783
+ onApprove,
784
+ onReject,
785
+ onResend
786
+ }) {
787
+ const [otp, setOtp] = React.useState("");
788
+ const [actionType, setActionType] = React.useState(null);
789
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
790
+ const [resendCooldownRemaining, setResendCooldownRemaining] = React.useState(0);
791
+ const [otpError, setOtpError] = React.useState(false);
792
+ const entrance = React.useRef(new reactNative.Animated.Value(0)).current;
793
+ const lastAutoSubmittedRef = React.useRef("");
794
+ const submitInFlightRef = React.useRef(false);
795
+ const submitGenerationRef = React.useRef(0);
796
+ const schema = getOtpSchemaFromRequest(userActionRequest?.requestedSchema);
797
+ const resetActionState = React.useCallback(() => {
798
+ setIsSubmitting(false);
799
+ setActionType(null);
800
+ }, []);
801
+ React.useEffect(() => {
802
+ if (userActionRequest) {
803
+ setResendCooldownRemaining(RESEND_OTP_COOLDOWN_SECONDS);
804
+ entrance.setValue(0);
805
+ reactNative.Animated.timing(entrance, {
806
+ toValue: 1,
807
+ duration: 220,
808
+ easing: reactNative.Easing.out(reactNative.Easing.cubic),
809
+ useNativeDriver: true
810
+ }).start();
811
+ } else {
812
+ setOtp("");
813
+ resetActionState();
814
+ setResendCooldownRemaining(0);
815
+ setOtpError(false);
816
+ lastAutoSubmittedRef.current = "";
817
+ submitInFlightRef.current = false;
818
+ submitGenerationRef.current += 1;
819
+ }
820
+ }, [entrance, resetActionState, userActionRequest]);
821
+ React.useEffect(() => {
822
+ if (resendCooldownRemaining <= 0) return;
823
+ const timer = setTimeout(
824
+ () => setResendCooldownRemaining((prev) => prev - 1),
825
+ 1e3
826
+ );
827
+ return () => clearTimeout(timer);
828
+ }, [resendCooldownRemaining]);
829
+ React.useEffect(() => {
830
+ if (clearOtpTrigger <= 0) return;
831
+ setOtpError(true);
832
+ const timer = setTimeout(() => {
833
+ setOtpError(false);
834
+ setOtp("");
835
+ resetActionState();
836
+ }, OTP_ERROR_FLASH_MS);
837
+ return () => clearTimeout(timer);
838
+ }, [clearOtpTrigger, resetActionState]);
839
+ React.useEffect(() => {
840
+ if (!userActionRequest || !isSubmitting) return;
841
+ if (actionType !== "approve" && actionType !== "reject") return;
842
+ const timeout = setTimeout(
843
+ () => resetActionState(),
844
+ ACTION_PENDING_TIMEOUT_MS
845
+ );
846
+ return () => clearTimeout(timeout);
847
+ }, [actionType, isSubmitting, resetActionState, userActionRequest]);
848
+ React.useEffect(() => {
849
+ if (!userActionRequest) return;
850
+ if (otp.length !== schema.maxLength || !/^\d+$/.test(otp)) return;
851
+ if (isSubmitting || submitInFlightRef.current) return;
852
+ if (lastAutoSubmittedRef.current === otp) return;
853
+ lastAutoSubmittedRef.current = otp;
854
+ submitInFlightRef.current = true;
855
+ const submitGeneration = submitGenerationRef.current;
856
+ void (async () => {
857
+ setIsSubmitting(true);
858
+ setActionType("approve");
859
+ try {
860
+ await onApprove(otp);
861
+ } catch {
862
+ if (submitGenerationRef.current !== submitGeneration) return;
863
+ resetActionState();
864
+ lastAutoSubmittedRef.current = otp;
865
+ } finally {
866
+ if (submitGenerationRef.current !== submitGeneration) return;
867
+ submitInFlightRef.current = false;
868
+ }
869
+ })();
870
+ }, [
871
+ isSubmitting,
872
+ onApprove,
873
+ otp,
874
+ resetActionState,
875
+ schema.maxLength,
876
+ userActionRequest
877
+ ]);
878
+ const handleReject = React.useCallback(async () => {
879
+ setIsSubmitting(true);
880
+ setActionType("reject");
881
+ try {
882
+ await onReject();
883
+ } catch {
884
+ resetActionState();
885
+ }
886
+ }, [onReject, resetActionState]);
887
+ const handleResend = React.useCallback(async () => {
888
+ if (resendCooldownRemaining > 0) return;
889
+ setIsSubmitting(true);
890
+ setActionType("resend");
891
+ try {
892
+ await onResend();
893
+ setResendCooldownRemaining(RESEND_OTP_COOLDOWN_SECONDS);
894
+ } catch {
895
+ } finally {
896
+ setActionType(null);
897
+ setIsSubmitting(false);
898
+ }
899
+ }, [onResend, resendCooldownRemaining]);
900
+ if (!userActionRequest) return null;
901
+ const translateY = entrance.interpolate({
902
+ inputRange: [0, 1],
903
+ outputRange: [10, 0]
904
+ });
905
+ const isVerifying = actionType === "approve" && isSubmitting;
906
+ const isCancelling = actionType === "reject" && isSubmitting;
907
+ return /* @__PURE__ */ jsxRuntime.jsxs(
908
+ reactNative.Animated.View,
909
+ {
910
+ style: [
911
+ s3.panel,
912
+ { opacity: entrance, transform: [{ translateY }] }
913
+ ],
914
+ accessibilityLabel: "payman-inline-verification",
915
+ children: [
916
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s3.title, children: "Enter the verification code sent to your email" }),
917
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: s3.otpWrap, accessibilityLabel: "payman-otp-wrap", children: /* @__PURE__ */ jsxRuntime.jsx(
918
+ OtpInput,
919
+ {
920
+ value: otp,
921
+ onChange: setOtp,
922
+ maxLength: schema.maxLength,
923
+ disabled: isSubmitting,
924
+ error: otpError
925
+ }
926
+ ) }),
927
+ isVerifying ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s3.statusRow, children: [
928
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { size: "small", color: BRAND }),
929
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s3.statusText, children: MODAL_CONTENT.LOADING_APPROVE })
930
+ ] }) : null,
931
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s3.actions, children: [
932
+ /* @__PURE__ */ jsxRuntime.jsx(
933
+ reactNative.Pressable,
934
+ {
935
+ onPress: handleResend,
936
+ disabled: isSubmitting || resendCooldownRemaining > 0,
937
+ hitSlop: 8,
938
+ accessibilityLabel: "payman-inline-verification-resend",
939
+ children: /* @__PURE__ */ jsxRuntime.jsx(
940
+ reactNative.Text,
941
+ {
942
+ style: [
943
+ s3.actionText,
944
+ (isSubmitting || resendCooldownRemaining > 0) && s3.actionTextDisabled
945
+ ],
946
+ children: actionType === "resend" ? MODAL_CONTENT.LOADING_RESEND : resendCooldownRemaining > 0 ? `${MODAL_CONTENT.RESEND_AVAILABLE_IN} ${resendCooldownRemaining}s` : BUTTON_LABELS.RESEND_CODE
947
+ }
948
+ )
949
+ }
950
+ ),
951
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: s3.divider }),
952
+ /* @__PURE__ */ jsxRuntime.jsx(
953
+ reactNative.Pressable,
954
+ {
955
+ onPress: handleReject,
956
+ disabled: isSubmitting,
957
+ hitSlop: 8,
958
+ accessibilityLabel: "payman-inline-verification-cancel",
959
+ children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s3.cancelContent, children: [
960
+ isCancelling ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { size: "small", color: TEXT_SECONDARY }) : null,
961
+ /* @__PURE__ */ jsxRuntime.jsx(
962
+ reactNative.Text,
963
+ {
964
+ style: [
965
+ s3.actionText,
966
+ isSubmitting && !isCancelling && s3.actionTextDisabled
967
+ ],
968
+ children: isCancelling ? MODAL_CONTENT.LOADING_REJECT : BUTTON_LABELS.CANCEL
969
+ }
970
+ )
971
+ ] })
972
+ }
973
+ )
974
+ ] })
975
+ ]
976
+ }
977
+ );
978
+ }
979
+ var s3 = reactNative.StyleSheet.create({
980
+ panel: {
981
+ backgroundColor: "#f8fafc",
982
+ borderWidth: 1,
983
+ borderBottomWidth: 0,
984
+ borderColor: BORDER,
985
+ borderTopLeftRadius: 24,
986
+ borderTopRightRadius: 24,
987
+ paddingHorizontal: 14,
988
+ paddingTop: 14,
989
+ paddingBottom: 12
990
+ },
991
+ title: {
992
+ color: TEXT_PRIMARY,
993
+ fontSize: 14,
994
+ fontWeight: "600",
995
+ lineHeight: 20,
996
+ textAlign: "center",
997
+ marginBottom: 12
998
+ },
999
+ otpWrap: {
1000
+ alignItems: "center"
1001
+ },
1002
+ statusRow: {
1003
+ flexDirection: "row",
1004
+ alignItems: "center",
1005
+ justifyContent: "center",
1006
+ gap: 8,
1007
+ marginTop: 10
1008
+ },
1009
+ statusText: {
1010
+ color: TEXT_SECONDARY,
1011
+ fontSize: 12,
1012
+ fontWeight: "500"
1013
+ },
1014
+ actions: {
1015
+ flexDirection: "row",
1016
+ alignItems: "center",
1017
+ justifyContent: "center",
1018
+ gap: 12,
1019
+ marginTop: 12
1020
+ },
1021
+ actionText: {
1022
+ color: BRAND,
1023
+ fontSize: 12,
1024
+ fontWeight: "600"
1025
+ },
1026
+ actionTextDisabled: {
1027
+ color: TEXT_SECONDARY,
1028
+ opacity: 0.55
1029
+ },
1030
+ divider: {
1031
+ width: 1,
1032
+ height: 14,
1033
+ backgroundColor: BORDER
1034
+ },
1035
+ cancelContent: {
1036
+ flexDirection: "row",
1037
+ alignItems: "center",
1038
+ gap: 6
1039
+ }
1040
+ });
1041
+
1042
+ // src/utils/errorMessages.ts
1043
+ var WORKFLOW_FAILED = "WORKFLOW_FAILED";
1044
+ var STREAM_NOT_STARTED = "STREAM_NOT_STARTED";
1045
+ var HTTP_ERROR_PREFIX = /^HTTP\s+(\d+)\s*:\s*([\s\S]+)$/;
1046
+ function isFriendlyWorkflowError(errorDetails) {
1047
+ if (!errorDetails) return false;
1048
+ return errorDetails === WORKFLOW_FAILED || errorDetails === STREAM_NOT_STARTED || errorDetails.includes(WORKFLOW_FAILED);
1049
+ }
1050
+ function parseErrorPayload(payload) {
1051
+ try {
1052
+ const parsed = JSON.parse(payload);
1053
+ if (typeof parsed === "string") {
1054
+ return { message: parsed.trim() || void 0 };
1055
+ }
1056
+ if (typeof parsed === "object" && parsed !== null) {
1057
+ const record = parsed;
1058
+ return {
1059
+ status: typeof record.status === "number" ? record.status : void 0,
1060
+ message: typeof record.message === "string" && record.message.trim() ? record.message.trim() : void 0
1061
+ };
1062
+ }
1063
+ } catch {
1064
+ }
1065
+ return {};
1066
+ }
1067
+ function getConflictErrorMessage(errorDetails) {
1068
+ if (!errorDetails) return void 0;
1069
+ const trimmedError = errorDetails.trim();
1070
+ const httpMatch = trimmedError.match(HTTP_ERROR_PREFIX);
1071
+ const httpStatus = httpMatch ? Number(httpMatch[1]) : void 0;
1072
+ const rawPayload = (httpMatch ? httpMatch[2] : trimmedError).trim();
1073
+ const payload = parseErrorPayload(rawPayload);
1074
+ const status = payload.status ?? httpStatus;
1075
+ if (status !== 409) {
1076
+ return void 0;
1077
+ }
1078
+ if (payload.message) {
1079
+ return payload.message;
1080
+ }
1081
+ return rawPayload || void 0;
1082
+ }
1083
+ var TEAL = "#00858d";
1084
+ function UserMessageV2({
1085
+ message,
1086
+ actions,
1087
+ onEdit,
1088
+ onRetry,
1089
+ retryDisabled = false
1090
+ }) {
1091
+ const [copied, setCopied] = React.useState(false);
1092
+ const timerRef = React.useRef(null);
1093
+ const showCopyAction = actions?.copy ?? true;
1094
+ const showEditAction = actions?.edit ?? false;
1095
+ const showRetryAction = actions?.retry ?? false;
1096
+ const hasVisibleActions = showCopyAction || showEditAction && !!onEdit || showRetryAction && !!onRetry;
1097
+ const fadeIn = React.useRef(new reactNative.Animated.Value(0)).current;
1098
+ const slideIn = React.useRef(new reactNative.Animated.Value(8)).current;
1099
+ React.useEffect(() => {
1100
+ reactNative.Animated.parallel([
1101
+ reactNative.Animated.timing(fadeIn, {
1102
+ toValue: 1,
1103
+ duration: 200,
1104
+ easing: reactNative.Easing.out(reactNative.Easing.cubic),
1105
+ useNativeDriver: true
1106
+ }),
1107
+ reactNative.Animated.timing(slideIn, {
1108
+ toValue: 0,
1109
+ duration: 200,
1110
+ easing: reactNative.Easing.out(reactNative.Easing.cubic),
1111
+ useNativeDriver: true
1112
+ })
1113
+ ]).start();
1114
+ }, [fadeIn, slideIn]);
1115
+ const handleCopy = React.useCallback(() => {
1116
+ reactNative.Clipboard.setString(message.content);
1117
+ setCopied(true);
1118
+ if (timerRef.current) clearTimeout(timerRef.current);
1119
+ timerRef.current = setTimeout(() => setCopied(false), 1800);
1120
+ }, [message.content]);
1121
+ React.useEffect(() => {
1122
+ return () => {
1123
+ if (timerRef.current) clearTimeout(timerRef.current);
1124
+ };
1125
+ }, []);
1126
+ const conflictErr = message.errorDetails ? getConflictErrorMessage(message.errorDetails) ?? message.errorDetails : null;
1127
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1128
+ reactNative.Animated.View,
1129
+ {
1130
+ style: [s4.wrapper, { opacity: fadeIn, transform: [{ translateY: slideIn }] }],
1131
+ children: [
1132
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: s4.bubble, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { selectable: true, style: s4.text, children: message.content }) }),
1133
+ message.isError && conflictErr ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s4.errorRow, children: [
1134
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.AlertCircle, { size: 13, color: "rgba(239, 68, 68, 0.8)", strokeWidth: 2 }),
1135
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s4.errorText, children: conflictErr })
1136
+ ] }) : null,
1137
+ hasVisibleActions ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s4.actions, children: [
1138
+ showCopyAction ? /* @__PURE__ */ jsxRuntime.jsx(
1139
+ reactNative.Pressable,
1140
+ {
1141
+ onPress: handleCopy,
1142
+ hitSlop: 8,
1143
+ style: s4.actionBtn,
1144
+ accessibilityLabel: "Copy message",
1145
+ children: copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.Check, { size: 13, color: "#059669", strokeWidth: 2.5 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.Copy, { size: 13, color: "#94a3b8", strokeWidth: 2 })
1146
+ }
1147
+ ) : null,
1148
+ showEditAction && onEdit ? /* @__PURE__ */ jsxRuntime.jsx(
1149
+ reactNative.Pressable,
1150
+ {
1151
+ onPress: () => onEdit(message.id),
1152
+ hitSlop: 8,
1153
+ style: s4.actionBtn,
1154
+ accessibilityLabel: "Edit message",
1155
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.Pencil, { size: 13, color: "#94a3b8", strokeWidth: 2 })
1156
+ }
1157
+ ) : null,
1158
+ showRetryAction && onRetry ? /* @__PURE__ */ jsxRuntime.jsx(
1159
+ reactNative.Pressable,
1160
+ {
1161
+ onPress: () => onRetry(message.id),
1162
+ disabled: retryDisabled,
1163
+ hitSlop: 8,
1164
+ style: [s4.actionBtn, retryDisabled && s4.actionBtnDisabled],
1165
+ accessibilityLabel: "Retry message",
1166
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.RotateCcw, { size: 13, color: "#94a3b8", strokeWidth: 2 })
1167
+ }
1168
+ ) : null
1169
+ ] }) : null
1170
+ ]
1171
+ }
1172
+ );
1173
+ }
1174
+ var s4 = reactNative.StyleSheet.create({
1175
+ wrapper: {
1176
+ paddingHorizontal: 16,
1177
+ paddingVertical: 5,
1178
+ alignItems: "flex-end"
1179
+ },
1180
+ bubble: {
1181
+ backgroundColor: TEAL,
1182
+ borderRadius: 20,
1183
+ borderBottomRightRadius: 6,
1184
+ paddingHorizontal: 14,
1185
+ paddingVertical: 10,
1186
+ maxWidth: 320
1187
+ },
1188
+ text: {
1189
+ fontSize: 15,
1190
+ lineHeight: 22,
1191
+ color: "#fff"
1192
+ },
1193
+ errorRow: {
1194
+ flexDirection: "row",
1195
+ alignItems: "flex-start",
1196
+ gap: 6,
1197
+ marginTop: 4,
1198
+ paddingRight: 4,
1199
+ maxWidth: 320
1200
+ },
1201
+ errorText: {
1202
+ flex: 1,
1203
+ fontSize: 12,
1204
+ color: "rgba(239, 68, 68, 0.95)",
1205
+ lineHeight: 18
1206
+ },
1207
+ actions: {
1208
+ flexDirection: "row",
1209
+ marginTop: 6,
1210
+ gap: 4
1211
+ },
1212
+ actionBtn: {
1213
+ padding: 6,
1214
+ borderRadius: 8
1215
+ },
1216
+ actionBtnDisabled: {
1217
+ opacity: 0.45
1218
+ }
1219
+ });
1220
+ var THINKING_SPEED = {
1221
+ normal: [6, 8],
1222
+ fast: 1,
1223
+ punctuation: [20, 30],
1224
+ newline: [12, 18],
1225
+ idle: 30
1226
+ };
1227
+ var RESPONSE_SPEED = {
1228
+ normal: [4, 8],
1229
+ fast: 1,
1230
+ punctuation: [20, 30],
1231
+ newline: [10, 15],
1232
+ idle: 30
1233
+ };
1234
+ function charDelay(char, speed) {
1235
+ if (char === "*") return speed.fast;
1236
+ if (char === "\n") return speed.newline[0] + Math.random() * speed.newline[1];
1237
+ if (".!?,;:".includes(char))
1238
+ return speed.punctuation[0] + Math.random() * speed.punctuation[1];
1239
+ return speed.normal[0] + Math.random() * speed.normal[1];
1240
+ }
1241
+ var MARKDOWN_IMAGE_REGEX = /^!\[[^\]]*\]\([^)]*\)/;
1242
+ var typingProgressCache = /* @__PURE__ */ new Map();
1243
+ function useTypingEffect(targetText, enabled, speed = RESPONSE_SPEED, initialDisplayedText, cacheKey) {
1244
+ const cached = cacheKey ? typingProgressCache.get(cacheKey) : void 0;
1245
+ const hydratedFromCache = cached !== void 0 && targetText.startsWith(cached) ? cached : void 0;
1246
+ const [displayedText, setDisplayedText] = React.useState(hydratedFromCache ?? "");
1247
+ const displayedRef = React.useRef(hydratedFromCache ?? "");
1248
+ const targetRef = React.useRef(targetText);
1249
+ const enabledRef = React.useRef(enabled);
1250
+ const initialDisplayedRef = React.useRef(initialDisplayedText);
1251
+ const cacheKeyRef = React.useRef(cacheKey);
1252
+ const timerRef = React.useRef(null);
1253
+ const runningRef = React.useRef(false);
1254
+ targetRef.current = targetText;
1255
+ enabledRef.current = enabled;
1256
+ initialDisplayedRef.current = initialDisplayedText;
1257
+ cacheKeyRef.current = cacheKey;
1258
+ const writeDisplayed = (next) => {
1259
+ displayedRef.current = next;
1260
+ setDisplayedText(next);
1261
+ if (cacheKeyRef.current) {
1262
+ typingProgressCache.set(cacheKeyRef.current, next);
1263
+ }
1264
+ };
1265
+ React.useEffect(() => {
1266
+ if (!enabled) {
1267
+ if (timerRef.current) {
1268
+ clearTimeout(timerRef.current);
1269
+ timerRef.current = null;
1270
+ }
1271
+ runningRef.current = false;
1272
+ displayedRef.current = targetText;
1273
+ setDisplayedText(targetText);
1274
+ if (cacheKeyRef.current) {
1275
+ typingProgressCache.delete(cacheKeyRef.current);
1276
+ }
1277
+ return;
1278
+ }
1279
+ if (displayedRef.current && !targetRef.current.startsWith(displayedRef.current)) {
1280
+ displayedRef.current = "";
1281
+ setDisplayedText("");
1282
+ if (cacheKeyRef.current) typingProgressCache.delete(cacheKeyRef.current);
1283
+ }
1284
+ if (displayedRef.current.length === 0 && initialDisplayedRef.current && targetRef.current.startsWith(initialDisplayedRef.current)) {
1285
+ writeDisplayed(initialDisplayedRef.current);
1286
+ }
1287
+ if (runningRef.current) return;
1288
+ runningRef.current = true;
1289
+ const tick = () => {
1290
+ if (!enabledRef.current) {
1291
+ runningRef.current = false;
1292
+ return;
1293
+ }
1294
+ if (displayedRef.current && !targetRef.current.startsWith(displayedRef.current)) {
1295
+ let divergeAt = 0;
1296
+ const minLen = Math.min(displayedRef.current.length, targetRef.current.length);
1297
+ while (divergeAt < minLen && displayedRef.current[divergeAt] === targetRef.current[divergeAt]) {
1298
+ divergeAt++;
1299
+ }
1300
+ const imgStart = targetRef.current.slice(0, divergeAt).lastIndexOf("![");
1301
+ if (imgStart >= 0) {
1302
+ const newImgMatch = MARKDOWN_IMAGE_REGEX.exec(targetRef.current.slice(imgStart));
1303
+ const oldImgMatch = MARKDOWN_IMAGE_REGEX.exec(displayedRef.current.slice(imgStart));
1304
+ if (newImgMatch && oldImgMatch) {
1305
+ const oldImgEnd = imgStart + oldImgMatch[0].length;
1306
+ const newImgEnd = imgStart + newImgMatch[0].length;
1307
+ const newCursor = Math.min(
1308
+ Math.max(displayedRef.current.length + (newImgEnd - oldImgEnd), newImgEnd),
1309
+ targetRef.current.length
1310
+ );
1311
+ writeDisplayed(targetRef.current.slice(0, newCursor));
1312
+ timerRef.current = setTimeout(tick, 0);
1313
+ return;
1314
+ }
1315
+ }
1316
+ writeDisplayed(targetRef.current.slice(0, imgStart >= 0 ? imgStart : divergeAt));
1317
+ timerRef.current = setTimeout(tick, 0);
1318
+ return;
1319
+ }
1320
+ if (displayedRef.current.length < targetRef.current.length) {
1321
+ const remaining = targetRef.current.slice(displayedRef.current.length);
1322
+ const imgMatch = MARKDOWN_IMAGE_REGEX.exec(remaining);
1323
+ if (imgMatch) {
1324
+ writeDisplayed(displayedRef.current + imgMatch[0]);
1325
+ timerRef.current = setTimeout(tick, 0);
1326
+ return;
1327
+ }
1328
+ const nextChar = remaining[0];
1329
+ writeDisplayed(displayedRef.current + nextChar);
1330
+ const delay = charDelay(nextChar, speed);
1331
+ timerRef.current = setTimeout(tick, delay);
1332
+ } else {
1333
+ timerRef.current = setTimeout(tick, speed.idle);
1334
+ }
1335
+ };
1336
+ tick();
1337
+ return () => {
1338
+ if (timerRef.current) {
1339
+ clearTimeout(timerRef.current);
1340
+ timerRef.current = null;
1341
+ }
1342
+ runningRef.current = false;
1343
+ };
1344
+ }, [enabled]);
1345
+ const isTyping = enabled && displayedRef.current.length < targetRef.current.length;
1346
+ return {
1347
+ displayedText: enabled ? displayedText : targetText,
1348
+ isTyping
1349
+ };
1350
+ }
1351
+ var CURSOR_MESSAGES = [
1352
+ "Analyzing",
1353
+ "Processing",
1354
+ "Calculating",
1355
+ "Reviewing",
1356
+ "Verifying",
1357
+ "Assessing",
1358
+ "Evaluating",
1359
+ "Checking",
1360
+ "Planning",
1361
+ "Working",
1362
+ "Updating",
1363
+ "Validating",
1364
+ "Monitoring",
1365
+ "Optimizing",
1366
+ "Reconciling",
1367
+ "Forecasting",
1368
+ "Inspecting",
1369
+ "Organizing",
1370
+ "Sorting",
1371
+ "Scanning",
1372
+ "Balancing",
1373
+ "Summarizing",
1374
+ "Predicting",
1375
+ "Comparing",
1376
+ "Tracking",
1377
+ "Adjusting",
1378
+ "Examining",
1379
+ "Mapping",
1380
+ "Modeling",
1381
+ "Reporting",
1382
+ "Confirming"
1383
+ ];
1384
+ var FINAL_CURSOR_MESSAGE = "Finishing up";
1385
+ var INITIAL_THINKING_PLACEHOLDER = [
1386
+ "**Getting things ready**",
1387
+ "Putting things together"
1388
+ ].join("\n");
1389
+ var PAYMAN_TEAL2 = "#00858d";
1390
+ var TEXT_PRIMARY2 = "#0f172a";
1391
+ var TEXT_SECONDARY2 = "#475569";
1392
+ var TEXT_TERTIARY = "#94a3b8";
1393
+ var TEXT_MUTED = "#cbd5e1";
1394
+ if (reactNative.Platform.OS === "android" && reactNative.UIManager.setLayoutAnimationEnabledExperimental) {
1395
+ reactNative.UIManager.setLayoutAnimationEnabledExperimental(true);
1396
+ }
1397
+ function PaymanMarkNative({ size = 14 }) {
1398
+ const scale = React.useRef(new reactNative.Animated.Value(0.7)).current;
1399
+ const opacity = React.useRef(new reactNative.Animated.Value(0.6)).current;
1400
+ React.useEffect(() => {
1401
+ const loop = reactNative.Animated.loop(
1402
+ reactNative.Animated.parallel([
1403
+ reactNative.Animated.sequence([
1404
+ reactNative.Animated.timing(scale, {
1405
+ toValue: 1.6,
1406
+ duration: 1100,
1407
+ easing: reactNative.Easing.out(reactNative.Easing.cubic),
1408
+ useNativeDriver: true
1409
+ }),
1410
+ reactNative.Animated.timing(scale, {
1411
+ toValue: 0.7,
1412
+ duration: 0,
1413
+ useNativeDriver: true
1414
+ })
1415
+ ]),
1416
+ reactNative.Animated.sequence([
1417
+ reactNative.Animated.timing(opacity, {
1418
+ toValue: 0,
1419
+ duration: 1100,
1420
+ easing: reactNative.Easing.out(reactNative.Easing.cubic),
1421
+ useNativeDriver: true
1422
+ }),
1423
+ reactNative.Animated.timing(opacity, {
1424
+ toValue: 0.55,
1425
+ duration: 0,
1426
+ useNativeDriver: true
1427
+ })
1428
+ ])
1429
+ ])
1430
+ );
1431
+ loop.start();
1432
+ return () => loop.stop();
1433
+ }, [scale, opacity]);
1434
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [mark.wrap, { width: size, height: size }], children: [
1435
+ /* @__PURE__ */ jsxRuntime.jsx(
1436
+ reactNative.Animated.View,
1437
+ {
1438
+ style: [
1439
+ mark.ring,
1440
+ {
1441
+ width: size,
1442
+ height: size,
1443
+ borderRadius: size / 2,
1444
+ transform: [{ scale }],
1445
+ opacity
1446
+ }
1447
+ ]
1448
+ }
1449
+ ),
1450
+ /* @__PURE__ */ jsxRuntime.jsx(
1451
+ reactNative.View,
1452
+ {
1453
+ style: [
1454
+ mark.core,
1455
+ {
1456
+ width: size * 0.55,
1457
+ height: size * 0.55,
1458
+ borderRadius: size * 0.55
1459
+ }
1460
+ ]
1461
+ }
1462
+ )
1463
+ ] });
1464
+ }
1465
+ function ShimmerText({
1466
+ children,
1467
+ style
1468
+ }) {
1469
+ const opacity = React.useRef(new reactNative.Animated.Value(0.5)).current;
1470
+ React.useEffect(() => {
1471
+ const anim = reactNative.Animated.loop(
1472
+ reactNative.Animated.sequence([
1473
+ reactNative.Animated.timing(opacity, {
1474
+ toValue: 1,
1475
+ duration: 900,
1476
+ easing: reactNative.Easing.inOut(reactNative.Easing.ease),
1477
+ useNativeDriver: true
1478
+ }),
1479
+ reactNative.Animated.timing(opacity, {
1480
+ toValue: 0.5,
1481
+ duration: 900,
1482
+ easing: reactNative.Easing.inOut(reactNative.Easing.ease),
1483
+ useNativeDriver: true
1484
+ })
1485
+ ])
1486
+ );
1487
+ anim.start();
1488
+ return () => anim.stop();
1489
+ }, [opacity]);
1490
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.Text, { style: [style, { opacity }], selectable: false, children });
1491
+ }
1492
+ function AnimatedSeconds({ value, style }) {
1493
+ const prevRef = React.useRef(value);
1494
+ const opacity = React.useRef(new reactNative.Animated.Value(1)).current;
1495
+ const translate = React.useRef(new reactNative.Animated.Value(0)).current;
1496
+ const [shown, setShown] = React.useState(value);
1497
+ React.useEffect(() => {
1498
+ if (value === prevRef.current) return;
1499
+ prevRef.current = value;
1500
+ reactNative.Animated.sequence([
1501
+ reactNative.Animated.parallel([
1502
+ reactNative.Animated.timing(opacity, { toValue: 0, duration: 90, useNativeDriver: true }),
1503
+ reactNative.Animated.timing(translate, { toValue: -4, duration: 90, useNativeDriver: true })
1504
+ ])
1505
+ ]).start(() => {
1506
+ setShown(value);
1507
+ translate.setValue(4);
1508
+ reactNative.Animated.parallel([
1509
+ reactNative.Animated.timing(opacity, { toValue: 1, duration: 140, useNativeDriver: true }),
1510
+ reactNative.Animated.timing(translate, { toValue: 0, duration: 140, useNativeDriver: true })
1511
+ ]).start();
1512
+ });
1513
+ }, [value, opacity, translate]);
1514
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.Text, { style: [style, { opacity, transform: [{ translateY: translate }] }], selectable: false, children: formatDuration(shown) });
1515
+ }
1516
+ function formatDuration(seconds) {
1517
+ if (seconds < 60) return `${seconds}s`;
1518
+ const m = Math.floor(seconds / 60);
1519
+ const s9 = seconds % 60;
1520
+ return s9 > 0 ? `${m}m ${s9}s` : `${m}m`;
1521
+ }
1522
+ function parseThinking(content) {
1523
+ const lines = content.split("\n");
1524
+ const out = [];
1525
+ for (const raw of lines) {
1526
+ const line = raw.trim();
1527
+ if (!line) continue;
1528
+ const stmt = line.match(/^\*\*(.+)\*\*$/);
1529
+ if (stmt) {
1530
+ out.push({ type: "statement", text: stmt[1].trim() });
1531
+ continue;
1532
+ }
1533
+ if (line.startsWith("\u2713 ")) {
1534
+ out.push({ type: "status", variant: "success", text: line.slice(2).trim() });
1535
+ continue;
1536
+ }
1537
+ if (line.startsWith("\u2717 ")) {
1538
+ out.push({ type: "status", variant: "error", text: line.slice(2).trim() });
1539
+ continue;
1540
+ }
1541
+ out.push({ type: "detail", text: line });
1542
+ }
1543
+ return out;
1544
+ }
1545
+ function ThinkingBlock({
1546
+ content,
1547
+ isStreaming,
1548
+ durationSec,
1549
+ startedAt
1550
+ }) {
1551
+ const [open, setOpen] = React.useState(true);
1552
+ const [cursorIdx, setCursorIdx] = React.useState(0);
1553
+ const [elapsedSec, setElapsedSec] = React.useState(
1554
+ () => isStreaming && startedAt ? Math.max(0, Math.floor((Date.now() - startedAt) / 1e3)) : 0
1555
+ );
1556
+ const elapsedSecRef = React.useRef(elapsedSec);
1557
+ const frozenSecRef = React.useRef(null);
1558
+ const prevStreaming = React.useRef(isStreaming);
1559
+ const chevronRot = React.useRef(new reactNative.Animated.Value(open ? 1 : 0)).current;
1560
+ const parsed = React.useMemo(() => parseThinking(content), [content]);
1561
+ const isFinalizingPhase = React.useMemo(() => {
1562
+ const statements = parsed.filter(
1563
+ (l) => l.type === "statement"
1564
+ );
1565
+ return statements.length > 0 && statements[statements.length - 1].text === "Finalizing";
1566
+ }, [parsed]);
1567
+ React.useEffect(() => {
1568
+ if (prevStreaming.current && !isStreaming) {
1569
+ reactNative.LayoutAnimation.configureNext({
1570
+ duration: 220,
1571
+ create: { type: "easeInEaseOut", property: "opacity" },
1572
+ update: { type: "easeInEaseOut" },
1573
+ delete: { type: "easeInEaseOut", property: "opacity" }
1574
+ });
1575
+ setOpen(false);
1576
+ frozenSecRef.current = elapsedSecRef.current;
1577
+ }
1578
+ prevStreaming.current = isStreaming;
1579
+ }, [isStreaming]);
1580
+ React.useEffect(() => {
1581
+ if (!isStreaming || !startedAt) return;
1582
+ let active = true;
1583
+ const tick = () => {
1584
+ if (!active) return;
1585
+ const val = Math.max(0, Math.floor((Date.now() - startedAt) / 1e3));
1586
+ elapsedSecRef.current = val;
1587
+ setElapsedSec(val);
1588
+ };
1589
+ tick();
1590
+ const id = setInterval(tick, 1e3);
1591
+ return () => {
1592
+ active = false;
1593
+ clearInterval(id);
1594
+ };
1595
+ }, [isStreaming, startedAt]);
1596
+ React.useEffect(() => {
1597
+ if (!isStreaming || isFinalizingPhase) return;
1598
+ const id = setInterval(() => {
1599
+ setCursorIdx((i) => (i + 1) % CURSOR_MESSAGES.length);
1600
+ }, 4e3);
1601
+ return () => clearInterval(id);
1602
+ }, [isStreaming, isFinalizingPhase]);
1603
+ React.useEffect(() => {
1604
+ reactNative.Animated.timing(chevronRot, {
1605
+ toValue: open ? 1 : 0,
1606
+ duration: 180,
1607
+ easing: reactNative.Easing.inOut(reactNative.Easing.ease),
1608
+ useNativeDriver: true
1609
+ }).start();
1610
+ }, [open, chevronRot]);
1611
+ const justStoppedSec = !isStreaming && prevStreaming.current && startedAt ? Math.max(0, Math.floor((Date.now() - startedAt) / 1e3)) : void 0;
1612
+ const finalSec = (() => {
1613
+ const candidates = [
1614
+ frozenSecRef.current,
1615
+ justStoppedSec,
1616
+ frozenSecRef.current == null && !prevStreaming.current ? durationSec : void 0
1617
+ ].filter((v) => typeof v === "number" && Number.isFinite(v));
1618
+ return candidates.length ? Math.max(...candidates) : void 0;
1619
+ })();
1620
+ const cursorText = isFinalizingPhase ? FINAL_CURSOR_MESSAGE : CURSOR_MESSAGES[cursorIdx];
1621
+ const toggle = React.useCallback(() => {
1622
+ reactNative.LayoutAnimation.configureNext({
1623
+ duration: 200,
1624
+ create: { type: "easeInEaseOut", property: "opacity" },
1625
+ update: { type: "easeInEaseOut" },
1626
+ delete: { type: "easeInEaseOut", property: "opacity" }
1627
+ });
1628
+ setOpen((o) => !o);
1629
+ }, []);
1630
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: ts.container, children: [
1631
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Pressable, { style: ts.header, onPress: toggle, hitSlop: 6, children: [
1632
+ /* @__PURE__ */ jsxRuntime.jsx(
1633
+ reactNative.Animated.View,
1634
+ {
1635
+ style: {
1636
+ transform: [
1637
+ {
1638
+ rotate: chevronRot.interpolate({
1639
+ inputRange: [0, 1],
1640
+ outputRange: ["0deg", "90deg"]
1641
+ })
1642
+ }
1643
+ ]
1644
+ },
1645
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.ChevronRight, { size: 14, color: TEXT_TERTIARY, strokeWidth: 2.25 })
1646
+ }
1647
+ ),
1648
+ isStreaming ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: ts.headerLabelRow, children: [
1649
+ /* @__PURE__ */ jsxRuntime.jsx(ShimmerText, { style: ts.headerLabel, children: "Working on it\u2026" }),
1650
+ startedAt !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx(AnimatedSeconds, { value: elapsedSec, style: ts.timerText }) : null
1651
+ ] }) : finalSec != null && finalSec > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: ts.headerLabelRow, children: [
1652
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: ts.headerLabelStatic, children: "Thought for " }),
1653
+ /* @__PURE__ */ jsxRuntime.jsx(AnimatedSeconds, { value: finalSec, style: ts.headerLabelStatic })
1654
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: ts.headerLabelStatic, children: "Thought" })
1655
+ ] }),
1656
+ open ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: ts.body, children: [
1657
+ parsed.map((item, i) => {
1658
+ if (item.type === "statement") {
1659
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: ts.statement, children: item.text }, i);
1660
+ }
1661
+ if (item.type === "status") {
1662
+ return /* @__PURE__ */ jsxRuntime.jsx(
1663
+ reactNative.View,
1664
+ {
1665
+ style: [
1666
+ ts.statusBadge,
1667
+ item.variant === "success" ? ts.statusSuccessBg : ts.statusErrorBg
1668
+ ],
1669
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1670
+ reactNative.Text,
1671
+ {
1672
+ style: [
1673
+ ts.statusBadgeText,
1674
+ item.variant === "success" ? ts.statusSuccessText : ts.statusErrorText
1675
+ ],
1676
+ children: item.text
1677
+ }
1678
+ )
1679
+ },
1680
+ i
1681
+ );
1682
+ }
1683
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: ts.detail, children: item.text }, i);
1684
+ }),
1685
+ isStreaming ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: ts.cursorRow, children: [
1686
+ /* @__PURE__ */ jsxRuntime.jsx(PaymanMarkNative, { size: 14 }),
1687
+ /* @__PURE__ */ jsxRuntime.jsx(ShimmerText, { style: ts.cursorLabel, children: cursorText })
1688
+ ] }) : null
1689
+ ] }) : null
1690
+ ] });
1691
+ }
1692
+ function StreamingDot() {
1693
+ const opacity = React.useRef(new reactNative.Animated.Value(0.3)).current;
1694
+ React.useEffect(() => {
1695
+ const anim = reactNative.Animated.loop(
1696
+ reactNative.Animated.sequence([
1697
+ reactNative.Animated.timing(opacity, { toValue: 1, duration: 700, easing: reactNative.Easing.inOut(reactNative.Easing.ease), useNativeDriver: true }),
1698
+ reactNative.Animated.timing(opacity, { toValue: 0.3, duration: 700, easing: reactNative.Easing.inOut(reactNative.Easing.ease), useNativeDriver: true })
1699
+ ])
1700
+ );
1701
+ anim.start();
1702
+ return () => anim.stop();
1703
+ }, [opacity]);
1704
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: [dotStyle.dot, { opacity }] });
1705
+ }
1706
+ function getFormattedThinking(message, includeInitialPlaceholder) {
1707
+ const plain = message.allThinkingText || message.activeThinkingText || "";
1708
+ const base = message.formattedThinkingText || paymanTypescriptAskSdk.buildFormattedThinking(message.steps, plain);
1709
+ if (includeInitialPlaceholder && base) {
1710
+ return INITIAL_THINKING_PLACEHOLDER + "\n" + base;
1711
+ }
1712
+ if (includeInitialPlaceholder) {
1713
+ return INITIAL_THINKING_PLACEHOLDER;
1714
+ }
1715
+ return base;
1716
+ }
1717
+ function AssistantMessageV2({
1718
+ message,
1719
+ onExecutionTraceClick: _onExecutionTraceClick,
1720
+ actions
1721
+ }) {
1722
+ const [copied, setCopied] = React.useState(false);
1723
+ const copyTimerRef = React.useRef(null);
1724
+ const showCopyAction = actions?.copy ?? true;
1725
+ const isHistorical = !!message.isHistorical;
1726
+ const hasEverStreamed = React.useRef(!!message.isStreaming && !isHistorical);
1727
+ const hasShownInitialThinking = React.useRef(
1728
+ !isHistorical && message.streamProgress === "processing"
1729
+ );
1730
+ if (message.isStreaming && !isHistorical) hasEverStreamed.current = true;
1731
+ const fadeIn = React.useRef(new reactNative.Animated.Value(0)).current;
1732
+ React.useEffect(() => {
1733
+ reactNative.Animated.timing(fadeIn, {
1734
+ toValue: 1,
1735
+ duration: 220,
1736
+ easing: reactNative.Easing.out(reactNative.Easing.cubic),
1737
+ useNativeDriver: true
1738
+ }).start();
1739
+ }, [fadeIn]);
1740
+ const rawResponseContent = (() => {
1741
+ const raw = message.isStreaming && !isHistorical ? message.streamingContent || message.content : message.content;
1742
+ if (!raw) return "";
1743
+ return raw.replace(/\\n/g, "\n");
1744
+ })();
1745
+ const hasReadyStreamPhase = !isHistorical && (message.streamProgress === "processing" || Boolean(message.steps?.length) || Boolean(message.allThinkingText) || Boolean(message.activeThinkingText) || Boolean(rawResponseContent));
1746
+ if (hasReadyStreamPhase && !message.isError) {
1747
+ hasShownInitialThinking.current = true;
1748
+ }
1749
+ const includeInitialPlaceholder = !isHistorical && hasShownInitialThinking.current && !message.isError;
1750
+ const rawThinkingContent = React.useMemo(
1751
+ () => getFormattedThinking(message, includeInitialPlaceholder),
1752
+ [message, includeInitialPlaceholder]
1753
+ );
1754
+ const isThinkingStreaming = !isHistorical && !!message.isStreaming && !rawResponseContent && !message.isError;
1755
+ const { displayedText: thinkingContent } = useTypingEffect(
1756
+ rawThinkingContent,
1757
+ hasEverStreamed.current && isThinkingStreaming,
1758
+ THINKING_SPEED,
1759
+ includeInitialPlaceholder ? INITIAL_THINKING_PLACEHOLDER : void 0,
1760
+ `thinking:${message.id}`
1761
+ );
1762
+ const hasThinkingContent = Boolean(thinkingContent);
1763
+ const showThinkingBlock = !isHistorical && (hasThinkingContent || isThinkingStreaming);
1764
+ const showLegacyThinkingPhase = !isHistorical && !!message.isStreaming && !message.isError && !rawResponseContent && message.streamProgress === "started";
1765
+ const responseTypingEnabled = !isHistorical && hasEverStreamed.current && Boolean(rawResponseContent) && !message.isError;
1766
+ const { displayedText: displayContent, isTyping: isResponseTyping } = useTypingEffect(
1767
+ rawResponseContent,
1768
+ responseTypingEnabled,
1769
+ RESPONSE_SPEED,
1770
+ void 0,
1771
+ `response:${message.id}`
1772
+ );
1773
+ const requestStartedAt = React.useMemo(() => {
1774
+ if (!message.timestamp) return void 0;
1775
+ const t = Date.parse(message.timestamp);
1776
+ return Number.isFinite(t) ? t : void 0;
1777
+ }, [message.timestamp]);
1778
+ const thinkingDuration = React.useMemo(() => {
1779
+ const steps = message.steps;
1780
+ if (!steps || steps.length === 0) return void 0;
1781
+ const last = steps[steps.length - 1];
1782
+ if (requestStartedAt && last.timestamp) {
1783
+ return Math.max(0, Math.round((last.timestamp - requestStartedAt) / 1e3));
1784
+ }
1785
+ const first = steps[0];
1786
+ if (first.timestamp && last.timestamp) {
1787
+ return Math.round((last.timestamp - first.timestamp) / 1e3);
1788
+ }
1789
+ const total = steps.reduce((sum, s9) => sum + (s9.elapsedMs || 0), 0);
1790
+ return total > 0 ? Math.round(total / 1e3) : void 0;
1791
+ }, [message.steps, requestStartedAt]);
1792
+ const handleCopy = React.useCallback(() => {
1793
+ reactNative.Clipboard.setString(displayContent);
1794
+ setCopied(true);
1795
+ if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
1796
+ copyTimerRef.current = setTimeout(() => setCopied(false), 1800);
1797
+ }, [displayContent]);
1798
+ React.useEffect(() => {
1799
+ return () => {
1800
+ if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
1801
+ };
1802
+ }, []);
1803
+ const conflictErrorMessage = getConflictErrorMessage(message.errorDetails);
1804
+ const isConflictError = Boolean(conflictErrorMessage);
1805
+ const resolvedErrorText = (() => {
1806
+ if (conflictErrorMessage) return conflictErrorMessage;
1807
+ if (isFriendlyWorkflowError(message.errorDetails) && !message.errorDetails) {
1808
+ return "Oops, something went wrong. Please try again.";
1809
+ }
1810
+ return message.errorDetails;
1811
+ })();
1812
+ if (isConflictError) {
1813
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: [s5.wrapper, { opacity: fadeIn }], children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s5.errorRow, children: [
1814
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.AlertCircle, { size: 15, color: "#ef4444", strokeWidth: 2 }),
1815
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { selectable: true, style: s5.errorText, children: conflictErrorMessage })
1816
+ ] }) });
1817
+ }
1818
+ if (message.isError && !displayContent && !hasThinkingContent) {
1819
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: [s5.wrapper, { opacity: fadeIn }], children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s5.errorRow, children: [
1820
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.AlertCircle, { size: 15, color: "#ef4444", strokeWidth: 2 }),
1821
+ resolvedErrorText ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { selectable: true, style: s5.errorText, children: resolvedErrorText }) : null
1822
+ ] }) });
1823
+ }
1824
+ if (showLegacyThinkingPhase && !showThinkingBlock) {
1825
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Animated.View, { style: [s5.wrapper, { opacity: fadeIn }], children: /* @__PURE__ */ jsxRuntime.jsx(ShimmerText, { style: s5.legacyThinking, children: "Working on it\u2026" }) });
1826
+ }
1827
+ const hasPartialError = message.isError && displayContent && !isConflictError;
1828
+ const isCancelled = message.isCancelled;
1829
+ const isDone = !message.isStreaming && displayContent && !hasPartialError && !isResponseTyping;
1830
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Animated.View, { style: [s5.wrapper, { opacity: fadeIn }], children: [
1831
+ showThinkingBlock ? /* @__PURE__ */ jsxRuntime.jsx(
1832
+ ThinkingBlock,
1833
+ {
1834
+ content: thinkingContent,
1835
+ isStreaming: isThinkingStreaming,
1836
+ durationSec: message.thinkingDurationSec ?? thinkingDuration,
1837
+ startedAt: requestStartedAt
1838
+ }
1839
+ ) : null,
1840
+ displayContent ? isResponseTyping ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { selectable: true, style: s5.plainText, children: displayContent }) : /* @__PURE__ */ jsxRuntime.jsx(Markdown__default.default, { style: mdStyles, children: displayContent }) : !isThinkingStreaming && !hasThinkingContent ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s5.placeholder, children: "\u2026" }) : null,
1841
+ isCancelled && message.isStreaming ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s5.pausedRow, children: [
1842
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.WifiOff, { size: 14, color: "rgba(217, 119, 6, 0.85)", strokeWidth: 2 }),
1843
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s5.pausedText, children: "Connection slow \u2014 resuming\u2026" })
1844
+ ] }) : null,
1845
+ hasPartialError ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s5.errorRow, children: [
1846
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.AlertCircle, { size: 15, color: "#ef4444", strokeWidth: 2 }),
1847
+ resolvedErrorText ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { selectable: true, style: s5.errorText, children: resolvedErrorText }) : null
1848
+ ] }) : null,
1849
+ message.isStreaming && displayContent && !isCancelled ? /* @__PURE__ */ jsxRuntime.jsx(StreamingDot, {}) : null,
1850
+ isDone && showCopyAction ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: s5.actions, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { onPress: handleCopy, hitSlop: 8, style: s5.actionBtn, children: copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.Check, { size: 14, color: "#059669", strokeWidth: 2.5 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.Copy, { size: 14, color: TEXT_TERTIARY, strokeWidth: 2 }) }) }) : null
1851
+ ] });
1852
+ }
1853
+ var s5 = reactNative.StyleSheet.create({
1854
+ wrapper: {
1855
+ paddingHorizontal: 16,
1856
+ paddingVertical: 6,
1857
+ alignItems: "flex-start"
1858
+ },
1859
+ plainText: {
1860
+ fontSize: 15,
1861
+ lineHeight: 23,
1862
+ color: TEXT_PRIMARY2
1863
+ },
1864
+ placeholder: {
1865
+ fontSize: 14,
1866
+ color: TEXT_MUTED
1867
+ },
1868
+ legacyThinking: {
1869
+ fontSize: 14,
1870
+ color: TEXT_SECONDARY2,
1871
+ fontStyle: "italic"
1872
+ },
1873
+ errorRow: {
1874
+ flexDirection: "row",
1875
+ alignItems: "flex-start",
1876
+ gap: 8,
1877
+ marginTop: 4
1878
+ },
1879
+ errorText: {
1880
+ flex: 1,
1881
+ fontSize: 14,
1882
+ color: "#ef4444",
1883
+ lineHeight: 20
1884
+ },
1885
+ pausedRow: {
1886
+ flexDirection: "row",
1887
+ alignItems: "center",
1888
+ gap: 6,
1889
+ marginTop: 6
1890
+ },
1891
+ pausedText: {
1892
+ fontSize: 13,
1893
+ color: "rgba(217, 119, 6, 0.95)"
1894
+ },
1895
+ actions: {
1896
+ flexDirection: "row",
1897
+ marginTop: 6,
1898
+ gap: 4
1899
+ },
1900
+ actionBtn: {
1901
+ padding: 6,
1902
+ borderRadius: 8
1903
+ }
1904
+ });
1905
+ var ts = reactNative.StyleSheet.create({
1906
+ container: {
1907
+ marginBottom: 8,
1908
+ paddingLeft: 4,
1909
+ alignSelf: "stretch"
1910
+ },
1911
+ header: {
1912
+ flexDirection: "row",
1913
+ alignItems: "center",
1914
+ gap: 8,
1915
+ paddingVertical: 4
1916
+ },
1917
+ headerLabelRow: {
1918
+ flexDirection: "row",
1919
+ alignItems: "center"
1920
+ },
1921
+ headerLabel: {
1922
+ fontSize: 13,
1923
+ color: TEXT_SECONDARY2,
1924
+ fontWeight: "500"
1925
+ },
1926
+ headerLabelStatic: {
1927
+ fontSize: 13,
1928
+ color: TEXT_SECONDARY2,
1929
+ fontWeight: "500"
1930
+ },
1931
+ timerText: {
1932
+ fontSize: 13,
1933
+ color: TEXT_TERTIARY,
1934
+ marginLeft: 6,
1935
+ fontVariant: ["tabular-nums"]
1936
+ },
1937
+ body: {
1938
+ marginTop: 6,
1939
+ marginLeft: 22,
1940
+ paddingLeft: 12,
1941
+ borderLeftWidth: 2,
1942
+ borderLeftColor: "rgba(0,133,141,0.15)",
1943
+ gap: 4
1944
+ },
1945
+ statement: {
1946
+ fontSize: 13,
1947
+ fontWeight: "500",
1948
+ color: TEXT_PRIMARY2,
1949
+ marginTop: 4
1950
+ },
1951
+ detail: {
1952
+ fontSize: 13,
1953
+ color: TEXT_SECONDARY2,
1954
+ lineHeight: 20
1955
+ },
1956
+ statusBadge: {
1957
+ alignSelf: "flex-start",
1958
+ borderRadius: 999,
1959
+ paddingHorizontal: 10,
1960
+ paddingVertical: 3,
1961
+ borderWidth: reactNative.StyleSheet.hairlineWidth,
1962
+ marginTop: 2
1963
+ },
1964
+ statusBadgeText: {
1965
+ fontSize: 11,
1966
+ fontWeight: "500"
1967
+ },
1968
+ statusSuccessBg: {
1969
+ backgroundColor: "rgba(5,150,105,0.06)",
1970
+ borderColor: "rgba(5,150,105,0.18)"
1971
+ },
1972
+ statusSuccessText: { color: "#059669" },
1973
+ statusErrorBg: {
1974
+ backgroundColor: "rgba(239,68,68,0.06)",
1975
+ borderColor: "rgba(239,68,68,0.18)"
1976
+ },
1977
+ statusErrorText: { color: "#ef4444" },
1978
+ cursorRow: {
1979
+ flexDirection: "row",
1980
+ alignItems: "center",
1981
+ gap: 8,
1982
+ marginTop: 4,
1983
+ minHeight: 18
1984
+ },
1985
+ cursorLabel: {
1986
+ fontSize: 13,
1987
+ color: TEXT_SECONDARY2
1988
+ }
1989
+ });
1990
+ var dotStyle = reactNative.StyleSheet.create({
1991
+ dot: {
1992
+ width: 7,
1993
+ height: 7,
1994
+ borderRadius: 4,
1995
+ backgroundColor: PAYMAN_TEAL2,
1996
+ marginTop: 6
1997
+ }
1998
+ });
1999
+ var mark = reactNative.StyleSheet.create({
2000
+ wrap: {
2001
+ alignItems: "center",
2002
+ justifyContent: "center",
2003
+ position: "relative"
2004
+ },
2005
+ ring: {
2006
+ position: "absolute",
2007
+ borderWidth: 1.5,
2008
+ borderColor: PAYMAN_TEAL2,
2009
+ backgroundColor: "transparent"
2010
+ },
2011
+ core: {
2012
+ backgroundColor: PAYMAN_TEAL2
2013
+ }
2014
+ });
2015
+ var mdStyles = reactNative.StyleSheet.create({
2016
+ body: {
2017
+ fontSize: 15,
2018
+ lineHeight: 23,
2019
+ color: TEXT_PRIMARY2
2020
+ },
2021
+ heading1: { fontSize: 20, fontWeight: "700", color: TEXT_PRIMARY2, marginTop: 12, marginBottom: 4 },
2022
+ heading2: { fontSize: 17, fontWeight: "700", color: TEXT_PRIMARY2, marginTop: 10, marginBottom: 4 },
2023
+ heading3: { fontSize: 15, fontWeight: "600", color: TEXT_PRIMARY2, marginTop: 8, marginBottom: 2 },
2024
+ strong: { fontWeight: "700" },
2025
+ em: { fontStyle: "italic" },
2026
+ code_inline: {
2027
+ fontFamily: reactNative.Platform.OS === "ios" ? "Menlo" : "monospace",
2028
+ fontSize: 13,
2029
+ backgroundColor: "rgba(15,23,42,0.06)",
2030
+ borderRadius: 4,
2031
+ paddingHorizontal: 4,
2032
+ color: TEXT_PRIMARY2
2033
+ },
2034
+ fence: {
2035
+ backgroundColor: "rgba(15,23,42,0.05)",
2036
+ borderRadius: 8,
2037
+ padding: 12,
2038
+ marginVertical: 6,
2039
+ fontFamily: reactNative.Platform.OS === "ios" ? "Menlo" : "monospace",
2040
+ fontSize: 13,
2041
+ color: TEXT_PRIMARY2
2042
+ },
2043
+ blockquote: {
2044
+ borderLeftWidth: 3,
2045
+ borderLeftColor: "#cbd5e1",
2046
+ paddingLeft: 12,
2047
+ marginLeft: 0,
2048
+ marginVertical: 4,
2049
+ opacity: 0.8
2050
+ },
2051
+ bullet_list: { marginVertical: 4 },
2052
+ ordered_list: { marginVertical: 4 },
2053
+ list_item: { marginVertical: 2 },
2054
+ hr: { backgroundColor: "rgba(15,23,42,0.1)", height: 1, marginVertical: 8 },
2055
+ link: { color: PAYMAN_TEAL2, textDecorationLine: "underline" },
2056
+ table: {
2057
+ borderWidth: 1,
2058
+ borderColor: "rgba(15,23,42,0.1)",
2059
+ borderRadius: 6,
2060
+ marginVertical: 6,
2061
+ overflow: "hidden"
2062
+ },
2063
+ th: { backgroundColor: "rgba(15,23,42,0.05)", padding: 8, fontWeight: "600", fontSize: 13 },
2064
+ td: {
2065
+ padding: 8,
2066
+ fontSize: 13,
2067
+ borderTopWidth: 1,
2068
+ borderTopColor: "rgba(15,23,42,0.07)"
2069
+ }
2070
+ });
2071
+ var NEAR_BOTTOM_THRESHOLD = 120;
2072
+ var MessageListV2 = React.forwardRef(
2073
+ function MessageListV22({
2074
+ messages,
2075
+ isLoadingSession = false,
2076
+ onEditUserMessage,
2077
+ onRetryUserMessage,
2078
+ onImageClick: _onImageClick,
2079
+ onExecutionTraceClick,
2080
+ messageActions,
2081
+ retryDisabled = false
2082
+ // userAction props are handled by the modal in PaymanChat.native — ignored here
2083
+ }, ref) {
2084
+ const scrollViewRef = React.useRef(null);
2085
+ const followingBottomRef = React.useRef(true);
2086
+ const isProgrammaticScrollRef = React.useRef(false);
2087
+ const prevCountRef = React.useRef(messages.length);
2088
+ const [showScrollBtn, setShowScrollBtn] = React.useState(false);
2089
+ const scrollToBottom = React.useCallback((animated = false) => {
2090
+ isProgrammaticScrollRef.current = true;
2091
+ followingBottomRef.current = true;
2092
+ setShowScrollBtn(false);
2093
+ scrollViewRef.current?.scrollToEnd({ animated });
2094
+ const clear = () => {
2095
+ isProgrammaticScrollRef.current = false;
2096
+ };
2097
+ if (animated) {
2098
+ setTimeout(clear, 400);
2099
+ } else {
2100
+ requestAnimationFrame(clear);
2101
+ }
2102
+ }, []);
2103
+ React.useImperativeHandle(
2104
+ ref,
2105
+ () => ({
2106
+ scrollToBottom: (animated = false) => scrollToBottom(animated)
2107
+ }),
2108
+ [scrollToBottom]
2109
+ );
2110
+ React.useEffect(() => {
2111
+ const prevCount = prevCountRef.current;
2112
+ prevCountRef.current = messages.length;
2113
+ if (messages.length > prevCount) {
2114
+ const last = messages[messages.length - 1];
2115
+ if (last?.role === "user" || followingBottomRef.current) {
2116
+ followingBottomRef.current = true;
2117
+ requestAnimationFrame(() => scrollToBottom(false));
2118
+ }
2119
+ }
2120
+ }, [messages.length, scrollToBottom]);
2121
+ React.useEffect(() => {
2122
+ if (messages.length > 0) {
2123
+ setTimeout(() => scrollToBottom(false), 50);
2124
+ }
2125
+ }, []);
2126
+ const handleContentSizeChange = React.useCallback(() => {
2127
+ if (followingBottomRef.current) {
2128
+ scrollViewRef.current?.scrollToEnd({ animated: false });
2129
+ }
2130
+ }, []);
2131
+ const handleScroll = React.useCallback(
2132
+ (e) => {
2133
+ if (isProgrammaticScrollRef.current) return;
2134
+ const { contentOffset, contentSize, layoutMeasurement } = e.nativeEvent;
2135
+ const distanceFromBottom = contentSize.height - contentOffset.y - layoutMeasurement.height;
2136
+ const nearBottom = distanceFromBottom <= NEAR_BOTTOM_THRESHOLD;
2137
+ followingBottomRef.current = nearBottom;
2138
+ setShowScrollBtn(!nearBottom);
2139
+ },
2140
+ []
2141
+ );
2142
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s6.root, children: [
2143
+ /* @__PURE__ */ jsxRuntime.jsxs(
2144
+ reactNative.ScrollView,
2145
+ {
2146
+ ref: scrollViewRef,
2147
+ style: s6.scroll,
2148
+ contentContainerStyle: s6.content,
2149
+ onScroll: handleScroll,
2150
+ onContentSizeChange: handleContentSizeChange,
2151
+ scrollEventThrottle: 16,
2152
+ keyboardDismissMode: "interactive",
2153
+ keyboardShouldPersistTaps: "handled",
2154
+ children: [
2155
+ isLoadingSession ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: s6.loadingContainer, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.ActivityIndicator, { size: "large", color: "#00858d" }) }) : messages.map(
2156
+ (message) => message.role === "user" ? /* @__PURE__ */ jsxRuntime.jsx(
2157
+ UserMessageV2,
2158
+ {
2159
+ message,
2160
+ actions: messageActions?.userMessageActions,
2161
+ onEdit: onEditUserMessage,
2162
+ onRetry: onRetryUserMessage,
2163
+ retryDisabled
2164
+ },
2165
+ message.id
2166
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
2167
+ AssistantMessageV2,
2168
+ {
2169
+ message,
2170
+ onExecutionTraceClick,
2171
+ actions: messageActions?.assistantMessageActions
2172
+ },
2173
+ message.id
2174
+ )
2175
+ ),
2176
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: s6.bottomPad })
2177
+ ]
2178
+ }
2179
+ ),
2180
+ showScrollBtn ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: s6.scrollBtnContainer, pointerEvents: "box-none", children: /* @__PURE__ */ jsxRuntime.jsx(
2181
+ reactNative.Pressable,
2182
+ {
2183
+ style: s6.scrollBtn,
2184
+ onPress: () => scrollToBottom(true),
2185
+ hitSlop: 8,
2186
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.ArrowDown, { size: 16, color: "#555", strokeWidth: 2.5 })
2187
+ }
2188
+ ) }) : null
2189
+ ] });
2190
+ }
2191
+ );
2192
+ var s6 = reactNative.StyleSheet.create({
2193
+ root: {
2194
+ flex: 1,
2195
+ minHeight: 0,
2196
+ position: "relative"
2197
+ },
2198
+ scroll: {
2199
+ flex: 1
2200
+ },
2201
+ content: {
2202
+ flexGrow: 1,
2203
+ paddingTop: 12,
2204
+ paddingBottom: 4
2205
+ },
2206
+ loadingContainer: {
2207
+ flex: 1,
2208
+ alignItems: "center",
2209
+ justifyContent: "center",
2210
+ paddingVertical: 60
2211
+ },
2212
+ bottomPad: {
2213
+ height: 16
2214
+ },
2215
+ scrollBtnContainer: {
2216
+ position: "absolute",
2217
+ bottom: 16,
2218
+ left: 0,
2219
+ right: 0,
2220
+ alignItems: "center"
2221
+ },
2222
+ scrollBtn: {
2223
+ backgroundColor: "#fff",
2224
+ borderRadius: 20,
2225
+ width: 36,
2226
+ height: 36,
2227
+ alignItems: "center",
2228
+ justifyContent: "center",
2229
+ shadowColor: "#000",
2230
+ shadowOffset: { width: 0, height: 2 },
2231
+ shadowOpacity: 0.12,
2232
+ shadowRadius: 6,
2233
+ elevation: 4,
2234
+ borderWidth: 1,
2235
+ borderColor: "rgba(0,0,0,0.07)"
2236
+ }
2237
+ });
2238
+ var WaveformBar = React.memo(
2239
+ ({
2240
+ delay,
2241
+ isActive,
2242
+ color
2243
+ }) => {
2244
+ const height = React.useRef(new reactNative.Animated.Value(6)).current;
2245
+ React.useEffect(() => {
2246
+ if (isActive) {
2247
+ const animation = reactNative.Animated.loop(
2248
+ reactNative.Animated.sequence([
2249
+ reactNative.Animated.timing(height, {
2250
+ toValue: 14 + Math.random() * 10,
2251
+ duration: 300 + Math.random() * 50,
2252
+ delay,
2253
+ easing: reactNative.Easing.inOut(reactNative.Easing.ease),
2254
+ useNativeDriver: false
2255
+ }),
2256
+ reactNative.Animated.timing(height, {
2257
+ toValue: 6 + Math.random() * 4,
2258
+ duration: 300 + Math.random() * 50,
2259
+ easing: reactNative.Easing.inOut(reactNative.Easing.ease),
2260
+ useNativeDriver: false
2261
+ })
2262
+ ])
2263
+ );
2264
+ animation.start();
2265
+ return () => animation.stop();
2266
+ } else {
2267
+ reactNative.Animated.timing(height, {
2268
+ toValue: 6,
2269
+ duration: 300,
2270
+ useNativeDriver: false
2271
+ }).start();
2272
+ }
2273
+ }, [isActive, delay, height]);
2274
+ return /* @__PURE__ */ jsxRuntime.jsx(
2275
+ reactNative.Animated.View,
2276
+ {
2277
+ style: [styles.waveformBar, { height, backgroundColor: color }]
2278
+ }
2279
+ );
2280
+ }
2281
+ );
2282
+ WaveformBar.displayName = "WaveformBar";
2283
+ var RollingText = React.memo(({ text, color }) => {
2284
+ const [lines, setLines] = React__default.default.useState([]);
2285
+ const [currentLineIndex, setCurrentLineIndex] = React__default.default.useState(0);
2286
+ const translateY = React.useRef(new reactNative.Animated.Value(0)).current;
2287
+ const opacity = React.useRef(new reactNative.Animated.Value(1)).current;
2288
+ React.useEffect(() => {
2289
+ if (!text) {
2290
+ setLines([]);
2291
+ setCurrentLineIndex(0);
2292
+ return;
2293
+ }
2294
+ const words = text.split(" ");
2295
+ const newLines = [];
2296
+ let currentLine = "";
2297
+ words.forEach((word) => {
2298
+ const testLine = currentLine ? `${currentLine} ${word}` : word;
2299
+ if (testLine.length > 35 && currentLine) {
2300
+ newLines.push(currentLine);
2301
+ currentLine = word;
2302
+ } else {
2303
+ currentLine = testLine;
2304
+ }
2305
+ });
2306
+ if (currentLine) {
2307
+ newLines.push(currentLine);
2308
+ }
2309
+ setLines(newLines);
2310
+ if (newLines.length > 0) {
2311
+ const newIndex = newLines.length - 1;
2312
+ if (newIndex > currentLineIndex) {
2313
+ reactNative.Animated.sequence([
2314
+ reactNative.Animated.parallel([
2315
+ reactNative.Animated.timing(translateY, {
2316
+ toValue: -20,
2317
+ duration: 150,
2318
+ useNativeDriver: true
2319
+ }),
2320
+ reactNative.Animated.timing(opacity, {
2321
+ toValue: 0,
2322
+ duration: 150,
2323
+ useNativeDriver: true
2324
+ })
2325
+ ]),
2326
+ reactNative.Animated.timing(translateY, {
2327
+ toValue: 20,
2328
+ duration: 0,
2329
+ useNativeDriver: true
2330
+ }),
2331
+ reactNative.Animated.parallel([
2332
+ reactNative.Animated.timing(translateY, {
2333
+ toValue: 0,
2334
+ duration: 200,
2335
+ easing: reactNative.Easing.out(reactNative.Easing.ease),
2336
+ useNativeDriver: true
2337
+ }),
2338
+ reactNative.Animated.timing(opacity, {
2339
+ toValue: 1,
2340
+ duration: 200,
2341
+ useNativeDriver: true
2342
+ })
2343
+ ])
2344
+ ]).start();
2345
+ setCurrentLineIndex(newIndex);
2346
+ }
2347
+ }
2348
+ }, [text, currentLineIndex, translateY, opacity]);
2349
+ const currentText = lines[currentLineIndex] || text;
2350
+ return /* @__PURE__ */ jsxRuntime.jsx(
2351
+ reactNative.Animated.Text,
2352
+ {
2353
+ style: [
2354
+ styles.transcribedText,
2355
+ {
2356
+ color,
2357
+ opacity,
2358
+ transform: [{ translateY }]
2359
+ }
2360
+ ],
2361
+ numberOfLines: 1,
2362
+ children: currentText
2363
+ }
2364
+ );
2365
+ });
2366
+ RollingText.displayName = "RollingText";
2367
+ var VoiceOverlay = React.memo(
2368
+ ({
2369
+ visible,
2370
+ voiceState,
2371
+ transcribedText,
2372
+ onStopRecording
2373
+ }) => {
2374
+ const panelHeight = React.useRef(new reactNative.Animated.Value(0)).current;
2375
+ const contentOpacity = React.useRef(new reactNative.Animated.Value(0)).current;
2376
+ const [mounted, setMounted] = React.useState(false);
2377
+ const isListening = voiceState === "listening";
2378
+ const PANEL_CONTENT_HEIGHT = 160;
2379
+ const bgColor = "#15687d";
2380
+ const textColor = "#ffffff";
2381
+ const mutedColor = "rgba(255,255,255,0.75)";
2382
+ const primaryColor = "#ffffff";
2383
+ React.useEffect(() => {
2384
+ if (visible) {
2385
+ setMounted(true);
2386
+ reactNative.Animated.sequence([
2387
+ reactNative.Animated.timing(panelHeight, {
2388
+ toValue: PANEL_CONTENT_HEIGHT,
2389
+ duration: 300,
2390
+ easing: reactNative.Easing.out(reactNative.Easing.cubic),
2391
+ useNativeDriver: false
2392
+ }),
2393
+ reactNative.Animated.timing(contentOpacity, {
2394
+ toValue: 1,
2395
+ duration: 150,
2396
+ useNativeDriver: true
2397
+ })
2398
+ ]).start();
2399
+ } else {
2400
+ reactNative.Animated.parallel([
2401
+ reactNative.Animated.timing(contentOpacity, {
2402
+ toValue: 0,
2403
+ duration: 100,
2404
+ useNativeDriver: true
2405
+ }),
2406
+ reactNative.Animated.timing(panelHeight, {
2407
+ toValue: 0,
2408
+ duration: 220,
2409
+ easing: reactNative.Easing.in(reactNative.Easing.ease),
2410
+ useNativeDriver: false
2411
+ })
2412
+ ]).start(() => setMounted(false));
2413
+ }
2414
+ }, [visible, panelHeight, contentOpacity]);
2415
+ if (!mounted) return null;
2416
+ return /* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { onPress: onStopRecording, style: styles.panelWrapper, children: /* @__PURE__ */ jsxRuntime.jsx(
2417
+ reactNative.Animated.View,
2418
+ {
2419
+ style: [
2420
+ styles.panel,
2421
+ {
2422
+ height: panelHeight,
2423
+ backgroundColor: bgColor
2424
+ }
2425
+ ],
2426
+ children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Animated.View, { style: [styles.content, { opacity: contentOpacity }], children: [
2427
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.textContainer, children: transcribedText.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(RollingText, { text: transcribedText, color: textColor }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles.placeholderText, { color: mutedColor }], children: "Listening..." }) }),
2428
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.controlsContainer, children: [
2429
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles.waveformContainer, children: [0, 1, 2, 3, 4].map((index) => /* @__PURE__ */ jsxRuntime.jsx(
2430
+ WaveformBar,
2431
+ {
2432
+ delay: index * 20,
2433
+ isActive: isListening,
2434
+ color: primaryColor
2435
+ },
2436
+ index
2437
+ )) }),
2438
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles.hintText, { color: mutedColor }], children: "Tap to stop" })
2439
+ ] })
2440
+ ] })
2441
+ }
2442
+ ) });
2443
+ }
2444
+ );
2445
+ VoiceOverlay.displayName = "VoiceOverlay";
2446
+ var styles = reactNative.StyleSheet.create({
2447
+ panelWrapper: {
2448
+ zIndex: 10,
2449
+ elevation: 10
2450
+ },
2451
+ panel: {
2452
+ overflow: "hidden",
2453
+ borderTopLeftRadius: 20,
2454
+ borderTopRightRadius: 20
2455
+ },
2456
+ content: {
2457
+ flex: 1,
2458
+ paddingHorizontal: 24,
2459
+ paddingTop: 20
2460
+ },
2461
+ textContainer: {
2462
+ height: 32,
2463
+ justifyContent: "center",
2464
+ marginBottom: 16,
2465
+ overflow: "hidden"
2466
+ },
2467
+ transcribedText: {
2468
+ fontSize: 18,
2469
+ fontWeight: "500",
2470
+ textAlign: "left"
2471
+ },
2472
+ placeholderText: {
2473
+ fontSize: 15,
2474
+ textAlign: "left",
2475
+ fontWeight: "800"
2476
+ },
2477
+ controlsContainer: {
2478
+ flex: 1,
2479
+ alignItems: "center",
2480
+ justifyContent: "flex-start"
2481
+ },
2482
+ waveformContainer: {
2483
+ flexDirection: "row",
2484
+ alignItems: "center",
2485
+ justifyContent: "center",
2486
+ gap: 5,
2487
+ height: 28,
2488
+ marginBottom: 12
2489
+ },
2490
+ waveformBar: {
2491
+ width: 3,
2492
+ borderRadius: 2
2493
+ },
2494
+ hintText: {
2495
+ fontSize: 12
2496
+ }
2497
+ });
2498
+ var DEFAULT_ACCENT = "#00858d";
2499
+ function getPalette(theme, accent) {
2500
+ if (theme === "dark") {
2501
+ return {
2502
+ background: "#0d1719",
2503
+ textPrimary: "#f5f8f8",
2504
+ textSecondary: "rgba(245,248,248,0.72)",
2505
+ textMuted: "rgba(245,248,248,0.45)",
2506
+ heroHaloFrom: "rgba(0,133,141,0.16)",
2507
+ heroHaloTo: "rgba(0,133,141,0.06)",
2508
+ heroRing: "rgba(0,133,141,0.35)",
2509
+ heroDot: accent,
2510
+ disabledText: "rgba(245,248,248,0.45)"
2511
+ };
2512
+ }
2513
+ return {
2514
+ background: "#ffffff",
2515
+ textPrimary: "#1d1d1f",
2516
+ textSecondary: "#5e5d5a",
2517
+ textMuted: "#8a8a86",
2518
+ heroHaloFrom: "rgba(0,133,141,0.10)",
2519
+ heroHaloTo: "rgba(0,133,141,0.02)",
2520
+ heroRing: "rgba(0,133,141,0.20)",
2521
+ heroDot: accent,
2522
+ disabledText: "#8a8a86"
2523
+ };
2524
+ }
2525
+ var PaymanChat = React.forwardRef(
2526
+ function PaymanChat2({ config, callbacks = {}, children }, ref) {
2527
+ const {
2528
+ messages,
2529
+ sendMessage,
2530
+ clearMessages,
2531
+ cancelStream,
2532
+ resetSession: resetChatSession,
2533
+ getSessionId,
2534
+ getMessages,
2535
+ isWaitingForResponse,
2536
+ userActionState,
2537
+ approveUserAction,
2538
+ rejectUserAction,
2539
+ resendOtp,
2540
+ loadSession,
2541
+ loadingSessionId
2542
+ } = paymanTypescriptAskSdk.useChatV2(config, callbacks);
2543
+ const voiceEnabled = config.ui?.input?.voice === true || typeof config.ui?.input?.voice === "object" && config.ui.input.voice !== null;
2544
+ const {
2545
+ voiceState,
2546
+ transcribedText,
2547
+ isAvailable: voiceAvailable,
2548
+ isRecording,
2549
+ startRecording,
2550
+ stopRecording,
2551
+ clearTranscript
2552
+ } = paymanTypescriptAskSdk.useVoice();
2553
+ const attachmentsCfg = config.ui?.input?.attachments;
2554
+ const attachmentsAllowed = attachmentsCfg === void 0 || attachmentsCfg === true || typeof attachmentsCfg === "object" && attachmentsCfg !== null;
2555
+ const showUploadImage = attachmentsAllowed && (typeof attachmentsCfg !== "object" || attachmentsCfg === null ? true : attachmentsCfg.uploadImage !== false);
2556
+ const showAttachFile = attachmentsAllowed && (typeof attachmentsCfg !== "object" || attachmentsCfg === null ? true : attachmentsCfg.attachFile !== false);
2557
+ const [hasEverSentMessage, setHasEverSentMessage] = React.useState(false);
2558
+ const chatInputRef = React.useRef(null);
2559
+ const messageListRef = React.useRef(null);
2560
+ const resetToEmptyRef = React.useRef(false);
2561
+ React.useEffect(() => {
2562
+ if (resetToEmptyRef.current) {
2563
+ if (messages.length === 0) {
2564
+ setHasEverSentMessage(false);
2565
+ resetToEmptyRef.current = false;
2566
+ }
2567
+ return;
2568
+ }
2569
+ if (messages.length > 0 && !hasEverSentMessage) {
2570
+ setHasEverSentMessage(true);
2571
+ }
2572
+ }, [messages.length, hasEverSentMessage]);
2573
+ const prevRecordingRef = React.useRef(isRecording);
2574
+ React.useEffect(() => {
2575
+ const wasRecording = prevRecordingRef.current;
2576
+ prevRecordingRef.current = isRecording;
2577
+ if (wasRecording && !isRecording && transcribedText.trim()) {
2578
+ chatInputRef.current?.setDraft(transcribedText.trim());
2579
+ }
2580
+ }, [isRecording, transcribedText]);
2581
+ const handleVoicePress = React.useCallback(async () => {
2582
+ if (!voiceAvailable) return;
2583
+ if (isRecording) {
2584
+ stopRecording();
2585
+ return;
2586
+ }
2587
+ clearTranscript();
2588
+ await startRecording();
2589
+ }, [voiceAvailable, isRecording, stopRecording, clearTranscript, startRecording]);
2590
+ const handleSend = React.useCallback(
2591
+ (text) => {
2592
+ if (isRecording) stopRecording();
2593
+ if (!text.trim()) return;
2594
+ void sendMessage(text.trim());
2595
+ },
2596
+ [isRecording, stopRecording, sendMessage]
2597
+ );
2598
+ const dismissKeyboard = React.useCallback(() => {
2599
+ reactNative.Keyboard.dismiss();
2600
+ }, []);
2601
+ const handleEditMessageDraft = React.useCallback(
2602
+ (messageId) => {
2603
+ const targetMessage = messages.find(
2604
+ (message) => message.id === messageId && message.role === "user"
2605
+ );
2606
+ if (!targetMessage?.content.trim()) return;
2607
+ chatInputRef.current?.setDraft(targetMessage.content);
2608
+ requestAnimationFrame(() => {
2609
+ messageListRef.current?.scrollToBottom(true);
2610
+ });
2611
+ },
2612
+ [messages]
2613
+ );
2614
+ const handleRetryUserMessage = React.useCallback(
2615
+ (messageId) => {
2616
+ if (isWaitingForResponse) return;
2617
+ const targetMessage = messages.find(
2618
+ (message) => message.id === messageId && message.role === "user"
2619
+ );
2620
+ if (!targetMessage?.content.trim()) return;
2621
+ void sendMessage(targetMessage.content.trim());
2622
+ requestAnimationFrame(() => {
2623
+ messageListRef.current?.scrollToBottom(false);
2624
+ });
2625
+ },
2626
+ [isWaitingForResponse, messages, sendMessage]
2627
+ );
2628
+ const performResetSession = React.useCallback(() => {
2629
+ resetToEmptyRef.current = true;
2630
+ if (isRecording) stopRecording();
2631
+ clearTranscript();
2632
+ chatInputRef.current?.setDraft("");
2633
+ resetChatSession();
2634
+ callbacks.onResetSession?.();
2635
+ }, [isRecording, stopRecording, clearTranscript, resetChatSession, callbacks]);
2636
+ React.useImperativeHandle(
2637
+ ref,
2638
+ () => ({
2639
+ resetSession: performResetSession,
2640
+ clearMessages,
2641
+ cancelStream,
2642
+ getSessionId,
2643
+ getMessages,
2644
+ loadSession
2645
+ }),
2646
+ [performResetSession, clearMessages, cancelStream, getSessionId, getMessages, loadSession]
2647
+ );
2648
+ const ui = config.ui ?? {};
2649
+ const theme = ui.theme === "dark" ? "dark" : "light";
2650
+ const accent = ui.accent ?? DEFAULT_ACCENT;
2651
+ const palette = React.useMemo(() => getPalette(theme, accent), [theme, accent]);
2652
+ const placeholder = ui.input?.placeholder ?? "Type your message\u2026";
2653
+ const showResetButton = ui.input?.showResetButton ?? false;
2654
+ const messageActionsConfig = ui.messages?.actions;
2655
+ const messageActions = React.useMemo(
2656
+ () => ({
2657
+ userMessageActions: {
2658
+ copy: messageActionsConfig?.userMessageActions?.copy ?? true,
2659
+ edit: messageActionsConfig?.userMessageActions?.edit ?? false,
2660
+ retry: messageActionsConfig?.userMessageActions?.retry ?? false
2661
+ },
2662
+ assistantMessageActions: {
2663
+ copy: messageActionsConfig?.assistantMessageActions?.copy ?? true,
2664
+ trace: messageActionsConfig?.assistantMessageActions?.trace ?? true
2665
+ }
2666
+ }),
2667
+ [messageActionsConfig]
2668
+ );
2669
+ const isEmpty = messages.length === 0;
2670
+ const showEmptyShell = isEmpty && !hasEverSentMessage;
2671
+ const emptyStateText = ui.emptyState?.text ?? "How may I assist you today?";
2672
+ const emptyStateEyebrow = ui.emptyState?.eyebrow;
2673
+ const showEmptyIcon = ui.emptyState?.icon ?? true;
2674
+ const emptyStateLogo = ui.emptyState?.logo;
2675
+ const availability = config.availability;
2676
+ if (availability?.state === "disabled") {
2677
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [s7.root, { backgroundColor: palette.background }], children: [
2678
+ children,
2679
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: s7.disabledContainer, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [s7.disabledText, { color: palette.disabledText }], children: "Chat is currently disabled" }) })
2680
+ ] });
2681
+ }
2682
+ const isReadOnly = availability?.state === "readOnly";
2683
+ const hideSendForVerification = userActionState.request != null && userActionState.result == null;
2684
+ const verificationPanel = userActionState.request ? /* @__PURE__ */ jsxRuntime.jsx(
2685
+ InlineVerificationPanel,
2686
+ {
2687
+ userActionRequest: userActionState.request,
2688
+ clearOtpTrigger: userActionState.clearOtpTrigger,
2689
+ onApprove: approveUserAction,
2690
+ onReject: rejectUserAction,
2691
+ onResend: resendOtp
2692
+ }
2693
+ ) : null;
2694
+ const inputProps = {
2695
+ onSend: handleSend,
2696
+ onCancel: cancelStream,
2697
+ disabled: false,
2698
+ isStreaming: isWaitingForResponse,
2699
+ placeholder: isRecording ? "Listening\u2026" : placeholder,
2700
+ enableVoice: voiceEnabled,
2701
+ voiceAvailable: voiceEnabled && voiceAvailable,
2702
+ isRecording,
2703
+ onVoicePress: voiceEnabled ? handleVoicePress : void 0,
2704
+ showResetSession: showResetButton,
2705
+ onResetSession: performResetSession,
2706
+ showUploadImageButton: showUploadImage,
2707
+ showAttachFileButton: showAttachFile,
2708
+ onUploadImageClick: callbacks.onUploadImageClick,
2709
+ onAttachFileClick: callbacks.onAttachFileClick,
2710
+ theme,
2711
+ hideSendButton: hideSendForVerification,
2712
+ topAccessory: verificationPanel
2713
+ };
2714
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2715
+ reactNative.KeyboardAvoidingView,
2716
+ {
2717
+ style: [s7.root, { backgroundColor: palette.background }],
2718
+ behavior: reactNative.Platform.OS === "ios" ? "padding" : "height",
2719
+ keyboardVerticalOffset: 0,
2720
+ children: [
2721
+ children,
2722
+ showEmptyShell ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s7.emptyStateRoot, children: [
2723
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s7.emptyStateCenter, onTouchStart: dismissKeyboard, children: [
2724
+ emptyStateLogo ? emptyStateLogo : showEmptyIcon ? /* @__PURE__ */ jsxRuntime.jsx(HeroMark, { palette }) : null,
2725
+ emptyStateEyebrow ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [s7.emptyEyebrow, { color: palette.textMuted }], children: emptyStateEyebrow }) : null,
2726
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [s7.emptyStateText, { color: "#94a3b8" }], children: emptyStateText }),
2727
+ !emptyStateLogo ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [s7.emptyStateSubtext, { color: palette.textSecondary }], children: "Ask anything about your accounts, payments, or transfers." }) : null
2728
+ ] }),
2729
+ !isReadOnly ? /* @__PURE__ */ jsxRuntime.jsx(ChatInputV2, { ref: chatInputRef, ...inputProps }) : null
2730
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2731
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: s7.messageListWrapper, onTouchStart: dismissKeyboard, children: /* @__PURE__ */ jsxRuntime.jsx(
2732
+ MessageListV2,
2733
+ {
2734
+ ref: messageListRef,
2735
+ messages,
2736
+ isStreaming: isWaitingForResponse,
2737
+ isLoadingSession: !!loadingSessionId,
2738
+ onEditUserMessage: handleEditMessageDraft,
2739
+ onRetryUserMessage: handleRetryUserMessage,
2740
+ onExecutionTraceClick: callbacks.onExecutionTraceClick,
2741
+ messageActions,
2742
+ retryDisabled: isWaitingForResponse
2743
+ }
2744
+ ) }),
2745
+ voiceEnabled ? /* @__PURE__ */ jsxRuntime.jsx(
2746
+ VoiceOverlay,
2747
+ {
2748
+ visible: isRecording,
2749
+ voiceState,
2750
+ transcribedText,
2751
+ onStopRecording: stopRecording
2752
+ }
2753
+ ) : null,
2754
+ !isReadOnly ? /* @__PURE__ */ jsxRuntime.jsx(
2755
+ ChatInputV2,
2756
+ {
2757
+ ref: chatInputRef,
2758
+ ...inputProps
2759
+ }
2760
+ ) : null
2761
+ ] })
2762
+ ]
2763
+ }
2764
+ );
28
2765
  }
29
- n.default = e;
30
- return Object.freeze(n);
2766
+ );
2767
+ function HeroMark({ palette }) {
2768
+ const scale = React.useRef(new reactNative.Animated.Value(0.92)).current;
2769
+ const opacity = React.useRef(new reactNative.Animated.Value(0)).current;
2770
+ const ringSpin = React.useRef(new reactNative.Animated.Value(0)).current;
2771
+ const dotPulse = React.useRef(new reactNative.Animated.Value(0)).current;
2772
+ React.useEffect(() => {
2773
+ reactNative.Animated.parallel([
2774
+ reactNative.Animated.timing(opacity, {
2775
+ toValue: 1,
2776
+ duration: 420,
2777
+ easing: reactNative.Easing.out(reactNative.Easing.cubic),
2778
+ useNativeDriver: true
2779
+ }),
2780
+ reactNative.Animated.spring(scale, {
2781
+ toValue: 1,
2782
+ friction: 6,
2783
+ tension: 90,
2784
+ useNativeDriver: true
2785
+ })
2786
+ ]).start();
2787
+ reactNative.Animated.loop(
2788
+ reactNative.Animated.timing(ringSpin, {
2789
+ toValue: 1,
2790
+ duration: 14e3,
2791
+ easing: reactNative.Easing.linear,
2792
+ useNativeDriver: true
2793
+ })
2794
+ ).start();
2795
+ reactNative.Animated.loop(
2796
+ reactNative.Animated.sequence([
2797
+ reactNative.Animated.timing(dotPulse, {
2798
+ toValue: 1,
2799
+ duration: 1600,
2800
+ easing: reactNative.Easing.inOut(reactNative.Easing.cubic),
2801
+ useNativeDriver: true
2802
+ }),
2803
+ reactNative.Animated.timing(dotPulse, {
2804
+ toValue: 0,
2805
+ duration: 1600,
2806
+ easing: reactNative.Easing.inOut(reactNative.Easing.cubic),
2807
+ useNativeDriver: true
2808
+ })
2809
+ ])
2810
+ ).start();
2811
+ }, [opacity, scale, ringSpin, dotPulse]);
2812
+ const ringRotate = ringSpin.interpolate({
2813
+ inputRange: [0, 1],
2814
+ outputRange: ["0deg", "360deg"]
2815
+ });
2816
+ const dotScale = dotPulse.interpolate({
2817
+ inputRange: [0, 1],
2818
+ outputRange: [0.92, 1.06]
2819
+ });
2820
+ return /* @__PURE__ */ jsxRuntime.jsx(
2821
+ reactNative.Animated.View,
2822
+ {
2823
+ style: [hero.halo, {
2824
+ backgroundColor: palette.heroHaloFrom,
2825
+ opacity,
2826
+ transform: [{ scale }]
2827
+ }],
2828
+ children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [hero.haloInner, { backgroundColor: palette.heroHaloTo }], children: [
2829
+ /* @__PURE__ */ jsxRuntime.jsx(
2830
+ reactNative.Animated.View,
2831
+ {
2832
+ style: [
2833
+ hero.ring,
2834
+ { borderColor: palette.heroRing, transform: [{ rotate: ringRotate }] }
2835
+ ]
2836
+ }
2837
+ ),
2838
+ /* @__PURE__ */ jsxRuntime.jsx(
2839
+ reactNative.Animated.View,
2840
+ {
2841
+ style: [
2842
+ hero.dot,
2843
+ { backgroundColor: palette.heroDot, transform: [{ scale: dotScale }] }
2844
+ ]
2845
+ }
2846
+ )
2847
+ ] })
2848
+ }
2849
+ );
31
2850
  }
32
-
33
- var Sentry__namespace = /*#__PURE__*/_interopNamespace(Sentry);
34
-
35
- // src/components/PaymanChat/index.native.tsx
36
- var PaymanChat = react.forwardRef(function PaymanChat2(_props, _ref) {
37
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles.root, children: [
38
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.title, children: "PaymanChat v2" }),
39
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles.body, children: "React Native support is coming in a follow-up release. Please use the web SDK for now." })
40
- ] });
41
- });
42
- var styles = reactNative.StyleSheet.create({
2851
+ var s7 = reactNative.StyleSheet.create({
43
2852
  root: {
2853
+ flex: 1,
2854
+ overflow: "hidden"
2855
+ },
2856
+ messageListWrapper: {
2857
+ flex: 1,
2858
+ minHeight: 0
2859
+ },
2860
+ emptyStateRoot: {
2861
+ flex: 1,
2862
+ justifyContent: "flex-end"
2863
+ },
2864
+ emptyStateCenter: {
44
2865
  flex: 1,
45
2866
  alignItems: "center",
46
2867
  justifyContent: "center",
47
- padding: 24
2868
+ paddingHorizontal: 32,
2869
+ paddingBottom: 24
48
2870
  },
49
- title: {
50
- fontSize: 16,
2871
+ emptyEyebrow: {
2872
+ marginTop: 28,
2873
+ marginBottom: 8,
2874
+ fontSize: 13,
51
2875
  fontWeight: "600",
52
- marginBottom: 8
2876
+ letterSpacing: 0.4,
2877
+ textTransform: "uppercase"
53
2878
  },
54
- body: {
55
- fontSize: 13,
56
- color: "#666",
2879
+ emptyStateText: {
2880
+ fontSize: 30,
2881
+ fontWeight: "600",
2882
+ textAlign: "center",
2883
+ letterSpacing: -0.7,
2884
+ lineHeight: 36,
2885
+ // Lean into a serif on iOS for a Claude-like editorial feel; system on Android
2886
+ ...reactNative.Platform.select({
2887
+ ios: { fontFamily: "Georgia" },
2888
+ default: {}
2889
+ }),
2890
+ marginTop: 24
2891
+ },
2892
+ emptyStateSubtext: {
2893
+ marginTop: 10,
2894
+ fontSize: 15,
2895
+ lineHeight: 22,
2896
+ textAlign: "center",
2897
+ letterSpacing: -0.15,
2898
+ maxWidth: 320
2899
+ },
2900
+ disabledContainer: {
2901
+ flex: 1,
2902
+ alignItems: "center",
2903
+ justifyContent: "center",
2904
+ padding: 16
2905
+ },
2906
+ disabledText: {
2907
+ fontSize: 14,
57
2908
  textAlign: "center"
58
2909
  }
59
2910
  });
2911
+ var hero = reactNative.StyleSheet.create({
2912
+ halo: {
2913
+ width: 96,
2914
+ height: 96,
2915
+ borderRadius: 48,
2916
+ alignItems: "center",
2917
+ justifyContent: "center"
2918
+ },
2919
+ haloInner: {
2920
+ width: 76,
2921
+ height: 76,
2922
+ borderRadius: 38,
2923
+ alignItems: "center",
2924
+ justifyContent: "center"
2925
+ },
2926
+ ring: {
2927
+ position: "absolute",
2928
+ width: 60,
2929
+ height: 60,
2930
+ borderRadius: 30,
2931
+ borderWidth: 1.5,
2932
+ borderStyle: "dashed"
2933
+ },
2934
+ dot: {
2935
+ width: 18,
2936
+ height: 18,
2937
+ borderRadius: 9
2938
+ }
2939
+ });
60
2940
  function cn(...inputs) {
61
2941
  return tailwindMerge.twMerge(clsx.clsx(inputs));
62
2942
  }
@@ -94,24 +2974,24 @@ function useSessionHistory(config, options = {}, optimisticActivity) {
94
2974
  const minWidth = options.minWidth ?? DEFAULT_MIN_WIDTH;
95
2975
  const maxWidth = options.maxWidth ?? DEFAULT_MAX_WIDTH;
96
2976
  const pageSize = options.pageSize ?? DEFAULT_PAGE_SIZE;
97
- const persistKey = react.useMemo(
2977
+ const persistKey = React.useMemo(
98
2978
  () => getPersistKey(config, options),
99
2979
  [config.workflow.id, options.persistKey]
100
2980
  );
101
- const [width, setWidthState] = react.useState(() => {
2981
+ const [width, setWidthState] = React.useState(() => {
102
2982
  const persisted = loadPersistedState(persistKey);
103
2983
  return persisted?.width ?? defaultWidth;
104
2984
  });
105
- const [collapsed, setCollapsedState] = react.useState(() => {
2985
+ const [collapsed, setCollapsedState] = React.useState(() => {
106
2986
  const persisted = loadPersistedState(persistKey);
107
2987
  return persisted?.collapsed ?? options.defaultCollapsed ?? false;
108
2988
  });
109
- react.useEffect(() => {
2989
+ React.useEffect(() => {
110
2990
  const persisted = loadPersistedState(persistKey);
111
2991
  setWidthState(persisted?.width ?? defaultWidth);
112
2992
  setCollapsedState(persisted?.collapsed ?? options.defaultCollapsed ?? false);
113
2993
  }, [persistKey]);
114
- const setWidth = react.useCallback(
2994
+ const setWidth = React.useCallback(
115
2995
  (px) => {
116
2996
  const clamped = Math.max(minWidth, Math.min(maxWidth, Math.round(px)));
117
2997
  setWidthState(clamped);
@@ -119,7 +2999,7 @@ function useSessionHistory(config, options = {}, optimisticActivity) {
119
2999
  },
120
3000
  [collapsed, maxWidth, minWidth, persistKey]
121
3001
  );
122
- const setCollapsed = react.useCallback(
3002
+ const setCollapsed = React.useCallback(
123
3003
  (value) => {
124
3004
  setCollapsedState((prev) => {
125
3005
  const next = typeof value === "function" ? value(prev) : value;
@@ -130,15 +3010,15 @@ function useSessionHistory(config, options = {}, optimisticActivity) {
130
3010
  [persistKey, width]
131
3011
  );
132
3012
  const isReady = !!(config.session?.owner?.id && (config.workflow.id || config.workflow.name));
133
- const [sessions, setSessions] = react.useState([]);
134
- const [isLoading, setIsLoading] = react.useState(false);
135
- const [error, setError] = react.useState(null);
136
- const [page, setPage] = react.useState(0);
137
- const [hasNext, setHasNext] = react.useState(false);
138
- const inFlightRef = react.useRef(null);
139
- const configRef = react.useRef(config);
3013
+ const [sessions, setSessions] = React.useState([]);
3014
+ const [isLoading, setIsLoading] = React.useState(false);
3015
+ const [error, setError] = React.useState(null);
3016
+ const [page, setPage] = React.useState(0);
3017
+ const [hasNext, setHasNext] = React.useState(false);
3018
+ const inFlightRef = React.useRef(null);
3019
+ const configRef = React.useRef(config);
140
3020
  configRef.current = config;
141
- const fetchPage = react.useCallback(
3021
+ const fetchPage = React.useCallback(
142
3022
  async (pageIndex, replace) => {
143
3023
  if (!isReady) return;
144
3024
  inFlightRef.current?.abort();
@@ -167,12 +3047,12 @@ function useSessionHistory(config, options = {}, optimisticActivity) {
167
3047
  },
168
3048
  [isReady, pageSize]
169
3049
  );
170
- const refresh = react.useCallback(() => fetchPage(0, true), [fetchPage]);
171
- const loadMore = react.useCallback(async () => {
3050
+ const refresh = React.useCallback(() => fetchPage(0, true), [fetchPage]);
3051
+ const loadMore = React.useCallback(async () => {
172
3052
  if (!hasNext || isLoading) return;
173
3053
  await fetchPage(page + 1, false);
174
3054
  }, [fetchPage, hasNext, isLoading, page]);
175
- react.useEffect(() => {
3055
+ React.useEffect(() => {
176
3056
  if (!optimisticActivity) return;
177
3057
  setSessions((prev) => {
178
3058
  const next = [...prev];
@@ -213,7 +3093,7 @@ function useSessionHistory(config, options = {}, optimisticActivity) {
213
3093
  config.workflow.version,
214
3094
  optimisticActivity
215
3095
  ]);
216
- react.useEffect(() => {
3096
+ React.useEffect(() => {
217
3097
  if (!isReady) return;
218
3098
  void fetchPage(0, true);
219
3099
  return () => {
@@ -243,11 +3123,11 @@ function useSessionHistory(config, options = {}, optimisticActivity) {
243
3123
  }
244
3124
  var MOBILE_BREAKPOINT = 640;
245
3125
  function useIsMobile() {
246
- const [isMobile, setIsMobile] = react.useState(() => {
3126
+ const [isMobile, setIsMobile] = React.useState(() => {
247
3127
  if (typeof window === "undefined") return false;
248
3128
  return window.innerWidth < MOBILE_BREAKPOINT;
249
3129
  });
250
- react.useEffect(() => {
3130
+ React.useEffect(() => {
251
3131
  if (typeof window === "undefined") return;
252
3132
  const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
253
3133
  const handler = (e) => setIsMobile(e.matches);
@@ -290,11 +3170,11 @@ function SessionHistorySidebar({
290
3170
  onMobileOpenChange
291
3171
  }) {
292
3172
  const isMobile = useIsMobile();
293
- const mobileThemeSourceRef = react.useRef(null);
294
- const [mobilePortalThemeStyle, setMobilePortalThemeStyle] = react.useState({});
3173
+ const mobileThemeSourceRef = React.useRef(null);
3174
+ const [mobilePortalThemeStyle, setMobilePortalThemeStyle] = React.useState({});
295
3175
  const history = useSessionHistory(config, options, optimisticActivity);
296
3176
  const showNewSessionButton = options.showNewSessionButton === true;
297
- react.useEffect(() => {
3177
+ React.useEffect(() => {
298
3178
  if (!isMobile) return;
299
3179
  setMobilePortalThemeStyle(readPortalThemeStyle(mobileThemeSourceRef.current));
300
3180
  }, [isMobile, mobileOpen]);
@@ -324,8 +3204,8 @@ function SessionHistorySidebar({
324
3204
  showNewSessionButton,
325
3205
  onNewSession,
326
3206
  newSessionDisabled,
327
- onSelectSession: (s3) => {
328
- onSelectSession(s3);
3207
+ onSelectSession: (s9) => {
3208
+ onSelectSession(s9);
329
3209
  onMobileOpenChange(false);
330
3210
  }
331
3211
  }
@@ -358,10 +3238,10 @@ function DesktopSidebar({
358
3238
  }) {
359
3239
  const { width, setWidth, collapsed, setCollapsed, minWidth, maxWidth } = history;
360
3240
  const reduceMotion = framerMotion.useReducedMotion();
361
- const dragStateRef = react.useRef(null);
362
- const [isDragging, setIsDragging] = react.useState(false);
363
- const [handleHover, setHandleHover] = react.useState(false);
364
- const onResizeStart = react.useCallback(
3241
+ const dragStateRef = React.useRef(null);
3242
+ const [isDragging, setIsDragging] = React.useState(false);
3243
+ const [handleHover, setHandleHover] = React.useState(false);
3244
+ const onResizeStart = React.useCallback(
365
3245
  (e) => {
366
3246
  e.preventDefault();
367
3247
  dragStateRef.current = { startX: e.clientX, startWidth: width };
@@ -369,7 +3249,7 @@ function DesktopSidebar({
369
3249
  },
370
3250
  [width]
371
3251
  );
372
- react.useEffect(() => {
3252
+ React.useEffect(() => {
373
3253
  if (!isDragging) return;
374
3254
  const onMove = (e) => {
375
3255
  const st = dragStateRef.current;
@@ -514,8 +3394,8 @@ function CollapsedButton({
514
3394
  onSelectSession
515
3395
  }) {
516
3396
  const reduceMotion = framerMotion.useReducedMotion();
517
- const [hoverOpen, setHoverOpen] = react.useState(false);
518
- const leaveTimerRef = react.useRef(null);
3397
+ const [hoverOpen, setHoverOpen] = React.useState(false);
3398
+ const leaveTimerRef = React.useRef(null);
519
3399
  const openPopover = () => {
520
3400
  if (leaveTimerRef.current) clearTimeout(leaveTimerRef.current);
521
3401
  setHoverOpen(true);
@@ -527,7 +3407,7 @@ function CollapsedButton({
527
3407
  POPOVER_LEAVE_DELAY_MS
528
3408
  );
529
3409
  };
530
- react.useEffect(
3410
+ React.useEffect(
531
3411
  () => () => {
532
3412
  if (leaveTimerRef.current) clearTimeout(leaveTimerRef.current);
533
3413
  },
@@ -593,8 +3473,8 @@ function CollapsedButton({
593
3473
  activeSessionId,
594
3474
  loadingSessionId,
595
3475
  recentlyCompletedSessionIds,
596
- onSelectSession: (s3) => {
597
- onSelectSession(s3);
3476
+ onSelectSession: (s9) => {
3477
+ onSelectSession(s9);
598
3478
  setHoverOpen(false);
599
3479
  }
600
3480
  }
@@ -744,10 +3624,10 @@ function SessionList({
744
3624
  recentlyCompletedSessionIds,
745
3625
  onSelectSession
746
3626
  }) {
747
- const listRef = react.useRef(null);
3627
+ const listRef = React.useRef(null);
748
3628
  const { sessions, hasNext, isLoading, error, loadMore, isReady, refresh } = history;
749
- const formattedNow = react.useMemo(() => /* @__PURE__ */ new Date(), []);
750
- const sessionGroups = react.useMemo(
3629
+ const formattedNow = React.useMemo(() => /* @__PURE__ */ new Date(), []);
3630
+ const sessionGroups = React.useMemo(
751
3631
  () => groupSessionsByDate(sessions, formattedNow),
752
3632
  [sessions, formattedNow]
753
3633
  );
@@ -771,16 +3651,16 @@ function SessionList({
771
3651
  "aria-label": group.label,
772
3652
  children: [
773
3653
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-sidebar-group-label", children: group.label }),
774
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-sidebar-group-items", children: group.sessions.map((s3) => /* @__PURE__ */ jsxRuntime.jsx(
3654
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "payman-sidebar-group-items", children: group.sessions.map((s9) => /* @__PURE__ */ jsxRuntime.jsx(
775
3655
  SessionRow,
776
3656
  {
777
- session: s3,
778
- isActive: s3.sessionId === activeSessionId,
779
- isLoading: s3.sessionId === loadingSessionId,
780
- isRecentlyCompleted: recentlyCompletedSessionIds?.has(s3.sessionId) ?? false,
3657
+ session: s9,
3658
+ isActive: s9.sessionId === activeSessionId,
3659
+ isLoading: s9.sessionId === loadingSessionId,
3660
+ isRecentlyCompleted: recentlyCompletedSessionIds?.has(s9.sessionId) ?? false,
781
3661
  onSelect: onSelectSession
782
3662
  },
783
- s3.sessionId
3663
+ s9.sessionId
784
3664
  )) })
785
3665
  ]
786
3666
  },
@@ -975,7 +3855,7 @@ function ChatHeader({
975
3855
  showResetSession = false,
976
3856
  children
977
3857
  }) {
978
- const [copiedSessionId, setCopiedSessionId] = react.useState(false);
3858
+ const [copiedSessionId, setCopiedSessionId] = React.useState(false);
979
3859
  const handleCopySessionId = () => {
980
3860
  if (sessionId && onCopySessionId) {
981
3861
  reactNative.Clipboard.setString(sessionId);
@@ -1032,203 +3912,8 @@ var styles2 = reactNative.StyleSheet.create({
1032
3912
 
1033
3913
  // src/assets/payman-mono-crop-blue.png
1034
3914
  var payman_mono_crop_blue_default = "data:image/png;base64,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";
1035
- var DEFAULT_MAX_LENGTH = 6;
1036
- var MAX_SUPPORTED_LENGTH = 12;
1037
- var OTP_ERROR_BORDER = "#ef4444";
1038
- var COMPLETE_PULSE_MS = 350;
1039
- var SHAKE_MS = 400;
1040
- function OtpInput({
1041
- value,
1042
- onChange,
1043
- maxLength,
1044
- disabled = false,
1045
- error = false
1046
- }) {
1047
- const inputRefs = react.useRef([]);
1048
- const shakeAnim = react.useRef(new reactNative.Animated.Value(0)).current;
1049
- const scaleAnim = react.useRef(new reactNative.Animated.Value(1)).current;
1050
- const prevLenRef = react.useRef(0);
1051
- const [internalError, setInternalError] = react.useState(false);
1052
- const safeMaxLength = Number.isInteger(maxLength) && maxLength > 0 ? Math.min(maxLength, MAX_SUPPORTED_LENGTH) : DEFAULT_MAX_LENGTH;
1053
- const digits = value.split("").concat(Array(safeMaxLength).fill("")).slice(0, safeMaxLength);
1054
- const isFull = value.length === safeMaxLength && /^\d+$/.test(value);
1055
- react.useEffect(() => {
1056
- if (!disabled) {
1057
- inputRefs.current[0]?.focus();
1058
- }
1059
- }, [disabled]);
1060
- react.useEffect(() => {
1061
- if (!error) {
1062
- setInternalError(false);
1063
- return;
1064
- }
1065
- setInternalError(true);
1066
- reactNative.Animated.sequence([
1067
- reactNative.Animated.timing(shakeAnim, { toValue: 1, duration: SHAKE_MS, useNativeDriver: true }),
1068
- reactNative.Animated.timing(shakeAnim, { toValue: 0, duration: 0, useNativeDriver: true })
1069
- ]).start();
1070
- }, [error, shakeAnim]);
1071
- react.useEffect(() => {
1072
- if (isFull && prevLenRef.current < safeMaxLength) {
1073
- reactNative.Animated.sequence([
1074
- reactNative.Animated.timing(scaleAnim, { toValue: 1.04, duration: COMPLETE_PULSE_MS * 0.4, useNativeDriver: true }),
1075
- reactNative.Animated.timing(scaleAnim, { toValue: 1, duration: COMPLETE_PULSE_MS * 0.6, useNativeDriver: true })
1076
- ]).start();
1077
- }
1078
- prevLenRef.current = value.length;
1079
- }, [isFull, value.length, safeMaxLength, scaleAnim]);
1080
- const shakeTranslate = shakeAnim.interpolate({
1081
- inputRange: [0, 0.15, 0.3, 0.45, 0.6, 0.75, 0.9, 1],
1082
- outputRange: [0, -6, 5, -4, 3, -2, 1, 0]
1083
- });
1084
- const focusInput = (index) => {
1085
- if (index >= 0 && index < safeMaxLength) {
1086
- inputRefs.current[index]?.focus();
1087
- }
1088
- };
1089
- const updateValue = (newDigits) => {
1090
- onChange(newDigits.join("").slice(0, safeMaxLength));
1091
- };
1092
- const handleChange = (index, text) => {
1093
- const cleaned = text.replace(/\D/g, "");
1094
- if (cleaned.length > 1) {
1095
- const pasted = cleaned.slice(0, safeMaxLength);
1096
- const newDigits2 = pasted.split("").concat(Array(safeMaxLength).fill("")).slice(0, safeMaxLength);
1097
- updateValue(newDigits2);
1098
- focusInput(Math.min(pasted.length, safeMaxLength - 1));
1099
- return;
1100
- }
1101
- const char = cleaned.slice(-1);
1102
- const newDigits = [...digits];
1103
- newDigits[index] = char;
1104
- updateValue(newDigits);
1105
- if (char && index < safeMaxLength - 1) {
1106
- focusInput(index + 1);
1107
- }
1108
- };
1109
- const handleKeyPress = (index, key) => {
1110
- if (key === "Backspace") {
1111
- if (digits[index]) {
1112
- const newDigits = [...digits];
1113
- newDigits[index] = "";
1114
- updateValue(newDigits);
1115
- } else if (index > 0) {
1116
- const newDigits = [...digits];
1117
- newDigits[index - 1] = "";
1118
- updateValue(newDigits);
1119
- focusInput(index - 1);
1120
- }
1121
- }
1122
- };
1123
- return /* @__PURE__ */ jsxRuntime.jsx(
1124
- reactNative.Animated.View,
1125
- {
1126
- style: [
1127
- s.container,
1128
- { transform: [{ translateX: shakeTranslate }, { scale: scaleAnim }] }
1129
- ],
1130
- children: digits.map((digit, i) => /* @__PURE__ */ jsxRuntime.jsx(
1131
- reactNative.TextInput,
1132
- {
1133
- ref: (el) => {
1134
- inputRefs.current[i] = el;
1135
- },
1136
- value: digit,
1137
- editable: !disabled,
1138
- keyboardType: "number-pad",
1139
- maxLength: 1,
1140
- onChangeText: (text) => handleChange(i, text),
1141
- onKeyPress: ({ nativeEvent }) => handleKeyPress(i, nativeEvent.key),
1142
- onFocus: () => inputRefs.current[i]?.setNativeProps({ selection: { start: 0, end: 1 } }),
1143
- style: [
1144
- s.input,
1145
- disabled && s.inputDisabled,
1146
- internalError && s.inputError
1147
- ],
1148
- accessibilityLabel: `Digit ${i + 1}`
1149
- },
1150
- i
1151
- ))
1152
- }
1153
- );
1154
- }
1155
- var PAYMAN_OTP = {
1156
- bg: "#FFFFFF",
1157
- border: "rgba(0,0,0,0.1)",
1158
- fg: "#18181b",
1159
- disabledBg: "rgba(0,0,0,0.03)"
1160
- };
1161
- var s = reactNative.StyleSheet.create({
1162
- container: { flexDirection: "row", gap: 8, justifyContent: "center" },
1163
- input: {
1164
- width: 44,
1165
- height: 50,
1166
- textAlign: "center",
1167
- fontSize: 20,
1168
- fontWeight: "600",
1169
- borderWidth: 1,
1170
- borderColor: PAYMAN_OTP.border,
1171
- borderRadius: 10,
1172
- color: PAYMAN_OTP.fg,
1173
- backgroundColor: PAYMAN_OTP.bg
1174
- },
1175
- inputDisabled: { backgroundColor: PAYMAN_OTP.disabledBg, opacity: 0.5 },
1176
- inputError: {
1177
- borderColor: OTP_ERROR_BORDER,
1178
- borderWidth: 1.5
1179
- }
1180
- });
1181
-
1182
- // src/components/UserActionModal/constants.ts
1183
- var BUTTON_LABELS = {
1184
- /** Link-style actions (new layout) */
1185
- RESEND_CODE: "Resend OTP",
1186
- CANCEL_TRANSFER: "Cancel Payment",
1187
- /** Short cancel label for payee approval flows */
1188
- CANCEL: "Cancel"
1189
- };
1190
- var RESEND_OTP_COOLDOWN_SECONDS = 30;
1191
- var DEFAULT_OTP_MAX_LENGTH = 6;
1192
- var MIN_OTP_MAX_LENGTH = 1;
1193
- var MAX_OTP_MAX_LENGTH = 12;
1194
- var ACTION_PENDING_TIMEOUT_MS = 15e3;
1195
- var MODAL_CONTENT = {
1196
- LOADING_APPROVE: "Verifying...",
1197
- LOADING_REJECT: "Rejecting...",
1198
- LOADING_RESEND: "Resending...",
1199
- RESEND_AVAILABLE_IN: "Resend OTP in",
1200
- SECURED_BY_PREFIX: "Secured by",
1201
- SECURED_BY_BRAND: "Payman"
1202
- };
1203
-
1204
- // src/components/UserActionModal/utils.ts
1205
- function getOtpSchemaFromRequest(schema) {
1206
- const properties = schema?.properties;
1207
- const otp = properties?.otp;
1208
- const maxLengthRaw = otp?.maxLength;
1209
- const parsedMaxLength = Number.isInteger(maxLengthRaw) ? Number(maxLengthRaw) : DEFAULT_OTP_MAX_LENGTH;
1210
- const clampedMaxLength = Math.min(
1211
- MAX_OTP_MAX_LENGTH,
1212
- Math.max(MIN_OTP_MAX_LENGTH, parsedMaxLength)
1213
- );
1214
- return {
1215
- maxLength: clampedMaxLength
1216
- };
1217
- }
1218
- function formatAmountForDisplay(amount) {
1219
- const normalized = amount.replace(/,/g, "").trim();
1220
- const n = Number(normalized);
1221
- if (!Number.isFinite(n)) {
1222
- return amount.startsWith("$") ? amount : `$${amount}`;
1223
- }
1224
- return new Intl.NumberFormat("en-US", {
1225
- style: "currency",
1226
- currency: "USD"
1227
- }).format(n);
1228
- }
1229
3915
  var PAYMAN_BRAND_GREEN = "#0A3B44";
1230
3916
  var PAYMAN = {
1231
- foreground: "#18181b",
1232
3917
  mutedForeground: "#71717a",
1233
3918
  border: "#e4e4e7",
1234
3919
  card: "#ffffff",
@@ -1237,7 +3922,7 @@ var PAYMAN = {
1237
3922
  var { width: SCREEN_WIDTH } = reactNative.Dimensions.get("window");
1238
3923
  var DIALOG_MAX_WIDTH = Math.min(440, SCREEN_WIDTH * 0.94);
1239
3924
  var DIALOG_PADDING = 28;
1240
- var OTP_ERROR_FLASH_MS = 600;
3925
+ var OTP_ERROR_FLASH_MS2 = 600;
1241
3926
  function UserActionModal({
1242
3927
  isOpen,
1243
3928
  userActionRequest,
@@ -1246,17 +3931,17 @@ function UserActionModal({
1246
3931
  onResend,
1247
3932
  clearOtpTrigger
1248
3933
  }) {
1249
- const [otp, setOtp] = react.useState("");
1250
- const [actionType, setActionType] = react.useState(null);
1251
- const [isSubmitting, setIsSubmitting] = react.useState(false);
1252
- const [resendCooldownRemaining, setResendCooldownRemaining] = react.useState(0);
1253
- const [keyboardVisible, setKeyboardVisible] = react.useState(false);
1254
- const [otpError, setOtpError] = react.useState(false);
1255
- const lastAutoSubmittedRef = react.useRef("");
1256
- const submitInFlightRef = react.useRef(false);
1257
- const submitGenerationRef = react.useRef(0);
3934
+ const [otp, setOtp] = React.useState("");
3935
+ const [actionType, setActionType] = React.useState(null);
3936
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
3937
+ const [resendCooldownRemaining, setResendCooldownRemaining] = React.useState(0);
3938
+ const [keyboardVisible, setKeyboardVisible] = React.useState(false);
3939
+ const [otpError, setOtpError] = React.useState(false);
3940
+ const lastAutoSubmittedRef = React.useRef("");
3941
+ const submitInFlightRef = React.useRef(false);
3942
+ const submitGenerationRef = React.useRef(0);
1258
3943
  const schema = getOtpSchemaFromRequest(userActionRequest?.requestedSchema);
1259
- react.useEffect(() => {
3944
+ React.useEffect(() => {
1260
3945
  const show = reactNative.Keyboard.addListener(
1261
3946
  reactNative.Platform.OS === "ios" ? "keyboardWillShow" : "keyboardDidShow",
1262
3947
  () => setKeyboardVisible(true)
@@ -1270,11 +3955,11 @@ function UserActionModal({
1270
3955
  hide.remove();
1271
3956
  };
1272
3957
  }, []);
1273
- const resetActionState = react.useCallback(() => {
3958
+ const resetActionState = React.useCallback(() => {
1274
3959
  setIsSubmitting(false);
1275
3960
  setActionType(null);
1276
3961
  }, []);
1277
- react.useEffect(() => {
3962
+ React.useEffect(() => {
1278
3963
  if (isOpen) {
1279
3964
  setResendCooldownRemaining(RESEND_OTP_COOLDOWN_SECONDS);
1280
3965
  } else {
@@ -1287,7 +3972,7 @@ function UserActionModal({
1287
3972
  submitGenerationRef.current += 1;
1288
3973
  }
1289
3974
  }, [isOpen, resetActionState]);
1290
- react.useEffect(() => {
3975
+ React.useEffect(() => {
1291
3976
  if (resendCooldownRemaining <= 0) return;
1292
3977
  const timer = setTimeout(
1293
3978
  () => setResendCooldownRemaining((prev) => prev - 1),
@@ -1295,18 +3980,18 @@ function UserActionModal({
1295
3980
  );
1296
3981
  return () => clearTimeout(timer);
1297
3982
  }, [resendCooldownRemaining]);
1298
- react.useEffect(() => {
3983
+ React.useEffect(() => {
1299
3984
  if (clearOtpTrigger > 0) {
1300
3985
  setOtpError(true);
1301
3986
  const t = setTimeout(() => {
1302
3987
  setOtpError(false);
1303
3988
  setOtp("");
1304
3989
  resetActionState();
1305
- }, OTP_ERROR_FLASH_MS);
3990
+ }, OTP_ERROR_FLASH_MS2);
1306
3991
  return () => clearTimeout(t);
1307
3992
  }
1308
3993
  }, [clearOtpTrigger, resetActionState]);
1309
- react.useEffect(() => {
3994
+ React.useEffect(() => {
1310
3995
  if (!isOpen || !isSubmitting) return;
1311
3996
  if (actionType !== "approve" && actionType !== "reject") return;
1312
3997
  const timeout = setTimeout(
@@ -1315,7 +4000,7 @@ function UserActionModal({
1315
4000
  );
1316
4001
  return () => clearTimeout(timeout);
1317
4002
  }, [isOpen, isSubmitting, actionType, resetActionState]);
1318
- react.useEffect(() => {
4003
+ React.useEffect(() => {
1319
4004
  if (!isOpen || !userActionRequest) return;
1320
4005
  if (otp.length !== schema.maxLength || !/^\d+$/.test(otp)) {
1321
4006
  return;
@@ -1348,7 +4033,7 @@ function UserActionModal({
1348
4033
  onApprove,
1349
4034
  resetActionState
1350
4035
  ]);
1351
- const handleReject = react.useCallback(async () => {
4036
+ const handleReject = React.useCallback(async () => {
1352
4037
  setIsSubmitting(true);
1353
4038
  setActionType("reject");
1354
4039
  try {
@@ -1357,7 +4042,7 @@ function UserActionModal({
1357
4042
  resetActionState();
1358
4043
  }
1359
4044
  }, [onReject, resetActionState]);
1360
- const handleResend = react.useCallback(async () => {
4045
+ const handleResend = React.useCallback(async () => {
1361
4046
  if (resendCooldownRemaining > 0) return;
1362
4047
  setIsSubmitting(true);
1363
4048
  setActionType("resend");
@@ -1388,32 +4073,32 @@ function UserActionModal({
1388
4073
  children: /* @__PURE__ */ jsxRuntime.jsx(
1389
4074
  reactNative.KeyboardAvoidingView,
1390
4075
  {
1391
- style: [s2.keyboardAvoid, { justifyContent: modalPosition }],
4076
+ style: [s8.keyboardAvoid, { justifyContent: modalPosition }],
1392
4077
  behavior: reactNative.Platform.OS === "ios" ? "padding" : "height",
1393
4078
  keyboardVerticalOffset: reactNative.Platform.OS === "ios" ? 0 : 20,
1394
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [s2.modalOverlay, { justifyContent: modalPosition }], children: /* @__PURE__ */ jsxRuntime.jsx(
4079
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [s8.modalOverlay, { justifyContent: modalPosition }], children: /* @__PURE__ */ jsxRuntime.jsx(
1395
4080
  reactNative.ScrollView,
1396
4081
  {
1397
4082
  contentContainerStyle: [
1398
- s2.scrollContent,
4083
+ s8.scrollContent,
1399
4084
  { justifyContent: modalPosition }
1400
4085
  ],
1401
4086
  showsVerticalScrollIndicator: false,
1402
4087
  keyboardShouldPersistTaps: "handled",
1403
- children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [s2.dialog, { width: DIALOG_MAX_WIDTH }], children: [
4088
+ children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [s8.dialog, { width: DIALOG_MAX_WIDTH }], children: [
1404
4089
  /* @__PURE__ */ jsxRuntime.jsx(
1405
4090
  reactNative.Pressable,
1406
4091
  {
1407
4092
  onPress: handleReject,
1408
4093
  disabled: isSubmitting,
1409
- style: s2.closeBtn,
4094
+ style: s8.closeBtn,
1410
4095
  accessibilityLabel: "Close",
1411
4096
  hitSlop: 8,
1412
- children: ({ pressed }) => /* @__PURE__ */ jsxRuntime.jsx(
4097
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1413
4098
  lucideReactNative.X,
1414
4099
  {
1415
4100
  size: 16,
1416
- color: pressed && !isSubmitting ? PAYMAN.foreground : PAYMAN.mutedForeground,
4101
+ color: PAYMAN.mutedForeground,
1417
4102
  strokeWidth: 2.5
1418
4103
  }
1419
4104
  )
@@ -1422,19 +4107,19 @@ function UserActionModal({
1422
4107
  /* @__PURE__ */ jsxRuntime.jsx(
1423
4108
  reactNative.Text,
1424
4109
  {
1425
- style: s2.description,
4110
+ style: s8.description,
1426
4111
  accessibilityLabel: "payman-modal-desc",
1427
4112
  children: userActionRequest.message
1428
4113
  }
1429
4114
  ),
1430
- isPayment ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s2.transferLabel, children: "Pay" }) : null,
1431
- isPayment && userActionRequest.metadata?.amount ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s2.heroAmount, children: formatAmountForDisplay(userActionRequest.metadata.amount) }) : null,
1432
- isPayee ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s2.transferLabel, children: "Create Payee" }) : null,
1433
- isPayee && userActionRequest.metadata?.payeeName ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s2.heroPayeeWrap, children: [
1434
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s2.heroPayeeName, children: userActionRequest.metadata.payeeName }),
1435
- userActionRequest.metadata.payeeType ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s2.heroPayeeType, children: userActionRequest.metadata.payeeType }) : null
4115
+ isPayment ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s8.transferLabel, children: "Pay" }) : null,
4116
+ isPayment && userActionRequest.metadata?.amount ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s8.heroAmount, children: formatAmountForDisplay(userActionRequest.metadata.amount) }) : null,
4117
+ isPayee ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s8.transferLabel, children: "Create Payee" }) : null,
4118
+ isPayee && userActionRequest.metadata?.payeeName ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s8.heroPayeeWrap, children: [
4119
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s8.heroPayeeName, children: userActionRequest.metadata.payeeName }),
4120
+ userActionRequest.metadata.payeeType ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s8.heroPayeeType, children: userActionRequest.metadata.payeeType }) : null
1436
4121
  ] }) : null,
1437
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s2.otpWrap, accessibilityLabel: "payman-otp-wrap", children: [
4122
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s8.otpWrap, accessibilityLabel: "payman-otp-wrap", children: [
1438
4123
  /* @__PURE__ */ jsxRuntime.jsx(
1439
4124
  OtpInput,
1440
4125
  {
@@ -1445,7 +4130,7 @@ function UserActionModal({
1445
4130
  error: otpError
1446
4131
  }
1447
4132
  ),
1448
- isVerifying ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s2.verifyingRow, children: [
4133
+ isVerifying ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s8.verifyingRow, children: [
1449
4134
  /* @__PURE__ */ jsxRuntime.jsx(
1450
4135
  reactNative.ActivityIndicator,
1451
4136
  {
@@ -1453,10 +4138,10 @@ function UserActionModal({
1453
4138
  color: PAYMAN_BRAND_GREEN
1454
4139
  }
1455
4140
  ),
1456
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s2.verifyingText, children: MODAL_CONTENT.LOADING_APPROVE })
4141
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s8.verifyingText, children: MODAL_CONTENT.LOADING_APPROVE })
1457
4142
  ] }) : null
1458
4143
  ] }),
1459
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s2.linksCol, children: [
4144
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s8.linksCol, children: [
1460
4145
  /* @__PURE__ */ jsxRuntime.jsx(
1461
4146
  reactNative.Pressable,
1462
4147
  {
@@ -1464,15 +4149,14 @@ function UserActionModal({
1464
4149
  disabled: isSubmitting || resendCooldownRemaining > 0,
1465
4150
  accessibilityLabel: "payman-modal-btn-resend",
1466
4151
  testID: "payman-modal-btn-resend",
1467
- children: ({ pressed }) => /* @__PURE__ */ jsxRuntime.jsx(
4152
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1468
4153
  reactNative.Text,
1469
4154
  {
1470
4155
  style: [
1471
- s2.linkText,
1472
- pressed && { opacity: 0.6 },
1473
- (isSubmitting || resendCooldownRemaining > 0) && s2.linkDisabled
4156
+ s8.linkText,
4157
+ (isSubmitting || resendCooldownRemaining > 0) && s8.linkDisabled
1474
4158
  ],
1475
- children: actionType === "resend" ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: MODAL_CONTENT.LOADING_RESEND }) : resendCooldownRemaining > 0 ? `${MODAL_CONTENT.RESEND_AVAILABLE_IN} ${resendCooldownRemaining}s` : BUTTON_LABELS.RESEND_CODE
4159
+ children: actionType === "resend" ? MODAL_CONTENT.LOADING_RESEND : resendCooldownRemaining > 0 ? `${MODAL_CONTENT.RESEND_AVAILABLE_IN} ${resendCooldownRemaining}s` : BUTTON_LABELS.RESEND_CODE
1476
4160
  }
1477
4161
  )
1478
4162
  }
@@ -1484,7 +4168,7 @@ function UserActionModal({
1484
4168
  disabled: isSubmitting,
1485
4169
  accessibilityLabel: "payman-modal-btn-reject",
1486
4170
  testID: "payman-modal-btn-reject",
1487
- children: ({ pressed }) => /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "center", gap: 6 }, children: [
4171
+ children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: { flexDirection: "row", alignItems: "center", justifyContent: "center", gap: 6 }, children: [
1488
4172
  isCancelling ? /* @__PURE__ */ jsxRuntime.jsx(
1489
4173
  reactNative.ActivityIndicator,
1490
4174
  {
@@ -1496,11 +4180,8 @@ function UserActionModal({
1496
4180
  reactNative.Text,
1497
4181
  {
1498
4182
  style: [
1499
- s2.linkText,
1500
- pressed && !isSubmitting && {
1501
- color: PAYMAN.foreground
1502
- },
1503
- isSubmitting && !isCancelling && s2.linkDisabled
4183
+ s8.linkText,
4184
+ isSubmitting && !isCancelling && s8.linkDisabled
1504
4185
  ],
1505
4186
  children: isCancelling ? MODAL_CONTENT.LOADING_REJECT : isPayee ? BUTTON_LABELS.CANCEL : BUTTON_LABELS.CANCEL_TRANSFER
1506
4187
  }
@@ -1509,19 +4190,19 @@ function UserActionModal({
1509
4190
  }
1510
4191
  )
1511
4192
  ] }),
1512
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s2.footer, children: [
1513
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s2.footerPrefix, children: MODAL_CONTENT.SECURED_BY_PREFIX }),
4193
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: s8.footer, children: [
4194
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s8.footerPrefix, children: MODAL_CONTENT.SECURED_BY_PREFIX }),
1514
4195
  /* @__PURE__ */ jsxRuntime.jsx(
1515
4196
  reactNative.Image,
1516
4197
  {
1517
4198
  source: { uri: payman_mono_crop_blue_default },
1518
- style: s2.footerLogo,
4199
+ style: s8.footerLogo,
1519
4200
  resizeMode: "contain",
1520
4201
  accessibilityElementsHidden: true,
1521
4202
  importantForAccessibility: "no-hide-descendants"
1522
4203
  }
1523
4204
  ),
1524
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s2.footerBrand, children: MODAL_CONTENT.SECURED_BY_BRAND })
4205
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: s8.footerBrand, children: MODAL_CONTENT.SECURED_BY_BRAND })
1525
4206
  ] })
1526
4207
  ] })
1527
4208
  }
@@ -1531,7 +4212,7 @@ function UserActionModal({
1531
4212
  }
1532
4213
  );
1533
4214
  }
1534
- var s2 = reactNative.StyleSheet.create({
4215
+ var s8 = reactNative.StyleSheet.create({
1535
4216
  keyboardAvoid: {
1536
4217
  flex: 1,
1537
4218
  width: "100%"
@@ -1742,7 +4423,7 @@ function FloatingChat({
1742
4423
  defaultOpen = false,
1743
4424
  showNotificationBadge = false
1744
4425
  }) {
1745
- const [isOpen, setIsOpen] = react.useState(defaultOpen);
4426
+ const [isOpen, setIsOpen] = React.useState(defaultOpen);
1746
4427
  const toggleChat = () => setIsOpen(!isOpen);
1747
4428
  const buttonSizes = { sm: "w-12 h-12", md: "w-14 h-14", lg: "w-16 h-16" };
1748
4429
  const iconSizes = { sm: "w-5 h-5", md: "w-6 h-6", lg: "w-7 h-7" };
@@ -1843,9 +4524,9 @@ function FloatingChat({
1843
4524
  )
1844
4525
  ] });
1845
4526
  }
1846
- var PaymanChatContext = react.createContext(void 0);
4527
+ var PaymanChatContext = React.createContext(void 0);
1847
4528
  function usePaymanChat() {
1848
- const ctx = react.useContext(PaymanChatContext);
4529
+ const ctx = React.useContext(PaymanChatContext);
1849
4530
  if (!ctx) {
1850
4531
  throw new Error("usePaymanChat must be used within a PaymanChat component");
1851
4532
  }