@squaredr/fieldcraft-pro 1.6.4 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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,31 +8,32 @@ 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
 
14
- // ../license/dist/index.mjs
15
- var PRO_FEATURES = [
16
- "SchemaEditor",
17
- "ResponseViewer",
18
- "ThemeEditor",
19
- "FormBuilder",
20
- "ApiManager",
21
- "Analytics"
22
- ];
23
- var ALL_FEATURES = [
24
- ...PRO_FEATURES,
25
- "Telehealth"
26
- ];
27
- var TIER_FEATURES = {
28
- starter: ["SchemaEditor", "ResponseViewer"],
29
- pro: PRO_FEATURES,
30
- business: ALL_FEATURES,
31
- enterprise: ALL_FEATURES
32
- };
33
- function tierHasFeature(tier, featureName) {
34
- return TIER_FEATURES[tier]?.includes(featureName) ?? false;
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);
35
31
  }
32
+
33
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
34
+ var SelectPrimitive__namespace = /*#__PURE__*/_interopNamespace(SelectPrimitive);
35
+
36
+ // ../license/dist/index.mjs
36
37
  var DEV_HOSTNAMES = /* @__PURE__ */ new Set([
37
38
  "localhost",
38
39
  "127.0.0.1",
@@ -104,10 +105,11 @@ function isProductionEnvironment() {
104
105
  }
105
106
  return false;
106
107
  }
107
- var defaultContext = { status: "validating", tier: null };
108
- var LicenseCtx = react.createContext(defaultContext);
108
+ typeof process !== "undefined" && process.env?.NEXT_PUBLIC_FCPRO_PING_URL || "https://fieldcraft.dev/api/license/ping";
109
+ var defaultContext = { status: "validating" };
110
+ var LicenseCtx = React.createContext(defaultContext);
109
111
  function useLicense() {
110
- return react.useContext(LicenseCtx);
112
+ return React.useContext(LicenseCtx);
111
113
  }
112
114
  function UnlicensedOverlay({ featureName, reason, children }) {
113
115
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", minHeight: "200px" }, children: [
@@ -304,7 +306,7 @@ function UnlicensedOverlay({ featureName, reason, children }) {
304
306
  }
305
307
  function requireLicense(Component3, featureName) {
306
308
  function LicenseGated(props) {
307
- const { status, tier } = useLicense();
309
+ const { status } = useLicense();
308
310
  const isProduction = isProductionEnvironment();
309
311
  if (!isProduction) {
310
312
  return /* @__PURE__ */ jsxRuntime.jsx(Component3, { ...props });
@@ -312,8 +314,7 @@ function requireLicense(Component3, featureName) {
312
314
  if (status === "validating") {
313
315
  return null;
314
316
  }
315
- const isLicensed = status === "valid" && tier != null && tierHasFeature(tier, featureName);
316
- if (isLicensed) {
317
+ if (status === "valid") {
317
318
  return /* @__PURE__ */ jsxRuntime.jsx(Component3, { ...props });
318
319
  }
319
320
  let reason = "A valid license is required for production use.";
@@ -325,8 +326,6 @@ function requireLicense(Component3, featureName) {
325
326
  reason = "This license key has been revoked. Please contact support or purchase a new license.";
326
327
  } else if (status === "domain_mismatch") {
327
328
  reason = "This license key is registered to a different domain. Each key can only be used on one production domain. Please purchase a new license for this domain.";
328
- } else if (!tier || !tierHasFeature(tier, featureName)) {
329
- reason = "Your license does not include this feature. Please upgrade your plan.";
330
329
  }
331
330
  return /* @__PURE__ */ jsxRuntime.jsx(UnlicensedOverlay, { featureName, reason, children: /* @__PURE__ */ jsxRuntime.jsx(Component3, { ...props }) });
332
331
  }
@@ -335,38 +334,41 @@ function requireLicense(Component3, featureName) {
335
334
  }
336
335
  var MAX_HISTORY = 50;
337
336
  function useUndoRedo(currentSchema, setSchema) {
338
- const historyRef = react.useRef([currentSchema]);
339
- const [currentIndex, setCurrentIndex] = react.useState(0);
337
+ const historyRef = React.useRef([currentSchema]);
338
+ const [currentIndex, setCurrentIndex] = React.useState(0);
339
+ const currentIndexRef = React.useRef(currentIndex);
340
+ currentIndexRef.current = currentIndex;
340
341
  const canUndo = currentIndex > 0;
341
342
  const canRedo = currentIndex < historyRef.current.length - 1;
342
- const push = react.useCallback(
343
+ const push = React.useCallback(
343
344
  (schema) => {
344
- historyRef.current = historyRef.current.slice(0, currentIndex + 1);
345
+ const idx = currentIndexRef.current;
346
+ historyRef.current = historyRef.current.slice(0, idx + 1);
345
347
  historyRef.current.push(schema);
346
348
  if (historyRef.current.length > MAX_HISTORY) {
347
349
  historyRef.current.shift();
348
350
  setCurrentIndex(historyRef.current.length - 1);
349
351
  } else {
350
- setCurrentIndex((prev) => prev + 1);
352
+ setCurrentIndex(idx + 1);
351
353
  }
352
354
  },
353
- [currentIndex]
355
+ []
354
356
  );
355
- const undo = react.useCallback(() => {
357
+ const undo = React.useCallback(() => {
356
358
  if (currentIndex > 0) {
357
359
  const newIndex = currentIndex - 1;
358
360
  setCurrentIndex(newIndex);
359
361
  setSchema(historyRef.current[newIndex]);
360
362
  }
361
363
  }, [currentIndex, setSchema]);
362
- const redo = react.useCallback(() => {
364
+ const redo = React.useCallback(() => {
363
365
  if (currentIndex < historyRef.current.length - 1) {
364
366
  const newIndex = currentIndex + 1;
365
367
  setCurrentIndex(newIndex);
366
368
  setSchema(historyRef.current[newIndex]);
367
369
  }
368
370
  }, [currentIndex, setSchema]);
369
- const clear = react.useCallback(() => {
371
+ const clear = React.useCallback(() => {
370
372
  historyRef.current = [currentSchema];
371
373
  setCurrentIndex(0);
372
374
  }, [currentSchema]);
@@ -595,16 +597,16 @@ function findSection(schema, sectionId) {
595
597
 
596
598
  // src/form-builder/hooks/use-builder-state.ts
597
599
  function useBuilderState(initialSchema) {
598
- const [schema, setSchema] = react.useState(initialSchema);
599
- const [selectedItem, setSelectedItem] = react.useState(null);
600
- const [isDirty, setIsDirty] = react.useState(false);
601
- const schemaRef = react.useRef(schema);
600
+ const [schema, setSchema] = React.useState(initialSchema);
601
+ const [selectedItem, setSelectedItem] = React.useState(null);
602
+ const [isDirty, setIsDirty] = React.useState(false);
603
+ const schemaRef = React.useRef(schema);
602
604
  schemaRef.current = schema;
603
605
  const undoRedo = useUndoRedo(schema, (newSchema) => {
604
606
  setSchema(newSchema);
605
607
  setIsDirty(true);
606
608
  });
607
- const updateSchema = react.useCallback(
609
+ const updateSchema = React.useCallback(
608
610
  (newSchema) => {
609
611
  setSchema(newSchema);
610
612
  undoRedo.push(newSchema);
@@ -612,20 +614,20 @@ function useBuilderState(initialSchema) {
612
614
  },
613
615
  [undoRedo]
614
616
  );
615
- const applyMutation = react.useCallback(
617
+ const applyMutation = React.useCallback(
616
618
  (mutate) => {
617
619
  const result = mutate(schemaRef.current);
618
620
  updateSchema(result);
619
621
  },
620
622
  [updateSchema]
621
623
  );
622
- const addSection2 = react.useCallback(
624
+ const addSection2 = React.useCallback(
623
625
  (section, index) => {
624
626
  applyMutation((s) => addSection(s, section, index));
625
627
  },
626
628
  [applyMutation]
627
629
  );
628
- const removeSection2 = react.useCallback(
630
+ const removeSection2 = React.useCallback(
629
631
  (sectionId) => {
630
632
  applyMutation((s) => removeSection(s, sectionId));
631
633
  setSelectedItem((prev) => {
@@ -635,31 +637,31 @@ function useBuilderState(initialSchema) {
635
637
  },
636
638
  [applyMutation]
637
639
  );
638
- const updateSection2 = react.useCallback(
640
+ const updateSection2 = React.useCallback(
639
641
  (sectionId, updates) => {
640
642
  applyMutation((s) => updateSection(s, sectionId, updates));
641
643
  },
642
644
  [applyMutation]
643
645
  );
644
- const moveSection2 = react.useCallback(
646
+ const moveSection2 = React.useCallback(
645
647
  (sectionId, newIndex) => {
646
648
  applyMutation((s) => moveSection(s, sectionId, newIndex));
647
649
  },
648
650
  [applyMutation]
649
651
  );
650
- const duplicateSection2 = react.useCallback(
652
+ const duplicateSection2 = React.useCallback(
651
653
  (sectionId) => {
652
654
  applyMutation((s) => duplicateSection(s, sectionId));
653
655
  },
654
656
  [applyMutation]
655
657
  );
656
- const addQuestion2 = react.useCallback(
658
+ const addQuestion2 = React.useCallback(
657
659
  (sectionId, question, index) => {
658
660
  applyMutation((s) => addQuestion(s, sectionId, question, index));
659
661
  },
660
662
  [applyMutation]
661
663
  );
662
- const removeQuestion2 = react.useCallback(
664
+ const removeQuestion2 = React.useCallback(
663
665
  (sectionId, questionId) => {
664
666
  applyMutation((s) => removeQuestion(s, sectionId, questionId));
665
667
  setSelectedItem((prev) => {
@@ -671,34 +673,34 @@ function useBuilderState(initialSchema) {
671
673
  },
672
674
  [applyMutation]
673
675
  );
674
- const updateQuestion2 = react.useCallback(
676
+ const updateQuestion2 = React.useCallback(
675
677
  (sectionId, questionId, updates) => {
676
678
  applyMutation((s) => updateQuestion(s, sectionId, questionId, updates));
677
679
  },
678
680
  [applyMutation]
679
681
  );
680
- const moveQuestion2 = react.useCallback(
682
+ const moveQuestion2 = React.useCallback(
681
683
  (sectionId, questionId, targetSectionId, newIndex) => {
682
684
  applyMutation((s) => moveQuestion(s, sectionId, questionId, targetSectionId, newIndex));
683
685
  },
684
686
  [applyMutation]
685
687
  );
686
- const duplicateQuestion2 = react.useCallback(
688
+ const duplicateQuestion2 = React.useCallback(
687
689
  (sectionId, questionId) => {
688
690
  applyMutation((s) => duplicateQuestion(s, sectionId, questionId));
689
691
  },
690
692
  [applyMutation]
691
693
  );
692
- const selectQuestion = react.useCallback((sectionId, questionId) => {
694
+ const selectQuestion = React.useCallback((sectionId, questionId) => {
693
695
  setSelectedItem({ type: "question", sectionId, questionId });
694
696
  }, []);
695
- const selectSection = react.useCallback((sectionId) => {
697
+ const selectSection = React.useCallback((sectionId) => {
696
698
  setSelectedItem({ type: "section", sectionId });
697
699
  }, []);
698
- const clearSelection = react.useCallback(() => {
700
+ const clearSelection = React.useCallback(() => {
699
701
  setSelectedItem(null);
700
702
  }, []);
701
- const resetSchema = react.useCallback(
703
+ const resetSchema = React.useCallback(
702
704
  (newSchema) => {
703
705
  setSchema(newSchema);
704
706
  undoRedo.clear();
@@ -707,7 +709,7 @@ function useBuilderState(initialSchema) {
707
709
  },
708
710
  [undoRedo]
709
711
  );
710
- const markClean = react.useCallback(() => {
712
+ const markClean = React.useCallback(() => {
711
713
  setIsDirty(false);
712
714
  }, []);
713
715
  return {
@@ -968,7 +970,7 @@ var QUESTION_TYPE_INFO = {
968
970
  category: "advanced",
969
971
  icon: "ListPlus",
970
972
  description: "Repeatable group of fields",
971
- defaultConfig: { type: "repeater", fields: [], minItems: 1, maxItems: 10 }
973
+ defaultConfig: { type: "repeater", fields: [], minEntries: 1, maxEntries: 10 }
972
974
  },
973
975
  likert: {
974
976
  type: "likert",
@@ -979,13 +981,7 @@ var QUESTION_TYPE_INFO = {
979
981
  requiresOptions: true,
980
982
  defaultConfig: {
981
983
  type: "likert",
982
- scale: [
983
- { label: "Strongly Disagree", value: "1" },
984
- { label: "Disagree", value: "2" },
985
- { label: "Neutral", value: "3" },
986
- { label: "Agree", value: "4" },
987
- { label: "Strongly Agree", value: "5" }
988
- ]
984
+ labels: ["Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"]
989
985
  }
990
986
  },
991
987
  scoring: {
@@ -1038,7 +1034,7 @@ var QUESTION_TYPE_INFO = {
1038
1034
  category: "advanced",
1039
1035
  icon: "CreditCard",
1040
1036
  description: "Collect payment via Stripe",
1041
- defaultConfig: { type: "payment", provider: "stripe", publicKey: "", currency: "USD" }
1037
+ defaultConfig: { type: "payment", provider: "stripe", publicKey: "", currency: "USD", serverUrl: "" }
1042
1038
  },
1043
1039
  // ── Structural ──
1044
1040
  section_header: {
@@ -1185,7 +1181,7 @@ var DEFAULT_PALETTE = [
1185
1181
 
1186
1182
  // src/form-builder/hooks/use-drag-drop.ts
1187
1183
  function useDragDrop(builderState) {
1188
- const [activeDragItem, setActiveDragItem] = react.useState(null);
1184
+ const [activeDragItem, setActiveDragItem] = React.useState(null);
1189
1185
  const sensors = core.useSensors(
1190
1186
  core.useSensor(core.MouseSensor, {
1191
1187
  activationConstraint: {
@@ -1235,11 +1231,11 @@ function useDragDrop(builderState) {
1235
1231
  }
1236
1232
  return null;
1237
1233
  };
1238
- const handleDragStart = react.useCallback((event) => {
1234
+ const handleDragStart = React.useCallback((event) => {
1239
1235
  const item = parseDragItem(event.active);
1240
1236
  setActiveDragItem(item);
1241
1237
  }, []);
1242
- const handleDragCancel = react.useCallback(() => {
1238
+ const handleDragCancel = React.useCallback(() => {
1243
1239
  setActiveDragItem(null);
1244
1240
  }, []);
1245
1241
  const handleDragEnd = (event) => {
@@ -1409,9 +1405,9 @@ function PaletteItem({ questionType, typeInfo }) {
1409
1405
  );
1410
1406
  }
1411
1407
  function QuestionPalette({ questionTypes, palette }) {
1412
- const [collapsed, setCollapsed] = react.useState({});
1413
- const [search, setSearch] = react.useState("");
1414
- const mergedPalette = react.useMemo(
1408
+ const [collapsed, setCollapsed] = React.useState({});
1409
+ const [search, setSearch] = React.useState("");
1410
+ const mergedPalette = React.useMemo(
1415
1411
  () => palette ? [...DEFAULT_PALETTE, ...palette] : DEFAULT_PALETTE,
1416
1412
  [palette]
1417
1413
  );
@@ -1492,13 +1488,13 @@ function QuestionBlock({
1492
1488
  }) {
1493
1489
  const typeInfo = QUESTION_TYPE_INFO[question.type];
1494
1490
  const IconComponent = typeInfo ? getIcon(typeInfo.icon) : null;
1495
- const [isEditing, setIsEditing] = react.useState(false);
1496
- const [editValue, setEditValue] = react.useState(question.label);
1497
- const inputRef = react.useRef(null);
1498
- react.useEffect(() => {
1491
+ const [isEditing, setIsEditing] = React.useState(false);
1492
+ const [editValue, setEditValue] = React.useState(question.label);
1493
+ const inputRef = React.useRef(null);
1494
+ React.useEffect(() => {
1499
1495
  if (!isEditing) setEditValue(question.label);
1500
1496
  }, [question.label, isEditing]);
1501
- react.useEffect(() => {
1497
+ React.useEffect(() => {
1502
1498
  if (isEditing && inputRef.current) {
1503
1499
  inputRef.current.focus();
1504
1500
  inputRef.current.select();
@@ -1655,7 +1651,7 @@ function ConfirmDialog({ open, title, message, onConfirm, onCancel }) {
1655
1651
  );
1656
1652
  }
1657
1653
  function SectionBlock({ section, builderState }) {
1658
- const [confirmDelete, setConfirmDelete] = react.useState(false);
1654
+ const [confirmDelete, setConfirmDelete] = React.useState(false);
1659
1655
  const { setNodeRef } = core.useDroppable({
1660
1656
  id: `section-end-${section.id}`,
1661
1657
  data: { type: "section", sectionId: section.id, index: section.questions.length }
@@ -1836,30 +1832,71 @@ function FormCanvas({ builderState }) {
1836
1832
  ] })
1837
1833
  ] }) });
1838
1834
  }
1839
- var NativeSelect = react.forwardRef(
1840
- ({ className, wrapperClassName, children, ...props }, ref) => {
1841
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative", wrapperClassName), children: [
1835
+ var Select = SelectPrimitive__namespace.Root;
1836
+ var SelectTrigger = React__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
1837
+ SelectPrimitive__namespace.Trigger,
1838
+ {
1839
+ ref,
1840
+ className: cn(
1841
+ "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",
1842
+ className
1843
+ ),
1844
+ ...props,
1845
+ children: [
1846
+ children,
1847
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Icon, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "size-4 text-muted-foreground" }) })
1848
+ ]
1849
+ }
1850
+ ));
1851
+ SelectTrigger.displayName = "SelectTrigger";
1852
+ var SelectContent = React__namespace.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
1853
+ SelectPrimitive__namespace.Content,
1854
+ {
1855
+ ref,
1856
+ className: cn(
1857
+ "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",
1858
+ 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",
1859
+ className
1860
+ ),
1861
+ position,
1862
+ ...props,
1863
+ children: [
1864
+ /* @__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" }) }),
1842
1865
  /* @__PURE__ */ jsxRuntime.jsx(
1843
- "select",
1866
+ SelectPrimitive__namespace.Viewport,
1844
1867
  {
1845
- ref,
1846
1868
  className: cn(
1847
- "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",
1848
- className
1869
+ "p-1",
1870
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
1849
1871
  ),
1850
- ...props,
1851
1872
  children
1852
1873
  }
1853
1874
  ),
1854
- /* @__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" })
1855
- ] });
1875
+ /* @__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" }) })
1876
+ ]
1856
1877
  }
1857
- );
1858
- NativeSelect.displayName = "NativeSelect";
1878
+ ) }));
1879
+ SelectContent.displayName = "SelectContent";
1880
+ var SelectItem = React__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
1881
+ SelectPrimitive__namespace.Item,
1882
+ {
1883
+ ref,
1884
+ className: cn(
1885
+ "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",
1886
+ className
1887
+ ),
1888
+ ...props,
1889
+ children: [
1890
+ /* @__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" }) }) }),
1891
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ItemText, { children })
1892
+ ]
1893
+ }
1894
+ ));
1895
+ SelectItem.displayName = "SelectItem";
1859
1896
  function useConfigUpdater(question, onUpdate) {
1860
- return (field, value) => {
1897
+ return (updates) => {
1861
1898
  const current = question.config ?? {};
1862
- onUpdate({ config: { ...current, type: question.type, [field]: value } });
1899
+ onUpdate({ config: { ...current, type: question.type, ...updates } });
1863
1900
  };
1864
1901
  }
1865
1902
  function QuestionConfigEditor({ question, onUpdate }) {
@@ -1869,226 +1906,274 @@ function QuestionConfigEditor({ question, onUpdate }) {
1869
1906
  // ── Text ──
1870
1907
  case "short_text":
1871
1908
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Text Settings", children: [
1872
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "255", onChange: (v) => updateConfig("maxLength", v) }),
1873
- /* @__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) }),
1874
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig("prefix", v) }),
1875
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. USD", onChange: (v) => updateConfig("suffix", v) })
1909
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "255", onChange: (v) => updateConfig({ maxLength: v }) }),
1910
+ /* @__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 }) }),
1911
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig({ prefix: v }) }),
1912
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. USD", onChange: (v) => updateConfig({ suffix: v }) })
1876
1913
  ] });
1877
1914
  case "long_text":
1878
1915
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Text Settings", children: [
1879
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "No limit", onChange: (v) => updateConfig("maxLength", v) }),
1880
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Rows", value: config.rows, placeholder: "4", onChange: (v) => updateConfig("rows", v) }),
1881
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Character Count", checked: !!config.showCharCount, onChange: (v) => updateConfig("showCharCount", v) })
1916
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "No limit", onChange: (v) => updateConfig({ maxLength: v }) }),
1917
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Rows", value: config.rows, placeholder: "4", onChange: (v) => updateConfig({ rows: v }) }),
1918
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Character Count", checked: !!config.showCharCount, onChange: (v) => updateConfig({ showCharCount: v }) })
1882
1919
  ] });
1883
1920
  case "legal_name":
1884
1921
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Name Fields", children: [
1885
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Middle Name", checked: !!config.showMiddleName, onChange: (v) => updateConfig("showMiddleName", v) }),
1886
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Suffix", checked: !!config.showSuffix, onChange: (v) => updateConfig("showSuffix", v) })
1922
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Middle Name", checked: !!config.showMiddleName, onChange: (v) => updateConfig({ showMiddleName: v }) }),
1923
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Suffix", checked: !!config.showSuffix, onChange: (v) => updateConfig({ showSuffix: v }) })
1887
1924
  ] });
1888
1925
  // ── Numeric ──
1889
1926
  case "number":
1890
1927
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Number Settings", children: [
1891
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min", value: config.min, onChange: (v) => updateConfig("min", v) }),
1892
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max", value: config.max, onChange: (v) => updateConfig("max", v) }),
1893
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig("step", v) }),
1894
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "0", onChange: (v) => updateConfig("decimalPlaces", v) }),
1895
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig("prefix", v) }),
1896
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. kg", onChange: (v) => updateConfig("suffix", v) })
1928
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min", value: config.min, onChange: (v) => updateConfig({ min: v }) }),
1929
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max", value: config.max, onChange: (v) => updateConfig({ max: v }) }),
1930
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig({ step: v }) }),
1931
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "0", onChange: (v) => updateConfig({ decimalPlaces: v }) }),
1932
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig({ prefix: v }) }),
1933
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. kg", onChange: (v) => updateConfig({ suffix: v }) })
1897
1934
  ] });
1898
1935
  case "slider":
1899
1936
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Slider Settings", children: [
1900
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min", value: config.min, placeholder: "0", onChange: (v) => updateConfig("min", v) }),
1901
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max", value: config.max, placeholder: "100", onChange: (v) => updateConfig("max", v) }),
1902
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig("step", v) }),
1903
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Value", checked: !!config.showValue, onChange: (v) => updateConfig("showValue", v) }),
1904
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig("minLabel", v) }),
1905
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig("maxLabel", v) })
1937
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min", value: config.min, placeholder: "0", onChange: (v) => updateConfig({ min: v }) }),
1938
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max", value: config.max, placeholder: "100", onChange: (v) => updateConfig({ max: v }) }),
1939
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig({ step: v }) }),
1940
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Value", checked: !!config.showValue, onChange: (v) => updateConfig({ showValue: v }) }),
1941
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig({ minLabel: v }) }),
1942
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig({ maxLabel: v }) })
1906
1943
  ] });
1907
1944
  case "rating":
1908
1945
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Rating Settings", children: [
1909
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Stars", value: config.max, placeholder: "5", onChange: (v) => updateConfig("max", v) }),
1910
- /* @__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) }),
1911
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Labels", checked: !!config.showLabels, onChange: (v) => updateConfig("showLabels", v) })
1946
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Stars", value: config.max, placeholder: "5", onChange: (v) => updateConfig({ max: v }) }),
1947
+ /* @__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 }) }),
1948
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Labels", checked: !!config.showLabels, onChange: (v) => updateConfig({ showLabels: v }) })
1912
1949
  ] });
1913
1950
  case "nps":
1914
1951
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "NPS Settings", children: [
1915
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Low Label", value: config.lowLabel ?? "Not likely", onChange: (v) => updateConfig("lowLabel", v) }),
1916
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "High Label", value: config.highLabel ?? "Very likely", onChange: (v) => updateConfig("highLabel", v) })
1952
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Low Label", value: config.lowLabel ?? "Not likely", onChange: (v) => updateConfig({ lowLabel: v }) }),
1953
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "High Label", value: config.highLabel ?? "Very likely", onChange: (v) => updateConfig({ highLabel: v }) })
1917
1954
  ] });
1918
1955
  case "opinion_scale":
1919
1956
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Scale Settings", children: [
1920
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min", value: config.min, placeholder: "1", onChange: (v) => updateConfig("min", v) }),
1921
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max", value: config.max, placeholder: "5", onChange: (v) => updateConfig("max", v) }),
1922
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig("step", v) }),
1923
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig("minLabel", v) }),
1924
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig("maxLabel", v) })
1957
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min", value: config.min, placeholder: "1", onChange: (v) => updateConfig({ min: v }) }),
1958
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max", value: config.max, placeholder: "5", onChange: (v) => updateConfig({ max: v }) }),
1959
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig({ step: v }) }),
1960
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig({ minLabel: v }) }),
1961
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig({ maxLabel: v }) })
1925
1962
  ] });
1926
1963
  case "likert":
1927
- 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) }) });
1964
+ 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 }) }) });
1928
1965
  // ── Selection ──
1929
1966
  case "single_select":
1930
1967
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Select Settings", children: [
1931
- /* @__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) }),
1932
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig("allowOther", v) }),
1933
- !!config.allowOther && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig("otherLabel", v) })
1968
+ /* @__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 }) }),
1969
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => v ? updateConfig({ allowOther: true }) : updateConfig({ allowOther: false, otherLabel: void 0 }) }),
1970
+ !!config.allowOther && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig({ otherLabel: v }) })
1934
1971
  ] });
1935
1972
  case "multi_select":
1936
1973
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Multi-Select Settings", children: [
1937
- /* @__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) }),
1938
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min Selections", value: config.minSelections, onChange: (v) => updateConfig("minSelections", v) }),
1939
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Selections", value: config.maxSelections, onChange: (v) => updateConfig("maxSelections", v) }),
1940
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig("allowOther", v) }),
1941
- !!config.allowOther && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig("otherLabel", v) })
1974
+ /* @__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 }) }),
1975
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min Selections", value: config.minSelections, onChange: (v) => updateConfig({ minSelections: v }) }),
1976
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Selections", value: config.maxSelections, onChange: (v) => updateConfig({ maxSelections: v }) }),
1977
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => v ? updateConfig({ allowOther: true }) : updateConfig({ allowOther: false, otherLabel: void 0 }) }),
1978
+ !!config.allowOther && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig({ otherLabel: v }) })
1942
1979
  ] });
1943
1980
  case "dropdown":
1944
1981
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Dropdown Settings", children: [
1945
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Searchable", checked: !!config.searchable, onChange: (v) => updateConfig("searchable", v) }),
1946
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig("allowOther", v) }),
1947
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Multiple", checked: !!config.multiple, onChange: (v) => updateConfig("multiple", v) })
1982
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Searchable", checked: !!config.searchable, onChange: (v) => updateConfig({ searchable: v }) }),
1983
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig({ allowOther: v }) }),
1984
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Multiple", checked: !!config.multiple, onChange: (v) => updateConfig({ multiple: v }) })
1948
1985
  ] });
1949
1986
  case "boolean":
1950
1987
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Yes/No Settings", children: [
1951
- /* @__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) }),
1952
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "True Label", value: config.trueLabel ?? "Yes", onChange: (v) => updateConfig("trueLabel", v) }),
1953
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "False Label", value: config.falseLabel ?? "No", onChange: (v) => updateConfig("falseLabel", v) })
1988
+ /* @__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 }) }),
1989
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "True Label", value: config.trueLabel ?? "Yes", onChange: (v) => updateConfig({ trueLabel: v }) }),
1990
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "False Label", value: config.falseLabel ?? "No", onChange: (v) => updateConfig({ falseLabel: v }) })
1954
1991
  ] });
1955
1992
  case "country_select":
1956
1993
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Country Settings", children: [
1957
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Flags", checked: config.showFlags !== false, onChange: (v) => updateConfig("showFlags", v) }),
1958
- /* @__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) }),
1959
- /* @__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) })
1994
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Flags", checked: config.showFlags !== false, onChange: (v) => updateConfig({ showFlags: v }) }),
1995
+ /* @__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 }) }),
1996
+ /* @__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 }) })
1960
1997
  ] });
1961
1998
  // ── Date/Time ──
1962
1999
  case "date":
1963
2000
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Date Settings", children: [
1964
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig("minDate", v) }),
1965
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig("maxDate", v) }),
1966
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Disable Past Dates", checked: !!config.disablePast, onChange: (v) => updateConfig("disablePast", v) }),
1967
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Disable Future Dates", checked: !!config.disableFuture, onChange: (v) => updateConfig("disableFuture", v) }),
1968
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Format", value: config.format, placeholder: "e.g. MM/DD/YYYY", onChange: (v) => updateConfig("format", v) })
2001
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ minDate: v }) }),
2002
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ maxDate: v }) }),
2003
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Disable Past Dates", checked: !!config.disablePast, onChange: (v) => updateConfig({ disablePast: v }) }),
2004
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Disable Future Dates", checked: !!config.disableFuture, onChange: (v) => updateConfig({ disableFuture: v }) }),
2005
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Format", value: config.format, placeholder: "e.g. MM/DD/YYYY", onChange: (v) => updateConfig({ format: v }) })
1969
2006
  ] });
1970
2007
  case "time":
1971
2008
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Time Settings", children: [
1972
- /* @__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) }),
1973
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Minute Step", value: config.minuteStep, placeholder: "1", onChange: (v) => updateConfig("minuteStep", v) })
2009
+ /* @__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 }) }),
2010
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Minute Step", value: config.minuteStep, placeholder: "1", onChange: (v) => updateConfig({ minuteStep: v }) })
1974
2011
  ] });
1975
2012
  case "date_range":
1976
2013
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Date Range Settings", children: [
1977
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig("minDate", v) }),
1978
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig("maxDate", v) }),
1979
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Range (days)", value: config.maxRangeDays, onChange: (v) => updateConfig("maxRangeDays", v) })
2014
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ minDate: v }) }),
2015
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ maxDate: v }) }),
2016
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Range (days)", value: config.maxRangeDays, onChange: (v) => updateConfig({ maxRangeDays: v }) })
1980
2017
  ] });
1981
- case "appointment":
2018
+ case "appointment": {
2019
+ const appointmentMode = typeof config.embedUrl === "string" ? "embed" : typeof config.slotsUrl === "string" ? "url" : "static";
1982
2020
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Appointment Settings", children: [
1983
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Duration (min)", value: config.duration ?? 30, onChange: (v) => updateConfig("duration", v) }),
1984
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Timezone", value: config.timezone, placeholder: "e.g. America/New_York", onChange: (v) => updateConfig("timezone", v) }),
1985
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Slots URL", value: config.slotsUrl, placeholder: "API endpoint for available slots", onChange: (v) => updateConfig("slotsUrl", v) })
2021
+ /* @__PURE__ */ jsxRuntime.jsx(
2022
+ SelectField,
2023
+ {
2024
+ label: "Mode",
2025
+ value: appointmentMode,
2026
+ options: [
2027
+ { label: "Static Slots", value: "static" },
2028
+ { label: "API Endpoint", value: "url" },
2029
+ { label: "Embed (Calendly / Cal.com)", value: "embed" }
2030
+ ],
2031
+ onChange: (v) => {
2032
+ if (v === "static") {
2033
+ updateConfig({ slotsUrl: void 0, embedUrl: void 0, embedProvider: void 0 });
2034
+ } else if (v === "url") {
2035
+ updateConfig({ slotsUrl: "", embedUrl: void 0, embedProvider: void 0, slots: void 0 });
2036
+ } else if (v === "embed") {
2037
+ updateConfig({ embedUrl: "", slotsUrl: void 0, slots: void 0 });
2038
+ }
2039
+ }
2040
+ }
2041
+ ),
2042
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Duration (min)", value: config.duration ?? 30, onChange: (v) => updateConfig({ duration: v }) }),
2043
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Timezone", value: config.timezone, placeholder: "e.g. America/New_York", onChange: (v) => updateConfig({ timezone: v }) }),
2044
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Timezone Field", value: config.timezoneField, placeholder: "Field ID for dynamic timezone", onChange: (v) => updateConfig({ timezoneField: v }) }),
2045
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Date Format", value: config.dateFormat, placeholder: "Locale-aware (default)", onChange: (v) => updateConfig({ dateFormat: v }) }),
2046
+ appointmentMode === "url" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Slots URL", value: config.slotsUrl, placeholder: "https://api.example.com/slots", onChange: (v) => updateConfig({ slotsUrl: v }) }),
2047
+ appointmentMode === "embed" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2048
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Embed URL", value: config.embedUrl, placeholder: "https://calendly.com/your-name/30min", onChange: (v) => updateConfig({ embedUrl: v }) }),
2049
+ /* @__PURE__ */ jsxRuntime.jsx(
2050
+ SelectField,
2051
+ {
2052
+ label: "Embed Provider",
2053
+ value: config.embedProvider ?? "custom",
2054
+ options: [
2055
+ { label: "Calendly", value: "calendly" },
2056
+ { label: "Cal.com", value: "cal_com" },
2057
+ { label: "Custom", value: "custom" }
2058
+ ],
2059
+ onChange: (v) => updateConfig({ embedProvider: v })
2060
+ }
2061
+ )
2062
+ ] }),
2063
+ appointmentMode === "static" && /* @__PURE__ */ jsxRuntime.jsx(
2064
+ AppointmentSlotsEditor,
2065
+ {
2066
+ slots: config.slots ?? [],
2067
+ onChange: (v) => updateConfig({ slots: v })
2068
+ }
2069
+ )
1986
2070
  ] });
2071
+ }
1987
2072
  // ── Media ──
1988
2073
  case "file_upload":
1989
2074
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Upload Settings", children: [
1990
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Files", value: config.maxFiles ?? 1, onChange: (v) => updateConfig("maxFiles", v) }),
1991
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb ?? 10, onChange: (v) => updateConfig("maxSizeMb", v) }),
1992
- /* @__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) }),
1993
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Upload URL", value: config.uploadUrl, placeholder: "Server upload endpoint", onChange: (v) => updateConfig("uploadUrl", v) })
2075
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Files", value: config.maxFiles ?? 1, onChange: (v) => updateConfig({ maxFiles: v }) }),
2076
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb ?? 10, onChange: (v) => updateConfig({ maxSizeMb: v }) }),
2077
+ /* @__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 }) }),
2078
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Upload URL", value: config.uploadUrl, placeholder: "Server upload endpoint", onChange: (v) => updateConfig({ uploadUrl: v }) })
1994
2079
  ] });
1995
2080
  case "signature":
1996
2081
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Signature Settings", children: [
1997
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Pen Color", value: config.penColor, placeholder: "#000000", onChange: (v) => updateConfig("penColor", v) }),
1998
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Background", value: config.backgroundColor, placeholder: "#ffffff", onChange: (v) => updateConfig("backgroundColor", v) }),
1999
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Width (px)", value: config.width, onChange: (v) => updateConfig("width", v) }),
2000
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Height (px)", value: config.height, onChange: (v) => updateConfig("height", v) })
2082
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Pen Color", value: config.penColor, placeholder: "#000000", onChange: (v) => updateConfig({ penColor: v }) }),
2083
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Background", value: config.backgroundColor, placeholder: "#ffffff", onChange: (v) => updateConfig({ backgroundColor: v }) }),
2084
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Width (px)", value: config.width, onChange: (v) => updateConfig({ width: v }) }),
2085
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Height (px)", value: config.height, onChange: (v) => updateConfig({ height: v }) })
2001
2086
  ] });
2002
2087
  case "image_capture":
2003
2088
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Camera Settings", children: [
2004
- /* @__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) }),
2005
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb, onChange: (v) => updateConfig("maxSizeMb", v) }),
2006
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Gallery", checked: config.allowGallery !== false, onChange: (v) => updateConfig("allowGallery", v) })
2089
+ /* @__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 }) }),
2090
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb, onChange: (v) => updateConfig({ maxSizeMb: v }) }),
2091
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Gallery", checked: config.allowGallery !== false, onChange: (v) => updateConfig({ allowGallery: v }) })
2007
2092
  ] });
2008
2093
  // ── Content & Visual ──
2009
2094
  case "welcome-screen":
2010
2095
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Welcome Screen", children: [
2011
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Heading", value: config.heading ?? "Welcome", onChange: (v) => updateConfig("heading", v) }),
2012
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Description", value: config.description, onChange: (v) => updateConfig("description", v) }),
2013
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Button Text", value: config.buttonText ?? "Start", onChange: (v) => updateConfig("buttonText", v) }),
2014
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig("imageUrl", v) }),
2015
- /* @__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) })
2096
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Heading", value: config.heading ?? "Welcome", onChange: (v) => updateConfig({ heading: v }) }),
2097
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Description", value: config.description, onChange: (v) => updateConfig({ description: v }) }),
2098
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Button Text", value: config.buttonText ?? "Start", onChange: (v) => updateConfig({ buttonText: v }) }),
2099
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig({ imageUrl: v }) }),
2100
+ /* @__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 }) })
2016
2101
  ] });
2017
2102
  case "thank-you-screen":
2018
2103
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Thank You Screen", children: [
2019
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Heading", value: config.heading ?? "Thank You!", onChange: (v) => updateConfig("heading", v) }),
2020
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Description", value: config.description ?? "", onChange: (v) => updateConfig("description", v) }),
2021
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig("imageUrl", v) }),
2022
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Redirect URL", value: config.redirectUrl, placeholder: "https://...", onChange: (v) => updateConfig("redirectUrl", v) }),
2023
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Redirect Delay (s)", value: config.redirectDelay, placeholder: "0", onChange: (v) => updateConfig("redirectDelay", v) }),
2024
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Response Summary", checked: !!config.showSummary, onChange: (v) => updateConfig("showSummary", v) })
2104
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Heading", value: config.heading ?? "Thank You!", onChange: (v) => updateConfig({ heading: v }) }),
2105
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Description", value: config.description ?? "", onChange: (v) => updateConfig({ description: v }) }),
2106
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig({ imageUrl: v }) }),
2107
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Redirect URL", value: config.redirectUrl, placeholder: "https://...", onChange: (v) => updateConfig({ redirectUrl: v }) }),
2108
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Redirect Delay (s)", value: config.redirectDelay, placeholder: "0", onChange: (v) => updateConfig({ redirectDelay: v }) }),
2109
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Response Summary", checked: !!config.showSummary, onChange: (v) => updateConfig({ showSummary: v }) })
2025
2110
  ] });
2026
2111
  case "rich-text":
2027
2112
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Rich Text", children: [
2028
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 6, onChange: (v) => updateConfig("content", v) }),
2029
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Format", value: config.format ?? "html", options: [{ label: "HTML", value: "html" }, { label: "Markdown", value: "markdown" }], onChange: (v) => updateConfig("format", v) })
2113
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 6, onChange: (v) => updateConfig({ content: v }) }),
2114
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Format", value: config.format ?? "html", options: [{ label: "HTML", value: "html" }, { label: "Markdown", value: "markdown" }], onChange: (v) => updateConfig({ format: v }) })
2030
2115
  ] });
2031
2116
  case "image":
2032
2117
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Image Settings", children: [
2033
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "https://...", onChange: (v) => updateConfig("src", v) }),
2034
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Alt Text", value: config.alt ?? "", onChange: (v) => updateConfig("alt", v) }),
2035
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Caption", value: config.caption, onChange: (v) => updateConfig("caption", v) }),
2036
- /* @__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) }),
2037
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 300px", onChange: (v) => updateConfig("width", v) }),
2038
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Link URL", value: config.link, placeholder: "Click opens this URL", onChange: (v) => updateConfig("link", v) })
2118
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "https://...", onChange: (v) => updateConfig({ src: v }) }),
2119
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Alt Text", value: config.alt ?? "", onChange: (v) => updateConfig({ alt: v }) }),
2120
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Caption", value: config.caption, onChange: (v) => updateConfig({ caption: v }) }),
2121
+ /* @__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 }) }),
2122
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 300px", onChange: (v) => updateConfig({ width: v }) }),
2123
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Link URL", value: config.link, placeholder: "Click opens this URL", onChange: (v) => updateConfig({ link: v }) })
2039
2124
  ] });
2040
2125
  case "video":
2041
2126
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Video Settings", children: [
2042
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "YouTube/Vimeo URL", onChange: (v) => updateConfig("src", v) }),
2043
- /* @__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) }),
2044
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Autoplay", checked: !!config.autoplay, onChange: (v) => updateConfig("autoplay", v) }),
2045
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Muted", checked: !!config.muted, onChange: (v) => updateConfig("muted", v) }),
2046
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 640px", onChange: (v) => updateConfig("width", v) }),
2047
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Height", value: config.height, placeholder: "e.g. 360px", onChange: (v) => updateConfig("height", v) })
2127
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "YouTube/Vimeo URL", onChange: (v) => updateConfig({ src: v }) }),
2128
+ /* @__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 }) }),
2129
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Autoplay", checked: !!config.autoplay, onChange: (v) => updateConfig({ autoplay: v }) }),
2130
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Muted", checked: !!config.muted, onChange: (v) => updateConfig({ muted: v }) }),
2131
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 640px", onChange: (v) => updateConfig({ width: v }) }),
2132
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Height", value: config.height, placeholder: "e.g. 360px", onChange: (v) => updateConfig({ height: v }) })
2048
2133
  ] });
2049
2134
  case "divider":
2050
2135
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Divider Settings", children: [
2051
- /* @__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) }),
2052
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Color", value: config.color, placeholder: "#e5e7eb", onChange: (v) => updateConfig("color", v) }),
2053
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Thickness (px)", value: config.thickness, placeholder: "1", onChange: (v) => updateConfig("thickness", v) }),
2054
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Spacing (px)", value: config.spacing, placeholder: "16", onChange: (v) => updateConfig("spacing", v) })
2136
+ /* @__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 }) }),
2137
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Color", value: config.color, placeholder: "#e5e7eb", onChange: (v) => updateConfig({ color: v }) }),
2138
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Thickness (px)", value: config.thickness, placeholder: "1", onChange: (v) => updateConfig({ thickness: v }) }),
2139
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Spacing (px)", value: config.spacing, placeholder: "16", onChange: (v) => updateConfig({ spacing: v }) })
2055
2140
  ] });
2056
2141
  case "spacer":
2057
- 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) }) });
2142
+ 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 }) }) });
2058
2143
  // ── Structural ──
2059
2144
  case "section_header":
2060
2145
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Header Settings", children: [
2061
- /* @__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) }),
2062
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Divider", checked: !!config.showDivider, onChange: (v) => updateConfig("showDivider", v) })
2146
+ /* @__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 }) }),
2147
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Divider", checked: !!config.showDivider, onChange: (v) => updateConfig({ showDivider: v }) })
2063
2148
  ] });
2064
2149
  case "info_block":
2065
2150
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Info Block", children: [
2066
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 4, onChange: (v) => updateConfig("content", v) }),
2067
- /* @__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) })
2151
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 4, onChange: (v) => updateConfig({ content: v }) }),
2152
+ /* @__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 }) })
2068
2153
  ] });
2069
2154
  case "page_break":
2070
- 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) }) });
2155
+ 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 }) }) });
2071
2156
  case "consent":
2072
2157
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Consent Settings", children: [
2073
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Consent Text", value: config.text ?? "", rows: 4, onChange: (v) => updateConfig("text", v) }),
2074
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Checkbox Label", value: config.checkboxLabel ?? "I agree", onChange: (v) => updateConfig("checkboxLabel", v) }),
2075
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Expandable Text", value: config.expandableText, rows: 3, placeholder: "Additional text shown on expand", onChange: (v) => updateConfig("expandableText", v) })
2158
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Consent Text", value: config.text ?? "", rows: 4, onChange: (v) => updateConfig({ text: v }) }),
2159
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Checkbox Label", value: config.checkboxLabel ?? "I agree", onChange: (v) => updateConfig({ checkboxLabel: v }) }),
2160
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Expandable Text", value: config.expandableText, rows: 3, placeholder: "Additional text shown on expand", onChange: (v) => updateConfig({ expandableText: v }) })
2076
2161
  ] });
2077
2162
  // ── Advanced ──
2078
2163
  case "matrix":
2079
2164
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Matrix Settings", children: [
2080
- /* @__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) }),
2081
- /* @__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) }),
2082
- /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Rows", items: config.rows ?? [], onChange: (v) => updateConfig("rows", v) }),
2083
- /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Columns", items: config.columns ?? [], onChange: (v) => updateConfig("columns", v) })
2165
+ /* @__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 }) }),
2166
+ /* @__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 }) }),
2167
+ /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Rows", items: config.rows ?? [], onChange: (v) => updateConfig({ rows: v }) }),
2168
+ /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Columns", items: config.columns ?? [], onChange: (v) => updateConfig({ columns: v }) })
2084
2169
  ] });
2085
2170
  case "repeater":
2086
2171
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Repeater Settings", children: [
2087
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min Entries", value: config.minEntries, placeholder: "1", onChange: (v) => updateConfig("minEntries", v) }),
2088
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Entries", value: config.maxEntries, onChange: (v) => updateConfig("maxEntries", v) }),
2089
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Default Entries", value: config.defaultEntries, placeholder: "1", onChange: (v) => updateConfig("defaultEntries", v) }),
2090
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Add Button Label", value: config.addLabel, placeholder: "Add Entry", onChange: (v) => updateConfig("addLabel", v) }),
2091
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Remove Button Label", value: config.removeLabel, placeholder: "Remove", onChange: (v) => updateConfig("removeLabel", v) }),
2172
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min Entries", value: config.minEntries, placeholder: "1", onChange: (v) => updateConfig({ minEntries: v }) }),
2173
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Entries", value: config.maxEntries, onChange: (v) => updateConfig({ maxEntries: v }) }),
2174
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Default Entries", value: config.defaultEntries, placeholder: "1", onChange: (v) => updateConfig({ defaultEntries: v }) }),
2175
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Add Button Label", value: config.addLabel, placeholder: "Add Entry", onChange: (v) => updateConfig({ addLabel: v }) }),
2176
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Remove Button Label", value: config.removeLabel, placeholder: "Remove", onChange: (v) => updateConfig({ removeLabel: v }) }),
2092
2177
  /* @__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." })
2093
2178
  ] });
2094
2179
  case "address": {
@@ -2102,9 +2187,9 @@ function QuestionConfigEditor({ question, onUpdate }) {
2102
2187
  ];
2103
2188
  const activeFields = config.fields ?? ["street", "city", "state", "zip", "country"];
2104
2189
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Address Settings", children: [
2105
- /* @__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) }),
2106
- config.provider !== "none" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "API Key", value: config.apiKey, placeholder: "Provider API key", onChange: (v) => updateConfig("apiKey", v) }),
2107
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Default Country", value: config.defaultCountry, placeholder: "e.g. US", onChange: (v) => updateConfig("defaultCountry", v) }),
2190
+ /* @__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 }) }),
2191
+ config.provider !== "none" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "API Key", value: config.apiKey, placeholder: "Provider API key", onChange: (v) => updateConfig({ apiKey: v }) }),
2192
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Default Country", value: config.defaultCountry, placeholder: "e.g. US", onChange: (v) => updateConfig({ defaultCountry: v }) }),
2108
2193
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2109
2194
  /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Label, { className: "text-xs text-muted-foreground mb-2 block", children: "Fields" }),
2110
2195
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: ADDRESS_FIELDS.map((f) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -2114,7 +2199,7 @@ function QuestionConfigEditor({ question, onUpdate }) {
2114
2199
  checked: activeFields.includes(f.value),
2115
2200
  onChange: (checked) => {
2116
2201
  const next = checked ? [...activeFields, f.value] : activeFields.filter((v) => v !== f.value);
2117
- updateConfig("fields", next.length > 0 ? next : void 0);
2202
+ updateConfig({ fields: next.length > 0 ? next : void 0 });
2118
2203
  }
2119
2204
  },
2120
2205
  f.value
@@ -2124,41 +2209,47 @@ function QuestionConfigEditor({ question, onUpdate }) {
2124
2209
  }
2125
2210
  case "payment":
2126
2211
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Payment Settings", children: [
2127
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Provider", value: config.provider ?? "stripe", options: [{ label: "Stripe", value: "stripe" }, { label: "PayPal", value: "paypal" }], onChange: (v) => updateConfig("provider", v) }),
2128
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Public Key", value: config.publicKey ?? "", placeholder: "Provider public/client key", onChange: (v) => updateConfig("publicKey", v) }),
2129
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Amount", value: config.amount, onChange: (v) => updateConfig("amount", v) }),
2130
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Amount Field", value: config.amountField, placeholder: "Field ID for dynamic amount", onChange: (v) => updateConfig("amountField", v) }),
2131
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Currency", value: config.currency, placeholder: "USD", onChange: (v) => updateConfig("currency", v) }),
2132
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Description", value: config.description, onChange: (v) => updateConfig("description", v) })
2212
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Provider", value: config.provider ?? "stripe", options: [{ label: "Stripe", value: "stripe" }, { label: "PayPal", value: "paypal" }], onChange: (v) => updateConfig({ provider: v }) }),
2213
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Public Key", value: config.publicKey ?? "", placeholder: "Provider public/client key", onChange: (v) => updateConfig({ publicKey: v }) }),
2214
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Server URL", value: config.serverUrl ?? "", placeholder: "https://api.example.com/create-intent", onChange: (v) => updateConfig({ serverUrl: v || void 0 }) }),
2215
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Client Secret Path", value: config.responseMapping?.clientSecretPath ?? "", placeholder: "clientSecret", onChange: (v) => updateConfig({ responseMapping: v ? { clientSecretPath: v } : void 0 }) }),
2216
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Amount", value: config.amount, onChange: (v) => updateConfig({ amount: v }) }),
2217
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Amount Field", value: config.amountField, placeholder: "Field ID for dynamic amount", onChange: (v) => updateConfig({ amountField: v }) }),
2218
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Currency", value: config.currency, placeholder: "USD", onChange: (v) => updateConfig({ currency: v }) }),
2219
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Description", value: config.description, onChange: (v) => updateConfig({ description: v }) })
2133
2220
  ] });
2134
2221
  case "calculated":
2135
2222
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Calculated Field", children: [
2136
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Expression", value: config.expression ?? "", placeholder: "e.g. {q1} + {q2}", onChange: (v) => updateConfig("expression", v) }),
2137
- /* @__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) }),
2138
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "2", onChange: (v) => updateConfig("decimalPlaces", v) }),
2139
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, onChange: (v) => updateConfig("prefix", v) }),
2140
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, onChange: (v) => updateConfig("suffix", v) }),
2141
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Visible to User", checked: config.visible !== false, onChange: (v) => updateConfig("visible", v) })
2223
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Expression", value: config.expression ?? "", placeholder: "e.g. {q1} + {q2}", onChange: (v) => updateConfig({ expression: v }) }),
2224
+ /* @__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 }) }),
2225
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "2", onChange: (v) => updateConfig({ decimalPlaces: v }) }),
2226
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, onChange: (v) => updateConfig({ prefix: v }) }),
2227
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, onChange: (v) => updateConfig({ suffix: v }) }),
2228
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Visible to User", checked: config.visible !== false, onChange: (v) => updateConfig({ visible: v }) })
2142
2229
  ] });
2143
2230
  case "hidden":
2144
2231
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Hidden Field", children: [
2145
- /* @__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) }),
2146
- config.source === "static" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Default Value", value: config.defaultValue, onChange: (v) => updateConfig("defaultValue", v) }),
2147
- config.source === "url_param" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Parameter Name", value: config.paramName, placeholder: "e.g. utm_source", onChange: (v) => updateConfig("paramName", v) }),
2148
- config.source === "cookie" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Cookie Name", value: config.cookieName, onChange: (v) => updateConfig("cookieName", v) })
2232
+ /* @__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 }) }),
2233
+ config.source === "static" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Default Value", value: config.defaultValue, onChange: (v) => updateConfig({ defaultValue: v }) }),
2234
+ config.source === "url_param" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Parameter Name", value: config.paramName, placeholder: "e.g. utm_source", onChange: (v) => updateConfig({ paramName: v }) }),
2235
+ config.source === "cookie" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Cookie Name", value: config.cookieName, onChange: (v) => updateConfig({ cookieName: v }) })
2149
2236
  ] });
2150
2237
  case "scoring":
2151
2238
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Scoring Settings", children: [
2152
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Score", checked: !!config.showScore, onChange: (v) => updateConfig("showScore", v) }),
2153
- /* @__PURE__ */ jsxRuntime.jsx(ScoringOptionsEditor, { options: config.options ?? [], onChange: (v) => updateConfig("options", v) }),
2154
- /* @__PURE__ */ jsxRuntime.jsx(ScoreRangesEditor, { ranges: config.scoreRanges ?? [], onChange: (v) => updateConfig("scoreRanges", v) })
2239
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Score", checked: !!config.showScore, onChange: (v) => updateConfig({ showScore: v }) }),
2240
+ /* @__PURE__ */ jsxRuntime.jsx(ScoringOptionsEditor, { options: config.options ?? [], onChange: (v) => updateConfig({ options: v }) }),
2241
+ /* @__PURE__ */ jsxRuntime.jsx(ScoreRangesEditor, { ranges: config.scoreRanges ?? [], onChange: (v) => updateConfig({ scoreRanges: v }) })
2155
2242
  ] });
2156
2243
  case "ranking":
2157
- return /* @__PURE__ */ jsxRuntime.jsx(ConfigSection, { title: "Ranking Settings", children: /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Items", items: config.items ?? [], onChange: (v) => updateConfig("items", v) }) });
2244
+ return /* @__PURE__ */ jsxRuntime.jsx(ConfigSection, { title: "Ranking Settings", children: /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Items", items: config.items ?? [], onChange: (v) => updateConfig({ items: v }) }) });
2245
+ case "phone_international":
2246
+ return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "International Phone Settings", children: [
2247
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Default Country", value: config.defaultCountry ?? "US", placeholder: "e.g. US", onChange: (v) => updateConfig({ defaultCountry: v }) }),
2248
+ /* @__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 }) })
2249
+ ] });
2158
2250
  // Types with no additional config
2159
2251
  case "email":
2160
2252
  case "phone":
2161
- case "phone_international":
2162
2253
  case "url":
2163
2254
  return null;
2164
2255
  default:
@@ -2250,7 +2341,10 @@ function SelectField({
2250
2341
  }) {
2251
2342
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2252
2343
  /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Label, { className: "text-xs text-muted-foreground mb-1", children: label }),
2253
- /* @__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)) })
2344
+ /* @__PURE__ */ jsxRuntime.jsxs(Select, { value, onValueChange: onChange, children: [
2345
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: options.find((o) => o.value === value)?.label ?? value }) }),
2346
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
2347
+ ] })
2254
2348
  ] });
2255
2349
  }
2256
2350
  function LikertLabelsEditor({
@@ -2396,6 +2490,59 @@ function ScoringOptionsEditor({
2396
2490
  ] }, index)) })
2397
2491
  ] });
2398
2492
  }
2493
+ function AppointmentSlotsEditor({
2494
+ slots,
2495
+ onChange
2496
+ }) {
2497
+ const handleDateChange = (index, date) => {
2498
+ const updated = slots.map((s, i) => i === index ? { ...s, date } : s);
2499
+ onChange(updated);
2500
+ };
2501
+ const handleTimesChange = (index, timesStr) => {
2502
+ const times = timesStr.split(",").map((t) => t.trim()).filter(Boolean);
2503
+ const updated = slots.map((s, i) => i === index ? { ...s, times } : s);
2504
+ onChange(updated);
2505
+ };
2506
+ const handleAdd = () => {
2507
+ const tomorrow = /* @__PURE__ */ new Date();
2508
+ tomorrow.setDate(tomorrow.getDate() + 1);
2509
+ const dateStr = tomorrow.toISOString().split("T")[0];
2510
+ onChange([...slots, { date: dateStr, times: ["09:00", "10:00", "11:00", "14:00", "15:00"] }]);
2511
+ };
2512
+ const handleRemove = (index) => {
2513
+ onChange(slots.filter((_, i) => i !== index));
2514
+ };
2515
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2516
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
2517
+ /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Label, { className: "text-xs text-muted-foreground", children: "Slots" }),
2518
+ /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Button, { type: "button", variant: "link", size: "xs", onClick: handleAdd, className: "px-0", children: "+ Add Date" })
2519
+ ] }),
2520
+ slots.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] text-muted-foreground", children: "No slots configured. Add a date to get started." }),
2521
+ /* @__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: [
2522
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
2523
+ /* @__PURE__ */ jsxRuntime.jsx(
2524
+ fieldcraftReact.Input,
2525
+ {
2526
+ type: "date",
2527
+ value: slot.date,
2528
+ onChange: (e) => handleDateChange(index, e.target.value),
2529
+ className: "h-7 text-xs flex-1"
2530
+ }
2531
+ ),
2532
+ /* @__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" })
2533
+ ] }),
2534
+ /* @__PURE__ */ jsxRuntime.jsx(
2535
+ fieldcraftReact.Input,
2536
+ {
2537
+ value: slot.times.join(", "),
2538
+ onChange: (e) => handleTimesChange(index, e.target.value),
2539
+ className: "h-7 text-xs",
2540
+ placeholder: "09:00, 10:00, 14:00, 15:00"
2541
+ }
2542
+ )
2543
+ ] }, index)) })
2544
+ ] });
2545
+ }
2399
2546
  function ScoreRangesEditor({
2400
2547
  ranges,
2401
2548
  onChange
@@ -2428,6 +2575,26 @@ function ScoreRangesEditor({
2428
2575
  ] }, index)) })
2429
2576
  ] });
2430
2577
  }
2578
+ var NativeSelect = React.forwardRef(
2579
+ ({ className, wrapperClassName, children, ...props }, ref) => {
2580
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative", wrapperClassName), children: [
2581
+ /* @__PURE__ */ jsxRuntime.jsx(
2582
+ "select",
2583
+ {
2584
+ ref,
2585
+ className: cn(
2586
+ "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",
2587
+ className
2588
+ ),
2589
+ ...props,
2590
+ children
2591
+ }
2592
+ ),
2593
+ /* @__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" })
2594
+ ] });
2595
+ }
2596
+ );
2597
+ NativeSelect.displayName = "NativeSelect";
2431
2598
  var RULE_TYPES = [
2432
2599
  { value: "minLength", label: "Min Length", description: "Minimum character count" },
2433
2600
  { value: "maxLength", label: "Max Length", description: "Maximum character count" },
@@ -2832,7 +2999,7 @@ function FormSettingsPanel({ schema, onUpdate }) {
2832
2999
  ];
2833
3000
  const displayMode = settings.displayMode ?? "stepped";
2834
3001
  const effectiveDisplayMode = hasConditions && displayMode === "classic" ? "stepped" : displayMode;
2835
- react.useEffect(() => {
3002
+ React.useEffect(() => {
2836
3003
  if (effectiveDisplayMode !== displayMode) {
2837
3004
  onUpdate({ ...schema, settings: { ...settings, displayMode: effectiveDisplayMode } });
2838
3005
  }
@@ -2989,7 +3156,7 @@ function SettingsSelect({
2989
3156
  }
2990
3157
  function PropertiesPanel({ builderState }) {
2991
3158
  const { schema, selectedItem } = builderState;
2992
- const [showSettings, setShowSettings] = react.useState(false);
3159
+ const [showSettings, setShowSettings] = React.useState(false);
2993
3160
  if (showSettings) {
2994
3161
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-80 h-full border-l border-border bg-card flex flex-col", children: [
2995
3162
  /* @__PURE__ */ jsxRuntime.jsx(PanelHeader, { title: "Form Settings", onClose: () => setShowSettings(false) }),
@@ -3064,11 +3231,11 @@ function SectionProperties({ section, onUpdate, onClose, onOpenSettings }) {
3064
3231
  ] });
3065
3232
  }
3066
3233
  function QuestionProperties({ question, sectionId, builderState, onClose, onOpenSettings }) {
3067
- const [activeTab, setActiveTab] = react.useState("basic");
3234
+ const [activeTab, setActiveTab] = React.useState("basic");
3068
3235
  const typeInfo = QUESTION_TYPE_INFO[question.type];
3069
3236
  const IconComponent = typeInfo ? getIcon(typeInfo.icon) : null;
3070
3237
  const hasOptions = typeInfo?.requiresOptions || question.options && question.options.length > 0;
3071
- const updateQuestion2 = react.useCallback(
3238
+ const updateQuestion2 = React.useCallback(
3072
3239
  (updates) => {
3073
3240
  builderState.updateQuestion(sectionId, question.id, updates);
3074
3241
  },
@@ -3243,7 +3410,7 @@ function FieldGroup({ label, children }) {
3243
3410
  children
3244
3411
  ] });
3245
3412
  }
3246
- var PreviewErrorBoundary = class extends react.Component {
3413
+ var PreviewErrorBoundary = class extends React.Component {
3247
3414
  state = { error: null };
3248
3415
  static getDerivedStateFromError(error) {
3249
3416
  return { error };
@@ -3304,15 +3471,15 @@ function errorsToMarkers(errors) {
3304
3471
  source: "FieldCraft Schema Validator"
3305
3472
  }));
3306
3473
  }
3307
- var Editor = react.lazy(() => import('@monaco-editor/react').then((m) => ({ default: m.default })));
3474
+ var Editor = React.lazy(() => import('@monaco-editor/react').then((m) => ({ default: m.default })));
3308
3475
  function MonacoWrapper({ value, onChange, errors }) {
3309
- const editorRef = react.useRef(null);
3310
- const monacoRef = react.useRef(null);
3476
+ const editorRef = React.useRef(null);
3477
+ const monacoRef = React.useRef(null);
3311
3478
  const handleMount = (editor, monaco) => {
3312
3479
  editorRef.current = editor;
3313
3480
  monacoRef.current = monaco;
3314
3481
  };
3315
- react.useEffect(() => {
3482
+ React.useEffect(() => {
3316
3483
  const editor = editorRef.current;
3317
3484
  const monaco = monacoRef.current;
3318
3485
  if (!editor || !monaco) return;
@@ -3344,14 +3511,14 @@ function MonacoWrapper({ value, onChange, errors }) {
3344
3511
  );
3345
3512
  }
3346
3513
  function JsonEditorPanel({ value, onChange, errors, onValidate }) {
3347
- const handleChange = react.useCallback(
3514
+ const handleChange = React.useCallback(
3348
3515
  (newValue) => {
3349
3516
  onChange(newValue);
3350
3517
  onValidate(newValue);
3351
3518
  },
3352
3519
  [onChange, onValidate]
3353
3520
  );
3354
- const handleFormat = react.useCallback(() => {
3521
+ const handleFormat = React.useCallback(() => {
3355
3522
  try {
3356
3523
  const formatted = JSON.stringify(JSON.parse(value), null, 2);
3357
3524
  onChange(formatted);
@@ -3384,7 +3551,7 @@ function JsonEditorPanel({ value, onChange, errors, onValidate }) {
3384
3551
  )
3385
3552
  ] }),
3386
3553
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
3387
- react.Suspense,
3554
+ React.Suspense,
3388
3555
  {
3389
3556
  fallback: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full text-sm text-muted-foreground", children: "Loading editor..." }),
3390
3557
  children: /* @__PURE__ */ jsxRuntime.jsx(MonacoWrapper, { value, onChange: handleChange, errors })
@@ -3583,7 +3750,7 @@ function SectionNodeInner({ data }) {
3583
3750
  const d = data;
3584
3751
  const color = SECTION_COLORS[d.colorIndex % SECTION_COLORS.length];
3585
3752
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fc-flow-section-group", style: { borderColor: color }, children: [
3586
- /* @__PURE__ */ jsxRuntime.jsx(react$1.Handle, { type: "target", position: react$1.Position.Left, className: "fc-flow-handle fc-flow-handle--section" }),
3753
+ /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "target", position: react.Position.Left, className: "fc-flow-handle fc-flow-handle--section" }),
3587
3754
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fc-flow-section-group__header", style: { background: color }, children: [
3588
3755
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "fc-flow-section-group__label", children: d.label.length > 30 ? d.label.slice(0, 30) + "\u2026" : d.label }),
3589
3756
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "fc-flow-section-group__meta", children: [
@@ -3594,10 +3761,10 @@ function SectionNodeInner({ data }) {
3594
3761
  d.hasExitLogic && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "fc-flow-section-group__badge fc-flow-section-group__badge--jump", title: "Has onExit jump", children: "\u2934" })
3595
3762
  ] })
3596
3763
  ] }),
3597
- /* @__PURE__ */ jsxRuntime.jsx(react$1.Handle, { type: "source", position: react$1.Position.Right, className: "fc-flow-handle fc-flow-handle--section" })
3764
+ /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "source", position: react.Position.Right, className: "fc-flow-handle fc-flow-handle--section" })
3598
3765
  ] });
3599
3766
  }
3600
- var SectionNode = react.memo(SectionNodeInner);
3767
+ var SectionNode = React.memo(SectionNodeInner);
3601
3768
  function FieldNodeInner({ data }) {
3602
3769
  const d = data;
3603
3770
  const color = SECTION_COLORS[d.colorIndex % SECTION_COLORS.length];
@@ -3610,18 +3777,18 @@ function FieldNodeInner({ data }) {
3610
3777
  borderWidth: d.hasCondition ? 2 : 1
3611
3778
  },
3612
3779
  children: [
3613
- /* @__PURE__ */ jsxRuntime.jsx(react$1.Handle, { type: "target", position: react$1.Position.Left, className: "fc-flow-handle" }),
3780
+ /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "target", position: react.Position.Left, className: "fc-flow-handle" }),
3614
3781
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fc-flow-field__content", children: [
3615
3782
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "fc-flow-field__label", children: d.label.length > 26 ? d.label.slice(0, 26) + "\u2026" : d.label }),
3616
3783
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "fc-flow-field__type", children: d.fieldType })
3617
3784
  ] }),
3618
3785
  d.hasCondition && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fc-flow-badge", style: { background: color }, title: "Has showIf condition", children: "?" }),
3619
- /* @__PURE__ */ jsxRuntime.jsx(react$1.Handle, { type: "source", position: react$1.Position.Right, className: "fc-flow-handle" })
3786
+ /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "source", position: react.Position.Right, className: "fc-flow-handle" })
3620
3787
  ]
3621
3788
  }
3622
3789
  );
3623
3790
  }
3624
- var FieldNode = react.memo(FieldNodeInner);
3791
+ var FieldNode = React.memo(FieldNodeInner);
3625
3792
  var logicFlowNodeTypes = {
3626
3793
  sectionNode: SectionNode,
3627
3794
  fieldNode: FieldNode
@@ -3639,7 +3806,7 @@ function ConditionEdgeInner({
3639
3806
  data,
3640
3807
  markerEnd
3641
3808
  }) {
3642
- const [edgePath, labelX, labelY] = react$1.getBezierPath({
3809
+ const [edgePath, labelX, labelY] = react.getBezierPath({
3643
3810
  sourceX,
3644
3811
  sourceY,
3645
3812
  sourcePosition,
@@ -3650,7 +3817,7 @@ function ConditionEdgeInner({
3650
3817
  const isJump = data?.edgeType === "onExit";
3651
3818
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3652
3819
  /* @__PURE__ */ jsxRuntime.jsx(
3653
- react$1.BaseEdge,
3820
+ react.BaseEdge,
3654
3821
  {
3655
3822
  id,
3656
3823
  path: edgePath,
@@ -3663,7 +3830,7 @@ function ConditionEdgeInner({
3663
3830
  }
3664
3831
  }
3665
3832
  ),
3666
- label && /* @__PURE__ */ jsxRuntime.jsx(react$1.EdgeLabelRenderer, { children: /* @__PURE__ */ jsxRuntime.jsx(
3833
+ label && /* @__PURE__ */ jsxRuntime.jsx(react.EdgeLabelRenderer, { children: /* @__PURE__ */ jsxRuntime.jsx(
3667
3834
  "div",
3668
3835
  {
3669
3836
  className: "fc-flow-edge-label",
@@ -3676,7 +3843,7 @@ function ConditionEdgeInner({
3676
3843
  ) })
3677
3844
  ] });
3678
3845
  }
3679
- var ConditionEdge = react.memo(ConditionEdgeInner);
3846
+ var ConditionEdge = React.memo(ConditionEdgeInner);
3680
3847
  function PipelineEdgeInner({
3681
3848
  id,
3682
3849
  sourceX,
@@ -3687,7 +3854,7 @@ function PipelineEdgeInner({
3687
3854
  targetPosition,
3688
3855
  markerEnd
3689
3856
  }) {
3690
- const [edgePath] = react$1.getBezierPath({
3857
+ const [edgePath] = react.getBezierPath({
3691
3858
  sourceX,
3692
3859
  sourceY,
3693
3860
  sourcePosition,
@@ -3696,7 +3863,7 @@ function PipelineEdgeInner({
3696
3863
  targetPosition
3697
3864
  });
3698
3865
  return /* @__PURE__ */ jsxRuntime.jsx(
3699
- react$1.BaseEdge,
3866
+ react.BaseEdge,
3700
3867
  {
3701
3868
  id,
3702
3869
  path: edgePath,
@@ -3709,7 +3876,7 @@ function PipelineEdgeInner({
3709
3876
  }
3710
3877
  );
3711
3878
  }
3712
- var PipelineEdge = react.memo(PipelineEdgeInner);
3879
+ var PipelineEdge = React.memo(PipelineEdgeInner);
3713
3880
  var logicFlowEdgeTypes = {
3714
3881
  conditionEdge: ConditionEdge,
3715
3882
  pipelineEdge: PipelineEdge
@@ -3747,30 +3914,30 @@ function removeConditionForSource(showIf, sourceFieldId) {
3747
3914
  }
3748
3915
  var defaultEdgeOptions = {
3749
3916
  markerEnd: {
3750
- type: react$1.MarkerType.ArrowClosed,
3917
+ type: react.MarkerType.ArrowClosed,
3751
3918
  width: 16,
3752
3919
  height: 12
3753
3920
  }
3754
3921
  };
3755
- function LogicFlowEditor({ schema, onChange, onClose }) {
3922
+ function LogicFlowEditor({ schema, onChange }) {
3756
3923
  const noSections = schema.sections.length === 0;
3757
- const flowGraph = react.useMemo(() => buildReactFlowGraph(schema), [schema]);
3758
- const [nodes, setNodes, onNodesChange] = react$1.useNodesState(flowGraph.nodes);
3759
- const [edges, setEdges, onEdgesChange] = react$1.useEdgesState(flowGraph.edges);
3760
- const [selectedFieldId, setSelectedFieldId] = react.useState(null);
3924
+ const flowGraph = React.useMemo(() => buildReactFlowGraph(schema), [schema]);
3925
+ const [nodes, setNodes, onNodesChange] = react.useNodesState(flowGraph.nodes);
3926
+ const [edges, setEdges, onEdgesChange] = react.useEdgesState(flowGraph.edges);
3927
+ const [selectedFieldId, setSelectedFieldId] = React.useState(null);
3761
3928
  const selectedQuestion = selectedFieldId ? findQuestion2(schema, selectedFieldId) : void 0;
3762
- react.useEffect(() => {
3929
+ React.useEffect(() => {
3763
3930
  setNodes(flowGraph.nodes);
3764
3931
  setEdges(flowGraph.edges);
3765
3932
  }, [flowGraph, setNodes, setEdges]);
3766
- const sectionIds = react.useMemo(() => {
3933
+ const sectionIds = React.useMemo(() => {
3767
3934
  const ids = [];
3768
3935
  for (const section of schema.sections) {
3769
3936
  ids.push(section.id);
3770
3937
  }
3771
3938
  return ids;
3772
3939
  }, [schema]);
3773
- const onNodeClick = react.useCallback(
3940
+ const onNodeClick = React.useCallback(
3774
3941
  (_event, node) => {
3775
3942
  if (node.type === "fieldNode") {
3776
3943
  setSelectedFieldId(node.id);
@@ -3778,7 +3945,7 @@ function LogicFlowEditor({ schema, onChange, onClose }) {
3778
3945
  },
3779
3946
  []
3780
3947
  );
3781
- const onConnect = react.useCallback(
3948
+ const onConnect = React.useCallback(
3782
3949
  (connection) => {
3783
3950
  if (!connection.source || !connection.target) return;
3784
3951
  const targetQuestion = findQuestion2(schema, connection.target);
@@ -3805,7 +3972,7 @@ function LogicFlowEditor({ schema, onChange, onClose }) {
3805
3972
  },
3806
3973
  [schema, onChange]
3807
3974
  );
3808
- const onEdgesDelete = react.useCallback(
3975
+ const onEdgesDelete = React.useCallback(
3809
3976
  (deletedEdges) => {
3810
3977
  let updatedSchema = schema;
3811
3978
  for (const edge of deletedEdges) {
@@ -3830,7 +3997,7 @@ function LogicFlowEditor({ schema, onChange, onClose }) {
3830
3997
  },
3831
3998
  [schema, onChange]
3832
3999
  );
3833
- const handleConditionUpdate = react.useCallback(
4000
+ const handleConditionUpdate = React.useCallback(
3834
4001
  (updates) => {
3835
4002
  if (!selectedFieldId) return;
3836
4003
  const updatedSchema = updateQuestionInSchema(schema, selectedFieldId, updates);
@@ -3844,34 +4011,90 @@ function LogicFlowEditor({ schema, onChange, onClose }) {
3844
4011
  const jumpCount = flowGraph.edges.filter(
3845
4012
  (e) => e.data?.edgeType === "onExit"
3846
4013
  ).length;
3847
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fixed inset-0 z-50 flex flex-col bg-background/95 backdrop-blur-sm", children: [
3848
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-12 shrink-0 flex items-center justify-between px-4 border-b border-border bg-card", children: [
3849
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
3850
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GitBranch, { size: 16, className: "text-primary" }),
3851
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm font-semibold", children: "Logic Flow" }),
3852
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [
3853
- showIfCount,
3854
- " condition",
3855
- showIfCount !== 1 ? "s" : "",
3856
- jumpCount > 0 && ` \xB7 ${jumpCount} jump${jumpCount !== 1 ? "s" : ""}`,
3857
- " \xB7 ",
3858
- sectionIds.length,
3859
- " section",
3860
- sectionIds.length !== 1 ? "s" : ""
3861
- ] })
3862
- ] }),
4014
+ const totalFields = React.useMemo(
4015
+ () => schema.sections.reduce((sum, s) => sum + s.questions.length, 0),
4016
+ [schema]
4017
+ );
4018
+ const conditionalFields = React.useMemo(
4019
+ () => schema.sections.reduce(
4020
+ (sum, s) => sum + s.questions.filter((q) => !!q.showIf).length,
4021
+ 0
4022
+ ),
4023
+ [schema]
4024
+ );
4025
+ return /* @__PURE__ */ jsxRuntime.jsx(react.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
4026
+ LogicFlowInner,
4027
+ {
4028
+ noSections,
4029
+ nodes,
4030
+ edges,
4031
+ onNodesChange,
4032
+ onEdgesChange,
4033
+ onNodeClick,
4034
+ onConnect,
4035
+ onEdgesDelete,
4036
+ selectedFieldId,
4037
+ selectedQuestion,
4038
+ setSelectedFieldId,
4039
+ handleConditionUpdate,
4040
+ schema,
4041
+ sectionIds,
4042
+ showIfCount,
4043
+ jumpCount,
4044
+ totalFields,
4045
+ conditionalFields
4046
+ }
4047
+ ) });
4048
+ }
4049
+ function LogicFlowInner({
4050
+ noSections,
4051
+ nodes,
4052
+ edges,
4053
+ onNodesChange,
4054
+ onEdgesChange,
4055
+ onNodeClick,
4056
+ onConnect,
4057
+ onEdgesDelete,
4058
+ selectedFieldId,
4059
+ selectedQuestion,
4060
+ setSelectedFieldId,
4061
+ handleConditionUpdate,
4062
+ schema,
4063
+ sectionIds,
4064
+ showIfCount,
4065
+ jumpCount,
4066
+ totalFields,
4067
+ conditionalFields
4068
+ }) {
4069
+ const { zoomIn, zoomOut, fitView } = react.useReactFlow();
4070
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col bg-background min-h-0", children: [
4071
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 h-9 flex items-center justify-between px-4 border-b border-border bg-card/50", children: [
4072
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [
4073
+ sectionIds.length,
4074
+ " section",
4075
+ sectionIds.length !== 1 ? "s" : "",
4076
+ " \xB7 ",
4077
+ totalFields,
4078
+ " field",
4079
+ totalFields !== 1 ? "s" : "",
4080
+ conditionalFields > 0 && ` \xB7 ${conditionalFields} conditional`,
4081
+ showIfCount > 0 && ` \xB7 ${showIfCount} rule${showIfCount !== 1 ? "s" : ""}`,
4082
+ jumpCount > 0 && ` \xB7 ${jumpCount} jump${jumpCount !== 1 ? "s" : ""}`
4083
+ ] }) }),
3863
4084
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
3864
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground mr-2", children: "Drag between nodes to create conditions \xB7 Select edges and press Delete to remove" }),
3865
- /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Button, { variant: "ghost", size: "icon-sm", onClick: onClose, title: "Close logic flow", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 16, strokeWidth: 1.75 }) })
4085
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] text-muted-foreground mr-2 hidden md:inline", children: "Drag between nodes to create conditions \xB7 Select edges + Delete to remove" }),
4086
+ /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Button, { variant: "ghost", size: "icon-xs", onClick: () => zoomOut(), title: "Zoom out", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ZoomOut, { size: 14, strokeWidth: 1.75 }) }),
4087
+ /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Button, { variant: "ghost", size: "icon-xs", onClick: () => zoomIn(), title: "Zoom in", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ZoomIn, { size: 14, strokeWidth: 1.75 }) }),
4088
+ /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Button, { variant: "ghost", size: "icon-xs", onClick: () => fitView({ padding: 0.2 }), title: "Fit to view", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize, { size: 14, strokeWidth: 1.75 }) })
3866
4089
  ] })
3867
4090
  ] }),
3868
- noSections ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex items-center justify-center text-muted-foreground text-sm", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center space-y-2", children: [
3869
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GitBranch, { size: 32, className: "mx-auto opacity-40" }),
3870
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium", children: "No sections found" }),
3871
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs max-w-xs", children: "Add sections and fields to your form to see the logic flow pipeline." })
3872
- ] }) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex", children: [
3873
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs(
3874
- react$1.ReactFlow,
4091
+ noSections ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex items-center justify-center text-muted-foreground text-sm", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center space-y-3", children: [
4092
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GitBranch, { size: 40, className: "mx-auto opacity-30" }),
4093
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium", children: "No logic to display" }),
4094
+ /* @__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." })
4095
+ ] }) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex min-h-0", children: [
4096
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntime.jsxs(
4097
+ react.ReactFlow,
3875
4098
  {
3876
4099
  nodes,
3877
4100
  edges,
@@ -3888,10 +4111,9 @@ function LogicFlowEditor({ schema, onChange, onClose }) {
3888
4111
  deleteKeyCode: ["Backspace", "Delete"],
3889
4112
  proOptions: { hideAttribution: true },
3890
4113
  children: [
3891
- /* @__PURE__ */ jsxRuntime.jsx(react$1.Background, { gap: 20, size: 1 }),
3892
- /* @__PURE__ */ jsxRuntime.jsx(react$1.Controls, { showInteractive: false }),
4114
+ /* @__PURE__ */ jsxRuntime.jsx(react.Background, { gap: 20, size: 1 }),
3893
4115
  /* @__PURE__ */ jsxRuntime.jsx(
3894
- react$1.MiniMap,
4116
+ react.MiniMap,
3895
4117
  {
3896
4118
  nodeColor: (node) => {
3897
4119
  const d = node.data;
@@ -3904,9 +4126,9 @@ function LogicFlowEditor({ schema, onChange, onClose }) {
3904
4126
  ]
3905
4127
  }
3906
4128
  ) }),
3907
- selectedFieldId && selectedQuestion && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-72 border-l border-border bg-card overflow-auto", children: [
4129
+ selectedFieldId && selectedQuestion && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-72 shrink-0 border-l border-border bg-card overflow-auto", children: [
3908
4130
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-3 border-b border-border flex items-center justify-between", children: [
3909
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
4131
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
3910
4132
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs font-semibold truncate", children: selectedQuestion.label || selectedQuestion.id }),
3911
4133
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] text-muted-foreground", children: selectedQuestion.type })
3912
4134
  ] }),
@@ -3917,7 +4139,7 @@ function LogicFlowEditor({ schema, onChange, onClose }) {
3917
4139
  size: "icon-xs",
3918
4140
  onClick: () => setSelectedFieldId(null),
3919
4141
  title: "Close panel",
3920
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 14, strokeWidth: 1.75 })
4142
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", children: "\xD7" })
3921
4143
  }
3922
4144
  )
3923
4145
  ] }),
@@ -3931,7 +4153,7 @@ function LogicFlowEditor({ schema, onChange, onClose }) {
3931
4153
  ) })
3932
4154
  ] })
3933
4155
  ] }),
3934
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 px-4 py-2 border-t border-border bg-card flex items-center gap-4 text-xs text-muted-foreground flex-wrap", children: [
4156
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 px-4 py-1.5 border-t border-border bg-card/50 flex items-center gap-4 text-[11px] text-muted-foreground flex-wrap", children: [
3935
4157
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
3936
4158
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-5 h-0.5 rounded", style: { background: "var(--muted-foreground)", opacity: 0.4 } }),
3937
4159
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "flow" })
@@ -3955,15 +4177,15 @@ function LogicFlowEditor({ schema, onChange, onClose }) {
3955
4177
  ] });
3956
4178
  }
3957
4179
  function TemplateGallery({ templates, onSelect, onClose }) {
3958
- const [search, setSearch] = react.useState("");
3959
- const [activeCategory, setActiveCategory] = react.useState("all");
3960
- const [confirmTemplate, setConfirmTemplate] = react.useState(null);
3961
- const categories = react.useMemo(() => {
4180
+ const [search, setSearch] = React.useState("");
4181
+ const [activeCategory, setActiveCategory] = React.useState("all");
4182
+ const [confirmTemplate, setConfirmTemplate] = React.useState(null);
4183
+ const categories = React.useMemo(() => {
3962
4184
  const cats = /* @__PURE__ */ new Set();
3963
4185
  for (const t of templates) cats.add(t.meta.category);
3964
4186
  return ["all", ...Array.from(cats)];
3965
4187
  }, [templates]);
3966
- const filtered = react.useMemo(() => {
4188
+ const filtered = React.useMemo(() => {
3967
4189
  return templates.filter((t) => {
3968
4190
  const matchesCategory = activeCategory === "all" || t.meta.category === activeCategory;
3969
4191
  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()));
@@ -4059,9 +4281,9 @@ function TemplateGallery({ templates, onSelect, onClose }) {
4059
4281
  ] }) });
4060
4282
  }
4061
4283
  function useDebouncedValidation(delayMs = 500) {
4062
- const [errors, setErrors] = react.useState([]);
4063
- const timerRef = react.useRef(null);
4064
- const validate = react.useCallback(
4284
+ const [errors, setErrors] = React.useState([]);
4285
+ const timerRef = React.useRef(null);
4286
+ const validate = React.useCallback(
4065
4287
  (text) => {
4066
4288
  if (timerRef.current) {
4067
4289
  clearTimeout(timerRef.current);
@@ -4110,9 +4332,9 @@ function useDebouncedValidation(delayMs = 500) {
4110
4332
  );
4111
4333
  return { errors, validate };
4112
4334
  }
4113
- var ThemeCtx = react.createContext({});
4335
+ var ThemeCtx = React.createContext({});
4114
4336
  function useBuilderTheme() {
4115
- return react.useContext(ThemeCtx);
4337
+ return React.useContext(ThemeCtx);
4116
4338
  }
4117
4339
  function themeToCssVars(theme) {
4118
4340
  const vars = {};
@@ -4148,10 +4370,10 @@ function themeToCssVars(theme) {
4148
4370
  }
4149
4371
  function FormBuilderThemeProvider({ theme, children }) {
4150
4372
  const resolved = theme ?? {};
4151
- const cssVars = react.useMemo(() => themeToCssVars(resolved), [resolved]);
4373
+ const cssVars = React.useMemo(() => themeToCssVars(resolved), [resolved]);
4152
4374
  return /* @__PURE__ */ jsxRuntime.jsx(ThemeCtx.Provider, { value: resolved, children: /* @__PURE__ */ jsxRuntime.jsx("div", { "data-fcb-root": "", style: cssVars, className: "w-full h-full", children }) });
4153
4375
  }
4154
- var FormBuilderErrorBoundary = class extends react.Component {
4376
+ var FormBuilderErrorBoundary = class extends React.Component {
4155
4377
  constructor(props) {
4156
4378
  super(props);
4157
4379
  this.state = { hasError: false, error: null };
@@ -4183,31 +4405,30 @@ var FormBuilderErrorBoundary = class extends react.Component {
4183
4405
  };
4184
4406
  function FormBuilderCore(props) {
4185
4407
  const { initialSchema = DEFAULT_SCHEMA, onChange, onSave, height = "100vh", theme, className, toolbarExtra, questionTypes, palette, preview, templates, schemaUrl } = props;
4186
- const [viewMode, setViewMode] = react.useState("design");
4187
- const [jsonText, setJsonText] = react.useState("");
4188
- const [jsonSwitchError, setJsonSwitchError] = react.useState(null);
4189
- const [showLogicMap, setShowLogicMap] = react.useState(false);
4190
- const [showTemplateGallery, setShowTemplateGallery] = react.useState(false);
4191
- const [saveValidationErrors, setSaveValidationErrors] = react.useState(null);
4192
- const [schemaUrlLoading, setSchemaUrlLoading] = react.useState(!!schemaUrl);
4193
- const [schemaUrlError, setSchemaUrlError] = react.useState(null);
4408
+ const [viewMode, setViewMode] = React.useState("design");
4409
+ const [jsonText, setJsonText] = React.useState("");
4410
+ const [jsonSwitchError, setJsonSwitchError] = React.useState(null);
4411
+ const [showTemplateGallery, setShowTemplateGallery] = React.useState(false);
4412
+ const [saveValidationErrors, setSaveValidationErrors] = React.useState(null);
4413
+ const [schemaUrlLoading, setSchemaUrlLoading] = React.useState(!!schemaUrl);
4414
+ const [schemaUrlError, setSchemaUrlError] = React.useState(null);
4194
4415
  const { errors: jsonErrors, validate: validateJson } = useDebouncedValidation(400);
4195
4416
  const mergedQuestionTypes = questionTypes ? { ...QUESTION_TYPE_INFO, ...questionTypes } : QUESTION_TYPE_INFO;
4196
4417
  const builderState = useBuilderState(initialSchema);
4197
4418
  const dragDrop = useDragDrop(builderState);
4198
- const fileInputRef = react.useRef(null);
4199
- const [mobilePanel, setMobilePanel] = react.useState("none");
4200
- react.useEffect(() => {
4419
+ const fileInputRef = React.useRef(null);
4420
+ const [mobilePanel, setMobilePanel] = React.useState("none");
4421
+ React.useEffect(() => {
4201
4422
  if (builderState.selectedItem && window.innerWidth < 768) {
4202
4423
  setMobilePanel("properties");
4203
4424
  }
4204
4425
  }, [builderState.selectedItem]);
4205
- react.useEffect(() => {
4426
+ React.useEffect(() => {
4206
4427
  if (!dragDrop.activeDragItem && mobilePanel === "palette") {
4207
4428
  setMobilePanel("none");
4208
4429
  }
4209
4430
  }, [dragDrop.activeDragItem]);
4210
- react.useEffect(() => {
4431
+ React.useEffect(() => {
4211
4432
  if (!schemaUrl) return;
4212
4433
  let cancelled = false;
4213
4434
  setSchemaUrlLoading(true);
@@ -4237,12 +4458,12 @@ function FormBuilderCore(props) {
4237
4458
  cancelled = true;
4238
4459
  };
4239
4460
  }, [schemaUrl]);
4240
- react.useEffect(() => {
4461
+ React.useEffect(() => {
4241
4462
  if (onChange && builderState.isDirty) {
4242
4463
  onChange(builderState.schema);
4243
4464
  }
4244
4465
  }, [builderState.schema, builderState.isDirty, onChange]);
4245
- const handleSave = react.useCallback(() => {
4466
+ const handleSave = React.useCallback(() => {
4246
4467
  if (!onSave) return;
4247
4468
  try {
4248
4469
  fieldcraftCore.validateSchema(builderState.schema);
@@ -4257,7 +4478,7 @@ function FormBuilderCore(props) {
4257
4478
  }
4258
4479
  }
4259
4480
  }, [onSave, builderState]);
4260
- const handleExport = react.useCallback(() => {
4481
+ const handleExport = React.useCallback(() => {
4261
4482
  const json = JSON.stringify(builderState.schema, null, 2);
4262
4483
  const blob = new Blob([json], { type: "application/json" });
4263
4484
  const url = URL.createObjectURL(blob);
@@ -4267,10 +4488,10 @@ function FormBuilderCore(props) {
4267
4488
  a.click();
4268
4489
  URL.revokeObjectURL(url);
4269
4490
  }, [builderState.schema]);
4270
- const handleImport = react.useCallback(() => {
4491
+ const handleImport = React.useCallback(() => {
4271
4492
  fileInputRef.current?.click();
4272
4493
  }, []);
4273
- const handleFileChange = react.useCallback(
4494
+ const handleFileChange = React.useCallback(
4274
4495
  (e) => {
4275
4496
  const file = e.target.files?.[0];
4276
4497
  if (!file) return;
@@ -4297,7 +4518,7 @@ ${details}`);
4297
4518
  },
4298
4519
  [builderState]
4299
4520
  );
4300
- const handleViewModeChange = react.useCallback(
4521
+ const handleViewModeChange = React.useCallback(
4301
4522
  (newMode) => {
4302
4523
  setJsonSwitchError(null);
4303
4524
  if (viewMode === "json" && newMode !== "json") {
@@ -4323,7 +4544,7 @@ ${details}`);
4323
4544
  },
4324
4545
  [viewMode, jsonText, builderState]
4325
4546
  );
4326
- const handleKeyDown = react.useCallback(
4547
+ const handleKeyDown = React.useCallback(
4327
4548
  (e) => {
4328
4549
  const mod = e.metaKey || e.ctrlKey;
4329
4550
  const tag = e.target.tagName;
@@ -4343,6 +4564,11 @@ ${details}`);
4343
4564
  handleSave();
4344
4565
  return;
4345
4566
  }
4567
+ if (mod && e.key === "l") {
4568
+ e.preventDefault();
4569
+ handleViewModeChange(viewMode === "logic" ? "design" : "logic");
4570
+ return;
4571
+ }
4346
4572
  if (isEditing) return;
4347
4573
  if (e.key === "Delete" || e.key === "Backspace") {
4348
4574
  const sel = builderState.selectedItem;
@@ -4373,7 +4599,7 @@ ${details}`);
4373
4599
  }
4374
4600
  }
4375
4601
  },
4376
- [builderState, handleSave]
4602
+ [builderState, handleSave, handleViewModeChange, viewMode]
4377
4603
  );
4378
4604
  return /* @__PURE__ */ jsxRuntime.jsx(FormBuilderThemeProvider, { theme, children: /* @__PURE__ */ jsxRuntime.jsxs(
4379
4605
  core.DndContext,
@@ -4464,6 +4690,19 @@ ${details}`);
4464
4690
  "JSON"
4465
4691
  ]
4466
4692
  }
4693
+ ),
4694
+ /* @__PURE__ */ jsxRuntime.jsxs(
4695
+ fieldcraftReact.Button,
4696
+ {
4697
+ variant: viewMode === "logic" ? "secondary" : "ghost",
4698
+ size: "sm",
4699
+ onClick: () => handleViewModeChange("logic"),
4700
+ className: "gap-1.5 h-7 px-2.5 text-xs",
4701
+ children: [
4702
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GitBranch, { size: 13, strokeWidth: 1.75 }),
4703
+ "Logic"
4704
+ ]
4705
+ }
4467
4706
  )
4468
4707
  ] }),
4469
4708
  toolbarExtra
@@ -4480,17 +4719,6 @@ ${details}`);
4480
4719
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LayoutTemplate, { size: 15, strokeWidth: 1.75 })
4481
4720
  }
4482
4721
  ),
4483
- /* @__PURE__ */ jsxRuntime.jsx(
4484
- fieldcraftReact.Button,
4485
- {
4486
- variant: "ghost",
4487
- size: "icon-sm",
4488
- onClick: () => setShowLogicMap(true),
4489
- title: "View branching logic map",
4490
- "aria-label": "Logic map",
4491
- children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GitBranch, { size: 15, strokeWidth: 1.75 })
4492
- }
4493
- ),
4494
4722
  /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Separator, { orientation: "vertical", className: "mx-1 h-5" }),
4495
4723
  /* @__PURE__ */ jsxRuntime.jsx(
4496
4724
  fieldcraftReact.Button,
@@ -4574,6 +4802,19 @@ ${details}`);
4574
4802
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: "JSON" })
4575
4803
  ]
4576
4804
  }
4805
+ ),
4806
+ /* @__PURE__ */ jsxRuntime.jsxs(
4807
+ fieldcraftReact.Button,
4808
+ {
4809
+ variant: viewMode === "logic" ? "secondary" : "ghost",
4810
+ size: "sm",
4811
+ onClick: () => handleViewModeChange("logic"),
4812
+ className: "gap-1 h-7 px-2 text-xs",
4813
+ children: [
4814
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GitBranch, { size: 12, strokeWidth: 1.75 }),
4815
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: "Logic" })
4816
+ ]
4817
+ }
4577
4818
  )
4578
4819
  ] }),
4579
4820
  toolbarExtra,
@@ -4707,7 +4948,13 @@ ${details}`);
4707
4948
  errors: jsonErrors,
4708
4949
  onValidate: validateJson
4709
4950
  }
4710
- ) : viewMode === "preview" ? /* @__PURE__ */ jsxRuntime.jsx(FormPreviewPanel, { schema: builderState.schema, preview }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4951
+ ) : viewMode === "preview" ? /* @__PURE__ */ jsxRuntime.jsx(FormPreviewPanel, { schema: builderState.schema, preview }) : viewMode === "logic" ? /* @__PURE__ */ jsxRuntime.jsx(
4952
+ LogicFlowEditor,
4953
+ {
4954
+ schema: builderState.schema,
4955
+ onChange: (updated) => builderState.resetSchema(updated)
4956
+ }
4957
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4711
4958
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden md:flex", children: /* @__PURE__ */ jsxRuntime.jsx(QuestionPalette, { questionTypes: mergedQuestionTypes, palette }) }),
4712
4959
  /* @__PURE__ */ jsxRuntime.jsx(FormCanvas, { builderState }),
4713
4960
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden md:flex", children: /* @__PURE__ */ jsxRuntime.jsx(PropertiesPanel, { builderState }) }),
@@ -4726,14 +4973,6 @@ ${details}`);
4726
4973
  }
4727
4974
  ),
4728
4975
  /* @__PURE__ */ jsxRuntime.jsx(core.DragOverlay, { dropAnimation: null, children: dragDrop.activeDragItem && /* @__PURE__ */ jsxRuntime.jsx(DragOverlayContent, { item: dragDrop.activeDragItem, schema: builderState.schema, questionTypes: mergedQuestionTypes }) }),
4729
- showLogicMap && /* @__PURE__ */ jsxRuntime.jsx(
4730
- LogicFlowEditor,
4731
- {
4732
- schema: builderState.schema,
4733
- onChange: (updated) => builderState.resetSchema(updated),
4734
- onClose: () => setShowLogicMap(false)
4735
- }
4736
- ),
4737
4976
  showTemplateGallery && templates && /* @__PURE__ */ jsxRuntime.jsx(
4738
4977
  TemplateGallery,
4739
4978
  {