@squaredr/fieldcraft-pro 1.7.0 → 1.9.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.
Files changed (33) hide show
  1. package/LICENSE.txt +51 -51
  2. package/README.md +139 -139
  3. package/dist/{chunk-VEP3DOCQ.mjs → chunk-5QXKDYWY.mjs} +103 -19
  4. package/dist/{chunk-GZIV2XAD.mjs → chunk-7GPX3YIB.mjs} +146 -183
  5. package/dist/{chunk-J5V6OVZO.mjs → chunk-DWRLPGX5.mjs} +690 -211
  6. package/dist/{chunk-4TN6YJDF.mjs → chunk-KTIU7VCP.mjs} +971 -214
  7. package/dist/default-schema-BGxf9Jrg.d.ts +174 -0
  8. package/dist/default-schema-Bwq8FATF.d.mts +174 -0
  9. package/dist/form-builder/index.d.mts +14 -170
  10. package/dist/form-builder/index.d.ts +14 -170
  11. package/dist/form-builder/index.js +827 -326
  12. package/dist/form-builder/index.mjs +1 -1
  13. package/dist/index.d.mts +111 -10
  14. package/dist/index.d.ts +111 -10
  15. package/dist/index.js +3525 -971
  16. package/dist/index.mjs +1424 -124
  17. package/dist/response-viewer/index.d.mts +1 -1
  18. package/dist/response-viewer/index.d.ts +1 -1
  19. package/dist/response-viewer/index.js +146 -183
  20. package/dist/response-viewer/index.mjs +1 -1
  21. package/dist/styles.css +2 -2
  22. package/dist/templates/index.d.mts +1 -1
  23. package/dist/templates/index.d.ts +1 -1
  24. package/dist/templates/index.js +103 -19
  25. package/dist/templates/index.mjs +1 -1
  26. package/dist/theme-editor/index.d.mts +12 -7
  27. package/dist/theme-editor/index.d.ts +12 -7
  28. package/dist/theme-editor/index.js +971 -214
  29. package/dist/theme-editor/index.mjs +1 -1
  30. package/dist/{types-bFHsZT1n.d.mts → types-BQOeI3LX.d.mts} +1 -1
  31. package/dist/{types-bFHsZT1n.d.ts → types-BQOeI3LX.d.ts} +1 -1
  32. package/package.json +29 -18
  33. package/theme-editor/styles.css +497 -466
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var react = require('react');
3
+ var React = require('react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var core = require('@dnd-kit/core');
6
6
  var lucideReact = require('lucide-react');
@@ -8,9 +8,31 @@ var fieldcraftReact = require('@squaredr/fieldcraft-react');
8
8
  var fieldcraftCore = require('@squaredr/fieldcraft-core');
9
9
  var clsx = require('clsx');
10
10
  var tailwindMerge = require('tailwind-merge');
11
- var react$1 = require('@xyflow/react');
11
+ var SelectPrimitive = require('@radix-ui/react-select');
12
+ var react = require('@xyflow/react');
12
13
  require('@xyflow/react/dist/style.css');
13
14
 
15
+ function _interopNamespace(e) {
16
+ if (e && e.__esModule) return e;
17
+ var n = Object.create(null);
18
+ if (e) {
19
+ Object.keys(e).forEach(function (k) {
20
+ if (k !== 'default') {
21
+ var d = Object.getOwnPropertyDescriptor(e, k);
22
+ Object.defineProperty(n, k, d.get ? d : {
23
+ enumerable: true,
24
+ get: function () { return e[k]; }
25
+ });
26
+ }
27
+ });
28
+ }
29
+ n.default = e;
30
+ return Object.freeze(n);
31
+ }
32
+
33
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
34
+ var SelectPrimitive__namespace = /*#__PURE__*/_interopNamespace(SelectPrimitive);
35
+
14
36
  // ../license/dist/index.mjs
15
37
  var DEV_HOSTNAMES = /* @__PURE__ */ new Set([
16
38
  "localhost",
@@ -85,9 +107,9 @@ function isProductionEnvironment() {
85
107
  }
86
108
  typeof process !== "undefined" && process.env?.NEXT_PUBLIC_FCPRO_PING_URL || "https://fieldcraft.dev/api/license/ping";
87
109
  var defaultContext = { status: "validating" };
88
- var LicenseCtx = react.createContext(defaultContext);
110
+ var LicenseCtx = React.createContext(defaultContext);
89
111
  function useLicense() {
90
- return react.useContext(LicenseCtx);
112
+ return React.useContext(LicenseCtx);
91
113
  }
92
114
  function UnlicensedOverlay({ featureName, reason, children }) {
93
115
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", minHeight: "200px" }, children: [
@@ -312,38 +334,40 @@ function requireLicense(Component3, featureName) {
312
334
  }
313
335
  var MAX_HISTORY = 50;
314
336
  function useUndoRedo(currentSchema, setSchema) {
315
- const historyRef = react.useRef([currentSchema]);
316
- const [currentIndex, setCurrentIndex] = react.useState(0);
337
+ const historyRef = React.useRef([currentSchema]);
338
+ const [currentIndex, setCurrentIndex] = React.useState(0);
317
339
  const canUndo = currentIndex > 0;
318
340
  const canRedo = currentIndex < historyRef.current.length - 1;
319
- const push = react.useCallback(
341
+ const push = React.useCallback(
320
342
  (schema) => {
321
- historyRef.current = historyRef.current.slice(0, currentIndex + 1);
322
- historyRef.current.push(schema);
323
- if (historyRef.current.length > MAX_HISTORY) {
324
- historyRef.current.shift();
325
- setCurrentIndex(historyRef.current.length - 1);
326
- } else {
327
- setCurrentIndex((prev) => prev + 1);
328
- }
343
+ setCurrentIndex((prevIndex) => {
344
+ historyRef.current = historyRef.current.slice(0, prevIndex + 1);
345
+ historyRef.current.push(schema);
346
+ let newIndex = prevIndex + 1;
347
+ if (historyRef.current.length > MAX_HISTORY) {
348
+ historyRef.current.shift();
349
+ newIndex = Math.max(0, newIndex - 1);
350
+ }
351
+ return newIndex;
352
+ });
329
353
  },
330
- [currentIndex]
354
+ []
331
355
  );
332
- const undo = react.useCallback(() => {
356
+ const undo = React.useCallback(() => {
333
357
  if (currentIndex > 0) {
334
358
  const newIndex = currentIndex - 1;
335
359
  setCurrentIndex(newIndex);
336
360
  setSchema(historyRef.current[newIndex]);
337
361
  }
338
362
  }, [currentIndex, setSchema]);
339
- const redo = react.useCallback(() => {
363
+ const redo = React.useCallback(() => {
340
364
  if (currentIndex < historyRef.current.length - 1) {
341
365
  const newIndex = currentIndex + 1;
342
366
  setCurrentIndex(newIndex);
343
367
  setSchema(historyRef.current[newIndex]);
344
368
  }
345
369
  }, [currentIndex, setSchema]);
346
- const clear = react.useCallback(() => {
370
+ const clear = React.useCallback(() => {
347
371
  historyRef.current = [currentSchema];
348
372
  setCurrentIndex(0);
349
373
  }, [currentSchema]);
@@ -358,13 +382,9 @@ function useUndoRedo(currentSchema, setSchema) {
358
382
  }
359
383
 
360
384
  // src/form-builder/utils/id-generator.ts
361
- var counter = 0;
362
385
  function generateId(prefix) {
363
- const timestamp = Date.now().toString(36);
364
- const random = Math.random().toString(36).substring(2, 7);
365
- counter = (counter + 1) % 1e4;
366
- const count = counter.toString(36);
367
- return `${prefix}_${timestamp}${count}${random}`;
386
+ const uuid = crypto.randomUUID().replace(/-/g, "").substring(0, 12);
387
+ return `${prefix}_${uuid}`;
368
388
  }
369
389
  function generateSectionId() {
370
390
  return generateId("section");
@@ -451,18 +471,39 @@ function duplicateSection(schema, sectionId) {
451
471
  const sectionIndex = newSchema.sections.findIndex((s) => s.id === sectionId);
452
472
  if (sectionIndex === -1) return schema;
453
473
  const original = newSchema.sections[sectionIndex];
474
+ const idMap = /* @__PURE__ */ new Map();
475
+ for (const q of original.questions) {
476
+ idMap.set(q.id, generateQuestionId());
477
+ }
454
478
  const duplicate = {
455
479
  ...original,
456
480
  id: generateSectionId(),
457
481
  title: `${original.title} (Copy)`,
482
+ showIf: original.showIf ? remapConditionFieldIds(original.showIf, idMap) : void 0,
458
483
  questions: original.questions.map((q) => ({
459
484
  ...q,
460
- id: generateQuestionId()
485
+ id: idMap.get(q.id),
486
+ showIf: q.showIf ? remapConditionFieldIds(q.showIf, idMap) : void 0
461
487
  }))
462
488
  };
463
489
  newSchema.sections.splice(sectionIndex + 1, 0, duplicate);
464
490
  return newSchema;
465
491
  }
492
+ function remapConditionFieldIds(expr, idMap) {
493
+ if (expr.field) {
494
+ return {
495
+ ...expr,
496
+ field: idMap.get(expr.field) ?? expr.field
497
+ };
498
+ }
499
+ if (expr.conditions) {
500
+ return {
501
+ ...expr,
502
+ conditions: expr.conditions.map((c) => remapConditionFieldIds(c, idMap))
503
+ };
504
+ }
505
+ return expr;
506
+ }
466
507
  function addQuestion(schema, sectionId, question, index) {
467
508
  const newSchema = deepClone(schema);
468
509
  const section = newSchema.sections.find((s) => s.id === sectionId);
@@ -572,16 +613,16 @@ function findSection(schema, sectionId) {
572
613
 
573
614
  // src/form-builder/hooks/use-builder-state.ts
574
615
  function useBuilderState(initialSchema) {
575
- const [schema, setSchema] = react.useState(initialSchema);
576
- const [selectedItem, setSelectedItem] = react.useState(null);
577
- const [isDirty, setIsDirty] = react.useState(false);
578
- const schemaRef = react.useRef(schema);
616
+ const [schema, setSchema] = React.useState(initialSchema);
617
+ const [selectedItem, setSelectedItem] = React.useState(null);
618
+ const [isDirty, setIsDirty] = React.useState(false);
619
+ const schemaRef = React.useRef(schema);
579
620
  schemaRef.current = schema;
580
621
  const undoRedo = useUndoRedo(schema, (newSchema) => {
581
622
  setSchema(newSchema);
582
623
  setIsDirty(true);
583
624
  });
584
- const updateSchema = react.useCallback(
625
+ const updateSchema = React.useCallback(
585
626
  (newSchema) => {
586
627
  setSchema(newSchema);
587
628
  undoRedo.push(newSchema);
@@ -589,54 +630,54 @@ function useBuilderState(initialSchema) {
589
630
  },
590
631
  [undoRedo]
591
632
  );
592
- const applyMutation = react.useCallback(
633
+ const applyMutation = React.useCallback(
593
634
  (mutate) => {
594
635
  const result = mutate(schemaRef.current);
595
636
  updateSchema(result);
596
637
  },
597
638
  [updateSchema]
598
639
  );
599
- const addSection2 = react.useCallback(
640
+ const addSection2 = React.useCallback(
600
641
  (section, index) => {
601
642
  applyMutation((s) => addSection(s, section, index));
602
643
  },
603
644
  [applyMutation]
604
645
  );
605
- const removeSection2 = react.useCallback(
646
+ const removeSection2 = React.useCallback(
606
647
  (sectionId) => {
607
648
  applyMutation((s) => removeSection(s, sectionId));
608
649
  setSelectedItem((prev) => {
609
- if (prev?.type === "section" && prev.sectionId === sectionId) return null;
650
+ if (prev?.sectionId === sectionId) return null;
610
651
  return prev;
611
652
  });
612
653
  },
613
654
  [applyMutation]
614
655
  );
615
- const updateSection2 = react.useCallback(
656
+ const updateSection2 = React.useCallback(
616
657
  (sectionId, updates) => {
617
658
  applyMutation((s) => updateSection(s, sectionId, updates));
618
659
  },
619
660
  [applyMutation]
620
661
  );
621
- const moveSection2 = react.useCallback(
662
+ const moveSection2 = React.useCallback(
622
663
  (sectionId, newIndex) => {
623
664
  applyMutation((s) => moveSection(s, sectionId, newIndex));
624
665
  },
625
666
  [applyMutation]
626
667
  );
627
- const duplicateSection2 = react.useCallback(
668
+ const duplicateSection2 = React.useCallback(
628
669
  (sectionId) => {
629
670
  applyMutation((s) => duplicateSection(s, sectionId));
630
671
  },
631
672
  [applyMutation]
632
673
  );
633
- const addQuestion2 = react.useCallback(
674
+ const addQuestion2 = React.useCallback(
634
675
  (sectionId, question, index) => {
635
676
  applyMutation((s) => addQuestion(s, sectionId, question, index));
636
677
  },
637
678
  [applyMutation]
638
679
  );
639
- const removeQuestion2 = react.useCallback(
680
+ const removeQuestion2 = React.useCallback(
640
681
  (sectionId, questionId) => {
641
682
  applyMutation((s) => removeQuestion(s, sectionId, questionId));
642
683
  setSelectedItem((prev) => {
@@ -648,34 +689,34 @@ function useBuilderState(initialSchema) {
648
689
  },
649
690
  [applyMutation]
650
691
  );
651
- const updateQuestion2 = react.useCallback(
692
+ const updateQuestion2 = React.useCallback(
652
693
  (sectionId, questionId, updates) => {
653
694
  applyMutation((s) => updateQuestion(s, sectionId, questionId, updates));
654
695
  },
655
696
  [applyMutation]
656
697
  );
657
- const moveQuestion2 = react.useCallback(
698
+ const moveQuestion2 = React.useCallback(
658
699
  (sectionId, questionId, targetSectionId, newIndex) => {
659
700
  applyMutation((s) => moveQuestion(s, sectionId, questionId, targetSectionId, newIndex));
660
701
  },
661
702
  [applyMutation]
662
703
  );
663
- const duplicateQuestion2 = react.useCallback(
704
+ const duplicateQuestion2 = React.useCallback(
664
705
  (sectionId, questionId) => {
665
706
  applyMutation((s) => duplicateQuestion(s, sectionId, questionId));
666
707
  },
667
708
  [applyMutation]
668
709
  );
669
- const selectQuestion = react.useCallback((sectionId, questionId) => {
710
+ const selectQuestion = React.useCallback((sectionId, questionId) => {
670
711
  setSelectedItem({ type: "question", sectionId, questionId });
671
712
  }, []);
672
- const selectSection = react.useCallback((sectionId) => {
713
+ const selectSection = React.useCallback((sectionId) => {
673
714
  setSelectedItem({ type: "section", sectionId });
674
715
  }, []);
675
- const clearSelection = react.useCallback(() => {
716
+ const clearSelection = React.useCallback(() => {
676
717
  setSelectedItem(null);
677
718
  }, []);
678
- const resetSchema = react.useCallback(
719
+ const resetSchema = React.useCallback(
679
720
  (newSchema) => {
680
721
  setSchema(newSchema);
681
722
  undoRedo.clear();
@@ -684,7 +725,7 @@ function useBuilderState(initialSchema) {
684
725
  },
685
726
  [undoRedo]
686
727
  );
687
- const markClean = react.useCallback(() => {
728
+ const markClean = React.useCallback(() => {
688
729
  setIsDirty(false);
689
730
  }, []);
690
731
  return {
@@ -945,7 +986,7 @@ var QUESTION_TYPE_INFO = {
945
986
  category: "advanced",
946
987
  icon: "ListPlus",
947
988
  description: "Repeatable group of fields",
948
- defaultConfig: { type: "repeater", fields: [], minItems: 1, maxItems: 10 }
989
+ defaultConfig: { type: "repeater", fields: [], minEntries: 1, maxEntries: 10 }
949
990
  },
950
991
  likert: {
951
992
  type: "likert",
@@ -956,13 +997,7 @@ var QUESTION_TYPE_INFO = {
956
997
  requiresOptions: true,
957
998
  defaultConfig: {
958
999
  type: "likert",
959
- scale: [
960
- { label: "Strongly Disagree", value: "1" },
961
- { label: "Disagree", value: "2" },
962
- { label: "Neutral", value: "3" },
963
- { label: "Agree", value: "4" },
964
- { label: "Strongly Agree", value: "5" }
965
- ]
1000
+ labels: ["Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"]
966
1001
  }
967
1002
  },
968
1003
  scoring: {
@@ -1015,7 +1050,7 @@ var QUESTION_TYPE_INFO = {
1015
1050
  category: "advanced",
1016
1051
  icon: "CreditCard",
1017
1052
  description: "Collect payment via Stripe",
1018
- defaultConfig: { type: "payment", provider: "stripe", publicKey: "", currency: "USD" }
1053
+ defaultConfig: { type: "payment", provider: "stripe", publicKey: "", currency: "USD", serverUrl: "" }
1019
1054
  },
1020
1055
  // ── Structural ──
1021
1056
  section_header: {
@@ -1162,7 +1197,7 @@ var DEFAULT_PALETTE = [
1162
1197
 
1163
1198
  // src/form-builder/hooks/use-drag-drop.ts
1164
1199
  function useDragDrop(builderState) {
1165
- const [activeDragItem, setActiveDragItem] = react.useState(null);
1200
+ const [activeDragItem, setActiveDragItem] = React.useState(null);
1166
1201
  const sensors = core.useSensors(
1167
1202
  core.useSensor(core.MouseSensor, {
1168
1203
  activationConstraint: {
@@ -1212,11 +1247,11 @@ function useDragDrop(builderState) {
1212
1247
  }
1213
1248
  return null;
1214
1249
  };
1215
- const handleDragStart = react.useCallback((event) => {
1250
+ const handleDragStart = React.useCallback((event) => {
1216
1251
  const item = parseDragItem(event.active);
1217
1252
  setActiveDragItem(item);
1218
1253
  }, []);
1219
- const handleDragCancel = react.useCallback(() => {
1254
+ const handleDragCancel = React.useCallback(() => {
1220
1255
  setActiveDragItem(null);
1221
1256
  }, []);
1222
1257
  const handleDragEnd = (event) => {
@@ -1386,9 +1421,9 @@ function PaletteItem({ questionType, typeInfo }) {
1386
1421
  );
1387
1422
  }
1388
1423
  function QuestionPalette({ questionTypes, palette }) {
1389
- const [collapsed, setCollapsed] = react.useState({});
1390
- const [search, setSearch] = react.useState("");
1391
- const mergedPalette = react.useMemo(
1424
+ const [collapsed, setCollapsed] = React.useState({});
1425
+ const [search, setSearch] = React.useState("");
1426
+ const mergedPalette = React.useMemo(
1392
1427
  () => palette ? [...DEFAULT_PALETTE, ...palette] : DEFAULT_PALETTE,
1393
1428
  [palette]
1394
1429
  );
@@ -1469,13 +1504,13 @@ function QuestionBlock({
1469
1504
  }) {
1470
1505
  const typeInfo = QUESTION_TYPE_INFO[question.type];
1471
1506
  const IconComponent = typeInfo ? getIcon(typeInfo.icon) : null;
1472
- const [isEditing, setIsEditing] = react.useState(false);
1473
- const [editValue, setEditValue] = react.useState(question.label);
1474
- const inputRef = react.useRef(null);
1475
- react.useEffect(() => {
1507
+ const [isEditing, setIsEditing] = React.useState(false);
1508
+ const [editValue, setEditValue] = React.useState(question.label);
1509
+ const inputRef = React.useRef(null);
1510
+ React.useEffect(() => {
1476
1511
  if (!isEditing) setEditValue(question.label);
1477
1512
  }, [question.label, isEditing]);
1478
- react.useEffect(() => {
1513
+ React.useEffect(() => {
1479
1514
  if (isEditing && inputRef.current) {
1480
1515
  inputRef.current.focus();
1481
1516
  inputRef.current.select();
@@ -1632,7 +1667,7 @@ function ConfirmDialog({ open, title, message, onConfirm, onCancel }) {
1632
1667
  );
1633
1668
  }
1634
1669
  function SectionBlock({ section, builderState }) {
1635
- const [confirmDelete, setConfirmDelete] = react.useState(false);
1670
+ const [confirmDelete, setConfirmDelete] = React.useState(false);
1636
1671
  const { setNodeRef } = core.useDroppable({
1637
1672
  id: `section-end-${section.id}`,
1638
1673
  data: { type: "section", sectionId: section.id, index: section.questions.length }
@@ -1745,6 +1780,14 @@ function SectionBlock({ section, builderState }) {
1745
1780
  }
1746
1781
  function FormCanvas({ builderState }) {
1747
1782
  const { schema } = builderState;
1783
+ const [localTitle, setLocalTitle] = React.useState(schema.title);
1784
+ const [localDesc, setLocalDesc] = React.useState(schema.description ?? "");
1785
+ React.useEffect(() => {
1786
+ setLocalTitle(schema.title);
1787
+ }, [schema.title]);
1788
+ React.useEffect(() => {
1789
+ setLocalDesc(schema.description ?? "");
1790
+ }, [schema.description]);
1748
1791
  const handleAddSection = () => {
1749
1792
  const newSection = {
1750
1793
  id: generateSectionId(),
@@ -1761,9 +1804,12 @@ function FormCanvas({ builderState }) {
1761
1804
  "input",
1762
1805
  {
1763
1806
  type: "text",
1764
- value: schema.title,
1765
- onChange: (e) => {
1766
- builderState.updateSchema({ ...schema, title: e.target.value });
1807
+ value: localTitle,
1808
+ onChange: (e) => setLocalTitle(e.target.value),
1809
+ onBlur: () => {
1810
+ if (localTitle !== schema.title) {
1811
+ builderState.updateSchema({ ...schema, title: localTitle });
1812
+ }
1767
1813
  },
1768
1814
  className: "w-full text-xl font-bold bg-transparent text-foreground border-0 outline-none p-1.5 rounded-md focus:bg-card transition-colors",
1769
1815
  placeholder: "Form Title"
@@ -1772,9 +1818,12 @@ function FormCanvas({ builderState }) {
1772
1818
  /* @__PURE__ */ jsxRuntime.jsx(
1773
1819
  "textarea",
1774
1820
  {
1775
- value: schema.description ?? "",
1776
- onChange: (e) => {
1777
- builderState.updateSchema({ ...schema, description: e.target.value });
1821
+ value: localDesc,
1822
+ onChange: (e) => setLocalDesc(e.target.value),
1823
+ onBlur: () => {
1824
+ if (localDesc !== (schema.description ?? "")) {
1825
+ builderState.updateSchema({ ...schema, description: localDesc || void 0 });
1826
+ }
1778
1827
  },
1779
1828
  className: "w-full text-sm text-muted-foreground bg-transparent border-0 outline-none p-1.5 resize-y min-h-12 rounded-md leading-relaxed focus:bg-card transition-colors",
1780
1829
  placeholder: "Form description (optional)"
@@ -1813,259 +1862,469 @@ function FormCanvas({ builderState }) {
1813
1862
  ] })
1814
1863
  ] }) });
1815
1864
  }
1816
- var NativeSelect = react.forwardRef(
1817
- ({ className, wrapperClassName, children, ...props }, ref) => {
1818
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative", wrapperClassName), children: [
1865
+ var Select = SelectPrimitive__namespace.Root;
1866
+ var SelectTrigger = React__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
1867
+ SelectPrimitive__namespace.Trigger,
1868
+ {
1869
+ ref,
1870
+ className: cn(
1871
+ "flex h-9 w-full items-center justify-between rounded-md border border-input bg-card px-3 py-1 text-sm shadow-xs transition-colors placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
1872
+ className
1873
+ ),
1874
+ ...props,
1875
+ children: [
1876
+ children,
1877
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Icon, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "size-4 text-muted-foreground" }) })
1878
+ ]
1879
+ }
1880
+ ));
1881
+ SelectTrigger.displayName = "SelectTrigger";
1882
+ var SelectContent = React__namespace.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
1883
+ SelectPrimitive__namespace.Content,
1884
+ {
1885
+ ref,
1886
+ className: cn(
1887
+ "relative z-50 max-h-64 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
1888
+ position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
1889
+ className
1890
+ ),
1891
+ position,
1892
+ ...props,
1893
+ children: [
1894
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ScrollUpButton, { className: "flex cursor-default items-center justify-center py-1", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, { className: "size-4" }) }),
1819
1895
  /* @__PURE__ */ jsxRuntime.jsx(
1820
- "select",
1896
+ SelectPrimitive__namespace.Viewport,
1821
1897
  {
1822
- ref,
1823
1898
  className: cn(
1824
- "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",
1825
- className
1899
+ "p-1",
1900
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
1826
1901
  ),
1827
- ...props,
1828
1902
  children
1829
1903
  }
1830
1904
  ),
1831
- /* @__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" })
1832
- ] });
1905
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ScrollDownButton, { className: "flex cursor-default items-center justify-center py-1", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "size-4" }) })
1906
+ ]
1833
1907
  }
1834
- );
1835
- NativeSelect.displayName = "NativeSelect";
1908
+ ) }));
1909
+ SelectContent.displayName = "SelectContent";
1910
+ var SelectItem = React__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
1911
+ SelectPrimitive__namespace.Item,
1912
+ {
1913
+ ref,
1914
+ className: cn(
1915
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
1916
+ className
1917
+ ),
1918
+ ...props,
1919
+ children: [
1920
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ItemIndicator, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "size-4" }) }) }),
1921
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ItemText, { children })
1922
+ ]
1923
+ }
1924
+ ));
1925
+ SelectItem.displayName = "SelectItem";
1836
1926
  function useConfigUpdater(question, onUpdate) {
1837
- return (field, value) => {
1927
+ return (updates) => {
1838
1928
  const current = question.config ?? {};
1839
- onUpdate({ config: { ...current, type: question.type, [field]: value } });
1929
+ const merged = { ...current, type: question.type, ...updates };
1930
+ for (const key of Object.keys(merged)) {
1931
+ if (merged[key] === void 0) delete merged[key];
1932
+ }
1933
+ onUpdate({ config: merged });
1840
1934
  };
1841
1935
  }
1842
- function QuestionConfigEditor({ question, onUpdate }) {
1936
+ function QuestionConfigEditor({ question, schema, onUpdate }) {
1843
1937
  const updateConfig = useConfigUpdater(question, onUpdate);
1844
1938
  const config = question.config ?? {};
1939
+ const allQuestions = React.useMemo(() => {
1940
+ if (!schema?.sections) return [];
1941
+ return schema.sections.flatMap((s) => s.questions || []);
1942
+ }, [schema]);
1943
+ const candidateAmountFields = React.useMemo(() => {
1944
+ return allQuestions.filter((q) => q.id !== question.id && ["calculated", "number", "slider", "rating", "single_select"].includes(q.type)).map((q) => ({ label: `${q.label || q.id} (${q.id})`, value: q.id }));
1945
+ }, [allQuestions, question.id]);
1946
+ const candidateTimezoneFields = React.useMemo(() => {
1947
+ return allQuestions.filter((q) => q.id !== question.id && ["dropdown", "single_select", "short_text"].includes(q.type)).map((q) => ({ label: `${q.label || q.id} (${q.id})`, value: q.id }));
1948
+ }, [allQuestions, question.id]);
1845
1949
  switch (question.type) {
1846
1950
  // ── Text ──
1847
1951
  case "short_text":
1848
1952
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Text Settings", children: [
1849
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "255", onChange: (v) => updateConfig("maxLength", v) }),
1850
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Input Type", value: config.inputType ?? "text", options: [{ label: "Text", value: "text" }, { label: "Password", value: "password" }], onChange: (v) => updateConfig("inputType", v) }),
1851
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig("prefix", v) }),
1852
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. USD", onChange: (v) => updateConfig("suffix", v) })
1953
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "255", onChange: (v) => updateConfig({ maxLength: v }) }),
1954
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Input Type", value: config.inputType ?? "text", options: [{ label: "Text", value: "text" }, { label: "Password", value: "password" }], onChange: (v) => updateConfig({ inputType: v }) }),
1955
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig({ prefix: v }) }),
1956
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. USD", onChange: (v) => updateConfig({ suffix: v }) })
1853
1957
  ] });
1854
1958
  case "long_text":
1855
1959
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Text Settings", children: [
1856
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "No limit", onChange: (v) => updateConfig("maxLength", v) }),
1857
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Rows", value: config.rows, placeholder: "4", onChange: (v) => updateConfig("rows", v) }),
1858
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Character Count", checked: !!config.showCharCount, onChange: (v) => updateConfig("showCharCount", v) })
1960
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "No limit", onChange: (v) => updateConfig({ maxLength: v }) }),
1961
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Rows", value: config.rows, placeholder: "4", onChange: (v) => updateConfig({ rows: v }) }),
1962
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Character Count", checked: !!config.showCharCount, onChange: (v) => updateConfig({ showCharCount: v }) })
1859
1963
  ] });
1860
1964
  case "legal_name":
1861
1965
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Name Fields", children: [
1862
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Middle Name", checked: !!config.showMiddleName, onChange: (v) => updateConfig("showMiddleName", v) }),
1863
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Suffix", checked: !!config.showSuffix, onChange: (v) => updateConfig("showSuffix", v) })
1966
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Middle Name", checked: !!config.showMiddleName, onChange: (v) => updateConfig({ showMiddleName: v }) }),
1967
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Suffix", checked: !!config.showSuffix, onChange: (v) => updateConfig({ showSuffix: v }) })
1864
1968
  ] });
1865
1969
  // ── Numeric ──
1866
1970
  case "number":
1867
1971
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Number Settings", children: [
1868
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min", value: config.min, onChange: (v) => updateConfig("min", v) }),
1869
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max", value: config.max, onChange: (v) => updateConfig("max", v) }),
1870
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig("step", v) }),
1871
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "0", onChange: (v) => updateConfig("decimalPlaces", v) }),
1872
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig("prefix", v) }),
1873
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. kg", onChange: (v) => updateConfig("suffix", v) })
1972
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min Value", value: config.min, onChange: (v) => updateConfig({ min: v }) }),
1973
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Value", value: config.max, onChange: (v) => updateConfig({ max: v }) }),
1974
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig({ step: v }) }),
1975
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig({ prefix: v }) }),
1976
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. kg", onChange: (v) => updateConfig({ suffix: v }) })
1874
1977
  ] });
1875
1978
  case "slider":
1876
1979
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Slider Settings", children: [
1877
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min", value: config.min, placeholder: "0", onChange: (v) => updateConfig("min", v) }),
1878
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max", value: config.max, placeholder: "100", onChange: (v) => updateConfig("max", v) }),
1879
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig("step", v) }),
1880
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Value", checked: !!config.showValue, onChange: (v) => updateConfig("showValue", v) }),
1881
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig("minLabel", v) }),
1882
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig("maxLabel", v) })
1980
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min Value", value: config.min, placeholder: "0", onChange: (v) => updateConfig({ min: v ?? 0 }) }),
1981
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Value", value: config.max, placeholder: "100", onChange: (v) => updateConfig({ max: v ?? 100 }) }),
1982
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig({ step: v ?? 1 }) }),
1983
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Label", value: config.minLabel, placeholder: "Low", onChange: (v) => updateConfig({ minLabel: v }) }),
1984
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Label", value: config.maxLabel, placeholder: "High", onChange: (v) => updateConfig({ maxLabel: v }) }),
1985
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Value", checked: config.showValue !== false, onChange: (v) => updateConfig({ showValue: v }) }),
1986
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Unit", value: config.unit, placeholder: "e.g. %", onChange: (v) => updateConfig({ unit: v }) })
1883
1987
  ] });
1884
1988
  case "rating":
1885
1989
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Rating Settings", children: [
1886
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Stars", value: config.max, placeholder: "5", onChange: (v) => updateConfig("max", v) }),
1887
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Icon", value: config.icon ?? "star", options: [{ label: "Star", value: "star" }, { label: "Heart", value: "heart" }, { label: "Circle", value: "circle" }], onChange: (v) => updateConfig("icon", v) }),
1888
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Labels", checked: !!config.showLabels, onChange: (v) => updateConfig("showLabels", v) })
1990
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Rating", value: config.maxRating, placeholder: "5", onChange: (v) => updateConfig({ maxRating: v ?? 5 }) }),
1991
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Icon", value: config.icon ?? "star", options: [{ label: "Star", value: "star" }, { label: "Heart", value: "heart" }, { label: "Thumb", value: "thumb" }], onChange: (v) => updateConfig({ icon: v }) }),
1992
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Half Ratings", checked: !!config.allowHalf, onChange: (v) => updateConfig({ allowHalf: v }) })
1889
1993
  ] });
1890
1994
  case "nps":
1891
1995
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "NPS Settings", children: [
1892
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Low Label", value: config.lowLabel ?? "Not likely", onChange: (v) => updateConfig("lowLabel", v) }),
1893
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "High Label", value: config.highLabel ?? "Very likely", onChange: (v) => updateConfig("highLabel", v) })
1996
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Left Label", value: config.leftLabel ?? "Not likely", onChange: (v) => updateConfig({ leftLabel: v }) }),
1997
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Right Label", value: config.rightLabel ?? "Extremely likely", onChange: (v) => updateConfig({ rightLabel: v }) })
1894
1998
  ] });
1895
1999
  case "opinion_scale":
1896
2000
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Scale Settings", children: [
1897
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min", value: config.min, placeholder: "1", onChange: (v) => updateConfig("min", v) }),
1898
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max", value: config.max, placeholder: "5", onChange: (v) => updateConfig("max", v) }),
1899
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig("step", v) }),
1900
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig("minLabel", v) }),
1901
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig("maxLabel", v) })
2001
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min", value: config.min, placeholder: "1", onChange: (v) => updateConfig({ min: v }) }),
2002
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max", value: config.max, placeholder: "5", onChange: (v) => updateConfig({ max: v }) }),
2003
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig({ step: v }) }),
2004
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig({ minLabel: v }) }),
2005
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig({ maxLabel: v }) })
1902
2006
  ] });
1903
2007
  case "likert":
1904
- return /* @__PURE__ */ jsxRuntime.jsx(ConfigSection, { title: "Likert Settings", children: /* @__PURE__ */ jsxRuntime.jsx(LikertLabelsEditor, { labels: config.labels ?? ["Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"], onChange: (v) => updateConfig("labels", v) }) });
2008
+ return /* @__PURE__ */ jsxRuntime.jsx(ConfigSection, { title: "Likert Settings", children: /* @__PURE__ */ jsxRuntime.jsx(LikertLabelsEditor, { labels: config.labels ?? ["Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"], onChange: (v) => updateConfig({ labels: v }) }) });
1905
2009
  // ── Selection ──
1906
2010
  case "single_select":
1907
2011
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Select Settings", children: [
1908
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Layout", value: config.layout ?? "vertical", options: [{ label: "Vertical", value: "vertical" }, { label: "Horizontal", value: "horizontal" }, { label: "Grid", value: "grid" }], onChange: (v) => updateConfig("layout", v) }),
1909
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig("allowOther", v) }),
1910
- !!config.allowOther && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig("otherLabel", v) })
2012
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Layout", value: config.layout ?? "vertical", options: [{ label: "Vertical", value: "vertical" }, { label: "Horizontal", value: "horizontal" }, { label: "Grid", value: "grid" }], onChange: (v) => updateConfig({ layout: v }) }),
2013
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => v ? updateConfig({ allowOther: true }) : updateConfig({ allowOther: false, otherLabel: void 0 }) }),
2014
+ !!config.allowOther && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig({ otherLabel: v }) })
1911
2015
  ] });
1912
2016
  case "multi_select":
1913
2017
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Multi-Select Settings", children: [
1914
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Layout", value: config.layout ?? "vertical", options: [{ label: "Vertical", value: "vertical" }, { label: "Horizontal", value: "horizontal" }, { label: "Grid", value: "grid" }], onChange: (v) => updateConfig("layout", v) }),
1915
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min Selections", value: config.minSelections, onChange: (v) => updateConfig("minSelections", v) }),
1916
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Selections", value: config.maxSelections, onChange: (v) => updateConfig("maxSelections", v) }),
1917
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig("allowOther", v) }),
1918
- !!config.allowOther && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig("otherLabel", v) })
2018
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Layout", value: config.layout ?? "vertical", options: [{ label: "Vertical", value: "vertical" }, { label: "Horizontal", value: "horizontal" }, { label: "Grid", value: "grid" }], onChange: (v) => updateConfig({ layout: v }) }),
2019
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min Selections", value: config.minSelections, onChange: (v) => updateConfig({ minSelections: v }) }),
2020
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Selections", value: config.maxSelections, onChange: (v) => updateConfig({ maxSelections: v }) }),
2021
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => v ? updateConfig({ allowOther: true }) : updateConfig({ allowOther: false, otherLabel: void 0 }) }),
2022
+ !!config.allowOther && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig({ otherLabel: v }) })
1919
2023
  ] });
1920
2024
  case "dropdown":
1921
2025
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Dropdown Settings", children: [
1922
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Searchable", checked: !!config.searchable, onChange: (v) => updateConfig("searchable", v) }),
1923
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig("allowOther", v) }),
1924
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Multiple", checked: !!config.multiple, onChange: (v) => updateConfig("multiple", v) })
2026
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Searchable", checked: !!config.searchable, onChange: (v) => updateConfig({ searchable: v }) }),
2027
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig({ allowOther: v }) }),
2028
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Multiple", checked: !!config.multiple, onChange: (v) => updateConfig({ multiple: v }) })
1925
2029
  ] });
1926
2030
  case "boolean":
1927
2031
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Yes/No Settings", children: [
1928
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Style", value: config.style ?? "toggle", options: [{ label: "Toggle", value: "toggle" }, { label: "Radio", value: "radio" }, { label: "Checkbox", value: "checkbox" }], onChange: (v) => updateConfig("style", v) }),
1929
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "True Label", value: config.trueLabel ?? "Yes", onChange: (v) => updateConfig("trueLabel", v) }),
1930
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "False Label", value: config.falseLabel ?? "No", onChange: (v) => updateConfig("falseLabel", v) })
2032
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Style", value: config.style ?? "toggle", options: [{ label: "Toggle", value: "toggle" }, { label: "Radio", value: "radio" }, { label: "Checkbox", value: "checkbox" }], onChange: (v) => updateConfig({ style: v }) }),
2033
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "True Label", value: config.trueLabel ?? "Yes", onChange: (v) => updateConfig({ trueLabel: v }) }),
2034
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "False Label", value: config.falseLabel ?? "No", onChange: (v) => updateConfig({ falseLabel: v }) })
1931
2035
  ] });
1932
2036
  case "country_select":
1933
2037
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Country Settings", children: [
1934
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Flags", checked: config.showFlags !== false, onChange: (v) => updateConfig("showFlags", v) }),
1935
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Priority Countries", value: config.priorityCountries?.join(", "), placeholder: "e.g. US, GB, CA", onChange: (v) => updateConfig("priorityCountries", v ? v.split(",").map((s) => s.trim()).filter(Boolean) : void 0) }),
1936
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Exclude Countries", value: config.excludeCountries?.join(", "), placeholder: "e.g. XX, YY", onChange: (v) => updateConfig("excludeCountries", v ? v.split(",").map((s) => s.trim()).filter(Boolean) : void 0) })
2038
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Flags", checked: config.showFlags !== false, onChange: (v) => updateConfig({ showFlags: v }) }),
2039
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Priority Countries", value: config.priorityCountries?.join(", "), placeholder: "e.g. US, GB, CA", onChange: (v) => updateConfig({ priorityCountries: v ? v.split(",").map((s) => s.trim()).filter(Boolean) : void 0 }) }),
2040
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Exclude Countries", value: config.excludeCountries?.join(", "), placeholder: "e.g. XX, YY", onChange: (v) => updateConfig({ excludeCountries: v ? v.split(",").map((s) => s.trim()).filter(Boolean) : void 0 }) })
1937
2041
  ] });
1938
2042
  // ── Date/Time ──
1939
2043
  case "date":
1940
2044
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Date Settings", children: [
1941
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig("minDate", v) }),
1942
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig("maxDate", v) }),
1943
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Disable Past Dates", checked: !!config.disablePast, onChange: (v) => updateConfig("disablePast", v) }),
1944
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Disable Future Dates", checked: !!config.disableFuture, onChange: (v) => updateConfig("disableFuture", v) }),
1945
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Format", value: config.format, placeholder: "e.g. MM/DD/YYYY", onChange: (v) => updateConfig("format", v) })
2045
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ minDate: v }) }),
2046
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ maxDate: v }) }),
2047
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Disable Past Dates", checked: !!config.disablePast, onChange: (v) => updateConfig({ disablePast: v }) }),
2048
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Disable Future Dates", checked: !!config.disableFuture, onChange: (v) => updateConfig({ disableFuture: v }) }),
2049
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Format", value: config.format, placeholder: "e.g. MM/DD/YYYY", onChange: (v) => updateConfig({ format: v }) })
1946
2050
  ] });
1947
2051
  case "time":
1948
2052
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Time Settings", children: [
1949
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Format", value: config.format ?? "12h", options: [{ label: "12 Hour", value: "12h" }, { label: "24 Hour", value: "24h" }], onChange: (v) => updateConfig("format", v) }),
1950
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Minute Step", value: config.minuteStep, placeholder: "1", onChange: (v) => updateConfig("minuteStep", v) })
2053
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Format", value: config.format ?? "12h", options: [{ label: "12 Hour", value: "12h" }, { label: "24 Hour", value: "24h" }], onChange: (v) => updateConfig({ format: v }) }),
2054
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Minute Step", value: config.minuteStep, placeholder: "1", onChange: (v) => updateConfig({ minuteStep: v }) })
1951
2055
  ] });
1952
2056
  case "date_range":
1953
2057
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Date Range Settings", children: [
1954
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig("minDate", v) }),
1955
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig("maxDate", v) }),
1956
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Range (days)", value: config.maxRangeDays, onChange: (v) => updateConfig("maxRangeDays", v) })
2058
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ minDate: v }) }),
2059
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ maxDate: v }) }),
2060
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Range (days)", value: config.maxRangeDays, onChange: (v) => updateConfig({ maxRangeDays: v }) })
1957
2061
  ] });
1958
- case "appointment":
2062
+ case "appointment": {
2063
+ const appointmentMode = typeof config.slotsUrl === "string" ? "url" : typeof config.embedUrl === "string" ? "embed" : "static";
2064
+ const timezoneFieldOptions = [
2065
+ { label: "None (Static Timezone)", value: "" },
2066
+ ...candidateTimezoneFields,
2067
+ { label: "Custom Field ID...", value: "__custom__" }
2068
+ ];
2069
+ const isCustomTzField = Boolean(config.timezoneField) && !candidateTimezoneFields.some((opt) => opt.value === config.timezoneField);
1959
2070
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Appointment Settings", children: [
1960
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Duration (min)", value: config.duration ?? 30, onChange: (v) => updateConfig("duration", v) }),
1961
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Timezone", value: config.timezone, placeholder: "e.g. America/New_York", onChange: (v) => updateConfig("timezone", v) }),
1962
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Slots URL", value: config.slotsUrl, placeholder: "API endpoint for available slots", onChange: (v) => updateConfig("slotsUrl", v) })
2071
+ /* @__PURE__ */ jsxRuntime.jsx(
2072
+ SelectField,
2073
+ {
2074
+ label: "Scheduling Mode",
2075
+ value: appointmentMode,
2076
+ options: [
2077
+ { label: "Manual Static Slots", value: "static" },
2078
+ { label: "Fetch from URL", value: "url" },
2079
+ { label: "Third-Party Embed (Calendly / Cal.com)", value: "embed" }
2080
+ ],
2081
+ onChange: (v) => {
2082
+ if (v === "url") {
2083
+ updateConfig({
2084
+ slotsUrl: "",
2085
+ embedUrl: void 0,
2086
+ embedProvider: void 0,
2087
+ slots: void 0
2088
+ });
2089
+ } else if (v === "embed") {
2090
+ updateConfig({
2091
+ embedUrl: "",
2092
+ embedProvider: config.embedProvider || "cal_com",
2093
+ slotsUrl: void 0,
2094
+ slots: void 0
2095
+ });
2096
+ } else {
2097
+ updateConfig({
2098
+ slots: config.slots ?? [],
2099
+ slotsUrl: void 0,
2100
+ embedUrl: void 0,
2101
+ embedProvider: void 0
2102
+ });
2103
+ }
2104
+ }
2105
+ }
2106
+ ),
2107
+ appointmentMode === "url" && /* @__PURE__ */ jsxRuntime.jsx(
2108
+ TextField,
2109
+ {
2110
+ label: "Slots URL",
2111
+ value: config.slotsUrl,
2112
+ placeholder: "https://example.com/slots",
2113
+ onChange: (v) => updateConfig({ slotsUrl: v ?? "" })
2114
+ }
2115
+ ),
2116
+ appointmentMode === "embed" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2117
+ /* @__PURE__ */ jsxRuntime.jsx(
2118
+ TextField,
2119
+ {
2120
+ label: "Embed URL",
2121
+ value: config.embedUrl,
2122
+ placeholder: "https://calendly.com/... or https://cal.com/...",
2123
+ onChange: (v) => updateConfig({ embedUrl: v ?? "" })
2124
+ }
2125
+ ),
2126
+ /* @__PURE__ */ jsxRuntime.jsx(
2127
+ SelectField,
2128
+ {
2129
+ label: "Embed Provider",
2130
+ value: config.embedProvider ?? "cal_com",
2131
+ options: [
2132
+ { label: "Cal.com", value: "cal_com" },
2133
+ { label: "Calendly", value: "calendly" },
2134
+ { label: "Custom", value: "custom" }
2135
+ ],
2136
+ onChange: (v) => updateConfig({ embedProvider: v })
2137
+ }
2138
+ )
2139
+ ] }),
2140
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Duration (min)", value: config.duration ?? 30, onChange: (v) => updateConfig({ duration: v }) }),
2141
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Timezone", value: config.timezone, placeholder: "e.g. America/New_York", onChange: (v) => updateConfig({ timezone: v }) }),
2142
+ candidateTimezoneFields.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2143
+ /* @__PURE__ */ jsxRuntime.jsx(
2144
+ SelectField,
2145
+ {
2146
+ label: "Dynamic Timezone Field",
2147
+ value: isCustomTzField ? "__custom__" : config.timezoneField ?? "",
2148
+ options: timezoneFieldOptions,
2149
+ onChange: (v) => {
2150
+ if (v !== "__custom__") {
2151
+ updateConfig({ timezoneField: v || void 0 });
2152
+ }
2153
+ }
2154
+ }
2155
+ ),
2156
+ isCustomTzField && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsxRuntime.jsx(
2157
+ TextField,
2158
+ {
2159
+ label: "Custom Timezone Field ID",
2160
+ value: config.timezoneField,
2161
+ placeholder: "e.g. timezone",
2162
+ onChange: (v) => updateConfig({ timezoneField: v || void 0 })
2163
+ }
2164
+ ) })
2165
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
2166
+ TextField,
2167
+ {
2168
+ label: "Timezone Field",
2169
+ value: config.timezoneField,
2170
+ placeholder: "Field ID for dynamic timezone",
2171
+ onChange: (v) => updateConfig({ timezoneField: v || void 0 })
2172
+ }
2173
+ ),
2174
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Date Format", value: config.dateFormat, placeholder: "Locale-aware (default)", onChange: (v) => updateConfig({ dateFormat: v }) }),
2175
+ /* @__PURE__ */ jsxRuntime.jsx(
2176
+ ToggleField,
2177
+ {
2178
+ label: "Auto-Advance on Booking Complete",
2179
+ checked: config.autoAdvance !== false,
2180
+ onChange: (v) => updateConfig({ autoAdvance: v })
2181
+ }
2182
+ ),
2183
+ appointmentMode === "static" && /* @__PURE__ */ jsxRuntime.jsx(
2184
+ AppointmentSlotsEditor,
2185
+ {
2186
+ slots: config.slots ?? [],
2187
+ onChange: (v) => updateConfig({ slots: v })
2188
+ }
2189
+ )
1963
2190
  ] });
2191
+ }
1964
2192
  // ── Media ──
1965
2193
  case "file_upload":
1966
2194
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Upload Settings", children: [
1967
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Files", value: config.maxFiles ?? 1, onChange: (v) => updateConfig("maxFiles", v) }),
1968
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb ?? 10, onChange: (v) => updateConfig("maxSizeMb", v) }),
1969
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Accepted Types", value: config.accept?.join(", "), placeholder: "e.g. .pdf, .jpg, .png", onChange: (v) => updateConfig("accept", v ? v.split(",").map((s) => s.trim()) : void 0) }),
1970
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Upload URL", value: config.uploadUrl, placeholder: "Server upload endpoint", onChange: (v) => updateConfig("uploadUrl", v) })
2195
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-2.5 bg-muted/40 border border-border rounded-md text-xs text-muted-foreground flex items-center gap-1.5", children: [
2196
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u{1F4E6}" }),
2197
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Uploads stream to your cloud bucket using Form / Account Storage settings." })
2198
+ ] }),
2199
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Files", value: config.maxFiles ?? 1, onChange: (v) => updateConfig({ maxFiles: v }) }),
2200
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb ?? 10, onChange: (v) => updateConfig({ maxSizeMb: v }) }),
2201
+ /* @__PURE__ */ jsxRuntime.jsx(
2202
+ TextField,
2203
+ {
2204
+ label: "Accepted Types (comma-separated)",
2205
+ value: config.accept?.join(", "),
2206
+ placeholder: "e.g. image/*, .pdf, .docx, .zip",
2207
+ onChange: (v) => updateConfig({
2208
+ accept: v ? v.split(",").map((s) => s.trim()).filter(Boolean) : void 0
2209
+ })
2210
+ }
2211
+ ),
2212
+ /* @__PURE__ */ jsxRuntime.jsx(
2213
+ TextField,
2214
+ {
2215
+ label: "Upload URL",
2216
+ value: config.uploadUrl,
2217
+ placeholder: "https://api.example.com/s3/presign",
2218
+ onChange: (v) => updateConfig({ uploadUrl: v || void 0 })
2219
+ }
2220
+ ),
2221
+ /* @__PURE__ */ jsxRuntime.jsx(
2222
+ TextField,
2223
+ {
2224
+ label: "Public Key",
2225
+ value: config.publicKey,
2226
+ placeholder: "pk_test_...",
2227
+ onChange: (v) => updateConfig({ publicKey: v || void 0 })
2228
+ }
2229
+ )
1971
2230
  ] });
1972
2231
  case "signature":
1973
2232
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Signature Settings", children: [
1974
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Pen Color", value: config.penColor, placeholder: "#000000", onChange: (v) => updateConfig("penColor", v) }),
1975
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Background", value: config.backgroundColor, placeholder: "#ffffff", onChange: (v) => updateConfig("backgroundColor", v) }),
1976
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Width (px)", value: config.width, onChange: (v) => updateConfig("width", v) }),
1977
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Height (px)", value: config.height, onChange: (v) => updateConfig("height", v) })
2233
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Pen Color", value: config.penColor, placeholder: "#000000", onChange: (v) => updateConfig({ penColor: v }) }),
2234
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Background", value: config.backgroundColor, placeholder: "#ffffff", onChange: (v) => updateConfig({ backgroundColor: v }) }),
2235
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Width (px)", value: config.width, onChange: (v) => updateConfig({ width: v }) }),
2236
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Height (px)", value: config.height, onChange: (v) => updateConfig({ height: v }) })
1978
2237
  ] });
1979
2238
  case "image_capture":
1980
2239
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Camera Settings", children: [
1981
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Camera", value: config.camera ?? "any", options: [{ label: "Any", value: "any" }, { label: "Front", value: "front" }, { label: "Back", value: "back" }], onChange: (v) => updateConfig("camera", v) }),
1982
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb, onChange: (v) => updateConfig("maxSizeMb", v) }),
1983
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Gallery", checked: config.allowGallery !== false, onChange: (v) => updateConfig("allowGallery", v) })
2240
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Camera", value: config.camera ?? "any", options: [{ label: "Any", value: "any" }, { label: "Front", value: "front" }, { label: "Back", value: "back" }], onChange: (v) => updateConfig({ camera: v }) }),
2241
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb, onChange: (v) => updateConfig({ maxSizeMb: v }) }),
2242
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Gallery", checked: config.allowGallery !== false, onChange: (v) => updateConfig({ allowGallery: v }) })
1984
2243
  ] });
1985
2244
  // ── Content & Visual ──
1986
2245
  case "welcome-screen":
1987
2246
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Welcome Screen", children: [
1988
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Heading", value: config.heading ?? "Welcome", onChange: (v) => updateConfig("heading", v) }),
1989
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Description", value: config.description, onChange: (v) => updateConfig("description", v) }),
1990
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Button Text", value: config.buttonText ?? "Start", onChange: (v) => updateConfig("buttonText", v) }),
1991
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig("imageUrl", v) }),
1992
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Alignment", value: config.alignment ?? "center", options: [{ label: "Left", value: "left" }, { label: "Center", value: "center" }, { label: "Right", value: "right" }], onChange: (v) => updateConfig("alignment", v) })
2247
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Heading", value: config.heading ?? "Welcome", onChange: (v) => updateConfig({ heading: v }) }),
2248
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Description", value: config.description, onChange: (v) => updateConfig({ description: v }) }),
2249
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Button Text", value: config.buttonText ?? "Start", onChange: (v) => updateConfig({ buttonText: v }) }),
2250
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig({ imageUrl: v }) }),
2251
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Alignment", value: config.alignment ?? "center", options: [{ label: "Left", value: "left" }, { label: "Center", value: "center" }, { label: "Right", value: "right" }], onChange: (v) => updateConfig({ alignment: v }) })
1993
2252
  ] });
1994
2253
  case "thank-you-screen":
1995
2254
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Thank You Screen", children: [
1996
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Heading", value: config.heading ?? "Thank You!", onChange: (v) => updateConfig("heading", v) }),
1997
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Description", value: config.description ?? "", onChange: (v) => updateConfig("description", v) }),
1998
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig("imageUrl", v) }),
1999
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Redirect URL", value: config.redirectUrl, placeholder: "https://...", onChange: (v) => updateConfig("redirectUrl", v) }),
2000
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Redirect Delay (s)", value: config.redirectDelay, placeholder: "0", onChange: (v) => updateConfig("redirectDelay", v) }),
2001
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Response Summary", checked: !!config.showSummary, onChange: (v) => updateConfig("showSummary", v) })
2255
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Heading", value: config.heading ?? "Thank You!", onChange: (v) => updateConfig({ heading: v }) }),
2256
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Description", value: config.description ?? "", onChange: (v) => updateConfig({ description: v }) }),
2257
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig({ imageUrl: v }) }),
2258
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Redirect URL", value: config.redirectUrl, placeholder: "https://...", onChange: (v) => updateConfig({ redirectUrl: v }) }),
2259
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Redirect Delay (s)", value: config.redirectDelay, placeholder: "0", onChange: (v) => updateConfig({ redirectDelay: v }) }),
2260
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Response Summary", checked: !!config.showSummary, onChange: (v) => updateConfig({ showSummary: v }) })
2002
2261
  ] });
2003
2262
  case "rich-text":
2004
2263
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Rich Text", children: [
2005
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 6, onChange: (v) => updateConfig("content", v) }),
2006
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Format", value: config.format ?? "html", options: [{ label: "HTML", value: "html" }, { label: "Markdown", value: "markdown" }], onChange: (v) => updateConfig("format", v) })
2264
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 6, onChange: (v) => updateConfig({ content: v }) }),
2265
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Format", value: config.format ?? "html", options: [{ label: "HTML", value: "html" }, { label: "Markdown", value: "markdown" }], onChange: (v) => updateConfig({ format: v }) })
2007
2266
  ] });
2008
2267
  case "image":
2009
2268
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Image Settings", children: [
2010
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "https://...", onChange: (v) => updateConfig("src", v) }),
2011
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Alt Text", value: config.alt ?? "", onChange: (v) => updateConfig("alt", v) }),
2012
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Caption", value: config.caption, onChange: (v) => updateConfig("caption", v) }),
2013
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Alignment", value: config.alignment ?? "center", options: [{ label: "Left", value: "left" }, { label: "Center", value: "center" }, { label: "Right", value: "right" }], onChange: (v) => updateConfig("alignment", v) }),
2014
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 300px", onChange: (v) => updateConfig("width", v) }),
2015
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Link URL", value: config.link, placeholder: "Click opens this URL", onChange: (v) => updateConfig("link", v) })
2269
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "https://...", onChange: (v) => updateConfig({ src: v }) }),
2270
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Alt Text", value: config.alt ?? "", onChange: (v) => updateConfig({ alt: v }) }),
2271
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Caption", value: config.caption, onChange: (v) => updateConfig({ caption: v }) }),
2272
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Alignment", value: config.alignment ?? "center", options: [{ label: "Left", value: "left" }, { label: "Center", value: "center" }, { label: "Right", value: "right" }], onChange: (v) => updateConfig({ alignment: v }) }),
2273
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 300px", onChange: (v) => updateConfig({ width: v }) }),
2274
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Link URL", value: config.link, placeholder: "Click opens this URL", onChange: (v) => updateConfig({ link: v }) })
2016
2275
  ] });
2017
2276
  case "video":
2018
2277
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Video Settings", children: [
2019
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "YouTube/Vimeo URL", onChange: (v) => updateConfig("src", v) }),
2020
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Provider", value: config.provider ?? "youtube", options: [{ label: "YouTube", value: "youtube" }, { label: "Vimeo", value: "vimeo" }, { label: "Direct URL", value: "url" }], onChange: (v) => updateConfig("provider", v) }),
2021
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Autoplay", checked: !!config.autoplay, onChange: (v) => updateConfig("autoplay", v) }),
2022
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Muted", checked: !!config.muted, onChange: (v) => updateConfig("muted", v) }),
2023
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 640px", onChange: (v) => updateConfig("width", v) }),
2024
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Height", value: config.height, placeholder: "e.g. 360px", onChange: (v) => updateConfig("height", v) })
2278
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "YouTube/Vimeo URL", onChange: (v) => updateConfig({ src: v }) }),
2279
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Provider", value: config.provider ?? "youtube", options: [{ label: "YouTube", value: "youtube" }, { label: "Vimeo", value: "vimeo" }, { label: "Direct URL", value: "url" }], onChange: (v) => updateConfig({ provider: v }) }),
2280
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Autoplay", checked: !!config.autoplay, onChange: (v) => updateConfig({ autoplay: v }) }),
2281
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Muted", checked: !!config.muted, onChange: (v) => updateConfig({ muted: v }) }),
2282
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 640px", onChange: (v) => updateConfig({ width: v }) }),
2283
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Height", value: config.height, placeholder: "e.g. 360px", onChange: (v) => updateConfig({ height: v }) })
2025
2284
  ] });
2026
2285
  case "divider":
2027
2286
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Divider Settings", children: [
2028
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Style", value: config.style ?? "solid", options: [{ label: "Solid", value: "solid" }, { label: "Dashed", value: "dashed" }, { label: "Dotted", value: "dotted" }], onChange: (v) => updateConfig("style", v) }),
2029
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Color", value: config.color, placeholder: "#e5e7eb", onChange: (v) => updateConfig("color", v) }),
2030
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Thickness (px)", value: config.thickness, placeholder: "1", onChange: (v) => updateConfig("thickness", v) }),
2031
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Spacing (px)", value: config.spacing, placeholder: "16", onChange: (v) => updateConfig("spacing", v) })
2287
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Style", value: config.style ?? "solid", options: [{ label: "Solid", value: "solid" }, { label: "Dashed", value: "dashed" }, { label: "Dotted", value: "dotted" }], onChange: (v) => updateConfig({ style: v }) }),
2288
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Color", value: config.color, placeholder: "#e5e7eb", onChange: (v) => updateConfig({ color: v }) }),
2289
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Thickness (px)", value: config.thickness, placeholder: "1", onChange: (v) => updateConfig({ thickness: v }) }),
2290
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Spacing (px)", value: config.spacing, placeholder: "16", onChange: (v) => updateConfig({ spacing: v }) })
2032
2291
  ] });
2033
2292
  case "spacer":
2034
- return /* @__PURE__ */ jsxRuntime.jsx(ConfigSection, { title: "Spacer Settings", children: /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Height (px)", value: config.height ?? 32, onChange: (v) => updateConfig("height", v) }) });
2293
+ return /* @__PURE__ */ jsxRuntime.jsx(ConfigSection, { title: "Spacer Settings", children: /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Height (px)", value: config.height ?? 32, onChange: (v) => updateConfig({ height: v }) }) });
2035
2294
  // ── Structural ──
2036
2295
  case "section_header":
2037
2296
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Header Settings", children: [
2038
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Level", value: config.level ?? "h3", options: [{ label: "H2", value: "h2" }, { label: "H3", value: "h3" }, { label: "H4", value: "h4" }], onChange: (v) => updateConfig("level", v) }),
2039
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Divider", checked: !!config.showDivider, onChange: (v) => updateConfig("showDivider", v) })
2297
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Level", value: config.level ?? "h3", options: [{ label: "H2", value: "h2" }, { label: "H3", value: "h3" }, { label: "H4", value: "h4" }], onChange: (v) => updateConfig({ level: v }) }),
2298
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Divider", checked: !!config.showDivider, onChange: (v) => updateConfig({ showDivider: v }) })
2040
2299
  ] });
2041
2300
  case "info_block":
2042
2301
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Info Block", children: [
2043
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 4, onChange: (v) => updateConfig("content", v) }),
2044
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Variant", value: config.variant ?? "info", options: [{ label: "Info", value: "info" }, { label: "Warning", value: "warning" }, { label: "Success", value: "success" }, { label: "Error", value: "error" }], onChange: (v) => updateConfig("variant", v) })
2302
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 4, onChange: (v) => updateConfig({ content: v }) }),
2303
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Variant", value: config.variant ?? "info", options: [{ label: "Info", value: "info" }, { label: "Warning", value: "warning" }, { label: "Success", value: "success" }, { label: "Error", value: "error" }], onChange: (v) => updateConfig({ variant: v }) })
2045
2304
  ] });
2046
2305
  case "page_break":
2047
- return /* @__PURE__ */ jsxRuntime.jsx(ConfigSection, { title: "Page Break", children: /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Label", value: config.label, placeholder: "Next page label", onChange: (v) => updateConfig("label", v) }) });
2306
+ return /* @__PURE__ */ jsxRuntime.jsx(ConfigSection, { title: "Page Break", children: /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Label", value: config.label, placeholder: "Next page label", onChange: (v) => updateConfig({ label: v }) }) });
2048
2307
  case "consent":
2049
2308
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Consent Settings", children: [
2050
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Consent Text", value: config.text ?? "", rows: 4, onChange: (v) => updateConfig("text", v) }),
2051
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Checkbox Label", value: config.checkboxLabel ?? "I agree", onChange: (v) => updateConfig("checkboxLabel", v) }),
2052
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Expandable Text", value: config.expandableText, rows: 3, placeholder: "Additional text shown on expand", onChange: (v) => updateConfig("expandableText", v) })
2309
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Consent Text", value: config.text ?? "", rows: 4, onChange: (v) => updateConfig({ text: v }) }),
2310
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Checkbox Label", value: config.checkboxLabel ?? "I agree", onChange: (v) => updateConfig({ checkboxLabel: v }) }),
2311
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Expandable Text", value: config.expandableText, rows: 3, placeholder: "Additional text shown on expand", onChange: (v) => updateConfig({ expandableText: v }) })
2053
2312
  ] });
2054
2313
  // ── Advanced ──
2055
2314
  case "matrix":
2056
2315
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Matrix Settings", children: [
2057
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Input Type", value: config.inputType ?? "radio", options: [{ label: "Radio", value: "radio" }, { label: "Checkbox", value: "checkbox" }, { label: "Text", value: "text" }, { label: "Number", value: "number" }], onChange: (v) => updateConfig("inputType", v) }),
2058
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Required", value: config.required ?? "none", options: [{ label: "All rows", value: "all" }, { label: "Any row", value: "any" }, { label: "None", value: "none" }], onChange: (v) => updateConfig("required", v) }),
2059
- /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Rows", items: config.rows ?? [], onChange: (v) => updateConfig("rows", v) }),
2060
- /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Columns", items: config.columns ?? [], onChange: (v) => updateConfig("columns", v) })
2316
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Input Type", value: config.inputType ?? "radio", options: [{ label: "Radio", value: "radio" }, { label: "Checkbox", value: "checkbox" }, { label: "Text", value: "text" }, { label: "Number", value: "number" }], onChange: (v) => updateConfig({ inputType: v }) }),
2317
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Required", value: config.required ?? "none", options: [{ label: "All rows", value: "all" }, { label: "Any row", value: "any" }, { label: "None", value: "none" }], onChange: (v) => updateConfig({ required: v }) }),
2318
+ /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Rows", items: config.rows ?? [], onChange: (v) => updateConfig({ rows: v }) }),
2319
+ /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Columns", items: config.columns ?? [], onChange: (v) => updateConfig({ columns: v }) })
2061
2320
  ] });
2062
2321
  case "repeater":
2063
2322
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Repeater Settings", children: [
2064
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min Entries", value: config.minEntries, placeholder: "1", onChange: (v) => updateConfig("minEntries", v) }),
2065
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Entries", value: config.maxEntries, onChange: (v) => updateConfig("maxEntries", v) }),
2066
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Default Entries", value: config.defaultEntries, placeholder: "1", onChange: (v) => updateConfig("defaultEntries", v) }),
2067
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Add Button Label", value: config.addLabel, placeholder: "Add Entry", onChange: (v) => updateConfig("addLabel", v) }),
2068
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Remove Button Label", value: config.removeLabel, placeholder: "Remove", onChange: (v) => updateConfig("removeLabel", v) }),
2323
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min Entries", value: config.minEntries, placeholder: "1", onChange: (v) => updateConfig({ minEntries: v }) }),
2324
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Entries", value: config.maxEntries, onChange: (v) => updateConfig({ maxEntries: v }) }),
2325
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Default Entries", value: config.defaultEntries, placeholder: "1", onChange: (v) => updateConfig({ defaultEntries: v }) }),
2326
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Add Button Label", value: config.addLabel, placeholder: "Add Entry", onChange: (v) => updateConfig({ addLabel: v }) }),
2327
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Remove Button Label", value: config.removeLabel, placeholder: "Remove", onChange: (v) => updateConfig({ removeLabel: v }) }),
2069
2328
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-1 text-[11px] text-muted-foreground leading-relaxed", children: "Sub-fields for each repeater entry are configured by nesting questions inside the repeater in the schema JSON." })
2070
2329
  ] });
2071
2330
  case "address": {
@@ -2079,63 +2338,157 @@ function QuestionConfigEditor({ question, onUpdate }) {
2079
2338
  ];
2080
2339
  const activeFields = config.fields ?? ["street", "city", "state", "zip", "country"];
2081
2340
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Address Settings", children: [
2082
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Provider", value: config.provider ?? "none", options: [{ label: "None", value: "none" }, { label: "Google", value: "google" }, { label: "Mapbox", value: "mapbox" }], onChange: (v) => updateConfig("provider", v) }),
2083
- config.provider !== "none" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "API Key", value: config.apiKey, placeholder: "Provider API key", onChange: (v) => updateConfig("apiKey", v) }),
2084
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Default Country", value: config.defaultCountry, placeholder: "e.g. US", onChange: (v) => updateConfig("defaultCountry", v) }),
2341
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Provider", value: config.provider ?? "none", options: [{ label: "None", value: "none" }, { label: "Google", value: "google" }, { label: "Mapbox", value: "mapbox" }], onChange: (v) => updateConfig({ provider: v }) }),
2342
+ config.provider !== "none" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "API Key", value: config.apiKey, placeholder: "Provider API key", onChange: (v) => updateConfig({ apiKey: v }) }),
2343
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Default Country", value: config.defaultCountry, placeholder: "e.g. US", onChange: (v) => updateConfig({ defaultCountry: v }) }),
2085
2344
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2086
2345
  /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Label, { className: "text-xs text-muted-foreground mb-2 block", children: "Fields" }),
2087
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: ADDRESS_FIELDS.map((f) => /* @__PURE__ */ jsxRuntime.jsx(
2088
- ToggleField,
2089
- {
2090
- label: f.label,
2091
- checked: activeFields.includes(f.value),
2092
- onChange: (checked) => {
2093
- const next = checked ? [...activeFields, f.value] : activeFields.filter((v) => v !== f.value);
2094
- updateConfig("fields", next.length > 0 ? next : void 0);
2095
- }
2096
- },
2097
- f.value
2098
- )) })
2346
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: ADDRESS_FIELDS.map((f) => {
2347
+ const isChecked = activeFields.includes(f.value);
2348
+ const isLastChecked = isChecked && activeFields.length === 1;
2349
+ return /* @__PURE__ */ jsxRuntime.jsx(
2350
+ ToggleField,
2351
+ {
2352
+ label: f.label,
2353
+ checked: isChecked,
2354
+ disabled: isLastChecked,
2355
+ onChange: (checked) => {
2356
+ const next = checked ? [...activeFields, f.value] : activeFields.filter((v) => v !== f.value);
2357
+ updateConfig({ fields: next });
2358
+ }
2359
+ },
2360
+ f.value
2361
+ );
2362
+ }) })
2099
2363
  ] })
2100
2364
  ] });
2101
2365
  }
2102
- case "payment":
2366
+ case "payment": {
2367
+ const amountFieldOptions = [
2368
+ { label: "None (Fixed Amount)", value: "" },
2369
+ ...candidateAmountFields,
2370
+ { label: "Custom Field ID...", value: "__custom__" }
2371
+ ];
2372
+ const isCustomAmountField = Boolean(config.amountField) && !candidateAmountFields.some((opt) => opt.value === config.amountField);
2103
2373
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Payment Settings", children: [
2104
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Provider", value: config.provider ?? "stripe", options: [{ label: "Stripe", value: "stripe" }, { label: "PayPal", value: "paypal" }], onChange: (v) => updateConfig("provider", v) }),
2105
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Public Key", value: config.publicKey ?? "", placeholder: "Provider public/client key", onChange: (v) => updateConfig("publicKey", v) }),
2106
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Amount", value: config.amount, onChange: (v) => updateConfig("amount", v) }),
2107
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Amount Field", value: config.amountField, placeholder: "Field ID for dynamic amount", onChange: (v) => updateConfig("amountField", v) }),
2108
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Currency", value: config.currency, placeholder: "USD", onChange: (v) => updateConfig("currency", v) }),
2109
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Description", value: config.description, onChange: (v) => updateConfig("description", v) })
2374
+ /* @__PURE__ */ jsxRuntime.jsx(
2375
+ SelectField,
2376
+ {
2377
+ label: "Provider",
2378
+ value: config.provider ?? "stripe",
2379
+ options: [
2380
+ { label: "Stripe", value: "stripe" },
2381
+ { label: "PayPal", value: "paypal" },
2382
+ { label: "Razorpay", value: "razorpay" }
2383
+ ],
2384
+ onChange: (v) => updateConfig({ provider: v })
2385
+ }
2386
+ ),
2387
+ /* @__PURE__ */ jsxRuntime.jsx(
2388
+ TextField,
2389
+ {
2390
+ label: "Public Key",
2391
+ value: config.publicKey,
2392
+ placeholder: "pk_test_...",
2393
+ onChange: (v) => updateConfig({ publicKey: v || void 0 })
2394
+ }
2395
+ ),
2396
+ /* @__PURE__ */ jsxRuntime.jsx(
2397
+ TextField,
2398
+ {
2399
+ label: "Server URL",
2400
+ value: config.serverUrl,
2401
+ placeholder: "https://api.example.com/create-intent",
2402
+ onChange: (v) => updateConfig({ serverUrl: v || void 0 })
2403
+ }
2404
+ ),
2405
+ candidateAmountFields.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2406
+ /* @__PURE__ */ jsxRuntime.jsx(
2407
+ SelectField,
2408
+ {
2409
+ label: "Dynamic Amount Field",
2410
+ value: isCustomAmountField ? "__custom__" : config.amountField ?? "",
2411
+ options: amountFieldOptions,
2412
+ onChange: (v) => {
2413
+ if (v !== "__custom__") {
2414
+ updateConfig({ amountField: v || void 0 });
2415
+ }
2416
+ }
2417
+ }
2418
+ ),
2419
+ isCustomAmountField && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsxRuntime.jsx(
2420
+ TextField,
2421
+ {
2422
+ label: "Custom Field ID",
2423
+ value: config.amountField,
2424
+ placeholder: "Field ID for dynamic amount",
2425
+ onChange: (v) => updateConfig({ amountField: v || void 0 })
2426
+ }
2427
+ ) })
2428
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(
2429
+ TextField,
2430
+ {
2431
+ label: "Amount Field",
2432
+ value: config.amountField,
2433
+ placeholder: "Field ID for dynamic amount (e.g. total_cost)",
2434
+ onChange: (v) => updateConfig({ amountField: v || void 0 })
2435
+ }
2436
+ ),
2437
+ !config.amountField && /* @__PURE__ */ jsxRuntime.jsx(
2438
+ NumberField,
2439
+ {
2440
+ label: "Fixed Amount",
2441
+ value: config.amount,
2442
+ onChange: (v) => updateConfig({ amount: v })
2443
+ }
2444
+ ),
2445
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Currency", value: config.currency ?? "USD", placeholder: "USD", onChange: (v) => updateConfig({ currency: v || "USD" }) }),
2446
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Description", value: config.description, onChange: (v) => updateConfig({ description: v }) }),
2447
+ /* @__PURE__ */ jsxRuntime.jsx(
2448
+ TextField,
2449
+ {
2450
+ label: "Client Secret Response Path",
2451
+ value: typeof config.responseMapping?.clientSecretPath === "string" ? config.responseMapping.clientSecretPath : config.responseMapping ?? "",
2452
+ placeholder: "clientSecret",
2453
+ onChange: (v) => updateConfig({
2454
+ responseMapping: v ? { clientSecretPath: v } : void 0
2455
+ })
2456
+ }
2457
+ )
2110
2458
  ] });
2459
+ }
2111
2460
  case "calculated":
2112
2461
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Calculated Field", children: [
2113
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Expression", value: config.expression ?? "", placeholder: "e.g. {q1} + {q2}", onChange: (v) => updateConfig("expression", v) }),
2114
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Format", value: config.format ?? "number", options: [{ label: "Number", value: "number" }, { label: "Currency", value: "currency" }, { label: "Percentage", value: "percentage" }], onChange: (v) => updateConfig("format", v) }),
2115
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "2", onChange: (v) => updateConfig("decimalPlaces", v) }),
2116
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, onChange: (v) => updateConfig("prefix", v) }),
2117
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, onChange: (v) => updateConfig("suffix", v) }),
2118
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Visible to User", checked: config.visible !== false, onChange: (v) => updateConfig("visible", v) })
2462
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Expression", value: config.expression ?? "", placeholder: "e.g. {q1} + {q2}", onChange: (v) => updateConfig({ expression: v }) }),
2463
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Format", value: config.format ?? "number", options: [{ label: "Number", value: "number" }, { label: "Currency", value: "currency" }, { label: "Percentage", value: "percentage" }], onChange: (v) => updateConfig({ format: v }) }),
2464
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "2", onChange: (v) => updateConfig({ decimalPlaces: v }) }),
2465
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, onChange: (v) => updateConfig({ prefix: v }) }),
2466
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, onChange: (v) => updateConfig({ suffix: v }) }),
2467
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Visible to User", checked: config.visible !== false, onChange: (v) => updateConfig({ visible: v }) })
2119
2468
  ] });
2120
2469
  case "hidden":
2121
2470
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Hidden Field", children: [
2122
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Source", value: config.source ?? "static", options: [{ label: "Static Value", value: "static" }, { label: "URL Parameter", value: "url_param" }, { label: "Cookie", value: "cookie" }, { label: "Referrer", value: "referrer" }], onChange: (v) => updateConfig("source", v) }),
2123
- config.source === "static" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Default Value", value: config.defaultValue, onChange: (v) => updateConfig("defaultValue", v) }),
2124
- config.source === "url_param" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Parameter Name", value: config.paramName, placeholder: "e.g. utm_source", onChange: (v) => updateConfig("paramName", v) }),
2125
- config.source === "cookie" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Cookie Name", value: config.cookieName, onChange: (v) => updateConfig("cookieName", v) })
2471
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Source", value: config.source ?? "static", options: [{ label: "Static Value", value: "static" }, { label: "URL Parameter", value: "url_param" }, { label: "Cookie", value: "cookie" }, { label: "Referrer", value: "referrer" }], onChange: (v) => updateConfig({ source: v }) }),
2472
+ config.source === "static" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Default Value", value: config.defaultValue, onChange: (v) => updateConfig({ defaultValue: v }) }),
2473
+ config.source === "url_param" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Parameter Name", value: config.paramName, placeholder: "e.g. utm_source", onChange: (v) => updateConfig({ paramName: v }) }),
2474
+ config.source === "cookie" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Cookie Name", value: config.cookieName, onChange: (v) => updateConfig({ cookieName: v }) })
2126
2475
  ] });
2127
2476
  case "scoring":
2128
2477
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Scoring Settings", children: [
2129
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Score", checked: !!config.showScore, onChange: (v) => updateConfig("showScore", v) }),
2130
- /* @__PURE__ */ jsxRuntime.jsx(ScoringOptionsEditor, { options: config.options ?? [], onChange: (v) => updateConfig("options", v) }),
2131
- /* @__PURE__ */ jsxRuntime.jsx(ScoreRangesEditor, { ranges: config.scoreRanges ?? [], onChange: (v) => updateConfig("scoreRanges", v) })
2478
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Score", checked: !!config.showScore, onChange: (v) => updateConfig({ showScore: v }) }),
2479
+ /* @__PURE__ */ jsxRuntime.jsx(ScoringOptionsEditor, { options: config.options ?? [], onChange: (v) => updateConfig({ options: v }) }),
2480
+ /* @__PURE__ */ jsxRuntime.jsx(ScoreRangesEditor, { ranges: config.scoreRanges ?? [], onChange: (v) => updateConfig({ scoreRanges: v }) })
2132
2481
  ] });
2133
2482
  case "ranking":
2134
- return /* @__PURE__ */ jsxRuntime.jsx(ConfigSection, { title: "Ranking Settings", children: /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Items", items: config.items ?? [], onChange: (v) => updateConfig("items", v) }) });
2483
+ return /* @__PURE__ */ jsxRuntime.jsx(ConfigSection, { title: "Ranking Settings", children: /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Items", items: config.items ?? [], onChange: (v) => updateConfig({ items: v }) }) });
2484
+ case "phone_international":
2485
+ return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "International Phone Settings", children: [
2486
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Default Country", value: config.defaultCountry ?? "US", placeholder: "e.g. US", onChange: (v) => updateConfig({ defaultCountry: v }) }),
2487
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Priority Countries", value: config.priorityCountries?.join(", "), placeholder: "e.g. US, GB, CA", onChange: (v) => updateConfig({ priorityCountries: v ? v.split(",").map((s) => s.trim()).filter(Boolean) : void 0 }) })
2488
+ ] });
2135
2489
  // Types with no additional config
2136
2490
  case "email":
2137
2491
  case "phone":
2138
- case "phone_international":
2139
2492
  case "url":
2140
2493
  return null;
2141
2494
  default:
@@ -2212,11 +2565,12 @@ function NumberField({
2212
2565
  function ToggleField({
2213
2566
  label,
2214
2567
  checked,
2215
- onChange
2568
+ onChange,
2569
+ disabled
2216
2570
  }) {
2217
2571
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
2218
2572
  /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Label, { className: "text-xs text-muted-foreground", children: label }),
2219
- /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Switch, { checked, onCheckedChange: onChange })
2573
+ /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Switch, { checked, onCheckedChange: onChange, disabled })
2220
2574
  ] });
2221
2575
  }
2222
2576
  function SelectField({
@@ -2227,7 +2581,10 @@ function SelectField({
2227
2581
  }) {
2228
2582
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2229
2583
  /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Label, { className: "text-xs text-muted-foreground mb-1", children: label }),
2230
- /* @__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)) })
2584
+ /* @__PURE__ */ jsxRuntime.jsxs(Select, { value, onValueChange: onChange, children: [
2585
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: options.find((o) => o.value === value)?.label ?? value }) }),
2586
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
2587
+ ] })
2231
2588
  ] });
2232
2589
  }
2233
2590
  function LikertLabelsEditor({
@@ -2373,6 +2730,59 @@ function ScoringOptionsEditor({
2373
2730
  ] }, index)) })
2374
2731
  ] });
2375
2732
  }
2733
+ function AppointmentSlotsEditor({
2734
+ slots,
2735
+ onChange
2736
+ }) {
2737
+ const handleDateChange = (index, date) => {
2738
+ const updated = slots.map((s, i) => i === index ? { ...s, date } : s);
2739
+ onChange(updated);
2740
+ };
2741
+ const handleTimesChange = (index, timesStr) => {
2742
+ const times = timesStr.split(",").map((t) => t.trim()).filter(Boolean);
2743
+ const updated = slots.map((s, i) => i === index ? { ...s, times } : s);
2744
+ onChange(updated);
2745
+ };
2746
+ const handleAdd = () => {
2747
+ const tomorrow = /* @__PURE__ */ new Date();
2748
+ tomorrow.setDate(tomorrow.getDate() + 1);
2749
+ const dateStr = tomorrow.toISOString().split("T")[0];
2750
+ onChange([...slots, { date: dateStr, times: ["09:00", "10:00", "11:00", "14:00", "15:00"] }]);
2751
+ };
2752
+ const handleRemove = (index) => {
2753
+ onChange(slots.filter((_, i) => i !== index));
2754
+ };
2755
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2756
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
2757
+ /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Label, { className: "text-xs text-muted-foreground", children: "Slots" }),
2758
+ /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Button, { type: "button", variant: "link", size: "xs", onClick: handleAdd, className: "px-0", children: "+ Add Date" })
2759
+ ] }),
2760
+ slots.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] text-muted-foreground", children: "No slots configured. Add a date to get started." }),
2761
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: slots.map((slot, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-2 rounded-md border border-border space-y-1.5 group", children: [
2762
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
2763
+ /* @__PURE__ */ jsxRuntime.jsx(
2764
+ fieldcraftReact.Input,
2765
+ {
2766
+ type: "date",
2767
+ value: slot.date,
2768
+ onChange: (e) => handleDateChange(index, e.target.value),
2769
+ className: "h-7 text-xs flex-1"
2770
+ }
2771
+ ),
2772
+ /* @__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" })
2773
+ ] }),
2774
+ /* @__PURE__ */ jsxRuntime.jsx(
2775
+ fieldcraftReact.Input,
2776
+ {
2777
+ value: slot.times.join(", "),
2778
+ onChange: (e) => handleTimesChange(index, e.target.value),
2779
+ className: "h-7 text-xs",
2780
+ placeholder: "09:00, 10:00, 14:00, 15:00"
2781
+ }
2782
+ )
2783
+ ] }, index)) })
2784
+ ] });
2785
+ }
2376
2786
  function ScoreRangesEditor({
2377
2787
  ranges,
2378
2788
  onChange
@@ -2405,6 +2815,26 @@ function ScoreRangesEditor({
2405
2815
  ] }, index)) })
2406
2816
  ] });
2407
2817
  }
2818
+ var NativeSelect = React.forwardRef(
2819
+ ({ className, wrapperClassName, children, ...props }, ref) => {
2820
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative", wrapperClassName), children: [
2821
+ /* @__PURE__ */ jsxRuntime.jsx(
2822
+ "select",
2823
+ {
2824
+ ref,
2825
+ className: cn(
2826
+ "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",
2827
+ className
2828
+ ),
2829
+ ...props,
2830
+ children
2831
+ }
2832
+ ),
2833
+ /* @__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" })
2834
+ ] });
2835
+ }
2836
+ );
2837
+ NativeSelect.displayName = "NativeSelect";
2408
2838
  var RULE_TYPES = [
2409
2839
  { value: "minLength", label: "Min Length", description: "Minimum character count" },
2410
2840
  { value: "maxLength", label: "Max Length", description: "Maximum character count" },
@@ -2809,7 +3239,7 @@ function FormSettingsPanel({ schema, onUpdate }) {
2809
3239
  ];
2810
3240
  const displayMode = settings.displayMode ?? "stepped";
2811
3241
  const effectiveDisplayMode = hasConditions && displayMode === "classic" ? "stepped" : displayMode;
2812
- react.useEffect(() => {
3242
+ React.useEffect(() => {
2813
3243
  if (effectiveDisplayMode !== displayMode) {
2814
3244
  onUpdate({ ...schema, settings: { ...settings, displayMode: effectiveDisplayMode } });
2815
3245
  }
@@ -2966,7 +3396,7 @@ function SettingsSelect({
2966
3396
  }
2967
3397
  function PropertiesPanel({ builderState }) {
2968
3398
  const { schema, selectedItem } = builderState;
2969
- const [showSettings, setShowSettings] = react.useState(false);
3399
+ const [showSettings, setShowSettings] = React.useState(false);
2970
3400
  if (showSettings) {
2971
3401
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-80 h-full border-l border-border bg-card flex flex-col", children: [
2972
3402
  /* @__PURE__ */ jsxRuntime.jsx(PanelHeader, { title: "Form Settings", onClose: () => setShowSettings(false) }),
@@ -3041,11 +3471,11 @@ function SectionProperties({ section, onUpdate, onClose, onOpenSettings }) {
3041
3471
  ] });
3042
3472
  }
3043
3473
  function QuestionProperties({ question, sectionId, builderState, onClose, onOpenSettings }) {
3044
- const [activeTab, setActiveTab] = react.useState("basic");
3474
+ const [activeTab, setActiveTab] = React.useState("basic");
3045
3475
  const typeInfo = QUESTION_TYPE_INFO[question.type];
3046
3476
  const IconComponent = typeInfo ? getIcon(typeInfo.icon) : null;
3047
3477
  const hasOptions = typeInfo?.requiresOptions || question.options && question.options.length > 0;
3048
- const updateQuestion2 = react.useCallback(
3478
+ const updateQuestion2 = React.useCallback(
3049
3479
  (updates) => {
3050
3480
  builderState.updateQuestion(sectionId, question.id, updates);
3051
3481
  },
@@ -3112,7 +3542,14 @@ function QuestionProperties({ question, sectionId, builderState, onClose, onOpen
3112
3542
  }
3113
3543
  )
3114
3544
  ] }),
3115
- /* @__PURE__ */ jsxRuntime.jsx(QuestionConfigEditor, { question, onUpdate: updateQuestion2 }),
3545
+ /* @__PURE__ */ jsxRuntime.jsx(
3546
+ QuestionConfigEditor,
3547
+ {
3548
+ question,
3549
+ schema: builderState.schema,
3550
+ onUpdate: updateQuestion2
3551
+ }
3552
+ ),
3116
3553
  hasOptions && /* @__PURE__ */ jsxRuntime.jsx(
3117
3554
  OptionsEditor,
3118
3555
  {
@@ -3220,7 +3657,7 @@ function FieldGroup({ label, children }) {
3220
3657
  children
3221
3658
  ] });
3222
3659
  }
3223
- var PreviewErrorBoundary = class extends react.Component {
3660
+ var PreviewErrorBoundary = class extends React.Component {
3224
3661
  state = { error: null };
3225
3662
  static getDerivedStateFromError(error) {
3226
3663
  return { error };
@@ -3281,15 +3718,20 @@ function errorsToMarkers(errors) {
3281
3718
  source: "FieldCraft Schema Validator"
3282
3719
  }));
3283
3720
  }
3284
- var Editor = react.lazy(() => import('@monaco-editor/react').then((m) => ({ default: m.default })));
3721
+ var Editor = React.lazy(() => import('@monaco-editor/react').then((m) => ({ default: m.default })));
3285
3722
  function MonacoWrapper({ value, onChange, errors }) {
3286
- const editorRef = react.useRef(null);
3287
- const monacoRef = react.useRef(null);
3723
+ const editorRef = React.useRef(null);
3724
+ const monacoRef = React.useRef(null);
3288
3725
  const handleMount = (editor, monaco) => {
3289
3726
  editorRef.current = editor;
3290
3727
  monacoRef.current = monaco;
3291
3728
  };
3292
- react.useEffect(() => {
3729
+ React.useEffect(() => {
3730
+ return () => {
3731
+ editorRef.current?.dispose();
3732
+ };
3733
+ }, []);
3734
+ React.useEffect(() => {
3293
3735
  const editor = editorRef.current;
3294
3736
  const monaco = monacoRef.current;
3295
3737
  if (!editor || !monaco) return;
@@ -3321,14 +3763,14 @@ function MonacoWrapper({ value, onChange, errors }) {
3321
3763
  );
3322
3764
  }
3323
3765
  function JsonEditorPanel({ value, onChange, errors, onValidate }) {
3324
- const handleChange = react.useCallback(
3766
+ const handleChange = React.useCallback(
3325
3767
  (newValue) => {
3326
3768
  onChange(newValue);
3327
3769
  onValidate(newValue);
3328
3770
  },
3329
3771
  [onChange, onValidate]
3330
3772
  );
3331
- const handleFormat = react.useCallback(() => {
3773
+ const handleFormat = React.useCallback(() => {
3332
3774
  try {
3333
3775
  const formatted = JSON.stringify(JSON.parse(value), null, 2);
3334
3776
  onChange(formatted);
@@ -3361,7 +3803,7 @@ function JsonEditorPanel({ value, onChange, errors, onValidate }) {
3361
3803
  )
3362
3804
  ] }),
3363
3805
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
3364
- react.Suspense,
3806
+ React.Suspense,
3365
3807
  {
3366
3808
  fallback: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full text-sm text-muted-foreground", children: "Loading editor..." }),
3367
3809
  children: /* @__PURE__ */ jsxRuntime.jsx(MonacoWrapper, { value, onChange: handleChange, errors })
@@ -3560,7 +4002,7 @@ function SectionNodeInner({ data }) {
3560
4002
  const d = data;
3561
4003
  const color = SECTION_COLORS[d.colorIndex % SECTION_COLORS.length];
3562
4004
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fc-flow-section-group", style: { borderColor: color }, children: [
3563
- /* @__PURE__ */ jsxRuntime.jsx(react$1.Handle, { type: "target", position: react$1.Position.Left, className: "fc-flow-handle fc-flow-handle--section" }),
4005
+ /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "target", position: react.Position.Left, className: "fc-flow-handle fc-flow-handle--section" }),
3564
4006
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fc-flow-section-group__header", style: { background: color }, children: [
3565
4007
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "fc-flow-section-group__label", children: d.label.length > 30 ? d.label.slice(0, 30) + "\u2026" : d.label }),
3566
4008
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "fc-flow-section-group__meta", children: [
@@ -3571,10 +4013,10 @@ function SectionNodeInner({ data }) {
3571
4013
  d.hasExitLogic && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "fc-flow-section-group__badge fc-flow-section-group__badge--jump", title: "Has onExit jump", children: "\u2934" })
3572
4014
  ] })
3573
4015
  ] }),
3574
- /* @__PURE__ */ jsxRuntime.jsx(react$1.Handle, { type: "source", position: react$1.Position.Right, className: "fc-flow-handle fc-flow-handle--section" })
4016
+ /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "source", position: react.Position.Right, className: "fc-flow-handle fc-flow-handle--section" })
3575
4017
  ] });
3576
4018
  }
3577
- var SectionNode = react.memo(SectionNodeInner);
4019
+ var SectionNode = React.memo(SectionNodeInner);
3578
4020
  function FieldNodeInner({ data }) {
3579
4021
  const d = data;
3580
4022
  const color = SECTION_COLORS[d.colorIndex % SECTION_COLORS.length];
@@ -3587,18 +4029,18 @@ function FieldNodeInner({ data }) {
3587
4029
  borderWidth: d.hasCondition ? 2 : 1
3588
4030
  },
3589
4031
  children: [
3590
- /* @__PURE__ */ jsxRuntime.jsx(react$1.Handle, { type: "target", position: react$1.Position.Left, className: "fc-flow-handle" }),
4032
+ /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "target", position: react.Position.Left, className: "fc-flow-handle" }),
3591
4033
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fc-flow-field__content", children: [
3592
4034
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "fc-flow-field__label", children: d.label.length > 26 ? d.label.slice(0, 26) + "\u2026" : d.label }),
3593
4035
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "fc-flow-field__type", children: d.fieldType })
3594
4036
  ] }),
3595
4037
  d.hasCondition && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fc-flow-badge", style: { background: color }, title: "Has showIf condition", children: "?" }),
3596
- /* @__PURE__ */ jsxRuntime.jsx(react$1.Handle, { type: "source", position: react$1.Position.Right, className: "fc-flow-handle" })
4038
+ /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "source", position: react.Position.Right, className: "fc-flow-handle" })
3597
4039
  ]
3598
4040
  }
3599
4041
  );
3600
4042
  }
3601
- var FieldNode = react.memo(FieldNodeInner);
4043
+ var FieldNode = React.memo(FieldNodeInner);
3602
4044
  var logicFlowNodeTypes = {
3603
4045
  sectionNode: SectionNode,
3604
4046
  fieldNode: FieldNode
@@ -3616,7 +4058,7 @@ function ConditionEdgeInner({
3616
4058
  data,
3617
4059
  markerEnd
3618
4060
  }) {
3619
- const [edgePath, labelX, labelY] = react$1.getBezierPath({
4061
+ const [edgePath, labelX, labelY] = react.getBezierPath({
3620
4062
  sourceX,
3621
4063
  sourceY,
3622
4064
  sourcePosition,
@@ -3627,7 +4069,7 @@ function ConditionEdgeInner({
3627
4069
  const isJump = data?.edgeType === "onExit";
3628
4070
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3629
4071
  /* @__PURE__ */ jsxRuntime.jsx(
3630
- react$1.BaseEdge,
4072
+ react.BaseEdge,
3631
4073
  {
3632
4074
  id,
3633
4075
  path: edgePath,
@@ -3640,7 +4082,7 @@ function ConditionEdgeInner({
3640
4082
  }
3641
4083
  }
3642
4084
  ),
3643
- label && /* @__PURE__ */ jsxRuntime.jsx(react$1.EdgeLabelRenderer, { children: /* @__PURE__ */ jsxRuntime.jsx(
4085
+ label && /* @__PURE__ */ jsxRuntime.jsx(react.EdgeLabelRenderer, { children: /* @__PURE__ */ jsxRuntime.jsx(
3644
4086
  "div",
3645
4087
  {
3646
4088
  className: "fc-flow-edge-label",
@@ -3653,7 +4095,7 @@ function ConditionEdgeInner({
3653
4095
  ) })
3654
4096
  ] });
3655
4097
  }
3656
- var ConditionEdge = react.memo(ConditionEdgeInner);
4098
+ var ConditionEdge = React.memo(ConditionEdgeInner);
3657
4099
  function PipelineEdgeInner({
3658
4100
  id,
3659
4101
  sourceX,
@@ -3664,7 +4106,7 @@ function PipelineEdgeInner({
3664
4106
  targetPosition,
3665
4107
  markerEnd
3666
4108
  }) {
3667
- const [edgePath] = react$1.getBezierPath({
4109
+ const [edgePath] = react.getBezierPath({
3668
4110
  sourceX,
3669
4111
  sourceY,
3670
4112
  sourcePosition,
@@ -3673,7 +4115,7 @@ function PipelineEdgeInner({
3673
4115
  targetPosition
3674
4116
  });
3675
4117
  return /* @__PURE__ */ jsxRuntime.jsx(
3676
- react$1.BaseEdge,
4118
+ react.BaseEdge,
3677
4119
  {
3678
4120
  id,
3679
4121
  path: edgePath,
@@ -3686,7 +4128,7 @@ function PipelineEdgeInner({
3686
4128
  }
3687
4129
  );
3688
4130
  }
3689
- var PipelineEdge = react.memo(PipelineEdgeInner);
4131
+ var PipelineEdge = React.memo(PipelineEdgeInner);
3690
4132
  var logicFlowEdgeTypes = {
3691
4133
  conditionEdge: ConditionEdge,
3692
4134
  pipelineEdge: PipelineEdge
@@ -3724,30 +4166,30 @@ function removeConditionForSource(showIf, sourceFieldId) {
3724
4166
  }
3725
4167
  var defaultEdgeOptions = {
3726
4168
  markerEnd: {
3727
- type: react$1.MarkerType.ArrowClosed,
4169
+ type: react.MarkerType.ArrowClosed,
3728
4170
  width: 16,
3729
4171
  height: 12
3730
4172
  }
3731
4173
  };
3732
4174
  function LogicFlowEditor({ schema, onChange }) {
3733
4175
  const noSections = schema.sections.length === 0;
3734
- const flowGraph = react.useMemo(() => buildReactFlowGraph(schema), [schema]);
3735
- const [nodes, setNodes, onNodesChange] = react$1.useNodesState(flowGraph.nodes);
3736
- const [edges, setEdges, onEdgesChange] = react$1.useEdgesState(flowGraph.edges);
3737
- const [selectedFieldId, setSelectedFieldId] = react.useState(null);
4176
+ const flowGraph = React.useMemo(() => buildReactFlowGraph(schema), [schema]);
4177
+ const [nodes, setNodes, onNodesChange] = react.useNodesState(flowGraph.nodes);
4178
+ const [edges, setEdges, onEdgesChange] = react.useEdgesState(flowGraph.edges);
4179
+ const [selectedFieldId, setSelectedFieldId] = React.useState(null);
3738
4180
  const selectedQuestion = selectedFieldId ? findQuestion2(schema, selectedFieldId) : void 0;
3739
- react.useEffect(() => {
4181
+ React.useEffect(() => {
3740
4182
  setNodes(flowGraph.nodes);
3741
4183
  setEdges(flowGraph.edges);
3742
4184
  }, [flowGraph, setNodes, setEdges]);
3743
- const sectionIds = react.useMemo(() => {
4185
+ const sectionIds = React.useMemo(() => {
3744
4186
  const ids = [];
3745
4187
  for (const section of schema.sections) {
3746
4188
  ids.push(section.id);
3747
4189
  }
3748
4190
  return ids;
3749
4191
  }, [schema]);
3750
- const onNodeClick = react.useCallback(
4192
+ const onNodeClick = React.useCallback(
3751
4193
  (_event, node) => {
3752
4194
  if (node.type === "fieldNode") {
3753
4195
  setSelectedFieldId(node.id);
@@ -3755,7 +4197,7 @@ function LogicFlowEditor({ schema, onChange }) {
3755
4197
  },
3756
4198
  []
3757
4199
  );
3758
- const onConnect = react.useCallback(
4200
+ const onConnect = React.useCallback(
3759
4201
  (connection) => {
3760
4202
  if (!connection.source || !connection.target) return;
3761
4203
  const targetQuestion = findQuestion2(schema, connection.target);
@@ -3782,7 +4224,7 @@ function LogicFlowEditor({ schema, onChange }) {
3782
4224
  },
3783
4225
  [schema, onChange]
3784
4226
  );
3785
- const onEdgesDelete = react.useCallback(
4227
+ const onEdgesDelete = React.useCallback(
3786
4228
  (deletedEdges) => {
3787
4229
  let updatedSchema = schema;
3788
4230
  for (const edge of deletedEdges) {
@@ -3807,7 +4249,7 @@ function LogicFlowEditor({ schema, onChange }) {
3807
4249
  },
3808
4250
  [schema, onChange]
3809
4251
  );
3810
- const handleConditionUpdate = react.useCallback(
4252
+ const handleConditionUpdate = React.useCallback(
3811
4253
  (updates) => {
3812
4254
  if (!selectedFieldId) return;
3813
4255
  const updatedSchema = updateQuestionInSchema(schema, selectedFieldId, updates);
@@ -3821,18 +4263,18 @@ function LogicFlowEditor({ schema, onChange }) {
3821
4263
  const jumpCount = flowGraph.edges.filter(
3822
4264
  (e) => e.data?.edgeType === "onExit"
3823
4265
  ).length;
3824
- const totalFields = react.useMemo(
4266
+ const totalFields = React.useMemo(
3825
4267
  () => schema.sections.reduce((sum, s) => sum + s.questions.length, 0),
3826
4268
  [schema]
3827
4269
  );
3828
- const conditionalFields = react.useMemo(
4270
+ const conditionalFields = React.useMemo(
3829
4271
  () => schema.sections.reduce(
3830
4272
  (sum, s) => sum + s.questions.filter((q) => !!q.showIf).length,
3831
4273
  0
3832
4274
  ),
3833
4275
  [schema]
3834
4276
  );
3835
- return /* @__PURE__ */ jsxRuntime.jsx(react$1.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
4277
+ return /* @__PURE__ */ jsxRuntime.jsx(react.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
3836
4278
  LogicFlowInner,
3837
4279
  {
3838
4280
  noSections,
@@ -3876,7 +4318,7 @@ function LogicFlowInner({
3876
4318
  totalFields,
3877
4319
  conditionalFields
3878
4320
  }) {
3879
- const { zoomIn, zoomOut, fitView } = react$1.useReactFlow();
4321
+ const { zoomIn, zoomOut, fitView } = react.useReactFlow();
3880
4322
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col bg-background min-h-0", children: [
3881
4323
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 h-9 flex items-center justify-between px-4 border-b border-border bg-card/50", children: [
3882
4324
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [
@@ -3904,7 +4346,7 @@ function LogicFlowInner({
3904
4346
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs max-w-xs mx-auto", children: "Switch to Design mode and add sections with fields. Then come back here to visualize and edit branching logic." })
3905
4347
  ] }) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex min-h-0", children: [
3906
4348
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntime.jsxs(
3907
- react$1.ReactFlow,
4349
+ react.ReactFlow,
3908
4350
  {
3909
4351
  nodes,
3910
4352
  edges,
@@ -3921,9 +4363,9 @@ function LogicFlowInner({
3921
4363
  deleteKeyCode: ["Backspace", "Delete"],
3922
4364
  proOptions: { hideAttribution: true },
3923
4365
  children: [
3924
- /* @__PURE__ */ jsxRuntime.jsx(react$1.Background, { gap: 20, size: 1 }),
4366
+ /* @__PURE__ */ jsxRuntime.jsx(react.Background, { gap: 20, size: 1 }),
3925
4367
  /* @__PURE__ */ jsxRuntime.jsx(
3926
- react$1.MiniMap,
4368
+ react.MiniMap,
3927
4369
  {
3928
4370
  nodeColor: (node) => {
3929
4371
  const d = node.data;
@@ -3987,15 +4429,15 @@ function LogicFlowInner({
3987
4429
  ] });
3988
4430
  }
3989
4431
  function TemplateGallery({ templates, onSelect, onClose }) {
3990
- const [search, setSearch] = react.useState("");
3991
- const [activeCategory, setActiveCategory] = react.useState("all");
3992
- const [confirmTemplate, setConfirmTemplate] = react.useState(null);
3993
- const categories = react.useMemo(() => {
4432
+ const [search, setSearch] = React.useState("");
4433
+ const [activeCategory, setActiveCategory] = React.useState("all");
4434
+ const [confirmTemplate, setConfirmTemplate] = React.useState(null);
4435
+ const categories = React.useMemo(() => {
3994
4436
  const cats = /* @__PURE__ */ new Set();
3995
4437
  for (const t of templates) cats.add(t.meta.category);
3996
4438
  return ["all", ...Array.from(cats)];
3997
4439
  }, [templates]);
3998
- const filtered = react.useMemo(() => {
4440
+ const filtered = React.useMemo(() => {
3999
4441
  return templates.filter((t) => {
4000
4442
  const matchesCategory = activeCategory === "all" || t.meta.category === activeCategory;
4001
4443
  const matchesSearch = !search || t.meta.name.toLowerCase().includes(search.toLowerCase()) || t.meta.description.toLowerCase().includes(search.toLowerCase()) || t.meta.tags?.some((tag) => tag.toLowerCase().includes(search.toLowerCase()));
@@ -4091,9 +4533,14 @@ function TemplateGallery({ templates, onSelect, onClose }) {
4091
4533
  ] }) });
4092
4534
  }
4093
4535
  function useDebouncedValidation(delayMs = 500) {
4094
- const [errors, setErrors] = react.useState([]);
4095
- const timerRef = react.useRef(null);
4096
- const validate = react.useCallback(
4536
+ const [errors, setErrors] = React.useState([]);
4537
+ const timerRef = React.useRef(null);
4538
+ React.useEffect(() => {
4539
+ return () => {
4540
+ if (timerRef.current) clearTimeout(timerRef.current);
4541
+ };
4542
+ }, []);
4543
+ const validate = React.useCallback(
4097
4544
  (text) => {
4098
4545
  if (timerRef.current) {
4099
4546
  clearTimeout(timerRef.current);
@@ -4142,9 +4589,9 @@ function useDebouncedValidation(delayMs = 500) {
4142
4589
  );
4143
4590
  return { errors, validate };
4144
4591
  }
4145
- var ThemeCtx = react.createContext({});
4592
+ var ThemeCtx = React.createContext({});
4146
4593
  function useBuilderTheme() {
4147
- return react.useContext(ThemeCtx);
4594
+ return React.useContext(ThemeCtx);
4148
4595
  }
4149
4596
  function themeToCssVars(theme) {
4150
4597
  const vars = {};
@@ -4180,10 +4627,10 @@ function themeToCssVars(theme) {
4180
4627
  }
4181
4628
  function FormBuilderThemeProvider({ theme, children }) {
4182
4629
  const resolved = theme ?? {};
4183
- const cssVars = react.useMemo(() => themeToCssVars(resolved), [resolved]);
4630
+ const cssVars = React.useMemo(() => themeToCssVars(resolved), [resolved]);
4184
4631
  return /* @__PURE__ */ jsxRuntime.jsx(ThemeCtx.Provider, { value: resolved, children: /* @__PURE__ */ jsxRuntime.jsx("div", { "data-fcb-root": "", style: cssVars, className: "w-full h-full", children }) });
4185
4632
  }
4186
- var FormBuilderErrorBoundary = class extends react.Component {
4633
+ var FormBuilderErrorBoundary = class extends React.Component {
4187
4634
  constructor(props) {
4188
4635
  super(props);
4189
4636
  this.state = { hasError: false, error: null };
@@ -4215,30 +4662,30 @@ var FormBuilderErrorBoundary = class extends react.Component {
4215
4662
  };
4216
4663
  function FormBuilderCore(props) {
4217
4664
  const { initialSchema = DEFAULT_SCHEMA, onChange, onSave, height = "100vh", theme, className, toolbarExtra, questionTypes, palette, preview, templates, schemaUrl } = props;
4218
- const [viewMode, setViewMode] = react.useState("design");
4219
- const [jsonText, setJsonText] = react.useState("");
4220
- const [jsonSwitchError, setJsonSwitchError] = react.useState(null);
4221
- const [showTemplateGallery, setShowTemplateGallery] = react.useState(false);
4222
- const [saveValidationErrors, setSaveValidationErrors] = react.useState(null);
4223
- const [schemaUrlLoading, setSchemaUrlLoading] = react.useState(!!schemaUrl);
4224
- const [schemaUrlError, setSchemaUrlError] = react.useState(null);
4665
+ const [viewMode, setViewMode] = React.useState("design");
4666
+ const [jsonText, setJsonText] = React.useState("");
4667
+ const [jsonSwitchError, setJsonSwitchError] = React.useState(null);
4668
+ const [showTemplateGallery, setShowTemplateGallery] = React.useState(false);
4669
+ const [saveValidationErrors, setSaveValidationErrors] = React.useState(null);
4670
+ const [schemaUrlLoading, setSchemaUrlLoading] = React.useState(!!schemaUrl);
4671
+ const [schemaUrlError, setSchemaUrlError] = React.useState(null);
4225
4672
  const { errors: jsonErrors, validate: validateJson } = useDebouncedValidation(400);
4226
4673
  const mergedQuestionTypes = questionTypes ? { ...QUESTION_TYPE_INFO, ...questionTypes } : QUESTION_TYPE_INFO;
4227
4674
  const builderState = useBuilderState(initialSchema);
4228
4675
  const dragDrop = useDragDrop(builderState);
4229
- const fileInputRef = react.useRef(null);
4230
- const [mobilePanel, setMobilePanel] = react.useState("none");
4231
- react.useEffect(() => {
4676
+ const fileInputRef = React.useRef(null);
4677
+ const [mobilePanel, setMobilePanel] = React.useState("none");
4678
+ React.useEffect(() => {
4232
4679
  if (builderState.selectedItem && window.innerWidth < 768) {
4233
4680
  setMobilePanel("properties");
4234
4681
  }
4235
4682
  }, [builderState.selectedItem]);
4236
- react.useEffect(() => {
4683
+ React.useEffect(() => {
4237
4684
  if (!dragDrop.activeDragItem && mobilePanel === "palette") {
4238
4685
  setMobilePanel("none");
4239
4686
  }
4240
4687
  }, [dragDrop.activeDragItem]);
4241
- react.useEffect(() => {
4688
+ React.useEffect(() => {
4242
4689
  if (!schemaUrl) return;
4243
4690
  let cancelled = false;
4244
4691
  setSchemaUrlLoading(true);
@@ -4268,12 +4715,12 @@ function FormBuilderCore(props) {
4268
4715
  cancelled = true;
4269
4716
  };
4270
4717
  }, [schemaUrl]);
4271
- react.useEffect(() => {
4718
+ React.useEffect(() => {
4272
4719
  if (onChange && builderState.isDirty) {
4273
4720
  onChange(builderState.schema);
4274
4721
  }
4275
4722
  }, [builderState.schema, builderState.isDirty, onChange]);
4276
- const handleSave = react.useCallback(() => {
4723
+ const handleSave = React.useCallback(() => {
4277
4724
  if (!onSave) return;
4278
4725
  try {
4279
4726
  fieldcraftCore.validateSchema(builderState.schema);
@@ -4288,7 +4735,7 @@ function FormBuilderCore(props) {
4288
4735
  }
4289
4736
  }
4290
4737
  }, [onSave, builderState]);
4291
- const handleExport = react.useCallback(() => {
4738
+ const handleExport = React.useCallback(() => {
4292
4739
  const json = JSON.stringify(builderState.schema, null, 2);
4293
4740
  const blob = new Blob([json], { type: "application/json" });
4294
4741
  const url = URL.createObjectURL(blob);
@@ -4298,10 +4745,10 @@ function FormBuilderCore(props) {
4298
4745
  a.click();
4299
4746
  URL.revokeObjectURL(url);
4300
4747
  }, [builderState.schema]);
4301
- const handleImport = react.useCallback(() => {
4748
+ const handleImport = React.useCallback(() => {
4302
4749
  fileInputRef.current?.click();
4303
4750
  }, []);
4304
- const handleFileChange = react.useCallback(
4751
+ const handleFileChange = React.useCallback(
4305
4752
  (e) => {
4306
4753
  const file = e.target.files?.[0];
4307
4754
  if (!file) return;
@@ -4328,7 +4775,7 @@ ${details}`);
4328
4775
  },
4329
4776
  [builderState]
4330
4777
  );
4331
- const handleViewModeChange = react.useCallback(
4778
+ const handleViewModeChange = React.useCallback(
4332
4779
  (newMode) => {
4333
4780
  setJsonSwitchError(null);
4334
4781
  if (viewMode === "json" && newMode !== "json") {
@@ -4354,7 +4801,7 @@ ${details}`);
4354
4801
  },
4355
4802
  [viewMode, jsonText, builderState]
4356
4803
  );
4357
- const handleKeyDown = react.useCallback(
4804
+ const handleKeyDown = React.useCallback(
4358
4805
  (e) => {
4359
4806
  const mod = e.metaKey || e.ctrlKey;
4360
4807
  const tag = e.target.tagName;
@@ -4843,6 +5290,58 @@ function FormBuilderInner(props) {
4843
5290
  // src/form-builder/components/FormBuilderGated.tsx
4844
5291
  var FormBuilder = requireLicense(FormBuilderInner, "FormBuilder");
4845
5292
 
5293
+ // src/form-builder/theme/presets.ts
5294
+ var squaredrDarkPreset = {
5295
+ background: "#0F1A1F",
5296
+ foreground: "#E8EFF1",
5297
+ card: "#16242A",
5298
+ primary: "#63BDB4",
5299
+ primaryForeground: "#0F1A1F",
5300
+ secondary: "#182F31",
5301
+ secondaryForeground: "#E8EFF1",
5302
+ muted: "#182F31",
5303
+ mutedForeground: "#8CA1A9",
5304
+ accent: "#182F31",
5305
+ accentForeground: "#E8EFF1",
5306
+ destructive: "#E08072",
5307
+ destructiveForeground: "#0F1A1F",
5308
+ border: "#2A3B42",
5309
+ input: "#2A3B42",
5310
+ ring: "#63BDB4",
5311
+ radius: "0px",
5312
+ surface: "#16242A",
5313
+ surfaceHover: "#182F31",
5314
+ canvas: "#0F1A1F",
5315
+ panel: "#16242A",
5316
+ borderStrong: "#2F4F4C",
5317
+ textDim: "#5E7680"
5318
+ };
5319
+ var cleanPreset = {
5320
+ background: "#F4F7F8",
5321
+ foreground: "#12222A",
5322
+ card: "#FFFFFF",
5323
+ primary: "#1F6B6E",
5324
+ primaryForeground: "#FFFFFF",
5325
+ secondary: "#EDF3F2",
5326
+ secondaryForeground: "#12222A",
5327
+ muted: "#EDF3F2",
5328
+ mutedForeground: "#6A7B85",
5329
+ accent: "#EDF3F2",
5330
+ accentForeground: "#12222A",
5331
+ destructive: "#B04A3C",
5332
+ destructiveForeground: "#FFFFFF",
5333
+ border: "#DCE4E8",
5334
+ input: "#DCE4E8",
5335
+ ring: "#1F6B6E",
5336
+ radius: "0px",
5337
+ surface: "#FAFCFC",
5338
+ surfaceHover: "#EDF3F2",
5339
+ canvas: "#F4F7F8",
5340
+ panel: "#FFFFFF",
5341
+ borderStrong: "#B9D1CF",
5342
+ textDim: "#6A7B85"
5343
+ };
5344
+
4846
5345
  exports.DEFAULT_PALETTE = DEFAULT_PALETTE;
4847
5346
  exports.DEFAULT_SCHEMA = DEFAULT_SCHEMA;
4848
5347
  exports.FormBuilder = FormBuilder;
@@ -4851,6 +5350,7 @@ exports.QUESTION_TYPE_INFO = QUESTION_TYPE_INFO;
4851
5350
  exports.addOption = addOption;
4852
5351
  exports.addQuestion = addQuestion;
4853
5352
  exports.addSection = addSection;
5353
+ exports.cleanPreset = cleanPreset;
4854
5354
  exports.cn = cn;
4855
5355
  exports.duplicateQuestion = duplicateQuestion;
4856
5356
  exports.duplicateSection = duplicateSection;
@@ -4866,6 +5366,7 @@ exports.moveSection = moveSection;
4866
5366
  exports.removeOption = removeOption;
4867
5367
  exports.removeQuestion = removeQuestion;
4868
5368
  exports.removeSection = removeSection;
5369
+ exports.squaredrDarkPreset = squaredrDarkPreset;
4869
5370
  exports.updateOption = updateOption;
4870
5371
  exports.updateQuestion = updateQuestion;
4871
5372
  exports.updateSection = updateSection;