@waypointjs/builder 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1492 -539
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -2
- package/dist/index.d.ts +10 -2
- package/dist/index.js +1494 -541
- package/dist/index.js.map +1 -1
- package/package.json +7 -4
package/dist/index.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { createRuntimeStore, getNextStep, validateSchema, getPreviousStep, resolveTree } from '@waypointjs/core';
|
|
2
|
-
import { useState, useRef, useEffect } from 'react';
|
|
2
|
+
import { createContext, useState, useRef, useEffect, useCallback, useContext } from 'react';
|
|
3
3
|
import { create } from 'zustand';
|
|
4
|
-
import {
|
|
4
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
|
+
import { useSensors, useSensor, PointerSensor, TouchSensor, KeyboardSensor, DndContext, closestCenter, DragOverlay } from '@dnd-kit/core';
|
|
6
|
+
import { SortableContext, verticalListSortingStrategy, useSortable } from '@dnd-kit/sortable';
|
|
7
|
+
import { CSS } from '@dnd-kit/utilities';
|
|
5
8
|
import { useWaypoint, useWaypointStep } from '@waypointjs/react';
|
|
6
9
|
import { DevPanel } from '@waypointjs/devtools';
|
|
7
10
|
|
|
@@ -195,6 +198,44 @@ var useBuilderStore = create((set, _get) => ({
|
|
|
195
198
|
selectedFieldId: s.selectedStepId === stepId ? null : s.selectedFieldId,
|
|
196
199
|
isDirty: true
|
|
197
200
|
})),
|
|
201
|
+
duplicateStep: (stepId) => {
|
|
202
|
+
const state = _get();
|
|
203
|
+
const step = state.schema.steps.find((s) => s.id === stepId);
|
|
204
|
+
if (!step) return;
|
|
205
|
+
const newStepId = generateId("step");
|
|
206
|
+
const fieldIdMap = {};
|
|
207
|
+
for (const f of step.fields) {
|
|
208
|
+
fieldIdMap[f.id] = generateId("field");
|
|
209
|
+
}
|
|
210
|
+
const newFields = step.fields.map((f) => ({
|
|
211
|
+
...f,
|
|
212
|
+
id: fieldIdMap[f.id],
|
|
213
|
+
dependsOn: f.dependsOn?.map((dep) => {
|
|
214
|
+
if (dep.startsWith(`${stepId}.`)) {
|
|
215
|
+
const oldFieldId = dep.slice(stepId.length + 1);
|
|
216
|
+
const newFieldId = fieldIdMap[oldFieldId];
|
|
217
|
+
return newFieldId ? `${newStepId}.${newFieldId}` : dep;
|
|
218
|
+
}
|
|
219
|
+
return dep;
|
|
220
|
+
})
|
|
221
|
+
}));
|
|
222
|
+
const newStep = {
|
|
223
|
+
...step,
|
|
224
|
+
id: newStepId,
|
|
225
|
+
title: `${step.title} (copy)`,
|
|
226
|
+
url: `${step.url}-copy`,
|
|
227
|
+
fields: newFields
|
|
228
|
+
};
|
|
229
|
+
const stepIndex = state.schema.steps.findIndex((s) => s.id === stepId);
|
|
230
|
+
const newSteps = [...state.schema.steps];
|
|
231
|
+
newSteps.splice(stepIndex + 1, 0, newStep);
|
|
232
|
+
set({
|
|
233
|
+
schema: { ...state.schema, steps: newSteps },
|
|
234
|
+
selectedStepId: newStepId,
|
|
235
|
+
selectedFieldId: null,
|
|
236
|
+
isDirty: true
|
|
237
|
+
});
|
|
238
|
+
},
|
|
198
239
|
reorderSteps: (fromIndex, toIndex) => set((s) => {
|
|
199
240
|
const steps = [...s.schema.steps];
|
|
200
241
|
const [moved] = steps.splice(fromIndex, 1);
|
|
@@ -247,6 +288,32 @@ var useBuilderStore = create((set, _get) => ({
|
|
|
247
288
|
selectedFieldId: s.selectedFieldId === fieldId ? null : s.selectedFieldId,
|
|
248
289
|
isDirty: true
|
|
249
290
|
})),
|
|
291
|
+
duplicateField: (stepId, fieldId) => {
|
|
292
|
+
const state = _get();
|
|
293
|
+
const step = state.schema.steps.find((s) => s.id === stepId);
|
|
294
|
+
if (!step) return;
|
|
295
|
+
const field = step.fields.find((f) => f.id === fieldId);
|
|
296
|
+
if (!field) return;
|
|
297
|
+
const newFieldId = generateId("field");
|
|
298
|
+
const newField = {
|
|
299
|
+
...field,
|
|
300
|
+
id: newFieldId,
|
|
301
|
+
label: `${field.label} (copy)`
|
|
302
|
+
};
|
|
303
|
+
const fieldIndex = step.fields.findIndex((f) => f.id === fieldId);
|
|
304
|
+
const newFields = [...step.fields];
|
|
305
|
+
newFields.splice(fieldIndex + 1, 0, newField);
|
|
306
|
+
set((s) => ({
|
|
307
|
+
schema: {
|
|
308
|
+
...s.schema,
|
|
309
|
+
steps: s.schema.steps.map(
|
|
310
|
+
(st) => st.id === stepId ? { ...st, fields: newFields } : st
|
|
311
|
+
)
|
|
312
|
+
},
|
|
313
|
+
selectedFieldId: newFieldId,
|
|
314
|
+
isDirty: true
|
|
315
|
+
}));
|
|
316
|
+
},
|
|
250
317
|
reorderFields: (stepId, fromIndex, toIndex) => set((s) => ({
|
|
251
318
|
schema: {
|
|
252
319
|
...s.schema,
|
|
@@ -345,6 +412,18 @@ var useBuilderStore = create((set, _get) => ({
|
|
|
345
412
|
isDirty: true
|
|
346
413
|
}))
|
|
347
414
|
}));
|
|
415
|
+
var BuilderReadOnlyContext = createContext(false);
|
|
416
|
+
function useBuilderReadOnly() {
|
|
417
|
+
return useContext(BuilderReadOnlyContext);
|
|
418
|
+
}
|
|
419
|
+
var BuilderCustomTypesContext = createContext([]);
|
|
420
|
+
function useBuilderCustomTypes() {
|
|
421
|
+
return useContext(BuilderCustomTypesContext);
|
|
422
|
+
}
|
|
423
|
+
var BuilderExternalEnumsContext = createContext([]);
|
|
424
|
+
function useBuilderExternalEnums() {
|
|
425
|
+
return useContext(BuilderExternalEnumsContext);
|
|
426
|
+
}
|
|
348
427
|
var BLANK_FORM = {
|
|
349
428
|
id: "",
|
|
350
429
|
label: "",
|
|
@@ -358,6 +437,7 @@ function ExternalVariablePanel() {
|
|
|
358
437
|
updateExternalVariable,
|
|
359
438
|
removeExternalVariable
|
|
360
439
|
} = useBuilderStore();
|
|
440
|
+
const readOnly = useBuilderReadOnly();
|
|
361
441
|
const variables = schema.externalVariables ?? [];
|
|
362
442
|
const [isAdding, setIsAdding] = useState(false);
|
|
363
443
|
const [editingId, setEditingId] = useState(null);
|
|
@@ -431,7 +511,7 @@ function ExternalVariablePanel() {
|
|
|
431
511
|
return /* @__PURE__ */ jsxs("div", { style: panelStyle, children: [
|
|
432
512
|
/* @__PURE__ */ jsxs("div", { style: headerStyle, children: [
|
|
433
513
|
/* @__PURE__ */ jsx("span", { style: titleStyle, children: "External Variables" }),
|
|
434
|
-
!isAdding && /* @__PURE__ */ jsx(
|
|
514
|
+
!readOnly && !isAdding && /* @__PURE__ */ jsx(
|
|
435
515
|
"button",
|
|
436
516
|
{
|
|
437
517
|
style: addBtnStyle,
|
|
@@ -486,7 +566,7 @@ function ExternalVariablePanel() {
|
|
|
486
566
|
/* @__PURE__ */ jsx("span", { style: varLabelStyle, children: v.label }),
|
|
487
567
|
refs.length > 0 && /* @__PURE__ */ jsx("div", { style: refsStyle, children: refs.map((ref, i) => /* @__PURE__ */ jsx("span", { style: refChipStyle, children: ref }, i)) })
|
|
488
568
|
] }),
|
|
489
|
-
/* @__PURE__ */ jsxs("div", { style: varActionsStyle, children: [
|
|
569
|
+
!readOnly && /* @__PURE__ */ jsxs("div", { style: varActionsStyle, children: [
|
|
490
570
|
/* @__PURE__ */ jsx("button", { style: actionBtnStyle, onClick: () => startEdit(v), children: "Edit" }),
|
|
491
571
|
/* @__PURE__ */ jsx(
|
|
492
572
|
"button",
|
|
@@ -813,15 +893,23 @@ var submitBtnStyle = {
|
|
|
813
893
|
// src/hooks/useAllFieldPaths.ts
|
|
814
894
|
function useAllFieldPaths(excludeStepId, excludeFieldId) {
|
|
815
895
|
const { schema } = useBuilderStore();
|
|
896
|
+
const externalEnums = useBuilderExternalEnums();
|
|
816
897
|
const paths = [];
|
|
817
898
|
for (const step of schema.steps) {
|
|
818
899
|
for (const field of step.fields) {
|
|
819
900
|
if (step.id === excludeStepId && field.id === excludeFieldId) continue;
|
|
901
|
+
let options;
|
|
902
|
+
if (field.externalEnumId) {
|
|
903
|
+
options = externalEnums.find((e) => e.id === field.externalEnumId)?.values;
|
|
904
|
+
} else if (field.options?.length) {
|
|
905
|
+
options = field.options;
|
|
906
|
+
}
|
|
820
907
|
paths.push({
|
|
821
908
|
path: `${step.id}.${field.id}`,
|
|
822
909
|
label: `${step.title} \u2192 ${field.label}`,
|
|
823
910
|
stepId: step.id,
|
|
824
|
-
fieldId: field.id
|
|
911
|
+
fieldId: field.id,
|
|
912
|
+
options
|
|
825
913
|
});
|
|
826
914
|
}
|
|
827
915
|
}
|
|
@@ -847,7 +935,9 @@ var OPERATORS = [
|
|
|
847
935
|
{ value: "notIn", label: "not in (comma list)", hasValue: true },
|
|
848
936
|
{ value: "matches", label: "matches regex", hasValue: true },
|
|
849
937
|
{ value: "exists", label: "exists", hasValue: false },
|
|
850
|
-
{ value: "notExists", label: "not exists", hasValue: false }
|
|
938
|
+
{ value: "notExists", label: "not exists", hasValue: false },
|
|
939
|
+
{ value: "inEnum", label: "is in enum", hasValue: true, isEnum: true },
|
|
940
|
+
{ value: "notInEnum", label: "not in enum", hasValue: true, isEnum: true }
|
|
851
941
|
];
|
|
852
942
|
function ConditionBuilder({
|
|
853
943
|
value,
|
|
@@ -856,6 +946,7 @@ function ConditionBuilder({
|
|
|
856
946
|
excludeFieldId
|
|
857
947
|
}) {
|
|
858
948
|
const allPaths = useAllFieldPaths(excludeStepId, excludeFieldId);
|
|
949
|
+
const externalEnums = useBuilderExternalEnums();
|
|
859
950
|
const group = value ?? { combinator: "and", rules: [] };
|
|
860
951
|
const updateRule = (index, updates) => {
|
|
861
952
|
const rules = group.rules.map((r, i) => i === index ? { ...r, ...updates } : r);
|
|
@@ -918,15 +1009,48 @@ function ConditionBuilder({
|
|
|
918
1009
|
children: OPERATORS.map((o) => /* @__PURE__ */ jsx("option", { value: o.value, children: o.label }, o.value))
|
|
919
1010
|
}
|
|
920
1011
|
),
|
|
921
|
-
opDef?.hasValue && /* @__PURE__ */
|
|
922
|
-
"
|
|
1012
|
+
opDef?.hasValue && (opDef.isEnum ? /* @__PURE__ */ jsxs(
|
|
1013
|
+
"select",
|
|
923
1014
|
{
|
|
924
|
-
style: styles.
|
|
925
|
-
placeholder: "value",
|
|
1015
|
+
style: { ...styles.select, width: 140 },
|
|
926
1016
|
value: rule.value != null ? String(rule.value) : "",
|
|
927
|
-
onChange: (e) => updateRule(index, { value: e.target.value })
|
|
1017
|
+
onChange: (e) => updateRule(index, { value: e.target.value }),
|
|
1018
|
+
children: [
|
|
1019
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "\u2014 pick enum \u2014" }),
|
|
1020
|
+
externalEnums.map((en) => /* @__PURE__ */ jsx("option", { value: en.id, children: en.label }, en.id))
|
|
1021
|
+
]
|
|
928
1022
|
}
|
|
929
|
-
),
|
|
1023
|
+
) : /* @__PURE__ */ jsxs("div", { style: styles.valueGroup, children: [
|
|
1024
|
+
/* @__PURE__ */ jsx(
|
|
1025
|
+
"input",
|
|
1026
|
+
{
|
|
1027
|
+
style: styles.valueInput,
|
|
1028
|
+
placeholder: "value",
|
|
1029
|
+
value: rule.value != null ? String(rule.value) : "",
|
|
1030
|
+
onChange: (e) => updateRule(index, { value: e.target.value })
|
|
1031
|
+
}
|
|
1032
|
+
),
|
|
1033
|
+
externalEnums.length > 0 && /* @__PURE__ */ jsxs(
|
|
1034
|
+
"select",
|
|
1035
|
+
{
|
|
1036
|
+
style: styles.enumPicker,
|
|
1037
|
+
title: "Pick a value from an enum",
|
|
1038
|
+
value: "",
|
|
1039
|
+
onChange: (e) => {
|
|
1040
|
+
if (e.target.value) updateRule(index, { value: e.target.value });
|
|
1041
|
+
},
|
|
1042
|
+
children: [
|
|
1043
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "\u229E" }),
|
|
1044
|
+
externalEnums.map((en) => /* @__PURE__ */ jsx("optgroup", { label: en.label, children: en.values.map((v) => /* @__PURE__ */ jsxs("option", { value: String(v.value), children: [
|
|
1045
|
+
v.label,
|
|
1046
|
+
" (",
|
|
1047
|
+
v.value,
|
|
1048
|
+
")"
|
|
1049
|
+
] }, String(v.value))) }, en.id))
|
|
1050
|
+
]
|
|
1051
|
+
}
|
|
1052
|
+
)
|
|
1053
|
+
] })),
|
|
930
1054
|
/* @__PURE__ */ jsx("button", { style: styles.removeBtn, onClick: () => removeRule(index), children: "\u2715" })
|
|
931
1055
|
] }, index);
|
|
932
1056
|
}),
|
|
@@ -1004,6 +1128,17 @@ var styles = {
|
|
|
1004
1128
|
alignSelf: "flex-start",
|
|
1005
1129
|
color: "var(--wp-text-secondary)"
|
|
1006
1130
|
},
|
|
1131
|
+
valueGroup: { display: "flex", alignItems: "center", gap: 4 },
|
|
1132
|
+
enumPicker: {
|
|
1133
|
+
fontSize: 11,
|
|
1134
|
+
padding: "4px 4px",
|
|
1135
|
+
border: "1px solid var(--wp-border-muted)",
|
|
1136
|
+
borderRadius: "var(--wp-radius)",
|
|
1137
|
+
background: "var(--wp-canvas)",
|
|
1138
|
+
color: "var(--wp-primary)",
|
|
1139
|
+
cursor: "pointer",
|
|
1140
|
+
flexShrink: 0
|
|
1141
|
+
},
|
|
1007
1142
|
preview: { marginTop: 4 },
|
|
1008
1143
|
previewLabel: {
|
|
1009
1144
|
fontSize: 10,
|
|
@@ -1025,6 +1160,244 @@ var styles = {
|
|
|
1025
1160
|
color: "var(--wp-text-mono)"
|
|
1026
1161
|
}
|
|
1027
1162
|
};
|
|
1163
|
+
var VALIDATION_RULES = [
|
|
1164
|
+
{ type: "required", label: "Required", hasValue: false },
|
|
1165
|
+
{ type: "min", label: "Min value", hasValue: true },
|
|
1166
|
+
{ type: "max", label: "Max value", hasValue: true },
|
|
1167
|
+
{ type: "minLength", label: "Min length", hasValue: true },
|
|
1168
|
+
{ type: "maxLength", label: "Max length", hasValue: true },
|
|
1169
|
+
{ type: "email", label: "Email format", hasValue: false },
|
|
1170
|
+
{ type: "url", label: "URL format", hasValue: false },
|
|
1171
|
+
{ type: "regex", label: "Matches regex", hasValue: true },
|
|
1172
|
+
{ type: "equals", label: "equals", hasValue: true },
|
|
1173
|
+
{ type: "notEquals", label: "not equals", hasValue: true },
|
|
1174
|
+
{ type: "greaterThan", label: ">", hasValue: true },
|
|
1175
|
+
{ type: "greaterThanOrEqual", label: ">=", hasValue: true },
|
|
1176
|
+
{ type: "lessThan", label: "<", hasValue: true },
|
|
1177
|
+
{ type: "lessThanOrEqual", label: "<=", hasValue: true },
|
|
1178
|
+
{ type: "contains", label: "contains", hasValue: true },
|
|
1179
|
+
{ type: "notContains", label: "not contains", hasValue: true },
|
|
1180
|
+
{ type: "matches", label: "matches regex", hasValue: true },
|
|
1181
|
+
{ type: "inEnum", label: "is in enum", hasValue: true, isEnum: true },
|
|
1182
|
+
{ type: "notInEnum", label: "not in enum", hasValue: true, isEnum: true },
|
|
1183
|
+
{ type: "custom", label: "Custom validator", hasValue: false }
|
|
1184
|
+
];
|
|
1185
|
+
var COMPARATOR_TYPES = /* @__PURE__ */ new Set([
|
|
1186
|
+
"equals",
|
|
1187
|
+
"notEquals",
|
|
1188
|
+
"greaterThan",
|
|
1189
|
+
"greaterThanOrEqual",
|
|
1190
|
+
"lessThan",
|
|
1191
|
+
"lessThanOrEqual",
|
|
1192
|
+
"contains",
|
|
1193
|
+
"notContains"
|
|
1194
|
+
]);
|
|
1195
|
+
function ValidationBuilder({ value, onChange }) {
|
|
1196
|
+
const externalEnums = useBuilderExternalEnums();
|
|
1197
|
+
const allFieldPaths = useAllFieldPaths();
|
|
1198
|
+
const updateRule = (index, updates) => {
|
|
1199
|
+
onChange(value.map((r, i) => i === index ? { ...r, ...updates } : r));
|
|
1200
|
+
};
|
|
1201
|
+
const addRule = () => {
|
|
1202
|
+
onChange([...value, { type: "required", message: "This field is required" }]);
|
|
1203
|
+
};
|
|
1204
|
+
const removeRule = (index) => {
|
|
1205
|
+
onChange(value.filter((_, i) => i !== index));
|
|
1206
|
+
};
|
|
1207
|
+
return /* @__PURE__ */ jsxs("div", { style: styles2.container, children: [
|
|
1208
|
+
value.length === 0 && /* @__PURE__ */ jsx("div", { style: styles2.empty, children: "No rules \u2014 field is optional by default." }),
|
|
1209
|
+
value.map((rule, index) => {
|
|
1210
|
+
const def = VALIDATION_RULES.find((r) => r.type === rule.type);
|
|
1211
|
+
return /* @__PURE__ */ jsxs("div", { style: styles2.rule, children: [
|
|
1212
|
+
/* @__PURE__ */ jsx(
|
|
1213
|
+
"select",
|
|
1214
|
+
{
|
|
1215
|
+
style: styles2.typeSelect,
|
|
1216
|
+
value: rule.type,
|
|
1217
|
+
onChange: (e) => updateRule(index, { type: e.target.value }),
|
|
1218
|
+
children: VALIDATION_RULES.map((r) => /* @__PURE__ */ jsx("option", { value: r.type, children: r.label }, r.type))
|
|
1219
|
+
}
|
|
1220
|
+
),
|
|
1221
|
+
def?.hasValue && (def.isEnum ? /* @__PURE__ */ jsxs(
|
|
1222
|
+
"select",
|
|
1223
|
+
{
|
|
1224
|
+
style: { ...styles2.typeSelect, flex: "0 0 140px" },
|
|
1225
|
+
value: rule.value != null ? String(rule.value) : "",
|
|
1226
|
+
onChange: (e) => updateRule(index, { value: e.target.value }),
|
|
1227
|
+
children: [
|
|
1228
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "\u2014 pick enum \u2014" }),
|
|
1229
|
+
externalEnums.map((en) => /* @__PURE__ */ jsx("option", { value: en.id, children: en.label }, en.id))
|
|
1230
|
+
]
|
|
1231
|
+
}
|
|
1232
|
+
) : /* @__PURE__ */ jsxs("div", { style: styles2.valueGroup, children: [
|
|
1233
|
+
COMPARATOR_TYPES.has(rule.type) && /* @__PURE__ */ jsx(
|
|
1234
|
+
"button",
|
|
1235
|
+
{
|
|
1236
|
+
type: "button",
|
|
1237
|
+
style: {
|
|
1238
|
+
...styles2.refToggle,
|
|
1239
|
+
background: rule.refField !== void 0 ? "var(--wp-primary)" : "var(--wp-surface-muted)",
|
|
1240
|
+
color: rule.refField !== void 0 ? "#fff" : "var(--wp-text-secondary)"
|
|
1241
|
+
},
|
|
1242
|
+
title: rule.refField !== void 0 ? "Comparing to field \u2014 click for static value" : "Static value \u2014 click to compare to another field",
|
|
1243
|
+
onClick: () => {
|
|
1244
|
+
if (rule.refField !== void 0) {
|
|
1245
|
+
updateRule(index, { refField: void 0, value: "" });
|
|
1246
|
+
} else {
|
|
1247
|
+
updateRule(index, { refField: "", value: void 0 });
|
|
1248
|
+
}
|
|
1249
|
+
},
|
|
1250
|
+
children: "\u21C4"
|
|
1251
|
+
}
|
|
1252
|
+
),
|
|
1253
|
+
rule.refField !== void 0 ? /* @__PURE__ */ jsxs(
|
|
1254
|
+
"select",
|
|
1255
|
+
{
|
|
1256
|
+
style: { ...styles2.typeSelect, flex: "1 1 auto" },
|
|
1257
|
+
value: rule.refField,
|
|
1258
|
+
onChange: (e) => updateRule(index, { refField: e.target.value }),
|
|
1259
|
+
children: [
|
|
1260
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "\u2014 pick field \u2014" }),
|
|
1261
|
+
allFieldPaths.filter((fp) => !fp.isExternal).map((fp) => /* @__PURE__ */ jsx("option", { value: fp.path, children: fp.label }, fp.path))
|
|
1262
|
+
]
|
|
1263
|
+
}
|
|
1264
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1265
|
+
/* @__PURE__ */ jsx(
|
|
1266
|
+
"input",
|
|
1267
|
+
{
|
|
1268
|
+
style: styles2.valueInput,
|
|
1269
|
+
placeholder: "value",
|
|
1270
|
+
value: rule.value != null ? String(rule.value) : "",
|
|
1271
|
+
onChange: (e) => updateRule(index, { value: e.target.value })
|
|
1272
|
+
}
|
|
1273
|
+
),
|
|
1274
|
+
externalEnums.length > 0 && /* @__PURE__ */ jsxs(
|
|
1275
|
+
"select",
|
|
1276
|
+
{
|
|
1277
|
+
style: styles2.enumPicker,
|
|
1278
|
+
title: "Pick a value from an enum",
|
|
1279
|
+
value: "",
|
|
1280
|
+
onChange: (e) => {
|
|
1281
|
+
if (e.target.value) updateRule(index, { value: e.target.value });
|
|
1282
|
+
},
|
|
1283
|
+
children: [
|
|
1284
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "\u229E" }),
|
|
1285
|
+
externalEnums.map((en) => /* @__PURE__ */ jsx("optgroup", { label: en.label, children: en.values.map((v) => /* @__PURE__ */ jsxs("option", { value: String(v.value), children: [
|
|
1286
|
+
v.label,
|
|
1287
|
+
" (",
|
|
1288
|
+
v.value,
|
|
1289
|
+
")"
|
|
1290
|
+
] }, String(v.value))) }, en.id))
|
|
1291
|
+
]
|
|
1292
|
+
}
|
|
1293
|
+
)
|
|
1294
|
+
] })
|
|
1295
|
+
] })),
|
|
1296
|
+
rule.type === "custom" && /* @__PURE__ */ jsx(
|
|
1297
|
+
"input",
|
|
1298
|
+
{
|
|
1299
|
+
style: styles2.valueInput,
|
|
1300
|
+
placeholder: "validatorId",
|
|
1301
|
+
value: rule.customValidatorId ?? "",
|
|
1302
|
+
onChange: (e) => updateRule(index, { customValidatorId: e.target.value })
|
|
1303
|
+
}
|
|
1304
|
+
),
|
|
1305
|
+
/* @__PURE__ */ jsx(
|
|
1306
|
+
"input",
|
|
1307
|
+
{
|
|
1308
|
+
style: styles2.messageInput,
|
|
1309
|
+
placeholder: "error message",
|
|
1310
|
+
value: rule.message,
|
|
1311
|
+
onChange: (e) => updateRule(index, { message: e.target.value })
|
|
1312
|
+
}
|
|
1313
|
+
),
|
|
1314
|
+
/* @__PURE__ */ jsx("button", { style: styles2.removeBtn, onClick: () => removeRule(index), children: "\u2715" })
|
|
1315
|
+
] }, index);
|
|
1316
|
+
}),
|
|
1317
|
+
/* @__PURE__ */ jsx("button", { style: styles2.addBtn, onClick: addRule, children: "+ Add rule" })
|
|
1318
|
+
] });
|
|
1319
|
+
}
|
|
1320
|
+
var styles2 = {
|
|
1321
|
+
container: { display: "flex", flexDirection: "column", gap: 10 },
|
|
1322
|
+
empty: { fontSize: 13, color: "var(--wp-text-subtle)", textAlign: "center", padding: "12px 0" },
|
|
1323
|
+
rule: {
|
|
1324
|
+
display: "flex",
|
|
1325
|
+
alignItems: "center",
|
|
1326
|
+
gap: 8,
|
|
1327
|
+
background: "var(--wp-surface)",
|
|
1328
|
+
border: "1px solid var(--wp-border)",
|
|
1329
|
+
borderRadius: "var(--wp-radius-lg)",
|
|
1330
|
+
padding: "8px 10px"
|
|
1331
|
+
},
|
|
1332
|
+
typeSelect: {
|
|
1333
|
+
flex: "0 0 150px",
|
|
1334
|
+
fontSize: 12,
|
|
1335
|
+
padding: "5px 6px",
|
|
1336
|
+
border: "1px solid var(--wp-border-muted)",
|
|
1337
|
+
borderRadius: "var(--wp-radius)",
|
|
1338
|
+
background: "var(--wp-canvas)",
|
|
1339
|
+
color: "var(--wp-text)"
|
|
1340
|
+
},
|
|
1341
|
+
valueGroup: { display: "flex", alignItems: "center", gap: 4, flex: "1 1 auto" },
|
|
1342
|
+
refToggle: {
|
|
1343
|
+
border: "1px solid var(--wp-border-muted)",
|
|
1344
|
+
borderRadius: "var(--wp-radius)",
|
|
1345
|
+
cursor: "pointer",
|
|
1346
|
+
fontSize: 11,
|
|
1347
|
+
padding: "4px 6px",
|
|
1348
|
+
flexShrink: 0,
|
|
1349
|
+
fontWeight: 600,
|
|
1350
|
+
lineHeight: 1
|
|
1351
|
+
},
|
|
1352
|
+
valueInput: {
|
|
1353
|
+
width: 90,
|
|
1354
|
+
fontSize: 12,
|
|
1355
|
+
padding: "5px 6px",
|
|
1356
|
+
border: "1px solid var(--wp-border-muted)",
|
|
1357
|
+
borderRadius: "var(--wp-radius)",
|
|
1358
|
+
background: "var(--wp-canvas)",
|
|
1359
|
+
color: "var(--wp-text)"
|
|
1360
|
+
},
|
|
1361
|
+
enumPicker: {
|
|
1362
|
+
fontSize: 11,
|
|
1363
|
+
padding: "4px 4px",
|
|
1364
|
+
border: "1px solid var(--wp-border-muted)",
|
|
1365
|
+
borderRadius: "var(--wp-radius)",
|
|
1366
|
+
background: "var(--wp-canvas)",
|
|
1367
|
+
color: "var(--wp-primary)",
|
|
1368
|
+
cursor: "pointer",
|
|
1369
|
+
flexShrink: 0
|
|
1370
|
+
},
|
|
1371
|
+
messageInput: {
|
|
1372
|
+
flex: 1,
|
|
1373
|
+
fontSize: 12,
|
|
1374
|
+
padding: "5px 6px",
|
|
1375
|
+
border: "1px solid var(--wp-border-muted)",
|
|
1376
|
+
borderRadius: "var(--wp-radius)",
|
|
1377
|
+
background: "var(--wp-canvas)",
|
|
1378
|
+
color: "var(--wp-text)",
|
|
1379
|
+
minWidth: 0
|
|
1380
|
+
},
|
|
1381
|
+
removeBtn: {
|
|
1382
|
+
border: "none",
|
|
1383
|
+
background: "transparent",
|
|
1384
|
+
color: "var(--wp-danger)",
|
|
1385
|
+
cursor: "pointer",
|
|
1386
|
+
fontSize: 13,
|
|
1387
|
+
flexShrink: 0
|
|
1388
|
+
},
|
|
1389
|
+
addBtn: {
|
|
1390
|
+
fontSize: 12,
|
|
1391
|
+
padding: "6px 12px",
|
|
1392
|
+
background: "var(--wp-surface-muted)",
|
|
1393
|
+
border: "1px solid var(--wp-border-muted)",
|
|
1394
|
+
borderRadius: "var(--wp-radius)",
|
|
1395
|
+
cursor: "pointer",
|
|
1396
|
+
fontWeight: 500,
|
|
1397
|
+
alignSelf: "flex-start",
|
|
1398
|
+
color: "var(--wp-text-secondary)"
|
|
1399
|
+
}
|
|
1400
|
+
};
|
|
1028
1401
|
function DependsOnInput({
|
|
1029
1402
|
value,
|
|
1030
1403
|
onChange,
|
|
@@ -1057,17 +1430,17 @@ function DependsOnInput({
|
|
|
1057
1430
|
}, []);
|
|
1058
1431
|
const getLabel = (path) => allPaths.find((p) => p.path === path)?.label ?? path;
|
|
1059
1432
|
const isExternal = (path) => path.startsWith("$ext.");
|
|
1060
|
-
return /* @__PURE__ */ jsxs("div", { ref: containerRef, style:
|
|
1061
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
1062
|
-
value.map((path) => /* @__PURE__ */ jsxs("span", { style: { ...
|
|
1433
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, style: styles3.container, children: [
|
|
1434
|
+
/* @__PURE__ */ jsxs("div", { style: styles3.tags, children: [
|
|
1435
|
+
value.map((path) => /* @__PURE__ */ jsxs("span", { style: { ...styles3.tag, ...isExternal(path) ? styles3.tagExt : {} }, children: [
|
|
1063
1436
|
getLabel(path),
|
|
1064
|
-
/* @__PURE__ */ jsx("button", { style:
|
|
1437
|
+
/* @__PURE__ */ jsx("button", { style: styles3.tagRemove, onClick: () => remove(path), children: "\u2715" })
|
|
1065
1438
|
] }, path)),
|
|
1066
1439
|
/* @__PURE__ */ jsx(
|
|
1067
1440
|
"input",
|
|
1068
1441
|
{
|
|
1069
1442
|
ref: inputRef,
|
|
1070
|
-
style:
|
|
1443
|
+
style: styles3.input,
|
|
1071
1444
|
placeholder: value.length === 0 ? "Search fields or $ext vars\u2026" : "Add more\u2026",
|
|
1072
1445
|
value: query,
|
|
1073
1446
|
onChange: (e) => {
|
|
@@ -1078,28 +1451,28 @@ function DependsOnInput({
|
|
|
1078
1451
|
}
|
|
1079
1452
|
)
|
|
1080
1453
|
] }),
|
|
1081
|
-
open && /* @__PURE__ */ jsxs("div", { style:
|
|
1082
|
-
available.length === 0 && /* @__PURE__ */ jsx("div", { style:
|
|
1454
|
+
open && /* @__PURE__ */ jsxs("div", { style: styles3.dropdown, children: [
|
|
1455
|
+
available.length === 0 && /* @__PURE__ */ jsx("div", { style: styles3.noResults, children: allPaths.length === 0 ? "No fields available in the tree yet." : "No matching fields." }),
|
|
1083
1456
|
available.map((p) => /* @__PURE__ */ jsxs(
|
|
1084
1457
|
"button",
|
|
1085
1458
|
{
|
|
1086
|
-
style:
|
|
1459
|
+
style: styles3.option,
|
|
1087
1460
|
onMouseDown: (e) => {
|
|
1088
1461
|
e.preventDefault();
|
|
1089
1462
|
add(p.path);
|
|
1090
1463
|
},
|
|
1091
1464
|
children: [
|
|
1092
|
-
/* @__PURE__ */ jsx("span", { style:
|
|
1093
|
-
/* @__PURE__ */ jsx("span", { style:
|
|
1465
|
+
/* @__PURE__ */ jsx("span", { style: styles3.optionLabel, children: p.label }),
|
|
1466
|
+
/* @__PURE__ */ jsx("span", { style: styles3.optionPath, children: p.path })
|
|
1094
1467
|
]
|
|
1095
1468
|
},
|
|
1096
1469
|
p.path
|
|
1097
1470
|
))
|
|
1098
1471
|
] }),
|
|
1099
|
-
value.length > 0 && /* @__PURE__ */ jsx("div", { style:
|
|
1472
|
+
value.length > 0 && /* @__PURE__ */ jsx("div", { style: styles3.hint, children: "This field will be blocked until all dependencies have a value." })
|
|
1100
1473
|
] });
|
|
1101
1474
|
}
|
|
1102
|
-
var
|
|
1475
|
+
var styles3 = {
|
|
1103
1476
|
container: { position: "relative" },
|
|
1104
1477
|
tags: {
|
|
1105
1478
|
display: "flex",
|
|
@@ -1181,15 +1554,15 @@ function Modal({ title, onClose, children, width = 560 }) {
|
|
|
1181
1554
|
document.addEventListener("keydown", handler);
|
|
1182
1555
|
return () => document.removeEventListener("keydown", handler);
|
|
1183
1556
|
}, [onClose]);
|
|
1184
|
-
return /* @__PURE__ */ jsx("div", { style:
|
|
1185
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
1186
|
-
/* @__PURE__ */ jsx("span", { style:
|
|
1187
|
-
/* @__PURE__ */ jsx("button", { style:
|
|
1557
|
+
return /* @__PURE__ */ jsx("div", { style: styles4.overlay, onClick: onClose, children: /* @__PURE__ */ jsxs("div", { style: { ...styles4.panel, width }, onClick: (e) => e.stopPropagation(), children: [
|
|
1558
|
+
/* @__PURE__ */ jsxs("div", { style: styles4.header, children: [
|
|
1559
|
+
/* @__PURE__ */ jsx("span", { style: styles4.title, children: title }),
|
|
1560
|
+
/* @__PURE__ */ jsx("button", { style: styles4.closeBtn, onClick: onClose, children: "\u2715" })
|
|
1188
1561
|
] }),
|
|
1189
|
-
/* @__PURE__ */ jsx("div", { style:
|
|
1562
|
+
/* @__PURE__ */ jsx("div", { style: styles4.body, children })
|
|
1190
1563
|
] }) });
|
|
1191
1564
|
}
|
|
1192
|
-
var
|
|
1565
|
+
var styles4 = {
|
|
1193
1566
|
overlay: {
|
|
1194
1567
|
position: "fixed",
|
|
1195
1568
|
inset: 0,
|
|
@@ -1226,16 +1599,7 @@ var styles3 = {
|
|
|
1226
1599
|
},
|
|
1227
1600
|
body: { overflowY: "auto", padding: 20, color: "var(--wp-text)" }
|
|
1228
1601
|
};
|
|
1229
|
-
var
|
|
1230
|
-
{ type: "required", label: "Required", hasValue: false },
|
|
1231
|
-
{ type: "min", label: "Min value", hasValue: true },
|
|
1232
|
-
{ type: "max", label: "Max value", hasValue: true },
|
|
1233
|
-
{ type: "minLength", label: "Min length", hasValue: true },
|
|
1234
|
-
{ type: "maxLength", label: "Max length", hasValue: true },
|
|
1235
|
-
{ type: "email", label: "Email format", hasValue: false },
|
|
1236
|
-
{ type: "url", label: "URL format", hasValue: false },
|
|
1237
|
-
{ type: "regex", label: "Regex pattern", hasValue: true }
|
|
1238
|
-
];
|
|
1602
|
+
var ENUM_FIELD_TYPES = ["select", "multiselect", "radio"];
|
|
1239
1603
|
function FieldEditor() {
|
|
1240
1604
|
const {
|
|
1241
1605
|
schema,
|
|
@@ -1244,85 +1608,171 @@ function FieldEditor() {
|
|
|
1244
1608
|
updateField,
|
|
1245
1609
|
setFieldCondition
|
|
1246
1610
|
} = useBuilderStore();
|
|
1247
|
-
const
|
|
1611
|
+
const readOnly = useBuilderReadOnly();
|
|
1612
|
+
const externalEnums = useBuilderExternalEnums();
|
|
1248
1613
|
const [conditionModalOpen, setConditionModalOpen] = useState(false);
|
|
1614
|
+
const [validationModalOpen, setValidationModalOpen] = useState(false);
|
|
1615
|
+
const [dynDefaultModalOpen, setDynDefaultModalOpen] = useState(false);
|
|
1616
|
+
const [editingDynIdx, setEditingDynIdx] = useState(null);
|
|
1249
1617
|
const step = schema.steps.find((s) => s.id === selectedStepId);
|
|
1250
1618
|
const field = step?.fields.find((f) => f.id === selectedFieldId);
|
|
1251
1619
|
if (!field || !step) {
|
|
1252
|
-
return /* @__PURE__ */ jsx("div", { style:
|
|
1620
|
+
return /* @__PURE__ */ jsx("div", { style: styles5.empty, children: "Select a field in the middle panel to edit its properties." });
|
|
1253
1621
|
}
|
|
1254
1622
|
const validation = field.validation ?? [];
|
|
1255
1623
|
const isRequired = validation.some((v) => v.type === "required");
|
|
1256
1624
|
const hasCondition = !!field.visibleWhen;
|
|
1257
1625
|
const ruleCount = field.visibleWhen?.rules.length ?? 0;
|
|
1258
|
-
const
|
|
1259
|
-
|
|
1260
|
-
updateField(step.id, field.id, { validation: updated });
|
|
1261
|
-
};
|
|
1262
|
-
const removeValidationRule = (index) => {
|
|
1263
|
-
const updated = validation.filter((_, i) => i !== index);
|
|
1264
|
-
updateField(step.id, field.id, { validation: updated.length ? updated : void 0 });
|
|
1265
|
-
};
|
|
1266
|
-
const addValidationRule = () => {
|
|
1267
|
-
const newRule = {
|
|
1268
|
-
type: newValidationType,
|
|
1269
|
-
message: `${newValidationType} error`
|
|
1270
|
-
};
|
|
1271
|
-
updateField(step.id, field.id, { validation: [...validation, newRule] });
|
|
1626
|
+
const handleValidationChange = (rules) => {
|
|
1627
|
+
updateField(step.id, field.id, { validation: rules.length ? rules : void 0 });
|
|
1272
1628
|
};
|
|
1273
1629
|
const handleDependsOnChange = (paths) => {
|
|
1274
1630
|
updateField(step.id, field.id, { dependsOn: paths.length ? paths : void 0 });
|
|
1275
1631
|
};
|
|
1276
|
-
return /* @__PURE__ */ jsxs("div", { style:
|
|
1277
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
1278
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
1279
|
-
/* @__PURE__ */ jsx("span", { style:
|
|
1280
|
-
!isRequired && /* @__PURE__ */ jsx("span", { style:
|
|
1281
|
-
isRequired && /* @__PURE__ */ jsx("span", { style:
|
|
1632
|
+
return /* @__PURE__ */ jsxs("div", { style: styles5.container, children: [
|
|
1633
|
+
/* @__PURE__ */ jsxs("div", { style: styles5.header, children: [
|
|
1634
|
+
/* @__PURE__ */ jsxs("div", { style: styles5.headerLeft, children: [
|
|
1635
|
+
/* @__PURE__ */ jsx("span", { style: styles5.headerTitle, children: "Field Editor" }),
|
|
1636
|
+
!isRequired && /* @__PURE__ */ jsx("span", { style: styles5.optionalBadge, children: "optional" }),
|
|
1637
|
+
isRequired && /* @__PURE__ */ jsx("span", { style: styles5.requiredBadge, children: "required" })
|
|
1282
1638
|
] }),
|
|
1283
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
1639
|
+
/* @__PURE__ */ jsxs("div", { style: styles5.fieldId, children: [
|
|
1284
1640
|
"id: ",
|
|
1285
1641
|
field.id
|
|
1286
1642
|
] })
|
|
1287
1643
|
] }),
|
|
1288
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
1289
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
1290
|
-
/* @__PURE__ */ jsx("label", { style:
|
|
1644
|
+
/* @__PURE__ */ jsxs("div", { style: styles5.body, children: [
|
|
1645
|
+
/* @__PURE__ */ jsxs("div", { style: styles5.group, children: [
|
|
1646
|
+
/* @__PURE__ */ jsx("label", { style: styles5.label, children: "Label" }),
|
|
1291
1647
|
/* @__PURE__ */ jsx(
|
|
1292
1648
|
"input",
|
|
1293
1649
|
{
|
|
1294
|
-
style:
|
|
1650
|
+
style: styles5.input,
|
|
1295
1651
|
value: field.label,
|
|
1296
1652
|
onChange: (e) => updateField(step.id, field.id, { label: e.target.value })
|
|
1297
1653
|
}
|
|
1298
1654
|
)
|
|
1299
1655
|
] }),
|
|
1300
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
1301
|
-
/* @__PURE__ */ jsx("label", { style:
|
|
1656
|
+
/* @__PURE__ */ jsxs("div", { style: styles5.group, children: [
|
|
1657
|
+
/* @__PURE__ */ jsx("label", { style: styles5.label, children: "Placeholder" }),
|
|
1302
1658
|
/* @__PURE__ */ jsx(
|
|
1303
1659
|
"input",
|
|
1304
1660
|
{
|
|
1305
|
-
style:
|
|
1661
|
+
style: styles5.input,
|
|
1306
1662
|
value: field.placeholder ?? "",
|
|
1307
1663
|
placeholder: "Optional",
|
|
1308
1664
|
onChange: (e) => updateField(step.id, field.id, { placeholder: e.target.value || void 0 })
|
|
1309
1665
|
}
|
|
1310
1666
|
)
|
|
1311
1667
|
] }),
|
|
1312
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
1313
|
-
/* @__PURE__ */ jsx("label", { style:
|
|
1668
|
+
/* @__PURE__ */ jsxs("div", { style: styles5.group, children: [
|
|
1669
|
+
/* @__PURE__ */ jsx("label", { style: styles5.label, children: "Default value" }),
|
|
1314
1670
|
/* @__PURE__ */ jsx(
|
|
1315
1671
|
"input",
|
|
1316
1672
|
{
|
|
1317
|
-
style:
|
|
1673
|
+
style: styles5.input,
|
|
1318
1674
|
value: field.defaultValue != null ? String(field.defaultValue) : "",
|
|
1319
1675
|
placeholder: "Optional",
|
|
1320
1676
|
onChange: (e) => updateField(step.id, field.id, { defaultValue: e.target.value || void 0 })
|
|
1321
1677
|
}
|
|
1322
1678
|
)
|
|
1323
1679
|
] }),
|
|
1324
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
1325
|
-
/* @__PURE__ */
|
|
1680
|
+
/* @__PURE__ */ jsxs("div", { style: styles5.conditionRow, children: [
|
|
1681
|
+
/* @__PURE__ */ jsxs("div", { style: styles5.conditionInfo, children: [
|
|
1682
|
+
/* @__PURE__ */ jsx("div", { style: styles5.label, children: "Dynamic defaults" }),
|
|
1683
|
+
(field.dynamicDefault?.length ?? 0) > 0 ? /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: field.dynamicDefault.map((rule, i) => /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
1684
|
+
/* @__PURE__ */ jsxs("span", { style: styles5.conditionBadge, children: [
|
|
1685
|
+
rule.when.rules.length,
|
|
1686
|
+
" rule",
|
|
1687
|
+
rule.when.rules.length !== 1 ? "s" : ""
|
|
1688
|
+
] }),
|
|
1689
|
+
/* @__PURE__ */ jsxs("span", { style: { fontSize: 11, color: "var(--wp-text-subtle)" }, children: [
|
|
1690
|
+
"\u2192 ",
|
|
1691
|
+
JSON.stringify(rule.value)
|
|
1692
|
+
] }),
|
|
1693
|
+
!readOnly && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1694
|
+
/* @__PURE__ */ jsx(
|
|
1695
|
+
"button",
|
|
1696
|
+
{
|
|
1697
|
+
style: { ...styles5.editConditionBtn, fontSize: 10, padding: "2px 6px" },
|
|
1698
|
+
onClick: () => {
|
|
1699
|
+
setEditingDynIdx(i);
|
|
1700
|
+
setDynDefaultModalOpen(true);
|
|
1701
|
+
},
|
|
1702
|
+
children: "Edit"
|
|
1703
|
+
}
|
|
1704
|
+
),
|
|
1705
|
+
/* @__PURE__ */ jsx(
|
|
1706
|
+
"button",
|
|
1707
|
+
{
|
|
1708
|
+
style: { ...styles5.clearConditionBtn, fontSize: 10, padding: "2px 6px" },
|
|
1709
|
+
onClick: () => {
|
|
1710
|
+
const updated = field.dynamicDefault.filter((_, j) => j !== i);
|
|
1711
|
+
updateField(step.id, field.id, { dynamicDefault: updated.length ? updated : void 0 });
|
|
1712
|
+
},
|
|
1713
|
+
children: "\xD7"
|
|
1714
|
+
}
|
|
1715
|
+
)
|
|
1716
|
+
] })
|
|
1717
|
+
] }, i)) }) : /* @__PURE__ */ jsx("div", { style: styles5.conditionNone, children: "No dynamic defaults" })
|
|
1718
|
+
] }),
|
|
1719
|
+
!readOnly && /* @__PURE__ */ jsx("div", { style: styles5.conditionActions, children: /* @__PURE__ */ jsx(
|
|
1720
|
+
"button",
|
|
1721
|
+
{
|
|
1722
|
+
style: styles5.editConditionBtn,
|
|
1723
|
+
onClick: () => {
|
|
1724
|
+
setEditingDynIdx(null);
|
|
1725
|
+
setDynDefaultModalOpen(true);
|
|
1726
|
+
},
|
|
1727
|
+
children: "Add"
|
|
1728
|
+
}
|
|
1729
|
+
) })
|
|
1730
|
+
] }),
|
|
1731
|
+
/* @__PURE__ */ jsx("div", { style: styles5.divider }),
|
|
1732
|
+
ENUM_FIELD_TYPES.includes(field.type) && externalEnums.length > 0 && /* @__PURE__ */ jsxs("div", { style: styles5.group, children: [
|
|
1733
|
+
/* @__PURE__ */ jsx("label", { style: styles5.label, children: "Options source" }),
|
|
1734
|
+
/* @__PURE__ */ jsxs(
|
|
1735
|
+
"select",
|
|
1736
|
+
{
|
|
1737
|
+
style: styles5.input,
|
|
1738
|
+
disabled: readOnly,
|
|
1739
|
+
value: field.externalEnumId ?? "",
|
|
1740
|
+
onChange: (e) => {
|
|
1741
|
+
const enumId = e.target.value || void 0;
|
|
1742
|
+
updateField(step.id, field.id, {
|
|
1743
|
+
externalEnumId: enumId,
|
|
1744
|
+
// Clear hardcoded options when switching to an enum
|
|
1745
|
+
options: enumId ? void 0 : field.options
|
|
1746
|
+
});
|
|
1747
|
+
},
|
|
1748
|
+
children: [
|
|
1749
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "\u2014 Hardcoded options \u2014" }),
|
|
1750
|
+
externalEnums.map((en) => /* @__PURE__ */ jsxs("option", { value: en.id, children: [
|
|
1751
|
+
en.label,
|
|
1752
|
+
" (",
|
|
1753
|
+
en.values.length,
|
|
1754
|
+
" items)"
|
|
1755
|
+
] }, en.id))
|
|
1756
|
+
]
|
|
1757
|
+
}
|
|
1758
|
+
),
|
|
1759
|
+
field.externalEnumId && /* @__PURE__ */ jsx("div", { style: styles5.enumInfo, children: (() => {
|
|
1760
|
+
const en = externalEnums.find((e) => e.id === field.externalEnumId);
|
|
1761
|
+
return en ? /* @__PURE__ */ jsxs("span", { style: styles5.enumBadge, children: [
|
|
1762
|
+
"\u229E ",
|
|
1763
|
+
en.label,
|
|
1764
|
+
" \xB7 ",
|
|
1765
|
+
en.values.length,
|
|
1766
|
+
" options"
|
|
1767
|
+
] }) : /* @__PURE__ */ jsxs("span", { style: styles5.enumMissing, children: [
|
|
1768
|
+
'\u26A0 Enum "',
|
|
1769
|
+
field.externalEnumId,
|
|
1770
|
+
'" not found'
|
|
1771
|
+
] });
|
|
1772
|
+
})() })
|
|
1773
|
+
] }),
|
|
1774
|
+
/* @__PURE__ */ jsxs("div", { style: styles5.group, children: [
|
|
1775
|
+
/* @__PURE__ */ jsx("label", { style: styles5.label, children: "Depends on" }),
|
|
1326
1776
|
/* @__PURE__ */ jsx(
|
|
1327
1777
|
DependsOnInput,
|
|
1328
1778
|
{
|
|
@@ -1333,92 +1783,101 @@ function FieldEditor() {
|
|
|
1333
1783
|
}
|
|
1334
1784
|
)
|
|
1335
1785
|
] }),
|
|
1336
|
-
/* @__PURE__ */ jsx("div", { style:
|
|
1337
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
1338
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
1339
|
-
/* @__PURE__ */ jsx("div", { style:
|
|
1340
|
-
hasCondition ? /* @__PURE__ */ jsxs("div", { style:
|
|
1341
|
-
/* @__PURE__ */ jsxs("span", { style:
|
|
1786
|
+
/* @__PURE__ */ jsx("div", { style: styles5.divider }),
|
|
1787
|
+
/* @__PURE__ */ jsxs("div", { style: styles5.conditionRow, children: [
|
|
1788
|
+
/* @__PURE__ */ jsxs("div", { style: styles5.conditionInfo, children: [
|
|
1789
|
+
/* @__PURE__ */ jsx("div", { style: styles5.label, children: "Visibility condition" }),
|
|
1790
|
+
hasCondition ? /* @__PURE__ */ jsxs("div", { style: styles5.conditionSummary, children: [
|
|
1791
|
+
/* @__PURE__ */ jsxs("span", { style: styles5.conditionBadge, children: [
|
|
1342
1792
|
ruleCount,
|
|
1343
1793
|
" rule",
|
|
1344
1794
|
ruleCount !== 1 ? "s" : "",
|
|
1345
1795
|
" \xB7 ",
|
|
1346
1796
|
field.visibleWhen.combinator.toUpperCase()
|
|
1347
1797
|
] }),
|
|
1348
|
-
/* @__PURE__ */ jsx("span", { style:
|
|
1349
|
-
] }) : /* @__PURE__ */ jsx("div", { style:
|
|
1798
|
+
/* @__PURE__ */ jsx("span", { style: styles5.conditionDesc, children: "Field is conditional" })
|
|
1799
|
+
] }) : /* @__PURE__ */ jsx("div", { style: styles5.conditionNone, children: "Always visible" })
|
|
1350
1800
|
] }),
|
|
1351
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
1352
|
-
/* @__PURE__ */ jsx("button", { style:
|
|
1801
|
+
/* @__PURE__ */ jsxs("div", { style: styles5.conditionActions, children: [
|
|
1802
|
+
/* @__PURE__ */ jsx("button", { style: styles5.editConditionBtn, onClick: () => setConditionModalOpen(true), children: hasCondition ? "Edit" : "Add" }),
|
|
1353
1803
|
hasCondition && /* @__PURE__ */ jsx(
|
|
1354
1804
|
"button",
|
|
1355
1805
|
{
|
|
1356
|
-
style:
|
|
1806
|
+
style: styles5.clearConditionBtn,
|
|
1357
1807
|
onClick: () => setFieldCondition(step.id, field.id, void 0),
|
|
1358
1808
|
children: "Clear"
|
|
1359
1809
|
}
|
|
1360
1810
|
)
|
|
1361
1811
|
] })
|
|
1362
1812
|
] }),
|
|
1363
|
-
/* @__PURE__ */ jsx("div", { style:
|
|
1364
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
1365
|
-
"
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
"input",
|
|
1389
|
-
{
|
|
1390
|
-
style: styles4.ruleInput,
|
|
1391
|
-
value: rule.value != null ? String(rule.value) : "",
|
|
1392
|
-
onChange: (e) => updateValidationRule(index, { value: e.target.value })
|
|
1393
|
-
}
|
|
1394
|
-
)
|
|
1395
|
-
] }),
|
|
1396
|
-
/* @__PURE__ */ jsxs("div", { style: styles4.ruleRow, children: [
|
|
1397
|
-
/* @__PURE__ */ jsx("label", { style: styles4.ruleLabel, children: "Error message" }),
|
|
1398
|
-
/* @__PURE__ */ jsx(
|
|
1399
|
-
"input",
|
|
1400
|
-
{
|
|
1401
|
-
style: styles4.ruleInput,
|
|
1402
|
-
value: rule.message,
|
|
1403
|
-
onChange: (e) => updateValidationRule(index, { message: e.target.value })
|
|
1404
|
-
}
|
|
1405
|
-
)
|
|
1406
|
-
] })
|
|
1407
|
-
] }, index);
|
|
1408
|
-
}),
|
|
1409
|
-
/* @__PURE__ */ jsxs("div", { style: styles4.addRule, children: [
|
|
1410
|
-
/* @__PURE__ */ jsx(
|
|
1411
|
-
"select",
|
|
1412
|
-
{
|
|
1413
|
-
style: styles4.ruleSelect,
|
|
1414
|
-
value: newValidationType,
|
|
1415
|
-
onChange: (e) => setNewValidationType(e.target.value),
|
|
1416
|
-
children: VALIDATION_TYPES.map((vt) => /* @__PURE__ */ jsx("option", { value: vt.type, children: vt.label }, vt.type))
|
|
1417
|
-
}
|
|
1418
|
-
),
|
|
1419
|
-
/* @__PURE__ */ jsx("button", { style: styles4.addRuleBtn, onClick: addValidationRule, children: "+ Add rule" })
|
|
1813
|
+
/* @__PURE__ */ jsx("div", { style: styles5.divider }),
|
|
1814
|
+
/* @__PURE__ */ jsxs("div", { style: styles5.conditionRow, children: [
|
|
1815
|
+
/* @__PURE__ */ jsxs("div", { style: styles5.conditionInfo, children: [
|
|
1816
|
+
/* @__PURE__ */ jsx("div", { style: styles5.label, children: "Validation" }),
|
|
1817
|
+
validation.length > 0 ? /* @__PURE__ */ jsxs("div", { style: styles5.conditionSummary, children: [
|
|
1818
|
+
/* @__PURE__ */ jsxs("span", { style: styles5.validationBadge, children: [
|
|
1819
|
+
validation.length,
|
|
1820
|
+
" rule",
|
|
1821
|
+
validation.length !== 1 ? "s" : "",
|
|
1822
|
+
isRequired ? " \xB7 required" : ""
|
|
1823
|
+
] }),
|
|
1824
|
+
/* @__PURE__ */ jsx("span", { style: styles5.conditionDesc, children: validation.map((r) => r.type).join(", ") })
|
|
1825
|
+
] }) : /* @__PURE__ */ jsx("div", { style: styles5.conditionNone, children: "No rules \xB7 field is optional" })
|
|
1826
|
+
] }),
|
|
1827
|
+
/* @__PURE__ */ jsxs("div", { style: styles5.conditionActions, children: [
|
|
1828
|
+
/* @__PURE__ */ jsx("button", { style: styles5.editConditionBtn, onClick: () => setValidationModalOpen(true), children: validation.length > 0 ? "Edit" : "Add" }),
|
|
1829
|
+
validation.length > 0 && /* @__PURE__ */ jsx(
|
|
1830
|
+
"button",
|
|
1831
|
+
{
|
|
1832
|
+
style: styles5.clearConditionBtn,
|
|
1833
|
+
onClick: () => updateField(step.id, field.id, { validation: void 0 }),
|
|
1834
|
+
children: "Clear"
|
|
1835
|
+
}
|
|
1836
|
+
)
|
|
1837
|
+
] })
|
|
1420
1838
|
] })
|
|
1421
1839
|
] }),
|
|
1840
|
+
validationModalOpen && /* @__PURE__ */ jsxs(
|
|
1841
|
+
Modal,
|
|
1842
|
+
{
|
|
1843
|
+
title: `Validation \u2014 "${field.label}"`,
|
|
1844
|
+
onClose: () => setValidationModalOpen(false),
|
|
1845
|
+
width: 680,
|
|
1846
|
+
children: [
|
|
1847
|
+
/* @__PURE__ */ jsx("p", { style: styles5.modalHint, children: "Define validation rules for this field. All rules must pass for the field to be valid." }),
|
|
1848
|
+
/* @__PURE__ */ jsx(
|
|
1849
|
+
ValidationBuilder,
|
|
1850
|
+
{
|
|
1851
|
+
value: validation,
|
|
1852
|
+
onChange: handleValidationChange
|
|
1853
|
+
}
|
|
1854
|
+
),
|
|
1855
|
+
/* @__PURE__ */ jsx("div", { style: styles5.modalFooter, children: /* @__PURE__ */ jsx("button", { style: styles5.modalCloseBtn, onClick: () => setValidationModalOpen(false), children: "Done" }) })
|
|
1856
|
+
]
|
|
1857
|
+
}
|
|
1858
|
+
),
|
|
1859
|
+
dynDefaultModalOpen && /* @__PURE__ */ jsx(
|
|
1860
|
+
DynDefaultModal,
|
|
1861
|
+
{
|
|
1862
|
+
rule: editingDynIdx !== null ? field.dynamicDefault?.[editingDynIdx] : void 0,
|
|
1863
|
+
onSave: (rule) => {
|
|
1864
|
+
const current = field.dynamicDefault ?? [];
|
|
1865
|
+
let updated;
|
|
1866
|
+
if (editingDynIdx !== null) {
|
|
1867
|
+
updated = current.map((r, i) => i === editingDynIdx ? rule : r);
|
|
1868
|
+
} else {
|
|
1869
|
+
updated = [...current, rule];
|
|
1870
|
+
}
|
|
1871
|
+
updateField(step.id, field.id, { dynamicDefault: updated });
|
|
1872
|
+
setDynDefaultModalOpen(false);
|
|
1873
|
+
setEditingDynIdx(null);
|
|
1874
|
+
},
|
|
1875
|
+
onClose: () => {
|
|
1876
|
+
setDynDefaultModalOpen(false);
|
|
1877
|
+
setEditingDynIdx(null);
|
|
1878
|
+
}
|
|
1879
|
+
}
|
|
1880
|
+
),
|
|
1422
1881
|
conditionModalOpen && /* @__PURE__ */ jsxs(
|
|
1423
1882
|
Modal,
|
|
1424
1883
|
{
|
|
@@ -1426,7 +1885,7 @@ function FieldEditor() {
|
|
|
1426
1885
|
onClose: () => setConditionModalOpen(false),
|
|
1427
1886
|
width: 620,
|
|
1428
1887
|
children: [
|
|
1429
|
-
/* @__PURE__ */ jsx("p", { style:
|
|
1888
|
+
/* @__PURE__ */ jsx("p", { style: styles5.modalHint, children: "Define when this field is visible within its step." }),
|
|
1430
1889
|
/* @__PURE__ */ jsx(
|
|
1431
1890
|
ConditionBuilder,
|
|
1432
1891
|
{
|
|
@@ -1436,13 +1895,103 @@ function FieldEditor() {
|
|
|
1436
1895
|
excludeFieldId: field.id
|
|
1437
1896
|
}
|
|
1438
1897
|
),
|
|
1439
|
-
/* @__PURE__ */ jsx("div", { style:
|
|
1898
|
+
/* @__PURE__ */ jsx("div", { style: styles5.modalFooter, children: /* @__PURE__ */ jsx("button", { style: styles5.modalCloseBtn, onClick: () => setConditionModalOpen(false), children: "Done" }) })
|
|
1440
1899
|
]
|
|
1441
1900
|
}
|
|
1442
1901
|
)
|
|
1443
1902
|
] });
|
|
1444
1903
|
}
|
|
1445
|
-
|
|
1904
|
+
function DynDefaultModal({
|
|
1905
|
+
rule,
|
|
1906
|
+
onSave,
|
|
1907
|
+
onClose
|
|
1908
|
+
}) {
|
|
1909
|
+
const [condition, setCondition] = useState(rule?.when);
|
|
1910
|
+
const [value, setValue] = useState(rule?.value != null ? String(rule.value) : "");
|
|
1911
|
+
const canSave = condition && condition.rules.length > 0 && value !== "";
|
|
1912
|
+
return /* @__PURE__ */ jsxs(
|
|
1913
|
+
Modal,
|
|
1914
|
+
{
|
|
1915
|
+
title: rule ? "Edit dynamic default" : "Add dynamic default",
|
|
1916
|
+
onClose,
|
|
1917
|
+
width: 620,
|
|
1918
|
+
children: [
|
|
1919
|
+
/* @__PURE__ */ jsx("p", { style: { fontSize: 13, color: "var(--wp-text-muted)", margin: "0 0 16px" }, children: "When the condition matches, this value will be used as the field default." }),
|
|
1920
|
+
/* @__PURE__ */ jsxs("div", { style: { marginBottom: 16 }, children: [
|
|
1921
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: 11, fontWeight: 600, color: "var(--wp-text-muted)", textTransform: "uppercase", letterSpacing: "0.05em", marginBottom: 6 }, children: "Condition" }),
|
|
1922
|
+
/* @__PURE__ */ jsx(ConditionBuilder, { value: condition, onChange: setCondition })
|
|
1923
|
+
] }),
|
|
1924
|
+
/* @__PURE__ */ jsxs("div", { style: { marginBottom: 20 }, children: [
|
|
1925
|
+
/* @__PURE__ */ jsx("div", { style: { fontSize: 11, fontWeight: 600, color: "var(--wp-text-muted)", textTransform: "uppercase", letterSpacing: "0.05em", marginBottom: 6 }, children: "Default value when condition matches" }),
|
|
1926
|
+
/* @__PURE__ */ jsx(
|
|
1927
|
+
"input",
|
|
1928
|
+
{
|
|
1929
|
+
style: {
|
|
1930
|
+
fontSize: 13,
|
|
1931
|
+
padding: "6px 8px",
|
|
1932
|
+
border: "1px solid var(--wp-border-muted)",
|
|
1933
|
+
borderRadius: "var(--wp-radius)",
|
|
1934
|
+
outline: "none",
|
|
1935
|
+
width: "100%",
|
|
1936
|
+
boxSizing: "border-box",
|
|
1937
|
+
background: "var(--wp-canvas)",
|
|
1938
|
+
color: "var(--wp-text)"
|
|
1939
|
+
},
|
|
1940
|
+
value,
|
|
1941
|
+
placeholder: "Value to set as default",
|
|
1942
|
+
onChange: (e) => setValue(e.target.value)
|
|
1943
|
+
}
|
|
1944
|
+
)
|
|
1945
|
+
] }),
|
|
1946
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "flex-end", gap: 8 }, children: [
|
|
1947
|
+
/* @__PURE__ */ jsx(
|
|
1948
|
+
"button",
|
|
1949
|
+
{
|
|
1950
|
+
style: {
|
|
1951
|
+
fontSize: 13,
|
|
1952
|
+
padding: "7px 16px",
|
|
1953
|
+
background: "transparent",
|
|
1954
|
+
color: "var(--wp-text-muted)",
|
|
1955
|
+
border: "1px solid var(--wp-border)",
|
|
1956
|
+
borderRadius: "var(--wp-radius-lg)",
|
|
1957
|
+
cursor: "pointer"
|
|
1958
|
+
},
|
|
1959
|
+
onClick: onClose,
|
|
1960
|
+
children: "Cancel"
|
|
1961
|
+
}
|
|
1962
|
+
),
|
|
1963
|
+
/* @__PURE__ */ jsx(
|
|
1964
|
+
"button",
|
|
1965
|
+
{
|
|
1966
|
+
disabled: !canSave,
|
|
1967
|
+
style: {
|
|
1968
|
+
fontSize: 13,
|
|
1969
|
+
padding: "7px 20px",
|
|
1970
|
+
background: canSave ? "var(--wp-primary)" : "var(--wp-border)",
|
|
1971
|
+
color: "var(--wp-canvas)",
|
|
1972
|
+
border: "none",
|
|
1973
|
+
borderRadius: "var(--wp-radius-lg)",
|
|
1974
|
+
cursor: canSave ? "pointer" : "not-allowed",
|
|
1975
|
+
fontWeight: 600,
|
|
1976
|
+
opacity: canSave ? 1 : 0.5
|
|
1977
|
+
},
|
|
1978
|
+
onClick: () => {
|
|
1979
|
+
if (!canSave || !condition) return;
|
|
1980
|
+
let parsed = value;
|
|
1981
|
+
if (value === "true") parsed = true;
|
|
1982
|
+
else if (value === "false") parsed = false;
|
|
1983
|
+
else if (!isNaN(Number(value)) && value.trim() !== "") parsed = Number(value);
|
|
1984
|
+
onSave({ when: condition, value: parsed });
|
|
1985
|
+
},
|
|
1986
|
+
children: rule ? "Update" : "Add"
|
|
1987
|
+
}
|
|
1988
|
+
)
|
|
1989
|
+
] })
|
|
1990
|
+
]
|
|
1991
|
+
}
|
|
1992
|
+
);
|
|
1993
|
+
}
|
|
1994
|
+
var styles5 = {
|
|
1446
1995
|
container: { display: "flex", flexDirection: "column", height: "100%", overflow: "hidden" },
|
|
1447
1996
|
empty: {
|
|
1448
1997
|
display: "flex",
|
|
@@ -1526,60 +2075,30 @@ var styles4 = {
|
|
|
1526
2075
|
borderRadius: "var(--wp-radius)",
|
|
1527
2076
|
cursor: "pointer"
|
|
1528
2077
|
},
|
|
1529
|
-
|
|
1530
|
-
optionalHint: { fontSize: 10, color: "var(--wp-text-subtle)", fontWeight: 400, textTransform: "none", letterSpacing: 0 },
|
|
1531
|
-
noRules: { fontSize: 12, color: "var(--wp-text-subtle)" },
|
|
1532
|
-
ruleCard: {
|
|
1533
|
-
background: "var(--wp-surface)",
|
|
1534
|
-
border: "1px solid var(--wp-border)",
|
|
1535
|
-
borderRadius: "var(--wp-radius-lg)",
|
|
1536
|
-
padding: 10,
|
|
1537
|
-
display: "flex",
|
|
1538
|
-
flexDirection: "column",
|
|
1539
|
-
gap: 8
|
|
1540
|
-
},
|
|
1541
|
-
ruleHeader: { display: "flex", justifyContent: "space-between", alignItems: "center" },
|
|
1542
|
-
ruleBadge: {
|
|
2078
|
+
validationBadge: {
|
|
1543
2079
|
fontSize: 11,
|
|
1544
2080
|
fontWeight: 700,
|
|
1545
|
-
color: "var(--wp-primary-dark)",
|
|
1546
2081
|
background: "var(--wp-primary-bg)",
|
|
2082
|
+
color: "var(--wp-primary-dark)",
|
|
1547
2083
|
padding: "2px 8px",
|
|
1548
|
-
borderRadius: 4
|
|
1549
|
-
},
|
|
1550
|
-
requiredRuleBadge: { background: "var(--wp-danger-bg-strong)", color: "var(--wp-danger)" },
|
|
1551
|
-
removeRuleBtn: { border: "none", background: "transparent", color: "var(--wp-danger)", cursor: "pointer", fontSize: 12 },
|
|
1552
|
-
ruleRow: { display: "flex", flexDirection: "column", gap: 3 },
|
|
1553
|
-
ruleLabel: { fontSize: 10, fontWeight: 600, color: "var(--wp-text-subtle)", textTransform: "uppercase" },
|
|
1554
|
-
ruleInput: {
|
|
1555
|
-
fontSize: 12,
|
|
1556
|
-
padding: "4px 6px",
|
|
1557
|
-
border: "1px solid var(--wp-border-muted)",
|
|
1558
|
-
borderRadius: 4,
|
|
1559
|
-
outline: "none",
|
|
1560
|
-
background: "var(--wp-canvas)",
|
|
1561
|
-
color: "var(--wp-text)"
|
|
1562
|
-
},
|
|
1563
|
-
addRule: { display: "flex", gap: 8, alignItems: "center" },
|
|
1564
|
-
ruleSelect: {
|
|
1565
|
-
flex: 1,
|
|
1566
|
-
fontSize: 12,
|
|
1567
|
-
padding: "5px 6px",
|
|
1568
|
-
border: "1px solid var(--wp-border-muted)",
|
|
1569
|
-
borderRadius: "var(--wp-radius)",
|
|
1570
|
-
background: "var(--wp-canvas)",
|
|
1571
|
-
color: "var(--wp-text)"
|
|
2084
|
+
borderRadius: 4
|
|
1572
2085
|
},
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
2086
|
+
enumInfo: { marginTop: 4 },
|
|
2087
|
+
enumBadge: {
|
|
2088
|
+
fontSize: 11,
|
|
2089
|
+
fontWeight: 600,
|
|
2090
|
+
padding: "2px 8px",
|
|
2091
|
+
background: "var(--wp-info-bg)",
|
|
2092
|
+
color: "var(--wp-info-text)",
|
|
2093
|
+
borderRadius: 4
|
|
2094
|
+
},
|
|
2095
|
+
enumMissing: {
|
|
2096
|
+
fontSize: 11,
|
|
2097
|
+
fontWeight: 600,
|
|
2098
|
+
padding: "2px 8px",
|
|
2099
|
+
background: "var(--wp-warning-bg)",
|
|
2100
|
+
color: "var(--wp-warning)",
|
|
2101
|
+
borderRadius: 4
|
|
1583
2102
|
},
|
|
1584
2103
|
modalHint: { fontSize: 13, color: "var(--wp-text-muted)", marginBottom: 16, marginTop: 0 },
|
|
1585
2104
|
modalFooter: { marginTop: 20, display: "flex", justifyContent: "flex-end" },
|
|
@@ -1691,6 +2210,107 @@ function getStepDependencyLabels(stepId, deps, schema) {
|
|
|
1691
2210
|
const required = deps.get(stepId) ?? /* @__PURE__ */ new Set();
|
|
1692
2211
|
return [...required].map((id) => schema.steps.find((s) => s.id === id)?.title ?? id).filter(Boolean);
|
|
1693
2212
|
}
|
|
2213
|
+
function SortableItem({ id, disabled, children }) {
|
|
2214
|
+
const {
|
|
2215
|
+
attributes,
|
|
2216
|
+
listeners,
|
|
2217
|
+
setNodeRef,
|
|
2218
|
+
transform,
|
|
2219
|
+
transition,
|
|
2220
|
+
isDragging
|
|
2221
|
+
} = useSortable({ id, disabled });
|
|
2222
|
+
const style = {
|
|
2223
|
+
transform: CSS.Transform.toString(transform),
|
|
2224
|
+
transition,
|
|
2225
|
+
opacity: isDragging ? 0.4 : 1,
|
|
2226
|
+
position: "relative"
|
|
2227
|
+
};
|
|
2228
|
+
return /* @__PURE__ */ jsx("div", { ref: setNodeRef, style, children: children({
|
|
2229
|
+
handleProps: { ...attributes, ...listeners },
|
|
2230
|
+
isDragging
|
|
2231
|
+
}) });
|
|
2232
|
+
}
|
|
2233
|
+
function DragHandle({ handleProps, disabled }) {
|
|
2234
|
+
return /* @__PURE__ */ jsx(
|
|
2235
|
+
"button",
|
|
2236
|
+
{
|
|
2237
|
+
type: "button",
|
|
2238
|
+
...handleProps,
|
|
2239
|
+
style: {
|
|
2240
|
+
...dragHandleStyle,
|
|
2241
|
+
...disabled ? dragHandleDisabledStyle : {}
|
|
2242
|
+
},
|
|
2243
|
+
title: "Drag to reorder",
|
|
2244
|
+
"aria-label": "Drag handle",
|
|
2245
|
+
children: "\u283F"
|
|
2246
|
+
}
|
|
2247
|
+
);
|
|
2248
|
+
}
|
|
2249
|
+
var dragHandleStyle = {
|
|
2250
|
+
cursor: "grab",
|
|
2251
|
+
touchAction: "none",
|
|
2252
|
+
border: "none",
|
|
2253
|
+
background: "transparent",
|
|
2254
|
+
color: "var(--wp-text-muted)",
|
|
2255
|
+
fontSize: 16,
|
|
2256
|
+
padding: "2px 4px",
|
|
2257
|
+
borderRadius: 4,
|
|
2258
|
+
display: "flex",
|
|
2259
|
+
alignItems: "center",
|
|
2260
|
+
justifyContent: "center",
|
|
2261
|
+
flexShrink: 0,
|
|
2262
|
+
lineHeight: 1
|
|
2263
|
+
};
|
|
2264
|
+
var dragHandleDisabledStyle = {
|
|
2265
|
+
cursor: "not-allowed",
|
|
2266
|
+
opacity: 0.3
|
|
2267
|
+
};
|
|
2268
|
+
function SortableList({
|
|
2269
|
+
items,
|
|
2270
|
+
disabled,
|
|
2271
|
+
onReorder,
|
|
2272
|
+
renderItem,
|
|
2273
|
+
renderOverlay
|
|
2274
|
+
}) {
|
|
2275
|
+
const [activeId, setActiveId] = useState(null);
|
|
2276
|
+
const sensors = useSensors(
|
|
2277
|
+
useSensor(PointerSensor, { activationConstraint: { distance: 8 } }),
|
|
2278
|
+
useSensor(TouchSensor, { activationConstraint: { delay: 150, tolerance: 5 } }),
|
|
2279
|
+
useSensor(KeyboardSensor)
|
|
2280
|
+
);
|
|
2281
|
+
const handleDragStart = useCallback((event) => {
|
|
2282
|
+
setActiveId(String(event.active.id));
|
|
2283
|
+
}, []);
|
|
2284
|
+
const handleDragEnd = useCallback(
|
|
2285
|
+
(event) => {
|
|
2286
|
+
setActiveId(null);
|
|
2287
|
+
const { active, over } = event;
|
|
2288
|
+
if (!over || active.id === over.id) return;
|
|
2289
|
+
const fromIndex = items.indexOf(String(active.id));
|
|
2290
|
+
const toIndex = items.indexOf(String(over.id));
|
|
2291
|
+
if (fromIndex === -1 || toIndex === -1) return;
|
|
2292
|
+
onReorder(fromIndex, toIndex);
|
|
2293
|
+
},
|
|
2294
|
+
[items, onReorder]
|
|
2295
|
+
);
|
|
2296
|
+
const handleDragCancel = useCallback(() => {
|
|
2297
|
+
setActiveId(null);
|
|
2298
|
+
}, []);
|
|
2299
|
+
return /* @__PURE__ */ jsxs(
|
|
2300
|
+
DndContext,
|
|
2301
|
+
{
|
|
2302
|
+
sensors,
|
|
2303
|
+
collisionDetection: closestCenter,
|
|
2304
|
+
onDragStart: handleDragStart,
|
|
2305
|
+
onDragEnd: handleDragEnd,
|
|
2306
|
+
onDragCancel: handleDragCancel,
|
|
2307
|
+
children: [
|
|
2308
|
+
/* @__PURE__ */ jsx(SortableContext, { items, strategy: verticalListSortingStrategy, disabled, children: items.map((id, index) => renderItem(id, index)) }),
|
|
2309
|
+
/* @__PURE__ */ jsx(DragOverlay, { dropAnimation: null, children: activeId && renderOverlay ? renderOverlay(activeId) : null })
|
|
2310
|
+
]
|
|
2311
|
+
}
|
|
2312
|
+
);
|
|
2313
|
+
}
|
|
1694
2314
|
var FIELD_TYPES = [
|
|
1695
2315
|
"text",
|
|
1696
2316
|
"number",
|
|
@@ -1713,10 +2333,14 @@ function FieldList() {
|
|
|
1713
2333
|
selectedFieldId,
|
|
1714
2334
|
addField,
|
|
1715
2335
|
removeField,
|
|
2336
|
+
duplicateField,
|
|
1716
2337
|
updateField,
|
|
1717
2338
|
selectField,
|
|
1718
2339
|
reorderFields
|
|
1719
2340
|
} = useBuilderStore();
|
|
2341
|
+
const readOnly = useBuilderReadOnly();
|
|
2342
|
+
const appCustomTypes = useBuilderCustomTypes();
|
|
2343
|
+
const externalEnums = useBuilderExternalEnums();
|
|
1720
2344
|
const [moveError, setMoveError] = useState(null);
|
|
1721
2345
|
const step = schema.steps.find((s) => s.id === selectedStepId);
|
|
1722
2346
|
const allDependencyTargets = /* @__PURE__ */ new Set();
|
|
@@ -1728,7 +2352,7 @@ function FieldList() {
|
|
|
1728
2352
|
}
|
|
1729
2353
|
}
|
|
1730
2354
|
if (!step) {
|
|
1731
|
-
return /* @__PURE__ */ jsx("div", { style:
|
|
2355
|
+
return /* @__PURE__ */ jsx("div", { style: styles6.empty, children: "Select a step on the left to manage its fields." });
|
|
1732
2356
|
}
|
|
1733
2357
|
const tryMove = (fromIndex, toIndex) => {
|
|
1734
2358
|
const check = isFieldMoveValid(step.fields, step.id, fromIndex, toIndex);
|
|
@@ -1740,127 +2364,180 @@ function FieldList() {
|
|
|
1740
2364
|
setMoveError(null);
|
|
1741
2365
|
reorderFields(step.id, fromIndex, toIndex);
|
|
1742
2366
|
};
|
|
1743
|
-
|
|
1744
|
-
|
|
2367
|
+
const fieldIds = step.fields.map((f) => f.id);
|
|
2368
|
+
const renderOverlay = (id) => {
|
|
2369
|
+
const field = step.fields.find((f) => f.id === id);
|
|
2370
|
+
if (!field) return null;
|
|
2371
|
+
const ct = appCustomTypes.find((c) => c.id === field.type);
|
|
2372
|
+
return /* @__PURE__ */ jsx("div", { style: { ...styles6.card, ...styles6.cardDragOverlay }, children: /* @__PURE__ */ jsx("div", { style: styles6.cardTop, children: /* @__PURE__ */ jsxs("div", { style: styles6.cardLeft, children: [
|
|
2373
|
+
/* @__PURE__ */ jsx("span", { style: { ...styles6.typeBadge, ...ct ? styles6.typeBadgeCustom : {} }, children: ct ? `${ct.icon ? ct.icon + " " : ""}${ct.label}` : field.type }),
|
|
2374
|
+
/* @__PURE__ */ jsx("span", { style: styles6.fieldLabel, children: field.label })
|
|
2375
|
+
] }) }) });
|
|
2376
|
+
};
|
|
2377
|
+
return /* @__PURE__ */ jsxs("div", { style: styles6.container, children: [
|
|
2378
|
+
/* @__PURE__ */ jsxs("div", { style: styles6.header, children: [
|
|
1745
2379
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
1746
|
-
/* @__PURE__ */ jsx("div", { style:
|
|
1747
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
2380
|
+
/* @__PURE__ */ jsx("div", { style: styles6.stepTitle, children: step.title }),
|
|
2381
|
+
/* @__PURE__ */ jsxs("div", { style: styles6.stepSub, children: [
|
|
1748
2382
|
step.fields.length,
|
|
1749
2383
|
" field",
|
|
1750
2384
|
step.fields.length !== 1 ? "s" : ""
|
|
1751
2385
|
] })
|
|
1752
2386
|
] }),
|
|
1753
|
-
/* @__PURE__ */ jsx("button", { style:
|
|
2387
|
+
!readOnly && /* @__PURE__ */ jsx("button", { style: styles6.addBtn, onClick: () => addField(step.id), children: "+ Add field" })
|
|
1754
2388
|
] }),
|
|
1755
|
-
moveError && /* @__PURE__ */ jsxs("div", { style:
|
|
2389
|
+
moveError && /* @__PURE__ */ jsxs("div", { style: styles6.errorBanner, children: [
|
|
1756
2390
|
/* @__PURE__ */ jsx("span", { children: "\u26A0" }),
|
|
1757
2391
|
" ",
|
|
1758
2392
|
moveError
|
|
1759
2393
|
] }),
|
|
1760
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
1761
|
-
step.fields.length === 0 && /* @__PURE__ */ jsx("div", { style:
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
{
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
2394
|
+
/* @__PURE__ */ jsxs("div", { style: styles6.list, children: [
|
|
2395
|
+
step.fields.length === 0 && /* @__PURE__ */ jsx("div", { style: styles6.emptyFields, children: 'No fields yet. Click "Add field" to start.' }),
|
|
2396
|
+
/* @__PURE__ */ jsx(
|
|
2397
|
+
SortableList,
|
|
2398
|
+
{
|
|
2399
|
+
items: fieldIds,
|
|
2400
|
+
disabled: readOnly,
|
|
2401
|
+
onReorder: tryMove,
|
|
2402
|
+
renderOverlay,
|
|
2403
|
+
renderItem: (id, index) => {
|
|
2404
|
+
const field = step.fields[index];
|
|
2405
|
+
const isSelected = field.id === selectedFieldId;
|
|
2406
|
+
const isRequired = field.validation?.some((v) => v.type === "required") ?? false;
|
|
2407
|
+
const hasCondition = !!field.visibleWhen;
|
|
2408
|
+
const hasDeps = (field.dependsOn?.length ?? 0) > 0;
|
|
2409
|
+
const enumDef = field.externalEnumId ? externalEnums.find((e) => e.id === field.externalEnumId) : void 0;
|
|
2410
|
+
const isUsedAsDep = allDependencyTargets.has(`${step.id}.${field.id}`);
|
|
2411
|
+
const canMoveUp = index > 0 && isFieldMoveValid(step.fields, step.id, index, index - 1).valid;
|
|
2412
|
+
const canMoveDown = index < step.fields.length - 1 && isFieldMoveValid(step.fields, step.id, index, index + 1).valid;
|
|
2413
|
+
const intraStepDeps = (field.dependsOn ?? []).filter((p) => p.startsWith(`${step.id}.`)).map((p) => {
|
|
2414
|
+
const fieldId = p.slice(step.id.length + 1);
|
|
2415
|
+
return step.fields.find((f) => f.id === fieldId)?.label ?? fieldId;
|
|
2416
|
+
});
|
|
2417
|
+
const intraStepDependents = step.fields.filter(
|
|
2418
|
+
(f) => f.id !== field.id && (f.dependsOn ?? []).includes(`${step.id}.${field.id}`)
|
|
2419
|
+
);
|
|
2420
|
+
return /* @__PURE__ */ jsx(SortableItem, { id: field.id, disabled: readOnly, children: ({ handleProps }) => /* @__PURE__ */ jsxs(
|
|
2421
|
+
"div",
|
|
2422
|
+
{
|
|
2423
|
+
style: { ...styles6.card, ...isSelected ? styles6.cardSelected : {} },
|
|
2424
|
+
onClick: () => selectField(field.id),
|
|
2425
|
+
children: [
|
|
2426
|
+
/* @__PURE__ */ jsxs("div", { style: styles6.cardTop, children: [
|
|
2427
|
+
/* @__PURE__ */ jsxs("div", { style: styles6.cardLeft, children: [
|
|
2428
|
+
!readOnly && /* @__PURE__ */ jsx(DragHandle, { handleProps }),
|
|
2429
|
+
(() => {
|
|
2430
|
+
const ct = appCustomTypes.find((c) => c.id === field.type);
|
|
2431
|
+
return /* @__PURE__ */ jsx("span", { style: { ...styles6.typeBadge, ...ct ? styles6.typeBadgeCustom : {} }, children: ct ? `${ct.icon ? ct.icon + " " : ""}${ct.label}` : field.type });
|
|
2432
|
+
})(),
|
|
2433
|
+
/* @__PURE__ */ jsx("span", { style: styles6.fieldLabel, children: field.label })
|
|
2434
|
+
] }),
|
|
2435
|
+
/* @__PURE__ */ jsxs("div", { style: styles6.cardRight, children: [
|
|
2436
|
+
!readOnly && /* @__PURE__ */ jsxs(
|
|
2437
|
+
"select",
|
|
2438
|
+
{
|
|
2439
|
+
style: styles6.typeSelect,
|
|
2440
|
+
value: field.type,
|
|
2441
|
+
onClick: (e) => e.stopPropagation(),
|
|
2442
|
+
onChange: (e) => {
|
|
2443
|
+
const newType = e.target.value;
|
|
2444
|
+
const customType = appCustomTypes.find((ct) => ct.id === newType);
|
|
2445
|
+
updateField(step.id, field.id, {
|
|
2446
|
+
type: newType,
|
|
2447
|
+
...customType?.defaultValidation ? { validation: customType.defaultValidation } : {}
|
|
2448
|
+
});
|
|
2449
|
+
},
|
|
2450
|
+
children: [
|
|
2451
|
+
FIELD_TYPES.map((t) => /* @__PURE__ */ jsx("option", { value: t, children: t }, t)),
|
|
2452
|
+
appCustomTypes.length > 0 && /* @__PURE__ */ jsx("optgroup", { label: "Custom", children: appCustomTypes.map((ct) => /* @__PURE__ */ jsxs("option", { value: ct.id, children: [
|
|
2453
|
+
ct.icon ? `${ct.icon} ` : "",
|
|
2454
|
+
ct.label
|
|
2455
|
+
] }, ct.id)) })
|
|
2456
|
+
]
|
|
2457
|
+
}
|
|
2458
|
+
),
|
|
2459
|
+
!readOnly && index > 0 && /* @__PURE__ */ jsx(
|
|
2460
|
+
"button",
|
|
2461
|
+
{
|
|
2462
|
+
style: { ...styles6.iconBtn, ...canMoveUp ? {} : styles6.iconBtnBlocked },
|
|
2463
|
+
title: canMoveUp ? "Move up" : "Can't move \u2014 dependency order required",
|
|
2464
|
+
onClick: (e) => {
|
|
2465
|
+
e.stopPropagation();
|
|
2466
|
+
tryMove(index, index - 1);
|
|
2467
|
+
},
|
|
2468
|
+
children: "\u2191"
|
|
2469
|
+
}
|
|
2470
|
+
),
|
|
2471
|
+
!readOnly && index < step.fields.length - 1 && /* @__PURE__ */ jsx(
|
|
2472
|
+
"button",
|
|
2473
|
+
{
|
|
2474
|
+
style: { ...styles6.iconBtn, ...canMoveDown ? {} : styles6.iconBtnBlocked },
|
|
2475
|
+
title: canMoveDown ? "Move down" : "Can't move \u2014 dependency order required",
|
|
2476
|
+
onClick: (e) => {
|
|
2477
|
+
e.stopPropagation();
|
|
2478
|
+
tryMove(index, index + 1);
|
|
2479
|
+
},
|
|
2480
|
+
children: "\u2193"
|
|
2481
|
+
}
|
|
2482
|
+
),
|
|
2483
|
+
!readOnly && /* @__PURE__ */ jsx(
|
|
2484
|
+
"button",
|
|
2485
|
+
{
|
|
2486
|
+
style: styles6.iconBtn,
|
|
2487
|
+
title: "Duplicate field",
|
|
2488
|
+
onClick: (e) => {
|
|
2489
|
+
e.stopPropagation();
|
|
2490
|
+
duplicateField(step.id, field.id);
|
|
2491
|
+
},
|
|
2492
|
+
children: "\u29C9"
|
|
2493
|
+
}
|
|
2494
|
+
),
|
|
2495
|
+
!readOnly && /* @__PURE__ */ jsx(
|
|
2496
|
+
"button",
|
|
2497
|
+
{
|
|
2498
|
+
style: { ...styles6.iconBtn, color: "var(--wp-danger)" },
|
|
2499
|
+
title: "Remove field",
|
|
2500
|
+
onClick: (e) => {
|
|
2501
|
+
e.stopPropagation();
|
|
2502
|
+
removeField(step.id, field.id);
|
|
2503
|
+
},
|
|
2504
|
+
children: "\u2715"
|
|
2505
|
+
}
|
|
2506
|
+
)
|
|
2507
|
+
] })
|
|
2508
|
+
] }),
|
|
2509
|
+
/* @__PURE__ */ jsxs("div", { style: styles6.badges, children: [
|
|
2510
|
+
!isRequired && /* @__PURE__ */ jsx("span", { style: styles6.badgeOptional, children: "optional" }),
|
|
2511
|
+
isRequired && /* @__PURE__ */ jsx("span", { style: styles6.badgeRequired, children: "required" }),
|
|
2512
|
+
hasCondition && /* @__PURE__ */ jsx("span", { style: styles6.badgeCondition, children: "conditional" }),
|
|
2513
|
+
hasDeps && /* @__PURE__ */ jsxs("span", { style: styles6.badgeDep, children: [
|
|
2514
|
+
"depends on ",
|
|
2515
|
+
field.dependsOn.length
|
|
2516
|
+
] }),
|
|
2517
|
+
isUsedAsDep && /* @__PURE__ */ jsx("span", { style: styles6.badgeUsed, children: "\u2190 dependency" }),
|
|
2518
|
+
field.externalEnumId && /* @__PURE__ */ jsxs("span", { style: styles6.badgeEnum, children: [
|
|
2519
|
+
"\u229E ",
|
|
2520
|
+
enumDef ? enumDef.label : field.externalEnumId
|
|
2521
|
+
] })
|
|
2522
|
+
] }),
|
|
2523
|
+
intraStepDeps.length > 0 && /* @__PURE__ */ jsxs("div", { style: styles6.depRow, children: [
|
|
2524
|
+
/* @__PURE__ */ jsx("span", { style: styles6.depLabel, children: "needs:" }),
|
|
2525
|
+
intraStepDeps.map((label) => /* @__PURE__ */ jsx("span", { style: styles6.depBadge, children: label }, label))
|
|
2526
|
+
] }),
|
|
2527
|
+
intraStepDependents.length > 0 && /* @__PURE__ */ jsxs("div", { style: styles6.depRow, children: [
|
|
2528
|
+
/* @__PURE__ */ jsx("span", { style: styles6.depLabelUsed, children: "used by:" }),
|
|
2529
|
+
intraStepDependents.map((f) => /* @__PURE__ */ jsx("span", { style: styles6.depBadgeUsed, children: f.label }, f.id))
|
|
2530
|
+
] })
|
|
2531
|
+
]
|
|
2532
|
+
}
|
|
2533
|
+
) }, field.id);
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
)
|
|
1860
2537
|
] })
|
|
1861
2538
|
] });
|
|
1862
2539
|
}
|
|
1863
|
-
var
|
|
2540
|
+
var styles6 = {
|
|
1864
2541
|
container: { display: "flex", flexDirection: "column", height: "100%" },
|
|
1865
2542
|
empty: {
|
|
1866
2543
|
display: "flex",
|
|
@@ -1917,6 +2594,12 @@ var styles5 = {
|
|
|
1917
2594
|
gap: 6
|
|
1918
2595
|
},
|
|
1919
2596
|
cardSelected: { background: "var(--wp-primary-muted)", border: "1px solid var(--wp-primary-border)" },
|
|
2597
|
+
cardDragOverlay: {
|
|
2598
|
+
boxShadow: "0 4px 16px rgba(0,0,0,0.25)",
|
|
2599
|
+
border: "1px solid var(--wp-primary-border)",
|
|
2600
|
+
background: "var(--wp-surface)",
|
|
2601
|
+
opacity: 0.95
|
|
2602
|
+
},
|
|
1920
2603
|
cardTop: { display: "flex", alignItems: "center", justifyContent: "space-between" },
|
|
1921
2604
|
cardLeft: { display: "flex", alignItems: "center", gap: 8, minWidth: 0 },
|
|
1922
2605
|
cardRight: { display: "flex", alignItems: "center", gap: 4, flexShrink: 0 },
|
|
@@ -1929,6 +2612,10 @@ var styles5 = {
|
|
|
1929
2612
|
fontWeight: 600,
|
|
1930
2613
|
flexShrink: 0
|
|
1931
2614
|
},
|
|
2615
|
+
typeBadgeCustom: {
|
|
2616
|
+
background: "var(--wp-success-bg)",
|
|
2617
|
+
color: "var(--wp-success)"
|
|
2618
|
+
},
|
|
1932
2619
|
fieldLabel: {
|
|
1933
2620
|
fontSize: 13,
|
|
1934
2621
|
fontWeight: 600,
|
|
@@ -2003,6 +2690,14 @@ var styles5 = {
|
|
|
2003
2690
|
borderRadius: 3,
|
|
2004
2691
|
textTransform: "uppercase"
|
|
2005
2692
|
},
|
|
2693
|
+
badgeEnum: {
|
|
2694
|
+
fontSize: 9,
|
|
2695
|
+
fontWeight: 600,
|
|
2696
|
+
padding: "1px 6px",
|
|
2697
|
+
background: "var(--wp-info-bg)",
|
|
2698
|
+
color: "var(--wp-info-text)",
|
|
2699
|
+
borderRadius: 3
|
|
2700
|
+
},
|
|
2006
2701
|
depRow: { display: "flex", alignItems: "center", flexWrap: "wrap", gap: 4 },
|
|
2007
2702
|
depLabel: { fontSize: 10, fontWeight: 600, color: "var(--wp-text-muted)", textTransform: "uppercase" },
|
|
2008
2703
|
depLabelUsed: { fontSize: 10, fontWeight: 600, color: "var(--wp-success)", textTransform: "uppercase" },
|
|
@@ -2023,12 +2718,28 @@ var styles5 = {
|
|
|
2023
2718
|
borderRadius: 4
|
|
2024
2719
|
}
|
|
2025
2720
|
};
|
|
2026
|
-
function PreviewPanel({ store, schema }) {
|
|
2721
|
+
function PreviewPanel({ store, schema, externalEnums }) {
|
|
2027
2722
|
const [done, setDone] = useState(false);
|
|
2028
|
-
const { tree, currentStep, progress } = useWaypoint(store);
|
|
2723
|
+
const { tree, currentStep, progress } = useWaypoint(store, externalEnums);
|
|
2029
2724
|
const stepId = currentStep?.definition.id ?? "";
|
|
2030
2725
|
const { fields, stepData, setFieldValue } = useWaypointStep(store, stepId);
|
|
2031
2726
|
const [errors, setErrors] = useState({});
|
|
2727
|
+
const extVarDefs = schema.externalVariables ?? [];
|
|
2728
|
+
const [mockVars, setMockVars] = useState(() => {
|
|
2729
|
+
const initial = {};
|
|
2730
|
+
for (const v of extVarDefs) {
|
|
2731
|
+
initial[v.id] = v.type === "boolean" ? false : v.type === "number" ? 0 : "";
|
|
2732
|
+
}
|
|
2733
|
+
return initial;
|
|
2734
|
+
});
|
|
2735
|
+
useEffect(() => {
|
|
2736
|
+
for (const [varId, value] of Object.entries(mockVars)) {
|
|
2737
|
+
store.getState().setExternalVar(varId, value);
|
|
2738
|
+
}
|
|
2739
|
+
}, [mockVars]);
|
|
2740
|
+
function handleMockVarChange(varId, value) {
|
|
2741
|
+
setMockVars((prev) => ({ ...prev, [varId]: value }));
|
|
2742
|
+
}
|
|
2032
2743
|
function handleNext() {
|
|
2033
2744
|
const newErrors = {};
|
|
2034
2745
|
for (const field of fields) {
|
|
@@ -2048,8 +2759,11 @@ function PreviewPanel({ store, schema }) {
|
|
|
2048
2759
|
setErrors({});
|
|
2049
2760
|
const oldIds = tree.steps.map((s) => s.definition.id).join(",");
|
|
2050
2761
|
store.getState().setStepData(stepId, stepData);
|
|
2762
|
+
if ((store.getState().skippedSteps ?? []).includes(stepId)) {
|
|
2763
|
+
store.getState().unskipStep(stepId);
|
|
2764
|
+
}
|
|
2051
2765
|
const newData = store.getState().data;
|
|
2052
|
-
const newTree = resolveTree(schema, newData,
|
|
2766
|
+
const newTree = resolveTree(schema, newData, store.getState().externalVars, externalEnums);
|
|
2053
2767
|
const newIds = newTree.steps.map((s) => s.definition.id).join(",");
|
|
2054
2768
|
if (oldIds !== newIds) {
|
|
2055
2769
|
store.getState().truncateHistoryAt(stepId);
|
|
@@ -2067,6 +2781,9 @@ function PreviewPanel({ store, schema }) {
|
|
|
2067
2781
|
}
|
|
2068
2782
|
function handleRestart() {
|
|
2069
2783
|
store.getState().init(schema);
|
|
2784
|
+
for (const [varId, value] of Object.entries(mockVars)) {
|
|
2785
|
+
store.getState().setExternalVar(varId, value);
|
|
2786
|
+
}
|
|
2070
2787
|
setDone(false);
|
|
2071
2788
|
setErrors({});
|
|
2072
2789
|
}
|
|
@@ -2074,77 +2791,124 @@ function PreviewPanel({ store, schema }) {
|
|
|
2074
2791
|
(s) => s.definition.id === currentStep?.definition.id
|
|
2075
2792
|
);
|
|
2076
2793
|
if (done) {
|
|
2077
|
-
return /* @__PURE__ */ jsxs("div", { style:
|
|
2078
|
-
/* @__PURE__ */
|
|
2794
|
+
return /* @__PURE__ */ jsxs("div", { style: styles7.panel, children: [
|
|
2795
|
+
/* @__PURE__ */ jsxs("div", { style: styles7.leftCol, children: [
|
|
2796
|
+
/* @__PURE__ */ jsx(
|
|
2797
|
+
StepList,
|
|
2798
|
+
{
|
|
2799
|
+
tree,
|
|
2800
|
+
currentIdx,
|
|
2801
|
+
onSelect: (id) => store.getState().setCurrentStep(id),
|
|
2802
|
+
skippedStepIds: store.getState().skippedSteps
|
|
2803
|
+
}
|
|
2804
|
+
),
|
|
2805
|
+
extVarDefs.length > 0 && /* @__PURE__ */ jsx(
|
|
2806
|
+
MockVarPanel,
|
|
2807
|
+
{
|
|
2808
|
+
extVarDefs,
|
|
2809
|
+
mockVars,
|
|
2810
|
+
onChange: handleMockVarChange
|
|
2811
|
+
}
|
|
2812
|
+
)
|
|
2813
|
+
] }),
|
|
2814
|
+
/* @__PURE__ */ jsx("div", { style: styles7.divider }),
|
|
2815
|
+
/* @__PURE__ */ jsx("div", { style: styles7.rightCol, children: /* @__PURE__ */ jsxs("div", { style: styles7.doneScreen, children: [
|
|
2816
|
+
/* @__PURE__ */ jsx("div", { style: styles7.doneIcon, children: "\u2713" }),
|
|
2817
|
+
/* @__PURE__ */ jsx("div", { style: styles7.doneTitle, children: "Parcours termin\xE9 !" }),
|
|
2818
|
+
/* @__PURE__ */ jsx("p", { style: styles7.doneText, children: "Toutes les \xE9tapes ont \xE9t\xE9 compl\xE9t\xE9es avec succ\xE8s." }),
|
|
2819
|
+
/* @__PURE__ */ jsx("button", { style: styles7.primaryBtn, onClick: handleRestart, children: "Recommencer" })
|
|
2820
|
+
] }) })
|
|
2821
|
+
] });
|
|
2822
|
+
}
|
|
2823
|
+
return /* @__PURE__ */ jsxs("div", { style: styles7.panel, children: [
|
|
2824
|
+
/* @__PURE__ */ jsx(DevPanel, { store }),
|
|
2825
|
+
/* @__PURE__ */ jsxs("div", { style: styles7.leftCol, children: [
|
|
2826
|
+
/* @__PURE__ */ jsx(
|
|
2079
2827
|
StepList,
|
|
2080
2828
|
{
|
|
2081
2829
|
tree,
|
|
2082
2830
|
currentIdx,
|
|
2083
2831
|
onSelect: (id) => store.getState().setCurrentStep(id)
|
|
2084
2832
|
}
|
|
2085
|
-
)
|
|
2086
|
-
/* @__PURE__ */ jsx(
|
|
2087
|
-
|
|
2088
|
-
/* @__PURE__ */ jsx("div", { style: styles6.doneIcon, children: "\u2713" }),
|
|
2089
|
-
/* @__PURE__ */ jsx("div", { style: styles6.doneTitle, children: "Parcours termin\xE9 !" }),
|
|
2090
|
-
/* @__PURE__ */ jsx("p", { style: styles6.doneText, children: "Toutes les \xE9tapes ont \xE9t\xE9 compl\xE9t\xE9es avec succ\xE8s." }),
|
|
2091
|
-
/* @__PURE__ */ jsx("button", { style: styles6.primaryBtn, onClick: handleRestart, children: "Recommencer" })
|
|
2092
|
-
] }) })
|
|
2093
|
-
] });
|
|
2094
|
-
}
|
|
2095
|
-
return /* @__PURE__ */ jsxs("div", { style: styles6.panel, children: [
|
|
2096
|
-
/* @__PURE__ */ jsx(DevPanel, { store }),
|
|
2097
|
-
/* @__PURE__ */ jsx("div", { style: styles6.leftCol, children: /* @__PURE__ */ jsx(
|
|
2098
|
-
StepList,
|
|
2099
|
-
{
|
|
2100
|
-
tree,
|
|
2101
|
-
currentIdx,
|
|
2102
|
-
onSelect: (id) => store.getState().setCurrentStep(id)
|
|
2103
|
-
}
|
|
2104
|
-
) }),
|
|
2105
|
-
/* @__PURE__ */ jsx("div", { style: styles6.divider }),
|
|
2106
|
-
/* @__PURE__ */ jsx("div", { style: styles6.rightCol, children: /* @__PURE__ */ jsxs("div", { style: styles6.stepRenderer, children: [
|
|
2107
|
-
/* @__PURE__ */ jsx("div", { style: styles6.progressTrack, children: /* @__PURE__ */ jsx("div", { style: { ...styles6.progressFill, width: `${progress}%` } }) }),
|
|
2108
|
-
/* @__PURE__ */ jsx("h2", { style: styles6.stepTitle, children: currentStep?.definition.title ?? "" }),
|
|
2109
|
-
/* @__PURE__ */ jsx("div", { style: styles6.fieldsContainer, children: fields.map((field) => /* @__PURE__ */ jsx(
|
|
2110
|
-
FieldRenderer,
|
|
2833
|
+
),
|
|
2834
|
+
extVarDefs.length > 0 && /* @__PURE__ */ jsx(
|
|
2835
|
+
MockVarPanel,
|
|
2111
2836
|
{
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2837
|
+
extVarDefs,
|
|
2838
|
+
mockVars,
|
|
2839
|
+
onChange: handleMockVarChange
|
|
2840
|
+
}
|
|
2841
|
+
)
|
|
2842
|
+
] }),
|
|
2843
|
+
/* @__PURE__ */ jsx("div", { style: styles7.divider }),
|
|
2844
|
+
/* @__PURE__ */ jsx("div", { style: styles7.rightCol, children: /* @__PURE__ */ jsxs("div", { style: styles7.stepRenderer, children: [
|
|
2845
|
+
/* @__PURE__ */ jsx("div", { style: styles7.progressTrack, children: /* @__PURE__ */ jsx("div", { style: { ...styles7.progressFill, width: `${progress}%` } }) }),
|
|
2846
|
+
/* @__PURE__ */ jsx("h2", { style: styles7.stepTitle, children: currentStep?.definition.title ?? "" }),
|
|
2847
|
+
/* @__PURE__ */ jsx("div", { style: styles7.fieldsContainer, children: fields.map((field) => {
|
|
2848
|
+
const storedVal = stepData[field.definition.id];
|
|
2849
|
+
const displayVal = storedVal !== void 0 && storedVal !== null && storedVal !== "" ? storedVal : field.resolvedDefaultValue ?? field.definition.defaultValue ?? void 0;
|
|
2850
|
+
return /* @__PURE__ */ jsx(
|
|
2851
|
+
FieldRenderer,
|
|
2852
|
+
{
|
|
2853
|
+
field,
|
|
2854
|
+
value: displayVal,
|
|
2855
|
+
error: errors[field.definition.id],
|
|
2856
|
+
onChange: (val) => {
|
|
2857
|
+
setFieldValue(field.definition.id, val);
|
|
2858
|
+
if (errors[field.definition.id]) {
|
|
2859
|
+
setErrors((prev) => {
|
|
2860
|
+
const next = { ...prev };
|
|
2861
|
+
delete next[field.definition.id];
|
|
2862
|
+
return next;
|
|
2863
|
+
});
|
|
2864
|
+
}
|
|
2123
2865
|
}
|
|
2124
|
-
}
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
)
|
|
2128
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
2129
|
-
currentIdx > 0 && /* @__PURE__ */ jsx("button", { style:
|
|
2130
|
-
/* @__PURE__ */
|
|
2866
|
+
},
|
|
2867
|
+
field.definition.id
|
|
2868
|
+
);
|
|
2869
|
+
}) }),
|
|
2870
|
+
/* @__PURE__ */ jsxs("div", { style: styles7.navRow, children: [
|
|
2871
|
+
currentIdx > 0 && /* @__PURE__ */ jsx("button", { style: styles7.secondaryBtn, onClick: handlePrev, children: "\u2190 Pr\xE9c\xE9dent" }),
|
|
2872
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8, marginLeft: "auto" }, children: [
|
|
2873
|
+
currentStep?.definition.skippable && /* @__PURE__ */ jsx(
|
|
2874
|
+
"button",
|
|
2875
|
+
{
|
|
2876
|
+
style: styles7.secondaryBtn,
|
|
2877
|
+
onClick: () => {
|
|
2878
|
+
setErrors({});
|
|
2879
|
+
store.getState().skipStep(stepId);
|
|
2880
|
+
const next = getNextStep(tree.steps, stepId);
|
|
2881
|
+
if (next) {
|
|
2882
|
+
store.getState().setCurrentStep(next.definition.id);
|
|
2883
|
+
} else {
|
|
2884
|
+
setDone(true);
|
|
2885
|
+
}
|
|
2886
|
+
},
|
|
2887
|
+
children: "Passer"
|
|
2888
|
+
}
|
|
2889
|
+
),
|
|
2890
|
+
/* @__PURE__ */ jsx("button", { style: styles7.primaryBtn, onClick: handleNext, children: getNextStep(tree.steps, stepId) ? "Continuer \u2192" : "Terminer \u2713" })
|
|
2891
|
+
] })
|
|
2131
2892
|
] })
|
|
2132
2893
|
] }) })
|
|
2133
2894
|
] });
|
|
2134
2895
|
}
|
|
2135
|
-
function StepList({ tree, currentIdx, onSelect }) {
|
|
2896
|
+
function StepList({ tree, currentIdx, onSelect, skippedStepIds }) {
|
|
2897
|
+
const skipped = new Set(skippedStepIds ?? []);
|
|
2136
2898
|
const allSteps = [
|
|
2137
2899
|
...tree.steps.map((s) => ({ ...s, hidden: false })),
|
|
2138
2900
|
...tree.hiddenSteps.map((s) => ({ ...s, hidden: true }))
|
|
2139
2901
|
];
|
|
2140
|
-
return /* @__PURE__ */ jsxs("div", { style:
|
|
2141
|
-
/* @__PURE__ */ jsx("div", { style:
|
|
2902
|
+
return /* @__PURE__ */ jsxs("div", { style: styles7.stepList, children: [
|
|
2903
|
+
/* @__PURE__ */ jsx("div", { style: styles7.stepListTitle, children: "\xC9tapes" }),
|
|
2142
2904
|
allSteps.map((step) => {
|
|
2143
|
-
const
|
|
2905
|
+
const isStepVisible = !step.hidden;
|
|
2144
2906
|
const visIdx = tree.steps.findIndex((s) => s.definition.id === step.definition.id);
|
|
2907
|
+
const isSkipped = skipped.has(step.definition.id);
|
|
2145
2908
|
let status = "hidden";
|
|
2146
|
-
if (
|
|
2147
|
-
if (visIdx < currentIdx) status = "
|
|
2909
|
+
if (isStepVisible) {
|
|
2910
|
+
if (isSkipped && visIdx < currentIdx) status = "skipped";
|
|
2911
|
+
else if (visIdx < currentIdx) status = "done";
|
|
2148
2912
|
else if (visIdx === currentIdx) status = "current";
|
|
2149
2913
|
else status = "upcoming";
|
|
2150
2914
|
}
|
|
@@ -2152,23 +2916,26 @@ function StepList({ tree, currentIdx, onSelect }) {
|
|
|
2152
2916
|
"div",
|
|
2153
2917
|
{
|
|
2154
2918
|
style: {
|
|
2155
|
-
...
|
|
2156
|
-
...status === "current" ?
|
|
2157
|
-
...status === "hidden" ?
|
|
2158
|
-
|
|
2919
|
+
...styles7.stepItem,
|
|
2920
|
+
...status === "current" ? styles7.stepItemCurrent : {},
|
|
2921
|
+
...status === "hidden" ? styles7.stepItemHidden : {},
|
|
2922
|
+
...status === "skipped" ? { opacity: 0.6 } : {},
|
|
2923
|
+
cursor: status === "done" || status === "skipped" ? "pointer" : "default"
|
|
2159
2924
|
},
|
|
2160
2925
|
onClick: () => {
|
|
2161
|
-
if (status === "done") onSelect(step.definition.id);
|
|
2926
|
+
if (status === "done" || status === "skipped") onSelect(step.definition.id);
|
|
2162
2927
|
},
|
|
2163
2928
|
children: [
|
|
2164
|
-
/* @__PURE__ */ jsxs("span", { style:
|
|
2929
|
+
/* @__PURE__ */ jsxs("span", { style: styles7.stepStatus, children: [
|
|
2165
2930
|
status === "done" && "\u2713",
|
|
2931
|
+
status === "skipped" && "\u23ED",
|
|
2166
2932
|
status === "current" && "\u2192",
|
|
2167
2933
|
status === "upcoming" && "\u25CB",
|
|
2168
2934
|
status === "hidden" && "\u2013"
|
|
2169
2935
|
] }),
|
|
2170
|
-
/* @__PURE__ */ jsx("span", { style:
|
|
2171
|
-
status === "hidden" && /* @__PURE__ */ jsx("span", { style:
|
|
2936
|
+
/* @__PURE__ */ jsx("span", { style: styles7.stepName, children: step.definition.title }),
|
|
2937
|
+
status === "hidden" && /* @__PURE__ */ jsx("span", { style: styles7.hiddenBadge, children: "hidden" }),
|
|
2938
|
+
status === "skipped" && /* @__PURE__ */ jsx("span", { style: { ...styles7.hiddenBadge, color: "var(--wp-warning)", background: "var(--wp-warning-bg)" }, children: "skipped" })
|
|
2172
2939
|
]
|
|
2173
2940
|
},
|
|
2174
2941
|
step.definition.id
|
|
@@ -2176,13 +2943,51 @@ function StepList({ tree, currentIdx, onSelect }) {
|
|
|
2176
2943
|
})
|
|
2177
2944
|
] });
|
|
2178
2945
|
}
|
|
2946
|
+
function MockVarPanel({ extVarDefs, mockVars, onChange }) {
|
|
2947
|
+
return /* @__PURE__ */ jsxs("div", { style: styles7.mockPanel, children: [
|
|
2948
|
+
/* @__PURE__ */ jsxs("div", { style: styles7.mockPanelTitle, children: [
|
|
2949
|
+
/* @__PURE__ */ jsx("span", { children: "\u26A1 External Variables" }),
|
|
2950
|
+
/* @__PURE__ */ jsx("span", { style: styles7.mockPanelHint, children: "mock values" })
|
|
2951
|
+
] }),
|
|
2952
|
+
extVarDefs.map((v) => /* @__PURE__ */ jsxs("div", { style: styles7.mockVarRow, children: [
|
|
2953
|
+
/* @__PURE__ */ jsxs("div", { style: styles7.mockVarLabel, children: [
|
|
2954
|
+
/* @__PURE__ */ jsxs("span", { style: styles7.mockVarId, children: [
|
|
2955
|
+
"$",
|
|
2956
|
+
`ext.${v.id}`
|
|
2957
|
+
] }),
|
|
2958
|
+
v.blocking && /* @__PURE__ */ jsx("span", { style: styles7.mockBlockingBadge, children: "!" })
|
|
2959
|
+
] }),
|
|
2960
|
+
v.type === "boolean" ? /* @__PURE__ */ jsxs("label", { style: styles7.mockCheckRow, children: [
|
|
2961
|
+
/* @__PURE__ */ jsx(
|
|
2962
|
+
"input",
|
|
2963
|
+
{
|
|
2964
|
+
type: "checkbox",
|
|
2965
|
+
checked: Boolean(mockVars[v.id]),
|
|
2966
|
+
onChange: (e) => onChange(v.id, e.target.checked)
|
|
2967
|
+
}
|
|
2968
|
+
),
|
|
2969
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 11, color: "var(--wp-text-muted)" }, children: String(mockVars[v.id]) })
|
|
2970
|
+
] }) : /* @__PURE__ */ jsx(
|
|
2971
|
+
"input",
|
|
2972
|
+
{
|
|
2973
|
+
style: styles7.mockInput,
|
|
2974
|
+
type: v.type === "number" ? "number" : "text",
|
|
2975
|
+
value: String(mockVars[v.id] ?? ""),
|
|
2976
|
+
placeholder: v.label,
|
|
2977
|
+
onChange: (e) => onChange(v.id, v.type === "number" ? Number(e.target.value) : e.target.value)
|
|
2978
|
+
}
|
|
2979
|
+
)
|
|
2980
|
+
] }, v.id))
|
|
2981
|
+
] });
|
|
2982
|
+
}
|
|
2179
2983
|
function FieldRenderer({ field, value, error, onChange }) {
|
|
2180
2984
|
const { definition } = field;
|
|
2181
|
-
const
|
|
2182
|
-
|
|
2183
|
-
|
|
2985
|
+
const options = field.resolvedOptions ?? definition.options ?? [];
|
|
2986
|
+
const inputStyle2 = { ...styles7.input, ...error ? styles7.inputError : {} };
|
|
2987
|
+
return /* @__PURE__ */ jsxs("div", { style: styles7.fieldGroup, children: [
|
|
2988
|
+
/* @__PURE__ */ jsxs("label", { style: styles7.label, children: [
|
|
2184
2989
|
definition.label,
|
|
2185
|
-
definition.validation?.some((r) => r.type === "required") && /* @__PURE__ */ jsx("span", { style:
|
|
2990
|
+
definition.validation?.some((r) => r.type === "required") && /* @__PURE__ */ jsx("span", { style: styles7.required, children: " *" })
|
|
2186
2991
|
] }),
|
|
2187
2992
|
(definition.type === "text" || definition.type === "email" || definition.type === "tel" || definition.type === "password" || definition.type === "url" || definition.type === "number" || definition.type === "date") && /* @__PURE__ */ jsx(
|
|
2188
2993
|
"input",
|
|
@@ -2211,7 +3016,7 @@ function FieldRenderer({ field, value, error, onChange }) {
|
|
|
2211
3016
|
onChange: (e) => onChange(e.target.value),
|
|
2212
3017
|
children: [
|
|
2213
3018
|
/* @__PURE__ */ jsx("option", { value: "", children: "\u2014 Choisir \u2014" }),
|
|
2214
|
-
|
|
3019
|
+
options.map((opt) => /* @__PURE__ */ jsx("option", { value: String(opt.value), children: opt.label }, String(opt.value)))
|
|
2215
3020
|
]
|
|
2216
3021
|
}
|
|
2217
3022
|
),
|
|
@@ -2225,10 +3030,10 @@ function FieldRenderer({ field, value, error, onChange }) {
|
|
|
2225
3030
|
const selected = Array.from(e.target.selectedOptions).map((o) => o.value);
|
|
2226
3031
|
onChange(selected);
|
|
2227
3032
|
},
|
|
2228
|
-
children:
|
|
3033
|
+
children: options.map((opt) => /* @__PURE__ */ jsx("option", { value: String(opt.value), children: opt.label }, String(opt.value)))
|
|
2229
3034
|
}
|
|
2230
3035
|
),
|
|
2231
|
-
definition.type === "radio" && /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children:
|
|
3036
|
+
definition.type === "radio" && /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: 6 }, children: options.map((opt) => /* @__PURE__ */ jsxs("label", { style: { display: "flex", alignItems: "center", gap: 8, cursor: "pointer", fontSize: 13 }, children: [
|
|
2232
3037
|
/* @__PURE__ */ jsx(
|
|
2233
3038
|
"input",
|
|
2234
3039
|
{
|
|
@@ -2252,10 +3057,10 @@ function FieldRenderer({ field, value, error, onChange }) {
|
|
|
2252
3057
|
),
|
|
2253
3058
|
definition.placeholder ?? definition.label
|
|
2254
3059
|
] }),
|
|
2255
|
-
error && /* @__PURE__ */ jsx("div", { style:
|
|
3060
|
+
error && /* @__PURE__ */ jsx("div", { style: styles7.errorMsg, children: error })
|
|
2256
3061
|
] });
|
|
2257
3062
|
}
|
|
2258
|
-
var
|
|
3063
|
+
var styles7 = {
|
|
2259
3064
|
panel: {
|
|
2260
3065
|
display: "flex",
|
|
2261
3066
|
flex: 1,
|
|
@@ -2424,6 +3229,80 @@ var styles6 = {
|
|
|
2424
3229
|
letterSpacing: "0.3px",
|
|
2425
3230
|
flexShrink: 0
|
|
2426
3231
|
},
|
|
3232
|
+
// Mock var panel
|
|
3233
|
+
mockPanel: {
|
|
3234
|
+
borderTop: "1px solid var(--wp-border)",
|
|
3235
|
+
padding: "12px",
|
|
3236
|
+
display: "flex",
|
|
3237
|
+
flexDirection: "column",
|
|
3238
|
+
gap: 8
|
|
3239
|
+
},
|
|
3240
|
+
mockPanelTitle: {
|
|
3241
|
+
display: "flex",
|
|
3242
|
+
alignItems: "center",
|
|
3243
|
+
justifyContent: "space-between",
|
|
3244
|
+
fontSize: 11,
|
|
3245
|
+
fontWeight: 700,
|
|
3246
|
+
color: "var(--wp-text-muted)",
|
|
3247
|
+
textTransform: "uppercase",
|
|
3248
|
+
letterSpacing: "0.5px",
|
|
3249
|
+
marginBottom: 4
|
|
3250
|
+
},
|
|
3251
|
+
mockPanelHint: {
|
|
3252
|
+
fontSize: 9,
|
|
3253
|
+
fontWeight: 500,
|
|
3254
|
+
color: "var(--wp-warning)",
|
|
3255
|
+
textTransform: "none",
|
|
3256
|
+
background: "var(--wp-warning-bg)",
|
|
3257
|
+
padding: "1px 5px",
|
|
3258
|
+
borderRadius: 4
|
|
3259
|
+
},
|
|
3260
|
+
mockVarRow: {
|
|
3261
|
+
display: "flex",
|
|
3262
|
+
flexDirection: "column",
|
|
3263
|
+
gap: 3
|
|
3264
|
+
},
|
|
3265
|
+
mockVarLabel: {
|
|
3266
|
+
display: "flex",
|
|
3267
|
+
alignItems: "center",
|
|
3268
|
+
gap: 4
|
|
3269
|
+
},
|
|
3270
|
+
mockVarId: {
|
|
3271
|
+
fontSize: 10,
|
|
3272
|
+
fontFamily: "monospace",
|
|
3273
|
+
fontWeight: 600,
|
|
3274
|
+
color: "var(--wp-text-secondary)"
|
|
3275
|
+
},
|
|
3276
|
+
mockBlockingBadge: {
|
|
3277
|
+
fontSize: 9,
|
|
3278
|
+
fontWeight: 700,
|
|
3279
|
+
width: 13,
|
|
3280
|
+
height: 13,
|
|
3281
|
+
borderRadius: "50%",
|
|
3282
|
+
background: "var(--wp-danger-bg-strong)",
|
|
3283
|
+
color: "var(--wp-danger)",
|
|
3284
|
+
display: "flex",
|
|
3285
|
+
alignItems: "center",
|
|
3286
|
+
justifyContent: "center",
|
|
3287
|
+
flexShrink: 0
|
|
3288
|
+
},
|
|
3289
|
+
mockInput: {
|
|
3290
|
+
fontSize: 11,
|
|
3291
|
+
padding: "4px 6px",
|
|
3292
|
+
border: "1px solid var(--wp-border-muted)",
|
|
3293
|
+
borderRadius: "var(--wp-radius)",
|
|
3294
|
+
background: "var(--wp-canvas)",
|
|
3295
|
+
color: "var(--wp-text)",
|
|
3296
|
+
outline: "none",
|
|
3297
|
+
width: "100%",
|
|
3298
|
+
boxSizing: "border-box"
|
|
3299
|
+
},
|
|
3300
|
+
mockCheckRow: {
|
|
3301
|
+
display: "flex",
|
|
3302
|
+
alignItems: "center",
|
|
3303
|
+
gap: 6,
|
|
3304
|
+
cursor: "pointer"
|
|
3305
|
+
},
|
|
2427
3306
|
// Done screen
|
|
2428
3307
|
doneScreen: {
|
|
2429
3308
|
display: "flex",
|
|
@@ -2460,83 +3339,100 @@ var styles6 = {
|
|
|
2460
3339
|
};
|
|
2461
3340
|
function StepEditor() {
|
|
2462
3341
|
const { schema, selectedStepId, updateStep, setStepCondition } = useBuilderStore();
|
|
3342
|
+
const readOnly = useBuilderReadOnly();
|
|
2463
3343
|
const [conditionModalOpen, setConditionModalOpen] = useState(false);
|
|
2464
3344
|
const step = schema.steps.find((s) => s.id === selectedStepId);
|
|
2465
3345
|
if (!step) {
|
|
2466
|
-
return /* @__PURE__ */ jsx("div", { style:
|
|
3346
|
+
return /* @__PURE__ */ jsx("div", { style: styles8.empty, children: "Select a step to configure its properties." });
|
|
2467
3347
|
}
|
|
2468
3348
|
const hasCondition = !!step.visibleWhen;
|
|
2469
3349
|
const ruleCount = step.visibleWhen?.rules.length ?? 0;
|
|
2470
|
-
return /* @__PURE__ */ jsxs("div", { style:
|
|
2471
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
2472
|
-
/* @__PURE__ */ jsx("div", { style:
|
|
2473
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
3350
|
+
return /* @__PURE__ */ jsxs("div", { style: styles8.container, children: [
|
|
3351
|
+
/* @__PURE__ */ jsxs("div", { style: styles8.header, children: [
|
|
3352
|
+
/* @__PURE__ */ jsx("div", { style: styles8.headerTitle, children: "Step Config" }),
|
|
3353
|
+
/* @__PURE__ */ jsxs("div", { style: styles8.stepId, children: [
|
|
2474
3354
|
"id: ",
|
|
2475
3355
|
step.id
|
|
2476
3356
|
] })
|
|
2477
3357
|
] }),
|
|
2478
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
2479
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
2480
|
-
/* @__PURE__ */ jsx("label", { style:
|
|
3358
|
+
/* @__PURE__ */ jsxs("div", { style: styles8.body, children: [
|
|
3359
|
+
/* @__PURE__ */ jsxs("div", { style: styles8.group, children: [
|
|
3360
|
+
/* @__PURE__ */ jsx("label", { style: styles8.label, children: "Title" }),
|
|
2481
3361
|
/* @__PURE__ */ jsx(
|
|
2482
3362
|
"input",
|
|
2483
3363
|
{
|
|
2484
|
-
style:
|
|
3364
|
+
style: styles8.input,
|
|
2485
3365
|
value: step.title,
|
|
2486
3366
|
placeholder: "Step title",
|
|
2487
|
-
|
|
3367
|
+
readOnly,
|
|
3368
|
+
onChange: readOnly ? void 0 : (e) => updateStep(step.id, { title: e.target.value })
|
|
2488
3369
|
}
|
|
2489
3370
|
)
|
|
2490
3371
|
] }),
|
|
2491
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
2492
|
-
/* @__PURE__ */ jsx("label", { style:
|
|
3372
|
+
/* @__PURE__ */ jsxs("div", { style: styles8.group, children: [
|
|
3373
|
+
/* @__PURE__ */ jsx("label", { style: styles8.label, children: "URL" }),
|
|
2493
3374
|
/* @__PURE__ */ jsx(
|
|
2494
3375
|
"input",
|
|
2495
3376
|
{
|
|
2496
|
-
style:
|
|
3377
|
+
style: styles8.input,
|
|
2497
3378
|
value: step.url,
|
|
2498
3379
|
placeholder: "/onboarding/step-name",
|
|
2499
|
-
|
|
3380
|
+
readOnly,
|
|
3381
|
+
onChange: readOnly ? void 0 : (e) => updateStep(step.id, { url: e.target.value })
|
|
2500
3382
|
}
|
|
2501
3383
|
),
|
|
2502
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
3384
|
+
/* @__PURE__ */ jsxs("div", { style: styles8.hint, children: [
|
|
2503
3385
|
"Supports ",
|
|
2504
3386
|
"{{PARAM}}",
|
|
2505
3387
|
" placeholders"
|
|
2506
3388
|
] })
|
|
2507
3389
|
] }),
|
|
2508
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
3390
|
+
/* @__PURE__ */ jsxs("div", { style: styles8.checkRow, children: [
|
|
2509
3391
|
/* @__PURE__ */ jsx(
|
|
2510
3392
|
"input",
|
|
2511
3393
|
{
|
|
2512
3394
|
type: "checkbox",
|
|
2513
3395
|
id: `resume-${step.id}`,
|
|
2514
3396
|
checked: !!step.enableResumeFromHere,
|
|
2515
|
-
|
|
3397
|
+
disabled: readOnly,
|
|
3398
|
+
onChange: readOnly ? void 0 : (e) => updateStep(step.id, { enableResumeFromHere: e.target.checked || void 0 })
|
|
2516
3399
|
}
|
|
2517
3400
|
),
|
|
2518
|
-
/* @__PURE__ */ jsx("label", { htmlFor: `resume-${step.id}`, style:
|
|
3401
|
+
/* @__PURE__ */ jsx("label", { htmlFor: `resume-${step.id}`, style: styles8.checkLabel, children: "Resume from this step" })
|
|
2519
3402
|
] }),
|
|
2520
|
-
/* @__PURE__ */
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
3403
|
+
/* @__PURE__ */ jsxs("div", { style: styles8.checkRow, children: [
|
|
3404
|
+
/* @__PURE__ */ jsx(
|
|
3405
|
+
"input",
|
|
3406
|
+
{
|
|
3407
|
+
type: "checkbox",
|
|
3408
|
+
id: `skippable-${step.id}`,
|
|
3409
|
+
checked: !!step.skippable,
|
|
3410
|
+
disabled: readOnly,
|
|
3411
|
+
onChange: readOnly ? void 0 : (e) => updateStep(step.id, { skippable: e.target.checked || void 0 })
|
|
3412
|
+
}
|
|
3413
|
+
),
|
|
3414
|
+
/* @__PURE__ */ jsx("label", { htmlFor: `skippable-${step.id}`, style: styles8.checkLabel, children: "Skippable (user can bypass this step)" })
|
|
3415
|
+
] }),
|
|
3416
|
+
/* @__PURE__ */ jsx("div", { style: styles8.divider }),
|
|
3417
|
+
/* @__PURE__ */ jsxs("div", { style: styles8.conditionRow, children: [
|
|
3418
|
+
/* @__PURE__ */ jsxs("div", { style: styles8.conditionInfo, children: [
|
|
3419
|
+
/* @__PURE__ */ jsx("div", { style: styles8.label, children: "Visibility condition" }),
|
|
3420
|
+
hasCondition ? /* @__PURE__ */ jsxs("div", { style: styles8.conditionSummary, children: [
|
|
3421
|
+
/* @__PURE__ */ jsxs("span", { style: styles8.conditionBadge, children: [
|
|
2526
3422
|
ruleCount,
|
|
2527
3423
|
" rule",
|
|
2528
3424
|
ruleCount !== 1 ? "s" : "",
|
|
2529
3425
|
" \xB7 ",
|
|
2530
3426
|
step.visibleWhen.combinator.toUpperCase()
|
|
2531
3427
|
] }),
|
|
2532
|
-
/* @__PURE__ */ jsx("span", { style:
|
|
2533
|
-
] }) : /* @__PURE__ */ jsx("div", { style:
|
|
3428
|
+
/* @__PURE__ */ jsx("span", { style: styles8.conditionDesc, children: "Step is conditional" })
|
|
3429
|
+
] }) : /* @__PURE__ */ jsx("div", { style: styles8.conditionNone, children: "Always visible" })
|
|
2534
3430
|
] }),
|
|
2535
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
3431
|
+
!readOnly && /* @__PURE__ */ jsxs("div", { style: styles8.conditionActions, children: [
|
|
2536
3432
|
/* @__PURE__ */ jsx(
|
|
2537
3433
|
"button",
|
|
2538
3434
|
{
|
|
2539
|
-
style:
|
|
3435
|
+
style: styles8.editConditionBtn,
|
|
2540
3436
|
onClick: () => setConditionModalOpen(true),
|
|
2541
3437
|
children: hasCondition ? "Edit" : "Add condition"
|
|
2542
3438
|
}
|
|
@@ -2544,7 +3440,7 @@ function StepEditor() {
|
|
|
2544
3440
|
hasCondition && /* @__PURE__ */ jsx(
|
|
2545
3441
|
"button",
|
|
2546
3442
|
{
|
|
2547
|
-
style:
|
|
3443
|
+
style: styles8.clearConditionBtn,
|
|
2548
3444
|
onClick: () => setStepCondition(step.id, void 0),
|
|
2549
3445
|
children: "Clear"
|
|
2550
3446
|
}
|
|
@@ -2559,7 +3455,7 @@ function StepEditor() {
|
|
|
2559
3455
|
onClose: () => setConditionModalOpen(false),
|
|
2560
3456
|
width: 620,
|
|
2561
3457
|
children: [
|
|
2562
|
-
/* @__PURE__ */ jsx("p", { style:
|
|
3458
|
+
/* @__PURE__ */ jsx("p", { style: styles8.modalHint, children: "Define when this step is visible. Leave empty to always show it." }),
|
|
2563
3459
|
/* @__PURE__ */ jsx(
|
|
2564
3460
|
ConditionBuilder,
|
|
2565
3461
|
{
|
|
@@ -2567,10 +3463,10 @@ function StepEditor() {
|
|
|
2567
3463
|
onChange: (c) => setStepCondition(step.id, c)
|
|
2568
3464
|
}
|
|
2569
3465
|
),
|
|
2570
|
-
/* @__PURE__ */ jsx("div", { style:
|
|
3466
|
+
/* @__PURE__ */ jsx("div", { style: styles8.modalFooter, children: /* @__PURE__ */ jsx(
|
|
2571
3467
|
"button",
|
|
2572
3468
|
{
|
|
2573
|
-
style:
|
|
3469
|
+
style: styles8.modalCloseBtn,
|
|
2574
3470
|
onClick: () => setConditionModalOpen(false),
|
|
2575
3471
|
children: "Done"
|
|
2576
3472
|
}
|
|
@@ -2580,7 +3476,7 @@ function StepEditor() {
|
|
|
2580
3476
|
)
|
|
2581
3477
|
] });
|
|
2582
3478
|
}
|
|
2583
|
-
var
|
|
3479
|
+
var styles8 = {
|
|
2584
3480
|
container: { display: "flex", flexDirection: "column", height: "100%", overflow: "hidden" },
|
|
2585
3481
|
empty: {
|
|
2586
3482
|
display: "flex",
|
|
@@ -2669,128 +3565,164 @@ var styles7 = {
|
|
|
2669
3565
|
}
|
|
2670
3566
|
};
|
|
2671
3567
|
function StepList2() {
|
|
2672
|
-
const { schema, selectedStepId, addStep, removeStep, selectStep, reorderSteps } = useBuilderStore();
|
|
3568
|
+
const { schema, selectedStepId, addStep, removeStep, duplicateStep, selectStep, reorderSteps } = useBuilderStore();
|
|
3569
|
+
const readOnly = useBuilderReadOnly();
|
|
2673
3570
|
const [moveError, setMoveError] = useState(null);
|
|
2674
3571
|
const steps = schema.steps;
|
|
2675
3572
|
const deps = computeStepDependencies(schema);
|
|
2676
|
-
const tryMove = (
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
3573
|
+
const tryMove = useCallback(
|
|
3574
|
+
(fromIndex, toIndex) => {
|
|
3575
|
+
const check = isMoveValid(steps, deps, fromIndex, toIndex);
|
|
3576
|
+
if (!check.valid) {
|
|
3577
|
+
setMoveError(check.reason ?? "Invalid move");
|
|
3578
|
+
setTimeout(() => setMoveError(null), 3e3);
|
|
3579
|
+
return;
|
|
3580
|
+
}
|
|
3581
|
+
setMoveError(null);
|
|
3582
|
+
reorderSteps(fromIndex, toIndex);
|
|
3583
|
+
},
|
|
3584
|
+
[steps, deps, reorderSteps]
|
|
3585
|
+
);
|
|
3586
|
+
const stepIds = steps.map((s) => s.id);
|
|
3587
|
+
const renderOverlay = (id) => {
|
|
3588
|
+
const step = steps.find((s) => s.id === id);
|
|
3589
|
+
if (!step) return null;
|
|
3590
|
+
const index = steps.indexOf(step);
|
|
3591
|
+
return /* @__PURE__ */ jsx("div", { style: { ...styles9.card, ...styles9.cardDragOverlay }, children: /* @__PURE__ */ jsx("div", { style: styles9.cardMain, children: /* @__PURE__ */ jsxs("div", { style: styles9.cardLeft, children: [
|
|
3592
|
+
/* @__PURE__ */ jsx("div", { style: styles9.cardIndex, children: index + 1 }),
|
|
3593
|
+
/* @__PURE__ */ jsx("div", { style: styles9.cardTitle, children: step.title })
|
|
3594
|
+
] }) }) });
|
|
2685
3595
|
};
|
|
2686
|
-
return /* @__PURE__ */ jsxs("div", { style:
|
|
2687
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
2688
|
-
/* @__PURE__ */ jsxs("span", { style:
|
|
3596
|
+
return /* @__PURE__ */ jsxs("div", { style: styles9.container, children: [
|
|
3597
|
+
/* @__PURE__ */ jsxs("div", { style: styles9.header, children: [
|
|
3598
|
+
/* @__PURE__ */ jsxs("span", { style: styles9.title, children: [
|
|
2689
3599
|
"Steps (",
|
|
2690
3600
|
steps.length,
|
|
2691
3601
|
")"
|
|
2692
3602
|
] }),
|
|
2693
|
-
/* @__PURE__ */ jsx("button", { style:
|
|
3603
|
+
!readOnly && /* @__PURE__ */ jsx("button", { style: styles9.addBtn, onClick: () => addStep(), children: "+ Add step" })
|
|
2694
3604
|
] }),
|
|
2695
|
-
moveError && /* @__PURE__ */ jsxs("div", { style:
|
|
2696
|
-
/* @__PURE__ */ jsx("span", { style:
|
|
3605
|
+
moveError && /* @__PURE__ */ jsxs("div", { style: styles9.errorBanner, children: [
|
|
3606
|
+
/* @__PURE__ */ jsx("span", { style: styles9.errorIcon, children: "\u26A0" }),
|
|
2697
3607
|
moveError
|
|
2698
3608
|
] }),
|
|
2699
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
2700
|
-
steps.length === 0 && /* @__PURE__ */ jsx("div", { style:
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
children:
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
3609
|
+
/* @__PURE__ */ jsxs("div", { style: styles9.list, children: [
|
|
3610
|
+
steps.length === 0 && /* @__PURE__ */ jsx("div", { style: styles9.empty, children: 'No steps yet. Click "Add step" to start.' }),
|
|
3611
|
+
/* @__PURE__ */ jsx(
|
|
3612
|
+
SortableList,
|
|
3613
|
+
{
|
|
3614
|
+
items: stepIds,
|
|
3615
|
+
disabled: readOnly,
|
|
3616
|
+
onReorder: tryMove,
|
|
3617
|
+
renderOverlay,
|
|
3618
|
+
renderItem: (id, index) => {
|
|
3619
|
+
const step = steps[index];
|
|
3620
|
+
const isSelected = step.id === selectedStepId;
|
|
3621
|
+
const hasCondition = !!step.visibleWhen;
|
|
3622
|
+
const depLabels = getStepDependencyLabels(step.id, deps, schema);
|
|
3623
|
+
const canMoveUp = index > 0 && isMoveValid(steps, deps, index, index - 1).valid;
|
|
3624
|
+
const canMoveDown = index < steps.length - 1 && isMoveValid(steps, deps, index, index + 1).valid;
|
|
3625
|
+
const dependents = steps.filter(
|
|
3626
|
+
(s) => (deps.get(s.id) ?? /* @__PURE__ */ new Set()).has(step.id)
|
|
3627
|
+
);
|
|
3628
|
+
return /* @__PURE__ */ jsx(SortableItem, { id: step.id, disabled: readOnly, children: ({ handleProps }) => /* @__PURE__ */ jsxs(
|
|
3629
|
+
"div",
|
|
3630
|
+
{
|
|
3631
|
+
style: {
|
|
3632
|
+
...styles9.card,
|
|
3633
|
+
...isSelected ? styles9.cardSelected : {}
|
|
3634
|
+
},
|
|
3635
|
+
onClick: () => selectStep(step.id),
|
|
3636
|
+
children: [
|
|
3637
|
+
/* @__PURE__ */ jsxs("div", { style: styles9.cardMain, children: [
|
|
3638
|
+
/* @__PURE__ */ jsxs("div", { style: styles9.cardLeft, children: [
|
|
3639
|
+
!readOnly && /* @__PURE__ */ jsx(DragHandle, { handleProps }),
|
|
3640
|
+
/* @__PURE__ */ jsx("div", { style: styles9.cardIndex, children: index + 1 }),
|
|
3641
|
+
/* @__PURE__ */ jsxs("div", { style: { minWidth: 0 }, children: [
|
|
3642
|
+
/* @__PURE__ */ jsx("div", { style: styles9.cardTitle, children: step.title }),
|
|
3643
|
+
/* @__PURE__ */ jsxs("div", { style: styles9.cardMeta, children: [
|
|
3644
|
+
step.fields.length,
|
|
3645
|
+
" field",
|
|
3646
|
+
step.fields.length !== 1 ? "s" : "",
|
|
3647
|
+
hasCondition && /* @__PURE__ */ jsx("span", { style: styles9.conditionBadge, children: "conditional" })
|
|
3648
|
+
] })
|
|
3649
|
+
] })
|
|
3650
|
+
] }),
|
|
3651
|
+
!readOnly && /* @__PURE__ */ jsxs("div", { style: styles9.cardActions, children: [
|
|
3652
|
+
index > 0 && /* @__PURE__ */ jsx(
|
|
3653
|
+
"button",
|
|
3654
|
+
{
|
|
3655
|
+
style: {
|
|
3656
|
+
...styles9.iconBtn,
|
|
3657
|
+
...canMoveUp ? {} : styles9.iconBtnBlocked
|
|
3658
|
+
},
|
|
3659
|
+
title: canMoveUp ? "Move up" : `Can't move up \u2014 dependency order required`,
|
|
3660
|
+
onClick: (e) => {
|
|
3661
|
+
e.stopPropagation();
|
|
3662
|
+
tryMove(index, index - 1);
|
|
3663
|
+
},
|
|
3664
|
+
children: "\u2191"
|
|
3665
|
+
}
|
|
3666
|
+
),
|
|
3667
|
+
index < steps.length - 1 && /* @__PURE__ */ jsx(
|
|
3668
|
+
"button",
|
|
3669
|
+
{
|
|
3670
|
+
style: {
|
|
3671
|
+
...styles9.iconBtn,
|
|
3672
|
+
...canMoveDown ? {} : styles9.iconBtnBlocked
|
|
3673
|
+
},
|
|
3674
|
+
title: canMoveDown ? "Move down" : `Can't move down \u2014 dependency order required`,
|
|
3675
|
+
onClick: (e) => {
|
|
3676
|
+
e.stopPropagation();
|
|
3677
|
+
tryMove(index, index + 1);
|
|
3678
|
+
},
|
|
3679
|
+
children: "\u2193"
|
|
3680
|
+
}
|
|
3681
|
+
),
|
|
3682
|
+
/* @__PURE__ */ jsx(
|
|
3683
|
+
"button",
|
|
3684
|
+
{
|
|
3685
|
+
style: styles9.iconBtn,
|
|
3686
|
+
title: "Duplicate step",
|
|
3687
|
+
onClick: (e) => {
|
|
3688
|
+
e.stopPropagation();
|
|
3689
|
+
duplicateStep(step.id);
|
|
3690
|
+
},
|
|
3691
|
+
children: "\u29C9"
|
|
3692
|
+
}
|
|
3693
|
+
),
|
|
3694
|
+
/* @__PURE__ */ jsx(
|
|
3695
|
+
"button",
|
|
3696
|
+
{
|
|
3697
|
+
style: { ...styles9.iconBtn, ...styles9.deleteBtn },
|
|
3698
|
+
title: "Remove step",
|
|
3699
|
+
onClick: (e) => {
|
|
3700
|
+
e.stopPropagation();
|
|
3701
|
+
removeStep(step.id);
|
|
3702
|
+
},
|
|
3703
|
+
children: "\u2715"
|
|
3704
|
+
}
|
|
3705
|
+
)
|
|
2729
3706
|
] })
|
|
3707
|
+
] }),
|
|
3708
|
+
depLabels.length > 0 && /* @__PURE__ */ jsxs("div", { style: styles9.depRow, children: [
|
|
3709
|
+
/* @__PURE__ */ jsx("span", { style: styles9.depLabel, children: "needs:" }),
|
|
3710
|
+
depLabels.map((label) => /* @__PURE__ */ jsx("span", { style: styles9.depBadge, children: label }, label))
|
|
3711
|
+
] }),
|
|
3712
|
+
dependents.length > 0 && /* @__PURE__ */ jsxs("div", { style: styles9.depRow, children: [
|
|
3713
|
+
/* @__PURE__ */ jsx("span", { style: styles9.depLabelUsed, children: "used by:" }),
|
|
3714
|
+
dependents.map((s) => /* @__PURE__ */ jsx("span", { style: styles9.depBadgeUsed, children: s.title }, s.id))
|
|
2730
3715
|
] })
|
|
2731
|
-
]
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
...styles8.iconBtn,
|
|
2738
|
-
...canMoveUp ? {} : styles8.iconBtnBlocked
|
|
2739
|
-
},
|
|
2740
|
-
title: canMoveUp ? "Move up" : `Can't move up \u2014 dependency order required`,
|
|
2741
|
-
onClick: (e) => {
|
|
2742
|
-
e.stopPropagation();
|
|
2743
|
-
tryMove(index, index - 1);
|
|
2744
|
-
},
|
|
2745
|
-
children: "\u2191"
|
|
2746
|
-
}
|
|
2747
|
-
),
|
|
2748
|
-
index < steps.length - 1 && /* @__PURE__ */ jsx(
|
|
2749
|
-
"button",
|
|
2750
|
-
{
|
|
2751
|
-
style: {
|
|
2752
|
-
...styles8.iconBtn,
|
|
2753
|
-
...canMoveDown ? {} : styles8.iconBtnBlocked
|
|
2754
|
-
},
|
|
2755
|
-
title: canMoveDown ? "Move down" : `Can't move down \u2014 dependency order required`,
|
|
2756
|
-
onClick: (e) => {
|
|
2757
|
-
e.stopPropagation();
|
|
2758
|
-
tryMove(index, index + 1);
|
|
2759
|
-
},
|
|
2760
|
-
children: "\u2193"
|
|
2761
|
-
}
|
|
2762
|
-
),
|
|
2763
|
-
/* @__PURE__ */ jsx(
|
|
2764
|
-
"button",
|
|
2765
|
-
{
|
|
2766
|
-
style: { ...styles8.iconBtn, ...styles8.deleteBtn },
|
|
2767
|
-
title: "Remove step",
|
|
2768
|
-
onClick: (e) => {
|
|
2769
|
-
e.stopPropagation();
|
|
2770
|
-
removeStep(step.id);
|
|
2771
|
-
},
|
|
2772
|
-
children: "\u2715"
|
|
2773
|
-
}
|
|
2774
|
-
)
|
|
2775
|
-
] })
|
|
2776
|
-
] }),
|
|
2777
|
-
depLabels.length > 0 && /* @__PURE__ */ jsxs("div", { style: styles8.depRow, children: [
|
|
2778
|
-
/* @__PURE__ */ jsx("span", { style: styles8.depLabel, children: "needs:" }),
|
|
2779
|
-
depLabels.map((label) => /* @__PURE__ */ jsx("span", { style: styles8.depBadge, children: label }, label))
|
|
2780
|
-
] }),
|
|
2781
|
-
dependents.length > 0 && /* @__PURE__ */ jsxs("div", { style: styles8.depRow, children: [
|
|
2782
|
-
/* @__PURE__ */ jsx("span", { style: styles8.depLabelUsed, children: "used by:" }),
|
|
2783
|
-
dependents.map((s) => /* @__PURE__ */ jsx("span", { style: styles8.depBadgeUsed, children: s.title }, s.id))
|
|
2784
|
-
] })
|
|
2785
|
-
]
|
|
2786
|
-
},
|
|
2787
|
-
step.id
|
|
2788
|
-
);
|
|
2789
|
-
})
|
|
3716
|
+
]
|
|
3717
|
+
}
|
|
3718
|
+
) }, step.id);
|
|
3719
|
+
}
|
|
3720
|
+
}
|
|
3721
|
+
)
|
|
2790
3722
|
] })
|
|
2791
3723
|
] });
|
|
2792
3724
|
}
|
|
2793
|
-
var
|
|
3725
|
+
var styles9 = {
|
|
2794
3726
|
container: { display: "flex", flexDirection: "column", height: "100%" },
|
|
2795
3727
|
header: {
|
|
2796
3728
|
display: "flex",
|
|
@@ -2838,6 +3770,12 @@ var styles8 = {
|
|
|
2838
3770
|
gap: 6
|
|
2839
3771
|
},
|
|
2840
3772
|
cardSelected: { background: "var(--wp-primary-muted)", border: "1px solid var(--wp-primary-border)" },
|
|
3773
|
+
cardDragOverlay: {
|
|
3774
|
+
boxShadow: "0 4px 16px rgba(0,0,0,0.25)",
|
|
3775
|
+
border: "1px solid var(--wp-primary-border)",
|
|
3776
|
+
background: "var(--wp-surface)",
|
|
3777
|
+
opacity: 0.95
|
|
3778
|
+
},
|
|
2841
3779
|
cardMain: { display: "flex", alignItems: "center", justifyContent: "space-between" },
|
|
2842
3780
|
cardLeft: { display: "flex", alignItems: "center", gap: 10, minWidth: 0, flex: 1 },
|
|
2843
3781
|
cardIndex: {
|
|
@@ -2910,7 +3848,7 @@ var styles8 = {
|
|
|
2910
3848
|
borderRadius: 4
|
|
2911
3849
|
}
|
|
2912
3850
|
};
|
|
2913
|
-
function Toolbar({ onSave, previewMode, onTest, isMobile }) {
|
|
3851
|
+
function Toolbar({ onSave, previewMode, onTest, isMobile, readOnly }) {
|
|
2914
3852
|
const { schema, isDirty, resetSchema } = useBuilderStore();
|
|
2915
3853
|
const handleExport = () => {
|
|
2916
3854
|
const json = JSON.stringify(schema, null, 2);
|
|
@@ -2950,31 +3888,31 @@ ${result.errors.map((e2) => `\u2022 ${e2}`).join("\n")}`);
|
|
|
2950
3888
|
input.click();
|
|
2951
3889
|
};
|
|
2952
3890
|
if (previewMode) {
|
|
2953
|
-
return /* @__PURE__ */ jsxs("div", { style:
|
|
2954
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
2955
|
-
/* @__PURE__ */ jsx("span", { style:
|
|
2956
|
-
/* @__PURE__ */ jsx("span", { style:
|
|
3891
|
+
return /* @__PURE__ */ jsxs("div", { style: styles10.toolbar, children: [
|
|
3892
|
+
/* @__PURE__ */ jsxs("div", { style: styles10.left, children: [
|
|
3893
|
+
/* @__PURE__ */ jsx("span", { style: styles10.logo, children: "\u25C8 waypoint" }),
|
|
3894
|
+
/* @__PURE__ */ jsx("span", { style: styles10.separator, children: "/" }),
|
|
2957
3895
|
/* @__PURE__ */ jsx(
|
|
2958
3896
|
"button",
|
|
2959
3897
|
{
|
|
2960
|
-
style: { ...
|
|
3898
|
+
style: { ...styles10.btn, ...styles10.editBtn },
|
|
2961
3899
|
onClick: onTest,
|
|
2962
3900
|
children: "\u2190 \xC9diter"
|
|
2963
3901
|
}
|
|
2964
3902
|
)
|
|
2965
3903
|
] }),
|
|
2966
|
-
/* @__PURE__ */ jsx("div", { style:
|
|
3904
|
+
/* @__PURE__ */ jsx("div", { style: styles10.right, children: /* @__PURE__ */ jsx("span", { style: { fontSize: 12, color: "var(--wp-text-muted)", fontStyle: "italic" }, children: "Mode aper\xE7u" }) })
|
|
2967
3905
|
] });
|
|
2968
3906
|
}
|
|
2969
|
-
return /* @__PURE__ */ jsxs("div", { style:
|
|
2970
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
2971
|
-
!isMobile && /* @__PURE__ */ jsx("span", { style:
|
|
2972
|
-
!isMobile && /* @__PURE__ */ jsx("span", { style:
|
|
3907
|
+
return /* @__PURE__ */ jsxs("div", { style: styles10.toolbar, children: [
|
|
3908
|
+
/* @__PURE__ */ jsxs("div", { style: styles10.left, children: [
|
|
3909
|
+
!isMobile && /* @__PURE__ */ jsx("span", { style: styles10.logo, children: "\u25C8 waypoint" }),
|
|
3910
|
+
!isMobile && /* @__PURE__ */ jsx("span", { style: styles10.separator, children: "/" }),
|
|
2973
3911
|
/* @__PURE__ */ jsx(
|
|
2974
3912
|
"input",
|
|
2975
3913
|
{
|
|
2976
3914
|
style: {
|
|
2977
|
-
...
|
|
3915
|
+
...styles10.journeyName,
|
|
2978
3916
|
...isMobile ? { maxWidth: 120, fontSize: 12 } : {}
|
|
2979
3917
|
},
|
|
2980
3918
|
value: schema.name,
|
|
@@ -2985,25 +3923,26 @@ ${result.errors.map((e2) => `\u2022 ${e2}`).join("\n")}`);
|
|
|
2985
3923
|
}))
|
|
2986
3924
|
}
|
|
2987
3925
|
),
|
|
2988
|
-
isDirty && /* @__PURE__ */ jsx("span", { style:
|
|
3926
|
+
isDirty && /* @__PURE__ */ jsx("span", { style: styles10.dirtyDot, title: "Unsaved changes" })
|
|
2989
3927
|
] }),
|
|
2990
|
-
/* @__PURE__ */ jsxs("div", { style:
|
|
2991
|
-
|
|
2992
|
-
/* @__PURE__ */ jsx("button", { style:
|
|
2993
|
-
/* @__PURE__ */ jsx("button", { style:
|
|
2994
|
-
|
|
3928
|
+
/* @__PURE__ */ jsxs("div", { style: styles10.right, children: [
|
|
3929
|
+
readOnly && /* @__PURE__ */ jsx("span", { style: styles10.readOnlyBadge, children: "View only" }),
|
|
3930
|
+
!readOnly && onTest && /* @__PURE__ */ jsx("button", { style: { ...styles10.btn, ...styles10.testBtn }, onClick: onTest, title: "Tester", children: isMobile ? "\u25B6" : "\u25B6 Tester" }),
|
|
3931
|
+
!readOnly && /* @__PURE__ */ jsx("button", { style: styles10.btn, onClick: handleImport, title: "Import", children: isMobile ? "\u2193" : "Import" }),
|
|
3932
|
+
/* @__PURE__ */ jsx("button", { style: styles10.btn, onClick: handleExport, title: "Export JSON", children: isMobile ? "\u2191" : "Export JSON" }),
|
|
3933
|
+
!readOnly && onSave && /* @__PURE__ */ jsx(
|
|
2995
3934
|
"button",
|
|
2996
3935
|
{
|
|
2997
|
-
style: { ...
|
|
3936
|
+
style: { ...styles10.btn, ...styles10.saveBtn },
|
|
2998
3937
|
onClick: () => onSave(schema),
|
|
2999
3938
|
title: "Save",
|
|
3000
3939
|
children: isMobile ? "\u2713" : "Save"
|
|
3001
3940
|
}
|
|
3002
3941
|
),
|
|
3003
|
-
/* @__PURE__ */ jsx(
|
|
3942
|
+
!readOnly && /* @__PURE__ */ jsx(
|
|
3004
3943
|
"button",
|
|
3005
3944
|
{
|
|
3006
|
-
style: { ...
|
|
3945
|
+
style: { ...styles10.btn, color: "var(--wp-danger)" },
|
|
3007
3946
|
title: "Reset",
|
|
3008
3947
|
onClick: () => {
|
|
3009
3948
|
if (confirm("Reset the journey? All changes will be lost.")) resetSchema();
|
|
@@ -3014,7 +3953,7 @@ ${result.errors.map((e2) => `\u2022 ${e2}`).join("\n")}`);
|
|
|
3014
3953
|
] })
|
|
3015
3954
|
] });
|
|
3016
3955
|
}
|
|
3017
|
-
var
|
|
3956
|
+
var styles10 = {
|
|
3018
3957
|
toolbar: {
|
|
3019
3958
|
display: "flex",
|
|
3020
3959
|
alignItems: "center",
|
|
@@ -3056,6 +3995,15 @@ var styles9 = {
|
|
|
3056
3995
|
fontWeight: 500
|
|
3057
3996
|
},
|
|
3058
3997
|
saveBtn: { background: "var(--wp-primary)", color: "var(--wp-canvas)", border: "1px solid var(--wp-primary)" },
|
|
3998
|
+
readOnlyBadge: {
|
|
3999
|
+
fontSize: 11,
|
|
4000
|
+
fontWeight: 600,
|
|
4001
|
+
color: "var(--wp-text-subtle)",
|
|
4002
|
+
background: "var(--wp-surface)",
|
|
4003
|
+
border: "1px solid var(--wp-border)",
|
|
4004
|
+
borderRadius: "var(--wp-radius)",
|
|
4005
|
+
padding: "3px 8px"
|
|
4006
|
+
},
|
|
3059
4007
|
testBtn: { background: "var(--wp-success, #22c55e)", color: "#fff", border: "1px solid var(--wp-success, #22c55e)", fontWeight: 600 },
|
|
3060
4008
|
editBtn: { background: "transparent", color: "var(--wp-toolbar-text)", border: "none", fontWeight: 600, cursor: "pointer", fontSize: 13, padding: "5px 0" }
|
|
3061
4009
|
};
|
|
@@ -3065,7 +4013,10 @@ function WaypointBuilder({
|
|
|
3065
4013
|
onSave,
|
|
3066
4014
|
theme,
|
|
3067
4015
|
className,
|
|
3068
|
-
style
|
|
4016
|
+
style,
|
|
4017
|
+
readOnly = false,
|
|
4018
|
+
appCustomTypes = [],
|
|
4019
|
+
externalEnums = []
|
|
3069
4020
|
}) {
|
|
3070
4021
|
const { loadSchema, schema, selectedStepId, selectedFieldId } = useBuilderStore();
|
|
3071
4022
|
const [previewMode, setPreviewMode] = useState(false);
|
|
@@ -3098,14 +4049,15 @@ function WaypointBuilder({
|
|
|
3098
4049
|
setPreviewMode(true);
|
|
3099
4050
|
}
|
|
3100
4051
|
const themeVars = buildThemeVars(theme);
|
|
3101
|
-
return /* @__PURE__ */ jsxs("div", { className, style: { ...rootStyle, ...themeVars, ...style }, children: [
|
|
4052
|
+
return /* @__PURE__ */ jsx(BuilderReadOnlyContext.Provider, { value: readOnly, children: /* @__PURE__ */ jsx(BuilderCustomTypesContext.Provider, { value: appCustomTypes, children: /* @__PURE__ */ jsx(BuilderExternalEnumsContext.Provider, { value: externalEnums, children: /* @__PURE__ */ jsxs("div", { className, style: { ...rootStyle, ...themeVars, ...style }, children: [
|
|
3102
4053
|
/* @__PURE__ */ jsx(
|
|
3103
4054
|
Toolbar,
|
|
3104
4055
|
{
|
|
3105
4056
|
isMobile,
|
|
3106
|
-
|
|
4057
|
+
readOnly,
|
|
4058
|
+
onSave: !previewMode && !readOnly && onSave ? () => onSave(schema) : void 0,
|
|
3107
4059
|
previewMode,
|
|
3108
|
-
onTest: previewMode ? () => setPreviewMode(false) : handleTest
|
|
4060
|
+
onTest: !readOnly ? previewMode ? () => setPreviewMode(false) : handleTest : void 0
|
|
3109
4061
|
}
|
|
3110
4062
|
),
|
|
3111
4063
|
previewMode ? /* @__PURE__ */ jsx(
|
|
@@ -3113,6 +4065,7 @@ function WaypointBuilder({
|
|
|
3113
4065
|
{
|
|
3114
4066
|
store: previewStoreRef.current,
|
|
3115
4067
|
schema,
|
|
4068
|
+
externalEnums,
|
|
3116
4069
|
onEdit: () => setPreviewMode(false)
|
|
3117
4070
|
}
|
|
3118
4071
|
) : isMobile ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -3150,7 +4103,7 @@ function WaypointBuilder({
|
|
|
3150
4103
|
/* @__PURE__ */ jsx("div", { style: { flex: 1, overflow: "hidden" }, children: /* @__PURE__ */ jsx(FieldEditor, {}) })
|
|
3151
4104
|
] })
|
|
3152
4105
|
] })
|
|
3153
|
-
] });
|
|
4106
|
+
] }) }) }) });
|
|
3154
4107
|
}
|
|
3155
4108
|
var rootStyle = {
|
|
3156
4109
|
display: "flex",
|