@squaredr/fieldcraft-pro 0.0.5 → 1.1.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/LICENSE.txt +48 -10
- package/README.md +37 -6
- package/dist/{chunk-MQGR25NG.mjs → chunk-7LQW5QYT.mjs} +1 -3
- package/dist/{chunk-APHGEYG4.mjs → chunk-CJBC3KWB.mjs} +156 -130
- package/dist/chunk-QQ4JZGTD.mjs +9 -0
- package/dist/chunk-RSU3X25P.mjs +976 -0
- package/dist/chunk-VECQKSWS.mjs +582 -0
- package/dist/form-builder/index.d.mts +2 -2
- package/dist/form-builder/index.d.ts +2 -2
- package/dist/form-builder/index.js +474 -123
- package/dist/form-builder/index.mjs +3 -1
- package/dist/index.d.mts +52 -3
- package/dist/index.d.ts +52 -3
- package/dist/index.js +1571 -474
- package/dist/index.mjs +7 -5
- package/dist/response-viewer/index.d.mts +4 -1
- package/dist/response-viewer/index.d.ts +4 -1
- package/dist/response-viewer/index.js +1155 -320
- package/dist/response-viewer/index.mjs +3 -1
- package/dist/styles.css +1 -1
- package/dist/theme-editor/index.js +324 -4
- package/dist/theme-editor/index.mjs +2 -1
- package/package.json +15 -14
- package/dist/chunk-NIKQEWPG.mjs +0 -467
- /package/{dist/theme-editor-styles.css → theme-editor/styles.css} +0 -0
|
@@ -1,15 +1,336 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var fieldcraftProLicense = require('@squaredr/fieldcraft-pro-license');
|
|
4
3
|
var react = require('react');
|
|
4
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
5
5
|
var core = require('@dnd-kit/core');
|
|
6
6
|
var lucideReact = require('lucide-react');
|
|
7
7
|
var fieldcraftReact = require('@squaredr/fieldcraft-react');
|
|
8
|
+
var fieldcraftCore = require('@squaredr/fieldcraft-core');
|
|
8
9
|
var clsx = require('clsx');
|
|
9
10
|
var tailwindMerge = require('tailwind-merge');
|
|
10
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
11
11
|
|
|
12
|
-
//
|
|
12
|
+
// ../license/dist/index.mjs
|
|
13
|
+
var PRO_FEATURES = [
|
|
14
|
+
"SchemaEditor",
|
|
15
|
+
"ResponseViewer",
|
|
16
|
+
"ThemeEditor",
|
|
17
|
+
"FormBuilder",
|
|
18
|
+
"ApiManager",
|
|
19
|
+
"Analytics"
|
|
20
|
+
];
|
|
21
|
+
var ALL_FEATURES = [
|
|
22
|
+
...PRO_FEATURES,
|
|
23
|
+
"Telehealth"
|
|
24
|
+
];
|
|
25
|
+
var TIER_FEATURES = {
|
|
26
|
+
starter: ["SchemaEditor", "ResponseViewer"],
|
|
27
|
+
pro: PRO_FEATURES,
|
|
28
|
+
business: ALL_FEATURES,
|
|
29
|
+
enterprise: ALL_FEATURES
|
|
30
|
+
};
|
|
31
|
+
function tierHasFeature(tier, featureName) {
|
|
32
|
+
return TIER_FEATURES[tier]?.includes(featureName) ?? false;
|
|
33
|
+
}
|
|
34
|
+
var DEV_HOSTNAMES = /* @__PURE__ */ new Set([
|
|
35
|
+
"localhost",
|
|
36
|
+
"127.0.0.1",
|
|
37
|
+
"0.0.0.0",
|
|
38
|
+
"[::1]",
|
|
39
|
+
"::1"
|
|
40
|
+
]);
|
|
41
|
+
var DEV_HOSTNAME_PATTERNS = [
|
|
42
|
+
/^192\.168\.\d+\.\d+$/,
|
|
43
|
+
// local network
|
|
44
|
+
/^10\.\d+\.\d+\.\d+$/,
|
|
45
|
+
// local network
|
|
46
|
+
/^172\.(1[6-9]|2\d|3[01])\.\d+\.\d+$/
|
|
47
|
+
// local network
|
|
48
|
+
];
|
|
49
|
+
var PRODUCTION_HOST_SUFFIXES = [
|
|
50
|
+
".vercel.app",
|
|
51
|
+
".netlify.app",
|
|
52
|
+
".netlify.com",
|
|
53
|
+
".herokuapp.com",
|
|
54
|
+
".fly.dev",
|
|
55
|
+
".railway.app",
|
|
56
|
+
".render.com",
|
|
57
|
+
".onrender.com",
|
|
58
|
+
".pages.dev",
|
|
59
|
+
// Cloudflare Pages
|
|
60
|
+
".workers.dev",
|
|
61
|
+
// Cloudflare Workers
|
|
62
|
+
".azurewebsites.net",
|
|
63
|
+
".web.app",
|
|
64
|
+
// Firebase
|
|
65
|
+
".firebaseapp.com",
|
|
66
|
+
".amplifyapp.com",
|
|
67
|
+
".surge.sh",
|
|
68
|
+
".github.io",
|
|
69
|
+
".gitlab.io"
|
|
70
|
+
];
|
|
71
|
+
function isDevHostname(hostname) {
|
|
72
|
+
if (DEV_HOSTNAMES.has(hostname)) return true;
|
|
73
|
+
for (const pattern of DEV_HOSTNAME_PATTERNS) {
|
|
74
|
+
if (pattern.test(hostname)) return true;
|
|
75
|
+
}
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
function isKnownProductionHost(hostname) {
|
|
79
|
+
for (const suffix of PRODUCTION_HOST_SUFFIXES) {
|
|
80
|
+
if (hostname.endsWith(suffix)) return true;
|
|
81
|
+
}
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
function hasRealTLD(hostname) {
|
|
85
|
+
return /\.[a-z]{2,}$/i.test(hostname) && !isDevHostname(hostname);
|
|
86
|
+
}
|
|
87
|
+
function isProductionEnvironment() {
|
|
88
|
+
const _proc = typeof globalThis !== "undefined" ? globalThis.process : void 0;
|
|
89
|
+
if (_proc?.env) {
|
|
90
|
+
const nodeEnv = _proc.env.NODE_ENV;
|
|
91
|
+
if (nodeEnv === "production") return true;
|
|
92
|
+
if (nodeEnv === "development" || nodeEnv === "test") return false;
|
|
93
|
+
}
|
|
94
|
+
if (typeof window !== "undefined" && window.location) {
|
|
95
|
+
const { hostname, protocol, port } = window.location;
|
|
96
|
+
if (protocol === "file:") return false;
|
|
97
|
+
if (isDevHostname(hostname)) return false;
|
|
98
|
+
if (port && port !== "443" && port !== "80") return false;
|
|
99
|
+
if (isKnownProductionHost(hostname)) return true;
|
|
100
|
+
if (protocol === "https:" && hasRealTLD(hostname)) return true;
|
|
101
|
+
if (hasRealTLD(hostname)) return true;
|
|
102
|
+
}
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
var defaultContext = { status: "validating", tier: null };
|
|
106
|
+
var LicenseCtx = react.createContext(defaultContext);
|
|
107
|
+
function useLicense() {
|
|
108
|
+
return react.useContext(LicenseCtx);
|
|
109
|
+
}
|
|
110
|
+
function UnlicensedOverlay({ featureName, reason, children }) {
|
|
111
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", minHeight: "200px" }, children: [
|
|
112
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { pointerEvents: "none", userSelect: "none", filter: "blur(2px)" }, children }),
|
|
113
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
114
|
+
"div",
|
|
115
|
+
{
|
|
116
|
+
style: {
|
|
117
|
+
position: "absolute",
|
|
118
|
+
inset: 0,
|
|
119
|
+
zIndex: 2147483647,
|
|
120
|
+
display: "flex",
|
|
121
|
+
flexDirection: "column",
|
|
122
|
+
alignItems: "center",
|
|
123
|
+
justifyContent: "center",
|
|
124
|
+
backgroundColor: "rgba(0, 0, 0, 0.75)",
|
|
125
|
+
backdropFilter: "blur(4px)",
|
|
126
|
+
fontFamily: "system-ui, -apple-system, sans-serif",
|
|
127
|
+
padding: "32px"
|
|
128
|
+
},
|
|
129
|
+
children: [
|
|
130
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
131
|
+
"div",
|
|
132
|
+
{
|
|
133
|
+
style: {
|
|
134
|
+
position: "absolute",
|
|
135
|
+
inset: 0,
|
|
136
|
+
overflow: "hidden",
|
|
137
|
+
pointerEvents: "none",
|
|
138
|
+
zIndex: 0
|
|
139
|
+
},
|
|
140
|
+
children: Array.from({ length: 12 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
141
|
+
"div",
|
|
142
|
+
{
|
|
143
|
+
style: {
|
|
144
|
+
position: "absolute",
|
|
145
|
+
top: `${i * 80}px`,
|
|
146
|
+
left: "-50%",
|
|
147
|
+
right: "-50%",
|
|
148
|
+
textAlign: "center",
|
|
149
|
+
transform: "rotate(-30deg)",
|
|
150
|
+
fontSize: "18px",
|
|
151
|
+
fontWeight: 700,
|
|
152
|
+
color: "rgba(255, 255, 255, 0.06)",
|
|
153
|
+
letterSpacing: "8px",
|
|
154
|
+
textTransform: "uppercase",
|
|
155
|
+
whiteSpace: "nowrap",
|
|
156
|
+
userSelect: "none"
|
|
157
|
+
},
|
|
158
|
+
children: "UNLICENSED \u2022 FIELDCRAFT PRO \u2022 UNLICENSED \u2022 FIELDCRAFT PRO \u2022 UNLICENSED \u2022 FIELDCRAFT PRO"
|
|
159
|
+
},
|
|
160
|
+
i
|
|
161
|
+
))
|
|
162
|
+
}
|
|
163
|
+
),
|
|
164
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
165
|
+
"div",
|
|
166
|
+
{
|
|
167
|
+
style: {
|
|
168
|
+
position: "relative",
|
|
169
|
+
zIndex: 1,
|
|
170
|
+
textAlign: "center",
|
|
171
|
+
maxWidth: "420px"
|
|
172
|
+
},
|
|
173
|
+
children: [
|
|
174
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
175
|
+
"div",
|
|
176
|
+
{
|
|
177
|
+
style: {
|
|
178
|
+
width: "64px",
|
|
179
|
+
height: "64px",
|
|
180
|
+
margin: "0 auto 16px",
|
|
181
|
+
borderRadius: "50%",
|
|
182
|
+
backgroundColor: "rgba(239, 68, 68, 0.2)",
|
|
183
|
+
border: "2px solid rgba(239, 68, 68, 0.5)",
|
|
184
|
+
display: "flex",
|
|
185
|
+
alignItems: "center",
|
|
186
|
+
justifyContent: "center",
|
|
187
|
+
fontSize: "28px"
|
|
188
|
+
},
|
|
189
|
+
children: "\u{1F6E1}"
|
|
190
|
+
}
|
|
191
|
+
),
|
|
192
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
193
|
+
"div",
|
|
194
|
+
{
|
|
195
|
+
style: {
|
|
196
|
+
fontSize: "22px",
|
|
197
|
+
fontWeight: 700,
|
|
198
|
+
color: "#ffffff",
|
|
199
|
+
marginBottom: "8px",
|
|
200
|
+
letterSpacing: "-0.02em"
|
|
201
|
+
},
|
|
202
|
+
children: "License Required"
|
|
203
|
+
}
|
|
204
|
+
),
|
|
205
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
206
|
+
"div",
|
|
207
|
+
{
|
|
208
|
+
style: {
|
|
209
|
+
fontSize: "15px",
|
|
210
|
+
fontWeight: 600,
|
|
211
|
+
color: "#f87171",
|
|
212
|
+
marginBottom: "6px"
|
|
213
|
+
},
|
|
214
|
+
children: featureName
|
|
215
|
+
}
|
|
216
|
+
),
|
|
217
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
218
|
+
"div",
|
|
219
|
+
{
|
|
220
|
+
style: {
|
|
221
|
+
fontSize: "14px",
|
|
222
|
+
color: "#d1d5db",
|
|
223
|
+
marginBottom: "24px",
|
|
224
|
+
lineHeight: "1.5"
|
|
225
|
+
},
|
|
226
|
+
children: reason
|
|
227
|
+
}
|
|
228
|
+
),
|
|
229
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: "10px", justifyContent: "center", flexWrap: "wrap" }, children: [
|
|
230
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
231
|
+
"a",
|
|
232
|
+
{
|
|
233
|
+
href: "https://squaredr.tech/products/fieldcraft/admin-pro#pricing",
|
|
234
|
+
target: "_blank",
|
|
235
|
+
rel: "noopener noreferrer",
|
|
236
|
+
style: {
|
|
237
|
+
display: "inline-block",
|
|
238
|
+
padding: "12px 24px",
|
|
239
|
+
fontSize: "14px",
|
|
240
|
+
fontWeight: 600,
|
|
241
|
+
color: "#ffffff",
|
|
242
|
+
backgroundColor: "#2563eb",
|
|
243
|
+
borderRadius: "8px",
|
|
244
|
+
textDecoration: "none",
|
|
245
|
+
boxShadow: "0 4px 14px rgba(37, 99, 235, 0.4)"
|
|
246
|
+
},
|
|
247
|
+
children: "Get a License"
|
|
248
|
+
}
|
|
249
|
+
),
|
|
250
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
251
|
+
"a",
|
|
252
|
+
{
|
|
253
|
+
href: "https://discord.gg/zMxdu5UVW",
|
|
254
|
+
target: "_blank",
|
|
255
|
+
rel: "noopener noreferrer",
|
|
256
|
+
style: {
|
|
257
|
+
display: "inline-block",
|
|
258
|
+
padding: "12px 24px",
|
|
259
|
+
fontSize: "14px",
|
|
260
|
+
fontWeight: 600,
|
|
261
|
+
color: "#93c5fd",
|
|
262
|
+
backgroundColor: "rgba(37, 99, 235, 0.15)",
|
|
263
|
+
border: "1px solid rgba(37, 99, 235, 0.4)",
|
|
264
|
+
borderRadius: "8px",
|
|
265
|
+
textDecoration: "none"
|
|
266
|
+
},
|
|
267
|
+
children: "Join Discord"
|
|
268
|
+
}
|
|
269
|
+
)
|
|
270
|
+
] }),
|
|
271
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
272
|
+
"div",
|
|
273
|
+
{
|
|
274
|
+
style: {
|
|
275
|
+
fontSize: "12px",
|
|
276
|
+
color: "#6b7280",
|
|
277
|
+
marginTop: "16px"
|
|
278
|
+
},
|
|
279
|
+
children: [
|
|
280
|
+
"This component works freely in development.",
|
|
281
|
+
" ",
|
|
282
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
283
|
+
"a",
|
|
284
|
+
{
|
|
285
|
+
href: "https://squaredr.tech/products/fieldcraft/docs/pro/license",
|
|
286
|
+
target: "_blank",
|
|
287
|
+
rel: "noopener noreferrer",
|
|
288
|
+
style: { color: "#9ca3af", textDecoration: "underline" },
|
|
289
|
+
children: "Learn more"
|
|
290
|
+
}
|
|
291
|
+
)
|
|
292
|
+
]
|
|
293
|
+
}
|
|
294
|
+
)
|
|
295
|
+
]
|
|
296
|
+
}
|
|
297
|
+
)
|
|
298
|
+
]
|
|
299
|
+
}
|
|
300
|
+
)
|
|
301
|
+
] });
|
|
302
|
+
}
|
|
303
|
+
function requireLicense(Component2, featureName) {
|
|
304
|
+
function LicenseGated(props) {
|
|
305
|
+
const { status, tier } = useLicense();
|
|
306
|
+
const isProduction = isProductionEnvironment();
|
|
307
|
+
if (!isProduction) {
|
|
308
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Component2, { ...props });
|
|
309
|
+
}
|
|
310
|
+
if (status === "validating") {
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
const isLicensed = status === "valid" && tier != null && tierHasFeature(tier, featureName);
|
|
314
|
+
if (isLicensed) {
|
|
315
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Component2, { ...props });
|
|
316
|
+
}
|
|
317
|
+
let reason = "A valid license is required for production use.";
|
|
318
|
+
if (status === "invalid") {
|
|
319
|
+
reason = "Invalid license key. Please check your license key and try again.";
|
|
320
|
+
} else if (status === "expired") {
|
|
321
|
+
reason = "Your license has expired. Please renew to continue using this component in production.";
|
|
322
|
+
} else if (status === "revoked") {
|
|
323
|
+
reason = "This license key has been revoked. Please contact support or purchase a new license.";
|
|
324
|
+
} else if (status === "domain_mismatch") {
|
|
325
|
+
reason = "This license key is registered to a different domain. Each key can only be used on one production domain. Please purchase a new license for this domain.";
|
|
326
|
+
} else if (!tier || !tierHasFeature(tier, featureName)) {
|
|
327
|
+
reason = "Your license does not include this feature. Please upgrade your plan.";
|
|
328
|
+
}
|
|
329
|
+
return /* @__PURE__ */ jsxRuntime.jsx(UnlicensedOverlay, { featureName, reason, children: /* @__PURE__ */ jsxRuntime.jsx(Component2, { ...props }) });
|
|
330
|
+
}
|
|
331
|
+
LicenseGated.displayName = `requireLicense(${Component2.displayName || Component2.name || "Component"})`;
|
|
332
|
+
return LicenseGated;
|
|
333
|
+
}
|
|
13
334
|
var MAX_HISTORY = 50;
|
|
14
335
|
function useUndoRedo(currentSchema, setSchema) {
|
|
15
336
|
const historyRef = react.useRef([currentSchema]);
|
|
@@ -80,6 +401,39 @@ function generateOptionId() {
|
|
|
80
401
|
function deepClone(obj) {
|
|
81
402
|
return structuredClone(obj);
|
|
82
403
|
}
|
|
404
|
+
function cleanCondition(expr, deletedFieldId) {
|
|
405
|
+
if (expr.field === deletedFieldId) return void 0;
|
|
406
|
+
if (expr.field && expr.field !== deletedFieldId) return expr;
|
|
407
|
+
if (expr.conditions) {
|
|
408
|
+
const cleaned = expr.conditions.map((c) => cleanCondition(c, deletedFieldId)).filter((c) => c !== void 0);
|
|
409
|
+
if (cleaned.length === 0) return void 0;
|
|
410
|
+
if (cleaned.length === 1) return cleaned[0];
|
|
411
|
+
return { ...expr, conditions: cleaned };
|
|
412
|
+
}
|
|
413
|
+
return expr;
|
|
414
|
+
}
|
|
415
|
+
function cleanupOrphanConditions(schema, deletedFieldId) {
|
|
416
|
+
for (const section of schema.sections) {
|
|
417
|
+
if (section.showIf) {
|
|
418
|
+
const cleaned = cleanCondition(section.showIf, deletedFieldId);
|
|
419
|
+
if (cleaned) {
|
|
420
|
+
section.showIf = cleaned;
|
|
421
|
+
} else {
|
|
422
|
+
delete section.showIf;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
for (const question of section.questions) {
|
|
426
|
+
if (question.showIf) {
|
|
427
|
+
const cleaned = cleanCondition(question.showIf, deletedFieldId);
|
|
428
|
+
if (cleaned) {
|
|
429
|
+
question.showIf = cleaned;
|
|
430
|
+
} else {
|
|
431
|
+
delete question.showIf;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
83
437
|
function addSection(schema, section, index) {
|
|
84
438
|
const newSchema = deepClone(schema);
|
|
85
439
|
newSchema.sections.splice(index, 0, section);
|
|
@@ -87,7 +441,12 @@ function addSection(schema, section, index) {
|
|
|
87
441
|
}
|
|
88
442
|
function removeSection(schema, sectionId) {
|
|
89
443
|
const newSchema = deepClone(schema);
|
|
444
|
+
const removedSection = newSchema.sections.find((s) => s.id === sectionId);
|
|
445
|
+
const removedFieldIds = removedSection ? removedSection.questions.map((q) => q.id) : [];
|
|
90
446
|
newSchema.sections = newSchema.sections.filter((s) => s.id !== sectionId);
|
|
447
|
+
for (const fieldId of removedFieldIds) {
|
|
448
|
+
cleanupOrphanConditions(newSchema, fieldId);
|
|
449
|
+
}
|
|
91
450
|
return newSchema;
|
|
92
451
|
}
|
|
93
452
|
function updateSection(schema, sectionId, updates) {
|
|
@@ -137,6 +496,7 @@ function removeQuestion(schema, sectionId, questionId) {
|
|
|
137
496
|
const section = newSchema.sections.find((s) => s.id === sectionId);
|
|
138
497
|
if (!section) return schema;
|
|
139
498
|
section.questions = section.questions.filter((q) => q.id !== questionId);
|
|
499
|
+
cleanupOrphanConditions(newSchema, questionId);
|
|
140
500
|
return newSchema;
|
|
141
501
|
}
|
|
142
502
|
function updateQuestion(schema, sectionId, questionId, updates) {
|
|
@@ -975,11 +1335,13 @@ function QuestionPalette({ questionTypes, palette }) {
|
|
|
975
1335
|
const isCollapsed = collapsed[category.category] && !search;
|
|
976
1336
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-3", children: [
|
|
977
1337
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
978
|
-
|
|
1338
|
+
fieldcraftReact.Button,
|
|
979
1339
|
{
|
|
980
1340
|
type: "button",
|
|
1341
|
+
variant: "ghost",
|
|
1342
|
+
size: "xs",
|
|
981
1343
|
onClick: () => toggleCategory(category.category),
|
|
982
|
-
className: "
|
|
1344
|
+
className: "w-full justify-start px-1 text-[11px] font-semibold uppercase tracking-widest text-muted-foreground",
|
|
983
1345
|
"aria-expanded": !isCollapsed,
|
|
984
1346
|
children: [
|
|
985
1347
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1343,11 +1705,12 @@ function FormCanvas({ builderState }) {
|
|
|
1343
1705
|
section.id
|
|
1344
1706
|
)),
|
|
1345
1707
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1346
|
-
|
|
1708
|
+
fieldcraftReact.Button,
|
|
1347
1709
|
{
|
|
1348
1710
|
type: "button",
|
|
1711
|
+
variant: "outline",
|
|
1349
1712
|
onClick: handleAddSection,
|
|
1350
|
-
className: "w-full py-4 text-sm font-medium
|
|
1713
|
+
className: "w-full py-4 h-auto text-sm font-medium border-dashed border-fcb-border-strong text-muted-foreground hover:border-primary hover:text-primary hover:bg-primary/5",
|
|
1351
1714
|
children: [
|
|
1352
1715
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { size: 14, strokeWidth: 2 }),
|
|
1353
1716
|
"Add Section"
|
|
@@ -1357,6 +1720,26 @@ function FormCanvas({ builderState }) {
|
|
|
1357
1720
|
] })
|
|
1358
1721
|
] }) });
|
|
1359
1722
|
}
|
|
1723
|
+
var NativeSelect = react.forwardRef(
|
|
1724
|
+
({ className, wrapperClassName, children, ...props }, ref) => {
|
|
1725
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative", wrapperClassName), children: [
|
|
1726
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1727
|
+
"select",
|
|
1728
|
+
{
|
|
1729
|
+
ref,
|
|
1730
|
+
className: cn(
|
|
1731
|
+
"flex h-9 w-full appearance-none rounded-md border border-input bg-card px-3 py-1 pr-8 text-sm shadow-xs transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring text-foreground cursor-pointer",
|
|
1732
|
+
className
|
|
1733
|
+
),
|
|
1734
|
+
...props,
|
|
1735
|
+
children
|
|
1736
|
+
}
|
|
1737
|
+
),
|
|
1738
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "pointer-events-none absolute right-2.5 top-1/2 -translate-y-1/2 size-4 text-muted-foreground" })
|
|
1739
|
+
] });
|
|
1740
|
+
}
|
|
1741
|
+
);
|
|
1742
|
+
NativeSelect.displayName = "NativeSelect";
|
|
1360
1743
|
function useConfigUpdater(question, onUpdate) {
|
|
1361
1744
|
return (field, value) => {
|
|
1362
1745
|
const current = question.config ?? {};
|
|
@@ -1751,18 +2134,7 @@ function SelectField({
|
|
|
1751
2134
|
}) {
|
|
1752
2135
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1753
2136
|
/* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Label, { className: "text-xs text-muted-foreground mb-1", children: label }),
|
|
1754
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1755
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1756
|
-
"select",
|
|
1757
|
-
{
|
|
1758
|
-
value,
|
|
1759
|
-
onChange: (e) => onChange(e.target.value),
|
|
1760
|
-
className: "flex h-9 w-full appearance-none rounded-md border border-input bg-card px-3 py-1 pr-8 text-sm shadow-xs transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring text-foreground cursor-pointer",
|
|
1761
|
-
children: options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt.value, children: opt.label }, opt.value))
|
|
1762
|
-
}
|
|
1763
|
-
),
|
|
1764
|
-
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "pointer-events-none absolute right-2.5 top-1/2 -translate-y-1/2 size-4 text-muted-foreground", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" }) })
|
|
1765
|
-
] })
|
|
2137
|
+
/* @__PURE__ */ jsxRuntime.jsx(NativeSelect, { value, onChange: (e) => onChange(e.target.value), children: options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt.value, children: opt.label }, opt.value)) })
|
|
1766
2138
|
] });
|
|
1767
2139
|
}
|
|
1768
2140
|
function LikertLabelsEditor({
|
|
@@ -1783,15 +2155,7 @@ function LikertLabelsEditor({
|
|
|
1783
2155
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1784
2156
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
1785
2157
|
/* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Label, { className: "text-xs text-muted-foreground", children: "Scale Labels" }),
|
|
1786
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1787
|
-
"button",
|
|
1788
|
-
{
|
|
1789
|
-
type: "button",
|
|
1790
|
-
onClick: handleAdd,
|
|
1791
|
-
className: "text-xs text-primary hover:underline",
|
|
1792
|
-
children: "+ Add"
|
|
1793
|
-
}
|
|
1794
|
-
)
|
|
2158
|
+
/* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Button, { type: "button", variant: "link", size: "xs", onClick: handleAdd, className: "px-0", children: "+ Add" })
|
|
1795
2159
|
] }),
|
|
1796
2160
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: labels.map((label, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 group", children: [
|
|
1797
2161
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground w-4 text-right shrink-0", children: index + 1 }),
|
|
@@ -1804,11 +2168,13 @@ function LikertLabelsEditor({
|
|
|
1804
2168
|
}
|
|
1805
2169
|
),
|
|
1806
2170
|
labels.length > 2 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1807
|
-
|
|
2171
|
+
fieldcraftReact.Button,
|
|
1808
2172
|
{
|
|
1809
2173
|
type: "button",
|
|
2174
|
+
variant: "ghost",
|
|
2175
|
+
size: "icon-xs",
|
|
1810
2176
|
onClick: () => handleRemove(index),
|
|
1811
|
-
className: "text-
|
|
2177
|
+
className: "text-destructive opacity-0 group-hover:opacity-100 transition-opacity",
|
|
1812
2178
|
children: "x"
|
|
1813
2179
|
}
|
|
1814
2180
|
)
|
|
@@ -1837,15 +2203,7 @@ function MatrixItemsEditor({
|
|
|
1837
2203
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1838
2204
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
1839
2205
|
/* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Label, { className: "text-xs text-muted-foreground", children: label }),
|
|
1840
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1841
|
-
"button",
|
|
1842
|
-
{
|
|
1843
|
-
type: "button",
|
|
1844
|
-
onClick: handleAdd,
|
|
1845
|
-
className: "text-xs text-primary hover:underline",
|
|
1846
|
-
children: "+ Add"
|
|
1847
|
-
}
|
|
1848
|
-
)
|
|
2206
|
+
/* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Button, { type: "button", variant: "link", size: "xs", onClick: handleAdd, className: "px-0", children: "+ Add" })
|
|
1849
2207
|
] }),
|
|
1850
2208
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 group", children: [
|
|
1851
2209
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1857,11 +2215,13 @@ function MatrixItemsEditor({
|
|
|
1857
2215
|
}
|
|
1858
2216
|
),
|
|
1859
2217
|
items.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1860
|
-
|
|
2218
|
+
fieldcraftReact.Button,
|
|
1861
2219
|
{
|
|
1862
2220
|
type: "button",
|
|
2221
|
+
variant: "ghost",
|
|
2222
|
+
size: "icon-xs",
|
|
1863
2223
|
onClick: () => handleRemove(index),
|
|
1864
|
-
className: "text-
|
|
2224
|
+
className: "text-destructive opacity-0 group-hover:opacity-100 transition-opacity",
|
|
1865
2225
|
children: "x"
|
|
1866
2226
|
}
|
|
1867
2227
|
)
|
|
@@ -1894,7 +2254,7 @@ function ScoringOptionsEditor({
|
|
|
1894
2254
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1895
2255
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
1896
2256
|
/* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Label, { className: "text-xs text-muted-foreground", children: "Score Options" }),
|
|
1897
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2257
|
+
/* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Button, { type: "button", variant: "link", size: "xs", onClick: handleAdd, className: "px-0", children: "+ Add" })
|
|
1898
2258
|
] }),
|
|
1899
2259
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: options.map((opt, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 group", children: [
|
|
1900
2260
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1916,7 +2276,7 @@ function ScoringOptionsEditor({
|
|
|
1916
2276
|
placeholder: "Score"
|
|
1917
2277
|
}
|
|
1918
2278
|
),
|
|
1919
|
-
options.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2279
|
+
options.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Button, { type: "button", variant: "ghost", size: "icon-xs", onClick: () => handleRemove(index), className: "text-destructive opacity-0 group-hover:opacity-100 transition-opacity", children: "x" })
|
|
1920
2280
|
] }, index)) })
|
|
1921
2281
|
] });
|
|
1922
2282
|
}
|
|
@@ -1938,7 +2298,7 @@ function ScoreRangesEditor({
|
|
|
1938
2298
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1939
2299
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
1940
2300
|
/* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Label, { className: "text-xs text-muted-foreground", children: "Score Ranges" }),
|
|
1941
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2301
|
+
/* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Button, { type: "button", variant: "link", size: "xs", onClick: handleAdd, className: "px-0", children: "+ Add" })
|
|
1942
2302
|
] }),
|
|
1943
2303
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: ranges.map((range, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-2 rounded-md border border-border space-y-1.5 group", children: [
|
|
1944
2304
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
@@ -1946,7 +2306,7 @@ function ScoreRangesEditor({
|
|
|
1946
2306
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: "to" }),
|
|
1947
2307
|
/* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Input, { type: "number", value: range.max, onChange: (e) => handleUpdate(index, { max: Number(e.target.value) }), className: "h-7 text-xs w-16", placeholder: "Max" }),
|
|
1948
2308
|
/* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Input, { value: range.label, onChange: (e) => handleUpdate(index, { label: e.target.value }), className: "h-7 text-xs flex-1", placeholder: "Label" }),
|
|
1949
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2309
|
+
/* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Button, { type: "button", variant: "ghost", size: "icon-xs", onClick: () => handleRemove(index), className: "text-destructive opacity-0 group-hover:opacity-100 transition-opacity", children: "x" })
|
|
1950
2310
|
] }),
|
|
1951
2311
|
/* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Input, { value: range.description ?? "", onChange: (e) => handleUpdate(index, { description: e.target.value || void 0 }), className: "h-7 text-xs", placeholder: "Description (optional)" })
|
|
1952
2312
|
] }, index)) })
|
|
@@ -1996,26 +2356,20 @@ function ValidationRulesEditor({ question, onUpdate }) {
|
|
|
1996
2356
|
},
|
|
1997
2357
|
`${rule.type}-${index}`
|
|
1998
2358
|
)) }),
|
|
1999
|
-
availableTypes.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
children:
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
availableTypes.map((t) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: t.value, children: t.label }, t.value))
|
|
2014
|
-
]
|
|
2015
|
-
}
|
|
2016
|
-
),
|
|
2017
|
-
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "pointer-events-none absolute right-2.5 top-1/2 -translate-y-1/2 size-3.5 text-muted-foreground", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" }) })
|
|
2018
|
-
] }) })
|
|
2359
|
+
availableTypes.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2360
|
+
NativeSelect,
|
|
2361
|
+
{
|
|
2362
|
+
value: "",
|
|
2363
|
+
onChange: (e) => {
|
|
2364
|
+
if (e.target.value) addRule(e.target.value);
|
|
2365
|
+
},
|
|
2366
|
+
className: "h-8 text-xs text-muted-foreground",
|
|
2367
|
+
children: [
|
|
2368
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Add validation rule..." }),
|
|
2369
|
+
availableTypes.map((t) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: t.value, children: t.label }, t.value))
|
|
2370
|
+
]
|
|
2371
|
+
}
|
|
2372
|
+
) })
|
|
2019
2373
|
] });
|
|
2020
2374
|
}
|
|
2021
2375
|
function RuleRow({
|
|
@@ -2029,13 +2383,15 @@ function RuleRow({
|
|
|
2029
2383
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2030
2384
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-foreground", children: label }),
|
|
2031
2385
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2032
|
-
|
|
2386
|
+
fieldcraftReact.Button,
|
|
2033
2387
|
{
|
|
2034
2388
|
type: "button",
|
|
2389
|
+
variant: "ghost",
|
|
2390
|
+
size: "icon-xs",
|
|
2035
2391
|
onClick: onRemove,
|
|
2036
|
-
className: "opacity-0 group-hover:opacity-100 transition-opacity",
|
|
2392
|
+
className: "opacity-0 group-hover:opacity-100 transition-opacity hover:bg-destructive/10 hover:text-destructive",
|
|
2037
2393
|
title: "Remove rule",
|
|
2038
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { size: 12,
|
|
2394
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { size: 12, strokeWidth: 1.75 })
|
|
2039
2395
|
}
|
|
2040
2396
|
)
|
|
2041
2397
|
] }),
|
|
@@ -2270,11 +2626,13 @@ function ConditionEditor({ question, schema, onUpdate }) {
|
|
|
2270
2626
|
!hasConditions && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground mb-3", children: "Always visible. Add a rule to show this field conditionally." }),
|
|
2271
2627
|
hasConditions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2 mb-3", children: showIf.conditions.map((cond, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2272
2628
|
index > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2273
|
-
|
|
2629
|
+
fieldcraftReact.Button,
|
|
2274
2630
|
{
|
|
2275
2631
|
type: "button",
|
|
2632
|
+
variant: "link",
|
|
2633
|
+
size: "xs",
|
|
2276
2634
|
onClick: toggleCombine,
|
|
2277
|
-
className: "text-[10px] font-semibold uppercase tracking-wider
|
|
2635
|
+
className: "text-[10px] font-semibold uppercase tracking-wider px-0 mb-1.5",
|
|
2278
2636
|
children: showIf.combine ?? "AND"
|
|
2279
2637
|
}
|
|
2280
2638
|
),
|
|
@@ -2282,43 +2640,39 @@ function ConditionEditor({ question, schema, onUpdate }) {
|
|
|
2282
2640
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2283
2641
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground uppercase tracking-wider", children: "When" }),
|
|
2284
2642
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2285
|
-
|
|
2643
|
+
fieldcraftReact.Button,
|
|
2286
2644
|
{
|
|
2287
2645
|
type: "button",
|
|
2646
|
+
variant: "ghost",
|
|
2647
|
+
size: "icon-xs",
|
|
2288
2648
|
onClick: () => removeCondition(index),
|
|
2289
|
-
className: "opacity-0 group-hover:opacity-100 transition-opacity",
|
|
2649
|
+
className: "opacity-0 group-hover:opacity-100 transition-opacity hover:bg-destructive/10 hover:text-destructive",
|
|
2290
2650
|
title: "Remove condition",
|
|
2291
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { size: 12,
|
|
2651
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { size: 12, strokeWidth: 1.75 })
|
|
2292
2652
|
}
|
|
2293
2653
|
)
|
|
2294
2654
|
] }),
|
|
2295
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
children:
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
"
|
|
2313
|
-
{
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
className: "flex h-7 w-full appearance-none rounded-md border border-input bg-card px-2 py-1 pr-7 text-xs shadow-xs transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring text-foreground cursor-pointer",
|
|
2317
|
-
children: OPERATORS.map((op) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: op.value, children: op.label }, op.value))
|
|
2318
|
-
}
|
|
2319
|
-
),
|
|
2320
|
-
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 size-3 text-muted-foreground", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" }) })
|
|
2321
|
-
] }),
|
|
2655
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2656
|
+
NativeSelect,
|
|
2657
|
+
{
|
|
2658
|
+
value: cond.field ?? "",
|
|
2659
|
+
onChange: (e) => updateCondition(index, { field: e.target.value }),
|
|
2660
|
+
className: "h-7 text-xs",
|
|
2661
|
+
children: [
|
|
2662
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "Select field..." }),
|
|
2663
|
+
fieldOptions.map((f) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: f.id, children: f.label }, f.id))
|
|
2664
|
+
]
|
|
2665
|
+
}
|
|
2666
|
+
),
|
|
2667
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2668
|
+
NativeSelect,
|
|
2669
|
+
{
|
|
2670
|
+
value: cond.operator ?? "eq",
|
|
2671
|
+
onChange: (e) => updateCondition(index, { operator: e.target.value }),
|
|
2672
|
+
className: "h-7 text-xs",
|
|
2673
|
+
children: OPERATORS.map((op) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: op.value, children: op.label }, op.value))
|
|
2674
|
+
}
|
|
2675
|
+
),
|
|
2322
2676
|
cond.operator !== "exists" && cond.operator !== "notExists" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2323
2677
|
fieldcraftReact.Input,
|
|
2324
2678
|
{
|
|
@@ -2331,11 +2685,13 @@ function ConditionEditor({ question, schema, onUpdate }) {
|
|
|
2331
2685
|
] })
|
|
2332
2686
|
] }, index)) }),
|
|
2333
2687
|
fieldOptions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2334
|
-
|
|
2688
|
+
fieldcraftReact.Button,
|
|
2335
2689
|
{
|
|
2336
2690
|
type: "button",
|
|
2691
|
+
variant: "link",
|
|
2692
|
+
size: "xs",
|
|
2337
2693
|
onClick: addCondition,
|
|
2338
|
-
className: "
|
|
2694
|
+
className: "px-0 gap-1.5",
|
|
2339
2695
|
children: [
|
|
2340
2696
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { size: 12, strokeWidth: 2 }),
|
|
2341
2697
|
"Add condition"
|
|
@@ -2497,18 +2853,7 @@ function SettingsSelect({
|
|
|
2497
2853
|
}) {
|
|
2498
2854
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2499
2855
|
/* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Label, { className: "text-xs text-muted-foreground mb-1", children: label }),
|
|
2500
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2501
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2502
|
-
"select",
|
|
2503
|
-
{
|
|
2504
|
-
value,
|
|
2505
|
-
onChange: (e) => onChange(e.target.value),
|
|
2506
|
-
className: "flex h-9 w-full appearance-none rounded-md border border-input bg-card px-3 py-1 pr-8 text-sm shadow-xs transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring text-foreground cursor-pointer",
|
|
2507
|
-
children: options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt.value, children: opt.label }, opt.value))
|
|
2508
|
-
}
|
|
2509
|
-
),
|
|
2510
|
-
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "pointer-events-none absolute right-2.5 top-1/2 -translate-y-1/2 size-4 text-muted-foreground", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" }) })
|
|
2511
|
-
] })
|
|
2856
|
+
/* @__PURE__ */ jsxRuntime.jsx(NativeSelect, { value, onChange: (e) => onChange(e.target.value), children: options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt.value, children: opt.label }, opt.value)) })
|
|
2512
2857
|
] });
|
|
2513
2858
|
}
|
|
2514
2859
|
function PropertiesPanel({ builderState }) {
|
|
@@ -2610,13 +2955,14 @@ function QuestionProperties({ question, sectionId, builderState, onClose, onOpen
|
|
|
2610
2955
|
typeInfo?.label
|
|
2611
2956
|
] }) }),
|
|
2612
2957
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "shrink-0 px-4 pt-3 flex gap-0.5", children: tabs.map((tab) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2613
|
-
|
|
2958
|
+
fieldcraftReact.Button,
|
|
2614
2959
|
{
|
|
2615
2960
|
type: "button",
|
|
2961
|
+
variant: activeTab === tab.key ? "default" : "ghost",
|
|
2962
|
+
size: "xs",
|
|
2616
2963
|
onClick: () => setActiveTab(tab.key),
|
|
2617
2964
|
className: cn(
|
|
2618
|
-
|
|
2619
|
-
activeTab === tab.key ? "bg-primary text-primary-foreground" : "bg-transparent text-muted-foreground hover:bg-accent hover:text-foreground"
|
|
2965
|
+
activeTab !== tab.key && "text-muted-foreground"
|
|
2620
2966
|
),
|
|
2621
2967
|
children: tab.label
|
|
2622
2968
|
},
|
|
@@ -2875,13 +3221,18 @@ function FormBuilderCore(props) {
|
|
|
2875
3221
|
reader.onload = (event) => {
|
|
2876
3222
|
try {
|
|
2877
3223
|
const parsed = JSON.parse(event.target?.result);
|
|
2878
|
-
|
|
2879
|
-
|
|
3224
|
+
const validated = fieldcraftCore.validateSchema(parsed);
|
|
3225
|
+
builderState.resetSchema(validated);
|
|
3226
|
+
} catch (err) {
|
|
3227
|
+
if (err instanceof fieldcraftCore.FormEngineSchemaError) {
|
|
3228
|
+
const details = err.issues.slice(0, 3).map((i) => `\u2022 ${i.path.join(".")}: ${i.message}`).join("\n");
|
|
3229
|
+
alert(`Invalid schema:
|
|
3230
|
+
${details}`);
|
|
3231
|
+
} else if (err instanceof SyntaxError) {
|
|
3232
|
+
alert("Failed to parse JSON file.");
|
|
2880
3233
|
} else {
|
|
2881
|
-
alert("Invalid schema
|
|
3234
|
+
alert("Invalid schema file.");
|
|
2882
3235
|
}
|
|
2883
|
-
} catch {
|
|
2884
|
-
alert("Failed to parse JSON file.");
|
|
2885
3236
|
}
|
|
2886
3237
|
};
|
|
2887
3238
|
reader.readAsText(file);
|
|
@@ -3091,7 +3442,7 @@ function FormBuilderInner(props) {
|
|
|
3091
3442
|
}
|
|
3092
3443
|
|
|
3093
3444
|
// src/form-builder/components/FormBuilderGated.tsx
|
|
3094
|
-
var FormBuilder =
|
|
3445
|
+
var FormBuilder = requireLicense(FormBuilderInner, "FormBuilder");
|
|
3095
3446
|
|
|
3096
3447
|
// src/form-builder/theme/presets.ts
|
|
3097
3448
|
var squaredrDarkPreset = {
|