@seedhape/react 0.1.0

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.cjs ADDED
@@ -0,0 +1,412 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ PaymentButton: () => PaymentButton,
24
+ PaymentModal: () => PaymentModal,
25
+ SeedhaPeProvider: () => SeedhaPeProvider,
26
+ usePayment: () => usePayment,
27
+ useSeedhaPe: () => useSeedhaPe
28
+ });
29
+ module.exports = __toCommonJS(index_exports);
30
+
31
+ // src/provider.tsx
32
+ var import_react = require("react");
33
+ var import_sdk = require("@seedhape/sdk");
34
+ var import_jsx_runtime = require("react/jsx-runtime");
35
+ var SeedhaPeContext = (0, import_react.createContext)(null);
36
+ function SeedhaPeProvider({
37
+ apiKey,
38
+ baseUrl,
39
+ children
40
+ }) {
41
+ const client = (0, import_react.useMemo)(() => {
42
+ const config = { apiKey };
43
+ if (baseUrl) config.baseUrl = baseUrl;
44
+ return new import_sdk.SeedhaPe(config);
45
+ }, [apiKey, baseUrl]);
46
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SeedhaPeContext.Provider, { value: { client }, children });
47
+ }
48
+ function useSeedhaPe() {
49
+ const ctx = (0, import_react.useContext)(SeedhaPeContext);
50
+ if (!ctx) throw new Error("useSeedhaPe must be used inside <SeedhaPeProvider>");
51
+ return ctx.client;
52
+ }
53
+
54
+ // src/PaymentButton.tsx
55
+ var import_react3 = require("react");
56
+
57
+ // src/PaymentModal.tsx
58
+ var import_react2 = require("react");
59
+ var import_jsx_runtime2 = require("react/jsx-runtime");
60
+ var API_URL = typeof __SEEDHAPE_API_URL__ !== "undefined" ? __SEEDHAPE_API_URL__ : "https://api.seedhape.com";
61
+ var TERMINAL = ["VERIFIED", "RESOLVED", "EXPIRED", "REJECTED"];
62
+ var baseStyles = {
63
+ overlay: {
64
+ position: "fixed",
65
+ inset: 0,
66
+ background: "rgba(0,0,0,0.5)",
67
+ display: "flex",
68
+ alignItems: "center",
69
+ justifyContent: "center",
70
+ zIndex: 99999,
71
+ fontFamily: "system-ui, sans-serif"
72
+ },
73
+ card: {
74
+ background: "white",
75
+ borderRadius: 16,
76
+ padding: 28,
77
+ width: 360,
78
+ maxWidth: "calc(100vw - 32px)",
79
+ textAlign: "center",
80
+ boxShadow: "0 25px 50px rgba(0,0,0,0.2)"
81
+ },
82
+ amountBox: {
83
+ background: "#f0fdf4",
84
+ borderRadius: 12,
85
+ padding: "12px 16px",
86
+ marginBottom: 20
87
+ },
88
+ amountLabel: { fontSize: 12, color: "#15803d", marginBottom: 2 },
89
+ amount: { fontSize: 28, fontWeight: 700, color: "#14532d", margin: 0 },
90
+ input: {
91
+ width: "100%",
92
+ border: "1.5px solid #d1d5db",
93
+ borderRadius: 10,
94
+ padding: "10px 12px",
95
+ fontSize: 14,
96
+ boxSizing: "border-box",
97
+ outline: "none",
98
+ marginBottom: 8
99
+ },
100
+ inputError: { borderColor: "#f87171" },
101
+ btnPrimary: {
102
+ width: "100%",
103
+ background: "#16a34a",
104
+ color: "white",
105
+ border: "none",
106
+ borderRadius: 12,
107
+ padding: "12px 0",
108
+ fontSize: 15,
109
+ fontWeight: 600,
110
+ cursor: "pointer",
111
+ display: "flex",
112
+ alignItems: "center",
113
+ justifyContent: "center",
114
+ gap: 8
115
+ },
116
+ btnDisabled: { opacity: 0.5, cursor: "not-allowed" },
117
+ closeBtn: {
118
+ marginTop: 14,
119
+ background: "none",
120
+ border: "none",
121
+ color: "#9ca3af",
122
+ fontSize: 13,
123
+ cursor: "pointer"
124
+ },
125
+ hint: { fontSize: 12, color: "#6b7280", lineHeight: 1.5, marginBottom: 12, textAlign: "left" },
126
+ errorText: { fontSize: 12, color: "#ef4444", marginBottom: 8, textAlign: "left" },
127
+ stepDots: { display: "flex", justifyContent: "center", gap: 6, marginTop: 14 },
128
+ dot: (active) => ({
129
+ width: 24,
130
+ height: 6,
131
+ borderRadius: 3,
132
+ background: active ? "#16a34a" : "#e5e7eb"
133
+ })
134
+ };
135
+ function PaymentModal({ orderId, open, onClose, onSuccess, onExpired }) {
136
+ const [order, setOrder] = (0, import_react2.useState)(null);
137
+ const [nameInput, setNameInput] = (0, import_react2.useState)("");
138
+ const [nameError, setNameError] = (0, import_react2.useState)(null);
139
+ const [savingName, setSavingName] = (0, import_react2.useState)(false);
140
+ const [nameConfirmed, setNameConfirmed] = (0, import_react2.useState)(false);
141
+ const pollRef = (0, import_react2.useRef)(null);
142
+ (0, import_react2.useEffect)(() => {
143
+ if (!open || !orderId) return;
144
+ setOrder(null);
145
+ setNameInput("");
146
+ setNameError(null);
147
+ setNameConfirmed(false);
148
+ fetchOrder();
149
+ return () => {
150
+ if (pollRef.current) clearInterval(pollRef.current);
151
+ };
152
+ }, [open, orderId]);
153
+ async function fetchOrder() {
154
+ const res = await fetch(`${API_URL}/v1/pay/${orderId}`);
155
+ if (!res.ok) return;
156
+ const data = await res.json();
157
+ setOrder(data);
158
+ if (data.expectedSenderName) {
159
+ setNameInput(data.expectedSenderName);
160
+ setNameConfirmed(true);
161
+ }
162
+ if (!TERMINAL.includes(data.status)) startPolling();
163
+ }
164
+ function startPolling() {
165
+ pollRef.current = setInterval(async () => {
166
+ const res = await fetch(`${API_URL}/v1/pay/${orderId}`);
167
+ if (!res.ok) return;
168
+ const data = await res.json();
169
+ setOrder(data);
170
+ if (TERMINAL.includes(data.status)) {
171
+ if (pollRef.current) clearInterval(pollRef.current);
172
+ handleTerminal(data);
173
+ }
174
+ }, 3e3);
175
+ }
176
+ function handleTerminal(data) {
177
+ if (data.status === "VERIFIED" || data.status === "RESOLVED") {
178
+ onSuccess?.({ orderId: data.id, status: data.status, amount: data.amount });
179
+ } else if (data.status === "EXPIRED") {
180
+ onExpired?.(data.id);
181
+ }
182
+ }
183
+ async function confirmName() {
184
+ const name = nameInput.trim();
185
+ if (name.length < 2) {
186
+ setNameError("Enter at least 2 characters.");
187
+ return;
188
+ }
189
+ setSavingName(true);
190
+ setNameError(null);
191
+ try {
192
+ const res = await fetch(`${API_URL}/v1/pay/${orderId}/expectation`, {
193
+ method: "POST",
194
+ headers: { "Content-Type": "application/json" },
195
+ body: JSON.stringify({ expectedSenderName: name })
196
+ });
197
+ if (!res.ok) throw new Error("Failed");
198
+ setNameConfirmed(true);
199
+ } catch {
200
+ setNameError("Could not save name. Please try again.");
201
+ } finally {
202
+ setSavingName(false);
203
+ }
204
+ }
205
+ if (!open) return null;
206
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: baseStyles.overlay, onClick: (e) => e.target === e.currentTarget && onClose(), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: baseStyles.card, children: [
207
+ !order ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { color: "#9ca3af" }, children: "Loading\u2026" }) : order.status === "VERIFIED" || order.status === "RESOLVED" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
208
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 48, marginBottom: 8 }, children: "\u2705" }),
209
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontWeight: 700, fontSize: 18, color: "#16a34a", margin: "0 0 4px" }, children: "Payment Verified!" }),
210
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { style: { fontSize: 26, fontWeight: 700, color: "#111", margin: 0 }, children: [
211
+ "\u20B9",
212
+ (order.amount / 100).toFixed(2)
213
+ ] })
214
+ ] }) : order.status === "EXPIRED" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
215
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontSize: 48, marginBottom: 8 }, children: "\u23F0" }),
216
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontWeight: 600, fontSize: 18, color: "#dc2626" }, children: "Link Expired" })
217
+ ] }) : !nameConfirmed ? (
218
+ /* ── Step 1: Name gate ── */
219
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
220
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: baseStyles.amountBox, children: [
221
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: baseStyles.amountLabel, children: "Amount" }),
222
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { style: baseStyles.amount, children: [
223
+ "\u20B9",
224
+ (order.amount / 100).toFixed(2)
225
+ ] })
226
+ ] }),
227
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontWeight: 700, fontSize: 15, textAlign: "left", marginBottom: 6 }, children: "Enter your name" }),
228
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: baseStyles.hint, children: "Enter your name exactly as shown in your UPI app. This is used to instantly match your payment." }),
229
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
230
+ "input",
231
+ {
232
+ style: { ...baseStyles.input, ...nameError ? baseStyles.inputError : {} },
233
+ value: nameInput,
234
+ onChange: (e) => {
235
+ setNameInput(e.target.value);
236
+ setNameError(null);
237
+ },
238
+ onKeyDown: (e) => e.key === "Enter" && confirmName(),
239
+ placeholder: "e.g. Rahul Sharma",
240
+ autoFocus: true
241
+ }
242
+ ),
243
+ nameError && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: baseStyles.errorText, children: nameError }),
244
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
245
+ "button",
246
+ {
247
+ style: { ...baseStyles.btnPrimary, ...savingName || nameInput.trim().length < 2 ? baseStyles.btnDisabled : {} },
248
+ onClick: confirmName,
249
+ disabled: savingName || nameInput.trim().length < 2,
250
+ children: savingName ? "Saving\u2026" : "Continue \u2192"
251
+ }
252
+ ),
253
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: baseStyles.stepDots, children: [
254
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: baseStyles.dot(true) }),
255
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: baseStyles.dot(false) })
256
+ ] })
257
+ ] })
258
+ ) : (
259
+ /* ── Step 2: QR + Pay ── */
260
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
261
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: baseStyles.amountBox, children: [
262
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: baseStyles.amountLabel, children: "Amount" }),
263
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { style: baseStyles.amount, children: [
264
+ "\u20B9",
265
+ (order.amount / 100).toFixed(2)
266
+ ] })
267
+ ] }),
268
+ order.description && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontSize: 14, color: "#4b5563", marginBottom: 12 }, children: order.description }),
269
+ order.qrCode && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("img", { src: order.qrCode, width: 200, height: 200, style: { borderRadius: 8, marginBottom: 14 }, alt: "UPI QR" }),
270
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
271
+ "a",
272
+ {
273
+ href: order.upiUri,
274
+ style: {
275
+ display: "flex",
276
+ alignItems: "center",
277
+ justifyContent: "center",
278
+ gap: 8,
279
+ background: "#16a34a",
280
+ color: "white",
281
+ padding: "12px 0",
282
+ borderRadius: 12,
283
+ textDecoration: "none",
284
+ fontWeight: 600,
285
+ fontSize: 15,
286
+ marginBottom: 10
287
+ },
288
+ children: "Open UPI App"
289
+ }
290
+ ),
291
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { style: { fontSize: 12, color: "#9ca3af", marginBottom: 2 }, children: "\u23F3 Waiting for payment\u2026" }),
292
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: baseStyles.stepDots, children: [
293
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: baseStyles.dot(false) }),
294
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: baseStyles.dot(true) })
295
+ ] })
296
+ ] })
297
+ ),
298
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { style: baseStyles.closeBtn, onClick: onClose, children: "Close" })
299
+ ] }) });
300
+ }
301
+
302
+ // src/PaymentButton.tsx
303
+ var import_jsx_runtime3 = require("react/jsx-runtime");
304
+ function PaymentButton({
305
+ amount,
306
+ description,
307
+ customerEmail,
308
+ customerPhone,
309
+ expectedSenderName,
310
+ metadata,
311
+ onSuccess,
312
+ onExpired,
313
+ className = "",
314
+ children = "Pay Now"
315
+ }) {
316
+ const client = useSeedhaPe();
317
+ const [orderId, setOrderId] = (0, import_react3.useState)(null);
318
+ const [loading, setLoading] = (0, import_react3.useState)(false);
319
+ async function handleClick() {
320
+ setLoading(true);
321
+ try {
322
+ const opts = { amount };
323
+ if (description) opts.description = description;
324
+ if (customerEmail) opts.customerEmail = customerEmail;
325
+ if (customerPhone) opts.customerPhone = customerPhone;
326
+ if (expectedSenderName) opts.expectedSenderName = expectedSenderName;
327
+ if (metadata) opts.metadata = metadata;
328
+ const order = await client.createOrder(opts);
329
+ setOrderId(order.id);
330
+ } catch (err) {
331
+ console.error("[SeedhaPe] Failed to create order:", err);
332
+ } finally {
333
+ setLoading(false);
334
+ }
335
+ }
336
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
337
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
338
+ "button",
339
+ {
340
+ onClick: handleClick,
341
+ disabled: loading,
342
+ className: className || "sp-pay-btn",
343
+ style: !className ? {
344
+ background: "#16a34a",
345
+ color: "white",
346
+ border: "none",
347
+ padding: "12px 24px",
348
+ borderRadius: "10px",
349
+ fontWeight: 600,
350
+ fontSize: "15px",
351
+ cursor: loading ? "not-allowed" : "pointer",
352
+ opacity: loading ? 0.7 : 1
353
+ } : void 0,
354
+ children: loading ? "Loading..." : children
355
+ }
356
+ ),
357
+ orderId && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
358
+ PaymentModal,
359
+ {
360
+ orderId,
361
+ open: true,
362
+ onClose: () => setOrderId(null),
363
+ onSuccess: (result) => {
364
+ setOrderId(null);
365
+ onSuccess?.(result);
366
+ },
367
+ onExpired: (id) => {
368
+ setOrderId(null);
369
+ onExpired?.(id);
370
+ }
371
+ }
372
+ )
373
+ ] });
374
+ }
375
+
376
+ // src/usePayment.ts
377
+ var import_react4 = require("react");
378
+ function usePayment() {
379
+ const client = useSeedhaPe();
380
+ const [state, setState] = (0, import_react4.useState)({ phase: "idle" });
381
+ const createPayment = (0, import_react4.useCallback)(
382
+ async (options) => {
383
+ setState({ phase: "creating" });
384
+ try {
385
+ const order = await client.createOrder(options);
386
+ setState({ phase: "pending", order });
387
+ return order;
388
+ } catch (err) {
389
+ setState({ phase: "error", error: String(err) });
390
+ throw err;
391
+ }
392
+ },
393
+ [client]
394
+ );
395
+ const onSuccess = (0, import_react4.useCallback)((result) => {
396
+ setState({ phase: "verified", result });
397
+ }, []);
398
+ const onExpired = (0, import_react4.useCallback)((orderId) => {
399
+ setState({ phase: "expired", orderId });
400
+ }, []);
401
+ const reset = (0, import_react4.useCallback)(() => setState({ phase: "idle" }), []);
402
+ return { state, createPayment, onSuccess, onExpired, reset };
403
+ }
404
+ // Annotate the CommonJS export names for ESM import in node:
405
+ 0 && (module.exports = {
406
+ PaymentButton,
407
+ PaymentModal,
408
+ SeedhaPeProvider,
409
+ usePayment,
410
+ useSeedhaPe
411
+ });
412
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/PaymentButton.tsx","../src/PaymentModal.tsx","../src/usePayment.ts"],"sourcesContent":["export { SeedhaPeProvider, useSeedhaPe } from './provider.js';\nexport { PaymentButton } from './PaymentButton.js';\nexport { PaymentModal } from './PaymentModal.js';\nexport { usePayment } from './usePayment.js';\nexport type { PaymentButtonProps, PaymentModalProps } from './types.js';\n","import React, { createContext, useContext, useMemo } from 'react';\nimport { SeedhaPe } from '@seedhape/sdk';\n\ninterface SeedhaPeContextValue {\n client: SeedhaPe;\n}\n\nconst SeedhaPeContext = createContext<SeedhaPeContextValue | null>(null);\n\nexport function SeedhaPeProvider({\n apiKey,\n baseUrl,\n children,\n}: {\n apiKey: string;\n baseUrl?: string;\n children: React.ReactNode;\n}) {\n const client = useMemo(() => {\n const config: import('@seedhape/sdk').SeedhaPeConfig = { apiKey };\n if (baseUrl) config.baseUrl = baseUrl;\n return new SeedhaPe(config);\n }, [apiKey, baseUrl]);\n\n return (\n <SeedhaPeContext.Provider value={{ client }}>\n {children}\n </SeedhaPeContext.Provider>\n );\n}\n\nexport function useSeedhaPe(): SeedhaPe {\n const ctx = useContext(SeedhaPeContext);\n if (!ctx) throw new Error('useSeedhaPe must be used inside <SeedhaPeProvider>');\n return ctx.client;\n}\n","import React, { useState } from 'react';\nimport type { PaymentButtonProps } from './types.js';\nimport { PaymentModal } from './PaymentModal.js';\nimport { useSeedhaPe } from './provider.js';\n\nexport function PaymentButton({\n amount,\n description,\n customerEmail,\n customerPhone,\n expectedSenderName,\n metadata,\n onSuccess,\n onExpired,\n className = '',\n children = 'Pay Now',\n}: PaymentButtonProps) {\n const client = useSeedhaPe();\n const [orderId, setOrderId] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n\n async function handleClick() {\n setLoading(true);\n try {\n const opts: import('@seedhape/sdk').CreateOrderOptions = { amount };\n if (description) opts.description = description;\n if (customerEmail) opts.customerEmail = customerEmail;\n if (customerPhone) opts.customerPhone = customerPhone;\n if (expectedSenderName) opts.expectedSenderName = expectedSenderName;\n if (metadata) opts.metadata = metadata;\n const order = await client.createOrder(opts);\n setOrderId(order.id);\n } catch (err) {\n console.error('[SeedhaPe] Failed to create order:', err);\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <>\n <button\n onClick={handleClick}\n disabled={loading}\n className={className || 'sp-pay-btn'}\n style={\n !className\n ? {\n background: '#16a34a',\n color: 'white',\n border: 'none',\n padding: '12px 24px',\n borderRadius: '10px',\n fontWeight: 600,\n fontSize: '15px',\n cursor: loading ? 'not-allowed' : 'pointer',\n opacity: loading ? 0.7 : 1,\n }\n : undefined\n }\n >\n {loading ? 'Loading...' : children}\n </button>\n\n {orderId && (\n <PaymentModal\n orderId={orderId}\n open={true}\n onClose={() => setOrderId(null)}\n onSuccess={(result) => {\n setOrderId(null);\n onSuccess?.(result);\n }}\n onExpired={(id) => {\n setOrderId(null);\n onExpired?.(id);\n }}\n />\n )}\n </>\n );\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport type { PaymentModalProps } from './types.js';\n\n// API URL can be set via __SEEDHAPE_API_URL__ global, or defaults to production\ndeclare const __SEEDHAPE_API_URL__: string | undefined;\nconst API_URL: string =\n typeof __SEEDHAPE_API_URL__ !== 'undefined'\n ? __SEEDHAPE_API_URL__\n : 'https://api.seedhape.com';\n\ntype OrderData = {\n id: string;\n amount: number;\n description: string | null;\n status: string;\n upiUri: string;\n qrCode: string;\n expiresAt: string;\n expectedSenderName: string | null;\n};\n\nconst TERMINAL = ['VERIFIED', 'RESOLVED', 'EXPIRED', 'REJECTED'];\n\nconst baseStyles = {\n overlay: {\n position: 'fixed' as const, inset: 0,\n background: 'rgba(0,0,0,0.5)',\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n zIndex: 99999, fontFamily: 'system-ui, sans-serif',\n },\n card: {\n background: 'white', borderRadius: 16, padding: 28,\n width: 360, maxWidth: 'calc(100vw - 32px)', textAlign: 'center' as const,\n boxShadow: '0 25px 50px rgba(0,0,0,0.2)',\n },\n amountBox: {\n background: '#f0fdf4', borderRadius: 12, padding: '12px 16px',\n marginBottom: 20,\n },\n amountLabel: { fontSize: 12, color: '#15803d', marginBottom: 2 },\n amount: { fontSize: 28, fontWeight: 700, color: '#14532d', margin: 0 },\n input: {\n width: '100%', border: '1.5px solid #d1d5db', borderRadius: 10,\n padding: '10px 12px', fontSize: 14, boxSizing: 'border-box' as const,\n outline: 'none', marginBottom: 8,\n },\n inputError: { borderColor: '#f87171' },\n btnPrimary: {\n width: '100%', background: '#16a34a', color: 'white', border: 'none',\n borderRadius: 12, padding: '12px 0', fontSize: 15, fontWeight: 600,\n cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,\n },\n btnDisabled: { opacity: 0.5, cursor: 'not-allowed' as const },\n closeBtn: {\n marginTop: 14, background: 'none', border: 'none',\n color: '#9ca3af', fontSize: 13, cursor: 'pointer',\n },\n hint: { fontSize: 12, color: '#6b7280', lineHeight: 1.5, marginBottom: 12, textAlign: 'left' as const },\n errorText: { fontSize: 12, color: '#ef4444', marginBottom: 8, textAlign: 'left' as const },\n stepDots: { display: 'flex', justifyContent: 'center', gap: 6, marginTop: 14 },\n dot: (active: boolean) => ({\n width: 24, height: 6, borderRadius: 3,\n background: active ? '#16a34a' : '#e5e7eb',\n }),\n};\n\nexport function PaymentModal({ orderId, open, onClose, onSuccess, onExpired }: PaymentModalProps) {\n const [order, setOrder] = useState<OrderData | null>(null);\n const [nameInput, setNameInput] = useState('');\n const [nameError, setNameError] = useState<string | null>(null);\n const [savingName, setSavingName] = useState(false);\n const [nameConfirmed, setNameConfirmed] = useState(false);\n const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n useEffect(() => {\n if (!open || !orderId) return;\n setOrder(null);\n setNameInput('');\n setNameError(null);\n setNameConfirmed(false);\n fetchOrder();\n return () => { if (pollRef.current) clearInterval(pollRef.current); };\n }, [open, orderId]);\n\n async function fetchOrder() {\n const res = await fetch(`${API_URL}/v1/pay/${orderId}`);\n if (!res.ok) return;\n const data = await res.json() as OrderData;\n setOrder(data);\n // Skip name gate if the merchant already supplied it at order creation time\n if (data.expectedSenderName) {\n setNameInput(data.expectedSenderName);\n setNameConfirmed(true);\n }\n if (!TERMINAL.includes(data.status)) startPolling();\n }\n\n function startPolling() {\n pollRef.current = setInterval(async () => {\n const res = await fetch(`${API_URL}/v1/pay/${orderId}`);\n if (!res.ok) return;\n const data = await res.json() as OrderData;\n setOrder(data);\n if (TERMINAL.includes(data.status)) {\n if (pollRef.current) clearInterval(pollRef.current);\n handleTerminal(data);\n }\n }, 3000);\n }\n\n function handleTerminal(data: OrderData) {\n if (data.status === 'VERIFIED' || data.status === 'RESOLVED') {\n onSuccess?.({ orderId: data.id, status: data.status as 'VERIFIED', amount: data.amount });\n } else if (data.status === 'EXPIRED') {\n onExpired?.(data.id);\n }\n }\n\n async function confirmName() {\n const name = nameInput.trim();\n if (name.length < 2) { setNameError('Enter at least 2 characters.'); return; }\n setSavingName(true);\n setNameError(null);\n try {\n const res = await fetch(`${API_URL}/v1/pay/${orderId}/expectation`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ expectedSenderName: name }),\n });\n if (!res.ok) throw new Error('Failed');\n setNameConfirmed(true);\n } catch {\n setNameError('Could not save name. Please try again.');\n } finally {\n setSavingName(false);\n }\n }\n\n if (!open) return null;\n\n return (\n <div style={baseStyles.overlay} onClick={(e) => e.target === e.currentTarget && onClose()}>\n <div style={baseStyles.card}>\n {!order ? (\n <p style={{ color: '#9ca3af' }}>Loading…</p>\n ) : (order.status === 'VERIFIED' || order.status === 'RESOLVED') ? (\n <>\n <div style={{ fontSize: 48, marginBottom: 8 }}>✅</div>\n <p style={{ fontWeight: 700, fontSize: 18, color: '#16a34a', margin: '0 0 4px' }}>Payment Verified!</p>\n <p style={{ fontSize: 26, fontWeight: 700, color: '#111', margin: 0 }}>\n ₹{(order.amount / 100).toFixed(2)}\n </p>\n </>\n ) : order.status === 'EXPIRED' ? (\n <>\n <div style={{ fontSize: 48, marginBottom: 8 }}>⏰</div>\n <p style={{ fontWeight: 600, fontSize: 18, color: '#dc2626' }}>Link Expired</p>\n </>\n ) : !nameConfirmed ? (\n /* ── Step 1: Name gate ── */\n <>\n <div style={baseStyles.amountBox}>\n <p style={baseStyles.amountLabel}>Amount</p>\n <p style={baseStyles.amount}>₹{(order.amount / 100).toFixed(2)}</p>\n </div>\n <p style={{ fontWeight: 700, fontSize: 15, textAlign: 'left', marginBottom: 6 }}>Enter your name</p>\n <p style={baseStyles.hint}>\n Enter your name exactly as shown in your UPI app. This is used to instantly match your payment.\n </p>\n <input\n style={{ ...baseStyles.input, ...(nameError ? baseStyles.inputError : {}) }}\n value={nameInput}\n onChange={(e) => { setNameInput(e.target.value); setNameError(null); }}\n onKeyDown={(e) => e.key === 'Enter' && confirmName()}\n placeholder=\"e.g. Rahul Sharma\"\n autoFocus\n />\n {nameError && <p style={baseStyles.errorText}>{nameError}</p>}\n <button\n style={{ ...baseStyles.btnPrimary, ...(savingName || nameInput.trim().length < 2 ? baseStyles.btnDisabled : {}) }}\n onClick={confirmName}\n disabled={savingName || nameInput.trim().length < 2}\n >\n {savingName ? 'Saving…' : 'Continue →'}\n </button>\n <div style={baseStyles.stepDots}>\n <div style={baseStyles.dot(true)} />\n <div style={baseStyles.dot(false)} />\n </div>\n </>\n ) : (\n /* ── Step 2: QR + Pay ── */\n <>\n <div style={baseStyles.amountBox}>\n <p style={baseStyles.amountLabel}>Amount</p>\n <p style={baseStyles.amount}>₹{(order.amount / 100).toFixed(2)}</p>\n </div>\n {order.description && (\n <p style={{ fontSize: 14, color: '#4b5563', marginBottom: 12 }}>{order.description}</p>\n )}\n {order.qrCode && (\n <img src={order.qrCode} width={200} height={200} style={{ borderRadius: 8, marginBottom: 14 }} alt=\"UPI QR\" />\n )}\n <a\n href={order.upiUri}\n style={{\n display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,\n background: '#16a34a', color: 'white',\n padding: '12px 0', borderRadius: 12, textDecoration: 'none',\n fontWeight: 600, fontSize: 15, marginBottom: 10,\n }}\n >\n Open UPI App\n </a>\n <p style={{ fontSize: 12, color: '#9ca3af', marginBottom: 2 }}>⏳ Waiting for payment…</p>\n <div style={baseStyles.stepDots}>\n <div style={baseStyles.dot(false)} />\n <div style={baseStyles.dot(true)} />\n </div>\n </>\n )}\n\n <button style={baseStyles.closeBtn} onClick={onClose}>Close</button>\n </div>\n </div>\n );\n}\n","import { useState, useCallback } from 'react';\nimport type { OrderData, PaymentResult } from '@seedhape/sdk';\n\nimport { useSeedhaPe } from './provider.js';\n\ntype PaymentState =\n | { phase: 'idle' }\n | { phase: 'creating' }\n | { phase: 'pending'; order: OrderData }\n | { phase: 'verified'; result: PaymentResult }\n | { phase: 'expired'; orderId: string }\n | { phase: 'error'; error: string };\n\nexport function usePayment() {\n const client = useSeedhaPe();\n const [state, setState] = useState<PaymentState>({ phase: 'idle' });\n\n const createPayment = useCallback(\n async (options: {\n amount: number;\n description?: string;\n customerEmail?: string;\n customerPhone?: string;\n metadata?: Record<string, unknown>;\n }) => {\n setState({ phase: 'creating' });\n try {\n const order = await client.createOrder(options);\n setState({ phase: 'pending', order });\n return order;\n } catch (err) {\n setState({ phase: 'error', error: String(err) });\n throw err;\n }\n },\n [client],\n );\n\n const onSuccess = useCallback((result: PaymentResult) => {\n setState({ phase: 'verified', result });\n }, []);\n\n const onExpired = useCallback((orderId: string) => {\n setState({ phase: 'expired', orderId });\n }, []);\n\n const reset = useCallback(() => setState({ phase: 'idle' }), []);\n\n return { state, createPayment, onSuccess, onExpired, reset };\n}\n"],"mappings":"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","names":["import_react","import_react","import_jsx_runtime","import_jsx_runtime","import_react"]}
@@ -0,0 +1,72 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React$1 from 'react';
3
+ import { SeedhaPe, PaymentResult, OrderData } from '@seedhape/sdk';
4
+
5
+ declare function SeedhaPeProvider({ apiKey, baseUrl, children, }: {
6
+ apiKey: string;
7
+ baseUrl?: string;
8
+ children: React$1.ReactNode;
9
+ }): react_jsx_runtime.JSX.Element;
10
+ declare function useSeedhaPe(): SeedhaPe;
11
+
12
+ interface PaymentButtonProps {
13
+ amount: number;
14
+ description?: string;
15
+ customerEmail?: string;
16
+ customerPhone?: string;
17
+ /**
18
+ * The payer's name exactly as it appears in their UPI app.
19
+ * Strongly recommended — improves payment matching accuracy.
20
+ * When omitted the modal will prompt the user to enter it before showing the QR code.
21
+ */
22
+ expectedSenderName?: string;
23
+ metadata?: Record<string, unknown>;
24
+ onSuccess?: (result: PaymentResult) => void;
25
+ onExpired?: (orderId: string) => void;
26
+ className?: string;
27
+ children?: React.ReactNode;
28
+ }
29
+ interface PaymentModalProps {
30
+ orderId: string;
31
+ open: boolean;
32
+ onClose: () => void;
33
+ onSuccess?: (result: PaymentResult) => void;
34
+ onExpired?: (orderId: string) => void;
35
+ }
36
+
37
+ declare function PaymentButton({ amount, description, customerEmail, customerPhone, expectedSenderName, metadata, onSuccess, onExpired, className, children, }: PaymentButtonProps): react_jsx_runtime.JSX.Element;
38
+
39
+ declare function PaymentModal({ orderId, open, onClose, onSuccess, onExpired }: PaymentModalProps): react_jsx_runtime.JSX.Element | null;
40
+
41
+ type PaymentState = {
42
+ phase: 'idle';
43
+ } | {
44
+ phase: 'creating';
45
+ } | {
46
+ phase: 'pending';
47
+ order: OrderData;
48
+ } | {
49
+ phase: 'verified';
50
+ result: PaymentResult;
51
+ } | {
52
+ phase: 'expired';
53
+ orderId: string;
54
+ } | {
55
+ phase: 'error';
56
+ error: string;
57
+ };
58
+ declare function usePayment(): {
59
+ state: PaymentState;
60
+ createPayment: (options: {
61
+ amount: number;
62
+ description?: string;
63
+ customerEmail?: string;
64
+ customerPhone?: string;
65
+ metadata?: Record<string, unknown>;
66
+ }) => Promise<OrderData>;
67
+ onSuccess: (result: PaymentResult) => void;
68
+ onExpired: (orderId: string) => void;
69
+ reset: () => void;
70
+ };
71
+
72
+ export { PaymentButton, type PaymentButtonProps, PaymentModal, type PaymentModalProps, SeedhaPeProvider, usePayment, useSeedhaPe };
@@ -0,0 +1,72 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React$1 from 'react';
3
+ import { SeedhaPe, PaymentResult, OrderData } from '@seedhape/sdk';
4
+
5
+ declare function SeedhaPeProvider({ apiKey, baseUrl, children, }: {
6
+ apiKey: string;
7
+ baseUrl?: string;
8
+ children: React$1.ReactNode;
9
+ }): react_jsx_runtime.JSX.Element;
10
+ declare function useSeedhaPe(): SeedhaPe;
11
+
12
+ interface PaymentButtonProps {
13
+ amount: number;
14
+ description?: string;
15
+ customerEmail?: string;
16
+ customerPhone?: string;
17
+ /**
18
+ * The payer's name exactly as it appears in their UPI app.
19
+ * Strongly recommended — improves payment matching accuracy.
20
+ * When omitted the modal will prompt the user to enter it before showing the QR code.
21
+ */
22
+ expectedSenderName?: string;
23
+ metadata?: Record<string, unknown>;
24
+ onSuccess?: (result: PaymentResult) => void;
25
+ onExpired?: (orderId: string) => void;
26
+ className?: string;
27
+ children?: React.ReactNode;
28
+ }
29
+ interface PaymentModalProps {
30
+ orderId: string;
31
+ open: boolean;
32
+ onClose: () => void;
33
+ onSuccess?: (result: PaymentResult) => void;
34
+ onExpired?: (orderId: string) => void;
35
+ }
36
+
37
+ declare function PaymentButton({ amount, description, customerEmail, customerPhone, expectedSenderName, metadata, onSuccess, onExpired, className, children, }: PaymentButtonProps): react_jsx_runtime.JSX.Element;
38
+
39
+ declare function PaymentModal({ orderId, open, onClose, onSuccess, onExpired }: PaymentModalProps): react_jsx_runtime.JSX.Element | null;
40
+
41
+ type PaymentState = {
42
+ phase: 'idle';
43
+ } | {
44
+ phase: 'creating';
45
+ } | {
46
+ phase: 'pending';
47
+ order: OrderData;
48
+ } | {
49
+ phase: 'verified';
50
+ result: PaymentResult;
51
+ } | {
52
+ phase: 'expired';
53
+ orderId: string;
54
+ } | {
55
+ phase: 'error';
56
+ error: string;
57
+ };
58
+ declare function usePayment(): {
59
+ state: PaymentState;
60
+ createPayment: (options: {
61
+ amount: number;
62
+ description?: string;
63
+ customerEmail?: string;
64
+ customerPhone?: string;
65
+ metadata?: Record<string, unknown>;
66
+ }) => Promise<OrderData>;
67
+ onSuccess: (result: PaymentResult) => void;
68
+ onExpired: (orderId: string) => void;
69
+ reset: () => void;
70
+ };
71
+
72
+ export { PaymentButton, type PaymentButtonProps, PaymentModal, type PaymentModalProps, SeedhaPeProvider, usePayment, useSeedhaPe };
package/dist/index.mjs ADDED
@@ -0,0 +1,381 @@
1
+ // src/provider.tsx
2
+ import { createContext, useContext, useMemo } from "react";
3
+ import { SeedhaPe } from "@seedhape/sdk";
4
+ import { jsx } from "react/jsx-runtime";
5
+ var SeedhaPeContext = createContext(null);
6
+ function SeedhaPeProvider({
7
+ apiKey,
8
+ baseUrl,
9
+ children
10
+ }) {
11
+ const client = useMemo(() => {
12
+ const config = { apiKey };
13
+ if (baseUrl) config.baseUrl = baseUrl;
14
+ return new SeedhaPe(config);
15
+ }, [apiKey, baseUrl]);
16
+ return /* @__PURE__ */ jsx(SeedhaPeContext.Provider, { value: { client }, children });
17
+ }
18
+ function useSeedhaPe() {
19
+ const ctx = useContext(SeedhaPeContext);
20
+ if (!ctx) throw new Error("useSeedhaPe must be used inside <SeedhaPeProvider>");
21
+ return ctx.client;
22
+ }
23
+
24
+ // src/PaymentButton.tsx
25
+ import { useState as useState2 } from "react";
26
+
27
+ // src/PaymentModal.tsx
28
+ import { useEffect, useRef, useState } from "react";
29
+ import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
30
+ var API_URL = typeof __SEEDHAPE_API_URL__ !== "undefined" ? __SEEDHAPE_API_URL__ : "https://api.seedhape.com";
31
+ var TERMINAL = ["VERIFIED", "RESOLVED", "EXPIRED", "REJECTED"];
32
+ var baseStyles = {
33
+ overlay: {
34
+ position: "fixed",
35
+ inset: 0,
36
+ background: "rgba(0,0,0,0.5)",
37
+ display: "flex",
38
+ alignItems: "center",
39
+ justifyContent: "center",
40
+ zIndex: 99999,
41
+ fontFamily: "system-ui, sans-serif"
42
+ },
43
+ card: {
44
+ background: "white",
45
+ borderRadius: 16,
46
+ padding: 28,
47
+ width: 360,
48
+ maxWidth: "calc(100vw - 32px)",
49
+ textAlign: "center",
50
+ boxShadow: "0 25px 50px rgba(0,0,0,0.2)"
51
+ },
52
+ amountBox: {
53
+ background: "#f0fdf4",
54
+ borderRadius: 12,
55
+ padding: "12px 16px",
56
+ marginBottom: 20
57
+ },
58
+ amountLabel: { fontSize: 12, color: "#15803d", marginBottom: 2 },
59
+ amount: { fontSize: 28, fontWeight: 700, color: "#14532d", margin: 0 },
60
+ input: {
61
+ width: "100%",
62
+ border: "1.5px solid #d1d5db",
63
+ borderRadius: 10,
64
+ padding: "10px 12px",
65
+ fontSize: 14,
66
+ boxSizing: "border-box",
67
+ outline: "none",
68
+ marginBottom: 8
69
+ },
70
+ inputError: { borderColor: "#f87171" },
71
+ btnPrimary: {
72
+ width: "100%",
73
+ background: "#16a34a",
74
+ color: "white",
75
+ border: "none",
76
+ borderRadius: 12,
77
+ padding: "12px 0",
78
+ fontSize: 15,
79
+ fontWeight: 600,
80
+ cursor: "pointer",
81
+ display: "flex",
82
+ alignItems: "center",
83
+ justifyContent: "center",
84
+ gap: 8
85
+ },
86
+ btnDisabled: { opacity: 0.5, cursor: "not-allowed" },
87
+ closeBtn: {
88
+ marginTop: 14,
89
+ background: "none",
90
+ border: "none",
91
+ color: "#9ca3af",
92
+ fontSize: 13,
93
+ cursor: "pointer"
94
+ },
95
+ hint: { fontSize: 12, color: "#6b7280", lineHeight: 1.5, marginBottom: 12, textAlign: "left" },
96
+ errorText: { fontSize: 12, color: "#ef4444", marginBottom: 8, textAlign: "left" },
97
+ stepDots: { display: "flex", justifyContent: "center", gap: 6, marginTop: 14 },
98
+ dot: (active) => ({
99
+ width: 24,
100
+ height: 6,
101
+ borderRadius: 3,
102
+ background: active ? "#16a34a" : "#e5e7eb"
103
+ })
104
+ };
105
+ function PaymentModal({ orderId, open, onClose, onSuccess, onExpired }) {
106
+ const [order, setOrder] = useState(null);
107
+ const [nameInput, setNameInput] = useState("");
108
+ const [nameError, setNameError] = useState(null);
109
+ const [savingName, setSavingName] = useState(false);
110
+ const [nameConfirmed, setNameConfirmed] = useState(false);
111
+ const pollRef = useRef(null);
112
+ useEffect(() => {
113
+ if (!open || !orderId) return;
114
+ setOrder(null);
115
+ setNameInput("");
116
+ setNameError(null);
117
+ setNameConfirmed(false);
118
+ fetchOrder();
119
+ return () => {
120
+ if (pollRef.current) clearInterval(pollRef.current);
121
+ };
122
+ }, [open, orderId]);
123
+ async function fetchOrder() {
124
+ const res = await fetch(`${API_URL}/v1/pay/${orderId}`);
125
+ if (!res.ok) return;
126
+ const data = await res.json();
127
+ setOrder(data);
128
+ if (data.expectedSenderName) {
129
+ setNameInput(data.expectedSenderName);
130
+ setNameConfirmed(true);
131
+ }
132
+ if (!TERMINAL.includes(data.status)) startPolling();
133
+ }
134
+ function startPolling() {
135
+ pollRef.current = setInterval(async () => {
136
+ const res = await fetch(`${API_URL}/v1/pay/${orderId}`);
137
+ if (!res.ok) return;
138
+ const data = await res.json();
139
+ setOrder(data);
140
+ if (TERMINAL.includes(data.status)) {
141
+ if (pollRef.current) clearInterval(pollRef.current);
142
+ handleTerminal(data);
143
+ }
144
+ }, 3e3);
145
+ }
146
+ function handleTerminal(data) {
147
+ if (data.status === "VERIFIED" || data.status === "RESOLVED") {
148
+ onSuccess?.({ orderId: data.id, status: data.status, amount: data.amount });
149
+ } else if (data.status === "EXPIRED") {
150
+ onExpired?.(data.id);
151
+ }
152
+ }
153
+ async function confirmName() {
154
+ const name = nameInput.trim();
155
+ if (name.length < 2) {
156
+ setNameError("Enter at least 2 characters.");
157
+ return;
158
+ }
159
+ setSavingName(true);
160
+ setNameError(null);
161
+ try {
162
+ const res = await fetch(`${API_URL}/v1/pay/${orderId}/expectation`, {
163
+ method: "POST",
164
+ headers: { "Content-Type": "application/json" },
165
+ body: JSON.stringify({ expectedSenderName: name })
166
+ });
167
+ if (!res.ok) throw new Error("Failed");
168
+ setNameConfirmed(true);
169
+ } catch {
170
+ setNameError("Could not save name. Please try again.");
171
+ } finally {
172
+ setSavingName(false);
173
+ }
174
+ }
175
+ if (!open) return null;
176
+ return /* @__PURE__ */ jsx2("div", { style: baseStyles.overlay, onClick: (e) => e.target === e.currentTarget && onClose(), children: /* @__PURE__ */ jsxs("div", { style: baseStyles.card, children: [
177
+ !order ? /* @__PURE__ */ jsx2("p", { style: { color: "#9ca3af" }, children: "Loading\u2026" }) : order.status === "VERIFIED" || order.status === "RESOLVED" ? /* @__PURE__ */ jsxs(Fragment, { children: [
178
+ /* @__PURE__ */ jsx2("div", { style: { fontSize: 48, marginBottom: 8 }, children: "\u2705" }),
179
+ /* @__PURE__ */ jsx2("p", { style: { fontWeight: 700, fontSize: 18, color: "#16a34a", margin: "0 0 4px" }, children: "Payment Verified!" }),
180
+ /* @__PURE__ */ jsxs("p", { style: { fontSize: 26, fontWeight: 700, color: "#111", margin: 0 }, children: [
181
+ "\u20B9",
182
+ (order.amount / 100).toFixed(2)
183
+ ] })
184
+ ] }) : order.status === "EXPIRED" ? /* @__PURE__ */ jsxs(Fragment, { children: [
185
+ /* @__PURE__ */ jsx2("div", { style: { fontSize: 48, marginBottom: 8 }, children: "\u23F0" }),
186
+ /* @__PURE__ */ jsx2("p", { style: { fontWeight: 600, fontSize: 18, color: "#dc2626" }, children: "Link Expired" })
187
+ ] }) : !nameConfirmed ? (
188
+ /* ── Step 1: Name gate ── */
189
+ /* @__PURE__ */ jsxs(Fragment, { children: [
190
+ /* @__PURE__ */ jsxs("div", { style: baseStyles.amountBox, children: [
191
+ /* @__PURE__ */ jsx2("p", { style: baseStyles.amountLabel, children: "Amount" }),
192
+ /* @__PURE__ */ jsxs("p", { style: baseStyles.amount, children: [
193
+ "\u20B9",
194
+ (order.amount / 100).toFixed(2)
195
+ ] })
196
+ ] }),
197
+ /* @__PURE__ */ jsx2("p", { style: { fontWeight: 700, fontSize: 15, textAlign: "left", marginBottom: 6 }, children: "Enter your name" }),
198
+ /* @__PURE__ */ jsx2("p", { style: baseStyles.hint, children: "Enter your name exactly as shown in your UPI app. This is used to instantly match your payment." }),
199
+ /* @__PURE__ */ jsx2(
200
+ "input",
201
+ {
202
+ style: { ...baseStyles.input, ...nameError ? baseStyles.inputError : {} },
203
+ value: nameInput,
204
+ onChange: (e) => {
205
+ setNameInput(e.target.value);
206
+ setNameError(null);
207
+ },
208
+ onKeyDown: (e) => e.key === "Enter" && confirmName(),
209
+ placeholder: "e.g. Rahul Sharma",
210
+ autoFocus: true
211
+ }
212
+ ),
213
+ nameError && /* @__PURE__ */ jsx2("p", { style: baseStyles.errorText, children: nameError }),
214
+ /* @__PURE__ */ jsx2(
215
+ "button",
216
+ {
217
+ style: { ...baseStyles.btnPrimary, ...savingName || nameInput.trim().length < 2 ? baseStyles.btnDisabled : {} },
218
+ onClick: confirmName,
219
+ disabled: savingName || nameInput.trim().length < 2,
220
+ children: savingName ? "Saving\u2026" : "Continue \u2192"
221
+ }
222
+ ),
223
+ /* @__PURE__ */ jsxs("div", { style: baseStyles.stepDots, children: [
224
+ /* @__PURE__ */ jsx2("div", { style: baseStyles.dot(true) }),
225
+ /* @__PURE__ */ jsx2("div", { style: baseStyles.dot(false) })
226
+ ] })
227
+ ] })
228
+ ) : (
229
+ /* ── Step 2: QR + Pay ── */
230
+ /* @__PURE__ */ jsxs(Fragment, { children: [
231
+ /* @__PURE__ */ jsxs("div", { style: baseStyles.amountBox, children: [
232
+ /* @__PURE__ */ jsx2("p", { style: baseStyles.amountLabel, children: "Amount" }),
233
+ /* @__PURE__ */ jsxs("p", { style: baseStyles.amount, children: [
234
+ "\u20B9",
235
+ (order.amount / 100).toFixed(2)
236
+ ] })
237
+ ] }),
238
+ order.description && /* @__PURE__ */ jsx2("p", { style: { fontSize: 14, color: "#4b5563", marginBottom: 12 }, children: order.description }),
239
+ order.qrCode && /* @__PURE__ */ jsx2("img", { src: order.qrCode, width: 200, height: 200, style: { borderRadius: 8, marginBottom: 14 }, alt: "UPI QR" }),
240
+ /* @__PURE__ */ jsx2(
241
+ "a",
242
+ {
243
+ href: order.upiUri,
244
+ style: {
245
+ display: "flex",
246
+ alignItems: "center",
247
+ justifyContent: "center",
248
+ gap: 8,
249
+ background: "#16a34a",
250
+ color: "white",
251
+ padding: "12px 0",
252
+ borderRadius: 12,
253
+ textDecoration: "none",
254
+ fontWeight: 600,
255
+ fontSize: 15,
256
+ marginBottom: 10
257
+ },
258
+ children: "Open UPI App"
259
+ }
260
+ ),
261
+ /* @__PURE__ */ jsx2("p", { style: { fontSize: 12, color: "#9ca3af", marginBottom: 2 }, children: "\u23F3 Waiting for payment\u2026" }),
262
+ /* @__PURE__ */ jsxs("div", { style: baseStyles.stepDots, children: [
263
+ /* @__PURE__ */ jsx2("div", { style: baseStyles.dot(false) }),
264
+ /* @__PURE__ */ jsx2("div", { style: baseStyles.dot(true) })
265
+ ] })
266
+ ] })
267
+ ),
268
+ /* @__PURE__ */ jsx2("button", { style: baseStyles.closeBtn, onClick: onClose, children: "Close" })
269
+ ] }) });
270
+ }
271
+
272
+ // src/PaymentButton.tsx
273
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
274
+ function PaymentButton({
275
+ amount,
276
+ description,
277
+ customerEmail,
278
+ customerPhone,
279
+ expectedSenderName,
280
+ metadata,
281
+ onSuccess,
282
+ onExpired,
283
+ className = "",
284
+ children = "Pay Now"
285
+ }) {
286
+ const client = useSeedhaPe();
287
+ const [orderId, setOrderId] = useState2(null);
288
+ const [loading, setLoading] = useState2(false);
289
+ async function handleClick() {
290
+ setLoading(true);
291
+ try {
292
+ const opts = { amount };
293
+ if (description) opts.description = description;
294
+ if (customerEmail) opts.customerEmail = customerEmail;
295
+ if (customerPhone) opts.customerPhone = customerPhone;
296
+ if (expectedSenderName) opts.expectedSenderName = expectedSenderName;
297
+ if (metadata) opts.metadata = metadata;
298
+ const order = await client.createOrder(opts);
299
+ setOrderId(order.id);
300
+ } catch (err) {
301
+ console.error("[SeedhaPe] Failed to create order:", err);
302
+ } finally {
303
+ setLoading(false);
304
+ }
305
+ }
306
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
307
+ /* @__PURE__ */ jsx3(
308
+ "button",
309
+ {
310
+ onClick: handleClick,
311
+ disabled: loading,
312
+ className: className || "sp-pay-btn",
313
+ style: !className ? {
314
+ background: "#16a34a",
315
+ color: "white",
316
+ border: "none",
317
+ padding: "12px 24px",
318
+ borderRadius: "10px",
319
+ fontWeight: 600,
320
+ fontSize: "15px",
321
+ cursor: loading ? "not-allowed" : "pointer",
322
+ opacity: loading ? 0.7 : 1
323
+ } : void 0,
324
+ children: loading ? "Loading..." : children
325
+ }
326
+ ),
327
+ orderId && /* @__PURE__ */ jsx3(
328
+ PaymentModal,
329
+ {
330
+ orderId,
331
+ open: true,
332
+ onClose: () => setOrderId(null),
333
+ onSuccess: (result) => {
334
+ setOrderId(null);
335
+ onSuccess?.(result);
336
+ },
337
+ onExpired: (id) => {
338
+ setOrderId(null);
339
+ onExpired?.(id);
340
+ }
341
+ }
342
+ )
343
+ ] });
344
+ }
345
+
346
+ // src/usePayment.ts
347
+ import { useState as useState3, useCallback } from "react";
348
+ function usePayment() {
349
+ const client = useSeedhaPe();
350
+ const [state, setState] = useState3({ phase: "idle" });
351
+ const createPayment = useCallback(
352
+ async (options) => {
353
+ setState({ phase: "creating" });
354
+ try {
355
+ const order = await client.createOrder(options);
356
+ setState({ phase: "pending", order });
357
+ return order;
358
+ } catch (err) {
359
+ setState({ phase: "error", error: String(err) });
360
+ throw err;
361
+ }
362
+ },
363
+ [client]
364
+ );
365
+ const onSuccess = useCallback((result) => {
366
+ setState({ phase: "verified", result });
367
+ }, []);
368
+ const onExpired = useCallback((orderId) => {
369
+ setState({ phase: "expired", orderId });
370
+ }, []);
371
+ const reset = useCallback(() => setState({ phase: "idle" }), []);
372
+ return { state, createPayment, onSuccess, onExpired, reset };
373
+ }
374
+ export {
375
+ PaymentButton,
376
+ PaymentModal,
377
+ SeedhaPeProvider,
378
+ usePayment,
379
+ useSeedhaPe
380
+ };
381
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/provider.tsx","../src/PaymentButton.tsx","../src/PaymentModal.tsx","../src/usePayment.ts"],"sourcesContent":["import React, { createContext, useContext, useMemo } from 'react';\nimport { SeedhaPe } from '@seedhape/sdk';\n\ninterface SeedhaPeContextValue {\n client: SeedhaPe;\n}\n\nconst SeedhaPeContext = createContext<SeedhaPeContextValue | null>(null);\n\nexport function SeedhaPeProvider({\n apiKey,\n baseUrl,\n children,\n}: {\n apiKey: string;\n baseUrl?: string;\n children: React.ReactNode;\n}) {\n const client = useMemo(() => {\n const config: import('@seedhape/sdk').SeedhaPeConfig = { apiKey };\n if (baseUrl) config.baseUrl = baseUrl;\n return new SeedhaPe(config);\n }, [apiKey, baseUrl]);\n\n return (\n <SeedhaPeContext.Provider value={{ client }}>\n {children}\n </SeedhaPeContext.Provider>\n );\n}\n\nexport function useSeedhaPe(): SeedhaPe {\n const ctx = useContext(SeedhaPeContext);\n if (!ctx) throw new Error('useSeedhaPe must be used inside <SeedhaPeProvider>');\n return ctx.client;\n}\n","import React, { useState } from 'react';\nimport type { PaymentButtonProps } from './types.js';\nimport { PaymentModal } from './PaymentModal.js';\nimport { useSeedhaPe } from './provider.js';\n\nexport function PaymentButton({\n amount,\n description,\n customerEmail,\n customerPhone,\n expectedSenderName,\n metadata,\n onSuccess,\n onExpired,\n className = '',\n children = 'Pay Now',\n}: PaymentButtonProps) {\n const client = useSeedhaPe();\n const [orderId, setOrderId] = useState<string | null>(null);\n const [loading, setLoading] = useState(false);\n\n async function handleClick() {\n setLoading(true);\n try {\n const opts: import('@seedhape/sdk').CreateOrderOptions = { amount };\n if (description) opts.description = description;\n if (customerEmail) opts.customerEmail = customerEmail;\n if (customerPhone) opts.customerPhone = customerPhone;\n if (expectedSenderName) opts.expectedSenderName = expectedSenderName;\n if (metadata) opts.metadata = metadata;\n const order = await client.createOrder(opts);\n setOrderId(order.id);\n } catch (err) {\n console.error('[SeedhaPe] Failed to create order:', err);\n } finally {\n setLoading(false);\n }\n }\n\n return (\n <>\n <button\n onClick={handleClick}\n disabled={loading}\n className={className || 'sp-pay-btn'}\n style={\n !className\n ? {\n background: '#16a34a',\n color: 'white',\n border: 'none',\n padding: '12px 24px',\n borderRadius: '10px',\n fontWeight: 600,\n fontSize: '15px',\n cursor: loading ? 'not-allowed' : 'pointer',\n opacity: loading ? 0.7 : 1,\n }\n : undefined\n }\n >\n {loading ? 'Loading...' : children}\n </button>\n\n {orderId && (\n <PaymentModal\n orderId={orderId}\n open={true}\n onClose={() => setOrderId(null)}\n onSuccess={(result) => {\n setOrderId(null);\n onSuccess?.(result);\n }}\n onExpired={(id) => {\n setOrderId(null);\n onExpired?.(id);\n }}\n />\n )}\n </>\n );\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport type { PaymentModalProps } from './types.js';\n\n// API URL can be set via __SEEDHAPE_API_URL__ global, or defaults to production\ndeclare const __SEEDHAPE_API_URL__: string | undefined;\nconst API_URL: string =\n typeof __SEEDHAPE_API_URL__ !== 'undefined'\n ? __SEEDHAPE_API_URL__\n : 'https://api.seedhape.com';\n\ntype OrderData = {\n id: string;\n amount: number;\n description: string | null;\n status: string;\n upiUri: string;\n qrCode: string;\n expiresAt: string;\n expectedSenderName: string | null;\n};\n\nconst TERMINAL = ['VERIFIED', 'RESOLVED', 'EXPIRED', 'REJECTED'];\n\nconst baseStyles = {\n overlay: {\n position: 'fixed' as const, inset: 0,\n background: 'rgba(0,0,0,0.5)',\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n zIndex: 99999, fontFamily: 'system-ui, sans-serif',\n },\n card: {\n background: 'white', borderRadius: 16, padding: 28,\n width: 360, maxWidth: 'calc(100vw - 32px)', textAlign: 'center' as const,\n boxShadow: '0 25px 50px rgba(0,0,0,0.2)',\n },\n amountBox: {\n background: '#f0fdf4', borderRadius: 12, padding: '12px 16px',\n marginBottom: 20,\n },\n amountLabel: { fontSize: 12, color: '#15803d', marginBottom: 2 },\n amount: { fontSize: 28, fontWeight: 700, color: '#14532d', margin: 0 },\n input: {\n width: '100%', border: '1.5px solid #d1d5db', borderRadius: 10,\n padding: '10px 12px', fontSize: 14, boxSizing: 'border-box' as const,\n outline: 'none', marginBottom: 8,\n },\n inputError: { borderColor: '#f87171' },\n btnPrimary: {\n width: '100%', background: '#16a34a', color: 'white', border: 'none',\n borderRadius: 12, padding: '12px 0', fontSize: 15, fontWeight: 600,\n cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,\n },\n btnDisabled: { opacity: 0.5, cursor: 'not-allowed' as const },\n closeBtn: {\n marginTop: 14, background: 'none', border: 'none',\n color: '#9ca3af', fontSize: 13, cursor: 'pointer',\n },\n hint: { fontSize: 12, color: '#6b7280', lineHeight: 1.5, marginBottom: 12, textAlign: 'left' as const },\n errorText: { fontSize: 12, color: '#ef4444', marginBottom: 8, textAlign: 'left' as const },\n stepDots: { display: 'flex', justifyContent: 'center', gap: 6, marginTop: 14 },\n dot: (active: boolean) => ({\n width: 24, height: 6, borderRadius: 3,\n background: active ? '#16a34a' : '#e5e7eb',\n }),\n};\n\nexport function PaymentModal({ orderId, open, onClose, onSuccess, onExpired }: PaymentModalProps) {\n const [order, setOrder] = useState<OrderData | null>(null);\n const [nameInput, setNameInput] = useState('');\n const [nameError, setNameError] = useState<string | null>(null);\n const [savingName, setSavingName] = useState(false);\n const [nameConfirmed, setNameConfirmed] = useState(false);\n const pollRef = useRef<ReturnType<typeof setInterval> | null>(null);\n\n useEffect(() => {\n if (!open || !orderId) return;\n setOrder(null);\n setNameInput('');\n setNameError(null);\n setNameConfirmed(false);\n fetchOrder();\n return () => { if (pollRef.current) clearInterval(pollRef.current); };\n }, [open, orderId]);\n\n async function fetchOrder() {\n const res = await fetch(`${API_URL}/v1/pay/${orderId}`);\n if (!res.ok) return;\n const data = await res.json() as OrderData;\n setOrder(data);\n // Skip name gate if the merchant already supplied it at order creation time\n if (data.expectedSenderName) {\n setNameInput(data.expectedSenderName);\n setNameConfirmed(true);\n }\n if (!TERMINAL.includes(data.status)) startPolling();\n }\n\n function startPolling() {\n pollRef.current = setInterval(async () => {\n const res = await fetch(`${API_URL}/v1/pay/${orderId}`);\n if (!res.ok) return;\n const data = await res.json() as OrderData;\n setOrder(data);\n if (TERMINAL.includes(data.status)) {\n if (pollRef.current) clearInterval(pollRef.current);\n handleTerminal(data);\n }\n }, 3000);\n }\n\n function handleTerminal(data: OrderData) {\n if (data.status === 'VERIFIED' || data.status === 'RESOLVED') {\n onSuccess?.({ orderId: data.id, status: data.status as 'VERIFIED', amount: data.amount });\n } else if (data.status === 'EXPIRED') {\n onExpired?.(data.id);\n }\n }\n\n async function confirmName() {\n const name = nameInput.trim();\n if (name.length < 2) { setNameError('Enter at least 2 characters.'); return; }\n setSavingName(true);\n setNameError(null);\n try {\n const res = await fetch(`${API_URL}/v1/pay/${orderId}/expectation`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ expectedSenderName: name }),\n });\n if (!res.ok) throw new Error('Failed');\n setNameConfirmed(true);\n } catch {\n setNameError('Could not save name. Please try again.');\n } finally {\n setSavingName(false);\n }\n }\n\n if (!open) return null;\n\n return (\n <div style={baseStyles.overlay} onClick={(e) => e.target === e.currentTarget && onClose()}>\n <div style={baseStyles.card}>\n {!order ? (\n <p style={{ color: '#9ca3af' }}>Loading…</p>\n ) : (order.status === 'VERIFIED' || order.status === 'RESOLVED') ? (\n <>\n <div style={{ fontSize: 48, marginBottom: 8 }}>✅</div>\n <p style={{ fontWeight: 700, fontSize: 18, color: '#16a34a', margin: '0 0 4px' }}>Payment Verified!</p>\n <p style={{ fontSize: 26, fontWeight: 700, color: '#111', margin: 0 }}>\n ₹{(order.amount / 100).toFixed(2)}\n </p>\n </>\n ) : order.status === 'EXPIRED' ? (\n <>\n <div style={{ fontSize: 48, marginBottom: 8 }}>⏰</div>\n <p style={{ fontWeight: 600, fontSize: 18, color: '#dc2626' }}>Link Expired</p>\n </>\n ) : !nameConfirmed ? (\n /* ── Step 1: Name gate ── */\n <>\n <div style={baseStyles.amountBox}>\n <p style={baseStyles.amountLabel}>Amount</p>\n <p style={baseStyles.amount}>₹{(order.amount / 100).toFixed(2)}</p>\n </div>\n <p style={{ fontWeight: 700, fontSize: 15, textAlign: 'left', marginBottom: 6 }}>Enter your name</p>\n <p style={baseStyles.hint}>\n Enter your name exactly as shown in your UPI app. This is used to instantly match your payment.\n </p>\n <input\n style={{ ...baseStyles.input, ...(nameError ? baseStyles.inputError : {}) }}\n value={nameInput}\n onChange={(e) => { setNameInput(e.target.value); setNameError(null); }}\n onKeyDown={(e) => e.key === 'Enter' && confirmName()}\n placeholder=\"e.g. Rahul Sharma\"\n autoFocus\n />\n {nameError && <p style={baseStyles.errorText}>{nameError}</p>}\n <button\n style={{ ...baseStyles.btnPrimary, ...(savingName || nameInput.trim().length < 2 ? baseStyles.btnDisabled : {}) }}\n onClick={confirmName}\n disabled={savingName || nameInput.trim().length < 2}\n >\n {savingName ? 'Saving…' : 'Continue →'}\n </button>\n <div style={baseStyles.stepDots}>\n <div style={baseStyles.dot(true)} />\n <div style={baseStyles.dot(false)} />\n </div>\n </>\n ) : (\n /* ── Step 2: QR + Pay ── */\n <>\n <div style={baseStyles.amountBox}>\n <p style={baseStyles.amountLabel}>Amount</p>\n <p style={baseStyles.amount}>₹{(order.amount / 100).toFixed(2)}</p>\n </div>\n {order.description && (\n <p style={{ fontSize: 14, color: '#4b5563', marginBottom: 12 }}>{order.description}</p>\n )}\n {order.qrCode && (\n <img src={order.qrCode} width={200} height={200} style={{ borderRadius: 8, marginBottom: 14 }} alt=\"UPI QR\" />\n )}\n <a\n href={order.upiUri}\n style={{\n display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8,\n background: '#16a34a', color: 'white',\n padding: '12px 0', borderRadius: 12, textDecoration: 'none',\n fontWeight: 600, fontSize: 15, marginBottom: 10,\n }}\n >\n Open UPI App\n </a>\n <p style={{ fontSize: 12, color: '#9ca3af', marginBottom: 2 }}>⏳ Waiting for payment…</p>\n <div style={baseStyles.stepDots}>\n <div style={baseStyles.dot(false)} />\n <div style={baseStyles.dot(true)} />\n </div>\n </>\n )}\n\n <button style={baseStyles.closeBtn} onClick={onClose}>Close</button>\n </div>\n </div>\n );\n}\n","import { useState, useCallback } from 'react';\nimport type { OrderData, PaymentResult } from '@seedhape/sdk';\n\nimport { useSeedhaPe } from './provider.js';\n\ntype PaymentState =\n | { phase: 'idle' }\n | { phase: 'creating' }\n | { phase: 'pending'; order: OrderData }\n | { phase: 'verified'; result: PaymentResult }\n | { phase: 'expired'; orderId: string }\n | { phase: 'error'; error: string };\n\nexport function usePayment() {\n const client = useSeedhaPe();\n const [state, setState] = useState<PaymentState>({ phase: 'idle' });\n\n const createPayment = useCallback(\n async (options: {\n amount: number;\n description?: string;\n customerEmail?: string;\n customerPhone?: string;\n metadata?: Record<string, unknown>;\n }) => {\n setState({ phase: 'creating' });\n try {\n const order = await client.createOrder(options);\n setState({ phase: 'pending', order });\n return order;\n } catch (err) {\n setState({ phase: 'error', error: String(err) });\n throw err;\n }\n },\n [client],\n );\n\n const onSuccess = useCallback((result: PaymentResult) => {\n setState({ phase: 'verified', result });\n }, []);\n\n const onExpired = useCallback((orderId: string) => {\n setState({ phase: 'expired', orderId });\n }, []);\n\n const reset = useCallback(() => setState({ phase: 'idle' }), []);\n\n return { state, createPayment, onSuccess, onExpired, reset };\n}\n"],"mappings":"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","names":["useState","jsx","Fragment","jsx","jsxs","useState","useState","useState"]}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@seedhape/react",
3
+ "version": "0.1.0",
4
+ "description": "SeedhaPe React components — PaymentButton, PaymentModal, usePayment hook",
5
+ "exports": {
6
+ ".": {
7
+ "types": "./dist/index.d.ts",
8
+ "import": "./dist/index.mjs",
9
+ "require": "./dist/index.cjs"
10
+ }
11
+ },
12
+ "main": "./dist/index.cjs",
13
+ "module": "./dist/index.mjs",
14
+ "types": "./dist/index.d.ts",
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "dependencies": {
19
+ "@seedhape/sdk": "0.1.0",
20
+ "@seedhape/shared": "0.0.0"
21
+ },
22
+ "devDependencies": {
23
+ "@types/react": "^19.0.7",
24
+ "tsup": "^8.3.5",
25
+ "typescript": "^5.7.2",
26
+ "@seedhape/typescript-config": "0.0.0"
27
+ },
28
+ "peerDependencies": {
29
+ "react": ">=18.0.0"
30
+ },
31
+ "scripts": {
32
+ "build": "tsup",
33
+ "dev": "tsup --watch",
34
+ "typecheck": "tsc --noEmit",
35
+ "clean": "rm -rf dist"
36
+ }
37
+ }