@squaredr/fieldcraft-pro 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -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,11 +8,36 @@ 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');
14
+ var paykitReact = require('@squaredr/paykit-react');
15
+ var client = require('@squaredr/paykit/stripe/client');
16
+ var paykit = require('@squaredr/paykit');
17
+
18
+ function _interopNamespace(e) {
19
+ if (e && e.__esModule) return e;
20
+ var n = Object.create(null);
21
+ if (e) {
22
+ Object.keys(e).forEach(function (k) {
23
+ if (k !== 'default') {
24
+ var d = Object.getOwnPropertyDescriptor(e, k);
25
+ Object.defineProperty(n, k, d.get ? d : {
26
+ enumerable: true,
27
+ get: function () { return e[k]; }
28
+ });
29
+ }
30
+ });
31
+ }
32
+ n.default = e;
33
+ return Object.freeze(n);
34
+ }
35
+
36
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
37
+ var SelectPrimitive__namespace = /*#__PURE__*/_interopNamespace(SelectPrimitive);
13
38
 
14
39
  // package.json
15
- var version = "1.6.4";
40
+ var version = "1.8.0";
16
41
  var PRODUCT_IDS = {
17
42
  FIELDCRAFT_PRO: 1
18
43
  };
@@ -308,10 +333,10 @@ async function performPing(key) {
308
333
  }
309
334
  }
310
335
  var defaultContext = { status: "validating" };
311
- var LicenseCtx = react.createContext(defaultContext);
336
+ var LicenseCtx = React.createContext(defaultContext);
312
337
  function FieldCraftProProvider({ licenseKey, children }) {
313
- const [license, setLicense] = react.useState(defaultContext);
314
- react.useEffect(() => {
338
+ const [license, setLicense] = React.useState(defaultContext);
339
+ React.useEffect(() => {
315
340
  let cancelled = false;
316
341
  setLicense(defaultContext);
317
342
  validateLicense(licenseKey).then((clientResult) => {
@@ -340,7 +365,7 @@ function FieldCraftProProvider({ licenseKey, children }) {
340
365
  return /* @__PURE__ */ jsxRuntime.jsx(LicenseCtx.Provider, { value: license, children });
341
366
  }
342
367
  function useLicense() {
343
- return react.useContext(LicenseCtx);
368
+ return React.useContext(LicenseCtx);
344
369
  }
345
370
  function UnlicensedOverlay({ featureName, reason, children }) {
346
371
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "relative", minHeight: "200px" }, children: [
@@ -565,38 +590,41 @@ function requireLicense(Component3, featureName) {
565
590
  }
566
591
  var MAX_HISTORY = 50;
567
592
  function useUndoRedo(currentSchema, setSchema) {
568
- const historyRef = react.useRef([currentSchema]);
569
- const [currentIndex, setCurrentIndex] = react.useState(0);
593
+ const historyRef = React.useRef([currentSchema]);
594
+ const [currentIndex, setCurrentIndex] = React.useState(0);
595
+ const currentIndexRef = React.useRef(currentIndex);
596
+ currentIndexRef.current = currentIndex;
570
597
  const canUndo = currentIndex > 0;
571
598
  const canRedo = currentIndex < historyRef.current.length - 1;
572
- const push = react.useCallback(
599
+ const push = React.useCallback(
573
600
  (schema) => {
574
- historyRef.current = historyRef.current.slice(0, currentIndex + 1);
601
+ const idx = currentIndexRef.current;
602
+ historyRef.current = historyRef.current.slice(0, idx + 1);
575
603
  historyRef.current.push(schema);
576
604
  if (historyRef.current.length > MAX_HISTORY) {
577
605
  historyRef.current.shift();
578
606
  setCurrentIndex(historyRef.current.length - 1);
579
607
  } else {
580
- setCurrentIndex((prev) => prev + 1);
608
+ setCurrentIndex(idx + 1);
581
609
  }
582
610
  },
583
- [currentIndex]
611
+ []
584
612
  );
585
- const undo = react.useCallback(() => {
613
+ const undo = React.useCallback(() => {
586
614
  if (currentIndex > 0) {
587
615
  const newIndex = currentIndex - 1;
588
616
  setCurrentIndex(newIndex);
589
617
  setSchema(historyRef.current[newIndex]);
590
618
  }
591
619
  }, [currentIndex, setSchema]);
592
- const redo = react.useCallback(() => {
620
+ const redo = React.useCallback(() => {
593
621
  if (currentIndex < historyRef.current.length - 1) {
594
622
  const newIndex = currentIndex + 1;
595
623
  setCurrentIndex(newIndex);
596
624
  setSchema(historyRef.current[newIndex]);
597
625
  }
598
626
  }, [currentIndex, setSchema]);
599
- const clear = react.useCallback(() => {
627
+ const clear = React.useCallback(() => {
600
628
  historyRef.current = [currentSchema];
601
629
  setCurrentIndex(0);
602
630
  }, [currentSchema]);
@@ -825,16 +853,16 @@ function findSection(schema, sectionId) {
825
853
 
826
854
  // src/form-builder/hooks/use-builder-state.ts
827
855
  function useBuilderState(initialSchema) {
828
- const [schema, setSchema] = react.useState(initialSchema);
829
- const [selectedItem, setSelectedItem] = react.useState(null);
830
- const [isDirty, setIsDirty] = react.useState(false);
831
- const schemaRef = react.useRef(schema);
856
+ const [schema, setSchema] = React.useState(initialSchema);
857
+ const [selectedItem, setSelectedItem] = React.useState(null);
858
+ const [isDirty, setIsDirty] = React.useState(false);
859
+ const schemaRef = React.useRef(schema);
832
860
  schemaRef.current = schema;
833
861
  const undoRedo = useUndoRedo(schema, (newSchema) => {
834
862
  setSchema(newSchema);
835
863
  setIsDirty(true);
836
864
  });
837
- const updateSchema = react.useCallback(
865
+ const updateSchema = React.useCallback(
838
866
  (newSchema) => {
839
867
  setSchema(newSchema);
840
868
  undoRedo.push(newSchema);
@@ -842,20 +870,20 @@ function useBuilderState(initialSchema) {
842
870
  },
843
871
  [undoRedo]
844
872
  );
845
- const applyMutation = react.useCallback(
873
+ const applyMutation = React.useCallback(
846
874
  (mutate) => {
847
875
  const result = mutate(schemaRef.current);
848
876
  updateSchema(result);
849
877
  },
850
878
  [updateSchema]
851
879
  );
852
- const addSection2 = react.useCallback(
880
+ const addSection2 = React.useCallback(
853
881
  (section, index) => {
854
882
  applyMutation((s) => addSection(s, section, index));
855
883
  },
856
884
  [applyMutation]
857
885
  );
858
- const removeSection2 = react.useCallback(
886
+ const removeSection2 = React.useCallback(
859
887
  (sectionId) => {
860
888
  applyMutation((s) => removeSection(s, sectionId));
861
889
  setSelectedItem((prev) => {
@@ -865,31 +893,31 @@ function useBuilderState(initialSchema) {
865
893
  },
866
894
  [applyMutation]
867
895
  );
868
- const updateSection2 = react.useCallback(
896
+ const updateSection2 = React.useCallback(
869
897
  (sectionId, updates) => {
870
898
  applyMutation((s) => updateSection(s, sectionId, updates));
871
899
  },
872
900
  [applyMutation]
873
901
  );
874
- const moveSection2 = react.useCallback(
902
+ const moveSection2 = React.useCallback(
875
903
  (sectionId, newIndex) => {
876
904
  applyMutation((s) => moveSection(s, sectionId, newIndex));
877
905
  },
878
906
  [applyMutation]
879
907
  );
880
- const duplicateSection2 = react.useCallback(
908
+ const duplicateSection2 = React.useCallback(
881
909
  (sectionId) => {
882
910
  applyMutation((s) => duplicateSection(s, sectionId));
883
911
  },
884
912
  [applyMutation]
885
913
  );
886
- const addQuestion2 = react.useCallback(
914
+ const addQuestion2 = React.useCallback(
887
915
  (sectionId, question, index) => {
888
916
  applyMutation((s) => addQuestion(s, sectionId, question, index));
889
917
  },
890
918
  [applyMutation]
891
919
  );
892
- const removeQuestion2 = react.useCallback(
920
+ const removeQuestion2 = React.useCallback(
893
921
  (sectionId, questionId) => {
894
922
  applyMutation((s) => removeQuestion(s, sectionId, questionId));
895
923
  setSelectedItem((prev) => {
@@ -901,34 +929,34 @@ function useBuilderState(initialSchema) {
901
929
  },
902
930
  [applyMutation]
903
931
  );
904
- const updateQuestion2 = react.useCallback(
932
+ const updateQuestion2 = React.useCallback(
905
933
  (sectionId, questionId, updates) => {
906
934
  applyMutation((s) => updateQuestion(s, sectionId, questionId, updates));
907
935
  },
908
936
  [applyMutation]
909
937
  );
910
- const moveQuestion2 = react.useCallback(
938
+ const moveQuestion2 = React.useCallback(
911
939
  (sectionId, questionId, targetSectionId, newIndex) => {
912
940
  applyMutation((s) => moveQuestion(s, sectionId, questionId, targetSectionId, newIndex));
913
941
  },
914
942
  [applyMutation]
915
943
  );
916
- const duplicateQuestion2 = react.useCallback(
944
+ const duplicateQuestion2 = React.useCallback(
917
945
  (sectionId, questionId) => {
918
946
  applyMutation((s) => duplicateQuestion(s, sectionId, questionId));
919
947
  },
920
948
  [applyMutation]
921
949
  );
922
- const selectQuestion = react.useCallback((sectionId, questionId) => {
950
+ const selectQuestion = React.useCallback((sectionId, questionId) => {
923
951
  setSelectedItem({ type: "question", sectionId, questionId });
924
952
  }, []);
925
- const selectSection = react.useCallback((sectionId) => {
953
+ const selectSection = React.useCallback((sectionId) => {
926
954
  setSelectedItem({ type: "section", sectionId });
927
955
  }, []);
928
- const clearSelection = react.useCallback(() => {
956
+ const clearSelection = React.useCallback(() => {
929
957
  setSelectedItem(null);
930
958
  }, []);
931
- const resetSchema = react.useCallback(
959
+ const resetSchema = React.useCallback(
932
960
  (newSchema) => {
933
961
  setSchema(newSchema);
934
962
  undoRedo.clear();
@@ -937,7 +965,7 @@ function useBuilderState(initialSchema) {
937
965
  },
938
966
  [undoRedo]
939
967
  );
940
- const markClean = react.useCallback(() => {
968
+ const markClean = React.useCallback(() => {
941
969
  setIsDirty(false);
942
970
  }, []);
943
971
  return {
@@ -1198,7 +1226,7 @@ var QUESTION_TYPE_INFO = {
1198
1226
  category: "advanced",
1199
1227
  icon: "ListPlus",
1200
1228
  description: "Repeatable group of fields",
1201
- defaultConfig: { type: "repeater", fields: [], minItems: 1, maxItems: 10 }
1229
+ defaultConfig: { type: "repeater", fields: [], minEntries: 1, maxEntries: 10 }
1202
1230
  },
1203
1231
  likert: {
1204
1232
  type: "likert",
@@ -1209,13 +1237,7 @@ var QUESTION_TYPE_INFO = {
1209
1237
  requiresOptions: true,
1210
1238
  defaultConfig: {
1211
1239
  type: "likert",
1212
- scale: [
1213
- { label: "Strongly Disagree", value: "1" },
1214
- { label: "Disagree", value: "2" },
1215
- { label: "Neutral", value: "3" },
1216
- { label: "Agree", value: "4" },
1217
- { label: "Strongly Agree", value: "5" }
1218
- ]
1240
+ labels: ["Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"]
1219
1241
  }
1220
1242
  },
1221
1243
  scoring: {
@@ -1268,7 +1290,7 @@ var QUESTION_TYPE_INFO = {
1268
1290
  category: "advanced",
1269
1291
  icon: "CreditCard",
1270
1292
  description: "Collect payment via Stripe",
1271
- defaultConfig: { type: "payment", provider: "stripe", publicKey: "", currency: "USD" }
1293
+ defaultConfig: { type: "payment", provider: "stripe", publicKey: "", currency: "USD", serverUrl: "" }
1272
1294
  },
1273
1295
  // ── Structural ──
1274
1296
  section_header: {
@@ -1415,7 +1437,7 @@ var DEFAULT_PALETTE = [
1415
1437
 
1416
1438
  // src/form-builder/hooks/use-drag-drop.ts
1417
1439
  function useDragDrop(builderState) {
1418
- const [activeDragItem, setActiveDragItem] = react.useState(null);
1440
+ const [activeDragItem, setActiveDragItem] = React.useState(null);
1419
1441
  const sensors = core.useSensors(
1420
1442
  core.useSensor(core.MouseSensor, {
1421
1443
  activationConstraint: {
@@ -1465,11 +1487,11 @@ function useDragDrop(builderState) {
1465
1487
  }
1466
1488
  return null;
1467
1489
  };
1468
- const handleDragStart = react.useCallback((event) => {
1490
+ const handleDragStart = React.useCallback((event) => {
1469
1491
  const item = parseDragItem(event.active);
1470
1492
  setActiveDragItem(item);
1471
1493
  }, []);
1472
- const handleDragCancel = react.useCallback(() => {
1494
+ const handleDragCancel = React.useCallback(() => {
1473
1495
  setActiveDragItem(null);
1474
1496
  }, []);
1475
1497
  const handleDragEnd = (event) => {
@@ -1639,9 +1661,9 @@ function PaletteItem({ questionType, typeInfo }) {
1639
1661
  );
1640
1662
  }
1641
1663
  function QuestionPalette({ questionTypes, palette }) {
1642
- const [collapsed, setCollapsed] = react.useState({});
1643
- const [search, setSearch] = react.useState("");
1644
- const mergedPalette = react.useMemo(
1664
+ const [collapsed, setCollapsed] = React.useState({});
1665
+ const [search, setSearch] = React.useState("");
1666
+ const mergedPalette = React.useMemo(
1645
1667
  () => palette ? [...DEFAULT_PALETTE, ...palette] : DEFAULT_PALETTE,
1646
1668
  [palette]
1647
1669
  );
@@ -1722,13 +1744,13 @@ function QuestionBlock({
1722
1744
  }) {
1723
1745
  const typeInfo = QUESTION_TYPE_INFO[question.type];
1724
1746
  const IconComponent = typeInfo ? getIcon(typeInfo.icon) : null;
1725
- const [isEditing, setIsEditing] = react.useState(false);
1726
- const [editValue, setEditValue] = react.useState(question.label);
1727
- const inputRef = react.useRef(null);
1728
- react.useEffect(() => {
1747
+ const [isEditing, setIsEditing] = React.useState(false);
1748
+ const [editValue, setEditValue] = React.useState(question.label);
1749
+ const inputRef = React.useRef(null);
1750
+ React.useEffect(() => {
1729
1751
  if (!isEditing) setEditValue(question.label);
1730
1752
  }, [question.label, isEditing]);
1731
- react.useEffect(() => {
1753
+ React.useEffect(() => {
1732
1754
  if (isEditing && inputRef.current) {
1733
1755
  inputRef.current.focus();
1734
1756
  inputRef.current.select();
@@ -1885,7 +1907,7 @@ function ConfirmDialog({ open, title, message, onConfirm, onCancel }) {
1885
1907
  );
1886
1908
  }
1887
1909
  function SectionBlock({ section, builderState }) {
1888
- const [confirmDelete, setConfirmDelete] = react.useState(false);
1910
+ const [confirmDelete, setConfirmDelete] = React.useState(false);
1889
1911
  const { setNodeRef } = core.useDroppable({
1890
1912
  id: `section-end-${section.id}`,
1891
1913
  data: { type: "section", sectionId: section.id, index: section.questions.length }
@@ -2066,30 +2088,71 @@ function FormCanvas({ builderState }) {
2066
2088
  ] })
2067
2089
  ] }) });
2068
2090
  }
2069
- var NativeSelect = react.forwardRef(
2070
- ({ className, wrapperClassName, children, ...props }, ref) => {
2071
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative", wrapperClassName), children: [
2091
+ var Select = SelectPrimitive__namespace.Root;
2092
+ var SelectTrigger = React__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
2093
+ SelectPrimitive__namespace.Trigger,
2094
+ {
2095
+ ref,
2096
+ className: cn(
2097
+ "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",
2098
+ className
2099
+ ),
2100
+ ...props,
2101
+ children: [
2102
+ children,
2103
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Icon, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "size-4 text-muted-foreground" }) })
2104
+ ]
2105
+ }
2106
+ ));
2107
+ SelectTrigger.displayName = "SelectTrigger";
2108
+ var SelectContent = React__namespace.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
2109
+ SelectPrimitive__namespace.Content,
2110
+ {
2111
+ ref,
2112
+ className: cn(
2113
+ "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",
2114
+ 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",
2115
+ className
2116
+ ),
2117
+ position,
2118
+ ...props,
2119
+ children: [
2120
+ /* @__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" }) }),
2072
2121
  /* @__PURE__ */ jsxRuntime.jsx(
2073
- "select",
2122
+ SelectPrimitive__namespace.Viewport,
2074
2123
  {
2075
- ref,
2076
2124
  className: cn(
2077
- "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",
2078
- className
2125
+ "p-1",
2126
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
2079
2127
  ),
2080
- ...props,
2081
2128
  children
2082
2129
  }
2083
2130
  ),
2084
- /* @__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" })
2085
- ] });
2131
+ /* @__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" }) })
2132
+ ]
2086
2133
  }
2087
- );
2088
- NativeSelect.displayName = "NativeSelect";
2134
+ ) }));
2135
+ SelectContent.displayName = "SelectContent";
2136
+ var SelectItem = React__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
2137
+ SelectPrimitive__namespace.Item,
2138
+ {
2139
+ ref,
2140
+ className: cn(
2141
+ "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",
2142
+ className
2143
+ ),
2144
+ ...props,
2145
+ children: [
2146
+ /* @__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" }) }) }),
2147
+ /* @__PURE__ */ jsxRuntime.jsx(SelectPrimitive__namespace.ItemText, { children })
2148
+ ]
2149
+ }
2150
+ ));
2151
+ SelectItem.displayName = "SelectItem";
2089
2152
  function useConfigUpdater(question, onUpdate) {
2090
- return (field, value) => {
2153
+ return (updates) => {
2091
2154
  const current = question.config ?? {};
2092
- onUpdate({ config: { ...current, type: question.type, [field]: value } });
2155
+ onUpdate({ config: { ...current, type: question.type, ...updates } });
2093
2156
  };
2094
2157
  }
2095
2158
  function QuestionConfigEditor({ question, onUpdate }) {
@@ -2099,226 +2162,274 @@ function QuestionConfigEditor({ question, onUpdate }) {
2099
2162
  // ── Text ──
2100
2163
  case "short_text":
2101
2164
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Text Settings", children: [
2102
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "255", onChange: (v) => updateConfig("maxLength", v) }),
2103
- /* @__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) }),
2104
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig("prefix", v) }),
2105
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. USD", onChange: (v) => updateConfig("suffix", v) })
2165
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "255", onChange: (v) => updateConfig({ maxLength: v }) }),
2166
+ /* @__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 }) }),
2167
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig({ prefix: v }) }),
2168
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. USD", onChange: (v) => updateConfig({ suffix: v }) })
2106
2169
  ] });
2107
2170
  case "long_text":
2108
2171
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Text Settings", children: [
2109
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "No limit", onChange: (v) => updateConfig("maxLength", v) }),
2110
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Rows", value: config.rows, placeholder: "4", onChange: (v) => updateConfig("rows", v) }),
2111
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Character Count", checked: !!config.showCharCount, onChange: (v) => updateConfig("showCharCount", v) })
2172
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "No limit", onChange: (v) => updateConfig({ maxLength: v }) }),
2173
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Rows", value: config.rows, placeholder: "4", onChange: (v) => updateConfig({ rows: v }) }),
2174
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Character Count", checked: !!config.showCharCount, onChange: (v) => updateConfig({ showCharCount: v }) })
2112
2175
  ] });
2113
2176
  case "legal_name":
2114
2177
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Name Fields", children: [
2115
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Middle Name", checked: !!config.showMiddleName, onChange: (v) => updateConfig("showMiddleName", v) }),
2116
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Suffix", checked: !!config.showSuffix, onChange: (v) => updateConfig("showSuffix", v) })
2178
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Middle Name", checked: !!config.showMiddleName, onChange: (v) => updateConfig({ showMiddleName: v }) }),
2179
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Suffix", checked: !!config.showSuffix, onChange: (v) => updateConfig({ showSuffix: v }) })
2117
2180
  ] });
2118
2181
  // ── Numeric ──
2119
2182
  case "number":
2120
2183
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Number Settings", children: [
2121
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min", value: config.min, onChange: (v) => updateConfig("min", v) }),
2122
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max", value: config.max, onChange: (v) => updateConfig("max", v) }),
2123
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig("step", v) }),
2124
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "0", onChange: (v) => updateConfig("decimalPlaces", v) }),
2125
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig("prefix", v) }),
2126
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. kg", onChange: (v) => updateConfig("suffix", v) })
2184
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min", value: config.min, onChange: (v) => updateConfig({ min: v }) }),
2185
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max", value: config.max, onChange: (v) => updateConfig({ max: v }) }),
2186
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig({ step: v }) }),
2187
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "0", onChange: (v) => updateConfig({ decimalPlaces: v }) }),
2188
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig({ prefix: v }) }),
2189
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. kg", onChange: (v) => updateConfig({ suffix: v }) })
2127
2190
  ] });
2128
2191
  case "slider":
2129
2192
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Slider Settings", children: [
2130
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min", value: config.min, placeholder: "0", onChange: (v) => updateConfig("min", v) }),
2131
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max", value: config.max, placeholder: "100", onChange: (v) => updateConfig("max", v) }),
2132
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig("step", v) }),
2133
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Value", checked: !!config.showValue, onChange: (v) => updateConfig("showValue", v) }),
2134
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig("minLabel", v) }),
2135
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig("maxLabel", v) })
2193
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min", value: config.min, placeholder: "0", onChange: (v) => updateConfig({ min: v }) }),
2194
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max", value: config.max, placeholder: "100", onChange: (v) => updateConfig({ max: v }) }),
2195
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig({ step: v }) }),
2196
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Value", checked: !!config.showValue, onChange: (v) => updateConfig({ showValue: v }) }),
2197
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig({ minLabel: v }) }),
2198
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig({ maxLabel: v }) })
2136
2199
  ] });
2137
2200
  case "rating":
2138
2201
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Rating Settings", children: [
2139
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Stars", value: config.max, placeholder: "5", onChange: (v) => updateConfig("max", v) }),
2140
- /* @__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) }),
2141
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Labels", checked: !!config.showLabels, onChange: (v) => updateConfig("showLabels", v) })
2202
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Stars", value: config.max, placeholder: "5", onChange: (v) => updateConfig({ max: v }) }),
2203
+ /* @__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 }) }),
2204
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Labels", checked: !!config.showLabels, onChange: (v) => updateConfig({ showLabels: v }) })
2142
2205
  ] });
2143
2206
  case "nps":
2144
2207
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "NPS Settings", children: [
2145
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Low Label", value: config.lowLabel ?? "Not likely", onChange: (v) => updateConfig("lowLabel", v) }),
2146
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "High Label", value: config.highLabel ?? "Very likely", onChange: (v) => updateConfig("highLabel", v) })
2208
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Low Label", value: config.lowLabel ?? "Not likely", onChange: (v) => updateConfig({ lowLabel: v }) }),
2209
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "High Label", value: config.highLabel ?? "Very likely", onChange: (v) => updateConfig({ highLabel: v }) })
2147
2210
  ] });
2148
2211
  case "opinion_scale":
2149
2212
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Scale Settings", children: [
2150
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min", value: config.min, placeholder: "1", onChange: (v) => updateConfig("min", v) }),
2151
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max", value: config.max, placeholder: "5", onChange: (v) => updateConfig("max", v) }),
2152
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig("step", v) }),
2153
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig("minLabel", v) }),
2154
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig("maxLabel", v) })
2213
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min", value: config.min, placeholder: "1", onChange: (v) => updateConfig({ min: v }) }),
2214
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max", value: config.max, placeholder: "5", onChange: (v) => updateConfig({ max: v }) }),
2215
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig({ step: v }) }),
2216
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig({ minLabel: v }) }),
2217
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig({ maxLabel: v }) })
2155
2218
  ] });
2156
2219
  case "likert":
2157
- 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) }) });
2220
+ 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 }) }) });
2158
2221
  // ── Selection ──
2159
2222
  case "single_select":
2160
2223
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Select Settings", children: [
2161
- /* @__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) }),
2162
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig("allowOther", v) }),
2163
- !!config.allowOther && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig("otherLabel", v) })
2224
+ /* @__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 }) }),
2225
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => v ? updateConfig({ allowOther: true }) : updateConfig({ allowOther: false, otherLabel: void 0 }) }),
2226
+ !!config.allowOther && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig({ otherLabel: v }) })
2164
2227
  ] });
2165
2228
  case "multi_select":
2166
2229
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Multi-Select Settings", children: [
2167
- /* @__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) }),
2168
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min Selections", value: config.minSelections, onChange: (v) => updateConfig("minSelections", v) }),
2169
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Selections", value: config.maxSelections, onChange: (v) => updateConfig("maxSelections", v) }),
2170
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig("allowOther", v) }),
2171
- !!config.allowOther && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig("otherLabel", v) })
2230
+ /* @__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 }) }),
2231
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min Selections", value: config.minSelections, onChange: (v) => updateConfig({ minSelections: v }) }),
2232
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Selections", value: config.maxSelections, onChange: (v) => updateConfig({ maxSelections: v }) }),
2233
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => v ? updateConfig({ allowOther: true }) : updateConfig({ allowOther: false, otherLabel: void 0 }) }),
2234
+ !!config.allowOther && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig({ otherLabel: v }) })
2172
2235
  ] });
2173
2236
  case "dropdown":
2174
2237
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Dropdown Settings", children: [
2175
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Searchable", checked: !!config.searchable, onChange: (v) => updateConfig("searchable", v) }),
2176
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig("allowOther", v) }),
2177
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Multiple", checked: !!config.multiple, onChange: (v) => updateConfig("multiple", v) })
2238
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Searchable", checked: !!config.searchable, onChange: (v) => updateConfig({ searchable: v }) }),
2239
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig({ allowOther: v }) }),
2240
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Multiple", checked: !!config.multiple, onChange: (v) => updateConfig({ multiple: v }) })
2178
2241
  ] });
2179
2242
  case "boolean":
2180
2243
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Yes/No Settings", children: [
2181
- /* @__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) }),
2182
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "True Label", value: config.trueLabel ?? "Yes", onChange: (v) => updateConfig("trueLabel", v) }),
2183
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "False Label", value: config.falseLabel ?? "No", onChange: (v) => updateConfig("falseLabel", v) })
2244
+ /* @__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 }) }),
2245
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "True Label", value: config.trueLabel ?? "Yes", onChange: (v) => updateConfig({ trueLabel: v }) }),
2246
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "False Label", value: config.falseLabel ?? "No", onChange: (v) => updateConfig({ falseLabel: v }) })
2184
2247
  ] });
2185
2248
  case "country_select":
2186
2249
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Country Settings", children: [
2187
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Flags", checked: config.showFlags !== false, onChange: (v) => updateConfig("showFlags", v) }),
2188
- /* @__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) }),
2189
- /* @__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) })
2250
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Flags", checked: config.showFlags !== false, onChange: (v) => updateConfig({ showFlags: v }) }),
2251
+ /* @__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 }) }),
2252
+ /* @__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 }) })
2190
2253
  ] });
2191
2254
  // ── Date/Time ──
2192
2255
  case "date":
2193
2256
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Date Settings", children: [
2194
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig("minDate", v) }),
2195
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig("maxDate", v) }),
2196
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Disable Past Dates", checked: !!config.disablePast, onChange: (v) => updateConfig("disablePast", v) }),
2197
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Disable Future Dates", checked: !!config.disableFuture, onChange: (v) => updateConfig("disableFuture", v) }),
2198
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Format", value: config.format, placeholder: "e.g. MM/DD/YYYY", onChange: (v) => updateConfig("format", v) })
2257
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ minDate: v }) }),
2258
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ maxDate: v }) }),
2259
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Disable Past Dates", checked: !!config.disablePast, onChange: (v) => updateConfig({ disablePast: v }) }),
2260
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Disable Future Dates", checked: !!config.disableFuture, onChange: (v) => updateConfig({ disableFuture: v }) }),
2261
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Format", value: config.format, placeholder: "e.g. MM/DD/YYYY", onChange: (v) => updateConfig({ format: v }) })
2199
2262
  ] });
2200
2263
  case "time":
2201
2264
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Time Settings", children: [
2202
- /* @__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) }),
2203
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Minute Step", value: config.minuteStep, placeholder: "1", onChange: (v) => updateConfig("minuteStep", v) })
2265
+ /* @__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 }) }),
2266
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Minute Step", value: config.minuteStep, placeholder: "1", onChange: (v) => updateConfig({ minuteStep: v }) })
2204
2267
  ] });
2205
2268
  case "date_range":
2206
2269
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Date Range Settings", children: [
2207
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig("minDate", v) }),
2208
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig("maxDate", v) }),
2209
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Range (days)", value: config.maxRangeDays, onChange: (v) => updateConfig("maxRangeDays", v) })
2270
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ minDate: v }) }),
2271
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ maxDate: v }) }),
2272
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Range (days)", value: config.maxRangeDays, onChange: (v) => updateConfig({ maxRangeDays: v }) })
2210
2273
  ] });
2211
- case "appointment":
2274
+ case "appointment": {
2275
+ const appointmentMode = typeof config.embedUrl === "string" ? "embed" : typeof config.slotsUrl === "string" ? "url" : "static";
2212
2276
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Appointment Settings", children: [
2213
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Duration (min)", value: config.duration ?? 30, onChange: (v) => updateConfig("duration", v) }),
2214
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Timezone", value: config.timezone, placeholder: "e.g. America/New_York", onChange: (v) => updateConfig("timezone", v) }),
2215
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Slots URL", value: config.slotsUrl, placeholder: "API endpoint for available slots", onChange: (v) => updateConfig("slotsUrl", v) })
2277
+ /* @__PURE__ */ jsxRuntime.jsx(
2278
+ SelectField,
2279
+ {
2280
+ label: "Mode",
2281
+ value: appointmentMode,
2282
+ options: [
2283
+ { label: "Static Slots", value: "static" },
2284
+ { label: "API Endpoint", value: "url" },
2285
+ { label: "Embed (Calendly / Cal.com)", value: "embed" }
2286
+ ],
2287
+ onChange: (v) => {
2288
+ if (v === "static") {
2289
+ updateConfig({ slotsUrl: void 0, embedUrl: void 0, embedProvider: void 0 });
2290
+ } else if (v === "url") {
2291
+ updateConfig({ slotsUrl: "", embedUrl: void 0, embedProvider: void 0, slots: void 0 });
2292
+ } else if (v === "embed") {
2293
+ updateConfig({ embedUrl: "", slotsUrl: void 0, slots: void 0 });
2294
+ }
2295
+ }
2296
+ }
2297
+ ),
2298
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Duration (min)", value: config.duration ?? 30, onChange: (v) => updateConfig({ duration: v }) }),
2299
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Timezone", value: config.timezone, placeholder: "e.g. America/New_York", onChange: (v) => updateConfig({ timezone: v }) }),
2300
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Timezone Field", value: config.timezoneField, placeholder: "Field ID for dynamic timezone", onChange: (v) => updateConfig({ timezoneField: v }) }),
2301
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Date Format", value: config.dateFormat, placeholder: "Locale-aware (default)", onChange: (v) => updateConfig({ dateFormat: v }) }),
2302
+ appointmentMode === "url" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Slots URL", value: config.slotsUrl, placeholder: "https://api.example.com/slots", onChange: (v) => updateConfig({ slotsUrl: v }) }),
2303
+ appointmentMode === "embed" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2304
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Embed URL", value: config.embedUrl, placeholder: "https://calendly.com/your-name/30min", onChange: (v) => updateConfig({ embedUrl: v }) }),
2305
+ /* @__PURE__ */ jsxRuntime.jsx(
2306
+ SelectField,
2307
+ {
2308
+ label: "Embed Provider",
2309
+ value: config.embedProvider ?? "custom",
2310
+ options: [
2311
+ { label: "Calendly", value: "calendly" },
2312
+ { label: "Cal.com", value: "cal_com" },
2313
+ { label: "Custom", value: "custom" }
2314
+ ],
2315
+ onChange: (v) => updateConfig({ embedProvider: v })
2316
+ }
2317
+ )
2318
+ ] }),
2319
+ appointmentMode === "static" && /* @__PURE__ */ jsxRuntime.jsx(
2320
+ AppointmentSlotsEditor,
2321
+ {
2322
+ slots: config.slots ?? [],
2323
+ onChange: (v) => updateConfig({ slots: v })
2324
+ }
2325
+ )
2216
2326
  ] });
2327
+ }
2217
2328
  // ── Media ──
2218
2329
  case "file_upload":
2219
2330
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Upload Settings", children: [
2220
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Files", value: config.maxFiles ?? 1, onChange: (v) => updateConfig("maxFiles", v) }),
2221
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb ?? 10, onChange: (v) => updateConfig("maxSizeMb", v) }),
2222
- /* @__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) }),
2223
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Upload URL", value: config.uploadUrl, placeholder: "Server upload endpoint", onChange: (v) => updateConfig("uploadUrl", v) })
2331
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Files", value: config.maxFiles ?? 1, onChange: (v) => updateConfig({ maxFiles: v }) }),
2332
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb ?? 10, onChange: (v) => updateConfig({ maxSizeMb: v }) }),
2333
+ /* @__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 }) }),
2334
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Upload URL", value: config.uploadUrl, placeholder: "Server upload endpoint", onChange: (v) => updateConfig({ uploadUrl: v }) })
2224
2335
  ] });
2225
2336
  case "signature":
2226
2337
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Signature Settings", children: [
2227
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Pen Color", value: config.penColor, placeholder: "#000000", onChange: (v) => updateConfig("penColor", v) }),
2228
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Background", value: config.backgroundColor, placeholder: "#ffffff", onChange: (v) => updateConfig("backgroundColor", v) }),
2229
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Width (px)", value: config.width, onChange: (v) => updateConfig("width", v) }),
2230
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Height (px)", value: config.height, onChange: (v) => updateConfig("height", v) })
2338
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Pen Color", value: config.penColor, placeholder: "#000000", onChange: (v) => updateConfig({ penColor: v }) }),
2339
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Background", value: config.backgroundColor, placeholder: "#ffffff", onChange: (v) => updateConfig({ backgroundColor: v }) }),
2340
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Width (px)", value: config.width, onChange: (v) => updateConfig({ width: v }) }),
2341
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Height (px)", value: config.height, onChange: (v) => updateConfig({ height: v }) })
2231
2342
  ] });
2232
2343
  case "image_capture":
2233
2344
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Camera Settings", children: [
2234
- /* @__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) }),
2235
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb, onChange: (v) => updateConfig("maxSizeMb", v) }),
2236
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Gallery", checked: config.allowGallery !== false, onChange: (v) => updateConfig("allowGallery", v) })
2345
+ /* @__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 }) }),
2346
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb, onChange: (v) => updateConfig({ maxSizeMb: v }) }),
2347
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Allow Gallery", checked: config.allowGallery !== false, onChange: (v) => updateConfig({ allowGallery: v }) })
2237
2348
  ] });
2238
2349
  // ── Content & Visual ──
2239
2350
  case "welcome-screen":
2240
2351
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Welcome Screen", children: [
2241
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Heading", value: config.heading ?? "Welcome", onChange: (v) => updateConfig("heading", v) }),
2242
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Description", value: config.description, onChange: (v) => updateConfig("description", v) }),
2243
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Button Text", value: config.buttonText ?? "Start", onChange: (v) => updateConfig("buttonText", v) }),
2244
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig("imageUrl", v) }),
2245
- /* @__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) })
2352
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Heading", value: config.heading ?? "Welcome", onChange: (v) => updateConfig({ heading: v }) }),
2353
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Description", value: config.description, onChange: (v) => updateConfig({ description: v }) }),
2354
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Button Text", value: config.buttonText ?? "Start", onChange: (v) => updateConfig({ buttonText: v }) }),
2355
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig({ imageUrl: v }) }),
2356
+ /* @__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 }) })
2246
2357
  ] });
2247
2358
  case "thank-you-screen":
2248
2359
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Thank You Screen", children: [
2249
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Heading", value: config.heading ?? "Thank You!", onChange: (v) => updateConfig("heading", v) }),
2250
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Description", value: config.description ?? "", onChange: (v) => updateConfig("description", v) }),
2251
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig("imageUrl", v) }),
2252
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Redirect URL", value: config.redirectUrl, placeholder: "https://...", onChange: (v) => updateConfig("redirectUrl", v) }),
2253
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Redirect Delay (s)", value: config.redirectDelay, placeholder: "0", onChange: (v) => updateConfig("redirectDelay", v) }),
2254
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Response Summary", checked: !!config.showSummary, onChange: (v) => updateConfig("showSummary", v) })
2360
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Heading", value: config.heading ?? "Thank You!", onChange: (v) => updateConfig({ heading: v }) }),
2361
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Description", value: config.description ?? "", onChange: (v) => updateConfig({ description: v }) }),
2362
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig({ imageUrl: v }) }),
2363
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Redirect URL", value: config.redirectUrl, placeholder: "https://...", onChange: (v) => updateConfig({ redirectUrl: v }) }),
2364
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Redirect Delay (s)", value: config.redirectDelay, placeholder: "0", onChange: (v) => updateConfig({ redirectDelay: v }) }),
2365
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Response Summary", checked: !!config.showSummary, onChange: (v) => updateConfig({ showSummary: v }) })
2255
2366
  ] });
2256
2367
  case "rich-text":
2257
2368
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Rich Text", children: [
2258
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 6, onChange: (v) => updateConfig("content", v) }),
2259
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Format", value: config.format ?? "html", options: [{ label: "HTML", value: "html" }, { label: "Markdown", value: "markdown" }], onChange: (v) => updateConfig("format", v) })
2369
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 6, onChange: (v) => updateConfig({ content: v }) }),
2370
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Format", value: config.format ?? "html", options: [{ label: "HTML", value: "html" }, { label: "Markdown", value: "markdown" }], onChange: (v) => updateConfig({ format: v }) })
2260
2371
  ] });
2261
2372
  case "image":
2262
2373
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Image Settings", children: [
2263
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "https://...", onChange: (v) => updateConfig("src", v) }),
2264
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Alt Text", value: config.alt ?? "", onChange: (v) => updateConfig("alt", v) }),
2265
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Caption", value: config.caption, onChange: (v) => updateConfig("caption", v) }),
2266
- /* @__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) }),
2267
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 300px", onChange: (v) => updateConfig("width", v) }),
2268
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Link URL", value: config.link, placeholder: "Click opens this URL", onChange: (v) => updateConfig("link", v) })
2374
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "https://...", onChange: (v) => updateConfig({ src: v }) }),
2375
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Alt Text", value: config.alt ?? "", onChange: (v) => updateConfig({ alt: v }) }),
2376
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Caption", value: config.caption, onChange: (v) => updateConfig({ caption: v }) }),
2377
+ /* @__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 }) }),
2378
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 300px", onChange: (v) => updateConfig({ width: v }) }),
2379
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Link URL", value: config.link, placeholder: "Click opens this URL", onChange: (v) => updateConfig({ link: v }) })
2269
2380
  ] });
2270
2381
  case "video":
2271
2382
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Video Settings", children: [
2272
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "YouTube/Vimeo URL", onChange: (v) => updateConfig("src", v) }),
2273
- /* @__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) }),
2274
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Autoplay", checked: !!config.autoplay, onChange: (v) => updateConfig("autoplay", v) }),
2275
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Muted", checked: !!config.muted, onChange: (v) => updateConfig("muted", v) }),
2276
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 640px", onChange: (v) => updateConfig("width", v) }),
2277
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Height", value: config.height, placeholder: "e.g. 360px", onChange: (v) => updateConfig("height", v) })
2383
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "YouTube/Vimeo URL", onChange: (v) => updateConfig({ src: v }) }),
2384
+ /* @__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 }) }),
2385
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Autoplay", checked: !!config.autoplay, onChange: (v) => updateConfig({ autoplay: v }) }),
2386
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Muted", checked: !!config.muted, onChange: (v) => updateConfig({ muted: v }) }),
2387
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 640px", onChange: (v) => updateConfig({ width: v }) }),
2388
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Height", value: config.height, placeholder: "e.g. 360px", onChange: (v) => updateConfig({ height: v }) })
2278
2389
  ] });
2279
2390
  case "divider":
2280
2391
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Divider Settings", children: [
2281
- /* @__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) }),
2282
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Color", value: config.color, placeholder: "#e5e7eb", onChange: (v) => updateConfig("color", v) }),
2283
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Thickness (px)", value: config.thickness, placeholder: "1", onChange: (v) => updateConfig("thickness", v) }),
2284
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Spacing (px)", value: config.spacing, placeholder: "16", onChange: (v) => updateConfig("spacing", v) })
2392
+ /* @__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 }) }),
2393
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Color", value: config.color, placeholder: "#e5e7eb", onChange: (v) => updateConfig({ color: v }) }),
2394
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Thickness (px)", value: config.thickness, placeholder: "1", onChange: (v) => updateConfig({ thickness: v }) }),
2395
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Spacing (px)", value: config.spacing, placeholder: "16", onChange: (v) => updateConfig({ spacing: v }) })
2285
2396
  ] });
2286
2397
  case "spacer":
2287
- 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) }) });
2398
+ 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 }) }) });
2288
2399
  // ── Structural ──
2289
2400
  case "section_header":
2290
2401
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Header Settings", children: [
2291
- /* @__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) }),
2292
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Divider", checked: !!config.showDivider, onChange: (v) => updateConfig("showDivider", v) })
2402
+ /* @__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 }) }),
2403
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Divider", checked: !!config.showDivider, onChange: (v) => updateConfig({ showDivider: v }) })
2293
2404
  ] });
2294
2405
  case "info_block":
2295
2406
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Info Block", children: [
2296
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 4, onChange: (v) => updateConfig("content", v) }),
2297
- /* @__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) })
2407
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 4, onChange: (v) => updateConfig({ content: v }) }),
2408
+ /* @__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 }) })
2298
2409
  ] });
2299
2410
  case "page_break":
2300
- 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) }) });
2411
+ 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 }) }) });
2301
2412
  case "consent":
2302
2413
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Consent Settings", children: [
2303
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Consent Text", value: config.text ?? "", rows: 4, onChange: (v) => updateConfig("text", v) }),
2304
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Checkbox Label", value: config.checkboxLabel ?? "I agree", onChange: (v) => updateConfig("checkboxLabel", v) }),
2305
- /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Expandable Text", value: config.expandableText, rows: 3, placeholder: "Additional text shown on expand", onChange: (v) => updateConfig("expandableText", v) })
2414
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Consent Text", value: config.text ?? "", rows: 4, onChange: (v) => updateConfig({ text: v }) }),
2415
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Checkbox Label", value: config.checkboxLabel ?? "I agree", onChange: (v) => updateConfig({ checkboxLabel: v }) }),
2416
+ /* @__PURE__ */ jsxRuntime.jsx(TextareaField, { label: "Expandable Text", value: config.expandableText, rows: 3, placeholder: "Additional text shown on expand", onChange: (v) => updateConfig({ expandableText: v }) })
2306
2417
  ] });
2307
2418
  // ── Advanced ──
2308
2419
  case "matrix":
2309
2420
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Matrix Settings", children: [
2310
- /* @__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) }),
2311
- /* @__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) }),
2312
- /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Rows", items: config.rows ?? [], onChange: (v) => updateConfig("rows", v) }),
2313
- /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Columns", items: config.columns ?? [], onChange: (v) => updateConfig("columns", v) })
2421
+ /* @__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 }) }),
2422
+ /* @__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 }) }),
2423
+ /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Rows", items: config.rows ?? [], onChange: (v) => updateConfig({ rows: v }) }),
2424
+ /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Columns", items: config.columns ?? [], onChange: (v) => updateConfig({ columns: v }) })
2314
2425
  ] });
2315
2426
  case "repeater":
2316
2427
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Repeater Settings", children: [
2317
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min Entries", value: config.minEntries, placeholder: "1", onChange: (v) => updateConfig("minEntries", v) }),
2318
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Entries", value: config.maxEntries, onChange: (v) => updateConfig("maxEntries", v) }),
2319
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Default Entries", value: config.defaultEntries, placeholder: "1", onChange: (v) => updateConfig("defaultEntries", v) }),
2320
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Add Button Label", value: config.addLabel, placeholder: "Add Entry", onChange: (v) => updateConfig("addLabel", v) }),
2321
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Remove Button Label", value: config.removeLabel, placeholder: "Remove", onChange: (v) => updateConfig("removeLabel", v) }),
2428
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Min Entries", value: config.minEntries, placeholder: "1", onChange: (v) => updateConfig({ minEntries: v }) }),
2429
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Max Entries", value: config.maxEntries, onChange: (v) => updateConfig({ maxEntries: v }) }),
2430
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Default Entries", value: config.defaultEntries, placeholder: "1", onChange: (v) => updateConfig({ defaultEntries: v }) }),
2431
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Add Button Label", value: config.addLabel, placeholder: "Add Entry", onChange: (v) => updateConfig({ addLabel: v }) }),
2432
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Remove Button Label", value: config.removeLabel, placeholder: "Remove", onChange: (v) => updateConfig({ removeLabel: v }) }),
2322
2433
  /* @__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." })
2323
2434
  ] });
2324
2435
  case "address": {
@@ -2332,9 +2443,9 @@ function QuestionConfigEditor({ question, onUpdate }) {
2332
2443
  ];
2333
2444
  const activeFields = config.fields ?? ["street", "city", "state", "zip", "country"];
2334
2445
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Address Settings", children: [
2335
- /* @__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) }),
2336
- config.provider !== "none" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "API Key", value: config.apiKey, placeholder: "Provider API key", onChange: (v) => updateConfig("apiKey", v) }),
2337
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Default Country", value: config.defaultCountry, placeholder: "e.g. US", onChange: (v) => updateConfig("defaultCountry", v) }),
2446
+ /* @__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 }) }),
2447
+ config.provider !== "none" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "API Key", value: config.apiKey, placeholder: "Provider API key", onChange: (v) => updateConfig({ apiKey: v }) }),
2448
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Default Country", value: config.defaultCountry, placeholder: "e.g. US", onChange: (v) => updateConfig({ defaultCountry: v }) }),
2338
2449
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2339
2450
  /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Label, { className: "text-xs text-muted-foreground mb-2 block", children: "Fields" }),
2340
2451
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: ADDRESS_FIELDS.map((f) => /* @__PURE__ */ jsxRuntime.jsx(
@@ -2344,7 +2455,7 @@ function QuestionConfigEditor({ question, onUpdate }) {
2344
2455
  checked: activeFields.includes(f.value),
2345
2456
  onChange: (checked) => {
2346
2457
  const next = checked ? [...activeFields, f.value] : activeFields.filter((v) => v !== f.value);
2347
- updateConfig("fields", next.length > 0 ? next : void 0);
2458
+ updateConfig({ fields: next.length > 0 ? next : void 0 });
2348
2459
  }
2349
2460
  },
2350
2461
  f.value
@@ -2354,41 +2465,47 @@ function QuestionConfigEditor({ question, onUpdate }) {
2354
2465
  }
2355
2466
  case "payment":
2356
2467
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Payment Settings", children: [
2357
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Provider", value: config.provider ?? "stripe", options: [{ label: "Stripe", value: "stripe" }, { label: "PayPal", value: "paypal" }], onChange: (v) => updateConfig("provider", v) }),
2358
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Public Key", value: config.publicKey ?? "", placeholder: "Provider public/client key", onChange: (v) => updateConfig("publicKey", v) }),
2359
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Amount", value: config.amount, onChange: (v) => updateConfig("amount", v) }),
2360
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Amount Field", value: config.amountField, placeholder: "Field ID for dynamic amount", onChange: (v) => updateConfig("amountField", v) }),
2361
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Currency", value: config.currency, placeholder: "USD", onChange: (v) => updateConfig("currency", v) }),
2362
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Description", value: config.description, onChange: (v) => updateConfig("description", v) })
2468
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Provider", value: config.provider ?? "stripe", options: [{ label: "Stripe", value: "stripe" }, { label: "PayPal", value: "paypal" }], onChange: (v) => updateConfig({ provider: v }) }),
2469
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Public Key", value: config.publicKey ?? "", placeholder: "Provider public/client key", onChange: (v) => updateConfig({ publicKey: v }) }),
2470
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Server URL", value: config.serverUrl ?? "", placeholder: "https://api.example.com/create-intent", onChange: (v) => updateConfig({ serverUrl: v || void 0 }) }),
2471
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Client Secret Path", value: config.responseMapping?.clientSecretPath ?? "", placeholder: "clientSecret", onChange: (v) => updateConfig({ responseMapping: v ? { clientSecretPath: v } : void 0 }) }),
2472
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Amount", value: config.amount, onChange: (v) => updateConfig({ amount: v }) }),
2473
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Amount Field", value: config.amountField, placeholder: "Field ID for dynamic amount", onChange: (v) => updateConfig({ amountField: v }) }),
2474
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Currency", value: config.currency, placeholder: "USD", onChange: (v) => updateConfig({ currency: v }) }),
2475
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Description", value: config.description, onChange: (v) => updateConfig({ description: v }) })
2363
2476
  ] });
2364
2477
  case "calculated":
2365
2478
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Calculated Field", children: [
2366
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Expression", value: config.expression ?? "", placeholder: "e.g. {q1} + {q2}", onChange: (v) => updateConfig("expression", v) }),
2367
- /* @__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) }),
2368
- /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "2", onChange: (v) => updateConfig("decimalPlaces", v) }),
2369
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, onChange: (v) => updateConfig("prefix", v) }),
2370
- /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, onChange: (v) => updateConfig("suffix", v) }),
2371
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Visible to User", checked: config.visible !== false, onChange: (v) => updateConfig("visible", v) })
2479
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Expression", value: config.expression ?? "", placeholder: "e.g. {q1} + {q2}", onChange: (v) => updateConfig({ expression: v }) }),
2480
+ /* @__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 }) }),
2481
+ /* @__PURE__ */ jsxRuntime.jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "2", onChange: (v) => updateConfig({ decimalPlaces: v }) }),
2482
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Prefix", value: config.prefix, onChange: (v) => updateConfig({ prefix: v }) }),
2483
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Suffix", value: config.suffix, onChange: (v) => updateConfig({ suffix: v }) }),
2484
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Visible to User", checked: config.visible !== false, onChange: (v) => updateConfig({ visible: v }) })
2372
2485
  ] });
2373
2486
  case "hidden":
2374
2487
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Hidden Field", children: [
2375
- /* @__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) }),
2376
- config.source === "static" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Default Value", value: config.defaultValue, onChange: (v) => updateConfig("defaultValue", v) }),
2377
- config.source === "url_param" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Parameter Name", value: config.paramName, placeholder: "e.g. utm_source", onChange: (v) => updateConfig("paramName", v) }),
2378
- config.source === "cookie" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Cookie Name", value: config.cookieName, onChange: (v) => updateConfig("cookieName", v) })
2488
+ /* @__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 }) }),
2489
+ config.source === "static" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Default Value", value: config.defaultValue, onChange: (v) => updateConfig({ defaultValue: v }) }),
2490
+ config.source === "url_param" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Parameter Name", value: config.paramName, placeholder: "e.g. utm_source", onChange: (v) => updateConfig({ paramName: v }) }),
2491
+ config.source === "cookie" && /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Cookie Name", value: config.cookieName, onChange: (v) => updateConfig({ cookieName: v }) })
2379
2492
  ] });
2380
2493
  case "scoring":
2381
2494
  return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "Scoring Settings", children: [
2382
- /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Score", checked: !!config.showScore, onChange: (v) => updateConfig("showScore", v) }),
2383
- /* @__PURE__ */ jsxRuntime.jsx(ScoringOptionsEditor, { options: config.options ?? [], onChange: (v) => updateConfig("options", v) }),
2384
- /* @__PURE__ */ jsxRuntime.jsx(ScoreRangesEditor, { ranges: config.scoreRanges ?? [], onChange: (v) => updateConfig("scoreRanges", v) })
2495
+ /* @__PURE__ */ jsxRuntime.jsx(ToggleField, { label: "Show Score", checked: !!config.showScore, onChange: (v) => updateConfig({ showScore: v }) }),
2496
+ /* @__PURE__ */ jsxRuntime.jsx(ScoringOptionsEditor, { options: config.options ?? [], onChange: (v) => updateConfig({ options: v }) }),
2497
+ /* @__PURE__ */ jsxRuntime.jsx(ScoreRangesEditor, { ranges: config.scoreRanges ?? [], onChange: (v) => updateConfig({ scoreRanges: v }) })
2385
2498
  ] });
2386
2499
  case "ranking":
2387
- return /* @__PURE__ */ jsxRuntime.jsx(ConfigSection, { title: "Ranking Settings", children: /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Items", items: config.items ?? [], onChange: (v) => updateConfig("items", v) }) });
2500
+ return /* @__PURE__ */ jsxRuntime.jsx(ConfigSection, { title: "Ranking Settings", children: /* @__PURE__ */ jsxRuntime.jsx(MatrixItemsEditor, { label: "Items", items: config.items ?? [], onChange: (v) => updateConfig({ items: v }) }) });
2501
+ case "phone_international":
2502
+ return /* @__PURE__ */ jsxRuntime.jsxs(ConfigSection, { title: "International Phone Settings", children: [
2503
+ /* @__PURE__ */ jsxRuntime.jsx(TextField, { label: "Default Country", value: config.defaultCountry ?? "US", placeholder: "e.g. US", onChange: (v) => updateConfig({ defaultCountry: v }) }),
2504
+ /* @__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 }) })
2505
+ ] });
2388
2506
  // Types with no additional config
2389
2507
  case "email":
2390
2508
  case "phone":
2391
- case "phone_international":
2392
2509
  case "url":
2393
2510
  return null;
2394
2511
  default:
@@ -2480,7 +2597,10 @@ function SelectField({
2480
2597
  }) {
2481
2598
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2482
2599
  /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Label, { className: "text-xs text-muted-foreground mb-1", children: label }),
2483
- /* @__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)) })
2600
+ /* @__PURE__ */ jsxRuntime.jsxs(Select, { value, onValueChange: onChange, children: [
2601
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx("span", { children: options.find((o) => o.value === value)?.label ?? value }) }),
2602
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: options.map((opt) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
2603
+ ] })
2484
2604
  ] });
2485
2605
  }
2486
2606
  function LikertLabelsEditor({
@@ -2626,6 +2746,59 @@ function ScoringOptionsEditor({
2626
2746
  ] }, index)) })
2627
2747
  ] });
2628
2748
  }
2749
+ function AppointmentSlotsEditor({
2750
+ slots,
2751
+ onChange
2752
+ }) {
2753
+ const handleDateChange = (index, date) => {
2754
+ const updated = slots.map((s, i) => i === index ? { ...s, date } : s);
2755
+ onChange(updated);
2756
+ };
2757
+ const handleTimesChange = (index, timesStr) => {
2758
+ const times = timesStr.split(",").map((t) => t.trim()).filter(Boolean);
2759
+ const updated = slots.map((s, i) => i === index ? { ...s, times } : s);
2760
+ onChange(updated);
2761
+ };
2762
+ const handleAdd = () => {
2763
+ const tomorrow = /* @__PURE__ */ new Date();
2764
+ tomorrow.setDate(tomorrow.getDate() + 1);
2765
+ const dateStr = tomorrow.toISOString().split("T")[0];
2766
+ onChange([...slots, { date: dateStr, times: ["09:00", "10:00", "11:00", "14:00", "15:00"] }]);
2767
+ };
2768
+ const handleRemove = (index) => {
2769
+ onChange(slots.filter((_, i) => i !== index));
2770
+ };
2771
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
2772
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
2773
+ /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Label, { className: "text-xs text-muted-foreground", children: "Slots" }),
2774
+ /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.Button, { type: "button", variant: "link", size: "xs", onClick: handleAdd, className: "px-0", children: "+ Add Date" })
2775
+ ] }),
2776
+ slots.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] text-muted-foreground", children: "No slots configured. Add a date to get started." }),
2777
+ /* @__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: [
2778
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
2779
+ /* @__PURE__ */ jsxRuntime.jsx(
2780
+ fieldcraftReact.Input,
2781
+ {
2782
+ type: "date",
2783
+ value: slot.date,
2784
+ onChange: (e) => handleDateChange(index, e.target.value),
2785
+ className: "h-7 text-xs flex-1"
2786
+ }
2787
+ ),
2788
+ /* @__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" })
2789
+ ] }),
2790
+ /* @__PURE__ */ jsxRuntime.jsx(
2791
+ fieldcraftReact.Input,
2792
+ {
2793
+ value: slot.times.join(", "),
2794
+ onChange: (e) => handleTimesChange(index, e.target.value),
2795
+ className: "h-7 text-xs",
2796
+ placeholder: "09:00, 10:00, 14:00, 15:00"
2797
+ }
2798
+ )
2799
+ ] }, index)) })
2800
+ ] });
2801
+ }
2629
2802
  function ScoreRangesEditor({
2630
2803
  ranges,
2631
2804
  onChange
@@ -2658,6 +2831,26 @@ function ScoreRangesEditor({
2658
2831
  ] }, index)) })
2659
2832
  ] });
2660
2833
  }
2834
+ var NativeSelect = React.forwardRef(
2835
+ ({ className, wrapperClassName, children, ...props }, ref) => {
2836
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative", wrapperClassName), children: [
2837
+ /* @__PURE__ */ jsxRuntime.jsx(
2838
+ "select",
2839
+ {
2840
+ ref,
2841
+ className: cn(
2842
+ "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",
2843
+ className
2844
+ ),
2845
+ ...props,
2846
+ children
2847
+ }
2848
+ ),
2849
+ /* @__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" })
2850
+ ] });
2851
+ }
2852
+ );
2853
+ NativeSelect.displayName = "NativeSelect";
2661
2854
  var RULE_TYPES = [
2662
2855
  { value: "minLength", label: "Min Length", description: "Minimum character count" },
2663
2856
  { value: "maxLength", label: "Max Length", description: "Maximum character count" },
@@ -3062,7 +3255,7 @@ function FormSettingsPanel({ schema, onUpdate }) {
3062
3255
  ];
3063
3256
  const displayMode = settings.displayMode ?? "stepped";
3064
3257
  const effectiveDisplayMode = hasConditions && displayMode === "classic" ? "stepped" : displayMode;
3065
- react.useEffect(() => {
3258
+ React.useEffect(() => {
3066
3259
  if (effectiveDisplayMode !== displayMode) {
3067
3260
  onUpdate({ ...schema, settings: { ...settings, displayMode: effectiveDisplayMode } });
3068
3261
  }
@@ -3219,7 +3412,7 @@ function SettingsSelect({
3219
3412
  }
3220
3413
  function PropertiesPanel({ builderState }) {
3221
3414
  const { schema, selectedItem } = builderState;
3222
- const [showSettings, setShowSettings] = react.useState(false);
3415
+ const [showSettings, setShowSettings] = React.useState(false);
3223
3416
  if (showSettings) {
3224
3417
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-80 h-full border-l border-border bg-card flex flex-col", children: [
3225
3418
  /* @__PURE__ */ jsxRuntime.jsx(PanelHeader, { title: "Form Settings", onClose: () => setShowSettings(false) }),
@@ -3294,11 +3487,11 @@ function SectionProperties({ section, onUpdate, onClose, onOpenSettings }) {
3294
3487
  ] });
3295
3488
  }
3296
3489
  function QuestionProperties({ question, sectionId, builderState, onClose, onOpenSettings }) {
3297
- const [activeTab, setActiveTab] = react.useState("basic");
3490
+ const [activeTab, setActiveTab] = React.useState("basic");
3298
3491
  const typeInfo = QUESTION_TYPE_INFO[question.type];
3299
3492
  const IconComponent = typeInfo ? getIcon(typeInfo.icon) : null;
3300
3493
  const hasOptions = typeInfo?.requiresOptions || question.options && question.options.length > 0;
3301
- const updateQuestion2 = react.useCallback(
3494
+ const updateQuestion2 = React.useCallback(
3302
3495
  (updates) => {
3303
3496
  builderState.updateQuestion(sectionId, question.id, updates);
3304
3497
  },
@@ -3473,7 +3666,7 @@ function FieldGroup({ label, children }) {
3473
3666
  children
3474
3667
  ] });
3475
3668
  }
3476
- var PreviewErrorBoundary = class extends react.Component {
3669
+ var PreviewErrorBoundary = class extends React.Component {
3477
3670
  state = { error: null };
3478
3671
  static getDerivedStateFromError(error) {
3479
3672
  return { error };
@@ -3534,15 +3727,15 @@ function errorsToMarkers(errors) {
3534
3727
  source: "FieldCraft Schema Validator"
3535
3728
  }));
3536
3729
  }
3537
- var Editor = react.lazy(() => import('@monaco-editor/react').then((m) => ({ default: m.default })));
3730
+ var Editor = React.lazy(() => import('@monaco-editor/react').then((m) => ({ default: m.default })));
3538
3731
  function MonacoWrapper({ value, onChange, errors }) {
3539
- const editorRef = react.useRef(null);
3540
- const monacoRef = react.useRef(null);
3732
+ const editorRef = React.useRef(null);
3733
+ const monacoRef = React.useRef(null);
3541
3734
  const handleMount = (editor, monaco) => {
3542
3735
  editorRef.current = editor;
3543
3736
  monacoRef.current = monaco;
3544
3737
  };
3545
- react.useEffect(() => {
3738
+ React.useEffect(() => {
3546
3739
  const editor = editorRef.current;
3547
3740
  const monaco = monacoRef.current;
3548
3741
  if (!editor || !monaco) return;
@@ -3574,14 +3767,14 @@ function MonacoWrapper({ value, onChange, errors }) {
3574
3767
  );
3575
3768
  }
3576
3769
  function JsonEditorPanel({ value, onChange, errors, onValidate }) {
3577
- const handleChange = react.useCallback(
3770
+ const handleChange = React.useCallback(
3578
3771
  (newValue) => {
3579
3772
  onChange(newValue);
3580
3773
  onValidate(newValue);
3581
3774
  },
3582
3775
  [onChange, onValidate]
3583
3776
  );
3584
- const handleFormat = react.useCallback(() => {
3777
+ const handleFormat = React.useCallback(() => {
3585
3778
  try {
3586
3779
  const formatted = JSON.stringify(JSON.parse(value), null, 2);
3587
3780
  onChange(formatted);
@@ -3614,7 +3807,7 @@ function JsonEditorPanel({ value, onChange, errors, onValidate }) {
3614
3807
  )
3615
3808
  ] }),
3616
3809
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
3617
- react.Suspense,
3810
+ React.Suspense,
3618
3811
  {
3619
3812
  fallback: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full text-sm text-muted-foreground", children: "Loading editor..." }),
3620
3813
  children: /* @__PURE__ */ jsxRuntime.jsx(MonacoWrapper, { value, onChange: handleChange, errors })
@@ -3813,7 +4006,7 @@ function SectionNodeInner({ data }) {
3813
4006
  const d = data;
3814
4007
  const color = SECTION_COLORS[d.colorIndex % SECTION_COLORS.length];
3815
4008
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fc-flow-section-group", style: { borderColor: color }, children: [
3816
- /* @__PURE__ */ jsxRuntime.jsx(react$1.Handle, { type: "target", position: react$1.Position.Left, className: "fc-flow-handle fc-flow-handle--section" }),
4009
+ /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "target", position: react.Position.Left, className: "fc-flow-handle fc-flow-handle--section" }),
3817
4010
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fc-flow-section-group__header", style: { background: color }, children: [
3818
4011
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "fc-flow-section-group__label", children: d.label.length > 30 ? d.label.slice(0, 30) + "\u2026" : d.label }),
3819
4012
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "fc-flow-section-group__meta", children: [
@@ -3824,10 +4017,10 @@ function SectionNodeInner({ data }) {
3824
4017
  d.hasExitLogic && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "fc-flow-section-group__badge fc-flow-section-group__badge--jump", title: "Has onExit jump", children: "\u2934" })
3825
4018
  ] })
3826
4019
  ] }),
3827
- /* @__PURE__ */ jsxRuntime.jsx(react$1.Handle, { type: "source", position: react$1.Position.Right, className: "fc-flow-handle fc-flow-handle--section" })
4020
+ /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "source", position: react.Position.Right, className: "fc-flow-handle fc-flow-handle--section" })
3828
4021
  ] });
3829
4022
  }
3830
- var SectionNode = react.memo(SectionNodeInner);
4023
+ var SectionNode = React.memo(SectionNodeInner);
3831
4024
  function FieldNodeInner({ data }) {
3832
4025
  const d = data;
3833
4026
  const color = SECTION_COLORS[d.colorIndex % SECTION_COLORS.length];
@@ -3840,18 +4033,18 @@ function FieldNodeInner({ data }) {
3840
4033
  borderWidth: d.hasCondition ? 2 : 1
3841
4034
  },
3842
4035
  children: [
3843
- /* @__PURE__ */ jsxRuntime.jsx(react$1.Handle, { type: "target", position: react$1.Position.Left, className: "fc-flow-handle" }),
4036
+ /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "target", position: react.Position.Left, className: "fc-flow-handle" }),
3844
4037
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fc-flow-field__content", children: [
3845
4038
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "fc-flow-field__label", children: d.label.length > 26 ? d.label.slice(0, 26) + "\u2026" : d.label }),
3846
4039
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "fc-flow-field__type", children: d.fieldType })
3847
4040
  ] }),
3848
4041
  d.hasCondition && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "fc-flow-badge", style: { background: color }, title: "Has showIf condition", children: "?" }),
3849
- /* @__PURE__ */ jsxRuntime.jsx(react$1.Handle, { type: "source", position: react$1.Position.Right, className: "fc-flow-handle" })
4042
+ /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "source", position: react.Position.Right, className: "fc-flow-handle" })
3850
4043
  ]
3851
4044
  }
3852
4045
  );
3853
4046
  }
3854
- var FieldNode = react.memo(FieldNodeInner);
4047
+ var FieldNode = React.memo(FieldNodeInner);
3855
4048
  var logicFlowNodeTypes = {
3856
4049
  sectionNode: SectionNode,
3857
4050
  fieldNode: FieldNode
@@ -3869,7 +4062,7 @@ function ConditionEdgeInner({
3869
4062
  data,
3870
4063
  markerEnd
3871
4064
  }) {
3872
- const [edgePath, labelX, labelY] = react$1.getBezierPath({
4065
+ const [edgePath, labelX, labelY] = react.getBezierPath({
3873
4066
  sourceX,
3874
4067
  sourceY,
3875
4068
  sourcePosition,
@@ -3880,7 +4073,7 @@ function ConditionEdgeInner({
3880
4073
  const isJump = data?.edgeType === "onExit";
3881
4074
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3882
4075
  /* @__PURE__ */ jsxRuntime.jsx(
3883
- react$1.BaseEdge,
4076
+ react.BaseEdge,
3884
4077
  {
3885
4078
  id,
3886
4079
  path: edgePath,
@@ -3893,7 +4086,7 @@ function ConditionEdgeInner({
3893
4086
  }
3894
4087
  }
3895
4088
  ),
3896
- label && /* @__PURE__ */ jsxRuntime.jsx(react$1.EdgeLabelRenderer, { children: /* @__PURE__ */ jsxRuntime.jsx(
4089
+ label && /* @__PURE__ */ jsxRuntime.jsx(react.EdgeLabelRenderer, { children: /* @__PURE__ */ jsxRuntime.jsx(
3897
4090
  "div",
3898
4091
  {
3899
4092
  className: "fc-flow-edge-label",
@@ -3906,7 +4099,7 @@ function ConditionEdgeInner({
3906
4099
  ) })
3907
4100
  ] });
3908
4101
  }
3909
- var ConditionEdge = react.memo(ConditionEdgeInner);
4102
+ var ConditionEdge = React.memo(ConditionEdgeInner);
3910
4103
  function PipelineEdgeInner({
3911
4104
  id,
3912
4105
  sourceX,
@@ -3917,7 +4110,7 @@ function PipelineEdgeInner({
3917
4110
  targetPosition,
3918
4111
  markerEnd
3919
4112
  }) {
3920
- const [edgePath] = react$1.getBezierPath({
4113
+ const [edgePath] = react.getBezierPath({
3921
4114
  sourceX,
3922
4115
  sourceY,
3923
4116
  sourcePosition,
@@ -3926,7 +4119,7 @@ function PipelineEdgeInner({
3926
4119
  targetPosition
3927
4120
  });
3928
4121
  return /* @__PURE__ */ jsxRuntime.jsx(
3929
- react$1.BaseEdge,
4122
+ react.BaseEdge,
3930
4123
  {
3931
4124
  id,
3932
4125
  path: edgePath,
@@ -3939,7 +4132,7 @@ function PipelineEdgeInner({
3939
4132
  }
3940
4133
  );
3941
4134
  }
3942
- var PipelineEdge = react.memo(PipelineEdgeInner);
4135
+ var PipelineEdge = React.memo(PipelineEdgeInner);
3943
4136
  var logicFlowEdgeTypes = {
3944
4137
  conditionEdge: ConditionEdge,
3945
4138
  pipelineEdge: PipelineEdge
@@ -3977,30 +4170,30 @@ function removeConditionForSource(showIf, sourceFieldId) {
3977
4170
  }
3978
4171
  var defaultEdgeOptions = {
3979
4172
  markerEnd: {
3980
- type: react$1.MarkerType.ArrowClosed,
4173
+ type: react.MarkerType.ArrowClosed,
3981
4174
  width: 16,
3982
4175
  height: 12
3983
4176
  }
3984
4177
  };
3985
4178
  function LogicFlowEditor({ schema, onChange }) {
3986
4179
  const noSections = schema.sections.length === 0;
3987
- const flowGraph = react.useMemo(() => buildReactFlowGraph(schema), [schema]);
3988
- const [nodes, setNodes, onNodesChange] = react$1.useNodesState(flowGraph.nodes);
3989
- const [edges, setEdges, onEdgesChange] = react$1.useEdgesState(flowGraph.edges);
3990
- const [selectedFieldId, setSelectedFieldId] = react.useState(null);
4180
+ const flowGraph = React.useMemo(() => buildReactFlowGraph(schema), [schema]);
4181
+ const [nodes, setNodes, onNodesChange] = react.useNodesState(flowGraph.nodes);
4182
+ const [edges, setEdges, onEdgesChange] = react.useEdgesState(flowGraph.edges);
4183
+ const [selectedFieldId, setSelectedFieldId] = React.useState(null);
3991
4184
  const selectedQuestion = selectedFieldId ? findQuestion2(schema, selectedFieldId) : void 0;
3992
- react.useEffect(() => {
4185
+ React.useEffect(() => {
3993
4186
  setNodes(flowGraph.nodes);
3994
4187
  setEdges(flowGraph.edges);
3995
4188
  }, [flowGraph, setNodes, setEdges]);
3996
- const sectionIds = react.useMemo(() => {
4189
+ const sectionIds = React.useMemo(() => {
3997
4190
  const ids = [];
3998
4191
  for (const section of schema.sections) {
3999
4192
  ids.push(section.id);
4000
4193
  }
4001
4194
  return ids;
4002
4195
  }, [schema]);
4003
- const onNodeClick = react.useCallback(
4196
+ const onNodeClick = React.useCallback(
4004
4197
  (_event, node) => {
4005
4198
  if (node.type === "fieldNode") {
4006
4199
  setSelectedFieldId(node.id);
@@ -4008,7 +4201,7 @@ function LogicFlowEditor({ schema, onChange }) {
4008
4201
  },
4009
4202
  []
4010
4203
  );
4011
- const onConnect = react.useCallback(
4204
+ const onConnect = React.useCallback(
4012
4205
  (connection) => {
4013
4206
  if (!connection.source || !connection.target) return;
4014
4207
  const targetQuestion = findQuestion2(schema, connection.target);
@@ -4035,7 +4228,7 @@ function LogicFlowEditor({ schema, onChange }) {
4035
4228
  },
4036
4229
  [schema, onChange]
4037
4230
  );
4038
- const onEdgesDelete = react.useCallback(
4231
+ const onEdgesDelete = React.useCallback(
4039
4232
  (deletedEdges) => {
4040
4233
  let updatedSchema = schema;
4041
4234
  for (const edge of deletedEdges) {
@@ -4060,7 +4253,7 @@ function LogicFlowEditor({ schema, onChange }) {
4060
4253
  },
4061
4254
  [schema, onChange]
4062
4255
  );
4063
- const handleConditionUpdate = react.useCallback(
4256
+ const handleConditionUpdate = React.useCallback(
4064
4257
  (updates) => {
4065
4258
  if (!selectedFieldId) return;
4066
4259
  const updatedSchema = updateQuestionInSchema(schema, selectedFieldId, updates);
@@ -4074,18 +4267,18 @@ function LogicFlowEditor({ schema, onChange }) {
4074
4267
  const jumpCount = flowGraph.edges.filter(
4075
4268
  (e) => e.data?.edgeType === "onExit"
4076
4269
  ).length;
4077
- const totalFields = react.useMemo(
4270
+ const totalFields = React.useMemo(
4078
4271
  () => schema.sections.reduce((sum, s) => sum + s.questions.length, 0),
4079
4272
  [schema]
4080
4273
  );
4081
- const conditionalFields = react.useMemo(
4274
+ const conditionalFields = React.useMemo(
4082
4275
  () => schema.sections.reduce(
4083
4276
  (sum, s) => sum + s.questions.filter((q) => !!q.showIf).length,
4084
4277
  0
4085
4278
  ),
4086
4279
  [schema]
4087
4280
  );
4088
- return /* @__PURE__ */ jsxRuntime.jsx(react$1.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
4281
+ return /* @__PURE__ */ jsxRuntime.jsx(react.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
4089
4282
  LogicFlowInner,
4090
4283
  {
4091
4284
  noSections,
@@ -4129,7 +4322,7 @@ function LogicFlowInner({
4129
4322
  totalFields,
4130
4323
  conditionalFields
4131
4324
  }) {
4132
- const { zoomIn, zoomOut, fitView } = react$1.useReactFlow();
4325
+ const { zoomIn, zoomOut, fitView } = react.useReactFlow();
4133
4326
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col bg-background min-h-0", children: [
4134
4327
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 h-9 flex items-center justify-between px-4 border-b border-border bg-card/50", children: [
4135
4328
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground", children: [
@@ -4157,7 +4350,7 @@ function LogicFlowInner({
4157
4350
  /* @__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." })
4158
4351
  ] }) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex min-h-0", children: [
4159
4352
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntime.jsxs(
4160
- react$1.ReactFlow,
4353
+ react.ReactFlow,
4161
4354
  {
4162
4355
  nodes,
4163
4356
  edges,
@@ -4174,9 +4367,9 @@ function LogicFlowInner({
4174
4367
  deleteKeyCode: ["Backspace", "Delete"],
4175
4368
  proOptions: { hideAttribution: true },
4176
4369
  children: [
4177
- /* @__PURE__ */ jsxRuntime.jsx(react$1.Background, { gap: 20, size: 1 }),
4370
+ /* @__PURE__ */ jsxRuntime.jsx(react.Background, { gap: 20, size: 1 }),
4178
4371
  /* @__PURE__ */ jsxRuntime.jsx(
4179
- react$1.MiniMap,
4372
+ react.MiniMap,
4180
4373
  {
4181
4374
  nodeColor: (node) => {
4182
4375
  const d = node.data;
@@ -4240,15 +4433,15 @@ function LogicFlowInner({
4240
4433
  ] });
4241
4434
  }
4242
4435
  function TemplateGallery({ templates, onSelect, onClose }) {
4243
- const [search, setSearch] = react.useState("");
4244
- const [activeCategory, setActiveCategory] = react.useState("all");
4245
- const [confirmTemplate, setConfirmTemplate] = react.useState(null);
4246
- const categories = react.useMemo(() => {
4436
+ const [search, setSearch] = React.useState("");
4437
+ const [activeCategory, setActiveCategory] = React.useState("all");
4438
+ const [confirmTemplate, setConfirmTemplate] = React.useState(null);
4439
+ const categories = React.useMemo(() => {
4247
4440
  const cats = /* @__PURE__ */ new Set();
4248
4441
  for (const t of templates) cats.add(t.meta.category);
4249
4442
  return ["all", ...Array.from(cats)];
4250
4443
  }, [templates]);
4251
- const filtered = react.useMemo(() => {
4444
+ const filtered = React.useMemo(() => {
4252
4445
  return templates.filter((t) => {
4253
4446
  const matchesCategory = activeCategory === "all" || t.meta.category === activeCategory;
4254
4447
  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()));
@@ -4344,9 +4537,9 @@ function TemplateGallery({ templates, onSelect, onClose }) {
4344
4537
  ] }) });
4345
4538
  }
4346
4539
  function useDebouncedValidation(delayMs = 500) {
4347
- const [errors, setErrors] = react.useState([]);
4348
- const timerRef = react.useRef(null);
4349
- const validate = react.useCallback(
4540
+ const [errors, setErrors] = React.useState([]);
4541
+ const timerRef = React.useRef(null);
4542
+ const validate = React.useCallback(
4350
4543
  (text) => {
4351
4544
  if (timerRef.current) {
4352
4545
  clearTimeout(timerRef.current);
@@ -4395,9 +4588,9 @@ function useDebouncedValidation(delayMs = 500) {
4395
4588
  );
4396
4589
  return { errors, validate };
4397
4590
  }
4398
- var ThemeCtx = react.createContext({});
4591
+ var ThemeCtx = React.createContext({});
4399
4592
  function useBuilderTheme() {
4400
- return react.useContext(ThemeCtx);
4593
+ return React.useContext(ThemeCtx);
4401
4594
  }
4402
4595
  function themeToCssVars(theme) {
4403
4596
  const vars = {};
@@ -4433,10 +4626,10 @@ function themeToCssVars(theme) {
4433
4626
  }
4434
4627
  function FormBuilderThemeProvider({ theme, children }) {
4435
4628
  const resolved = theme ?? {};
4436
- const cssVars = react.useMemo(() => themeToCssVars(resolved), [resolved]);
4629
+ const cssVars = React.useMemo(() => themeToCssVars(resolved), [resolved]);
4437
4630
  return /* @__PURE__ */ jsxRuntime.jsx(ThemeCtx.Provider, { value: resolved, children: /* @__PURE__ */ jsxRuntime.jsx("div", { "data-fcb-root": "", style: cssVars, className: "w-full h-full", children }) });
4438
4631
  }
4439
- var FormBuilderErrorBoundary = class extends react.Component {
4632
+ var FormBuilderErrorBoundary = class extends React.Component {
4440
4633
  constructor(props) {
4441
4634
  super(props);
4442
4635
  this.state = { hasError: false, error: null };
@@ -4468,30 +4661,30 @@ var FormBuilderErrorBoundary = class extends react.Component {
4468
4661
  };
4469
4662
  function FormBuilderCore(props) {
4470
4663
  const { initialSchema = DEFAULT_SCHEMA, onChange, onSave, height = "100vh", theme, className, toolbarExtra, questionTypes, palette, preview, templates, schemaUrl } = props;
4471
- const [viewMode, setViewMode] = react.useState("design");
4472
- const [jsonText, setJsonText] = react.useState("");
4473
- const [jsonSwitchError, setJsonSwitchError] = react.useState(null);
4474
- const [showTemplateGallery, setShowTemplateGallery] = react.useState(false);
4475
- const [saveValidationErrors, setSaveValidationErrors] = react.useState(null);
4476
- const [schemaUrlLoading, setSchemaUrlLoading] = react.useState(!!schemaUrl);
4477
- const [schemaUrlError, setSchemaUrlError] = react.useState(null);
4664
+ const [viewMode, setViewMode] = React.useState("design");
4665
+ const [jsonText, setJsonText] = React.useState("");
4666
+ const [jsonSwitchError, setJsonSwitchError] = React.useState(null);
4667
+ const [showTemplateGallery, setShowTemplateGallery] = React.useState(false);
4668
+ const [saveValidationErrors, setSaveValidationErrors] = React.useState(null);
4669
+ const [schemaUrlLoading, setSchemaUrlLoading] = React.useState(!!schemaUrl);
4670
+ const [schemaUrlError, setSchemaUrlError] = React.useState(null);
4478
4671
  const { errors: jsonErrors, validate: validateJson } = useDebouncedValidation(400);
4479
4672
  const mergedQuestionTypes = questionTypes ? { ...QUESTION_TYPE_INFO, ...questionTypes } : QUESTION_TYPE_INFO;
4480
4673
  const builderState = useBuilderState(initialSchema);
4481
4674
  const dragDrop = useDragDrop(builderState);
4482
- const fileInputRef = react.useRef(null);
4483
- const [mobilePanel, setMobilePanel] = react.useState("none");
4484
- react.useEffect(() => {
4675
+ const fileInputRef = React.useRef(null);
4676
+ const [mobilePanel, setMobilePanel] = React.useState("none");
4677
+ React.useEffect(() => {
4485
4678
  if (builderState.selectedItem && window.innerWidth < 768) {
4486
4679
  setMobilePanel("properties");
4487
4680
  }
4488
4681
  }, [builderState.selectedItem]);
4489
- react.useEffect(() => {
4682
+ React.useEffect(() => {
4490
4683
  if (!dragDrop.activeDragItem && mobilePanel === "palette") {
4491
4684
  setMobilePanel("none");
4492
4685
  }
4493
4686
  }, [dragDrop.activeDragItem]);
4494
- react.useEffect(() => {
4687
+ React.useEffect(() => {
4495
4688
  if (!schemaUrl) return;
4496
4689
  let cancelled = false;
4497
4690
  setSchemaUrlLoading(true);
@@ -4521,12 +4714,12 @@ function FormBuilderCore(props) {
4521
4714
  cancelled = true;
4522
4715
  };
4523
4716
  }, [schemaUrl]);
4524
- react.useEffect(() => {
4717
+ React.useEffect(() => {
4525
4718
  if (onChange && builderState.isDirty) {
4526
4719
  onChange(builderState.schema);
4527
4720
  }
4528
4721
  }, [builderState.schema, builderState.isDirty, onChange]);
4529
- const handleSave = react.useCallback(() => {
4722
+ const handleSave = React.useCallback(() => {
4530
4723
  if (!onSave) return;
4531
4724
  try {
4532
4725
  fieldcraftCore.validateSchema(builderState.schema);
@@ -4541,7 +4734,7 @@ function FormBuilderCore(props) {
4541
4734
  }
4542
4735
  }
4543
4736
  }, [onSave, builderState]);
4544
- const handleExport = react.useCallback(() => {
4737
+ const handleExport = React.useCallback(() => {
4545
4738
  const json = JSON.stringify(builderState.schema, null, 2);
4546
4739
  const blob = new Blob([json], { type: "application/json" });
4547
4740
  const url = URL.createObjectURL(blob);
@@ -4551,10 +4744,10 @@ function FormBuilderCore(props) {
4551
4744
  a.click();
4552
4745
  URL.revokeObjectURL(url);
4553
4746
  }, [builderState.schema]);
4554
- const handleImport = react.useCallback(() => {
4747
+ const handleImport = React.useCallback(() => {
4555
4748
  fileInputRef.current?.click();
4556
4749
  }, []);
4557
- const handleFileChange = react.useCallback(
4750
+ const handleFileChange = React.useCallback(
4558
4751
  (e) => {
4559
4752
  const file = e.target.files?.[0];
4560
4753
  if (!file) return;
@@ -4581,7 +4774,7 @@ ${details}`);
4581
4774
  },
4582
4775
  [builderState]
4583
4776
  );
4584
- const handleViewModeChange = react.useCallback(
4777
+ const handleViewModeChange = React.useCallback(
4585
4778
  (newMode) => {
4586
4779
  setJsonSwitchError(null);
4587
4780
  if (viewMode === "json" && newMode !== "json") {
@@ -4607,7 +4800,7 @@ ${details}`);
4607
4800
  },
4608
4801
  [viewMode, jsonText, builderState]
4609
4802
  );
4610
- const handleKeyDown = react.useCallback(
4803
+ const handleKeyDown = React.useCallback(
4611
4804
  (e) => {
4612
4805
  const mod = e.metaKey || e.ctrlKey;
4613
4806
  const tag = e.target.tagName;
@@ -5095,19 +5288,104 @@ function FormBuilderInner(props) {
5095
5288
 
5096
5289
  // src/form-builder/components/FormBuilderGated.tsx
5097
5290
  var FormBuilder = requireLicense(FormBuilderInner, "FormBuilder");
5098
- function formatCurrency(amount, currency) {
5099
- if (amount == null) return "";
5100
- try {
5101
- return new Intl.NumberFormat(void 0, {
5102
- style: "currency",
5103
- currency: currency ?? "USD"
5104
- }).format(amount);
5105
- } catch {
5106
- return `${currency ?? "USD"} ${amount.toFixed(2)}`;
5291
+ function resolvePath(obj, path) {
5292
+ let current = obj;
5293
+ for (const key of path.split(".")) {
5294
+ if (current == null || typeof current !== "object") return void 0;
5295
+ current = current[key];
5107
5296
  }
5297
+ return current;
5298
+ }
5299
+ function isDarkTheme(theme) {
5300
+ const bg = theme.colors?.background ?? "#FFFFFF";
5301
+ let hex = bg.replace("#", "");
5302
+ if (hex.length === 3) {
5303
+ hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
5304
+ }
5305
+ if (hex.length < 6) return false;
5306
+ const r = parseInt(hex.slice(0, 2), 16);
5307
+ const g = parseInt(hex.slice(2, 4), 16);
5308
+ const b = parseInt(hex.slice(4, 6), 16);
5309
+ return 0.299 * r + 0.587 * g + 0.114 * b < 128;
5310
+ }
5311
+ function resolveAppearance(theme) {
5312
+ const c = theme.colors;
5313
+ const isDark = isDarkTheme(theme);
5314
+ return {
5315
+ theme: isDark ? "night" : "default",
5316
+ variables: {
5317
+ colorPrimary: c?.primary,
5318
+ colorBackground: c?.surface || c?.background,
5319
+ colorText: c?.text,
5320
+ colorDanger: c?.error,
5321
+ colorSuccess: c?.success || "#22c55e",
5322
+ borderRadius: theme.shape?.inputRadius || "6px",
5323
+ fontFamily: theme.typography?.fontFamily
5324
+ }
5325
+ };
5326
+ }
5327
+ var PAYKIT_STYLES = `
5328
+ [data-paykit-form] {
5329
+ display: flex;
5330
+ flex-direction: column;
5331
+ gap: 16px;
5332
+ }
5333
+ [data-paykit-submit] {
5334
+ display: inline-flex;
5335
+ align-items: center;
5336
+ justify-content: center;
5337
+ width: 100%;
5338
+ padding: 10px 20px;
5339
+ font-size: 0.9375rem;
5340
+ font-weight: 600;
5341
+ font-family: var(--paykit-font-family, inherit);
5342
+ line-height: 1.5;
5343
+ color: #fff;
5344
+ background: var(--paykit-color-primary, #635BFF);
5345
+ border: none;
5346
+ border-radius: var(--paykit-border-radius, 6px);
5347
+ cursor: pointer;
5348
+ transition: opacity 150ms ease, box-shadow 150ms ease, filter 150ms ease;
5349
+ }
5350
+ [data-paykit-submit]:hover:not(:disabled) {
5351
+ filter: brightness(1.1);
5352
+ box-shadow: 0 2px 8px color-mix(in srgb, var(--paykit-color-primary, #635BFF) 35%, transparent);
5353
+ }
5354
+ [data-paykit-submit]:active:not(:disabled) {
5355
+ filter: brightness(0.95);
5356
+ }
5357
+ [data-paykit-submit]:disabled {
5358
+ opacity: 0.5;
5359
+ cursor: not-allowed;
5360
+ }
5361
+ `;
5362
+ var paykitStylesInjected = false;
5363
+ function injectPayKitStyles() {
5364
+ if (paykitStylesInjected || typeof document === "undefined") return;
5365
+ const style = document.createElement("style");
5366
+ style.setAttribute("data-paykit-pro", "");
5367
+ style.textContent = PAYKIT_STYLES;
5368
+ document.head.appendChild(style);
5369
+ paykitStylesInjected = true;
5370
+ }
5371
+ function formatCurrency(amountCents, currency) {
5372
+ if (amountCents == null) return "";
5373
+ return paykit.formatAmount(amountCents, currency ?? "USD");
5108
5374
  }
5109
5375
  function ProPaymentField(props) {
5110
- const { field, value, error, touched, disabled, readonly, onChange, onBlur, customProps } = props;
5376
+ injectPayKitStyles();
5377
+ const {
5378
+ field,
5379
+ value,
5380
+ error,
5381
+ touched,
5382
+ disabled,
5383
+ readonly,
5384
+ onChange,
5385
+ onBlur,
5386
+ customProps,
5387
+ theme: formTheme
5388
+ } = props;
5111
5389
  const config = field.config;
5112
5390
  const current = value ?? { status: "pending" };
5113
5391
  const provider = config?.provider ?? "stripe";
@@ -5118,42 +5396,88 @@ function ProPaymentField(props) {
5118
5396
  const onCreateIntent = customProps?.onCreatePaymentIntent;
5119
5397
  const onPaymentComplete = customProps?.onPaymentComplete;
5120
5398
  const serverUrl = config?.serverUrl;
5121
- const [clientSecret, setClientSecret] = react.useState(directSecret);
5122
- const [intentLoading, setIntentLoading] = react.useState(false);
5123
- const [intentError, setIntentError] = react.useState(null);
5399
+ const [clientSecret, setClientSecret] = React.useState(directSecret);
5400
+ const [intentLoading, setIntentLoading] = React.useState(false);
5401
+ const [intentError, setIntentError] = React.useState(null);
5124
5402
  const mode = directSecret ? "direct" : onCreateIntent ? "callback" : serverUrl ? "url" : "setup";
5125
- react.useEffect(() => {
5403
+ React.useEffect(() => {
5126
5404
  if (directSecret) {
5127
5405
  setClientSecret(directSecret);
5128
5406
  return;
5129
5407
  }
5130
5408
  if (mode === "setup" || !amount || !publicKey) return;
5131
5409
  if (clientSecret) return;
5410
+ let cancelled = false;
5411
+ const controller = mode === "url" ? new AbortController() : void 0;
5132
5412
  const fetchIntent = async () => {
5133
5413
  setIntentLoading(true);
5134
5414
  setIntentError(null);
5135
5415
  try {
5136
5416
  if (mode === "callback" && onCreateIntent) {
5137
- const result = await onCreateIntent({ amount, currency, provider, metadata: { fieldId: field.id } });
5138
- setClientSecret(result.clientSecret);
5417
+ const result = await onCreateIntent({
5418
+ amount,
5419
+ currency,
5420
+ provider,
5421
+ metadata: { fieldId: field.id }
5422
+ });
5423
+ if (!cancelled) setClientSecret(result.clientSecret);
5139
5424
  } else if (mode === "url" && serverUrl) {
5140
5425
  const res = await fetch(serverUrl, {
5141
5426
  method: "POST",
5142
5427
  headers: { "Content-Type": "application/json" },
5143
- body: JSON.stringify({ amount, currency, provider, metadata: { fieldId: field.id } })
5428
+ body: JSON.stringify({ amount, currency, provider, metadata: { fieldId: field.id } }),
5429
+ signal: controller?.signal
5144
5430
  });
5145
5431
  if (!res.ok) throw new Error(`Server error (${res.status})`);
5146
5432
  const data = await res.json();
5147
- setClientSecret(data.clientSecret);
5433
+ const secretPath = config?.responseMapping?.clientSecretPath;
5434
+ const secret = secretPath ? resolvePath(data, secretPath) : data.clientSecret;
5435
+ if (!secret)
5436
+ throw new Error(
5437
+ "No clientSecret in response" + (secretPath ? ` at path "${secretPath}"` : "")
5438
+ );
5439
+ if (!cancelled) setClientSecret(secret);
5148
5440
  }
5149
5441
  } catch (err) {
5442
+ if (cancelled) return;
5150
5443
  setIntentError(err instanceof Error ? err.message : "Failed to create payment intent");
5151
5444
  } finally {
5152
- setIntentLoading(false);
5445
+ if (!cancelled) setIntentLoading(false);
5153
5446
  }
5154
5447
  };
5155
5448
  fetchIntent();
5156
- }, [mode, amount, currency, provider, publicKey, directSecret, clientSecret, onCreateIntent, serverUrl, field.id]);
5449
+ return () => {
5450
+ cancelled = true;
5451
+ controller?.abort();
5452
+ };
5453
+ }, [
5454
+ mode,
5455
+ amount,
5456
+ currency,
5457
+ provider,
5458
+ publicKey,
5459
+ directSecret,
5460
+ clientSecret,
5461
+ onCreateIntent,
5462
+ serverUrl,
5463
+ field.id
5464
+ ]);
5465
+ const c = formTheme.colors;
5466
+ const cardStyle = {
5467
+ borderRadius: formTheme.shape?.inputRadius || "8px",
5468
+ border: `1px solid ${c?.border || "#e2e8f0"}`,
5469
+ padding: "16px",
5470
+ background: c?.surface || c?.background,
5471
+ color: c?.text
5472
+ };
5473
+ const mutedTextStyle = { color: c?.textMuted, fontSize: "0.875rem" };
5474
+ const badgeStyle = {
5475
+ fontSize: "0.75rem",
5476
+ padding: "2px 8px",
5477
+ borderRadius: formTheme.shape?.inputRadius || "4px",
5478
+ background: c?.secondary || c?.surface,
5479
+ color: c?.secondaryForeground || c?.textMuted
5480
+ };
5157
5481
  const handleSuccess = (chargeId) => {
5158
5482
  const result = { status: "succeeded", chargeId };
5159
5483
  onChange(result);
@@ -5168,7 +5492,8 @@ function ProPaymentField(props) {
5168
5492
  };
5169
5493
  if (!publicKey) {
5170
5494
  return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border-2 border-dashed border-input p-4 text-center", children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
5171
- "Payment field \u2014 configure a ",
5495
+ "Payment field \u2014 configure a",
5496
+ " ",
5172
5497
  /* @__PURE__ */ jsxRuntime.jsx("code", { className: "bg-muted px-1 rounded text-xs", children: "publicKey" }),
5173
5498
  " in the field properties panel."
5174
5499
  ] }) }) });
@@ -5181,40 +5506,97 @@ function ProPaymentField(props) {
5181
5506
  ] }) }) });
5182
5507
  }
5183
5508
  if (current.status === "succeeded") {
5184
- return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-input p-4", children: [
5185
- amount != null && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground mb-2", children: [
5509
+ return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: cardStyle, children: [
5510
+ amount != null && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { ...mutedTextStyle, marginBottom: "8px" }, children: [
5186
5511
  formatCurrency(amount, currency),
5187
5512
  config?.description && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
5188
5513
  " \u2014 ",
5189
5514
  config.description
5190
5515
  ] })
5191
5516
  ] }),
5192
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm font-medium", style: { color: "var(--success, #22c55e)" }, children: [
5193
- /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, width: 16, height: 16, children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" }) }),
5194
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
5195
- "Payment successful",
5196
- current.chargeId ? ` (${current.chargeId})` : ""
5197
- ] })
5198
- ] })
5517
+ /* @__PURE__ */ jsxRuntime.jsxs(
5518
+ "div",
5519
+ {
5520
+ style: {
5521
+ display: "flex",
5522
+ alignItems: "center",
5523
+ gap: "8px",
5524
+ fontSize: "0.875rem",
5525
+ fontWeight: 500,
5526
+ color: c?.success || "#22c55e"
5527
+ },
5528
+ children: [
5529
+ /* @__PURE__ */ jsxRuntime.jsx(
5530
+ "svg",
5531
+ {
5532
+ viewBox: "0 0 24 24",
5533
+ fill: "none",
5534
+ stroke: "currentColor",
5535
+ strokeWidth: 2,
5536
+ width: 16,
5537
+ height: 16,
5538
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" })
5539
+ }
5540
+ ),
5541
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
5542
+ "Payment successful",
5543
+ current.chargeId ? ` (${current.chargeId})` : ""
5544
+ ] })
5545
+ ]
5546
+ }
5547
+ )
5199
5548
  ] }) });
5200
5549
  }
5201
5550
  if (current.status === "failed") {
5202
- return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-destructive/50 p-4", children: [
5203
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-destructive font-medium", children: [
5204
- /* @__PURE__ */ jsxRuntime.jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, width: 16, height: 16, children: [
5205
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
5206
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
5207
- ] }),
5208
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
5209
- "Payment failed",
5210
- current.error ? `: ${current.error}` : ""
5211
- ] })
5212
- ] }),
5551
+ return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { ...cardStyle, borderColor: c?.error || "#dc2626" }, children: [
5552
+ /* @__PURE__ */ jsxRuntime.jsxs(
5553
+ "div",
5554
+ {
5555
+ style: {
5556
+ display: "flex",
5557
+ alignItems: "center",
5558
+ gap: "8px",
5559
+ fontSize: "0.875rem",
5560
+ fontWeight: 500,
5561
+ color: c?.error || "#dc2626"
5562
+ },
5563
+ children: [
5564
+ /* @__PURE__ */ jsxRuntime.jsxs(
5565
+ "svg",
5566
+ {
5567
+ viewBox: "0 0 24 24",
5568
+ fill: "none",
5569
+ stroke: "currentColor",
5570
+ strokeWidth: 2,
5571
+ width: 16,
5572
+ height: 16,
5573
+ children: [
5574
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
5575
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
5576
+ ]
5577
+ }
5578
+ ),
5579
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
5580
+ "Payment failed",
5581
+ current.error ? `: ${current.error}` : ""
5582
+ ] })
5583
+ ]
5584
+ }
5585
+ ),
5213
5586
  /* @__PURE__ */ jsxRuntime.jsx(
5214
5587
  "button",
5215
5588
  {
5216
5589
  type: "button",
5217
- className: "mt-2 text-xs text-primary hover:underline",
5590
+ style: {
5591
+ marginTop: "8px",
5592
+ fontSize: "0.75rem",
5593
+ color: c?.primary,
5594
+ background: "none",
5595
+ border: "none",
5596
+ cursor: "pointer",
5597
+ textDecoration: "underline",
5598
+ padding: 0
5599
+ },
5218
5600
  onClick: () => {
5219
5601
  onChange({ status: "pending" });
5220
5602
  setClientSecret(void 0);
@@ -5225,26 +5607,46 @@ function ProPaymentField(props) {
5225
5607
  ] }) });
5226
5608
  }
5227
5609
  if (intentLoading || mode !== "setup" && mode !== "direct" && !clientSecret) {
5228
- return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-input p-4", children: [
5229
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-3", children: [
5230
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: "Payment" }),
5231
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs bg-muted px-2 py-0.5 rounded", children: provider })
5232
- ] }),
5233
- amount != null && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground mb-3", children: [
5610
+ return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: cardStyle, children: [
5611
+ /* @__PURE__ */ jsxRuntime.jsxs(
5612
+ "div",
5613
+ {
5614
+ style: {
5615
+ display: "flex",
5616
+ alignItems: "center",
5617
+ justifyContent: "space-between",
5618
+ marginBottom: "12px"
5619
+ },
5620
+ children: [
5621
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.875rem", fontWeight: 500 }, children: "Payment" }),
5622
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: badgeStyle, children: provider })
5623
+ ]
5624
+ }
5625
+ ),
5626
+ amount != null && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { ...mutedTextStyle, marginBottom: "12px" }, children: [
5234
5627
  "Amount: ",
5235
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: formatCurrency(amount, currency) }),
5628
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 500 }, children: formatCurrency(amount, currency) }),
5236
5629
  config?.description && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
5237
5630
  " \u2014 ",
5238
5631
  config.description
5239
5632
  ] })
5240
5633
  ] }),
5241
5634
  intentError ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
5242
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: intentError }),
5635
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.875rem", color: c?.error || "#dc2626" }, children: intentError }),
5243
5636
  /* @__PURE__ */ jsxRuntime.jsx(
5244
5637
  "button",
5245
5638
  {
5246
5639
  type: "button",
5247
- className: "mt-2 text-xs text-primary hover:underline",
5640
+ style: {
5641
+ marginTop: "8px",
5642
+ fontSize: "0.75rem",
5643
+ color: c?.primary,
5644
+ background: "none",
5645
+ border: "none",
5646
+ cursor: "pointer",
5647
+ textDecoration: "underline",
5648
+ padding: 0
5649
+ },
5248
5650
  onClick: () => {
5249
5651
  setIntentError(null);
5250
5652
  setClientSecret(void 0);
@@ -5252,54 +5654,78 @@ function ProPaymentField(props) {
5252
5654
  children: "Retry"
5253
5655
  }
5254
5656
  )
5255
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
5256
- /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "animate-spin size-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", strokeDasharray: "60", strokeDashoffset: "20" }) }),
5657
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: "8px", ...mutedTextStyle }, children: [
5658
+ /* @__PURE__ */ jsxRuntime.jsx(
5659
+ "svg",
5660
+ {
5661
+ style: { width: "16px", height: "16px", animation: "spin 1s linear infinite" },
5662
+ viewBox: "0 0 24 24",
5663
+ fill: "none",
5664
+ stroke: "currentColor",
5665
+ strokeWidth: 2,
5666
+ children: /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", strokeDasharray: "60", strokeDashoffset: "20" })
5667
+ }
5668
+ ),
5257
5669
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Preparing payment..." })
5258
5670
  ] })
5259
5671
  ] }) });
5260
5672
  }
5261
5673
  if (!clientSecret) {
5262
5674
  const waitingForAmount = config?.amountField && !amount;
5263
- return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-input p-4", children: [
5264
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-3", children: [
5265
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: "Payment" }),
5266
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs bg-muted px-2 py-0.5 rounded", children: provider })
5267
- ] }),
5268
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: waitingForAmount ? "Select an option above to proceed with payment." : "Provide a clientSecret via customProps, an onCreatePaymentIntent callback, or a serverUrl." })
5675
+ return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: cardStyle, children: [
5676
+ /* @__PURE__ */ jsxRuntime.jsxs(
5677
+ "div",
5678
+ {
5679
+ style: {
5680
+ display: "flex",
5681
+ alignItems: "center",
5682
+ justifyContent: "space-between",
5683
+ marginBottom: "12px"
5684
+ },
5685
+ children: [
5686
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.875rem", fontWeight: 500 }, children: "Payment" }),
5687
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: badgeStyle, children: provider })
5688
+ ]
5689
+ }
5690
+ ),
5691
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: mutedTextStyle, children: waitingForAmount ? "Select an option above to proceed with payment." : "Provide a clientSecret via customProps, an onCreatePaymentIntent callback, or a serverUrl." })
5269
5692
  ] }) });
5270
5693
  }
5271
- return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-input p-4", children: [
5272
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-3", children: [
5273
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium", children: "Payment" }),
5274
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs bg-muted px-2 py-0.5 rounded", children: provider })
5275
- ] }),
5276
- amount != null && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground mb-3", children: [
5694
+ return /* @__PURE__ */ jsxRuntime.jsx(fieldcraftReact.FieldWrapper, { field, error, touched, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: cardStyle, children: [
5695
+ /* @__PURE__ */ jsxRuntime.jsxs(
5696
+ "div",
5697
+ {
5698
+ style: {
5699
+ display: "flex",
5700
+ alignItems: "center",
5701
+ justifyContent: "space-between",
5702
+ marginBottom: "12px"
5703
+ },
5704
+ children: [
5705
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.875rem", fontWeight: 500 }, children: "Payment" }),
5706
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: badgeStyle, children: provider })
5707
+ ]
5708
+ }
5709
+ ),
5710
+ amount != null && /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { ...mutedTextStyle, marginBottom: "12px" }, children: [
5277
5711
  "Amount: ",
5278
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: formatCurrency(amount, currency) }),
5712
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 500 }, children: formatCurrency(amount, currency) }),
5279
5713
  config?.description && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
5280
5714
  " \u2014 ",
5281
5715
  config.description
5282
5716
  ] })
5283
5717
  ] }),
5284
5718
  /* @__PURE__ */ jsxRuntime.jsx(
5285
- react.Suspense,
5719
+ PayKitCheckout,
5286
5720
  {
5287
- fallback: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground py-4", children: [
5288
- /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "animate-spin size-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", strokeDasharray: "60", strokeDashoffset: "20" }) }),
5289
- "Loading payment form..."
5290
- ] }),
5291
- children: /* @__PURE__ */ jsxRuntime.jsx(
5292
- PayKitCheckout,
5293
- {
5294
- publicKey,
5295
- clientSecret,
5296
- amount,
5297
- currency,
5298
- disabled: disabled || readonly,
5299
- onSuccess: handleSuccess,
5300
- onError: handleError
5301
- }
5302
- )
5721
+ publicKey,
5722
+ clientSecret,
5723
+ amount,
5724
+ currency,
5725
+ appearance: resolveAppearance(formTheme),
5726
+ disabled: disabled || readonly,
5727
+ onSuccess: handleSuccess,
5728
+ onError: handleError
5303
5729
  }
5304
5730
  )
5305
5731
  ] }) });
@@ -5309,48 +5735,17 @@ function PayKitCheckout({
5309
5735
  clientSecret,
5310
5736
  amount,
5311
5737
  currency,
5738
+ appearance,
5312
5739
  disabled,
5313
5740
  onSuccess,
5314
5741
  onError
5315
5742
  }) {
5316
- const [PayKit, setPayKit] = react.useState(null);
5317
- const [loadError, setLoadError] = react.useState(null);
5318
- react.useEffect(() => {
5319
- let cancelled = false;
5320
- Promise.all([
5321
- import('@squaredr/paykit-react'),
5322
- // @ts-expect-error — optional peer dep, types not available at build time
5323
- import('@squaredr/paykit/stripe/client')
5324
- ]).then(([paykit, stripe]) => {
5325
- if (cancelled) return;
5326
- setPayKit({
5327
- Provider: paykit.PayKitProvider,
5328
- Form: paykit.CheckoutForm,
5329
- adapter: new stripe.StripeClientAdapter(publicKey)
5330
- });
5331
- }).catch((err) => {
5332
- if (cancelled) return;
5333
- setLoadError(
5334
- `Failed to load payment SDK. Ensure @squaredr/paykit-react and @squaredr/paykit are installed. (${err.message})`
5335
- );
5336
- });
5337
- return () => {
5338
- cancelled = true;
5339
- };
5340
- }, [publicKey]);
5341
- if (loadError) {
5342
- return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: loadError });
5343
- }
5344
- if (!PayKit) {
5345
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-muted-foreground py-2", children: [
5346
- /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "animate-spin size-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10", strokeDasharray: "60", strokeDashoffset: "20" }) }),
5347
- "Loading Stripe..."
5348
- ] });
5349
- }
5350
- return /* @__PURE__ */ jsxRuntime.jsx(PayKit.Provider, { clientAdapter: PayKit.adapter, children: /* @__PURE__ */ jsxRuntime.jsx(
5351
- PayKit.Form,
5743
+ const clientAdapter = React.useMemo(() => new client.StripeClientAdapter(publicKey), [publicKey]);
5744
+ return /* @__PURE__ */ jsxRuntime.jsx(paykitReact.PayKitProvider, { clientAdapter, children: /* @__PURE__ */ jsxRuntime.jsx(
5745
+ paykitReact.CheckoutForm,
5352
5746
  {
5353
5747
  clientSecret,
5748
+ appearance,
5354
5749
  submitLabel: disabled ? "Payment disabled" : `Pay ${formatCurrency(amount, currency)}`,
5355
5750
  onSuccess: (result) => onSuccess(result.chargeId),
5356
5751
  onError: (err) => onError(err.message)
@@ -5360,40 +5755,155 @@ function PayKitCheckout({
5360
5755
  var PRO_FIELD_OVERRIDES = {
5361
5756
  payment: ProPaymentField
5362
5757
  };
5363
-
5364
- // src/response-viewer/clinical-display-data.ts
5365
- var BODY_REGION_LABELS = {
5366
- head: "Head",
5367
- neck: "Neck",
5368
- "left-shoulder": "Left Shoulder",
5369
- "right-shoulder": "Right Shoulder",
5370
- chest: "Chest",
5371
- abdomen: "Abdomen",
5372
- "left-upper-arm": "Left Upper Arm",
5373
- "right-upper-arm": "Right Upper Arm",
5374
- "left-forearm": "Left Forearm",
5375
- "right-forearm": "Right Forearm",
5376
- "left-hand": "Left Hand",
5377
- "right-hand": "Right Hand",
5378
- pelvis: "Pelvis",
5379
- "left-thigh": "Left Thigh",
5380
- "right-thigh": "Right Thigh",
5381
- "left-knee": "Left Knee",
5382
- "right-knee": "Right Knee",
5383
- "left-shin": "Left Shin",
5384
- "right-shin": "Right Shin",
5385
- "left-foot": "Left Foot",
5386
- "right-foot": "Right Foot"
5387
- };
5388
- var PAIN_FACE_LABELS = [
5389
- { score: 0, label: "No Hurt", color: "#22c55e" },
5390
- { score: 2, label: "Hurts Little Bit", color: "#84cc16" },
5391
- { score: 4, label: "Hurts Little More", color: "#eab308" },
5392
- { score: 6, label: "Hurts Even More", color: "#f97316" },
5393
- { score: 8, label: "Hurts Whole Lot", color: "#ef4444" },
5394
- { score: 10, label: "Hurts Worst", color: "#dc2626" }
5395
- ];
5396
- function getPainLabel(score) {
5758
+ function formatDuration(ms) {
5759
+ if (ms == null) return "\u2014";
5760
+ const totalSeconds = Math.round(ms / 1e3);
5761
+ if (totalSeconds < 60) return `${totalSeconds}s`;
5762
+ const minutes = Math.floor(totalSeconds / 60);
5763
+ const seconds = totalSeconds % 60;
5764
+ return `${minutes}m ${seconds}s`;
5765
+ }
5766
+ function countAnswered(values) {
5767
+ let count = 0;
5768
+ for (const v of Object.values(values)) {
5769
+ if (v !== void 0 && v !== null && v !== "") count++;
5770
+ }
5771
+ return count;
5772
+ }
5773
+ function getTotalFieldCount(schema) {
5774
+ let count = 0;
5775
+ for (const section of schema.sections) {
5776
+ for (const q of section.questions) {
5777
+ if (!DISPLAY_ONLY_TYPES.has(q.type)) count++;
5778
+ }
5779
+ }
5780
+ return count;
5781
+ }
5782
+ function ResponseTable({
5783
+ schema,
5784
+ responses,
5785
+ onRowClick,
5786
+ selectable,
5787
+ selectedIds,
5788
+ onToggleSelect,
5789
+ onSelectAll
5790
+ }) {
5791
+ const totalFields = getTotalFieldCount(schema);
5792
+ const allPageSelected = selectable && responses.length > 0 && responses.every(
5793
+ (r) => r.sessionToken && selectedIds?.has(r.sessionToken)
5794
+ );
5795
+ const colCount = 4 + (selectable ? 1 : 0);
5796
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse text-[13px]", children: [
5797
+ /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "bg-muted", children: [
5798
+ selectable && /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2 w-8 border-b-2 border-border", children: /* @__PURE__ */ jsxRuntime.jsx(
5799
+ "input",
5800
+ {
5801
+ type: "checkbox",
5802
+ checked: allPageSelected,
5803
+ onChange: () => onSelectAll?.(),
5804
+ className: "accent-primary"
5805
+ }
5806
+ ) }),
5807
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2 text-left font-semibold text-foreground border-b-2 border-border whitespace-nowrap", children: "Submitted" }),
5808
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2 text-left font-semibold text-foreground border-b-2 border-border whitespace-nowrap", children: "Completion Time" }),
5809
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2 text-left font-semibold text-foreground border-b-2 border-border whitespace-nowrap", children: "Fields Answered" }),
5810
+ /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2 text-left font-semibold text-foreground border-b-2 border-border whitespace-nowrap", children: "Score" })
5811
+ ] }) }),
5812
+ /* @__PURE__ */ jsxRuntime.jsxs("tbody", { children: [
5813
+ responses.map((response, idx) => {
5814
+ const answered = countAnswered(response.values);
5815
+ return /* @__PURE__ */ jsxRuntime.jsxs(
5816
+ "tr",
5817
+ {
5818
+ onClick: () => onRowClick?.(response),
5819
+ className: onRowClick ? "cursor-pointer border-b border-border hover:bg-accent transition-colors" : "border-b border-border",
5820
+ children: [
5821
+ selectable && /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 w-8", children: /* @__PURE__ */ jsxRuntime.jsx(
5822
+ "input",
5823
+ {
5824
+ type: "checkbox",
5825
+ checked: !!(response.sessionToken && selectedIds?.has(response.sessionToken)),
5826
+ onChange: (e) => {
5827
+ e.stopPropagation();
5828
+ if (response.sessionToken) onToggleSelect?.(response.sessionToken);
5829
+ },
5830
+ onClick: (e) => e.stopPropagation(),
5831
+ className: "accent-primary"
5832
+ }
5833
+ ) }),
5834
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-foreground whitespace-nowrap", children: new Date(response.submittedAt).toLocaleString() }),
5835
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-foreground whitespace-nowrap", children: formatDuration(response.completionTimeMs) }),
5836
+ /* @__PURE__ */ jsxRuntime.jsxs("td", { className: "px-3 py-2 text-foreground whitespace-nowrap", children: [
5837
+ answered,
5838
+ "/",
5839
+ totalFields
5840
+ ] }),
5841
+ /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-foreground whitespace-nowrap", children: response.totalScore ?? "\u2014" })
5842
+ ]
5843
+ },
5844
+ response.sessionToken || idx
5845
+ );
5846
+ }),
5847
+ responses.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
5848
+ "td",
5849
+ {
5850
+ colSpan: colCount,
5851
+ className: "px-3 py-8 text-center text-muted-foreground",
5852
+ children: "No responses yet"
5853
+ }
5854
+ ) })
5855
+ ] })
5856
+ ] }) });
5857
+ }
5858
+ var DISPLAY_ONLY_TYPES = /* @__PURE__ */ new Set([
5859
+ "info-block",
5860
+ "info_block",
5861
+ "section-header",
5862
+ "page-break",
5863
+ "image",
5864
+ "divider",
5865
+ "spacer",
5866
+ "video",
5867
+ "rich-text",
5868
+ "welcome-screen",
5869
+ "thank-you-screen",
5870
+ "hidden",
5871
+ "calculated"
5872
+ ]);
5873
+
5874
+ // src/response-viewer/clinical-display-data.ts
5875
+ var BODY_REGION_LABELS = {
5876
+ head: "Head",
5877
+ neck: "Neck",
5878
+ "left-shoulder": "Left Shoulder",
5879
+ "right-shoulder": "Right Shoulder",
5880
+ chest: "Chest",
5881
+ abdomen: "Abdomen",
5882
+ "left-upper-arm": "Left Upper Arm",
5883
+ "right-upper-arm": "Right Upper Arm",
5884
+ "left-forearm": "Left Forearm",
5885
+ "right-forearm": "Right Forearm",
5886
+ "left-hand": "Left Hand",
5887
+ "right-hand": "Right Hand",
5888
+ pelvis: "Pelvis",
5889
+ "left-thigh": "Left Thigh",
5890
+ "right-thigh": "Right Thigh",
5891
+ "left-knee": "Left Knee",
5892
+ "right-knee": "Right Knee",
5893
+ "left-shin": "Left Shin",
5894
+ "right-shin": "Right Shin",
5895
+ "left-foot": "Left Foot",
5896
+ "right-foot": "Right Foot"
5897
+ };
5898
+ var PAIN_FACE_LABELS = [
5899
+ { score: 0, label: "No Hurt", color: "#22c55e" },
5900
+ { score: 2, label: "Hurts Little Bit", color: "#84cc16" },
5901
+ { score: 4, label: "Hurts Little More", color: "#eab308" },
5902
+ { score: 6, label: "Hurts Even More", color: "#f97316" },
5903
+ { score: 8, label: "Hurts Whole Lot", color: "#ef4444" },
5904
+ { score: 10, label: "Hurts Worst", color: "#dc2626" }
5905
+ ];
5906
+ function getPainLabel(score) {
5397
5907
  const face = PAIN_FACE_LABELS.reduce(
5398
5908
  (closest, f) => closest == null || Math.abs(f.score - score) < Math.abs(closest.score - score) ? f : closest,
5399
5909
  void 0
@@ -5497,166 +6007,6 @@ function getScoreSeverity(instrumentKey, score) {
5497
6007
  if (!thresholds) return void 0;
5498
6008
  return thresholds.find((t) => score >= t.min && score <= t.max);
5499
6009
  }
5500
- function ResponseTable({
5501
- schema,
5502
- responses,
5503
- onRowClick,
5504
- selectable,
5505
- selectedIds,
5506
- onToggleSelect,
5507
- onSelectAll
5508
- }) {
5509
- const questions = getAllQuestions(schema);
5510
- const allPageSelected = selectable && responses.length > 0 && responses.every(
5511
- (r) => r.sessionToken && selectedIds?.has(r.sessionToken)
5512
- );
5513
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse text-[13px]", children: [
5514
- /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { className: "bg-muted", children: [
5515
- selectable && /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2 w-8 border-b-2 border-border", children: /* @__PURE__ */ jsxRuntime.jsx(
5516
- "input",
5517
- {
5518
- type: "checkbox",
5519
- checked: allPageSelected,
5520
- onChange: () => onSelectAll?.(),
5521
- className: "accent-primary"
5522
- }
5523
- ) }),
5524
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2 text-left font-semibold text-foreground border-b-2 border-border whitespace-nowrap", children: "Submitted" }),
5525
- questions.map((q) => /* @__PURE__ */ jsxRuntime.jsx(
5526
- "th",
5527
- {
5528
- className: "px-3 py-2 text-left font-semibold text-foreground border-b-2 border-border whitespace-nowrap",
5529
- children: q.label
5530
- },
5531
- q.id
5532
- )),
5533
- /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2 text-left font-semibold text-foreground border-b-2 border-border whitespace-nowrap", children: "Score" })
5534
- ] }) }),
5535
- /* @__PURE__ */ jsxRuntime.jsxs("tbody", { children: [
5536
- responses.map((response, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
5537
- "tr",
5538
- {
5539
- onClick: () => onRowClick?.(response),
5540
- className: onRowClick ? "cursor-pointer border-b border-border hover:bg-accent transition-colors" : "border-b border-border",
5541
- children: [
5542
- selectable && /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 w-8", children: /* @__PURE__ */ jsxRuntime.jsx(
5543
- "input",
5544
- {
5545
- type: "checkbox",
5546
- checked: !!(response.sessionToken && selectedIds?.has(response.sessionToken)),
5547
- onChange: (e) => {
5548
- e.stopPropagation();
5549
- if (response.sessionToken) onToggleSelect?.(response.sessionToken);
5550
- },
5551
- onClick: (e) => e.stopPropagation(),
5552
- className: "accent-primary"
5553
- }
5554
- ) }),
5555
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-foreground max-w-50 overflow-hidden text-ellipsis whitespace-nowrap", children: new Date(response.submittedAt).toLocaleString() }),
5556
- questions.map((q) => /* @__PURE__ */ jsxRuntime.jsx(
5557
- "td",
5558
- {
5559
- className: "px-3 py-2 text-foreground max-w-50 overflow-hidden text-ellipsis whitespace-nowrap",
5560
- children: formatCellValue(response.values[q.id], q.type)
5561
- },
5562
- q.id
5563
- )),
5564
- /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-foreground max-w-50 overflow-hidden text-ellipsis whitespace-nowrap", children: response.totalScore ?? "\u2014" })
5565
- ]
5566
- },
5567
- response.sessionToken || idx
5568
- )),
5569
- responses.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
5570
- "td",
5571
- {
5572
- colSpan: questions.length + 2 + (selectable ? 1 : 0),
5573
- className: "px-3 py-8 text-center text-muted-foreground",
5574
- children: "No responses yet"
5575
- }
5576
- ) })
5577
- ] })
5578
- ] }) });
5579
- }
5580
- function getAllQuestions(schema) {
5581
- const questions = [];
5582
- for (const section of schema.sections) {
5583
- for (const q of section.questions) {
5584
- if (q.type === "info-block" || q.type === "section-header" || q.type === "page-break") {
5585
- continue;
5586
- }
5587
- questions.push(q);
5588
- }
5589
- }
5590
- return questions;
5591
- }
5592
- function formatCellValue(value, type) {
5593
- if (value == null) return "\u2014";
5594
- if (type) {
5595
- switch (type) {
5596
- case "vitals_entry": {
5597
- if (typeof value !== "object" || value === null) break;
5598
- const v = value;
5599
- const parts = [];
5600
- if (v.systolicBp && v.diastolicBp) parts.push(`BP ${v.systolicBp}/${v.diastolicBp}`);
5601
- if (v.heartRate) parts.push(`HR ${v.heartRate}`);
5602
- if (v.temperature) parts.push(`${v.temperature}\xB0F`);
5603
- if (v.oxygenSaturation) parts.push(`SpO\u2082 ${v.oxygenSaturation}%`);
5604
- return parts.length > 0 ? parts.join(", ") : "\u2014";
5605
- }
5606
- case "medication_list":
5607
- if (Array.isArray(value)) return `${value.length} medication${value.length !== 1 ? "s" : ""}`;
5608
- break;
5609
- case "allergy_list":
5610
- if (Array.isArray(value)) return `${value.length} allerg${value.length !== 1 ? "ies" : "y"}`;
5611
- break;
5612
- case "body_diagram":
5613
- if (Array.isArray(value)) {
5614
- const labels = value.map((id) => BODY_REGION_LABELS[id] ?? id);
5615
- return labels.join(", ");
5616
- }
5617
- break;
5618
- case "pain_scale":
5619
- if (typeof value === "number") return `${value}/10`;
5620
- break;
5621
- case "bmi_calculator": {
5622
- if (typeof value !== "object" || value === null) break;
5623
- const d = value;
5624
- if (d.bmi != null) return `BMI ${d.bmi}`;
5625
- break;
5626
- }
5627
- case "payment": {
5628
- if (typeof value !== "object" || value === null) break;
5629
- const p = value;
5630
- const status = p.status;
5631
- return status ? status.charAt(0).toUpperCase() + status.slice(1) : "\u2014";
5632
- }
5633
- case "insurance_card": {
5634
- if (typeof value !== "object" || value === null) break;
5635
- const ins = value;
5636
- const parts = [ins.carrierId, ins.planName].filter(Boolean);
5637
- return parts.length > 0 ? parts.join(" \u2014 ") : "Card uploaded";
5638
- }
5639
- case "legal_name": {
5640
- if (typeof value !== "object" || value === null) break;
5641
- const n = value;
5642
- return [n.first, n.last].filter(Boolean).join(" ") || "\u2014";
5643
- }
5644
- case "address": {
5645
- if (typeof value !== "object" || value === null) break;
5646
- const a = value;
5647
- return [a.city, a.state].filter(Boolean).join(", ") || "\u2014";
5648
- }
5649
- case "consent":
5650
- return value === true || value === "true" || value === "agreed" ? "Agreed" : "Not agreed";
5651
- case "signature":
5652
- return typeof value === "string" && value.startsWith("data:image") ? "Signed" : "\u2014";
5653
- }
5654
- }
5655
- if (typeof value === "boolean") return value ? "Yes" : "No";
5656
- if (Array.isArray(value)) return value.join(", ");
5657
- if (typeof value === "object") return JSON.stringify(value);
5658
- return String(value);
5659
- }
5660
6010
  function ResponseCard({
5661
6011
  response,
5662
6012
  fields,
@@ -6144,7 +6494,7 @@ function formatFallbackValue(value) {
6144
6494
  return String(value);
6145
6495
  }
6146
6496
  function TimelineView({ responses, questions, onSelect }) {
6147
- const grouped = react.useMemo(() => groupByDay(responses), [responses]);
6497
+ const grouped = React.useMemo(() => groupByDay(responses), [responses]);
6148
6498
  if (responses.length === 0) {
6149
6499
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-8 text-center text-muted-foreground text-sm", children: "No responses to display." });
6150
6500
  }
@@ -6370,7 +6720,7 @@ function getStatsQuestions(schema) {
6370
6720
  return questions;
6371
6721
  }
6372
6722
  function StatsPanel({ schema, responses, onClose }) {
6373
- const stats = react.useMemo(() => computeStats(responses, schema), [responses, schema]);
6723
+ const stats = React.useMemo(() => computeStats(responses, schema), [responses, schema]);
6374
6724
  if (stats.totalCount === 0) {
6375
6725
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-3 text-sm text-muted-foreground", children: "No responses to compute statistics." });
6376
6726
  }
@@ -6523,9 +6873,9 @@ function getChartableFieldIds(schema) {
6523
6873
  return chartable;
6524
6874
  }
6525
6875
  function ChartPanel({ schema, responses, onClose }) {
6526
- const chartableFields = react.useMemo(() => getChartableFieldIds(schema), [schema]);
6527
- const [selectedFieldId, setSelectedFieldId] = react.useState(chartableFields[0]?.id ?? "");
6528
- const distribution = react.useMemo(() => {
6876
+ const chartableFields = React.useMemo(() => getChartableFieldIds(schema), [schema]);
6877
+ const [selectedFieldId, setSelectedFieldId] = React.useState(chartableFields[0]?.id ?? "");
6878
+ const distribution = React.useMemo(() => {
6529
6879
  if (!selectedFieldId) return [];
6530
6880
  return computeFieldDistribution(responses, selectedFieldId);
6531
6881
  }, [responses, selectedFieldId]);
@@ -6654,13 +7004,26 @@ function exportToJson(responses, filename = "responses.json") {
6654
7004
  const content = JSON.stringify(responses, null, 2);
6655
7005
  downloadBlob(content, filename, "application/json;charset=utf-8;");
6656
7006
  }
7007
+ var DISPLAY_ONLY_TYPES2 = /* @__PURE__ */ new Set([
7008
+ "info-block",
7009
+ "info_block",
7010
+ "section-header",
7011
+ "page-break",
7012
+ "image",
7013
+ "divider",
7014
+ "spacer",
7015
+ "video",
7016
+ "rich-text",
7017
+ "welcome-screen",
7018
+ "thank-you-screen",
7019
+ "hidden",
7020
+ "calculated"
7021
+ ]);
6657
7022
  function getExportableQuestions(schema) {
6658
7023
  const questions = [];
6659
7024
  for (const section of schema.sections) {
6660
7025
  for (const q of section.questions) {
6661
- if (q.type === "info-block" || q.type === "section-header" || q.type === "page-break") {
6662
- continue;
6663
- }
7026
+ if (DISPLAY_ONLY_TYPES2.has(q.type)) continue;
6664
7027
  questions.push(q);
6665
7028
  }
6666
7029
  }
@@ -6726,6 +7089,10 @@ function formatExportValue(value, type) {
6726
7089
  return String(value);
6727
7090
  }
6728
7091
  function escapeCsvField(field) {
7092
+ const first = field.charAt(0);
7093
+ if (first === "=" || first === "+" || first === "-" || first === "@" || first === " " || first === "\r") {
7094
+ field = `'${field}`;
7095
+ }
6729
7096
  if (field.includes(",") || field.includes('"') || field.includes("\n")) {
6730
7097
  return `"${field.replace(/"/g, '""')}"`;
6731
7098
  }
@@ -6740,7 +7107,7 @@ function downloadBlob(content, filename, mimeType) {
6740
7107
  document.body.appendChild(link);
6741
7108
  link.click();
6742
7109
  document.body.removeChild(link);
6743
- URL.revokeObjectURL(url);
7110
+ setTimeout(() => URL.revokeObjectURL(url), 1e4);
6744
7111
  }
6745
7112
 
6746
7113
  // src/response-viewer/pagination-utils.ts
@@ -6944,38 +7311,41 @@ function ResponseViewerInner({
6944
7311
  onBulkExport,
6945
7312
  selectable = false
6946
7313
  }) {
6947
- const [viewMode, setViewMode] = react.useState("table");
6948
- const [selectedResponse, setSelectedResponse] = react.useState(null);
6949
- const [currentPage, setCurrentPage] = react.useState(1);
6950
- const [effectivePageSize, setEffectivePageSize] = react.useState(pageSize);
6951
- const [filterState, setFilterState] = react.useState(createEmptyFilterState);
6952
- const [showFilterPanel, setShowFilterPanel] = react.useState(false);
6953
- const [searchQuery, setSearchQuery] = react.useState("");
6954
- const [showStats, setShowStats] = react.useState(false);
6955
- const [showCharts, setShowCharts] = react.useState(false);
6956
- const [selectedIds, setSelectedIds] = react.useState(/* @__PURE__ */ new Set());
6957
- const [confirmDialog, setConfirmDialog] = react.useState(null);
6958
- const [draftFieldId, setDraftFieldId] = react.useState("");
6959
- const [draftOperator, setDraftOperator] = react.useState("contains");
6960
- const [draftValue, setDraftValue] = react.useState("");
6961
- react.useEffect(() => {
7314
+ const [viewMode, setViewMode] = React.useState("table");
7315
+ const [selectedResponse, setSelectedResponse] = React.useState(null);
7316
+ const [currentPage, setCurrentPage] = React.useState(1);
7317
+ const [effectivePageSize, setEffectivePageSize] = React.useState(pageSize);
7318
+ const [filterState, setFilterState] = React.useState(createEmptyFilterState);
7319
+ const [showFilterPanel, setShowFilterPanel] = React.useState(false);
7320
+ const [searchQuery, setSearchQuery] = React.useState("");
7321
+ const [showStats, setShowStats] = React.useState(false);
7322
+ const [showCharts, setShowCharts] = React.useState(false);
7323
+ const [selectedIds, setSelectedIds] = React.useState(/* @__PURE__ */ new Set());
7324
+ const [confirmDialog, setConfirmDialog] = React.useState(null);
7325
+ const [draftFieldId, setDraftFieldId] = React.useState("");
7326
+ const [draftOperator, setDraftOperator] = React.useState("contains");
7327
+ const [draftValue, setDraftValue] = React.useState("");
7328
+ React.useEffect(() => {
6962
7329
  setCurrentPage(1);
6963
7330
  }, [responses]);
6964
- react.useEffect(() => {
7331
+ React.useEffect(() => {
6965
7332
  setEffectivePageSize(pageSize);
6966
7333
  setCurrentPage(1);
6967
7334
  }, [pageSize]);
6968
- react.useEffect(() => {
7335
+ React.useEffect(() => {
6969
7336
  setSelectedIds(/* @__PURE__ */ new Set());
6970
7337
  }, [responses]);
6971
- const searchedResponses = react.useMemo(
7338
+ const searchedResponses = React.useMemo(
6972
7339
  () => searchResponses(responses, searchQuery, schema),
6973
7340
  [responses, searchQuery, schema]
6974
7341
  );
6975
7342
  const isFiltered = hasActiveFilters(filterState);
6976
- const filteredResponses = applyFilters(searchedResponses, filterState);
7343
+ const filteredResponses = React.useMemo(
7344
+ () => applyFilters(searchedResponses, filterState),
7345
+ [searchedResponses, filterState]
7346
+ );
6977
7347
  const pag = paginate(filteredResponses, currentPage, effectivePageSize);
6978
- const questions = getAllQuestions2(schema);
7348
+ const questions = getAllQuestions(schema);
6979
7349
  const isSelectable = selectable && (!!onBulkDelete || !!onBulkExport);
6980
7350
  function handleSelect(response) {
6981
7351
  setSelectedResponse(response);
@@ -7077,7 +7447,7 @@ function ResponseViewerInner({
7077
7447
  });
7078
7448
  }
7079
7449
  function getFields(response) {
7080
- return questions.map((q) => ({
7450
+ return questions.filter((q) => response.values[q.id] !== void 0).map((q) => ({
7081
7451
  questionId: q.id,
7082
7452
  label: q.label,
7083
7453
  type: q.type,
@@ -7230,10 +7600,10 @@ function ResponseViewerInner({
7230
7600
  className: "h-7 text-xs",
7231
7601
  onClick: () => {
7232
7602
  const csvFilename = filename ? filename.replace(/\.\w+$/, ".csv") : "responses.csv";
7233
- exportToCsv(schema, responses, csvFilename, { dateFormat, columnLabels });
7234
- onExport?.("csv", responses.length);
7603
+ exportToCsv(schema, filteredResponses, csvFilename, { dateFormat, columnLabels });
7604
+ onExport?.("csv", filteredResponses.length);
7235
7605
  },
7236
- disabled: responses.length === 0,
7606
+ disabled: filteredResponses.length === 0,
7237
7607
  children: "Export CSV"
7238
7608
  }
7239
7609
  ),
@@ -7245,10 +7615,10 @@ function ResponseViewerInner({
7245
7615
  className: "h-7 text-xs",
7246
7616
  onClick: () => {
7247
7617
  const jsonFilename = filename ? filename.replace(/\.\w+$/, ".json") : "responses.json";
7248
- exportToJson(responses, jsonFilename);
7249
- onExport?.("json", responses.length);
7618
+ exportToJson(filteredResponses, jsonFilename);
7619
+ onExport?.("json", filteredResponses.length);
7250
7620
  },
7251
- disabled: responses.length === 0,
7621
+ disabled: filteredResponses.length === 0,
7252
7622
  children: "Export JSON"
7253
7623
  }
7254
7624
  )
@@ -7529,13 +7899,26 @@ function ResponseViewerInner({
7529
7899
  }
7530
7900
  );
7531
7901
  }
7532
- function getAllQuestions2(schema) {
7902
+ var DISPLAY_ONLY_TYPES3 = /* @__PURE__ */ new Set([
7903
+ "info-block",
7904
+ "info_block",
7905
+ "section-header",
7906
+ "page-break",
7907
+ "image",
7908
+ "divider",
7909
+ "spacer",
7910
+ "video",
7911
+ "rich-text",
7912
+ "welcome-screen",
7913
+ "thank-you-screen",
7914
+ "hidden",
7915
+ "calculated"
7916
+ ]);
7917
+ function getAllQuestions(schema) {
7533
7918
  const questions = [];
7534
7919
  for (const section of schema.sections) {
7535
7920
  for (const q of section.questions) {
7536
- if (q.type === "info-block" || q.type === "section-header" || q.type === "page-break") {
7537
- continue;
7538
- }
7921
+ if (DISPLAY_ONLY_TYPES3.has(q.type)) continue;
7539
7922
  questions.push(q);
7540
7923
  }
7541
7924
  }
@@ -7550,18 +7933,23 @@ var PREVIEW_SCHEMA = {
7550
7933
  id: "theme-preview",
7551
7934
  version: "1.0.0",
7552
7935
  title: "Theme Preview",
7553
- description: "See how your theme looks on a real form.",
7936
+ description: "See how your theme looks across every field type.",
7937
+ settings: {
7938
+ displayMode: "classic",
7939
+ showProgress: false
7940
+ },
7554
7941
  sections: [
7555
7942
  {
7556
- id: "s1",
7557
- title: "Contact Information",
7943
+ id: "s-text",
7944
+ title: "Text Inputs",
7558
7945
  questions: [
7559
7946
  {
7560
7947
  id: "name",
7561
7948
  type: "short_text",
7562
7949
  label: "Full Name",
7563
7950
  required: true,
7564
- placeholder: "Jane Doe"
7951
+ placeholder: "Jane Doe",
7952
+ helpText: "Enter your full legal name."
7565
7953
  },
7566
7954
  {
7567
7955
  id: "email",
@@ -7570,6 +7958,31 @@ var PREVIEW_SCHEMA = {
7570
7958
  required: true,
7571
7959
  placeholder: "jane@example.com"
7572
7960
  },
7961
+ {
7962
+ id: "phone",
7963
+ type: "phone",
7964
+ label: "Phone Number",
7965
+ placeholder: "(555) 123-4567"
7966
+ },
7967
+ {
7968
+ id: "website",
7969
+ type: "url",
7970
+ label: "Website",
7971
+ placeholder: "https://example.com"
7972
+ },
7973
+ {
7974
+ id: "bio",
7975
+ type: "long_text",
7976
+ label: "Bio / Notes",
7977
+ placeholder: "Tell us about yourself...",
7978
+ helpText: "Markdown is supported."
7979
+ }
7980
+ ]
7981
+ },
7982
+ {
7983
+ id: "s-selection",
7984
+ title: "Selection Fields",
7985
+ questions: [
7573
7986
  {
7574
7987
  id: "department",
7575
7988
  type: "dropdown",
@@ -7577,20 +7990,184 @@ var PREVIEW_SCHEMA = {
7577
7990
  options: [
7578
7991
  { label: "Engineering", value: "engineering" },
7579
7992
  { label: "Design", value: "design" },
7580
- { label: "Marketing", value: "marketing" }
7993
+ { label: "Marketing", value: "marketing" },
7994
+ { label: "Sales", value: "sales" }
7581
7995
  ]
7582
7996
  },
7583
7997
  {
7584
- id: "rating",
7585
- type: "rating",
7586
- label: "How would you rate this experience?",
7998
+ id: "role",
7999
+ type: "single_select",
8000
+ label: "Role",
8001
+ helpText: "Select one option.",
8002
+ options: [
8003
+ { label: "Individual Contributor", value: "ic" },
8004
+ { label: "Team Lead", value: "lead" },
8005
+ { label: "Manager", value: "manager" },
8006
+ { label: "Director", value: "director" }
8007
+ ],
8008
+ config: { type: "single_select", layout: "vertical" }
8009
+ },
8010
+ {
8011
+ id: "skills",
8012
+ type: "multi_select",
8013
+ label: "Skills",
8014
+ helpText: "Select all that apply.",
8015
+ options: [
8016
+ { label: "JavaScript", value: "js" },
8017
+ { label: "TypeScript", value: "ts" },
8018
+ { label: "Python", value: "py" },
8019
+ { label: "Rust", value: "rust" },
8020
+ { label: "Go", value: "go" }
8021
+ ],
8022
+ config: { type: "multi_select", layout: "vertical" }
8023
+ },
8024
+ {
8025
+ id: "newsletter",
8026
+ type: "boolean",
8027
+ label: "Subscribe to newsletter?",
8028
+ config: { type: "boolean", style: "toggle" }
8029
+ }
8030
+ ]
8031
+ },
8032
+ {
8033
+ id: "s-numeric",
8034
+ title: "Numeric & Rating",
8035
+ questions: [
8036
+ {
8037
+ id: "age",
8038
+ type: "number",
8039
+ label: "Age",
8040
+ placeholder: "25",
8041
+ config: { type: "number", min: 0, max: 150 }
8042
+ },
8043
+ {
8044
+ id: "satisfaction",
8045
+ type: "slider",
8046
+ label: "Satisfaction Level",
8047
+ config: { type: "slider", min: 0, max: 100, step: 5 }
8048
+ },
8049
+ {
8050
+ id: "rating",
8051
+ type: "rating",
8052
+ label: "Overall Rating",
7587
8053
  config: { type: "rating", max: 5 }
7588
8054
  },
7589
8055
  {
7590
- id: "notes",
7591
- type: "long_text",
7592
- label: "Additional Notes",
7593
- placeholder: "Any other feedback..."
8056
+ id: "nps",
8057
+ type: "nps",
8058
+ label: "How likely are you to recommend us?"
8059
+ },
8060
+ {
8061
+ id: "opinion",
8062
+ type: "opinion_scale",
8063
+ label: "How do you feel about the onboarding?",
8064
+ config: {
8065
+ type: "opinion_scale",
8066
+ min: 1,
8067
+ max: 5,
8068
+ minLabel: "Very Poor",
8069
+ maxLabel: "Excellent"
8070
+ }
8071
+ }
8072
+ ]
8073
+ },
8074
+ {
8075
+ id: "s-datetime",
8076
+ title: "Date & Time",
8077
+ questions: [
8078
+ {
8079
+ id: "dob",
8080
+ type: "date",
8081
+ label: "Date of Birth",
8082
+ config: { type: "date", disableFuture: true }
8083
+ },
8084
+ {
8085
+ id: "preferred_time",
8086
+ type: "time",
8087
+ label: "Preferred Time",
8088
+ config: { type: "time", format: "12h" }
8089
+ },
8090
+ {
8091
+ id: "travel_dates",
8092
+ type: "date_range",
8093
+ label: "Travel Dates"
8094
+ }
8095
+ ]
8096
+ },
8097
+ {
8098
+ id: "s-media",
8099
+ title: "Media & Files",
8100
+ questions: [
8101
+ {
8102
+ id: "resume",
8103
+ type: "file_upload",
8104
+ label: "Upload Resume",
8105
+ helpText: "PDF or DOCX, max 10 MB.",
8106
+ config: { type: "file_upload", maxFiles: 1, maxSizeMb: 10, accept: [".pdf", ".docx"] }
8107
+ },
8108
+ {
8109
+ id: "signature",
8110
+ type: "signature",
8111
+ label: "Signature",
8112
+ helpText: "Draw your signature below."
8113
+ }
8114
+ ]
8115
+ },
8116
+ {
8117
+ id: "s-advanced",
8118
+ title: "Advanced Fields",
8119
+ questions: [
8120
+ {
8121
+ id: "experience",
8122
+ type: "likert",
8123
+ label: "Rate the following aspects:",
8124
+ config: {
8125
+ type: "likert",
8126
+ labels: ["Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"]
8127
+ }
8128
+ },
8129
+ {
8130
+ id: "country",
8131
+ type: "country_select",
8132
+ label: "Country",
8133
+ config: { type: "country_select", showFlags: true }
8134
+ },
8135
+ {
8136
+ id: "consent",
8137
+ type: "consent",
8138
+ label: "Terms & Conditions",
8139
+ config: {
8140
+ type: "consent",
8141
+ text: "I agree to the Terms of Service and Privacy Policy.",
8142
+ checkboxLabel: "I agree"
8143
+ }
8144
+ }
8145
+ ]
8146
+ },
8147
+ {
8148
+ id: "s-content",
8149
+ title: "Content & Visual",
8150
+ questions: [
8151
+ {
8152
+ id: "info",
8153
+ type: "info_block",
8154
+ label: "This is an informational message block. It can be used to display important notices."
8155
+ },
8156
+ {
8157
+ id: "warning_info",
8158
+ type: "info_block",
8159
+ label: "Please double-check all information before submitting."
8160
+ },
8161
+ {
8162
+ id: "divider",
8163
+ type: "divider",
8164
+ label: ""
8165
+ },
8166
+ {
8167
+ id: "section_head",
8168
+ type: "section_header",
8169
+ label: "Section Header Example",
8170
+ config: { type: "section_header", level: "h3", showDivider: true }
7594
8171
  }
7595
8172
  ]
7596
8173
  }
@@ -7893,8 +8470,8 @@ var SWATCH_KEYS = [
7893
8470
  { key: "success", label: "Success" }
7894
8471
  ];
7895
8472
  function PaletteGenerator({ theme, onApply, onClose }) {
7896
- const [baseColor, setBaseColor] = react.useState(theme.colors?.primary ?? "#3b82f6");
7897
- const palette = react.useMemo(() => generatePalette(baseColor), [baseColor]);
8473
+ const [baseColor, setBaseColor] = React.useState(theme.colors?.primary ?? "#3b82f6");
8474
+ const palette = React.useMemo(() => generatePalette(baseColor), [baseColor]);
7898
8475
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fcte-palette", children: [
7899
8476
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fcte-palette__header", children: [
7900
8477
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "fcte-palette__title", children: "Generate Palette" }),
@@ -7949,148 +8526,458 @@ function PaletteGenerator({ theme, onApply, onClose }) {
7949
8526
  }
7950
8527
 
7951
8528
  // src/theme-editor/presets.ts
7952
- var cleanPreset = {
8529
+ var cleanLight = {
7953
8530
  colors: {
7954
- primary: "#1F6B6E",
8531
+ primary: "#2563EB",
7955
8532
  primaryForeground: "#FFFFFF",
7956
- secondary: "#B9D1CF",
7957
- secondaryForeground: "#12222A",
7958
- error: "#B04A3C",
8533
+ secondary: "#DBEAFE",
8534
+ secondaryForeground: "#1E3A5F",
8535
+ error: "#DC2626",
7959
8536
  errorForeground: "#FFFFFF",
7960
- warning: "#C98A2E",
7961
- success: "#2E7D5B",
8537
+ warning: "#D97706",
8538
+ success: "#16A34A",
7962
8539
  surface: "#FFFFFF",
7963
- background: "#F4F7F8",
7964
- text: "#12222A",
7965
- textMuted: "#6A7B85",
7966
- textDisabled: "#B9D1CF",
7967
- border: "#DCE4E8",
7968
- borderFocus: "#1F6B6E",
8540
+ background: "#F8FAFC",
8541
+ text: "#0F172A",
8542
+ textMuted: "#64748B",
8543
+ textDisabled: "#CBD5E1",
8544
+ border: "#E2E8F0",
8545
+ borderFocus: "#2563EB",
7969
8546
  inputBackground: "#FFFFFF"
7970
8547
  },
7971
8548
  typography: {
7972
8549
  fontFamily: "Inter, system-ui, sans-serif",
7973
8550
  scale: "comfortable",
7974
- questionSize: "1.125rem",
8551
+ questionSize: "1.0625rem",
7975
8552
  labelSize: "0.875rem",
7976
8553
  helpTextSize: "0.8125rem",
7977
8554
  bodySize: "0.9375rem"
7978
8555
  },
7979
- shape: { radius: "none", inputRadius: "0px", buttonRadius: "0px", cardRadius: "0px" },
8556
+ shape: { radius: "sm", inputRadius: "6px", buttonRadius: "6px", cardRadius: "8px" },
7980
8557
  spacing: { base: 16, sectionGap: 32, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
7981
- layout: { maxWidth: "640px", alignment: "left", progressPosition: "top", sectionLayout: "card" }
8558
+ layout: { maxWidth: "640px", alignment: "left", progressPosition: "top", sectionLayout: "flat" }
7982
8559
  };
7983
- var cleanDarkPreset = {
8560
+ var cleanDark = {
7984
8561
  colors: {
7985
- primary: "#63BDB4",
7986
- primaryForeground: "#0F1A1F",
7987
- secondary: "#2F4F4C",
7988
- secondaryForeground: "#E8EFF1",
7989
- error: "#E08072",
7990
- errorForeground: "#0F1A1F",
7991
- warning: "#E0A94F",
7992
- success: "#5DB89A",
7993
- surface: "#16242A",
7994
- background: "#0F1A1F",
7995
- text: "#E8EFF1",
7996
- textMuted: "#8CA1A9",
7997
- textDisabled: "#3D5259",
7998
- border: "#2A3B42",
7999
- borderFocus: "#63BDB4",
8000
- inputBackground: "#16242A"
8562
+ primary: "#60A5FA",
8563
+ primaryForeground: "#0C1929",
8564
+ secondary: "#1E3A5F",
8565
+ secondaryForeground: "#DBEAFE",
8566
+ error: "#F87171",
8567
+ errorForeground: "#1C1917",
8568
+ warning: "#FBBF24",
8569
+ success: "#4ADE80",
8570
+ surface: "#1E293B",
8571
+ background: "#0F172A",
8572
+ text: "#F1F5F9",
8573
+ textMuted: "#94A3B8",
8574
+ textDisabled: "#334155",
8575
+ border: "#334155",
8576
+ borderFocus: "#60A5FA",
8577
+ inputBackground: "#1E293B"
8001
8578
  },
8002
8579
  typography: {
8003
8580
  fontFamily: "Inter, system-ui, sans-serif",
8004
8581
  scale: "comfortable",
8005
- questionSize: "1.125rem",
8582
+ questionSize: "1.0625rem",
8583
+ labelSize: "0.875rem",
8584
+ helpTextSize: "0.8125rem",
8585
+ bodySize: "0.9375rem"
8586
+ },
8587
+ shape: { radius: "sm", inputRadius: "6px", buttonRadius: "6px", cardRadius: "8px" },
8588
+ spacing: { base: 16, sectionGap: 32, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
8589
+ layout: { maxWidth: "640px", alignment: "left", progressPosition: "top", sectionLayout: "flat" }
8590
+ };
8591
+ var stripeLight = {
8592
+ colors: {
8593
+ primary: "#635BFF",
8594
+ primaryForeground: "#FFFFFF",
8595
+ secondary: "#E8E6FF",
8596
+ secondaryForeground: "#32297D",
8597
+ error: "#DF1B41",
8598
+ errorForeground: "#FFFFFF",
8599
+ warning: "#D97706",
8600
+ success: "#30B130",
8601
+ surface: "#FFFFFF",
8602
+ background: "#F6F9FC",
8603
+ text: "#1A1F36",
8604
+ textMuted: "#697386",
8605
+ textDisabled: "#C1C9D2",
8606
+ border: "#E3E8EE",
8607
+ borderFocus: "#635BFF",
8608
+ inputBackground: "#FFFFFF"
8609
+ },
8610
+ typography: {
8611
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
8612
+ scale: "comfortable",
8613
+ questionSize: "1rem",
8006
8614
  labelSize: "0.875rem",
8007
8615
  helpTextSize: "0.8125rem",
8008
8616
  bodySize: "0.9375rem"
8009
8617
  },
8010
- shape: { radius: "none", inputRadius: "0px", buttonRadius: "0px", cardRadius: "0px" },
8618
+ shape: { radius: "md", inputRadius: "8px", buttonRadius: "8px", cardRadius: "12px" },
8011
8619
  spacing: { base: 16, sectionGap: 32, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
8012
8620
  layout: { maxWidth: "640px", alignment: "left", progressPosition: "top", sectionLayout: "card" }
8013
8621
  };
8014
- var modernPreset = {
8622
+ var stripeDark = {
8015
8623
  colors: {
8016
- primary: "#6366F1",
8017
- primaryForeground: "#ffffff",
8018
- secondary: "#8B5CF6",
8019
- secondaryForeground: "#ffffff",
8020
- error: "#F43F5E",
8021
- errorForeground: "#ffffff",
8022
- warning: "#F59E0B",
8023
- success: "#22C55E",
8024
- surface: "#ffffff",
8624
+ primary: "#7A73FF",
8625
+ primaryForeground: "#FFFFFF",
8626
+ secondary: "#2D2A5E",
8627
+ secondaryForeground: "#CBC8FF",
8628
+ error: "#F93A5E",
8629
+ errorForeground: "#FFFFFF",
8630
+ warning: "#FBBF24",
8631
+ success: "#4ADE80",
8632
+ surface: "#1C2033",
8633
+ background: "#0A0E1A",
8634
+ text: "#E3E5EA",
8635
+ textMuted: "#8992A7",
8636
+ textDisabled: "#3C4257",
8637
+ border: "#2C3046",
8638
+ borderFocus: "#7A73FF",
8639
+ inputBackground: "#1C2033"
8640
+ },
8641
+ typography: {
8642
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
8643
+ scale: "comfortable",
8644
+ questionSize: "1rem",
8645
+ labelSize: "0.875rem",
8646
+ helpTextSize: "0.8125rem",
8647
+ bodySize: "0.9375rem"
8648
+ },
8649
+ shape: { radius: "md", inputRadius: "8px", buttonRadius: "8px", cardRadius: "12px" },
8650
+ spacing: { base: 16, sectionGap: 32, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
8651
+ layout: { maxWidth: "640px", alignment: "left", progressPosition: "top", sectionLayout: "card" }
8652
+ };
8653
+ var githubLight = {
8654
+ colors: {
8655
+ primary: "#1F6FEB",
8656
+ primaryForeground: "#FFFFFF",
8657
+ secondary: "#DDF4FF",
8658
+ secondaryForeground: "#0550AE",
8659
+ error: "#CF222E",
8660
+ errorForeground: "#FFFFFF",
8661
+ warning: "#9A6700",
8662
+ success: "#1A7F37",
8663
+ surface: "#FFFFFF",
8664
+ background: "#F6F8FA",
8665
+ text: "#1F2328",
8666
+ textMuted: "#656D76",
8667
+ textDisabled: "#B1BAC4",
8668
+ border: "#D0D7DE",
8669
+ borderFocus: "#1F6FEB",
8670
+ inputBackground: "#FFFFFF"
8671
+ },
8672
+ typography: {
8673
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif",
8674
+ scale: "comfortable",
8675
+ questionSize: "1rem",
8676
+ labelSize: "0.875rem",
8677
+ helpTextSize: "0.75rem",
8678
+ bodySize: "0.875rem"
8679
+ },
8680
+ shape: { radius: "md", inputRadius: "6px", buttonRadius: "6px", cardRadius: "6px" },
8681
+ spacing: { base: 16, sectionGap: 28, fieldGap: 20, inputPaddingX: 12, inputPaddingY: 8 },
8682
+ layout: { maxWidth: "640px", alignment: "left", progressPosition: "top", sectionLayout: "bordered" }
8683
+ };
8684
+ var githubDark = {
8685
+ colors: {
8686
+ primary: "#58A6FF",
8687
+ primaryForeground: "#0D1117",
8688
+ secondary: "#172B4D",
8689
+ secondaryForeground: "#A5D6FF",
8690
+ error: "#F85149",
8691
+ errorForeground: "#0D1117",
8692
+ warning: "#E3B341",
8693
+ success: "#3FB950",
8694
+ surface: "#161B22",
8695
+ background: "#0D1117",
8696
+ text: "#E6EDF3",
8697
+ textMuted: "#8B949E",
8698
+ textDisabled: "#3D444D",
8699
+ border: "#30363D",
8700
+ borderFocus: "#58A6FF",
8701
+ inputBackground: "#161B22"
8702
+ },
8703
+ typography: {
8704
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif",
8705
+ scale: "comfortable",
8706
+ questionSize: "1rem",
8707
+ labelSize: "0.875rem",
8708
+ helpTextSize: "0.75rem",
8709
+ bodySize: "0.875rem"
8710
+ },
8711
+ shape: { radius: "md", inputRadius: "6px", buttonRadius: "6px", cardRadius: "6px" },
8712
+ spacing: { base: 16, sectionGap: 28, fieldGap: 20, inputPaddingX: 12, inputPaddingY: 8 },
8713
+ layout: { maxWidth: "640px", alignment: "left", progressPosition: "top", sectionLayout: "bordered" }
8714
+ };
8715
+ var vercelLight = {
8716
+ colors: {
8717
+ primary: "#000000",
8718
+ primaryForeground: "#FFFFFF",
8719
+ secondary: "#F5F5F5",
8720
+ secondaryForeground: "#171717",
8721
+ error: "#E5484D",
8722
+ errorForeground: "#FFFFFF",
8723
+ warning: "#F5A623",
8724
+ success: "#45A557",
8725
+ surface: "#FFFFFF",
8025
8726
  background: "#FAFAFA",
8026
- text: "#18181B",
8027
- textMuted: "#71717A",
8028
- textDisabled: "#D4D4D8",
8029
- border: "#E4E4E7",
8030
- borderFocus: "#6366F1",
8031
- inputBackground: "#FAFAFA"
8727
+ text: "#171717",
8728
+ textMuted: "#666666",
8729
+ textDisabled: "#C7C7C7",
8730
+ border: "#EAEAEA",
8731
+ borderFocus: "#000000",
8732
+ inputBackground: "#FFFFFF"
8032
8733
  },
8033
8734
  typography: {
8034
- fontFamily: "'Plus Jakarta Sans', Inter, system-ui, sans-serif",
8735
+ fontFamily: "'Geist', Inter, -apple-system, sans-serif",
8035
8736
  scale: "comfortable",
8036
- questionSize: "1.25rem",
8737
+ questionSize: "1rem",
8037
8738
  labelSize: "0.875rem",
8038
8739
  helpTextSize: "0.8125rem",
8039
- bodySize: "1rem"
8740
+ bodySize: "0.875rem"
8040
8741
  },
8041
- shape: { radius: "lg", inputRadius: "12px", buttonRadius: "12px", cardRadius: "16px" },
8042
- spacing: { base: 16, sectionGap: 40, fieldGap: 28, inputPaddingX: 16, inputPaddingY: 12 },
8043
- layout: { maxWidth: "680px", alignment: "center", progressPosition: "top", sectionLayout: "card" }
8742
+ shape: { radius: "md", inputRadius: "8px", buttonRadius: "8px", cardRadius: "12px" },
8743
+ spacing: { base: 16, sectionGap: 32, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
8744
+ layout: { maxWidth: "600px", alignment: "left", progressPosition: "top", sectionLayout: "flat" }
8745
+ };
8746
+ var vercelDark = {
8747
+ colors: {
8748
+ primary: "#FFFFFF",
8749
+ primaryForeground: "#000000",
8750
+ secondary: "#1A1A1A",
8751
+ secondaryForeground: "#EDEDED",
8752
+ error: "#E5484D",
8753
+ errorForeground: "#FFFFFF",
8754
+ warning: "#F5A623",
8755
+ success: "#45A557",
8756
+ surface: "#111111",
8757
+ background: "#000000",
8758
+ text: "#EDEDED",
8759
+ textMuted: "#888888",
8760
+ textDisabled: "#444444",
8761
+ border: "#333333",
8762
+ borderFocus: "#FFFFFF",
8763
+ inputBackground: "#111111"
8764
+ },
8765
+ typography: {
8766
+ fontFamily: "'Geist', Inter, -apple-system, sans-serif",
8767
+ scale: "comfortable",
8768
+ questionSize: "1rem",
8769
+ labelSize: "0.875rem",
8770
+ helpTextSize: "0.8125rem",
8771
+ bodySize: "0.875rem"
8772
+ },
8773
+ shape: { radius: "md", inputRadius: "8px", buttonRadius: "8px", cardRadius: "12px" },
8774
+ spacing: { base: 16, sectionGap: 32, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
8775
+ layout: { maxWidth: "600px", alignment: "left", progressPosition: "top", sectionLayout: "flat" }
8044
8776
  };
8045
- var modernDarkPreset = {
8777
+ var shopifyLight = {
8778
+ colors: {
8779
+ primary: "#008060",
8780
+ primaryForeground: "#FFFFFF",
8781
+ secondary: "#E3F1DF",
8782
+ secondaryForeground: "#1A4D2E",
8783
+ error: "#D72C0D",
8784
+ errorForeground: "#FFFFFF",
8785
+ warning: "#B98900",
8786
+ success: "#008060",
8787
+ surface: "#FFFFFF",
8788
+ background: "#F6F6F7",
8789
+ text: "#202223",
8790
+ textMuted: "#6D7175",
8791
+ textDisabled: "#BABEC3",
8792
+ border: "#C9CCCF",
8793
+ borderFocus: "#008060",
8794
+ inputBackground: "#FFFFFF"
8795
+ },
8796
+ typography: {
8797
+ fontFamily: "Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
8798
+ scale: "comfortable",
8799
+ questionSize: "1rem",
8800
+ labelSize: "0.875rem",
8801
+ helpTextSize: "0.8125rem",
8802
+ bodySize: "0.9375rem"
8803
+ },
8804
+ shape: { radius: "md", inputRadius: "8px", buttonRadius: "8px", cardRadius: "12px" },
8805
+ spacing: { base: 16, sectionGap: 32, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
8806
+ layout: { maxWidth: "640px", alignment: "left", progressPosition: "top", sectionLayout: "card" }
8807
+ };
8808
+ var shopifyDark = {
8809
+ colors: {
8810
+ primary: "#36D399",
8811
+ primaryForeground: "#0D2818",
8812
+ secondary: "#1A3A2A",
8813
+ secondaryForeground: "#B5E4CA",
8814
+ error: "#FE6B6B",
8815
+ errorForeground: "#1C1110",
8816
+ warning: "#FFD60A",
8817
+ success: "#36D399",
8818
+ surface: "#1A1C1E",
8819
+ background: "#111213",
8820
+ text: "#E3E5E7",
8821
+ textMuted: "#8C9196",
8822
+ textDisabled: "#44474A",
8823
+ border: "#333638",
8824
+ borderFocus: "#36D399",
8825
+ inputBackground: "#1A1C1E"
8826
+ },
8827
+ typography: {
8828
+ fontFamily: "Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
8829
+ scale: "comfortable",
8830
+ questionSize: "1rem",
8831
+ labelSize: "0.875rem",
8832
+ helpTextSize: "0.8125rem",
8833
+ bodySize: "0.9375rem"
8834
+ },
8835
+ shape: { radius: "md", inputRadius: "8px", buttonRadius: "8px", cardRadius: "12px" },
8836
+ spacing: { base: 16, sectionGap: 32, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
8837
+ layout: { maxWidth: "640px", alignment: "left", progressPosition: "top", sectionLayout: "card" }
8838
+ };
8839
+ var slackLight = {
8840
+ colors: {
8841
+ primary: "#611F69",
8842
+ primaryForeground: "#FFFFFF",
8843
+ secondary: "#F3E8F5",
8844
+ secondaryForeground: "#4A154B",
8845
+ error: "#E01E5A",
8846
+ errorForeground: "#FFFFFF",
8847
+ warning: "#ECB22E",
8848
+ success: "#2EB67D",
8849
+ surface: "#FFFFFF",
8850
+ background: "#F8F8F8",
8851
+ text: "#1D1C1D",
8852
+ textMuted: "#616061",
8853
+ textDisabled: "#B9B9B9",
8854
+ border: "#DDDDDD",
8855
+ borderFocus: "#611F69",
8856
+ inputBackground: "#FFFFFF"
8857
+ },
8858
+ typography: {
8859
+ fontFamily: "'Lato', 'Helvetica Neue', Helvetica, sans-serif",
8860
+ scale: "comfortable",
8861
+ questionSize: "1.0625rem",
8862
+ labelSize: "0.875rem",
8863
+ helpTextSize: "0.8125rem",
8864
+ bodySize: "0.9375rem"
8865
+ },
8866
+ shape: { radius: "md", inputRadius: "8px", buttonRadius: "8px", cardRadius: "10px" },
8867
+ spacing: { base: 16, sectionGap: 32, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
8868
+ layout: { maxWidth: "640px", alignment: "left", progressPosition: "top", sectionLayout: "card" }
8869
+ };
8870
+ var slackDark = {
8871
+ colors: {
8872
+ primary: "#D4A8DB",
8873
+ primaryForeground: "#1A0A1E",
8874
+ secondary: "#2C1332",
8875
+ secondaryForeground: "#E2C6E9",
8876
+ error: "#F5638B",
8877
+ errorForeground: "#1C0E14",
8878
+ warning: "#F0CA4D",
8879
+ success: "#4FCEA2",
8880
+ surface: "#1A1D21",
8881
+ background: "#0F1114",
8882
+ text: "#D1D2D3",
8883
+ textMuted: "#9B9C9E",
8884
+ textDisabled: "#4D4D4F",
8885
+ border: "#383A3E",
8886
+ borderFocus: "#D4A8DB",
8887
+ inputBackground: "#1A1D21"
8888
+ },
8889
+ typography: {
8890
+ fontFamily: "'Lato', 'Helvetica Neue', Helvetica, sans-serif",
8891
+ scale: "comfortable",
8892
+ questionSize: "1.0625rem",
8893
+ labelSize: "0.875rem",
8894
+ helpTextSize: "0.8125rem",
8895
+ bodySize: "0.9375rem"
8896
+ },
8897
+ shape: { radius: "md", inputRadius: "8px", buttonRadius: "8px", cardRadius: "10px" },
8898
+ spacing: { base: 16, sectionGap: 32, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
8899
+ layout: { maxWidth: "640px", alignment: "left", progressPosition: "top", sectionLayout: "card" }
8900
+ };
8901
+ var tailwindLight = {
8902
+ colors: {
8903
+ primary: "#4F46E5",
8904
+ primaryForeground: "#FFFFFF",
8905
+ secondary: "#EEF2FF",
8906
+ secondaryForeground: "#3730A3",
8907
+ error: "#DC2626",
8908
+ errorForeground: "#FFFFFF",
8909
+ warning: "#D97706",
8910
+ success: "#059669",
8911
+ surface: "#FFFFFF",
8912
+ background: "#F9FAFB",
8913
+ text: "#111827",
8914
+ textMuted: "#6B7280",
8915
+ textDisabled: "#D1D5DB",
8916
+ border: "#E5E7EB",
8917
+ borderFocus: "#4F46E5",
8918
+ inputBackground: "#FFFFFF"
8919
+ },
8920
+ typography: {
8921
+ fontFamily: "Inter, system-ui, sans-serif",
8922
+ scale: "comfortable",
8923
+ questionSize: "1rem",
8924
+ labelSize: "0.875rem",
8925
+ helpTextSize: "0.8125rem",
8926
+ bodySize: "0.875rem"
8927
+ },
8928
+ shape: { radius: "md", inputRadius: "8px", buttonRadius: "8px", cardRadius: "12px" },
8929
+ spacing: { base: 16, sectionGap: 32, fieldGap: 24, inputPaddingX: 14, inputPaddingY: 10 },
8930
+ layout: { maxWidth: "640px", alignment: "left", progressPosition: "top", sectionLayout: "card" }
8931
+ };
8932
+ var tailwindDark = {
8046
8933
  colors: {
8047
8934
  primary: "#818CF8",
8048
8935
  primaryForeground: "#1E1B4B",
8049
- secondary: "#A78BFA",
8050
- secondaryForeground: "#1E1B4B",
8051
- error: "#FB7185",
8052
- errorForeground: "#1E1B4B",
8936
+ secondary: "#1E1B4B",
8937
+ secondaryForeground: "#C7D2FE",
8938
+ error: "#F87171",
8939
+ errorForeground: "#1C1917",
8053
8940
  warning: "#FBBF24",
8054
- success: "#4ADE80",
8055
- surface: "#1E1B4B",
8056
- background: "#13111C",
8057
- text: "#E8E6F0",
8058
- textMuted: "#A1A1AA",
8059
- textDisabled: "#3F3F46",
8060
- border: "#2E2B4A",
8941
+ success: "#34D399",
8942
+ surface: "#1F2937",
8943
+ background: "#111827",
8944
+ text: "#F9FAFB",
8945
+ textMuted: "#9CA3AF",
8946
+ textDisabled: "#374151",
8947
+ border: "#374151",
8061
8948
  borderFocus: "#818CF8",
8062
- inputBackground: "#1E1B4B"
8949
+ inputBackground: "#1F2937"
8063
8950
  },
8064
8951
  typography: {
8065
- fontFamily: "'Plus Jakarta Sans', Inter, system-ui, sans-serif",
8952
+ fontFamily: "Inter, system-ui, sans-serif",
8066
8953
  scale: "comfortable",
8067
- questionSize: "1.25rem",
8954
+ questionSize: "1rem",
8068
8955
  labelSize: "0.875rem",
8069
8956
  helpTextSize: "0.8125rem",
8070
- bodySize: "1rem"
8957
+ bodySize: "0.875rem"
8071
8958
  },
8072
- shape: { radius: "lg", inputRadius: "12px", buttonRadius: "12px", cardRadius: "16px" },
8073
- spacing: { base: 16, sectionGap: 40, fieldGap: 28, inputPaddingX: 16, inputPaddingY: 12 },
8074
- layout: { maxWidth: "680px", alignment: "center", progressPosition: "top", sectionLayout: "card" }
8959
+ shape: { radius: "md", inputRadius: "8px", buttonRadius: "8px", cardRadius: "12px" },
8960
+ spacing: { base: 16, sectionGap: 32, fieldGap: 24, inputPaddingX: 14, inputPaddingY: 10 },
8961
+ layout: { maxWidth: "640px", alignment: "left", progressPosition: "top", sectionLayout: "card" }
8075
8962
  };
8076
- var clinicalPreset = {
8963
+ var clinicalLight = {
8077
8964
  colors: {
8078
- primary: "#0284C7",
8079
- primaryForeground: "#ffffff",
8080
- secondary: "#0891B2",
8081
- secondaryForeground: "#ffffff",
8082
- error: "#DC2626",
8083
- errorForeground: "#ffffff",
8084
- warning: "#D97706",
8085
- success: "#16A34A",
8086
- surface: "#ffffff",
8965
+ primary: "#0369A1",
8966
+ primaryForeground: "#FFFFFF",
8967
+ secondary: "#E0F2FE",
8968
+ secondaryForeground: "#0C4A6E",
8969
+ error: "#B91C1C",
8970
+ errorForeground: "#FFFFFF",
8971
+ warning: "#B45309",
8972
+ success: "#15803D",
8973
+ surface: "#FFFFFF",
8087
8974
  background: "#F0F9FF",
8088
8975
  text: "#0C4A6E",
8089
- textMuted: "#64748B",
8090
- textDisabled: "#CBD5E1",
8976
+ textMuted: "#4B6B82",
8977
+ textDisabled: "#BAD6E9",
8091
8978
  border: "#BAE6FD",
8092
- borderFocus: "#0284C7",
8093
- inputBackground: "#ffffff"
8979
+ borderFocus: "#0369A1",
8980
+ inputBackground: "#FFFFFF"
8094
8981
  },
8095
8982
  typography: {
8096
8983
  fontFamily: "'Source Sans 3', 'Segoe UI', system-ui, sans-serif",
@@ -8104,22 +8991,22 @@ var clinicalPreset = {
8104
8991
  spacing: { base: 16, sectionGap: 28, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
8105
8992
  layout: { maxWidth: "680px", alignment: "left", progressPosition: "top", sectionLayout: "bordered" }
8106
8993
  };
8107
- var clinicalDarkPreset = {
8994
+ var clinicalDark = {
8108
8995
  colors: {
8109
8996
  primary: "#38BDF8",
8110
8997
  primaryForeground: "#0C1929",
8111
- secondary: "#22D3EE",
8112
- secondaryForeground: "#0C1929",
8113
- error: "#F87171",
8114
- errorForeground: "#0C1929",
8115
- warning: "#FBBF24",
8116
- success: "#34D399",
8998
+ secondary: "#0C3554",
8999
+ secondaryForeground: "#BAE6FD",
9000
+ error: "#FCA5A5",
9001
+ errorForeground: "#1C1110",
9002
+ warning: "#FCD34D",
9003
+ success: "#6EE7B7",
8117
9004
  surface: "#0F2438",
8118
- background: "#0C1929",
9005
+ background: "#0B1929",
8119
9006
  text: "#E0F2FE",
8120
- textMuted: "#7DD3FC",
9007
+ textMuted: "#7DC4E8",
8121
9008
  textDisabled: "#1E3A5F",
8122
- border: "#1E3A5F",
9009
+ border: "#1C3A5A",
8123
9010
  borderFocus: "#38BDF8",
8124
9011
  inputBackground: "#0F2438"
8125
9012
  },
@@ -8135,86 +9022,210 @@ var clinicalDarkPreset = {
8135
9022
  spacing: { base: 16, sectionGap: 28, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
8136
9023
  layout: { maxWidth: "680px", alignment: "left", progressPosition: "top", sectionLayout: "bordered" }
8137
9024
  };
8138
- var playfulPreset = {
9025
+ var notionLight = {
8139
9026
  colors: {
8140
- primary: "#EC4899",
8141
- primaryForeground: "#ffffff",
8142
- secondary: "#8B5CF6",
8143
- secondaryForeground: "#ffffff",
8144
- error: "#EF4444",
8145
- errorForeground: "#ffffff",
8146
- warning: "#F59E0B",
8147
- success: "#10B981",
8148
- surface: "#ffffff",
8149
- background: "#FFF7ED",
8150
- text: "#1C1917",
9027
+ primary: "#2383E2",
9028
+ primaryForeground: "#FFFFFF",
9029
+ secondary: "#EBF5FB",
9030
+ secondaryForeground: "#1B4F7B",
9031
+ error: "#EB5757",
9032
+ errorForeground: "#FFFFFF",
9033
+ warning: "#CB912F",
9034
+ success: "#0F7B6C",
9035
+ surface: "#FFFFFF",
9036
+ background: "#FFFFFF",
9037
+ text: "#37352F",
9038
+ textMuted: "#787774",
9039
+ textDisabled: "#C3C2BF",
9040
+ border: "#E3E2E0",
9041
+ borderFocus: "#2383E2",
9042
+ inputBackground: "#F7F6F3"
9043
+ },
9044
+ typography: {
9045
+ fontFamily: "'Lyon Text', Georgia, 'Times New Roman', serif",
9046
+ scale: "comfortable",
9047
+ questionSize: "1.0625rem",
9048
+ labelSize: "0.875rem",
9049
+ helpTextSize: "0.8125rem",
9050
+ bodySize: "1rem"
9051
+ },
9052
+ shape: { radius: "sm", inputRadius: "4px", buttonRadius: "4px", cardRadius: "4px" },
9053
+ spacing: { base: 16, sectionGap: 32, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
9054
+ layout: { maxWidth: "680px", alignment: "left", progressPosition: "top", sectionLayout: "flat" }
9055
+ };
9056
+ var notionDark = {
9057
+ colors: {
9058
+ primary: "#529CCA",
9059
+ primaryForeground: "#FFFFFF",
9060
+ secondary: "#143046",
9061
+ secondaryForeground: "#9ECBEB",
9062
+ error: "#FF6B6B",
9063
+ errorForeground: "#1C1210",
9064
+ warning: "#E0AD50",
9065
+ success: "#4DAB9A",
9066
+ surface: "#2F3437",
9067
+ background: "#191919",
9068
+ text: "#E6E3DD",
9069
+ textMuted: "#9B9A97",
9070
+ textDisabled: "#4F4F4F",
9071
+ border: "#434343",
9072
+ borderFocus: "#529CCA",
9073
+ inputBackground: "#2F3437"
9074
+ },
9075
+ typography: {
9076
+ fontFamily: "'Lyon Text', Georgia, 'Times New Roman', serif",
9077
+ scale: "comfortable",
9078
+ questionSize: "1.0625rem",
9079
+ labelSize: "0.875rem",
9080
+ helpTextSize: "0.8125rem",
9081
+ bodySize: "1rem"
9082
+ },
9083
+ shape: { radius: "sm", inputRadius: "4px", buttonRadius: "4px", cardRadius: "4px" },
9084
+ spacing: { base: 16, sectionGap: 32, fieldGap: 24, inputPaddingX: 12, inputPaddingY: 10 },
9085
+ layout: { maxWidth: "680px", alignment: "left", progressPosition: "top", sectionLayout: "flat" }
9086
+ };
9087
+ var sunsetLight = {
9088
+ colors: {
9089
+ primary: "#C2410C",
9090
+ primaryForeground: "#FFFFFF",
9091
+ secondary: "#FFF7ED",
9092
+ secondaryForeground: "#7C2D12",
9093
+ error: "#B91C1C",
9094
+ errorForeground: "#FFFFFF",
9095
+ warning: "#A16207",
9096
+ success: "#15803D",
9097
+ surface: "#FFFFFF",
9098
+ background: "#FFFBF5",
9099
+ text: "#292524",
8151
9100
  textMuted: "#78716C",
8152
9101
  textDisabled: "#D6D3D1",
8153
- border: "#FDE68A",
8154
- borderFocus: "#EC4899",
8155
- inputBackground: "#FFFBEB"
9102
+ border: "#E7E5E4",
9103
+ borderFocus: "#C2410C",
9104
+ inputBackground: "#FFFFFF"
8156
9105
  },
8157
9106
  typography: {
8158
- fontFamily: "'Nunito', 'Comic Neue', system-ui, sans-serif",
8159
- scale: "spacious",
8160
- questionSize: "1.25rem",
8161
- labelSize: "0.9375rem",
8162
- helpTextSize: "0.875rem",
8163
- bodySize: "1rem"
9107
+ fontFamily: "'DM Sans', Inter, system-ui, sans-serif",
9108
+ scale: "comfortable",
9109
+ questionSize: "1.125rem",
9110
+ labelSize: "0.875rem",
9111
+ helpTextSize: "0.8125rem",
9112
+ bodySize: "0.9375rem"
8164
9113
  },
8165
- shape: { radius: "full", inputRadius: "9999px", buttonRadius: "9999px", cardRadius: "20px" },
8166
- spacing: { base: 18, sectionGap: 36, fieldGap: 28, inputPaddingX: 18, inputPaddingY: 12 },
8167
- layout: { maxWidth: "600px", alignment: "center", progressPosition: "top", sectionLayout: "card" }
9114
+ shape: { radius: "lg", inputRadius: "10px", buttonRadius: "10px", cardRadius: "14px" },
9115
+ spacing: { base: 16, sectionGap: 36, fieldGap: 26, inputPaddingX: 14, inputPaddingY: 11 },
9116
+ layout: { maxWidth: "640px", alignment: "center", progressPosition: "top", sectionLayout: "card" }
8168
9117
  };
8169
- var playfulDarkPreset = {
9118
+ var sunsetDark = {
8170
9119
  colors: {
8171
- primary: "#F472B6",
8172
- primaryForeground: "#1A0A14",
8173
- secondary: "#A78BFA",
8174
- secondaryForeground: "#1A0A14",
9120
+ primary: "#FB923C",
9121
+ primaryForeground: "#1C1210",
9122
+ secondary: "#3D1F0E",
9123
+ secondaryForeground: "#FED7AA",
8175
9124
  error: "#FCA5A5",
8176
- errorForeground: "#1A0A14",
9125
+ errorForeground: "#1C1210",
8177
9126
  warning: "#FCD34D",
8178
9127
  success: "#6EE7B7",
8179
- surface: "#2D1F2B",
8180
- background: "#1A0F19",
8181
- text: "#FDF2F8",
8182
- textMuted: "#D4A9C4",
8183
- textDisabled: "#4A3248",
8184
- border: "#5C3D56",
8185
- borderFocus: "#F472B6",
8186
- inputBackground: "#2D1F2B"
9128
+ surface: "#292019",
9129
+ background: "#1C1510",
9130
+ text: "#F5F0EB",
9131
+ textMuted: "#B0A89E",
9132
+ textDisabled: "#4A413A",
9133
+ border: "#3D352D",
9134
+ borderFocus: "#FB923C",
9135
+ inputBackground: "#292019"
9136
+ },
9137
+ typography: {
9138
+ fontFamily: "'DM Sans', Inter, system-ui, sans-serif",
9139
+ scale: "comfortable",
9140
+ questionSize: "1.125rem",
9141
+ labelSize: "0.875rem",
9142
+ helpTextSize: "0.8125rem",
9143
+ bodySize: "0.9375rem"
9144
+ },
9145
+ shape: { radius: "lg", inputRadius: "10px", buttonRadius: "10px", cardRadius: "14px" },
9146
+ spacing: { base: 16, sectionGap: 36, fieldGap: 26, inputPaddingX: 14, inputPaddingY: 11 },
9147
+ layout: { maxWidth: "640px", alignment: "center", progressPosition: "top", sectionLayout: "card" }
9148
+ };
9149
+ var roseLight = {
9150
+ colors: {
9151
+ primary: "#BE185D",
9152
+ primaryForeground: "#FFFFFF",
9153
+ secondary: "#FFF1F2",
9154
+ secondaryForeground: "#881337",
9155
+ error: "#DC2626",
9156
+ errorForeground: "#FFFFFF",
9157
+ warning: "#D97706",
9158
+ success: "#059669",
9159
+ surface: "#FFFFFF",
9160
+ background: "#FFFBFB",
9161
+ text: "#1C1917",
9162
+ textMuted: "#737373",
9163
+ textDisabled: "#D4D4D4",
9164
+ border: "#FECDD3",
9165
+ borderFocus: "#BE185D",
9166
+ inputBackground: "#FFFFFF"
8187
9167
  },
8188
9168
  typography: {
8189
- fontFamily: "'Nunito', 'Comic Neue', system-ui, sans-serif",
9169
+ fontFamily: "'Plus Jakarta Sans', Inter, system-ui, sans-serif",
8190
9170
  scale: "spacious",
8191
- questionSize: "1.25rem",
8192
- labelSize: "0.9375rem",
8193
- helpTextSize: "0.875rem",
8194
- bodySize: "1rem"
9171
+ questionSize: "1.1875rem",
9172
+ labelSize: "0.875rem",
9173
+ helpTextSize: "0.8125rem",
9174
+ bodySize: "0.9375rem"
8195
9175
  },
8196
- shape: { radius: "full", inputRadius: "9999px", buttonRadius: "9999px", cardRadius: "20px" },
8197
- spacing: { base: 18, sectionGap: 36, fieldGap: 28, inputPaddingX: 18, inputPaddingY: 12 },
8198
- layout: { maxWidth: "600px", alignment: "center", progressPosition: "top", sectionLayout: "card" }
9176
+ shape: { radius: "lg", inputRadius: "12px", buttonRadius: "12px", cardRadius: "16px" },
9177
+ spacing: { base: 18, sectionGap: 36, fieldGap: 28, inputPaddingX: 16, inputPaddingY: 12 },
9178
+ layout: { maxWidth: "640px", alignment: "center", progressPosition: "top", sectionLayout: "card" }
8199
9179
  };
8200
- var highContrastPreset = {
9180
+ var roseDark = {
8201
9181
  colors: {
8202
- primary: "#0000EE",
8203
- primaryForeground: "#ffffff",
8204
- secondary: "#6B21A8",
8205
- secondaryForeground: "#ffffff",
9182
+ primary: "#FB7185",
9183
+ primaryForeground: "#1C0A12",
9184
+ secondary: "#3B0A22",
9185
+ secondaryForeground: "#FECDD3",
9186
+ error: "#F87171",
9187
+ errorForeground: "#1C1210",
9188
+ warning: "#FBBF24",
9189
+ success: "#34D399",
9190
+ surface: "#1F1318",
9191
+ background: "#150D11",
9192
+ text: "#FAF0F2",
9193
+ textMuted: "#C9A4AE",
9194
+ textDisabled: "#4A3039",
9195
+ border: "#3D2030",
9196
+ borderFocus: "#FB7185",
9197
+ inputBackground: "#1F1318"
9198
+ },
9199
+ typography: {
9200
+ fontFamily: "'Plus Jakarta Sans', Inter, system-ui, sans-serif",
9201
+ scale: "spacious",
9202
+ questionSize: "1.1875rem",
9203
+ labelSize: "0.875rem",
9204
+ helpTextSize: "0.8125rem",
9205
+ bodySize: "0.9375rem"
9206
+ },
9207
+ shape: { radius: "lg", inputRadius: "12px", buttonRadius: "12px", cardRadius: "16px" },
9208
+ spacing: { base: 18, sectionGap: 36, fieldGap: 28, inputPaddingX: 16, inputPaddingY: 12 },
9209
+ layout: { maxWidth: "640px", alignment: "center", progressPosition: "top", sectionLayout: "card" }
9210
+ };
9211
+ var highContrastLight = {
9212
+ colors: {
9213
+ primary: "#0000CC",
9214
+ primaryForeground: "#FFFFFF",
9215
+ secondary: "#E6E6FF",
9216
+ secondaryForeground: "#000066",
8206
9217
  error: "#B91C1C",
8207
- errorForeground: "#ffffff",
8208
- warning: "#92400E",
9218
+ errorForeground: "#FFFFFF",
9219
+ warning: "#854D0E",
8209
9220
  success: "#166534",
8210
- surface: "#ffffff",
8211
- background: "#ffffff",
9221
+ surface: "#FFFFFF",
9222
+ background: "#FFFFFF",
8212
9223
  text: "#000000",
8213
- textMuted: "#374151",
8214
- textDisabled: "#9CA3AF",
9224
+ textMuted: "#333333",
9225
+ textDisabled: "#888888",
8215
9226
  border: "#000000",
8216
- borderFocus: "#0000EE",
8217
- inputBackground: "#ffffff"
9227
+ borderFocus: "#0000CC",
9228
+ inputBackground: "#FFFFFF"
8218
9229
  },
8219
9230
  typography: {
8220
9231
  fontFamily: "Arial, Helvetica, sans-serif",
@@ -8228,24 +9239,24 @@ var highContrastPreset = {
8228
9239
  spacing: { base: 20, sectionGap: 40, fieldGap: 32, inputPaddingX: 14, inputPaddingY: 12 },
8229
9240
  layout: { maxWidth: "720px", alignment: "left", progressPosition: "top", sectionLayout: "bordered" }
8230
9241
  };
8231
- var highContrastDarkPreset = {
9242
+ var highContrastDark = {
8232
9243
  colors: {
8233
- primary: "#93C5FD",
9244
+ primary: "#6CB4FF",
8234
9245
  primaryForeground: "#000000",
8235
- secondary: "#C084FC",
8236
- secondaryForeground: "#000000",
8237
- error: "#FCA5A5",
9246
+ secondary: "#002255",
9247
+ secondaryForeground: "#99CCFF",
9248
+ error: "#FF8A8A",
8238
9249
  errorForeground: "#000000",
8239
- warning: "#FCD34D",
8240
- success: "#86EFAC",
8241
- surface: "#000000",
9250
+ warning: "#FFD54F",
9251
+ success: "#69F0AE",
9252
+ surface: "#0A0A0A",
8242
9253
  background: "#000000",
8243
9254
  text: "#FFFFFF",
8244
- textMuted: "#D1D5DB",
8245
- textDisabled: "#6B7280",
9255
+ textMuted: "#CCCCCC",
9256
+ textDisabled: "#666666",
8246
9257
  border: "#FFFFFF",
8247
- borderFocus: "#93C5FD",
8248
- inputBackground: "#000000"
9258
+ borderFocus: "#6CB4FF",
9259
+ inputBackground: "#0A0A0A"
8249
9260
  },
8250
9261
  typography: {
8251
9262
  fontFamily: "Arial, Helvetica, sans-serif",
@@ -8260,11 +9271,18 @@ var highContrastDarkPreset = {
8260
9271
  layout: { maxWidth: "720px", alignment: "left", progressPosition: "top", sectionLayout: "bordered" }
8261
9272
  };
8262
9273
  var PRESET_FAMILIES = {
8263
- clean: { light: cleanPreset, dark: cleanDarkPreset, label: "Clean" },
8264
- modern: { light: modernPreset, dark: modernDarkPreset, label: "Modern" },
8265
- clinical: { light: clinicalPreset, dark: clinicalDarkPreset, label: "Clinical" },
8266
- playful: { light: playfulPreset, dark: playfulDarkPreset, label: "Playful" },
8267
- "high-contrast": { light: highContrastPreset, dark: highContrastDarkPreset, label: "High contrast" }
9274
+ clean: { light: cleanLight, dark: cleanDark, label: "Clean" },
9275
+ stripe: { light: stripeLight, dark: stripeDark, label: "Stripe" },
9276
+ github: { light: githubLight, dark: githubDark, label: "GitHub" },
9277
+ vercel: { light: vercelLight, dark: vercelDark, label: "Vercel" },
9278
+ shopify: { light: shopifyLight, dark: shopifyDark, label: "Shopify" },
9279
+ slack: { light: slackLight, dark: slackDark, label: "Slack" },
9280
+ tailwind: { light: tailwindLight, dark: tailwindDark, label: "Tailwind" },
9281
+ clinical: { light: clinicalLight, dark: clinicalDark, label: "Clinical" },
9282
+ notion: { light: notionLight, dark: notionDark, label: "Notion" },
9283
+ sunset: { light: sunsetLight, dark: sunsetDark, label: "Sunset" },
9284
+ rose: { light: roseLight, dark: roseDark, label: "Rose" },
9285
+ "high-contrast": { light: highContrastLight, dark: highContrastDark, label: "High contrast" }
8268
9286
  };
8269
9287
  var COMPARISON_PRESETS = Object.fromEntries(
8270
9288
  Object.entries(PRESET_FAMILIES).map(([key, family]) => [
@@ -8273,7 +9291,7 @@ var COMPARISON_PRESETS = Object.fromEntries(
8273
9291
  ])
8274
9292
  );
8275
9293
  function ThemeComparison({ currentTheme, onClose }) {
8276
- const [compareKey, setCompareKey] = react.useState("clean");
9294
+ const [compareKey, setCompareKey] = React.useState("clean");
8277
9295
  const compareTheme = COMPARISON_PRESETS[compareKey]?.theme ?? PRESET_FAMILIES.clean.light;
8278
9296
  const diffs = getColorDiffs(currentTheme, compareTheme);
8279
9297
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "fcte-compare", children: [
@@ -8416,9 +9434,9 @@ function resolveThemeFromDOM() {
8416
9434
  }
8417
9435
  };
8418
9436
  }
8419
- var ThemeCtx2 = react.createContext({});
9437
+ var ThemeCtx2 = React.createContext({});
8420
9438
  function useEditorTheme() {
8421
- return react.useContext(ThemeCtx2);
9439
+ return React.useContext(ThemeCtx2);
8422
9440
  }
8423
9441
  function themeToCssVars2(theme) {
8424
9442
  const vars = {};
@@ -8437,18 +9455,36 @@ function themeToCssVars2(theme) {
8437
9455
  }
8438
9456
  function ThemeEditorThemeProvider({ theme, children }) {
8439
9457
  const resolved = theme ?? {};
8440
- const cssVars = react.useMemo(() => themeToCssVars2(resolved), [resolved]);
9458
+ const cssVars = React.useMemo(() => themeToCssVars2(resolved), [resolved]);
8441
9459
  return /* @__PURE__ */ jsxRuntime.jsx(ThemeCtx2.Provider, { value: resolved, children: /* @__PURE__ */ jsxRuntime.jsx("div", { "data-fcte-root": "", style: cssVars, className: "fcte-provider-root", children }) });
8442
9460
  }
8443
- function isDarkTheme(theme) {
9461
+ function isDarkTheme2(theme) {
8444
9462
  const bg = theme.colors?.background ?? "#FFFFFF";
8445
- const hex = bg.replace("#", "");
9463
+ let hex = bg.replace("#", "");
9464
+ if (hex.length === 3) {
9465
+ hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
9466
+ }
8446
9467
  if (hex.length < 6) return false;
8447
9468
  const r = parseInt(hex.slice(0, 2), 16);
8448
9469
  const g = parseInt(hex.slice(2, 4), 16);
8449
9470
  const b = parseInt(hex.slice(4, 6), 16);
8450
9471
  return 0.299 * r + 0.587 * g + 0.114 * b < 128;
8451
9472
  }
9473
+ function detectPresetFamily(theme) {
9474
+ const c = theme.colors;
9475
+ if (!c) return null;
9476
+ for (const [key, family] of Object.entries(PRESET_FAMILIES)) {
9477
+ for (const variant of ["light", "dark"]) {
9478
+ const preset = family[variant];
9479
+ const pc = preset.colors;
9480
+ if (!pc) continue;
9481
+ if (c.primary?.toLowerCase() === pc.primary?.toLowerCase() && c.background?.toLowerCase() === pc.background?.toLowerCase() && c.surface?.toLowerCase() === pc.surface?.toLowerCase()) {
9482
+ return key;
9483
+ }
9484
+ }
9485
+ }
9486
+ return null;
9487
+ }
8452
9488
  var SECTIONS = [
8453
9489
  {
8454
9490
  id: "colors",
@@ -8569,6 +9605,7 @@ var SECTIONS = [
8569
9605
  ];
8570
9606
  function ThemeEditorInner({
8571
9607
  initialTheme,
9608
+ initialPreset,
8572
9609
  onChange,
8573
9610
  onSave,
8574
9611
  theme: chromeTheme,
@@ -8578,74 +9615,118 @@ function ThemeEditorInner({
8578
9615
  toolbarExtra,
8579
9616
  showPreview = true
8580
9617
  }) {
8581
- const resolvedInitial = react.useMemo(
9618
+ const resolvedInitial = React.useMemo(
8582
9619
  () => initialTheme ?? resolveThemeFromDOM(),
8583
- // eslint-disable-next-line react-hooks/exhaustive-deps
8584
- []
9620
+ [initialTheme]
8585
9621
  );
8586
- const [theme, setTheme] = react.useState(resolvedInitial);
8587
- const [activeSection, setActiveSection] = react.useState("colors");
8588
- const [presetKey, setPresetKey] = react.useState("custom");
8589
- const [showPalette, setShowPalette] = react.useState(false);
8590
- const [showComparison, setShowComparison] = react.useState(false);
8591
- const themeRef = react.useRef(theme);
9622
+ const [theme, setTheme] = React.useState(resolvedInitial);
9623
+ const [activeSection, setActiveSection] = React.useState("colors");
9624
+ const resolvedPresetInit = initialPreset ?? detectPresetFamily(resolvedInitial) ?? "custom";
9625
+ const [presetKey, setPresetKey] = React.useState(resolvedPresetInit);
9626
+ const presetKeyRef = React.useRef(presetKey);
9627
+ presetKeyRef.current = presetKey;
9628
+ const [showPalette, setShowPalette] = React.useState(false);
9629
+ const [showComparison, setShowComparison] = React.useState(false);
9630
+ const themeRef = React.useRef(theme);
8592
9631
  themeRef.current = theme;
8593
- const hasInitialTheme = react.useRef(initialTheme != null);
8594
- react.useEffect(() => {
8595
- if (hasInitialTheme.current) return;
9632
+ const prevInitialRef = React.useRef(initialTheme);
9633
+ const prevPresetRef = React.useRef(initialPreset);
9634
+ React.useEffect(() => {
9635
+ if (!initialTheme) return;
9636
+ const themeChanged = JSON.stringify(initialTheme) !== JSON.stringify(prevInitialRef.current);
9637
+ const presetChanged = initialPreset !== prevPresetRef.current;
9638
+ if (!themeChanged && !presetChanged) return;
9639
+ prevInitialRef.current = initialTheme;
9640
+ prevPresetRef.current = initialPreset;
9641
+ setTheme(initialTheme);
9642
+ const resolvedPreset = initialPreset ?? detectPresetFamily(initialTheme) ?? "custom";
9643
+ setPresetKey(resolvedPreset);
9644
+ }, [initialTheme, initialPreset]);
9645
+ const mountReadyRef = React.useRef(false);
9646
+ React.useEffect(() => {
8596
9647
  if (typeof window === "undefined") return;
9648
+ const initialAttr = document.documentElement.getAttribute("data-theme");
9649
+ const lastAttrRef = { current: initialAttr };
9650
+ const readyTimer = setTimeout(() => {
9651
+ mountReadyRef.current = true;
9652
+ }, 500);
8597
9653
  const observer = new MutationObserver(() => {
9654
+ if (!mountReadyRef.current) return;
9655
+ const currentAttr = document.documentElement.getAttribute("data-theme");
9656
+ if (currentAttr === lastAttrRef.current) return;
9657
+ lastAttrRef.current = currentAttr;
8598
9658
  requestAnimationFrame(() => {
8599
- const resolved = resolveThemeFromDOM();
8600
- setTheme(resolved);
8601
- setPresetKey("custom");
8602
- onChange?.(resolved);
9659
+ const variant = currentAttr === "dark" ? "dark" : "light";
9660
+ let key = presetKeyRef.current;
9661
+ if (key === "custom") {
9662
+ const detected = detectPresetFamily(themeRef.current);
9663
+ if (detected) {
9664
+ key = detected;
9665
+ setPresetKey(detected);
9666
+ }
9667
+ }
9668
+ if (key !== "custom") {
9669
+ const family = PRESET_FAMILIES[key];
9670
+ if (family) {
9671
+ const preset = family[variant];
9672
+ setTheme(preset);
9673
+ onChange?.(preset, key);
9674
+ }
9675
+ } else {
9676
+ const resolved = resolveThemeFromDOM();
9677
+ setTheme(resolved);
9678
+ onChange?.(resolved, "custom");
9679
+ }
8603
9680
  });
8604
9681
  });
8605
9682
  observer.observe(document.documentElement, {
8606
9683
  attributes: true,
8607
9684
  attributeFilter: ["data-theme", "class"]
8608
9685
  });
8609
- return () => observer.disconnect();
9686
+ return () => {
9687
+ clearTimeout(readyTimer);
9688
+ observer.disconnect();
9689
+ };
8610
9690
  }, [onChange]);
8611
- react.useEffect(() => {
9691
+ React.useEffect(() => {
8612
9692
  function handleKeyDown(e) {
8613
9693
  if ((e.metaKey || e.ctrlKey) && e.key === "s") {
8614
9694
  e.preventDefault();
8615
- onSave?.(themeRef.current);
9695
+ onSave?.(themeRef.current, presetKeyRef.current);
8616
9696
  }
8617
9697
  }
8618
9698
  window.addEventListener("keydown", handleKeyDown);
8619
9699
  return () => window.removeEventListener("keydown", handleKeyDown);
8620
9700
  }, [onSave]);
8621
- const updateField = react.useCallback(
9701
+ const updateField = React.useCallback(
8622
9702
  (section, key, value) => {
8623
9703
  setTheme((prev) => {
8624
9704
  const next = {
8625
9705
  ...prev,
8626
9706
  [section]: { ...prev[section], [key]: value }
8627
9707
  };
8628
- onChange?.(next);
9708
+ onChange?.(next, "custom");
8629
9709
  return next;
8630
9710
  });
8631
9711
  setPresetKey("custom");
8632
9712
  },
8633
9713
  [onChange]
8634
9714
  );
8635
- const loadPreset = react.useCallback(
9715
+ const loadPreset = React.useCallback(
8636
9716
  (key) => {
8637
9717
  const family = PRESET_FAMILIES[key];
8638
9718
  if (family) {
8639
- const variant = isDarkTheme(theme) ? "dark" : "light";
9719
+ const htmlTheme = typeof document !== "undefined" ? document.documentElement.getAttribute("data-theme") : null;
9720
+ const variant = htmlTheme === "dark" ? "dark" : htmlTheme === "light" ? "light" : isDarkTheme2(theme) ? "dark" : "light";
8640
9721
  const preset = family[variant];
8641
9722
  setTheme(preset);
8642
9723
  setPresetKey(key);
8643
- onChange?.(preset);
9724
+ onChange?.(preset, key);
8644
9725
  }
8645
9726
  },
8646
9727
  [onChange, theme]
8647
9728
  );
8648
- const exportJson = react.useCallback(() => {
9729
+ const exportJson = React.useCallback(() => {
8649
9730
  const blob = new Blob([JSON.stringify(theme, null, 2)], { type: "application/json" });
8650
9731
  const url = URL.createObjectURL(blob);
8651
9732
  const a = document.createElement("a");
@@ -8654,7 +9735,7 @@ function ThemeEditorInner({
8654
9735
  a.click();
8655
9736
  URL.revokeObjectURL(url);
8656
9737
  }, [theme]);
8657
- const importJson = react.useCallback(() => {
9738
+ const importJson = React.useCallback(() => {
8658
9739
  const input = document.createElement("input");
8659
9740
  input.type = "file";
8660
9741
  input.accept = ".json";
@@ -8667,7 +9748,7 @@ function ThemeEditorInner({
8667
9748
  const parsed = JSON.parse(reader.result);
8668
9749
  setTheme(parsed);
8669
9750
  setPresetKey("custom");
8670
- onChange?.(parsed);
9751
+ onChange?.(parsed, "custom");
8671
9752
  } catch {
8672
9753
  }
8673
9754
  };
@@ -8675,17 +9756,17 @@ function ThemeEditorInner({
8675
9756
  };
8676
9757
  input.click();
8677
9758
  }, [onChange]);
8678
- const exportCss = react.useCallback(() => {
9759
+ const exportCss = React.useCallback(() => {
8679
9760
  exportCssFile(theme);
8680
9761
  }, [theme]);
8681
- const importCss = react.useCallback(() => {
9762
+ const importCss = React.useCallback(() => {
8682
9763
  importCssFile(theme, (merged) => {
8683
9764
  setTheme(merged);
8684
9765
  setPresetKey("custom");
8685
- onChange?.(merged);
9766
+ onChange?.(merged, "custom");
8686
9767
  });
8687
9768
  }, [theme, onChange]);
8688
- const currentSection = react.useMemo(
9769
+ const currentSection = React.useMemo(
8689
9770
  () => SECTIONS.find((s) => s.id === activeSection),
8690
9771
  [activeSection]
8691
9772
  );
@@ -8743,7 +9824,7 @@ function ThemeEditorInner({
8743
9824
  children: "Compare"
8744
9825
  }
8745
9826
  ),
8746
- onSave && /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => onSave(theme), className: "fcte-btn fcte-btn--primary", children: "Save" })
9827
+ onSave && /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => onSave(theme, presetKey), className: "fcte-btn fcte-btn--primary", children: "Save" })
8747
9828
  ] })
8748
9829
  ] }),
8749
9830
  showPalette && /* @__PURE__ */ jsxRuntime.jsx(
@@ -8753,7 +9834,7 @@ function ThemeEditorInner({
8753
9834
  onApply: (newTheme) => {
8754
9835
  setTheme(newTheme);
8755
9836
  setPresetKey("custom");
8756
- onChange?.(newTheme);
9837
+ onChange?.(newTheme, "custom");
8757
9838
  setShowPalette(false);
8758
9839
  },
8759
9840
  onClose: () => setShowPalette(false)
@@ -8908,8 +9989,6 @@ var themeEditorDarkPreset = {
8908
9989
  accent: "#63BDB4",
8909
9990
  accentForeground: "#0F1A1F"
8910
9991
  };
8911
-
8912
- // src/templates/consultation-booking.ts
8913
9992
  var consultationBookingSchema = {
8914
9993
  id: "consultation-booking",
8915
9994
  version: "1.0.0",
@@ -9275,17 +10354,10 @@ var consultationBookingSchema = {
9275
10354
  type: "dropdown",
9276
10355
  label: "Your Timezone",
9277
10356
  required: true,
9278
- options: [
9279
- { label: "US Eastern (ET)", value: "America/New_York" },
9280
- { label: "US Central (CT)", value: "America/Chicago" },
9281
- { label: "US Mountain (MT)", value: "America/Denver" },
9282
- { label: "US Pacific (PT)", value: "America/Los_Angeles" },
9283
- { label: "UK (GMT/BST)", value: "Europe/London" },
9284
- { label: "Central Europe (CET)", value: "Europe/Berlin" },
9285
- { label: "India (IST)", value: "Asia/Kolkata" },
9286
- { label: "Japan (JST)", value: "Asia/Tokyo" },
9287
- { label: "Australia Eastern (AEST)", value: "Australia/Sydney" }
9288
- ]
10357
+ options: fieldcraftCore.TIMEZONES.map((tz) => ({
10358
+ label: `${tz.label} (${tz.offset})`,
10359
+ value: tz.value
10360
+ }))
9289
10361
  },
9290
10362
  {
9291
10363
  id: "appointment_slot",
@@ -9316,7 +10388,7 @@ var consultationBookingSchema = {
9316
10388
  times: ["09:00", "11:00", "13:00", "14:00", "16:00"]
9317
10389
  }
9318
10390
  ],
9319
- timezone: "America/New_York",
10391
+ timezoneField: "timezone",
9320
10392
  duration: 60
9321
10393
  }
9322
10394
  },
@@ -9412,10 +10484,11 @@ var consultationBookingSchema = {
9412
10484
  type: "payment",
9413
10485
  provider: "stripe",
9414
10486
  publicKey: "",
10487
+ // Set your Stripe publishable key (pk_test_... or pk_live_...)
9415
10488
  amount: 2e4,
9416
10489
  currency: "USD",
9417
- description: "Consultation Session",
9418
- serverUrl: "/api/payment-intents"
10490
+ description: "Consultation Session"
10491
+ // No serverUrl — developer must configure their own endpoint via customProps or serverUrl
9419
10492
  }
9420
10493
  }
9421
10494
  ]
@@ -9939,10 +11012,11 @@ var ecommerceCheckoutSchema = {
9939
11012
  type: "payment",
9940
11013
  provider: "stripe",
9941
11014
  publicKey: "",
11015
+ // Set your Stripe publishable key (pk_test_... or pk_live_...)
9942
11016
  amount: 1e4,
9943
11017
  currency: "USD",
9944
- description: "E-commerce Order",
9945
- serverUrl: "/api/payment-intents"
11018
+ description: "E-commerce Order"
11019
+ // No serverUrl — developer must configure their own endpoint via customProps or serverUrl
9946
11020
  }
9947
11021
  }
9948
11022
  ]