@unseen_fi/ui 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,16 +1,2 @@
1
1
  import type { UnseenPayButtonProps } from "./types";
2
- /**
3
- * A drop-in "Pay with Unseen" button that opens a checkout modal.
4
- * The modal shows wallet picker, QR code / deeplinks, and "I have paid" confirmation.
5
- *
6
- * @example
7
- * ```tsx
8
- * <UnseenPayButton
9
- * amount={50_000_000}
10
- * reference="order_123"
11
- * description="Premium Plan"
12
- * onSuccess={(p) => console.log("Paid!", p.id)}
13
- * />
14
- * ```
15
- */
16
- export declare function UnseenPayButton({ amount, mint, reference, description, expiresIn, onSuccess, onError, onCreated, label, className, disabled, }: UnseenPayButtonProps): import("react/jsx-runtime").JSX.Element;
2
+ export declare function UnseenPayButton({ amount, mint, reference, description, expiresIn, onSuccess, onError, onCreated, createPaymentSession, label, className, disabled, }: UnseenPayButtonProps): import("react/jsx-runtime").JSX.Element;
@@ -7,39 +7,29 @@ const context_1 = require("./context");
7
7
  const hooks_1 = require("./hooks");
8
8
  const wallets_1 = require("./wallets");
9
9
  // ─── UnseenPayButton ─────────────────────────────────────────────────────────
10
- /**
11
- * A drop-in "Pay with Unseen" button that opens a checkout modal.
12
- * The modal shows wallet picker, QR code / deeplinks, and "I have paid" confirmation.
13
- *
14
- * @example
15
- * ```tsx
16
- * <UnseenPayButton
17
- * amount={50_000_000}
18
- * reference="order_123"
19
- * description="Premium Plan"
20
- * onSuccess={(p) => console.log("Paid!", p.id)}
21
- * />
22
- * ```
23
- */
24
- function UnseenPayButton({ amount, mint, reference, description, expiresIn, onSuccess, onError, onCreated, label = "Pay with Unseen", className, disabled, }) {
10
+ function UnseenPayButton({ amount, mint, reference, description, expiresIn, onSuccess, onError, onCreated, createPaymentSession, label = "Pay with Unseen", className, disabled, }) {
25
11
  const [modalOpen, setModalOpen] = (0, react_1.useState)(false);
26
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("button", { className: className, style: className ? undefined : defaultButtonStyle, onClick: () => setModalOpen(true), disabled: disabled, children: [(0, jsx_runtime_1.jsx)(ShieldIcon, {}), label] }), modalOpen && ((0, jsx_runtime_1.jsx)(UnseenModal, { amount: amount, mint: mint, reference: reference, description: description, expiresIn: expiresIn, onSuccess: (p) => {
12
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("button", { className: className, style: className ? undefined : defaultButtonStyle, onClick: () => setModalOpen(true), disabled: disabled, children: [(0, jsx_runtime_1.jsx)(ShieldIcon, {}), label] }), modalOpen && ((0, jsx_runtime_1.jsx)(UnseenModal, { amount: amount, mint: mint, reference: reference, description: description, expiresIn: expiresIn, createPaymentSession: createPaymentSession, onSuccess: (p) => {
27
13
  onSuccess?.(p);
28
14
  setModalOpen(false);
29
15
  }, onError: onError, onCreated: onCreated, onClose: () => setModalOpen(false) }))] }));
30
16
  }
31
- function UnseenModal({ amount, mint, reference, description, expiresIn, onSuccess, onError, onCreated, onClose, }) {
17
+ function UnseenModal({ amount, mint, reference, description, expiresIn, createPaymentSession, onSuccess, onError, onCreated, onClose, }) {
32
18
  const { baseUrl } = (0, context_1.useUnseenConfig)();
33
19
  const { payment, createPayment } = (0, hooks_1.usePayment)();
34
20
  const { verify } = (0, hooks_1.useVerify)();
35
21
  const [step, setStep] = (0, react_1.useState)("creating");
36
22
  const [errorMsg, setErrorMsg] = (0, react_1.useState)("");
37
23
  const [selectedWallet, setSelectedWallet] = (0, react_1.useState)(null);
24
+ const [deeplink, setDeeplink] = (0, react_1.useState)("");
38
25
  const [verifyCountdown, setVerifyCountdown] = (0, react_1.useState)(60);
39
26
  // ─── Create payment on mount ────────────────────────────────────────────
40
27
  (0, react_1.useEffect)(() => {
41
28
  let cancelled = false;
42
- createPayment({ amount, reference, description, mint, expiresIn })
29
+ const initiator = createPaymentSession
30
+ ? () => createPaymentSession({ amount, reference, description, mint, expiresIn })
31
+ : () => createPayment({ amount, reference, description, mint, expiresIn });
32
+ initiator()
43
33
  .then((p) => {
44
34
  if (cancelled)
45
35
  return;
@@ -57,16 +47,15 @@ function UnseenModal({ amount, mint, reference, description, expiresIn, onSucces
57
47
  return () => { cancelled = true; };
58
48
  // eslint-disable-next-line react-hooks/exhaustive-deps
59
49
  }, []);
60
- // ─── Handle wallet selection ────────────────────────────────────────────
50
+ // ─── Handle wallet selection → show QR step ─────────────────────────────
61
51
  const handleWalletSelect = (0, react_1.useCallback)((wallet) => {
62
52
  if (!payment)
63
53
  return;
54
+ const checkoutUrl = payment.checkoutUrl || `${baseUrl}/pay/${payment.id}`;
55
+ const dl = wallet.deeplink(checkoutUrl);
64
56
  setSelectedWallet(wallet);
65
- // Open the checkout page in the wallet's in-app browser via deeplink
66
- const checkoutUrl = `${baseUrl}/pay/${payment.id}`;
67
- const deeplink = wallet.deeplink(checkoutUrl);
68
- window.open(deeplink, "_blank");
69
- setStep("waiting");
57
+ setDeeplink(dl);
58
+ setStep("qr-display");
70
59
  }, [payment, baseUrl]);
71
60
  // ─── Handle "I have paid" verification ──────────────────────────────────
72
61
  const handleVerify = (0, react_1.useCallback)(async () => {
@@ -75,7 +64,6 @@ function UnseenModal({ amount, mint, reference, description, expiresIn, onSucces
75
64
  setStep("verifying");
76
65
  setVerifyCountdown(60);
77
66
  try {
78
- // Keep verifying for up to 60s to improve UX and reduce manual retries.
79
67
  const startedAt = Date.now();
80
68
  while (Date.now() - startedAt < 60000) {
81
69
  const result = await verify(payment.id);
@@ -93,7 +81,7 @@ function UnseenModal({ amount, mint, reference, description, expiresIn, onSucces
93
81
  await new Promise((resolve) => setTimeout(resolve, 3000));
94
82
  }
95
83
  setErrorMsg("Still waiting for confirmation. Please try again in a few seconds.");
96
- setStep("waiting");
84
+ setStep("qr-display");
97
85
  }
98
86
  catch (err) {
99
87
  const e = err instanceof Error ? err : new Error(String(err));
@@ -111,7 +99,13 @@ function UnseenModal({ amount, mint, reference, description, expiresIn, onSucces
111
99
  return () => clearInterval(timer);
112
100
  }, [step]);
113
101
  // ─── Render ─────────────────────────────────────────────────────────────
114
- return ((0, jsx_runtime_1.jsx)("div", { style: overlayStyle, onClick: onClose, children: (0, jsx_runtime_1.jsxs)("div", { style: modalStyle, onClick: (e) => e.stopPropagation(), children: [(0, jsx_runtime_1.jsxs)("div", { style: modalHeaderStyle, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [(0, jsx_runtime_1.jsx)(ShieldIcon, { size: 20 }), (0, jsx_runtime_1.jsx)("span", { style: { fontWeight: 600, fontSize: "16px", color: "#fff" }, children: "Unseen Pay" })] }), (0, jsx_runtime_1.jsx)("button", { style: closeButtonStyle, onClick: onClose, children: "\u2715" })] }), (0, jsx_runtime_1.jsxs)("div", { style: modalBodyStyle, children: [step === "creating" && ((0, jsx_runtime_1.jsxs)(StepContent, { children: [(0, jsx_runtime_1.jsx)(Spinner, {}), (0, jsx_runtime_1.jsx)(StepText, { children: "Creating payment session..." })] })), step === "wallet-picker" && ((0, jsx_runtime_1.jsxs)(StepContent, { children: [(0, jsx_runtime_1.jsx)(StepText, { children: "Choose your wallet" }), (0, jsx_runtime_1.jsx)(StepHint, { children: "Select a wallet to complete the private payment." }), (0, jsx_runtime_1.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: "8px", width: "100%", marginTop: "8px" }, children: wallets_1.WALLETS.map((w) => ((0, jsx_runtime_1.jsxs)("button", { style: walletButtonStyle, onClick: () => handleWalletSelect(w), children: [(0, jsx_runtime_1.jsx)("div", { style: walletIconStyle, children: (0, jsx_runtime_1.jsx)("img", { src: w.icon, alt: `${w.name} logo`, style: walletLogoImageStyle }) }), (0, jsx_runtime_1.jsx)("span", { style: { fontWeight: 500, color: "#fff" }, children: w.name }), (0, jsx_runtime_1.jsx)("span", { style: { marginLeft: "auto", color: "rgba(255,255,255,0.3)", fontSize: "13px" }, children: "\u2192" })] }, w.id))) })] })), step === "waiting" && ((0, jsx_runtime_1.jsxs)(StepContent, { children: [(0, jsx_runtime_1.jsxs)("div", { style: walletBadgeStyle, children: [selectedWallet && ((0, jsx_runtime_1.jsx)("div", { style: { ...walletIconStyle, width: "24px", height: "24px" }, children: (0, jsx_runtime_1.jsx)("img", { src: selectedWallet.icon, alt: `${selectedWallet.name} logo`, style: walletLogoImageStyle }) })), (0, jsx_runtime_1.jsxs)("span", { style: { fontSize: "13px", color: "rgba(255,255,255,0.5)" }, children: ["Opened in ", selectedWallet?.name ?? "wallet"] })] }), (0, jsx_runtime_1.jsx)(StepText, { children: "Complete payment in your wallet" }), (0, jsx_runtime_1.jsx)(StepHint, { children: "After signing the transaction in your wallet, come back here and confirm." }), errorMsg && ((0, jsx_runtime_1.jsx)("div", { style: inlineErrorStyle, children: errorMsg })), (0, jsx_runtime_1.jsx)("button", { style: confirmButtonStyle, onClick: handleVerify, children: "I have paid" }), (0, jsx_runtime_1.jsx)("button", { style: linkButtonStyle, onClick: () => { setStep("wallet-picker"); setErrorMsg(""); }, children: "Use a different wallet" })] })), step === "verifying" && ((0, jsx_runtime_1.jsxs)(StepContent, { children: [(0, jsx_runtime_1.jsx)(Spinner, {}), (0, jsx_runtime_1.jsx)(StepText, { children: "Verifying on Solana..." }), (0, jsx_runtime_1.jsxs)(StepHint, { children: ["Checking your transaction on-chain (", verifyCountdown, "s)."] })] })), step === "confirmed" && ((0, jsx_runtime_1.jsxs)(StepContent, { children: [(0, jsx_runtime_1.jsx)("div", { style: successCircle, children: (0, jsx_runtime_1.jsx)("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: "#22c55e", strokeWidth: "2.5", children: (0, jsx_runtime_1.jsx)("polyline", { points: "20 6 9 17 4 12" }) }) }), (0, jsx_runtime_1.jsx)(StepText, { style: { color: "#22c55e" }, children: "Payment Confirmed!" }), (0, jsx_runtime_1.jsx)(StepHint, { children: "Your transaction has been verified on Solana." }), (0, jsx_runtime_1.jsx)("button", { style: confirmButtonStyle, onClick: onClose, children: "Done" })] })), step === "error" && ((0, jsx_runtime_1.jsxs)(StepContent, { children: [(0, jsx_runtime_1.jsx)("div", { style: errorCircle, children: (0, jsx_runtime_1.jsxs)("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "#ef4444", strokeWidth: "2", children: [(0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "12", r: "10" }), (0, jsx_runtime_1.jsx)("line", { x1: "15", y1: "9", x2: "9", y2: "15" }), (0, jsx_runtime_1.jsx)("line", { x1: "9", y1: "9", x2: "15", y2: "15" })] }) }), (0, jsx_runtime_1.jsx)(StepText, { style: { color: "#ef4444" }, children: "Error" }), (0, jsx_runtime_1.jsx)(StepHint, { children: errorMsg }), (0, jsx_runtime_1.jsx)("button", { style: confirmButtonStyle, onClick: () => { setStep("wallet-picker"); setErrorMsg(""); }, children: "Try Again" })] }))] }), (0, jsx_runtime_1.jsx)("div", { style: modalFooterStyle, children: (0, jsx_runtime_1.jsx)("span", { style: { fontSize: "11px", color: "rgba(255,255,255,0.2)" }, children: "Powered by Unseen Finance \u2022 Privacy-preserving payments" }) })] }) }));
102
+ return ((0, jsx_runtime_1.jsx)("div", { style: overlayStyle, onClick: onClose, children: (0, jsx_runtime_1.jsxs)("div", { style: modalStyle, onClick: (e) => e.stopPropagation(), children: [(0, jsx_runtime_1.jsxs)("div", { style: modalHeaderStyle, children: [(0, jsx_runtime_1.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [(0, jsx_runtime_1.jsx)(ShieldIcon, { size: 18 }), (0, jsx_runtime_1.jsx)("span", { style: { fontWeight: 700, fontSize: "15px", color: "#1a0a3d" }, children: "Unseen Pay" })] }), (0, jsx_runtime_1.jsx)("button", { style: closeButtonStyle, onClick: onClose, children: "\u2715" })] }), (0, jsx_runtime_1.jsxs)("div", { style: modalBodyStyle, children: [step === "creating" && ((0, jsx_runtime_1.jsxs)(StepContent, { children: [(0, jsx_runtime_1.jsx)(Spinner, {}), (0, jsx_runtime_1.jsx)(StepText, { children: "Setting up payment\u2026" }), (0, jsx_runtime_1.jsx)(StepHint, { children: "Creating a secure payment session for you." })] })), step === "wallet-picker" && ((0, jsx_runtime_1.jsxs)(StepContent, { children: [(0, jsx_runtime_1.jsx)(StepText, { children: "Which wallet would you like to use?" }), (0, jsx_runtime_1.jsx)(StepHint, { children: "Select a wallet to complete this private payment." }), (0, jsx_runtime_1.jsx)("div", { style: walletRowStyle, children: wallets_1.WALLETS.map((w) => ((0, jsx_runtime_1.jsxs)("button", { style: walletCardStyle, onClick: () => handleWalletSelect(w), onMouseEnter: (e) => {
103
+ e.currentTarget.style.background = "rgba(123,47,255,0.1)";
104
+ e.currentTarget.style.borderColor = "rgba(123,47,255,0.35)";
105
+ }, onMouseLeave: (e) => {
106
+ e.currentTarget.style.background = "rgba(123,47,255,0.04)";
107
+ e.currentTarget.style.borderColor = "rgba(123,47,255,0.12)";
108
+ }, children: [(0, jsx_runtime_1.jsx)("div", { style: walletIconContainerStyle, children: (0, jsx_runtime_1.jsx)("img", { src: w.icon, alt: `${w.name} logo`, style: walletLogoImageStyle }) }), (0, jsx_runtime_1.jsx)("span", { style: walletNameStyle, children: w.name })] }, w.id))) })] })), step === "qr-display" && selectedWallet && ((0, jsx_runtime_1.jsxs)(StepContent, { children: [(0, jsx_runtime_1.jsxs)("div", { style: walletBadgeStyle, children: [(0, jsx_runtime_1.jsx)("img", { src: selectedWallet.icon, alt: selectedWallet.name, style: { width: "18px", height: "18px", borderRadius: "5px", objectFit: "cover" } }), (0, jsx_runtime_1.jsx)("span", { style: { fontSize: "12px", color: "#6b21a8", fontWeight: 600 }, children: selectedWallet.name })] }), (0, jsx_runtime_1.jsx)(StepText, { children: "Scan to pay" }), (0, jsx_runtime_1.jsx)(StepHint, { children: "Point another device's camera at this code to open in your wallet, or use the link below to pay on this device." }), (0, jsx_runtime_1.jsx)("div", { style: qrWrapperStyle, children: (0, jsx_runtime_1.jsx)("img", { src: `https://api.qrserver.com/v1/create-qr-code/?size=220x220&data=${encodeURIComponent(deeplink)}&bgcolor=ffffff&color=1a0a3d&margin=8&qzone=1`, alt: "Payment QR code", width: 220, height: 220, style: { display: "block", borderRadius: "8px" } }) }), (0, jsx_runtime_1.jsxs)("button", { style: deepLinkButtonStyle, onClick: () => window.open(deeplink, "_blank"), children: ["Or open in ", selectedWallet.name, " directly \u2192"] }), errorMsg && (0, jsx_runtime_1.jsx)("div", { style: inlineErrorStyle, children: errorMsg }), (0, jsx_runtime_1.jsx)("button", { style: confirmButtonStyle, onClick: handleVerify, children: "I have paid" }), (0, jsx_runtime_1.jsx)("button", { style: linkButtonStyle, onClick: () => { setStep("wallet-picker"); setErrorMsg(""); setDeeplink(""); }, children: "Use a different wallet" })] })), step === "verifying" && ((0, jsx_runtime_1.jsxs)(StepContent, { children: [(0, jsx_runtime_1.jsx)(Spinner, {}), (0, jsx_runtime_1.jsx)(StepText, { children: "Verifying on Solana\u2026" }), (0, jsx_runtime_1.jsxs)(StepHint, { children: ["Checking your transaction on-chain (", verifyCountdown, "s)."] })] })), step === "confirmed" && ((0, jsx_runtime_1.jsxs)(StepContent, { children: [(0, jsx_runtime_1.jsx)("div", { style: successCircle, children: (0, jsx_runtime_1.jsx)("svg", { width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: "#16a34a", strokeWidth: "2.5", children: (0, jsx_runtime_1.jsx)("polyline", { points: "20 6 9 17 4 12" }) }) }), (0, jsx_runtime_1.jsx)(StepText, { style: { color: "#16a34a" }, children: "Payment Confirmed!" }), (0, jsx_runtime_1.jsx)(StepHint, { children: "Your transaction has been verified on Solana." }), (0, jsx_runtime_1.jsx)("button", { style: confirmButtonStyle, onClick: onClose, children: "Done" })] })), step === "error" && ((0, jsx_runtime_1.jsxs)(StepContent, { children: [(0, jsx_runtime_1.jsx)("div", { style: errorCircle, children: (0, jsx_runtime_1.jsxs)("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "#dc2626", strokeWidth: "2", children: [(0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "12", r: "10" }), (0, jsx_runtime_1.jsx)("line", { x1: "15", y1: "9", x2: "9", y2: "15" }), (0, jsx_runtime_1.jsx)("line", { x1: "9", y1: "9", x2: "15", y2: "15" })] }) }), (0, jsx_runtime_1.jsx)(StepText, { style: { color: "#dc2626" }, children: "Something went wrong" }), (0, jsx_runtime_1.jsx)(StepHint, { children: errorMsg }), (0, jsx_runtime_1.jsx)("button", { style: confirmButtonStyle, onClick: () => { setStep("wallet-picker"); setErrorMsg(""); }, children: "Try Again" })] }))] }), (0, jsx_runtime_1.jsx)("div", { style: modalFooterStyle, children: (0, jsx_runtime_1.jsx)("span", { style: { fontSize: "11px", color: "rgba(100,60,180,0.35)" }, children: "Powered by Unseen Finance \u00B7 Privacy-preserving payments on Solana" }) })] }) }));
115
109
  }
116
110
  // ─── Sub-components ──────────────────────────────────────────────────────────
117
111
  function StepContent({ children }) {
@@ -127,7 +121,7 @@ function Spinner() {
127
121
  return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("style", { children: `@keyframes unseen-spin { to { transform: rotate(360deg); } }` }), (0, jsx_runtime_1.jsx)("div", { style: spinnerStyle })] }));
128
122
  }
129
123
  function ShieldIcon({ size = 16 }) {
130
- return ((0, jsx_runtime_1.jsx)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: (0, jsx_runtime_1.jsx)("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }) }));
124
+ return ((0, jsx_runtime_1.jsx)("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "#7b2fff", strokeWidth: "2.5", children: (0, jsx_runtime_1.jsx)("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }) }));
131
125
  }
132
126
  // ─── Styles ──────────────────────────────────────────────────────────────────
133
127
  const defaultButtonStyle = {
@@ -148,97 +142,109 @@ const defaultButtonStyle = {
148
142
  const overlayStyle = {
149
143
  position: "fixed",
150
144
  inset: 0,
151
- background: "rgba(0,0,0,0.7)",
152
- backdropFilter: "blur(8px)",
145
+ background: "rgba(10,4,30,0.55)",
146
+ backdropFilter: "blur(10px)",
153
147
  display: "flex",
154
148
  alignItems: "center",
155
149
  justifyContent: "center",
156
150
  zIndex: 999999,
157
151
  fontFamily: "'Inter', system-ui, sans-serif",
158
- color: "#fff",
159
152
  padding: "16px",
160
153
  };
161
154
  const modalStyle = {
162
- background: "rgba(18,16,31,0.98)",
163
- border: "1px solid rgba(255,255,255,0.08)",
155
+ background: "linear-gradient(145deg, #ffffff 0%, #f7f3ff 55%, #ede8ff 100%)",
156
+ border: "1px solid rgba(123,47,255,0.14)",
164
157
  borderRadius: "20px",
165
158
  width: "100%",
166
- maxWidth: "400px",
159
+ maxWidth: "420px",
167
160
  overflow: "hidden",
161
+ boxShadow: "0 24px 64px rgba(100,40,220,0.14), 0 4px 16px rgba(0,0,0,0.08)",
168
162
  };
169
163
  const modalHeaderStyle = {
170
164
  display: "flex",
171
165
  justifyContent: "space-between",
172
166
  alignItems: "center",
173
167
  padding: "16px 20px",
174
- borderBottom: "1px solid rgba(255,255,255,0.06)",
168
+ borderBottom: "1px solid rgba(123,47,255,0.08)",
169
+ background: "rgba(255,255,255,0.7)",
175
170
  };
176
171
  const closeButtonStyle = {
177
172
  background: "none",
178
173
  border: "none",
179
- color: "rgba(255,255,255,0.4)",
180
- fontSize: "16px",
174
+ color: "rgba(80,40,140,0.4)",
175
+ fontSize: "15px",
181
176
  cursor: "pointer",
182
177
  padding: "4px 8px",
183
178
  borderRadius: "6px",
179
+ lineHeight: 1,
184
180
  };
185
181
  const modalBodyStyle = {
186
- padding: "24px 20px",
187
- minHeight: "200px",
182
+ padding: "28px 24px",
183
+ minHeight: "220px",
188
184
  };
189
185
  const modalFooterStyle = {
190
186
  padding: "12px 20px",
191
- borderTop: "1px solid rgba(255,255,255,0.04)",
187
+ borderTop: "1px solid rgba(123,47,255,0.06)",
192
188
  textAlign: "center",
189
+ background: "rgba(255,255,255,0.5)",
193
190
  };
194
191
  const stepContainerStyle = {
195
192
  display: "flex",
196
193
  flexDirection: "column",
197
194
  alignItems: "center",
198
- gap: "12px",
195
+ gap: "14px",
199
196
  };
200
197
  const stepTextBase = {
201
198
  fontSize: "16px",
202
- fontWeight: 600,
203
- color: "#fff",
199
+ fontWeight: 700,
200
+ color: "#1a0a3d",
204
201
  margin: 0,
202
+ textAlign: "center",
205
203
  };
206
204
  const hintStyle = {
207
205
  fontSize: "13px",
208
- color: "rgba(255,255,255,0.35)",
206
+ color: "#6b7280",
209
207
  textAlign: "center",
210
208
  lineHeight: 1.6,
211
209
  margin: 0,
212
- maxWidth: "280px",
210
+ maxWidth: "300px",
213
211
  };
214
212
  const spinnerStyle = {
215
213
  width: "32px",
216
214
  height: "32px",
217
- border: "3px solid rgba(255,255,255,0.1)",
215
+ border: "3px solid rgba(123,47,255,0.12)",
218
216
  borderTopColor: "#7b2fff",
219
217
  borderRadius: "50%",
220
218
  animation: "unseen-spin 0.8s linear infinite",
221
219
  };
222
- const walletButtonStyle = {
220
+ // Wallet picker — horizontal row
221
+ const walletRowStyle = {
222
+ display: "flex",
223
+ flexDirection: "row",
224
+ justifyContent: "center",
225
+ gap: "14px",
226
+ width: "100%",
227
+ marginTop: "6px",
228
+ };
229
+ const walletCardStyle = {
223
230
  display: "flex",
231
+ flexDirection: "column",
224
232
  alignItems: "center",
225
- gap: "12px",
226
- padding: "14px 16px",
227
- background: "rgba(255,255,255,0.04)",
228
- border: "1px solid rgba(255,255,255,0.06)",
229
- borderRadius: "12px",
233
+ gap: "8px",
234
+ padding: "16px 20px",
235
+ background: "rgba(123,47,255,0.04)",
236
+ border: "1px solid rgba(123,47,255,0.12)",
237
+ borderRadius: "14px",
230
238
  cursor: "pointer",
231
239
  transition: "all 0.15s ease",
232
- width: "100%",
233
- textAlign: "left",
234
- fontSize: "15px",
235
- color: "#fff",
236
240
  fontFamily: "inherit",
241
+ flex: "1 1 0",
242
+ maxWidth: "110px",
237
243
  };
238
- const walletIconStyle = {
239
- width: "32px",
240
- height: "32px",
241
- borderRadius: "8px",
244
+ const walletIconContainerStyle = {
245
+ width: "52px",
246
+ height: "52px",
247
+ borderRadius: "12px",
242
248
  overflow: "hidden",
243
249
  flexShrink: 0,
244
250
  };
@@ -248,13 +254,40 @@ const walletLogoImageStyle = {
248
254
  objectFit: "cover",
249
255
  display: "block",
250
256
  };
257
+ const walletNameStyle = {
258
+ fontSize: "11px",
259
+ fontWeight: 600,
260
+ color: "#4b207a",
261
+ letterSpacing: "0.02em",
262
+ };
263
+ // QR display
264
+ const qrWrapperStyle = {
265
+ padding: "10px",
266
+ background: "#ffffff",
267
+ borderRadius: "14px",
268
+ border: "1px solid rgba(123,47,255,0.1)",
269
+ boxShadow: "0 2px 12px rgba(100,40,220,0.08)",
270
+ };
271
+ const deepLinkButtonStyle = {
272
+ background: "none",
273
+ border: "1px solid rgba(123,47,255,0.2)",
274
+ borderRadius: "8px",
275
+ color: "#7b2fff",
276
+ fontSize: "13px",
277
+ fontWeight: 500,
278
+ cursor: "pointer",
279
+ padding: "8px 16px",
280
+ fontFamily: "inherit",
281
+ transition: "all 0.15s ease",
282
+ };
251
283
  const walletBadgeStyle = {
252
- display: "flex",
284
+ display: "inline-flex",
253
285
  alignItems: "center",
254
- gap: "8px",
255
- background: "rgba(255,255,255,0.04)",
256
- borderRadius: "10px",
257
- padding: "8px 14px",
286
+ gap: "6px",
287
+ background: "rgba(123,47,255,0.07)",
288
+ border: "1px solid rgba(123,47,255,0.15)",
289
+ borderRadius: "20px",
290
+ padding: "5px 12px",
258
291
  };
259
292
  const confirmButtonStyle = {
260
293
  width: "100%",
@@ -267,13 +300,14 @@ const confirmButtonStyle = {
267
300
  fontWeight: 600,
268
301
  cursor: "pointer",
269
302
  fontFamily: "inherit",
270
- marginTop: "8px",
303
+ marginTop: "4px",
304
+ boxShadow: "0 4px 16px rgba(123,47,255,0.3)",
271
305
  };
272
306
  const linkButtonStyle = {
273
307
  background: "none",
274
308
  border: "none",
275
- color: "rgba(255,255,255,0.35)",
276
- fontSize: "13px",
309
+ color: "#9ca3af",
310
+ fontSize: "12px",
277
311
  cursor: "pointer",
278
312
  padding: "4px",
279
313
  fontFamily: "inherit",
@@ -281,10 +315,10 @@ const linkButtonStyle = {
281
315
  };
282
316
  const inlineErrorStyle = {
283
317
  fontSize: "13px",
284
- color: "#ef4444",
318
+ color: "#dc2626",
285
319
  textAlign: "center",
286
- background: "rgba(239,68,68,0.08)",
287
- border: "1px solid rgba(239,68,68,0.15)",
320
+ background: "rgba(220,38,38,0.05)",
321
+ border: "1px solid rgba(220,38,38,0.15)",
288
322
  borderRadius: "8px",
289
323
  padding: "8px 12px",
290
324
  width: "100%",
@@ -293,14 +327,14 @@ const successCircle = {
293
327
  width: "56px",
294
328
  height: "56px",
295
329
  borderRadius: "50%",
296
- background: "rgba(34,197,94,0.1)",
297
- border: "1px solid rgba(34,197,94,0.2)",
330
+ background: "rgba(22,163,74,0.08)",
331
+ border: "1px solid rgba(22,163,74,0.2)",
298
332
  display: "flex",
299
333
  alignItems: "center",
300
334
  justifyContent: "center",
301
335
  };
302
336
  const errorCircle = {
303
337
  ...successCircle,
304
- background: "rgba(239,68,68,0.1)",
305
- border: "1px solid rgba(239,68,68,0.2)",
338
+ background: "rgba(220,38,38,0.08)",
339
+ border: "1px solid rgba(220,38,38,0.2)",
306
340
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unseen_fi/ui",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "React components for Unseen Pay — wallet picker modal, QR checkout, and payment button",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",