@squaredr/fieldcraft-pro 1.3.0 → 1.5.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/chunk-22T5PY6L.mjs +1081 -0
- package/dist/{chunk-GNBXIG63.mjs → chunk-6LRUDBC7.mjs} +1305 -89
- package/dist/{chunk-4BX7FCXH.mjs → chunk-BK4SMEW4.mjs} +840 -21
- package/dist/form-builder/index.d.mts +7 -367
- package/dist/form-builder/index.d.ts +7 -367
- package/dist/form-builder/index.js +1307 -91
- package/dist/form-builder/index.mjs +1 -1
- package/dist/index-BHJ4mqHP.d.mts +398 -0
- package/dist/index-BHJ4mqHP.d.ts +398 -0
- package/dist/index.d.mts +30 -3
- package/dist/index.d.ts +30 -3
- package/dist/index.js +3230 -331
- package/dist/index.mjs +276 -4
- package/dist/preview-schema-DFvV4y6J.d.mts +66 -0
- package/dist/preview-schema-DFvV4y6J.d.ts +66 -0
- package/dist/response-viewer/index.d.mts +9 -1
- package/dist/response-viewer/index.d.ts +9 -1
- package/dist/response-viewer/index.js +838 -19
- package/dist/response-viewer/index.mjs +1 -1
- package/dist/styles.css +1 -1
- package/dist/theme-editor/index.d.mts +30 -26
- package/dist/theme-editor/index.d.ts +30 -26
- package/dist/theme-editor/index.js +702 -22
- package/dist/theme-editor/index.mjs +1 -1
- package/package.json +18 -6
- package/theme-editor/styles.css +266 -62
- package/dist/chunk-7LQW5QYT.mjs +0 -407
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,283 @@
|
|
|
1
|
-
export { DEFAULT_PALETTE, DEFAULT_SCHEMA, FormBuilder, FormBuilderThemeProvider, QUESTION_TYPE_INFO, addOption, addQuestion, addSection, cleanPreset, duplicateQuestion, duplicateSection, findQuestion, findSection, generateId, generateOptionId, generateQuestionId, generateSectionId, moveOption, moveQuestion, moveSection, removeOption, removeQuestion, removeSection, squaredrDarkPreset, updateOption, updateQuestion, updateSection, useBuilderState, useBuilderTheme, useDragDrop, useUndoRedo } from './chunk-
|
|
2
|
-
export { ResponseViewer } from './chunk-
|
|
1
|
+
export { DEFAULT_PALETTE, DEFAULT_SCHEMA, FormBuilder, FormBuilderThemeProvider, QUESTION_TYPE_INFO, addOption, addQuestion, addSection, cleanPreset, duplicateQuestion, duplicateSection, findQuestion, findSection, generateId, generateOptionId, generateQuestionId, generateSectionId, moveOption, moveQuestion, moveSection, removeOption, removeQuestion, removeSection, squaredrDarkPreset, updateOption, updateQuestion, updateSection, useBuilderState, useBuilderTheme, useDragDrop, useUndoRedo } from './chunk-6LRUDBC7.mjs';
|
|
2
|
+
export { ResponseViewer } from './chunk-BK4SMEW4.mjs';
|
|
3
3
|
export { cn } from './chunk-QQ4JZGTD.mjs';
|
|
4
|
-
export { PREVIEW_SCHEMA, ThemeEditor, ThemeEditorInner } from './chunk-
|
|
4
|
+
export { PREVIEW_SCHEMA, ThemeEditor, ThemeEditorInner } from './chunk-22T5PY6L.mjs';
|
|
5
5
|
export { FieldCraftProProvider, UnlicensedOverlay, isProductionEnvironment, requireLicense, useLicense, validateLicense } from './chunk-VECQKSWS.mjs';
|
|
6
|
+
import { useState, useEffect, Suspense } from 'react';
|
|
7
|
+
import { FieldWrapper } from '@squaredr/fieldcraft-react';
|
|
8
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
9
|
+
|
|
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)}`;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function ProPaymentField(props) {
|
|
22
|
+
const { field, value, error, touched, disabled, readonly, onChange, onBlur, customProps } = props;
|
|
23
|
+
const config = field.config;
|
|
24
|
+
const current = value ?? { status: "pending" };
|
|
25
|
+
const provider = config?.provider ?? "stripe";
|
|
26
|
+
const publicKey = config?.publicKey;
|
|
27
|
+
const amount = customProps?.amount ?? config?.amount;
|
|
28
|
+
const currency = config?.currency ?? "USD";
|
|
29
|
+
const directSecret = customProps?.clientSecret;
|
|
30
|
+
const onCreateIntent = customProps?.onCreatePaymentIntent;
|
|
31
|
+
const onPaymentComplete = customProps?.onPaymentComplete;
|
|
32
|
+
const serverUrl = config?.serverUrl;
|
|
33
|
+
const [clientSecret, setClientSecret] = useState(directSecret);
|
|
34
|
+
const [intentLoading, setIntentLoading] = useState(false);
|
|
35
|
+
const [intentError, setIntentError] = useState(null);
|
|
36
|
+
const mode = directSecret ? "direct" : onCreateIntent ? "callback" : serverUrl ? "url" : "setup";
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (directSecret) {
|
|
39
|
+
setClientSecret(directSecret);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
if (mode === "setup" || !amount || !publicKey) return;
|
|
43
|
+
if (clientSecret) return;
|
|
44
|
+
const fetchIntent = async () => {
|
|
45
|
+
setIntentLoading(true);
|
|
46
|
+
setIntentError(null);
|
|
47
|
+
try {
|
|
48
|
+
if (mode === "callback" && onCreateIntent) {
|
|
49
|
+
const result = await onCreateIntent({ amount, currency, provider, metadata: { fieldId: field.id } });
|
|
50
|
+
setClientSecret(result.clientSecret);
|
|
51
|
+
} else if (mode === "url" && serverUrl) {
|
|
52
|
+
const res = await fetch(serverUrl, {
|
|
53
|
+
method: "POST",
|
|
54
|
+
headers: { "Content-Type": "application/json" },
|
|
55
|
+
body: JSON.stringify({ amount, currency, provider, metadata: { fieldId: field.id } })
|
|
56
|
+
});
|
|
57
|
+
if (!res.ok) throw new Error(`Server error (${res.status})`);
|
|
58
|
+
const data = await res.json();
|
|
59
|
+
setClientSecret(data.clientSecret);
|
|
60
|
+
}
|
|
61
|
+
} catch (err) {
|
|
62
|
+
setIntentError(err instanceof Error ? err.message : "Failed to create payment intent");
|
|
63
|
+
} finally {
|
|
64
|
+
setIntentLoading(false);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
fetchIntent();
|
|
68
|
+
}, [mode, amount, currency, provider, publicKey, directSecret, clientSecret, onCreateIntent, serverUrl, field.id]);
|
|
69
|
+
const handleSuccess = (chargeId) => {
|
|
70
|
+
const result = { status: "succeeded", chargeId };
|
|
71
|
+
onChange(result);
|
|
72
|
+
onPaymentComplete?.(result);
|
|
73
|
+
onBlur();
|
|
74
|
+
};
|
|
75
|
+
const handleError = (message) => {
|
|
76
|
+
const result = { status: "failed", error: message };
|
|
77
|
+
onChange(result);
|
|
78
|
+
onPaymentComplete?.(result);
|
|
79
|
+
onBlur();
|
|
80
|
+
};
|
|
81
|
+
if (!publicKey) {
|
|
82
|
+
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 ",
|
|
84
|
+
/* @__PURE__ */ jsx("code", { className: "bg-muted px-1 rounded text-xs", children: "publicKey" }),
|
|
85
|
+
" in the field properties panel."
|
|
86
|
+
] }) }) });
|
|
87
|
+
}
|
|
88
|
+
if (provider !== "stripe") {
|
|
89
|
+
return /* @__PURE__ */ jsx(FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-input bg-muted/50 p-4", children: /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
90
|
+
'Provider "',
|
|
91
|
+
provider,
|
|
92
|
+
'" \u2014 coming soon.'
|
|
93
|
+
] }) }) });
|
|
94
|
+
}
|
|
95
|
+
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: [
|
|
98
|
+
formatCurrency(amount, currency),
|
|
99
|
+
config?.description && /* @__PURE__ */ jsxs("span", { children: [
|
|
100
|
+
" \u2014 ",
|
|
101
|
+
config.description
|
|
102
|
+
] })
|
|
103
|
+
] }),
|
|
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
|
+
] })
|
|
111
|
+
] }) });
|
|
112
|
+
}
|
|
113
|
+
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
|
+
] }),
|
|
125
|
+
/* @__PURE__ */ jsx(
|
|
126
|
+
"button",
|
|
127
|
+
{
|
|
128
|
+
type: "button",
|
|
129
|
+
className: "mt-2 text-xs text-primary hover:underline",
|
|
130
|
+
onClick: () => {
|
|
131
|
+
onChange({ status: "pending" });
|
|
132
|
+
setClientSecret(void 0);
|
|
133
|
+
},
|
|
134
|
+
children: "Retry"
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
] }) });
|
|
138
|
+
}
|
|
139
|
+
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: [
|
|
146
|
+
"Amount: ",
|
|
147
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: formatCurrency(amount, currency) }),
|
|
148
|
+
config?.description && /* @__PURE__ */ jsxs("span", { children: [
|
|
149
|
+
" \u2014 ",
|
|
150
|
+
config.description
|
|
151
|
+
] })
|
|
152
|
+
] }),
|
|
153
|
+
intentError ? /* @__PURE__ */ jsxs("div", { children: [
|
|
154
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: intentError }),
|
|
155
|
+
/* @__PURE__ */ jsx(
|
|
156
|
+
"button",
|
|
157
|
+
{
|
|
158
|
+
type: "button",
|
|
159
|
+
className: "mt-2 text-xs text-primary hover:underline",
|
|
160
|
+
onClick: () => {
|
|
161
|
+
setIntentError(null);
|
|
162
|
+
setClientSecret(void 0);
|
|
163
|
+
},
|
|
164
|
+
children: "Retry"
|
|
165
|
+
}
|
|
166
|
+
)
|
|
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" }) }),
|
|
169
|
+
/* @__PURE__ */ jsx("span", { children: "Preparing payment..." })
|
|
170
|
+
] })
|
|
171
|
+
] }) });
|
|
172
|
+
}
|
|
173
|
+
if (!clientSecret) {
|
|
174
|
+
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." })
|
|
181
|
+
] }) });
|
|
182
|
+
}
|
|
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: [
|
|
189
|
+
"Amount: ",
|
|
190
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: formatCurrency(amount, currency) }),
|
|
191
|
+
config?.description && /* @__PURE__ */ jsxs("span", { children: [
|
|
192
|
+
" \u2014 ",
|
|
193
|
+
config.description
|
|
194
|
+
] })
|
|
195
|
+
] }),
|
|
196
|
+
/* @__PURE__ */ jsx(
|
|
197
|
+
Suspense,
|
|
198
|
+
{
|
|
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
|
+
)
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
] }) });
|
|
218
|
+
}
|
|
219
|
+
function PayKitCheckout({
|
|
220
|
+
publicKey,
|
|
221
|
+
clientSecret,
|
|
222
|
+
amount,
|
|
223
|
+
currency,
|
|
224
|
+
disabled,
|
|
225
|
+
onSuccess,
|
|
226
|
+
onError
|
|
227
|
+
}) {
|
|
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,
|
|
265
|
+
{
|
|
266
|
+
clientSecret,
|
|
267
|
+
submitLabel: disabled ? "Payment disabled" : `Pay ${formatCurrency(amount, currency)}`,
|
|
268
|
+
onSuccess: (result) => onSuccess(result.chargeId),
|
|
269
|
+
onError: (err) => onError(err.message)
|
|
270
|
+
}
|
|
271
|
+
) });
|
|
272
|
+
}
|
|
273
|
+
var PRO_FIELD_OVERRIDES = {
|
|
274
|
+
payment: ProPaymentField
|
|
275
|
+
};
|
|
6
276
|
|
|
7
277
|
// src/index.ts
|
|
8
278
|
if (typeof globalThis !== "undefined" && typeof globalThis.process !== "undefined" && globalThis.process.env?.NODE_ENV !== "production") {
|
|
9
279
|
const _fc_banner = `
|
|
10
|
-
%c FieldCraft Pro %c v1.
|
|
280
|
+
%c FieldCraft Pro %c v1.5.0
|
|
11
281
|
|
|
12
282
|
%cForm Builder \xB7 Response Viewer \xB7 Theme Editor
|
|
13
283
|
|
|
@@ -24,3 +294,5 @@ Need a license? \u2192 https://squaredr.tech/products/fieldcraft/admin-pro#prici
|
|
|
24
294
|
"color:#6b7280"
|
|
25
295
|
);
|
|
26
296
|
}
|
|
297
|
+
|
|
298
|
+
export { PRO_FIELD_OVERRIDES, ProPaymentField };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
import { FormEngineTheme, FormEngineSchema } from '@squaredr/fieldcraft-core';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ThemeEditor chrome theme configuration.
|
|
8
|
+
* Controls the appearance of the editor UI (toolbar, controls, panels)
|
|
9
|
+
* — NOT the form preview, which uses the FormEngineTheme being edited.
|
|
10
|
+
*
|
|
11
|
+
* All values are CSS color strings (hex, oklch, hsl, etc.).
|
|
12
|
+
*/
|
|
13
|
+
type ThemeEditorTheme = {
|
|
14
|
+
/** Main background of the entire editor */
|
|
15
|
+
background?: string;
|
|
16
|
+
/** Surface background (toolbar, panels, editor column) */
|
|
17
|
+
surface?: string;
|
|
18
|
+
/** Surface hover state */
|
|
19
|
+
surfaceHover?: string;
|
|
20
|
+
/** Primary text color */
|
|
21
|
+
text?: string;
|
|
22
|
+
/** Muted text color (labels, secondary info) */
|
|
23
|
+
textMuted?: string;
|
|
24
|
+
/** Dim text color (suffixes, tertiary info) */
|
|
25
|
+
textDim?: string;
|
|
26
|
+
/** Default border color */
|
|
27
|
+
border?: string;
|
|
28
|
+
/** Strong border color (inputs, emphasis) */
|
|
29
|
+
borderStrong?: string;
|
|
30
|
+
/** Input background color */
|
|
31
|
+
inputBackground?: string;
|
|
32
|
+
/** Primary accent color (buttons, focus) */
|
|
33
|
+
accent?: string;
|
|
34
|
+
/** Text color on accent backgrounds */
|
|
35
|
+
accentForeground?: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
type ThemeEditorProps = {
|
|
39
|
+
/** Initial theme to load. Defaults to draftingTealPreset. */
|
|
40
|
+
initialTheme?: FormEngineTheme;
|
|
41
|
+
/** Called on every theme change. */
|
|
42
|
+
onChange?: (theme: FormEngineTheme) => void;
|
|
43
|
+
/** Called when user clicks Save or presses Ctrl+S. */
|
|
44
|
+
onSave?: (theme: FormEngineTheme) => void;
|
|
45
|
+
/** Editor chrome theme. Controls toolbar, panel, and control appearance. */
|
|
46
|
+
theme?: ThemeEditorTheme;
|
|
47
|
+
/** Container height. */
|
|
48
|
+
height?: string | number;
|
|
49
|
+
/** Container width. */
|
|
50
|
+
width?: string | number;
|
|
51
|
+
/** Additional CSS class on root element. */
|
|
52
|
+
className?: string;
|
|
53
|
+
/** Extra content in the toolbar. */
|
|
54
|
+
toolbarExtra?: ReactNode;
|
|
55
|
+
/** Show live preview panel. Default: true. */
|
|
56
|
+
showPreview?: boolean;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
declare const ThemeEditor: react.ComponentType<ThemeEditorProps>;
|
|
60
|
+
|
|
61
|
+
declare function ThemeEditorInner({ initialTheme, onChange, onSave, theme: chromeTheme, height, width, className, toolbarExtra, showPreview, }: ThemeEditorProps): react_jsx_runtime.JSX.Element;
|
|
62
|
+
|
|
63
|
+
/** Compact schema used in the ThemeEditor live preview panel. */
|
|
64
|
+
declare const PREVIEW_SCHEMA: FormEngineSchema;
|
|
65
|
+
|
|
66
|
+
export { PREVIEW_SCHEMA as P, ThemeEditor as T, ThemeEditorInner as a, type ThemeEditorProps as b, type ThemeEditorTheme as c };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
import { FormEngineTheme, FormEngineSchema } from '@squaredr/fieldcraft-core';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ThemeEditor chrome theme configuration.
|
|
8
|
+
* Controls the appearance of the editor UI (toolbar, controls, panels)
|
|
9
|
+
* — NOT the form preview, which uses the FormEngineTheme being edited.
|
|
10
|
+
*
|
|
11
|
+
* All values are CSS color strings (hex, oklch, hsl, etc.).
|
|
12
|
+
*/
|
|
13
|
+
type ThemeEditorTheme = {
|
|
14
|
+
/** Main background of the entire editor */
|
|
15
|
+
background?: string;
|
|
16
|
+
/** Surface background (toolbar, panels, editor column) */
|
|
17
|
+
surface?: string;
|
|
18
|
+
/** Surface hover state */
|
|
19
|
+
surfaceHover?: string;
|
|
20
|
+
/** Primary text color */
|
|
21
|
+
text?: string;
|
|
22
|
+
/** Muted text color (labels, secondary info) */
|
|
23
|
+
textMuted?: string;
|
|
24
|
+
/** Dim text color (suffixes, tertiary info) */
|
|
25
|
+
textDim?: string;
|
|
26
|
+
/** Default border color */
|
|
27
|
+
border?: string;
|
|
28
|
+
/** Strong border color (inputs, emphasis) */
|
|
29
|
+
borderStrong?: string;
|
|
30
|
+
/** Input background color */
|
|
31
|
+
inputBackground?: string;
|
|
32
|
+
/** Primary accent color (buttons, focus) */
|
|
33
|
+
accent?: string;
|
|
34
|
+
/** Text color on accent backgrounds */
|
|
35
|
+
accentForeground?: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
type ThemeEditorProps = {
|
|
39
|
+
/** Initial theme to load. Defaults to draftingTealPreset. */
|
|
40
|
+
initialTheme?: FormEngineTheme;
|
|
41
|
+
/** Called on every theme change. */
|
|
42
|
+
onChange?: (theme: FormEngineTheme) => void;
|
|
43
|
+
/** Called when user clicks Save or presses Ctrl+S. */
|
|
44
|
+
onSave?: (theme: FormEngineTheme) => void;
|
|
45
|
+
/** Editor chrome theme. Controls toolbar, panel, and control appearance. */
|
|
46
|
+
theme?: ThemeEditorTheme;
|
|
47
|
+
/** Container height. */
|
|
48
|
+
height?: string | number;
|
|
49
|
+
/** Container width. */
|
|
50
|
+
width?: string | number;
|
|
51
|
+
/** Additional CSS class on root element. */
|
|
52
|
+
className?: string;
|
|
53
|
+
/** Extra content in the toolbar. */
|
|
54
|
+
toolbarExtra?: ReactNode;
|
|
55
|
+
/** Show live preview panel. Default: true. */
|
|
56
|
+
showPreview?: boolean;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
declare const ThemeEditor: react.ComponentType<ThemeEditorProps>;
|
|
60
|
+
|
|
61
|
+
declare function ThemeEditorInner({ initialTheme, onChange, onSave, theme: chromeTheme, height, width, className, toolbarExtra, showPreview, }: ThemeEditorProps): react_jsx_runtime.JSX.Element;
|
|
62
|
+
|
|
63
|
+
/** Compact schema used in the ThemeEditor live preview panel. */
|
|
64
|
+
declare const PREVIEW_SCHEMA: FormEngineSchema;
|
|
65
|
+
|
|
66
|
+
export { PREVIEW_SCHEMA as P, ThemeEditor as T, ThemeEditorInner as a, type ThemeEditorProps as b, type ThemeEditorTheme as c };
|
|
@@ -20,8 +20,16 @@ type ResponseViewerProps = {
|
|
|
20
20
|
onExport?: (format: "csv" | "json", count: number) => void;
|
|
21
21
|
/** Number of responses per page in table/card views. Defaults to 25. */
|
|
22
22
|
pageSize?: 10 | 25 | 50 | 100;
|
|
23
|
+
/** Callback to delete a single response by its sessionToken. */
|
|
24
|
+
onDelete?: (sessionToken: string) => void;
|
|
25
|
+
/** Callback to bulk-delete responses by sessionToken. */
|
|
26
|
+
onBulkDelete?: (sessionTokens: string[]) => void;
|
|
27
|
+
/** Callback to bulk-export selected responses. */
|
|
28
|
+
onBulkExport?: (responses: FormResponse[]) => void;
|
|
29
|
+
/** Enable checkbox selection for bulk operations. */
|
|
30
|
+
selectable?: boolean;
|
|
23
31
|
};
|
|
24
|
-
type ViewMode = "table" | "card" | "detail";
|
|
32
|
+
type ViewMode = "table" | "card" | "detail" | "timeline";
|
|
25
33
|
type ResponseField = {
|
|
26
34
|
questionId: string;
|
|
27
35
|
label: string;
|
|
@@ -20,8 +20,16 @@ type ResponseViewerProps = {
|
|
|
20
20
|
onExport?: (format: "csv" | "json", count: number) => void;
|
|
21
21
|
/** Number of responses per page in table/card views. Defaults to 25. */
|
|
22
22
|
pageSize?: 10 | 25 | 50 | 100;
|
|
23
|
+
/** Callback to delete a single response by its sessionToken. */
|
|
24
|
+
onDelete?: (sessionToken: string) => void;
|
|
25
|
+
/** Callback to bulk-delete responses by sessionToken. */
|
|
26
|
+
onBulkDelete?: (sessionTokens: string[]) => void;
|
|
27
|
+
/** Callback to bulk-export selected responses. */
|
|
28
|
+
onBulkExport?: (responses: FormResponse[]) => void;
|
|
29
|
+
/** Enable checkbox selection for bulk operations. */
|
|
30
|
+
selectable?: boolean;
|
|
23
31
|
};
|
|
24
|
-
type ViewMode = "table" | "card" | "detail";
|
|
32
|
+
type ViewMode = "table" | "card" | "detail" | "timeline";
|
|
25
33
|
type ResponseField = {
|
|
26
34
|
questionId: string;
|
|
27
35
|
label: string;
|