@10x-media/form-builder 0.1.0-beta.3 → 0.1.0-beta.4
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/CHANGELOG.md +42 -0
- package/README.md +2 -2
- package/dist/actions/body/serializeBody.d.ts +19 -4
- package/dist/actions/body/serializeBody.js +3 -1
- package/dist/actions/body/serializeBody.js.map +1 -1
- package/dist/actions/builtin/confirmation.js +13 -4
- package/dist/actions/builtin/confirmation.js.map +1 -1
- package/dist/actions/builtin/emailTeam.js +13 -4
- package/dist/actions/builtin/emailTeam.js.map +1 -1
- package/dist/actions/builtin/index.d.ts +13 -1
- package/dist/actions/builtin/index.js +18 -7
- package/dist/actions/builtin/index.js.map +1 -1
- package/dist/actions/builtin/signedWebhook.js +2 -16
- package/dist/actions/builtin/signedWebhook.js.map +1 -1
- package/dist/actions/runActions.js +2 -0
- package/dist/actions/runActions.js.map +1 -1
- package/dist/aggregation/resolveResultsRequest.d.ts +22 -6
- package/dist/aggregation/resolveResultsRequest.js +18 -7
- package/dist/aggregation/resolveResultsRequest.js.map +1 -1
- package/dist/client/FlowBuilder.js +98 -53
- package/dist/client/FlowBuilder.js.map +1 -1
- package/dist/client/admin.css +47 -5
- package/dist/client/flowAuthoring.js +35 -0
- package/dist/client/flowAuthoring.js.map +1 -0
- package/dist/client/synthesizeClientField.js +6 -2
- package/dist/client/synthesizeClientField.js.map +1 -1
- package/dist/collections/formSubmissions.js +47 -9
- package/dist/collections/formSubmissions.js.map +1 -1
- package/dist/collections/forms.js +180 -34
- package/dist/collections/forms.js.map +1 -1
- package/dist/conditions/conditionType.js +9 -2
- package/dist/conditions/conditionType.js.map +1 -1
- package/dist/conditions/normalizeConditions.js +2 -1
- package/dist/conditions/normalizeConditions.js.map +1 -1
- package/dist/consent/builtin/index.d.ts +11 -1
- package/dist/consent/builtin/index.js +15 -5
- package/dist/consent/builtin/index.js.map +1 -1
- package/dist/consent/builtin/static.js +7 -3
- package/dist/consent/builtin/static.js.map +1 -1
- package/dist/exports/react.d.ts +10 -6
- package/dist/exports/react.js +6 -2
- package/dist/exports/rsc.d.ts +6 -1
- package/dist/exports/rsc.js +6 -1
- package/dist/exports/types.d.ts +4 -4
- package/dist/fields/buildFieldBlocks.js +17 -8
- package/dist/fields/buildFieldBlocks.js.map +1 -1
- package/dist/fields/builtin/consent.js +8 -4
- package/dist/fields/builtin/consent.js.map +1 -1
- package/dist/fields/builtin/file.js +8 -4
- package/dist/fields/builtin/file.js.map +1 -1
- package/dist/fields/builtin/index.d.ts +11 -1
- package/dist/fields/builtin/index.js +21 -9
- package/dist/fields/builtin/index.js.map +1 -1
- package/dist/fields/builtin/message.js +26 -0
- package/dist/fields/builtin/message.js.map +1 -0
- package/dist/fields/builtin/repeater.js +7 -3
- package/dist/fields/builtin/repeater.js.map +1 -1
- package/dist/fields/builtin/select.js +7 -3
- package/dist/fields/builtin/select.js.map +1 -1
- package/dist/fields/localizedIf.d.ts +13 -0
- package/dist/fields/localizedIf.js +12 -0
- package/dist/fields/localizedIf.js.map +1 -0
- package/dist/fields/sharedConfig.js +64 -51
- package/dist/fields/sharedConfig.js.map +1 -1
- package/dist/fields/types.d.ts +7 -2
- package/dist/flow/normalizeFlow.js +7 -1
- package/dist/flow/normalizeFlow.js.map +1 -1
- package/dist/flow/stepLabel.js +15 -0
- package/dist/flow/stepLabel.js.map +1 -0
- package/dist/form/pollState.d.ts +22 -0
- package/dist/form/pollState.js +17 -0
- package/dist/form/pollState.js.map +1 -0
- package/dist/form/toFormDocument.d.ts +60 -0
- package/dist/form/toFormDocument.js +39 -0
- package/dist/form/toFormDocument.js.map +1 -0
- package/dist/form/types.d.ts +48 -0
- package/dist/index.d.ts +69 -18
- package/dist/index.js +24 -13
- package/dist/index.js.map +1 -1
- package/dist/plugin/registerCollections.js +15 -36
- package/dist/plugin/registerCollections.js.map +1 -1
- package/dist/plugin/uploadsCollection.d.ts +11 -0
- package/dist/plugin/uploadsCollection.js +44 -0
- package/dist/plugin/uploadsCollection.js.map +1 -0
- package/dist/poll/applyPollOptions.js +17 -0
- package/dist/poll/applyPollOptions.js.map +1 -0
- package/dist/poll/buildPollOptionSourceFields.js +53 -0
- package/dist/poll/buildPollOptionSourceFields.js.map +1 -0
- package/dist/poll/definePollOptionSource.d.ts +35 -0
- package/dist/poll/definePollOptionSource.js +6 -0
- package/dist/poll/definePollOptionSource.js.map +1 -0
- package/dist/poll/registry.d.ts +16 -0
- package/dist/poll/registry.js +16 -0
- package/dist/poll/registry.js.map +1 -0
- package/dist/poll/resolvePollOptions.d.ts +28 -0
- package/dist/poll/resolvePollOptions.js +64 -0
- package/dist/poll/resolvePollOptions.js.map +1 -0
- package/dist/poll/resolvePollOutcome.d.ts +21 -0
- package/dist/poll/resolvePollOutcome.js +36 -0
- package/dist/poll/resolvePollOutcome.js.map +1 -0
- package/dist/prefill/valuesFromSearchParams.js +1 -1
- package/dist/prefill/valuesFromSearchParams.js.map +1 -1
- package/dist/presentations/types.d.ts +3 -2
- package/dist/react/Form.d.ts +13 -31
- package/dist/react/Form.js +96 -83
- package/dist/react/Form.js.map +1 -1
- package/dist/react/FormContext.d.ts +35 -1
- package/dist/react/FormContext.js.map +1 -1
- package/dist/react/FormControls.d.ts +55 -0
- package/dist/react/FormControls.js +56 -0
- package/dist/react/FormControls.js.map +1 -0
- package/dist/react/FormResults.d.ts +6 -3
- package/dist/react/FormResults.js +37 -29
- package/dist/react/FormResults.js.map +1 -1
- package/dist/react/FormSteps.d.ts +17 -0
- package/dist/react/FormSteps.js +35 -0
- package/dist/react/FormSteps.js.map +1 -0
- package/dist/react/Poll.d.ts +17 -6
- package/dist/react/Poll.js +66 -18
- package/dist/react/Poll.js.map +1 -1
- package/dist/react/fetchResults.d.ts +1 -1
- package/dist/react/fetchResults.js +1 -1
- package/dist/react/fetchResults.js.map +1 -1
- package/dist/react/renderers/file.js +5 -1
- package/dist/react/renderers/file.js.map +1 -1
- package/dist/react/renderers/index.js +2 -0
- package/dist/react/renderers/index.js.map +1 -1
- package/dist/react/renderers/message.js +35 -0
- package/dist/react/renderers/message.js.map +1 -0
- package/dist/react/state.d.ts +25 -1
- package/dist/react/state.js +14 -1
- package/dist/react/state.js.map +1 -1
- package/dist/react/uploadFile.d.ts +2 -2
- package/dist/react/uploadFile.js +1 -1
- package/dist/react/uploadFile.js.map +1 -1
- package/dist/submissions/runSubmission.js +70 -33
- package/dist/submissions/runSubmission.js.map +1 -1
- package/dist/submissions/validateSubmission.js +41 -7
- package/dist/submissions/validateSubmission.js.map +1 -1
- package/dist/submissions/votedCookie.d.ts +13 -0
- package/dist/submissions/votedCookie.js +27 -0
- package/dist/submissions/votedCookie.js.map +1 -0
- package/dist/translations/de.js +219 -0
- package/dist/translations/de.js.map +1 -0
- package/dist/translations/en.js +45 -6
- package/dist/translations/en.js.map +1 -1
- package/dist/translations/index.d.ts +2 -1
- package/dist/translations/index.js +6 -2
- package/dist/translations/index.js.map +1 -1
- package/dist/translations/keys.d.ts +43 -4
- package/dist/translations/keys.js +44 -5
- package/dist/translations/keys.js.map +1 -1
- package/dist/uploads/types.d.ts +1 -2
- package/dist/validation/validateUrl.js +22 -0
- package/dist/validation/validateUrl.js.map +1 -0
- package/package.json +2 -1
- package/styles/form-builder.css +10 -0
- package/dist/collections/uploads.d.ts +0 -30
- package/dist/collections/uploads.js +0 -55
- package/dist/collections/uploads.js.map +0 -1
- package/dist/presentations/registry.d.ts +0 -15
- package/dist/presentations/registry.js +0 -15
- package/dist/presentations/registry.js.map +0 -1
- package/dist/react/toFormDocument.d.ts +0 -24
- package/dist/react/toFormDocument.js +0 -22
- package/dist/react/toFormDocument.js.map +0 -1
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { keys } from "../translations/keys.js";
|
|
3
|
+
import { resolveMessage } from "../validation/message.js";
|
|
2
4
|
import { toStaticLabel } from "./toStaticLabel.js";
|
|
5
|
+
import { useTranslation as useTranslation$1 } from "../translations/useTranslation.js";
|
|
3
6
|
import { ConditionBuilder } from "./ConditionBuilder.js";
|
|
7
|
+
import { stepLabel } from "../flow/stepLabel.js";
|
|
8
|
+
import { assignFieldToStep, fieldHolders, removeFieldFromStep, unassignedFields } from "./flowAuthoring.js";
|
|
4
9
|
import { reduceFieldsToValues } from "payload/shared";
|
|
5
10
|
import { Button, CheckboxInput, Collapsible, FieldLabel, ReactSelect, TextInput, useField, useFormFields } from "@payloadcms/ui";
|
|
6
11
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -12,11 +17,7 @@ import "./admin.css";
|
|
|
12
17
|
const extractFieldNames = (data) => {
|
|
13
18
|
return (Array.isArray(data.fields) ? data.fields : []).map((row) => typeof row.name === "string" ? row.name.trim() : null).filter((name) => name !== null && name.length > 0);
|
|
14
19
|
};
|
|
15
|
-
const TransitionRow = ({ transition,
|
|
16
|
-
const toOptions = stepIds.map((id) => ({
|
|
17
|
-
label: id,
|
|
18
|
-
value: id
|
|
19
|
-
}));
|
|
20
|
+
const TransitionRow = ({ transition, stepOptions, conditionTypes, isFirst, isLast, onChange, onRemove, onMoveUp, onMoveDown }) => {
|
|
20
21
|
const handleGotoChange = (selected) => {
|
|
21
22
|
const chosen = Array.isArray(selected) ? selected[0] : selected;
|
|
22
23
|
if (chosen) onChange({
|
|
@@ -37,8 +38,8 @@ const TransitionRow = ({ transition, stepIds, conditionTypes, isFirst, isLast, o
|
|
|
37
38
|
/* @__PURE__ */ jsx("div", {
|
|
38
39
|
className: "fb-flow-transition__goto",
|
|
39
40
|
children: /* @__PURE__ */ jsx(ReactSelect, {
|
|
40
|
-
options:
|
|
41
|
-
value:
|
|
41
|
+
options: stepOptions,
|
|
42
|
+
value: stepOptions.find((o) => o.value === transition.to) ?? void 0,
|
|
42
43
|
placeholder: "Select step…",
|
|
43
44
|
isClearable: false,
|
|
44
45
|
onChange: handleGotoChange
|
|
@@ -92,21 +93,19 @@ const TransitionRow = ({ transition, stepIds, conditionTypes, isFirst, isLast, o
|
|
|
92
93
|
]
|
|
93
94
|
});
|
|
94
95
|
};
|
|
95
|
-
const StepCard = ({ step, stepKey, stepIndex, stepCount,
|
|
96
|
+
const StepCard = ({ step, stepKey, stepIndex, stepCount, otherStepOptions, holders, stepLabels, fieldNames, conditionTypes, isExpanded, onToggle, onChange, onToggleField, onRemove, onMoveUp, onMoveDown, onAddAbove, onAddBelow }) => {
|
|
97
|
+
const { t } = useTranslation$1();
|
|
96
98
|
const nextOptions = [{
|
|
97
|
-
label:
|
|
99
|
+
label: t(keys.flowNextTerminal),
|
|
98
100
|
value: ""
|
|
99
|
-
}, ...
|
|
100
|
-
label: id,
|
|
101
|
-
value: id
|
|
102
|
-
}))];
|
|
101
|
+
}, ...otherStepOptions];
|
|
103
102
|
const transitions = step.transitions ?? [];
|
|
104
103
|
const tKeysRef = useRef([]);
|
|
105
104
|
if (tKeysRef.current.length !== transitions.length) tKeysRef.current = transitions.map((_, i) => tKeysRef.current[i] ?? crypto.randomUUID());
|
|
106
105
|
const tKeys = tKeysRef.current;
|
|
107
106
|
const addTransition = () => {
|
|
108
|
-
const firstOtherStep =
|
|
109
|
-
if (
|
|
107
|
+
const firstOtherStep = otherStepOptions[0]?.value;
|
|
108
|
+
if (firstOtherStep === void 0) return;
|
|
110
109
|
tKeysRef.current = [...tKeys, crypto.randomUUID()];
|
|
111
110
|
onChange({
|
|
112
111
|
...step,
|
|
@@ -152,16 +151,17 @@ const StepCard = ({ step, stepKey, stepIndex, stepCount, otherStepIds, fieldName
|
|
|
152
151
|
next
|
|
153
152
|
});
|
|
154
153
|
};
|
|
154
|
+
const title = step.title?.trim() ?? "";
|
|
155
155
|
return /* @__PURE__ */ jsx(Collapsible, {
|
|
156
156
|
header: /* @__PURE__ */ jsxs("div", {
|
|
157
157
|
className: "fb-flow-step__header-content",
|
|
158
|
-
children: [/* @__PURE__ */
|
|
158
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
159
159
|
className: "fb-flow-step__index",
|
|
160
|
-
children:
|
|
161
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
162
|
-
className: "fb-flow-
|
|
163
|
-
children:
|
|
164
|
-
})]
|
|
160
|
+
children: resolveMessage(t(keys.flowStepFallbackTitle), { n: stepIndex + 1 })
|
|
161
|
+
}), title.length > 0 ? /* @__PURE__ */ jsx("span", {
|
|
162
|
+
className: "fb-flow-step__title",
|
|
163
|
+
children: title
|
|
164
|
+
}) : null]
|
|
165
165
|
}),
|
|
166
166
|
actions: /* @__PURE__ */ jsx(Popup, {
|
|
167
167
|
button: /* @__PURE__ */ jsx(MoreIcon, {}),
|
|
@@ -200,16 +200,6 @@ const StepCard = ({ step, stepKey, stepIndex, stepCount, otherStepIds, fieldName
|
|
|
200
200
|
children: /* @__PURE__ */ jsxs("div", {
|
|
201
201
|
className: "fb-flow-step__body",
|
|
202
202
|
children: [
|
|
203
|
-
/* @__PURE__ */ jsx(TextInput, {
|
|
204
|
-
path: `fb-flow-step-${stepKey}-id`,
|
|
205
|
-
label: "Step ID",
|
|
206
|
-
value: step.id,
|
|
207
|
-
placeholder: "e.g. intro",
|
|
208
|
-
onChange: (e) => onChange({
|
|
209
|
-
...step,
|
|
210
|
-
id: e.target.value
|
|
211
|
-
})
|
|
212
|
-
}),
|
|
213
203
|
/* @__PURE__ */ jsx(TextInput, {
|
|
214
204
|
path: `fb-flow-step-${stepKey}-title`,
|
|
215
205
|
label: "Title",
|
|
@@ -227,17 +217,25 @@ const StepCard = ({ step, stepKey, stepIndex, stepCount, otherStepIds, fieldName
|
|
|
227
217
|
children: "No fields defined on the form yet."
|
|
228
218
|
}) : /* @__PURE__ */ jsx("div", {
|
|
229
219
|
className: "fb-flow-step__field-picker",
|
|
230
|
-
children: fieldNames.map((name) =>
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
fields
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
220
|
+
children: fieldNames.map((name) => {
|
|
221
|
+
const holder = holders.get(name);
|
|
222
|
+
const inOtherStep = holder !== void 0 && holder !== stepIndex;
|
|
223
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
224
|
+
className: "fb-flow-step__field-option",
|
|
225
|
+
children: [/* @__PURE__ */ jsx(CheckboxInput, {
|
|
226
|
+
label: name,
|
|
227
|
+
checked: step.fields.includes(name) || inOtherStep,
|
|
228
|
+
readOnly: inOtherStep,
|
|
229
|
+
onToggle: (e) => {
|
|
230
|
+
if (inOtherStep) return;
|
|
231
|
+
onToggleField(name, e.target.checked);
|
|
232
|
+
}
|
|
233
|
+
}), inOtherStep ? /* @__PURE__ */ jsx("span", {
|
|
234
|
+
className: "fb-flow-step__field-hint",
|
|
235
|
+
children: resolveMessage(t(keys.flowFieldInStep), { step: stepLabels[holder] ?? "" })
|
|
236
|
+
}) : null]
|
|
237
|
+
}, name);
|
|
238
|
+
})
|
|
241
239
|
})]
|
|
242
240
|
}),
|
|
243
241
|
/* @__PURE__ */ jsxs("div", {
|
|
@@ -264,7 +262,7 @@ const StepCard = ({ step, stepKey, stepIndex, stepCount, otherStepIds, fieldName
|
|
|
264
262
|
if (tKey === void 0) return null;
|
|
265
263
|
return /* @__PURE__ */ jsx(TransitionRow, {
|
|
266
264
|
transition,
|
|
267
|
-
|
|
265
|
+
stepOptions: otherStepOptions,
|
|
268
266
|
conditionTypes,
|
|
269
267
|
isFirst: tIndex === 0,
|
|
270
268
|
isLast: tIndex === transitions.length - 1,
|
|
@@ -291,15 +289,23 @@ const StepCard = ({ step, stepKey, stepIndex, stepCount, otherStepIds, fieldName
|
|
|
291
289
|
};
|
|
292
290
|
const FlowBuilder = (props) => {
|
|
293
291
|
const { setValue, value } = useField();
|
|
292
|
+
const { t } = useTranslation$1();
|
|
294
293
|
const label = toStaticLabel(props.field?.label ?? props.label);
|
|
295
294
|
const [expandedKeys, setExpandedKeys] = useState(/* @__PURE__ */ new Set());
|
|
296
295
|
const fieldNamesJson = useFormFields(([fields]) => JSON.stringify(extractFieldNames(reduceFieldsToValues(fields, true))));
|
|
297
296
|
const fieldNames = useMemo(() => JSON.parse(fieldNamesJson), [fieldNamesJson]);
|
|
298
297
|
const steps = value?.steps ?? [];
|
|
299
|
-
const
|
|
298
|
+
const fallbackTitle = t(keys.flowStepFallbackTitle);
|
|
299
|
+
const stepLabels = steps.map((step, index) => stepLabel(step, index, fallbackTitle));
|
|
300
|
+
const stepOptions = steps.map((step, index) => ({
|
|
301
|
+
label: stepLabels[index] ?? "",
|
|
302
|
+
value: step.id
|
|
303
|
+
})).filter((option) => option.value.length > 0);
|
|
304
|
+
const holders = fieldHolders(steps);
|
|
305
|
+
const unassigned = unassignedFields(fieldNames, steps);
|
|
300
306
|
const keysRef = useRef([]);
|
|
301
307
|
if (keysRef.current.length !== steps.length) keysRef.current = steps.map((_, i) => keysRef.current[i] ?? crypto.randomUUID());
|
|
302
|
-
const
|
|
308
|
+
const stepKeys = keysRef.current;
|
|
303
309
|
const toggleExpanded = (key) => {
|
|
304
310
|
setExpandedKeys((prev) => {
|
|
305
311
|
const next = new Set(prev);
|
|
@@ -319,18 +325,26 @@ const FlowBuilder = (props) => {
|
|
|
319
325
|
id: crypto.randomUUID(),
|
|
320
326
|
fields: []
|
|
321
327
|
});
|
|
322
|
-
const nextKeys = [...
|
|
328
|
+
const nextKeys = [...stepKeys];
|
|
323
329
|
nextKeys.splice(at, 0, key);
|
|
324
330
|
emit(nextSteps, nextKeys);
|
|
325
331
|
setExpandedKeys((prev) => new Set(prev).add(key));
|
|
326
332
|
};
|
|
327
333
|
const addStep = () => insertStep(steps.length);
|
|
328
334
|
const updateStep = (index, next) => {
|
|
329
|
-
emit(steps.map((s, i) => i === index ? next : s),
|
|
335
|
+
emit(steps.map((s, i) => i === index ? next : s), stepKeys);
|
|
336
|
+
};
|
|
337
|
+
const toggleField = (stepIndex, name, checked) => {
|
|
338
|
+
emit(checked ? assignFieldToStep(steps, stepIndex, name) : removeFieldFromStep(steps, stepIndex, name), stepKeys);
|
|
339
|
+
};
|
|
340
|
+
const assignUnassignedField = (name, stepId) => {
|
|
341
|
+
const targetIndex = steps.findIndex((s) => s.id === stepId);
|
|
342
|
+
if (targetIndex === -1) return;
|
|
343
|
+
emit(assignFieldToStep(steps, targetIndex, name), stepKeys);
|
|
330
344
|
};
|
|
331
345
|
const removeStep = (index) => {
|
|
332
|
-
const removedKey =
|
|
333
|
-
emit(steps.filter((_, i) => i !== index),
|
|
346
|
+
const removedKey = stepKeys[index];
|
|
347
|
+
emit(steps.filter((_, i) => i !== index), stepKeys.filter((_, i) => i !== index));
|
|
334
348
|
if (removedKey !== void 0) setExpandedKeys((prev) => {
|
|
335
349
|
const next = new Set(prev);
|
|
336
350
|
next.delete(removedKey);
|
|
@@ -342,7 +356,7 @@ const FlowBuilder = (props) => {
|
|
|
342
356
|
const [movedStep] = nextSteps.splice(from, 1);
|
|
343
357
|
if (movedStep === void 0) return;
|
|
344
358
|
nextSteps.splice(to, 0, movedStep);
|
|
345
|
-
const nextKeys = [...
|
|
359
|
+
const nextKeys = [...stepKeys];
|
|
346
360
|
const [movedKey] = nextKeys.splice(from, 1);
|
|
347
361
|
if (movedKey !== void 0) nextKeys.splice(to, 0, movedKey);
|
|
348
362
|
emit(nextSteps, nextKeys);
|
|
@@ -357,26 +371,33 @@ const FlowBuilder = (props) => {
|
|
|
357
371
|
children: /* @__PURE__ */ jsx("h3", { children: typeof label === "string" ? label : "Flow" })
|
|
358
372
|
})
|
|
359
373
|
}),
|
|
374
|
+
/* @__PURE__ */ jsx("p", {
|
|
375
|
+
className: "fb-flow-builder__description",
|
|
376
|
+
children: t(keys.flowDescription)
|
|
377
|
+
}),
|
|
360
378
|
steps.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
361
379
|
className: "fb-flow-builder__hint",
|
|
362
380
|
children: "No steps defined. Add at least two steps to enable multi-page flow routing."
|
|
363
381
|
}) : /* @__PURE__ */ jsx("div", {
|
|
364
382
|
className: "fb-flow-builder__steps",
|
|
365
383
|
children: steps.map((step, index) => {
|
|
366
|
-
const key =
|
|
384
|
+
const key = stepKeys[index];
|
|
367
385
|
if (key === void 0) return null;
|
|
368
|
-
const
|
|
386
|
+
const otherStepOptions = stepOptions.filter((option) => option.value !== step.id);
|
|
369
387
|
return /* @__PURE__ */ jsx(StepCard, {
|
|
370
388
|
stepKey: key,
|
|
371
389
|
step,
|
|
372
390
|
stepIndex: index,
|
|
373
391
|
stepCount: steps.length,
|
|
374
|
-
|
|
392
|
+
otherStepOptions,
|
|
393
|
+
holders,
|
|
394
|
+
stepLabels,
|
|
375
395
|
fieldNames,
|
|
376
396
|
conditionTypes: props.conditionTypes,
|
|
377
397
|
isExpanded: expandedKeys.has(key),
|
|
378
398
|
onToggle: () => toggleExpanded(key),
|
|
379
399
|
onChange: (next) => updateStep(index, next),
|
|
400
|
+
onToggleField: (name, checked) => toggleField(index, name, checked),
|
|
380
401
|
onRemove: () => removeStep(index),
|
|
381
402
|
onMoveUp: () => moveStep(index, index - 1),
|
|
382
403
|
onMoveDown: () => moveStep(index, index + 1),
|
|
@@ -385,6 +406,30 @@ const FlowBuilder = (props) => {
|
|
|
385
406
|
}, key);
|
|
386
407
|
})
|
|
387
408
|
}),
|
|
409
|
+
steps.length > 0 && unassigned.length > 0 ? /* @__PURE__ */ jsxs("div", {
|
|
410
|
+
className: "fb-flow-unassigned",
|
|
411
|
+
children: [/* @__PURE__ */ jsx(FieldLabel, { label: t(keys.flowUnassigned) }), /* @__PURE__ */ jsx("div", {
|
|
412
|
+
className: "fb-flow-unassigned__rows",
|
|
413
|
+
children: unassigned.map((name) => /* @__PURE__ */ jsxs("div", {
|
|
414
|
+
className: "fb-flow-unassigned__row",
|
|
415
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
416
|
+
className: "fb-flow-unassigned__name",
|
|
417
|
+
children: name
|
|
418
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
419
|
+
className: "fb-flow-unassigned__select",
|
|
420
|
+
children: /* @__PURE__ */ jsx(ReactSelect, {
|
|
421
|
+
options: stepOptions,
|
|
422
|
+
placeholder: t(keys.flowAssignToStep),
|
|
423
|
+
isClearable: false,
|
|
424
|
+
onChange: (selected) => {
|
|
425
|
+
const chosen = Array.isArray(selected) ? selected[0] : selected;
|
|
426
|
+
if (chosen) assignUnassignedField(name, chosen.value);
|
|
427
|
+
}
|
|
428
|
+
})
|
|
429
|
+
})]
|
|
430
|
+
}, name))
|
|
431
|
+
})]
|
|
432
|
+
}) : null,
|
|
388
433
|
/* @__PURE__ */ jsx("div", {
|
|
389
434
|
className: "fb-flow-builder__actions",
|
|
390
435
|
children: /* @__PURE__ */ jsx(Button, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FlowBuilder.js","names":[],"sources":["../../src/client/FlowBuilder.tsx"],"sourcesContent":["'use client'\n\nimport {\n\tButton,\n\tCheckboxInput,\n\tCollapsible,\n\tFieldLabel,\n\tReactSelect,\n\ttype ReactSelectOption,\n\tTextInput,\n\tuseField,\n\tuseFormFields,\n} from '@payloadcms/ui'\nimport { Popup, PopupList } from '@payloadcms/ui/elements/Popup'\nimport { MoreIcon } from '@payloadcms/ui/icons/More'\nimport { reduceFieldsToValues } from 'payload/shared'\nimport type { ChangeEvent } from 'react'\nimport { useMemo, useRef, useState } from 'react'\nimport type { ConditionFieldType } from '../conditions/fieldTypes'\nimport type { FlowStep, FlowTransition, FormFlow } from '../flow/types'\nimport { ConditionBuilder } from './ConditionBuilder'\nimport type { FieldRow } from './synthesizeClientField'\nimport { toStaticLabel } from './toStaticLabel'\nimport './admin.css'\n\nexport type FlowBuilderProps = {\n\tpath?: string\n\tfield?: { label?: unknown }\n\tlabel?: unknown\n\tconditionTypes: Record<string, ConditionFieldType>\n}\n\nconst extractFieldNames = (data: Record<string, unknown>): string[] => {\n\tconst rows = Array.isArray(data.fields) ? (data.fields as FieldRow[]) : []\n\treturn rows\n\t\t.map((row) => (typeof row.name === 'string' ? row.name.trim() : null))\n\t\t.filter((name): name is string => name !== null && name.length > 0)\n}\n\ntype TransitionRowProps = {\n\ttransition: FlowTransition\n\tstepIds: string[]\n\tconditionTypes: Record<string, ConditionFieldType>\n\tisFirst: boolean\n\tisLast: boolean\n\tonChange: (next: FlowTransition) => void\n\tonRemove: () => void\n\tonMoveUp: () => void\n\tonMoveDown: () => void\n}\n\nconst TransitionRow = ({\n\ttransition,\n\tstepIds,\n\tconditionTypes,\n\tisFirst,\n\tisLast,\n\tonChange,\n\tonRemove,\n\tonMoveUp,\n\tonMoveDown,\n}: TransitionRowProps) => {\n\tconst toOptions: ReactSelectOption[] = stepIds.map((id) => ({ label: id, value: id }))\n\n\tconst handleGotoChange = (selected: ReactSelectOption | ReactSelectOption[]) => {\n\t\tconst chosen = Array.isArray(selected) ? selected[0] : selected\n\t\tif (chosen) onChange({ ...transition, to: chosen.value as string })\n\t}\n\n\treturn (\n\t\t<div className=\"fb-flow-transition\">\n\t\t\t<div className=\"fb-flow-transition__header\">\n\t\t\t\t<span className=\"fb-flow-transition__label\">go to</span>\n\t\t\t\t<div className=\"fb-flow-transition__goto\">\n\t\t\t\t\t<ReactSelect\n\t\t\t\t\t\toptions={toOptions}\n\t\t\t\t\t\tvalue={toOptions.find((o) => o.value === transition.to) ?? undefined}\n\t\t\t\t\t\tplaceholder=\"Select step…\"\n\t\t\t\t\t\tisClearable={false}\n\t\t\t\t\t\tonChange={handleGotoChange}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"fb-flow-transition__actions\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"fb-flow__move-btn\"\n\t\t\t\t\t\tonClick={onMoveUp}\n\t\t\t\t\t\tdisabled={isFirst}\n\t\t\t\t\t\taria-label=\"Move transition up\"\n\t\t\t\t\t>\n\t\t\t\t\t\t↑\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"fb-flow__move-btn\"\n\t\t\t\t\t\tonClick={onMoveDown}\n\t\t\t\t\t\tdisabled={isLast}\n\t\t\t\t\t\taria-label=\"Move transition down\"\n\t\t\t\t\t>\n\t\t\t\t\t\t↓\n\t\t\t\t\t</button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tbuttonStyle=\"icon-label\"\n\t\t\t\t\t\ticon=\"x\"\n\t\t\t\t\t\tonClick={onRemove}\n\t\t\t\t\t\tmargin={false}\n\t\t\t\t\t\taria-label=\"Remove transition\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<span className=\"fb-flow-transition__when-label\">when</span>\n\t\t\t<div className=\"fb-flow-transition__condition\">\n\t\t\t\t<ConditionBuilder\n\t\t\t\t\tvalue={transition.when}\n\t\t\t\t\tonChange={(when) => onChange({ ...transition, when })}\n\t\t\t\t\tconditionTypes={conditionTypes}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\ntype StepCardProps = {\n\tstep: FlowStep\n\tstepKey: string\n\tstepIndex: number\n\tstepCount: number\n\totherStepIds: string[]\n\tfieldNames: string[]\n\tconditionTypes: Record<string, ConditionFieldType>\n\tisExpanded: boolean\n\tonToggle: () => void\n\tonChange: (next: FlowStep) => void\n\tonRemove: () => void\n\tonMoveUp: () => void\n\tonMoveDown: () => void\n\tonAddAbove: () => void\n\tonAddBelow: () => void\n}\n\nconst StepCard = ({\n\tstep,\n\tstepKey,\n\tstepIndex,\n\tstepCount,\n\totherStepIds,\n\tfieldNames,\n\tconditionTypes,\n\tisExpanded,\n\tonToggle,\n\tonChange,\n\tonRemove,\n\tonMoveUp,\n\tonMoveDown,\n\tonAddAbove,\n\tonAddBelow,\n}: StepCardProps) => {\n\tconst nextOptions: ReactSelectOption[] = [\n\t\t{ label: '— terminal —', value: '' },\n\t\t...otherStepIds.map((id) => ({ label: id, value: id })),\n\t]\n\n\tconst transitions = step.transitions ?? []\n\n\t// Stable per-transition keys, mirroring the step-level scheme so transition reorder/remove\n\t// reconciles by identity rather than array position.\n\tconst tKeysRef = useRef<string[]>([])\n\tif (tKeysRef.current.length !== transitions.length) {\n\t\ttKeysRef.current = transitions.map((_, i) => tKeysRef.current[i] ?? crypto.randomUUID())\n\t}\n\tconst tKeys = tKeysRef.current\n\n\tconst addTransition = () => {\n\t\tconst firstOtherStep = otherStepIds[0]\n\t\tif (!firstOtherStep) return\n\t\ttKeysRef.current = [...tKeys, crypto.randomUUID()]\n\t\tonChange({\n\t\t\t...step,\n\t\t\ttransitions: [...transitions, { when: {}, to: firstOtherStep }],\n\t\t})\n\t}\n\n\tconst updateTransition = (index: number, next: FlowTransition) => {\n\t\tconst updated = [...transitions]\n\t\tupdated[index] = next\n\t\tonChange({ ...step, transitions: updated })\n\t}\n\n\tconst removeTransition = (index: number) => {\n\t\ttKeysRef.current = tKeys.filter((_, i) => i !== index)\n\t\tconst updated = transitions.filter((_, i) => i !== index)\n\t\tonChange({ ...step, transitions: updated.length > 0 ? updated : undefined })\n\t}\n\n\tconst moveTransition = (from: number, to: number) => {\n\t\tconst updated = [...transitions]\n\t\tconst [item] = updated.splice(from, 1)\n\t\tif (item !== undefined) updated.splice(to, 0, item)\n\t\tconst nextKeys = [...tKeys]\n\t\tconst [movedKey] = nextKeys.splice(from, 1)\n\t\tif (movedKey !== undefined) nextKeys.splice(to, 0, movedKey)\n\t\ttKeysRef.current = nextKeys\n\t\tonChange({ ...step, transitions: updated })\n\t}\n\n\tconst handleNextChange = (selected: ReactSelectOption | ReactSelectOption[]) => {\n\t\tconst chosen = Array.isArray(selected) ? selected[0] : selected\n\t\tconst next = (chosen?.value as string | undefined) || undefined\n\t\tonChange({ ...step, next })\n\t}\n\n\tconst stepHeader = (\n\t\t<div className=\"fb-flow-step__header-content\">\n\t\t\t<span className=\"fb-flow-step__index\">Step {stepIndex + 1}</span>\n\t\t\t<span className=\"fb-flow-step__id-preview\">\n\t\t\t\t{step.id.length > 0 ? step.id : <em>no id</em>}\n\t\t\t</span>\n\t\t</div>\n\t)\n\n\treturn (\n\t\t<Collapsible\n\t\t\theader={stepHeader}\n\t\t\tactions={\n\t\t\t\t<Popup\n\t\t\t\t\tbutton={<MoreIcon />}\n\t\t\t\t\tbuttonType=\"default\"\n\t\t\t\t\thorizontalAlign=\"right\"\n\t\t\t\t\tsize=\"fit-content\"\n\t\t\t\t\tverticalAlign=\"bottom\"\n\t\t\t\t>\n\t\t\t\t\t<PopupList.ButtonGroup>\n\t\t\t\t\t\t<PopupList.Button onClick={onAddAbove}>Add above</PopupList.Button>\n\t\t\t\t\t\t<PopupList.Button onClick={onAddBelow}>Add below</PopupList.Button>\n\t\t\t\t\t\t<PopupList.Button onClick={onMoveUp} disabled={stepIndex === 0}>\n\t\t\t\t\t\t\tMove up\n\t\t\t\t\t\t</PopupList.Button>\n\t\t\t\t\t\t<PopupList.Button onClick={onMoveDown} disabled={stepIndex === stepCount - 1}>\n\t\t\t\t\t\t\tMove down\n\t\t\t\t\t\t</PopupList.Button>\n\t\t\t\t\t\t<PopupList.Button onClick={onRemove}>Remove</PopupList.Button>\n\t\t\t\t\t</PopupList.ButtonGroup>\n\t\t\t\t</Popup>\n\t\t\t}\n\t\t\tisCollapsed={!isExpanded}\n\t\t\tonToggle={() => onToggle()}\n\t\t\tclassName=\"fb-flow-step\"\n\t\t>\n\t\t\t<div className=\"fb-flow-step__body\">\n\t\t\t\t<TextInput\n\t\t\t\t\tpath={`fb-flow-step-${stepKey}-id`}\n\t\t\t\t\tlabel=\"Step ID\"\n\t\t\t\t\tvalue={step.id}\n\t\t\t\t\tplaceholder=\"e.g. intro\"\n\t\t\t\t\tonChange={(e: ChangeEvent<HTMLInputElement>) => onChange({ ...step, id: e.target.value })}\n\t\t\t\t/>\n\n\t\t\t\t<TextInput\n\t\t\t\t\tpath={`fb-flow-step-${stepKey}-title`}\n\t\t\t\t\tlabel=\"Title\"\n\t\t\t\t\tvalue={step.title ?? ''}\n\t\t\t\t\tplaceholder=\"Optional display title\"\n\t\t\t\t\tonChange={(e: ChangeEvent<HTMLInputElement>) =>\n\t\t\t\t\t\tonChange({ ...step, title: e.target.value.length > 0 ? e.target.value : undefined })\n\t\t\t\t\t}\n\t\t\t\t/>\n\n\t\t\t\t<div className=\"fb-flow-step__row\">\n\t\t\t\t\t<FieldLabel label=\"Fields\" />\n\t\t\t\t\t{fieldNames.length === 0 ? (\n\t\t\t\t\t\t<p className=\"fb-flow-step__hint\">No fields defined on the form yet.</p>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<div className=\"fb-flow-step__field-picker\">\n\t\t\t\t\t\t\t{fieldNames.map((name) => (\n\t\t\t\t\t\t\t\t<CheckboxInput\n\t\t\t\t\t\t\t\t\tkey={name}\n\t\t\t\t\t\t\t\t\tlabel={name}\n\t\t\t\t\t\t\t\t\tchecked={step.fields.includes(name)}\n\t\t\t\t\t\t\t\t\tonToggle={(e) => {\n\t\t\t\t\t\t\t\t\t\tconst fields = e.target.checked\n\t\t\t\t\t\t\t\t\t\t\t? [...step.fields, name]\n\t\t\t\t\t\t\t\t\t\t\t: step.fields.filter((f) => f !== name)\n\t\t\t\t\t\t\t\t\t\tonChange({ ...step, fields })\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"fb-flow-step__row\">\n\t\t\t\t\t<FieldLabel label=\"Default next\" />\n\t\t\t\t\t<ReactSelect\n\t\t\t\t\t\toptions={nextOptions}\n\t\t\t\t\t\tvalue={\n\t\t\t\t\t\t\tstep.next\n\t\t\t\t\t\t\t\t? (nextOptions.find((o) => o.value === step.next) ?? undefined)\n\t\t\t\t\t\t\t\t: (nextOptions[0] ?? undefined)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tisClearable={false}\n\t\t\t\t\t\tonChange={handleNextChange}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"fb-flow-step__transitions\">\n\t\t\t\t\t<div className=\"fb-flow-step__transitions-header\">\n\t\t\t\t\t\t<FieldLabel label=\"Conditional transitions\" />\n\t\t\t\t\t\t<span className=\"fb-flow-step__hint\">(first match wins)</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t{transitions.map((transition, tIndex) => {\n\t\t\t\t\t\tconst tKey = tKeys[tIndex]\n\t\t\t\t\t\tif (tKey === undefined) return null\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<TransitionRow\n\t\t\t\t\t\t\t\tkey={tKey}\n\t\t\t\t\t\t\t\ttransition={transition}\n\t\t\t\t\t\t\t\tstepIds={otherStepIds}\n\t\t\t\t\t\t\t\tconditionTypes={conditionTypes}\n\t\t\t\t\t\t\t\tisFirst={tIndex === 0}\n\t\t\t\t\t\t\t\tisLast={tIndex === transitions.length - 1}\n\t\t\t\t\t\t\t\tonChange={(next) => updateTransition(tIndex, next)}\n\t\t\t\t\t\t\t\tonRemove={() => removeTransition(tIndex)}\n\t\t\t\t\t\t\t\tonMoveUp={() => moveTransition(tIndex, tIndex - 1)}\n\t\t\t\t\t\t\t\tonMoveDown={() => moveTransition(tIndex, tIndex + 1)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)\n\t\t\t\t\t})}\n\t\t\t\t\t<Button\n\t\t\t\t\t\tbuttonStyle=\"icon-label\"\n\t\t\t\t\t\ticon=\"plus\"\n\t\t\t\t\t\ticonStyle=\"with-border\"\n\t\t\t\t\t\ticonPosition=\"left\"\n\t\t\t\t\t\tonClick={addTransition}\n\t\t\t\t\t\tmargin={false}\n\t\t\t\t\t>\n\t\t\t\t\t\tAdd transition\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</Collapsible>\n\t)\n}\n\nexport const FlowBuilder = (props: FlowBuilderProps) => {\n\tconst { setValue, value } = useField<FormFlow | undefined>()\n\tconst label = toStaticLabel(props.field?.label ?? props.label)\n\tconst [expandedKeys, setExpandedKeys] = useState<Set<string>>(new Set())\n\n\tconst fieldNamesJson = useFormFields(([fields]) =>\n\t\tJSON.stringify(extractFieldNames(reduceFieldsToValues(fields, true) as Record<string, unknown>))\n\t)\n\tconst fieldNames = useMemo(() => JSON.parse(fieldNamesJson) as string[], [fieldNamesJson])\n\n\tconst steps = value?.steps ?? []\n\tconst allStepIds = steps.map((s) => s.id).filter((id) => id.length > 0)\n\n\t// Stable per-step keys, decoupled from the user-editable step.id. Reorder/insert/remove\n\t// reconcile by identity so the focused Step ID input and each step's expand state stay with\n\t// their step instead of jumping to whichever step now sits at that array position.\n\tconst keysRef = useRef<string[]>([])\n\tif (keysRef.current.length !== steps.length) {\n\t\tkeysRef.current = steps.map((_, i) => keysRef.current[i] ?? crypto.randomUUID())\n\t}\n\tconst keys = keysRef.current\n\n\tconst toggleExpanded = (key: string) => {\n\t\tsetExpandedKeys((prev) => {\n\t\t\tconst next = new Set(prev)\n\t\t\tif (next.has(key)) next.delete(key)\n\t\t\telse next.add(key)\n\t\t\treturn next\n\t\t})\n\t}\n\n\tconst emit = (nextSteps: FlowStep[], nextKeys: string[]) => {\n\t\tkeysRef.current = nextKeys\n\t\tsetValue({ steps: nextSteps } as FormFlow)\n\t}\n\n\tconst insertStep = (at: number) => {\n\t\tconst key = crypto.randomUUID()\n\t\tconst nextSteps = [...steps]\n\t\tnextSteps.splice(at, 0, { id: crypto.randomUUID(), fields: [] })\n\t\tconst nextKeys = [...keys]\n\t\tnextKeys.splice(at, 0, key)\n\t\temit(nextSteps, nextKeys)\n\t\tsetExpandedKeys((prev) => new Set(prev).add(key))\n\t}\n\n\tconst addStep = () => insertStep(steps.length)\n\n\tconst updateStep = (index: number, next: FlowStep) => {\n\t\temit(\n\t\t\tsteps.map((s, i) => (i === index ? next : s)),\n\t\t\tkeys\n\t\t)\n\t}\n\n\tconst removeStep = (index: number) => {\n\t\tconst removedKey = keys[index]\n\t\temit(\n\t\t\tsteps.filter((_, i) => i !== index),\n\t\t\tkeys.filter((_, i) => i !== index)\n\t\t)\n\t\tif (removedKey !== undefined) {\n\t\t\tsetExpandedKeys((prev) => {\n\t\t\t\tconst next = new Set(prev)\n\t\t\t\tnext.delete(removedKey)\n\t\t\t\treturn next\n\t\t\t})\n\t\t}\n\t}\n\n\tconst moveStep = (from: number, to: number) => {\n\t\tconst nextSteps = [...steps]\n\t\tconst [movedStep] = nextSteps.splice(from, 1)\n\t\tif (movedStep === undefined) return\n\t\tnextSteps.splice(to, 0, movedStep)\n\t\tconst nextKeys = [...keys]\n\t\tconst [movedKey] = nextKeys.splice(from, 1)\n\t\tif (movedKey !== undefined) nextKeys.splice(to, 0, movedKey)\n\t\temit(nextSteps, nextKeys)\n\t}\n\n\treturn (\n\t\t<div className=\"field-type fb-flow-builder\">\n\t\t\t<div className=\"blocks-field__header\">\n\t\t\t\t<div className=\"blocks-field__header-wrap\">\n\t\t\t\t\t<h3>{typeof label === 'string' ? label : 'Flow'}</h3>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t{steps.length === 0 ? (\n\t\t\t\t<p className=\"fb-flow-builder__hint\">\n\t\t\t\t\tNo steps defined. Add at least two steps to enable multi-page flow routing.\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<div className=\"fb-flow-builder__steps\">\n\t\t\t\t\t{steps.map((step, index) => {\n\t\t\t\t\t\tconst key = keys[index]\n\t\t\t\t\t\tif (key === undefined) return null\n\t\t\t\t\t\tconst otherStepIds = allStepIds.filter((id) => id !== step.id)\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<StepCard\n\t\t\t\t\t\t\t\tkey={key}\n\t\t\t\t\t\t\t\tstepKey={key}\n\t\t\t\t\t\t\t\tstep={step}\n\t\t\t\t\t\t\t\tstepIndex={index}\n\t\t\t\t\t\t\t\tstepCount={steps.length}\n\t\t\t\t\t\t\t\totherStepIds={otherStepIds}\n\t\t\t\t\t\t\t\tfieldNames={fieldNames}\n\t\t\t\t\t\t\t\tconditionTypes={props.conditionTypes}\n\t\t\t\t\t\t\t\tisExpanded={expandedKeys.has(key)}\n\t\t\t\t\t\t\t\tonToggle={() => toggleExpanded(key)}\n\t\t\t\t\t\t\t\tonChange={(next) => updateStep(index, next)}\n\t\t\t\t\t\t\t\tonRemove={() => removeStep(index)}\n\t\t\t\t\t\t\t\tonMoveUp={() => moveStep(index, index - 1)}\n\t\t\t\t\t\t\t\tonMoveDown={() => moveStep(index, index + 1)}\n\t\t\t\t\t\t\t\tonAddAbove={() => insertStep(index)}\n\t\t\t\t\t\t\t\tonAddBelow={() => insertStep(index + 1)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)\n\t\t\t\t\t})}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<div className=\"fb-flow-builder__actions\">\n\t\t\t\t<Button\n\t\t\t\t\tbuttonStyle=\"icon-label\"\n\t\t\t\t\ticon=\"plus\"\n\t\t\t\t\ticonStyle=\"with-border\"\n\t\t\t\t\ticonPosition=\"left\"\n\t\t\t\t\tonClick={addStep}\n\t\t\t\t\tmargin={false}\n\t\t\t\t>\n\t\t\t\t\tAdd step\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FlowBuilder.js","names":["useTranslation"],"sources":["../../src/client/FlowBuilder.tsx"],"sourcesContent":["'use client'\n\nimport {\n\tButton,\n\tCheckboxInput,\n\tCollapsible,\n\tFieldLabel,\n\tReactSelect,\n\ttype ReactSelectOption,\n\tTextInput,\n\tuseField,\n\tuseFormFields,\n} from '@payloadcms/ui'\nimport { Popup, PopupList } from '@payloadcms/ui/elements/Popup'\nimport { MoreIcon } from '@payloadcms/ui/icons/More'\nimport { reduceFieldsToValues } from 'payload/shared'\nimport type { ChangeEvent } from 'react'\nimport { useMemo, useRef, useState } from 'react'\nimport type { ConditionFieldType } from '../conditions/fieldTypes'\nimport type { FlowStep, FlowTransition, FormFlow } from '../flow/types'\nimport { keys } from '../translations/keys'\nimport { useTranslation } from '../translations/useTranslation'\nimport { resolveMessage } from '../validation/message'\nimport { ConditionBuilder } from './ConditionBuilder'\nimport {\n\tassignFieldToStep,\n\tfieldHolders,\n\tremoveFieldFromStep,\n\tstepLabel,\n\tunassignedFields,\n} from './flowAuthoring'\nimport type { FieldRow } from './synthesizeClientField'\nimport { toStaticLabel } from './toStaticLabel'\nimport './admin.css'\n\nexport type FlowBuilderProps = {\n\tpath?: string\n\tfield?: { label?: unknown }\n\tlabel?: unknown\n\tconditionTypes: Record<string, ConditionFieldType>\n}\n\nconst extractFieldNames = (data: Record<string, unknown>): string[] => {\n\tconst rows = Array.isArray(data.fields) ? (data.fields as FieldRow[]) : []\n\treturn rows\n\t\t.map((row) => (typeof row.name === 'string' ? row.name.trim() : null))\n\t\t.filter((name): name is string => name !== null && name.length > 0)\n}\n\ntype TransitionRowProps = {\n\ttransition: FlowTransition\n\tstepOptions: ReactSelectOption[]\n\tconditionTypes: Record<string, ConditionFieldType>\n\tisFirst: boolean\n\tisLast: boolean\n\tonChange: (next: FlowTransition) => void\n\tonRemove: () => void\n\tonMoveUp: () => void\n\tonMoveDown: () => void\n}\n\nconst TransitionRow = ({\n\ttransition,\n\tstepOptions,\n\tconditionTypes,\n\tisFirst,\n\tisLast,\n\tonChange,\n\tonRemove,\n\tonMoveUp,\n\tonMoveDown,\n}: TransitionRowProps) => {\n\tconst handleGotoChange = (selected: ReactSelectOption | ReactSelectOption[]) => {\n\t\tconst chosen = Array.isArray(selected) ? selected[0] : selected\n\t\tif (chosen) onChange({ ...transition, to: chosen.value as string })\n\t}\n\n\treturn (\n\t\t<div className=\"fb-flow-transition\">\n\t\t\t<div className=\"fb-flow-transition__header\">\n\t\t\t\t<span className=\"fb-flow-transition__label\">go to</span>\n\t\t\t\t<div className=\"fb-flow-transition__goto\">\n\t\t\t\t\t<ReactSelect\n\t\t\t\t\t\toptions={stepOptions}\n\t\t\t\t\t\tvalue={stepOptions.find((o) => o.value === transition.to) ?? undefined}\n\t\t\t\t\t\tplaceholder=\"Select step…\"\n\t\t\t\t\t\tisClearable={false}\n\t\t\t\t\t\tonChange={handleGotoChange}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"fb-flow-transition__actions\">\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"fb-flow__move-btn\"\n\t\t\t\t\t\tonClick={onMoveUp}\n\t\t\t\t\t\tdisabled={isFirst}\n\t\t\t\t\t\taria-label=\"Move transition up\"\n\t\t\t\t\t>\n\t\t\t\t\t\t↑\n\t\t\t\t\t</button>\n\t\t\t\t\t<button\n\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\tclassName=\"fb-flow__move-btn\"\n\t\t\t\t\t\tonClick={onMoveDown}\n\t\t\t\t\t\tdisabled={isLast}\n\t\t\t\t\t\taria-label=\"Move transition down\"\n\t\t\t\t\t>\n\t\t\t\t\t\t↓\n\t\t\t\t\t</button>\n\t\t\t\t\t<Button\n\t\t\t\t\t\tbuttonStyle=\"icon-label\"\n\t\t\t\t\t\ticon=\"x\"\n\t\t\t\t\t\tonClick={onRemove}\n\t\t\t\t\t\tmargin={false}\n\t\t\t\t\t\taria-label=\"Remove transition\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<span className=\"fb-flow-transition__when-label\">when</span>\n\t\t\t<div className=\"fb-flow-transition__condition\">\n\t\t\t\t<ConditionBuilder\n\t\t\t\t\tvalue={transition.when}\n\t\t\t\t\tonChange={(when) => onChange({ ...transition, when })}\n\t\t\t\t\tconditionTypes={conditionTypes}\n\t\t\t\t/>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n\ntype StepCardProps = {\n\tstep: FlowStep\n\tstepKey: string\n\tstepIndex: number\n\tstepCount: number\n\totherStepOptions: ReactSelectOption[]\n\tholders: Map<string, number>\n\tstepLabels: string[]\n\tfieldNames: string[]\n\tconditionTypes: Record<string, ConditionFieldType>\n\tisExpanded: boolean\n\tonToggle: () => void\n\tonChange: (next: FlowStep) => void\n\tonToggleField: (name: string, checked: boolean) => void\n\tonRemove: () => void\n\tonMoveUp: () => void\n\tonMoveDown: () => void\n\tonAddAbove: () => void\n\tonAddBelow: () => void\n}\n\nconst StepCard = ({\n\tstep,\n\tstepKey,\n\tstepIndex,\n\tstepCount,\n\totherStepOptions,\n\tholders,\n\tstepLabels,\n\tfieldNames,\n\tconditionTypes,\n\tisExpanded,\n\tonToggle,\n\tonChange,\n\tonToggleField,\n\tonRemove,\n\tonMoveUp,\n\tonMoveDown,\n\tonAddAbove,\n\tonAddBelow,\n}: StepCardProps) => {\n\tconst { t } = useTranslation()\n\n\tconst nextOptions: ReactSelectOption[] = [\n\t\t{ label: t(keys.flowNextTerminal), value: '' },\n\t\t...otherStepOptions,\n\t]\n\n\tconst transitions = step.transitions ?? []\n\n\t// Stable per-transition keys, mirroring the step-level scheme so transition reorder/remove\n\t// reconciles by identity rather than array position.\n\tconst tKeysRef = useRef<string[]>([])\n\tif (tKeysRef.current.length !== transitions.length) {\n\t\ttKeysRef.current = transitions.map((_, i) => tKeysRef.current[i] ?? crypto.randomUUID())\n\t}\n\tconst tKeys = tKeysRef.current\n\n\tconst addTransition = () => {\n\t\tconst firstOtherStep = otherStepOptions[0]?.value as string | undefined\n\t\tif (firstOtherStep === undefined) return\n\t\ttKeysRef.current = [...tKeys, crypto.randomUUID()]\n\t\tonChange({\n\t\t\t...step,\n\t\t\ttransitions: [...transitions, { when: {}, to: firstOtherStep }],\n\t\t})\n\t}\n\n\tconst updateTransition = (index: number, next: FlowTransition) => {\n\t\tconst updated = [...transitions]\n\t\tupdated[index] = next\n\t\tonChange({ ...step, transitions: updated })\n\t}\n\n\tconst removeTransition = (index: number) => {\n\t\ttKeysRef.current = tKeys.filter((_, i) => i !== index)\n\t\tconst updated = transitions.filter((_, i) => i !== index)\n\t\tonChange({ ...step, transitions: updated.length > 0 ? updated : undefined })\n\t}\n\n\tconst moveTransition = (from: number, to: number) => {\n\t\tconst updated = [...transitions]\n\t\tconst [item] = updated.splice(from, 1)\n\t\tif (item !== undefined) updated.splice(to, 0, item)\n\t\tconst nextKeys = [...tKeys]\n\t\tconst [movedKey] = nextKeys.splice(from, 1)\n\t\tif (movedKey !== undefined) nextKeys.splice(to, 0, movedKey)\n\t\ttKeysRef.current = nextKeys\n\t\tonChange({ ...step, transitions: updated })\n\t}\n\n\tconst handleNextChange = (selected: ReactSelectOption | ReactSelectOption[]) => {\n\t\tconst chosen = Array.isArray(selected) ? selected[0] : selected\n\t\tconst next = (chosen?.value as string | undefined) || undefined\n\t\tonChange({ ...step, next })\n\t}\n\n\tconst title = step.title?.trim() ?? ''\n\n\tconst stepHeader = (\n\t\t<div className=\"fb-flow-step__header-content\">\n\t\t\t<span className=\"fb-flow-step__index\">\n\t\t\t\t{resolveMessage(t(keys.flowStepFallbackTitle), { n: stepIndex + 1 })}\n\t\t\t</span>\n\t\t\t{title.length > 0 ? <span className=\"fb-flow-step__title\">{title}</span> : null}\n\t\t</div>\n\t)\n\n\treturn (\n\t\t<Collapsible\n\t\t\theader={stepHeader}\n\t\t\tactions={\n\t\t\t\t<Popup\n\t\t\t\t\tbutton={<MoreIcon />}\n\t\t\t\t\tbuttonType=\"default\"\n\t\t\t\t\thorizontalAlign=\"right\"\n\t\t\t\t\tsize=\"fit-content\"\n\t\t\t\t\tverticalAlign=\"bottom\"\n\t\t\t\t>\n\t\t\t\t\t<PopupList.ButtonGroup>\n\t\t\t\t\t\t<PopupList.Button onClick={onAddAbove}>Add above</PopupList.Button>\n\t\t\t\t\t\t<PopupList.Button onClick={onAddBelow}>Add below</PopupList.Button>\n\t\t\t\t\t\t<PopupList.Button onClick={onMoveUp} disabled={stepIndex === 0}>\n\t\t\t\t\t\t\tMove up\n\t\t\t\t\t\t</PopupList.Button>\n\t\t\t\t\t\t<PopupList.Button onClick={onMoveDown} disabled={stepIndex === stepCount - 1}>\n\t\t\t\t\t\t\tMove down\n\t\t\t\t\t\t</PopupList.Button>\n\t\t\t\t\t\t<PopupList.Button onClick={onRemove}>Remove</PopupList.Button>\n\t\t\t\t\t</PopupList.ButtonGroup>\n\t\t\t\t</Popup>\n\t\t\t}\n\t\t\tisCollapsed={!isExpanded}\n\t\t\tonToggle={() => onToggle()}\n\t\t\tclassName=\"fb-flow-step\"\n\t\t>\n\t\t\t<div className=\"fb-flow-step__body\">\n\t\t\t\t<TextInput\n\t\t\t\t\tpath={`fb-flow-step-${stepKey}-title`}\n\t\t\t\t\tlabel=\"Title\"\n\t\t\t\t\tvalue={step.title ?? ''}\n\t\t\t\t\tplaceholder=\"Optional display title\"\n\t\t\t\t\tonChange={(e: ChangeEvent<HTMLInputElement>) =>\n\t\t\t\t\t\tonChange({ ...step, title: e.target.value.length > 0 ? e.target.value : undefined })\n\t\t\t\t\t}\n\t\t\t\t/>\n\n\t\t\t\t<div className=\"fb-flow-step__row\">\n\t\t\t\t\t<FieldLabel label=\"Fields\" />\n\t\t\t\t\t{fieldNames.length === 0 ? (\n\t\t\t\t\t\t<p className=\"fb-flow-step__hint\">No fields defined on the form yet.</p>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<div className=\"fb-flow-step__field-picker\">\n\t\t\t\t\t\t\t{fieldNames.map((name) => {\n\t\t\t\t\t\t\t\tconst holder = holders.get(name)\n\t\t\t\t\t\t\t\tconst inOtherStep = holder !== undefined && holder !== stepIndex\n\t\t\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t\t\t<div key={name} className=\"fb-flow-step__field-option\">\n\t\t\t\t\t\t\t\t\t\t<CheckboxInput\n\t\t\t\t\t\t\t\t\t\t\tlabel={name}\n\t\t\t\t\t\t\t\t\t\t\tchecked={step.fields.includes(name) || inOtherStep}\n\t\t\t\t\t\t\t\t\t\t\treadOnly={inOtherStep}\n\t\t\t\t\t\t\t\t\t\t\tonToggle={(e) => {\n\t\t\t\t\t\t\t\t\t\t\t\tif (inOtherStep) return\n\t\t\t\t\t\t\t\t\t\t\t\tonToggleField(name, e.target.checked)\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t\t\t{inOtherStep ? (\n\t\t\t\t\t\t\t\t\t\t\t<span className=\"fb-flow-step__field-hint\">\n\t\t\t\t\t\t\t\t\t\t\t\t{resolveMessage(t(keys.flowFieldInStep), {\n\t\t\t\t\t\t\t\t\t\t\t\t\tstep: stepLabels[holder] ?? '',\n\t\t\t\t\t\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"fb-flow-step__row\">\n\t\t\t\t\t<FieldLabel label=\"Default next\" />\n\t\t\t\t\t<ReactSelect\n\t\t\t\t\t\toptions={nextOptions}\n\t\t\t\t\t\tvalue={\n\t\t\t\t\t\t\tstep.next\n\t\t\t\t\t\t\t\t? (nextOptions.find((o) => o.value === step.next) ?? undefined)\n\t\t\t\t\t\t\t\t: (nextOptions[0] ?? undefined)\n\t\t\t\t\t\t}\n\t\t\t\t\t\tisClearable={false}\n\t\t\t\t\t\tonChange={handleNextChange}\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\n\t\t\t\t<div className=\"fb-flow-step__transitions\">\n\t\t\t\t\t<div className=\"fb-flow-step__transitions-header\">\n\t\t\t\t\t\t<FieldLabel label=\"Conditional transitions\" />\n\t\t\t\t\t\t<span className=\"fb-flow-step__hint\">(first match wins)</span>\n\t\t\t\t\t</div>\n\t\t\t\t\t{transitions.map((transition, tIndex) => {\n\t\t\t\t\t\tconst tKey = tKeys[tIndex]\n\t\t\t\t\t\tif (tKey === undefined) return null\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<TransitionRow\n\t\t\t\t\t\t\t\tkey={tKey}\n\t\t\t\t\t\t\t\ttransition={transition}\n\t\t\t\t\t\t\t\tstepOptions={otherStepOptions}\n\t\t\t\t\t\t\t\tconditionTypes={conditionTypes}\n\t\t\t\t\t\t\t\tisFirst={tIndex === 0}\n\t\t\t\t\t\t\t\tisLast={tIndex === transitions.length - 1}\n\t\t\t\t\t\t\t\tonChange={(next) => updateTransition(tIndex, next)}\n\t\t\t\t\t\t\t\tonRemove={() => removeTransition(tIndex)}\n\t\t\t\t\t\t\t\tonMoveUp={() => moveTransition(tIndex, tIndex - 1)}\n\t\t\t\t\t\t\t\tonMoveDown={() => moveTransition(tIndex, tIndex + 1)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)\n\t\t\t\t\t})}\n\t\t\t\t\t<Button\n\t\t\t\t\t\tbuttonStyle=\"icon-label\"\n\t\t\t\t\t\ticon=\"plus\"\n\t\t\t\t\t\ticonStyle=\"with-border\"\n\t\t\t\t\t\ticonPosition=\"left\"\n\t\t\t\t\t\tonClick={addTransition}\n\t\t\t\t\t\tmargin={false}\n\t\t\t\t\t>\n\t\t\t\t\t\tAdd transition\n\t\t\t\t\t</Button>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</Collapsible>\n\t)\n}\n\nexport const FlowBuilder = (props: FlowBuilderProps) => {\n\tconst { setValue, value } = useField<FormFlow | undefined>()\n\tconst { t } = useTranslation()\n\tconst label = toStaticLabel(props.field?.label ?? props.label)\n\tconst [expandedKeys, setExpandedKeys] = useState<Set<string>>(new Set())\n\n\tconst fieldNamesJson = useFormFields(([fields]) =>\n\t\tJSON.stringify(extractFieldNames(reduceFieldsToValues(fields, true) as Record<string, unknown>))\n\t)\n\tconst fieldNames = useMemo(() => JSON.parse(fieldNamesJson) as string[], [fieldNamesJson])\n\n\tconst steps = value?.steps ?? []\n\tconst fallbackTitle = t(keys.flowStepFallbackTitle)\n\tconst stepLabels = steps.map((step, index) => stepLabel(step, index, fallbackTitle))\n\tconst stepOptions: ReactSelectOption[] = steps\n\t\t.map((step, index) => ({ label: stepLabels[index] ?? '', value: step.id }))\n\t\t.filter((option) => (option.value as string).length > 0)\n\tconst holders = fieldHolders(steps)\n\tconst unassigned = unassignedFields(fieldNames, steps)\n\n\t// Stable per-step React keys, independent of step ids. Reorder/insert/remove reconcile by\n\t// identity so focused inputs and each step's expand state stay with their step instead of\n\t// jumping to whichever step now sits at that array position.\n\tconst keysRef = useRef<string[]>([])\n\tif (keysRef.current.length !== steps.length) {\n\t\tkeysRef.current = steps.map((_, i) => keysRef.current[i] ?? crypto.randomUUID())\n\t}\n\tconst stepKeys = keysRef.current\n\n\tconst toggleExpanded = (key: string) => {\n\t\tsetExpandedKeys((prev) => {\n\t\t\tconst next = new Set(prev)\n\t\t\tif (next.has(key)) next.delete(key)\n\t\t\telse next.add(key)\n\t\t\treturn next\n\t\t})\n\t}\n\n\tconst emit = (nextSteps: FlowStep[], nextKeys: string[]) => {\n\t\tkeysRef.current = nextKeys\n\t\tsetValue({ steps: nextSteps } as FormFlow)\n\t}\n\n\tconst insertStep = (at: number) => {\n\t\tconst key = crypto.randomUUID()\n\t\tconst nextSteps = [...steps]\n\t\tnextSteps.splice(at, 0, { id: crypto.randomUUID(), fields: [] })\n\t\tconst nextKeys = [...stepKeys]\n\t\tnextKeys.splice(at, 0, key)\n\t\temit(nextSteps, nextKeys)\n\t\tsetExpandedKeys((prev) => new Set(prev).add(key))\n\t}\n\n\tconst addStep = () => insertStep(steps.length)\n\n\tconst updateStep = (index: number, next: FlowStep) => {\n\t\temit(\n\t\t\tsteps.map((s, i) => (i === index ? next : s)),\n\t\t\tstepKeys\n\t\t)\n\t}\n\n\tconst toggleField = (stepIndex: number, name: string, checked: boolean) => {\n\t\tconst nextSteps = checked\n\t\t\t? assignFieldToStep(steps, stepIndex, name)\n\t\t\t: removeFieldFromStep(steps, stepIndex, name)\n\t\temit(nextSteps, stepKeys)\n\t}\n\n\tconst assignUnassignedField = (name: string, stepId: string) => {\n\t\tconst targetIndex = steps.findIndex((s) => s.id === stepId)\n\t\tif (targetIndex === -1) return\n\t\temit(assignFieldToStep(steps, targetIndex, name), stepKeys)\n\t}\n\n\tconst removeStep = (index: number) => {\n\t\tconst removedKey = stepKeys[index]\n\t\temit(\n\t\t\tsteps.filter((_, i) => i !== index),\n\t\t\tstepKeys.filter((_, i) => i !== index)\n\t\t)\n\t\tif (removedKey !== undefined) {\n\t\t\tsetExpandedKeys((prev) => {\n\t\t\t\tconst next = new Set(prev)\n\t\t\t\tnext.delete(removedKey)\n\t\t\t\treturn next\n\t\t\t})\n\t\t}\n\t}\n\n\tconst moveStep = (from: number, to: number) => {\n\t\tconst nextSteps = [...steps]\n\t\tconst [movedStep] = nextSteps.splice(from, 1)\n\t\tif (movedStep === undefined) return\n\t\tnextSteps.splice(to, 0, movedStep)\n\t\tconst nextKeys = [...stepKeys]\n\t\tconst [movedKey] = nextKeys.splice(from, 1)\n\t\tif (movedKey !== undefined) nextKeys.splice(to, 0, movedKey)\n\t\temit(nextSteps, nextKeys)\n\t}\n\n\treturn (\n\t\t<div className=\"field-type fb-flow-builder\">\n\t\t\t<div className=\"blocks-field__header\">\n\t\t\t\t<div className=\"blocks-field__header-wrap\">\n\t\t\t\t\t<h3>{typeof label === 'string' ? label : 'Flow'}</h3>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t\t<p className=\"fb-flow-builder__description\">{t(keys.flowDescription)}</p>\n\t\t\t{steps.length === 0 ? (\n\t\t\t\t<p className=\"fb-flow-builder__hint\">\n\t\t\t\t\tNo steps defined. Add at least two steps to enable multi-page flow routing.\n\t\t\t\t</p>\n\t\t\t) : (\n\t\t\t\t<div className=\"fb-flow-builder__steps\">\n\t\t\t\t\t{steps.map((step, index) => {\n\t\t\t\t\t\tconst key = stepKeys[index]\n\t\t\t\t\t\tif (key === undefined) return null\n\t\t\t\t\t\tconst otherStepOptions = stepOptions.filter((option) => option.value !== step.id)\n\t\t\t\t\t\treturn (\n\t\t\t\t\t\t\t<StepCard\n\t\t\t\t\t\t\t\tkey={key}\n\t\t\t\t\t\t\t\tstepKey={key}\n\t\t\t\t\t\t\t\tstep={step}\n\t\t\t\t\t\t\t\tstepIndex={index}\n\t\t\t\t\t\t\t\tstepCount={steps.length}\n\t\t\t\t\t\t\t\totherStepOptions={otherStepOptions}\n\t\t\t\t\t\t\t\tholders={holders}\n\t\t\t\t\t\t\t\tstepLabels={stepLabels}\n\t\t\t\t\t\t\t\tfieldNames={fieldNames}\n\t\t\t\t\t\t\t\tconditionTypes={props.conditionTypes}\n\t\t\t\t\t\t\t\tisExpanded={expandedKeys.has(key)}\n\t\t\t\t\t\t\t\tonToggle={() => toggleExpanded(key)}\n\t\t\t\t\t\t\t\tonChange={(next) => updateStep(index, next)}\n\t\t\t\t\t\t\t\tonToggleField={(name, checked) => toggleField(index, name, checked)}\n\t\t\t\t\t\t\t\tonRemove={() => removeStep(index)}\n\t\t\t\t\t\t\t\tonMoveUp={() => moveStep(index, index - 1)}\n\t\t\t\t\t\t\t\tonMoveDown={() => moveStep(index, index + 1)}\n\t\t\t\t\t\t\t\tonAddAbove={() => insertStep(index)}\n\t\t\t\t\t\t\t\tonAddBelow={() => insertStep(index + 1)}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t)\n\t\t\t\t\t})}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t{steps.length > 0 && unassigned.length > 0 ? (\n\t\t\t\t<div className=\"fb-flow-unassigned\">\n\t\t\t\t\t<FieldLabel label={t(keys.flowUnassigned)} />\n\t\t\t\t\t<div className=\"fb-flow-unassigned__rows\">\n\t\t\t\t\t\t{unassigned.map((name) => (\n\t\t\t\t\t\t\t<div key={name} className=\"fb-flow-unassigned__row\">\n\t\t\t\t\t\t\t\t<span className=\"fb-flow-unassigned__name\">{name}</span>\n\t\t\t\t\t\t\t\t<div className=\"fb-flow-unassigned__select\">\n\t\t\t\t\t\t\t\t\t<ReactSelect\n\t\t\t\t\t\t\t\t\t\toptions={stepOptions}\n\t\t\t\t\t\t\t\t\t\tplaceholder={t(keys.flowAssignToStep)}\n\t\t\t\t\t\t\t\t\t\tisClearable={false}\n\t\t\t\t\t\t\t\t\t\tonChange={(selected: ReactSelectOption | ReactSelectOption[]) => {\n\t\t\t\t\t\t\t\t\t\t\tconst chosen = Array.isArray(selected) ? selected[0] : selected\n\t\t\t\t\t\t\t\t\t\t\tif (chosen) assignUnassignedField(name, chosen.value as string)\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t))}\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t) : null}\n\t\t\t<div className=\"fb-flow-builder__actions\">\n\t\t\t\t<Button\n\t\t\t\t\tbuttonStyle=\"icon-label\"\n\t\t\t\t\ticon=\"plus\"\n\t\t\t\t\ticonStyle=\"with-border\"\n\t\t\t\t\ticonPosition=\"left\"\n\t\t\t\t\tonClick={addStep}\n\t\t\t\t\tmargin={false}\n\t\t\t\t>\n\t\t\t\t\tAdd step\n\t\t\t\t</Button>\n\t\t\t</div>\n\t\t</div>\n\t)\n}\n"],"mappings":"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"}
|
package/dist/client/admin.css
CHANGED
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
gap: 0.5rem;
|
|
9
9
|
margin-block-end: 1rem;
|
|
10
10
|
}
|
|
11
|
+
.fb-flow-builder__description {
|
|
12
|
+
color: var(--theme-elevation-400);
|
|
13
|
+
font-size: 0.875rem;
|
|
14
|
+
margin: 0;
|
|
15
|
+
}
|
|
11
16
|
.fb-flow-builder__hint {
|
|
12
17
|
color: var(--theme-elevation-400);
|
|
13
18
|
font-size: 0.875rem;
|
|
@@ -36,16 +41,12 @@
|
|
|
36
41
|
color: var(--theme-elevation-400);
|
|
37
42
|
flex-shrink: 0;
|
|
38
43
|
}
|
|
39
|
-
.fb-flow-
|
|
44
|
+
.fb-flow-step__title {
|
|
40
45
|
font-size: 0.875rem;
|
|
41
46
|
overflow: hidden;
|
|
42
47
|
text-overflow: ellipsis;
|
|
43
48
|
white-space: nowrap;
|
|
44
49
|
}
|
|
45
|
-
.fb-flow-step__id-preview em {
|
|
46
|
-
color: var(--theme-elevation-400);
|
|
47
|
-
font-style: italic;
|
|
48
|
-
}
|
|
49
50
|
.fb-flow-step__body {
|
|
50
51
|
padding: 0.75rem;
|
|
51
52
|
display: flex;
|
|
@@ -68,6 +69,16 @@
|
|
|
68
69
|
gap: 0.25rem 1.25rem;
|
|
69
70
|
padding-block: 0.25rem;
|
|
70
71
|
}
|
|
72
|
+
.fb-flow-step__field-option {
|
|
73
|
+
display: flex;
|
|
74
|
+
align-items: center;
|
|
75
|
+
gap: 0.375rem;
|
|
76
|
+
}
|
|
77
|
+
.fb-flow-step__field-hint {
|
|
78
|
+
font-size: 0.75rem;
|
|
79
|
+
color: var(--theme-elevation-400);
|
|
80
|
+
white-space: nowrap;
|
|
81
|
+
}
|
|
71
82
|
.fb-flow-step__transitions {
|
|
72
83
|
display: flex;
|
|
73
84
|
flex-direction: column;
|
|
@@ -80,6 +91,37 @@
|
|
|
80
91
|
gap: 0.5rem;
|
|
81
92
|
}
|
|
82
93
|
|
|
94
|
+
.fb-flow-unassigned {
|
|
95
|
+
display: flex;
|
|
96
|
+
flex-direction: column;
|
|
97
|
+
gap: 0.25rem;
|
|
98
|
+
padding: 0.75rem;
|
|
99
|
+
border: 1px solid var(--theme-border-color);
|
|
100
|
+
border-radius: var(--style-radius-s);
|
|
101
|
+
}
|
|
102
|
+
.fb-flow-unassigned__rows {
|
|
103
|
+
display: flex;
|
|
104
|
+
flex-direction: column;
|
|
105
|
+
gap: 0.375rem;
|
|
106
|
+
}
|
|
107
|
+
.fb-flow-unassigned__row {
|
|
108
|
+
display: flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
gap: 0.75rem;
|
|
111
|
+
}
|
|
112
|
+
.fb-flow-unassigned__name {
|
|
113
|
+
font-size: 0.875rem;
|
|
114
|
+
flex: 1;
|
|
115
|
+
min-width: 0;
|
|
116
|
+
overflow: hidden;
|
|
117
|
+
text-overflow: ellipsis;
|
|
118
|
+
white-space: nowrap;
|
|
119
|
+
}
|
|
120
|
+
.fb-flow-unassigned__select {
|
|
121
|
+
flex: 0 1 14rem;
|
|
122
|
+
min-width: 9rem;
|
|
123
|
+
}
|
|
124
|
+
|
|
83
125
|
.fb-flow-transition {
|
|
84
126
|
border: 1px solid var(--theme-border-color);
|
|
85
127
|
border-radius: var(--style-radius-s);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import "../flow/stepLabel.js";
|
|
2
|
+
//#region src/client/flowAuthoring.ts
|
|
3
|
+
/** Field name to index of the step holding it (first occurrence wins). */
|
|
4
|
+
const fieldHolders = (steps) => {
|
|
5
|
+
const holders = /* @__PURE__ */ new Map();
|
|
6
|
+
steps.forEach((step, index) => {
|
|
7
|
+
for (const field of step.fields) if (!holders.has(field)) holders.set(field, index);
|
|
8
|
+
});
|
|
9
|
+
return holders;
|
|
10
|
+
};
|
|
11
|
+
/** Form fields not assigned to any step, in form order. */
|
|
12
|
+
const unassignedFields = (fieldNames, steps) => {
|
|
13
|
+
const assigned = new Set(steps.flatMap((step) => step.fields));
|
|
14
|
+
return fieldNames.filter((name) => !assigned.has(name));
|
|
15
|
+
};
|
|
16
|
+
/** Assign a field to the step at `targetIndex`, stripping it from every other step. */
|
|
17
|
+
const assignFieldToStep = (steps, targetIndex, field) => steps.map((step, index) => {
|
|
18
|
+
if (index === targetIndex) return step.fields.includes(field) ? step : {
|
|
19
|
+
...step,
|
|
20
|
+
fields: [...step.fields, field]
|
|
21
|
+
};
|
|
22
|
+
return step.fields.includes(field) ? {
|
|
23
|
+
...step,
|
|
24
|
+
fields: step.fields.filter((f) => f !== field)
|
|
25
|
+
} : step;
|
|
26
|
+
});
|
|
27
|
+
/** Remove a field from the step at `targetIndex`, leaving other steps untouched. */
|
|
28
|
+
const removeFieldFromStep = (steps, targetIndex, field) => steps.map((step, index) => index === targetIndex && step.fields.includes(field) ? {
|
|
29
|
+
...step,
|
|
30
|
+
fields: step.fields.filter((f) => f !== field)
|
|
31
|
+
} : step);
|
|
32
|
+
//#endregion
|
|
33
|
+
export { assignFieldToStep, fieldHolders, removeFieldFromStep, unassignedFields };
|
|
34
|
+
|
|
35
|
+
//# sourceMappingURL=flowAuthoring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flowAuthoring.js","names":[],"sources":["../../src/client/flowAuthoring.ts"],"sourcesContent":["import type { FlowStep } from '../flow/types'\n\nexport { stepLabel } from '../flow/stepLabel'\n\n/** Field name to index of the step holding it (first occurrence wins). */\nexport const fieldHolders = (steps: Pick<FlowStep, 'fields'>[]): Map<string, number> => {\n\tconst holders = new Map<string, number>()\n\tsteps.forEach((step, index) => {\n\t\tfor (const field of step.fields) {\n\t\t\tif (!holders.has(field)) holders.set(field, index)\n\t\t}\n\t})\n\treturn holders\n}\n\n/** Form fields not assigned to any step, in form order. */\nexport const unassignedFields = (\n\tfieldNames: string[],\n\tsteps: Pick<FlowStep, 'fields'>[]\n): string[] => {\n\tconst assigned = new Set(steps.flatMap((step) => step.fields))\n\treturn fieldNames.filter((name) => !assigned.has(name))\n}\n\n/** Assign a field to the step at `targetIndex`, stripping it from every other step. */\nexport const assignFieldToStep = (\n\tsteps: FlowStep[],\n\ttargetIndex: number,\n\tfield: string\n): FlowStep[] =>\n\tsteps.map((step, index) => {\n\t\tif (index === targetIndex) {\n\t\t\treturn step.fields.includes(field) ? step : { ...step, fields: [...step.fields, field] }\n\t\t}\n\t\treturn step.fields.includes(field)\n\t\t\t? { ...step, fields: step.fields.filter((f) => f !== field) }\n\t\t\t: step\n\t})\n\n/** Remove a field from the step at `targetIndex`, leaving other steps untouched. */\nexport const removeFieldFromStep = (\n\tsteps: FlowStep[],\n\ttargetIndex: number,\n\tfield: string\n): FlowStep[] =>\n\tsteps.map((step, index) =>\n\t\tindex === targetIndex && step.fields.includes(field)\n\t\t\t? { ...step, fields: step.fields.filter((f) => f !== field) }\n\t\t\t: step\n\t)\n"],"mappings":";;;AAKA,MAAa,gBAAgB,UAA2D;CACvF,MAAM,0BAAU,IAAI,IAAoB;CACxC,MAAM,SAAS,MAAM,UAAU;EAC9B,KAAK,MAAM,SAAS,KAAK,QACxB,IAAI,CAAC,QAAQ,IAAI,KAAK,GAAG,QAAQ,IAAI,OAAO,KAAK;CAEnD,CAAC;CACD,OAAO;AACR;;AAGA,MAAa,oBACZ,YACA,UACc;CACd,MAAM,WAAW,IAAI,IAAI,MAAM,SAAS,SAAS,KAAK,MAAM,CAAC;CAC7D,OAAO,WAAW,QAAQ,SAAS,CAAC,SAAS,IAAI,IAAI,CAAC;AACvD;;AAGA,MAAa,qBACZ,OACA,aACA,UAEA,MAAM,KAAK,MAAM,UAAU;CAC1B,IAAI,UAAU,aACb,OAAO,KAAK,OAAO,SAAS,KAAK,IAAI,OAAO;EAAE,GAAG;EAAM,QAAQ,CAAC,GAAG,KAAK,QAAQ,KAAK;CAAE;CAExF,OAAO,KAAK,OAAO,SAAS,KAAK,IAC9B;EAAE,GAAG;EAAM,QAAQ,KAAK,OAAO,QAAQ,MAAM,MAAM,KAAK;CAAE,IAC1D;AACJ,CAAC;;AAGF,MAAa,uBACZ,OACA,aACA,UAEA,MAAM,KAAK,MAAM,UAChB,UAAU,eAAe,KAAK,OAAO,SAAS,KAAK,IAChD;CAAE,GAAG;CAAM,QAAQ,KAAK,OAAO,QAAQ,MAAM,MAAM,KAAK;AAAE,IAC1D,IACJ"}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
//#region src/client/synthesizeClientField.ts
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Project a stored field row into a condition operand, or `null` when the row has no usable name or
|
|
4
|
+
* its type is absent from the condition-type map (not conditionable, e.g. a display-only message).
|
|
5
|
+
*/
|
|
3
6
|
const operandFromRow = (row, conditionTypes) => {
|
|
4
7
|
const name = typeof row.name === "string" ? row.name.trim() : "";
|
|
5
8
|
if (name.length === 0) return null;
|
|
6
|
-
const conditionType = conditionTypes[row.blockType]
|
|
9
|
+
const conditionType = conditionTypes[row.blockType];
|
|
10
|
+
if (!conditionType) return null;
|
|
7
11
|
return {
|
|
8
12
|
name,
|
|
9
13
|
label: typeof row.label === "string" && row.label.length > 0 ? row.label : name,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"synthesizeClientField.js","names":[],"sources":["../../src/client/synthesizeClientField.ts"],"sourcesContent":["import type {\n\tDateFieldClient,\n\tNumberFieldClient,\n\tOption,\n\tSelectFieldClient,\n\tTextFieldClient,\n} from 'payload'\nimport type { ConditionFieldType } from '../conditions/fieldTypes'\n\n/** A field row as stored in the form's `fields` blocks array (only the keys the builder reads). */\nexport type FieldRow = {\n\tblockType: string\n\tname?: string\n\tlabel?: string\n\toptions?: Option[]\n\t[key: string]: unknown\n}\n\n/** A condition operand: a selectable form field the builder can compare against. */\nexport type ConditionOperand = {\n\tname: string\n\tlabel: string\n\tconditionType: ConditionFieldType\n\toptions?: Option[]\n}\n\n
|
|
1
|
+
{"version":3,"file":"synthesizeClientField.js","names":[],"sources":["../../src/client/synthesizeClientField.ts"],"sourcesContent":["import type {\n\tDateFieldClient,\n\tNumberFieldClient,\n\tOption,\n\tSelectFieldClient,\n\tTextFieldClient,\n} from 'payload'\nimport type { ConditionFieldType } from '../conditions/fieldTypes'\n\n/** A field row as stored in the form's `fields` blocks array (only the keys the builder reads). */\nexport type FieldRow = {\n\tblockType: string\n\tname?: string\n\tlabel?: string\n\toptions?: Option[]\n\t[key: string]: unknown\n}\n\n/** A condition operand: a selectable form field the builder can compare against. */\nexport type ConditionOperand = {\n\tname: string\n\tlabel: string\n\tconditionType: ConditionFieldType\n\toptions?: Option[]\n}\n\n/**\n * Project a stored field row into a condition operand, or `null` when the row has no usable name or\n * its type is absent from the condition-type map (not conditionable, e.g. a display-only message).\n */\nexport const operandFromRow = (\n\trow: FieldRow,\n\tconditionTypes: Record<string, ConditionFieldType>\n): ConditionOperand | null => {\n\tconst name = typeof row.name === 'string' ? row.name.trim() : ''\n\tif (name.length === 0) {\n\t\treturn null\n\t}\n\tconst conditionType = conditionTypes[row.blockType]\n\tif (!conditionType) {\n\t\treturn null\n\t}\n\treturn {\n\t\tname,\n\t\tlabel: typeof row.label === 'string' && row.label.length > 0 ? row.label : name,\n\t\tconditionType,\n\t\toptions: Array.isArray(row.options) ? row.options : undefined,\n\t}\n}\n\n/**\n * Build the minimal `*FieldClient` a Payload leaf condition input requires for a given operand. Casts\n * are localized to these four synths and nowhere else: `FieldBaseClient` requires only `name`, and each\n * leaf is `FieldBaseClient & Pick<…, 'type' | …>` where every picked member but `type` (and `select`'s\n * required `options`) is optional, so the literals are structurally complete. `dateClientField` omits\n * `admin.date`, so `DateCondition` falls back to its default date format. Each synth returns a single\n * concrete client type so leaf `field` props need no narrowing.\n */\nexport const textClientField = (operand: ConditionOperand): TextFieldClient =>\n\t({ name: operand.name, label: operand.label, type: 'text' }) as TextFieldClient\n\nexport const numberClientField = (operand: ConditionOperand): NumberFieldClient =>\n\t({ name: operand.name, label: operand.label, type: 'number' }) as NumberFieldClient\n\nexport const dateClientField = (operand: ConditionOperand): DateFieldClient =>\n\t({ name: operand.name, label: operand.label, type: 'date' }) as DateFieldClient\n\nexport const selectClientField = (operand: ConditionOperand): SelectFieldClient =>\n\t({\n\t\tname: operand.name,\n\t\tlabel: operand.label,\n\t\ttype: 'select',\n\t\toptions: operand.options ?? [],\n\t}) as SelectFieldClient\n"],"mappings":";;;;;AA8BA,MAAa,kBACZ,KACA,mBAC6B;CAC7B,MAAM,OAAO,OAAO,IAAI,SAAS,WAAW,IAAI,KAAK,KAAK,IAAI;CAC9D,IAAI,KAAK,WAAW,GACnB,OAAO;CAER,MAAM,gBAAgB,eAAe,IAAI;CACzC,IAAI,CAAC,eACJ,OAAO;CAER,OAAO;EACN;EACA,OAAO,OAAO,IAAI,UAAU,YAAY,IAAI,MAAM,SAAS,IAAI,IAAI,QAAQ;EAC3E;EACA,SAAS,MAAM,QAAQ,IAAI,OAAO,IAAI,IAAI,UAAU,KAAA;CACrD;AACD;;;;;;;;;AAUA,MAAa,mBAAmB,aAC9B;CAAE,MAAM,QAAQ;CAAM,OAAO,QAAQ;CAAO,MAAM;AAAO;AAE3D,MAAa,qBAAqB,aAChC;CAAE,MAAM,QAAQ;CAAM,OAAO,QAAQ;CAAO,MAAM;AAAS;AAE7D,MAAa,mBAAmB,aAC9B;CAAE,MAAM,QAAQ;CAAM,OAAO,QAAQ;CAAO,MAAM;AAAO;AAE3D,MAAa,qBAAqB,aAChC;CACA,MAAM,QAAQ;CACd,OAAO,QAAQ;CACf,MAAM;CACN,SAAS,QAAQ,WAAW,CAAC;AAC9B"}
|