forgelayer-react 1.0.0 → 1.1.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.cjs.js +478 -0
- package/dist/index.cjs.js.map +7 -0
- package/dist/index.d.ts +121 -0
- package/dist/index.esm.js +446 -0
- package/dist/index.esm.js.map +7 -0
- package/package.json +17 -5
- package/src/ForgeLayerButton.jsx +0 -94
- package/src/ForgeLayerModal.jsx +0 -267
- package/src/index.js +0 -3
- package/src/useForgeLayerCheckout.js +0 -93
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
29
|
+
// src/index.js
|
|
30
|
+
var index_exports = {};
|
|
31
|
+
__export(index_exports, {
|
|
32
|
+
ForgeLayerButton: () => ForgeLayerButton,
|
|
33
|
+
ForgeLayerModal: () => ForgeLayerModal,
|
|
34
|
+
useForgeLayerCheckout: () => useForgeLayerCheckout
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
|
|
38
|
+
// src/ForgeLayerButton.jsx
|
|
39
|
+
var import_react3 = __toESM(require("react"));
|
|
40
|
+
|
|
41
|
+
// src/useForgeLayerCheckout.js
|
|
42
|
+
var import_react = require("react");
|
|
43
|
+
function useForgeLayerCheckout({
|
|
44
|
+
baseUrl = "/fl",
|
|
45
|
+
pollInterval = 15e3,
|
|
46
|
+
onSuccess,
|
|
47
|
+
onExpired,
|
|
48
|
+
onError,
|
|
49
|
+
onOpen,
|
|
50
|
+
onClose: onCloseProp
|
|
51
|
+
} = {}) {
|
|
52
|
+
const [modalState, setModalState] = (0, import_react.useState)("closed");
|
|
53
|
+
const [order, setOrder] = (0, import_react.useState)(null);
|
|
54
|
+
const [timeLeft, setTimeLeft] = (0, import_react.useState)(null);
|
|
55
|
+
const [error, setError] = (0, import_react.useState)(null);
|
|
56
|
+
const pollRef = (0, import_react.useRef)(null);
|
|
57
|
+
const cdRef = (0, import_react.useRef)(null);
|
|
58
|
+
const stopTimers = (0, import_react.useCallback)(() => {
|
|
59
|
+
if (pollRef.current) {
|
|
60
|
+
clearInterval(pollRef.current);
|
|
61
|
+
pollRef.current = null;
|
|
62
|
+
}
|
|
63
|
+
if (cdRef.current) {
|
|
64
|
+
clearInterval(cdRef.current);
|
|
65
|
+
cdRef.current = null;
|
|
66
|
+
}
|
|
67
|
+
}, []);
|
|
68
|
+
(0, import_react.useEffect)(() => stopTimers, [stopTimers]);
|
|
69
|
+
const close = (0, import_react.useCallback)(() => {
|
|
70
|
+
stopTimers();
|
|
71
|
+
setModalState("closed");
|
|
72
|
+
setOrder(null);
|
|
73
|
+
setTimeLeft(null);
|
|
74
|
+
setError(null);
|
|
75
|
+
onCloseProp?.();
|
|
76
|
+
}, [stopTimers, onCloseProp]);
|
|
77
|
+
const startCountdown = (0, import_react.useCallback)((expiresAt) => {
|
|
78
|
+
if (cdRef.current) clearInterval(cdRef.current);
|
|
79
|
+
const tick = () => {
|
|
80
|
+
const rem = expiresAt - Math.floor(Date.now() / 1e3);
|
|
81
|
+
setTimeLeft(rem <= 0 ? 0 : rem);
|
|
82
|
+
if (rem <= 0) clearInterval(cdRef.current);
|
|
83
|
+
};
|
|
84
|
+
tick();
|
|
85
|
+
cdRef.current = setInterval(tick, 1e3);
|
|
86
|
+
}, []);
|
|
87
|
+
const startPolling = (0, import_react.useCallback)((orderData) => {
|
|
88
|
+
if (pollRef.current) clearInterval(pollRef.current);
|
|
89
|
+
pollRef.current = setInterval(async () => {
|
|
90
|
+
try {
|
|
91
|
+
const res = await fetch(`${baseUrl}/status?session=${encodeURIComponent(orderData.sessionKey)}`);
|
|
92
|
+
const data = await res.json();
|
|
93
|
+
if (!data.ok) return;
|
|
94
|
+
if (data.status === "confirmed") {
|
|
95
|
+
stopTimers();
|
|
96
|
+
setModalState("success");
|
|
97
|
+
onSuccess?.(orderData);
|
|
98
|
+
} else if (data.status === "expired") {
|
|
99
|
+
stopTimers();
|
|
100
|
+
setModalState("expired");
|
|
101
|
+
onExpired?.();
|
|
102
|
+
}
|
|
103
|
+
} catch (_) {
|
|
104
|
+
}
|
|
105
|
+
}, pollInterval);
|
|
106
|
+
}, [baseUrl, pollInterval, stopTimers, onSuccess, onExpired]);
|
|
107
|
+
const open = (0, import_react.useCallback)(async (params) => {
|
|
108
|
+
stopTimers();
|
|
109
|
+
setModalState("loading");
|
|
110
|
+
setOrder(null);
|
|
111
|
+
setTimeLeft(null);
|
|
112
|
+
setError(null);
|
|
113
|
+
onOpen?.();
|
|
114
|
+
try {
|
|
115
|
+
const res = await fetch(`${baseUrl}/create`, {
|
|
116
|
+
method: "POST",
|
|
117
|
+
headers: { "Content-Type": "application/json" },
|
|
118
|
+
body: JSON.stringify(params)
|
|
119
|
+
});
|
|
120
|
+
const data = await res.json();
|
|
121
|
+
if (!data.ok) throw new Error(data.error || "Failed to generate payment address.");
|
|
122
|
+
setOrder(data);
|
|
123
|
+
setModalState("payment");
|
|
124
|
+
startCountdown(data.expiresAt);
|
|
125
|
+
startPolling(data);
|
|
126
|
+
} catch (e) {
|
|
127
|
+
setError(e.message);
|
|
128
|
+
setModalState("error");
|
|
129
|
+
onError?.(e);
|
|
130
|
+
}
|
|
131
|
+
}, [baseUrl, stopTimers, startCountdown, startPolling, onOpen, onError]);
|
|
132
|
+
return { modalState, order, timeLeft, error, open, close };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// src/ForgeLayerModal.jsx
|
|
136
|
+
var import_react2 = __toESM(require("react"));
|
|
137
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
138
|
+
var MODAL_CSS = `
|
|
139
|
+
@keyframes fl-r-fade{from{opacity:0}to{opacity:1}}
|
|
140
|
+
@keyframes fl-r-up{from{transform:translateY(16px);opacity:0}to{transform:translateY(0);opacity:1}}
|
|
141
|
+
@keyframes fl-r-spin{to{transform:rotate(360deg)}}
|
|
142
|
+
@keyframes fl-r-pulse{0%,100%{opacity:1}50%{opacity:.35}}
|
|
143
|
+
.fl-r-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:99999;
|
|
144
|
+
display:flex;align-items:center;justify-content:center;padding:16px;
|
|
145
|
+
animation:fl-r-fade .18s ease}
|
|
146
|
+
.fl-r-modal{background:#fff;border-radius:16px;width:100%;max-width:520px;
|
|
147
|
+
box-shadow:0 24px 64px rgba(0,0,0,.28);overflow:hidden;
|
|
148
|
+
animation:fl-r-up .22s ease;
|
|
149
|
+
font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;
|
|
150
|
+
font-size:14px;color:#111}
|
|
151
|
+
.fl-r-spinner{width:38px;height:38px;border:3px solid #e5e7eb;
|
|
152
|
+
border-top-color:#f7931a;border-radius:50%;
|
|
153
|
+
animation:fl-r-spin .7s linear infinite;margin:0 auto 14px}
|
|
154
|
+
.fl-r-dot-pending{background:#f59e0b;animation:fl-r-pulse 1.6s ease-in-out infinite}
|
|
155
|
+
.fl-r-dot-confirmed{background:#10b981}
|
|
156
|
+
.fl-r-dot-expired{background:#ef4444}
|
|
157
|
+
.fl-r-xbtn:hover{background:#f3f4f6 !important;color:#111 !important}
|
|
158
|
+
.fl-r-cpbtn:hover{background:#f3f4f6 !important}
|
|
159
|
+
.fl-r-cpbtn-copied{border-color:#10b981 !important;color:#059669 !important}
|
|
160
|
+
@media(max-width:460px){.fl-r-grid{flex-direction:column !important;align-items:center !important}}
|
|
161
|
+
`;
|
|
162
|
+
var _cssInjected = false;
|
|
163
|
+
function ensureCSS() {
|
|
164
|
+
if (_cssInjected || typeof document === "undefined") return;
|
|
165
|
+
_cssInjected = true;
|
|
166
|
+
const el = document.createElement("style");
|
|
167
|
+
el.textContent = MODAL_CSS;
|
|
168
|
+
document.head.appendChild(el);
|
|
169
|
+
}
|
|
170
|
+
function fmtTime(secs) {
|
|
171
|
+
const m = Math.floor(secs / 60);
|
|
172
|
+
const s = secs % 60;
|
|
173
|
+
return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
174
|
+
}
|
|
175
|
+
function ForgeLayerModal({ modalState, order, timeLeft, error, onClose }) {
|
|
176
|
+
const [copied, setCopied] = (0, import_react2.useState)(false);
|
|
177
|
+
(0, import_react2.useEffect)(() => {
|
|
178
|
+
ensureCSS();
|
|
179
|
+
}, []);
|
|
180
|
+
(0, import_react2.useEffect)(() => {
|
|
181
|
+
const handler = (e) => {
|
|
182
|
+
if (e.key === "Escape") onClose();
|
|
183
|
+
};
|
|
184
|
+
document.addEventListener("keydown", handler);
|
|
185
|
+
return () => document.removeEventListener("keydown", handler);
|
|
186
|
+
}, [onClose]);
|
|
187
|
+
(0, import_react2.useEffect)(() => {
|
|
188
|
+
const prev = document.body.style.overflow;
|
|
189
|
+
document.body.style.overflow = "hidden";
|
|
190
|
+
return () => {
|
|
191
|
+
document.body.style.overflow = prev;
|
|
192
|
+
};
|
|
193
|
+
}, []);
|
|
194
|
+
const copyAddress = () => {
|
|
195
|
+
if (!order?.address) return;
|
|
196
|
+
navigator.clipboard?.writeText(order.address).catch(() => {
|
|
197
|
+
});
|
|
198
|
+
setCopied(true);
|
|
199
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
200
|
+
};
|
|
201
|
+
const urgent = timeLeft !== null && timeLeft <= 120;
|
|
202
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
203
|
+
"div",
|
|
204
|
+
{
|
|
205
|
+
className: "fl-r-backdrop",
|
|
206
|
+
role: "dialog",
|
|
207
|
+
"aria-modal": "true",
|
|
208
|
+
"aria-label": "Crypto payment",
|
|
209
|
+
onClick: (e) => {
|
|
210
|
+
if (e.target === e.currentTarget) onClose();
|
|
211
|
+
},
|
|
212
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "fl-r-modal", children: [
|
|
213
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: {
|
|
214
|
+
display: "flex",
|
|
215
|
+
alignItems: "center",
|
|
216
|
+
justifyContent: "space-between",
|
|
217
|
+
padding: "16px 18px",
|
|
218
|
+
borderBottom: "1px solid #e5e7eb",
|
|
219
|
+
background: "#fafafa"
|
|
220
|
+
}, children: [
|
|
221
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 9, fontSize: 15, fontWeight: 700 }, children: [
|
|
222
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: {
|
|
223
|
+
width: 26,
|
|
224
|
+
height: 26,
|
|
225
|
+
background: "#f7931a",
|
|
226
|
+
borderRadius: 6,
|
|
227
|
+
display: "flex",
|
|
228
|
+
alignItems: "center",
|
|
229
|
+
justifyContent: "center",
|
|
230
|
+
color: "#fff",
|
|
231
|
+
fontSize: 10,
|
|
232
|
+
fontWeight: 800,
|
|
233
|
+
flexShrink: 0
|
|
234
|
+
}, children: "FL" }),
|
|
235
|
+
"Pay with Crypto"
|
|
236
|
+
] }),
|
|
237
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
238
|
+
"button",
|
|
239
|
+
{
|
|
240
|
+
className: "fl-r-xbtn",
|
|
241
|
+
onClick: onClose,
|
|
242
|
+
"aria-label": "Close",
|
|
243
|
+
style: {
|
|
244
|
+
background: "none",
|
|
245
|
+
border: "none",
|
|
246
|
+
fontSize: 22,
|
|
247
|
+
lineHeight: 1,
|
|
248
|
+
cursor: "pointer",
|
|
249
|
+
color: "#6b7280",
|
|
250
|
+
padding: "4px 8px",
|
|
251
|
+
borderRadius: 5,
|
|
252
|
+
transition: "background .12s"
|
|
253
|
+
},
|
|
254
|
+
children: "\xD7"
|
|
255
|
+
}
|
|
256
|
+
)
|
|
257
|
+
] }),
|
|
258
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: "20px 18px" }, children: [
|
|
259
|
+
modalState === "loading" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { textAlign: "center", padding: "28px 0" }, children: [
|
|
260
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "fl-r-spinner" }),
|
|
261
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { color: "#6b7280", fontSize: 13, margin: 0 }, children: "Generating payment address\u2026" })
|
|
262
|
+
] }),
|
|
263
|
+
modalState === "error" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { textAlign: "center", padding: "28px 0" }, children: [
|
|
264
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 48, marginBottom: 12 }, children: "\u26A0\uFE0F" }),
|
|
265
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 15, fontWeight: 700, marginBottom: 8 }, children: "Something went wrong" }),
|
|
266
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 13, color: "#6b7280" }, children: error })
|
|
267
|
+
] }),
|
|
268
|
+
modalState === "payment" && order && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
269
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: {
|
|
270
|
+
display: "flex",
|
|
271
|
+
alignItems: "center",
|
|
272
|
+
gap: 9,
|
|
273
|
+
padding: "9px 13px",
|
|
274
|
+
borderRadius: 8,
|
|
275
|
+
background: "#f9fafb",
|
|
276
|
+
border: "1px solid #e5e7eb",
|
|
277
|
+
marginBottom: 14,
|
|
278
|
+
fontSize: 13
|
|
279
|
+
}, children: [
|
|
280
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
281
|
+
"span",
|
|
282
|
+
{
|
|
283
|
+
className: "fl-r-dot-pending",
|
|
284
|
+
style: { width: 8, height: 8, borderRadius: "50%", flexShrink: 0 }
|
|
285
|
+
}
|
|
286
|
+
),
|
|
287
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "Awaiting payment\u2026" }),
|
|
288
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: {
|
|
289
|
+
marginLeft: "auto",
|
|
290
|
+
fontWeight: 600,
|
|
291
|
+
fontSize: 13,
|
|
292
|
+
color: urgent ? "#ef4444" : "#374151",
|
|
293
|
+
fontVariantNumeric: "tabular-nums"
|
|
294
|
+
}, children: timeLeft !== null ? fmtTime(timeLeft) : "--:--" })
|
|
295
|
+
] }),
|
|
296
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: {
|
|
297
|
+
background: "#fffbeb",
|
|
298
|
+
border: "1px solid #fde68a",
|
|
299
|
+
borderRadius: 8,
|
|
300
|
+
padding: "9px 13px",
|
|
301
|
+
fontSize: 12,
|
|
302
|
+
color: "#92400e",
|
|
303
|
+
marginBottom: 14,
|
|
304
|
+
lineHeight: 1.5
|
|
305
|
+
}, children: [
|
|
306
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: "\u26A0 Important:" }),
|
|
307
|
+
" Send only ",
|
|
308
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: order.token }),
|
|
309
|
+
" on the",
|
|
310
|
+
" ",
|
|
311
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("strong", { children: order.chainName }),
|
|
312
|
+
" network only. Wrong network = permanent loss."
|
|
313
|
+
] }),
|
|
314
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "fl-r-grid", style: { display: "flex", gap: 18, marginBottom: 14 }, children: [
|
|
315
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { flexShrink: 0, display: "flex", flexDirection: "column", alignItems: "center", gap: 6 }, children: [
|
|
316
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
317
|
+
"img",
|
|
318
|
+
{
|
|
319
|
+
src: order.qrUrl,
|
|
320
|
+
alt: `Send to ${order.address}`,
|
|
321
|
+
width: 148,
|
|
322
|
+
height: 148,
|
|
323
|
+
style: { border: "1px solid #e5e7eb", borderRadius: 10, display: "block", background: "#f9fafb" }
|
|
324
|
+
}
|
|
325
|
+
),
|
|
326
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: 11, color: "#9ca3af", margin: 0 }, children: "Scan with wallet" })
|
|
327
|
+
] }),
|
|
328
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { flex: 1, minWidth: 0, display: "flex", flexDirection: "column", gap: 13 }, children: [
|
|
329
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
330
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { style: { display: "block", fontSize: 10, fontWeight: 700, color: "#6b7280", textTransform: "uppercase", letterSpacing: ".06em", marginBottom: 4 }, children: "Amount to Send" }),
|
|
331
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 22, fontWeight: 700, lineHeight: 1.2 }, children: order.cryptoAmount ? `${parseFloat(order.cryptoAmount).toFixed(8).replace(/\.?0+$/, "")} ${order.token}` : `${order.currency} ${parseFloat(order.amount).toFixed(2)}` }),
|
|
332
|
+
order.cryptoAmount && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { fontSize: 12, color: "#6b7280", marginTop: 2 }, children: [
|
|
333
|
+
"\u2248 ",
|
|
334
|
+
order.currency,
|
|
335
|
+
" ",
|
|
336
|
+
parseFloat(order.amount).toFixed(2)
|
|
337
|
+
] })
|
|
338
|
+
] }),
|
|
339
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
340
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { style: { display: "block", fontSize: 10, fontWeight: 700, color: "#6b7280", textTransform: "uppercase", letterSpacing: ".06em", marginBottom: 4 }, children: "Deposit Address" }),
|
|
341
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "flex-start", gap: 7 }, children: [
|
|
342
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontFamily: "monospace", fontSize: 12, color: "#374151", wordBreak: "break-all", flex: 1, lineHeight: 1.5 }, children: order.address }),
|
|
343
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
344
|
+
"button",
|
|
345
|
+
{
|
|
346
|
+
className: `fl-r-cpbtn${copied ? " fl-r-cpbtn-copied" : ""}`,
|
|
347
|
+
onClick: copyAddress,
|
|
348
|
+
style: {
|
|
349
|
+
flexShrink: 0,
|
|
350
|
+
background: "#fff",
|
|
351
|
+
border: "1px solid #d1d5db",
|
|
352
|
+
borderRadius: 6,
|
|
353
|
+
padding: "5px 11px",
|
|
354
|
+
fontSize: 12,
|
|
355
|
+
cursor: "pointer",
|
|
356
|
+
color: "#374151",
|
|
357
|
+
transition: "background .12s",
|
|
358
|
+
whiteSpace: "nowrap"
|
|
359
|
+
},
|
|
360
|
+
children: copied ? "Copied!" : "Copy"
|
|
361
|
+
}
|
|
362
|
+
)
|
|
363
|
+
] })
|
|
364
|
+
] }),
|
|
365
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
366
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("label", { style: { display: "block", fontSize: 10, fontWeight: 700, color: "#6b7280", textTransform: "uppercase", letterSpacing: ".06em", marginBottom: 4 }, children: "Network" }),
|
|
367
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: { display: "inline-flex", alignItems: "center", gap: 5, padding: "3px 10px", background: "#f3f4f6", borderRadius: 100, fontSize: 12, fontWeight: 500, color: "#374151" }, children: [
|
|
368
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { width: 7, height: 7, borderRadius: "50%", background: "#10b981", flexShrink: 0 } }),
|
|
369
|
+
order.chainName,
|
|
370
|
+
" \xB7 ",
|
|
371
|
+
order.token
|
|
372
|
+
] })
|
|
373
|
+
] })
|
|
374
|
+
] })
|
|
375
|
+
] })
|
|
376
|
+
] }),
|
|
377
|
+
modalState === "success" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { textAlign: "center", padding: "30px 16px" }, children: [
|
|
378
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 52, marginBottom: 14 }, children: "\u2705" }),
|
|
379
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 19, fontWeight: 700, color: "#111", marginBottom: 7 }, children: "Payment Confirmed!" }),
|
|
380
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 13, color: "#6b7280" }, children: "Your payment has been received." })
|
|
381
|
+
] }),
|
|
382
|
+
modalState === "expired" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { textAlign: "center", padding: "30px 16px" }, children: [
|
|
383
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 52, marginBottom: 14 }, children: "\u23F3" }),
|
|
384
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 19, fontWeight: 700, color: "#111", marginBottom: 7 }, children: "Payment Expired" }),
|
|
385
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { fontSize: 13, color: "#6b7280" }, children: "The payment window has closed. Please start a new payment." })
|
|
386
|
+
] })
|
|
387
|
+
] }),
|
|
388
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { padding: "10px 18px 14px", textAlign: "center", fontSize: 11, color: "#9ca3af", borderTop: "1px solid #f3f4f6" }, children: [
|
|
389
|
+
"Secured by",
|
|
390
|
+
" ",
|
|
391
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: "https://forgelayer.io", target: "_blank", rel: "noopener noreferrer", style: { color: "#f7931a", textDecoration: "none" }, children: "ForgeLayer" })
|
|
392
|
+
] })
|
|
393
|
+
] })
|
|
394
|
+
}
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// src/ForgeLayerButton.jsx
|
|
399
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
400
|
+
function ForgeLayerButton({
|
|
401
|
+
// Payment params
|
|
402
|
+
amount,
|
|
403
|
+
currency = "USD",
|
|
404
|
+
chain = "ethereum",
|
|
405
|
+
token = "USDT",
|
|
406
|
+
orderId,
|
|
407
|
+
paymentWindow,
|
|
408
|
+
reuseAddress,
|
|
409
|
+
// Backend base path (proxied or absolute)
|
|
410
|
+
baseUrl = "/fl",
|
|
411
|
+
pollInterval,
|
|
412
|
+
// Button UI
|
|
413
|
+
label,
|
|
414
|
+
children,
|
|
415
|
+
className,
|
|
416
|
+
style,
|
|
417
|
+
disabled,
|
|
418
|
+
// Callbacks
|
|
419
|
+
onSuccess,
|
|
420
|
+
onExpired,
|
|
421
|
+
onError,
|
|
422
|
+
onOpen,
|
|
423
|
+
onClose
|
|
424
|
+
}) {
|
|
425
|
+
const { modalState, order, timeLeft, error, open, close } = useForgeLayerCheckout({
|
|
426
|
+
baseUrl,
|
|
427
|
+
pollInterval,
|
|
428
|
+
onSuccess,
|
|
429
|
+
onExpired,
|
|
430
|
+
onError,
|
|
431
|
+
onOpen,
|
|
432
|
+
onClose
|
|
433
|
+
});
|
|
434
|
+
const isOpen = modalState !== "closed";
|
|
435
|
+
const handleClick = () => {
|
|
436
|
+
open({ amount, currency, chain, token, orderId, paymentWindow, reuseAddress });
|
|
437
|
+
};
|
|
438
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
439
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
440
|
+
"button",
|
|
441
|
+
{
|
|
442
|
+
onClick: handleClick,
|
|
443
|
+
disabled: disabled || isOpen,
|
|
444
|
+
className,
|
|
445
|
+
style: {
|
|
446
|
+
display: "inline-flex",
|
|
447
|
+
alignItems: "center",
|
|
448
|
+
gap: 8,
|
|
449
|
+
padding: "12px 24px",
|
|
450
|
+
background: "#f7931a",
|
|
451
|
+
color: "#fff",
|
|
452
|
+
border: "none",
|
|
453
|
+
borderRadius: 8,
|
|
454
|
+
fontSize: 15,
|
|
455
|
+
fontWeight: 600,
|
|
456
|
+
cursor: disabled || isOpen ? "not-allowed" : "pointer",
|
|
457
|
+
opacity: disabled || isOpen ? 0.65 : 1,
|
|
458
|
+
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif',
|
|
459
|
+
lineHeight: 1.2,
|
|
460
|
+
transition: "opacity .15s",
|
|
461
|
+
...style
|
|
462
|
+
},
|
|
463
|
+
children: label ?? children ?? "Pay with Crypto"
|
|
464
|
+
}
|
|
465
|
+
),
|
|
466
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
467
|
+
ForgeLayerModal,
|
|
468
|
+
{
|
|
469
|
+
modalState,
|
|
470
|
+
order,
|
|
471
|
+
timeLeft,
|
|
472
|
+
error,
|
|
473
|
+
onClose: close
|
|
474
|
+
}
|
|
475
|
+
)
|
|
476
|
+
] });
|
|
477
|
+
}
|
|
478
|
+
//# sourceMappingURL=index.cjs.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/index.js", "../src/ForgeLayerButton.jsx", "../src/useForgeLayerCheckout.js", "../src/ForgeLayerModal.jsx"],
|
|
4
|
+
"sourcesContent": ["export { ForgeLayerButton } from './ForgeLayerButton.jsx';\nexport { ForgeLayerModal } from './ForgeLayerModal.jsx';\nexport { useForgeLayerCheckout } from './useForgeLayerCheckout.js';\n", "import React from 'react';\nimport { useForgeLayerCheckout } from './useForgeLayerCheckout.js';\nimport { ForgeLayerModal } from './ForgeLayerModal.jsx';\n\n/**\n * Drop-in React checkout button.\n *\n * Usage:\n * <ForgeLayerButton\n * amount={49.99}\n * currency=\"USD\"\n * chain=\"ethereum\"\n * token=\"USDT\"\n * orderId=\"ORDER-123\"\n * onSuccess={(order) => router.push('/thank-you')}\n * >\n * Pay $49.99\n * </ForgeLayerButton>\n */\nexport function ForgeLayerButton({\n // Payment params\n amount,\n currency = 'USD',\n chain = 'ethereum',\n token = 'USDT',\n orderId,\n paymentWindow,\n reuseAddress,\n // Backend base path (proxied or absolute)\n baseUrl = '/fl',\n pollInterval,\n // Button UI\n label,\n children,\n className,\n style,\n disabled,\n // Callbacks\n onSuccess,\n onExpired,\n onError,\n onOpen,\n onClose,\n}) {\n const { modalState, order, timeLeft, error, open, close } = useForgeLayerCheckout({\n baseUrl,\n pollInterval,\n onSuccess,\n onExpired,\n onError,\n onOpen,\n onClose,\n });\n\n const isOpen = modalState !== 'closed';\n\n const handleClick = () => {\n open({ amount, currency, chain, token, orderId, paymentWindow, reuseAddress });\n };\n\n return (\n <>\n <button\n onClick={handleClick}\n disabled={disabled || isOpen}\n className={className}\n style={{\n display: 'inline-flex',\n alignItems: 'center',\n gap: 8,\n padding: '12px 24px',\n background: '#f7931a',\n color: '#fff',\n border: 'none',\n borderRadius: 8,\n fontSize: 15,\n fontWeight: 600,\n cursor: (disabled || isOpen) ? 'not-allowed' : 'pointer',\n opacity: (disabled || isOpen) ? 0.65 : 1,\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif',\n lineHeight: 1.2,\n transition: 'opacity .15s',\n ...style,\n }}\n >\n {label ?? children ?? 'Pay with Crypto'}\n </button>\n\n {isOpen && (\n <ForgeLayerModal\n modalState={modalState}\n order={order}\n timeLeft={timeLeft}\n error={error}\n onClose={close}\n />\n )}\n </>\n );\n}\n", "'use strict';\nimport { useState, useRef, useCallback, useEffect } from 'react';\n\n/**\n * Core hook \u2014 handles all state and API calls for the checkout flow.\n *\n * modalState values:\n * 'closed' | 'loading' | 'payment' | 'success' | 'expired' | 'error'\n */\nexport function useForgeLayerCheckout({\n baseUrl = '/fl',\n pollInterval = 15_000,\n onSuccess,\n onExpired,\n onError,\n onOpen,\n onClose: onCloseProp,\n} = {}) {\n const [modalState, setModalState] = useState('closed');\n const [order, setOrder] = useState(null);\n const [timeLeft, setTimeLeft] = useState(null);\n const [error, setError] = useState(null);\n\n const pollRef = useRef(null);\n const cdRef = useRef(null);\n\n const stopTimers = useCallback(() => {\n if (pollRef.current) { clearInterval(pollRef.current); pollRef.current = null; }\n if (cdRef.current) { clearInterval(cdRef.current); cdRef.current = null; }\n }, []);\n\n // Cleanup on unmount\n useEffect(() => stopTimers, [stopTimers]);\n\n const close = useCallback(() => {\n stopTimers();\n setModalState('closed');\n setOrder(null);\n setTimeLeft(null);\n setError(null);\n onCloseProp?.();\n }, [stopTimers, onCloseProp]);\n\n const startCountdown = useCallback((expiresAt) => {\n if (cdRef.current) clearInterval(cdRef.current);\n const tick = () => {\n const rem = expiresAt - Math.floor(Date.now() / 1000);\n setTimeLeft(rem <= 0 ? 0 : rem);\n if (rem <= 0) clearInterval(cdRef.current);\n };\n tick();\n cdRef.current = setInterval(tick, 1000);\n }, []);\n\n const startPolling = useCallback((orderData) => {\n if (pollRef.current) clearInterval(pollRef.current);\n pollRef.current = setInterval(async () => {\n try {\n const res = await fetch(`${baseUrl}/status?session=${encodeURIComponent(orderData.sessionKey)}`);\n const data = await res.json();\n if (!data.ok) return;\n if (data.status === 'confirmed') {\n stopTimers();\n setModalState('success');\n onSuccess?.(orderData);\n } else if (data.status === 'expired') {\n stopTimers();\n setModalState('expired');\n onExpired?.();\n }\n } catch (_) {}\n }, pollInterval);\n }, [baseUrl, pollInterval, stopTimers, onSuccess, onExpired]);\n\n const open = useCallback(async (params) => {\n stopTimers();\n setModalState('loading');\n setOrder(null);\n setTimeLeft(null);\n setError(null);\n onOpen?.();\n\n try {\n const res = await fetch(`${baseUrl}/create`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(params),\n });\n const data = await res.json();\n if (!data.ok) throw new Error(data.error || 'Failed to generate payment address.');\n setOrder(data);\n setModalState('payment');\n startCountdown(data.expiresAt);\n startPolling(data);\n } catch (e) {\n setError(e.message);\n setModalState('error');\n onError?.(e);\n }\n }, [baseUrl, stopTimers, startCountdown, startPolling, onOpen, onError]);\n\n return { modalState, order, timeLeft, error, open, close };\n}\n", "import React, { useEffect, useState } from 'react';\n\n// Injected once \u2014 handles animations, hover, and pseudo-elements\n// that can't be done with inline styles.\nconst MODAL_CSS = `\n@keyframes fl-r-fade{from{opacity:0}to{opacity:1}}\n@keyframes fl-r-up{from{transform:translateY(16px);opacity:0}to{transform:translateY(0);opacity:1}}\n@keyframes fl-r-spin{to{transform:rotate(360deg)}}\n@keyframes fl-r-pulse{0%,100%{opacity:1}50%{opacity:.35}}\n.fl-r-backdrop{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:99999;\n display:flex;align-items:center;justify-content:center;padding:16px;\n animation:fl-r-fade .18s ease}\n.fl-r-modal{background:#fff;border-radius:16px;width:100%;max-width:520px;\n box-shadow:0 24px 64px rgba(0,0,0,.28);overflow:hidden;\n animation:fl-r-up .22s ease;\n font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;\n font-size:14px;color:#111}\n.fl-r-spinner{width:38px;height:38px;border:3px solid #e5e7eb;\n border-top-color:#f7931a;border-radius:50%;\n animation:fl-r-spin .7s linear infinite;margin:0 auto 14px}\n.fl-r-dot-pending{background:#f59e0b;animation:fl-r-pulse 1.6s ease-in-out infinite}\n.fl-r-dot-confirmed{background:#10b981}\n.fl-r-dot-expired{background:#ef4444}\n.fl-r-xbtn:hover{background:#f3f4f6 !important;color:#111 !important}\n.fl-r-cpbtn:hover{background:#f3f4f6 !important}\n.fl-r-cpbtn-copied{border-color:#10b981 !important;color:#059669 !important}\n@media(max-width:460px){.fl-r-grid{flex-direction:column !important;align-items:center !important}}\n`;\n\nlet _cssInjected = false;\nfunction ensureCSS() {\n if (_cssInjected || typeof document === 'undefined') return;\n _cssInjected = true;\n const el = document.createElement('style');\n el.textContent = MODAL_CSS;\n document.head.appendChild(el);\n}\n\nfunction fmtTime(secs) {\n const m = Math.floor(secs / 60);\n const s = secs % 60;\n return `${String(m).padStart(2, '0')}:${String(s).padStart(2, '0')}`;\n}\n\nexport function ForgeLayerModal({ modalState, order, timeLeft, error, onClose }) {\n const [copied, setCopied] = useState(false);\n\n useEffect(() => { ensureCSS(); }, []);\n\n // Escape key\n useEffect(() => {\n const handler = (e) => { if (e.key === 'Escape') onClose(); };\n document.addEventListener('keydown', handler);\n return () => document.removeEventListener('keydown', handler);\n }, [onClose]);\n\n // Lock body scroll\n useEffect(() => {\n const prev = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n return () => { document.body.style.overflow = prev; };\n }, []);\n\n const copyAddress = () => {\n if (!order?.address) return;\n navigator.clipboard?.writeText(order.address).catch(() => {});\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n };\n\n const urgent = timeLeft !== null && timeLeft <= 120;\n\n return (\n <div\n className=\"fl-r-backdrop\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"Crypto payment\"\n onClick={(e) => { if (e.target === e.currentTarget) onClose(); }}\n >\n <div className=\"fl-r-modal\">\n\n {/* \u2500\u2500 Header \u2500\u2500 */}\n <div style={{\n display: 'flex', alignItems: 'center', justifyContent: 'space-between',\n padding: '16px 18px', borderBottom: '1px solid #e5e7eb', background: '#fafafa',\n }}>\n <div style={{ display: 'flex', alignItems: 'center', gap: 9, fontSize: 15, fontWeight: 700 }}>\n <div style={{\n width: 26, height: 26, background: '#f7931a', borderRadius: 6,\n display: 'flex', alignItems: 'center', justifyContent: 'center',\n color: '#fff', fontSize: 10, fontWeight: 800, flexShrink: 0,\n }}>FL</div>\n Pay with Crypto\n </div>\n <button\n className=\"fl-r-xbtn\"\n onClick={onClose}\n aria-label=\"Close\"\n style={{\n background: 'none', border: 'none', fontSize: 22, lineHeight: 1,\n cursor: 'pointer', color: '#6b7280', padding: '4px 8px',\n borderRadius: 5, transition: 'background .12s',\n }}\n >\u00D7</button>\n </div>\n\n {/* \u2500\u2500 Body \u2500\u2500 */}\n <div style={{ padding: '20px 18px' }}>\n\n {/* Loading */}\n {modalState === 'loading' && (\n <div style={{ textAlign: 'center', padding: '28px 0' }}>\n <div className=\"fl-r-spinner\" />\n <p style={{ color: '#6b7280', fontSize: 13, margin: 0 }}>\n Generating payment address\u2026\n </p>\n </div>\n )}\n\n {/* Error */}\n {modalState === 'error' && (\n <div style={{ textAlign: 'center', padding: '28px 0' }}>\n <div style={{ fontSize: 48, marginBottom: 12 }}>\u26A0\uFE0F</div>\n <div style={{ fontSize: 15, fontWeight: 700, marginBottom: 8 }}>Something went wrong</div>\n <div style={{ fontSize: 13, color: '#6b7280' }}>{error}</div>\n </div>\n )}\n\n {/* Payment */}\n {modalState === 'payment' && order && (\n <>\n {/* Status bar */}\n <div style={{\n display: 'flex', alignItems: 'center', gap: 9,\n padding: '9px 13px', borderRadius: 8,\n background: '#f9fafb', border: '1px solid #e5e7eb',\n marginBottom: 14, fontSize: 13,\n }}>\n <span\n className=\"fl-r-dot-pending\"\n style={{ width: 8, height: 8, borderRadius: '50%', flexShrink: 0 }}\n />\n <span>Awaiting payment\u2026</span>\n <span style={{\n marginLeft: 'auto', fontWeight: 600, fontSize: 13,\n color: urgent ? '#ef4444' : '#374151',\n fontVariantNumeric: 'tabular-nums',\n }}>\n {timeLeft !== null ? fmtTime(timeLeft) : '--:--'}\n </span>\n </div>\n\n {/* Network warning */}\n <div style={{\n background: '#fffbeb', border: '1px solid #fde68a', borderRadius: 8,\n padding: '9px 13px', fontSize: 12, color: '#92400e',\n marginBottom: 14, lineHeight: 1.5,\n }}>\n <strong>\u26A0 Important:</strong> Send only <strong>{order.token}</strong> on the{' '}\n <strong>{order.chainName}</strong> network only. Wrong network = permanent loss.\n </div>\n\n {/* QR + info grid */}\n <div className=\"fl-r-grid\" style={{ display: 'flex', gap: 18, marginBottom: 14 }}>\n {/* QR side */}\n <div style={{ flexShrink: 0, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 6 }}>\n <img\n src={order.qrUrl}\n alt={`Send to ${order.address}`}\n width={148}\n height={148}\n style={{ border: '1px solid #e5e7eb', borderRadius: 10, display: 'block', background: '#f9fafb' }}\n />\n <p style={{ fontSize: 11, color: '#9ca3af', margin: 0 }}>Scan with wallet</p>\n </div>\n\n {/* Info side */}\n <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', gap: 13 }}>\n {/* Amount */}\n <div>\n <label style={{ display: 'block', fontSize: 10, fontWeight: 700, color: '#6b7280', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: 4 }}>\n Amount to Send\n </label>\n <div style={{ fontSize: 22, fontWeight: 700, lineHeight: 1.2 }}>\n {order.cryptoAmount\n ? `${parseFloat(order.cryptoAmount).toFixed(8).replace(/\\.?0+$/, '')} ${order.token}`\n : `${order.currency} ${parseFloat(order.amount).toFixed(2)}`}\n </div>\n {order.cryptoAmount && (\n <div style={{ fontSize: 12, color: '#6b7280', marginTop: 2 }}>\n \u2248 {order.currency} {parseFloat(order.amount).toFixed(2)}\n </div>\n )}\n </div>\n\n {/* Address */}\n <div>\n <label style={{ display: 'block', fontSize: 10, fontWeight: 700, color: '#6b7280', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: 4 }}>\n Deposit Address\n </label>\n <div style={{ display: 'flex', alignItems: 'flex-start', gap: 7 }}>\n <span style={{ fontFamily: 'monospace', fontSize: 12, color: '#374151', wordBreak: 'break-all', flex: 1, lineHeight: 1.5 }}>\n {order.address}\n </span>\n <button\n className={`fl-r-cpbtn${copied ? ' fl-r-cpbtn-copied' : ''}`}\n onClick={copyAddress}\n style={{\n flexShrink: 0, background: '#fff', border: '1px solid #d1d5db',\n borderRadius: 6, padding: '5px 11px', fontSize: 12,\n cursor: 'pointer', color: '#374151',\n transition: 'background .12s', whiteSpace: 'nowrap',\n }}\n >\n {copied ? 'Copied!' : 'Copy'}\n </button>\n </div>\n </div>\n\n {/* Network badge */}\n <div>\n <label style={{ display: 'block', fontSize: 10, fontWeight: 700, color: '#6b7280', textTransform: 'uppercase', letterSpacing: '.06em', marginBottom: 4 }}>\n Network\n </label>\n <span style={{ display: 'inline-flex', alignItems: 'center', gap: 5, padding: '3px 10px', background: '#f3f4f6', borderRadius: 100, fontSize: 12, fontWeight: 500, color: '#374151' }}>\n <span style={{ width: 7, height: 7, borderRadius: '50%', background: '#10b981', flexShrink: 0 }} />\n {order.chainName} \u00B7 {order.token}\n </span>\n </div>\n </div>\n </div>\n </>\n )}\n\n {/* Success */}\n {modalState === 'success' && (\n <div style={{ textAlign: 'center', padding: '30px 16px' }}>\n <div style={{ fontSize: 52, marginBottom: 14 }}>\u2705</div>\n <div style={{ fontSize: 19, fontWeight: 700, color: '#111', marginBottom: 7 }}>Payment Confirmed!</div>\n <div style={{ fontSize: 13, color: '#6b7280' }}>Your payment has been received.</div>\n </div>\n )}\n\n {/* Expired */}\n {modalState === 'expired' && (\n <div style={{ textAlign: 'center', padding: '30px 16px' }}>\n <div style={{ fontSize: 52, marginBottom: 14 }}>\u23F3</div>\n <div style={{ fontSize: 19, fontWeight: 700, color: '#111', marginBottom: 7 }}>Payment Expired</div>\n <div style={{ fontSize: 13, color: '#6b7280' }}>\n The payment window has closed. Please start a new payment.\n </div>\n </div>\n )}\n </div>\n\n {/* \u2500\u2500 Footer \u2500\u2500 */}\n <div style={{ padding: '10px 18px 14px', textAlign: 'center', fontSize: 11, color: '#9ca3af', borderTop: '1px solid #f3f4f6' }}>\n Secured by{' '}\n <a href=\"https://forgelayer.io\" target=\"_blank\" rel=\"noopener noreferrer\" style={{ color: '#f7931a', textDecoration: 'none' }}>\n ForgeLayer\n </a>\n </div>\n </div>\n </div>\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_react", "import_react", "import_jsx_runtime"]
|
|
7
|
+
}
|