@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.
Files changed (166) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +2 -2
  3. package/dist/actions/body/serializeBody.d.ts +19 -4
  4. package/dist/actions/body/serializeBody.js +3 -1
  5. package/dist/actions/body/serializeBody.js.map +1 -1
  6. package/dist/actions/builtin/confirmation.js +13 -4
  7. package/dist/actions/builtin/confirmation.js.map +1 -1
  8. package/dist/actions/builtin/emailTeam.js +13 -4
  9. package/dist/actions/builtin/emailTeam.js.map +1 -1
  10. package/dist/actions/builtin/index.d.ts +13 -1
  11. package/dist/actions/builtin/index.js +18 -7
  12. package/dist/actions/builtin/index.js.map +1 -1
  13. package/dist/actions/builtin/signedWebhook.js +2 -16
  14. package/dist/actions/builtin/signedWebhook.js.map +1 -1
  15. package/dist/actions/runActions.js +2 -0
  16. package/dist/actions/runActions.js.map +1 -1
  17. package/dist/aggregation/resolveResultsRequest.d.ts +22 -6
  18. package/dist/aggregation/resolveResultsRequest.js +18 -7
  19. package/dist/aggregation/resolveResultsRequest.js.map +1 -1
  20. package/dist/client/FlowBuilder.js +98 -53
  21. package/dist/client/FlowBuilder.js.map +1 -1
  22. package/dist/client/admin.css +47 -5
  23. package/dist/client/flowAuthoring.js +35 -0
  24. package/dist/client/flowAuthoring.js.map +1 -0
  25. package/dist/client/synthesizeClientField.js +6 -2
  26. package/dist/client/synthesizeClientField.js.map +1 -1
  27. package/dist/collections/formSubmissions.js +47 -9
  28. package/dist/collections/formSubmissions.js.map +1 -1
  29. package/dist/collections/forms.js +180 -34
  30. package/dist/collections/forms.js.map +1 -1
  31. package/dist/conditions/conditionType.js +9 -2
  32. package/dist/conditions/conditionType.js.map +1 -1
  33. package/dist/conditions/normalizeConditions.js +2 -1
  34. package/dist/conditions/normalizeConditions.js.map +1 -1
  35. package/dist/consent/builtin/index.d.ts +11 -1
  36. package/dist/consent/builtin/index.js +15 -5
  37. package/dist/consent/builtin/index.js.map +1 -1
  38. package/dist/consent/builtin/static.js +7 -3
  39. package/dist/consent/builtin/static.js.map +1 -1
  40. package/dist/exports/react.d.ts +10 -6
  41. package/dist/exports/react.js +6 -2
  42. package/dist/exports/rsc.d.ts +6 -1
  43. package/dist/exports/rsc.js +6 -1
  44. package/dist/exports/types.d.ts +4 -4
  45. package/dist/fields/buildFieldBlocks.js +17 -8
  46. package/dist/fields/buildFieldBlocks.js.map +1 -1
  47. package/dist/fields/builtin/consent.js +8 -4
  48. package/dist/fields/builtin/consent.js.map +1 -1
  49. package/dist/fields/builtin/file.js +8 -4
  50. package/dist/fields/builtin/file.js.map +1 -1
  51. package/dist/fields/builtin/index.d.ts +11 -1
  52. package/dist/fields/builtin/index.js +21 -9
  53. package/dist/fields/builtin/index.js.map +1 -1
  54. package/dist/fields/builtin/message.js +26 -0
  55. package/dist/fields/builtin/message.js.map +1 -0
  56. package/dist/fields/builtin/repeater.js +7 -3
  57. package/dist/fields/builtin/repeater.js.map +1 -1
  58. package/dist/fields/builtin/select.js +7 -3
  59. package/dist/fields/builtin/select.js.map +1 -1
  60. package/dist/fields/localizedIf.d.ts +13 -0
  61. package/dist/fields/localizedIf.js +12 -0
  62. package/dist/fields/localizedIf.js.map +1 -0
  63. package/dist/fields/sharedConfig.js +64 -51
  64. package/dist/fields/sharedConfig.js.map +1 -1
  65. package/dist/fields/types.d.ts +7 -2
  66. package/dist/flow/normalizeFlow.js +7 -1
  67. package/dist/flow/normalizeFlow.js.map +1 -1
  68. package/dist/flow/stepLabel.js +15 -0
  69. package/dist/flow/stepLabel.js.map +1 -0
  70. package/dist/form/pollState.d.ts +22 -0
  71. package/dist/form/pollState.js +17 -0
  72. package/dist/form/pollState.js.map +1 -0
  73. package/dist/form/toFormDocument.d.ts +60 -0
  74. package/dist/form/toFormDocument.js +39 -0
  75. package/dist/form/toFormDocument.js.map +1 -0
  76. package/dist/form/types.d.ts +48 -0
  77. package/dist/index.d.ts +69 -18
  78. package/dist/index.js +24 -13
  79. package/dist/index.js.map +1 -1
  80. package/dist/plugin/registerCollections.js +15 -36
  81. package/dist/plugin/registerCollections.js.map +1 -1
  82. package/dist/plugin/uploadsCollection.d.ts +11 -0
  83. package/dist/plugin/uploadsCollection.js +44 -0
  84. package/dist/plugin/uploadsCollection.js.map +1 -0
  85. package/dist/poll/applyPollOptions.js +17 -0
  86. package/dist/poll/applyPollOptions.js.map +1 -0
  87. package/dist/poll/buildPollOptionSourceFields.js +53 -0
  88. package/dist/poll/buildPollOptionSourceFields.js.map +1 -0
  89. package/dist/poll/definePollOptionSource.d.ts +35 -0
  90. package/dist/poll/definePollOptionSource.js +6 -0
  91. package/dist/poll/definePollOptionSource.js.map +1 -0
  92. package/dist/poll/registry.d.ts +16 -0
  93. package/dist/poll/registry.js +16 -0
  94. package/dist/poll/registry.js.map +1 -0
  95. package/dist/poll/resolvePollOptions.d.ts +28 -0
  96. package/dist/poll/resolvePollOptions.js +64 -0
  97. package/dist/poll/resolvePollOptions.js.map +1 -0
  98. package/dist/poll/resolvePollOutcome.d.ts +21 -0
  99. package/dist/poll/resolvePollOutcome.js +36 -0
  100. package/dist/poll/resolvePollOutcome.js.map +1 -0
  101. package/dist/prefill/valuesFromSearchParams.js +1 -1
  102. package/dist/prefill/valuesFromSearchParams.js.map +1 -1
  103. package/dist/presentations/types.d.ts +3 -2
  104. package/dist/react/Form.d.ts +13 -31
  105. package/dist/react/Form.js +96 -83
  106. package/dist/react/Form.js.map +1 -1
  107. package/dist/react/FormContext.d.ts +35 -1
  108. package/dist/react/FormContext.js.map +1 -1
  109. package/dist/react/FormControls.d.ts +55 -0
  110. package/dist/react/FormControls.js +56 -0
  111. package/dist/react/FormControls.js.map +1 -0
  112. package/dist/react/FormResults.d.ts +6 -3
  113. package/dist/react/FormResults.js +37 -29
  114. package/dist/react/FormResults.js.map +1 -1
  115. package/dist/react/FormSteps.d.ts +17 -0
  116. package/dist/react/FormSteps.js +35 -0
  117. package/dist/react/FormSteps.js.map +1 -0
  118. package/dist/react/Poll.d.ts +17 -6
  119. package/dist/react/Poll.js +66 -18
  120. package/dist/react/Poll.js.map +1 -1
  121. package/dist/react/fetchResults.d.ts +1 -1
  122. package/dist/react/fetchResults.js +1 -1
  123. package/dist/react/fetchResults.js.map +1 -1
  124. package/dist/react/renderers/file.js +5 -1
  125. package/dist/react/renderers/file.js.map +1 -1
  126. package/dist/react/renderers/index.js +2 -0
  127. package/dist/react/renderers/index.js.map +1 -1
  128. package/dist/react/renderers/message.js +35 -0
  129. package/dist/react/renderers/message.js.map +1 -0
  130. package/dist/react/state.d.ts +25 -1
  131. package/dist/react/state.js +14 -1
  132. package/dist/react/state.js.map +1 -1
  133. package/dist/react/uploadFile.d.ts +2 -2
  134. package/dist/react/uploadFile.js +1 -1
  135. package/dist/react/uploadFile.js.map +1 -1
  136. package/dist/submissions/runSubmission.js +70 -33
  137. package/dist/submissions/runSubmission.js.map +1 -1
  138. package/dist/submissions/validateSubmission.js +41 -7
  139. package/dist/submissions/validateSubmission.js.map +1 -1
  140. package/dist/submissions/votedCookie.d.ts +13 -0
  141. package/dist/submissions/votedCookie.js +27 -0
  142. package/dist/submissions/votedCookie.js.map +1 -0
  143. package/dist/translations/de.js +219 -0
  144. package/dist/translations/de.js.map +1 -0
  145. package/dist/translations/en.js +45 -6
  146. package/dist/translations/en.js.map +1 -1
  147. package/dist/translations/index.d.ts +2 -1
  148. package/dist/translations/index.js +6 -2
  149. package/dist/translations/index.js.map +1 -1
  150. package/dist/translations/keys.d.ts +43 -4
  151. package/dist/translations/keys.js +44 -5
  152. package/dist/translations/keys.js.map +1 -1
  153. package/dist/uploads/types.d.ts +1 -2
  154. package/dist/validation/validateUrl.js +22 -0
  155. package/dist/validation/validateUrl.js.map +1 -0
  156. package/package.json +2 -1
  157. package/styles/form-builder.css +10 -0
  158. package/dist/collections/uploads.d.ts +0 -30
  159. package/dist/collections/uploads.js +0 -55
  160. package/dist/collections/uploads.js.map +0 -1
  161. package/dist/presentations/registry.d.ts +0 -15
  162. package/dist/presentations/registry.js +0 -15
  163. package/dist/presentations/registry.js.map +0 -1
  164. package/dist/react/toFormDocument.d.ts +0 -24
  165. package/dist/react/toFormDocument.js +0 -22
  166. 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, stepIds, conditionTypes, isFirst, isLast, onChange, onRemove, onMoveUp, onMoveDown }) => {
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: toOptions,
41
- value: toOptions.find((o) => o.value === transition.to) ?? void 0,
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, otherStepIds, fieldNames, conditionTypes, isExpanded, onToggle, onChange, onRemove, onMoveUp, onMoveDown, onAddAbove, onAddBelow }) => {
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: "— terminal —",
99
+ label: t(keys.flowNextTerminal),
98
100
  value: ""
99
- }, ...otherStepIds.map((id) => ({
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 = otherStepIds[0];
109
- if (!firstOtherStep) return;
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__ */ jsxs("span", {
158
+ children: [/* @__PURE__ */ jsx("span", {
159
159
  className: "fb-flow-step__index",
160
- children: ["Step ", stepIndex + 1]
161
- }), /* @__PURE__ */ jsx("span", {
162
- className: "fb-flow-step__id-preview",
163
- children: step.id.length > 0 ? step.id : /* @__PURE__ */ jsx("em", { children: "no id" })
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) => /* @__PURE__ */ jsx(CheckboxInput, {
231
- label: name,
232
- checked: step.fields.includes(name),
233
- onToggle: (e) => {
234
- const fields = e.target.checked ? [...step.fields, name] : step.fields.filter((f) => f !== name);
235
- onChange({
236
- ...step,
237
- fields
238
- });
239
- }
240
- }, name))
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
- stepIds: otherStepIds,
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 allStepIds = steps.map((s) => s.id).filter((id) => id.length > 0);
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 keys = keysRef.current;
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 = [...keys];
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), keys);
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 = keys[index];
333
- emit(steps.filter((_, i) => i !== index), keys.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 = [...keys];
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 = keys[index];
384
+ const key = stepKeys[index];
367
385
  if (key === void 0) return null;
368
- const otherStepIds = allStepIds.filter((id) => id !== step.id);
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
- otherStepIds,
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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"}
@@ -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-step__id-preview {
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
- /** Project a stored field row into a condition operand, or `null` when the row has no usable name. */
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] ?? "text";
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/** Project a stored field row into a condition operand, or `null` when the row has no usable name. */\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] ?? 'text'\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":";;AA2BA,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,cAAc;CACvD,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"}
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"}