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