@rotateprotocol/sdk 1.0.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/README.md +453 -0
- package/dist/catalog.d.ts +112 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +210 -0
- package/dist/catalog.js.map +1 -0
- package/dist/components/CheckoutForm.d.ts +86 -0
- package/dist/components/CheckoutForm.d.ts.map +1 -0
- package/dist/components/CheckoutForm.js +332 -0
- package/dist/components/CheckoutForm.js.map +1 -0
- package/dist/components/HostedCheckout.d.ts +57 -0
- package/dist/components/HostedCheckout.d.ts.map +1 -0
- package/dist/components/HostedCheckout.js +414 -0
- package/dist/components/HostedCheckout.js.map +1 -0
- package/dist/components/PaymentButton.d.ts +80 -0
- package/dist/components/PaymentButton.d.ts.map +1 -0
- package/dist/components/PaymentButton.js +210 -0
- package/dist/components/PaymentButton.js.map +1 -0
- package/dist/components/RotateProvider.d.ts +115 -0
- package/dist/components/RotateProvider.d.ts.map +1 -0
- package/dist/components/RotateProvider.js +264 -0
- package/dist/components/RotateProvider.js.map +1 -0
- package/dist/components/index.d.ts +17 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +27 -0
- package/dist/components/index.js.map +1 -0
- package/dist/embed.d.ts +85 -0
- package/dist/embed.d.ts.map +1 -0
- package/dist/embed.js +313 -0
- package/dist/embed.js.map +1 -0
- package/dist/hooks.d.ts +156 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +280 -0
- package/dist/hooks.js.map +1 -0
- package/dist/idl/rotate_connect.json +2572 -0
- package/dist/index.d.ts +505 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1197 -0
- package/dist/index.js.map +1 -0
- package/dist/marketplace.d.ts +257 -0
- package/dist/marketplace.d.ts.map +1 -0
- package/dist/marketplace.js +433 -0
- package/dist/marketplace.js.map +1 -0
- package/dist/platform.d.ts +234 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +268 -0
- package/dist/platform.js.map +1 -0
- package/dist/react.d.ts +140 -0
- package/dist/react.d.ts.map +1 -0
- package/dist/react.js +429 -0
- package/dist/react.js.map +1 -0
- package/dist/store.d.ts +213 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +404 -0
- package/dist/store.js.map +1 -0
- package/dist/webhooks.d.ts +149 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +371 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +114 -0
- package/src/catalog.ts +299 -0
- package/src/components/CheckoutForm.tsx +608 -0
- package/src/components/HostedCheckout.tsx +675 -0
- package/src/components/PaymentButton.tsx +348 -0
- package/src/components/RotateProvider.tsx +370 -0
- package/src/components/index.ts +26 -0
- package/src/embed.ts +408 -0
- package/src/hooks.ts +518 -0
- package/src/idl/rotate_connect.json +2572 -0
- package/src/index.ts +1538 -0
- package/src/marketplace.ts +642 -0
- package/src/platform.ts +403 -0
- package/src/react.ts +459 -0
- package/src/store.ts +577 -0
- package/src/webhooks.ts +506 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rotate Protocol React Components
|
|
3
|
+
*
|
|
4
|
+
* Drop-in components for seamless payment integration on Solana.
|
|
5
|
+
*
|
|
6
|
+
* @packageDocumentation
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// Provider
|
|
10
|
+
export { RotateProvider, useRotateContext } from './RotateProvider';
|
|
11
|
+
export type { RotateProviderProps, RotateConfig, RotateContextType, CheckoutSession, CreateCheckoutParams } from './RotateProvider';
|
|
12
|
+
|
|
13
|
+
// Payment Button
|
|
14
|
+
export { PaymentButton } from './PaymentButton';
|
|
15
|
+
export type { PaymentButtonProps, PaymentResult } from './PaymentButton';
|
|
16
|
+
|
|
17
|
+
// Checkout Form
|
|
18
|
+
export { CheckoutForm } from './CheckoutForm';
|
|
19
|
+
export type { CheckoutFormProps } from './CheckoutForm';
|
|
20
|
+
|
|
21
|
+
// Hosted Checkout
|
|
22
|
+
export { HostedCheckout } from './HostedCheckout';
|
|
23
|
+
export type { HostedCheckoutProps } from './HostedCheckout';
|
|
24
|
+
|
|
25
|
+
// Default export for convenience
|
|
26
|
+
export { RotateProvider as default } from './RotateProvider';
|
package/src/embed.ts
ADDED
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rotate Embeddable Widget
|
|
3
|
+
*
|
|
4
|
+
* Add Rotate payments to any website with just a script tag.
|
|
5
|
+
* No React required - works with vanilla HTML/JS.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```html
|
|
9
|
+
* <!-- Add this to your HTML -->
|
|
10
|
+
* <script src="https://js.rotate.app/embed.js"></script>
|
|
11
|
+
*
|
|
12
|
+
* <!-- Simple payment button -->
|
|
13
|
+
* <button data-rotate-pay data-amount="29.99" data-merchant="1000000" data-platform="1000000">
|
|
14
|
+
* Pay $29.99
|
|
15
|
+
* </button>
|
|
16
|
+
*
|
|
17
|
+
* <!-- Or use JavaScript -->
|
|
18
|
+
* <script>
|
|
19
|
+
* Rotate.checkout({
|
|
20
|
+
* amount: 29.99,
|
|
21
|
+
* merchantId: 1000000,
|
|
22
|
+
* platformId: 1000000,
|
|
23
|
+
* onSuccess: (payment) => console.log('Paid!', payment)
|
|
24
|
+
* });
|
|
25
|
+
* </script>
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
// ==================== TYPES ====================
|
|
30
|
+
|
|
31
|
+
interface RotateCheckoutOptions {
|
|
32
|
+
amount: number;
|
|
33
|
+
merchantId: number;
|
|
34
|
+
platformId: number;
|
|
35
|
+
currency?: 'SOL' | 'USDC' | 'USDT' | 'USD';
|
|
36
|
+
description?: string;
|
|
37
|
+
orderRef?: string;
|
|
38
|
+
allowTips?: boolean;
|
|
39
|
+
brandName?: string;
|
|
40
|
+
brandLogo?: string;
|
|
41
|
+
brandColor?: string;
|
|
42
|
+
successUrl?: string;
|
|
43
|
+
cancelUrl?: string;
|
|
44
|
+
popup?: boolean;
|
|
45
|
+
onSuccess?: (payment: PaymentResult) => void;
|
|
46
|
+
onCancel?: () => void;
|
|
47
|
+
onError?: (error: Error) => void;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
interface PaymentResult {
|
|
51
|
+
linkId: number;
|
|
52
|
+
amount: number;
|
|
53
|
+
currency: string;
|
|
54
|
+
transactionId: string;
|
|
55
|
+
paidAt: number;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface RotateButtonOptions extends RotateCheckoutOptions {
|
|
59
|
+
element: HTMLElement;
|
|
60
|
+
label?: string;
|
|
61
|
+
size?: 'sm' | 'md' | 'lg';
|
|
62
|
+
variant?: 'solid' | 'outline' | 'ghost';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ==================== STYLES ====================
|
|
66
|
+
|
|
67
|
+
const BUTTON_BASE_STYLES = `
|
|
68
|
+
display: inline-flex;
|
|
69
|
+
align-items: center;
|
|
70
|
+
justify-content: center;
|
|
71
|
+
gap: 8px;
|
|
72
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
73
|
+
font-weight: 600;
|
|
74
|
+
border: none;
|
|
75
|
+
cursor: pointer;
|
|
76
|
+
transition: all 0.2s ease;
|
|
77
|
+
position: relative;
|
|
78
|
+
overflow: hidden;
|
|
79
|
+
`;
|
|
80
|
+
|
|
81
|
+
const BUTTON_SIZES: Record<string, string> = {
|
|
82
|
+
sm: 'padding: 8px 16px; font-size: 14px; border-radius: 6px;',
|
|
83
|
+
md: 'padding: 12px 24px; font-size: 16px; border-radius: 8px;',
|
|
84
|
+
lg: 'padding: 16px 32px; font-size: 18px; border-radius: 10px;',
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const SPINNER_CSS = `
|
|
88
|
+
@keyframes rotate-spin {
|
|
89
|
+
from { transform: rotate(0deg); }
|
|
90
|
+
to { transform: rotate(360deg); }
|
|
91
|
+
}
|
|
92
|
+
`;
|
|
93
|
+
|
|
94
|
+
// ==================== UTILITY FUNCTIONS ====================
|
|
95
|
+
|
|
96
|
+
function adjustColor(hex: string, percent: number): string {
|
|
97
|
+
const num = parseInt(hex.replace('#', ''), 16);
|
|
98
|
+
const amt = Math.round(2.55 * percent);
|
|
99
|
+
const R = (num >> 16) + amt;
|
|
100
|
+
const G = (num >> 8 & 0x00FF) + amt;
|
|
101
|
+
const B = (num & 0x0000FF) + amt;
|
|
102
|
+
return '#' + (
|
|
103
|
+
0x1000000 +
|
|
104
|
+
(R < 255 ? R < 1 ? 0 : R : 255) * 0x10000 +
|
|
105
|
+
(G < 255 ? G < 1 ? 0 : G : 255) * 0x100 +
|
|
106
|
+
(B < 255 ? B < 1 ? 0 : B : 255)
|
|
107
|
+
).toString(16).slice(1);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function createSpinner(): string {
|
|
111
|
+
return `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="animation: rotate-spin 1s linear infinite;">
|
|
112
|
+
<circle cx="12" cy="12" r="10" stroke-opacity="0.25"/>
|
|
113
|
+
<path d="M12 2a10 10 0 0 1 10 10" stroke-linecap="round"/>
|
|
114
|
+
</svg>`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function createWalletIcon(): string {
|
|
118
|
+
return `<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
119
|
+
<path d="M21 12V7H5a2 2 0 0 1 0-4h14v4"/>
|
|
120
|
+
<path d="M3 5v14a2 2 0 0 0 2 2h16v-5"/>
|
|
121
|
+
<path d="M18 12a2 2 0 0 0 0 4h4v-4h-4z"/>
|
|
122
|
+
</svg>`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ==================== MAIN ROTATE OBJECT ====================
|
|
126
|
+
|
|
127
|
+
const Rotate = {
|
|
128
|
+
// Configuration
|
|
129
|
+
_config: {
|
|
130
|
+
baseUrl: 'https://rotate.app',
|
|
131
|
+
network: 'mainnet-beta' as 'devnet' | 'mainnet-beta',
|
|
132
|
+
},
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Configure Rotate settings
|
|
136
|
+
*/
|
|
137
|
+
configure(options: { baseUrl?: string; network?: 'devnet' | 'mainnet-beta' }) {
|
|
138
|
+
if (options.baseUrl) this._config.baseUrl = options.baseUrl;
|
|
139
|
+
if (options.network) this._config.network = options.network;
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Open checkout popup/redirect
|
|
144
|
+
*/
|
|
145
|
+
checkout(options: RotateCheckoutOptions) {
|
|
146
|
+
const {
|
|
147
|
+
amount,
|
|
148
|
+
merchantId,
|
|
149
|
+
platformId,
|
|
150
|
+
currency = 'USD',
|
|
151
|
+
description,
|
|
152
|
+
orderRef,
|
|
153
|
+
allowTips,
|
|
154
|
+
brandName,
|
|
155
|
+
brandLogo,
|
|
156
|
+
brandColor = '#8B5CF6',
|
|
157
|
+
successUrl,
|
|
158
|
+
cancelUrl,
|
|
159
|
+
popup = true,
|
|
160
|
+
onSuccess,
|
|
161
|
+
onCancel,
|
|
162
|
+
onError,
|
|
163
|
+
} = options;
|
|
164
|
+
|
|
165
|
+
// Build checkout URL
|
|
166
|
+
const params = new URLSearchParams({
|
|
167
|
+
amount: amount.toString(),
|
|
168
|
+
merchant: merchantId.toString(),
|
|
169
|
+
platform: platformId.toString(),
|
|
170
|
+
currency,
|
|
171
|
+
network: this._config.network,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
if (description) params.set('description', description);
|
|
175
|
+
if (orderRef) params.set('ref', orderRef);
|
|
176
|
+
if (allowTips) params.set('tips', '1');
|
|
177
|
+
if (brandName) params.set('brand', brandName);
|
|
178
|
+
if (brandLogo) params.set('logo', brandLogo);
|
|
179
|
+
if (brandColor) params.set('color', brandColor.replace('#', ''));
|
|
180
|
+
if (successUrl) params.set('success', successUrl);
|
|
181
|
+
if (cancelUrl) params.set('cancel', cancelUrl);
|
|
182
|
+
|
|
183
|
+
const checkoutUrl = `${this._config.baseUrl}/checkout?${params.toString()}`;
|
|
184
|
+
|
|
185
|
+
if (popup) {
|
|
186
|
+
// Open popup window
|
|
187
|
+
const width = 450;
|
|
188
|
+
const height = 700;
|
|
189
|
+
const left = window.screenX + (window.outerWidth - width) / 2;
|
|
190
|
+
const top = window.screenY + (window.outerHeight - height) / 2;
|
|
191
|
+
|
|
192
|
+
const popupWindow = window.open(
|
|
193
|
+
checkoutUrl,
|
|
194
|
+
'rotate_checkout',
|
|
195
|
+
`width=${width},height=${height},left=${left},top=${top},popup=1`
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
if (popupWindow) {
|
|
199
|
+
// Listen for popup messages
|
|
200
|
+
const messageHandler = (event: MessageEvent) => {
|
|
201
|
+
if (event.data?.type === 'rotate_payment_success') {
|
|
202
|
+
onSuccess?.(event.data.payment);
|
|
203
|
+
window.removeEventListener('message', messageHandler);
|
|
204
|
+
} else if (event.data?.type === 'rotate_payment_cancel') {
|
|
205
|
+
onCancel?.();
|
|
206
|
+
window.removeEventListener('message', messageHandler);
|
|
207
|
+
} else if (event.data?.type === 'rotate_payment_error') {
|
|
208
|
+
onError?.(new Error(event.data.message));
|
|
209
|
+
window.removeEventListener('message', messageHandler);
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
window.addEventListener('message', messageHandler);
|
|
214
|
+
|
|
215
|
+
// Check if popup closed without completing
|
|
216
|
+
const checkClosed = setInterval(() => {
|
|
217
|
+
if (popupWindow.closed) {
|
|
218
|
+
clearInterval(checkClosed);
|
|
219
|
+
window.removeEventListener('message', messageHandler);
|
|
220
|
+
}
|
|
221
|
+
}, 500);
|
|
222
|
+
}
|
|
223
|
+
} else {
|
|
224
|
+
// Redirect
|
|
225
|
+
window.location.href = checkoutUrl;
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Create a payment button
|
|
231
|
+
*/
|
|
232
|
+
createButton(options: RotateButtonOptions) {
|
|
233
|
+
const {
|
|
234
|
+
element,
|
|
235
|
+
amount,
|
|
236
|
+
merchantId,
|
|
237
|
+
platformId,
|
|
238
|
+
currency = 'USD',
|
|
239
|
+
label,
|
|
240
|
+
size = 'md',
|
|
241
|
+
variant = 'solid',
|
|
242
|
+
brandColor = '#8B5CF6',
|
|
243
|
+
onSuccess,
|
|
244
|
+
onCancel,
|
|
245
|
+
onError,
|
|
246
|
+
...checkoutOptions
|
|
247
|
+
} = options;
|
|
248
|
+
|
|
249
|
+
// Inject styles
|
|
250
|
+
if (!document.getElementById('rotate-styles')) {
|
|
251
|
+
const style = document.createElement('style');
|
|
252
|
+
style.id = 'rotate-styles';
|
|
253
|
+
style.textContent = SPINNER_CSS;
|
|
254
|
+
document.head.appendChild(style);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Format amount
|
|
258
|
+
const formattedAmount = currency === 'SOL'
|
|
259
|
+
? `${amount} SOL`
|
|
260
|
+
: `$${amount.toFixed(2)}`;
|
|
261
|
+
|
|
262
|
+
const buttonLabel = label || `Pay ${formattedAmount}`;
|
|
263
|
+
|
|
264
|
+
// Build styles
|
|
265
|
+
let buttonStyles = BUTTON_BASE_STYLES + BUTTON_SIZES[size];
|
|
266
|
+
|
|
267
|
+
if (variant === 'solid') {
|
|
268
|
+
buttonStyles += `
|
|
269
|
+
background: linear-gradient(135deg, ${brandColor} 0%, ${adjustColor(brandColor, -20)} 100%);
|
|
270
|
+
color: #ffffff;
|
|
271
|
+
box-shadow: 0 4px 14px ${brandColor}40;
|
|
272
|
+
`;
|
|
273
|
+
} else if (variant === 'outline') {
|
|
274
|
+
buttonStyles += `
|
|
275
|
+
background: transparent;
|
|
276
|
+
color: ${brandColor};
|
|
277
|
+
border: 2px solid ${brandColor};
|
|
278
|
+
`;
|
|
279
|
+
} else {
|
|
280
|
+
buttonStyles += `
|
|
281
|
+
background: ${brandColor}15;
|
|
282
|
+
color: ${brandColor};
|
|
283
|
+
`;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Create button
|
|
287
|
+
const button = document.createElement('button');
|
|
288
|
+
button.setAttribute('style', buttonStyles);
|
|
289
|
+
button.innerHTML = `${createWalletIcon()}<span>${buttonLabel}</span>`;
|
|
290
|
+
button.className = 'rotate-pay-button';
|
|
291
|
+
|
|
292
|
+
// Add hover effect
|
|
293
|
+
button.addEventListener('mouseenter', () => {
|
|
294
|
+
button.style.transform = 'translateY(-2px)';
|
|
295
|
+
button.style.filter = 'brightness(1.1)';
|
|
296
|
+
});
|
|
297
|
+
button.addEventListener('mouseleave', () => {
|
|
298
|
+
button.style.transform = 'translateY(0)';
|
|
299
|
+
button.style.filter = 'brightness(1)';
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
// Handle click
|
|
303
|
+
let loading = false;
|
|
304
|
+
button.addEventListener('click', () => {
|
|
305
|
+
if (loading) return;
|
|
306
|
+
|
|
307
|
+
loading = true;
|
|
308
|
+
button.innerHTML = `${createSpinner()}<span>Processing...</span>`;
|
|
309
|
+
button.style.cursor = 'wait';
|
|
310
|
+
|
|
311
|
+
this.checkout({
|
|
312
|
+
amount,
|
|
313
|
+
merchantId,
|
|
314
|
+
platformId,
|
|
315
|
+
currency,
|
|
316
|
+
brandColor,
|
|
317
|
+
...checkoutOptions,
|
|
318
|
+
onSuccess: (payment) => {
|
|
319
|
+
loading = false;
|
|
320
|
+
button.innerHTML = `<span>✓ Paid!</span>`;
|
|
321
|
+
button.style.background = '#10B981';
|
|
322
|
+
button.style.cursor = 'pointer';
|
|
323
|
+
onSuccess?.(payment);
|
|
324
|
+
|
|
325
|
+
// Reset after delay
|
|
326
|
+
setTimeout(() => {
|
|
327
|
+
button.innerHTML = `${createWalletIcon()}<span>${buttonLabel}</span>`;
|
|
328
|
+
button.style.background = variant === 'solid'
|
|
329
|
+
? `linear-gradient(135deg, ${brandColor} 0%, ${adjustColor(brandColor, -20)} 100%)`
|
|
330
|
+
: variant === 'outline' ? 'transparent' : `${brandColor}15`;
|
|
331
|
+
}, 3000);
|
|
332
|
+
},
|
|
333
|
+
onCancel: () => {
|
|
334
|
+
loading = false;
|
|
335
|
+
button.innerHTML = `${createWalletIcon()}<span>${buttonLabel}</span>`;
|
|
336
|
+
button.style.cursor = 'pointer';
|
|
337
|
+
onCancel?.();
|
|
338
|
+
},
|
|
339
|
+
onError: (error) => {
|
|
340
|
+
loading = false;
|
|
341
|
+
button.innerHTML = `${createWalletIcon()}<span>${buttonLabel}</span>`;
|
|
342
|
+
button.style.cursor = 'pointer';
|
|
343
|
+
onError?.(error);
|
|
344
|
+
},
|
|
345
|
+
});
|
|
346
|
+
});
|
|
347
|
+
|
|
348
|
+
// Replace element content
|
|
349
|
+
element.innerHTML = '';
|
|
350
|
+
element.appendChild(button);
|
|
351
|
+
|
|
352
|
+
return button;
|
|
353
|
+
},
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Auto-initialize buttons from data attributes
|
|
357
|
+
*/
|
|
358
|
+
init() {
|
|
359
|
+
// Find all elements with data-rotate-pay
|
|
360
|
+
const buttons = document.querySelectorAll('[data-rotate-pay]');
|
|
361
|
+
|
|
362
|
+
buttons.forEach((element) => {
|
|
363
|
+
const el = element as HTMLElement;
|
|
364
|
+
|
|
365
|
+
const amount = parseFloat(el.dataset.amount || '0');
|
|
366
|
+
const merchantId = parseInt(el.dataset.merchant || '0');
|
|
367
|
+
const platformId = parseInt(el.dataset.platform || '0');
|
|
368
|
+
|
|
369
|
+
if (!amount || !merchantId || !platformId) {
|
|
370
|
+
console.warn('Rotate: Missing required data attributes (amount, merchant, platform)', el);
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
this.createButton({
|
|
375
|
+
element: el,
|
|
376
|
+
amount,
|
|
377
|
+
merchantId,
|
|
378
|
+
platformId,
|
|
379
|
+
currency: (el.dataset.currency as any) || 'USD',
|
|
380
|
+
label: el.dataset.label || el.textContent?.trim(),
|
|
381
|
+
size: (el.dataset.size as any) || 'md',
|
|
382
|
+
variant: (el.dataset.variant as any) || 'solid',
|
|
383
|
+
brandColor: el.dataset.color || '#8B5CF6',
|
|
384
|
+
brandName: el.dataset.brand,
|
|
385
|
+
description: el.dataset.description,
|
|
386
|
+
orderRef: el.dataset.ref,
|
|
387
|
+
allowTips: el.dataset.tips === 'true',
|
|
388
|
+
successUrl: el.dataset.successUrl,
|
|
389
|
+
cancelUrl: el.dataset.cancelUrl,
|
|
390
|
+
popup: el.dataset.popup !== 'false',
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
},
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
// Auto-initialize on DOMContentLoaded
|
|
397
|
+
if (typeof window !== 'undefined') {
|
|
398
|
+
if (document.readyState === 'loading') {
|
|
399
|
+
document.addEventListener('DOMContentLoaded', () => Rotate.init());
|
|
400
|
+
} else {
|
|
401
|
+
Rotate.init();
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// Expose globally
|
|
405
|
+
(window as any).Rotate = Rotate;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
export default Rotate;
|