@squaredr/fieldcraft-pro 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-22T5PY6L.mjs +1081 -0
- package/dist/{chunk-GNBXIG63.mjs → chunk-6LRUDBC7.mjs} +1305 -89
- package/dist/{chunk-4BX7FCXH.mjs → chunk-BK4SMEW4.mjs} +840 -21
- package/dist/form-builder/index.d.mts +7 -367
- package/dist/form-builder/index.d.ts +7 -367
- package/dist/form-builder/index.js +1307 -91
- package/dist/form-builder/index.mjs +1 -1
- package/dist/index-BHJ4mqHP.d.mts +398 -0
- package/dist/index-BHJ4mqHP.d.ts +398 -0
- package/dist/index.d.mts +30 -3
- package/dist/index.d.ts +30 -3
- package/dist/index.js +3230 -331
- package/dist/index.mjs +276 -4
- package/dist/preview-schema-DFvV4y6J.d.mts +66 -0
- package/dist/preview-schema-DFvV4y6J.d.ts +66 -0
- package/dist/response-viewer/index.d.mts +9 -1
- package/dist/response-viewer/index.d.ts +9 -1
- package/dist/response-viewer/index.js +838 -19
- package/dist/response-viewer/index.mjs +1 -1
- package/dist/styles.css +1 -1
- package/dist/theme-editor/index.d.mts +30 -26
- package/dist/theme-editor/index.d.ts +30 -26
- package/dist/theme-editor/index.js +702 -22
- package/dist/theme-editor/index.mjs +1 -1
- package/package.json +18 -6
- package/theme-editor/styles.css +266 -62
- package/dist/chunk-7LQW5QYT.mjs +0 -407
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { cn } from './chunk-QQ4JZGTD.mjs';
|
|
2
2
|
import { requireLicense } from './chunk-VECQKSWS.mjs';
|
|
3
|
-
import { forwardRef, createContext, Component,
|
|
3
|
+
import { forwardRef, lazy, memo, createContext, Component, useState, useRef, useEffect, useCallback, useMemo, Suspense, useContext } from 'react';
|
|
4
4
|
import { DndContext, DragOverlay, useSensors, useSensor, MouseSensor, TouchSensor, useDraggable, useDroppable } from '@dnd-kit/core';
|
|
5
|
-
import { ChevronDown, Undo2, Redo2, Upload, Download, Save, X, PanelLeft, PanelRight, Search, ChevronRight, Plus, Settings, Copy, Trash2, HelpCircle, MoveVertical, Minus, Video, Image,
|
|
6
|
-
import { Button, Separator, Input, Badge, Textarea, Label, Switch } from '@squaredr/fieldcraft-react';
|
|
5
|
+
import { ChevronDown, Undo2, Redo2, PencilRuler, Eye, Code, LayoutTemplate, GitBranch, Upload, Download, Save, X, PanelLeft, PanelRight, Search, ChevronRight, Plus, Settings, FileText, Layers, Copy, Trash2, HelpCircle, MoveVertical, Minus, Video, Image, PartyPopper, Hand, ShieldCheck, SeparatorHorizontal, Info, Heading, Trophy, EyeOff, Calculator, CreditCard, MapPin, Repeat, Grid3X3, Camera, PenTool, Paperclip, CalendarCheck, CalendarRange, Clock, Calendar, ArrowUpDown, Globe, ToggleLeft, CheckSquare, CircleDot, ListOrdered, TrendingUp, BarChart3, Star, SlidersHorizontal, Hash, UserCheck, Link, PhoneCall, Phone, Mail, AlignLeft, Type, GripVertical } from 'lucide-react';
|
|
6
|
+
import { Button, Separator, FormEngineRenderer, Input, Badge, Textarea, Label, Switch } from '@squaredr/fieldcraft-react';
|
|
7
7
|
import { validateSchema, FormEngineSchemaError } from '@squaredr/fieldcraft-core';
|
|
8
8
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
9
|
+
import { MarkerType, Handle, Position, getBezierPath, BaseEdge, EdgeLabelRenderer, useNodesState, useEdgesState, ReactFlow, Background, Controls, MiniMap } from '@xyflow/react';
|
|
10
|
+
import '@xyflow/react/dist/style.css';
|
|
9
11
|
|
|
10
12
|
var MAX_HISTORY = 50;
|
|
11
13
|
function useUndoRedo(currentSchema, setSchema) {
|
|
@@ -451,6 +453,14 @@ var QUESTION_TYPE_INFO = {
|
|
|
451
453
|
icon: "Phone",
|
|
452
454
|
description: "US phone number input"
|
|
453
455
|
},
|
|
456
|
+
phone_international: {
|
|
457
|
+
type: "phone_international",
|
|
458
|
+
label: "Intl Phone",
|
|
459
|
+
category: "text",
|
|
460
|
+
icon: "Globe2",
|
|
461
|
+
description: "Phone with country code",
|
|
462
|
+
defaultConfig: { type: "phone_international", defaultCountry: "US" }
|
|
463
|
+
},
|
|
454
464
|
url: {
|
|
455
465
|
type: "url",
|
|
456
466
|
label: "URL",
|
|
@@ -544,6 +554,14 @@ var QUESTION_TYPE_INFO = {
|
|
|
544
554
|
requiresOptions: true,
|
|
545
555
|
defaultConfig: { type: "ranking", items: [] }
|
|
546
556
|
},
|
|
557
|
+
country_select: {
|
|
558
|
+
type: "country_select",
|
|
559
|
+
label: "Country",
|
|
560
|
+
category: "selection",
|
|
561
|
+
icon: "Globe",
|
|
562
|
+
description: "Country dropdown with search",
|
|
563
|
+
defaultConfig: { type: "country_select" }
|
|
564
|
+
},
|
|
547
565
|
// ── Date/Time ──
|
|
548
566
|
date: {
|
|
549
567
|
type: "date",
|
|
@@ -570,7 +588,97 @@ var QUESTION_TYPE_INFO = {
|
|
|
570
588
|
description: "Upload files",
|
|
571
589
|
defaultConfig: { type: "file_upload", maxFiles: 1, maxSizeMb: 10 }
|
|
572
590
|
},
|
|
591
|
+
// ── Compound ──
|
|
592
|
+
legal_name: {
|
|
593
|
+
type: "legal_name",
|
|
594
|
+
label: "Legal Name",
|
|
595
|
+
category: "text",
|
|
596
|
+
icon: "UserCheck",
|
|
597
|
+
description: "First, middle, and last name",
|
|
598
|
+
defaultConfig: { type: "legal_name" }
|
|
599
|
+
},
|
|
600
|
+
address: {
|
|
601
|
+
type: "address",
|
|
602
|
+
label: "Address",
|
|
603
|
+
category: "text",
|
|
604
|
+
icon: "MapPin",
|
|
605
|
+
description: "Street, city, state, ZIP",
|
|
606
|
+
defaultConfig: { type: "address", includeCountry: false }
|
|
607
|
+
},
|
|
608
|
+
signature: {
|
|
609
|
+
type: "signature",
|
|
610
|
+
label: "Signature",
|
|
611
|
+
category: "media",
|
|
612
|
+
icon: "PenTool",
|
|
613
|
+
description: "Canvas signature pad",
|
|
614
|
+
defaultConfig: { type: "signature" }
|
|
615
|
+
},
|
|
616
|
+
image_capture: {
|
|
617
|
+
type: "image_capture",
|
|
618
|
+
label: "Camera",
|
|
619
|
+
category: "media",
|
|
620
|
+
icon: "Camera",
|
|
621
|
+
description: "Capture photo from camera",
|
|
622
|
+
defaultConfig: { type: "image_capture", allowGallery: true }
|
|
623
|
+
},
|
|
624
|
+
date_range: {
|
|
625
|
+
type: "date_range",
|
|
626
|
+
label: "Date Range",
|
|
627
|
+
category: "datetime",
|
|
628
|
+
icon: "CalendarRange",
|
|
629
|
+
description: "Start and end date picker",
|
|
630
|
+
defaultConfig: { type: "date_range" }
|
|
631
|
+
},
|
|
632
|
+
appointment: {
|
|
633
|
+
type: "appointment",
|
|
634
|
+
label: "Appointment",
|
|
635
|
+
category: "datetime",
|
|
636
|
+
icon: "CalendarCheck",
|
|
637
|
+
description: "Date & time slot booking",
|
|
638
|
+
defaultConfig: { type: "appointment", duration: 30 }
|
|
639
|
+
},
|
|
573
640
|
// ── Advanced ──
|
|
641
|
+
repeater: {
|
|
642
|
+
type: "repeater",
|
|
643
|
+
label: "Repeater",
|
|
644
|
+
category: "advanced",
|
|
645
|
+
icon: "ListPlus",
|
|
646
|
+
description: "Repeatable group of fields",
|
|
647
|
+
defaultConfig: { type: "repeater", fields: [], minItems: 1, maxItems: 10 }
|
|
648
|
+
},
|
|
649
|
+
likert: {
|
|
650
|
+
type: "likert",
|
|
651
|
+
label: "Likert Scale",
|
|
652
|
+
category: "advanced",
|
|
653
|
+
icon: "AlignHorizontalSpaceAround",
|
|
654
|
+
description: "Agreement scale (e.g. Strongly Disagree to Strongly Agree)",
|
|
655
|
+
requiresOptions: true,
|
|
656
|
+
defaultConfig: {
|
|
657
|
+
type: "likert",
|
|
658
|
+
scale: [
|
|
659
|
+
{ label: "Strongly Disagree", value: "1" },
|
|
660
|
+
{ label: "Disagree", value: "2" },
|
|
661
|
+
{ label: "Neutral", value: "3" },
|
|
662
|
+
{ label: "Agree", value: "4" },
|
|
663
|
+
{ label: "Strongly Agree", value: "5" }
|
|
664
|
+
]
|
|
665
|
+
}
|
|
666
|
+
},
|
|
667
|
+
scoring: {
|
|
668
|
+
type: "scoring",
|
|
669
|
+
label: "Scoring",
|
|
670
|
+
category: "advanced",
|
|
671
|
+
icon: "Award",
|
|
672
|
+
description: "Scored question with point values per option",
|
|
673
|
+
requiresOptions: true,
|
|
674
|
+
defaultConfig: {
|
|
675
|
+
type: "scoring",
|
|
676
|
+
options: [
|
|
677
|
+
{ label: "Option 1", value: "1", score: 1 },
|
|
678
|
+
{ label: "Option 2", value: "2", score: 2 }
|
|
679
|
+
]
|
|
680
|
+
}
|
|
681
|
+
},
|
|
574
682
|
matrix: {
|
|
575
683
|
type: "matrix",
|
|
576
684
|
label: "Matrix",
|
|
@@ -600,6 +708,14 @@ var QUESTION_TYPE_INFO = {
|
|
|
600
708
|
description: "Hidden value from URL or static",
|
|
601
709
|
defaultConfig: { type: "hidden", source: "static" }
|
|
602
710
|
},
|
|
711
|
+
payment: {
|
|
712
|
+
type: "payment",
|
|
713
|
+
label: "Payment",
|
|
714
|
+
category: "advanced",
|
|
715
|
+
icon: "CreditCard",
|
|
716
|
+
description: "Collect payment via Stripe",
|
|
717
|
+
defaultConfig: { type: "payment", provider: "stripe", publicKey: "", currency: "USD" }
|
|
718
|
+
},
|
|
603
719
|
// ── Structural ──
|
|
604
720
|
section_header: {
|
|
605
721
|
type: "section_header",
|
|
@@ -704,7 +820,7 @@ var DEFAULT_PALETTE = [
|
|
|
704
820
|
{
|
|
705
821
|
category: "text",
|
|
706
822
|
label: "Text Input",
|
|
707
|
-
types: ["short_text", "long_text", "email", "phone", "url"]
|
|
823
|
+
types: ["short_text", "long_text", "email", "phone", "phone_international", "url", "legal_name", "address"]
|
|
708
824
|
},
|
|
709
825
|
{
|
|
710
826
|
category: "numeric",
|
|
@@ -714,17 +830,17 @@ var DEFAULT_PALETTE = [
|
|
|
714
830
|
{
|
|
715
831
|
category: "selection",
|
|
716
832
|
label: "Selection",
|
|
717
|
-
types: ["single_select", "multi_select", "dropdown", "boolean", "ranking"]
|
|
833
|
+
types: ["single_select", "multi_select", "dropdown", "boolean", "ranking", "country_select"]
|
|
718
834
|
},
|
|
719
835
|
{
|
|
720
836
|
category: "datetime",
|
|
721
837
|
label: "Date & Time",
|
|
722
|
-
types: ["date", "time"]
|
|
838
|
+
types: ["date", "time", "date_range", "appointment"]
|
|
723
839
|
},
|
|
724
840
|
{
|
|
725
841
|
category: "media",
|
|
726
842
|
label: "Media",
|
|
727
|
-
types: ["file_upload"]
|
|
843
|
+
types: ["file_upload", "signature", "image_capture"]
|
|
728
844
|
},
|
|
729
845
|
{
|
|
730
846
|
category: "content",
|
|
@@ -739,7 +855,7 @@ var DEFAULT_PALETTE = [
|
|
|
739
855
|
{
|
|
740
856
|
category: "advanced",
|
|
741
857
|
label: "Advanced",
|
|
742
|
-
types: ["matrix", "calculated", "hidden"]
|
|
858
|
+
types: ["repeater", "likert", "scoring", "matrix", "calculated", "hidden", "payment"]
|
|
743
859
|
}
|
|
744
860
|
];
|
|
745
861
|
|
|
@@ -2253,7 +2369,8 @@ function getFieldOptions(schema, excludeId) {
|
|
|
2253
2369
|
return fields;
|
|
2254
2370
|
}
|
|
2255
2371
|
function ConditionEditor({ question, schema, onUpdate }) {
|
|
2256
|
-
const
|
|
2372
|
+
const rawShowIf = question.showIf;
|
|
2373
|
+
const showIf = rawShowIf && rawShowIf.field && !rawShowIf.conditions ? { combine: "AND", conditions: [rawShowIf] } : rawShowIf;
|
|
2257
2374
|
const fieldOptions = getFieldOptions(schema, question.id);
|
|
2258
2375
|
const updateShowIf = (next) => {
|
|
2259
2376
|
onUpdate({ showIf: next });
|
|
@@ -2375,6 +2492,24 @@ function ConditionEditor({ question, schema, onUpdate }) {
|
|
|
2375
2492
|
}
|
|
2376
2493
|
function FormSettingsPanel({ schema, onUpdate }) {
|
|
2377
2494
|
const settings = schema.settings ?? {};
|
|
2495
|
+
const hasConditions = schema.sections.some(
|
|
2496
|
+
(s) => s.showIf || s.questions.some((q) => q.showIf)
|
|
2497
|
+
);
|
|
2498
|
+
const displayModeOptions = hasConditions ? [
|
|
2499
|
+
{ label: "Stepped", value: "stepped" },
|
|
2500
|
+
{ label: "Conversational", value: "conversational" }
|
|
2501
|
+
] : [
|
|
2502
|
+
{ label: "Stepped", value: "stepped" },
|
|
2503
|
+
{ label: "Classic", value: "classic" },
|
|
2504
|
+
{ label: "Conversational", value: "conversational" }
|
|
2505
|
+
];
|
|
2506
|
+
const displayMode = settings.displayMode ?? "stepped";
|
|
2507
|
+
const effectiveDisplayMode = hasConditions && displayMode === "classic" ? "stepped" : displayMode;
|
|
2508
|
+
useEffect(() => {
|
|
2509
|
+
if (effectiveDisplayMode !== displayMode) {
|
|
2510
|
+
onUpdate({ ...schema, settings: { ...settings, displayMode: effectiveDisplayMode } });
|
|
2511
|
+
}
|
|
2512
|
+
}, [effectiveDisplayMode, displayMode]);
|
|
2378
2513
|
const updateSettings = (updates) => {
|
|
2379
2514
|
onUpdate({ ...schema, settings: { ...settings, ...updates } });
|
|
2380
2515
|
};
|
|
@@ -2402,12 +2537,8 @@ function FormSettingsPanel({ schema, onUpdate }) {
|
|
|
2402
2537
|
SettingsSelect,
|
|
2403
2538
|
{
|
|
2404
2539
|
label: "Mode",
|
|
2405
|
-
value:
|
|
2406
|
-
options:
|
|
2407
|
-
{ label: "Classic", value: "classic" },
|
|
2408
|
-
{ label: "Stepped", value: "stepped" },
|
|
2409
|
-
{ label: "Conversational", value: "conversational" }
|
|
2410
|
-
],
|
|
2540
|
+
value: effectiveDisplayMode,
|
|
2541
|
+
options: displayModeOptions,
|
|
2411
2542
|
onChange: (v) => updateSettings({ displayMode: v })
|
|
2412
2543
|
}
|
|
2413
2544
|
),
|
|
@@ -2785,6 +2916,873 @@ function FieldGroup({ label, children }) {
|
|
|
2785
2916
|
children
|
|
2786
2917
|
] });
|
|
2787
2918
|
}
|
|
2919
|
+
var PreviewErrorBoundary = class extends Component {
|
|
2920
|
+
state = { error: null };
|
|
2921
|
+
static getDerivedStateFromError(error) {
|
|
2922
|
+
return { error };
|
|
2923
|
+
}
|
|
2924
|
+
componentDidCatch(error, info) {
|
|
2925
|
+
console.error("[FormBuilder Preview]", error, info);
|
|
2926
|
+
}
|
|
2927
|
+
componentDidUpdate(prevProps) {
|
|
2928
|
+
if (prevProps.resetKey !== this.props.resetKey && this.state.error) {
|
|
2929
|
+
this.setState({ error: null });
|
|
2930
|
+
}
|
|
2931
|
+
}
|
|
2932
|
+
render() {
|
|
2933
|
+
if (this.state.error) {
|
|
2934
|
+
return /* @__PURE__ */ jsxs("div", { className: "p-4 text-destructive text-sm font-mono", children: [
|
|
2935
|
+
/* @__PURE__ */ jsx("strong", { children: "Render Error:" }),
|
|
2936
|
+
" ",
|
|
2937
|
+
this.state.error.message
|
|
2938
|
+
] });
|
|
2939
|
+
}
|
|
2940
|
+
return this.props.children;
|
|
2941
|
+
}
|
|
2942
|
+
};
|
|
2943
|
+
function FormPreviewPanel({ schema, preview }) {
|
|
2944
|
+
const hasSections = schema.sections && schema.sections.length > 0;
|
|
2945
|
+
const hasFields = hasSections && schema.sections.some((s) => s.questions.length > 0);
|
|
2946
|
+
if (!hasFields) {
|
|
2947
|
+
return /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-center text-muted-foreground text-sm", children: /* @__PURE__ */ jsxs("div", { className: "text-center space-y-2", children: [
|
|
2948
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium", children: "No fields to preview" }),
|
|
2949
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs", children: "Add fields in the Design view to see a live preview here." })
|
|
2950
|
+
] }) });
|
|
2951
|
+
}
|
|
2952
|
+
return /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: /* @__PURE__ */ jsx("div", { className: "max-w-2xl mx-auto py-8 px-4", children: /* @__PURE__ */ jsx(PreviewErrorBoundary, { resetKey: schema.id + (schema.version ?? ""), children: /* @__PURE__ */ jsx(
|
|
2953
|
+
FormEngineRenderer,
|
|
2954
|
+
{
|
|
2955
|
+
schema,
|
|
2956
|
+
theme: preview?.theme,
|
|
2957
|
+
components: preview?.components,
|
|
2958
|
+
onReady: preview?.onReady,
|
|
2959
|
+
onFieldChange: preview?.onFieldChange,
|
|
2960
|
+
onSubmit: preview?.onSubmit ?? (() => {
|
|
2961
|
+
})
|
|
2962
|
+
}
|
|
2963
|
+
) }) }) });
|
|
2964
|
+
}
|
|
2965
|
+
|
|
2966
|
+
// src/form-builder/utils/validation-markers.ts
|
|
2967
|
+
var MarkerSeverity = {
|
|
2968
|
+
Error: 8};
|
|
2969
|
+
function errorsToMarkers(errors) {
|
|
2970
|
+
return errors.map((error) => ({
|
|
2971
|
+
severity: MarkerSeverity.Error,
|
|
2972
|
+
message: error.message,
|
|
2973
|
+
startLineNumber: error.line ?? 1,
|
|
2974
|
+
startColumn: error.column ?? 1,
|
|
2975
|
+
endLineNumber: error.endLine ?? error.line ?? 1,
|
|
2976
|
+
endColumn: error.endColumn ?? error.column ?? 1,
|
|
2977
|
+
source: "FieldCraft Schema Validator"
|
|
2978
|
+
}));
|
|
2979
|
+
}
|
|
2980
|
+
var Editor = lazy(() => import('@monaco-editor/react').then((m) => ({ default: m.default })));
|
|
2981
|
+
function MonacoWrapper({ value, onChange, errors }) {
|
|
2982
|
+
const editorRef = useRef(null);
|
|
2983
|
+
const monacoRef = useRef(null);
|
|
2984
|
+
const handleMount = (editor, monaco) => {
|
|
2985
|
+
editorRef.current = editor;
|
|
2986
|
+
monacoRef.current = monaco;
|
|
2987
|
+
};
|
|
2988
|
+
useEffect(() => {
|
|
2989
|
+
const editor = editorRef.current;
|
|
2990
|
+
const monaco = monacoRef.current;
|
|
2991
|
+
if (!editor || !monaco) return;
|
|
2992
|
+
const model = editor.getModel();
|
|
2993
|
+
if (!model) return;
|
|
2994
|
+
const markers = errorsToMarkers(errors);
|
|
2995
|
+
monaco.editor.setModelMarkers(model, "fieldcraft-schema", markers);
|
|
2996
|
+
}, [errors]);
|
|
2997
|
+
return /* @__PURE__ */ jsx(
|
|
2998
|
+
Editor,
|
|
2999
|
+
{
|
|
3000
|
+
height: "100%",
|
|
3001
|
+
language: "json",
|
|
3002
|
+
theme: "vs-dark",
|
|
3003
|
+
value,
|
|
3004
|
+
onChange: (val) => onChange(val ?? ""),
|
|
3005
|
+
onMount: handleMount,
|
|
3006
|
+
options: {
|
|
3007
|
+
minimap: { enabled: false },
|
|
3008
|
+
fontSize: 13,
|
|
3009
|
+
wordWrap: "on",
|
|
3010
|
+
formatOnPaste: true,
|
|
3011
|
+
automaticLayout: true,
|
|
3012
|
+
tabSize: 2,
|
|
3013
|
+
scrollBeyondLastLine: false,
|
|
3014
|
+
padding: { top: 12 }
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
3017
|
+
);
|
|
3018
|
+
}
|
|
3019
|
+
function JsonEditorPanel({ value, onChange, errors, onValidate }) {
|
|
3020
|
+
const handleChange = useCallback(
|
|
3021
|
+
(newValue) => {
|
|
3022
|
+
onChange(newValue);
|
|
3023
|
+
onValidate(newValue);
|
|
3024
|
+
},
|
|
3025
|
+
[onChange, onValidate]
|
|
3026
|
+
);
|
|
3027
|
+
const handleFormat = useCallback(() => {
|
|
3028
|
+
try {
|
|
3029
|
+
const formatted = JSON.stringify(JSON.parse(value), null, 2);
|
|
3030
|
+
onChange(formatted);
|
|
3031
|
+
} catch {
|
|
3032
|
+
}
|
|
3033
|
+
}, [value, onChange]);
|
|
3034
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col overflow-hidden", children: [
|
|
3035
|
+
errors.length > 0 && /* @__PURE__ */ jsxs("div", { className: "shrink-0 px-3 py-1.5 bg-destructive/10 border-b border-destructive/20 text-destructive text-xs font-mono overflow-x-auto", children: [
|
|
3036
|
+
errors.slice(0, 3).map((e, i) => /* @__PURE__ */ jsxs("div", { children: [
|
|
3037
|
+
e.line ? `Line ${e.line}: ` : "",
|
|
3038
|
+
e.path ? `${e.path}: ` : "",
|
|
3039
|
+
e.message
|
|
3040
|
+
] }, i)),
|
|
3041
|
+
errors.length > 3 && /* @__PURE__ */ jsxs("div", { className: "text-muted-foreground", children: [
|
|
3042
|
+
"...and ",
|
|
3043
|
+
errors.length - 3,
|
|
3044
|
+
" more"
|
|
3045
|
+
] })
|
|
3046
|
+
] }),
|
|
3047
|
+
/* @__PURE__ */ jsxs("div", { className: "shrink-0 flex items-center justify-between px-3 py-1.5 bg-card border-b border-border text-xs", children: [
|
|
3048
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: errors.length === 0 ? "Valid schema" : `${errors.length} error${errors.length !== 1 ? "s" : ""}` }),
|
|
3049
|
+
/* @__PURE__ */ jsx(
|
|
3050
|
+
"button",
|
|
3051
|
+
{
|
|
3052
|
+
type: "button",
|
|
3053
|
+
onClick: handleFormat,
|
|
3054
|
+
className: "text-primary hover:underline",
|
|
3055
|
+
children: "Format JSON"
|
|
3056
|
+
}
|
|
3057
|
+
)
|
|
3058
|
+
] }),
|
|
3059
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
3060
|
+
Suspense,
|
|
3061
|
+
{
|
|
3062
|
+
fallback: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-full text-sm text-muted-foreground", children: "Loading editor..." }),
|
|
3063
|
+
children: /* @__PURE__ */ jsx(MonacoWrapper, { value, onChange: handleChange, errors })
|
|
3064
|
+
}
|
|
3065
|
+
) })
|
|
3066
|
+
] });
|
|
3067
|
+
}
|
|
3068
|
+
|
|
3069
|
+
// src/form-builder/utils/logic-graph.ts
|
|
3070
|
+
function extractFieldRefs(expr) {
|
|
3071
|
+
const refs = [];
|
|
3072
|
+
if (expr.field) {
|
|
3073
|
+
refs.push({ field: expr.field, operator: expr.operator, value: expr.value });
|
|
3074
|
+
}
|
|
3075
|
+
if (expr.conditions) {
|
|
3076
|
+
for (const child of expr.conditions) {
|
|
3077
|
+
refs.push(...extractFieldRefs(child));
|
|
3078
|
+
}
|
|
3079
|
+
}
|
|
3080
|
+
return refs;
|
|
3081
|
+
}
|
|
3082
|
+
function buildLogicGraph(schema) {
|
|
3083
|
+
const nodes = [];
|
|
3084
|
+
const edges = [];
|
|
3085
|
+
const nodeIds = /* @__PURE__ */ new Set();
|
|
3086
|
+
for (const section of schema.sections) {
|
|
3087
|
+
nodes.push({
|
|
3088
|
+
id: section.id,
|
|
3089
|
+
label: section.title || "Untitled Section",
|
|
3090
|
+
type: "section",
|
|
3091
|
+
sectionId: section.id,
|
|
3092
|
+
sectionTitle: section.title || "Untitled Section",
|
|
3093
|
+
hasCondition: !!section.showIf
|
|
3094
|
+
});
|
|
3095
|
+
nodeIds.add(section.id);
|
|
3096
|
+
if (section.showIf) {
|
|
3097
|
+
const refs = extractFieldRefs(section.showIf);
|
|
3098
|
+
for (const ref of refs) {
|
|
3099
|
+
edges.push({ from: ref.field, to: section.id, edgeType: "showIf", operator: ref.operator, value: ref.value });
|
|
3100
|
+
}
|
|
3101
|
+
}
|
|
3102
|
+
if (section.onExit) {
|
|
3103
|
+
for (const rule of section.onExit.rules) {
|
|
3104
|
+
if (rule.jumpTo) {
|
|
3105
|
+
edges.push({ from: section.id, to: rule.jumpTo, edgeType: "onExit", jumpTo: rule.jumpTo });
|
|
3106
|
+
}
|
|
3107
|
+
}
|
|
3108
|
+
if (section.onExit.default) {
|
|
3109
|
+
edges.push({ from: section.id, to: section.onExit.default, edgeType: "onExit", jumpTo: section.onExit.default });
|
|
3110
|
+
}
|
|
3111
|
+
}
|
|
3112
|
+
for (const question of section.questions) {
|
|
3113
|
+
nodes.push({
|
|
3114
|
+
id: question.id,
|
|
3115
|
+
label: question.label || question.id,
|
|
3116
|
+
type: "field",
|
|
3117
|
+
fieldType: question.type,
|
|
3118
|
+
sectionId: section.id,
|
|
3119
|
+
sectionTitle: section.title || "Untitled Section",
|
|
3120
|
+
hasCondition: !!question.showIf
|
|
3121
|
+
});
|
|
3122
|
+
nodeIds.add(question.id);
|
|
3123
|
+
if (question.showIf) {
|
|
3124
|
+
const refs = extractFieldRefs(question.showIf);
|
|
3125
|
+
for (const ref of refs) {
|
|
3126
|
+
edges.push({ from: ref.field, to: question.id, edgeType: "showIf", operator: ref.operator, value: ref.value });
|
|
3127
|
+
}
|
|
3128
|
+
}
|
|
3129
|
+
}
|
|
3130
|
+
}
|
|
3131
|
+
const validEdges = edges.filter((e) => nodeIds.has(e.from) && nodeIds.has(e.to));
|
|
3132
|
+
return { nodes, edges: validEdges };
|
|
3133
|
+
}
|
|
3134
|
+
var SECTION_COLORS = [
|
|
3135
|
+
"#3b82f6",
|
|
3136
|
+
// blue
|
|
3137
|
+
"#8b5cf6",
|
|
3138
|
+
// violet
|
|
3139
|
+
"#06b6d4",
|
|
3140
|
+
// cyan
|
|
3141
|
+
"#f59e0b",
|
|
3142
|
+
// amber
|
|
3143
|
+
"#10b981",
|
|
3144
|
+
// emerald
|
|
3145
|
+
"#ef4444",
|
|
3146
|
+
// red
|
|
3147
|
+
"#ec4899",
|
|
3148
|
+
// pink
|
|
3149
|
+
"#6366f1"
|
|
3150
|
+
// indigo
|
|
3151
|
+
];
|
|
3152
|
+
var FIELD_NODE_WIDTH = 220;
|
|
3153
|
+
var FIELD_NODE_HEIGHT = 52;
|
|
3154
|
+
var SECTION_HEADER_HEIGHT = 40;
|
|
3155
|
+
var SECTION_PADDING_X = 16;
|
|
3156
|
+
var SECTION_PADDING_TOP = 12;
|
|
3157
|
+
var SECTION_PADDING_BOTTOM = 16;
|
|
3158
|
+
var FIELD_GAP = 10;
|
|
3159
|
+
var SECTION_GAP = 80;
|
|
3160
|
+
function formatEdgeLabel(edge) {
|
|
3161
|
+
if (edge.edgeType === "onExit") return "jump";
|
|
3162
|
+
if (!edge.operator) return "";
|
|
3163
|
+
const op = edge.operator;
|
|
3164
|
+
const val = edge.value;
|
|
3165
|
+
if (op === "exists") return "has value";
|
|
3166
|
+
if (op === "notExists") return "is empty";
|
|
3167
|
+
if (val === void 0 || val === null || val === "") return op;
|
|
3168
|
+
const short = String(val).length > 12 ? String(val).slice(0, 12) + "\u2026" : String(val);
|
|
3169
|
+
return `${op} ${short}`;
|
|
3170
|
+
}
|
|
3171
|
+
function buildReactFlowGraph(schema) {
|
|
3172
|
+
const graph = buildLogicGraph(schema);
|
|
3173
|
+
const nodes = [];
|
|
3174
|
+
const edges = [];
|
|
3175
|
+
let sectionX = 0;
|
|
3176
|
+
let maxSectionHeight = 0;
|
|
3177
|
+
for (const section of schema.sections) {
|
|
3178
|
+
const fieldCount = section.questions.length;
|
|
3179
|
+
const contentHeight = SECTION_HEADER_HEIGHT + SECTION_PADDING_TOP + fieldCount * FIELD_NODE_HEIGHT + Math.max(0, fieldCount - 1) * FIELD_GAP + SECTION_PADDING_BOTTOM;
|
|
3180
|
+
if (contentHeight > maxSectionHeight) maxSectionHeight = contentHeight;
|
|
3181
|
+
}
|
|
3182
|
+
if (maxSectionHeight < SECTION_HEADER_HEIGHT + SECTION_PADDING_TOP + SECTION_PADDING_BOTTOM + FIELD_NODE_HEIGHT) {
|
|
3183
|
+
maxSectionHeight = SECTION_HEADER_HEIGHT + SECTION_PADDING_TOP + SECTION_PADDING_BOTTOM + FIELD_NODE_HEIGHT;
|
|
3184
|
+
}
|
|
3185
|
+
const sectionWidth = FIELD_NODE_WIDTH + SECTION_PADDING_X * 2;
|
|
3186
|
+
for (let sIdx = 0; sIdx < schema.sections.length; sIdx++) {
|
|
3187
|
+
const section = schema.sections[sIdx];
|
|
3188
|
+
const colorIndex = sIdx;
|
|
3189
|
+
nodes.push({
|
|
3190
|
+
id: section.id,
|
|
3191
|
+
type: "sectionNode",
|
|
3192
|
+
position: { x: sectionX, y: 0 },
|
|
3193
|
+
data: {
|
|
3194
|
+
label: section.title || "Untitled Section",
|
|
3195
|
+
sectionId: section.id,
|
|
3196
|
+
fieldCount: section.questions.length,
|
|
3197
|
+
hasCondition: !!section.showIf,
|
|
3198
|
+
hasExitLogic: !!section.onExit,
|
|
3199
|
+
colorIndex
|
|
3200
|
+
},
|
|
3201
|
+
style: { width: sectionWidth, height: maxSectionHeight }
|
|
3202
|
+
});
|
|
3203
|
+
for (let fIdx = 0; fIdx < section.questions.length; fIdx++) {
|
|
3204
|
+
const question = section.questions[fIdx];
|
|
3205
|
+
const fieldY = SECTION_HEADER_HEIGHT + SECTION_PADDING_TOP + fIdx * (FIELD_NODE_HEIGHT + FIELD_GAP);
|
|
3206
|
+
nodes.push({
|
|
3207
|
+
id: question.id,
|
|
3208
|
+
type: "fieldNode",
|
|
3209
|
+
position: { x: SECTION_PADDING_X, y: fieldY },
|
|
3210
|
+
parentId: section.id,
|
|
3211
|
+
extent: "parent",
|
|
3212
|
+
data: {
|
|
3213
|
+
label: question.label || question.id,
|
|
3214
|
+
fieldType: question.type,
|
|
3215
|
+
sectionId: section.id,
|
|
3216
|
+
hasCondition: !!question.showIf,
|
|
3217
|
+
colorIndex
|
|
3218
|
+
},
|
|
3219
|
+
style: { width: FIELD_NODE_WIDTH }
|
|
3220
|
+
});
|
|
3221
|
+
}
|
|
3222
|
+
if (sIdx < schema.sections.length - 1) {
|
|
3223
|
+
const nextSection = schema.sections[sIdx + 1];
|
|
3224
|
+
edges.push({
|
|
3225
|
+
id: `pipeline-${section.id}-${nextSection.id}`,
|
|
3226
|
+
source: section.id,
|
|
3227
|
+
target: nextSection.id,
|
|
3228
|
+
type: "pipelineEdge",
|
|
3229
|
+
data: { edgeType: "pipeline" }
|
|
3230
|
+
});
|
|
3231
|
+
}
|
|
3232
|
+
sectionX += sectionWidth + SECTION_GAP;
|
|
3233
|
+
}
|
|
3234
|
+
for (let i = 0; i < graph.edges.length; i++) {
|
|
3235
|
+
const edge = graph.edges[i];
|
|
3236
|
+
edges.push({
|
|
3237
|
+
id: `e-${edge.from}-${edge.to}-${i}`,
|
|
3238
|
+
source: edge.from,
|
|
3239
|
+
target: edge.to,
|
|
3240
|
+
type: "conditionEdge",
|
|
3241
|
+
animated: edge.edgeType === "showIf",
|
|
3242
|
+
style: edge.edgeType === "onExit" ? { strokeDasharray: "6 3", stroke: "#f59e0b" } : void 0,
|
|
3243
|
+
label: formatEdgeLabel(edge),
|
|
3244
|
+
data: {
|
|
3245
|
+
edgeType: edge.edgeType,
|
|
3246
|
+
operator: edge.operator,
|
|
3247
|
+
value: edge.value,
|
|
3248
|
+
sourceId: edge.from,
|
|
3249
|
+
targetId: edge.to
|
|
3250
|
+
}
|
|
3251
|
+
});
|
|
3252
|
+
}
|
|
3253
|
+
return { nodes, edges };
|
|
3254
|
+
}
|
|
3255
|
+
function SectionNodeInner({ data }) {
|
|
3256
|
+
const d = data;
|
|
3257
|
+
const color = SECTION_COLORS[d.colorIndex % SECTION_COLORS.length];
|
|
3258
|
+
return /* @__PURE__ */ jsxs("div", { className: "fc-flow-section-group", style: { borderColor: color }, children: [
|
|
3259
|
+
/* @__PURE__ */ jsx(Handle, { type: "target", position: Position.Left, className: "fc-flow-handle fc-flow-handle--section" }),
|
|
3260
|
+
/* @__PURE__ */ jsxs("div", { className: "fc-flow-section-group__header", style: { background: color }, children: [
|
|
3261
|
+
/* @__PURE__ */ jsx("span", { className: "fc-flow-section-group__label", children: d.label.length > 30 ? d.label.slice(0, 30) + "\u2026" : d.label }),
|
|
3262
|
+
/* @__PURE__ */ jsxs("span", { className: "fc-flow-section-group__meta", children: [
|
|
3263
|
+
d.fieldCount,
|
|
3264
|
+
" field",
|
|
3265
|
+
d.fieldCount !== 1 ? "s" : "",
|
|
3266
|
+
d.hasCondition && /* @__PURE__ */ jsx("span", { className: "fc-flow-section-group__badge", title: "Has showIf condition", children: "?" }),
|
|
3267
|
+
d.hasExitLogic && /* @__PURE__ */ jsx("span", { className: "fc-flow-section-group__badge fc-flow-section-group__badge--jump", title: "Has onExit jump", children: "\u2934" })
|
|
3268
|
+
] })
|
|
3269
|
+
] }),
|
|
3270
|
+
/* @__PURE__ */ jsx(Handle, { type: "source", position: Position.Right, className: "fc-flow-handle fc-flow-handle--section" })
|
|
3271
|
+
] });
|
|
3272
|
+
}
|
|
3273
|
+
var SectionNode = memo(SectionNodeInner);
|
|
3274
|
+
function FieldNodeInner({ data }) {
|
|
3275
|
+
const d = data;
|
|
3276
|
+
const color = SECTION_COLORS[d.colorIndex % SECTION_COLORS.length];
|
|
3277
|
+
return /* @__PURE__ */ jsxs(
|
|
3278
|
+
"div",
|
|
3279
|
+
{
|
|
3280
|
+
className: "fc-flow-field",
|
|
3281
|
+
style: {
|
|
3282
|
+
borderColor: d.hasCondition ? color : void 0,
|
|
3283
|
+
borderWidth: d.hasCondition ? 2 : 1
|
|
3284
|
+
},
|
|
3285
|
+
children: [
|
|
3286
|
+
/* @__PURE__ */ jsx(Handle, { type: "target", position: Position.Left, className: "fc-flow-handle" }),
|
|
3287
|
+
/* @__PURE__ */ jsxs("div", { className: "fc-flow-field__content", children: [
|
|
3288
|
+
/* @__PURE__ */ jsx("span", { className: "fc-flow-field__label", children: d.label.length > 26 ? d.label.slice(0, 26) + "\u2026" : d.label }),
|
|
3289
|
+
/* @__PURE__ */ jsx("span", { className: "fc-flow-field__type", children: d.fieldType })
|
|
3290
|
+
] }),
|
|
3291
|
+
d.hasCondition && /* @__PURE__ */ jsx("div", { className: "fc-flow-badge", style: { background: color }, title: "Has showIf condition", children: "?" }),
|
|
3292
|
+
/* @__PURE__ */ jsx(Handle, { type: "source", position: Position.Right, className: "fc-flow-handle" })
|
|
3293
|
+
]
|
|
3294
|
+
}
|
|
3295
|
+
);
|
|
3296
|
+
}
|
|
3297
|
+
var FieldNode = memo(FieldNodeInner);
|
|
3298
|
+
var logicFlowNodeTypes = {
|
|
3299
|
+
sectionNode: SectionNode,
|
|
3300
|
+
fieldNode: FieldNode
|
|
3301
|
+
};
|
|
3302
|
+
function ConditionEdgeInner({
|
|
3303
|
+
id,
|
|
3304
|
+
sourceX,
|
|
3305
|
+
sourceY,
|
|
3306
|
+
targetX,
|
|
3307
|
+
targetY,
|
|
3308
|
+
sourcePosition,
|
|
3309
|
+
targetPosition,
|
|
3310
|
+
label,
|
|
3311
|
+
style,
|
|
3312
|
+
data,
|
|
3313
|
+
markerEnd
|
|
3314
|
+
}) {
|
|
3315
|
+
const [edgePath, labelX, labelY] = getBezierPath({
|
|
3316
|
+
sourceX,
|
|
3317
|
+
sourceY,
|
|
3318
|
+
sourcePosition,
|
|
3319
|
+
targetX,
|
|
3320
|
+
targetY,
|
|
3321
|
+
targetPosition
|
|
3322
|
+
});
|
|
3323
|
+
const isJump = data?.edgeType === "onExit";
|
|
3324
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3325
|
+
/* @__PURE__ */ jsx(
|
|
3326
|
+
BaseEdge,
|
|
3327
|
+
{
|
|
3328
|
+
id,
|
|
3329
|
+
path: edgePath,
|
|
3330
|
+
markerEnd,
|
|
3331
|
+
style: {
|
|
3332
|
+
stroke: isJump ? "#f59e0b" : "var(--primary, #3b82f6)",
|
|
3333
|
+
strokeWidth: 1.5,
|
|
3334
|
+
strokeOpacity: 0.7,
|
|
3335
|
+
...style
|
|
3336
|
+
}
|
|
3337
|
+
}
|
|
3338
|
+
),
|
|
3339
|
+
label && /* @__PURE__ */ jsx(EdgeLabelRenderer, { children: /* @__PURE__ */ jsx(
|
|
3340
|
+
"div",
|
|
3341
|
+
{
|
|
3342
|
+
className: "fc-flow-edge-label",
|
|
3343
|
+
style: {
|
|
3344
|
+
transform: `translate(-50%, -50%) translate(${labelX}px, ${labelY}px)`,
|
|
3345
|
+
background: isJump ? "#f59e0b" : "var(--primary, #3b82f6)"
|
|
3346
|
+
},
|
|
3347
|
+
children: label
|
|
3348
|
+
}
|
|
3349
|
+
) })
|
|
3350
|
+
] });
|
|
3351
|
+
}
|
|
3352
|
+
var ConditionEdge = memo(ConditionEdgeInner);
|
|
3353
|
+
function PipelineEdgeInner({
|
|
3354
|
+
id,
|
|
3355
|
+
sourceX,
|
|
3356
|
+
sourceY,
|
|
3357
|
+
targetX,
|
|
3358
|
+
targetY,
|
|
3359
|
+
sourcePosition,
|
|
3360
|
+
targetPosition,
|
|
3361
|
+
markerEnd
|
|
3362
|
+
}) {
|
|
3363
|
+
const [edgePath] = getBezierPath({
|
|
3364
|
+
sourceX,
|
|
3365
|
+
sourceY,
|
|
3366
|
+
sourcePosition,
|
|
3367
|
+
targetX,
|
|
3368
|
+
targetY,
|
|
3369
|
+
targetPosition
|
|
3370
|
+
});
|
|
3371
|
+
return /* @__PURE__ */ jsx(
|
|
3372
|
+
BaseEdge,
|
|
3373
|
+
{
|
|
3374
|
+
id,
|
|
3375
|
+
path: edgePath,
|
|
3376
|
+
markerEnd,
|
|
3377
|
+
style: {
|
|
3378
|
+
stroke: "var(--muted-foreground, #71717a)",
|
|
3379
|
+
strokeWidth: 2,
|
|
3380
|
+
strokeOpacity: 0.4
|
|
3381
|
+
}
|
|
3382
|
+
}
|
|
3383
|
+
);
|
|
3384
|
+
}
|
|
3385
|
+
var PipelineEdge = memo(PipelineEdgeInner);
|
|
3386
|
+
var logicFlowEdgeTypes = {
|
|
3387
|
+
conditionEdge: ConditionEdge,
|
|
3388
|
+
pipelineEdge: PipelineEdge
|
|
3389
|
+
};
|
|
3390
|
+
function findQuestion2(schema, fieldId) {
|
|
3391
|
+
for (const section of schema.sections) {
|
|
3392
|
+
for (const q of section.questions) {
|
|
3393
|
+
if (q.id === fieldId) return q;
|
|
3394
|
+
}
|
|
3395
|
+
}
|
|
3396
|
+
return void 0;
|
|
3397
|
+
}
|
|
3398
|
+
function updateQuestionInSchema(schema, fieldId, updates) {
|
|
3399
|
+
return {
|
|
3400
|
+
...schema,
|
|
3401
|
+
sections: schema.sections.map((section) => ({
|
|
3402
|
+
...section,
|
|
3403
|
+
questions: section.questions.map(
|
|
3404
|
+
(q) => q.id === fieldId ? { ...q, ...updates } : q
|
|
3405
|
+
)
|
|
3406
|
+
}))
|
|
3407
|
+
};
|
|
3408
|
+
}
|
|
3409
|
+
function removeConditionForSource(showIf, sourceFieldId) {
|
|
3410
|
+
if (!showIf) return void 0;
|
|
3411
|
+
if (showIf.field === sourceFieldId) return void 0;
|
|
3412
|
+
if (showIf.field && showIf.field !== sourceFieldId) return showIf;
|
|
3413
|
+
if (showIf.conditions) {
|
|
3414
|
+
const filtered = showIf.conditions.map((c) => removeConditionForSource(c, sourceFieldId)).filter((c) => c !== void 0);
|
|
3415
|
+
if (filtered.length === 0) return void 0;
|
|
3416
|
+
if (filtered.length === 1) return filtered[0];
|
|
3417
|
+
return { ...showIf, conditions: filtered };
|
|
3418
|
+
}
|
|
3419
|
+
return showIf;
|
|
3420
|
+
}
|
|
3421
|
+
var defaultEdgeOptions = {
|
|
3422
|
+
markerEnd: {
|
|
3423
|
+
type: MarkerType.ArrowClosed,
|
|
3424
|
+
width: 16,
|
|
3425
|
+
height: 12
|
|
3426
|
+
}
|
|
3427
|
+
};
|
|
3428
|
+
function LogicFlowEditor({ schema, onChange, onClose }) {
|
|
3429
|
+
const noSections = schema.sections.length === 0;
|
|
3430
|
+
const flowGraph = useMemo(() => buildReactFlowGraph(schema), [schema]);
|
|
3431
|
+
const [nodes, setNodes, onNodesChange] = useNodesState(flowGraph.nodes);
|
|
3432
|
+
const [edges, setEdges, onEdgesChange] = useEdgesState(flowGraph.edges);
|
|
3433
|
+
const [selectedFieldId, setSelectedFieldId] = useState(null);
|
|
3434
|
+
const selectedQuestion = selectedFieldId ? findQuestion2(schema, selectedFieldId) : void 0;
|
|
3435
|
+
useEffect(() => {
|
|
3436
|
+
setNodes(flowGraph.nodes);
|
|
3437
|
+
setEdges(flowGraph.edges);
|
|
3438
|
+
}, [flowGraph, setNodes, setEdges]);
|
|
3439
|
+
const sectionIds = useMemo(() => {
|
|
3440
|
+
const ids = [];
|
|
3441
|
+
for (const section of schema.sections) {
|
|
3442
|
+
ids.push(section.id);
|
|
3443
|
+
}
|
|
3444
|
+
return ids;
|
|
3445
|
+
}, [schema]);
|
|
3446
|
+
const onNodeClick = useCallback(
|
|
3447
|
+
(_event, node) => {
|
|
3448
|
+
if (node.type === "fieldNode") {
|
|
3449
|
+
setSelectedFieldId(node.id);
|
|
3450
|
+
}
|
|
3451
|
+
},
|
|
3452
|
+
[]
|
|
3453
|
+
);
|
|
3454
|
+
const onConnect = useCallback(
|
|
3455
|
+
(connection) => {
|
|
3456
|
+
if (!connection.source || !connection.target) return;
|
|
3457
|
+
const targetQuestion = findQuestion2(schema, connection.target);
|
|
3458
|
+
if (!targetQuestion) return;
|
|
3459
|
+
const newCondition = {
|
|
3460
|
+
field: connection.source,
|
|
3461
|
+
operator: "exists"
|
|
3462
|
+
};
|
|
3463
|
+
let updatedShowIf;
|
|
3464
|
+
const existing = targetQuestion.showIf;
|
|
3465
|
+
if (!existing) {
|
|
3466
|
+
updatedShowIf = { combine: "AND", conditions: [newCondition] };
|
|
3467
|
+
} else {
|
|
3468
|
+
updatedShowIf = {
|
|
3469
|
+
...existing,
|
|
3470
|
+
conditions: [...existing.conditions ?? [], newCondition]
|
|
3471
|
+
};
|
|
3472
|
+
}
|
|
3473
|
+
const updatedSchema = updateQuestionInSchema(schema, connection.target, {
|
|
3474
|
+
showIf: updatedShowIf
|
|
3475
|
+
});
|
|
3476
|
+
onChange(updatedSchema);
|
|
3477
|
+
setSelectedFieldId(connection.target);
|
|
3478
|
+
},
|
|
3479
|
+
[schema, onChange]
|
|
3480
|
+
);
|
|
3481
|
+
const onEdgesDelete = useCallback(
|
|
3482
|
+
(deletedEdges) => {
|
|
3483
|
+
let updatedSchema = schema;
|
|
3484
|
+
for (const edge of deletedEdges) {
|
|
3485
|
+
const edgeData = edge.data;
|
|
3486
|
+
if (!edgeData) continue;
|
|
3487
|
+
const targetId = edge.target;
|
|
3488
|
+
const sourceId = edge.source;
|
|
3489
|
+
const edgeType = edgeData.edgeType;
|
|
3490
|
+
if (edgeType === "showIf") {
|
|
3491
|
+
const question = findQuestion2(updatedSchema, targetId);
|
|
3492
|
+
if (!question) continue;
|
|
3493
|
+
const updatedShowIf = removeConditionForSource(
|
|
3494
|
+
question.showIf,
|
|
3495
|
+
sourceId
|
|
3496
|
+
);
|
|
3497
|
+
updatedSchema = updateQuestionInSchema(updatedSchema, targetId, {
|
|
3498
|
+
showIf: updatedShowIf
|
|
3499
|
+
});
|
|
3500
|
+
}
|
|
3501
|
+
}
|
|
3502
|
+
onChange(updatedSchema);
|
|
3503
|
+
},
|
|
3504
|
+
[schema, onChange]
|
|
3505
|
+
);
|
|
3506
|
+
const handleConditionUpdate = useCallback(
|
|
3507
|
+
(updates) => {
|
|
3508
|
+
if (!selectedFieldId) return;
|
|
3509
|
+
const updatedSchema = updateQuestionInSchema(schema, selectedFieldId, updates);
|
|
3510
|
+
onChange(updatedSchema);
|
|
3511
|
+
},
|
|
3512
|
+
[schema, selectedFieldId, onChange]
|
|
3513
|
+
);
|
|
3514
|
+
const showIfCount = flowGraph.edges.filter(
|
|
3515
|
+
(e) => e.data?.edgeType === "showIf"
|
|
3516
|
+
).length;
|
|
3517
|
+
const jumpCount = flowGraph.edges.filter(
|
|
3518
|
+
(e) => e.data?.edgeType === "onExit"
|
|
3519
|
+
).length;
|
|
3520
|
+
return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-50 flex flex-col bg-background/95 backdrop-blur-sm", children: [
|
|
3521
|
+
/* @__PURE__ */ jsxs("div", { className: "h-12 shrink-0 flex items-center justify-between px-4 border-b border-border bg-card", children: [
|
|
3522
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
3523
|
+
/* @__PURE__ */ jsx(GitBranch, { size: 16, className: "text-primary" }),
|
|
3524
|
+
/* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold", children: "Logic Flow" }),
|
|
3525
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
3526
|
+
showIfCount,
|
|
3527
|
+
" condition",
|
|
3528
|
+
showIfCount !== 1 ? "s" : "",
|
|
3529
|
+
jumpCount > 0 && ` \xB7 ${jumpCount} jump${jumpCount !== 1 ? "s" : ""}`,
|
|
3530
|
+
" \xB7 ",
|
|
3531
|
+
sectionIds.length,
|
|
3532
|
+
" section",
|
|
3533
|
+
sectionIds.length !== 1 ? "s" : ""
|
|
3534
|
+
] })
|
|
3535
|
+
] }),
|
|
3536
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
3537
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] text-muted-foreground mr-2", children: "Drag between nodes to create conditions \xB7 Select edges and press Delete to remove" }),
|
|
3538
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", onClick: onClose, title: "Close logic flow", children: /* @__PURE__ */ jsx(X, { size: 16, strokeWidth: 1.75 }) })
|
|
3539
|
+
] })
|
|
3540
|
+
] }),
|
|
3541
|
+
noSections ? /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-center text-muted-foreground text-sm", children: /* @__PURE__ */ jsxs("div", { className: "text-center space-y-2", children: [
|
|
3542
|
+
/* @__PURE__ */ jsx(GitBranch, { size: 32, className: "mx-auto opacity-40" }),
|
|
3543
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium", children: "No sections found" }),
|
|
3544
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs max-w-xs", children: "Add sections and fields to your form to see the logic flow pipeline." })
|
|
3545
|
+
] }) }) : /* @__PURE__ */ jsxs("div", { className: "flex-1 flex", children: [
|
|
3546
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxs(
|
|
3547
|
+
ReactFlow,
|
|
3548
|
+
{
|
|
3549
|
+
nodes,
|
|
3550
|
+
edges,
|
|
3551
|
+
onNodesChange,
|
|
3552
|
+
onEdgesChange,
|
|
3553
|
+
onNodeClick,
|
|
3554
|
+
onConnect,
|
|
3555
|
+
onEdgesDelete,
|
|
3556
|
+
nodeTypes: logicFlowNodeTypes,
|
|
3557
|
+
edgeTypes: logicFlowEdgeTypes,
|
|
3558
|
+
defaultEdgeOptions,
|
|
3559
|
+
fitView: true,
|
|
3560
|
+
fitViewOptions: { padding: 0.2 },
|
|
3561
|
+
deleteKeyCode: ["Backspace", "Delete"],
|
|
3562
|
+
proOptions: { hideAttribution: true },
|
|
3563
|
+
children: [
|
|
3564
|
+
/* @__PURE__ */ jsx(Background, { gap: 20, size: 1 }),
|
|
3565
|
+
/* @__PURE__ */ jsx(Controls, { showInteractive: false }),
|
|
3566
|
+
/* @__PURE__ */ jsx(
|
|
3567
|
+
MiniMap,
|
|
3568
|
+
{
|
|
3569
|
+
nodeColor: (node) => {
|
|
3570
|
+
const d = node.data;
|
|
3571
|
+
const idx = d.colorIndex ?? 0;
|
|
3572
|
+
return SECTION_COLORS[idx % SECTION_COLORS.length];
|
|
3573
|
+
},
|
|
3574
|
+
maskColor: "rgba(0, 0, 0, 0.3)"
|
|
3575
|
+
}
|
|
3576
|
+
)
|
|
3577
|
+
]
|
|
3578
|
+
}
|
|
3579
|
+
) }),
|
|
3580
|
+
selectedFieldId && selectedQuestion && /* @__PURE__ */ jsxs("div", { className: "w-72 border-l border-border bg-card overflow-auto", children: [
|
|
3581
|
+
/* @__PURE__ */ jsxs("div", { className: "px-3 py-3 border-b border-border flex items-center justify-between", children: [
|
|
3582
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
3583
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-semibold truncate", children: selectedQuestion.label || selectedQuestion.id }),
|
|
3584
|
+
/* @__PURE__ */ jsx("p", { className: "text-[10px] text-muted-foreground", children: selectedQuestion.type })
|
|
3585
|
+
] }),
|
|
3586
|
+
/* @__PURE__ */ jsx(
|
|
3587
|
+
Button,
|
|
3588
|
+
{
|
|
3589
|
+
variant: "ghost",
|
|
3590
|
+
size: "icon-xs",
|
|
3591
|
+
onClick: () => setSelectedFieldId(null),
|
|
3592
|
+
title: "Close panel",
|
|
3593
|
+
children: /* @__PURE__ */ jsx(X, { size: 14, strokeWidth: 1.75 })
|
|
3594
|
+
}
|
|
3595
|
+
)
|
|
3596
|
+
] }),
|
|
3597
|
+
/* @__PURE__ */ jsx("div", { className: "px-3 py-3", children: /* @__PURE__ */ jsx(
|
|
3598
|
+
ConditionEditor,
|
|
3599
|
+
{
|
|
3600
|
+
question: selectedQuestion,
|
|
3601
|
+
schema,
|
|
3602
|
+
onUpdate: handleConditionUpdate
|
|
3603
|
+
}
|
|
3604
|
+
) })
|
|
3605
|
+
] })
|
|
3606
|
+
] }),
|
|
3607
|
+
/* @__PURE__ */ jsxs("div", { className: "shrink-0 px-4 py-2 border-t border-border bg-card flex items-center gap-4 text-xs text-muted-foreground flex-wrap", children: [
|
|
3608
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
3609
|
+
/* @__PURE__ */ jsx("div", { className: "w-5 h-0.5 rounded", style: { background: "var(--muted-foreground)", opacity: 0.4 } }),
|
|
3610
|
+
/* @__PURE__ */ jsx("span", { children: "flow" })
|
|
3611
|
+
] }),
|
|
3612
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
3613
|
+
/* @__PURE__ */ jsx("div", { className: "w-5 h-0.5 bg-primary rounded" }),
|
|
3614
|
+
/* @__PURE__ */ jsx("span", { children: "showIf" })
|
|
3615
|
+
] }),
|
|
3616
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
3617
|
+
/* @__PURE__ */ jsx("div", { className: "w-5 h-0.5 rounded", style: { background: "#f59e0b" } }),
|
|
3618
|
+
/* @__PURE__ */ jsx("span", { children: "jump" })
|
|
3619
|
+
] }),
|
|
3620
|
+
sectionIds.map((id, i) => {
|
|
3621
|
+
const section = schema.sections.find((s) => s.id === id);
|
|
3622
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
3623
|
+
/* @__PURE__ */ jsx("div", { className: "w-3 h-3 rounded-sm", style: { background: SECTION_COLORS[i % SECTION_COLORS.length] } }),
|
|
3624
|
+
/* @__PURE__ */ jsx("span", { children: section?.title || id })
|
|
3625
|
+
] }, id);
|
|
3626
|
+
})
|
|
3627
|
+
] })
|
|
3628
|
+
] });
|
|
3629
|
+
}
|
|
3630
|
+
function TemplateGallery({ templates, onSelect, onClose }) {
|
|
3631
|
+
const [search, setSearch] = useState("");
|
|
3632
|
+
const [activeCategory, setActiveCategory] = useState("all");
|
|
3633
|
+
const [confirmTemplate, setConfirmTemplate] = useState(null);
|
|
3634
|
+
const categories = useMemo(() => {
|
|
3635
|
+
const cats = /* @__PURE__ */ new Set();
|
|
3636
|
+
for (const t of templates) cats.add(t.meta.category);
|
|
3637
|
+
return ["all", ...Array.from(cats)];
|
|
3638
|
+
}, [templates]);
|
|
3639
|
+
const filtered = useMemo(() => {
|
|
3640
|
+
return templates.filter((t) => {
|
|
3641
|
+
const matchesCategory = activeCategory === "all" || t.meta.category === activeCategory;
|
|
3642
|
+
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()));
|
|
3643
|
+
return matchesCategory && matchesSearch;
|
|
3644
|
+
});
|
|
3645
|
+
}, [templates, activeCategory, search]);
|
|
3646
|
+
const handleConfirm = () => {
|
|
3647
|
+
if (confirmTemplate) {
|
|
3648
|
+
onSelect(confirmTemplate);
|
|
3649
|
+
setConfirmTemplate(null);
|
|
3650
|
+
onClose();
|
|
3651
|
+
}
|
|
3652
|
+
};
|
|
3653
|
+
return /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 backdrop-blur-sm", children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-3xl max-h-[85vh] mx-4 bg-card border border-border rounded-lg shadow-xl flex flex-col overflow-hidden", children: [
|
|
3654
|
+
/* @__PURE__ */ jsxs("div", { className: "shrink-0 flex items-center justify-between px-4 py-3 border-b border-border", children: [
|
|
3655
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3656
|
+
/* @__PURE__ */ jsx(LayoutTemplate, { size: 18, className: "text-primary", strokeWidth: 1.75 }),
|
|
3657
|
+
/* @__PURE__ */ jsx("h2", { className: "text-sm font-semibold", children: "Template Gallery" }),
|
|
3658
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
3659
|
+
"(",
|
|
3660
|
+
templates.length,
|
|
3661
|
+
" templates)"
|
|
3662
|
+
] })
|
|
3663
|
+
] }),
|
|
3664
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", onClick: onClose, title: "Close", children: /* @__PURE__ */ jsx(X, { size: 16, strokeWidth: 1.75 }) })
|
|
3665
|
+
] }),
|
|
3666
|
+
/* @__PURE__ */ jsxs("div", { className: "shrink-0 px-4 py-2 space-y-2 border-b border-border", children: [
|
|
3667
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
3668
|
+
/* @__PURE__ */ jsx(Search, { size: 14, className: "absolute left-2.5 top-1/2 -translate-y-1/2 text-muted-foreground", strokeWidth: 1.75 }),
|
|
3669
|
+
/* @__PURE__ */ jsx(
|
|
3670
|
+
"input",
|
|
3671
|
+
{
|
|
3672
|
+
type: "text",
|
|
3673
|
+
placeholder: "Search templates...",
|
|
3674
|
+
value: search,
|
|
3675
|
+
onChange: (e) => setSearch(e.target.value),
|
|
3676
|
+
className: "w-full pl-8 pr-3 py-1.5 text-sm bg-background border border-border rounded-md text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-primary"
|
|
3677
|
+
}
|
|
3678
|
+
)
|
|
3679
|
+
] }),
|
|
3680
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1 overflow-x-auto pb-0.5", children: categories.map((cat) => /* @__PURE__ */ jsx(
|
|
3681
|
+
"button",
|
|
3682
|
+
{
|
|
3683
|
+
type: "button",
|
|
3684
|
+
onClick: () => setActiveCategory(cat),
|
|
3685
|
+
className: `shrink-0 px-2.5 py-1 rounded-md text-xs font-medium transition-colors ${activeCategory === cat ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground hover:text-foreground"}`,
|
|
3686
|
+
children: cat === "all" ? "All" : cat.charAt(0).toUpperCase() + cat.slice(1)
|
|
3687
|
+
},
|
|
3688
|
+
cat
|
|
3689
|
+
)) })
|
|
3690
|
+
] }),
|
|
3691
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto p-4", children: filtered.length === 0 ? /* @__PURE__ */ jsx("div", { className: "flex flex-col items-center justify-center h-40 text-muted-foreground text-sm", children: /* @__PURE__ */ jsx("p", { children: "No templates match your search." }) }) : /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-3", children: filtered.map((template) => /* @__PURE__ */ jsxs(
|
|
3692
|
+
"button",
|
|
3693
|
+
{
|
|
3694
|
+
type: "button",
|
|
3695
|
+
onClick: () => setConfirmTemplate(template),
|
|
3696
|
+
className: "text-left p-3 rounded-lg border border-border bg-background hover:border-primary/50 hover:bg-primary/5 transition-colors group",
|
|
3697
|
+
children: [
|
|
3698
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2 mb-1.5", children: [
|
|
3699
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-medium text-foreground group-hover:text-primary transition-colors", children: template.meta.name }),
|
|
3700
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 px-1.5 py-0.5 rounded text-[10px] font-medium bg-muted text-muted-foreground", children: template.meta.category })
|
|
3701
|
+
] }),
|
|
3702
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mb-2 line-clamp-2", children: template.meta.description }),
|
|
3703
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 text-xs text-muted-foreground", children: [
|
|
3704
|
+
/* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
|
|
3705
|
+
/* @__PURE__ */ jsx(FileText, { size: 11, strokeWidth: 1.75 }),
|
|
3706
|
+
template.meta.fieldCount,
|
|
3707
|
+
" field",
|
|
3708
|
+
template.meta.fieldCount !== 1 ? "s" : ""
|
|
3709
|
+
] }),
|
|
3710
|
+
/* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
|
|
3711
|
+
/* @__PURE__ */ jsx(Layers, { size: 11, strokeWidth: 1.75 }),
|
|
3712
|
+
template.meta.sectionCount,
|
|
3713
|
+
" section",
|
|
3714
|
+
template.meta.sectionCount !== 1 ? "s" : ""
|
|
3715
|
+
] })
|
|
3716
|
+
] })
|
|
3717
|
+
]
|
|
3718
|
+
},
|
|
3719
|
+
template.meta.id
|
|
3720
|
+
)) }) }),
|
|
3721
|
+
confirmTemplate && /* @__PURE__ */ jsxs("div", { className: "shrink-0 px-4 py-3 border-t border-border bg-muted/50 flex items-center justify-between gap-3", children: [
|
|
3722
|
+
/* @__PURE__ */ jsxs("div", { className: "text-sm", children: [
|
|
3723
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Use " }),
|
|
3724
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: confirmTemplate.meta.name }),
|
|
3725
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "? This will replace the current form." })
|
|
3726
|
+
] }),
|
|
3727
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
3728
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: () => setConfirmTemplate(null), children: "Cancel" }),
|
|
3729
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", onClick: handleConfirm, children: "Use Template" })
|
|
3730
|
+
] })
|
|
3731
|
+
] })
|
|
3732
|
+
] }) });
|
|
3733
|
+
}
|
|
3734
|
+
function useDebouncedValidation(delayMs = 500) {
|
|
3735
|
+
const [errors, setErrors] = useState([]);
|
|
3736
|
+
const timerRef = useRef(null);
|
|
3737
|
+
const validate = useCallback(
|
|
3738
|
+
(text) => {
|
|
3739
|
+
if (timerRef.current) {
|
|
3740
|
+
clearTimeout(timerRef.current);
|
|
3741
|
+
}
|
|
3742
|
+
timerRef.current = setTimeout(() => {
|
|
3743
|
+
const result = [];
|
|
3744
|
+
let parsed;
|
|
3745
|
+
try {
|
|
3746
|
+
parsed = JSON.parse(text);
|
|
3747
|
+
} catch (err) {
|
|
3748
|
+
if (err instanceof SyntaxError) {
|
|
3749
|
+
const posMatch = err.message.match(/position\s+(\d+)/i);
|
|
3750
|
+
let line = 1;
|
|
3751
|
+
let column = 1;
|
|
3752
|
+
if (posMatch) {
|
|
3753
|
+
const pos = parseInt(posMatch[1], 10);
|
|
3754
|
+
const upToPos = text.slice(0, pos);
|
|
3755
|
+
line = (upToPos.match(/\n/g) || []).length + 1;
|
|
3756
|
+
column = pos - upToPos.lastIndexOf("\n");
|
|
3757
|
+
}
|
|
3758
|
+
result.push({ message: err.message, line, column, endLine: line, endColumn: column + 1 });
|
|
3759
|
+
} else {
|
|
3760
|
+
result.push({ message: "Invalid JSON" });
|
|
3761
|
+
}
|
|
3762
|
+
setErrors(result);
|
|
3763
|
+
return;
|
|
3764
|
+
}
|
|
3765
|
+
try {
|
|
3766
|
+
validateSchema(parsed);
|
|
3767
|
+
} catch (err) {
|
|
3768
|
+
if (err instanceof FormEngineSchemaError) {
|
|
3769
|
+
for (const issue of err.issues) {
|
|
3770
|
+
result.push({
|
|
3771
|
+
message: issue.message,
|
|
3772
|
+
path: issue.path?.join(".")
|
|
3773
|
+
});
|
|
3774
|
+
}
|
|
3775
|
+
} else if (err instanceof Error) {
|
|
3776
|
+
result.push({ message: err.message });
|
|
3777
|
+
}
|
|
3778
|
+
}
|
|
3779
|
+
setErrors(result);
|
|
3780
|
+
}, delayMs);
|
|
3781
|
+
},
|
|
3782
|
+
[delayMs]
|
|
3783
|
+
);
|
|
3784
|
+
return { errors, validate };
|
|
3785
|
+
}
|
|
2788
3786
|
var ThemeCtx = createContext({});
|
|
2789
3787
|
function useBuilderTheme() {
|
|
2790
3788
|
return useContext(ThemeCtx);
|
|
@@ -2857,7 +3855,16 @@ var FormBuilderErrorBoundary = class extends Component {
|
|
|
2857
3855
|
}
|
|
2858
3856
|
};
|
|
2859
3857
|
function FormBuilderCore(props) {
|
|
2860
|
-
const { initialSchema = DEFAULT_SCHEMA, onChange, onSave, height = "100vh", theme, className, toolbarExtra, questionTypes, palette } = props;
|
|
3858
|
+
const { initialSchema = DEFAULT_SCHEMA, onChange, onSave, height = "100vh", theme, className, toolbarExtra, questionTypes, palette, preview, templates, schemaUrl } = props;
|
|
3859
|
+
const [viewMode, setViewMode] = useState("design");
|
|
3860
|
+
const [jsonText, setJsonText] = useState("");
|
|
3861
|
+
const [jsonSwitchError, setJsonSwitchError] = useState(null);
|
|
3862
|
+
const [showLogicMap, setShowLogicMap] = useState(false);
|
|
3863
|
+
const [showTemplateGallery, setShowTemplateGallery] = useState(false);
|
|
3864
|
+
const [saveValidationErrors, setSaveValidationErrors] = useState(null);
|
|
3865
|
+
const [schemaUrlLoading, setSchemaUrlLoading] = useState(!!schemaUrl);
|
|
3866
|
+
const [schemaUrlError, setSchemaUrlError] = useState(null);
|
|
3867
|
+
const { errors: jsonErrors, validate: validateJson } = useDebouncedValidation(400);
|
|
2861
3868
|
const mergedQuestionTypes = questionTypes ? { ...QUESTION_TYPE_INFO, ...questionTypes } : QUESTION_TYPE_INFO;
|
|
2862
3869
|
const builderState = useBuilderState(initialSchema);
|
|
2863
3870
|
const dragDrop = useDragDrop(builderState);
|
|
@@ -2873,15 +3880,54 @@ function FormBuilderCore(props) {
|
|
|
2873
3880
|
setMobilePanel("none");
|
|
2874
3881
|
}
|
|
2875
3882
|
}, [dragDrop.activeDragItem]);
|
|
3883
|
+
useEffect(() => {
|
|
3884
|
+
if (!schemaUrl) return;
|
|
3885
|
+
let cancelled = false;
|
|
3886
|
+
setSchemaUrlLoading(true);
|
|
3887
|
+
setSchemaUrlError(null);
|
|
3888
|
+
fetch(schemaUrl).then((res) => {
|
|
3889
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
3890
|
+
return res.json();
|
|
3891
|
+
}).then((json) => {
|
|
3892
|
+
if (cancelled) return;
|
|
3893
|
+
try {
|
|
3894
|
+
const validated = validateSchema(json);
|
|
3895
|
+
builderState.resetSchema(validated);
|
|
3896
|
+
} catch (err) {
|
|
3897
|
+
if (err instanceof FormEngineSchemaError) {
|
|
3898
|
+
setSchemaUrlError(`Invalid schema: ${err.issues[0]?.message ?? "validation failed"}`);
|
|
3899
|
+
} else {
|
|
3900
|
+
setSchemaUrlError(err.message);
|
|
3901
|
+
}
|
|
3902
|
+
}
|
|
3903
|
+
setSchemaUrlLoading(false);
|
|
3904
|
+
}).catch((err) => {
|
|
3905
|
+
if (cancelled) return;
|
|
3906
|
+
setSchemaUrlError(err.message ?? "Failed to fetch schema");
|
|
3907
|
+
setSchemaUrlLoading(false);
|
|
3908
|
+
});
|
|
3909
|
+
return () => {
|
|
3910
|
+
cancelled = true;
|
|
3911
|
+
};
|
|
3912
|
+
}, [schemaUrl]);
|
|
2876
3913
|
useEffect(() => {
|
|
2877
3914
|
if (onChange && builderState.isDirty) {
|
|
2878
3915
|
onChange(builderState.schema);
|
|
2879
3916
|
}
|
|
2880
3917
|
}, [builderState.schema, builderState.isDirty, onChange]);
|
|
2881
3918
|
const handleSave = useCallback(() => {
|
|
2882
|
-
if (onSave)
|
|
3919
|
+
if (!onSave) return;
|
|
3920
|
+
try {
|
|
3921
|
+
validateSchema(builderState.schema);
|
|
3922
|
+
setSaveValidationErrors(null);
|
|
2883
3923
|
onSave(builderState.schema);
|
|
2884
3924
|
builderState.markClean();
|
|
3925
|
+
} catch (err) {
|
|
3926
|
+
if (err instanceof FormEngineSchemaError) {
|
|
3927
|
+
setSaveValidationErrors(err.issues.map((issue) => issue.message));
|
|
3928
|
+
} else {
|
|
3929
|
+
setSaveValidationErrors([err.message ?? "Unknown validation error"]);
|
|
3930
|
+
}
|
|
2885
3931
|
}
|
|
2886
3932
|
}, [onSave, builderState]);
|
|
2887
3933
|
const handleExport = useCallback(() => {
|
|
@@ -2924,6 +3970,32 @@ ${details}`);
|
|
|
2924
3970
|
},
|
|
2925
3971
|
[builderState]
|
|
2926
3972
|
);
|
|
3973
|
+
const handleViewModeChange = useCallback(
|
|
3974
|
+
(newMode) => {
|
|
3975
|
+
setJsonSwitchError(null);
|
|
3976
|
+
if (viewMode === "json" && newMode !== "json") {
|
|
3977
|
+
try {
|
|
3978
|
+
const parsed = JSON.parse(jsonText);
|
|
3979
|
+
const validated = validateSchema(parsed);
|
|
3980
|
+
builderState.resetSchema(validated);
|
|
3981
|
+
} catch (err) {
|
|
3982
|
+
if (err instanceof SyntaxError) {
|
|
3983
|
+
setJsonSwitchError("Cannot switch: JSON has syntax errors");
|
|
3984
|
+
} else if (err instanceof FormEngineSchemaError) {
|
|
3985
|
+
setJsonSwitchError(`Cannot switch: ${err.issues[0]?.message ?? "Invalid schema"}`);
|
|
3986
|
+
} else {
|
|
3987
|
+
setJsonSwitchError("Cannot switch: Invalid schema");
|
|
3988
|
+
}
|
|
3989
|
+
return;
|
|
3990
|
+
}
|
|
3991
|
+
}
|
|
3992
|
+
if (newMode === "json") {
|
|
3993
|
+
setJsonText(JSON.stringify(builderState.schema, null, 2));
|
|
3994
|
+
}
|
|
3995
|
+
setViewMode(newMode);
|
|
3996
|
+
},
|
|
3997
|
+
[viewMode, jsonText, builderState]
|
|
3998
|
+
);
|
|
2927
3999
|
const handleKeyDown = useCallback(
|
|
2928
4000
|
(e) => {
|
|
2929
4001
|
const mod = e.metaKey || e.ctrlKey;
|
|
@@ -3025,8 +4097,74 @@ ${details}`);
|
|
|
3025
4097
|
/* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "mx-2 h-5" }),
|
|
3026
4098
|
builderState.isDirty && /* @__PURE__ */ jsx("span", { className: "text-xs text-primary", role: "status", children: "Unsaved changes" })
|
|
3027
4099
|
] }),
|
|
3028
|
-
/* @__PURE__ */
|
|
4100
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-2", children: [
|
|
4101
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 bg-muted rounded-md p-0.5", children: [
|
|
4102
|
+
/* @__PURE__ */ jsxs(
|
|
4103
|
+
Button,
|
|
4104
|
+
{
|
|
4105
|
+
variant: viewMode === "design" ? "secondary" : "ghost",
|
|
4106
|
+
size: "sm",
|
|
4107
|
+
onClick: () => handleViewModeChange("design"),
|
|
4108
|
+
className: "gap-1.5 h-7 px-2.5 text-xs",
|
|
4109
|
+
children: [
|
|
4110
|
+
/* @__PURE__ */ jsx(PencilRuler, { size: 13, strokeWidth: 1.75 }),
|
|
4111
|
+
"Design"
|
|
4112
|
+
]
|
|
4113
|
+
}
|
|
4114
|
+
),
|
|
4115
|
+
/* @__PURE__ */ jsxs(
|
|
4116
|
+
Button,
|
|
4117
|
+
{
|
|
4118
|
+
variant: viewMode === "preview" ? "secondary" : "ghost",
|
|
4119
|
+
size: "sm",
|
|
4120
|
+
onClick: () => handleViewModeChange("preview"),
|
|
4121
|
+
className: "gap-1.5 h-7 px-2.5 text-xs",
|
|
4122
|
+
children: [
|
|
4123
|
+
/* @__PURE__ */ jsx(Eye, { size: 13, strokeWidth: 1.75 }),
|
|
4124
|
+
"Preview"
|
|
4125
|
+
]
|
|
4126
|
+
}
|
|
4127
|
+
),
|
|
4128
|
+
/* @__PURE__ */ jsxs(
|
|
4129
|
+
Button,
|
|
4130
|
+
{
|
|
4131
|
+
variant: viewMode === "json" ? "secondary" : "ghost",
|
|
4132
|
+
size: "sm",
|
|
4133
|
+
onClick: () => handleViewModeChange("json"),
|
|
4134
|
+
className: "gap-1.5 h-7 px-2.5 text-xs",
|
|
4135
|
+
children: [
|
|
4136
|
+
/* @__PURE__ */ jsx(Code, { size: 13, strokeWidth: 1.75 }),
|
|
4137
|
+
"JSON"
|
|
4138
|
+
]
|
|
4139
|
+
}
|
|
4140
|
+
)
|
|
4141
|
+
] }),
|
|
4142
|
+
toolbarExtra
|
|
4143
|
+
] }),
|
|
3029
4144
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-1.5", children: [
|
|
4145
|
+
templates && templates.length > 0 && /* @__PURE__ */ jsx(
|
|
4146
|
+
Button,
|
|
4147
|
+
{
|
|
4148
|
+
variant: "ghost",
|
|
4149
|
+
size: "icon-sm",
|
|
4150
|
+
onClick: () => setShowTemplateGallery(true),
|
|
4151
|
+
title: "Browse templates",
|
|
4152
|
+
"aria-label": "Template gallery",
|
|
4153
|
+
children: /* @__PURE__ */ jsx(LayoutTemplate, { size: 15, strokeWidth: 1.75 })
|
|
4154
|
+
}
|
|
4155
|
+
),
|
|
4156
|
+
/* @__PURE__ */ jsx(
|
|
4157
|
+
Button,
|
|
4158
|
+
{
|
|
4159
|
+
variant: "ghost",
|
|
4160
|
+
size: "icon-sm",
|
|
4161
|
+
onClick: () => setShowLogicMap(true),
|
|
4162
|
+
title: "View branching logic map",
|
|
4163
|
+
"aria-label": "Logic map",
|
|
4164
|
+
children: /* @__PURE__ */ jsx(GitBranch, { size: 15, strokeWidth: 1.75 })
|
|
4165
|
+
}
|
|
4166
|
+
),
|
|
4167
|
+
/* @__PURE__ */ jsx(Separator, { orientation: "vertical", className: "mx-1 h-5" }),
|
|
3030
4168
|
/* @__PURE__ */ jsx(
|
|
3031
4169
|
Button,
|
|
3032
4170
|
{
|
|
@@ -3070,6 +4208,47 @@ ${details}`);
|
|
|
3070
4208
|
}
|
|
3071
4209
|
) }),
|
|
3072
4210
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-1", children: [
|
|
4211
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-0.5 bg-muted rounded-md p-0.5", children: [
|
|
4212
|
+
/* @__PURE__ */ jsxs(
|
|
4213
|
+
Button,
|
|
4214
|
+
{
|
|
4215
|
+
variant: viewMode === "design" ? "secondary" : "ghost",
|
|
4216
|
+
size: "sm",
|
|
4217
|
+
onClick: () => handleViewModeChange("design"),
|
|
4218
|
+
className: "gap-1 h-7 px-2 text-xs",
|
|
4219
|
+
children: [
|
|
4220
|
+
/* @__PURE__ */ jsx(PencilRuler, { size: 12, strokeWidth: 1.75 }),
|
|
4221
|
+
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Design" })
|
|
4222
|
+
]
|
|
4223
|
+
}
|
|
4224
|
+
),
|
|
4225
|
+
/* @__PURE__ */ jsxs(
|
|
4226
|
+
Button,
|
|
4227
|
+
{
|
|
4228
|
+
variant: viewMode === "preview" ? "secondary" : "ghost",
|
|
4229
|
+
size: "sm",
|
|
4230
|
+
onClick: () => handleViewModeChange("preview"),
|
|
4231
|
+
className: "gap-1 h-7 px-2 text-xs",
|
|
4232
|
+
children: [
|
|
4233
|
+
/* @__PURE__ */ jsx(Eye, { size: 12, strokeWidth: 1.75 }),
|
|
4234
|
+
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "Preview" })
|
|
4235
|
+
]
|
|
4236
|
+
}
|
|
4237
|
+
),
|
|
4238
|
+
/* @__PURE__ */ jsxs(
|
|
4239
|
+
Button,
|
|
4240
|
+
{
|
|
4241
|
+
variant: viewMode === "json" ? "secondary" : "ghost",
|
|
4242
|
+
size: "sm",
|
|
4243
|
+
onClick: () => handleViewModeChange("json"),
|
|
4244
|
+
className: "gap-1 h-7 px-2 text-xs",
|
|
4245
|
+
children: [
|
|
4246
|
+
/* @__PURE__ */ jsx(Code, { size: 12, strokeWidth: 1.75 }),
|
|
4247
|
+
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: "JSON" })
|
|
4248
|
+
]
|
|
4249
|
+
}
|
|
4250
|
+
)
|
|
4251
|
+
] }),
|
|
3073
4252
|
toolbarExtra,
|
|
3074
4253
|
/* @__PURE__ */ jsxs(Button, { onClick: handleSave, size: "sm", className: "border-0 shadow-sm fcb-glow ml-1", "aria-label": "Save form", children: [
|
|
3075
4254
|
/* @__PURE__ */ jsx(Save, { size: 14, strokeWidth: 2 }),
|
|
@@ -3158,7 +4337,50 @@ ${details}`);
|
|
|
3158
4337
|
"aria-hidden": "true"
|
|
3159
4338
|
}
|
|
3160
4339
|
),
|
|
3161
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
4340
|
+
jsonSwitchError && /* @__PURE__ */ jsxs("div", { className: "shrink-0 px-4 py-2 bg-destructive/10 border-b border-destructive/20 text-destructive text-xs flex items-center justify-between", children: [
|
|
4341
|
+
/* @__PURE__ */ jsx("span", { children: jsonSwitchError }),
|
|
4342
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => setJsonSwitchError(null), className: "ml-2 hover:underline", children: "Dismiss" })
|
|
4343
|
+
] }),
|
|
4344
|
+
saveValidationErrors && saveValidationErrors.length > 0 && /* @__PURE__ */ jsxs("div", { className: "shrink-0 px-4 py-2 bg-destructive/10 border-b border-destructive/20 text-xs", children: [
|
|
4345
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-1", children: [
|
|
4346
|
+
/* @__PURE__ */ jsxs("span", { className: "font-semibold text-destructive", children: [
|
|
4347
|
+
"Schema validation failed (",
|
|
4348
|
+
saveValidationErrors.length,
|
|
4349
|
+
" issue",
|
|
4350
|
+
saveValidationErrors.length !== 1 ? "s" : "",
|
|
4351
|
+
")"
|
|
4352
|
+
] }),
|
|
4353
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => setSaveValidationErrors(null), className: "text-destructive hover:underline", children: "Dismiss" })
|
|
4354
|
+
] }),
|
|
4355
|
+
/* @__PURE__ */ jsxs("ul", { className: "list-disc pl-4 text-destructive/80 space-y-0.5", children: [
|
|
4356
|
+
saveValidationErrors.slice(0, 10).map((msg, i) => /* @__PURE__ */ jsx("li", { children: msg }, i)),
|
|
4357
|
+
saveValidationErrors.length > 10 && /* @__PURE__ */ jsxs("li", { children: [
|
|
4358
|
+
"...and ",
|
|
4359
|
+
saveValidationErrors.length - 10,
|
|
4360
|
+
" more"
|
|
4361
|
+
] })
|
|
4362
|
+
] })
|
|
4363
|
+
] }),
|
|
4364
|
+
schemaUrlLoading && /* @__PURE__ */ jsxs("div", { className: "shrink-0 px-4 py-2 border-b border-border bg-muted/50 text-xs text-muted-foreground flex items-center gap-2", children: [
|
|
4365
|
+
/* @__PURE__ */ jsx("span", { className: "inline-block w-3 h-3 border-2 border-primary border-t-transparent rounded-full animate-spin" }),
|
|
4366
|
+
"Loading schema from URL..."
|
|
4367
|
+
] }),
|
|
4368
|
+
schemaUrlError && /* @__PURE__ */ jsxs("div", { className: "shrink-0 px-4 py-2 bg-destructive/10 border-b border-destructive/20 text-destructive text-xs flex items-center justify-between", children: [
|
|
4369
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
4370
|
+
"Failed to load schema: ",
|
|
4371
|
+
schemaUrlError
|
|
4372
|
+
] }),
|
|
4373
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => setSchemaUrlError(null), className: "ml-2 hover:underline", children: "Dismiss" })
|
|
4374
|
+
] }),
|
|
4375
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 flex overflow-hidden relative", children: viewMode === "json" ? /* @__PURE__ */ jsx(
|
|
4376
|
+
JsonEditorPanel,
|
|
4377
|
+
{
|
|
4378
|
+
value: jsonText,
|
|
4379
|
+
onChange: setJsonText,
|
|
4380
|
+
errors: jsonErrors,
|
|
4381
|
+
onValidate: validateJson
|
|
4382
|
+
}
|
|
4383
|
+
) : viewMode === "preview" ? /* @__PURE__ */ jsx(FormPreviewPanel, { schema: builderState.schema, preview }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3162
4384
|
/* @__PURE__ */ jsx("div", { className: "hidden md:flex", children: /* @__PURE__ */ jsx(QuestionPalette, { questionTypes: mergedQuestionTypes, palette }) }),
|
|
3163
4385
|
/* @__PURE__ */ jsx(FormCanvas, { builderState }),
|
|
3164
4386
|
/* @__PURE__ */ jsx("div", { className: "hidden md:flex", children: /* @__PURE__ */ jsx(PropertiesPanel, { builderState }) }),
|
|
@@ -3172,11 +4394,27 @@ ${details}`);
|
|
|
3172
4394
|
"aria-hidden": "true"
|
|
3173
4395
|
}
|
|
3174
4396
|
)
|
|
3175
|
-
] })
|
|
4397
|
+
] }) })
|
|
3176
4398
|
]
|
|
3177
4399
|
}
|
|
3178
4400
|
),
|
|
3179
|
-
/* @__PURE__ */ jsx(DragOverlay, { dropAnimation: null, children: dragDrop.activeDragItem && /* @__PURE__ */ jsx(DragOverlayContent, { item: dragDrop.activeDragItem, schema: builderState.schema, questionTypes: mergedQuestionTypes }) })
|
|
4401
|
+
/* @__PURE__ */ jsx(DragOverlay, { dropAnimation: null, children: dragDrop.activeDragItem && /* @__PURE__ */ jsx(DragOverlayContent, { item: dragDrop.activeDragItem, schema: builderState.schema, questionTypes: mergedQuestionTypes }) }),
|
|
4402
|
+
showLogicMap && /* @__PURE__ */ jsx(
|
|
4403
|
+
LogicFlowEditor,
|
|
4404
|
+
{
|
|
4405
|
+
schema: builderState.schema,
|
|
4406
|
+
onChange: (updated) => builderState.resetSchema(updated),
|
|
4407
|
+
onClose: () => setShowLogicMap(false)
|
|
4408
|
+
}
|
|
4409
|
+
),
|
|
4410
|
+
showTemplateGallery && templates && /* @__PURE__ */ jsx(
|
|
4411
|
+
TemplateGallery,
|
|
4412
|
+
{
|
|
4413
|
+
templates,
|
|
4414
|
+
onSelect: (template) => builderState.resetSchema(template.schema),
|
|
4415
|
+
onClose: () => setShowTemplateGallery(false)
|
|
4416
|
+
}
|
|
4417
|
+
)
|
|
3180
4418
|
]
|
|
3181
4419
|
}
|
|
3182
4420
|
) });
|
|
@@ -3231,76 +4469,54 @@ var FormBuilder = requireLicense(FormBuilderInner, "FormBuilder");
|
|
|
3231
4469
|
|
|
3232
4470
|
// src/form-builder/theme/presets.ts
|
|
3233
4471
|
var squaredrDarkPreset = {
|
|
3234
|
-
background: "#
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
// sr-error
|
|
3258
|
-
destructiveForeground: "#e8e8ea",
|
|
3259
|
-
// ink-100
|
|
3260
|
-
border: "#1c1c20",
|
|
3261
|
-
// ink-800
|
|
3262
|
-
input: "#1c1c20",
|
|
3263
|
-
// ink-800
|
|
3264
|
-
ring: "oklch(0.82 0.14 210)",
|
|
3265
|
-
// sr-accent-cyan
|
|
3266
|
-
radius: "6px",
|
|
3267
|
-
surface: "#111113",
|
|
3268
|
-
// ink-900
|
|
3269
|
-
surfaceHover: "#17171a",
|
|
3270
|
-
// ink-850
|
|
3271
|
-
canvas: "#0a0a0b",
|
|
3272
|
-
// ink-950
|
|
3273
|
-
panel: "#111113",
|
|
3274
|
-
// ink-900
|
|
3275
|
-
borderStrong: "#26262c",
|
|
3276
|
-
// ink-700
|
|
3277
|
-
textDim: "#5a5a66"
|
|
3278
|
-
// ink-500
|
|
4472
|
+
background: "#0F1A1F",
|
|
4473
|
+
foreground: "#E8EFF1",
|
|
4474
|
+
card: "#16242A",
|
|
4475
|
+
primary: "#63BDB4",
|
|
4476
|
+
primaryForeground: "#0F1A1F",
|
|
4477
|
+
secondary: "#182F31",
|
|
4478
|
+
secondaryForeground: "#E8EFF1",
|
|
4479
|
+
muted: "#182F31",
|
|
4480
|
+
mutedForeground: "#8CA1A9",
|
|
4481
|
+
accent: "#182F31",
|
|
4482
|
+
accentForeground: "#E8EFF1",
|
|
4483
|
+
destructive: "#E08072",
|
|
4484
|
+
destructiveForeground: "#0F1A1F",
|
|
4485
|
+
border: "#2A3B42",
|
|
4486
|
+
input: "#2A3B42",
|
|
4487
|
+
ring: "#63BDB4",
|
|
4488
|
+
radius: "0px",
|
|
4489
|
+
surface: "#16242A",
|
|
4490
|
+
surfaceHover: "#182F31",
|
|
4491
|
+
canvas: "#0F1A1F",
|
|
4492
|
+
panel: "#16242A",
|
|
4493
|
+
borderStrong: "#2F4F4C",
|
|
4494
|
+
textDim: "#5E7680"
|
|
3279
4495
|
};
|
|
3280
4496
|
var cleanPreset = {
|
|
3281
|
-
background: "#
|
|
3282
|
-
foreground: "#
|
|
3283
|
-
card: "#
|
|
3284
|
-
primary: "#
|
|
3285
|
-
primaryForeground: "#
|
|
3286
|
-
secondary: "#
|
|
3287
|
-
secondaryForeground: "#
|
|
3288
|
-
muted: "#
|
|
3289
|
-
mutedForeground: "#
|
|
3290
|
-
accent: "#
|
|
3291
|
-
accentForeground: "#
|
|
3292
|
-
destructive: "#
|
|
3293
|
-
destructiveForeground: "#
|
|
3294
|
-
border: "#
|
|
3295
|
-
input: "#
|
|
3296
|
-
ring: "#
|
|
3297
|
-
radius: "
|
|
3298
|
-
surface: "#
|
|
3299
|
-
surfaceHover: "#
|
|
3300
|
-
canvas: "#
|
|
3301
|
-
panel: "#
|
|
3302
|
-
borderStrong: "#
|
|
3303
|
-
textDim: "#
|
|
4497
|
+
background: "#F4F7F8",
|
|
4498
|
+
foreground: "#12222A",
|
|
4499
|
+
card: "#FFFFFF",
|
|
4500
|
+
primary: "#1F6B6E",
|
|
4501
|
+
primaryForeground: "#FFFFFF",
|
|
4502
|
+
secondary: "#EDF3F2",
|
|
4503
|
+
secondaryForeground: "#12222A",
|
|
4504
|
+
muted: "#EDF3F2",
|
|
4505
|
+
mutedForeground: "#6A7B85",
|
|
4506
|
+
accent: "#EDF3F2",
|
|
4507
|
+
accentForeground: "#12222A",
|
|
4508
|
+
destructive: "#B04A3C",
|
|
4509
|
+
destructiveForeground: "#FFFFFF",
|
|
4510
|
+
border: "#DCE4E8",
|
|
4511
|
+
input: "#DCE4E8",
|
|
4512
|
+
ring: "#1F6B6E",
|
|
4513
|
+
radius: "0px",
|
|
4514
|
+
surface: "#FAFCFC",
|
|
4515
|
+
surfaceHover: "#EDF3F2",
|
|
4516
|
+
canvas: "#F4F7F8",
|
|
4517
|
+
panel: "#FFFFFF",
|
|
4518
|
+
borderStrong: "#B9D1CF",
|
|
4519
|
+
textDim: "#6A7B85"
|
|
3304
4520
|
};
|
|
3305
4521
|
|
|
3306
4522
|
export { DEFAULT_PALETTE, DEFAULT_SCHEMA, FormBuilder, FormBuilderThemeProvider, QUESTION_TYPE_INFO, addOption, addQuestion, addSection, cleanPreset, duplicateQuestion, duplicateSection, findQuestion, findSection, generateId, generateOptionId, generateQuestionId, generateSectionId, moveOption, moveQuestion, moveSection, removeOption, removeQuestion, removeSection, squaredrDarkPreset, updateOption, updateQuestion, updateSection, useBuilderState, useBuilderTheme, useDragDrop, useUndoRedo };
|