@paymanai/payman-ask-sdk 1.2.17 → 1.2.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import { useChat, useVoice } from '@paymanai/payman-typescript-ask-sdk';
2
2
  export { cancelUserAction, generateId, resendUserAction, streamWorkflowEvents, submitUserAction, useChat, useVoice } from '@paymanai/payman-typescript-ask-sdk';
3
- import { createContext, forwardRef, useState, useRef, useMemo, useImperativeHandle, useEffect, useCallback, useLayoutEffect, useContext } from 'react';
3
+ import { AnimatePresence, motion } from 'framer-motion';
4
+ import { createContext, forwardRef, useState, useRef, useEffect, useMemo, useImperativeHandle, useCallback, useLayoutEffect, useContext } from 'react';
4
5
  import { clsx } from 'clsx';
5
6
  import { twMerge } from 'tailwind-merge';
6
- import { motion, AnimatePresence } from 'framer-motion';
7
- import { MessageCircle, ArrowDown, Square, Mic, ArrowUp, ShieldCheck, Loader2, X, Check, RefreshCw, User, Clock, Sparkles, Binoculars, ChevronDown, ChevronRight } from 'lucide-react';
7
+ import { Check, RotateCcw, Mic, ArrowUp, ArrowDown, X, Loader2, User, Clock, Sparkles, Binoculars, ChevronDown, ChevronRight } from 'lucide-react';
8
8
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
9
  import ReactMarkdown from 'react-markdown';
10
10
  import remarkGfm from 'remark-gfm';
@@ -68,20 +68,25 @@ function ChatInput({
68
68
  enableVoice = false,
69
69
  onVoicePress,
70
70
  voiceAvailable = false,
71
- isRecording = false
71
+ isRecording = false,
72
+ transcribedText = "",
73
+ onCancelRecording,
74
+ onConfirmRecording,
75
+ showResetSession = false,
76
+ onResetSession
72
77
  }) {
73
78
  const textareaRef = useRef(null);
74
79
  const containerRef = useRef(null);
75
80
  const prevWaitingRef = useRef(isWaitingForResponse);
81
+ const [recordingSeconds, setRecordingSeconds] = useState(0);
82
+ const recordingTimerRef = useRef(null);
83
+ const [isFocused, setIsFocused] = useState(false);
76
84
  useEffect(() => {
77
85
  if (textareaRef.current) {
78
86
  textareaRef.current.style.height = "auto";
79
87
  const scrollHeight = textareaRef.current.scrollHeight;
80
88
  const maxHeight = 160;
81
- textareaRef.current.style.height = `${Math.min(
82
- scrollHeight,
83
- maxHeight
84
- )}px`;
89
+ textareaRef.current.style.height = `${Math.min(scrollHeight, maxHeight)}px`;
85
90
  }
86
91
  }, [value]);
87
92
  useEffect(() => {
@@ -99,6 +104,25 @@ function ChatInput({
99
104
  });
100
105
  }
101
106
  }, [isWaitingForResponse]);
107
+ useEffect(() => {
108
+ if (isRecording) {
109
+ setRecordingSeconds(0);
110
+ recordingTimerRef.current = setInterval(() => {
111
+ setRecordingSeconds((s) => s + 1);
112
+ }, 1e3);
113
+ } else {
114
+ if (recordingTimerRef.current) {
115
+ clearInterval(recordingTimerRef.current);
116
+ recordingTimerRef.current = null;
117
+ }
118
+ setRecordingSeconds(0);
119
+ }
120
+ return () => {
121
+ if (recordingTimerRef.current) {
122
+ clearInterval(recordingTimerRef.current);
123
+ }
124
+ };
125
+ }, [isRecording]);
102
126
  const handleKeyDown = (e) => {
103
127
  if (e.key === "Enter" && !e.shiftKey) {
104
128
  e.preventDefault();
@@ -114,101 +138,178 @@ function ChatInput({
114
138
  if (!isSessionParamsConfigured) return "Configure session params to begin";
115
139
  return placeholder;
116
140
  };
141
+ const formatTime = useCallback((seconds) => {
142
+ const mins = Math.floor(seconds / 60);
143
+ const secs = seconds % 60;
144
+ return `${String(mins).padStart(2, "0")}:${String(secs).padStart(2, "0")}`;
145
+ }, []);
146
+ const handleCancel = () => {
147
+ if (onCancelRecording) {
148
+ onCancelRecording();
149
+ } else if (onVoicePress) {
150
+ onVoicePress();
151
+ }
152
+ };
153
+ const handleConfirm = () => {
154
+ if (onConfirmRecording) {
155
+ onConfirmRecording();
156
+ } else if (onVoicePress) {
157
+ onVoicePress();
158
+ }
159
+ };
117
160
  return /* @__PURE__ */ jsx(
118
161
  "div",
119
162
  {
120
163
  ref: containerRef,
121
- className: cn("flex-shrink-0 w-full", className),
122
- style: { flexShrink: 0 },
123
- children: /* @__PURE__ */ jsx("div", { className: "px-3 pb-3 pt-1.5 w-full", children: /* @__PURE__ */ jsxs("div", { className: "relative w-full max-w-2xl mx-auto", children: [
124
- /* @__PURE__ */ jsxs(
125
- motion.div,
126
- {
127
- initial: false,
128
- className: cn(
129
- "flex items-end overflow-hidden",
130
- "payman-chat-input"
131
- ),
132
- children: [
133
- /* @__PURE__ */ jsx(
134
- "textarea",
135
- {
136
- ref: textareaRef,
137
- value,
138
- onChange: (e) => onChange(e.target.value),
139
- onKeyDown: handleKeyDown,
140
- onClick,
141
- disabled: isInputDisabled,
142
- placeholder: getPlaceholder(),
143
- className: cn(
144
- "payman-chat-input-field",
145
- "focus:outline-none resize-none overflow-y-auto",
146
- "flex-1 min-w-0 py-3"
147
- ),
148
- style: {
149
- minHeight: "44px",
150
- maxHeight: "160px",
151
- paddingLeft: "18px",
152
- paddingRight: "8px"
153
- },
154
- rows: 1
155
- }
156
- ),
157
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 shrink-0 p-2", children: [
158
- showVoiceButton && /* @__PURE__ */ jsxs(
159
- "button",
164
+ className: cn("payman-chat-input-wrapper", className),
165
+ children: /* @__PURE__ */ jsx("div", { className: "payman-chat-input-container", children: /* @__PURE__ */ jsxs("div", { className: "payman-chat-input-inner", children: [
166
+ /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: isRecording ? (
167
+ /* ======== Recording State ======== */
168
+ /* @__PURE__ */ jsxs(
169
+ motion.div,
170
+ {
171
+ initial: { opacity: 0, y: 6 },
172
+ animate: { opacity: 1, y: 0 },
173
+ exit: { opacity: 0, y: 6 },
174
+ transition: { duration: 0.25, ease: [0.25, 0.46, 0.45, 0.94] },
175
+ className: "payman-chat-input payman-chat-input--recording",
176
+ children: [
177
+ /* @__PURE__ */ jsx("div", { className: "payman-recording-transcript-area", children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: transcribedText ? /* @__PURE__ */ jsxs(
178
+ motion.p,
160
179
  {
161
- type: "button",
162
- onClick: onVoicePress,
163
- disabled: isVoiceButtonDisabled,
164
- className: cn(
165
- "relative flex items-center justify-center",
166
- "w-8 h-8 rounded-full transition-all duration-200",
167
- "payman-chat-input-btn-voice",
168
- isRecording && "recording"
169
- ),
170
- "aria-label": isRecording ? "Stop recording" : "Voice input",
180
+ initial: { opacity: 0 },
181
+ animate: { opacity: 1 },
182
+ exit: { opacity: 0 },
183
+ transition: { duration: 0.15 },
184
+ className: "payman-recording-transcript-text",
171
185
  children: [
172
- isRecording && /* @__PURE__ */ jsx(
173
- "span",
174
- {
175
- className: "absolute inset-0 rounded-full border-2 animate-ping opacity-40",
176
- style: {
177
- borderColor: "var(--payman-input-btn-voice-recording-ring)"
178
- }
179
- }
180
- ),
181
- isRecording ? /* @__PURE__ */ jsx(
182
- Square,
186
+ transcribedText,
187
+ /* @__PURE__ */ jsx(
188
+ motion.span,
183
189
  {
184
- className: "w-3 h-3 relative z-10",
185
- fill: "currentColor"
190
+ className: "payman-recording-cursor",
191
+ animate: { opacity: [1, 0] },
192
+ transition: { duration: 0.8, repeat: Infinity, repeatType: "reverse" }
186
193
  }
187
- ) : /* @__PURE__ */ jsx(Mic, { className: "w-4 h-4" })
194
+ )
188
195
  ]
189
- }
190
- ),
196
+ },
197
+ "text"
198
+ ) : /* @__PURE__ */ jsx(
199
+ motion.p,
200
+ {
201
+ initial: { opacity: 0 },
202
+ animate: { opacity: 0.5 },
203
+ className: "payman-recording-transcript-placeholder",
204
+ children: "Listening..."
205
+ },
206
+ "placeholder"
207
+ ) }) }),
208
+ /* @__PURE__ */ jsxs("div", { className: "payman-recording-bar", children: [
209
+ /* @__PURE__ */ jsx(
210
+ "button",
211
+ {
212
+ type: "button",
213
+ onClick: handleCancel,
214
+ className: "payman-recording-btn-cancel",
215
+ "aria-label": "Cancel recording",
216
+ children: "Cancel"
217
+ }
218
+ ),
219
+ /* @__PURE__ */ jsxs("div", { className: "payman-recording-indicator", children: [
220
+ /* @__PURE__ */ jsx("span", { className: "payman-recording-dot" }),
221
+ /* @__PURE__ */ jsx("span", { className: "payman-recording-timer", children: formatTime(recordingSeconds) })
222
+ ] }),
223
+ /* @__PURE__ */ jsx(
224
+ "button",
225
+ {
226
+ type: "button",
227
+ onClick: handleConfirm,
228
+ className: "payman-recording-btn-confirm",
229
+ "aria-label": "Confirm recording",
230
+ children: /* @__PURE__ */ jsx(Check, { className: "w-4 h-4", strokeWidth: 2.5 })
231
+ }
232
+ )
233
+ ] })
234
+ ]
235
+ },
236
+ "recording"
237
+ )
238
+ ) : (
239
+ /* ======== Normal Input State ======== */
240
+ /* @__PURE__ */ jsxs(
241
+ motion.div,
242
+ {
243
+ initial: false,
244
+ animate: { opacity: 1, y: 0 },
245
+ exit: { opacity: 0, y: 6 },
246
+ transition: { duration: 0.2 },
247
+ className: cn(
248
+ "payman-chat-input",
249
+ isFocused && "payman-chat-input--focused"
250
+ ),
251
+ children: [
191
252
  /* @__PURE__ */ jsx(
192
- "button",
253
+ "textarea",
193
254
  {
194
- type: "button",
195
- onClick: onSend,
196
- disabled: !canSend,
197
- className: cn(
198
- "flex items-center justify-center",
199
- "w-8 h-8 rounded-full",
200
- "payman-chat-input-btn-send",
201
- "hover:opacity-90 active:scale-95",
202
- "transition-all duration-150"
203
- ),
204
- "aria-label": "Send message",
205
- children: /* @__PURE__ */ jsx(ArrowUp, { className: "w-4 h-4", strokeWidth: 2.5 })
255
+ ref: textareaRef,
256
+ value,
257
+ onChange: (e) => onChange(e.target.value),
258
+ onKeyDown: handleKeyDown,
259
+ onFocus: () => setIsFocused(true),
260
+ onBlur: () => setIsFocused(false),
261
+ onClick,
262
+ disabled: isInputDisabled,
263
+ placeholder: getPlaceholder(),
264
+ className: "payman-chat-input-field",
265
+ rows: 1
206
266
  }
207
- )
208
- ] })
209
- ]
210
- }
211
- ),
267
+ ),
268
+ /* @__PURE__ */ jsxs("div", { className: "payman-chat-input-bottom", children: [
269
+ /* @__PURE__ */ jsx("div", { className: "payman-chat-input-actions-left", children: showResetSession && onResetSession && /* @__PURE__ */ jsxs(
270
+ "button",
271
+ {
272
+ type: "button",
273
+ onClick: onResetSession,
274
+ disabled: isWaitingForResponse,
275
+ className: "payman-chat-input-btn-reset",
276
+ "aria-label": "New Session",
277
+ children: [
278
+ /* @__PURE__ */ jsx(RotateCcw, { className: "w-3.5 h-3.5", strokeWidth: 2.5 }),
279
+ /* @__PURE__ */ jsx("span", { className: "payman-chat-input-btn-reset-tooltip", children: "New Session" })
280
+ ]
281
+ }
282
+ ) }),
283
+ /* @__PURE__ */ jsxs("div", { className: "payman-chat-input-actions", children: [
284
+ showVoiceButton && /* @__PURE__ */ jsx(
285
+ "button",
286
+ {
287
+ type: "button",
288
+ onClick: onVoicePress,
289
+ disabled: isVoiceButtonDisabled,
290
+ className: "payman-chat-input-btn-voice",
291
+ "aria-label": "Voice input",
292
+ children: /* @__PURE__ */ jsx(Mic, { className: "w-[18px] h-[18px]" })
293
+ }
294
+ ),
295
+ /* @__PURE__ */ jsx(
296
+ "button",
297
+ {
298
+ type: "button",
299
+ onClick: onSend,
300
+ disabled: !canSend,
301
+ className: "payman-chat-input-btn-send",
302
+ "aria-label": "Send message",
303
+ children: /* @__PURE__ */ jsx(ArrowUp, { className: "w-4 h-4", strokeWidth: 2.5 })
304
+ }
305
+ )
306
+ ] })
307
+ ] })
308
+ ]
309
+ },
310
+ "input"
311
+ )
312
+ ) }),
212
313
  /* @__PURE__ */ jsx("p", { className: "payman-chat-input-disclaimer", children: AI_DISCLAIMER_TEXT })
213
314
  ] }) })
214
315
  }
@@ -777,6 +878,7 @@ function MessageList({
777
878
  isLoading = false,
778
879
  emptyStateText = "What can I help with?",
779
880
  showEmptyStateIcon = true,
881
+ emptyStateComponent,
780
882
  layout = "full-width",
781
883
  showTimestamps = false,
782
884
  stage = "DEV",
@@ -901,7 +1003,7 @@ function MessageList({
901
1003
  }
902
1004
  if (messages.length === 0) {
903
1005
  const lines = emptyStateText.split("\n").map((l) => l.trim()).filter(Boolean);
904
- return /* @__PURE__ */ jsx("div", { className: cn("payman-empty-root p-8", className), children: /* @__PURE__ */ jsxs(
1006
+ return /* @__PURE__ */ jsx("div", { className: cn("payman-empty-root", className), children: /* @__PURE__ */ jsxs(
905
1007
  motion.div,
906
1008
  {
907
1009
  initial: { opacity: 0, y: 20 },
@@ -909,17 +1011,17 @@ function MessageList({
909
1011
  transition: { duration: 0.5, ease: [0.25, 0.46, 0.45, 0.94] },
910
1012
  className: "payman-empty-content",
911
1013
  children: [
912
- showEmptyStateIcon && /* @__PURE__ */ jsx(
1014
+ emptyStateComponent && /* @__PURE__ */ jsx(
913
1015
  motion.div,
914
1016
  {
915
- initial: { scale: 0.85, opacity: 0 },
1017
+ initial: { scale: 0.9, opacity: 0 },
916
1018
  animate: { scale: 1, opacity: 1 },
917
- transition: { delay: 0.08, duration: 0.45, ease: [0.25, 0.46, 0.45, 0.94] },
918
- className: "payman-empty-icon-wrap",
919
- children: /* @__PURE__ */ jsx(MessageCircle, { className: "h-7 w-7 payman-empty-icon", strokeWidth: 1.5 })
1019
+ transition: { delay: 0.05, duration: 0.45, ease: [0.25, 0.46, 0.45, 0.94] },
1020
+ className: "payman-empty-custom-component",
1021
+ children: emptyStateComponent
920
1022
  }
921
1023
  ),
922
- /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-1.5", children: lines.map((line, i) => /* @__PURE__ */ jsx(
1024
+ /* @__PURE__ */ jsx("div", { className: "payman-empty-text-group", children: lines.map((line, i) => /* @__PURE__ */ jsx(
923
1025
  motion.p,
924
1026
  {
925
1027
  initial: { opacity: 0, y: 6 },
@@ -997,18 +1099,26 @@ function MessageList({
997
1099
  }
998
1100
  ) });
999
1101
  }
1102
+
1103
+ // src/assets/payman-mono-crop-blue.png
1104
+ var payman_mono_crop_blue_default = "data:image/png;base64,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";
1000
1105
  var DEFAULT_MAX_LENGTH = 6;
1001
1106
  var MAX_SUPPORTED_LENGTH = 12;
1002
1107
  var AUTO_FOCUS_DELAY_MS = 250;
1108
+ var COMPLETE_PULSE_MS = 400;
1003
1109
  function OtpInput({
1004
1110
  value,
1005
1111
  onChange,
1006
1112
  maxLength,
1007
- disabled = false
1113
+ disabled = false,
1114
+ error = false
1008
1115
  }) {
1009
1116
  const inputRefs = useRef([]);
1117
+ const [completePulse, setCompletePulse] = useState(false);
1118
+ const prevLenRef = useRef(0);
1010
1119
  const safeMaxLength = Number.isInteger(maxLength) && maxLength > 0 ? Math.min(maxLength, MAX_SUPPORTED_LENGTH) : DEFAULT_MAX_LENGTH;
1011
1120
  const digits = value.split("").concat(Array(safeMaxLength).fill("")).slice(0, safeMaxLength);
1121
+ const isFull = value.length === safeMaxLength && /^\d+$/.test(value);
1012
1122
  useEffect(() => {
1013
1123
  if (disabled) return;
1014
1124
  const timer = window.setTimeout(() => {
@@ -1016,6 +1126,22 @@ function OtpInput({
1016
1126
  }, AUTO_FOCUS_DELAY_MS);
1017
1127
  return () => window.clearTimeout(timer);
1018
1128
  }, [disabled]);
1129
+ useEffect(() => {
1130
+ let t;
1131
+ if (isFull && prevLenRef.current < safeMaxLength) {
1132
+ setCompletePulse(true);
1133
+ t = window.setTimeout(
1134
+ () => setCompletePulse(false),
1135
+ COMPLETE_PULSE_MS
1136
+ );
1137
+ }
1138
+ prevLenRef.current = value.length;
1139
+ return () => {
1140
+ if (typeof t === "number") {
1141
+ window.clearTimeout(t);
1142
+ }
1143
+ };
1144
+ }, [isFull, value.length, safeMaxLength]);
1019
1145
  const focusInput = (index) => {
1020
1146
  if (index >= 0 && index < safeMaxLength) {
1021
1147
  inputRefs.current[index]?.focus();
@@ -1066,38 +1192,57 @@ function OtpInput({
1066
1192
  updateValue(newDigits);
1067
1193
  focusInput(Math.min(pasted.length, safeMaxLength - 1));
1068
1194
  };
1069
- return /* @__PURE__ */ jsx("div", { className: "flex gap-2.5 justify-center", children: digits.map((digit, i) => /* @__PURE__ */ jsx(
1070
- "input",
1195
+ return /* @__PURE__ */ jsx(
1196
+ "div",
1071
1197
  {
1072
- ref: (el) => {
1073
- inputRefs.current[i] = el;
1074
- },
1075
- type: "text",
1076
- inputMode: "numeric",
1077
- maxLength: 1,
1078
- value: digit,
1079
- disabled,
1080
- onChange: (e) => handleChange(i, e.target.value.slice(-1)),
1081
- onKeyDown: (e) => handleKeyDown(i, e),
1082
- onPaste: handlePaste,
1083
- onFocus: (e) => e.target.select(),
1084
- "aria-label": `Digit ${i + 1}`,
1085
1198
  className: cn(
1086
- "w-12 h-14 text-center text-xl font-semibold rounded-xl",
1087
- "payman-otp-input otp-input",
1088
- "transition-all duration-150 cursor-text",
1089
- disabled && "cursor-not-allowed"
1090
- )
1091
- },
1092
- i
1093
- )) });
1199
+ "flex justify-center",
1200
+ error && "payman-otp-shake",
1201
+ completePulse && "payman-otp-complete-pulse"
1202
+ ),
1203
+ style: { gap: 10 },
1204
+ children: digits.map((digit, i) => /* @__PURE__ */ jsx(
1205
+ "input",
1206
+ {
1207
+ ref: (el) => {
1208
+ inputRefs.current[i] = el;
1209
+ },
1210
+ type: "text",
1211
+ inputMode: "numeric",
1212
+ maxLength: 1,
1213
+ value: digit,
1214
+ disabled,
1215
+ onChange: (e) => handleChange(i, e.target.value.slice(-1)),
1216
+ onKeyDown: (e) => handleKeyDown(i, e),
1217
+ onPaste: handlePaste,
1218
+ onFocus: (e) => e.target.select(),
1219
+ "aria-label": `Digit ${i + 1}`,
1220
+ className: cn(
1221
+ "text-center font-semibold rounded-lg",
1222
+ "payman-otp-input otp-input",
1223
+ "transition-all duration-150 cursor-text",
1224
+ disabled && "cursor-not-allowed",
1225
+ error && "payman-otp-input--error"
1226
+ ),
1227
+ style: {
1228
+ width: 44,
1229
+ height: 50,
1230
+ fontSize: 20
1231
+ }
1232
+ },
1233
+ i
1234
+ ))
1235
+ }
1236
+ );
1094
1237
  }
1095
1238
 
1096
1239
  // src/components/UserActionModal/constants.ts
1097
1240
  var BUTTON_LABELS = {
1098
- APPROVE: "Verify",
1099
- REJECT: "Reject",
1100
- RESEND: "Resend OTP"
1241
+ /** Link-style actions (new layout) */
1242
+ RESEND_CODE: "Resend OTP",
1243
+ CANCEL_TRANSFER: "Cancel Payment",
1244
+ /** Short cancel label for payee approval flows */
1245
+ CANCEL: "Cancel"
1101
1246
  };
1102
1247
  var RESEND_OTP_COOLDOWN_SECONDS = 30;
1103
1248
  var DEFAULT_OTP_MAX_LENGTH = 6;
@@ -1105,11 +1250,12 @@ var MIN_OTP_MAX_LENGTH = 1;
1105
1250
  var MAX_OTP_MAX_LENGTH = 12;
1106
1251
  var ACTION_PENDING_TIMEOUT_MS = 15e3;
1107
1252
  var MODAL_CONTENT = {
1108
- TITLE: "Verification Required",
1109
1253
  LOADING_APPROVE: "Verifying...",
1110
1254
  LOADING_REJECT: "Rejecting...",
1111
1255
  LOADING_RESEND: "Resending...",
1112
- RESEND_AVAILABLE_IN: "Resend OTP in"
1256
+ RESEND_AVAILABLE_IN: "Resend OTP in",
1257
+ SECURED_BY_PREFIX: "Secured by",
1258
+ SECURED_BY_BRAND: "Payman"
1113
1259
  };
1114
1260
 
1115
1261
  // src/components/UserActionModal/utils.ts
@@ -1126,6 +1272,18 @@ function getOtpSchemaFromRequest(schema) {
1126
1272
  maxLength: clampedMaxLength
1127
1273
  };
1128
1274
  }
1275
+ function formatAmountForDisplay(amount) {
1276
+ const normalized = amount.replace(/,/g, "").trim();
1277
+ const n = Number(normalized);
1278
+ if (!Number.isFinite(n)) {
1279
+ return amount.startsWith("$") ? amount : `$${amount}`;
1280
+ }
1281
+ return new Intl.NumberFormat("en-US", {
1282
+ style: "currency",
1283
+ currency: "USD"
1284
+ }).format(n);
1285
+ }
1286
+ var OTP_ERROR_FLASH_MS = 600;
1129
1287
  function UserActionModal({
1130
1288
  isOpen,
1131
1289
  userActionRequest,
@@ -1138,8 +1296,12 @@ function UserActionModal({
1138
1296
  const [actionType, setActionType] = useState(null);
1139
1297
  const [isSubmitting, setIsSubmitting] = useState(false);
1140
1298
  const [resendCooldownRemaining, setResendCooldownRemaining] = useState(0);
1299
+ const [otpError, setOtpError] = useState(false);
1141
1300
  const dialogRef = useRef(null);
1142
1301
  const previousFocusedRef = useRef(null);
1302
+ const lastAutoSubmittedRef = useRef("");
1303
+ const submitInFlightRef = useRef(false);
1304
+ const submitGenerationRef = useRef(0);
1143
1305
  const schema = getOtpSchemaFromRequest(userActionRequest?.requestedSchema);
1144
1306
  const resetActionState = useCallback(() => {
1145
1307
  setIsSubmitting(false);
@@ -1152,6 +1314,10 @@ function UserActionModal({
1152
1314
  setOtp("");
1153
1315
  resetActionState();
1154
1316
  setResendCooldownRemaining(0);
1317
+ setOtpError(false);
1318
+ lastAutoSubmittedRef.current = "";
1319
+ submitInFlightRef.current = false;
1320
+ submitGenerationRef.current += 1;
1155
1321
  }
1156
1322
  }, [isOpen, resetActionState]);
1157
1323
  useEffect(() => {
@@ -1164,8 +1330,13 @@ function UserActionModal({
1164
1330
  }, [resendCooldownRemaining]);
1165
1331
  useEffect(() => {
1166
1332
  if (clearOtpTrigger > 0) {
1167
- setOtp("");
1168
- resetActionState();
1333
+ setOtpError(true);
1334
+ const t = setTimeout(() => {
1335
+ setOtpError(false);
1336
+ setOtp("");
1337
+ resetActionState();
1338
+ }, OTP_ERROR_FLASH_MS);
1339
+ return () => clearTimeout(t);
1169
1340
  }
1170
1341
  }, [clearOtpTrigger, resetActionState]);
1171
1342
  useEffect(() => {
@@ -1174,6 +1345,39 @@ function UserActionModal({
1174
1345
  const timeout = setTimeout(resetActionState, ACTION_PENDING_TIMEOUT_MS);
1175
1346
  return () => clearTimeout(timeout);
1176
1347
  }, [isOpen, isSubmitting, actionType, resetActionState]);
1348
+ useEffect(() => {
1349
+ if (!isOpen || !userActionRequest) return;
1350
+ if (otp.length !== schema.maxLength || !/^\d+$/.test(otp)) {
1351
+ return;
1352
+ }
1353
+ if (isSubmitting || submitInFlightRef.current) return;
1354
+ if (lastAutoSubmittedRef.current === otp) return;
1355
+ lastAutoSubmittedRef.current = otp;
1356
+ submitInFlightRef.current = true;
1357
+ const submitGeneration = submitGenerationRef.current;
1358
+ void (async () => {
1359
+ setIsSubmitting(true);
1360
+ setActionType("approve");
1361
+ try {
1362
+ await onApprove(otp);
1363
+ } catch {
1364
+ if (submitGenerationRef.current !== submitGeneration) return;
1365
+ resetActionState();
1366
+ lastAutoSubmittedRef.current = otp;
1367
+ } finally {
1368
+ if (submitGenerationRef.current !== submitGeneration) return;
1369
+ submitInFlightRef.current = false;
1370
+ }
1371
+ })();
1372
+ }, [
1373
+ otp,
1374
+ isOpen,
1375
+ isSubmitting,
1376
+ userActionRequest,
1377
+ schema.maxLength,
1378
+ onApprove,
1379
+ resetActionState
1380
+ ]);
1177
1381
  useEffect(() => {
1178
1382
  if (!isOpen) return;
1179
1383
  const dialog = dialogRef.current;
@@ -1223,16 +1427,6 @@ function UserActionModal({
1223
1427
  previousFocusedRef.current?.focus();
1224
1428
  };
1225
1429
  }, [isOpen]);
1226
- const handleApprove = useCallback(async () => {
1227
- if (otp.length !== schema.maxLength || !/^\d+$/.test(otp)) return;
1228
- setIsSubmitting(true);
1229
- setActionType("approve");
1230
- try {
1231
- await onApprove(otp);
1232
- } catch {
1233
- resetActionState();
1234
- }
1235
- }, [otp, schema.maxLength, onApprove, resetActionState]);
1236
1430
  const handleReject = useCallback(async () => {
1237
1431
  setIsSubmitting(true);
1238
1432
  setActionType("reject");
@@ -1256,7 +1450,10 @@ function UserActionModal({
1256
1450
  }
1257
1451
  }, [resendCooldownRemaining, onResend]);
1258
1452
  if (!isOpen || !userActionRequest) return null;
1259
- const isOtpValid = otp.length === schema.maxLength && /^\d+$/.test(otp);
1453
+ const isPayment = userActionRequest.userActionType === "PAYMENT_APPROVAL" && Boolean(userActionRequest.metadata?.amount);
1454
+ const isPayee = userActionRequest.userActionType === "PAYEE_APPROVAL" && Boolean(userActionRequest.metadata?.payeeName);
1455
+ const isVerifying = actionType === "approve" && isSubmitting;
1456
+ const isCancelling = actionType === "reject" && isSubmitting;
1260
1457
  return /* @__PURE__ */ jsxs(
1261
1458
  "div",
1262
1459
  {
@@ -1288,7 +1485,7 @@ function UserActionModal({
1288
1485
  style: {
1289
1486
  flexShrink: 0,
1290
1487
  width: "100%",
1291
- maxWidth: 400,
1488
+ maxWidth: 440,
1292
1489
  minWidth: 0
1293
1490
  },
1294
1491
  children: /* @__PURE__ */ jsxs(
@@ -1297,143 +1494,258 @@ function UserActionModal({
1297
1494
  ref: dialogRef,
1298
1495
  role: "dialog",
1299
1496
  "aria-modal": "true",
1300
- "aria-labelledby": "payman-modal-title",
1497
+ "aria-labelledby": "payman-user-action-message",
1301
1498
  className: cn(
1302
- "relative w-full rounded-2xl p-6 shadow-2xl",
1499
+ "relative w-full rounded-2xl shadow-2xl",
1303
1500
  "payman-modal-dialog payman-modal-animate"
1304
1501
  ),
1305
1502
  style: {
1306
1503
  width: "100%",
1307
- maxWidth: 400,
1504
+ maxWidth: 440,
1308
1505
  boxSizing: "border-box",
1506
+ padding: "36px 32px 28px",
1309
1507
  background: "var(--payman-modal-dialog-bg, var(--payman-card, #ffffff))",
1310
1508
  border: "1px solid var(--payman-modal-dialog-border, var(--payman-border, #e4e4e7))"
1311
1509
  },
1312
1510
  tabIndex: -1,
1313
1511
  children: [
1314
- /* @__PURE__ */ jsxs("div", { className: "text-center mb-5", children: [
1315
- /* @__PURE__ */ jsx(
1316
- "div",
1317
- {
1318
- className: "inline-flex items-center justify-center w-12 h-12 rounded-2xl payman-modal-icon-wrap mb-3",
1319
- style: {
1320
- background: "var(--payman-modal-icon-bg, color-mix(in srgb, var(--payman-primary, #18181b) 10%, transparent))",
1321
- border: "1px solid var(--payman-modal-icon-border, color-mix(in srgb, var(--payman-primary, #18181b) 20%, transparent))"
1322
- },
1323
- children: /* @__PURE__ */ jsx(
1324
- ShieldCheck,
1325
- {
1326
- className: "w-6 h-6 payman-modal-icon",
1327
- style: {
1328
- color: "var(--payman-modal-icon-fg, var(--payman-primary, #18181b))"
1329
- }
1330
- }
1331
- )
1332
- }
1333
- ),
1334
- /* @__PURE__ */ jsx(
1335
- "h2",
1336
- {
1337
- id: "payman-modal-title",
1338
- className: "text-lg font-semibold payman-modal-title tracking-tight",
1339
- style: {
1340
- color: "var(--payman-modal-title-fg, var(--payman-foreground, #18181b))"
1341
- },
1342
- children: MODAL_CONTENT.TITLE
1343
- }
1344
- )
1345
- ] }),
1512
+ /* @__PURE__ */ jsx(
1513
+ "button",
1514
+ {
1515
+ type: "button",
1516
+ onClick: handleReject,
1517
+ disabled: isSubmitting,
1518
+ className: "payman-modal-close-btn absolute flex items-center justify-center rounded-full border-0 bg-transparent p-0 cursor-pointer disabled:cursor-not-allowed",
1519
+ style: {
1520
+ top: 12,
1521
+ right: 12,
1522
+ width: 28,
1523
+ height: 28
1524
+ },
1525
+ "aria-label": "Close",
1526
+ children: /* @__PURE__ */ jsx(X, { size: 16, strokeWidth: 2.5 })
1527
+ }
1528
+ ),
1346
1529
  /* @__PURE__ */ jsx(
1347
1530
  "p",
1348
1531
  {
1349
- className: "text-sm payman-modal-desc text-center mb-6 leading-relaxed px-0.5",
1532
+ id: "payman-user-action-message",
1533
+ className: "text-center leading-snug",
1350
1534
  style: {
1535
+ fontSize: 14,
1536
+ lineHeight: 1.5,
1537
+ margin: "0 0 20px",
1538
+ paddingRight: 24,
1539
+ paddingLeft: 24,
1351
1540
  color: "var(--payman-modal-desc-fg, var(--payman-muted-foreground, #71717a))"
1352
1541
  },
1353
1542
  children: userActionRequest.message
1354
1543
  }
1355
1544
  ),
1356
- /* @__PURE__ */ jsx("div", { className: "mb-6", children: /* @__PURE__ */ jsx(
1357
- OtpInput,
1545
+ isPayment && /* @__PURE__ */ jsx(
1546
+ "p",
1358
1547
  {
1359
- value: otp,
1360
- onChange: setOtp,
1361
- maxLength: schema.maxLength,
1362
- disabled: isSubmitting
1548
+ className: "text-center font-semibold uppercase",
1549
+ style: {
1550
+ fontSize: 12,
1551
+ letterSpacing: "0.08em",
1552
+ margin: "0 0 4px",
1553
+ color: "var(--payman-modal-desc-fg, var(--payman-muted-foreground, #71717a))",
1554
+ opacity: 0.7
1555
+ },
1556
+ children: "Pay"
1363
1557
  }
1364
- ) }),
1365
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
1366
- /* @__PURE__ */ jsxs("div", { className: "flex gap-2.5", children: [
1367
- /* @__PURE__ */ jsxs(
1368
- "button",
1369
- {
1370
- type: "button",
1371
- onClick: handleReject,
1372
- disabled: isSubmitting,
1373
- className: cn(
1374
- "flex-1 flex items-center justify-center gap-2",
1375
- "min-h-[48px] py-3 px-4 rounded-xl text-sm font-medium border-0 cursor-pointer",
1376
- "payman-modal-btn-reject",
1377
- "active:scale-[0.98] transition-all duration-150",
1378
- "disabled:cursor-not-allowed"
1379
- ),
1380
- style: {
1381
- background: "var(--payman-modal-btn-reject-bg, color-mix(in srgb, var(--payman-destructive, #ef4444) 10%, transparent))",
1382
- color: "var(--payman-modal-btn-reject-fg, var(--payman-destructive, #ef4444))"
1383
- },
1384
- children: [
1385
- actionType === "reject" ? /* @__PURE__ */ jsx(Loader2, { className: "w-4 h-4 animate-spin shrink-0" }) : /* @__PURE__ */ jsx(X, { className: "w-4 h-4 shrink-0", strokeWidth: 2.5 }),
1386
- actionType === "reject" ? MODAL_CONTENT.LOADING_REJECT : BUTTON_LABELS.REJECT
1387
- ]
1388
- }
1389
- ),
1390
- /* @__PURE__ */ jsxs(
1391
- "button",
1392
- {
1393
- type: "button",
1394
- onClick: handleApprove,
1395
- disabled: !isOtpValid || isSubmitting,
1396
- className: cn(
1397
- "flex-1 flex items-center justify-center gap-2",
1398
- "min-h-[48px] py-3 px-4 rounded-xl text-sm font-medium border-0 cursor-pointer",
1399
- "payman-modal-btn-approve",
1400
- "active:scale-[0.98] transition-all duration-150",
1401
- "disabled:cursor-not-allowed"
1402
- ),
1403
- style: {
1404
- background: "var(--payman-modal-btn-approve-bg, var(--payman-primary, #18181b))",
1405
- color: "var(--payman-modal-btn-approve-fg, var(--payman-primary-foreground, #fafafa))"
1406
- },
1407
- children: [
1408
- actionType === "approve" ? /* @__PURE__ */ jsx(Loader2, { className: "w-4 h-4 animate-spin shrink-0" }) : /* @__PURE__ */ jsx(Check, { className: "w-4 h-4 shrink-0", strokeWidth: 2.5 }),
1409
- actionType === "approve" ? MODAL_CONTENT.LOADING_APPROVE : BUTTON_LABELS.APPROVE
1410
- ]
1411
- }
1412
- )
1413
- ] }),
1414
- /* @__PURE__ */ jsxs(
1415
- "button",
1416
- {
1417
- type: "button",
1418
- onClick: handleResend,
1419
- disabled: isSubmitting || resendCooldownRemaining > 0,
1420
- className: cn(
1421
- "w-full flex items-center justify-center gap-2",
1422
- "min-h-[48px] py-3 px-4 rounded-xl text-sm font-medium cursor-pointer",
1423
- "payman-modal-btn-resend",
1424
- "transition-all duration-150 disabled:cursor-not-allowed"
1558
+ ),
1559
+ isPayment && userActionRequest.metadata?.amount && /* @__PURE__ */ jsx(
1560
+ "p",
1561
+ {
1562
+ className: "text-center font-bold tabular-nums tracking-tight",
1563
+ style: {
1564
+ fontSize: 42,
1565
+ lineHeight: 1.1,
1566
+ margin: "0 0 32px",
1567
+ color: "var(--payman-modal-hero-fg, #0a3b44)"
1568
+ },
1569
+ children: formatAmountForDisplay(userActionRequest.metadata.amount)
1570
+ }
1571
+ ),
1572
+ isPayee && /* @__PURE__ */ jsx(
1573
+ "p",
1574
+ {
1575
+ className: "text-center font-semibold uppercase",
1576
+ style: {
1577
+ fontSize: 12,
1578
+ letterSpacing: "0.08em",
1579
+ margin: "0 0 4px",
1580
+ color: "var(--payman-modal-desc-fg, var(--payman-muted-foreground, #71717a))",
1581
+ opacity: 0.7
1582
+ },
1583
+ children: "Create Payee"
1584
+ }
1585
+ ),
1586
+ isPayee && userActionRequest.metadata?.payeeName && /* @__PURE__ */ jsxs(
1587
+ "div",
1588
+ {
1589
+ className: "text-center",
1590
+ style: { margin: "0 0 32px" },
1591
+ children: [
1592
+ /* @__PURE__ */ jsx(
1593
+ "p",
1594
+ {
1595
+ className: "font-bold leading-tight",
1596
+ style: {
1597
+ fontSize: 28,
1598
+ margin: "0 0 4px",
1599
+ color: "var(--payman-modal-hero-fg, #0a3b44)"
1600
+ },
1601
+ children: userActionRequest.metadata.payeeName
1602
+ }
1425
1603
  ),
1604
+ userActionRequest.metadata.payeeType ? /* @__PURE__ */ jsx(
1605
+ "p",
1606
+ {
1607
+ className: "font-semibold uppercase",
1608
+ style: {
1609
+ fontSize: 10,
1610
+ letterSpacing: "0.08em",
1611
+ margin: 0,
1612
+ color: "var(--payman-modal-hero-fg, #0a3b44)",
1613
+ opacity: 0.85
1614
+ },
1615
+ children: userActionRequest.metadata.payeeType
1616
+ }
1617
+ ) : null
1618
+ ]
1619
+ }
1620
+ ),
1621
+ /* @__PURE__ */ jsxs("div", { style: { marginBottom: 30 }, children: [
1622
+ /* @__PURE__ */ jsx(
1623
+ OtpInput,
1624
+ {
1625
+ value: otp,
1626
+ onChange: setOtp,
1627
+ maxLength: schema.maxLength,
1628
+ disabled: isSubmitting,
1629
+ error: otpError
1630
+ }
1631
+ ),
1632
+ isVerifying ? /* @__PURE__ */ jsxs(
1633
+ "div",
1634
+ {
1635
+ className: "flex items-center justify-center gap-2",
1426
1636
  style: {
1427
- border: "1px solid var(--payman-modal-btn-resend-border, var(--payman-border, #e4e4e7))",
1428
- color: "var(--payman-modal-btn-resend-fg, var(--payman-muted-foreground, #71717a))"
1637
+ marginTop: 10,
1638
+ fontSize: 12,
1639
+ color: "var(--payman-modal-hero-fg, #0a3b44)"
1429
1640
  },
1430
1641
  children: [
1431
- actionType === "resend" ? /* @__PURE__ */ jsx(Loader2, { className: "w-4 h-4 animate-spin shrink-0" }) : /* @__PURE__ */ jsx(RefreshCw, { className: "w-4 h-4 shrink-0", strokeWidth: 2.5 }),
1432
- actionType === "resend" ? MODAL_CONTENT.LOADING_RESEND : resendCooldownRemaining > 0 ? `${MODAL_CONTENT.RESEND_AVAILABLE_IN} ${resendCooldownRemaining}s` : BUTTON_LABELS.RESEND
1642
+ /* @__PURE__ */ jsx(
1643
+ Loader2,
1644
+ {
1645
+ className: "animate-spin shrink-0",
1646
+ style: { width: 14, height: 14 }
1647
+ }
1648
+ ),
1649
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: MODAL_CONTENT.LOADING_APPROVE })
1433
1650
  ]
1434
1651
  }
1435
- )
1436
- ] })
1652
+ ) : null
1653
+ ] }),
1654
+ /* @__PURE__ */ jsxs(
1655
+ "div",
1656
+ {
1657
+ className: "flex flex-col items-center",
1658
+ style: { gap: 12, marginBottom: 32 },
1659
+ children: [
1660
+ /* @__PURE__ */ jsx(
1661
+ "button",
1662
+ {
1663
+ type: "button",
1664
+ onClick: handleResend,
1665
+ disabled: isSubmitting || resendCooldownRemaining > 0,
1666
+ className: "payman-modal-link-resend border-0 bg-transparent p-0 cursor-pointer font-semibold transition-colors disabled:cursor-not-allowed disabled:opacity-40",
1667
+ style: {
1668
+ fontSize: 11,
1669
+ letterSpacing: "0.06em",
1670
+ color: "var(--payman-modal-desc-fg, var(--payman-muted-foreground, #71717a))"
1671
+ },
1672
+ children: actionType === "resend" ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5", children: [
1673
+ /* @__PURE__ */ jsx(Loader2, { className: "h-3 w-3 animate-spin" }),
1674
+ MODAL_CONTENT.LOADING_RESEND
1675
+ ] }) : resendCooldownRemaining > 0 ? `${MODAL_CONTENT.RESEND_AVAILABLE_IN} ${resendCooldownRemaining}s` : BUTTON_LABELS.RESEND_CODE
1676
+ }
1677
+ ),
1678
+ /* @__PURE__ */ jsx(
1679
+ "button",
1680
+ {
1681
+ type: "button",
1682
+ onClick: handleReject,
1683
+ disabled: isSubmitting,
1684
+ className: "payman-modal-link-cancel border-0 bg-transparent p-0 cursor-pointer font-semibold transition-colors disabled:cursor-not-allowed disabled:opacity-40",
1685
+ style: {
1686
+ fontSize: 11,
1687
+ letterSpacing: "0.06em",
1688
+ color: "var(--payman-modal-desc-fg, var(--payman-muted-foreground, #71717a))"
1689
+ },
1690
+ children: isCancelling ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5", children: [
1691
+ /* @__PURE__ */ jsx(Loader2, { className: "h-3 w-3 animate-spin" }),
1692
+ MODAL_CONTENT.LOADING_REJECT
1693
+ ] }) : isPayee ? BUTTON_LABELS.CANCEL : BUTTON_LABELS.CANCEL_TRANSFER
1694
+ }
1695
+ )
1696
+ ]
1697
+ }
1698
+ ),
1699
+ /* @__PURE__ */ jsxs(
1700
+ "div",
1701
+ {
1702
+ className: "flex flex-row flex-nowrap items-center justify-center gap-1.5",
1703
+ style: {
1704
+ borderTop: "1px solid var(--payman-modal-dialog-border, var(--payman-border, #e4e4e7))",
1705
+ paddingTop: 20
1706
+ },
1707
+ children: [
1708
+ /* @__PURE__ */ jsx(
1709
+ "span",
1710
+ {
1711
+ className: "font-medium whitespace-nowrap",
1712
+ style: {
1713
+ fontSize: 11,
1714
+ color: "var(--payman-modal-desc-fg, var(--payman-muted-foreground, #71717a))",
1715
+ opacity: 0.9
1716
+ },
1717
+ children: MODAL_CONTENT.SECURED_BY_PREFIX
1718
+ }
1719
+ ),
1720
+ /* @__PURE__ */ jsx(
1721
+ "img",
1722
+ {
1723
+ src: payman_mono_crop_blue_default,
1724
+ alt: "",
1725
+ style: {
1726
+ height: 18,
1727
+ width: "auto",
1728
+ flexShrink: 0,
1729
+ objectFit: "contain"
1730
+ },
1731
+ draggable: false
1732
+ }
1733
+ ),
1734
+ /* @__PURE__ */ jsx(
1735
+ "span",
1736
+ {
1737
+ className: "font-bold whitespace-nowrap",
1738
+ style: {
1739
+ fontSize: 12,
1740
+ letterSpacing: "0.02em",
1741
+ color: "var(--payman-modal-brand-fg, #0a3b44)"
1742
+ },
1743
+ children: MODAL_CONTENT.SECURED_BY_BRAND
1744
+ }
1745
+ )
1746
+ ]
1747
+ }
1748
+ )
1437
1749
  ]
1438
1750
  }
1439
1751
  )
@@ -1461,6 +1773,7 @@ var PaymanChat = forwardRef(function PaymanChat2({
1461
1773
  }, ref) {
1462
1774
  const [inputValue, setInputValue] = useState("");
1463
1775
  const prevInputValueRef = useRef(inputValue);
1776
+ const [hasEverSentMessage, setHasEverSentMessage] = useState(false);
1464
1777
  const chat = useChat(config, callbacks);
1465
1778
  const {
1466
1779
  messages,
@@ -1473,6 +1786,11 @@ var PaymanChat = forwardRef(function PaymanChat2({
1473
1786
  getSessionId,
1474
1787
  getMessages
1475
1788
  } = chat;
1789
+ useEffect(() => {
1790
+ if (messages.length > 0 && !hasEverSentMessage) {
1791
+ setHasEverSentMessage(true);
1792
+ }
1793
+ }, [messages.length, hasEverSentMessage]);
1476
1794
  const userActionState = chat.userActionState ?? DEFAULT_USER_ACTION_STATE;
1477
1795
  const approveUserAction = chat.approveUserAction ?? NOOP_ASYNC;
1478
1796
  const rejectUserAction = chat.rejectUserAction ?? NOOP_ASYNC;
@@ -1521,14 +1839,17 @@ var PaymanChat = forwardRef(function PaymanChat2({
1521
1839
  isWaitingForResponse
1522
1840
  ]
1523
1841
  );
1842
+ const { onExecutionTraceClick, onResetSession } = callbacks;
1524
1843
  useImperativeHandle(ref, () => ({
1525
- resetSession,
1844
+ resetSession: () => {
1845
+ resetSession();
1846
+ onResetSession?.();
1847
+ },
1526
1848
  clearMessages,
1527
1849
  cancelStream,
1528
1850
  getSessionId,
1529
1851
  getMessages
1530
- }), [resetSession, clearMessages, cancelStream, getSessionId, getMessages]);
1531
- const { onExecutionTraceClick } = callbacks;
1852
+ }), [resetSession, clearMessages, cancelStream, getSessionId, getMessages, onResetSession]);
1532
1853
  const {
1533
1854
  placeholder = "Type your message...",
1534
1855
  emptyStateText = "What can I help with?",
@@ -1550,7 +1871,9 @@ var PaymanChat = forwardRef(function PaymanChat2({
1550
1871
  animated = true,
1551
1872
  isChatDisabled = false,
1552
1873
  disabledComponent,
1553
- showEmptyStateIcon = true
1874
+ showEmptyStateIcon = true,
1875
+ emptyStateComponent,
1876
+ showResetSession = false
1554
1877
  } = config;
1555
1878
  const isSessionParamsConfigured = useMemo(() => {
1556
1879
  if (!sessionParams) return false;
@@ -1558,9 +1881,9 @@ var PaymanChat = forwardRef(function PaymanChat2({
1558
1881
  }, [sessionParams?.id, sessionParams?.name]);
1559
1882
  useEffect(() => {
1560
1883
  const wasEmpty = prevInputValueRef.current.trim() === "";
1561
- const isEmpty = inputValue.trim() === "";
1884
+ const isEmpty2 = inputValue.trim() === "";
1562
1885
  prevInputValueRef.current = inputValue;
1563
- if (!wasEmpty && isEmpty) {
1886
+ if (!wasEmpty && isEmpty2) {
1564
1887
  clearTranscript();
1565
1888
  if (isRecording) {
1566
1889
  stopRecording();
@@ -1576,14 +1899,23 @@ var PaymanChat = forwardRef(function PaymanChat2({
1576
1899
  setInputValue("");
1577
1900
  }
1578
1901
  };
1902
+ const handleCancelRecording = () => {
1903
+ stopRecording();
1904
+ clearTranscript();
1905
+ setInputValue("");
1906
+ };
1907
+ const handleConfirmRecording = () => {
1908
+ stopRecording();
1909
+ };
1579
1910
  const isInputDisabled = isWaitingForResponse || !isSessionParamsConfigured || disableInput;
1911
+ const isEmpty = messages.length === 0;
1580
1912
  if (isChatDisabled) {
1581
1913
  if (disabledComponent) {
1582
1914
  return /* @__PURE__ */ jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
1583
1915
  "div",
1584
1916
  {
1585
1917
  className: cn(
1586
- "bg-card overflow-hidden flex flex-col flex-[4]",
1918
+ "bg-background overflow-hidden flex flex-col flex-[4]",
1587
1919
  className
1588
1920
  ),
1589
1921
  style,
@@ -1598,7 +1930,7 @@ var PaymanChat = forwardRef(function PaymanChat2({
1598
1930
  "div",
1599
1931
  {
1600
1932
  className: cn(
1601
- "bg-card overflow-hidden flex flex-col flex-[4]",
1933
+ "bg-background overflow-hidden flex flex-col flex-[4]",
1602
1934
  className
1603
1935
  ),
1604
1936
  style,
@@ -1609,62 +1941,138 @@ var PaymanChat = forwardRef(function PaymanChat2({
1609
1941
  }
1610
1942
  ) });
1611
1943
  }
1944
+ const inputElement = hasAskPermission && /* @__PURE__ */ jsx(
1945
+ ChatInput,
1946
+ {
1947
+ value: inputValue,
1948
+ onChange: setInputValue,
1949
+ onSend: handleSend,
1950
+ onPause: cancelStream,
1951
+ disabled: isInputDisabled,
1952
+ placeholder: isRecording ? "Listening..." : placeholder,
1953
+ isWaitingForResponse,
1954
+ hasSelectedSession: true,
1955
+ isSessionParamsConfigured,
1956
+ enableVoice: config.enableVoice === true,
1957
+ onVoicePress: isRecording ? stopRecording : startRecording,
1958
+ voiceAvailable: config.enableVoice === true && voiceAvailable,
1959
+ isRecording,
1960
+ transcribedText: inputValue,
1961
+ onCancelRecording: handleCancelRecording,
1962
+ onConfirmRecording: handleConfirmRecording,
1963
+ inputStyle,
1964
+ layout,
1965
+ showResetSession,
1966
+ onResetSession: () => {
1967
+ resetSession();
1968
+ onResetSession?.();
1969
+ }
1970
+ }
1971
+ );
1612
1972
  return /* @__PURE__ */ jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
1613
1973
  "div",
1614
1974
  {
1615
1975
  className: cn(
1616
- "bg-card overflow-hidden flex flex-col flex-[4]",
1976
+ "bg-background overflow-hidden flex flex-col flex-[4]",
1617
1977
  className
1618
1978
  ),
1619
1979
  style,
1620
1980
  children: [
1621
1981
  children,
1622
- /* @__PURE__ */ jsx(
1623
- MessageList,
1624
- {
1625
- messages,
1626
- isLoading: false,
1627
- emptyStateText,
1628
- showEmptyStateIcon,
1629
- layout,
1630
- showTimestamps,
1631
- stage: config.stage || "DEV",
1632
- animated,
1633
- showAgentName,
1634
- agentName,
1635
- showAvatars,
1636
- showUserAvatar,
1637
- showAssistantAvatar,
1638
- showExecutionSteps,
1639
- showStreamingDot,
1640
- streamingStepsText,
1641
- completedStepsText,
1642
- onExecutionTraceClick,
1643
- onLoadMoreMessages,
1644
- isLoadingMoreMessages,
1645
- hasMoreMessages
1646
- }
1647
- ),
1648
- hasAskPermission && /* @__PURE__ */ jsx(
1649
- ChatInput,
1650
- {
1651
- value: inputValue,
1652
- onChange: setInputValue,
1653
- onSend: handleSend,
1654
- onPause: cancelStream,
1655
- disabled: isInputDisabled,
1656
- placeholder: isRecording ? "Listening..." : placeholder,
1657
- isWaitingForResponse,
1658
- hasSelectedSession: true,
1659
- isSessionParamsConfigured,
1660
- enableVoice: config.enableVoice === true,
1661
- onVoicePress: isRecording ? stopRecording : startRecording,
1662
- voiceAvailable: config.enableVoice === true && voiceAvailable,
1663
- isRecording,
1664
- inputStyle,
1665
- layout
1666
- }
1667
- ),
1982
+ /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: isEmpty && !hasEverSentMessage ? (
1983
+ /* ---- Centered empty state with input ---- */
1984
+ /* @__PURE__ */ jsx(
1985
+ motion.div,
1986
+ {
1987
+ initial: { opacity: 1 },
1988
+ exit: { opacity: 0 },
1989
+ transition: { duration: 0.3 },
1990
+ className: "payman-empty-centered-layout",
1991
+ children: /* @__PURE__ */ jsxs("div", { className: "payman-empty-centered-inner", children: [
1992
+ /* @__PURE__ */ jsx(
1993
+ MessageList,
1994
+ {
1995
+ messages,
1996
+ isLoading: false,
1997
+ emptyStateText,
1998
+ showEmptyStateIcon,
1999
+ emptyStateComponent,
2000
+ layout,
2001
+ showTimestamps,
2002
+ stage: config.stage || "DEV",
2003
+ animated,
2004
+ showAgentName,
2005
+ agentName,
2006
+ showAvatars,
2007
+ showUserAvatar,
2008
+ showAssistantAvatar,
2009
+ showExecutionSteps,
2010
+ showStreamingDot,
2011
+ streamingStepsText,
2012
+ completedStepsText,
2013
+ onExecutionTraceClick,
2014
+ onLoadMoreMessages,
2015
+ isLoadingMoreMessages,
2016
+ hasMoreMessages
2017
+ }
2018
+ ),
2019
+ /* @__PURE__ */ jsx(
2020
+ motion.div,
2021
+ {
2022
+ initial: { opacity: 0, y: 12 },
2023
+ animate: { opacity: 1, y: 0 },
2024
+ transition: { delay: 0.2, duration: 0.4, ease: [0.25, 0.46, 0.45, 0.94] },
2025
+ className: "payman-empty-centered-input",
2026
+ children: inputElement
2027
+ }
2028
+ )
2029
+ ] })
2030
+ },
2031
+ "empty-centered"
2032
+ )
2033
+ ) : (
2034
+ /* ---- Normal chat layout ---- */
2035
+ /* @__PURE__ */ jsxs(
2036
+ motion.div,
2037
+ {
2038
+ initial: hasEverSentMessage ? { opacity: 0 } : false,
2039
+ animate: { opacity: 1 },
2040
+ transition: { duration: 0.3 },
2041
+ className: "flex flex-col flex-1 min-h-0",
2042
+ children: [
2043
+ /* @__PURE__ */ jsx(
2044
+ MessageList,
2045
+ {
2046
+ messages,
2047
+ isLoading: false,
2048
+ emptyStateText,
2049
+ showEmptyStateIcon,
2050
+ emptyStateComponent,
2051
+ layout,
2052
+ showTimestamps,
2053
+ stage: config.stage || "DEV",
2054
+ animated,
2055
+ showAgentName,
2056
+ agentName,
2057
+ showAvatars,
2058
+ showUserAvatar,
2059
+ showAssistantAvatar,
2060
+ showExecutionSteps,
2061
+ showStreamingDot,
2062
+ streamingStepsText,
2063
+ completedStepsText,
2064
+ onExecutionTraceClick,
2065
+ onLoadMoreMessages,
2066
+ isLoadingMoreMessages,
2067
+ hasMoreMessages
2068
+ }
2069
+ ),
2070
+ inputElement
2071
+ ]
2072
+ },
2073
+ "chat-layout"
2074
+ )
2075
+ ) }),
1668
2076
  /* @__PURE__ */ jsx(
1669
2077
  UserActionModal,
1670
2078
  {