@paymanai/payman-ask-sdk 2.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -6,7 +6,7 @@ import { twMerge } from 'tailwind-merge';
6
6
  import * as Sentry from '@sentry/react';
7
7
  import { AnimatePresence, motion } from 'framer-motion';
8
8
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
9
- import { ArrowDown, Pencil, X, RotateCcw, Plus, ImagePlus, Paperclip, Mic, ArrowUp, Check, AlertCircle, Copy, WifiOff, SearchCode, ShieldCheck, Loader2, PanelBottomOpen, Download, ChevronRight, PanelLeftClose, PanelLeftOpen, ImageOff, Eye, MessageSquare, Menu, MessageCircle, ChevronDown } from 'lucide-react';
9
+ import { ArrowDown, Pencil, X, RotateCcw, Plus, ImagePlus, Paperclip, Mic, ArrowUp, Check, AlertCircle, Copy, WifiOff, SearchCode, ShieldCheck, PanelBottomOpen, Download, Loader2, ChevronRight, PanelLeftClose, PanelLeftOpen, ImageOff, Eye, MessageSquare, Menu, MessageCircle, ChevronDown } from 'lucide-react';
10
10
  import { createPortal } from 'react-dom';
11
11
  import ReactMarkdown from 'react-markdown';
12
12
  import remarkGfm from 'remark-gfm';
@@ -1538,6 +1538,7 @@ function VerificationCardV2({
1538
1538
  messageId,
1539
1539
  action,
1540
1540
  status,
1541
+ clearOtpTrigger = 0,
1541
1542
  onApprove,
1542
1543
  onReject,
1543
1544
  onResend
@@ -1545,33 +1546,41 @@ function VerificationCardV2({
1545
1546
  const [otp, setOtp] = useState("");
1546
1547
  const [otpErrored, setOtpErrored] = useState(false);
1547
1548
  const [resendSec, setResendSec] = useState(0);
1549
+ const [localPending, setLocalPending] = useState(false);
1548
1550
  const lastSubmittedRef = useRef(null);
1549
1551
  const resendTimerRef = useRef(void 0);
1550
1552
  useEffect(() => {
1551
- if (status !== "error") {
1552
- setOtpErrored(false);
1553
- return;
1554
- }
1553
+ if (clearOtpTrigger <= 0) return;
1555
1554
  setOtpErrored(true);
1556
1555
  const t = window.setTimeout(() => {
1557
1556
  setOtp("");
1558
1557
  setOtpErrored(false);
1558
+ setLocalPending(false);
1559
1559
  lastSubmittedRef.current = null;
1560
1560
  }, 600);
1561
1561
  return () => window.clearTimeout(t);
1562
- }, [status]);
1562
+ }, [clearOtpTrigger]);
1563
1563
  useEffect(() => {
1564
1564
  if (otp.length < OTP_LEN) {
1565
1565
  lastSubmittedRef.current = null;
1566
1566
  }
1567
1567
  }, [otp]);
1568
+ useEffect(() => {
1569
+ if (status !== "pending") {
1570
+ setLocalPending(false);
1571
+ }
1572
+ }, [status]);
1568
1573
  useEffect(() => {
1569
1574
  if (otp.length !== OTP_LEN || !/^\d+$/.test(otp) || status !== "pending") {
1570
1575
  return;
1571
1576
  }
1572
1577
  if (lastSubmittedRef.current === otp) return;
1573
1578
  lastSubmittedRef.current = otp;
1574
- void onApprove(messageId, otp);
1579
+ setLocalPending(true);
1580
+ void onApprove(messageId, otp).catch(() => {
1581
+ lastSubmittedRef.current = null;
1582
+ setLocalPending(false);
1583
+ });
1575
1584
  }, [messageId, onApprove, otp, status]);
1576
1585
  useEffect(() => {
1577
1586
  return () => {
@@ -1599,23 +1608,25 @@ function VerificationCardV2({
1599
1608
  }, 1e3);
1600
1609
  }, []);
1601
1610
  const handleResend = useCallback(async () => {
1602
- if (resendSec > 0 || status === "verifying") return;
1603
- await onResend(messageId);
1604
- startResendCooldown();
1605
- }, [messageId, onResend, resendSec, startResendCooldown, status]);
1611
+ if (resendSec > 0 || status === "verifying" || localPending) return;
1612
+ setLocalPending(true);
1613
+ try {
1614
+ await onResend(messageId);
1615
+ startResendCooldown();
1616
+ } finally {
1617
+ setLocalPending(false);
1618
+ }
1619
+ }, [localPending, messageId, onResend, resendSec, startResendCooldown, status]);
1606
1620
  const handleCancel = useCallback(async () => {
1607
- await onReject(messageId);
1608
- }, [messageId, onReject]);
1609
- useCallback(async () => {
1610
- if (otp.length !== OTP_LEN || !/^\d+$/.test(otp) || status !== "pending") {
1611
- return;
1621
+ if (status === "verifying" || localPending) return;
1622
+ setLocalPending(true);
1623
+ try {
1624
+ await onReject(messageId);
1625
+ } finally {
1626
+ setLocalPending(false);
1612
1627
  }
1613
- if (lastSubmittedRef.current === otp) return;
1614
- lastSubmittedRef.current = otp;
1615
- await onApprove(messageId, otp);
1616
- }, [messageId, onApprove, otp, status]);
1617
- const busy = status === "verifying";
1618
- status === "pending" && otp.length === OTP_LEN && /^\d+$/.test(otp);
1628
+ }, [localPending, messageId, onReject, status]);
1629
+ const busy = status === "verifying" || localPending;
1619
1630
  if (status === "approved" || status === "rejected") {
1620
1631
  return null;
1621
1632
  }
@@ -1627,61 +1638,53 @@ function VerificationCardV2({
1627
1638
  animate: { opacity: 1, y: 0 },
1628
1639
  transition: { type: "spring", stiffness: 320, damping: 28 },
1629
1640
  children: [
1630
- /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-card", children: [
1631
- /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-header", children: [
1632
- /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-header-row", children: [
1633
- /* @__PURE__ */ jsx(
1634
- ShieldCheck,
1635
- {
1636
- className: "payman-v2-verification-icon",
1637
- size: 18,
1638
- strokeWidth: 1.75,
1639
- "aria-hidden": true
1640
- }
1641
- ),
1642
- /* @__PURE__ */ jsx("p", { className: "payman-v2-verification-title", children: "Verify" }),
1643
- action.amount != null ? /* @__PURE__ */ jsx("span", { className: "payman-v2-verification-amount", children: action.amount }) : action.payeeName ? /* @__PURE__ */ jsx("span", { className: "payman-v2-verification-payee", children: action.payeeName }) : null
1644
- ] }),
1645
- /* @__PURE__ */ jsx("p", { className: "payman-v2-verification-description", children: "Enter the 6-digit code sent to your phone" }),
1646
- /* @__PURE__ */ jsx(
1647
- OtpInputV2,
1648
- {
1649
- value: otp,
1650
- onChange: setOtp,
1651
- maxLength: OTP_LEN,
1652
- disabled: busy,
1653
- error: otpErrored
1654
- }
1641
+ /* @__PURE__ */ jsxs(
1642
+ "div",
1643
+ {
1644
+ className: cn(
1645
+ "payman-v2-verification-card",
1646
+ busy && "payman-v2-verification-card-busy"
1655
1647
  ),
1656
- busy ? /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-submitting", children: [
1657
- /* @__PURE__ */ jsx(
1658
- motion.span,
1648
+ children: [
1649
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-header", children: [
1650
+ /* @__PURE__ */ jsxs("div", { className: "payman-v2-verification-header-row", children: [
1651
+ /* @__PURE__ */ jsx(
1652
+ ShieldCheck,
1653
+ {
1654
+ className: "payman-v2-verification-icon",
1655
+ size: 18,
1656
+ strokeWidth: 1.75,
1657
+ "aria-hidden": true
1658
+ }
1659
+ ),
1660
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-verification-title", children: "Verify" }),
1661
+ action.amount != null ? /* @__PURE__ */ jsx("span", { className: "payman-v2-verification-amount", children: action.amount }) : action.payeeName ? /* @__PURE__ */ jsx("span", { className: "payman-v2-verification-payee", children: action.payeeName }) : null
1662
+ ] }),
1663
+ /* @__PURE__ */ jsx("p", { className: "payman-v2-verification-description", children: "Enter the 6-digit code sent to your phone" }),
1664
+ /* @__PURE__ */ jsx(
1665
+ OtpInputV2,
1666
+ {
1667
+ value: otp,
1668
+ onChange: setOtp,
1669
+ maxLength: OTP_LEN,
1670
+ disabled: busy,
1671
+ error: otpErrored
1672
+ }
1673
+ )
1674
+ ] }),
1675
+ /* @__PURE__ */ jsx("div", { className: "payman-v2-verification-actions", children: /* @__PURE__ */ jsx(
1676
+ "button",
1659
1677
  {
1660
- "aria-hidden": true,
1661
- style: { display: "inline-flex" },
1662
- animate: { rotate: 360 },
1663
- transition: {
1664
- repeat: Infinity,
1665
- duration: 0.7,
1666
- ease: "linear"
1667
- },
1668
- children: /* @__PURE__ */ jsx(Loader2, { size: 14, strokeWidth: 2 })
1678
+ type: "button",
1679
+ className: "payman-v2-verification-cancel-btn",
1680
+ disabled: busy,
1681
+ onClick: () => void handleCancel(),
1682
+ children: "Cancel"
1669
1683
  }
1670
- ),
1671
- /* @__PURE__ */ jsx("span", { className: "payman-v2-verification-submitting-text", children: "Verifying..." })
1672
- ] }) : null
1673
- ] }),
1674
- /* @__PURE__ */ jsx("div", { className: "payman-v2-verification-actions", children: /* @__PURE__ */ jsx(
1675
- "button",
1676
- {
1677
- type: "button",
1678
- className: "payman-v2-verification-cancel-btn",
1679
- disabled: busy,
1680
- onClick: () => void handleCancel(),
1681
- children: "Cancel"
1682
- }
1683
- ) })
1684
- ] }),
1684
+ ) })
1685
+ ]
1686
+ }
1687
+ ),
1685
1688
  /* @__PURE__ */ jsx(
1686
1689
  "button",
1687
1690
  {
@@ -1874,6 +1877,7 @@ var MessageListV2 = forwardRef(
1874
1877
  messageId: userAction.messageId,
1875
1878
  action: userAction.action,
1876
1879
  status: userAction.status,
1880
+ clearOtpTrigger: userAction.clearOtpTrigger,
1877
1881
  onApprove: onApproveAction ?? (async () => {
1878
1882
  }),
1879
1883
  onReject: onRejectAction ?? (async () => {
@@ -3682,6 +3686,14 @@ var PaymanChat = forwardRef(function PaymanChat2({
3682
3686
  }),
3683
3687
  [performResetSession, clearMessages, cancelStream, getSessionId, getMessages, loadSession]
3684
3688
  );
3689
+ const [v2VerificationPending, setV2VerificationPending] = useState(false);
3690
+ useEffect(() => {
3691
+ setV2VerificationPending(false);
3692
+ }, [
3693
+ userActionState.request?.userActionId,
3694
+ userActionState.clearOtpTrigger,
3695
+ userActionState.result
3696
+ ]);
3685
3697
  if (availability.state === "disabled") {
3686
3698
  return /* @__PURE__ */ jsx(PaymanChatContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
3687
3699
  "div",
@@ -3704,7 +3716,8 @@ var PaymanChat = forwardRef(function PaymanChat2({
3704
3716
  if (!userActionState.request) return null;
3705
3717
  const req = userActionState.request;
3706
3718
  let status = "pending";
3707
- if (userActionState.result === "approved") status = "approved";
3719
+ if (v2VerificationPending) status = "verifying";
3720
+ else if (userActionState.result === "approved") status = "approved";
3708
3721
  else if (userActionState.result === "rejected") status = "rejected";
3709
3722
  return {
3710
3723
  messageId: `ua-${req.userActionId || Date.now()}`,
@@ -3714,9 +3727,15 @@ var PaymanChat = forwardRef(function PaymanChat2({
3714
3727
  amount: req.metadata?.amount,
3715
3728
  payeeName: req.metadata?.payeeName
3716
3729
  },
3717
- status
3730
+ status,
3731
+ clearOtpTrigger: userActionState.clearOtpTrigger
3718
3732
  };
3719
- }, [userActionState.request, userActionState.result]);
3733
+ }, [
3734
+ userActionState.request,
3735
+ userActionState.result,
3736
+ userActionState.clearOtpTrigger,
3737
+ v2VerificationPending
3738
+ ]);
3720
3739
  const hideV2SendDuringVerification = v2UserAction != null && v2UserAction.status !== "approved" && v2UserAction.status !== "rejected";
3721
3740
  const handleV2Send = (text) => {
3722
3741
  if (isRecording) stopRecording();
@@ -3878,10 +3897,22 @@ var PaymanChat = forwardRef(function PaymanChat2({
3878
3897
  retryDisabled: isWaitingForResponse,
3879
3898
  userAction: v2UserAction,
3880
3899
  onApproveAction: async (_id, otp) => {
3881
- await approveUserAction(otp);
3900
+ setV2VerificationPending(true);
3901
+ try {
3902
+ await approveUserAction(otp);
3903
+ } catch (error) {
3904
+ setV2VerificationPending(false);
3905
+ throw error;
3906
+ }
3882
3907
  },
3883
3908
  onRejectAction: async () => {
3884
- await rejectUserAction();
3909
+ setV2VerificationPending(true);
3910
+ try {
3911
+ await rejectUserAction();
3912
+ } catch (error) {
3913
+ setV2VerificationPending(false);
3914
+ throw error;
3915
+ }
3885
3916
  },
3886
3917
  onResendAction: async () => {
3887
3918
  await resendOtp();