@gait-financial/react 0.1.11 → 0.1.13
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 +25 -84
- package/dist/index.cjs +97 -175
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -24
- package/dist/index.d.ts +0 -24
- package/dist/index.js +98 -182
- package/dist/index.js.map +1 -1
- package/dist/register.cjs +17 -34
- package/dist/register.cjs.map +1 -1
- package/dist/register.d.cts +2 -16
- package/dist/register.d.ts +2 -16
- package/dist/register.js +17 -34
- package/dist/register.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
# @gait-financial/react
|
|
2
2
|
|
|
3
|
-
React
|
|
3
|
+
React wrapper for Gait Web Components. Use `<GaitButton>` with `data-id` and optional props for checkout/split payment.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Installation
|
|
5
|
+
## Install
|
|
8
6
|
|
|
9
7
|
```bash
|
|
10
8
|
npm install @gait-financial/react
|
|
@@ -12,103 +10,46 @@ npm install @gait-financial/react
|
|
|
12
10
|
|
|
13
11
|
## Setup
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
Import the registration module once (e.g. in `_app.tsx`, `layout.tsx`, or your root component):
|
|
13
|
+
**1. Register once** (e.g. in your root or layout):
|
|
18
14
|
|
|
19
15
|
```tsx
|
|
20
16
|
import '@gait-financial/react/register';
|
|
21
17
|
```
|
|
22
18
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
**Alternative:** Load the Web Component via script tag and skip the register import:
|
|
26
|
-
|
|
27
|
-
```html
|
|
28
|
-
<script src="https://cdn.usegait.com/button.js"></script>
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### 2. Use the Components
|
|
19
|
+
**2. Use the component:**
|
|
32
20
|
|
|
33
21
|
```tsx
|
|
34
22
|
import { GaitButton } from '@gait-financial/react';
|
|
35
23
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
onClick={(detail) => console.log('Clicked', detail)}
|
|
42
|
-
onSplitFeedback={(detail) => {
|
|
43
|
-
if (detail.success) console.log('Split sent!');
|
|
44
|
-
else console.error('Failed', detail.error);
|
|
45
|
-
}}
|
|
46
|
-
/>
|
|
47
|
-
);
|
|
48
|
-
}
|
|
24
|
+
<GaitButton
|
|
25
|
+
data-id="your-checkout-id"
|
|
26
|
+
totalCost={99.99}
|
|
27
|
+
onSplitFeedback={(d) => console.log(d.success ? 'OK' : d.error)}
|
|
28
|
+
/>
|
|
49
29
|
```
|
|
50
30
|
|
|
51
|
-
## GaitButton Props
|
|
52
|
-
|
|
53
|
-
| Prop | Type | Description |
|
|
54
|
-
|------|------|-------------|
|
|
55
|
-
| `data-id` | `string` | Checkout/data identity (required for payments) |
|
|
56
|
-
| `disabled` | `boolean` | Disable the button |
|
|
57
|
-
| `size` | `'small' \| 'medium' \| 'large'` | Button size |
|
|
58
|
-
| `style` | `string \| React.CSSProperties` | Inline styles |
|
|
59
|
-
| `items` | `GaitButtonItem[] \| string` | Cart items for split payment modal |
|
|
60
|
-
| `priceBreakdown` | `GaitPriceBreakdownItem[] \| string` | Price breakdown |
|
|
61
|
-
| `totalCost` | `number \| string` | Total cost |
|
|
62
|
-
| `customer` | `GaitCustomer \| string` | Customer info for split payment |
|
|
63
|
-
| `webhook` | `GaitWebhook \| string` | Webhook config for split callbacks |
|
|
64
|
-
| `merchantStoreUrl` | `string` | Merchant store URL |
|
|
65
|
-
| `onClick` | `(detail) => void` | Button clicked |
|
|
66
|
-
| `onLoaded` | `(detail) => void` | Component loaded |
|
|
67
|
-
| `onDataProcessed` | `(detail) => void` | Data processed |
|
|
68
|
-
| `onSplitFeedback` | `(detail) => void` | Split payment API result |
|
|
69
|
-
| `onMerchantIdError` | `(detail) => void` | Merchant ID lookup failed |
|
|
70
|
-
| `onConfirm` | `(detail) => void` | Pay remaining confirmed |
|
|
71
|
-
|
|
72
|
-
The button label is always **"Gait"** (with icon). Brand color is fixed to **#4147BF**; split-option styling uses **#F3F2FF**.
|
|
73
|
-
|
|
74
31
|
## Vite
|
|
75
32
|
|
|
76
|
-
|
|
33
|
+
Add to `vite.config.ts` so the web component script loads:
|
|
77
34
|
|
|
78
35
|
```ts
|
|
79
|
-
|
|
80
|
-
optimizeDeps: {
|
|
81
|
-
exclude: ['@gait-financial/react'],
|
|
82
|
-
},
|
|
83
|
-
// ...
|
|
84
|
-
});
|
|
36
|
+
optimizeDeps: { exclude: ['@gait-financial/react'] },
|
|
85
37
|
```
|
|
86
38
|
|
|
87
|
-
##
|
|
88
|
-
|
|
89
|
-
The package uses `"use client"` directives. Import and use in Client Components:
|
|
90
|
-
|
|
91
|
-
```tsx
|
|
92
|
-
'use client';
|
|
93
|
-
|
|
94
|
-
import '@gait-financial/react/register';
|
|
95
|
-
import { GaitButton } from '@gait-financial/react';
|
|
96
|
-
|
|
97
|
-
export default function CheckoutPage() {
|
|
98
|
-
return <GaitButton data-id="your-checkout-id" />;
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## Architecture
|
|
103
|
-
|
|
104
|
-
This package is a thin wrapper. The Web Component implementation is the source of truth. The structure allows adding other framework packages (e.g. `@gait/vue`, `@gait/svelte`) later without refactoring the core.
|
|
39
|
+
## Builds (from repo root)
|
|
105
40
|
|
|
106
|
-
|
|
41
|
+
- **Production:** `npm run publish:react` — builds WC + React package, publishes to `latest`
|
|
42
|
+
- **Staging:** `npm run publish:react:staging` — builds with `.env.staging`, publishes with tag `staging`
|
|
43
|
+
From `packages/react`: `npm run publish:staging`
|
|
107
44
|
|
|
108
|
-
|
|
45
|
+
## Props
|
|
109
46
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
47
|
+
| Prop | Description |
|
|
48
|
+
|------|-------------|
|
|
49
|
+
| `data-id` | Checkout identity (required for payments) |
|
|
50
|
+
| `totalCost` | Total amount |
|
|
51
|
+
| `items` | Cart items for split payment |
|
|
52
|
+
| `customer` | `{ email, name? }` |
|
|
53
|
+
| `webhook` | `{ url, body? }` for split callbacks |
|
|
54
|
+
| `disabled`, `size`, `style` | Button options |
|
|
55
|
+
| `onClick`, `onLoaded`, `onDataProcessed`, `onSplitFeedback`, `onMerchantIdError`, `onConfirm` | Event callbacks |
|
package/dist/index.cjs
CHANGED
|
@@ -41,45 +41,28 @@ var import_react = __toESM(require("react"), 1);
|
|
|
41
41
|
// src/register.ts
|
|
42
42
|
var import_meta = {};
|
|
43
43
|
var loadPromise = null;
|
|
44
|
-
|
|
45
|
-
if (typeof window === "undefined" || typeof customElements === "undefined")
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
44
|
+
function defineCustomElements(scriptUrl) {
|
|
45
|
+
if (typeof window === "undefined" || typeof customElements === "undefined") return Promise.resolve();
|
|
46
|
+
if (customElements.get("gait-button")) return Promise.resolve();
|
|
47
|
+
if (loadPromise) return loadPromise;
|
|
48
|
+
loadPromise = new Promise((resolve, reject) => {
|
|
49
|
+
let src;
|
|
50
|
+
if (scriptUrl) src = scriptUrl;
|
|
51
|
+
else {
|
|
52
|
+
try {
|
|
53
|
+
src = new URL("./wc/button.js", import_meta.url).href;
|
|
54
|
+
} catch {
|
|
55
|
+
reject(new Error('[@gait-financial/react] Could not resolve script. With Vite, add optimizeDeps: { exclude: ["@gait-financial/react"] } to vite.config.'));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
55
59
|
const script = document.createElement("script");
|
|
56
60
|
script.async = true;
|
|
57
|
-
script.src =
|
|
61
|
+
script.src = src;
|
|
58
62
|
script.onload = () => resolve();
|
|
59
|
-
script.onerror = () => reject();
|
|
63
|
+
script.onerror = () => reject(new Error("[@gait-financial/react] Failed to load web component."));
|
|
60
64
|
document.head.appendChild(script);
|
|
61
65
|
});
|
|
62
|
-
loadPromise = (async () => {
|
|
63
|
-
const fallbackUrl = `${typeof window !== "undefined" ? window.location.origin : ""}/node_modules/@gait-financial/react/dist/wc/button.js`;
|
|
64
|
-
if (scriptUrl) {
|
|
65
|
-
await tryLoad(scriptUrl);
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
try {
|
|
69
|
-
const url = new URL("./wc/button.js", import_meta.url).href;
|
|
70
|
-
await tryLoad(url);
|
|
71
|
-
return;
|
|
72
|
-
} catch {
|
|
73
|
-
}
|
|
74
|
-
try {
|
|
75
|
-
await tryLoad(fallbackUrl);
|
|
76
|
-
return;
|
|
77
|
-
} catch {
|
|
78
|
-
throw new Error(
|
|
79
|
-
'[@gait-financial/react] Failed to load web component script. If using Vite, add optimizeDeps: { exclude: ["@gait-financial/react"] } to vite.config.'
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
})();
|
|
83
66
|
return loadPromise;
|
|
84
67
|
}
|
|
85
68
|
if (typeof window !== "undefined" && typeof customElements !== "undefined") {
|
|
@@ -87,85 +70,33 @@ if (typeof window !== "undefined" && typeof customElements !== "undefined") {
|
|
|
87
70
|
}
|
|
88
71
|
|
|
89
72
|
// src/components/GaitButton.tsx
|
|
90
|
-
var
|
|
91
|
-
"
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
webhook,
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
defineCustomElements().then(() => setIsReady(true)).catch(() => setIsReady(false));
|
|
120
|
-
}, []);
|
|
121
|
-
(0, import_react.useEffect)(() => {
|
|
122
|
-
const el = elementRef.current;
|
|
123
|
-
if (!el) return;
|
|
124
|
-
if (dataId !== void 0) el.setAttribute("data-id", dataId);
|
|
125
|
-
if (size !== void 0) el.setAttribute("size", size);
|
|
126
|
-
if (disabled) {
|
|
127
|
-
el.setAttribute("disabled", "");
|
|
128
|
-
} else {
|
|
129
|
-
el.removeAttribute("disabled");
|
|
130
|
-
}
|
|
131
|
-
if (style !== void 0) {
|
|
132
|
-
const styleStr = typeof style === "string" ? style : Object.entries(style).map(
|
|
133
|
-
([k, v]) => `${k.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${v}`
|
|
134
|
-
).join("; ");
|
|
135
|
-
el.setAttribute("style", styleStr);
|
|
136
|
-
}
|
|
137
|
-
if (items !== void 0) {
|
|
138
|
-
el.setAttribute(
|
|
139
|
-
"items",
|
|
140
|
-
typeof items === "string" ? items : JSON.stringify(items)
|
|
141
|
-
);
|
|
142
|
-
}
|
|
143
|
-
if (priceBreakdown !== void 0) {
|
|
144
|
-
el.setAttribute(
|
|
145
|
-
"price-breakdown",
|
|
146
|
-
typeof priceBreakdown === "string" ? priceBreakdown : JSON.stringify(priceBreakdown)
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
if (totalCost !== void 0) {
|
|
150
|
-
el.setAttribute("total-cost", String(totalCost));
|
|
151
|
-
}
|
|
152
|
-
if (customer !== void 0) {
|
|
153
|
-
el.setAttribute(
|
|
154
|
-
"customer",
|
|
155
|
-
typeof customer === "string" ? customer : JSON.stringify(customer)
|
|
156
|
-
);
|
|
157
|
-
}
|
|
158
|
-
if (webhook !== void 0) {
|
|
159
|
-
el.setAttribute(
|
|
160
|
-
"webhook",
|
|
161
|
-
typeof webhook === "string" ? webhook : JSON.stringify(webhook)
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
if (merchantStoreUrl !== void 0) {
|
|
165
|
-
el.setAttribute("merchant-store-url", merchantStoreUrl);
|
|
166
|
-
}
|
|
167
|
-
}, [
|
|
168
|
-
dataId,
|
|
73
|
+
var EVENT_HANDLERS = [
|
|
74
|
+
{ event: "gait-click", key: "onClick" },
|
|
75
|
+
{ event: "gait-loaded", key: "onLoaded" },
|
|
76
|
+
{ event: "gait-data-processed", key: "onDataProcessed" },
|
|
77
|
+
{ event: "gait-split-feedback", key: "onSplitFeedback" },
|
|
78
|
+
{ event: "gait-merchant-id-error", key: "onMerchantIdError" },
|
|
79
|
+
{ event: "gait-confirm", key: "onConfirm" }
|
|
80
|
+
];
|
|
81
|
+
function applyAttributes(el, props) {
|
|
82
|
+
const { "data-id": dataId, disabled, size, style, items, priceBreakdown, totalCost, customer, webhook, merchantStoreUrl } = props;
|
|
83
|
+
if (dataId !== void 0) el.setAttribute("data-id", dataId);
|
|
84
|
+
if (size !== void 0) el.setAttribute("size", size);
|
|
85
|
+
disabled ? el.setAttribute("disabled", "") : el.removeAttribute("disabled");
|
|
86
|
+
if (style !== void 0) {
|
|
87
|
+
const s = typeof style === "string" ? style : Object.entries(style).map(([k, v]) => `${k.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${v}`).join("; ");
|
|
88
|
+
el.setAttribute("style", s);
|
|
89
|
+
}
|
|
90
|
+
if (items !== void 0) el.setAttribute("items", typeof items === "string" ? items : JSON.stringify(items));
|
|
91
|
+
if (priceBreakdown !== void 0) el.setAttribute("price-breakdown", typeof priceBreakdown === "string" ? priceBreakdown : JSON.stringify(priceBreakdown));
|
|
92
|
+
if (totalCost !== void 0) el.setAttribute("total-cost", String(totalCost));
|
|
93
|
+
if (customer !== void 0) el.setAttribute("customer", typeof customer === "string" ? customer : JSON.stringify(customer));
|
|
94
|
+
if (webhook !== void 0) el.setAttribute("webhook", typeof webhook === "string" ? webhook : JSON.stringify(webhook));
|
|
95
|
+
if (merchantStoreUrl !== void 0) el.setAttribute("merchant-store-url", merchantStoreUrl);
|
|
96
|
+
}
|
|
97
|
+
var GaitButton = (0, import_react.forwardRef)(function GaitButton2(props, ref) {
|
|
98
|
+
const {
|
|
99
|
+
"data-id": dataId,
|
|
169
100
|
disabled,
|
|
170
101
|
size,
|
|
171
102
|
style,
|
|
@@ -174,73 +105,64 @@ var GaitButton = (0, import_react.forwardRef)(function GaitButton2({
|
|
|
174
105
|
totalCost,
|
|
175
106
|
customer,
|
|
176
107
|
webhook,
|
|
177
|
-
merchantStoreUrl
|
|
178
|
-
]);
|
|
179
|
-
(0, import_react.useEffect)(() => {
|
|
180
|
-
const el = elementRef.current;
|
|
181
|
-
if (!el) return;
|
|
182
|
-
const handleClick = (e) => {
|
|
183
|
-
if (onClick && e instanceof CustomEvent && e.detail) {
|
|
184
|
-
onClick(e.detail);
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
const handleLoaded = (e) => {
|
|
188
|
-
if (onLoaded && e instanceof CustomEvent && e.detail) {
|
|
189
|
-
onLoaded(e.detail);
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
const handleDataProcessed = (e) => {
|
|
193
|
-
if (onDataProcessed && e instanceof CustomEvent && e.detail) {
|
|
194
|
-
onDataProcessed(e.detail);
|
|
195
|
-
}
|
|
196
|
-
};
|
|
197
|
-
const handleSplitFeedback = (e) => {
|
|
198
|
-
if (onSplitFeedback && e instanceof CustomEvent && e.detail) {
|
|
199
|
-
onSplitFeedback(e.detail);
|
|
200
|
-
}
|
|
201
|
-
};
|
|
202
|
-
const handleMerchantIdError = (e) => {
|
|
203
|
-
if (onMerchantIdError && e instanceof CustomEvent && e.detail) {
|
|
204
|
-
onMerchantIdError(e.detail);
|
|
205
|
-
}
|
|
206
|
-
};
|
|
207
|
-
const handleConfirm = (e) => {
|
|
208
|
-
if (onConfirm && e instanceof CustomEvent && e.detail) {
|
|
209
|
-
onConfirm(e.detail);
|
|
210
|
-
}
|
|
211
|
-
};
|
|
212
|
-
el.addEventListener("gait-click", handleClick);
|
|
213
|
-
el.addEventListener("gait-loaded", handleLoaded);
|
|
214
|
-
el.addEventListener("gait-data-processed", handleDataProcessed);
|
|
215
|
-
el.addEventListener("gait-split-feedback", handleSplitFeedback);
|
|
216
|
-
el.addEventListener("gait-merchant-id-error", handleMerchantIdError);
|
|
217
|
-
el.addEventListener("gait-confirm", handleConfirm);
|
|
218
|
-
return () => {
|
|
219
|
-
el.removeEventListener("gait-click", handleClick);
|
|
220
|
-
el.removeEventListener("gait-loaded", handleLoaded);
|
|
221
|
-
el.removeEventListener("gait-data-processed", handleDataProcessed);
|
|
222
|
-
el.removeEventListener("gait-split-feedback", handleSplitFeedback);
|
|
223
|
-
el.removeEventListener("gait-merchant-id-error", handleMerchantIdError);
|
|
224
|
-
el.removeEventListener("gait-confirm", handleConfirm);
|
|
225
|
-
};
|
|
226
|
-
}, [
|
|
108
|
+
merchantStoreUrl,
|
|
227
109
|
onClick,
|
|
228
110
|
onLoaded,
|
|
229
111
|
onDataProcessed,
|
|
230
112
|
onSplitFeedback,
|
|
231
113
|
onMerchantIdError,
|
|
232
|
-
onConfirm
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
114
|
+
onConfirm,
|
|
115
|
+
className,
|
|
116
|
+
id
|
|
117
|
+
} = props;
|
|
118
|
+
const containerRef = (0, import_react.useRef)(null);
|
|
119
|
+
const elementRef = (0, import_react.useRef)(null);
|
|
120
|
+
const [ready, setReady] = (0, import_react.useState)(false);
|
|
121
|
+
const callbacksRef = (0, import_react.useRef)({ onClick, onLoaded, onDataProcessed, onSplitFeedback, onMerchantIdError, onConfirm });
|
|
122
|
+
callbacksRef.current = { onClick, onLoaded, onDataProcessed, onSplitFeedback, onMerchantIdError, onConfirm };
|
|
123
|
+
(0, import_react.useImperativeHandle)(ref, () => elementRef.current, []);
|
|
124
|
+
(0, import_react.useEffect)(() => {
|
|
125
|
+
if (typeof customElements !== "undefined" && customElements.get("gait-button")) {
|
|
126
|
+
setReady(true);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
defineCustomElements().then(() => setReady(true), () => setReady(false));
|
|
130
|
+
}, []);
|
|
131
|
+
(0, import_react.useEffect)(() => {
|
|
132
|
+
if (!ready || !containerRef.current) return;
|
|
133
|
+
const container = containerRef.current;
|
|
134
|
+
const el = document.createElement("gait-button");
|
|
135
|
+
applyAttributes(el, { "data-id": dataId, disabled, size, style, items, priceBreakdown, totalCost, customer, webhook, merchantStoreUrl });
|
|
136
|
+
if (className) el.className = className;
|
|
137
|
+
if (id) el.id = id;
|
|
138
|
+
const listeners = [];
|
|
139
|
+
EVENT_HANDLERS.forEach(({ event, key }) => {
|
|
140
|
+
const handler = (e) => {
|
|
141
|
+
const cb = callbacksRef.current[key];
|
|
142
|
+
if (cb && e instanceof CustomEvent && e.detail) cb(e.detail);
|
|
143
|
+
};
|
|
144
|
+
el.addEventListener(event, handler);
|
|
145
|
+
listeners.push(() => el.removeEventListener(event, handler));
|
|
146
|
+
});
|
|
147
|
+
elementRef.current = el;
|
|
148
|
+
container.appendChild(el);
|
|
149
|
+
return () => {
|
|
150
|
+
listeners.forEach((off) => off());
|
|
151
|
+
if (el.parentNode) el.parentNode.removeChild(el);
|
|
152
|
+
elementRef.current = null;
|
|
153
|
+
};
|
|
154
|
+
}, [ready]);
|
|
155
|
+
(0, import_react.useEffect)(() => {
|
|
156
|
+
const el = elementRef.current;
|
|
157
|
+
if (!el) return;
|
|
158
|
+
applyAttributes(el, { "data-id": dataId, disabled, size, style, items, priceBreakdown, totalCost, customer, webhook, merchantStoreUrl });
|
|
159
|
+
if (className) el.className = className;
|
|
160
|
+
else el.removeAttribute("class");
|
|
161
|
+
if (id) el.id = id;
|
|
162
|
+
else el.removeAttribute("id");
|
|
163
|
+
}, [dataId, disabled, size, style, items, priceBreakdown, totalCost, customer, webhook, merchantStoreUrl, className, id]);
|
|
164
|
+
if (!ready) return null;
|
|
165
|
+
return import_react.default.createElement("div", { ref: containerRef });
|
|
244
166
|
});
|
|
245
167
|
GaitButton.displayName = "GaitButton";
|
|
246
168
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/components/GaitButton.tsx","../src/register.ts"],"sourcesContent":["'use client';\n\n/**\n * @gait-financial/react - React wrappers for Gait Web Components\n *\n * Usage:\n * 1. Register the Web Component (run once, e.g. in _app.tsx or layout):\n * import '@gait-financial/react/register';\n *\n * 2. Use the React components:\n * import { GaitButton } from '@gait-financial/react';\n */\n\nexport { GaitButton } from './components/GaitButton';\nexport type { GaitButtonProps } from './components/GaitButton';\n\nexport type {\n ButtonSize,\n GaitButtonItem,\n GaitPriceBreakdownItem,\n GaitCustomer,\n GaitWebhook,\n GaitClickDetail,\n GaitLoadedDetail,\n GaitDataProcessedDetail,\n GaitSplitFeedbackDetail,\n GaitMerchantIdErrorDetail,\n GaitConfirmDetail,\n} from './types';\n","'use client';\n\n/**\n * React wrapper for GaitButton Web Component\n * Maps React props to element attributes (WC uses attributes as source of truth).\n * Uses ref + useEffect for binding - no direct JSX attribute spread to avoid React's\n * string coercion of booleans/objects.\n * Waits for WC registration before rendering to avoid invisible element (race condition).\n */\n\nimport React, {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react';\nimport { defineCustomElements } from '../register';\nimport type {\n GaitButtonItem,\n GaitPriceBreakdownItem,\n GaitCustomer,\n GaitWebhook,\n GaitClickDetail,\n GaitLoadedDetail,\n GaitDataProcessedDetail,\n GaitSplitFeedbackDetail,\n GaitMerchantIdErrorDetail,\n GaitConfirmDetail,\n} from '../types';\n\nexport interface GaitButtonProps\n extends Omit<React.HTMLAttributes<HTMLElement>, 'onClick' | 'style'> {\n /** Checkout/data identity (required for payment flow) */\n 'data-id'?: string;\n /** Disable the button */\n disabled?: boolean;\n /** Button size */\n size?: 'small' | 'medium' | 'large';\n /** Inline styles - string (for WC) or React.CSSProperties */\n style?: React.CSSProperties | string;\n /** Cart/order items for split payment modal */\n items?: GaitButtonItem[] | string;\n /** Price breakdown items */\n priceBreakdown?: GaitPriceBreakdownItem[] | string;\n /** Total cost */\n totalCost?: number | string;\n /** Customer info for split payment */\n customer?: GaitCustomer | string;\n /** Webhook config for split payment callbacks */\n webhook?: GaitWebhook | string;\n /** Merchant store URL (defaults to window.location.origin) */\n merchantStoreUrl?: string;\n\n /** Button clicked */\n onClick?: (detail: GaitClickDetail) => void;\n /** Component loaded/rendered */\n onLoaded?: (detail: GaitLoadedDetail) => void;\n /** Data processed (e.g. checkoutId resolved) */\n onDataProcessed?: (detail: GaitDataProcessedDetail) => void;\n /** Split payment API feedback (success/failure) */\n onSplitFeedback?: (detail: GaitSplitFeedbackDetail) => void;\n /** Merchant ID lookup failed */\n onMerchantIdError?: (detail: GaitMerchantIdErrorDetail) => void;\n /** Pay remaining confirmed */\n onConfirm?: (detail: GaitConfirmDetail) => void;\n}\n\nconst GaitButton = forwardRef<HTMLElement, GaitButtonProps>(function GaitButton(\n {\n 'data-id': dataId,\n disabled,\n size,\n style,\n items,\n priceBreakdown,\n totalCost,\n customer,\n webhook,\n merchantStoreUrl,\n onClick,\n onLoaded,\n onDataProcessed,\n onSplitFeedback,\n onMerchantIdError,\n onConfirm,\n className,\n id,\n ...rest\n },\n ref\n) {\n const elementRef = useRef<HTMLElement>(null);\n const [isReady, setIsReady] = useState(false);\n\n useImperativeHandle(ref, () => elementRef.current as HTMLElement, []);\n\n // Wait for WC to be registered before rendering (avoids invisible element)\n useEffect(() => {\n if (typeof customElements !== 'undefined' && customElements.get('gait-button')) {\n setIsReady(true);\n return;\n }\n defineCustomElements().then(() => setIsReady(true)).catch(() => setIsReady(false));\n }, []);\n\n // Sync props to element attributes via ref (WC reads attributes) - must run every render (hooks order)\n useEffect(() => {\n const el = elementRef.current;\n if (!el) return;\n\n if (dataId !== undefined) el.setAttribute('data-id', dataId);\n if (size !== undefined) el.setAttribute('size', size);\n\n if (disabled) {\n el.setAttribute('disabled', '');\n } else {\n el.removeAttribute('disabled');\n }\n\n if (style !== undefined) {\n const styleStr =\n typeof style === 'string'\n ? style\n : Object.entries(style)\n .map(\n ([k, v]) =>\n `${k.replace(/([A-Z])/g, '-$1').toLowerCase()}: ${v}`\n )\n .join('; ');\n el.setAttribute('style', styleStr);\n }\n\n if (items !== undefined) {\n el.setAttribute(\n 'items',\n typeof items === 'string' ? items : JSON.stringify(items)\n );\n }\n\n if (priceBreakdown !== undefined) {\n el.setAttribute(\n 'price-breakdown',\n typeof priceBreakdown === 'string'\n ? priceBreakdown\n : JSON.stringify(priceBreakdown)\n );\n }\n\n if (totalCost !== undefined) {\n el.setAttribute('total-cost', String(totalCost));\n }\n\n if (customer !== undefined) {\n el.setAttribute(\n 'customer',\n typeof customer === 'string' ? customer : JSON.stringify(customer)\n );\n }\n\n if (webhook !== undefined) {\n el.setAttribute(\n 'webhook',\n typeof webhook === 'string' ? webhook : JSON.stringify(webhook)\n );\n }\n\n if (merchantStoreUrl !== undefined) {\n el.setAttribute('merchant-store-url', merchantStoreUrl);\n }\n }, [\n dataId,\n disabled,\n size,\n style,\n items,\n priceBreakdown,\n totalCost,\n customer,\n webhook,\n merchantStoreUrl,\n ]);\n\n // Event listeners\n useEffect(() => {\n const el = elementRef.current;\n if (!el) return;\n\n const handleClick = (e: Event) => {\n if (onClick && e instanceof CustomEvent && e.detail) {\n onClick(e.detail as GaitClickDetail);\n }\n };\n const handleLoaded = (e: Event) => {\n if (onLoaded && e instanceof CustomEvent && e.detail) {\n onLoaded(e.detail as GaitLoadedDetail);\n }\n };\n const handleDataProcessed = (e: Event) => {\n if (onDataProcessed && e instanceof CustomEvent && e.detail) {\n onDataProcessed(e.detail as GaitDataProcessedDetail);\n }\n };\n const handleSplitFeedback = (e: Event) => {\n if (onSplitFeedback && e instanceof CustomEvent && e.detail) {\n onSplitFeedback(e.detail as GaitSplitFeedbackDetail);\n }\n };\n const handleMerchantIdError = (e: Event) => {\n if (onMerchantIdError && e instanceof CustomEvent && e.detail) {\n onMerchantIdError(e.detail as GaitMerchantIdErrorDetail);\n }\n };\n const handleConfirm = (e: Event) => {\n if (onConfirm && e instanceof CustomEvent && e.detail) {\n onConfirm(e.detail as GaitConfirmDetail);\n }\n };\n\n el.addEventListener('gait-click', handleClick as EventListener);\n el.addEventListener('gait-loaded', handleLoaded as EventListener);\n el.addEventListener('gait-data-processed', handleDataProcessed as EventListener);\n el.addEventListener('gait-split-feedback', handleSplitFeedback as EventListener);\n el.addEventListener('gait-merchant-id-error', handleMerchantIdError as EventListener);\n el.addEventListener('gait-confirm', handleConfirm as EventListener);\n\n return () => {\n el.removeEventListener('gait-click', handleClick as EventListener);\n el.removeEventListener('gait-loaded', handleLoaded as EventListener);\n el.removeEventListener('gait-data-processed', handleDataProcessed as EventListener);\n el.removeEventListener('gait-split-feedback', handleSplitFeedback as EventListener);\n el.removeEventListener('gait-merchant-id-error', handleMerchantIdError as EventListener);\n el.removeEventListener('gait-confirm', handleConfirm as EventListener);\n };\n }, [\n onClick,\n onLoaded,\n onDataProcessed,\n onSplitFeedback,\n onMerchantIdError,\n onConfirm,\n ]);\n\n // Conditional render AFTER all hooks - required by Rules of Hooks\n if (!isReady) {\n return null;\n }\n\n // Only pass ref, className, id - React assigns props as properties, which throws\n // \"readonly property\" on custom elements. All other attrs set via setAttribute in useEffect.\n const elementProps: Record<string, unknown> = {\n ref: elementRef,\n };\n if (className) elementProps.className = className;\n if (id) elementProps.id = id;\n Object.assign(elementProps, rest);\n\n return React.createElement('gait-button', elementProps);\n});\n\nGaitButton.displayName = 'GaitButton';\n\nexport { GaitButton };\n","/**\n * Registers Gait Web Components in the browser.\n * Safe to call in SSR environments - no-op when window/customElements unavailable.\n *\n * Usage:\n * import '@gait-financial/react/register'; // Side-effect: registers when in browser\n * // or\n * import { defineCustomElements } from '@gait-financial/react/register';\n * await defineCustomElements(); // Optional: load from custom URL\n */\n\nlet loadPromise: Promise<void> | null = null;\n\n/**\n * Loads and registers Gait Web Components.\n * In browser: loads the WC script if not already registered.\n * In SSR: no-op.\n * Deduplicated: multiple calls return the same promise.\n *\n * @param scriptUrl - Optional URL to the button.js script. If omitted, uses the bundled script.\n */\nexport async function defineCustomElements(\n scriptUrl?: string\n): Promise<void> {\n if (typeof window === 'undefined' || typeof customElements === 'undefined') {\n return;\n }\n if (customElements.get('gait-button')) {\n return;\n }\n if (loadPromise) {\n return loadPromise;\n }\n\n const tryLoad = (url: string): Promise<void> =>\n new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.async = true;\n script.src = url;\n script.onload = () => resolve();\n script.onerror = () => reject();\n document.head.appendChild(script);\n });\n\n loadPromise = (async () => {\n const fallbackUrl = `${typeof window !== 'undefined' ? window.location.origin : ''}/node_modules/@gait-financial/react/dist/wc/button.js`;\n\n if (scriptUrl) {\n await tryLoad(scriptUrl);\n return;\n }\n\n // Try relative to module first (works when not pre-bundled)\n try {\n const url = new URL('./wc/button.js', import.meta.url).href;\n await tryLoad(url);\n return;\n } catch {\n // ignore\n }\n\n // Fallback: direct path (works when Vite pre-bundles and breaks import.meta.url)\n try {\n await tryLoad(fallbackUrl);\n return;\n } catch {\n throw new Error(\n '[@gait-financial/react] Failed to load web component script. If using Vite, add optimizeDeps: { exclude: [\"@gait-financial/react\"] } to vite.config.'\n );\n }\n })();\n return loadPromise;\n}\n\n// Side-effect: auto-register when imported in browser (SSR-safe)\nif (typeof window !== 'undefined' && typeof customElements !== 'undefined') {\n void defineCustomElements();\n}\n"],"mappings":"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","names":["GaitButton","React"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/components/GaitButton.tsx","../src/register.ts"],"sourcesContent":["'use client';\n\nexport { GaitButton } from './components/GaitButton';\nexport type { GaitButtonProps } from './components/GaitButton';\nexport type {\n ButtonSize,\n GaitButtonItem,\n GaitPriceBreakdownItem,\n GaitCustomer,\n GaitWebhook,\n GaitClickDetail,\n GaitLoadedDetail,\n GaitDataProcessedDetail,\n GaitSplitFeedbackDetail,\n GaitMerchantIdErrorDetail,\n GaitConfirmDetail,\n} from './types';\n","'use client';\n\nimport React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';\nimport { defineCustomElements } from '../register';\nimport type {\n GaitButtonItem,\n GaitPriceBreakdownItem,\n GaitCustomer,\n GaitWebhook,\n GaitClickDetail,\n GaitLoadedDetail,\n GaitDataProcessedDetail,\n GaitSplitFeedbackDetail,\n GaitMerchantIdErrorDetail,\n GaitConfirmDetail,\n} from '../types';\n\nexport interface GaitButtonProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onClick' | 'style'> {\n 'data-id'?: string;\n disabled?: boolean;\n size?: 'small' | 'medium' | 'large';\n style?: React.CSSProperties | string;\n items?: GaitButtonItem[] | string;\n priceBreakdown?: GaitPriceBreakdownItem[] | string;\n totalCost?: number | string;\n customer?: GaitCustomer | string;\n webhook?: GaitWebhook | string;\n merchantStoreUrl?: string;\n onClick?: (detail: GaitClickDetail) => void;\n onLoaded?: (detail: GaitLoadedDetail) => void;\n onDataProcessed?: (detail: GaitDataProcessedDetail) => void;\n onSplitFeedback?: (detail: GaitSplitFeedbackDetail) => void;\n onMerchantIdError?: (detail: GaitMerchantIdErrorDetail) => void;\n onConfirm?: (detail: GaitConfirmDetail) => void;\n}\n\nconst EVENT_HANDLERS: Array<{ event: string; key: keyof Pick<GaitButtonProps, 'onClick' | 'onLoaded' | 'onDataProcessed' | 'onSplitFeedback' | 'onMerchantIdError' | 'onConfirm'> }> = [\n { event: 'gait-click', key: 'onClick' },\n { event: 'gait-loaded', key: 'onLoaded' },\n { event: 'gait-data-processed', key: 'onDataProcessed' },\n { event: 'gait-split-feedback', key: 'onSplitFeedback' },\n { event: 'gait-merchant-id-error', key: 'onMerchantIdError' },\n { event: 'gait-confirm', key: 'onConfirm' },\n];\n\nfunction applyAttributes(\n el: HTMLElement,\n props: Pick<GaitButtonProps, 'data-id' | 'disabled' | 'size' | 'style' | 'items' | 'priceBreakdown' | 'totalCost' | 'customer' | 'webhook' | 'merchantStoreUrl'>\n) {\n const { 'data-id': dataId, disabled, size, style, items, priceBreakdown, totalCost, customer, webhook, merchantStoreUrl } = props;\n if (dataId !== undefined) el.setAttribute('data-id', dataId);\n if (size !== undefined) el.setAttribute('size', size);\n disabled ? el.setAttribute('disabled', '') : el.removeAttribute('disabled');\n if (style !== undefined) {\n const s = typeof style === 'string' ? style : Object.entries(style).map(([k, v]) => `${k.replace(/([A-Z])/g, '-$1').toLowerCase()}: ${v}`).join('; ');\n el.setAttribute('style', s);\n }\n if (items !== undefined) el.setAttribute('items', typeof items === 'string' ? items : JSON.stringify(items));\n if (priceBreakdown !== undefined) el.setAttribute('price-breakdown', typeof priceBreakdown === 'string' ? priceBreakdown : JSON.stringify(priceBreakdown));\n if (totalCost !== undefined) el.setAttribute('total-cost', String(totalCost));\n if (customer !== undefined) el.setAttribute('customer', typeof customer === 'string' ? customer : JSON.stringify(customer));\n if (webhook !== undefined) el.setAttribute('webhook', typeof webhook === 'string' ? webhook : JSON.stringify(webhook));\n if (merchantStoreUrl !== undefined) el.setAttribute('merchant-store-url', merchantStoreUrl);\n}\n\nconst GaitButton = forwardRef<HTMLElement, GaitButtonProps>(function GaitButton(props, ref) {\n const {\n 'data-id': dataId,\n disabled,\n size,\n style,\n items,\n priceBreakdown,\n totalCost,\n customer,\n webhook,\n merchantStoreUrl,\n onClick,\n onLoaded,\n onDataProcessed,\n onSplitFeedback,\n onMerchantIdError,\n onConfirm,\n className,\n id,\n } = props;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const elementRef = useRef<HTMLElement | null>(null);\n const [ready, setReady] = useState(false);\n const callbacksRef = useRef({ onClick, onLoaded, onDataProcessed, onSplitFeedback, onMerchantIdError, onConfirm });\n callbacksRef.current = { onClick, onLoaded, onDataProcessed, onSplitFeedback, onMerchantIdError, onConfirm };\n\n useImperativeHandle(ref, () => elementRef.current as HTMLElement, []);\n\n useEffect(() => {\n if (typeof customElements !== 'undefined' && customElements.get('gait-button')) {\n setReady(true);\n return;\n }\n defineCustomElements().then(() => setReady(true), () => setReady(false));\n }, []);\n\n useEffect(() => {\n if (!ready || !containerRef.current) return;\n\n const container = containerRef.current;\n const el = document.createElement('gait-button') as HTMLElement;\n\n applyAttributes(el, { 'data-id': dataId, disabled, size, style, items, priceBreakdown, totalCost, customer, webhook, merchantStoreUrl });\n if (className) el.className = className;\n if (id) el.id = id;\n\n const listeners: Array<() => void> = [];\n EVENT_HANDLERS.forEach(({ event, key }) => {\n const handler = (e: Event) => {\n const cb = callbacksRef.current[key];\n if (cb && e instanceof CustomEvent && e.detail) cb(e.detail as never);\n };\n el.addEventListener(event, handler as EventListener);\n listeners.push(() => el.removeEventListener(event, handler as EventListener));\n });\n\n elementRef.current = el;\n container.appendChild(el);\n\n return () => {\n listeners.forEach((off) => off());\n if (el.parentNode) el.parentNode.removeChild(el);\n elementRef.current = null;\n };\n }, [ready]);\n\n useEffect(() => {\n const el = elementRef.current;\n if (!el) return;\n applyAttributes(el, { 'data-id': dataId, disabled, size, style, items, priceBreakdown, totalCost, customer, webhook, merchantStoreUrl });\n if (className) el.className = className;\n else el.removeAttribute('class');\n if (id) el.id = id;\n else el.removeAttribute('id');\n }, [dataId, disabled, size, style, items, priceBreakdown, totalCost, customer, webhook, merchantStoreUrl, className, id]);\n\n if (!ready) return null;\n return React.createElement('div', { ref: containerRef });\n});\n\nGaitButton.displayName = 'GaitButton';\nexport { GaitButton };\n","/**\n * Loads and registers Gait Web Components. Safe for SSR (no-op when no window).\n * Import once: import '@gait-financial/react/register';\n */\n\nlet loadPromise: Promise<void> | null = null;\n\nexport function defineCustomElements(scriptUrl?: string): Promise<void> {\n if (typeof window === 'undefined' || typeof customElements === 'undefined') return Promise.resolve();\n if (customElements.get('gait-button')) return Promise.resolve();\n if (loadPromise) return loadPromise;\n\n loadPromise = new Promise((resolve, reject) => {\n let src: string;\n if (scriptUrl) src = scriptUrl;\n else {\n try {\n src = new URL('./wc/button.js', import.meta.url).href;\n } catch {\n reject(new Error('[@gait-financial/react] Could not resolve script. With Vite, add optimizeDeps: { exclude: [\"@gait-financial/react\"] } to vite.config.'));\n return;\n }\n }\n const script = document.createElement('script');\n script.async = true;\n script.src = src;\n script.onload = () => resolve();\n script.onerror = () => reject(new Error('[@gait-financial/react] Failed to load web component.'));\n document.head.appendChild(script);\n });\n return loadPromise;\n}\n\nif (typeof window !== 'undefined' && typeof customElements !== 'undefined') {\n void defineCustomElements();\n}\n"],"mappings":"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","names":["GaitButton","React"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -68,46 +68,22 @@ interface GaitConfirmDetail {
|
|
|
68
68
|
paymentId: string;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
/**
|
|
72
|
-
* React wrapper for GaitButton Web Component
|
|
73
|
-
* Maps React props to element attributes (WC uses attributes as source of truth).
|
|
74
|
-
* Uses ref + useEffect for binding - no direct JSX attribute spread to avoid React's
|
|
75
|
-
* string coercion of booleans/objects.
|
|
76
|
-
* Waits for WC registration before rendering to avoid invisible element (race condition).
|
|
77
|
-
*/
|
|
78
|
-
|
|
79
71
|
interface GaitButtonProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onClick' | 'style'> {
|
|
80
|
-
/** Checkout/data identity (required for payment flow) */
|
|
81
72
|
'data-id'?: string;
|
|
82
|
-
/** Disable the button */
|
|
83
73
|
disabled?: boolean;
|
|
84
|
-
/** Button size */
|
|
85
74
|
size?: 'small' | 'medium' | 'large';
|
|
86
|
-
/** Inline styles - string (for WC) or React.CSSProperties */
|
|
87
75
|
style?: React.CSSProperties | string;
|
|
88
|
-
/** Cart/order items for split payment modal */
|
|
89
76
|
items?: GaitButtonItem[] | string;
|
|
90
|
-
/** Price breakdown items */
|
|
91
77
|
priceBreakdown?: GaitPriceBreakdownItem[] | string;
|
|
92
|
-
/** Total cost */
|
|
93
78
|
totalCost?: number | string;
|
|
94
|
-
/** Customer info for split payment */
|
|
95
79
|
customer?: GaitCustomer | string;
|
|
96
|
-
/** Webhook config for split payment callbacks */
|
|
97
80
|
webhook?: GaitWebhook | string;
|
|
98
|
-
/** Merchant store URL (defaults to window.location.origin) */
|
|
99
81
|
merchantStoreUrl?: string;
|
|
100
|
-
/** Button clicked */
|
|
101
82
|
onClick?: (detail: GaitClickDetail) => void;
|
|
102
|
-
/** Component loaded/rendered */
|
|
103
83
|
onLoaded?: (detail: GaitLoadedDetail) => void;
|
|
104
|
-
/** Data processed (e.g. checkoutId resolved) */
|
|
105
84
|
onDataProcessed?: (detail: GaitDataProcessedDetail) => void;
|
|
106
|
-
/** Split payment API feedback (success/failure) */
|
|
107
85
|
onSplitFeedback?: (detail: GaitSplitFeedbackDetail) => void;
|
|
108
|
-
/** Merchant ID lookup failed */
|
|
109
86
|
onMerchantIdError?: (detail: GaitMerchantIdErrorDetail) => void;
|
|
110
|
-
/** Pay remaining confirmed */
|
|
111
87
|
onConfirm?: (detail: GaitConfirmDetail) => void;
|
|
112
88
|
}
|
|
113
89
|
declare const GaitButton: React.ForwardRefExoticComponent<GaitButtonProps & React.RefAttributes<HTMLElement>>;
|
package/dist/index.d.ts
CHANGED
|
@@ -68,46 +68,22 @@ interface GaitConfirmDetail {
|
|
|
68
68
|
paymentId: string;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
/**
|
|
72
|
-
* React wrapper for GaitButton Web Component
|
|
73
|
-
* Maps React props to element attributes (WC uses attributes as source of truth).
|
|
74
|
-
* Uses ref + useEffect for binding - no direct JSX attribute spread to avoid React's
|
|
75
|
-
* string coercion of booleans/objects.
|
|
76
|
-
* Waits for WC registration before rendering to avoid invisible element (race condition).
|
|
77
|
-
*/
|
|
78
|
-
|
|
79
71
|
interface GaitButtonProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onClick' | 'style'> {
|
|
80
|
-
/** Checkout/data identity (required for payment flow) */
|
|
81
72
|
'data-id'?: string;
|
|
82
|
-
/** Disable the button */
|
|
83
73
|
disabled?: boolean;
|
|
84
|
-
/** Button size */
|
|
85
74
|
size?: 'small' | 'medium' | 'large';
|
|
86
|
-
/** Inline styles - string (for WC) or React.CSSProperties */
|
|
87
75
|
style?: React.CSSProperties | string;
|
|
88
|
-
/** Cart/order items for split payment modal */
|
|
89
76
|
items?: GaitButtonItem[] | string;
|
|
90
|
-
/** Price breakdown items */
|
|
91
77
|
priceBreakdown?: GaitPriceBreakdownItem[] | string;
|
|
92
|
-
/** Total cost */
|
|
93
78
|
totalCost?: number | string;
|
|
94
|
-
/** Customer info for split payment */
|
|
95
79
|
customer?: GaitCustomer | string;
|
|
96
|
-
/** Webhook config for split payment callbacks */
|
|
97
80
|
webhook?: GaitWebhook | string;
|
|
98
|
-
/** Merchant store URL (defaults to window.location.origin) */
|
|
99
81
|
merchantStoreUrl?: string;
|
|
100
|
-
/** Button clicked */
|
|
101
82
|
onClick?: (detail: GaitClickDetail) => void;
|
|
102
|
-
/** Component loaded/rendered */
|
|
103
83
|
onLoaded?: (detail: GaitLoadedDetail) => void;
|
|
104
|
-
/** Data processed (e.g. checkoutId resolved) */
|
|
105
84
|
onDataProcessed?: (detail: GaitDataProcessedDetail) => void;
|
|
106
|
-
/** Split payment API feedback (success/failure) */
|
|
107
85
|
onSplitFeedback?: (detail: GaitSplitFeedbackDetail) => void;
|
|
108
|
-
/** Merchant ID lookup failed */
|
|
109
86
|
onMerchantIdError?: (detail: GaitMerchantIdErrorDetail) => void;
|
|
110
|
-
/** Pay remaining confirmed */
|
|
111
87
|
onConfirm?: (detail: GaitConfirmDetail) => void;
|
|
112
88
|
}
|
|
113
89
|
declare const GaitButton: React.ForwardRefExoticComponent<GaitButtonProps & React.RefAttributes<HTMLElement>>;
|
package/dist/index.js
CHANGED
|
@@ -1,55 +1,32 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
// src/components/GaitButton.tsx
|
|
4
|
-
import React, {
|
|
5
|
-
forwardRef,
|
|
6
|
-
useEffect,
|
|
7
|
-
useImperativeHandle,
|
|
8
|
-
useRef,
|
|
9
|
-
useState
|
|
10
|
-
} from "react";
|
|
4
|
+
import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from "react";
|
|
11
5
|
|
|
12
6
|
// src/register.ts
|
|
13
7
|
var loadPromise = null;
|
|
14
|
-
|
|
15
|
-
if (typeof window === "undefined" || typeof customElements === "undefined")
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
8
|
+
function defineCustomElements(scriptUrl) {
|
|
9
|
+
if (typeof window === "undefined" || typeof customElements === "undefined") return Promise.resolve();
|
|
10
|
+
if (customElements.get("gait-button")) return Promise.resolve();
|
|
11
|
+
if (loadPromise) return loadPromise;
|
|
12
|
+
loadPromise = new Promise((resolve, reject) => {
|
|
13
|
+
let src;
|
|
14
|
+
if (scriptUrl) src = scriptUrl;
|
|
15
|
+
else {
|
|
16
|
+
try {
|
|
17
|
+
src = new URL("./wc/button.js", import.meta.url).href;
|
|
18
|
+
} catch {
|
|
19
|
+
reject(new Error('[@gait-financial/react] Could not resolve script. With Vite, add optimizeDeps: { exclude: ["@gait-financial/react"] } to vite.config.'));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
25
23
|
const script = document.createElement("script");
|
|
26
24
|
script.async = true;
|
|
27
|
-
script.src =
|
|
25
|
+
script.src = src;
|
|
28
26
|
script.onload = () => resolve();
|
|
29
|
-
script.onerror = () => reject();
|
|
27
|
+
script.onerror = () => reject(new Error("[@gait-financial/react] Failed to load web component."));
|
|
30
28
|
document.head.appendChild(script);
|
|
31
29
|
});
|
|
32
|
-
loadPromise = (async () => {
|
|
33
|
-
const fallbackUrl = `${typeof window !== "undefined" ? window.location.origin : ""}/node_modules/@gait-financial/react/dist/wc/button.js`;
|
|
34
|
-
if (scriptUrl) {
|
|
35
|
-
await tryLoad(scriptUrl);
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
try {
|
|
39
|
-
const url = new URL("./wc/button.js", import.meta.url).href;
|
|
40
|
-
await tryLoad(url);
|
|
41
|
-
return;
|
|
42
|
-
} catch {
|
|
43
|
-
}
|
|
44
|
-
try {
|
|
45
|
-
await tryLoad(fallbackUrl);
|
|
46
|
-
return;
|
|
47
|
-
} catch {
|
|
48
|
-
throw new Error(
|
|
49
|
-
'[@gait-financial/react] Failed to load web component script. If using Vite, add optimizeDeps: { exclude: ["@gait-financial/react"] } to vite.config.'
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
})();
|
|
53
30
|
return loadPromise;
|
|
54
31
|
}
|
|
55
32
|
if (typeof window !== "undefined" && typeof customElements !== "undefined") {
|
|
@@ -57,85 +34,33 @@ if (typeof window !== "undefined" && typeof customElements !== "undefined") {
|
|
|
57
34
|
}
|
|
58
35
|
|
|
59
36
|
// src/components/GaitButton.tsx
|
|
60
|
-
var
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
webhook,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
defineCustomElements().then(() => setIsReady(true)).catch(() => setIsReady(false));
|
|
90
|
-
}, []);
|
|
91
|
-
useEffect(() => {
|
|
92
|
-
const el = elementRef.current;
|
|
93
|
-
if (!el) return;
|
|
94
|
-
if (dataId !== void 0) el.setAttribute("data-id", dataId);
|
|
95
|
-
if (size !== void 0) el.setAttribute("size", size);
|
|
96
|
-
if (disabled) {
|
|
97
|
-
el.setAttribute("disabled", "");
|
|
98
|
-
} else {
|
|
99
|
-
el.removeAttribute("disabled");
|
|
100
|
-
}
|
|
101
|
-
if (style !== void 0) {
|
|
102
|
-
const styleStr = typeof style === "string" ? style : Object.entries(style).map(
|
|
103
|
-
([k, v]) => `${k.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${v}`
|
|
104
|
-
).join("; ");
|
|
105
|
-
el.setAttribute("style", styleStr);
|
|
106
|
-
}
|
|
107
|
-
if (items !== void 0) {
|
|
108
|
-
el.setAttribute(
|
|
109
|
-
"items",
|
|
110
|
-
typeof items === "string" ? items : JSON.stringify(items)
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
if (priceBreakdown !== void 0) {
|
|
114
|
-
el.setAttribute(
|
|
115
|
-
"price-breakdown",
|
|
116
|
-
typeof priceBreakdown === "string" ? priceBreakdown : JSON.stringify(priceBreakdown)
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
if (totalCost !== void 0) {
|
|
120
|
-
el.setAttribute("total-cost", String(totalCost));
|
|
121
|
-
}
|
|
122
|
-
if (customer !== void 0) {
|
|
123
|
-
el.setAttribute(
|
|
124
|
-
"customer",
|
|
125
|
-
typeof customer === "string" ? customer : JSON.stringify(customer)
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
if (webhook !== void 0) {
|
|
129
|
-
el.setAttribute(
|
|
130
|
-
"webhook",
|
|
131
|
-
typeof webhook === "string" ? webhook : JSON.stringify(webhook)
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
|
-
if (merchantStoreUrl !== void 0) {
|
|
135
|
-
el.setAttribute("merchant-store-url", merchantStoreUrl);
|
|
136
|
-
}
|
|
137
|
-
}, [
|
|
138
|
-
dataId,
|
|
37
|
+
var EVENT_HANDLERS = [
|
|
38
|
+
{ event: "gait-click", key: "onClick" },
|
|
39
|
+
{ event: "gait-loaded", key: "onLoaded" },
|
|
40
|
+
{ event: "gait-data-processed", key: "onDataProcessed" },
|
|
41
|
+
{ event: "gait-split-feedback", key: "onSplitFeedback" },
|
|
42
|
+
{ event: "gait-merchant-id-error", key: "onMerchantIdError" },
|
|
43
|
+
{ event: "gait-confirm", key: "onConfirm" }
|
|
44
|
+
];
|
|
45
|
+
function applyAttributes(el, props) {
|
|
46
|
+
const { "data-id": dataId, disabled, size, style, items, priceBreakdown, totalCost, customer, webhook, merchantStoreUrl } = props;
|
|
47
|
+
if (dataId !== void 0) el.setAttribute("data-id", dataId);
|
|
48
|
+
if (size !== void 0) el.setAttribute("size", size);
|
|
49
|
+
disabled ? el.setAttribute("disabled", "") : el.removeAttribute("disabled");
|
|
50
|
+
if (style !== void 0) {
|
|
51
|
+
const s = typeof style === "string" ? style : Object.entries(style).map(([k, v]) => `${k.replace(/([A-Z])/g, "-$1").toLowerCase()}: ${v}`).join("; ");
|
|
52
|
+
el.setAttribute("style", s);
|
|
53
|
+
}
|
|
54
|
+
if (items !== void 0) el.setAttribute("items", typeof items === "string" ? items : JSON.stringify(items));
|
|
55
|
+
if (priceBreakdown !== void 0) el.setAttribute("price-breakdown", typeof priceBreakdown === "string" ? priceBreakdown : JSON.stringify(priceBreakdown));
|
|
56
|
+
if (totalCost !== void 0) el.setAttribute("total-cost", String(totalCost));
|
|
57
|
+
if (customer !== void 0) el.setAttribute("customer", typeof customer === "string" ? customer : JSON.stringify(customer));
|
|
58
|
+
if (webhook !== void 0) el.setAttribute("webhook", typeof webhook === "string" ? webhook : JSON.stringify(webhook));
|
|
59
|
+
if (merchantStoreUrl !== void 0) el.setAttribute("merchant-store-url", merchantStoreUrl);
|
|
60
|
+
}
|
|
61
|
+
var GaitButton = forwardRef(function GaitButton2(props, ref) {
|
|
62
|
+
const {
|
|
63
|
+
"data-id": dataId,
|
|
139
64
|
disabled,
|
|
140
65
|
size,
|
|
141
66
|
style,
|
|
@@ -144,73 +69,64 @@ var GaitButton = forwardRef(function GaitButton2({
|
|
|
144
69
|
totalCost,
|
|
145
70
|
customer,
|
|
146
71
|
webhook,
|
|
147
|
-
merchantStoreUrl
|
|
148
|
-
]);
|
|
149
|
-
useEffect(() => {
|
|
150
|
-
const el = elementRef.current;
|
|
151
|
-
if (!el) return;
|
|
152
|
-
const handleClick = (e) => {
|
|
153
|
-
if (onClick && e instanceof CustomEvent && e.detail) {
|
|
154
|
-
onClick(e.detail);
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
const handleLoaded = (e) => {
|
|
158
|
-
if (onLoaded && e instanceof CustomEvent && e.detail) {
|
|
159
|
-
onLoaded(e.detail);
|
|
160
|
-
}
|
|
161
|
-
};
|
|
162
|
-
const handleDataProcessed = (e) => {
|
|
163
|
-
if (onDataProcessed && e instanceof CustomEvent && e.detail) {
|
|
164
|
-
onDataProcessed(e.detail);
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
const handleSplitFeedback = (e) => {
|
|
168
|
-
if (onSplitFeedback && e instanceof CustomEvent && e.detail) {
|
|
169
|
-
onSplitFeedback(e.detail);
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
const handleMerchantIdError = (e) => {
|
|
173
|
-
if (onMerchantIdError && e instanceof CustomEvent && e.detail) {
|
|
174
|
-
onMerchantIdError(e.detail);
|
|
175
|
-
}
|
|
176
|
-
};
|
|
177
|
-
const handleConfirm = (e) => {
|
|
178
|
-
if (onConfirm && e instanceof CustomEvent && e.detail) {
|
|
179
|
-
onConfirm(e.detail);
|
|
180
|
-
}
|
|
181
|
-
};
|
|
182
|
-
el.addEventListener("gait-click", handleClick);
|
|
183
|
-
el.addEventListener("gait-loaded", handleLoaded);
|
|
184
|
-
el.addEventListener("gait-data-processed", handleDataProcessed);
|
|
185
|
-
el.addEventListener("gait-split-feedback", handleSplitFeedback);
|
|
186
|
-
el.addEventListener("gait-merchant-id-error", handleMerchantIdError);
|
|
187
|
-
el.addEventListener("gait-confirm", handleConfirm);
|
|
188
|
-
return () => {
|
|
189
|
-
el.removeEventListener("gait-click", handleClick);
|
|
190
|
-
el.removeEventListener("gait-loaded", handleLoaded);
|
|
191
|
-
el.removeEventListener("gait-data-processed", handleDataProcessed);
|
|
192
|
-
el.removeEventListener("gait-split-feedback", handleSplitFeedback);
|
|
193
|
-
el.removeEventListener("gait-merchant-id-error", handleMerchantIdError);
|
|
194
|
-
el.removeEventListener("gait-confirm", handleConfirm);
|
|
195
|
-
};
|
|
196
|
-
}, [
|
|
72
|
+
merchantStoreUrl,
|
|
197
73
|
onClick,
|
|
198
74
|
onLoaded,
|
|
199
75
|
onDataProcessed,
|
|
200
76
|
onSplitFeedback,
|
|
201
77
|
onMerchantIdError,
|
|
202
|
-
onConfirm
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
78
|
+
onConfirm,
|
|
79
|
+
className,
|
|
80
|
+
id
|
|
81
|
+
} = props;
|
|
82
|
+
const containerRef = useRef(null);
|
|
83
|
+
const elementRef = useRef(null);
|
|
84
|
+
const [ready, setReady] = useState(false);
|
|
85
|
+
const callbacksRef = useRef({ onClick, onLoaded, onDataProcessed, onSplitFeedback, onMerchantIdError, onConfirm });
|
|
86
|
+
callbacksRef.current = { onClick, onLoaded, onDataProcessed, onSplitFeedback, onMerchantIdError, onConfirm };
|
|
87
|
+
useImperativeHandle(ref, () => elementRef.current, []);
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
if (typeof customElements !== "undefined" && customElements.get("gait-button")) {
|
|
90
|
+
setReady(true);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
defineCustomElements().then(() => setReady(true), () => setReady(false));
|
|
94
|
+
}, []);
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
if (!ready || !containerRef.current) return;
|
|
97
|
+
const container = containerRef.current;
|
|
98
|
+
const el = document.createElement("gait-button");
|
|
99
|
+
applyAttributes(el, { "data-id": dataId, disabled, size, style, items, priceBreakdown, totalCost, customer, webhook, merchantStoreUrl });
|
|
100
|
+
if (className) el.className = className;
|
|
101
|
+
if (id) el.id = id;
|
|
102
|
+
const listeners = [];
|
|
103
|
+
EVENT_HANDLERS.forEach(({ event, key }) => {
|
|
104
|
+
const handler = (e) => {
|
|
105
|
+
const cb = callbacksRef.current[key];
|
|
106
|
+
if (cb && e instanceof CustomEvent && e.detail) cb(e.detail);
|
|
107
|
+
};
|
|
108
|
+
el.addEventListener(event, handler);
|
|
109
|
+
listeners.push(() => el.removeEventListener(event, handler));
|
|
110
|
+
});
|
|
111
|
+
elementRef.current = el;
|
|
112
|
+
container.appendChild(el);
|
|
113
|
+
return () => {
|
|
114
|
+
listeners.forEach((off) => off());
|
|
115
|
+
if (el.parentNode) el.parentNode.removeChild(el);
|
|
116
|
+
elementRef.current = null;
|
|
117
|
+
};
|
|
118
|
+
}, [ready]);
|
|
119
|
+
useEffect(() => {
|
|
120
|
+
const el = elementRef.current;
|
|
121
|
+
if (!el) return;
|
|
122
|
+
applyAttributes(el, { "data-id": dataId, disabled, size, style, items, priceBreakdown, totalCost, customer, webhook, merchantStoreUrl });
|
|
123
|
+
if (className) el.className = className;
|
|
124
|
+
else el.removeAttribute("class");
|
|
125
|
+
if (id) el.id = id;
|
|
126
|
+
else el.removeAttribute("id");
|
|
127
|
+
}, [dataId, disabled, size, style, items, priceBreakdown, totalCost, customer, webhook, merchantStoreUrl, className, id]);
|
|
128
|
+
if (!ready) return null;
|
|
129
|
+
return React.createElement("div", { ref: containerRef });
|
|
214
130
|
});
|
|
215
131
|
GaitButton.displayName = "GaitButton";
|
|
216
132
|
export {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/GaitButton.tsx","../src/register.ts"],"sourcesContent":["'use client';\n\n/**\n * React wrapper for GaitButton Web Component\n * Maps React props to element attributes (WC uses attributes as source of truth).\n * Uses ref + useEffect for binding - no direct JSX attribute spread to avoid React's\n * string coercion of booleans/objects.\n * Waits for WC registration before rendering to avoid invisible element (race condition).\n */\n\nimport React, {\n forwardRef,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react';\nimport { defineCustomElements } from '../register';\nimport type {\n GaitButtonItem,\n GaitPriceBreakdownItem,\n GaitCustomer,\n GaitWebhook,\n GaitClickDetail,\n GaitLoadedDetail,\n GaitDataProcessedDetail,\n GaitSplitFeedbackDetail,\n GaitMerchantIdErrorDetail,\n GaitConfirmDetail,\n} from '../types';\n\nexport interface GaitButtonProps\n extends Omit<React.HTMLAttributes<HTMLElement>, 'onClick' | 'style'> {\n /** Checkout/data identity (required for payment flow) */\n 'data-id'?: string;\n /** Disable the button */\n disabled?: boolean;\n /** Button size */\n size?: 'small' | 'medium' | 'large';\n /** Inline styles - string (for WC) or React.CSSProperties */\n style?: React.CSSProperties | string;\n /** Cart/order items for split payment modal */\n items?: GaitButtonItem[] | string;\n /** Price breakdown items */\n priceBreakdown?: GaitPriceBreakdownItem[] | string;\n /** Total cost */\n totalCost?: number | string;\n /** Customer info for split payment */\n customer?: GaitCustomer | string;\n /** Webhook config for split payment callbacks */\n webhook?: GaitWebhook | string;\n /** Merchant store URL (defaults to window.location.origin) */\n merchantStoreUrl?: string;\n\n /** Button clicked */\n onClick?: (detail: GaitClickDetail) => void;\n /** Component loaded/rendered */\n onLoaded?: (detail: GaitLoadedDetail) => void;\n /** Data processed (e.g. checkoutId resolved) */\n onDataProcessed?: (detail: GaitDataProcessedDetail) => void;\n /** Split payment API feedback (success/failure) */\n onSplitFeedback?: (detail: GaitSplitFeedbackDetail) => void;\n /** Merchant ID lookup failed */\n onMerchantIdError?: (detail: GaitMerchantIdErrorDetail) => void;\n /** Pay remaining confirmed */\n onConfirm?: (detail: GaitConfirmDetail) => void;\n}\n\nconst GaitButton = forwardRef<HTMLElement, GaitButtonProps>(function GaitButton(\n {\n 'data-id': dataId,\n disabled,\n size,\n style,\n items,\n priceBreakdown,\n totalCost,\n customer,\n webhook,\n merchantStoreUrl,\n onClick,\n onLoaded,\n onDataProcessed,\n onSplitFeedback,\n onMerchantIdError,\n onConfirm,\n className,\n id,\n ...rest\n },\n ref\n) {\n const elementRef = useRef<HTMLElement>(null);\n const [isReady, setIsReady] = useState(false);\n\n useImperativeHandle(ref, () => elementRef.current as HTMLElement, []);\n\n // Wait for WC to be registered before rendering (avoids invisible element)\n useEffect(() => {\n if (typeof customElements !== 'undefined' && customElements.get('gait-button')) {\n setIsReady(true);\n return;\n }\n defineCustomElements().then(() => setIsReady(true)).catch(() => setIsReady(false));\n }, []);\n\n // Sync props to element attributes via ref (WC reads attributes) - must run every render (hooks order)\n useEffect(() => {\n const el = elementRef.current;\n if (!el) return;\n\n if (dataId !== undefined) el.setAttribute('data-id', dataId);\n if (size !== undefined) el.setAttribute('size', size);\n\n if (disabled) {\n el.setAttribute('disabled', '');\n } else {\n el.removeAttribute('disabled');\n }\n\n if (style !== undefined) {\n const styleStr =\n typeof style === 'string'\n ? style\n : Object.entries(style)\n .map(\n ([k, v]) =>\n `${k.replace(/([A-Z])/g, '-$1').toLowerCase()}: ${v}`\n )\n .join('; ');\n el.setAttribute('style', styleStr);\n }\n\n if (items !== undefined) {\n el.setAttribute(\n 'items',\n typeof items === 'string' ? items : JSON.stringify(items)\n );\n }\n\n if (priceBreakdown !== undefined) {\n el.setAttribute(\n 'price-breakdown',\n typeof priceBreakdown === 'string'\n ? priceBreakdown\n : JSON.stringify(priceBreakdown)\n );\n }\n\n if (totalCost !== undefined) {\n el.setAttribute('total-cost', String(totalCost));\n }\n\n if (customer !== undefined) {\n el.setAttribute(\n 'customer',\n typeof customer === 'string' ? customer : JSON.stringify(customer)\n );\n }\n\n if (webhook !== undefined) {\n el.setAttribute(\n 'webhook',\n typeof webhook === 'string' ? webhook : JSON.stringify(webhook)\n );\n }\n\n if (merchantStoreUrl !== undefined) {\n el.setAttribute('merchant-store-url', merchantStoreUrl);\n }\n }, [\n dataId,\n disabled,\n size,\n style,\n items,\n priceBreakdown,\n totalCost,\n customer,\n webhook,\n merchantStoreUrl,\n ]);\n\n // Event listeners\n useEffect(() => {\n const el = elementRef.current;\n if (!el) return;\n\n const handleClick = (e: Event) => {\n if (onClick && e instanceof CustomEvent && e.detail) {\n onClick(e.detail as GaitClickDetail);\n }\n };\n const handleLoaded = (e: Event) => {\n if (onLoaded && e instanceof CustomEvent && e.detail) {\n onLoaded(e.detail as GaitLoadedDetail);\n }\n };\n const handleDataProcessed = (e: Event) => {\n if (onDataProcessed && e instanceof CustomEvent && e.detail) {\n onDataProcessed(e.detail as GaitDataProcessedDetail);\n }\n };\n const handleSplitFeedback = (e: Event) => {\n if (onSplitFeedback && e instanceof CustomEvent && e.detail) {\n onSplitFeedback(e.detail as GaitSplitFeedbackDetail);\n }\n };\n const handleMerchantIdError = (e: Event) => {\n if (onMerchantIdError && e instanceof CustomEvent && e.detail) {\n onMerchantIdError(e.detail as GaitMerchantIdErrorDetail);\n }\n };\n const handleConfirm = (e: Event) => {\n if (onConfirm && e instanceof CustomEvent && e.detail) {\n onConfirm(e.detail as GaitConfirmDetail);\n }\n };\n\n el.addEventListener('gait-click', handleClick as EventListener);\n el.addEventListener('gait-loaded', handleLoaded as EventListener);\n el.addEventListener('gait-data-processed', handleDataProcessed as EventListener);\n el.addEventListener('gait-split-feedback', handleSplitFeedback as EventListener);\n el.addEventListener('gait-merchant-id-error', handleMerchantIdError as EventListener);\n el.addEventListener('gait-confirm', handleConfirm as EventListener);\n\n return () => {\n el.removeEventListener('gait-click', handleClick as EventListener);\n el.removeEventListener('gait-loaded', handleLoaded as EventListener);\n el.removeEventListener('gait-data-processed', handleDataProcessed as EventListener);\n el.removeEventListener('gait-split-feedback', handleSplitFeedback as EventListener);\n el.removeEventListener('gait-merchant-id-error', handleMerchantIdError as EventListener);\n el.removeEventListener('gait-confirm', handleConfirm as EventListener);\n };\n }, [\n onClick,\n onLoaded,\n onDataProcessed,\n onSplitFeedback,\n onMerchantIdError,\n onConfirm,\n ]);\n\n // Conditional render AFTER all hooks - required by Rules of Hooks\n if (!isReady) {\n return null;\n }\n\n // Only pass ref, className, id - React assigns props as properties, which throws\n // \"readonly property\" on custom elements. All other attrs set via setAttribute in useEffect.\n const elementProps: Record<string, unknown> = {\n ref: elementRef,\n };\n if (className) elementProps.className = className;\n if (id) elementProps.id = id;\n Object.assign(elementProps, rest);\n\n return React.createElement('gait-button', elementProps);\n});\n\nGaitButton.displayName = 'GaitButton';\n\nexport { GaitButton };\n","/**\n * Registers Gait Web Components in the browser.\n * Safe to call in SSR environments - no-op when window/customElements unavailable.\n *\n * Usage:\n * import '@gait-financial/react/register'; // Side-effect: registers when in browser\n * // or\n * import { defineCustomElements } from '@gait-financial/react/register';\n * await defineCustomElements(); // Optional: load from custom URL\n */\n\nlet loadPromise: Promise<void> | null = null;\n\n/**\n * Loads and registers Gait Web Components.\n * In browser: loads the WC script if not already registered.\n * In SSR: no-op.\n * Deduplicated: multiple calls return the same promise.\n *\n * @param scriptUrl - Optional URL to the button.js script. If omitted, uses the bundled script.\n */\nexport async function defineCustomElements(\n scriptUrl?: string\n): Promise<void> {\n if (typeof window === 'undefined' || typeof customElements === 'undefined') {\n return;\n }\n if (customElements.get('gait-button')) {\n return;\n }\n if (loadPromise) {\n return loadPromise;\n }\n\n const tryLoad = (url: string): Promise<void> =>\n new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.async = true;\n script.src = url;\n script.onload = () => resolve();\n script.onerror = () => reject();\n document.head.appendChild(script);\n });\n\n loadPromise = (async () => {\n const fallbackUrl = `${typeof window !== 'undefined' ? window.location.origin : ''}/node_modules/@gait-financial/react/dist/wc/button.js`;\n\n if (scriptUrl) {\n await tryLoad(scriptUrl);\n return;\n }\n\n // Try relative to module first (works when not pre-bundled)\n try {\n const url = new URL('./wc/button.js', import.meta.url).href;\n await tryLoad(url);\n return;\n } catch {\n // ignore\n }\n\n // Fallback: direct path (works when Vite pre-bundles and breaks import.meta.url)\n try {\n await tryLoad(fallbackUrl);\n return;\n } catch {\n throw new Error(\n '[@gait-financial/react] Failed to load web component script. If using Vite, add optimizeDeps: { exclude: [\"@gait-financial/react\"] } to vite.config.'\n );\n }\n })();\n return loadPromise;\n}\n\n// Side-effect: auto-register when imported in browser (SSR-safe)\nif (typeof window !== 'undefined' && typeof customElements !== 'undefined') {\n void defineCustomElements();\n}\n"],"mappings":";;;AAUA,OAAO;AAAA,EACL;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACLP,IAAI,cAAoC;AAUxC,eAAsB,qBACpB,WACe;AACf,MAAI,OAAO,WAAW,eAAe,OAAO,mBAAmB,aAAa;AAC1E;AAAA,EACF;AACA,MAAI,eAAe,IAAI,aAAa,GAAG;AACrC;AAAA,EACF;AACA,MAAI,aAAa;AACf,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,CAAC,QACf,IAAI,QAAQ,CAAC,SAAS,WAAW;AAC/B,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,QAAQ;AACf,WAAO,MAAM;AACb,WAAO,SAAS,MAAM,QAAQ;AAC9B,WAAO,UAAU,MAAM,OAAO;AAC9B,aAAS,KAAK,YAAY,MAAM;AAAA,EAClC,CAAC;AAEH,iBAAe,YAAY;AACzB,UAAM,cAAc,GAAG,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS,EAAE;AAElF,QAAI,WAAW;AACb,YAAM,QAAQ,SAAS;AACvB;AAAA,IACF;AAGA,QAAI;AACF,YAAM,MAAM,IAAI,IAAI,kBAAkB,YAAY,GAAG,EAAE;AACvD,YAAM,QAAQ,GAAG;AACjB;AAAA,IACF,QAAQ;AAAA,IAER;AAGA,QAAI;AACF,YAAM,QAAQ,WAAW;AACzB;AAAA,IACF,QAAQ;AACN,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF,GAAG;AACH,SAAO;AACT;AAGA,IAAI,OAAO,WAAW,eAAe,OAAO,mBAAmB,aAAa;AAC1E,OAAK,qBAAqB;AAC5B;;;ADTA,IAAM,aAAa,WAAyC,SAASA,YACnE;AAAA,EACE,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GACA,KACA;AACA,QAAM,aAAa,OAAoB,IAAI;AAC3C,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,sBAAoB,KAAK,MAAM,WAAW,SAAwB,CAAC,CAAC;AAGpE,YAAU,MAAM;AACd,QAAI,OAAO,mBAAmB,eAAe,eAAe,IAAI,aAAa,GAAG;AAC9E,iBAAW,IAAI;AACf;AAAA,IACF;AACA,yBAAqB,EAAE,KAAK,MAAM,WAAW,IAAI,CAAC,EAAE,MAAM,MAAM,WAAW,KAAK,CAAC;AAAA,EACnF,GAAG,CAAC,CAAC;AAGL,YAAU,MAAM;AACd,UAAM,KAAK,WAAW;AACtB,QAAI,CAAC,GAAI;AAET,QAAI,WAAW,OAAW,IAAG,aAAa,WAAW,MAAM;AAC3D,QAAI,SAAS,OAAW,IAAG,aAAa,QAAQ,IAAI;AAEpD,QAAI,UAAU;AACZ,SAAG,aAAa,YAAY,EAAE;AAAA,IAChC,OAAO;AACL,SAAG,gBAAgB,UAAU;AAAA,IAC/B;AAEA,QAAI,UAAU,QAAW;AACvB,YAAM,WACJ,OAAO,UAAU,WACb,QACA,OAAO,QAAQ,KAAK,EACjB;AAAA,QACC,CAAC,CAAC,GAAG,CAAC,MACJ,GAAG,EAAE,QAAQ,YAAY,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;AAAA,MACvD,EACC,KAAK,IAAI;AAClB,SAAG,aAAa,SAAS,QAAQ;AAAA,IACnC;AAEA,QAAI,UAAU,QAAW;AACvB,SAAG;AAAA,QACD;AAAA,QACA,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,KAAK;AAAA,MAC1D;AAAA,IACF;AAEA,QAAI,mBAAmB,QAAW;AAChC,SAAG;AAAA,QACD;AAAA,QACA,OAAO,mBAAmB,WACtB,iBACA,KAAK,UAAU,cAAc;AAAA,MACnC;AAAA,IACF;AAEA,QAAI,cAAc,QAAW;AAC3B,SAAG,aAAa,cAAc,OAAO,SAAS,CAAC;AAAA,IACjD;AAEA,QAAI,aAAa,QAAW;AAC1B,SAAG;AAAA,QACD;AAAA,QACA,OAAO,aAAa,WAAW,WAAW,KAAK,UAAU,QAAQ;AAAA,MACnE;AAAA,IACF;AAEA,QAAI,YAAY,QAAW;AACzB,SAAG;AAAA,QACD;AAAA,QACA,OAAO,YAAY,WAAW,UAAU,KAAK,UAAU,OAAO;AAAA,MAChE;AAAA,IACF;AAEA,QAAI,qBAAqB,QAAW;AAClC,SAAG,aAAa,sBAAsB,gBAAgB;AAAA,IACxD;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAGD,YAAU,MAAM;AACd,UAAM,KAAK,WAAW;AACtB,QAAI,CAAC,GAAI;AAET,UAAM,cAAc,CAAC,MAAa;AAChC,UAAI,WAAW,aAAa,eAAe,EAAE,QAAQ;AACnD,gBAAQ,EAAE,MAAyB;AAAA,MACrC;AAAA,IACF;AACA,UAAM,eAAe,CAAC,MAAa;AACjC,UAAI,YAAY,aAAa,eAAe,EAAE,QAAQ;AACpD,iBAAS,EAAE,MAA0B;AAAA,MACvC;AAAA,IACF;AACA,UAAM,sBAAsB,CAAC,MAAa;AACxC,UAAI,mBAAmB,aAAa,eAAe,EAAE,QAAQ;AAC3D,wBAAgB,EAAE,MAAiC;AAAA,MACrD;AAAA,IACF;AACA,UAAM,sBAAsB,CAAC,MAAa;AACxC,UAAI,mBAAmB,aAAa,eAAe,EAAE,QAAQ;AAC3D,wBAAgB,EAAE,MAAiC;AAAA,MACrD;AAAA,IACF;AACA,UAAM,wBAAwB,CAAC,MAAa;AAC1C,UAAI,qBAAqB,aAAa,eAAe,EAAE,QAAQ;AAC7D,0BAAkB,EAAE,MAAmC;AAAA,MACzD;AAAA,IACF;AACA,UAAM,gBAAgB,CAAC,MAAa;AAClC,UAAI,aAAa,aAAa,eAAe,EAAE,QAAQ;AACrD,kBAAU,EAAE,MAA2B;AAAA,MACzC;AAAA,IACF;AAEA,OAAG,iBAAiB,cAAc,WAA4B;AAC9D,OAAG,iBAAiB,eAAe,YAA6B;AAChE,OAAG,iBAAiB,uBAAuB,mBAAoC;AAC/E,OAAG,iBAAiB,uBAAuB,mBAAoC;AAC/E,OAAG,iBAAiB,0BAA0B,qBAAsC;AACpF,OAAG,iBAAiB,gBAAgB,aAA8B;AAElE,WAAO,MAAM;AACX,SAAG,oBAAoB,cAAc,WAA4B;AACjE,SAAG,oBAAoB,eAAe,YAA6B;AACnE,SAAG,oBAAoB,uBAAuB,mBAAoC;AAClF,SAAG,oBAAoB,uBAAuB,mBAAoC;AAClF,SAAG,oBAAoB,0BAA0B,qBAAsC;AACvF,SAAG,oBAAoB,gBAAgB,aAA8B;AAAA,IACvE;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAGD,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,EACT;AAIA,QAAM,eAAwC;AAAA,IAC5C,KAAK;AAAA,EACP;AACA,MAAI,UAAW,cAAa,YAAY;AACxC,MAAI,GAAI,cAAa,KAAK;AAC1B,SAAO,OAAO,cAAc,IAAI;AAEhC,SAAO,MAAM,cAAc,eAAe,YAAY;AACxD,CAAC;AAED,WAAW,cAAc;","names":["GaitButton"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/GaitButton.tsx","../src/register.ts"],"sourcesContent":["'use client';\n\nimport React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';\nimport { defineCustomElements } from '../register';\nimport type {\n GaitButtonItem,\n GaitPriceBreakdownItem,\n GaitCustomer,\n GaitWebhook,\n GaitClickDetail,\n GaitLoadedDetail,\n GaitDataProcessedDetail,\n GaitSplitFeedbackDetail,\n GaitMerchantIdErrorDetail,\n GaitConfirmDetail,\n} from '../types';\n\nexport interface GaitButtonProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onClick' | 'style'> {\n 'data-id'?: string;\n disabled?: boolean;\n size?: 'small' | 'medium' | 'large';\n style?: React.CSSProperties | string;\n items?: GaitButtonItem[] | string;\n priceBreakdown?: GaitPriceBreakdownItem[] | string;\n totalCost?: number | string;\n customer?: GaitCustomer | string;\n webhook?: GaitWebhook | string;\n merchantStoreUrl?: string;\n onClick?: (detail: GaitClickDetail) => void;\n onLoaded?: (detail: GaitLoadedDetail) => void;\n onDataProcessed?: (detail: GaitDataProcessedDetail) => void;\n onSplitFeedback?: (detail: GaitSplitFeedbackDetail) => void;\n onMerchantIdError?: (detail: GaitMerchantIdErrorDetail) => void;\n onConfirm?: (detail: GaitConfirmDetail) => void;\n}\n\nconst EVENT_HANDLERS: Array<{ event: string; key: keyof Pick<GaitButtonProps, 'onClick' | 'onLoaded' | 'onDataProcessed' | 'onSplitFeedback' | 'onMerchantIdError' | 'onConfirm'> }> = [\n { event: 'gait-click', key: 'onClick' },\n { event: 'gait-loaded', key: 'onLoaded' },\n { event: 'gait-data-processed', key: 'onDataProcessed' },\n { event: 'gait-split-feedback', key: 'onSplitFeedback' },\n { event: 'gait-merchant-id-error', key: 'onMerchantIdError' },\n { event: 'gait-confirm', key: 'onConfirm' },\n];\n\nfunction applyAttributes(\n el: HTMLElement,\n props: Pick<GaitButtonProps, 'data-id' | 'disabled' | 'size' | 'style' | 'items' | 'priceBreakdown' | 'totalCost' | 'customer' | 'webhook' | 'merchantStoreUrl'>\n) {\n const { 'data-id': dataId, disabled, size, style, items, priceBreakdown, totalCost, customer, webhook, merchantStoreUrl } = props;\n if (dataId !== undefined) el.setAttribute('data-id', dataId);\n if (size !== undefined) el.setAttribute('size', size);\n disabled ? el.setAttribute('disabled', '') : el.removeAttribute('disabled');\n if (style !== undefined) {\n const s = typeof style === 'string' ? style : Object.entries(style).map(([k, v]) => `${k.replace(/([A-Z])/g, '-$1').toLowerCase()}: ${v}`).join('; ');\n el.setAttribute('style', s);\n }\n if (items !== undefined) el.setAttribute('items', typeof items === 'string' ? items : JSON.stringify(items));\n if (priceBreakdown !== undefined) el.setAttribute('price-breakdown', typeof priceBreakdown === 'string' ? priceBreakdown : JSON.stringify(priceBreakdown));\n if (totalCost !== undefined) el.setAttribute('total-cost', String(totalCost));\n if (customer !== undefined) el.setAttribute('customer', typeof customer === 'string' ? customer : JSON.stringify(customer));\n if (webhook !== undefined) el.setAttribute('webhook', typeof webhook === 'string' ? webhook : JSON.stringify(webhook));\n if (merchantStoreUrl !== undefined) el.setAttribute('merchant-store-url', merchantStoreUrl);\n}\n\nconst GaitButton = forwardRef<HTMLElement, GaitButtonProps>(function GaitButton(props, ref) {\n const {\n 'data-id': dataId,\n disabled,\n size,\n style,\n items,\n priceBreakdown,\n totalCost,\n customer,\n webhook,\n merchantStoreUrl,\n onClick,\n onLoaded,\n onDataProcessed,\n onSplitFeedback,\n onMerchantIdError,\n onConfirm,\n className,\n id,\n } = props;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const elementRef = useRef<HTMLElement | null>(null);\n const [ready, setReady] = useState(false);\n const callbacksRef = useRef({ onClick, onLoaded, onDataProcessed, onSplitFeedback, onMerchantIdError, onConfirm });\n callbacksRef.current = { onClick, onLoaded, onDataProcessed, onSplitFeedback, onMerchantIdError, onConfirm };\n\n useImperativeHandle(ref, () => elementRef.current as HTMLElement, []);\n\n useEffect(() => {\n if (typeof customElements !== 'undefined' && customElements.get('gait-button')) {\n setReady(true);\n return;\n }\n defineCustomElements().then(() => setReady(true), () => setReady(false));\n }, []);\n\n useEffect(() => {\n if (!ready || !containerRef.current) return;\n\n const container = containerRef.current;\n const el = document.createElement('gait-button') as HTMLElement;\n\n applyAttributes(el, { 'data-id': dataId, disabled, size, style, items, priceBreakdown, totalCost, customer, webhook, merchantStoreUrl });\n if (className) el.className = className;\n if (id) el.id = id;\n\n const listeners: Array<() => void> = [];\n EVENT_HANDLERS.forEach(({ event, key }) => {\n const handler = (e: Event) => {\n const cb = callbacksRef.current[key];\n if (cb && e instanceof CustomEvent && e.detail) cb(e.detail as never);\n };\n el.addEventListener(event, handler as EventListener);\n listeners.push(() => el.removeEventListener(event, handler as EventListener));\n });\n\n elementRef.current = el;\n container.appendChild(el);\n\n return () => {\n listeners.forEach((off) => off());\n if (el.parentNode) el.parentNode.removeChild(el);\n elementRef.current = null;\n };\n }, [ready]);\n\n useEffect(() => {\n const el = elementRef.current;\n if (!el) return;\n applyAttributes(el, { 'data-id': dataId, disabled, size, style, items, priceBreakdown, totalCost, customer, webhook, merchantStoreUrl });\n if (className) el.className = className;\n else el.removeAttribute('class');\n if (id) el.id = id;\n else el.removeAttribute('id');\n }, [dataId, disabled, size, style, items, priceBreakdown, totalCost, customer, webhook, merchantStoreUrl, className, id]);\n\n if (!ready) return null;\n return React.createElement('div', { ref: containerRef });\n});\n\nGaitButton.displayName = 'GaitButton';\nexport { GaitButton };\n","/**\n * Loads and registers Gait Web Components. Safe for SSR (no-op when no window).\n * Import once: import '@gait-financial/react/register';\n */\n\nlet loadPromise: Promise<void> | null = null;\n\nexport function defineCustomElements(scriptUrl?: string): Promise<void> {\n if (typeof window === 'undefined' || typeof customElements === 'undefined') return Promise.resolve();\n if (customElements.get('gait-button')) return Promise.resolve();\n if (loadPromise) return loadPromise;\n\n loadPromise = new Promise((resolve, reject) => {\n let src: string;\n if (scriptUrl) src = scriptUrl;\n else {\n try {\n src = new URL('./wc/button.js', import.meta.url).href;\n } catch {\n reject(new Error('[@gait-financial/react] Could not resolve script. With Vite, add optimizeDeps: { exclude: [\"@gait-financial/react\"] } to vite.config.'));\n return;\n }\n }\n const script = document.createElement('script');\n script.async = true;\n script.src = src;\n script.onload = () => resolve();\n script.onerror = () => reject(new Error('[@gait-financial/react] Failed to load web component.'));\n document.head.appendChild(script);\n });\n return loadPromise;\n}\n\nif (typeof window !== 'undefined' && typeof customElements !== 'undefined') {\n void defineCustomElements();\n}\n"],"mappings":"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","names":["GaitButton"]}
|
package/dist/register.cjs
CHANGED
|
@@ -25,45 +25,28 @@ __export(register_exports, {
|
|
|
25
25
|
module.exports = __toCommonJS(register_exports);
|
|
26
26
|
var import_meta = {};
|
|
27
27
|
var loadPromise = null;
|
|
28
|
-
|
|
29
|
-
if (typeof window === "undefined" || typeof customElements === "undefined")
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
28
|
+
function defineCustomElements(scriptUrl) {
|
|
29
|
+
if (typeof window === "undefined" || typeof customElements === "undefined") return Promise.resolve();
|
|
30
|
+
if (customElements.get("gait-button")) return Promise.resolve();
|
|
31
|
+
if (loadPromise) return loadPromise;
|
|
32
|
+
loadPromise = new Promise((resolve, reject) => {
|
|
33
|
+
let src;
|
|
34
|
+
if (scriptUrl) src = scriptUrl;
|
|
35
|
+
else {
|
|
36
|
+
try {
|
|
37
|
+
src = new URL("./wc/button.js", import_meta.url).href;
|
|
38
|
+
} catch {
|
|
39
|
+
reject(new Error('[@gait-financial/react] Could not resolve script. With Vite, add optimizeDeps: { exclude: ["@gait-financial/react"] } to vite.config.'));
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
39
43
|
const script = document.createElement("script");
|
|
40
44
|
script.async = true;
|
|
41
|
-
script.src =
|
|
45
|
+
script.src = src;
|
|
42
46
|
script.onload = () => resolve();
|
|
43
|
-
script.onerror = () => reject();
|
|
47
|
+
script.onerror = () => reject(new Error("[@gait-financial/react] Failed to load web component."));
|
|
44
48
|
document.head.appendChild(script);
|
|
45
49
|
});
|
|
46
|
-
loadPromise = (async () => {
|
|
47
|
-
const fallbackUrl = `${typeof window !== "undefined" ? window.location.origin : ""}/node_modules/@gait-financial/react/dist/wc/button.js`;
|
|
48
|
-
if (scriptUrl) {
|
|
49
|
-
await tryLoad(scriptUrl);
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
try {
|
|
53
|
-
const url = new URL("./wc/button.js", import_meta.url).href;
|
|
54
|
-
await tryLoad(url);
|
|
55
|
-
return;
|
|
56
|
-
} catch {
|
|
57
|
-
}
|
|
58
|
-
try {
|
|
59
|
-
await tryLoad(fallbackUrl);
|
|
60
|
-
return;
|
|
61
|
-
} catch {
|
|
62
|
-
throw new Error(
|
|
63
|
-
'[@gait-financial/react] Failed to load web component script. If using Vite, add optimizeDeps: { exclude: ["@gait-financial/react"] } to vite.config.'
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
})();
|
|
67
50
|
return loadPromise;
|
|
68
51
|
}
|
|
69
52
|
if (typeof window !== "undefined" && typeof customElements !== "undefined") {
|
package/dist/register.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/register.ts"],"sourcesContent":["/**\n *
|
|
1
|
+
{"version":3,"sources":["../src/register.ts"],"sourcesContent":["/**\n * Loads and registers Gait Web Components. Safe for SSR (no-op when no window).\n * Import once: import '@gait-financial/react/register';\n */\n\nlet loadPromise: Promise<void> | null = null;\n\nexport function defineCustomElements(scriptUrl?: string): Promise<void> {\n if (typeof window === 'undefined' || typeof customElements === 'undefined') return Promise.resolve();\n if (customElements.get('gait-button')) return Promise.resolve();\n if (loadPromise) return loadPromise;\n\n loadPromise = new Promise((resolve, reject) => {\n let src: string;\n if (scriptUrl) src = scriptUrl;\n else {\n try {\n src = new URL('./wc/button.js', import.meta.url).href;\n } catch {\n reject(new Error('[@gait-financial/react] Could not resolve script. With Vite, add optimizeDeps: { exclude: [\"@gait-financial/react\"] } to vite.config.'));\n return;\n }\n }\n const script = document.createElement('script');\n script.async = true;\n script.src = src;\n script.onload = () => resolve();\n script.onerror = () => reject(new Error('[@gait-financial/react] Failed to load web component.'));\n document.head.appendChild(script);\n });\n return loadPromise;\n}\n\nif (typeof window !== 'undefined' && typeof customElements !== 'undefined') {\n void defineCustomElements();\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,IAAI,cAAoC;AAEjC,SAAS,qBAAqB,WAAmC;AACtE,MAAI,OAAO,WAAW,eAAe,OAAO,mBAAmB,YAAa,QAAO,QAAQ,QAAQ;AACnG,MAAI,eAAe,IAAI,aAAa,EAAG,QAAO,QAAQ,QAAQ;AAC9D,MAAI,YAAa,QAAO;AAExB,gBAAc,IAAI,QAAQ,CAAC,SAAS,WAAW;AAC7C,QAAI;AACJ,QAAI,UAAW,OAAM;AAAA,SAChB;AACH,UAAI;AACF,cAAM,IAAI,IAAI,kBAAkB,YAAY,GAAG,EAAE;AAAA,MACnD,QAAQ;AACN,eAAO,IAAI,MAAM,uIAAuI,CAAC;AACzJ;AAAA,MACF;AAAA,IACF;AACA,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,QAAQ;AACf,WAAO,MAAM;AACb,WAAO,SAAS,MAAM,QAAQ;AAC9B,WAAO,UAAU,MAAM,OAAO,IAAI,MAAM,uDAAuD,CAAC;AAChG,aAAS,KAAK,YAAY,MAAM;AAAA,EAClC,CAAC;AACD,SAAO;AACT;AAEA,IAAI,OAAO,WAAW,eAAe,OAAO,mBAAmB,aAAa;AAC1E,OAAK,qBAAqB;AAC5B;","names":[]}
|
package/dist/register.d.cts
CHANGED
|
@@ -1,20 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Usage:
|
|
6
|
-
* import '@gait-financial/react/register'; // Side-effect: registers when in browser
|
|
7
|
-
* // or
|
|
8
|
-
* import { defineCustomElements } from '@gait-financial/react/register';
|
|
9
|
-
* await defineCustomElements(); // Optional: load from custom URL
|
|
10
|
-
*/
|
|
11
|
-
/**
|
|
12
|
-
* Loads and registers Gait Web Components.
|
|
13
|
-
* In browser: loads the WC script if not already registered.
|
|
14
|
-
* In SSR: no-op.
|
|
15
|
-
* Deduplicated: multiple calls return the same promise.
|
|
16
|
-
*
|
|
17
|
-
* @param scriptUrl - Optional URL to the button.js script. If omitted, uses the bundled script.
|
|
2
|
+
* Loads and registers Gait Web Components. Safe for SSR (no-op when no window).
|
|
3
|
+
* Import once: import '@gait-financial/react/register';
|
|
18
4
|
*/
|
|
19
5
|
declare function defineCustomElements(scriptUrl?: string): Promise<void>;
|
|
20
6
|
|
package/dist/register.d.ts
CHANGED
|
@@ -1,20 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* Usage:
|
|
6
|
-
* import '@gait-financial/react/register'; // Side-effect: registers when in browser
|
|
7
|
-
* // or
|
|
8
|
-
* import { defineCustomElements } from '@gait-financial/react/register';
|
|
9
|
-
* await defineCustomElements(); // Optional: load from custom URL
|
|
10
|
-
*/
|
|
11
|
-
/**
|
|
12
|
-
* Loads and registers Gait Web Components.
|
|
13
|
-
* In browser: loads the WC script if not already registered.
|
|
14
|
-
* In SSR: no-op.
|
|
15
|
-
* Deduplicated: multiple calls return the same promise.
|
|
16
|
-
*
|
|
17
|
-
* @param scriptUrl - Optional URL to the button.js script. If omitted, uses the bundled script.
|
|
2
|
+
* Loads and registers Gait Web Components. Safe for SSR (no-op when no window).
|
|
3
|
+
* Import once: import '@gait-financial/react/register';
|
|
18
4
|
*/
|
|
19
5
|
declare function defineCustomElements(scriptUrl?: string): Promise<void>;
|
|
20
6
|
|
package/dist/register.js
CHANGED
|
@@ -1,44 +1,27 @@
|
|
|
1
1
|
// src/register.ts
|
|
2
2
|
var loadPromise = null;
|
|
3
|
-
|
|
4
|
-
if (typeof window === "undefined" || typeof customElements === "undefined")
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
3
|
+
function defineCustomElements(scriptUrl) {
|
|
4
|
+
if (typeof window === "undefined" || typeof customElements === "undefined") return Promise.resolve();
|
|
5
|
+
if (customElements.get("gait-button")) return Promise.resolve();
|
|
6
|
+
if (loadPromise) return loadPromise;
|
|
7
|
+
loadPromise = new Promise((resolve, reject) => {
|
|
8
|
+
let src;
|
|
9
|
+
if (scriptUrl) src = scriptUrl;
|
|
10
|
+
else {
|
|
11
|
+
try {
|
|
12
|
+
src = new URL("./wc/button.js", import.meta.url).href;
|
|
13
|
+
} catch {
|
|
14
|
+
reject(new Error('[@gait-financial/react] Could not resolve script. With Vite, add optimizeDeps: { exclude: ["@gait-financial/react"] } to vite.config.'));
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
14
18
|
const script = document.createElement("script");
|
|
15
19
|
script.async = true;
|
|
16
|
-
script.src =
|
|
20
|
+
script.src = src;
|
|
17
21
|
script.onload = () => resolve();
|
|
18
|
-
script.onerror = () => reject();
|
|
22
|
+
script.onerror = () => reject(new Error("[@gait-financial/react] Failed to load web component."));
|
|
19
23
|
document.head.appendChild(script);
|
|
20
24
|
});
|
|
21
|
-
loadPromise = (async () => {
|
|
22
|
-
const fallbackUrl = `${typeof window !== "undefined" ? window.location.origin : ""}/node_modules/@gait-financial/react/dist/wc/button.js`;
|
|
23
|
-
if (scriptUrl) {
|
|
24
|
-
await tryLoad(scriptUrl);
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
try {
|
|
28
|
-
const url = new URL("./wc/button.js", import.meta.url).href;
|
|
29
|
-
await tryLoad(url);
|
|
30
|
-
return;
|
|
31
|
-
} catch {
|
|
32
|
-
}
|
|
33
|
-
try {
|
|
34
|
-
await tryLoad(fallbackUrl);
|
|
35
|
-
return;
|
|
36
|
-
} catch {
|
|
37
|
-
throw new Error(
|
|
38
|
-
'[@gait-financial/react] Failed to load web component script. If using Vite, add optimizeDeps: { exclude: ["@gait-financial/react"] } to vite.config.'
|
|
39
|
-
);
|
|
40
|
-
}
|
|
41
|
-
})();
|
|
42
25
|
return loadPromise;
|
|
43
26
|
}
|
|
44
27
|
if (typeof window !== "undefined" && typeof customElements !== "undefined") {
|
package/dist/register.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/register.ts"],"sourcesContent":["/**\n *
|
|
1
|
+
{"version":3,"sources":["../src/register.ts"],"sourcesContent":["/**\n * Loads and registers Gait Web Components. Safe for SSR (no-op when no window).\n * Import once: import '@gait-financial/react/register';\n */\n\nlet loadPromise: Promise<void> | null = null;\n\nexport function defineCustomElements(scriptUrl?: string): Promise<void> {\n if (typeof window === 'undefined' || typeof customElements === 'undefined') return Promise.resolve();\n if (customElements.get('gait-button')) return Promise.resolve();\n if (loadPromise) return loadPromise;\n\n loadPromise = new Promise((resolve, reject) => {\n let src: string;\n if (scriptUrl) src = scriptUrl;\n else {\n try {\n src = new URL('./wc/button.js', import.meta.url).href;\n } catch {\n reject(new Error('[@gait-financial/react] Could not resolve script. With Vite, add optimizeDeps: { exclude: [\"@gait-financial/react\"] } to vite.config.'));\n return;\n }\n }\n const script = document.createElement('script');\n script.async = true;\n script.src = src;\n script.onload = () => resolve();\n script.onerror = () => reject(new Error('[@gait-financial/react] Failed to load web component.'));\n document.head.appendChild(script);\n });\n return loadPromise;\n}\n\nif (typeof window !== 'undefined' && typeof customElements !== 'undefined') {\n void defineCustomElements();\n}\n"],"mappings":";AAKA,IAAI,cAAoC;AAEjC,SAAS,qBAAqB,WAAmC;AACtE,MAAI,OAAO,WAAW,eAAe,OAAO,mBAAmB,YAAa,QAAO,QAAQ,QAAQ;AACnG,MAAI,eAAe,IAAI,aAAa,EAAG,QAAO,QAAQ,QAAQ;AAC9D,MAAI,YAAa,QAAO;AAExB,gBAAc,IAAI,QAAQ,CAAC,SAAS,WAAW;AAC7C,QAAI;AACJ,QAAI,UAAW,OAAM;AAAA,SAChB;AACH,UAAI;AACF,cAAM,IAAI,IAAI,kBAAkB,YAAY,GAAG,EAAE;AAAA,MACnD,QAAQ;AACN,eAAO,IAAI,MAAM,uIAAuI,CAAC;AACzJ;AAAA,MACF;AAAA,IACF;AACA,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,QAAQ;AACf,WAAO,MAAM;AACb,WAAO,SAAS,MAAM,QAAQ;AAC9B,WAAO,UAAU,MAAM,OAAO,IAAI,MAAM,uDAAuD,CAAC;AAChG,aAAS,KAAK,YAAY,MAAM;AAAA,EAClC,CAAC;AACD,SAAO;AACT;AAEA,IAAI,OAAO,WAAW,eAAe,OAAO,mBAAmB,aAAa;AAC1E,OAAK,qBAAqB;AAC5B;","names":[]}
|