@squaredr/fieldcraft-pro 1.6.4 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,25 +1,116 @@
1
- export { DEFAULT_PALETTE, DEFAULT_SCHEMA, FormBuilder, FormBuilderThemeProvider, QUESTION_TYPE_INFO, addOption, addQuestion, addSection, duplicateQuestion, duplicateSection, findQuestion, findSection, generateId, generateOptionId, generateQuestionId, generateSectionId, moveOption, moveQuestion, moveSection, removeOption, removeQuestion, removeSection, updateOption, updateQuestion, updateSection, useBuilderState, useBuilderTheme, useDragDrop, useUndoRedo } from './chunk-ANBMT5AW.mjs';
2
- export { ResponseViewer } from './chunk-5LKGCZAW.mjs';
1
+ export { DEFAULT_PALETTE, DEFAULT_SCHEMA, FormBuilder, FormBuilderThemeProvider, QUESTION_TYPE_INFO, addOption, addQuestion, addSection, duplicateQuestion, duplicateSection, findQuestion, findSection, generateId, generateOptionId, generateQuestionId, generateSectionId, moveOption, moveQuestion, moveSection, removeOption, removeQuestion, removeSection, updateOption, updateQuestion, updateSection, useBuilderState, useBuilderTheme, useDragDrop, useUndoRedo } from './chunk-GXKQCXIB.mjs';
2
+ export { ResponseViewer } from './chunk-MLP5EDWP.mjs';
3
3
  export { cn } from './chunk-QQ4JZGTD.mjs';
4
- export { PRESET_FAMILIES, PREVIEW_SCHEMA, ThemeEditor, ThemeEditorThemeProvider, resolveThemeFromDOM, themeEditorDarkPreset, themeEditorLightPreset, useEditorTheme } from './chunk-CFVT2R42.mjs';
5
- export { FieldCraftProProvider, UnlicensedOverlay, isProductionEnvironment, requireLicense, useLicense, validateLicense } from './chunk-VECQKSWS.mjs';
6
- import { useState, useEffect, Suspense } from 'react';
4
+ export { consultationBooking, consultationBookingMeta, consultationBookingSchema, ecommerceCheckout, ecommerceCheckoutMeta, ecommerceCheckoutSchema, proTemplates } from './chunk-IW654Z3M.mjs';
5
+ export { PRESET_FAMILIES, PREVIEW_SCHEMA, ThemeEditor, ThemeEditorThemeProvider, resolveThemeFromDOM, themeEditorDarkPreset, themeEditorLightPreset, useEditorTheme } from './chunk-CYXJGOQH.mjs';
6
+ export { FieldCraftProProvider, UnlicensedOverlay, isProductionEnvironment, requireLicense, useLicense, validateLicense } from './chunk-4MMKB2EW.mjs';
7
+ import { useState, useEffect, useMemo } from 'react';
7
8
  import { FieldWrapper } from '@squaredr/fieldcraft-react';
9
+ import { PayKitProvider, CheckoutForm } from '@squaredr/paykit-react';
10
+ import { StripeClientAdapter } from '@squaredr/paykit/stripe/client';
11
+ import { formatAmount } from '@squaredr/paykit';
8
12
  import { jsx, jsxs } from 'react/jsx-runtime';
9
13
 
10
- function formatCurrency(amount, currency) {
11
- if (amount == null) return "";
12
- try {
13
- return new Intl.NumberFormat(void 0, {
14
- style: "currency",
15
- currency: currency ?? "USD"
16
- }).format(amount);
17
- } catch {
18
- return `${currency ?? "USD"} ${amount.toFixed(2)}`;
14
+ // package.json
15
+ var version = "1.8.0";
16
+ function resolvePath(obj, path) {
17
+ let current = obj;
18
+ for (const key of path.split(".")) {
19
+ if (current == null || typeof current !== "object") return void 0;
20
+ current = current[key];
19
21
  }
22
+ return current;
23
+ }
24
+ function isDarkTheme(theme) {
25
+ const bg = theme.colors?.background ?? "#FFFFFF";
26
+ let hex = bg.replace("#", "");
27
+ if (hex.length === 3) {
28
+ hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
29
+ }
30
+ if (hex.length < 6) return false;
31
+ const r = parseInt(hex.slice(0, 2), 16);
32
+ const g = parseInt(hex.slice(2, 4), 16);
33
+ const b = parseInt(hex.slice(4, 6), 16);
34
+ return 0.299 * r + 0.587 * g + 0.114 * b < 128;
35
+ }
36
+ function resolveAppearance(theme) {
37
+ const c = theme.colors;
38
+ const isDark = isDarkTheme(theme);
39
+ return {
40
+ theme: isDark ? "night" : "default",
41
+ variables: {
42
+ colorPrimary: c?.primary,
43
+ colorBackground: c?.surface || c?.background,
44
+ colorText: c?.text,
45
+ colorDanger: c?.error,
46
+ colorSuccess: c?.success || "#22c55e",
47
+ borderRadius: theme.shape?.inputRadius || "6px",
48
+ fontFamily: theme.typography?.fontFamily
49
+ }
50
+ };
51
+ }
52
+ var PAYKIT_STYLES = `
53
+ [data-paykit-form] {
54
+ display: flex;
55
+ flex-direction: column;
56
+ gap: 16px;
57
+ }
58
+ [data-paykit-submit] {
59
+ display: inline-flex;
60
+ align-items: center;
61
+ justify-content: center;
62
+ width: 100%;
63
+ padding: 10px 20px;
64
+ font-size: 0.9375rem;
65
+ font-weight: 600;
66
+ font-family: var(--paykit-font-family, inherit);
67
+ line-height: 1.5;
68
+ color: #fff;
69
+ background: var(--paykit-color-primary, #635BFF);
70
+ border: none;
71
+ border-radius: var(--paykit-border-radius, 6px);
72
+ cursor: pointer;
73
+ transition: opacity 150ms ease, box-shadow 150ms ease, filter 150ms ease;
74
+ }
75
+ [data-paykit-submit]:hover:not(:disabled) {
76
+ filter: brightness(1.1);
77
+ box-shadow: 0 2px 8px color-mix(in srgb, var(--paykit-color-primary, #635BFF) 35%, transparent);
78
+ }
79
+ [data-paykit-submit]:active:not(:disabled) {
80
+ filter: brightness(0.95);
81
+ }
82
+ [data-paykit-submit]:disabled {
83
+ opacity: 0.5;
84
+ cursor: not-allowed;
85
+ }
86
+ `;
87
+ var paykitStylesInjected = false;
88
+ function injectPayKitStyles() {
89
+ if (paykitStylesInjected || typeof document === "undefined") return;
90
+ const style = document.createElement("style");
91
+ style.setAttribute("data-paykit-pro", "");
92
+ style.textContent = PAYKIT_STYLES;
93
+ document.head.appendChild(style);
94
+ paykitStylesInjected = true;
95
+ }
96
+ function formatCurrency(amountCents, currency) {
97
+ if (amountCents == null) return "";
98
+ return formatAmount(amountCents, currency ?? "USD");
20
99
  }
21
100
  function ProPaymentField(props) {
22
- const { field, value, error, touched, disabled, readonly, onChange, onBlur, customProps } = props;
101
+ injectPayKitStyles();
102
+ const {
103
+ field,
104
+ value,
105
+ error,
106
+ touched,
107
+ disabled,
108
+ readonly,
109
+ onChange,
110
+ onBlur,
111
+ customProps,
112
+ theme: formTheme
113
+ } = props;
23
114
  const config = field.config;
24
115
  const current = value ?? { status: "pending" };
25
116
  const provider = config?.provider ?? "stripe";
@@ -41,31 +132,77 @@ function ProPaymentField(props) {
41
132
  }
42
133
  if (mode === "setup" || !amount || !publicKey) return;
43
134
  if (clientSecret) return;
135
+ let cancelled = false;
136
+ const controller = mode === "url" ? new AbortController() : void 0;
44
137
  const fetchIntent = async () => {
45
138
  setIntentLoading(true);
46
139
  setIntentError(null);
47
140
  try {
48
141
  if (mode === "callback" && onCreateIntent) {
49
- const result = await onCreateIntent({ amount, currency, provider, metadata: { fieldId: field.id } });
50
- setClientSecret(result.clientSecret);
142
+ const result = await onCreateIntent({
143
+ amount,
144
+ currency,
145
+ provider,
146
+ metadata: { fieldId: field.id }
147
+ });
148
+ if (!cancelled) setClientSecret(result.clientSecret);
51
149
  } else if (mode === "url" && serverUrl) {
52
150
  const res = await fetch(serverUrl, {
53
151
  method: "POST",
54
152
  headers: { "Content-Type": "application/json" },
55
- body: JSON.stringify({ amount, currency, provider, metadata: { fieldId: field.id } })
153
+ body: JSON.stringify({ amount, currency, provider, metadata: { fieldId: field.id } }),
154
+ signal: controller?.signal
56
155
  });
57
156
  if (!res.ok) throw new Error(`Server error (${res.status})`);
58
157
  const data = await res.json();
59
- setClientSecret(data.clientSecret);
158
+ const secretPath = config?.responseMapping?.clientSecretPath;
159
+ const secret = secretPath ? resolvePath(data, secretPath) : data.clientSecret;
160
+ if (!secret)
161
+ throw new Error(
162
+ "No clientSecret in response" + (secretPath ? ` at path "${secretPath}"` : "")
163
+ );
164
+ if (!cancelled) setClientSecret(secret);
60
165
  }
61
166
  } catch (err) {
167
+ if (cancelled) return;
62
168
  setIntentError(err instanceof Error ? err.message : "Failed to create payment intent");
63
169
  } finally {
64
- setIntentLoading(false);
170
+ if (!cancelled) setIntentLoading(false);
65
171
  }
66
172
  };
67
173
  fetchIntent();
68
- }, [mode, amount, currency, provider, publicKey, directSecret, clientSecret, onCreateIntent, serverUrl, field.id]);
174
+ return () => {
175
+ cancelled = true;
176
+ controller?.abort();
177
+ };
178
+ }, [
179
+ mode,
180
+ amount,
181
+ currency,
182
+ provider,
183
+ publicKey,
184
+ directSecret,
185
+ clientSecret,
186
+ onCreateIntent,
187
+ serverUrl,
188
+ field.id
189
+ ]);
190
+ const c = formTheme.colors;
191
+ const cardStyle = {
192
+ borderRadius: formTheme.shape?.inputRadius || "8px",
193
+ border: `1px solid ${c?.border || "#e2e8f0"}`,
194
+ padding: "16px",
195
+ background: c?.surface || c?.background,
196
+ color: c?.text
197
+ };
198
+ const mutedTextStyle = { color: c?.textMuted, fontSize: "0.875rem" };
199
+ const badgeStyle = {
200
+ fontSize: "0.75rem",
201
+ padding: "2px 8px",
202
+ borderRadius: formTheme.shape?.inputRadius || "4px",
203
+ background: c?.secondary || c?.surface,
204
+ color: c?.secondaryForeground || c?.textMuted
205
+ };
69
206
  const handleSuccess = (chargeId) => {
70
207
  const result = { status: "succeeded", chargeId };
71
208
  onChange(result);
@@ -80,7 +217,8 @@ function ProPaymentField(props) {
80
217
  };
81
218
  if (!publicKey) {
82
219
  return /* @__PURE__ */ jsx(FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsx("div", { className: "rounded-lg border-2 border-dashed border-input p-4 text-center", children: /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
83
- "Payment field \u2014 configure a ",
220
+ "Payment field \u2014 configure a",
221
+ " ",
84
222
  /* @__PURE__ */ jsx("code", { className: "bg-muted px-1 rounded text-xs", children: "publicKey" }),
85
223
  " in the field properties panel."
86
224
  ] }) }) });
@@ -93,40 +231,97 @@ function ProPaymentField(props) {
93
231
  ] }) }) });
94
232
  }
95
233
  if (current.status === "succeeded") {
96
- return /* @__PURE__ */ jsx(FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-input p-4", children: [
97
- amount != null && /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground mb-2", children: [
234
+ return /* @__PURE__ */ jsx(FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxs("div", { style: cardStyle, children: [
235
+ amount != null && /* @__PURE__ */ jsxs("p", { style: { ...mutedTextStyle, marginBottom: "8px" }, children: [
98
236
  formatCurrency(amount, currency),
99
237
  config?.description && /* @__PURE__ */ jsxs("span", { children: [
100
238
  " \u2014 ",
101
239
  config.description
102
240
  ] })
103
241
  ] }),
104
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm font-medium", style: { color: "var(--success, #22c55e)" }, children: [
105
- /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, width: 16, height: 16, children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" }) }),
106
- /* @__PURE__ */ jsxs("span", { children: [
107
- "Payment successful",
108
- current.chargeId ? ` (${current.chargeId})` : ""
109
- ] })
110
- ] })
242
+ /* @__PURE__ */ jsxs(
243
+ "div",
244
+ {
245
+ style: {
246
+ display: "flex",
247
+ alignItems: "center",
248
+ gap: "8px",
249
+ fontSize: "0.875rem",
250
+ fontWeight: 500,
251
+ color: c?.success || "#22c55e"
252
+ },
253
+ children: [
254
+ /* @__PURE__ */ jsx(
255
+ "svg",
256
+ {
257
+ viewBox: "0 0 24 24",
258
+ fill: "none",
259
+ stroke: "currentColor",
260
+ strokeWidth: 2,
261
+ width: 16,
262
+ height: 16,
263
+ children: /* @__PURE__ */ jsx("polyline", { points: "20 6 9 17 4 12" })
264
+ }
265
+ ),
266
+ /* @__PURE__ */ jsxs("span", { children: [
267
+ "Payment successful",
268
+ current.chargeId ? ` (${current.chargeId})` : ""
269
+ ] })
270
+ ]
271
+ }
272
+ )
111
273
  ] }) });
112
274
  }
113
275
  if (current.status === "failed") {
114
- return /* @__PURE__ */ jsx(FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-destructive/50 p-4", children: [
115
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-destructive font-medium", children: [
116
- /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, width: 16, height: 16, children: [
117
- /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
118
- /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
119
- ] }),
120
- /* @__PURE__ */ jsxs("span", { children: [
121
- "Payment failed",
122
- current.error ? `: ${current.error}` : ""
123
- ] })
124
- ] }),
276
+ return /* @__PURE__ */ jsx(FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxs("div", { style: { ...cardStyle, borderColor: c?.error || "#dc2626" }, children: [
277
+ /* @__PURE__ */ jsxs(
278
+ "div",
279
+ {
280
+ style: {
281
+ display: "flex",
282
+ alignItems: "center",
283
+ gap: "8px",
284
+ fontSize: "0.875rem",
285
+ fontWeight: 500,
286
+ color: c?.error || "#dc2626"
287
+ },
288
+ children: [
289
+ /* @__PURE__ */ jsxs(
290
+ "svg",
291
+ {
292
+ viewBox: "0 0 24 24",
293
+ fill: "none",
294
+ stroke: "currentColor",
295
+ strokeWidth: 2,
296
+ width: 16,
297
+ height: 16,
298
+ children: [
299
+ /* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
300
+ /* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
301
+ ]
302
+ }
303
+ ),
304
+ /* @__PURE__ */ jsxs("span", { children: [
305
+ "Payment failed",
306
+ current.error ? `: ${current.error}` : ""
307
+ ] })
308
+ ]
309
+ }
310
+ ),
125
311
  /* @__PURE__ */ jsx(
126
312
  "button",
127
313
  {
128
314
  type: "button",
129
- className: "mt-2 text-xs text-primary hover:underline",
315
+ style: {
316
+ marginTop: "8px",
317
+ fontSize: "0.75rem",
318
+ color: c?.primary,
319
+ background: "none",
320
+ border: "none",
321
+ cursor: "pointer",
322
+ textDecoration: "underline",
323
+ padding: 0
324
+ },
130
325
  onClick: () => {
131
326
  onChange({ status: "pending" });
132
327
  setClientSecret(void 0);
@@ -137,26 +332,46 @@ function ProPaymentField(props) {
137
332
  ] }) });
138
333
  }
139
334
  if (intentLoading || mode !== "setup" && mode !== "direct" && !clientSecret) {
140
- return /* @__PURE__ */ jsx(FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-input p-4", children: [
141
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
142
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Payment" }),
143
- /* @__PURE__ */ jsx("span", { className: "text-xs bg-muted px-2 py-0.5 rounded", children: provider })
144
- ] }),
145
- amount != null && /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground mb-3", children: [
335
+ return /* @__PURE__ */ jsx(FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxs("div", { style: cardStyle, children: [
336
+ /* @__PURE__ */ jsxs(
337
+ "div",
338
+ {
339
+ style: {
340
+ display: "flex",
341
+ alignItems: "center",
342
+ justifyContent: "space-between",
343
+ marginBottom: "12px"
344
+ },
345
+ children: [
346
+ /* @__PURE__ */ jsx("p", { style: { fontSize: "0.875rem", fontWeight: 500 }, children: "Payment" }),
347
+ /* @__PURE__ */ jsx("span", { style: badgeStyle, children: provider })
348
+ ]
349
+ }
350
+ ),
351
+ amount != null && /* @__PURE__ */ jsxs("p", { style: { ...mutedTextStyle, marginBottom: "12px" }, children: [
146
352
  "Amount: ",
147
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: formatCurrency(amount, currency) }),
353
+ /* @__PURE__ */ jsx("span", { style: { fontWeight: 500 }, children: formatCurrency(amount, currency) }),
148
354
  config?.description && /* @__PURE__ */ jsxs("span", { children: [
149
355
  " \u2014 ",
150
356
  config.description
151
357
  ] })
152
358
  ] }),
153
359
  intentError ? /* @__PURE__ */ jsxs("div", { children: [
154
- /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: intentError }),
360
+ /* @__PURE__ */ jsx("p", { style: { fontSize: "0.875rem", color: c?.error || "#dc2626" }, children: intentError }),
155
361
  /* @__PURE__ */ jsx(
156
362
  "button",
157
363
  {
158
364
  type: "button",
159
- className: "mt-2 text-xs text-primary hover:underline",
365
+ style: {
366
+ marginTop: "8px",
367
+ fontSize: "0.75rem",
368
+ color: c?.primary,
369
+ background: "none",
370
+ border: "none",
371
+ cursor: "pointer",
372
+ textDecoration: "underline",
373
+ padding: 0
374
+ },
160
375
  onClick: () => {
161
376
  setIntentError(null);
162
377
  setClientSecret(void 0);
@@ -164,54 +379,78 @@ function ProPaymentField(props) {
164
379
  children: "Retry"
165
380
  }
166
381
  )
167
- ] }) : /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
168
- /* @__PURE__ */ jsx("svg", { className: "animate-spin size-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10", strokeDasharray: "60", strokeDashoffset: "20" }) }),
382
+ ] }) : /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", ...mutedTextStyle }, children: [
383
+ /* @__PURE__ */ jsx(
384
+ "svg",
385
+ {
386
+ style: { width: "16px", height: "16px", animation: "spin 1s linear infinite" },
387
+ viewBox: "0 0 24 24",
388
+ fill: "none",
389
+ stroke: "currentColor",
390
+ strokeWidth: 2,
391
+ children: /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10", strokeDasharray: "60", strokeDashoffset: "20" })
392
+ }
393
+ ),
169
394
  /* @__PURE__ */ jsx("span", { children: "Preparing payment..." })
170
395
  ] })
171
396
  ] }) });
172
397
  }
173
398
  if (!clientSecret) {
174
399
  const waitingForAmount = config?.amountField && !amount;
175
- return /* @__PURE__ */ jsx(FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-input p-4", children: [
176
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
177
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Payment" }),
178
- /* @__PURE__ */ jsx("span", { className: "text-xs bg-muted px-2 py-0.5 rounded", children: provider })
179
- ] }),
180
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: waitingForAmount ? "Select an option above to proceed with payment." : "Provide a clientSecret via customProps, an onCreatePaymentIntent callback, or a serverUrl." })
400
+ return /* @__PURE__ */ jsx(FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxs("div", { style: cardStyle, children: [
401
+ /* @__PURE__ */ jsxs(
402
+ "div",
403
+ {
404
+ style: {
405
+ display: "flex",
406
+ alignItems: "center",
407
+ justifyContent: "space-between",
408
+ marginBottom: "12px"
409
+ },
410
+ children: [
411
+ /* @__PURE__ */ jsx("p", { style: { fontSize: "0.875rem", fontWeight: 500 }, children: "Payment" }),
412
+ /* @__PURE__ */ jsx("span", { style: badgeStyle, children: provider })
413
+ ]
414
+ }
415
+ ),
416
+ /* @__PURE__ */ jsx("p", { style: mutedTextStyle, children: waitingForAmount ? "Select an option above to proceed with payment." : "Provide a clientSecret via customProps, an onCreatePaymentIntent callback, or a serverUrl." })
181
417
  ] }) });
182
418
  }
183
- return /* @__PURE__ */ jsx(FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-input p-4", children: [
184
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-3", children: [
185
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Payment" }),
186
- /* @__PURE__ */ jsx("span", { className: "text-xs bg-muted px-2 py-0.5 rounded", children: provider })
187
- ] }),
188
- amount != null && /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground mb-3", children: [
419
+ return /* @__PURE__ */ jsx(FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxs("div", { style: cardStyle, children: [
420
+ /* @__PURE__ */ jsxs(
421
+ "div",
422
+ {
423
+ style: {
424
+ display: "flex",
425
+ alignItems: "center",
426
+ justifyContent: "space-between",
427
+ marginBottom: "12px"
428
+ },
429
+ children: [
430
+ /* @__PURE__ */ jsx("p", { style: { fontSize: "0.875rem", fontWeight: 500 }, children: "Payment" }),
431
+ /* @__PURE__ */ jsx("span", { style: badgeStyle, children: provider })
432
+ ]
433
+ }
434
+ ),
435
+ amount != null && /* @__PURE__ */ jsxs("p", { style: { ...mutedTextStyle, marginBottom: "12px" }, children: [
189
436
  "Amount: ",
190
- /* @__PURE__ */ jsx("span", { className: "font-medium", children: formatCurrency(amount, currency) }),
437
+ /* @__PURE__ */ jsx("span", { style: { fontWeight: 500 }, children: formatCurrency(amount, currency) }),
191
438
  config?.description && /* @__PURE__ */ jsxs("span", { children: [
192
439
  " \u2014 ",
193
440
  config.description
194
441
  ] })
195
442
  ] }),
196
443
  /* @__PURE__ */ jsx(
197
- Suspense,
444
+ PayKitCheckout,
198
445
  {
199
- fallback: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground py-4", children: [
200
- /* @__PURE__ */ jsx("svg", { className: "animate-spin size-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10", strokeDasharray: "60", strokeDashoffset: "20" }) }),
201
- "Loading payment form..."
202
- ] }),
203
- children: /* @__PURE__ */ jsx(
204
- PayKitCheckout,
205
- {
206
- publicKey,
207
- clientSecret,
208
- amount,
209
- currency,
210
- disabled: disabled || readonly,
211
- onSuccess: handleSuccess,
212
- onError: handleError
213
- }
214
- )
446
+ publicKey,
447
+ clientSecret,
448
+ amount,
449
+ currency,
450
+ appearance: resolveAppearance(formTheme),
451
+ disabled: disabled || readonly,
452
+ onSuccess: handleSuccess,
453
+ onError: handleError
215
454
  }
216
455
  )
217
456
  ] }) });
@@ -221,49 +460,17 @@ function PayKitCheckout({
221
460
  clientSecret,
222
461
  amount,
223
462
  currency,
463
+ appearance,
224
464
  disabled,
225
465
  onSuccess,
226
466
  onError
227
467
  }) {
228
- const [PayKit, setPayKit] = useState(null);
229
- const [loadError, setLoadError] = useState(null);
230
- useEffect(() => {
231
- let cancelled = false;
232
- Promise.all([
233
- // @ts-expect-error — optional peer dep, resolved at runtime
234
- import('@squaredr/paykit-react'),
235
- // @ts-expect-error — optional peer dep, resolved at runtime
236
- import('@squaredr/paykit-stripe/client')
237
- ]).then(([paykit, stripe]) => {
238
- if (cancelled) return;
239
- setPayKit({
240
- Provider: paykit.PayKitProvider,
241
- Form: paykit.CheckoutForm,
242
- adapter: new stripe.StripeClientAdapter(publicKey)
243
- });
244
- }).catch((err) => {
245
- if (cancelled) return;
246
- setLoadError(
247
- `Failed to load payment SDK. Ensure @squaredr/paykit-react and @squaredr/paykit-stripe are installed. (${err.message})`
248
- );
249
- });
250
- return () => {
251
- cancelled = true;
252
- };
253
- }, [publicKey]);
254
- if (loadError) {
255
- return /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: loadError });
256
- }
257
- if (!PayKit) {
258
- return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground py-2", children: [
259
- /* @__PURE__ */ jsx("svg", { className: "animate-spin size-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10", strokeDasharray: "60", strokeDashoffset: "20" }) }),
260
- "Loading Stripe..."
261
- ] });
262
- }
263
- return /* @__PURE__ */ jsx(PayKit.Provider, { clientAdapter: PayKit.adapter, children: /* @__PURE__ */ jsx(
264
- PayKit.Form,
468
+ const clientAdapter = useMemo(() => new StripeClientAdapter(publicKey), [publicKey]);
469
+ return /* @__PURE__ */ jsx(PayKitProvider, { clientAdapter, children: /* @__PURE__ */ jsx(
470
+ CheckoutForm,
265
471
  {
266
472
  clientSecret,
473
+ appearance,
267
474
  submitLabel: disabled ? "Payment disabled" : `Pay ${formatCurrency(amount, currency)}`,
268
475
  onSuccess: (result) => onSuccess(result.chargeId),
269
476
  onError: (err) => onError(err.message)
@@ -277,15 +484,15 @@ var PRO_FIELD_OVERRIDES = {
277
484
  // src/index.ts
278
485
  if (typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" && globalThis.process.env?.NODE_ENV !== "production") {
279
486
  const _fc_banner = `
280
- %c FieldCraft Pro %c v1.6.3
487
+ %c FieldCraft Pro %c v${version}
281
488
 
282
489
  %cForm Builder \xB7 Response Viewer \xB7 Theme Editor
283
490
 
284
- Docs \u2192 https://squaredr.tech/products/fieldcraft/docs/pro
285
- Pro Tools \u2192 https://squaredr.tech/products/fieldcraft/admin-pro
491
+ Docs \u2192 https://fieldcraft.squaredr.tech/docs
492
+ Pro \u2192 https://fieldcraft.squaredr.tech/pro
286
493
  Discord \u2192 https://discord.gg/zMxdu5UVW
287
494
 
288
- Need a license? \u2192 https://squaredr.tech/products/fieldcraft/admin-pro#pricing
495
+ Need a license? \u2192 https://fieldcraft.squaredr.tech/pro#pricing
289
496
  `;
290
497
  console.log(
291
498
  _fc_banner,
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { FormEngineSchema, FormResponse } from '@squaredr/fieldcraft-core';
2
+ import { FormResponse, FormEngineSchema } from '@squaredr/fieldcraft-core';
3
3
 
4
4
  type FieldRenderer = (field: ResponseField, response: FormResponse) => React.ReactNode;
5
5
  type ResponseViewerProps = {
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { FormEngineSchema, FormResponse } from '@squaredr/fieldcraft-core';
2
+ import { FormResponse, FormEngineSchema } from '@squaredr/fieldcraft-core';
3
3
 
4
4
  type FieldRenderer = (field: ResponseField, response: FormResponse) => React.ReactNode;
5
5
  type ResponseViewerProps = {