@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.
@@ -1,11 +1,13 @@
1
1
  import { cn } from './chunk-QQ4JZGTD.mjs';
2
2
  import { requireLicense } from './chunk-4MMKB2EW.mjs';
3
+ import * as React from 'react';
3
4
  import { forwardRef, lazy, memo, createContext, Component, useState, useRef, useEffect, useCallback, useMemo, Suspense, useContext } from 'react';
4
5
  import { DndContext, DragOverlay, useSensors, useSensor, MouseSensor, TouchSensor, useDraggable, useDroppable } from '@dnd-kit/core';
5
- import { ChevronDown, Undo2, Redo2, PencilRuler, Eye, Code, GitBranch, LayoutTemplate, Upload, Download, Save, X, PanelLeft, PanelRight, Search, ChevronRight, Plus, Settings, FileText, Layers, ZoomOut, ZoomIn, Maximize, Copy, Trash2, HelpCircle, MoveVertical, Minus, Video, Image, PartyPopper, Hand, ShieldCheck, SeparatorHorizontal, Info, Heading, Trophy, EyeOff, Calculator, CreditCard, MapPin, Repeat, Grid3X3, Camera, PenTool, Paperclip, CalendarCheck, CalendarRange, Clock, Calendar, ArrowUpDown, Globe, ToggleLeft, CheckSquare, CircleDot, ListOrdered, TrendingUp, BarChart3, Star, SlidersHorizontal, Hash, UserCheck, Link, PhoneCall, Phone, Mail, AlignLeft, Type, GripVertical } from 'lucide-react';
6
+ import { ChevronDown, ChevronUp, Check, Undo2, Redo2, PencilRuler, Eye, Code, GitBranch, LayoutTemplate, Upload, Download, Save, X, PanelLeft, PanelRight, Search, ChevronRight, Plus, Settings, FileText, Layers, ZoomOut, ZoomIn, Maximize, Copy, Trash2, HelpCircle, MoveVertical, Minus, Video, Image, PartyPopper, Hand, ShieldCheck, SeparatorHorizontal, Info, Heading, Trophy, EyeOff, Calculator, CreditCard, MapPin, Repeat, Grid3X3, Camera, PenTool, Paperclip, CalendarCheck, CalendarRange, Clock, Calendar, ArrowUpDown, Globe, ToggleLeft, CheckSquare, CircleDot, ListOrdered, TrendingUp, BarChart3, Star, SlidersHorizontal, Hash, UserCheck, Link, PhoneCall, Phone, Mail, AlignLeft, Type, GripVertical } from 'lucide-react';
6
7
  import { Button, Separator, FormEngineRenderer, Input, Badge, Textarea, Label, Switch } from '@squaredr/fieldcraft-react';
7
8
  import { validateSchema, FormEngineSchemaError } from '@squaredr/fieldcraft-core';
8
9
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
10
+ import * as SelectPrimitive from '@radix-ui/react-select';
9
11
  import { MarkerType, Handle, Position, getBezierPath, BaseEdge, EdgeLabelRenderer, useNodesState, useEdgesState, ReactFlowProvider, useReactFlow, ReactFlow, Background, MiniMap } from '@xyflow/react';
10
12
  import '@xyflow/react/dist/style.css';
11
13
 
@@ -13,20 +15,23 @@ var MAX_HISTORY = 50;
13
15
  function useUndoRedo(currentSchema, setSchema) {
14
16
  const historyRef = useRef([currentSchema]);
15
17
  const [currentIndex, setCurrentIndex] = useState(0);
18
+ const currentIndexRef = useRef(currentIndex);
19
+ currentIndexRef.current = currentIndex;
16
20
  const canUndo = currentIndex > 0;
17
21
  const canRedo = currentIndex < historyRef.current.length - 1;
18
22
  const push = useCallback(
19
23
  (schema) => {
20
- historyRef.current = historyRef.current.slice(0, currentIndex + 1);
24
+ const idx = currentIndexRef.current;
25
+ historyRef.current = historyRef.current.slice(0, idx + 1);
21
26
  historyRef.current.push(schema);
22
27
  if (historyRef.current.length > MAX_HISTORY) {
23
28
  historyRef.current.shift();
24
29
  setCurrentIndex(historyRef.current.length - 1);
25
30
  } else {
26
- setCurrentIndex((prev) => prev + 1);
31
+ setCurrentIndex(idx + 1);
27
32
  }
28
33
  },
29
- [currentIndex]
34
+ []
30
35
  );
31
36
  const undo = useCallback(() => {
32
37
  if (currentIndex > 0) {
@@ -644,7 +649,7 @@ var QUESTION_TYPE_INFO = {
644
649
  category: "advanced",
645
650
  icon: "ListPlus",
646
651
  description: "Repeatable group of fields",
647
- defaultConfig: { type: "repeater", fields: [], minItems: 1, maxItems: 10 }
652
+ defaultConfig: { type: "repeater", fields: [], minEntries: 1, maxEntries: 10 }
648
653
  },
649
654
  likert: {
650
655
  type: "likert",
@@ -655,13 +660,7 @@ var QUESTION_TYPE_INFO = {
655
660
  requiresOptions: true,
656
661
  defaultConfig: {
657
662
  type: "likert",
658
- scale: [
659
- { label: "Strongly Disagree", value: "1" },
660
- { label: "Disagree", value: "2" },
661
- { label: "Neutral", value: "3" },
662
- { label: "Agree", value: "4" },
663
- { label: "Strongly Agree", value: "5" }
664
- ]
663
+ labels: ["Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"]
665
664
  }
666
665
  },
667
666
  scoring: {
@@ -714,7 +713,7 @@ var QUESTION_TYPE_INFO = {
714
713
  category: "advanced",
715
714
  icon: "CreditCard",
716
715
  description: "Collect payment via Stripe",
717
- defaultConfig: { type: "payment", provider: "stripe", publicKey: "", currency: "USD" }
716
+ defaultConfig: { type: "payment", provider: "stripe", publicKey: "", currency: "USD", serverUrl: "" }
718
717
  },
719
718
  // ── Structural ──
720
719
  section_header: {
@@ -1509,30 +1508,71 @@ function FormCanvas({ builderState }) {
1509
1508
  ] })
1510
1509
  ] }) });
1511
1510
  }
1512
- var NativeSelect = forwardRef(
1513
- ({ className, wrapperClassName, children, ...props }, ref) => {
1514
- return /* @__PURE__ */ jsxs("div", { className: cn("relative", wrapperClassName), children: [
1511
+ var Select = SelectPrimitive.Root;
1512
+ var SelectTrigger = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
1513
+ SelectPrimitive.Trigger,
1514
+ {
1515
+ ref,
1516
+ className: cn(
1517
+ "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",
1518
+ className
1519
+ ),
1520
+ ...props,
1521
+ children: [
1522
+ children,
1523
+ /* @__PURE__ */ jsx(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-4 text-muted-foreground" }) })
1524
+ ]
1525
+ }
1526
+ ));
1527
+ SelectTrigger.displayName = "SelectTrigger";
1528
+ var SelectContent = React.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
1529
+ SelectPrimitive.Content,
1530
+ {
1531
+ ref,
1532
+ className: cn(
1533
+ "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",
1534
+ 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",
1535
+ className
1536
+ ),
1537
+ position,
1538
+ ...props,
1539
+ children: [
1540
+ /* @__PURE__ */ jsx(SelectPrimitive.ScrollUpButton, { className: "flex cursor-default items-center justify-center py-1", children: /* @__PURE__ */ jsx(ChevronUp, { className: "size-4" }) }),
1515
1541
  /* @__PURE__ */ jsx(
1516
- "select",
1542
+ SelectPrimitive.Viewport,
1517
1543
  {
1518
- ref,
1519
1544
  className: cn(
1520
- "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",
1521
- className
1545
+ "p-1",
1546
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
1522
1547
  ),
1523
- ...props,
1524
1548
  children
1525
1549
  }
1526
1550
  ),
1527
- /* @__PURE__ */ jsx(ChevronDown, { className: "pointer-events-none absolute right-2.5 top-1/2 -translate-y-1/2 size-4 text-muted-foreground" })
1528
- ] });
1551
+ /* @__PURE__ */ jsx(SelectPrimitive.ScrollDownButton, { className: "flex cursor-default items-center justify-center py-1", children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-4" }) })
1552
+ ]
1529
1553
  }
1530
- );
1531
- NativeSelect.displayName = "NativeSelect";
1554
+ ) }));
1555
+ SelectContent.displayName = "SelectContent";
1556
+ var SelectItem = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
1557
+ SelectPrimitive.Item,
1558
+ {
1559
+ ref,
1560
+ className: cn(
1561
+ "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",
1562
+ className
1563
+ ),
1564
+ ...props,
1565
+ children: [
1566
+ /* @__PURE__ */ jsx("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "size-4" }) }) }),
1567
+ /* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children })
1568
+ ]
1569
+ }
1570
+ ));
1571
+ SelectItem.displayName = "SelectItem";
1532
1572
  function useConfigUpdater(question, onUpdate) {
1533
- return (field, value) => {
1573
+ return (updates) => {
1534
1574
  const current = question.config ?? {};
1535
- onUpdate({ config: { ...current, type: question.type, [field]: value } });
1575
+ onUpdate({ config: { ...current, type: question.type, ...updates } });
1536
1576
  };
1537
1577
  }
1538
1578
  function QuestionConfigEditor({ question, onUpdate }) {
@@ -1542,226 +1582,274 @@ function QuestionConfigEditor({ question, onUpdate }) {
1542
1582
  // ── Text ──
1543
1583
  case "short_text":
1544
1584
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Text Settings", children: [
1545
- /* @__PURE__ */ jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "255", onChange: (v) => updateConfig("maxLength", v) }),
1546
- /* @__PURE__ */ jsx(SelectField, { label: "Input Type", value: config.inputType ?? "text", options: [{ label: "Text", value: "text" }, { label: "Password", value: "password" }], onChange: (v) => updateConfig("inputType", v) }),
1547
- /* @__PURE__ */ jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig("prefix", v) }),
1548
- /* @__PURE__ */ jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. USD", onChange: (v) => updateConfig("suffix", v) })
1585
+ /* @__PURE__ */ jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "255", onChange: (v) => updateConfig({ maxLength: v }) }),
1586
+ /* @__PURE__ */ jsx(SelectField, { label: "Input Type", value: config.inputType ?? "text", options: [{ label: "Text", value: "text" }, { label: "Password", value: "password" }], onChange: (v) => updateConfig({ inputType: v }) }),
1587
+ /* @__PURE__ */ jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig({ prefix: v }) }),
1588
+ /* @__PURE__ */ jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. USD", onChange: (v) => updateConfig({ suffix: v }) })
1549
1589
  ] });
1550
1590
  case "long_text":
1551
1591
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Text Settings", children: [
1552
- /* @__PURE__ */ jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "No limit", onChange: (v) => updateConfig("maxLength", v) }),
1553
- /* @__PURE__ */ jsx(NumberField, { label: "Rows", value: config.rows, placeholder: "4", onChange: (v) => updateConfig("rows", v) }),
1554
- /* @__PURE__ */ jsx(ToggleField, { label: "Show Character Count", checked: !!config.showCharCount, onChange: (v) => updateConfig("showCharCount", v) })
1592
+ /* @__PURE__ */ jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "No limit", onChange: (v) => updateConfig({ maxLength: v }) }),
1593
+ /* @__PURE__ */ jsx(NumberField, { label: "Rows", value: config.rows, placeholder: "4", onChange: (v) => updateConfig({ rows: v }) }),
1594
+ /* @__PURE__ */ jsx(ToggleField, { label: "Show Character Count", checked: !!config.showCharCount, onChange: (v) => updateConfig({ showCharCount: v }) })
1555
1595
  ] });
1556
1596
  case "legal_name":
1557
1597
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Name Fields", children: [
1558
- /* @__PURE__ */ jsx(ToggleField, { label: "Show Middle Name", checked: !!config.showMiddleName, onChange: (v) => updateConfig("showMiddleName", v) }),
1559
- /* @__PURE__ */ jsx(ToggleField, { label: "Show Suffix", checked: !!config.showSuffix, onChange: (v) => updateConfig("showSuffix", v) })
1598
+ /* @__PURE__ */ jsx(ToggleField, { label: "Show Middle Name", checked: !!config.showMiddleName, onChange: (v) => updateConfig({ showMiddleName: v }) }),
1599
+ /* @__PURE__ */ jsx(ToggleField, { label: "Show Suffix", checked: !!config.showSuffix, onChange: (v) => updateConfig({ showSuffix: v }) })
1560
1600
  ] });
1561
1601
  // ── Numeric ──
1562
1602
  case "number":
1563
1603
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Number Settings", children: [
1564
- /* @__PURE__ */ jsx(NumberField, { label: "Min", value: config.min, onChange: (v) => updateConfig("min", v) }),
1565
- /* @__PURE__ */ jsx(NumberField, { label: "Max", value: config.max, onChange: (v) => updateConfig("max", v) }),
1566
- /* @__PURE__ */ jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig("step", v) }),
1567
- /* @__PURE__ */ jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "0", onChange: (v) => updateConfig("decimalPlaces", v) }),
1568
- /* @__PURE__ */ jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig("prefix", v) }),
1569
- /* @__PURE__ */ jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. kg", onChange: (v) => updateConfig("suffix", v) })
1604
+ /* @__PURE__ */ jsx(NumberField, { label: "Min", value: config.min, onChange: (v) => updateConfig({ min: v }) }),
1605
+ /* @__PURE__ */ jsx(NumberField, { label: "Max", value: config.max, onChange: (v) => updateConfig({ max: v }) }),
1606
+ /* @__PURE__ */ jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig({ step: v }) }),
1607
+ /* @__PURE__ */ jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "0", onChange: (v) => updateConfig({ decimalPlaces: v }) }),
1608
+ /* @__PURE__ */ jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig({ prefix: v }) }),
1609
+ /* @__PURE__ */ jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. kg", onChange: (v) => updateConfig({ suffix: v }) })
1570
1610
  ] });
1571
1611
  case "slider":
1572
1612
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Slider Settings", children: [
1573
- /* @__PURE__ */ jsx(NumberField, { label: "Min", value: config.min, placeholder: "0", onChange: (v) => updateConfig("min", v) }),
1574
- /* @__PURE__ */ jsx(NumberField, { label: "Max", value: config.max, placeholder: "100", onChange: (v) => updateConfig("max", v) }),
1575
- /* @__PURE__ */ jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig("step", v) }),
1576
- /* @__PURE__ */ jsx(ToggleField, { label: "Show Value", checked: !!config.showValue, onChange: (v) => updateConfig("showValue", v) }),
1577
- /* @__PURE__ */ jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig("minLabel", v) }),
1578
- /* @__PURE__ */ jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig("maxLabel", v) })
1613
+ /* @__PURE__ */ jsx(NumberField, { label: "Min", value: config.min, placeholder: "0", onChange: (v) => updateConfig({ min: v }) }),
1614
+ /* @__PURE__ */ jsx(NumberField, { label: "Max", value: config.max, placeholder: "100", onChange: (v) => updateConfig({ max: v }) }),
1615
+ /* @__PURE__ */ jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig({ step: v }) }),
1616
+ /* @__PURE__ */ jsx(ToggleField, { label: "Show Value", checked: !!config.showValue, onChange: (v) => updateConfig({ showValue: v }) }),
1617
+ /* @__PURE__ */ jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig({ minLabel: v }) }),
1618
+ /* @__PURE__ */ jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig({ maxLabel: v }) })
1579
1619
  ] });
1580
1620
  case "rating":
1581
1621
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Rating Settings", children: [
1582
- /* @__PURE__ */ jsx(NumberField, { label: "Max Stars", value: config.max, placeholder: "5", onChange: (v) => updateConfig("max", v) }),
1583
- /* @__PURE__ */ 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) }),
1584
- /* @__PURE__ */ jsx(ToggleField, { label: "Show Labels", checked: !!config.showLabels, onChange: (v) => updateConfig("showLabels", v) })
1622
+ /* @__PURE__ */ jsx(NumberField, { label: "Max Stars", value: config.max, placeholder: "5", onChange: (v) => updateConfig({ max: v }) }),
1623
+ /* @__PURE__ */ 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 }) }),
1624
+ /* @__PURE__ */ jsx(ToggleField, { label: "Show Labels", checked: !!config.showLabels, onChange: (v) => updateConfig({ showLabels: v }) })
1585
1625
  ] });
1586
1626
  case "nps":
1587
1627
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "NPS Settings", children: [
1588
- /* @__PURE__ */ jsx(TextField, { label: "Low Label", value: config.lowLabel ?? "Not likely", onChange: (v) => updateConfig("lowLabel", v) }),
1589
- /* @__PURE__ */ jsx(TextField, { label: "High Label", value: config.highLabel ?? "Very likely", onChange: (v) => updateConfig("highLabel", v) })
1628
+ /* @__PURE__ */ jsx(TextField, { label: "Low Label", value: config.lowLabel ?? "Not likely", onChange: (v) => updateConfig({ lowLabel: v }) }),
1629
+ /* @__PURE__ */ jsx(TextField, { label: "High Label", value: config.highLabel ?? "Very likely", onChange: (v) => updateConfig({ highLabel: v }) })
1590
1630
  ] });
1591
1631
  case "opinion_scale":
1592
1632
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Scale Settings", children: [
1593
- /* @__PURE__ */ jsx(NumberField, { label: "Min", value: config.min, placeholder: "1", onChange: (v) => updateConfig("min", v) }),
1594
- /* @__PURE__ */ jsx(NumberField, { label: "Max", value: config.max, placeholder: "5", onChange: (v) => updateConfig("max", v) }),
1595
- /* @__PURE__ */ jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig("step", v) }),
1596
- /* @__PURE__ */ jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig("minLabel", v) }),
1597
- /* @__PURE__ */ jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig("maxLabel", v) })
1633
+ /* @__PURE__ */ jsx(NumberField, { label: "Min", value: config.min, placeholder: "1", onChange: (v) => updateConfig({ min: v }) }),
1634
+ /* @__PURE__ */ jsx(NumberField, { label: "Max", value: config.max, placeholder: "5", onChange: (v) => updateConfig({ max: v }) }),
1635
+ /* @__PURE__ */ jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig({ step: v }) }),
1636
+ /* @__PURE__ */ jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig({ minLabel: v }) }),
1637
+ /* @__PURE__ */ jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig({ maxLabel: v }) })
1598
1638
  ] });
1599
1639
  case "likert":
1600
- return /* @__PURE__ */ jsx(ConfigSection, { title: "Likert Settings", children: /* @__PURE__ */ jsx(LikertLabelsEditor, { labels: config.labels ?? ["Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"], onChange: (v) => updateConfig("labels", v) }) });
1640
+ return /* @__PURE__ */ jsx(ConfigSection, { title: "Likert Settings", children: /* @__PURE__ */ jsx(LikertLabelsEditor, { labels: config.labels ?? ["Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"], onChange: (v) => updateConfig({ labels: v }) }) });
1601
1641
  // ── Selection ──
1602
1642
  case "single_select":
1603
1643
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Select Settings", children: [
1604
- /* @__PURE__ */ 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) }),
1605
- /* @__PURE__ */ jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig("allowOther", v) }),
1606
- !!config.allowOther && /* @__PURE__ */ jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig("otherLabel", v) })
1644
+ /* @__PURE__ */ 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 }) }),
1645
+ /* @__PURE__ */ jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => v ? updateConfig({ allowOther: true }) : updateConfig({ allowOther: false, otherLabel: void 0 }) }),
1646
+ !!config.allowOther && /* @__PURE__ */ jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig({ otherLabel: v }) })
1607
1647
  ] });
1608
1648
  case "multi_select":
1609
1649
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Multi-Select Settings", children: [
1610
- /* @__PURE__ */ 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) }),
1611
- /* @__PURE__ */ jsx(NumberField, { label: "Min Selections", value: config.minSelections, onChange: (v) => updateConfig("minSelections", v) }),
1612
- /* @__PURE__ */ jsx(NumberField, { label: "Max Selections", value: config.maxSelections, onChange: (v) => updateConfig("maxSelections", v) }),
1613
- /* @__PURE__ */ jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig("allowOther", v) }),
1614
- !!config.allowOther && /* @__PURE__ */ jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig("otherLabel", v) })
1650
+ /* @__PURE__ */ 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 }) }),
1651
+ /* @__PURE__ */ jsx(NumberField, { label: "Min Selections", value: config.minSelections, onChange: (v) => updateConfig({ minSelections: v }) }),
1652
+ /* @__PURE__ */ jsx(NumberField, { label: "Max Selections", value: config.maxSelections, onChange: (v) => updateConfig({ maxSelections: v }) }),
1653
+ /* @__PURE__ */ jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => v ? updateConfig({ allowOther: true }) : updateConfig({ allowOther: false, otherLabel: void 0 }) }),
1654
+ !!config.allowOther && /* @__PURE__ */ jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig({ otherLabel: v }) })
1615
1655
  ] });
1616
1656
  case "dropdown":
1617
1657
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Dropdown Settings", children: [
1618
- /* @__PURE__ */ jsx(ToggleField, { label: "Searchable", checked: !!config.searchable, onChange: (v) => updateConfig("searchable", v) }),
1619
- /* @__PURE__ */ jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig("allowOther", v) }),
1620
- /* @__PURE__ */ jsx(ToggleField, { label: "Multiple", checked: !!config.multiple, onChange: (v) => updateConfig("multiple", v) })
1658
+ /* @__PURE__ */ jsx(ToggleField, { label: "Searchable", checked: !!config.searchable, onChange: (v) => updateConfig({ searchable: v }) }),
1659
+ /* @__PURE__ */ jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig({ allowOther: v }) }),
1660
+ /* @__PURE__ */ jsx(ToggleField, { label: "Multiple", checked: !!config.multiple, onChange: (v) => updateConfig({ multiple: v }) })
1621
1661
  ] });
1622
1662
  case "boolean":
1623
1663
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Yes/No Settings", children: [
1624
- /* @__PURE__ */ 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) }),
1625
- /* @__PURE__ */ jsx(TextField, { label: "True Label", value: config.trueLabel ?? "Yes", onChange: (v) => updateConfig("trueLabel", v) }),
1626
- /* @__PURE__ */ jsx(TextField, { label: "False Label", value: config.falseLabel ?? "No", onChange: (v) => updateConfig("falseLabel", v) })
1664
+ /* @__PURE__ */ 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 }) }),
1665
+ /* @__PURE__ */ jsx(TextField, { label: "True Label", value: config.trueLabel ?? "Yes", onChange: (v) => updateConfig({ trueLabel: v }) }),
1666
+ /* @__PURE__ */ jsx(TextField, { label: "False Label", value: config.falseLabel ?? "No", onChange: (v) => updateConfig({ falseLabel: v }) })
1627
1667
  ] });
1628
1668
  case "country_select":
1629
1669
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Country Settings", children: [
1630
- /* @__PURE__ */ jsx(ToggleField, { label: "Show Flags", checked: config.showFlags !== false, onChange: (v) => updateConfig("showFlags", v) }),
1631
- /* @__PURE__ */ 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) }),
1632
- /* @__PURE__ */ 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) })
1670
+ /* @__PURE__ */ jsx(ToggleField, { label: "Show Flags", checked: config.showFlags !== false, onChange: (v) => updateConfig({ showFlags: v }) }),
1671
+ /* @__PURE__ */ 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 }) }),
1672
+ /* @__PURE__ */ 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 }) })
1633
1673
  ] });
1634
1674
  // ── Date/Time ──
1635
1675
  case "date":
1636
1676
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Date Settings", children: [
1637
- /* @__PURE__ */ jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig("minDate", v) }),
1638
- /* @__PURE__ */ jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig("maxDate", v) }),
1639
- /* @__PURE__ */ jsx(ToggleField, { label: "Disable Past Dates", checked: !!config.disablePast, onChange: (v) => updateConfig("disablePast", v) }),
1640
- /* @__PURE__ */ jsx(ToggleField, { label: "Disable Future Dates", checked: !!config.disableFuture, onChange: (v) => updateConfig("disableFuture", v) }),
1641
- /* @__PURE__ */ jsx(TextField, { label: "Format", value: config.format, placeholder: "e.g. MM/DD/YYYY", onChange: (v) => updateConfig("format", v) })
1677
+ /* @__PURE__ */ jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ minDate: v }) }),
1678
+ /* @__PURE__ */ jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ maxDate: v }) }),
1679
+ /* @__PURE__ */ jsx(ToggleField, { label: "Disable Past Dates", checked: !!config.disablePast, onChange: (v) => updateConfig({ disablePast: v }) }),
1680
+ /* @__PURE__ */ jsx(ToggleField, { label: "Disable Future Dates", checked: !!config.disableFuture, onChange: (v) => updateConfig({ disableFuture: v }) }),
1681
+ /* @__PURE__ */ jsx(TextField, { label: "Format", value: config.format, placeholder: "e.g. MM/DD/YYYY", onChange: (v) => updateConfig({ format: v }) })
1642
1682
  ] });
1643
1683
  case "time":
1644
1684
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Time Settings", children: [
1645
- /* @__PURE__ */ jsx(SelectField, { label: "Format", value: config.format ?? "12h", options: [{ label: "12 Hour", value: "12h" }, { label: "24 Hour", value: "24h" }], onChange: (v) => updateConfig("format", v) }),
1646
- /* @__PURE__ */ jsx(NumberField, { label: "Minute Step", value: config.minuteStep, placeholder: "1", onChange: (v) => updateConfig("minuteStep", v) })
1685
+ /* @__PURE__ */ jsx(SelectField, { label: "Format", value: config.format ?? "12h", options: [{ label: "12 Hour", value: "12h" }, { label: "24 Hour", value: "24h" }], onChange: (v) => updateConfig({ format: v }) }),
1686
+ /* @__PURE__ */ jsx(NumberField, { label: "Minute Step", value: config.minuteStep, placeholder: "1", onChange: (v) => updateConfig({ minuteStep: v }) })
1647
1687
  ] });
1648
1688
  case "date_range":
1649
1689
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Date Range Settings", children: [
1650
- /* @__PURE__ */ jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig("minDate", v) }),
1651
- /* @__PURE__ */ jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig("maxDate", v) }),
1652
- /* @__PURE__ */ jsx(NumberField, { label: "Max Range (days)", value: config.maxRangeDays, onChange: (v) => updateConfig("maxRangeDays", v) })
1690
+ /* @__PURE__ */ jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ minDate: v }) }),
1691
+ /* @__PURE__ */ jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ maxDate: v }) }),
1692
+ /* @__PURE__ */ jsx(NumberField, { label: "Max Range (days)", value: config.maxRangeDays, onChange: (v) => updateConfig({ maxRangeDays: v }) })
1653
1693
  ] });
1654
- case "appointment":
1694
+ case "appointment": {
1695
+ const appointmentMode = typeof config.embedUrl === "string" ? "embed" : typeof config.slotsUrl === "string" ? "url" : "static";
1655
1696
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Appointment Settings", children: [
1656
- /* @__PURE__ */ jsx(NumberField, { label: "Duration (min)", value: config.duration ?? 30, onChange: (v) => updateConfig("duration", v) }),
1657
- /* @__PURE__ */ jsx(TextField, { label: "Timezone", value: config.timezone, placeholder: "e.g. America/New_York", onChange: (v) => updateConfig("timezone", v) }),
1658
- /* @__PURE__ */ jsx(TextField, { label: "Slots URL", value: config.slotsUrl, placeholder: "API endpoint for available slots", onChange: (v) => updateConfig("slotsUrl", v) })
1697
+ /* @__PURE__ */ jsx(
1698
+ SelectField,
1699
+ {
1700
+ label: "Mode",
1701
+ value: appointmentMode,
1702
+ options: [
1703
+ { label: "Static Slots", value: "static" },
1704
+ { label: "API Endpoint", value: "url" },
1705
+ { label: "Embed (Calendly / Cal.com)", value: "embed" }
1706
+ ],
1707
+ onChange: (v) => {
1708
+ if (v === "static") {
1709
+ updateConfig({ slotsUrl: void 0, embedUrl: void 0, embedProvider: void 0 });
1710
+ } else if (v === "url") {
1711
+ updateConfig({ slotsUrl: "", embedUrl: void 0, embedProvider: void 0, slots: void 0 });
1712
+ } else if (v === "embed") {
1713
+ updateConfig({ embedUrl: "", slotsUrl: void 0, slots: void 0 });
1714
+ }
1715
+ }
1716
+ }
1717
+ ),
1718
+ /* @__PURE__ */ jsx(NumberField, { label: "Duration (min)", value: config.duration ?? 30, onChange: (v) => updateConfig({ duration: v }) }),
1719
+ /* @__PURE__ */ jsx(TextField, { label: "Timezone", value: config.timezone, placeholder: "e.g. America/New_York", onChange: (v) => updateConfig({ timezone: v }) }),
1720
+ /* @__PURE__ */ jsx(TextField, { label: "Timezone Field", value: config.timezoneField, placeholder: "Field ID for dynamic timezone", onChange: (v) => updateConfig({ timezoneField: v }) }),
1721
+ /* @__PURE__ */ jsx(TextField, { label: "Date Format", value: config.dateFormat, placeholder: "Locale-aware (default)", onChange: (v) => updateConfig({ dateFormat: v }) }),
1722
+ appointmentMode === "url" && /* @__PURE__ */ jsx(TextField, { label: "Slots URL", value: config.slotsUrl, placeholder: "https://api.example.com/slots", onChange: (v) => updateConfig({ slotsUrl: v }) }),
1723
+ appointmentMode === "embed" && /* @__PURE__ */ jsxs(Fragment, { children: [
1724
+ /* @__PURE__ */ jsx(TextField, { label: "Embed URL", value: config.embedUrl, placeholder: "https://calendly.com/your-name/30min", onChange: (v) => updateConfig({ embedUrl: v }) }),
1725
+ /* @__PURE__ */ jsx(
1726
+ SelectField,
1727
+ {
1728
+ label: "Embed Provider",
1729
+ value: config.embedProvider ?? "custom",
1730
+ options: [
1731
+ { label: "Calendly", value: "calendly" },
1732
+ { label: "Cal.com", value: "cal_com" },
1733
+ { label: "Custom", value: "custom" }
1734
+ ],
1735
+ onChange: (v) => updateConfig({ embedProvider: v })
1736
+ }
1737
+ )
1738
+ ] }),
1739
+ appointmentMode === "static" && /* @__PURE__ */ jsx(
1740
+ AppointmentSlotsEditor,
1741
+ {
1742
+ slots: config.slots ?? [],
1743
+ onChange: (v) => updateConfig({ slots: v })
1744
+ }
1745
+ )
1659
1746
  ] });
1747
+ }
1660
1748
  // ── Media ──
1661
1749
  case "file_upload":
1662
1750
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Upload Settings", children: [
1663
- /* @__PURE__ */ jsx(NumberField, { label: "Max Files", value: config.maxFiles ?? 1, onChange: (v) => updateConfig("maxFiles", v) }),
1664
- /* @__PURE__ */ jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb ?? 10, onChange: (v) => updateConfig("maxSizeMb", v) }),
1665
- /* @__PURE__ */ 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) }),
1666
- /* @__PURE__ */ jsx(TextField, { label: "Upload URL", value: config.uploadUrl, placeholder: "Server upload endpoint", onChange: (v) => updateConfig("uploadUrl", v) })
1751
+ /* @__PURE__ */ jsx(NumberField, { label: "Max Files", value: config.maxFiles ?? 1, onChange: (v) => updateConfig({ maxFiles: v }) }),
1752
+ /* @__PURE__ */ jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb ?? 10, onChange: (v) => updateConfig({ maxSizeMb: v }) }),
1753
+ /* @__PURE__ */ 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 }) }),
1754
+ /* @__PURE__ */ jsx(TextField, { label: "Upload URL", value: config.uploadUrl, placeholder: "Server upload endpoint", onChange: (v) => updateConfig({ uploadUrl: v }) })
1667
1755
  ] });
1668
1756
  case "signature":
1669
1757
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Signature Settings", children: [
1670
- /* @__PURE__ */ jsx(TextField, { label: "Pen Color", value: config.penColor, placeholder: "#000000", onChange: (v) => updateConfig("penColor", v) }),
1671
- /* @__PURE__ */ jsx(TextField, { label: "Background", value: config.backgroundColor, placeholder: "#ffffff", onChange: (v) => updateConfig("backgroundColor", v) }),
1672
- /* @__PURE__ */ jsx(NumberField, { label: "Width (px)", value: config.width, onChange: (v) => updateConfig("width", v) }),
1673
- /* @__PURE__ */ jsx(NumberField, { label: "Height (px)", value: config.height, onChange: (v) => updateConfig("height", v) })
1758
+ /* @__PURE__ */ jsx(TextField, { label: "Pen Color", value: config.penColor, placeholder: "#000000", onChange: (v) => updateConfig({ penColor: v }) }),
1759
+ /* @__PURE__ */ jsx(TextField, { label: "Background", value: config.backgroundColor, placeholder: "#ffffff", onChange: (v) => updateConfig({ backgroundColor: v }) }),
1760
+ /* @__PURE__ */ jsx(NumberField, { label: "Width (px)", value: config.width, onChange: (v) => updateConfig({ width: v }) }),
1761
+ /* @__PURE__ */ jsx(NumberField, { label: "Height (px)", value: config.height, onChange: (v) => updateConfig({ height: v }) })
1674
1762
  ] });
1675
1763
  case "image_capture":
1676
1764
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Camera Settings", children: [
1677
- /* @__PURE__ */ 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) }),
1678
- /* @__PURE__ */ jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb, onChange: (v) => updateConfig("maxSizeMb", v) }),
1679
- /* @__PURE__ */ jsx(ToggleField, { label: "Allow Gallery", checked: config.allowGallery !== false, onChange: (v) => updateConfig("allowGallery", v) })
1765
+ /* @__PURE__ */ 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 }) }),
1766
+ /* @__PURE__ */ jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb, onChange: (v) => updateConfig({ maxSizeMb: v }) }),
1767
+ /* @__PURE__ */ jsx(ToggleField, { label: "Allow Gallery", checked: config.allowGallery !== false, onChange: (v) => updateConfig({ allowGallery: v }) })
1680
1768
  ] });
1681
1769
  // ── Content & Visual ──
1682
1770
  case "welcome-screen":
1683
1771
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Welcome Screen", children: [
1684
- /* @__PURE__ */ jsx(TextField, { label: "Heading", value: config.heading ?? "Welcome", onChange: (v) => updateConfig("heading", v) }),
1685
- /* @__PURE__ */ jsx(TextareaField, { label: "Description", value: config.description, onChange: (v) => updateConfig("description", v) }),
1686
- /* @__PURE__ */ jsx(TextField, { label: "Button Text", value: config.buttonText ?? "Start", onChange: (v) => updateConfig("buttonText", v) }),
1687
- /* @__PURE__ */ jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig("imageUrl", v) }),
1688
- /* @__PURE__ */ 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) })
1772
+ /* @__PURE__ */ jsx(TextField, { label: "Heading", value: config.heading ?? "Welcome", onChange: (v) => updateConfig({ heading: v }) }),
1773
+ /* @__PURE__ */ jsx(TextareaField, { label: "Description", value: config.description, onChange: (v) => updateConfig({ description: v }) }),
1774
+ /* @__PURE__ */ jsx(TextField, { label: "Button Text", value: config.buttonText ?? "Start", onChange: (v) => updateConfig({ buttonText: v }) }),
1775
+ /* @__PURE__ */ jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig({ imageUrl: v }) }),
1776
+ /* @__PURE__ */ 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 }) })
1689
1777
  ] });
1690
1778
  case "thank-you-screen":
1691
1779
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Thank You Screen", children: [
1692
- /* @__PURE__ */ jsx(TextField, { label: "Heading", value: config.heading ?? "Thank You!", onChange: (v) => updateConfig("heading", v) }),
1693
- /* @__PURE__ */ jsx(TextareaField, { label: "Description", value: config.description ?? "", onChange: (v) => updateConfig("description", v) }),
1694
- /* @__PURE__ */ jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig("imageUrl", v) }),
1695
- /* @__PURE__ */ jsx(TextField, { label: "Redirect URL", value: config.redirectUrl, placeholder: "https://...", onChange: (v) => updateConfig("redirectUrl", v) }),
1696
- /* @__PURE__ */ jsx(NumberField, { label: "Redirect Delay (s)", value: config.redirectDelay, placeholder: "0", onChange: (v) => updateConfig("redirectDelay", v) }),
1697
- /* @__PURE__ */ jsx(ToggleField, { label: "Show Response Summary", checked: !!config.showSummary, onChange: (v) => updateConfig("showSummary", v) })
1780
+ /* @__PURE__ */ jsx(TextField, { label: "Heading", value: config.heading ?? "Thank You!", onChange: (v) => updateConfig({ heading: v }) }),
1781
+ /* @__PURE__ */ jsx(TextareaField, { label: "Description", value: config.description ?? "", onChange: (v) => updateConfig({ description: v }) }),
1782
+ /* @__PURE__ */ jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig({ imageUrl: v }) }),
1783
+ /* @__PURE__ */ jsx(TextField, { label: "Redirect URL", value: config.redirectUrl, placeholder: "https://...", onChange: (v) => updateConfig({ redirectUrl: v }) }),
1784
+ /* @__PURE__ */ jsx(NumberField, { label: "Redirect Delay (s)", value: config.redirectDelay, placeholder: "0", onChange: (v) => updateConfig({ redirectDelay: v }) }),
1785
+ /* @__PURE__ */ jsx(ToggleField, { label: "Show Response Summary", checked: !!config.showSummary, onChange: (v) => updateConfig({ showSummary: v }) })
1698
1786
  ] });
1699
1787
  case "rich-text":
1700
1788
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Rich Text", children: [
1701
- /* @__PURE__ */ jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 6, onChange: (v) => updateConfig("content", v) }),
1702
- /* @__PURE__ */ jsx(SelectField, { label: "Format", value: config.format ?? "html", options: [{ label: "HTML", value: "html" }, { label: "Markdown", value: "markdown" }], onChange: (v) => updateConfig("format", v) })
1789
+ /* @__PURE__ */ jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 6, onChange: (v) => updateConfig({ content: v }) }),
1790
+ /* @__PURE__ */ jsx(SelectField, { label: "Format", value: config.format ?? "html", options: [{ label: "HTML", value: "html" }, { label: "Markdown", value: "markdown" }], onChange: (v) => updateConfig({ format: v }) })
1703
1791
  ] });
1704
1792
  case "image":
1705
1793
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Image Settings", children: [
1706
- /* @__PURE__ */ jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "https://...", onChange: (v) => updateConfig("src", v) }),
1707
- /* @__PURE__ */ jsx(TextField, { label: "Alt Text", value: config.alt ?? "", onChange: (v) => updateConfig("alt", v) }),
1708
- /* @__PURE__ */ jsx(TextField, { label: "Caption", value: config.caption, onChange: (v) => updateConfig("caption", v) }),
1709
- /* @__PURE__ */ 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) }),
1710
- /* @__PURE__ */ jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 300px", onChange: (v) => updateConfig("width", v) }),
1711
- /* @__PURE__ */ jsx(TextField, { label: "Link URL", value: config.link, placeholder: "Click opens this URL", onChange: (v) => updateConfig("link", v) })
1794
+ /* @__PURE__ */ jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "https://...", onChange: (v) => updateConfig({ src: v }) }),
1795
+ /* @__PURE__ */ jsx(TextField, { label: "Alt Text", value: config.alt ?? "", onChange: (v) => updateConfig({ alt: v }) }),
1796
+ /* @__PURE__ */ jsx(TextField, { label: "Caption", value: config.caption, onChange: (v) => updateConfig({ caption: v }) }),
1797
+ /* @__PURE__ */ 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 }) }),
1798
+ /* @__PURE__ */ jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 300px", onChange: (v) => updateConfig({ width: v }) }),
1799
+ /* @__PURE__ */ jsx(TextField, { label: "Link URL", value: config.link, placeholder: "Click opens this URL", onChange: (v) => updateConfig({ link: v }) })
1712
1800
  ] });
1713
1801
  case "video":
1714
1802
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Video Settings", children: [
1715
- /* @__PURE__ */ jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "YouTube/Vimeo URL", onChange: (v) => updateConfig("src", v) }),
1716
- /* @__PURE__ */ 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) }),
1717
- /* @__PURE__ */ jsx(ToggleField, { label: "Autoplay", checked: !!config.autoplay, onChange: (v) => updateConfig("autoplay", v) }),
1718
- /* @__PURE__ */ jsx(ToggleField, { label: "Muted", checked: !!config.muted, onChange: (v) => updateConfig("muted", v) }),
1719
- /* @__PURE__ */ jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 640px", onChange: (v) => updateConfig("width", v) }),
1720
- /* @__PURE__ */ jsx(TextField, { label: "Height", value: config.height, placeholder: "e.g. 360px", onChange: (v) => updateConfig("height", v) })
1803
+ /* @__PURE__ */ jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "YouTube/Vimeo URL", onChange: (v) => updateConfig({ src: v }) }),
1804
+ /* @__PURE__ */ 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 }) }),
1805
+ /* @__PURE__ */ jsx(ToggleField, { label: "Autoplay", checked: !!config.autoplay, onChange: (v) => updateConfig({ autoplay: v }) }),
1806
+ /* @__PURE__ */ jsx(ToggleField, { label: "Muted", checked: !!config.muted, onChange: (v) => updateConfig({ muted: v }) }),
1807
+ /* @__PURE__ */ jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 640px", onChange: (v) => updateConfig({ width: v }) }),
1808
+ /* @__PURE__ */ jsx(TextField, { label: "Height", value: config.height, placeholder: "e.g. 360px", onChange: (v) => updateConfig({ height: v }) })
1721
1809
  ] });
1722
1810
  case "divider":
1723
1811
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Divider Settings", children: [
1724
- /* @__PURE__ */ 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) }),
1725
- /* @__PURE__ */ jsx(TextField, { label: "Color", value: config.color, placeholder: "#e5e7eb", onChange: (v) => updateConfig("color", v) }),
1726
- /* @__PURE__ */ jsx(NumberField, { label: "Thickness (px)", value: config.thickness, placeholder: "1", onChange: (v) => updateConfig("thickness", v) }),
1727
- /* @__PURE__ */ jsx(NumberField, { label: "Spacing (px)", value: config.spacing, placeholder: "16", onChange: (v) => updateConfig("spacing", v) })
1812
+ /* @__PURE__ */ 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 }) }),
1813
+ /* @__PURE__ */ jsx(TextField, { label: "Color", value: config.color, placeholder: "#e5e7eb", onChange: (v) => updateConfig({ color: v }) }),
1814
+ /* @__PURE__ */ jsx(NumberField, { label: "Thickness (px)", value: config.thickness, placeholder: "1", onChange: (v) => updateConfig({ thickness: v }) }),
1815
+ /* @__PURE__ */ jsx(NumberField, { label: "Spacing (px)", value: config.spacing, placeholder: "16", onChange: (v) => updateConfig({ spacing: v }) })
1728
1816
  ] });
1729
1817
  case "spacer":
1730
- return /* @__PURE__ */ jsx(ConfigSection, { title: "Spacer Settings", children: /* @__PURE__ */ jsx(NumberField, { label: "Height (px)", value: config.height ?? 32, onChange: (v) => updateConfig("height", v) }) });
1818
+ return /* @__PURE__ */ jsx(ConfigSection, { title: "Spacer Settings", children: /* @__PURE__ */ jsx(NumberField, { label: "Height (px)", value: config.height ?? 32, onChange: (v) => updateConfig({ height: v }) }) });
1731
1819
  // ── Structural ──
1732
1820
  case "section_header":
1733
1821
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Header Settings", children: [
1734
- /* @__PURE__ */ 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) }),
1735
- /* @__PURE__ */ jsx(ToggleField, { label: "Show Divider", checked: !!config.showDivider, onChange: (v) => updateConfig("showDivider", v) })
1822
+ /* @__PURE__ */ 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 }) }),
1823
+ /* @__PURE__ */ jsx(ToggleField, { label: "Show Divider", checked: !!config.showDivider, onChange: (v) => updateConfig({ showDivider: v }) })
1736
1824
  ] });
1737
1825
  case "info_block":
1738
1826
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Info Block", children: [
1739
- /* @__PURE__ */ jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 4, onChange: (v) => updateConfig("content", v) }),
1740
- /* @__PURE__ */ 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) })
1827
+ /* @__PURE__ */ jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 4, onChange: (v) => updateConfig({ content: v }) }),
1828
+ /* @__PURE__ */ 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 }) })
1741
1829
  ] });
1742
1830
  case "page_break":
1743
- return /* @__PURE__ */ jsx(ConfigSection, { title: "Page Break", children: /* @__PURE__ */ jsx(TextField, { label: "Label", value: config.label, placeholder: "Next page label", onChange: (v) => updateConfig("label", v) }) });
1831
+ return /* @__PURE__ */ jsx(ConfigSection, { title: "Page Break", children: /* @__PURE__ */ jsx(TextField, { label: "Label", value: config.label, placeholder: "Next page label", onChange: (v) => updateConfig({ label: v }) }) });
1744
1832
  case "consent":
1745
1833
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Consent Settings", children: [
1746
- /* @__PURE__ */ jsx(TextareaField, { label: "Consent Text", value: config.text ?? "", rows: 4, onChange: (v) => updateConfig("text", v) }),
1747
- /* @__PURE__ */ jsx(TextField, { label: "Checkbox Label", value: config.checkboxLabel ?? "I agree", onChange: (v) => updateConfig("checkboxLabel", v) }),
1748
- /* @__PURE__ */ jsx(TextareaField, { label: "Expandable Text", value: config.expandableText, rows: 3, placeholder: "Additional text shown on expand", onChange: (v) => updateConfig("expandableText", v) })
1834
+ /* @__PURE__ */ jsx(TextareaField, { label: "Consent Text", value: config.text ?? "", rows: 4, onChange: (v) => updateConfig({ text: v }) }),
1835
+ /* @__PURE__ */ jsx(TextField, { label: "Checkbox Label", value: config.checkboxLabel ?? "I agree", onChange: (v) => updateConfig({ checkboxLabel: v }) }),
1836
+ /* @__PURE__ */ jsx(TextareaField, { label: "Expandable Text", value: config.expandableText, rows: 3, placeholder: "Additional text shown on expand", onChange: (v) => updateConfig({ expandableText: v }) })
1749
1837
  ] });
1750
1838
  // ── Advanced ──
1751
1839
  case "matrix":
1752
1840
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Matrix Settings", children: [
1753
- /* @__PURE__ */ 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) }),
1754
- /* @__PURE__ */ 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) }),
1755
- /* @__PURE__ */ jsx(MatrixItemsEditor, { label: "Rows", items: config.rows ?? [], onChange: (v) => updateConfig("rows", v) }),
1756
- /* @__PURE__ */ jsx(MatrixItemsEditor, { label: "Columns", items: config.columns ?? [], onChange: (v) => updateConfig("columns", v) })
1841
+ /* @__PURE__ */ 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 }) }),
1842
+ /* @__PURE__ */ 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 }) }),
1843
+ /* @__PURE__ */ jsx(MatrixItemsEditor, { label: "Rows", items: config.rows ?? [], onChange: (v) => updateConfig({ rows: v }) }),
1844
+ /* @__PURE__ */ jsx(MatrixItemsEditor, { label: "Columns", items: config.columns ?? [], onChange: (v) => updateConfig({ columns: v }) })
1757
1845
  ] });
1758
1846
  case "repeater":
1759
1847
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Repeater Settings", children: [
1760
- /* @__PURE__ */ jsx(NumberField, { label: "Min Entries", value: config.minEntries, placeholder: "1", onChange: (v) => updateConfig("minEntries", v) }),
1761
- /* @__PURE__ */ jsx(NumberField, { label: "Max Entries", value: config.maxEntries, onChange: (v) => updateConfig("maxEntries", v) }),
1762
- /* @__PURE__ */ jsx(NumberField, { label: "Default Entries", value: config.defaultEntries, placeholder: "1", onChange: (v) => updateConfig("defaultEntries", v) }),
1763
- /* @__PURE__ */ jsx(TextField, { label: "Add Button Label", value: config.addLabel, placeholder: "Add Entry", onChange: (v) => updateConfig("addLabel", v) }),
1764
- /* @__PURE__ */ jsx(TextField, { label: "Remove Button Label", value: config.removeLabel, placeholder: "Remove", onChange: (v) => updateConfig("removeLabel", v) }),
1848
+ /* @__PURE__ */ jsx(NumberField, { label: "Min Entries", value: config.minEntries, placeholder: "1", onChange: (v) => updateConfig({ minEntries: v }) }),
1849
+ /* @__PURE__ */ jsx(NumberField, { label: "Max Entries", value: config.maxEntries, onChange: (v) => updateConfig({ maxEntries: v }) }),
1850
+ /* @__PURE__ */ jsx(NumberField, { label: "Default Entries", value: config.defaultEntries, placeholder: "1", onChange: (v) => updateConfig({ defaultEntries: v }) }),
1851
+ /* @__PURE__ */ jsx(TextField, { label: "Add Button Label", value: config.addLabel, placeholder: "Add Entry", onChange: (v) => updateConfig({ addLabel: v }) }),
1852
+ /* @__PURE__ */ jsx(TextField, { label: "Remove Button Label", value: config.removeLabel, placeholder: "Remove", onChange: (v) => updateConfig({ removeLabel: v }) }),
1765
1853
  /* @__PURE__ */ 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." })
1766
1854
  ] });
1767
1855
  case "address": {
@@ -1775,9 +1863,9 @@ function QuestionConfigEditor({ question, onUpdate }) {
1775
1863
  ];
1776
1864
  const activeFields = config.fields ?? ["street", "city", "state", "zip", "country"];
1777
1865
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Address Settings", children: [
1778
- /* @__PURE__ */ 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) }),
1779
- config.provider !== "none" && /* @__PURE__ */ jsx(TextField, { label: "API Key", value: config.apiKey, placeholder: "Provider API key", onChange: (v) => updateConfig("apiKey", v) }),
1780
- /* @__PURE__ */ jsx(TextField, { label: "Default Country", value: config.defaultCountry, placeholder: "e.g. US", onChange: (v) => updateConfig("defaultCountry", v) }),
1866
+ /* @__PURE__ */ 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 }) }),
1867
+ config.provider !== "none" && /* @__PURE__ */ jsx(TextField, { label: "API Key", value: config.apiKey, placeholder: "Provider API key", onChange: (v) => updateConfig({ apiKey: v }) }),
1868
+ /* @__PURE__ */ jsx(TextField, { label: "Default Country", value: config.defaultCountry, placeholder: "e.g. US", onChange: (v) => updateConfig({ defaultCountry: v }) }),
1781
1869
  /* @__PURE__ */ jsxs("div", { children: [
1782
1870
  /* @__PURE__ */ jsx(Label, { className: "text-xs text-muted-foreground mb-2 block", children: "Fields" }),
1783
1871
  /* @__PURE__ */ jsx("div", { className: "space-y-1.5", children: ADDRESS_FIELDS.map((f) => /* @__PURE__ */ jsx(
@@ -1787,7 +1875,7 @@ function QuestionConfigEditor({ question, onUpdate }) {
1787
1875
  checked: activeFields.includes(f.value),
1788
1876
  onChange: (checked) => {
1789
1877
  const next = checked ? [...activeFields, f.value] : activeFields.filter((v) => v !== f.value);
1790
- updateConfig("fields", next.length > 0 ? next : void 0);
1878
+ updateConfig({ fields: next.length > 0 ? next : void 0 });
1791
1879
  }
1792
1880
  },
1793
1881
  f.value
@@ -1797,41 +1885,47 @@ function QuestionConfigEditor({ question, onUpdate }) {
1797
1885
  }
1798
1886
  case "payment":
1799
1887
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Payment Settings", children: [
1800
- /* @__PURE__ */ jsx(SelectField, { label: "Provider", value: config.provider ?? "stripe", options: [{ label: "Stripe", value: "stripe" }, { label: "PayPal", value: "paypal" }], onChange: (v) => updateConfig("provider", v) }),
1801
- /* @__PURE__ */ jsx(TextField, { label: "Public Key", value: config.publicKey ?? "", placeholder: "Provider public/client key", onChange: (v) => updateConfig("publicKey", v) }),
1802
- /* @__PURE__ */ jsx(NumberField, { label: "Amount", value: config.amount, onChange: (v) => updateConfig("amount", v) }),
1803
- /* @__PURE__ */ jsx(TextField, { label: "Amount Field", value: config.amountField, placeholder: "Field ID for dynamic amount", onChange: (v) => updateConfig("amountField", v) }),
1804
- /* @__PURE__ */ jsx(TextField, { label: "Currency", value: config.currency, placeholder: "USD", onChange: (v) => updateConfig("currency", v) }),
1805
- /* @__PURE__ */ jsx(TextField, { label: "Description", value: config.description, onChange: (v) => updateConfig("description", v) })
1888
+ /* @__PURE__ */ jsx(SelectField, { label: "Provider", value: config.provider ?? "stripe", options: [{ label: "Stripe", value: "stripe" }, { label: "PayPal", value: "paypal" }], onChange: (v) => updateConfig({ provider: v }) }),
1889
+ /* @__PURE__ */ jsx(TextField, { label: "Public Key", value: config.publicKey ?? "", placeholder: "Provider public/client key", onChange: (v) => updateConfig({ publicKey: v }) }),
1890
+ /* @__PURE__ */ jsx(TextField, { label: "Server URL", value: config.serverUrl ?? "", placeholder: "https://api.example.com/create-intent", onChange: (v) => updateConfig({ serverUrl: v || void 0 }) }),
1891
+ /* @__PURE__ */ jsx(TextField, { label: "Client Secret Path", value: config.responseMapping?.clientSecretPath ?? "", placeholder: "clientSecret", onChange: (v) => updateConfig({ responseMapping: v ? { clientSecretPath: v } : void 0 }) }),
1892
+ /* @__PURE__ */ jsx(NumberField, { label: "Amount", value: config.amount, onChange: (v) => updateConfig({ amount: v }) }),
1893
+ /* @__PURE__ */ jsx(TextField, { label: "Amount Field", value: config.amountField, placeholder: "Field ID for dynamic amount", onChange: (v) => updateConfig({ amountField: v }) }),
1894
+ /* @__PURE__ */ jsx(TextField, { label: "Currency", value: config.currency, placeholder: "USD", onChange: (v) => updateConfig({ currency: v }) }),
1895
+ /* @__PURE__ */ jsx(TextField, { label: "Description", value: config.description, onChange: (v) => updateConfig({ description: v }) })
1806
1896
  ] });
1807
1897
  case "calculated":
1808
1898
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Calculated Field", children: [
1809
- /* @__PURE__ */ jsx(TextField, { label: "Expression", value: config.expression ?? "", placeholder: "e.g. {q1} + {q2}", onChange: (v) => updateConfig("expression", v) }),
1810
- /* @__PURE__ */ 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) }),
1811
- /* @__PURE__ */ jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "2", onChange: (v) => updateConfig("decimalPlaces", v) }),
1812
- /* @__PURE__ */ jsx(TextField, { label: "Prefix", value: config.prefix, onChange: (v) => updateConfig("prefix", v) }),
1813
- /* @__PURE__ */ jsx(TextField, { label: "Suffix", value: config.suffix, onChange: (v) => updateConfig("suffix", v) }),
1814
- /* @__PURE__ */ jsx(ToggleField, { label: "Visible to User", checked: config.visible !== false, onChange: (v) => updateConfig("visible", v) })
1899
+ /* @__PURE__ */ jsx(TextField, { label: "Expression", value: config.expression ?? "", placeholder: "e.g. {q1} + {q2}", onChange: (v) => updateConfig({ expression: v }) }),
1900
+ /* @__PURE__ */ 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 }) }),
1901
+ /* @__PURE__ */ jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "2", onChange: (v) => updateConfig({ decimalPlaces: v }) }),
1902
+ /* @__PURE__ */ jsx(TextField, { label: "Prefix", value: config.prefix, onChange: (v) => updateConfig({ prefix: v }) }),
1903
+ /* @__PURE__ */ jsx(TextField, { label: "Suffix", value: config.suffix, onChange: (v) => updateConfig({ suffix: v }) }),
1904
+ /* @__PURE__ */ jsx(ToggleField, { label: "Visible to User", checked: config.visible !== false, onChange: (v) => updateConfig({ visible: v }) })
1815
1905
  ] });
1816
1906
  case "hidden":
1817
1907
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Hidden Field", children: [
1818
- /* @__PURE__ */ 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) }),
1819
- config.source === "static" && /* @__PURE__ */ jsx(TextField, { label: "Default Value", value: config.defaultValue, onChange: (v) => updateConfig("defaultValue", v) }),
1820
- config.source === "url_param" && /* @__PURE__ */ jsx(TextField, { label: "Parameter Name", value: config.paramName, placeholder: "e.g. utm_source", onChange: (v) => updateConfig("paramName", v) }),
1821
- config.source === "cookie" && /* @__PURE__ */ jsx(TextField, { label: "Cookie Name", value: config.cookieName, onChange: (v) => updateConfig("cookieName", v) })
1908
+ /* @__PURE__ */ 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 }) }),
1909
+ config.source === "static" && /* @__PURE__ */ jsx(TextField, { label: "Default Value", value: config.defaultValue, onChange: (v) => updateConfig({ defaultValue: v }) }),
1910
+ config.source === "url_param" && /* @__PURE__ */ jsx(TextField, { label: "Parameter Name", value: config.paramName, placeholder: "e.g. utm_source", onChange: (v) => updateConfig({ paramName: v }) }),
1911
+ config.source === "cookie" && /* @__PURE__ */ jsx(TextField, { label: "Cookie Name", value: config.cookieName, onChange: (v) => updateConfig({ cookieName: v }) })
1822
1912
  ] });
1823
1913
  case "scoring":
1824
1914
  return /* @__PURE__ */ jsxs(ConfigSection, { title: "Scoring Settings", children: [
1825
- /* @__PURE__ */ jsx(ToggleField, { label: "Show Score", checked: !!config.showScore, onChange: (v) => updateConfig("showScore", v) }),
1826
- /* @__PURE__ */ jsx(ScoringOptionsEditor, { options: config.options ?? [], onChange: (v) => updateConfig("options", v) }),
1827
- /* @__PURE__ */ jsx(ScoreRangesEditor, { ranges: config.scoreRanges ?? [], onChange: (v) => updateConfig("scoreRanges", v) })
1915
+ /* @__PURE__ */ jsx(ToggleField, { label: "Show Score", checked: !!config.showScore, onChange: (v) => updateConfig({ showScore: v }) }),
1916
+ /* @__PURE__ */ jsx(ScoringOptionsEditor, { options: config.options ?? [], onChange: (v) => updateConfig({ options: v }) }),
1917
+ /* @__PURE__ */ jsx(ScoreRangesEditor, { ranges: config.scoreRanges ?? [], onChange: (v) => updateConfig({ scoreRanges: v }) })
1828
1918
  ] });
1829
1919
  case "ranking":
1830
- return /* @__PURE__ */ jsx(ConfigSection, { title: "Ranking Settings", children: /* @__PURE__ */ jsx(MatrixItemsEditor, { label: "Items", items: config.items ?? [], onChange: (v) => updateConfig("items", v) }) });
1920
+ return /* @__PURE__ */ jsx(ConfigSection, { title: "Ranking Settings", children: /* @__PURE__ */ jsx(MatrixItemsEditor, { label: "Items", items: config.items ?? [], onChange: (v) => updateConfig({ items: v }) }) });
1921
+ case "phone_international":
1922
+ return /* @__PURE__ */ jsxs(ConfigSection, { title: "International Phone Settings", children: [
1923
+ /* @__PURE__ */ jsx(TextField, { label: "Default Country", value: config.defaultCountry ?? "US", placeholder: "e.g. US", onChange: (v) => updateConfig({ defaultCountry: v }) }),
1924
+ /* @__PURE__ */ 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 }) })
1925
+ ] });
1831
1926
  // Types with no additional config
1832
1927
  case "email":
1833
1928
  case "phone":
1834
- case "phone_international":
1835
1929
  case "url":
1836
1930
  return null;
1837
1931
  default:
@@ -1923,7 +2017,10 @@ function SelectField({
1923
2017
  }) {
1924
2018
  return /* @__PURE__ */ jsxs("div", { children: [
1925
2019
  /* @__PURE__ */ jsx(Label, { className: "text-xs text-muted-foreground mb-1", children: label }),
1926
- /* @__PURE__ */ jsx(NativeSelect, { value, onChange: (e) => onChange(e.target.value), children: options.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label }, opt.value)) })
2020
+ /* @__PURE__ */ jsxs(Select, { value, onValueChange: onChange, children: [
2021
+ /* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx("span", { children: options.find((o) => o.value === value)?.label ?? value }) }),
2022
+ /* @__PURE__ */ jsx(SelectContent, { children: options.map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
2023
+ ] })
1927
2024
  ] });
1928
2025
  }
1929
2026
  function LikertLabelsEditor({
@@ -2069,6 +2166,59 @@ function ScoringOptionsEditor({
2069
2166
  ] }, index)) })
2070
2167
  ] });
2071
2168
  }
2169
+ function AppointmentSlotsEditor({
2170
+ slots,
2171
+ onChange
2172
+ }) {
2173
+ const handleDateChange = (index, date) => {
2174
+ const updated = slots.map((s, i) => i === index ? { ...s, date } : s);
2175
+ onChange(updated);
2176
+ };
2177
+ const handleTimesChange = (index, timesStr) => {
2178
+ const times = timesStr.split(",").map((t) => t.trim()).filter(Boolean);
2179
+ const updated = slots.map((s, i) => i === index ? { ...s, times } : s);
2180
+ onChange(updated);
2181
+ };
2182
+ const handleAdd = () => {
2183
+ const tomorrow = /* @__PURE__ */ new Date();
2184
+ tomorrow.setDate(tomorrow.getDate() + 1);
2185
+ const dateStr = tomorrow.toISOString().split("T")[0];
2186
+ onChange([...slots, { date: dateStr, times: ["09:00", "10:00", "11:00", "14:00", "15:00"] }]);
2187
+ };
2188
+ const handleRemove = (index) => {
2189
+ onChange(slots.filter((_, i) => i !== index));
2190
+ };
2191
+ return /* @__PURE__ */ jsxs("div", { children: [
2192
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2", children: [
2193
+ /* @__PURE__ */ jsx(Label, { className: "text-xs text-muted-foreground", children: "Slots" }),
2194
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "link", size: "xs", onClick: handleAdd, className: "px-0", children: "+ Add Date" })
2195
+ ] }),
2196
+ slots.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: "No slots configured. Add a date to get started." }),
2197
+ /* @__PURE__ */ jsx("div", { className: "space-y-2", children: slots.map((slot, index) => /* @__PURE__ */ jsxs("div", { className: "p-2 rounded-md border border-border space-y-1.5 group", children: [
2198
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
2199
+ /* @__PURE__ */ jsx(
2200
+ Input,
2201
+ {
2202
+ type: "date",
2203
+ value: slot.date,
2204
+ onChange: (e) => handleDateChange(index, e.target.value),
2205
+ className: "h-7 text-xs flex-1"
2206
+ }
2207
+ ),
2208
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-xs", onClick: () => handleRemove(index), className: "text-destructive opacity-0 group-hover:opacity-100 transition-opacity", children: "x" })
2209
+ ] }),
2210
+ /* @__PURE__ */ jsx(
2211
+ Input,
2212
+ {
2213
+ value: slot.times.join(", "),
2214
+ onChange: (e) => handleTimesChange(index, e.target.value),
2215
+ className: "h-7 text-xs",
2216
+ placeholder: "09:00, 10:00, 14:00, 15:00"
2217
+ }
2218
+ )
2219
+ ] }, index)) })
2220
+ ] });
2221
+ }
2072
2222
  function ScoreRangesEditor({
2073
2223
  ranges,
2074
2224
  onChange
@@ -2101,6 +2251,26 @@ function ScoreRangesEditor({
2101
2251
  ] }, index)) })
2102
2252
  ] });
2103
2253
  }
2254
+ var NativeSelect = forwardRef(
2255
+ ({ className, wrapperClassName, children, ...props }, ref) => {
2256
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative", wrapperClassName), children: [
2257
+ /* @__PURE__ */ jsx(
2258
+ "select",
2259
+ {
2260
+ ref,
2261
+ className: cn(
2262
+ "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",
2263
+ className
2264
+ ),
2265
+ ...props,
2266
+ children
2267
+ }
2268
+ ),
2269
+ /* @__PURE__ */ jsx(ChevronDown, { className: "pointer-events-none absolute right-2.5 top-1/2 -translate-y-1/2 size-4 text-muted-foreground" })
2270
+ ] });
2271
+ }
2272
+ );
2273
+ NativeSelect.displayName = "NativeSelect";
2104
2274
  var RULE_TYPES = [
2105
2275
  { value: "minLength", label: "Min Length", description: "Minimum character count" },
2106
2276
  { value: "maxLength", label: "Max Length", description: "Maximum character count" },