@orion-studios/payload-studio 0.6.0-beta.25 → 0.6.0-beta.27

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.
@@ -749,7 +749,7 @@ var init_OrionBlocksFieldImpl = __esm({
749
749
  const schemaPath = schemaPathFromProps ?? name;
750
750
  const minRows = minRowsProp ?? (required ? 1 : 0);
751
751
  const { setDocFieldPreferences } = (0, import_DocumentInfo.useDocumentInfo)();
752
- const { addFieldRow, dispatchFields, getFields, moveFieldRow, removeFieldRow, replaceState, setModified } = (0, import_Form.useForm)();
752
+ const { addFieldRow, dispatchFields, getFields: getFields2, moveFieldRow, removeFieldRow, replaceState, setModified } = (0, import_Form.useForm)();
753
753
  const { code: locale } = (0, import_Locale.useLocale)();
754
754
  const configContext = (0, import_Config.useConfig)();
755
755
  const config = configContext?.config ?? {};
@@ -911,7 +911,7 @@ var init_OrionBlocksFieldImpl = __esm({
911
911
  (rowIndex) => {
912
912
  const result = clipboardCopy({
913
913
  getDataToCopy: () => reduceFormStateByPath({
914
- formState: getFields(),
914
+ formState: getFields2(),
915
915
  path: safePath,
916
916
  rowIndex
917
917
  }),
@@ -929,13 +929,13 @@ var init_OrionBlocksFieldImpl = __esm({
929
929
  import_sonner.toast.success(t("general:copied"));
930
930
  }
931
931
  },
932
- [clientBlocks, getFields, safePath, t, type]
932
+ [clientBlocks, getFields2, safePath, t, type]
933
933
  );
934
934
  const pasteRow = (0, import_react10.useCallback)(
935
935
  (rowIndex) => {
936
936
  const result = clipboardPaste({
937
937
  onPaste: (dataFromClipboard) => {
938
- const formState = getFields();
938
+ const formState = getFields2();
939
939
  const newState = mergeFormStateFromClipboard({
940
940
  dataFromClipboard,
941
941
  formState,
@@ -952,11 +952,11 @@ var init_OrionBlocksFieldImpl = __esm({
952
952
  import_sonner.toast.error(result);
953
953
  }
954
954
  },
955
- [clientBlocks, getFields, replaceState, safePath, setModified, t]
955
+ [clientBlocks, getFields2, replaceState, safePath, setModified, t]
956
956
  );
957
957
  const pasteBlocks = (0, import_react10.useCallback)(
958
958
  (dataFromClipboard) => {
959
- const formState = getFields();
959
+ const formState = getFields2();
960
960
  const newState = mergeFormStateFromClipboard({
961
961
  dataFromClipboard,
962
962
  formState,
@@ -965,7 +965,7 @@ var init_OrionBlocksFieldImpl = __esm({
965
965
  replaceState(newState);
966
966
  setModified(true);
967
967
  },
968
- [getFields, replaceState, safePath, setModified]
968
+ [getFields2, replaceState, safePath, setModified]
969
969
  );
970
970
  const hasMaxRows = Boolean(maxRows && rows.length >= maxRows);
971
971
  const fieldErrorCount = errorPaths.length;
@@ -1042,7 +1042,7 @@ var init_OrionBlocksFieldImpl = __esm({
1042
1042
  className: `${baseClass}__header-action`,
1043
1043
  disabled,
1044
1044
  getDataToCopy: () => reduceFormStateByPath({
1045
- formState: getFields(),
1045
+ formState: getFields2(),
1046
1046
  path: safePath
1047
1047
  }),
1048
1048
  onPaste: pasteBlocks,
@@ -8258,15 +8258,11 @@ var getFormTitle2 = (value) => {
8258
8258
  // src/admin/components/studio/AdminStudioFormDetailView.tsx
8259
8259
  var import_jsx_runtime41 = require("react/jsx-runtime");
8260
8260
  var getNonEmptyText = (value, fallback = "") => typeof value === "string" && value.trim().length > 0 ? value : fallback;
8261
- var formatStepsText = (value) => {
8261
+ var normalizeSteps = (value) => {
8262
8262
  if (!Array.isArray(value)) {
8263
- return "[]";
8264
- }
8265
- try {
8266
- return JSON.stringify(value, null, 2);
8267
- } catch {
8268
- return "[]";
8263
+ return [];
8269
8264
  }
8265
+ return value.map((step) => step && typeof step === "object" && !Array.isArray(step) ? step : {});
8270
8266
  };
8271
8267
  var toEditorState = (doc) => {
8272
8268
  const emails = doc.emails && typeof doc.emails === "object" ? doc.emails : null;
@@ -8282,7 +8278,7 @@ var toEditorState = (doc) => {
8282
8278
  sendAdmin: emails?.sendAdmin !== false,
8283
8279
  sendConfirmation: emails?.sendConfirmation !== false,
8284
8280
  slug: getNonEmptyText(doc.slug),
8285
- stepsText: formatStepsText(doc.steps),
8281
+ steps: normalizeSteps(doc.steps),
8286
8282
  submitLabel: getNonEmptyText(doc.submitLabel, "Submit"),
8287
8283
  successMessage: getNonEmptyText(doc.successMessage),
8288
8284
  title: getNonEmptyText(doc.title, "Untitled Form")
@@ -8293,25 +8289,72 @@ var checkboxLabelStyle = {
8293
8289
  display: "flex",
8294
8290
  gap: "0.6rem"
8295
8291
  };
8296
- var codeStyle = {
8297
- background: "color-mix(in srgb, var(--orion-admin-card-bg) 82%, black)",
8298
- border: "1px solid var(--orion-admin-card-border)",
8299
- borderRadius: "var(--orion-admin-radius-sm)",
8300
- color: "var(--orion-admin-text)",
8301
- fontFamily: "ui-monospace, SFMono-Regular, SFMono-Regular, Menlo, monospace",
8302
- fontSize: "0.86rem",
8303
- lineHeight: 1.55,
8304
- margin: 0,
8305
- maxHeight: "28rem",
8306
- overflow: "auto",
8307
- padding: "0.9rem",
8308
- whiteSpace: "pre-wrap"
8309
- };
8310
8292
  var sectionGridStyle = {
8311
8293
  display: "grid",
8312
8294
  gap: "1rem",
8313
8295
  gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))"
8314
8296
  };
8297
+ var fieldTypeOptions = [
8298
+ "text",
8299
+ "textarea",
8300
+ "email",
8301
+ "phone",
8302
+ "url",
8303
+ "select",
8304
+ "radio",
8305
+ "checkbox",
8306
+ "checkbox-group",
8307
+ "date",
8308
+ "file"
8309
+ ];
8310
+ var getFields = (step) => Array.isArray(step.fields) ? step.fields.map(
8311
+ (field) => field && typeof field === "object" && !Array.isArray(field) ? field : {}
8312
+ ) : [];
8313
+ var toOptionsText = (value) => Array.isArray(value) ? value.map((entry) => {
8314
+ if (entry && typeof entry === "object" && !Array.isArray(entry)) {
8315
+ const record = entry;
8316
+ const label = typeof record.label === "string" ? record.label : "";
8317
+ const optionValue = typeof record.value === "string" ? record.value : label;
8318
+ return label && optionValue && label !== optionValue ? `${label} | ${optionValue}` : label || optionValue;
8319
+ }
8320
+ return typeof entry === "string" ? entry : "";
8321
+ }).filter(Boolean).join("\n") : "";
8322
+ var fromOptionsText = (value) => value.split("\n").map((entry) => entry.trim()).filter(Boolean).map((entry) => {
8323
+ const [label, optionValue] = entry.split("|").map((part) => part.trim());
8324
+ return {
8325
+ label,
8326
+ value: optionValue || label
8327
+ };
8328
+ });
8329
+ var slugifyFieldName = (value) => value.trim().replace(/[^a-z0-9]+/gi, " ").trim().replace(/\s+([a-z0-9])/gi, (_, char) => char.toUpperCase()).replace(/^./, (char) => char.toLowerCase());
8330
+ var blankField = () => ({
8331
+ label: "New field",
8332
+ name: "newField",
8333
+ required: false,
8334
+ type: "text"
8335
+ });
8336
+ var blankStep = () => ({
8337
+ fields: [blankField()],
8338
+ title: "New step"
8339
+ });
8340
+ var getStepTitle = (step, stepIndex) => getNonEmptyText(step.title, `Step ${stepIndex + 1}`);
8341
+ var getFieldLabel = (field, fieldIndex) => getNonEmptyText(field.label, getNonEmptyText(field.name, `Field ${fieldIndex + 1}`));
8342
+ var formatFieldTypeLabel = (value) => getNonEmptyText(value, "text").replace(/-/g, " ").replace(/^./, (char) => char.toUpperCase());
8343
+ var getStepDestination = (stepIndex, stepCount) => {
8344
+ if (stepIndex < stepCount - 1) {
8345
+ return `Next: Step ${stepIndex + 2}`;
8346
+ }
8347
+ return "Then: Submit form";
8348
+ };
8349
+ var moveItem = (items, fromIndex, toIndex) => {
8350
+ if (toIndex < 0 || toIndex >= items.length) {
8351
+ return items;
8352
+ }
8353
+ const nextItems = [...items];
8354
+ const [item] = nextItems.splice(fromIndex, 1);
8355
+ nextItems.splice(toIndex, 0, item);
8356
+ return nextItems;
8357
+ };
8315
8358
  function getFormIDFromPathname(pathname) {
8316
8359
  const marker = "/forms/";
8317
8360
  const raw = getIDFromPathname(pathname, marker);
@@ -8404,10 +8447,6 @@ function AdminStudioFormDetailView(props) {
8404
8447
  setError(null);
8405
8448
  setSavedMessage(null);
8406
8449
  try {
8407
- const parsedSteps = JSON.parse(editorState.stepsText);
8408
- if (!Array.isArray(parsedSteps)) {
8409
- throw new Error("Structure JSON must be an array of steps.");
8410
- }
8411
8450
  const payload = {
8412
8451
  emails: {
8413
8452
  adminRecipients: editorState.adminRecipientsText.split("\n").map((value) => value.trim()).filter(Boolean).map((email) => ({ email })),
@@ -8419,7 +8458,7 @@ function AdminStudioFormDetailView(props) {
8419
8458
  sendConfirmation: editorState.sendConfirmation
8420
8459
  },
8421
8460
  slug: editorState.slug.trim(),
8422
- steps: parsedSteps,
8461
+ steps: editorState.steps,
8423
8462
  submitLabel: editorState.submitLabel.trim(),
8424
8463
  successMessage: editorState.successMessage,
8425
8464
  title: editorState.title.trim()
@@ -8465,8 +8504,52 @@ function AdminStudioFormDetailView(props) {
8465
8504
  const toneStyle = getFormToneStyle2(slug, title || formID || "form");
8466
8505
  const fieldLabels = doc ? buildFieldLabelMap2(doc) : /* @__PURE__ */ new Map();
8467
8506
  const latestSubmission = submissions[0];
8468
- const stepCount = doc && Array.isArray(doc.steps) ? doc.steps.length : 0;
8469
- const fieldCount = doc ? getFieldCount2(doc) : 0;
8507
+ const stepCount = editorState?.steps.length || 0;
8508
+ const fieldCount = editorState ? editorState.steps.reduce((count, step) => count + getFields(step).length, 0) : doc ? getFieldCount2(doc) : 0;
8509
+ const updateStep = (stepIndex, patch) => {
8510
+ setEditorState(
8511
+ (current) => current ? {
8512
+ ...current,
8513
+ steps: current.steps.map(
8514
+ (step, index) => index === stepIndex ? { ...step, ...patch } : step
8515
+ )
8516
+ } : current
8517
+ );
8518
+ };
8519
+ const updateField = (stepIndex, fieldIndex, patch) => {
8520
+ setEditorState((current) => {
8521
+ if (!current) return current;
8522
+ return {
8523
+ ...current,
8524
+ steps: current.steps.map((step, index) => {
8525
+ if (index !== stepIndex) return step;
8526
+ const fields = getFields(step).map(
8527
+ (field, currentFieldIndex) => currentFieldIndex === fieldIndex ? { ...field, ...patch } : field
8528
+ );
8529
+ return { ...step, fields };
8530
+ })
8531
+ };
8532
+ });
8533
+ };
8534
+ const moveStep = (stepIndex, direction) => {
8535
+ setEditorState(
8536
+ (current) => current ? {
8537
+ ...current,
8538
+ steps: moveItem(current.steps, stepIndex, stepIndex + direction)
8539
+ } : current
8540
+ );
8541
+ };
8542
+ const moveField = (stepIndex, fieldIndex, direction) => {
8543
+ setEditorState((current) => {
8544
+ if (!current) return current;
8545
+ return {
8546
+ ...current,
8547
+ steps: current.steps.map(
8548
+ (step, index) => index === stepIndex ? { ...step, fields: moveItem(getFields(step), fieldIndex, fieldIndex + direction) } : step
8549
+ )
8550
+ };
8551
+ });
8552
+ };
8470
8553
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(
8471
8554
  AdminPage,
8472
8555
  {
@@ -8545,10 +8628,9 @@ function AdminStudioFormDetailView(props) {
8545
8628
  /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { style: { display: "grid", gap: "1rem" }, children: [
8546
8629
  /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-card", children: [
8547
8630
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Step preview" }),
8548
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Review the configured workflow structure before editing the JSON source." }),
8549
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: Array.isArray(doc.steps) && doc.steps.length > 0 ? doc.steps.map((step, stepIndex) => {
8550
- const record = step && typeof step === "object" && !Array.isArray(step) ? step : null;
8551
- const fields = Array.isArray(record?.fields) ? record.fields : [];
8631
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Review the public workflow as visitors will move through it." }),
8632
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: editorState.steps.length > 0 ? editorState.steps.map((record, stepIndex) => {
8633
+ const fields = getFields(record);
8552
8634
  return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-form", children: [
8553
8635
  /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { children: [
8554
8636
  /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("strong", { children: [
@@ -8600,7 +8682,7 @@ function AdminStudioFormDetailView(props) {
8600
8682
  ] }, `step-${stepIndex}`);
8601
8683
  }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-empty-state", children: [
8602
8684
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "No steps configured" }),
8603
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Add at least one step in the JSON editor to publish this form." })
8685
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Add at least one step in Form settings to publish this form." })
8604
8686
  ] }) })
8605
8687
  ] }),
8606
8688
  /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-card", children: [
@@ -8782,32 +8864,315 @@ function AdminStudioFormDetailView(props) {
8782
8864
  ] })
8783
8865
  ] })
8784
8866
  ] }),
8785
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
8786
- "Structure JSON",
8787
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8788
- "textarea",
8789
- {
8790
- onChange: (event) => setEditorState(
8791
- (current) => current ? { ...current, stepsText: event.target.value } : current
8792
- ),
8793
- rows: 18,
8794
- spellCheck: false,
8795
- style: {
8796
- fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
8797
- minHeight: "24rem"
8798
- },
8799
- value: editorState.stepsText
8800
- }
8801
- )
8867
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-card orion-admin-workflow-editor", children: [
8868
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-workflow-editor-header", children: [
8869
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { children: [
8870
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Form steps" }),
8871
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Build the visitor flow, then edit each step's fields below." })
8872
+ ] }),
8873
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8874
+ "button",
8875
+ {
8876
+ className: "orion-admin-action-button orion-admin-action-button--ghost",
8877
+ onClick: () => setEditorState(
8878
+ (current) => current ? { ...current, steps: [...current.steps, blankStep()] } : current
8879
+ ),
8880
+ type: "button",
8881
+ children: "Add step"
8882
+ }
8883
+ )
8884
+ ] }),
8885
+ editorState.steps.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-workflow-map", "aria-label": "Form step flow", children: editorState.steps.map((step, stepIndex) => {
8886
+ const fields = getFields(step);
8887
+ const requiredCount = fields.filter((field) => field.required === true).length;
8888
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-workflow-node", children: [
8889
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-workflow-node-number", children: stepIndex + 1 }),
8890
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-workflow-node-body", children: [
8891
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: getStepTitle(step, stepIndex) }),
8892
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { children: [
8893
+ fields.length,
8894
+ " field",
8895
+ fields.length === 1 ? "" : "s",
8896
+ requiredCount > 0 ? ` \xB7 ${requiredCount} required` : ""
8897
+ ] })
8898
+ ] }),
8899
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-workflow-node-destination", children: getStepDestination(stepIndex, editorState.steps.length) })
8900
+ ] }, `flow-step-${stepIndex}`);
8901
+ }) }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-empty-state", children: [
8902
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "No steps configured" }),
8903
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Add a first step to start building the public form flow." })
8904
+ ] }),
8905
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-step-editor-list", children: editorState.steps.map((step, stepIndex) => {
8906
+ const fields = getFields(step);
8907
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("details", { className: "orion-admin-step-editor", open: true, children: [
8908
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("summary", { className: "orion-admin-step-editor-summary", children: [
8909
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "orion-admin-step-editor-index", children: [
8910
+ "Step ",
8911
+ stepIndex + 1
8912
+ ] }),
8913
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-step-editor-title", children: getStepTitle(step, stepIndex) }),
8914
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "orion-admin-step-editor-meta", children: [
8915
+ fields.length,
8916
+ " field",
8917
+ fields.length === 1 ? "" : "s",
8918
+ " \xB7",
8919
+ " ",
8920
+ getStepDestination(stepIndex, editorState.steps.length)
8921
+ ] })
8922
+ ] }),
8923
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-step-editor-body", children: [
8924
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-step-editor-actions", children: [
8925
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8926
+ "button",
8927
+ {
8928
+ className: "orion-admin-action-button orion-admin-action-button--ghost",
8929
+ disabled: stepIndex === 0,
8930
+ onClick: () => moveStep(stepIndex, -1),
8931
+ type: "button",
8932
+ children: "Move up"
8933
+ }
8934
+ ),
8935
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8936
+ "button",
8937
+ {
8938
+ className: "orion-admin-action-button orion-admin-action-button--ghost",
8939
+ disabled: stepIndex === editorState.steps.length - 1,
8940
+ onClick: () => moveStep(stepIndex, 1),
8941
+ type: "button",
8942
+ children: "Move down"
8943
+ }
8944
+ ),
8945
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8946
+ "button",
8947
+ {
8948
+ className: "orion-admin-action-button orion-admin-action-button--ghost",
8949
+ onClick: () => setEditorState(
8950
+ (current) => current ? {
8951
+ ...current,
8952
+ steps: current.steps.filter((_, index) => index !== stepIndex)
8953
+ } : current
8954
+ ),
8955
+ type: "button",
8956
+ children: "Remove step"
8957
+ }
8958
+ )
8959
+ ] }),
8960
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-step-settings-grid", children: [
8961
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
8962
+ "Step title",
8963
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8964
+ "input",
8965
+ {
8966
+ onChange: (event) => updateStep(stepIndex, { title: event.target.value }),
8967
+ type: "text",
8968
+ value: getNonEmptyText(step.title)
8969
+ }
8970
+ )
8971
+ ] }),
8972
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
8973
+ "Next button label",
8974
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8975
+ "input",
8976
+ {
8977
+ onChange: (event) => updateStep(stepIndex, { nextLabel: event.target.value }),
8978
+ placeholder: "Next",
8979
+ type: "text",
8980
+ value: getNonEmptyText(step.nextLabel)
8981
+ }
8982
+ )
8983
+ ] })
8984
+ ] }),
8985
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
8986
+ "Step intro text",
8987
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8988
+ "textarea",
8989
+ {
8990
+ onChange: (event) => updateStep(stepIndex, { subtitle: event.target.value }),
8991
+ rows: 3,
8992
+ value: getNonEmptyText(step.subtitle)
8993
+ }
8994
+ )
8995
+ ] }),
8996
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { style: checkboxLabelStyle, children: [
8997
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
8998
+ "input",
8999
+ {
9000
+ checked: step.allowSkip === true,
9001
+ onChange: (event) => updateStep(stepIndex, { allowSkip: event.target.checked }),
9002
+ type: "checkbox"
9003
+ }
9004
+ ),
9005
+ "Allow visitors to skip this step"
9006
+ ] }),
9007
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-field-list-header", children: [
9008
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { children: [
9009
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Fields in this step" }),
9010
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "These appear together before the visitor moves to the next step." })
9011
+ ] }),
9012
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9013
+ "button",
9014
+ {
9015
+ className: "orion-admin-action-button orion-admin-action-button--ghost",
9016
+ onClick: () => setEditorState(
9017
+ (current) => current ? {
9018
+ ...current,
9019
+ steps: current.steps.map(
9020
+ (currentStep, index) => index === stepIndex ? { ...currentStep, fields: [...getFields(currentStep), blankField()] } : currentStep
9021
+ )
9022
+ } : current
9023
+ ),
9024
+ type: "button",
9025
+ children: "Add field"
9026
+ }
9027
+ )
9028
+ ] }),
9029
+ fields.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-field-editor-list", children: fields.map((field, fieldIndex) => {
9030
+ const label = getFieldLabel(field, fieldIndex);
9031
+ const fieldType = getNonEmptyText(field.type, "text");
9032
+ return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("details", { className: "orion-admin-field-editor", children: [
9033
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("summary", { className: "orion-admin-field-editor-summary", children: [
9034
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-field-order", children: fieldIndex + 1 }),
9035
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "orion-admin-field-editor-title", children: label }),
9036
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "orion-admin-field-editor-meta", children: [
9037
+ formatFieldTypeLabel(fieldType),
9038
+ field.required === true ? " \xB7 Required" : ""
9039
+ ] })
9040
+ ] }),
9041
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-field-editor-body", children: [
9042
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-step-editor-actions", children: [
9043
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9044
+ "button",
9045
+ {
9046
+ className: "orion-admin-action-button orion-admin-action-button--ghost",
9047
+ disabled: fieldIndex === 0,
9048
+ onClick: () => moveField(stepIndex, fieldIndex, -1),
9049
+ type: "button",
9050
+ children: "Move up"
9051
+ }
9052
+ ),
9053
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9054
+ "button",
9055
+ {
9056
+ className: "orion-admin-action-button orion-admin-action-button--ghost",
9057
+ disabled: fieldIndex === fields.length - 1,
9058
+ onClick: () => moveField(stepIndex, fieldIndex, 1),
9059
+ type: "button",
9060
+ children: "Move down"
9061
+ }
9062
+ ),
9063
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9064
+ "button",
9065
+ {
9066
+ className: "orion-admin-action-button orion-admin-action-button--ghost",
9067
+ onClick: () => setEditorState((current) => {
9068
+ if (!current) return current;
9069
+ return {
9070
+ ...current,
9071
+ steps: current.steps.map(
9072
+ (currentStep, index) => index === stepIndex ? {
9073
+ ...currentStep,
9074
+ fields: getFields(currentStep).filter(
9075
+ (_, currentFieldIndex) => currentFieldIndex !== fieldIndex
9076
+ )
9077
+ } : currentStep
9078
+ )
9079
+ };
9080
+ }),
9081
+ type: "button",
9082
+ children: "Remove field"
9083
+ }
9084
+ )
9085
+ ] }),
9086
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-step-settings-grid", children: [
9087
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
9088
+ "Field label",
9089
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9090
+ "input",
9091
+ {
9092
+ onChange: (event) => {
9093
+ const nextLabel = event.target.value;
9094
+ const currentName = getNonEmptyText(field.name);
9095
+ updateField(stepIndex, fieldIndex, {
9096
+ label: nextLabel,
9097
+ name: currentName || slugifyFieldName(nextLabel)
9098
+ });
9099
+ },
9100
+ type: "text",
9101
+ value: label
9102
+ }
9103
+ )
9104
+ ] }),
9105
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
9106
+ "Field type",
9107
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9108
+ "select",
9109
+ {
9110
+ onChange: (event) => updateField(stepIndex, fieldIndex, { type: event.target.value }),
9111
+ value: fieldType,
9112
+ children: fieldTypeOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("option", { value: option, children: formatFieldTypeLabel(option) }, option))
9113
+ }
9114
+ )
9115
+ ] })
9116
+ ] }),
9117
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
9118
+ "Field key",
9119
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9120
+ "input",
9121
+ {
9122
+ onChange: (event) => updateField(stepIndex, fieldIndex, { name: event.target.value }),
9123
+ type: "text",
9124
+ value: getNonEmptyText(field.name)
9125
+ }
9126
+ )
9127
+ ] }),
9128
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { style: checkboxLabelStyle, children: [
9129
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9130
+ "input",
9131
+ {
9132
+ checked: field.required === true,
9133
+ onChange: (event) => updateField(stepIndex, fieldIndex, { required: event.target.checked }),
9134
+ type: "checkbox"
9135
+ }
9136
+ ),
9137
+ "Required"
9138
+ ] }),
9139
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
9140
+ "Help text",
9141
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9142
+ "textarea",
9143
+ {
9144
+ onChange: (event) => updateField(stepIndex, fieldIndex, { helpText: event.target.value }),
9145
+ rows: 2,
9146
+ value: getNonEmptyText(field.helpText)
9147
+ }
9148
+ )
9149
+ ] }),
9150
+ ["select", "radio", "checkbox-group"].includes(fieldType) ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("label", { children: [
9151
+ "Options",
9152
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
9153
+ "textarea",
9154
+ {
9155
+ onChange: (event) => updateField(stepIndex, fieldIndex, {
9156
+ options: fromOptionsText(event.target.value)
9157
+ }),
9158
+ placeholder: "Option one\nOption two",
9159
+ rows: 4,
9160
+ value: toOptionsText(field.options)
9161
+ }
9162
+ )
9163
+ ] }) : null
9164
+ ] })
9165
+ ] }, `edit-field-${stepIndex}-${fieldIndex}`);
9166
+ }) }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-empty-state", children: [
9167
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "No fields in this step" }),
9168
+ /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Add a field so visitors have something to answer here." })
9169
+ ] })
9170
+ ] })
9171
+ ] }, `edit-step-${stepIndex}`);
9172
+ }) })
8802
9173
  ] }),
8803
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "orion-admin-list-meta", children: "Edit the public workflow as JSON. The saved payload must remain an array of step objects compatible with the form collection schema." }),
8804
9174
  /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { disabled: saving, type: "submit", children: saving ? "Saving..." : "Save Form" })
8805
9175
  ] })
8806
- ] }),
8807
- /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "orion-admin-card", children: [
8808
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("strong", { children: "Current structure payload" }),
8809
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { children: "Reference snapshot of the form steps that will be written back on save." }),
8810
- /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("pre", { style: { ...codeStyle, marginTop: "1rem" }, children: editorState.stepsText })
8811
9176
  ] })
8812
9177
  ] }) : null
8813
9178
  ]
@@ -8819,25 +9184,17 @@ function AdminStudioFormDetailView(props) {
8819
9184
  var import_link5 = __toESM(require("next/link"));
8820
9185
  var import_react33 = require("react");
8821
9186
  var import_jsx_runtime42 = require("react/jsx-runtime");
8822
- var codeStyle2 = {
8823
- background: "color-mix(in srgb, var(--orion-admin-card-bg) 82%, black)",
8824
- border: "1px solid var(--orion-admin-card-border)",
8825
- borderRadius: "var(--orion-admin-radius-sm)",
8826
- color: "var(--orion-admin-text)",
8827
- fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
8828
- fontSize: "0.86rem",
8829
- lineHeight: 1.55,
8830
- margin: 0,
8831
- maxHeight: "28rem",
8832
- overflow: "auto",
8833
- padding: "0.9rem",
8834
- whiteSpace: "pre-wrap"
8835
- };
8836
9187
  var sectionGridStyle2 = {
8837
9188
  display: "grid",
8838
9189
  gap: "1rem",
8839
9190
  gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))"
8840
9191
  };
9192
+ var nestedListStyle = {
9193
+ display: "grid",
9194
+ gap: "0.45rem",
9195
+ margin: 0,
9196
+ padding: 0
9197
+ };
8841
9198
  var renderFieldValue = (value) => {
8842
9199
  if (value === null || value === void 0) {
8843
9200
  return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-list-meta", children: "No value" });
@@ -8851,7 +9208,26 @@ var renderFieldValue = (value) => {
8851
9208
  if (typeof value === "string") {
8852
9209
  return value.trim().length > 0 ? value : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-list-meta", children: "No value" });
8853
9210
  }
8854
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("pre", { style: codeStyle2, children: JSON.stringify(value, null, 2) });
9211
+ if (Array.isArray(value)) {
9212
+ const entries = value.filter((entry) => entry !== null && entry !== void 0 && entry !== "");
9213
+ if (entries.length === 0) {
9214
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-list-meta", children: "No value" });
9215
+ }
9216
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ul", { style: nestedListStyle, children: entries.map((entry, index) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("li", { children: renderFieldValue(entry) }, index)) });
9217
+ }
9218
+ if (typeof value === "object") {
9219
+ const entries = Object.entries(value).filter(
9220
+ ([, entryValue]) => entryValue !== null && entryValue !== void 0 && entryValue !== ""
9221
+ );
9222
+ if (entries.length === 0) {
9223
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-list-meta", children: "No value" });
9224
+ }
9225
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { style: { display: "grid", gap: "0.65rem" }, children: entries.map(([key, entryValue]) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-meta-row", children: [
9226
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-label", children: humanizeKey2(key) }),
9227
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-meta-value", children: renderFieldValue(entryValue) })
9228
+ ] }, key)) });
9229
+ }
9230
+ return String(value);
8855
9231
  };
8856
9232
  function getSubmissionIDFromPathname(pathname) {
8857
9233
  return getIDFromPathname(pathname, "/forms/submissions/");
@@ -9003,31 +9379,24 @@ function AdminStudioFormSubmissionView(props) {
9003
9379
  /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("article", { className: "orion-admin-overview-stat", children: [
9004
9380
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "orion-admin-overview-stat-label", children: "Highlighted answers" }),
9005
9381
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: previewFields.length }),
9006
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { children: "Readable answer previews surfaced from the structured payload." })
9382
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { children: "Readable answer previews from this response." })
9007
9383
  ] })
9008
9384
  ] }),
9009
9385
  /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { style: sectionGridStyle2, children: [
9010
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { style: { display: "grid", gap: "1rem" }, children: [
9011
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-card", children: [
9012
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: "Response details" }),
9013
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { children: "Formatted answers using the current form field labels when available." }),
9014
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: answerEntries.length > 0 ? answerEntries.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-form", children: [
9015
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { children: [
9016
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: fieldLabels.get(key) || humanizeKey2(key) }),
9017
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "orion-admin-list-meta", children: key })
9018
- ] }),
9019
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { children: renderFieldValue(value) })
9020
- ] }, key)) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-empty-state", children: [
9021
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: "No response payload" }),
9022
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { children: "This submission does not contain a structured data object." })
9023
- ] }) })
9024
- ] }),
9025
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-card", children: [
9026
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: "Raw payload" }),
9027
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { children: "Verbatim submission data for troubleshooting or export checks." }),
9028
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("pre", { style: { ...codeStyle2, marginTop: "1rem" }, children: JSON.stringify(doc.data ?? {}, null, 2) })
9029
- ] })
9030
- ] }),
9386
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { style: { display: "grid", gap: "1rem" }, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-card", children: [
9387
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: "Response details" }),
9388
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { children: "Formatted answers using the current form field labels when available." }),
9389
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: answerEntries.length > 0 ? answerEntries.map(([key, value]) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-form", children: [
9390
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { children: [
9391
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: fieldLabels.get(key) || humanizeKey2(key) }),
9392
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "orion-admin-list-meta", children: key })
9393
+ ] }),
9394
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { children: renderFieldValue(value) })
9395
+ ] }, key)) : /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-empty-state", children: [
9396
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("strong", { children: "No answers available" }),
9397
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { children: "This submission does not contain visible response details." })
9398
+ ] }) })
9399
+ ] }) }),
9031
9400
  /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { style: { display: "grid", gap: "1rem" }, children: [
9032
9401
  /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-card orion-admin-meta-table", children: [
9033
9402
  /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "orion-admin-meta-row", children: [