@squaredr/fieldcraft-pro 1.7.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +51 -51
- package/README.md +139 -139
- package/dist/{chunk-VEP3DOCQ.mjs → chunk-5QXKDYWY.mjs} +103 -19
- package/dist/{chunk-GZIV2XAD.mjs → chunk-7GPX3YIB.mjs} +146 -183
- package/dist/{chunk-J5V6OVZO.mjs → chunk-DWRLPGX5.mjs} +690 -211
- package/dist/{chunk-4TN6YJDF.mjs → chunk-KTIU7VCP.mjs} +971 -214
- package/dist/default-schema-BGxf9Jrg.d.ts +174 -0
- package/dist/default-schema-Bwq8FATF.d.mts +174 -0
- package/dist/form-builder/index.d.mts +14 -170
- package/dist/form-builder/index.d.ts +14 -170
- package/dist/form-builder/index.js +827 -326
- package/dist/form-builder/index.mjs +1 -1
- package/dist/index.d.mts +111 -10
- package/dist/index.d.ts +111 -10
- package/dist/index.js +3525 -971
- package/dist/index.mjs +1424 -124
- package/dist/response-viewer/index.d.mts +1 -1
- package/dist/response-viewer/index.d.ts +1 -1
- package/dist/response-viewer/index.js +146 -183
- package/dist/response-viewer/index.mjs +1 -1
- package/dist/styles.css +2 -2
- package/dist/templates/index.d.mts +1 -1
- package/dist/templates/index.d.ts +1 -1
- package/dist/templates/index.js +103 -19
- package/dist/templates/index.mjs +1 -1
- package/dist/theme-editor/index.d.mts +12 -7
- package/dist/theme-editor/index.d.ts +12 -7
- package/dist/theme-editor/index.js +971 -214
- package/dist/theme-editor/index.mjs +1 -1
- package/dist/{types-bFHsZT1n.d.mts → types-BQOeI3LX.d.mts} +1 -1
- package/dist/{types-bFHsZT1n.d.ts → types-BQOeI3LX.d.ts} +1 -1
- package/package.json +29 -18
- package/theme-editor/styles.css +497 -466
|
@@ -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
|
|
|
@@ -17,16 +19,18 @@ function useUndoRedo(currentSchema, setSchema) {
|
|
|
17
19
|
const canRedo = currentIndex < historyRef.current.length - 1;
|
|
18
20
|
const push = useCallback(
|
|
19
21
|
(schema) => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
setCurrentIndex((prevIndex) => {
|
|
23
|
+
historyRef.current = historyRef.current.slice(0, prevIndex + 1);
|
|
24
|
+
historyRef.current.push(schema);
|
|
25
|
+
let newIndex = prevIndex + 1;
|
|
26
|
+
if (historyRef.current.length > MAX_HISTORY) {
|
|
27
|
+
historyRef.current.shift();
|
|
28
|
+
newIndex = Math.max(0, newIndex - 1);
|
|
29
|
+
}
|
|
30
|
+
return newIndex;
|
|
31
|
+
});
|
|
28
32
|
},
|
|
29
|
-
[
|
|
33
|
+
[]
|
|
30
34
|
);
|
|
31
35
|
const undo = useCallback(() => {
|
|
32
36
|
if (currentIndex > 0) {
|
|
@@ -57,13 +61,9 @@ function useUndoRedo(currentSchema, setSchema) {
|
|
|
57
61
|
}
|
|
58
62
|
|
|
59
63
|
// src/form-builder/utils/id-generator.ts
|
|
60
|
-
var counter = 0;
|
|
61
64
|
function generateId(prefix) {
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
counter = (counter + 1) % 1e4;
|
|
65
|
-
const count = counter.toString(36);
|
|
66
|
-
return `${prefix}_${timestamp}${count}${random}`;
|
|
65
|
+
const uuid = crypto.randomUUID().replace(/-/g, "").substring(0, 12);
|
|
66
|
+
return `${prefix}_${uuid}`;
|
|
67
67
|
}
|
|
68
68
|
function generateSectionId() {
|
|
69
69
|
return generateId("section");
|
|
@@ -150,18 +150,39 @@ function duplicateSection(schema, sectionId) {
|
|
|
150
150
|
const sectionIndex = newSchema.sections.findIndex((s) => s.id === sectionId);
|
|
151
151
|
if (sectionIndex === -1) return schema;
|
|
152
152
|
const original = newSchema.sections[sectionIndex];
|
|
153
|
+
const idMap = /* @__PURE__ */ new Map();
|
|
154
|
+
for (const q of original.questions) {
|
|
155
|
+
idMap.set(q.id, generateQuestionId());
|
|
156
|
+
}
|
|
153
157
|
const duplicate = {
|
|
154
158
|
...original,
|
|
155
159
|
id: generateSectionId(),
|
|
156
160
|
title: `${original.title} (Copy)`,
|
|
161
|
+
showIf: original.showIf ? remapConditionFieldIds(original.showIf, idMap) : void 0,
|
|
157
162
|
questions: original.questions.map((q) => ({
|
|
158
163
|
...q,
|
|
159
|
-
id:
|
|
164
|
+
id: idMap.get(q.id),
|
|
165
|
+
showIf: q.showIf ? remapConditionFieldIds(q.showIf, idMap) : void 0
|
|
160
166
|
}))
|
|
161
167
|
};
|
|
162
168
|
newSchema.sections.splice(sectionIndex + 1, 0, duplicate);
|
|
163
169
|
return newSchema;
|
|
164
170
|
}
|
|
171
|
+
function remapConditionFieldIds(expr, idMap) {
|
|
172
|
+
if (expr.field) {
|
|
173
|
+
return {
|
|
174
|
+
...expr,
|
|
175
|
+
field: idMap.get(expr.field) ?? expr.field
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
if (expr.conditions) {
|
|
179
|
+
return {
|
|
180
|
+
...expr,
|
|
181
|
+
conditions: expr.conditions.map((c) => remapConditionFieldIds(c, idMap))
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
return expr;
|
|
185
|
+
}
|
|
165
186
|
function addQuestion(schema, sectionId, question, index) {
|
|
166
187
|
const newSchema = deepClone(schema);
|
|
167
188
|
const section = newSchema.sections.find((s) => s.id === sectionId);
|
|
@@ -305,7 +326,7 @@ function useBuilderState(initialSchema) {
|
|
|
305
326
|
(sectionId) => {
|
|
306
327
|
applyMutation((s) => removeSection(s, sectionId));
|
|
307
328
|
setSelectedItem((prev) => {
|
|
308
|
-
if (prev?.
|
|
329
|
+
if (prev?.sectionId === sectionId) return null;
|
|
309
330
|
return prev;
|
|
310
331
|
});
|
|
311
332
|
},
|
|
@@ -644,7 +665,7 @@ var QUESTION_TYPE_INFO = {
|
|
|
644
665
|
category: "advanced",
|
|
645
666
|
icon: "ListPlus",
|
|
646
667
|
description: "Repeatable group of fields",
|
|
647
|
-
defaultConfig: { type: "repeater", fields: [],
|
|
668
|
+
defaultConfig: { type: "repeater", fields: [], minEntries: 1, maxEntries: 10 }
|
|
648
669
|
},
|
|
649
670
|
likert: {
|
|
650
671
|
type: "likert",
|
|
@@ -655,13 +676,7 @@ var QUESTION_TYPE_INFO = {
|
|
|
655
676
|
requiresOptions: true,
|
|
656
677
|
defaultConfig: {
|
|
657
678
|
type: "likert",
|
|
658
|
-
|
|
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
|
-
]
|
|
679
|
+
labels: ["Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"]
|
|
665
680
|
}
|
|
666
681
|
},
|
|
667
682
|
scoring: {
|
|
@@ -714,7 +729,7 @@ var QUESTION_TYPE_INFO = {
|
|
|
714
729
|
category: "advanced",
|
|
715
730
|
icon: "CreditCard",
|
|
716
731
|
description: "Collect payment via Stripe",
|
|
717
|
-
defaultConfig: { type: "payment", provider: "stripe", publicKey: "", currency: "USD" }
|
|
732
|
+
defaultConfig: { type: "payment", provider: "stripe", publicKey: "", currency: "USD", serverUrl: "" }
|
|
718
733
|
},
|
|
719
734
|
// ── Structural ──
|
|
720
735
|
section_header: {
|
|
@@ -1441,6 +1456,14 @@ function SectionBlock({ section, builderState }) {
|
|
|
1441
1456
|
}
|
|
1442
1457
|
function FormCanvas({ builderState }) {
|
|
1443
1458
|
const { schema } = builderState;
|
|
1459
|
+
const [localTitle, setLocalTitle] = useState(schema.title);
|
|
1460
|
+
const [localDesc, setLocalDesc] = useState(schema.description ?? "");
|
|
1461
|
+
useEffect(() => {
|
|
1462
|
+
setLocalTitle(schema.title);
|
|
1463
|
+
}, [schema.title]);
|
|
1464
|
+
useEffect(() => {
|
|
1465
|
+
setLocalDesc(schema.description ?? "");
|
|
1466
|
+
}, [schema.description]);
|
|
1444
1467
|
const handleAddSection = () => {
|
|
1445
1468
|
const newSection = {
|
|
1446
1469
|
id: generateSectionId(),
|
|
@@ -1457,9 +1480,12 @@ function FormCanvas({ builderState }) {
|
|
|
1457
1480
|
"input",
|
|
1458
1481
|
{
|
|
1459
1482
|
type: "text",
|
|
1460
|
-
value:
|
|
1461
|
-
onChange: (e) =>
|
|
1462
|
-
|
|
1483
|
+
value: localTitle,
|
|
1484
|
+
onChange: (e) => setLocalTitle(e.target.value),
|
|
1485
|
+
onBlur: () => {
|
|
1486
|
+
if (localTitle !== schema.title) {
|
|
1487
|
+
builderState.updateSchema({ ...schema, title: localTitle });
|
|
1488
|
+
}
|
|
1463
1489
|
},
|
|
1464
1490
|
className: "w-full text-xl font-bold bg-transparent text-foreground border-0 outline-none p-1.5 rounded-md focus:bg-card transition-colors",
|
|
1465
1491
|
placeholder: "Form Title"
|
|
@@ -1468,9 +1494,12 @@ function FormCanvas({ builderState }) {
|
|
|
1468
1494
|
/* @__PURE__ */ jsx(
|
|
1469
1495
|
"textarea",
|
|
1470
1496
|
{
|
|
1471
|
-
value:
|
|
1472
|
-
onChange: (e) =>
|
|
1473
|
-
|
|
1497
|
+
value: localDesc,
|
|
1498
|
+
onChange: (e) => setLocalDesc(e.target.value),
|
|
1499
|
+
onBlur: () => {
|
|
1500
|
+
if (localDesc !== (schema.description ?? "")) {
|
|
1501
|
+
builderState.updateSchema({ ...schema, description: localDesc || void 0 });
|
|
1502
|
+
}
|
|
1474
1503
|
},
|
|
1475
1504
|
className: "w-full text-sm text-muted-foreground bg-transparent border-0 outline-none p-1.5 resize-y min-h-12 rounded-md leading-relaxed focus:bg-card transition-colors",
|
|
1476
1505
|
placeholder: "Form description (optional)"
|
|
@@ -1509,259 +1538,469 @@ function FormCanvas({ builderState }) {
|
|
|
1509
1538
|
] })
|
|
1510
1539
|
] }) });
|
|
1511
1540
|
}
|
|
1512
|
-
var
|
|
1513
|
-
|
|
1514
|
-
|
|
1541
|
+
var Select = SelectPrimitive.Root;
|
|
1542
|
+
var SelectTrigger = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
1543
|
+
SelectPrimitive.Trigger,
|
|
1544
|
+
{
|
|
1545
|
+
ref,
|
|
1546
|
+
className: cn(
|
|
1547
|
+
"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",
|
|
1548
|
+
className
|
|
1549
|
+
),
|
|
1550
|
+
...props,
|
|
1551
|
+
children: [
|
|
1552
|
+
children,
|
|
1553
|
+
/* @__PURE__ */ jsx(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-4 text-muted-foreground" }) })
|
|
1554
|
+
]
|
|
1555
|
+
}
|
|
1556
|
+
));
|
|
1557
|
+
SelectTrigger.displayName = "SelectTrigger";
|
|
1558
|
+
var SelectContent = React.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
|
|
1559
|
+
SelectPrimitive.Content,
|
|
1560
|
+
{
|
|
1561
|
+
ref,
|
|
1562
|
+
className: cn(
|
|
1563
|
+
"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",
|
|
1564
|
+
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",
|
|
1565
|
+
className
|
|
1566
|
+
),
|
|
1567
|
+
position,
|
|
1568
|
+
...props,
|
|
1569
|
+
children: [
|
|
1570
|
+
/* @__PURE__ */ jsx(SelectPrimitive.ScrollUpButton, { className: "flex cursor-default items-center justify-center py-1", children: /* @__PURE__ */ jsx(ChevronUp, { className: "size-4" }) }),
|
|
1515
1571
|
/* @__PURE__ */ jsx(
|
|
1516
|
-
|
|
1572
|
+
SelectPrimitive.Viewport,
|
|
1517
1573
|
{
|
|
1518
|
-
ref,
|
|
1519
1574
|
className: cn(
|
|
1520
|
-
"
|
|
1521
|
-
|
|
1575
|
+
"p-1",
|
|
1576
|
+
position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
|
|
1522
1577
|
),
|
|
1523
|
-
...props,
|
|
1524
1578
|
children
|
|
1525
1579
|
}
|
|
1526
1580
|
),
|
|
1527
|
-
/* @__PURE__ */ jsx(
|
|
1528
|
-
]
|
|
1581
|
+
/* @__PURE__ */ jsx(SelectPrimitive.ScrollDownButton, { className: "flex cursor-default items-center justify-center py-1", children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-4" }) })
|
|
1582
|
+
]
|
|
1529
1583
|
}
|
|
1530
|
-
);
|
|
1531
|
-
|
|
1584
|
+
) }));
|
|
1585
|
+
SelectContent.displayName = "SelectContent";
|
|
1586
|
+
var SelectItem = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
1587
|
+
SelectPrimitive.Item,
|
|
1588
|
+
{
|
|
1589
|
+
ref,
|
|
1590
|
+
className: cn(
|
|
1591
|
+
"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",
|
|
1592
|
+
className
|
|
1593
|
+
),
|
|
1594
|
+
...props,
|
|
1595
|
+
children: [
|
|
1596
|
+
/* @__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" }) }) }),
|
|
1597
|
+
/* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children })
|
|
1598
|
+
]
|
|
1599
|
+
}
|
|
1600
|
+
));
|
|
1601
|
+
SelectItem.displayName = "SelectItem";
|
|
1532
1602
|
function useConfigUpdater(question, onUpdate) {
|
|
1533
|
-
return (
|
|
1603
|
+
return (updates) => {
|
|
1534
1604
|
const current = question.config ?? {};
|
|
1535
|
-
|
|
1605
|
+
const merged = { ...current, type: question.type, ...updates };
|
|
1606
|
+
for (const key of Object.keys(merged)) {
|
|
1607
|
+
if (merged[key] === void 0) delete merged[key];
|
|
1608
|
+
}
|
|
1609
|
+
onUpdate({ config: merged });
|
|
1536
1610
|
};
|
|
1537
1611
|
}
|
|
1538
|
-
function QuestionConfigEditor({ question, onUpdate }) {
|
|
1612
|
+
function QuestionConfigEditor({ question, schema, onUpdate }) {
|
|
1539
1613
|
const updateConfig = useConfigUpdater(question, onUpdate);
|
|
1540
1614
|
const config = question.config ?? {};
|
|
1615
|
+
const allQuestions = useMemo(() => {
|
|
1616
|
+
if (!schema?.sections) return [];
|
|
1617
|
+
return schema.sections.flatMap((s) => s.questions || []);
|
|
1618
|
+
}, [schema]);
|
|
1619
|
+
const candidateAmountFields = useMemo(() => {
|
|
1620
|
+
return allQuestions.filter((q) => q.id !== question.id && ["calculated", "number", "slider", "rating", "single_select"].includes(q.type)).map((q) => ({ label: `${q.label || q.id} (${q.id})`, value: q.id }));
|
|
1621
|
+
}, [allQuestions, question.id]);
|
|
1622
|
+
const candidateTimezoneFields = useMemo(() => {
|
|
1623
|
+
return allQuestions.filter((q) => q.id !== question.id && ["dropdown", "single_select", "short_text"].includes(q.type)).map((q) => ({ label: `${q.label || q.id} (${q.id})`, value: q.id }));
|
|
1624
|
+
}, [allQuestions, question.id]);
|
|
1541
1625
|
switch (question.type) {
|
|
1542
1626
|
// ── Text ──
|
|
1543
1627
|
case "short_text":
|
|
1544
1628
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Text Settings", children: [
|
|
1545
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "255", onChange: (v) => updateConfig(
|
|
1546
|
-
/* @__PURE__ */ jsx(SelectField, { label: "Input Type", value: config.inputType ?? "text", options: [{ label: "Text", value: "text" }, { label: "Password", value: "password" }], onChange: (v) => updateConfig(
|
|
1547
|
-
/* @__PURE__ */ jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig(
|
|
1548
|
-
/* @__PURE__ */ jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. USD", onChange: (v) => updateConfig(
|
|
1629
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "255", onChange: (v) => updateConfig({ maxLength: v }) }),
|
|
1630
|
+
/* @__PURE__ */ jsx(SelectField, { label: "Input Type", value: config.inputType ?? "text", options: [{ label: "Text", value: "text" }, { label: "Password", value: "password" }], onChange: (v) => updateConfig({ inputType: v }) }),
|
|
1631
|
+
/* @__PURE__ */ jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig({ prefix: v }) }),
|
|
1632
|
+
/* @__PURE__ */ jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. USD", onChange: (v) => updateConfig({ suffix: v }) })
|
|
1549
1633
|
] });
|
|
1550
1634
|
case "long_text":
|
|
1551
1635
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Text Settings", children: [
|
|
1552
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "No limit", onChange: (v) => updateConfig(
|
|
1553
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Rows", value: config.rows, placeholder: "4", onChange: (v) => updateConfig(
|
|
1554
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Show Character Count", checked: !!config.showCharCount, onChange: (v) => updateConfig(
|
|
1636
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Max Length", value: config.maxLength, placeholder: "No limit", onChange: (v) => updateConfig({ maxLength: v }) }),
|
|
1637
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Rows", value: config.rows, placeholder: "4", onChange: (v) => updateConfig({ rows: v }) }),
|
|
1638
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Show Character Count", checked: !!config.showCharCount, onChange: (v) => updateConfig({ showCharCount: v }) })
|
|
1555
1639
|
] });
|
|
1556
1640
|
case "legal_name":
|
|
1557
1641
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Name Fields", children: [
|
|
1558
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Show Middle Name", checked: !!config.showMiddleName, onChange: (v) => updateConfig(
|
|
1559
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Show Suffix", checked: !!config.showSuffix, onChange: (v) => updateConfig(
|
|
1642
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Show Middle Name", checked: !!config.showMiddleName, onChange: (v) => updateConfig({ showMiddleName: v }) }),
|
|
1643
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Show Suffix", checked: !!config.showSuffix, onChange: (v) => updateConfig({ showSuffix: v }) })
|
|
1560
1644
|
] });
|
|
1561
1645
|
// ── Numeric ──
|
|
1562
1646
|
case "number":
|
|
1563
1647
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Number Settings", children: [
|
|
1564
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Min", value: config.min, onChange: (v) => updateConfig(
|
|
1565
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Max", value: config.max, onChange: (v) => updateConfig(
|
|
1566
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig(
|
|
1567
|
-
/* @__PURE__ */ jsx(
|
|
1568
|
-
/* @__PURE__ */ jsx(TextField, { label: "
|
|
1569
|
-
/* @__PURE__ */ jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. kg", onChange: (v) => updateConfig("suffix", v) })
|
|
1648
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Min Value", value: config.min, onChange: (v) => updateConfig({ min: v }) }),
|
|
1649
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Max Value", value: config.max, onChange: (v) => updateConfig({ max: v }) }),
|
|
1650
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig({ step: v }) }),
|
|
1651
|
+
/* @__PURE__ */ jsx(TextField, { label: "Prefix", value: config.prefix, placeholder: "e.g. $", onChange: (v) => updateConfig({ prefix: v }) }),
|
|
1652
|
+
/* @__PURE__ */ jsx(TextField, { label: "Suffix", value: config.suffix, placeholder: "e.g. kg", onChange: (v) => updateConfig({ suffix: v }) })
|
|
1570
1653
|
] });
|
|
1571
1654
|
case "slider":
|
|
1572
1655
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Slider Settings", children: [
|
|
1573
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Min", value: config.min, placeholder: "0", onChange: (v) => updateConfig(
|
|
1574
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Max", value: config.max, placeholder: "100", onChange: (v) => updateConfig(
|
|
1575
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig(
|
|
1576
|
-
/* @__PURE__ */ jsx(
|
|
1577
|
-
/* @__PURE__ */ jsx(TextField, { label: "
|
|
1578
|
-
/* @__PURE__ */ jsx(
|
|
1656
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Min Value", value: config.min, placeholder: "0", onChange: (v) => updateConfig({ min: v ?? 0 }) }),
|
|
1657
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Max Value", value: config.max, placeholder: "100", onChange: (v) => updateConfig({ max: v ?? 100 }) }),
|
|
1658
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig({ step: v ?? 1 }) }),
|
|
1659
|
+
/* @__PURE__ */ jsx(TextField, { label: "Min Label", value: config.minLabel, placeholder: "Low", onChange: (v) => updateConfig({ minLabel: v }) }),
|
|
1660
|
+
/* @__PURE__ */ jsx(TextField, { label: "Max Label", value: config.maxLabel, placeholder: "High", onChange: (v) => updateConfig({ maxLabel: v }) }),
|
|
1661
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Show Value", checked: config.showValue !== false, onChange: (v) => updateConfig({ showValue: v }) }),
|
|
1662
|
+
/* @__PURE__ */ jsx(TextField, { label: "Unit", value: config.unit, placeholder: "e.g. %", onChange: (v) => updateConfig({ unit: v }) })
|
|
1579
1663
|
] });
|
|
1580
1664
|
case "rating":
|
|
1581
1665
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Rating Settings", children: [
|
|
1582
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Max
|
|
1583
|
-
/* @__PURE__ */ jsx(SelectField, { label: "Icon", value: config.icon ?? "star", options: [{ label: "Star", value: "star" }, { label: "Heart", value: "heart" }, { label: "
|
|
1584
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "
|
|
1666
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Max Rating", value: config.maxRating, placeholder: "5", onChange: (v) => updateConfig({ maxRating: v ?? 5 }) }),
|
|
1667
|
+
/* @__PURE__ */ jsx(SelectField, { label: "Icon", value: config.icon ?? "star", options: [{ label: "Star", value: "star" }, { label: "Heart", value: "heart" }, { label: "Thumb", value: "thumb" }], onChange: (v) => updateConfig({ icon: v }) }),
|
|
1668
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Allow Half Ratings", checked: !!config.allowHalf, onChange: (v) => updateConfig({ allowHalf: v }) })
|
|
1585
1669
|
] });
|
|
1586
1670
|
case "nps":
|
|
1587
1671
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "NPS Settings", children: [
|
|
1588
|
-
/* @__PURE__ */ jsx(TextField, { label: "
|
|
1589
|
-
/* @__PURE__ */ jsx(TextField, { label: "
|
|
1672
|
+
/* @__PURE__ */ jsx(TextField, { label: "Left Label", value: config.leftLabel ?? "Not likely", onChange: (v) => updateConfig({ leftLabel: v }) }),
|
|
1673
|
+
/* @__PURE__ */ jsx(TextField, { label: "Right Label", value: config.rightLabel ?? "Extremely likely", onChange: (v) => updateConfig({ rightLabel: v }) })
|
|
1590
1674
|
] });
|
|
1591
1675
|
case "opinion_scale":
|
|
1592
1676
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Scale Settings", children: [
|
|
1593
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Min", value: config.min, placeholder: "1", onChange: (v) => updateConfig(
|
|
1594
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Max", value: config.max, placeholder: "5", onChange: (v) => updateConfig(
|
|
1595
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig(
|
|
1596
|
-
/* @__PURE__ */ jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig(
|
|
1597
|
-
/* @__PURE__ */ jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig(
|
|
1677
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Min", value: config.min, placeholder: "1", onChange: (v) => updateConfig({ min: v }) }),
|
|
1678
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Max", value: config.max, placeholder: "5", onChange: (v) => updateConfig({ max: v }) }),
|
|
1679
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Step", value: config.step, placeholder: "1", onChange: (v) => updateConfig({ step: v }) }),
|
|
1680
|
+
/* @__PURE__ */ jsx(TextField, { label: "Min Label", value: config.minLabel, onChange: (v) => updateConfig({ minLabel: v }) }),
|
|
1681
|
+
/* @__PURE__ */ jsx(TextField, { label: "Max Label", value: config.maxLabel, onChange: (v) => updateConfig({ maxLabel: v }) })
|
|
1598
1682
|
] });
|
|
1599
1683
|
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(
|
|
1684
|
+
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
1685
|
// ── Selection ──
|
|
1602
1686
|
case "single_select":
|
|
1603
1687
|
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(
|
|
1605
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig(
|
|
1606
|
-
!!config.allowOther && /* @__PURE__ */ jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig(
|
|
1688
|
+
/* @__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 }) }),
|
|
1689
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => v ? updateConfig({ allowOther: true }) : updateConfig({ allowOther: false, otherLabel: void 0 }) }),
|
|
1690
|
+
!!config.allowOther && /* @__PURE__ */ jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig({ otherLabel: v }) })
|
|
1607
1691
|
] });
|
|
1608
1692
|
case "multi_select":
|
|
1609
1693
|
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(
|
|
1611
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Min Selections", value: config.minSelections, onChange: (v) => updateConfig(
|
|
1612
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Max Selections", value: config.maxSelections, onChange: (v) => updateConfig(
|
|
1613
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig(
|
|
1614
|
-
!!config.allowOther && /* @__PURE__ */ jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig(
|
|
1694
|
+
/* @__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 }) }),
|
|
1695
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Min Selections", value: config.minSelections, onChange: (v) => updateConfig({ minSelections: v }) }),
|
|
1696
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Max Selections", value: config.maxSelections, onChange: (v) => updateConfig({ maxSelections: v }) }),
|
|
1697
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => v ? updateConfig({ allowOther: true }) : updateConfig({ allowOther: false, otherLabel: void 0 }) }),
|
|
1698
|
+
!!config.allowOther && /* @__PURE__ */ jsx(TextField, { label: "Other Label", value: config.otherLabel ?? "Other", onChange: (v) => updateConfig({ otherLabel: v }) })
|
|
1615
1699
|
] });
|
|
1616
1700
|
case "dropdown":
|
|
1617
1701
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Dropdown Settings", children: [
|
|
1618
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Searchable", checked: !!config.searchable, onChange: (v) => updateConfig(
|
|
1619
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig(
|
|
1620
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Multiple", checked: !!config.multiple, onChange: (v) => updateConfig(
|
|
1702
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Searchable", checked: !!config.searchable, onChange: (v) => updateConfig({ searchable: v }) }),
|
|
1703
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Allow Other", checked: !!config.allowOther, onChange: (v) => updateConfig({ allowOther: v }) }),
|
|
1704
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Multiple", checked: !!config.multiple, onChange: (v) => updateConfig({ multiple: v }) })
|
|
1621
1705
|
] });
|
|
1622
1706
|
case "boolean":
|
|
1623
1707
|
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(
|
|
1625
|
-
/* @__PURE__ */ jsx(TextField, { label: "True Label", value: config.trueLabel ?? "Yes", onChange: (v) => updateConfig(
|
|
1626
|
-
/* @__PURE__ */ jsx(TextField, { label: "False Label", value: config.falseLabel ?? "No", onChange: (v) => updateConfig(
|
|
1708
|
+
/* @__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 }) }),
|
|
1709
|
+
/* @__PURE__ */ jsx(TextField, { label: "True Label", value: config.trueLabel ?? "Yes", onChange: (v) => updateConfig({ trueLabel: v }) }),
|
|
1710
|
+
/* @__PURE__ */ jsx(TextField, { label: "False Label", value: config.falseLabel ?? "No", onChange: (v) => updateConfig({ falseLabel: v }) })
|
|
1627
1711
|
] });
|
|
1628
1712
|
case "country_select":
|
|
1629
1713
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Country Settings", children: [
|
|
1630
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Show Flags", checked: config.showFlags !== false, onChange: (v) => updateConfig(
|
|
1631
|
-
/* @__PURE__ */ jsx(TextField, { label: "Priority Countries", value: config.priorityCountries?.join(", "), placeholder: "e.g. US, GB, CA", onChange: (v) => updateConfig(
|
|
1632
|
-
/* @__PURE__ */ jsx(TextField, { label: "Exclude Countries", value: config.excludeCountries?.join(", "), placeholder: "e.g. XX, YY", onChange: (v) => updateConfig(
|
|
1714
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Show Flags", checked: config.showFlags !== false, onChange: (v) => updateConfig({ showFlags: v }) }),
|
|
1715
|
+
/* @__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 }) }),
|
|
1716
|
+
/* @__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
1717
|
] });
|
|
1634
1718
|
// ── Date/Time ──
|
|
1635
1719
|
case "date":
|
|
1636
1720
|
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(
|
|
1638
|
-
/* @__PURE__ */ jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig(
|
|
1639
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Disable Past Dates", checked: !!config.disablePast, onChange: (v) => updateConfig(
|
|
1640
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Disable Future Dates", checked: !!config.disableFuture, onChange: (v) => updateConfig(
|
|
1641
|
-
/* @__PURE__ */ jsx(TextField, { label: "Format", value: config.format, placeholder: "e.g. MM/DD/YYYY", onChange: (v) => updateConfig(
|
|
1721
|
+
/* @__PURE__ */ jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ minDate: v }) }),
|
|
1722
|
+
/* @__PURE__ */ jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ maxDate: v }) }),
|
|
1723
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Disable Past Dates", checked: !!config.disablePast, onChange: (v) => updateConfig({ disablePast: v }) }),
|
|
1724
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Disable Future Dates", checked: !!config.disableFuture, onChange: (v) => updateConfig({ disableFuture: v }) }),
|
|
1725
|
+
/* @__PURE__ */ jsx(TextField, { label: "Format", value: config.format, placeholder: "e.g. MM/DD/YYYY", onChange: (v) => updateConfig({ format: v }) })
|
|
1642
1726
|
] });
|
|
1643
1727
|
case "time":
|
|
1644
1728
|
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(
|
|
1646
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Minute Step", value: config.minuteStep, placeholder: "1", onChange: (v) => updateConfig(
|
|
1729
|
+
/* @__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 }) }),
|
|
1730
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Minute Step", value: config.minuteStep, placeholder: "1", onChange: (v) => updateConfig({ minuteStep: v }) })
|
|
1647
1731
|
] });
|
|
1648
1732
|
case "date_range":
|
|
1649
1733
|
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(
|
|
1651
|
-
/* @__PURE__ */ jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig(
|
|
1652
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Max Range (days)", value: config.maxRangeDays, onChange: (v) => updateConfig(
|
|
1734
|
+
/* @__PURE__ */ jsx(TextField, { label: "Min Date", value: config.minDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ minDate: v }) }),
|
|
1735
|
+
/* @__PURE__ */ jsx(TextField, { label: "Max Date", value: config.maxDate, placeholder: "YYYY-MM-DD", onChange: (v) => updateConfig({ maxDate: v }) }),
|
|
1736
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Max Range (days)", value: config.maxRangeDays, onChange: (v) => updateConfig({ maxRangeDays: v }) })
|
|
1653
1737
|
] });
|
|
1654
|
-
case "appointment":
|
|
1738
|
+
case "appointment": {
|
|
1739
|
+
const appointmentMode = typeof config.slotsUrl === "string" ? "url" : typeof config.embedUrl === "string" ? "embed" : "static";
|
|
1740
|
+
const timezoneFieldOptions = [
|
|
1741
|
+
{ label: "None (Static Timezone)", value: "" },
|
|
1742
|
+
...candidateTimezoneFields,
|
|
1743
|
+
{ label: "Custom Field ID...", value: "__custom__" }
|
|
1744
|
+
];
|
|
1745
|
+
const isCustomTzField = Boolean(config.timezoneField) && !candidateTimezoneFields.some((opt) => opt.value === config.timezoneField);
|
|
1655
1746
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Appointment Settings", children: [
|
|
1656
|
-
/* @__PURE__ */ jsx(
|
|
1657
|
-
|
|
1658
|
-
|
|
1747
|
+
/* @__PURE__ */ jsx(
|
|
1748
|
+
SelectField,
|
|
1749
|
+
{
|
|
1750
|
+
label: "Scheduling Mode",
|
|
1751
|
+
value: appointmentMode,
|
|
1752
|
+
options: [
|
|
1753
|
+
{ label: "Manual Static Slots", value: "static" },
|
|
1754
|
+
{ label: "Fetch from URL", value: "url" },
|
|
1755
|
+
{ label: "Third-Party Embed (Calendly / Cal.com)", value: "embed" }
|
|
1756
|
+
],
|
|
1757
|
+
onChange: (v) => {
|
|
1758
|
+
if (v === "url") {
|
|
1759
|
+
updateConfig({
|
|
1760
|
+
slotsUrl: "",
|
|
1761
|
+
embedUrl: void 0,
|
|
1762
|
+
embedProvider: void 0,
|
|
1763
|
+
slots: void 0
|
|
1764
|
+
});
|
|
1765
|
+
} else if (v === "embed") {
|
|
1766
|
+
updateConfig({
|
|
1767
|
+
embedUrl: "",
|
|
1768
|
+
embedProvider: config.embedProvider || "cal_com",
|
|
1769
|
+
slotsUrl: void 0,
|
|
1770
|
+
slots: void 0
|
|
1771
|
+
});
|
|
1772
|
+
} else {
|
|
1773
|
+
updateConfig({
|
|
1774
|
+
slots: config.slots ?? [],
|
|
1775
|
+
slotsUrl: void 0,
|
|
1776
|
+
embedUrl: void 0,
|
|
1777
|
+
embedProvider: void 0
|
|
1778
|
+
});
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
}
|
|
1782
|
+
),
|
|
1783
|
+
appointmentMode === "url" && /* @__PURE__ */ jsx(
|
|
1784
|
+
TextField,
|
|
1785
|
+
{
|
|
1786
|
+
label: "Slots URL",
|
|
1787
|
+
value: config.slotsUrl,
|
|
1788
|
+
placeholder: "https://example.com/slots",
|
|
1789
|
+
onChange: (v) => updateConfig({ slotsUrl: v ?? "" })
|
|
1790
|
+
}
|
|
1791
|
+
),
|
|
1792
|
+
appointmentMode === "embed" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1793
|
+
/* @__PURE__ */ jsx(
|
|
1794
|
+
TextField,
|
|
1795
|
+
{
|
|
1796
|
+
label: "Embed URL",
|
|
1797
|
+
value: config.embedUrl,
|
|
1798
|
+
placeholder: "https://calendly.com/... or https://cal.com/...",
|
|
1799
|
+
onChange: (v) => updateConfig({ embedUrl: v ?? "" })
|
|
1800
|
+
}
|
|
1801
|
+
),
|
|
1802
|
+
/* @__PURE__ */ jsx(
|
|
1803
|
+
SelectField,
|
|
1804
|
+
{
|
|
1805
|
+
label: "Embed Provider",
|
|
1806
|
+
value: config.embedProvider ?? "cal_com",
|
|
1807
|
+
options: [
|
|
1808
|
+
{ label: "Cal.com", value: "cal_com" },
|
|
1809
|
+
{ label: "Calendly", value: "calendly" },
|
|
1810
|
+
{ label: "Custom", value: "custom" }
|
|
1811
|
+
],
|
|
1812
|
+
onChange: (v) => updateConfig({ embedProvider: v })
|
|
1813
|
+
}
|
|
1814
|
+
)
|
|
1815
|
+
] }),
|
|
1816
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Duration (min)", value: config.duration ?? 30, onChange: (v) => updateConfig({ duration: v }) }),
|
|
1817
|
+
/* @__PURE__ */ jsx(TextField, { label: "Timezone", value: config.timezone, placeholder: "e.g. America/New_York", onChange: (v) => updateConfig({ timezone: v }) }),
|
|
1818
|
+
candidateTimezoneFields.length > 0 ? /* @__PURE__ */ jsxs("div", { children: [
|
|
1819
|
+
/* @__PURE__ */ jsx(
|
|
1820
|
+
SelectField,
|
|
1821
|
+
{
|
|
1822
|
+
label: "Dynamic Timezone Field",
|
|
1823
|
+
value: isCustomTzField ? "__custom__" : config.timezoneField ?? "",
|
|
1824
|
+
options: timezoneFieldOptions,
|
|
1825
|
+
onChange: (v) => {
|
|
1826
|
+
if (v !== "__custom__") {
|
|
1827
|
+
updateConfig({ timezoneField: v || void 0 });
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
),
|
|
1832
|
+
isCustomTzField && /* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsx(
|
|
1833
|
+
TextField,
|
|
1834
|
+
{
|
|
1835
|
+
label: "Custom Timezone Field ID",
|
|
1836
|
+
value: config.timezoneField,
|
|
1837
|
+
placeholder: "e.g. timezone",
|
|
1838
|
+
onChange: (v) => updateConfig({ timezoneField: v || void 0 })
|
|
1839
|
+
}
|
|
1840
|
+
) })
|
|
1841
|
+
] }) : /* @__PURE__ */ jsx(
|
|
1842
|
+
TextField,
|
|
1843
|
+
{
|
|
1844
|
+
label: "Timezone Field",
|
|
1845
|
+
value: config.timezoneField,
|
|
1846
|
+
placeholder: "Field ID for dynamic timezone",
|
|
1847
|
+
onChange: (v) => updateConfig({ timezoneField: v || void 0 })
|
|
1848
|
+
}
|
|
1849
|
+
),
|
|
1850
|
+
/* @__PURE__ */ jsx(TextField, { label: "Date Format", value: config.dateFormat, placeholder: "Locale-aware (default)", onChange: (v) => updateConfig({ dateFormat: v }) }),
|
|
1851
|
+
/* @__PURE__ */ jsx(
|
|
1852
|
+
ToggleField,
|
|
1853
|
+
{
|
|
1854
|
+
label: "Auto-Advance on Booking Complete",
|
|
1855
|
+
checked: config.autoAdvance !== false,
|
|
1856
|
+
onChange: (v) => updateConfig({ autoAdvance: v })
|
|
1857
|
+
}
|
|
1858
|
+
),
|
|
1859
|
+
appointmentMode === "static" && /* @__PURE__ */ jsx(
|
|
1860
|
+
AppointmentSlotsEditor,
|
|
1861
|
+
{
|
|
1862
|
+
slots: config.slots ?? [],
|
|
1863
|
+
onChange: (v) => updateConfig({ slots: v })
|
|
1864
|
+
}
|
|
1865
|
+
)
|
|
1659
1866
|
] });
|
|
1867
|
+
}
|
|
1660
1868
|
// ── Media ──
|
|
1661
1869
|
case "file_upload":
|
|
1662
1870
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Upload Settings", children: [
|
|
1663
|
-
/* @__PURE__ */
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1871
|
+
/* @__PURE__ */ jsxs("div", { className: "p-2.5 bg-muted/40 border border-border rounded-md text-xs text-muted-foreground flex items-center gap-1.5", children: [
|
|
1872
|
+
/* @__PURE__ */ jsx("span", { children: "\u{1F4E6}" }),
|
|
1873
|
+
/* @__PURE__ */ jsx("span", { children: "Uploads stream to your cloud bucket using Form / Account Storage settings." })
|
|
1874
|
+
] }),
|
|
1875
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Max Files", value: config.maxFiles ?? 1, onChange: (v) => updateConfig({ maxFiles: v }) }),
|
|
1876
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb ?? 10, onChange: (v) => updateConfig({ maxSizeMb: v }) }),
|
|
1877
|
+
/* @__PURE__ */ jsx(
|
|
1878
|
+
TextField,
|
|
1879
|
+
{
|
|
1880
|
+
label: "Accepted Types (comma-separated)",
|
|
1881
|
+
value: config.accept?.join(", "),
|
|
1882
|
+
placeholder: "e.g. image/*, .pdf, .docx, .zip",
|
|
1883
|
+
onChange: (v) => updateConfig({
|
|
1884
|
+
accept: v ? v.split(",").map((s) => s.trim()).filter(Boolean) : void 0
|
|
1885
|
+
})
|
|
1886
|
+
}
|
|
1887
|
+
),
|
|
1888
|
+
/* @__PURE__ */ jsx(
|
|
1889
|
+
TextField,
|
|
1890
|
+
{
|
|
1891
|
+
label: "Upload URL",
|
|
1892
|
+
value: config.uploadUrl,
|
|
1893
|
+
placeholder: "https://api.example.com/s3/presign",
|
|
1894
|
+
onChange: (v) => updateConfig({ uploadUrl: v || void 0 })
|
|
1895
|
+
}
|
|
1896
|
+
),
|
|
1897
|
+
/* @__PURE__ */ jsx(
|
|
1898
|
+
TextField,
|
|
1899
|
+
{
|
|
1900
|
+
label: "Public Key",
|
|
1901
|
+
value: config.publicKey,
|
|
1902
|
+
placeholder: "pk_test_...",
|
|
1903
|
+
onChange: (v) => updateConfig({ publicKey: v || void 0 })
|
|
1904
|
+
}
|
|
1905
|
+
)
|
|
1667
1906
|
] });
|
|
1668
1907
|
case "signature":
|
|
1669
1908
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Signature Settings", children: [
|
|
1670
|
-
/* @__PURE__ */ jsx(TextField, { label: "Pen Color", value: config.penColor, placeholder: "#000000", onChange: (v) => updateConfig(
|
|
1671
|
-
/* @__PURE__ */ jsx(TextField, { label: "Background", value: config.backgroundColor, placeholder: "#ffffff", onChange: (v) => updateConfig(
|
|
1672
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Width (px)", value: config.width, onChange: (v) => updateConfig(
|
|
1673
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Height (px)", value: config.height, onChange: (v) => updateConfig(
|
|
1909
|
+
/* @__PURE__ */ jsx(TextField, { label: "Pen Color", value: config.penColor, placeholder: "#000000", onChange: (v) => updateConfig({ penColor: v }) }),
|
|
1910
|
+
/* @__PURE__ */ jsx(TextField, { label: "Background", value: config.backgroundColor, placeholder: "#ffffff", onChange: (v) => updateConfig({ backgroundColor: v }) }),
|
|
1911
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Width (px)", value: config.width, onChange: (v) => updateConfig({ width: v }) }),
|
|
1912
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Height (px)", value: config.height, onChange: (v) => updateConfig({ height: v }) })
|
|
1674
1913
|
] });
|
|
1675
1914
|
case "image_capture":
|
|
1676
1915
|
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(
|
|
1678
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb, onChange: (v) => updateConfig(
|
|
1679
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Allow Gallery", checked: config.allowGallery !== false, onChange: (v) => updateConfig(
|
|
1916
|
+
/* @__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 }) }),
|
|
1917
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Max Size (MB)", value: config.maxSizeMb, onChange: (v) => updateConfig({ maxSizeMb: v }) }),
|
|
1918
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Allow Gallery", checked: config.allowGallery !== false, onChange: (v) => updateConfig({ allowGallery: v }) })
|
|
1680
1919
|
] });
|
|
1681
1920
|
// ── Content & Visual ──
|
|
1682
1921
|
case "welcome-screen":
|
|
1683
1922
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Welcome Screen", children: [
|
|
1684
|
-
/* @__PURE__ */ jsx(TextField, { label: "Heading", value: config.heading ?? "Welcome", onChange: (v) => updateConfig(
|
|
1685
|
-
/* @__PURE__ */ jsx(TextareaField, { label: "Description", value: config.description, onChange: (v) => updateConfig(
|
|
1686
|
-
/* @__PURE__ */ jsx(TextField, { label: "Button Text", value: config.buttonText ?? "Start", onChange: (v) => updateConfig(
|
|
1687
|
-
/* @__PURE__ */ jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig(
|
|
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(
|
|
1923
|
+
/* @__PURE__ */ jsx(TextField, { label: "Heading", value: config.heading ?? "Welcome", onChange: (v) => updateConfig({ heading: v }) }),
|
|
1924
|
+
/* @__PURE__ */ jsx(TextareaField, { label: "Description", value: config.description, onChange: (v) => updateConfig({ description: v }) }),
|
|
1925
|
+
/* @__PURE__ */ jsx(TextField, { label: "Button Text", value: config.buttonText ?? "Start", onChange: (v) => updateConfig({ buttonText: v }) }),
|
|
1926
|
+
/* @__PURE__ */ jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig({ imageUrl: v }) }),
|
|
1927
|
+
/* @__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
1928
|
] });
|
|
1690
1929
|
case "thank-you-screen":
|
|
1691
1930
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Thank You Screen", children: [
|
|
1692
|
-
/* @__PURE__ */ jsx(TextField, { label: "Heading", value: config.heading ?? "Thank You!", onChange: (v) => updateConfig(
|
|
1693
|
-
/* @__PURE__ */ jsx(TextareaField, { label: "Description", value: config.description ?? "", onChange: (v) => updateConfig(
|
|
1694
|
-
/* @__PURE__ */ jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig(
|
|
1695
|
-
/* @__PURE__ */ jsx(TextField, { label: "Redirect URL", value: config.redirectUrl, placeholder: "https://...", onChange: (v) => updateConfig(
|
|
1696
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Redirect Delay (s)", value: config.redirectDelay, placeholder: "0", onChange: (v) => updateConfig(
|
|
1697
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Show Response Summary", checked: !!config.showSummary, onChange: (v) => updateConfig(
|
|
1931
|
+
/* @__PURE__ */ jsx(TextField, { label: "Heading", value: config.heading ?? "Thank You!", onChange: (v) => updateConfig({ heading: v }) }),
|
|
1932
|
+
/* @__PURE__ */ jsx(TextareaField, { label: "Description", value: config.description ?? "", onChange: (v) => updateConfig({ description: v }) }),
|
|
1933
|
+
/* @__PURE__ */ jsx(TextField, { label: "Image URL", value: config.imageUrl, placeholder: "https://...", onChange: (v) => updateConfig({ imageUrl: v }) }),
|
|
1934
|
+
/* @__PURE__ */ jsx(TextField, { label: "Redirect URL", value: config.redirectUrl, placeholder: "https://...", onChange: (v) => updateConfig({ redirectUrl: v }) }),
|
|
1935
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Redirect Delay (s)", value: config.redirectDelay, placeholder: "0", onChange: (v) => updateConfig({ redirectDelay: v }) }),
|
|
1936
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Show Response Summary", checked: !!config.showSummary, onChange: (v) => updateConfig({ showSummary: v }) })
|
|
1698
1937
|
] });
|
|
1699
1938
|
case "rich-text":
|
|
1700
1939
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Rich Text", children: [
|
|
1701
|
-
/* @__PURE__ */ jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 6, onChange: (v) => updateConfig(
|
|
1702
|
-
/* @__PURE__ */ jsx(SelectField, { label: "Format", value: config.format ?? "html", options: [{ label: "HTML", value: "html" }, { label: "Markdown", value: "markdown" }], onChange: (v) => updateConfig(
|
|
1940
|
+
/* @__PURE__ */ jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 6, onChange: (v) => updateConfig({ content: v }) }),
|
|
1941
|
+
/* @__PURE__ */ jsx(SelectField, { label: "Format", value: config.format ?? "html", options: [{ label: "HTML", value: "html" }, { label: "Markdown", value: "markdown" }], onChange: (v) => updateConfig({ format: v }) })
|
|
1703
1942
|
] });
|
|
1704
1943
|
case "image":
|
|
1705
1944
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Image Settings", children: [
|
|
1706
|
-
/* @__PURE__ */ jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "https://...", onChange: (v) => updateConfig(
|
|
1707
|
-
/* @__PURE__ */ jsx(TextField, { label: "Alt Text", value: config.alt ?? "", onChange: (v) => updateConfig(
|
|
1708
|
-
/* @__PURE__ */ jsx(TextField, { label: "Caption", value: config.caption, onChange: (v) => updateConfig(
|
|
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(
|
|
1710
|
-
/* @__PURE__ */ jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 300px", onChange: (v) => updateConfig(
|
|
1711
|
-
/* @__PURE__ */ jsx(TextField, { label: "Link URL", value: config.link, placeholder: "Click opens this URL", onChange: (v) => updateConfig(
|
|
1945
|
+
/* @__PURE__ */ jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "https://...", onChange: (v) => updateConfig({ src: v }) }),
|
|
1946
|
+
/* @__PURE__ */ jsx(TextField, { label: "Alt Text", value: config.alt ?? "", onChange: (v) => updateConfig({ alt: v }) }),
|
|
1947
|
+
/* @__PURE__ */ jsx(TextField, { label: "Caption", value: config.caption, onChange: (v) => updateConfig({ caption: v }) }),
|
|
1948
|
+
/* @__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 }) }),
|
|
1949
|
+
/* @__PURE__ */ jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 300px", onChange: (v) => updateConfig({ width: v }) }),
|
|
1950
|
+
/* @__PURE__ */ jsx(TextField, { label: "Link URL", value: config.link, placeholder: "Click opens this URL", onChange: (v) => updateConfig({ link: v }) })
|
|
1712
1951
|
] });
|
|
1713
1952
|
case "video":
|
|
1714
1953
|
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(
|
|
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(
|
|
1717
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Autoplay", checked: !!config.autoplay, onChange: (v) => updateConfig(
|
|
1718
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Muted", checked: !!config.muted, onChange: (v) => updateConfig(
|
|
1719
|
-
/* @__PURE__ */ jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 640px", onChange: (v) => updateConfig(
|
|
1720
|
-
/* @__PURE__ */ jsx(TextField, { label: "Height", value: config.height, placeholder: "e.g. 360px", onChange: (v) => updateConfig(
|
|
1954
|
+
/* @__PURE__ */ jsx(TextField, { label: "Source URL", value: config.src ?? "", placeholder: "YouTube/Vimeo URL", onChange: (v) => updateConfig({ src: v }) }),
|
|
1955
|
+
/* @__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 }) }),
|
|
1956
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Autoplay", checked: !!config.autoplay, onChange: (v) => updateConfig({ autoplay: v }) }),
|
|
1957
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Muted", checked: !!config.muted, onChange: (v) => updateConfig({ muted: v }) }),
|
|
1958
|
+
/* @__PURE__ */ jsx(TextField, { label: "Width", value: config.width, placeholder: "e.g. 100% or 640px", onChange: (v) => updateConfig({ width: v }) }),
|
|
1959
|
+
/* @__PURE__ */ jsx(TextField, { label: "Height", value: config.height, placeholder: "e.g. 360px", onChange: (v) => updateConfig({ height: v }) })
|
|
1721
1960
|
] });
|
|
1722
1961
|
case "divider":
|
|
1723
1962
|
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(
|
|
1725
|
-
/* @__PURE__ */ jsx(TextField, { label: "Color", value: config.color, placeholder: "#e5e7eb", onChange: (v) => updateConfig(
|
|
1726
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Thickness (px)", value: config.thickness, placeholder: "1", onChange: (v) => updateConfig(
|
|
1727
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Spacing (px)", value: config.spacing, placeholder: "16", onChange: (v) => updateConfig(
|
|
1963
|
+
/* @__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 }) }),
|
|
1964
|
+
/* @__PURE__ */ jsx(TextField, { label: "Color", value: config.color, placeholder: "#e5e7eb", onChange: (v) => updateConfig({ color: v }) }),
|
|
1965
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Thickness (px)", value: config.thickness, placeholder: "1", onChange: (v) => updateConfig({ thickness: v }) }),
|
|
1966
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Spacing (px)", value: config.spacing, placeholder: "16", onChange: (v) => updateConfig({ spacing: v }) })
|
|
1728
1967
|
] });
|
|
1729
1968
|
case "spacer":
|
|
1730
|
-
return /* @__PURE__ */ jsx(ConfigSection, { title: "Spacer Settings", children: /* @__PURE__ */ jsx(NumberField, { label: "Height (px)", value: config.height ?? 32, onChange: (v) => updateConfig(
|
|
1969
|
+
return /* @__PURE__ */ jsx(ConfigSection, { title: "Spacer Settings", children: /* @__PURE__ */ jsx(NumberField, { label: "Height (px)", value: config.height ?? 32, onChange: (v) => updateConfig({ height: v }) }) });
|
|
1731
1970
|
// ── Structural ──
|
|
1732
1971
|
case "section_header":
|
|
1733
1972
|
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(
|
|
1735
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Show Divider", checked: !!config.showDivider, onChange: (v) => updateConfig(
|
|
1973
|
+
/* @__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 }) }),
|
|
1974
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Show Divider", checked: !!config.showDivider, onChange: (v) => updateConfig({ showDivider: v }) })
|
|
1736
1975
|
] });
|
|
1737
1976
|
case "info_block":
|
|
1738
1977
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Info Block", children: [
|
|
1739
|
-
/* @__PURE__ */ jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 4, onChange: (v) => updateConfig(
|
|
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(
|
|
1978
|
+
/* @__PURE__ */ jsx(TextareaField, { label: "Content", value: config.content ?? "", rows: 4, onChange: (v) => updateConfig({ content: v }) }),
|
|
1979
|
+
/* @__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
1980
|
] });
|
|
1742
1981
|
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(
|
|
1982
|
+
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
1983
|
case "consent":
|
|
1745
1984
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Consent Settings", children: [
|
|
1746
|
-
/* @__PURE__ */ jsx(TextareaField, { label: "Consent Text", value: config.text ?? "", rows: 4, onChange: (v) => updateConfig(
|
|
1747
|
-
/* @__PURE__ */ jsx(TextField, { label: "Checkbox Label", value: config.checkboxLabel ?? "I agree", onChange: (v) => updateConfig(
|
|
1748
|
-
/* @__PURE__ */ jsx(TextareaField, { label: "Expandable Text", value: config.expandableText, rows: 3, placeholder: "Additional text shown on expand", onChange: (v) => updateConfig(
|
|
1985
|
+
/* @__PURE__ */ jsx(TextareaField, { label: "Consent Text", value: config.text ?? "", rows: 4, onChange: (v) => updateConfig({ text: v }) }),
|
|
1986
|
+
/* @__PURE__ */ jsx(TextField, { label: "Checkbox Label", value: config.checkboxLabel ?? "I agree", onChange: (v) => updateConfig({ checkboxLabel: v }) }),
|
|
1987
|
+
/* @__PURE__ */ jsx(TextareaField, { label: "Expandable Text", value: config.expandableText, rows: 3, placeholder: "Additional text shown on expand", onChange: (v) => updateConfig({ expandableText: v }) })
|
|
1749
1988
|
] });
|
|
1750
1989
|
// ── Advanced ──
|
|
1751
1990
|
case "matrix":
|
|
1752
1991
|
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(
|
|
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(
|
|
1755
|
-
/* @__PURE__ */ jsx(MatrixItemsEditor, { label: "Rows", items: config.rows ?? [], onChange: (v) => updateConfig(
|
|
1756
|
-
/* @__PURE__ */ jsx(MatrixItemsEditor, { label: "Columns", items: config.columns ?? [], onChange: (v) => updateConfig(
|
|
1992
|
+
/* @__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 }) }),
|
|
1993
|
+
/* @__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 }) }),
|
|
1994
|
+
/* @__PURE__ */ jsx(MatrixItemsEditor, { label: "Rows", items: config.rows ?? [], onChange: (v) => updateConfig({ rows: v }) }),
|
|
1995
|
+
/* @__PURE__ */ jsx(MatrixItemsEditor, { label: "Columns", items: config.columns ?? [], onChange: (v) => updateConfig({ columns: v }) })
|
|
1757
1996
|
] });
|
|
1758
1997
|
case "repeater":
|
|
1759
1998
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Repeater Settings", children: [
|
|
1760
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Min Entries", value: config.minEntries, placeholder: "1", onChange: (v) => updateConfig(
|
|
1761
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Max Entries", value: config.maxEntries, onChange: (v) => updateConfig(
|
|
1762
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Default Entries", value: config.defaultEntries, placeholder: "1", onChange: (v) => updateConfig(
|
|
1763
|
-
/* @__PURE__ */ jsx(TextField, { label: "Add Button Label", value: config.addLabel, placeholder: "Add Entry", onChange: (v) => updateConfig(
|
|
1764
|
-
/* @__PURE__ */ jsx(TextField, { label: "Remove Button Label", value: config.removeLabel, placeholder: "Remove", onChange: (v) => updateConfig(
|
|
1999
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Min Entries", value: config.minEntries, placeholder: "1", onChange: (v) => updateConfig({ minEntries: v }) }),
|
|
2000
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Max Entries", value: config.maxEntries, onChange: (v) => updateConfig({ maxEntries: v }) }),
|
|
2001
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Default Entries", value: config.defaultEntries, placeholder: "1", onChange: (v) => updateConfig({ defaultEntries: v }) }),
|
|
2002
|
+
/* @__PURE__ */ jsx(TextField, { label: "Add Button Label", value: config.addLabel, placeholder: "Add Entry", onChange: (v) => updateConfig({ addLabel: v }) }),
|
|
2003
|
+
/* @__PURE__ */ jsx(TextField, { label: "Remove Button Label", value: config.removeLabel, placeholder: "Remove", onChange: (v) => updateConfig({ removeLabel: v }) }),
|
|
1765
2004
|
/* @__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
2005
|
] });
|
|
1767
2006
|
case "address": {
|
|
@@ -1775,63 +2014,157 @@ function QuestionConfigEditor({ question, onUpdate }) {
|
|
|
1775
2014
|
];
|
|
1776
2015
|
const activeFields = config.fields ?? ["street", "city", "state", "zip", "country"];
|
|
1777
2016
|
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(
|
|
1779
|
-
config.provider !== "none" && /* @__PURE__ */ jsx(TextField, { label: "API Key", value: config.apiKey, placeholder: "Provider API key", onChange: (v) => updateConfig(
|
|
1780
|
-
/* @__PURE__ */ jsx(TextField, { label: "Default Country", value: config.defaultCountry, placeholder: "e.g. US", onChange: (v) => updateConfig(
|
|
2017
|
+
/* @__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 }) }),
|
|
2018
|
+
config.provider !== "none" && /* @__PURE__ */ jsx(TextField, { label: "API Key", value: config.apiKey, placeholder: "Provider API key", onChange: (v) => updateConfig({ apiKey: v }) }),
|
|
2019
|
+
/* @__PURE__ */ jsx(TextField, { label: "Default Country", value: config.defaultCountry, placeholder: "e.g. US", onChange: (v) => updateConfig({ defaultCountry: v }) }),
|
|
1781
2020
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
1782
2021
|
/* @__PURE__ */ jsx(Label, { className: "text-xs text-muted-foreground mb-2 block", children: "Fields" }),
|
|
1783
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-1.5", children: ADDRESS_FIELDS.map((f) =>
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
2022
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-1.5", children: ADDRESS_FIELDS.map((f) => {
|
|
2023
|
+
const isChecked = activeFields.includes(f.value);
|
|
2024
|
+
const isLastChecked = isChecked && activeFields.length === 1;
|
|
2025
|
+
return /* @__PURE__ */ jsx(
|
|
2026
|
+
ToggleField,
|
|
2027
|
+
{
|
|
2028
|
+
label: f.label,
|
|
2029
|
+
checked: isChecked,
|
|
2030
|
+
disabled: isLastChecked,
|
|
2031
|
+
onChange: (checked) => {
|
|
2032
|
+
const next = checked ? [...activeFields, f.value] : activeFields.filter((v) => v !== f.value);
|
|
2033
|
+
updateConfig({ fields: next });
|
|
2034
|
+
}
|
|
2035
|
+
},
|
|
2036
|
+
f.value
|
|
2037
|
+
);
|
|
2038
|
+
}) })
|
|
1795
2039
|
] })
|
|
1796
2040
|
] });
|
|
1797
2041
|
}
|
|
1798
|
-
case "payment":
|
|
2042
|
+
case "payment": {
|
|
2043
|
+
const amountFieldOptions = [
|
|
2044
|
+
{ label: "None (Fixed Amount)", value: "" },
|
|
2045
|
+
...candidateAmountFields,
|
|
2046
|
+
{ label: "Custom Field ID...", value: "__custom__" }
|
|
2047
|
+
];
|
|
2048
|
+
const isCustomAmountField = Boolean(config.amountField) && !candidateAmountFields.some((opt) => opt.value === config.amountField);
|
|
1799
2049
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Payment Settings", children: [
|
|
1800
|
-
/* @__PURE__ */ jsx(
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
2050
|
+
/* @__PURE__ */ jsx(
|
|
2051
|
+
SelectField,
|
|
2052
|
+
{
|
|
2053
|
+
label: "Provider",
|
|
2054
|
+
value: config.provider ?? "stripe",
|
|
2055
|
+
options: [
|
|
2056
|
+
{ label: "Stripe", value: "stripe" },
|
|
2057
|
+
{ label: "PayPal", value: "paypal" },
|
|
2058
|
+
{ label: "Razorpay", value: "razorpay" }
|
|
2059
|
+
],
|
|
2060
|
+
onChange: (v) => updateConfig({ provider: v })
|
|
2061
|
+
}
|
|
2062
|
+
),
|
|
2063
|
+
/* @__PURE__ */ jsx(
|
|
2064
|
+
TextField,
|
|
2065
|
+
{
|
|
2066
|
+
label: "Public Key",
|
|
2067
|
+
value: config.publicKey,
|
|
2068
|
+
placeholder: "pk_test_...",
|
|
2069
|
+
onChange: (v) => updateConfig({ publicKey: v || void 0 })
|
|
2070
|
+
}
|
|
2071
|
+
),
|
|
2072
|
+
/* @__PURE__ */ jsx(
|
|
2073
|
+
TextField,
|
|
2074
|
+
{
|
|
2075
|
+
label: "Server URL",
|
|
2076
|
+
value: config.serverUrl,
|
|
2077
|
+
placeholder: "https://api.example.com/create-intent",
|
|
2078
|
+
onChange: (v) => updateConfig({ serverUrl: v || void 0 })
|
|
2079
|
+
}
|
|
2080
|
+
),
|
|
2081
|
+
candidateAmountFields.length > 0 ? /* @__PURE__ */ jsxs("div", { children: [
|
|
2082
|
+
/* @__PURE__ */ jsx(
|
|
2083
|
+
SelectField,
|
|
2084
|
+
{
|
|
2085
|
+
label: "Dynamic Amount Field",
|
|
2086
|
+
value: isCustomAmountField ? "__custom__" : config.amountField ?? "",
|
|
2087
|
+
options: amountFieldOptions,
|
|
2088
|
+
onChange: (v) => {
|
|
2089
|
+
if (v !== "__custom__") {
|
|
2090
|
+
updateConfig({ amountField: v || void 0 });
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
),
|
|
2095
|
+
isCustomAmountField && /* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsx(
|
|
2096
|
+
TextField,
|
|
2097
|
+
{
|
|
2098
|
+
label: "Custom Field ID",
|
|
2099
|
+
value: config.amountField,
|
|
2100
|
+
placeholder: "Field ID for dynamic amount",
|
|
2101
|
+
onChange: (v) => updateConfig({ amountField: v || void 0 })
|
|
2102
|
+
}
|
|
2103
|
+
) })
|
|
2104
|
+
] }) : /* @__PURE__ */ jsx(
|
|
2105
|
+
TextField,
|
|
2106
|
+
{
|
|
2107
|
+
label: "Amount Field",
|
|
2108
|
+
value: config.amountField,
|
|
2109
|
+
placeholder: "Field ID for dynamic amount (e.g. total_cost)",
|
|
2110
|
+
onChange: (v) => updateConfig({ amountField: v || void 0 })
|
|
2111
|
+
}
|
|
2112
|
+
),
|
|
2113
|
+
!config.amountField && /* @__PURE__ */ jsx(
|
|
2114
|
+
NumberField,
|
|
2115
|
+
{
|
|
2116
|
+
label: "Fixed Amount",
|
|
2117
|
+
value: config.amount,
|
|
2118
|
+
onChange: (v) => updateConfig({ amount: v })
|
|
2119
|
+
}
|
|
2120
|
+
),
|
|
2121
|
+
/* @__PURE__ */ jsx(TextField, { label: "Currency", value: config.currency ?? "USD", placeholder: "USD", onChange: (v) => updateConfig({ currency: v || "USD" }) }),
|
|
2122
|
+
/* @__PURE__ */ jsx(TextField, { label: "Description", value: config.description, onChange: (v) => updateConfig({ description: v }) }),
|
|
2123
|
+
/* @__PURE__ */ jsx(
|
|
2124
|
+
TextField,
|
|
2125
|
+
{
|
|
2126
|
+
label: "Client Secret Response Path",
|
|
2127
|
+
value: typeof config.responseMapping?.clientSecretPath === "string" ? config.responseMapping.clientSecretPath : config.responseMapping ?? "",
|
|
2128
|
+
placeholder: "clientSecret",
|
|
2129
|
+
onChange: (v) => updateConfig({
|
|
2130
|
+
responseMapping: v ? { clientSecretPath: v } : void 0
|
|
2131
|
+
})
|
|
2132
|
+
}
|
|
2133
|
+
)
|
|
1806
2134
|
] });
|
|
2135
|
+
}
|
|
1807
2136
|
case "calculated":
|
|
1808
2137
|
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(
|
|
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(
|
|
1811
|
-
/* @__PURE__ */ jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "2", onChange: (v) => updateConfig(
|
|
1812
|
-
/* @__PURE__ */ jsx(TextField, { label: "Prefix", value: config.prefix, onChange: (v) => updateConfig(
|
|
1813
|
-
/* @__PURE__ */ jsx(TextField, { label: "Suffix", value: config.suffix, onChange: (v) => updateConfig(
|
|
1814
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Visible to User", checked: config.visible !== false, onChange: (v) => updateConfig(
|
|
2138
|
+
/* @__PURE__ */ jsx(TextField, { label: "Expression", value: config.expression ?? "", placeholder: "e.g. {q1} + {q2}", onChange: (v) => updateConfig({ expression: v }) }),
|
|
2139
|
+
/* @__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 }) }),
|
|
2140
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Decimal Places", value: config.decimalPlaces, placeholder: "2", onChange: (v) => updateConfig({ decimalPlaces: v }) }),
|
|
2141
|
+
/* @__PURE__ */ jsx(TextField, { label: "Prefix", value: config.prefix, onChange: (v) => updateConfig({ prefix: v }) }),
|
|
2142
|
+
/* @__PURE__ */ jsx(TextField, { label: "Suffix", value: config.suffix, onChange: (v) => updateConfig({ suffix: v }) }),
|
|
2143
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Visible to User", checked: config.visible !== false, onChange: (v) => updateConfig({ visible: v }) })
|
|
1815
2144
|
] });
|
|
1816
2145
|
case "hidden":
|
|
1817
2146
|
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(
|
|
1819
|
-
config.source === "static" && /* @__PURE__ */ jsx(TextField, { label: "Default Value", value: config.defaultValue, onChange: (v) => updateConfig(
|
|
1820
|
-
config.source === "url_param" && /* @__PURE__ */ jsx(TextField, { label: "Parameter Name", value: config.paramName, placeholder: "e.g. utm_source", onChange: (v) => updateConfig(
|
|
1821
|
-
config.source === "cookie" && /* @__PURE__ */ jsx(TextField, { label: "Cookie Name", value: config.cookieName, onChange: (v) => updateConfig(
|
|
2147
|
+
/* @__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 }) }),
|
|
2148
|
+
config.source === "static" && /* @__PURE__ */ jsx(TextField, { label: "Default Value", value: config.defaultValue, onChange: (v) => updateConfig({ defaultValue: v }) }),
|
|
2149
|
+
config.source === "url_param" && /* @__PURE__ */ jsx(TextField, { label: "Parameter Name", value: config.paramName, placeholder: "e.g. utm_source", onChange: (v) => updateConfig({ paramName: v }) }),
|
|
2150
|
+
config.source === "cookie" && /* @__PURE__ */ jsx(TextField, { label: "Cookie Name", value: config.cookieName, onChange: (v) => updateConfig({ cookieName: v }) })
|
|
1822
2151
|
] });
|
|
1823
2152
|
case "scoring":
|
|
1824
2153
|
return /* @__PURE__ */ jsxs(ConfigSection, { title: "Scoring Settings", children: [
|
|
1825
|
-
/* @__PURE__ */ jsx(ToggleField, { label: "Show Score", checked: !!config.showScore, onChange: (v) => updateConfig(
|
|
1826
|
-
/* @__PURE__ */ jsx(ScoringOptionsEditor, { options: config.options ?? [], onChange: (v) => updateConfig(
|
|
1827
|
-
/* @__PURE__ */ jsx(ScoreRangesEditor, { ranges: config.scoreRanges ?? [], onChange: (v) => updateConfig(
|
|
2154
|
+
/* @__PURE__ */ jsx(ToggleField, { label: "Show Score", checked: !!config.showScore, onChange: (v) => updateConfig({ showScore: v }) }),
|
|
2155
|
+
/* @__PURE__ */ jsx(ScoringOptionsEditor, { options: config.options ?? [], onChange: (v) => updateConfig({ options: v }) }),
|
|
2156
|
+
/* @__PURE__ */ jsx(ScoreRangesEditor, { ranges: config.scoreRanges ?? [], onChange: (v) => updateConfig({ scoreRanges: v }) })
|
|
1828
2157
|
] });
|
|
1829
2158
|
case "ranking":
|
|
1830
|
-
return /* @__PURE__ */ jsx(ConfigSection, { title: "Ranking Settings", children: /* @__PURE__ */ jsx(MatrixItemsEditor, { label: "Items", items: config.items ?? [], onChange: (v) => updateConfig(
|
|
2159
|
+
return /* @__PURE__ */ jsx(ConfigSection, { title: "Ranking Settings", children: /* @__PURE__ */ jsx(MatrixItemsEditor, { label: "Items", items: config.items ?? [], onChange: (v) => updateConfig({ items: v }) }) });
|
|
2160
|
+
case "phone_international":
|
|
2161
|
+
return /* @__PURE__ */ jsxs(ConfigSection, { title: "International Phone Settings", children: [
|
|
2162
|
+
/* @__PURE__ */ jsx(TextField, { label: "Default Country", value: config.defaultCountry ?? "US", placeholder: "e.g. US", onChange: (v) => updateConfig({ defaultCountry: v }) }),
|
|
2163
|
+
/* @__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 }) })
|
|
2164
|
+
] });
|
|
1831
2165
|
// Types with no additional config
|
|
1832
2166
|
case "email":
|
|
1833
2167
|
case "phone":
|
|
1834
|
-
case "phone_international":
|
|
1835
2168
|
case "url":
|
|
1836
2169
|
return null;
|
|
1837
2170
|
default:
|
|
@@ -1908,11 +2241,12 @@ function NumberField({
|
|
|
1908
2241
|
function ToggleField({
|
|
1909
2242
|
label,
|
|
1910
2243
|
checked,
|
|
1911
|
-
onChange
|
|
2244
|
+
onChange,
|
|
2245
|
+
disabled
|
|
1912
2246
|
}) {
|
|
1913
2247
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
1914
2248
|
/* @__PURE__ */ jsx(Label, { className: "text-xs text-muted-foreground", children: label }),
|
|
1915
|
-
/* @__PURE__ */ jsx(Switch, { checked, onCheckedChange: onChange })
|
|
2249
|
+
/* @__PURE__ */ jsx(Switch, { checked, onCheckedChange: onChange, disabled })
|
|
1916
2250
|
] });
|
|
1917
2251
|
}
|
|
1918
2252
|
function SelectField({
|
|
@@ -1923,7 +2257,10 @@ function SelectField({
|
|
|
1923
2257
|
}) {
|
|
1924
2258
|
return /* @__PURE__ */ jsxs("div", { children: [
|
|
1925
2259
|
/* @__PURE__ */ jsx(Label, { className: "text-xs text-muted-foreground mb-1", children: label }),
|
|
1926
|
-
/* @__PURE__ */
|
|
2260
|
+
/* @__PURE__ */ jsxs(Select, { value, onValueChange: onChange, children: [
|
|
2261
|
+
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx("span", { children: options.find((o) => o.value === value)?.label ?? value }) }),
|
|
2262
|
+
/* @__PURE__ */ jsx(SelectContent, { children: options.map((opt) => /* @__PURE__ */ jsx(SelectItem, { value: opt.value, children: opt.label }, opt.value)) })
|
|
2263
|
+
] })
|
|
1927
2264
|
] });
|
|
1928
2265
|
}
|
|
1929
2266
|
function LikertLabelsEditor({
|
|
@@ -2069,6 +2406,59 @@ function ScoringOptionsEditor({
|
|
|
2069
2406
|
] }, index)) })
|
|
2070
2407
|
] });
|
|
2071
2408
|
}
|
|
2409
|
+
function AppointmentSlotsEditor({
|
|
2410
|
+
slots,
|
|
2411
|
+
onChange
|
|
2412
|
+
}) {
|
|
2413
|
+
const handleDateChange = (index, date) => {
|
|
2414
|
+
const updated = slots.map((s, i) => i === index ? { ...s, date } : s);
|
|
2415
|
+
onChange(updated);
|
|
2416
|
+
};
|
|
2417
|
+
const handleTimesChange = (index, timesStr) => {
|
|
2418
|
+
const times = timesStr.split(",").map((t) => t.trim()).filter(Boolean);
|
|
2419
|
+
const updated = slots.map((s, i) => i === index ? { ...s, times } : s);
|
|
2420
|
+
onChange(updated);
|
|
2421
|
+
};
|
|
2422
|
+
const handleAdd = () => {
|
|
2423
|
+
const tomorrow = /* @__PURE__ */ new Date();
|
|
2424
|
+
tomorrow.setDate(tomorrow.getDate() + 1);
|
|
2425
|
+
const dateStr = tomorrow.toISOString().split("T")[0];
|
|
2426
|
+
onChange([...slots, { date: dateStr, times: ["09:00", "10:00", "11:00", "14:00", "15:00"] }]);
|
|
2427
|
+
};
|
|
2428
|
+
const handleRemove = (index) => {
|
|
2429
|
+
onChange(slots.filter((_, i) => i !== index));
|
|
2430
|
+
};
|
|
2431
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
2432
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
2433
|
+
/* @__PURE__ */ jsx(Label, { className: "text-xs text-muted-foreground", children: "Slots" }),
|
|
2434
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "link", size: "xs", onClick: handleAdd, className: "px-0", children: "+ Add Date" })
|
|
2435
|
+
] }),
|
|
2436
|
+
slots.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-[11px] text-muted-foreground", children: "No slots configured. Add a date to get started." }),
|
|
2437
|
+
/* @__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: [
|
|
2438
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
2439
|
+
/* @__PURE__ */ jsx(
|
|
2440
|
+
Input,
|
|
2441
|
+
{
|
|
2442
|
+
type: "date",
|
|
2443
|
+
value: slot.date,
|
|
2444
|
+
onChange: (e) => handleDateChange(index, e.target.value),
|
|
2445
|
+
className: "h-7 text-xs flex-1"
|
|
2446
|
+
}
|
|
2447
|
+
),
|
|
2448
|
+
/* @__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" })
|
|
2449
|
+
] }),
|
|
2450
|
+
/* @__PURE__ */ jsx(
|
|
2451
|
+
Input,
|
|
2452
|
+
{
|
|
2453
|
+
value: slot.times.join(", "),
|
|
2454
|
+
onChange: (e) => handleTimesChange(index, e.target.value),
|
|
2455
|
+
className: "h-7 text-xs",
|
|
2456
|
+
placeholder: "09:00, 10:00, 14:00, 15:00"
|
|
2457
|
+
}
|
|
2458
|
+
)
|
|
2459
|
+
] }, index)) })
|
|
2460
|
+
] });
|
|
2461
|
+
}
|
|
2072
2462
|
function ScoreRangesEditor({
|
|
2073
2463
|
ranges,
|
|
2074
2464
|
onChange
|
|
@@ -2101,6 +2491,26 @@ function ScoreRangesEditor({
|
|
|
2101
2491
|
] }, index)) })
|
|
2102
2492
|
] });
|
|
2103
2493
|
}
|
|
2494
|
+
var NativeSelect = forwardRef(
|
|
2495
|
+
({ className, wrapperClassName, children, ...props }, ref) => {
|
|
2496
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative", wrapperClassName), children: [
|
|
2497
|
+
/* @__PURE__ */ jsx(
|
|
2498
|
+
"select",
|
|
2499
|
+
{
|
|
2500
|
+
ref,
|
|
2501
|
+
className: cn(
|
|
2502
|
+
"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",
|
|
2503
|
+
className
|
|
2504
|
+
),
|
|
2505
|
+
...props,
|
|
2506
|
+
children
|
|
2507
|
+
}
|
|
2508
|
+
),
|
|
2509
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "pointer-events-none absolute right-2.5 top-1/2 -translate-y-1/2 size-4 text-muted-foreground" })
|
|
2510
|
+
] });
|
|
2511
|
+
}
|
|
2512
|
+
);
|
|
2513
|
+
NativeSelect.displayName = "NativeSelect";
|
|
2104
2514
|
var RULE_TYPES = [
|
|
2105
2515
|
{ value: "minLength", label: "Min Length", description: "Minimum character count" },
|
|
2106
2516
|
{ value: "maxLength", label: "Max Length", description: "Maximum character count" },
|
|
@@ -2808,7 +3218,14 @@ function QuestionProperties({ question, sectionId, builderState, onClose, onOpen
|
|
|
2808
3218
|
}
|
|
2809
3219
|
)
|
|
2810
3220
|
] }),
|
|
2811
|
-
/* @__PURE__ */ jsx(
|
|
3221
|
+
/* @__PURE__ */ jsx(
|
|
3222
|
+
QuestionConfigEditor,
|
|
3223
|
+
{
|
|
3224
|
+
question,
|
|
3225
|
+
schema: builderState.schema,
|
|
3226
|
+
onUpdate: updateQuestion2
|
|
3227
|
+
}
|
|
3228
|
+
),
|
|
2812
3229
|
hasOptions && /* @__PURE__ */ jsx(
|
|
2813
3230
|
OptionsEditor,
|
|
2814
3231
|
{
|
|
@@ -2985,6 +3402,11 @@ function MonacoWrapper({ value, onChange, errors }) {
|
|
|
2985
3402
|
editorRef.current = editor;
|
|
2986
3403
|
monacoRef.current = monaco;
|
|
2987
3404
|
};
|
|
3405
|
+
useEffect(() => {
|
|
3406
|
+
return () => {
|
|
3407
|
+
editorRef.current?.dispose();
|
|
3408
|
+
};
|
|
3409
|
+
}, []);
|
|
2988
3410
|
useEffect(() => {
|
|
2989
3411
|
const editor = editorRef.current;
|
|
2990
3412
|
const monaco = monacoRef.current;
|
|
@@ -3789,6 +4211,11 @@ function TemplateGallery({ templates, onSelect, onClose }) {
|
|
|
3789
4211
|
function useDebouncedValidation(delayMs = 500) {
|
|
3790
4212
|
const [errors, setErrors] = useState([]);
|
|
3791
4213
|
const timerRef = useRef(null);
|
|
4214
|
+
useEffect(() => {
|
|
4215
|
+
return () => {
|
|
4216
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
4217
|
+
};
|
|
4218
|
+
}, []);
|
|
3792
4219
|
const validate = useCallback(
|
|
3793
4220
|
(text) => {
|
|
3794
4221
|
if (timerRef.current) {
|
|
@@ -4539,4 +4966,56 @@ function FormBuilderInner(props) {
|
|
|
4539
4966
|
// src/form-builder/components/FormBuilderGated.tsx
|
|
4540
4967
|
var FormBuilder = requireLicense(FormBuilderInner, "FormBuilder");
|
|
4541
4968
|
|
|
4542
|
-
|
|
4969
|
+
// src/form-builder/theme/presets.ts
|
|
4970
|
+
var squaredrDarkPreset = {
|
|
4971
|
+
background: "#0F1A1F",
|
|
4972
|
+
foreground: "#E8EFF1",
|
|
4973
|
+
card: "#16242A",
|
|
4974
|
+
primary: "#63BDB4",
|
|
4975
|
+
primaryForeground: "#0F1A1F",
|
|
4976
|
+
secondary: "#182F31",
|
|
4977
|
+
secondaryForeground: "#E8EFF1",
|
|
4978
|
+
muted: "#182F31",
|
|
4979
|
+
mutedForeground: "#8CA1A9",
|
|
4980
|
+
accent: "#182F31",
|
|
4981
|
+
accentForeground: "#E8EFF1",
|
|
4982
|
+
destructive: "#E08072",
|
|
4983
|
+
destructiveForeground: "#0F1A1F",
|
|
4984
|
+
border: "#2A3B42",
|
|
4985
|
+
input: "#2A3B42",
|
|
4986
|
+
ring: "#63BDB4",
|
|
4987
|
+
radius: "0px",
|
|
4988
|
+
surface: "#16242A",
|
|
4989
|
+
surfaceHover: "#182F31",
|
|
4990
|
+
canvas: "#0F1A1F",
|
|
4991
|
+
panel: "#16242A",
|
|
4992
|
+
borderStrong: "#2F4F4C",
|
|
4993
|
+
textDim: "#5E7680"
|
|
4994
|
+
};
|
|
4995
|
+
var cleanPreset = {
|
|
4996
|
+
background: "#F4F7F8",
|
|
4997
|
+
foreground: "#12222A",
|
|
4998
|
+
card: "#FFFFFF",
|
|
4999
|
+
primary: "#1F6B6E",
|
|
5000
|
+
primaryForeground: "#FFFFFF",
|
|
5001
|
+
secondary: "#EDF3F2",
|
|
5002
|
+
secondaryForeground: "#12222A",
|
|
5003
|
+
muted: "#EDF3F2",
|
|
5004
|
+
mutedForeground: "#6A7B85",
|
|
5005
|
+
accent: "#EDF3F2",
|
|
5006
|
+
accentForeground: "#12222A",
|
|
5007
|
+
destructive: "#B04A3C",
|
|
5008
|
+
destructiveForeground: "#FFFFFF",
|
|
5009
|
+
border: "#DCE4E8",
|
|
5010
|
+
input: "#DCE4E8",
|
|
5011
|
+
ring: "#1F6B6E",
|
|
5012
|
+
radius: "0px",
|
|
5013
|
+
surface: "#FAFCFC",
|
|
5014
|
+
surfaceHover: "#EDF3F2",
|
|
5015
|
+
canvas: "#F4F7F8",
|
|
5016
|
+
panel: "#FFFFFF",
|
|
5017
|
+
borderStrong: "#B9D1CF",
|
|
5018
|
+
textDim: "#6A7B85"
|
|
5019
|
+
};
|
|
5020
|
+
|
|
5021
|
+
export { DEFAULT_PALETTE, DEFAULT_SCHEMA, FormBuilder, FormBuilderThemeProvider, QUESTION_TYPE_INFO, addOption, addQuestion, addSection, cleanPreset, duplicateQuestion, duplicateSection, findQuestion, findSection, generateId, generateOptionId, generateQuestionId, generateSectionId, moveOption, moveQuestion, moveSection, removeOption, removeQuestion, removeSection, squaredrDarkPreset, updateOption, updateQuestion, updateSection, useBuilderState, useBuilderTheme, useDragDrop, useUndoRedo };
|