@paymanai/payman-ask-sdk 4.0.17 → 4.0.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.d.mts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +36 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +36 -4
- package/dist/index.mjs.map +1 -1
- package/dist/index.native.js +966 -24
- package/dist/index.native.js.map +1 -1
- package/package.json +2 -2
package/dist/index.native.js
CHANGED
|
@@ -1099,6 +1099,9 @@ async function cancelUserAction(config, userActionId) {
|
|
|
1099
1099
|
async function resendUserAction(config, userActionId) {
|
|
1100
1100
|
return sendUserActionRequest(config, userActionId, "resend");
|
|
1101
1101
|
}
|
|
1102
|
+
async function expireUserAction(config, userActionId) {
|
|
1103
|
+
return sendUserActionRequest(config, userActionId, "expired");
|
|
1104
|
+
}
|
|
1102
1105
|
var EMPTY_USER_ACTION_STATE = { prompts: [], notifications: [] };
|
|
1103
1106
|
function upsertPrompt(prompts, req) {
|
|
1104
1107
|
const active = { ...req, status: "pending" };
|
|
@@ -1390,6 +1393,19 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1390
1393
|
},
|
|
1391
1394
|
[setPromptStatus]
|
|
1392
1395
|
);
|
|
1396
|
+
const expireUserAction2 = react.useCallback(
|
|
1397
|
+
async (userActionId) => {
|
|
1398
|
+
setPromptStatus(userActionId, "expired");
|
|
1399
|
+
try {
|
|
1400
|
+
await expireUserAction(configRef.current, userActionId);
|
|
1401
|
+
} catch (error) {
|
|
1402
|
+
if (error instanceof UserActionStaleError) return;
|
|
1403
|
+
callbacksRef.current.onError?.(error);
|
|
1404
|
+
throw error;
|
|
1405
|
+
}
|
|
1406
|
+
},
|
|
1407
|
+
[setPromptStatus]
|
|
1408
|
+
);
|
|
1393
1409
|
const dismissNotification = react.useCallback((id) => {
|
|
1394
1410
|
setUserActionState((prev) => ({
|
|
1395
1411
|
...prev,
|
|
@@ -1469,6 +1485,7 @@ function useChatV2(config, callbacks = {}) {
|
|
|
1469
1485
|
submitUserAction: submitUserAction2,
|
|
1470
1486
|
cancelUserAction: cancelUserAction2,
|
|
1471
1487
|
resendUserAction: resendUserAction2,
|
|
1488
|
+
expireUserAction: expireUserAction2,
|
|
1472
1489
|
dismissNotification
|
|
1473
1490
|
};
|
|
1474
1491
|
}
|
|
@@ -1687,6 +1704,122 @@ function useVoice(config = {}, callbacks = {}) {
|
|
|
1687
1704
|
reset
|
|
1688
1705
|
};
|
|
1689
1706
|
}
|
|
1707
|
+
function classifyField(field) {
|
|
1708
|
+
if (!field) return "text";
|
|
1709
|
+
if (Array.isArray(field.oneOf) && field.oneOf.length > 0) return "select";
|
|
1710
|
+
switch (field.type) {
|
|
1711
|
+
case "boolean":
|
|
1712
|
+
return "boolean";
|
|
1713
|
+
case "integer":
|
|
1714
|
+
return "integer";
|
|
1715
|
+
case "number":
|
|
1716
|
+
return "decimal";
|
|
1717
|
+
case "string":
|
|
1718
|
+
return "text";
|
|
1719
|
+
default:
|
|
1720
|
+
return "text";
|
|
1721
|
+
}
|
|
1722
|
+
}
|
|
1723
|
+
function isNestedOrUnsupported(field) {
|
|
1724
|
+
if (!field) return false;
|
|
1725
|
+
if (field.type === "object" || field.type === "array") return true;
|
|
1726
|
+
if ("properties" in field && field.properties != null) return true;
|
|
1727
|
+
if ("items" in field && field.items != null) return true;
|
|
1728
|
+
return false;
|
|
1729
|
+
}
|
|
1730
|
+
function getOptions(field) {
|
|
1731
|
+
if (!field || !Array.isArray(field.oneOf)) return [];
|
|
1732
|
+
return field.oneOf.filter(
|
|
1733
|
+
(o) => !!o && typeof o === "object" && typeof o.const === "string"
|
|
1734
|
+
);
|
|
1735
|
+
}
|
|
1736
|
+
function isRequired(schema, key) {
|
|
1737
|
+
return Array.isArray(schema?.required) && schema.required.includes(key);
|
|
1738
|
+
}
|
|
1739
|
+
function coerceValue(field, raw) {
|
|
1740
|
+
const widget = classifyField(field);
|
|
1741
|
+
if (widget === "boolean") {
|
|
1742
|
+
if (typeof raw === "boolean") return raw;
|
|
1743
|
+
if (raw === "true") return true;
|
|
1744
|
+
if (raw === "false") return false;
|
|
1745
|
+
return Boolean(raw);
|
|
1746
|
+
}
|
|
1747
|
+
if (widget === "integer" || widget === "decimal") {
|
|
1748
|
+
if (raw === "" || raw == null) return void 0;
|
|
1749
|
+
const num = typeof raw === "number" ? raw : Number(String(raw).trim());
|
|
1750
|
+
if (Number.isNaN(num)) return void 0;
|
|
1751
|
+
return widget === "integer" ? Math.trunc(num) : num;
|
|
1752
|
+
}
|
|
1753
|
+
if (raw == null) return void 0;
|
|
1754
|
+
const str = String(raw);
|
|
1755
|
+
return str === "" ? void 0 : str;
|
|
1756
|
+
}
|
|
1757
|
+
function defaultValueFor(field) {
|
|
1758
|
+
if (!field || field.default === void 0) {
|
|
1759
|
+
return classifyField(field) === "boolean" ? false : "";
|
|
1760
|
+
}
|
|
1761
|
+
return field.default;
|
|
1762
|
+
}
|
|
1763
|
+
function validateField(field, value, required) {
|
|
1764
|
+
const widget = classifyField(field);
|
|
1765
|
+
const label = field?.title || "This field";
|
|
1766
|
+
const isEmpty = value === void 0 || value === null || typeof value === "string" && value.trim() === "";
|
|
1767
|
+
if (isEmpty) {
|
|
1768
|
+
if (required && widget !== "boolean") return `${label} is required.`;
|
|
1769
|
+
return null;
|
|
1770
|
+
}
|
|
1771
|
+
if (widget === "integer" || widget === "decimal") {
|
|
1772
|
+
const num = typeof value === "number" ? value : Number(value);
|
|
1773
|
+
if (Number.isNaN(num)) return `${label} must be a number.`;
|
|
1774
|
+
if (widget === "integer" && !Number.isInteger(num)) {
|
|
1775
|
+
return `${label} must be a whole number.`;
|
|
1776
|
+
}
|
|
1777
|
+
if (typeof field?.minimum === "number" && num < field.minimum) {
|
|
1778
|
+
return `${label} must be at least ${field.minimum}.`;
|
|
1779
|
+
}
|
|
1780
|
+
if (typeof field?.maximum === "number" && num > field.maximum) {
|
|
1781
|
+
return `${label} must be at most ${field.maximum}.`;
|
|
1782
|
+
}
|
|
1783
|
+
return null;
|
|
1784
|
+
}
|
|
1785
|
+
if (widget === "select") {
|
|
1786
|
+
const allowed = getOptions(field).map((o) => o.const);
|
|
1787
|
+
if (allowed.length > 0 && !allowed.includes(String(value))) {
|
|
1788
|
+
return `${label} has an invalid selection.`;
|
|
1789
|
+
}
|
|
1790
|
+
return null;
|
|
1791
|
+
}
|
|
1792
|
+
const str = String(value);
|
|
1793
|
+
if (typeof field?.minLength === "number" && str.length < field.minLength) {
|
|
1794
|
+
return `${label} must be at least ${field.minLength} characters.`;
|
|
1795
|
+
}
|
|
1796
|
+
if (typeof field?.maxLength === "number" && str.length > field.maxLength) {
|
|
1797
|
+
return `${label} must be at most ${field.maxLength} characters.`;
|
|
1798
|
+
}
|
|
1799
|
+
return null;
|
|
1800
|
+
}
|
|
1801
|
+
function renderableFields(schema) {
|
|
1802
|
+
const props = schema?.properties;
|
|
1803
|
+
if (!props) return [];
|
|
1804
|
+
return Object.entries(props).filter(([, field]) => !isNestedOrUnsupported(field));
|
|
1805
|
+
}
|
|
1806
|
+
function validateForm(schema, values) {
|
|
1807
|
+
const errors = {};
|
|
1808
|
+
for (const [key, field] of renderableFields(schema)) {
|
|
1809
|
+
const coerced = coerceValue(field, values[key]);
|
|
1810
|
+
const err = validateField(field, coerced, isRequired(schema, key));
|
|
1811
|
+
if (err) errors[key] = err;
|
|
1812
|
+
}
|
|
1813
|
+
return errors;
|
|
1814
|
+
}
|
|
1815
|
+
function buildContent(schema, values) {
|
|
1816
|
+
const content = {};
|
|
1817
|
+
for (const [key, field] of renderableFields(schema)) {
|
|
1818
|
+
const coerced = coerceValue(field, values[key]);
|
|
1819
|
+
if (coerced !== void 0) content[key] = coerced;
|
|
1820
|
+
}
|
|
1821
|
+
return content;
|
|
1822
|
+
}
|
|
1690
1823
|
var PaymanChatContext = react.createContext(void 0);
|
|
1691
1824
|
function usePaymanChat() {
|
|
1692
1825
|
const context = react.useContext(PaymanChatContext);
|
|
@@ -1767,7 +1900,8 @@ function InputBar({
|
|
|
1767
1900
|
onFocus,
|
|
1768
1901
|
insetBottom
|
|
1769
1902
|
}) {
|
|
1770
|
-
const canSend = !disabled && value.trim().length > 0;
|
|
1903
|
+
const canSend = !disabled && !isStreaming && value.trim().length > 0;
|
|
1904
|
+
const voiceDisabled = !voiceAvailable || disabled || isStreaming;
|
|
1771
1905
|
const showVoiceBar = enableVoice && isRecording;
|
|
1772
1906
|
const showVoiceBtn = enableVoice && !isRecording;
|
|
1773
1907
|
const [keyboardOpen, setKeyboardOpen] = react.useState(false);
|
|
@@ -1875,12 +2009,8 @@ function InputBar({
|
|
|
1875
2009
|
reactNative.Pressable,
|
|
1876
2010
|
{
|
|
1877
2011
|
onPress: onVoicePress,
|
|
1878
|
-
disabled:
|
|
1879
|
-
style:
|
|
1880
|
-
s.iconBtn,
|
|
1881
|
-
(!voiceAvailable || disabled) && s.btnDisabled,
|
|
1882
|
-
pressed && s.pressed
|
|
1883
|
-
],
|
|
2012
|
+
disabled: voiceDisabled,
|
|
2013
|
+
style: [s.iconBtn, voiceDisabled && s.btnDisabled],
|
|
1884
2014
|
accessibilityLabel: "Voice input",
|
|
1885
2015
|
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: s.iconBtnInner, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.Mic, { size: 16, color: "#6B7280", strokeWidth: 2 }) })
|
|
1886
2016
|
}
|
|
@@ -1888,13 +2018,9 @@ function InputBar({
|
|
|
1888
2018
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1889
2019
|
reactNative.Pressable,
|
|
1890
2020
|
{
|
|
1891
|
-
onPress:
|
|
1892
|
-
disabled: !
|
|
1893
|
-
style:
|
|
1894
|
-
s.sendBtn,
|
|
1895
|
-
!isStreaming && !canSend && s.btnDisabled,
|
|
1896
|
-
pressed && s.pressed
|
|
1897
|
-
],
|
|
2021
|
+
onPress: onSend,
|
|
2022
|
+
disabled: !canSend,
|
|
2023
|
+
style: [s.sendBtn, !canSend && s.btnDisabled],
|
|
1898
2024
|
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [s.sendBtnInner, { backgroundColor: accent }], children: /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.Send, { size: 14, color: "#FFFFFF" }) })
|
|
1899
2025
|
}
|
|
1900
2026
|
)
|
|
@@ -2161,11 +2287,27 @@ function stripIncompleteImageToken(text) {
|
|
|
2161
2287
|
if (/^!\[[^\]]*\]\([^)]*\)/.test(after)) return text;
|
|
2162
2288
|
return text.slice(0, lastBang);
|
|
2163
2289
|
}
|
|
2290
|
+
function stripDuplicatePromptText(text, promptText) {
|
|
2291
|
+
if (!promptText) return text;
|
|
2292
|
+
const pm = promptText.replace(/\\n/g, "\n").trim();
|
|
2293
|
+
if (!pm) return text;
|
|
2294
|
+
const idx = text.indexOf(pm);
|
|
2295
|
+
if (idx !== -1) {
|
|
2296
|
+
return (text.slice(0, idx) + text.slice(idx + pm.length)).trim();
|
|
2297
|
+
}
|
|
2298
|
+
for (let cut = Math.min(text.length, pm.length); cut >= 24; cut--) {
|
|
2299
|
+
if (text.endsWith(pm.slice(0, cut))) {
|
|
2300
|
+
return text.slice(0, text.length - cut).trim();
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
return text;
|
|
2304
|
+
}
|
|
2164
2305
|
function AssistantBubble({
|
|
2165
2306
|
message,
|
|
2166
2307
|
shouldType,
|
|
2167
2308
|
isDark,
|
|
2168
|
-
accent
|
|
2309
|
+
accent,
|
|
2310
|
+
suppressText
|
|
2169
2311
|
}) {
|
|
2170
2312
|
const isCurrentlyStreaming = !!message.isStreaming && !message.isCancelled;
|
|
2171
2313
|
const mdStyles = isDark ? MD_STYLES_DARK : MD_STYLES_LIGHT;
|
|
@@ -2176,7 +2318,8 @@ function AssistantBubble({
|
|
|
2176
2318
|
const raw = message.isStreaming ? message.streamingContent || message.content : message.content;
|
|
2177
2319
|
if (!raw) return "";
|
|
2178
2320
|
const normalized = raw.replace(/\\n/g, "\n");
|
|
2179
|
-
|
|
2321
|
+
const cleaned = message.isStreaming ? stripIncompleteImageToken(normalized) : normalized;
|
|
2322
|
+
return stripDuplicatePromptText(cleaned, suppressText);
|
|
2180
2323
|
})();
|
|
2181
2324
|
const isThinkingStreaming = isCurrentlyStreaming && !rawResponseContent && !message.isError;
|
|
2182
2325
|
const hasEverStreamed = react.useRef(!!message.isStreaming);
|
|
@@ -2206,10 +2349,740 @@ function AssistantBubble({
|
|
|
2206
2349
|
message.isError && displayedText && /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: sd.partialErrorText, children: message.errorDetails || "The response was interrupted." })
|
|
2207
2350
|
] }) });
|
|
2208
2351
|
}
|
|
2209
|
-
function MessageBubble({ message, accent, shouldType, isDark }) {
|
|
2352
|
+
function MessageBubble({ message, accent, shouldType, isDark, suppressText }) {
|
|
2210
2353
|
if (message.role === "user") return /* @__PURE__ */ jsxRuntime.jsx(UserBubble, { message, accent });
|
|
2211
|
-
return /* @__PURE__ */ jsxRuntime.jsx(AssistantBubble, { message, shouldType, isDark, accent });
|
|
2354
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AssistantBubble, { message, shouldType, isDark, accent, suppressText });
|
|
2355
|
+
}
|
|
2356
|
+
var RESEND_COOLDOWN_S = 30;
|
|
2357
|
+
var DEFAULT_CODE_LEN = 6;
|
|
2358
|
+
function uaPalette(isDark) {
|
|
2359
|
+
return isDark ? {
|
|
2360
|
+
sheetBg: "#13201f",
|
|
2361
|
+
text: "rgba(255,255,255,0.95)",
|
|
2362
|
+
muted: "rgba(255,255,255,0.55)",
|
|
2363
|
+
border: "rgba(255,255,255,0.10)",
|
|
2364
|
+
fieldBg: "rgba(255,255,255,0.06)",
|
|
2365
|
+
fieldBorder: "rgba(255,255,255,0.18)",
|
|
2366
|
+
overlay: "rgba(0,0,0,0.62)",
|
|
2367
|
+
grabber: "rgba(255,255,255,0.22)"
|
|
2368
|
+
} : {
|
|
2369
|
+
sheetBg: "#ffffff",
|
|
2370
|
+
text: "#111827",
|
|
2371
|
+
muted: "#6b7280",
|
|
2372
|
+
border: "#eceef1",
|
|
2373
|
+
fieldBg: "#f9fafb",
|
|
2374
|
+
fieldBorder: "#d1d5db",
|
|
2375
|
+
overlay: "rgba(15,23,42,0.45)",
|
|
2376
|
+
grabber: "rgba(15,23,42,0.18)"
|
|
2377
|
+
};
|
|
2378
|
+
}
|
|
2379
|
+
function promptInitialSeconds(prompt) {
|
|
2380
|
+
return prompt && typeof prompt.expirySeconds === "number" && prompt.expirySeconds > 0 ? Math.floor(prompt.expirySeconds) : void 0;
|
|
2381
|
+
}
|
|
2382
|
+
function promptTimerKey(prompt) {
|
|
2383
|
+
return prompt ? `${prompt.userActionId}|${prompt.subAction ?? ""}` : "";
|
|
2384
|
+
}
|
|
2385
|
+
function useExpiredFlag(prompt) {
|
|
2386
|
+
const initial = promptInitialSeconds(prompt);
|
|
2387
|
+
const key = promptTimerKey(prompt);
|
|
2388
|
+
const [expired, setExpired] = react.useState(false);
|
|
2389
|
+
react.useEffect(() => {
|
|
2390
|
+
setExpired(false);
|
|
2391
|
+
if (initial === void 0) return;
|
|
2392
|
+
const t = setTimeout(() => setExpired(true), initial * 1e3);
|
|
2393
|
+
return () => clearTimeout(t);
|
|
2394
|
+
}, [key, initial]);
|
|
2395
|
+
return expired;
|
|
2396
|
+
}
|
|
2397
|
+
function useSecondsLeft(expirySeconds, restartKey) {
|
|
2398
|
+
const initial = typeof expirySeconds === "number" && expirySeconds > 0 ? Math.floor(expirySeconds) : void 0;
|
|
2399
|
+
const [left, setLeft] = react.useState(initial);
|
|
2400
|
+
react.useEffect(() => {
|
|
2401
|
+
setLeft(initial);
|
|
2402
|
+
if (initial === void 0) return;
|
|
2403
|
+
const id = setInterval(() => {
|
|
2404
|
+
setLeft((s2) => s2 === void 0 ? s2 : s2 <= 1 ? 0 : s2 - 1);
|
|
2405
|
+
}, 1e3);
|
|
2406
|
+
return () => clearInterval(id);
|
|
2407
|
+
}, [restartKey, initial]);
|
|
2408
|
+
return left;
|
|
2409
|
+
}
|
|
2410
|
+
function SheetTimerPill({
|
|
2411
|
+
prompt,
|
|
2412
|
+
accent,
|
|
2413
|
+
isDark
|
|
2414
|
+
}) {
|
|
2415
|
+
const left = useSecondsLeft(prompt.expirySeconds, promptTimerKey(prompt));
|
|
2416
|
+
if (left === void 0 || prompt.status === "stale") return null;
|
|
2417
|
+
const expired = left <= 0;
|
|
2418
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2419
|
+
reactNative.View,
|
|
2420
|
+
{
|
|
2421
|
+
style: [
|
|
2422
|
+
sht.timer,
|
|
2423
|
+
{
|
|
2424
|
+
borderColor: expired ? "#ef4444" : accent + "40",
|
|
2425
|
+
backgroundColor: expired ? "rgba(239,68,68,0.10)" : accent + (isDark ? "1F" : "12")
|
|
2426
|
+
}
|
|
2427
|
+
],
|
|
2428
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: { color: expired ? "#ef4444" : accent, fontSize: 12.5, fontWeight: "700", letterSpacing: 0.2 }, children: expired ? "Expired" : `${left}s` })
|
|
2429
|
+
}
|
|
2430
|
+
);
|
|
2212
2431
|
}
|
|
2432
|
+
function CardTimerPill({
|
|
2433
|
+
prompt,
|
|
2434
|
+
accent,
|
|
2435
|
+
isDark
|
|
2436
|
+
}) {
|
|
2437
|
+
const left = useSecondsLeft(prompt.expirySeconds, promptTimerKey(prompt));
|
|
2438
|
+
if (left === void 0 || left <= 0) return null;
|
|
2439
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [rc.timer, { backgroundColor: accent + (isDark ? "26" : "14") }], children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: { color: accent, fontSize: 12, fontWeight: "700" }, children: [
|
|
2440
|
+
left,
|
|
2441
|
+
"s"
|
|
2442
|
+
] }) });
|
|
2443
|
+
}
|
|
2444
|
+
function CodeInput({
|
|
2445
|
+
value,
|
|
2446
|
+
onChange,
|
|
2447
|
+
length,
|
|
2448
|
+
disabled,
|
|
2449
|
+
error,
|
|
2450
|
+
accent,
|
|
2451
|
+
pal
|
|
2452
|
+
}) {
|
|
2453
|
+
const ref = react.useRef(null);
|
|
2454
|
+
react.useEffect(() => {
|
|
2455
|
+
const t = setTimeout(() => ref.current?.focus(), 380);
|
|
2456
|
+
return () => clearTimeout(t);
|
|
2457
|
+
}, []);
|
|
2458
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Pressable, { onPress: () => ref.current?.focus(), style: ub.codeRow, children: [
|
|
2459
|
+
Array.from({ length }).map((_, i) => {
|
|
2460
|
+
const ch = value[i] ?? "";
|
|
2461
|
+
const isCursor = i === value.length && !disabled;
|
|
2462
|
+
const bc = error ? "#ef4444" : isCursor ? accent : pal.fieldBorder;
|
|
2463
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [ub.codeBox, { borderColor: bc, backgroundColor: pal.fieldBg }], children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [ub.codeChar, { color: pal.text }], children: ch }) }, i);
|
|
2464
|
+
}),
|
|
2465
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2466
|
+
reactNative.TextInput,
|
|
2467
|
+
{
|
|
2468
|
+
ref,
|
|
2469
|
+
value,
|
|
2470
|
+
onChangeText: (t) => onChange(t.replace(/[^0-9]/g, "").slice(0, length)),
|
|
2471
|
+
keyboardType: "number-pad",
|
|
2472
|
+
maxLength: length,
|
|
2473
|
+
editable: !disabled,
|
|
2474
|
+
caretHidden: true,
|
|
2475
|
+
style: ub.codeHidden
|
|
2476
|
+
}
|
|
2477
|
+
)
|
|
2478
|
+
] });
|
|
2479
|
+
}
|
|
2480
|
+
function PrimaryButton({
|
|
2481
|
+
label,
|
|
2482
|
+
onPress,
|
|
2483
|
+
disabled,
|
|
2484
|
+
accent
|
|
2485
|
+
}) {
|
|
2486
|
+
const bg = accent || DEFAULT_ACCENT;
|
|
2487
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2488
|
+
reactNative.Pressable,
|
|
2489
|
+
{
|
|
2490
|
+
onPress,
|
|
2491
|
+
disabled,
|
|
2492
|
+
android_ripple: { color: "rgba(255,255,255,0.22)" },
|
|
2493
|
+
style: [ub.primaryBtn, { backgroundColor: bg, borderColor: bg, opacity: disabled ? 0.5 : 1 }],
|
|
2494
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: ub.primaryBtnText, children: label })
|
|
2495
|
+
}
|
|
2496
|
+
);
|
|
2497
|
+
}
|
|
2498
|
+
function VerificationBody({
|
|
2499
|
+
prompt,
|
|
2500
|
+
expired,
|
|
2501
|
+
pal,
|
|
2502
|
+
accent,
|
|
2503
|
+
onSubmit,
|
|
2504
|
+
onCancel,
|
|
2505
|
+
onResend
|
|
2506
|
+
}) {
|
|
2507
|
+
const isNumeric = prompt.verificationType !== "ALPHANUMERIC_CODE";
|
|
2508
|
+
const field = prompt.requestedSchema?.properties?.verificationCode;
|
|
2509
|
+
const codeLen = (typeof field?.maxLength === "number" ? field.maxLength : void 0) ?? (typeof field?.minLength === "number" ? field.minLength : void 0) ?? DEFAULT_CODE_LEN;
|
|
2510
|
+
const [code, setCode] = react.useState("");
|
|
2511
|
+
const [errored, setErrored] = react.useState(false);
|
|
2512
|
+
const [resendSec, setResendSec] = react.useState(0);
|
|
2513
|
+
const lastSubmitted = react.useRef(null);
|
|
2514
|
+
const resendTimer = react.useRef(null);
|
|
2515
|
+
const busy = prompt.status === "submitting";
|
|
2516
|
+
const stale = prompt.status === "stale";
|
|
2517
|
+
const locked = busy || stale || expired;
|
|
2518
|
+
react.useEffect(() => {
|
|
2519
|
+
if (prompt.subAction === "SubmissionInvalid") {
|
|
2520
|
+
setErrored(true);
|
|
2521
|
+
setCode("");
|
|
2522
|
+
lastSubmitted.current = null;
|
|
2523
|
+
}
|
|
2524
|
+
}, [prompt.subAction, prompt.userActionId]);
|
|
2525
|
+
const doSubmit = react.useCallback(
|
|
2526
|
+
(value) => {
|
|
2527
|
+
if (locked || !value) return;
|
|
2528
|
+
if (lastSubmitted.current === value) return;
|
|
2529
|
+
lastSubmitted.current = value;
|
|
2530
|
+
void onSubmit(prompt.userActionId, { verificationCode: value }).catch(() => {
|
|
2531
|
+
lastSubmitted.current = null;
|
|
2532
|
+
setErrored(true);
|
|
2533
|
+
});
|
|
2534
|
+
},
|
|
2535
|
+
[locked, onSubmit, prompt.userActionId]
|
|
2536
|
+
);
|
|
2537
|
+
react.useEffect(() => {
|
|
2538
|
+
if (!isNumeric || locked) return;
|
|
2539
|
+
if (code.length === codeLen && /^\d+$/.test(code)) doSubmit(code);
|
|
2540
|
+
}, [code, codeLen, doSubmit, isNumeric, locked]);
|
|
2541
|
+
react.useEffect(() => () => {
|
|
2542
|
+
if (resendTimer.current) clearInterval(resendTimer.current);
|
|
2543
|
+
}, []);
|
|
2544
|
+
const handleResend = react.useCallback(async () => {
|
|
2545
|
+
if (locked || resendSec > 0) return;
|
|
2546
|
+
setErrored(false);
|
|
2547
|
+
setCode("");
|
|
2548
|
+
lastSubmitted.current = null;
|
|
2549
|
+
try {
|
|
2550
|
+
await onResend(prompt.userActionId);
|
|
2551
|
+
setResendSec(RESEND_COOLDOWN_S);
|
|
2552
|
+
if (resendTimer.current) clearInterval(resendTimer.current);
|
|
2553
|
+
resendTimer.current = setInterval(() => {
|
|
2554
|
+
setResendSec((s2) => {
|
|
2555
|
+
if (s2 <= 1) {
|
|
2556
|
+
if (resendTimer.current) clearInterval(resendTimer.current);
|
|
2557
|
+
return 0;
|
|
2558
|
+
}
|
|
2559
|
+
return s2 - 1;
|
|
2560
|
+
});
|
|
2561
|
+
}, 1e3);
|
|
2562
|
+
} catch {
|
|
2563
|
+
}
|
|
2564
|
+
}, [locked, onResend, prompt.userActionId, resendSec]);
|
|
2565
|
+
const description = prompt.message?.trim() || (isNumeric ? `Enter the ${codeLen}-digit code to continue` : "Enter the verification code to continue");
|
|
2566
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: ub.bodyWrap, children: [
|
|
2567
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2568
|
+
reactNative.ScrollView,
|
|
2569
|
+
{
|
|
2570
|
+
style: ub.fieldsScroll,
|
|
2571
|
+
contentContainerStyle: ub.fieldsContent,
|
|
2572
|
+
keyboardShouldPersistTaps: "handled",
|
|
2573
|
+
showsVerticalScrollIndicator: false,
|
|
2574
|
+
children: [
|
|
2575
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [ub.desc, { color: pal.muted }], children: description }),
|
|
2576
|
+
isNumeric ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2577
|
+
CodeInput,
|
|
2578
|
+
{
|
|
2579
|
+
value: code,
|
|
2580
|
+
onChange: (v) => {
|
|
2581
|
+
setErrored(false);
|
|
2582
|
+
setCode(v);
|
|
2583
|
+
},
|
|
2584
|
+
length: codeLen,
|
|
2585
|
+
disabled: locked,
|
|
2586
|
+
error: errored,
|
|
2587
|
+
accent,
|
|
2588
|
+
pal
|
|
2589
|
+
}
|
|
2590
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2591
|
+
reactNative.TextInput,
|
|
2592
|
+
{
|
|
2593
|
+
value: code,
|
|
2594
|
+
onChangeText: (t) => {
|
|
2595
|
+
setErrored(false);
|
|
2596
|
+
setCode(t);
|
|
2597
|
+
},
|
|
2598
|
+
editable: !locked,
|
|
2599
|
+
placeholder: "Verification code",
|
|
2600
|
+
placeholderTextColor: pal.muted,
|
|
2601
|
+
autoComplete: "one-time-code",
|
|
2602
|
+
style: [
|
|
2603
|
+
ub.input,
|
|
2604
|
+
{ color: pal.text, backgroundColor: pal.fieldBg, borderColor: errored ? "#ef4444" : pal.fieldBorder }
|
|
2605
|
+
]
|
|
2606
|
+
}
|
|
2607
|
+
)
|
|
2608
|
+
]
|
|
2609
|
+
}
|
|
2610
|
+
),
|
|
2611
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: ub.actions, children: [
|
|
2612
|
+
!isNumeric && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2613
|
+
PrimaryButton,
|
|
2614
|
+
{
|
|
2615
|
+
label: busy ? "Verifying\u2026" : "Verify",
|
|
2616
|
+
onPress: () => doSubmit(code.trim()),
|
|
2617
|
+
disabled: locked || !code.trim(),
|
|
2618
|
+
accent
|
|
2619
|
+
}
|
|
2620
|
+
),
|
|
2621
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: ub.linkRow, children: [
|
|
2622
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { disabled: locked || resendSec > 0, onPress: () => void handleResend(), children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [ub.link, { color: accent, opacity: locked || resendSec > 0 ? 0.4 : 1 }], children: resendSec > 0 ? `Resend (${resendSec}s)` : "Resend" }) }),
|
|
2623
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { disabled: busy, onPress: () => void onCancel(prompt.userActionId), children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [ub.link, ub.linkDanger, { opacity: busy ? 0.4 : 1 }], children: "Cancel" }) })
|
|
2624
|
+
] })
|
|
2625
|
+
] })
|
|
2626
|
+
] });
|
|
2627
|
+
}
|
|
2628
|
+
function FormBody({
|
|
2629
|
+
prompt,
|
|
2630
|
+
pal,
|
|
2631
|
+
accent,
|
|
2632
|
+
isDark,
|
|
2633
|
+
onSubmit,
|
|
2634
|
+
onCancel
|
|
2635
|
+
}) {
|
|
2636
|
+
const schema = prompt.requestedSchema;
|
|
2637
|
+
const fields = react.useMemo(() => renderableFields(schema), [schema]);
|
|
2638
|
+
const [values, setValues] = react.useState(() => {
|
|
2639
|
+
const init = {};
|
|
2640
|
+
for (const [key, field] of fields) init[key] = defaultValueFor(field);
|
|
2641
|
+
return init;
|
|
2642
|
+
});
|
|
2643
|
+
const [errors, setErrors] = react.useState({});
|
|
2644
|
+
const busy = prompt.status === "submitting";
|
|
2645
|
+
const stale = prompt.status === "stale";
|
|
2646
|
+
const locked = busy || stale;
|
|
2647
|
+
const isConfirm = prompt.subAction === "UserConfirmation";
|
|
2648
|
+
const setValue = (key, v) => {
|
|
2649
|
+
setValues((prev) => ({ ...prev, [key]: v }));
|
|
2650
|
+
setErrors((prev) => {
|
|
2651
|
+
if (!prev[key]) return prev;
|
|
2652
|
+
const next = { ...prev };
|
|
2653
|
+
delete next[key];
|
|
2654
|
+
return next;
|
|
2655
|
+
});
|
|
2656
|
+
};
|
|
2657
|
+
const handleSubmit = () => {
|
|
2658
|
+
if (locked) return;
|
|
2659
|
+
const validation = validateForm(schema, values);
|
|
2660
|
+
if (Object.keys(validation).length > 0) {
|
|
2661
|
+
setErrors(validation);
|
|
2662
|
+
return;
|
|
2663
|
+
}
|
|
2664
|
+
void onSubmit(prompt.userActionId, buildContent(schema, values)).catch(() => {
|
|
2665
|
+
});
|
|
2666
|
+
};
|
|
2667
|
+
const mdStyles = isDark ? MD_STYLES_DARK : MD_STYLES_LIGHT;
|
|
2668
|
+
const mdRules = react.useMemo(() => makeMdRules(isDark, accent), [isDark, accent]);
|
|
2669
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: ub.bodyWrap, children: [
|
|
2670
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2671
|
+
reactNative.ScrollView,
|
|
2672
|
+
{
|
|
2673
|
+
style: ub.fieldsScroll,
|
|
2674
|
+
contentContainerStyle: ub.fieldsContent,
|
|
2675
|
+
keyboardShouldPersistTaps: "handled",
|
|
2676
|
+
showsVerticalScrollIndicator: true,
|
|
2677
|
+
children: [
|
|
2678
|
+
prompt.message?.trim() ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: ub.messageBlock, children: /* @__PURE__ */ jsxRuntime.jsx(Markdown__default.default, { style: mdStyles, rules: mdRules, children: prompt.message.replace(/\\n/g, "\n") }) }) : null,
|
|
2679
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: ub.form, children: fields.map(([key, field]) => {
|
|
2680
|
+
const widget = classifyField(field);
|
|
2681
|
+
const label = field.title || key;
|
|
2682
|
+
const required = isRequired(schema, key);
|
|
2683
|
+
const err = errors[key];
|
|
2684
|
+
if (widget === "boolean") {
|
|
2685
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: ub.switchRow, children: [
|
|
2686
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [ub.label, { color: pal.text, flex: 1 }], children: [
|
|
2687
|
+
label,
|
|
2688
|
+
required ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: { color: "#ef4444" }, children: " *" }) : null
|
|
2689
|
+
] }),
|
|
2690
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2691
|
+
reactNative.Switch,
|
|
2692
|
+
{
|
|
2693
|
+
value: Boolean(values[key]),
|
|
2694
|
+
disabled: locked,
|
|
2695
|
+
onValueChange: (v) => setValue(key, v),
|
|
2696
|
+
trackColor: { true: accent }
|
|
2697
|
+
}
|
|
2698
|
+
)
|
|
2699
|
+
] }, key);
|
|
2700
|
+
}
|
|
2701
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: ub.field, children: [
|
|
2702
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [ub.label, { color: pal.text }], children: [
|
|
2703
|
+
label,
|
|
2704
|
+
required ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: { color: "#ef4444" }, children: " *" }) : null
|
|
2705
|
+
] }),
|
|
2706
|
+
field.description ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [ub.hint, { color: pal.muted }], children: field.description }) : null,
|
|
2707
|
+
widget === "select" ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: ub.optionList, children: getOptions(field).map((opt) => {
|
|
2708
|
+
const selected = String(values[key] ?? "") === opt.const;
|
|
2709
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2710
|
+
reactNative.Pressable,
|
|
2711
|
+
{
|
|
2712
|
+
disabled: locked,
|
|
2713
|
+
onPress: () => setValue(key, opt.const),
|
|
2714
|
+
android_ripple: { color: accent + "22" },
|
|
2715
|
+
style: [
|
|
2716
|
+
ub.optionRow,
|
|
2717
|
+
{
|
|
2718
|
+
borderColor: selected ? accent : pal.fieldBorder,
|
|
2719
|
+
backgroundColor: selected ? accent + (isDark ? "26" : "14") : pal.fieldBg
|
|
2720
|
+
}
|
|
2721
|
+
],
|
|
2722
|
+
children: [
|
|
2723
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2724
|
+
reactNative.View,
|
|
2725
|
+
{
|
|
2726
|
+
style: [
|
|
2727
|
+
ub.radio,
|
|
2728
|
+
{ borderColor: selected ? accent : pal.fieldBorder }
|
|
2729
|
+
],
|
|
2730
|
+
children: selected ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [ub.radioDot, { backgroundColor: accent }] }) : null
|
|
2731
|
+
}
|
|
2732
|
+
),
|
|
2733
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2734
|
+
reactNative.Text,
|
|
2735
|
+
{
|
|
2736
|
+
style: [
|
|
2737
|
+
ub.optionLabel,
|
|
2738
|
+
{ color: pal.text, fontWeight: selected ? "600" : "500" }
|
|
2739
|
+
],
|
|
2740
|
+
children: opt.title || opt.const
|
|
2741
|
+
}
|
|
2742
|
+
)
|
|
2743
|
+
]
|
|
2744
|
+
},
|
|
2745
|
+
opt.const
|
|
2746
|
+
);
|
|
2747
|
+
}) }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
2748
|
+
reactNative.TextInput,
|
|
2749
|
+
{
|
|
2750
|
+
value: String(values[key] ?? ""),
|
|
2751
|
+
editable: !locked,
|
|
2752
|
+
onChangeText: (t) => setValue(key, t),
|
|
2753
|
+
placeholder: field.description ? void 0 : label,
|
|
2754
|
+
placeholderTextColor: pal.muted,
|
|
2755
|
+
keyboardType: widget === "integer" ? "number-pad" : widget === "decimal" ? "decimal-pad" : "default",
|
|
2756
|
+
style: [
|
|
2757
|
+
ub.input,
|
|
2758
|
+
{ color: pal.text, backgroundColor: pal.fieldBg, borderColor: err ? "#ef4444" : pal.fieldBorder }
|
|
2759
|
+
]
|
|
2760
|
+
}
|
|
2761
|
+
),
|
|
2762
|
+
err ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: ub.error, children: err }) : null
|
|
2763
|
+
] }, key);
|
|
2764
|
+
}) })
|
|
2765
|
+
]
|
|
2766
|
+
}
|
|
2767
|
+
),
|
|
2768
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: ub.actions, children: [
|
|
2769
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2770
|
+
PrimaryButton,
|
|
2771
|
+
{
|
|
2772
|
+
label: busy ? "Submitting\u2026" : isConfirm ? "Confirm" : "Next",
|
|
2773
|
+
onPress: handleSubmit,
|
|
2774
|
+
disabled: locked,
|
|
2775
|
+
accent
|
|
2776
|
+
}
|
|
2777
|
+
),
|
|
2778
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: ub.linkRow, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { disabled: busy, onPress: () => void onCancel(prompt.userActionId), children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [ub.link, ub.linkDanger, { opacity: busy ? 0.4 : 1 }], children: "Cancel" }) }) })
|
|
2779
|
+
] })
|
|
2780
|
+
] });
|
|
2781
|
+
}
|
|
2782
|
+
function UserActionSheet({
|
|
2783
|
+
open,
|
|
2784
|
+
active,
|
|
2785
|
+
expired,
|
|
2786
|
+
isDark,
|
|
2787
|
+
accent,
|
|
2788
|
+
insetBottom,
|
|
2789
|
+
onSubmit,
|
|
2790
|
+
onCancel,
|
|
2791
|
+
onResend,
|
|
2792
|
+
onMinimize
|
|
2793
|
+
}) {
|
|
2794
|
+
const pal = uaPalette(isDark);
|
|
2795
|
+
const screenH = reactNative.Dimensions.get("window").height;
|
|
2796
|
+
const [shown, setShown] = react.useState(active);
|
|
2797
|
+
react.useEffect(() => {
|
|
2798
|
+
if (active) setShown(active);
|
|
2799
|
+
}, [active]);
|
|
2800
|
+
const translateY = react.useRef(new reactNative.Animated.Value(screenH)).current;
|
|
2801
|
+
const backdrop = react.useRef(new reactNative.Animated.Value(0)).current;
|
|
2802
|
+
const minimizeRef = react.useRef(onMinimize);
|
|
2803
|
+
react.useEffect(() => {
|
|
2804
|
+
minimizeRef.current = onMinimize;
|
|
2805
|
+
});
|
|
2806
|
+
const [kbHeight, setKbHeight] = react.useState(0);
|
|
2807
|
+
react.useEffect(() => {
|
|
2808
|
+
const showEvt = reactNative.Platform.OS === "ios" ? "keyboardWillShow" : "keyboardDidShow";
|
|
2809
|
+
const hideEvt = reactNative.Platform.OS === "ios" ? "keyboardWillHide" : "keyboardDidHide";
|
|
2810
|
+
const s1 = reactNative.Keyboard.addListener(showEvt, (e) => setKbHeight(e?.endCoordinates?.height ?? 0));
|
|
2811
|
+
const s2 = reactNative.Keyboard.addListener(hideEvt, () => setKbHeight(0));
|
|
2812
|
+
return () => {
|
|
2813
|
+
s1.remove();
|
|
2814
|
+
s2.remove();
|
|
2815
|
+
};
|
|
2816
|
+
}, []);
|
|
2817
|
+
react.useEffect(() => {
|
|
2818
|
+
if (open) {
|
|
2819
|
+
reactNative.Animated.parallel([
|
|
2820
|
+
reactNative.Animated.spring(translateY, { toValue: 0, useNativeDriver: true, damping: 30, stiffness: 360, mass: 0.85 }),
|
|
2821
|
+
reactNative.Animated.timing(backdrop, { toValue: 1, duration: 190, useNativeDriver: true })
|
|
2822
|
+
]).start();
|
|
2823
|
+
} else {
|
|
2824
|
+
reactNative.Animated.parallel([
|
|
2825
|
+
reactNative.Animated.timing(translateY, { toValue: screenH, duration: 210, easing: reactNative.Easing.in(reactNative.Easing.cubic), useNativeDriver: true }),
|
|
2826
|
+
reactNative.Animated.timing(backdrop, { toValue: 0, duration: 170, useNativeDriver: true })
|
|
2827
|
+
]).start();
|
|
2828
|
+
}
|
|
2829
|
+
}, [open, translateY, backdrop, screenH]);
|
|
2830
|
+
const pan = react.useRef(
|
|
2831
|
+
reactNative.PanResponder.create({
|
|
2832
|
+
onMoveShouldSetPanResponder: (_evt, g) => g.dy > 6 && Math.abs(g.dy) > Math.abs(g.dx) * 1.4,
|
|
2833
|
+
onPanResponderMove: (_evt, g) => {
|
|
2834
|
+
if (g.dy > 0) translateY.setValue(g.dy);
|
|
2835
|
+
},
|
|
2836
|
+
onPanResponderRelease: (_evt, g) => {
|
|
2837
|
+
if (g.dy > 110 || g.vy > 0.8) {
|
|
2838
|
+
minimizeRef.current();
|
|
2839
|
+
} else {
|
|
2840
|
+
reactNative.Animated.spring(translateY, { toValue: 0, useNativeDriver: true, damping: 30, stiffness: 360 }).start();
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
})
|
|
2844
|
+
).current;
|
|
2845
|
+
const a = active ?? shown;
|
|
2846
|
+
if (!a) return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { pointerEvents: "none" });
|
|
2847
|
+
const isVerification = a.kind === "verification";
|
|
2848
|
+
const title = isVerification ? "Verification required" : "Action required";
|
|
2849
|
+
const subtitle = isVerification ? "Confirm the one-time code to continue" : "Review the details and confirm to continue";
|
|
2850
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [reactNative.StyleSheet.absoluteFill, sht.overlay], pointerEvents: open ? "auto" : "none", children: [
|
|
2851
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2852
|
+
reactNative.Animated.View,
|
|
2853
|
+
{
|
|
2854
|
+
pointerEvents: "none",
|
|
2855
|
+
style: [sht.backdrop, { backgroundColor: pal.overlay, opacity: backdrop }]
|
|
2856
|
+
}
|
|
2857
|
+
),
|
|
2858
|
+
open ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { style: reactNative.StyleSheet.absoluteFill, onPress: () => minimizeRef.current(), accessibilityLabel: "Dismiss" }) : null,
|
|
2859
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [sht.kav, { paddingBottom: kbHeight }], pointerEvents: "box-none", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2860
|
+
reactNative.Animated.View,
|
|
2861
|
+
{
|
|
2862
|
+
style: [
|
|
2863
|
+
sht.sheet,
|
|
2864
|
+
{
|
|
2865
|
+
backgroundColor: pal.sheetBg,
|
|
2866
|
+
borderColor: pal.border,
|
|
2867
|
+
// Cap to the space above the keyboard (and a top margin) so the
|
|
2868
|
+
// header stays visible and the footer sits above the keyboard;
|
|
2869
|
+
// the field area scrolls within whatever's left.
|
|
2870
|
+
maxHeight: Math.min(screenH * 0.9, screenH - kbHeight - 72),
|
|
2871
|
+
paddingBottom: kbHeight > 0 ? 16 : Math.max(insetBottom, 16) + 6,
|
|
2872
|
+
transform: [{ translateY }]
|
|
2873
|
+
}
|
|
2874
|
+
],
|
|
2875
|
+
children: [
|
|
2876
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { ...pan.panHandlers, style: sht.handleZone, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [sht.grabber, { backgroundColor: pal.grabber }] }) }),
|
|
2877
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: sht.header, children: [
|
|
2878
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [sht.iconCircle, { backgroundColor: accent + (isDark ? "26" : "14") }], children: isVerification ? /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.ShieldCheck, { size: 20, color: accent, strokeWidth: 2 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.Pencil, { size: 18, color: accent, strokeWidth: 2 }) }),
|
|
2879
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: sht.headerText, children: [
|
|
2880
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [sht.title, { color: pal.text }], children: title }),
|
|
2881
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [sht.subtitle, { color: pal.muted }], numberOfLines: 1, children: subtitle })
|
|
2882
|
+
] }),
|
|
2883
|
+
/* @__PURE__ */ jsxRuntime.jsx(SheetTimerPill, { prompt: a, accent, isDark }),
|
|
2884
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { onPress: () => minimizeRef.current(), hitSlop: 10, style: [sht.closeBtn, { backgroundColor: pal.fieldBg }], children: /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.X, { size: 16, color: pal.muted, strokeWidth: 2.2 }) })
|
|
2885
|
+
] }),
|
|
2886
|
+
a.status === "stale" ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: sht.simpleBody, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [ub.desc, { color: pal.muted }], children: "This request is no longer available." }) }) : expired ? /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: sht.simpleBody, children: [
|
|
2887
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [ub.desc, { color: pal.muted }], children: isVerification ? "This verification request expired." : "This request expired." }),
|
|
2888
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: ub.actions, children: /* @__PURE__ */ jsxRuntime.jsx(PrimaryButton, { label: "Close", onPress: () => void onCancel(a.userActionId), accent }) })
|
|
2889
|
+
] }) : isVerification ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2890
|
+
VerificationBody,
|
|
2891
|
+
{
|
|
2892
|
+
prompt: a,
|
|
2893
|
+
expired,
|
|
2894
|
+
pal,
|
|
2895
|
+
accent,
|
|
2896
|
+
onSubmit,
|
|
2897
|
+
onCancel,
|
|
2898
|
+
onResend
|
|
2899
|
+
},
|
|
2900
|
+
a.userActionId
|
|
2901
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(FormBody, { prompt: a, pal, accent, isDark, onSubmit, onCancel }, a.userActionId)
|
|
2902
|
+
]
|
|
2903
|
+
}
|
|
2904
|
+
) })
|
|
2905
|
+
] });
|
|
2906
|
+
}
|
|
2907
|
+
function UserActionReopenCard({
|
|
2908
|
+
active,
|
|
2909
|
+
expired,
|
|
2910
|
+
isDark,
|
|
2911
|
+
accent,
|
|
2912
|
+
onReopen
|
|
2913
|
+
}) {
|
|
2914
|
+
if (expired || active.status === "stale") return null;
|
|
2915
|
+
const pal = uaPalette(isDark);
|
|
2916
|
+
const isVerification = active.kind === "verification";
|
|
2917
|
+
const title = isVerification ? "Verification required" : "Action required";
|
|
2918
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2919
|
+
reactNative.Pressable,
|
|
2920
|
+
{
|
|
2921
|
+
onPress: onReopen,
|
|
2922
|
+
accessibilityRole: "button",
|
|
2923
|
+
accessibilityLabel: `${title}. Tap to respond.`,
|
|
2924
|
+
android_ripple: { color: accent + "22" },
|
|
2925
|
+
style: [
|
|
2926
|
+
rc.card,
|
|
2927
|
+
{
|
|
2928
|
+
backgroundColor: pal.sheetBg,
|
|
2929
|
+
borderColor: accent + (isDark ? "59" : "40")
|
|
2930
|
+
}
|
|
2931
|
+
],
|
|
2932
|
+
children: [
|
|
2933
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [rc.iconCircle, { backgroundColor: accent + (isDark ? "26" : "14") }], children: isVerification ? /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.ShieldCheck, { size: 18, color: accent, strokeWidth: 2 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.Pencil, { size: 16, color: accent, strokeWidth: 2 }) }),
|
|
2934
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: rc.textWrap, children: [
|
|
2935
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [rc.title, { color: pal.text }], numberOfLines: 1, children: title }),
|
|
2936
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [rc.subtitle, { color: pal.muted }], numberOfLines: 1, children: "Tap to respond and continue" })
|
|
2937
|
+
] }),
|
|
2938
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardTimerPill, { prompt: active, accent, isDark }),
|
|
2939
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.ChevronRight, { size: 18, color: pal.muted, strokeWidth: 2 })
|
|
2940
|
+
]
|
|
2941
|
+
}
|
|
2942
|
+
);
|
|
2943
|
+
}
|
|
2944
|
+
function NotificationStack({
|
|
2945
|
+
notifications,
|
|
2946
|
+
isDark,
|
|
2947
|
+
onDismiss
|
|
2948
|
+
}) {
|
|
2949
|
+
if (notifications.length === 0) return null;
|
|
2950
|
+
const pal = uaPalette(isDark);
|
|
2951
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: ub.noteStack, children: notifications.map((n) => /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: [ub.note, { backgroundColor: pal.fieldBg, borderColor: pal.border }], children: [
|
|
2952
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.Info, { size: 14, color: pal.muted, strokeWidth: 1.9 }),
|
|
2953
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [ub.noteText, { color: pal.text }], children: n.message }),
|
|
2954
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { onPress: () => onDismiss(n.id), hitSlop: 8, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReactNative.X, { size: 14, color: pal.muted, strokeWidth: 2 }) })
|
|
2955
|
+
] }, n.id)) });
|
|
2956
|
+
}
|
|
2957
|
+
var ub = reactNative.StyleSheet.create({
|
|
2958
|
+
// Body wrapper can shrink within the sheet's (bounded) maxHeight so the inner
|
|
2959
|
+
// field scroll takes over for tall forms while the footer stays pinned.
|
|
2960
|
+
bodyWrap: { flexShrink: 1 },
|
|
2961
|
+
// Field scroll region. flexShrink:1 + no flexGrow → hugs content for short
|
|
2962
|
+
// forms (no scroll), shrinks and scrolls only when the form exceeds the sheet.
|
|
2963
|
+
fieldsScroll: { flexShrink: 1 },
|
|
2964
|
+
fieldsContent: { paddingBottom: 6 },
|
|
2965
|
+
messageBlock: { marginBottom: 18, marginTop: 2 },
|
|
2966
|
+
desc: { fontSize: 14.5, lineHeight: 21, marginBottom: 16 },
|
|
2967
|
+
form: { gap: 18 },
|
|
2968
|
+
field: { gap: 7 },
|
|
2969
|
+
label: { fontSize: 14, fontWeight: "600" },
|
|
2970
|
+
hint: { fontSize: 12.5, lineHeight: 17 },
|
|
2971
|
+
input: {
|
|
2972
|
+
borderWidth: 1,
|
|
2973
|
+
borderRadius: 12,
|
|
2974
|
+
paddingHorizontal: 14,
|
|
2975
|
+
paddingVertical: 13,
|
|
2976
|
+
fontSize: 16
|
|
2977
|
+
},
|
|
2978
|
+
error: { color: "#ef4444", fontSize: 12.5, marginTop: 2 },
|
|
2979
|
+
switchRow: { flexDirection: "row", alignItems: "center", gap: 12 },
|
|
2980
|
+
// Selectable option "boxes" for oneOf / enum single-select fields.
|
|
2981
|
+
optionList: { gap: 10 },
|
|
2982
|
+
optionRow: {
|
|
2983
|
+
flexDirection: "row",
|
|
2984
|
+
alignItems: "center",
|
|
2985
|
+
gap: 12,
|
|
2986
|
+
borderWidth: 1.5,
|
|
2987
|
+
borderRadius: 14,
|
|
2988
|
+
paddingHorizontal: 14,
|
|
2989
|
+
paddingVertical: 14
|
|
2990
|
+
},
|
|
2991
|
+
radio: {
|
|
2992
|
+
width: 20,
|
|
2993
|
+
height: 20,
|
|
2994
|
+
borderRadius: 10,
|
|
2995
|
+
borderWidth: 2,
|
|
2996
|
+
alignItems: "center",
|
|
2997
|
+
justifyContent: "center"
|
|
2998
|
+
},
|
|
2999
|
+
radioDot: { width: 10, height: 10, borderRadius: 5 },
|
|
3000
|
+
optionLabel: { flex: 1, fontSize: 15, letterSpacing: -0.1 },
|
|
3001
|
+
// Pinned footer (outside the fields scroll) — always visible.
|
|
3002
|
+
actions: { paddingTop: 16, gap: 14 },
|
|
3003
|
+
primaryBtn: { minHeight: 52, borderRadius: 14, borderWidth: 1, paddingVertical: 15, alignItems: "center", justifyContent: "center" },
|
|
3004
|
+
primaryBtnText: { color: "#fff", fontSize: 15.5, fontWeight: "600", letterSpacing: -0.1 },
|
|
3005
|
+
linkRow: { flexDirection: "row", justifyContent: "center", gap: 24 },
|
|
3006
|
+
link: { fontSize: 14, fontWeight: "500" },
|
|
3007
|
+
linkDanger: { color: "#dc2626" },
|
|
3008
|
+
codeRow: { flexDirection: "row", justifyContent: "center", gap: 9, position: "relative" },
|
|
3009
|
+
codeBox: {
|
|
3010
|
+
width: 46,
|
|
3011
|
+
height: 56,
|
|
3012
|
+
borderWidth: 1.5,
|
|
3013
|
+
borderRadius: 12,
|
|
3014
|
+
alignItems: "center",
|
|
3015
|
+
justifyContent: "center"
|
|
3016
|
+
},
|
|
3017
|
+
codeChar: { fontSize: 24, fontWeight: "600" },
|
|
3018
|
+
codeHidden: { ...reactNative.StyleSheet.absoluteFillObject, opacity: 0 },
|
|
3019
|
+
noteStack: { paddingHorizontal: 16, paddingBottom: 6, gap: 6 },
|
|
3020
|
+
note: {
|
|
3021
|
+
flexDirection: "row",
|
|
3022
|
+
alignItems: "center",
|
|
3023
|
+
gap: 8,
|
|
3024
|
+
borderWidth: 1,
|
|
3025
|
+
borderRadius: 12,
|
|
3026
|
+
paddingHorizontal: 12,
|
|
3027
|
+
paddingVertical: 10
|
|
3028
|
+
},
|
|
3029
|
+
noteText: { flex: 1, fontSize: 13.5, lineHeight: 19 }
|
|
3030
|
+
});
|
|
3031
|
+
var sht = reactNative.StyleSheet.create({
|
|
3032
|
+
// High stacking so the sheet sits above the chat input bar (which carries its
|
|
3033
|
+
// own zIndex/elevation) and everything else in the chat.
|
|
3034
|
+
overlay: { zIndex: 100, ...reactNative.Platform.select({ android: { elevation: 100 }, default: {} }) },
|
|
3035
|
+
backdrop: { ...reactNative.StyleSheet.absoluteFillObject },
|
|
3036
|
+
kav: { flex: 1, justifyContent: "flex-end" },
|
|
3037
|
+
sheet: {
|
|
3038
|
+
borderTopLeftRadius: 28,
|
|
3039
|
+
borderTopRightRadius: 28,
|
|
3040
|
+
borderWidth: reactNative.StyleSheet.hairlineWidth,
|
|
3041
|
+
borderBottomWidth: 0,
|
|
3042
|
+
paddingHorizontal: 22,
|
|
3043
|
+
paddingTop: 6,
|
|
3044
|
+
maxWidth: 640,
|
|
3045
|
+
width: "100%",
|
|
3046
|
+
alignSelf: "center",
|
|
3047
|
+
...reactNative.Platform.select({
|
|
3048
|
+
ios: {
|
|
3049
|
+
shadowColor: "#000",
|
|
3050
|
+
shadowOffset: { width: 0, height: -6 },
|
|
3051
|
+
shadowOpacity: 0.18,
|
|
3052
|
+
shadowRadius: 24
|
|
3053
|
+
},
|
|
3054
|
+
android: { elevation: 24 }
|
|
3055
|
+
})
|
|
3056
|
+
},
|
|
3057
|
+
handleZone: { alignItems: "center", paddingVertical: 10 },
|
|
3058
|
+
grabber: { width: 40, height: 5, borderRadius: 3 },
|
|
3059
|
+
header: { flexDirection: "row", alignItems: "center", gap: 12, marginTop: 2, marginBottom: 18 },
|
|
3060
|
+
iconCircle: { width: 40, height: 40, borderRadius: 20, alignItems: "center", justifyContent: "center" },
|
|
3061
|
+
headerText: { flex: 1, gap: 2 },
|
|
3062
|
+
title: { fontSize: 18, fontWeight: "700", letterSpacing: -0.3 },
|
|
3063
|
+
subtitle: { fontSize: 13, letterSpacing: -0.1 },
|
|
3064
|
+
timer: { borderWidth: 1, borderRadius: 999, paddingHorizontal: 11, paddingVertical: 5, minWidth: 46, alignItems: "center" },
|
|
3065
|
+
closeBtn: { width: 30, height: 30, borderRadius: 15, alignItems: "center", justifyContent: "center" },
|
|
3066
|
+
// Short, non-scrolling bodies (stale / expired notices).
|
|
3067
|
+
simpleBody: { paddingBottom: 8 }
|
|
3068
|
+
});
|
|
3069
|
+
var rc = reactNative.StyleSheet.create({
|
|
3070
|
+
card: {
|
|
3071
|
+
flexDirection: "row",
|
|
3072
|
+
alignItems: "center",
|
|
3073
|
+
gap: 12,
|
|
3074
|
+
borderWidth: 1.5,
|
|
3075
|
+
borderRadius: 18,
|
|
3076
|
+
paddingHorizontal: 14,
|
|
3077
|
+
paddingVertical: 13,
|
|
3078
|
+
marginVertical: 6
|
|
3079
|
+
},
|
|
3080
|
+
iconCircle: { width: 34, height: 34, borderRadius: 17, alignItems: "center", justifyContent: "center" },
|
|
3081
|
+
textWrap: { flex: 1, gap: 1 },
|
|
3082
|
+
title: { fontSize: 14.5, fontWeight: "700", letterSpacing: -0.2 },
|
|
3083
|
+
subtitle: { fontSize: 12.5, letterSpacing: -0.1 },
|
|
3084
|
+
timer: { borderRadius: 999, paddingHorizontal: 9, paddingVertical: 4, minWidth: 40, alignItems: "center" }
|
|
3085
|
+
});
|
|
2213
3086
|
var PaymanChat = react.forwardRef(
|
|
2214
3087
|
function PaymanChat2({ config, callbacks, children, onLoadMoreMessages, isLoadingMoreMessages = false, hasMoreMessages = false }, ref) {
|
|
2215
3088
|
const accent = config.accent ?? DEFAULT_ACCENT;
|
|
@@ -2236,8 +3109,14 @@ var PaymanChat = react.forwardRef(
|
|
|
2236
3109
|
},
|
|
2237
3110
|
onStatusMessage: (m) => callbacksRef.current?.onStatusMessage?.(m),
|
|
2238
3111
|
onStepsUpdate: (steps) => callbacksRef.current?.onStepsUpdate?.(steps),
|
|
2239
|
-
onUserActionRequired: (r) =>
|
|
2240
|
-
|
|
3112
|
+
onUserActionRequired: (r) => {
|
|
3113
|
+
console.log("[PaymanChat] USER_ACTION_REQUIRED:", JSON.stringify({ kind: r?.kind, rawAction: r?.rawAction, userActionId: r?.userActionId, hasSchema: !!r?.requestedSchema }));
|
|
3114
|
+
callbacksRef.current?.onUserActionRequired?.(r);
|
|
3115
|
+
},
|
|
3116
|
+
onUserNotification: (n) => {
|
|
3117
|
+
console.log("[PaymanChat] USER_NOTIFICATION:", JSON.stringify({ id: n?.id, message: n?.message }));
|
|
3118
|
+
callbacksRef.current?.onUserNotification?.(n);
|
|
3119
|
+
}
|
|
2241
3120
|
}), []);
|
|
2242
3121
|
const {
|
|
2243
3122
|
messages,
|
|
@@ -2248,8 +3127,37 @@ var PaymanChat = react.forwardRef(
|
|
|
2248
3127
|
prependMessages,
|
|
2249
3128
|
cancelStream,
|
|
2250
3129
|
getSessionId,
|
|
2251
|
-
getMessages
|
|
3130
|
+
getMessages,
|
|
3131
|
+
userActionState,
|
|
3132
|
+
submitUserAction: submitUserAction2,
|
|
3133
|
+
cancelUserAction: cancelUserAction2,
|
|
3134
|
+
resendUserAction: resendUserAction2,
|
|
3135
|
+
dismissNotification
|
|
2252
3136
|
} = useChatV2(config, stableCallbacks);
|
|
3137
|
+
react.useEffect(() => {
|
|
3138
|
+
console.log(
|
|
3139
|
+
"[PaymanChat] userActionState ->",
|
|
3140
|
+
"prompts:",
|
|
3141
|
+
userActionState.prompts.length,
|
|
3142
|
+
userActionState.prompts.map((p) => `${p.kind}:${p.status}`).join(","),
|
|
3143
|
+
"| notifications:",
|
|
3144
|
+
userActionState.notifications.length
|
|
3145
|
+
);
|
|
3146
|
+
}, [userActionState]);
|
|
3147
|
+
const activePrompt = react.useMemo(
|
|
3148
|
+
() => userActionState.prompts.find((p) => p.kind !== "notification"),
|
|
3149
|
+
[userActionState.prompts]
|
|
3150
|
+
);
|
|
3151
|
+
const expired = useExpiredFlag(activePrompt);
|
|
3152
|
+
const [dismissedActionId, setDismissedActionId] = react.useState(null);
|
|
3153
|
+
react.useEffect(() => {
|
|
3154
|
+
if (activePrompt) setDismissedActionId(null);
|
|
3155
|
+
}, [activePrompt?.userActionId, activePrompt?.subAction]);
|
|
3156
|
+
const sheetOpen = !!activePrompt && dismissedActionId !== activePrompt.userActionId;
|
|
3157
|
+
const showReopenCard = !!activePrompt && !sheetOpen && !expired && activePrompt.status !== "stale";
|
|
3158
|
+
const minimizeActivePrompt = react.useCallback(() => {
|
|
3159
|
+
setDismissedActionId((prev) => activePrompt?.userActionId ?? prev);
|
|
3160
|
+
}, [activePrompt?.userActionId]);
|
|
2253
3161
|
const {
|
|
2254
3162
|
transcribedText,
|
|
2255
3163
|
isAvailable: voiceAvailable,
|
|
@@ -2326,7 +3234,7 @@ var PaymanChat = react.forwardRef(
|
|
|
2326
3234
|
stopRecording();
|
|
2327
3235
|
clearTranscript();
|
|
2328
3236
|
}, [stopRecording, clearTranscript]);
|
|
2329
|
-
const isInputDisabled =
|
|
3237
|
+
const isInputDisabled = !config.sessionParams?.id?.trim();
|
|
2330
3238
|
const enableVoice = config.enableVoice !== false;
|
|
2331
3239
|
const isEmpty = messages.length === 0;
|
|
2332
3240
|
const prevMessageCountRef = react.useRef(messages.length);
|
|
@@ -2376,14 +3284,33 @@ var PaymanChat = react.forwardRef(
|
|
|
2376
3284
|
message: msg,
|
|
2377
3285
|
accent,
|
|
2378
3286
|
shouldType: typingMessageIds.current.has(msg.id),
|
|
2379
|
-
isDark
|
|
3287
|
+
isDark,
|
|
3288
|
+
suppressText: activePrompt?.message && msg.role === "assistant" && msg.id === messages[messages.length - 1]?.id ? activePrompt.message : void 0
|
|
2380
3289
|
},
|
|
2381
3290
|
msg.id
|
|
2382
3291
|
)),
|
|
3292
|
+
showReopenCard && activePrompt ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
3293
|
+
UserActionReopenCard,
|
|
3294
|
+
{
|
|
3295
|
+
active: activePrompt,
|
|
3296
|
+
expired,
|
|
3297
|
+
isDark,
|
|
3298
|
+
accent,
|
|
3299
|
+
onReopen: () => setDismissedActionId(null)
|
|
3300
|
+
}
|
|
3301
|
+
) : null,
|
|
2383
3302
|
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: { height: 4 } })
|
|
2384
3303
|
]
|
|
2385
3304
|
}
|
|
2386
3305
|
) }),
|
|
3306
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3307
|
+
NotificationStack,
|
|
3308
|
+
{
|
|
3309
|
+
notifications: userActionState.notifications,
|
|
3310
|
+
isDark,
|
|
3311
|
+
onDismiss: dismissNotification
|
|
3312
|
+
}
|
|
3313
|
+
),
|
|
2387
3314
|
/* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: s.inputBarWrap, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2388
3315
|
InputBar,
|
|
2389
3316
|
{
|
|
@@ -2407,7 +3334,22 @@ var PaymanChat = react.forwardRef(
|
|
|
2407
3334
|
},
|
|
2408
3335
|
insetBottom: config.contentInsetBottom ?? (reactNative.Platform.OS === "ios" ? 20 : 8)
|
|
2409
3336
|
}
|
|
2410
|
-
) })
|
|
3337
|
+
) }),
|
|
3338
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3339
|
+
UserActionSheet,
|
|
3340
|
+
{
|
|
3341
|
+
open: sheetOpen,
|
|
3342
|
+
active: activePrompt,
|
|
3343
|
+
expired,
|
|
3344
|
+
isDark,
|
|
3345
|
+
accent,
|
|
3346
|
+
insetBottom: config.contentInsetBottom ?? (reactNative.Platform.OS === "ios" ? 20 : 8),
|
|
3347
|
+
onSubmit: submitUserAction2,
|
|
3348
|
+
onCancel: cancelUserAction2,
|
|
3349
|
+
onResend: resendUserAction2,
|
|
3350
|
+
onMinimize: minimizeActivePrompt
|
|
3351
|
+
}
|
|
3352
|
+
)
|
|
2411
3353
|
]
|
|
2412
3354
|
}
|
|
2413
3355
|
) });
|