@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.
@@ -5928,15 +5928,11 @@ var getFormTitle2 = (value) => {
5928
5928
  // src/admin/components/studio/AdminStudioFormDetailView.tsx
5929
5929
  import { Fragment as Fragment5, jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
5930
5930
  var getNonEmptyText = (value, fallback = "") => typeof value === "string" && value.trim().length > 0 ? value : fallback;
5931
- var formatStepsText = (value) => {
5931
+ var normalizeSteps = (value) => {
5932
5932
  if (!Array.isArray(value)) {
5933
- return "[]";
5934
- }
5935
- try {
5936
- return JSON.stringify(value, null, 2);
5937
- } catch {
5938
- return "[]";
5933
+ return [];
5939
5934
  }
5935
+ return value.map((step) => step && typeof step === "object" && !Array.isArray(step) ? step : {});
5940
5936
  };
5941
5937
  var toEditorState = (doc) => {
5942
5938
  const emails = doc.emails && typeof doc.emails === "object" ? doc.emails : null;
@@ -5952,7 +5948,7 @@ var toEditorState = (doc) => {
5952
5948
  sendAdmin: emails?.sendAdmin !== false,
5953
5949
  sendConfirmation: emails?.sendConfirmation !== false,
5954
5950
  slug: getNonEmptyText(doc.slug),
5955
- stepsText: formatStepsText(doc.steps),
5951
+ steps: normalizeSteps(doc.steps),
5956
5952
  submitLabel: getNonEmptyText(doc.submitLabel, "Submit"),
5957
5953
  successMessage: getNonEmptyText(doc.successMessage),
5958
5954
  title: getNonEmptyText(doc.title, "Untitled Form")
@@ -5963,25 +5959,72 @@ var checkboxLabelStyle = {
5963
5959
  display: "flex",
5964
5960
  gap: "0.6rem"
5965
5961
  };
5966
- var codeStyle = {
5967
- background: "color-mix(in srgb, var(--orion-admin-card-bg) 82%, black)",
5968
- border: "1px solid var(--orion-admin-card-border)",
5969
- borderRadius: "var(--orion-admin-radius-sm)",
5970
- color: "var(--orion-admin-text)",
5971
- fontFamily: "ui-monospace, SFMono-Regular, SFMono-Regular, Menlo, monospace",
5972
- fontSize: "0.86rem",
5973
- lineHeight: 1.55,
5974
- margin: 0,
5975
- maxHeight: "28rem",
5976
- overflow: "auto",
5977
- padding: "0.9rem",
5978
- whiteSpace: "pre-wrap"
5979
- };
5980
5962
  var sectionGridStyle = {
5981
5963
  display: "grid",
5982
5964
  gap: "1rem",
5983
5965
  gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))"
5984
5966
  };
5967
+ var fieldTypeOptions = [
5968
+ "text",
5969
+ "textarea",
5970
+ "email",
5971
+ "phone",
5972
+ "url",
5973
+ "select",
5974
+ "radio",
5975
+ "checkbox",
5976
+ "checkbox-group",
5977
+ "date",
5978
+ "file"
5979
+ ];
5980
+ var getFields = (step) => Array.isArray(step.fields) ? step.fields.map(
5981
+ (field) => field && typeof field === "object" && !Array.isArray(field) ? field : {}
5982
+ ) : [];
5983
+ var toOptionsText = (value) => Array.isArray(value) ? value.map((entry) => {
5984
+ if (entry && typeof entry === "object" && !Array.isArray(entry)) {
5985
+ const record = entry;
5986
+ const label = typeof record.label === "string" ? record.label : "";
5987
+ const optionValue = typeof record.value === "string" ? record.value : label;
5988
+ return label && optionValue && label !== optionValue ? `${label} | ${optionValue}` : label || optionValue;
5989
+ }
5990
+ return typeof entry === "string" ? entry : "";
5991
+ }).filter(Boolean).join("\n") : "";
5992
+ var fromOptionsText = (value) => value.split("\n").map((entry) => entry.trim()).filter(Boolean).map((entry) => {
5993
+ const [label, optionValue] = entry.split("|").map((part) => part.trim());
5994
+ return {
5995
+ label,
5996
+ value: optionValue || label
5997
+ };
5998
+ });
5999
+ var slugifyFieldName = (value) => value.trim().replace(/[^a-z0-9]+/gi, " ").trim().replace(/\s+([a-z0-9])/gi, (_, char) => char.toUpperCase()).replace(/^./, (char) => char.toLowerCase());
6000
+ var blankField = () => ({
6001
+ label: "New field",
6002
+ name: "newField",
6003
+ required: false,
6004
+ type: "text"
6005
+ });
6006
+ var blankStep = () => ({
6007
+ fields: [blankField()],
6008
+ title: "New step"
6009
+ });
6010
+ var getStepTitle = (step, stepIndex) => getNonEmptyText(step.title, `Step ${stepIndex + 1}`);
6011
+ var getFieldLabel = (field, fieldIndex) => getNonEmptyText(field.label, getNonEmptyText(field.name, `Field ${fieldIndex + 1}`));
6012
+ var formatFieldTypeLabel = (value) => getNonEmptyText(value, "text").replace(/-/g, " ").replace(/^./, (char) => char.toUpperCase());
6013
+ var getStepDestination = (stepIndex, stepCount) => {
6014
+ if (stepIndex < stepCount - 1) {
6015
+ return `Next: Step ${stepIndex + 2}`;
6016
+ }
6017
+ return "Then: Submit form";
6018
+ };
6019
+ var moveItem = (items, fromIndex, toIndex) => {
6020
+ if (toIndex < 0 || toIndex >= items.length) {
6021
+ return items;
6022
+ }
6023
+ const nextItems = [...items];
6024
+ const [item] = nextItems.splice(fromIndex, 1);
6025
+ nextItems.splice(toIndex, 0, item);
6026
+ return nextItems;
6027
+ };
5985
6028
  function getFormIDFromPathname(pathname) {
5986
6029
  const marker = "/forms/";
5987
6030
  const raw = getIDFromPathname(pathname, marker);
@@ -6074,10 +6117,6 @@ function AdminStudioFormDetailView(props) {
6074
6117
  setError(null);
6075
6118
  setSavedMessage(null);
6076
6119
  try {
6077
- const parsedSteps = JSON.parse(editorState.stepsText);
6078
- if (!Array.isArray(parsedSteps)) {
6079
- throw new Error("Structure JSON must be an array of steps.");
6080
- }
6081
6120
  const payload = {
6082
6121
  emails: {
6083
6122
  adminRecipients: editorState.adminRecipientsText.split("\n").map((value) => value.trim()).filter(Boolean).map((email) => ({ email })),
@@ -6089,7 +6128,7 @@ function AdminStudioFormDetailView(props) {
6089
6128
  sendConfirmation: editorState.sendConfirmation
6090
6129
  },
6091
6130
  slug: editorState.slug.trim(),
6092
- steps: parsedSteps,
6131
+ steps: editorState.steps,
6093
6132
  submitLabel: editorState.submitLabel.trim(),
6094
6133
  successMessage: editorState.successMessage,
6095
6134
  title: editorState.title.trim()
@@ -6135,8 +6174,52 @@ function AdminStudioFormDetailView(props) {
6135
6174
  const toneStyle = getFormToneStyle2(slug, title || formID || "form");
6136
6175
  const fieldLabels = doc ? buildFieldLabelMap2(doc) : /* @__PURE__ */ new Map();
6137
6176
  const latestSubmission = submissions[0];
6138
- const stepCount = doc && Array.isArray(doc.steps) ? doc.steps.length : 0;
6139
- const fieldCount = doc ? getFieldCount2(doc) : 0;
6177
+ const stepCount = editorState?.steps.length || 0;
6178
+ const fieldCount = editorState ? editorState.steps.reduce((count, step) => count + getFields(step).length, 0) : doc ? getFieldCount2(doc) : 0;
6179
+ const updateStep = (stepIndex, patch) => {
6180
+ setEditorState(
6181
+ (current) => current ? {
6182
+ ...current,
6183
+ steps: current.steps.map(
6184
+ (step, index) => index === stepIndex ? { ...step, ...patch } : step
6185
+ )
6186
+ } : current
6187
+ );
6188
+ };
6189
+ const updateField = (stepIndex, fieldIndex, patch) => {
6190
+ setEditorState((current) => {
6191
+ if (!current) return current;
6192
+ return {
6193
+ ...current,
6194
+ steps: current.steps.map((step, index) => {
6195
+ if (index !== stepIndex) return step;
6196
+ const fields = getFields(step).map(
6197
+ (field, currentFieldIndex) => currentFieldIndex === fieldIndex ? { ...field, ...patch } : field
6198
+ );
6199
+ return { ...step, fields };
6200
+ })
6201
+ };
6202
+ });
6203
+ };
6204
+ const moveStep = (stepIndex, direction) => {
6205
+ setEditorState(
6206
+ (current) => current ? {
6207
+ ...current,
6208
+ steps: moveItem(current.steps, stepIndex, stepIndex + direction)
6209
+ } : current
6210
+ );
6211
+ };
6212
+ const moveField = (stepIndex, fieldIndex, direction) => {
6213
+ setEditorState((current) => {
6214
+ if (!current) return current;
6215
+ return {
6216
+ ...current,
6217
+ steps: current.steps.map(
6218
+ (step, index) => index === stepIndex ? { ...step, fields: moveItem(getFields(step), fieldIndex, fieldIndex + direction) } : step
6219
+ )
6220
+ };
6221
+ });
6222
+ };
6140
6223
  return /* @__PURE__ */ jsx30(StudioSectionLayout, { navProps: props, children: /* @__PURE__ */ jsxs27(
6141
6224
  AdminPage,
6142
6225
  {
@@ -6215,10 +6298,9 @@ function AdminStudioFormDetailView(props) {
6215
6298
  /* @__PURE__ */ jsxs27("div", { style: { display: "grid", gap: "1rem" }, children: [
6216
6299
  /* @__PURE__ */ jsxs27("div", { className: "orion-admin-card", children: [
6217
6300
  /* @__PURE__ */ jsx30("strong", { children: "Step preview" }),
6218
- /* @__PURE__ */ jsx30("span", { children: "Review the configured workflow structure before editing the JSON source." }),
6219
- /* @__PURE__ */ jsx30("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: Array.isArray(doc.steps) && doc.steps.length > 0 ? doc.steps.map((step, stepIndex) => {
6220
- const record = step && typeof step === "object" && !Array.isArray(step) ? step : null;
6221
- const fields = Array.isArray(record?.fields) ? record.fields : [];
6301
+ /* @__PURE__ */ jsx30("span", { children: "Review the public workflow as visitors will move through it." }),
6302
+ /* @__PURE__ */ jsx30("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: editorState.steps.length > 0 ? editorState.steps.map((record, stepIndex) => {
6303
+ const fields = getFields(record);
6222
6304
  return /* @__PURE__ */ jsxs27("div", { className: "orion-admin-form", children: [
6223
6305
  /* @__PURE__ */ jsxs27("div", { children: [
6224
6306
  /* @__PURE__ */ jsxs27("strong", { children: [
@@ -6270,7 +6352,7 @@ function AdminStudioFormDetailView(props) {
6270
6352
  ] }, `step-${stepIndex}`);
6271
6353
  }) : /* @__PURE__ */ jsxs27("div", { className: "orion-admin-empty-state", children: [
6272
6354
  /* @__PURE__ */ jsx30("strong", { children: "No steps configured" }),
6273
- /* @__PURE__ */ jsx30("span", { children: "Add at least one step in the JSON editor to publish this form." })
6355
+ /* @__PURE__ */ jsx30("span", { children: "Add at least one step in Form settings to publish this form." })
6274
6356
  ] }) })
6275
6357
  ] }),
6276
6358
  /* @__PURE__ */ jsxs27("div", { className: "orion-admin-card", children: [
@@ -6452,32 +6534,315 @@ function AdminStudioFormDetailView(props) {
6452
6534
  ] })
6453
6535
  ] })
6454
6536
  ] }),
6455
- /* @__PURE__ */ jsxs27("label", { children: [
6456
- "Structure JSON",
6457
- /* @__PURE__ */ jsx30(
6458
- "textarea",
6459
- {
6460
- onChange: (event) => setEditorState(
6461
- (current) => current ? { ...current, stepsText: event.target.value } : current
6462
- ),
6463
- rows: 18,
6464
- spellCheck: false,
6465
- style: {
6466
- fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
6467
- minHeight: "24rem"
6468
- },
6469
- value: editorState.stepsText
6470
- }
6471
- )
6537
+ /* @__PURE__ */ jsxs27("div", { className: "orion-admin-card orion-admin-workflow-editor", children: [
6538
+ /* @__PURE__ */ jsxs27("div", { className: "orion-admin-workflow-editor-header", children: [
6539
+ /* @__PURE__ */ jsxs27("div", { children: [
6540
+ /* @__PURE__ */ jsx30("strong", { children: "Form steps" }),
6541
+ /* @__PURE__ */ jsx30("span", { children: "Build the visitor flow, then edit each step's fields below." })
6542
+ ] }),
6543
+ /* @__PURE__ */ jsx30(
6544
+ "button",
6545
+ {
6546
+ className: "orion-admin-action-button orion-admin-action-button--ghost",
6547
+ onClick: () => setEditorState(
6548
+ (current) => current ? { ...current, steps: [...current.steps, blankStep()] } : current
6549
+ ),
6550
+ type: "button",
6551
+ children: "Add step"
6552
+ }
6553
+ )
6554
+ ] }),
6555
+ editorState.steps.length > 0 ? /* @__PURE__ */ jsx30("div", { className: "orion-admin-workflow-map", "aria-label": "Form step flow", children: editorState.steps.map((step, stepIndex) => {
6556
+ const fields = getFields(step);
6557
+ const requiredCount = fields.filter((field) => field.required === true).length;
6558
+ return /* @__PURE__ */ jsxs27("div", { className: "orion-admin-workflow-node", children: [
6559
+ /* @__PURE__ */ jsx30("div", { className: "orion-admin-workflow-node-number", children: stepIndex + 1 }),
6560
+ /* @__PURE__ */ jsxs27("div", { className: "orion-admin-workflow-node-body", children: [
6561
+ /* @__PURE__ */ jsx30("strong", { children: getStepTitle(step, stepIndex) }),
6562
+ /* @__PURE__ */ jsxs27("span", { children: [
6563
+ fields.length,
6564
+ " field",
6565
+ fields.length === 1 ? "" : "s",
6566
+ requiredCount > 0 ? ` \xB7 ${requiredCount} required` : ""
6567
+ ] })
6568
+ ] }),
6569
+ /* @__PURE__ */ jsx30("div", { className: "orion-admin-workflow-node-destination", children: getStepDestination(stepIndex, editorState.steps.length) })
6570
+ ] }, `flow-step-${stepIndex}`);
6571
+ }) }) : /* @__PURE__ */ jsxs27("div", { className: "orion-admin-empty-state", children: [
6572
+ /* @__PURE__ */ jsx30("strong", { children: "No steps configured" }),
6573
+ /* @__PURE__ */ jsx30("span", { children: "Add a first step to start building the public form flow." })
6574
+ ] }),
6575
+ /* @__PURE__ */ jsx30("div", { className: "orion-admin-step-editor-list", children: editorState.steps.map((step, stepIndex) => {
6576
+ const fields = getFields(step);
6577
+ return /* @__PURE__ */ jsxs27("details", { className: "orion-admin-step-editor", open: true, children: [
6578
+ /* @__PURE__ */ jsxs27("summary", { className: "orion-admin-step-editor-summary", children: [
6579
+ /* @__PURE__ */ jsxs27("span", { className: "orion-admin-step-editor-index", children: [
6580
+ "Step ",
6581
+ stepIndex + 1
6582
+ ] }),
6583
+ /* @__PURE__ */ jsx30("span", { className: "orion-admin-step-editor-title", children: getStepTitle(step, stepIndex) }),
6584
+ /* @__PURE__ */ jsxs27("span", { className: "orion-admin-step-editor-meta", children: [
6585
+ fields.length,
6586
+ " field",
6587
+ fields.length === 1 ? "" : "s",
6588
+ " \xB7",
6589
+ " ",
6590
+ getStepDestination(stepIndex, editorState.steps.length)
6591
+ ] })
6592
+ ] }),
6593
+ /* @__PURE__ */ jsxs27("div", { className: "orion-admin-step-editor-body", children: [
6594
+ /* @__PURE__ */ jsxs27("div", { className: "orion-admin-step-editor-actions", children: [
6595
+ /* @__PURE__ */ jsx30(
6596
+ "button",
6597
+ {
6598
+ className: "orion-admin-action-button orion-admin-action-button--ghost",
6599
+ disabled: stepIndex === 0,
6600
+ onClick: () => moveStep(stepIndex, -1),
6601
+ type: "button",
6602
+ children: "Move up"
6603
+ }
6604
+ ),
6605
+ /* @__PURE__ */ jsx30(
6606
+ "button",
6607
+ {
6608
+ className: "orion-admin-action-button orion-admin-action-button--ghost",
6609
+ disabled: stepIndex === editorState.steps.length - 1,
6610
+ onClick: () => moveStep(stepIndex, 1),
6611
+ type: "button",
6612
+ children: "Move down"
6613
+ }
6614
+ ),
6615
+ /* @__PURE__ */ jsx30(
6616
+ "button",
6617
+ {
6618
+ className: "orion-admin-action-button orion-admin-action-button--ghost",
6619
+ onClick: () => setEditorState(
6620
+ (current) => current ? {
6621
+ ...current,
6622
+ steps: current.steps.filter((_, index) => index !== stepIndex)
6623
+ } : current
6624
+ ),
6625
+ type: "button",
6626
+ children: "Remove step"
6627
+ }
6628
+ )
6629
+ ] }),
6630
+ /* @__PURE__ */ jsxs27("div", { className: "orion-admin-step-settings-grid", children: [
6631
+ /* @__PURE__ */ jsxs27("label", { children: [
6632
+ "Step title",
6633
+ /* @__PURE__ */ jsx30(
6634
+ "input",
6635
+ {
6636
+ onChange: (event) => updateStep(stepIndex, { title: event.target.value }),
6637
+ type: "text",
6638
+ value: getNonEmptyText(step.title)
6639
+ }
6640
+ )
6641
+ ] }),
6642
+ /* @__PURE__ */ jsxs27("label", { children: [
6643
+ "Next button label",
6644
+ /* @__PURE__ */ jsx30(
6645
+ "input",
6646
+ {
6647
+ onChange: (event) => updateStep(stepIndex, { nextLabel: event.target.value }),
6648
+ placeholder: "Next",
6649
+ type: "text",
6650
+ value: getNonEmptyText(step.nextLabel)
6651
+ }
6652
+ )
6653
+ ] })
6654
+ ] }),
6655
+ /* @__PURE__ */ jsxs27("label", { children: [
6656
+ "Step intro text",
6657
+ /* @__PURE__ */ jsx30(
6658
+ "textarea",
6659
+ {
6660
+ onChange: (event) => updateStep(stepIndex, { subtitle: event.target.value }),
6661
+ rows: 3,
6662
+ value: getNonEmptyText(step.subtitle)
6663
+ }
6664
+ )
6665
+ ] }),
6666
+ /* @__PURE__ */ jsxs27("label", { style: checkboxLabelStyle, children: [
6667
+ /* @__PURE__ */ jsx30(
6668
+ "input",
6669
+ {
6670
+ checked: step.allowSkip === true,
6671
+ onChange: (event) => updateStep(stepIndex, { allowSkip: event.target.checked }),
6672
+ type: "checkbox"
6673
+ }
6674
+ ),
6675
+ "Allow visitors to skip this step"
6676
+ ] }),
6677
+ /* @__PURE__ */ jsxs27("div", { className: "orion-admin-field-list-header", children: [
6678
+ /* @__PURE__ */ jsxs27("div", { children: [
6679
+ /* @__PURE__ */ jsx30("strong", { children: "Fields in this step" }),
6680
+ /* @__PURE__ */ jsx30("span", { children: "These appear together before the visitor moves to the next step." })
6681
+ ] }),
6682
+ /* @__PURE__ */ jsx30(
6683
+ "button",
6684
+ {
6685
+ className: "orion-admin-action-button orion-admin-action-button--ghost",
6686
+ onClick: () => setEditorState(
6687
+ (current) => current ? {
6688
+ ...current,
6689
+ steps: current.steps.map(
6690
+ (currentStep, index) => index === stepIndex ? { ...currentStep, fields: [...getFields(currentStep), blankField()] } : currentStep
6691
+ )
6692
+ } : current
6693
+ ),
6694
+ type: "button",
6695
+ children: "Add field"
6696
+ }
6697
+ )
6698
+ ] }),
6699
+ fields.length > 0 ? /* @__PURE__ */ jsx30("div", { className: "orion-admin-field-editor-list", children: fields.map((field, fieldIndex) => {
6700
+ const label = getFieldLabel(field, fieldIndex);
6701
+ const fieldType = getNonEmptyText(field.type, "text");
6702
+ return /* @__PURE__ */ jsxs27("details", { className: "orion-admin-field-editor", children: [
6703
+ /* @__PURE__ */ jsxs27("summary", { className: "orion-admin-field-editor-summary", children: [
6704
+ /* @__PURE__ */ jsx30("span", { className: "orion-admin-field-order", children: fieldIndex + 1 }),
6705
+ /* @__PURE__ */ jsx30("span", { className: "orion-admin-field-editor-title", children: label }),
6706
+ /* @__PURE__ */ jsxs27("span", { className: "orion-admin-field-editor-meta", children: [
6707
+ formatFieldTypeLabel(fieldType),
6708
+ field.required === true ? " \xB7 Required" : ""
6709
+ ] })
6710
+ ] }),
6711
+ /* @__PURE__ */ jsxs27("div", { className: "orion-admin-field-editor-body", children: [
6712
+ /* @__PURE__ */ jsxs27("div", { className: "orion-admin-step-editor-actions", children: [
6713
+ /* @__PURE__ */ jsx30(
6714
+ "button",
6715
+ {
6716
+ className: "orion-admin-action-button orion-admin-action-button--ghost",
6717
+ disabled: fieldIndex === 0,
6718
+ onClick: () => moveField(stepIndex, fieldIndex, -1),
6719
+ type: "button",
6720
+ children: "Move up"
6721
+ }
6722
+ ),
6723
+ /* @__PURE__ */ jsx30(
6724
+ "button",
6725
+ {
6726
+ className: "orion-admin-action-button orion-admin-action-button--ghost",
6727
+ disabled: fieldIndex === fields.length - 1,
6728
+ onClick: () => moveField(stepIndex, fieldIndex, 1),
6729
+ type: "button",
6730
+ children: "Move down"
6731
+ }
6732
+ ),
6733
+ /* @__PURE__ */ jsx30(
6734
+ "button",
6735
+ {
6736
+ className: "orion-admin-action-button orion-admin-action-button--ghost",
6737
+ onClick: () => setEditorState((current) => {
6738
+ if (!current) return current;
6739
+ return {
6740
+ ...current,
6741
+ steps: current.steps.map(
6742
+ (currentStep, index) => index === stepIndex ? {
6743
+ ...currentStep,
6744
+ fields: getFields(currentStep).filter(
6745
+ (_, currentFieldIndex) => currentFieldIndex !== fieldIndex
6746
+ )
6747
+ } : currentStep
6748
+ )
6749
+ };
6750
+ }),
6751
+ type: "button",
6752
+ children: "Remove field"
6753
+ }
6754
+ )
6755
+ ] }),
6756
+ /* @__PURE__ */ jsxs27("div", { className: "orion-admin-step-settings-grid", children: [
6757
+ /* @__PURE__ */ jsxs27("label", { children: [
6758
+ "Field label",
6759
+ /* @__PURE__ */ jsx30(
6760
+ "input",
6761
+ {
6762
+ onChange: (event) => {
6763
+ const nextLabel = event.target.value;
6764
+ const currentName = getNonEmptyText(field.name);
6765
+ updateField(stepIndex, fieldIndex, {
6766
+ label: nextLabel,
6767
+ name: currentName || slugifyFieldName(nextLabel)
6768
+ });
6769
+ },
6770
+ type: "text",
6771
+ value: label
6772
+ }
6773
+ )
6774
+ ] }),
6775
+ /* @__PURE__ */ jsxs27("label", { children: [
6776
+ "Field type",
6777
+ /* @__PURE__ */ jsx30(
6778
+ "select",
6779
+ {
6780
+ onChange: (event) => updateField(stepIndex, fieldIndex, { type: event.target.value }),
6781
+ value: fieldType,
6782
+ children: fieldTypeOptions.map((option) => /* @__PURE__ */ jsx30("option", { value: option, children: formatFieldTypeLabel(option) }, option))
6783
+ }
6784
+ )
6785
+ ] })
6786
+ ] }),
6787
+ /* @__PURE__ */ jsxs27("label", { children: [
6788
+ "Field key",
6789
+ /* @__PURE__ */ jsx30(
6790
+ "input",
6791
+ {
6792
+ onChange: (event) => updateField(stepIndex, fieldIndex, { name: event.target.value }),
6793
+ type: "text",
6794
+ value: getNonEmptyText(field.name)
6795
+ }
6796
+ )
6797
+ ] }),
6798
+ /* @__PURE__ */ jsxs27("label", { style: checkboxLabelStyle, children: [
6799
+ /* @__PURE__ */ jsx30(
6800
+ "input",
6801
+ {
6802
+ checked: field.required === true,
6803
+ onChange: (event) => updateField(stepIndex, fieldIndex, { required: event.target.checked }),
6804
+ type: "checkbox"
6805
+ }
6806
+ ),
6807
+ "Required"
6808
+ ] }),
6809
+ /* @__PURE__ */ jsxs27("label", { children: [
6810
+ "Help text",
6811
+ /* @__PURE__ */ jsx30(
6812
+ "textarea",
6813
+ {
6814
+ onChange: (event) => updateField(stepIndex, fieldIndex, { helpText: event.target.value }),
6815
+ rows: 2,
6816
+ value: getNonEmptyText(field.helpText)
6817
+ }
6818
+ )
6819
+ ] }),
6820
+ ["select", "radio", "checkbox-group"].includes(fieldType) ? /* @__PURE__ */ jsxs27("label", { children: [
6821
+ "Options",
6822
+ /* @__PURE__ */ jsx30(
6823
+ "textarea",
6824
+ {
6825
+ onChange: (event) => updateField(stepIndex, fieldIndex, {
6826
+ options: fromOptionsText(event.target.value)
6827
+ }),
6828
+ placeholder: "Option one\nOption two",
6829
+ rows: 4,
6830
+ value: toOptionsText(field.options)
6831
+ }
6832
+ )
6833
+ ] }) : null
6834
+ ] })
6835
+ ] }, `edit-field-${stepIndex}-${fieldIndex}`);
6836
+ }) }) : /* @__PURE__ */ jsxs27("div", { className: "orion-admin-empty-state", children: [
6837
+ /* @__PURE__ */ jsx30("strong", { children: "No fields in this step" }),
6838
+ /* @__PURE__ */ jsx30("span", { children: "Add a field so visitors have something to answer here." })
6839
+ ] })
6840
+ ] })
6841
+ ] }, `edit-step-${stepIndex}`);
6842
+ }) })
6472
6843
  ] }),
6473
- /* @__PURE__ */ jsx30("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." }),
6474
6844
  /* @__PURE__ */ jsx30("button", { disabled: saving, type: "submit", children: saving ? "Saving..." : "Save Form" })
6475
6845
  ] })
6476
- ] }),
6477
- /* @__PURE__ */ jsxs27("div", { className: "orion-admin-card", children: [
6478
- /* @__PURE__ */ jsx30("strong", { children: "Current structure payload" }),
6479
- /* @__PURE__ */ jsx30("span", { children: "Reference snapshot of the form steps that will be written back on save." }),
6480
- /* @__PURE__ */ jsx30("pre", { style: { ...codeStyle, marginTop: "1rem" }, children: editorState.stepsText })
6481
6846
  ] })
6482
6847
  ] }) : null
6483
6848
  ]
@@ -6489,25 +6854,17 @@ function AdminStudioFormDetailView(props) {
6489
6854
  import Link5 from "next/link";
6490
6855
  import { useEffect as useEffect19, useMemo as useMemo15, useState as useState20 } from "react";
6491
6856
  import { Fragment as Fragment6, jsx as jsx31, jsxs as jsxs28 } from "react/jsx-runtime";
6492
- var codeStyle2 = {
6493
- background: "color-mix(in srgb, var(--orion-admin-card-bg) 82%, black)",
6494
- border: "1px solid var(--orion-admin-card-border)",
6495
- borderRadius: "var(--orion-admin-radius-sm)",
6496
- color: "var(--orion-admin-text)",
6497
- fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
6498
- fontSize: "0.86rem",
6499
- lineHeight: 1.55,
6500
- margin: 0,
6501
- maxHeight: "28rem",
6502
- overflow: "auto",
6503
- padding: "0.9rem",
6504
- whiteSpace: "pre-wrap"
6505
- };
6506
6857
  var sectionGridStyle2 = {
6507
6858
  display: "grid",
6508
6859
  gap: "1rem",
6509
6860
  gridTemplateColumns: "repeat(auto-fit, minmax(320px, 1fr))"
6510
6861
  };
6862
+ var nestedListStyle = {
6863
+ display: "grid",
6864
+ gap: "0.45rem",
6865
+ margin: 0,
6866
+ padding: 0
6867
+ };
6511
6868
  var renderFieldValue = (value) => {
6512
6869
  if (value === null || value === void 0) {
6513
6870
  return /* @__PURE__ */ jsx31("span", { className: "orion-admin-list-meta", children: "No value" });
@@ -6521,7 +6878,26 @@ var renderFieldValue = (value) => {
6521
6878
  if (typeof value === "string") {
6522
6879
  return value.trim().length > 0 ? value : /* @__PURE__ */ jsx31("span", { className: "orion-admin-list-meta", children: "No value" });
6523
6880
  }
6524
- return /* @__PURE__ */ jsx31("pre", { style: codeStyle2, children: JSON.stringify(value, null, 2) });
6881
+ if (Array.isArray(value)) {
6882
+ const entries = value.filter((entry) => entry !== null && entry !== void 0 && entry !== "");
6883
+ if (entries.length === 0) {
6884
+ return /* @__PURE__ */ jsx31("span", { className: "orion-admin-list-meta", children: "No value" });
6885
+ }
6886
+ return /* @__PURE__ */ jsx31("ul", { style: nestedListStyle, children: entries.map((entry, index) => /* @__PURE__ */ jsx31("li", { children: renderFieldValue(entry) }, index)) });
6887
+ }
6888
+ if (typeof value === "object") {
6889
+ const entries = Object.entries(value).filter(
6890
+ ([, entryValue]) => entryValue !== null && entryValue !== void 0 && entryValue !== ""
6891
+ );
6892
+ if (entries.length === 0) {
6893
+ return /* @__PURE__ */ jsx31("span", { className: "orion-admin-list-meta", children: "No value" });
6894
+ }
6895
+ return /* @__PURE__ */ jsx31("div", { style: { display: "grid", gap: "0.65rem" }, children: entries.map(([key, entryValue]) => /* @__PURE__ */ jsxs28("div", { className: "orion-admin-meta-row", children: [
6896
+ /* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-label", children: humanizeKey2(key) }),
6897
+ /* @__PURE__ */ jsx31("span", { className: "orion-admin-meta-value", children: renderFieldValue(entryValue) })
6898
+ ] }, key)) });
6899
+ }
6900
+ return String(value);
6525
6901
  };
6526
6902
  function getSubmissionIDFromPathname(pathname) {
6527
6903
  return getIDFromPathname(pathname, "/forms/submissions/");
@@ -6673,31 +7049,24 @@ function AdminStudioFormSubmissionView(props) {
6673
7049
  /* @__PURE__ */ jsxs28("article", { className: "orion-admin-overview-stat", children: [
6674
7050
  /* @__PURE__ */ jsx31("span", { className: "orion-admin-overview-stat-label", children: "Highlighted answers" }),
6675
7051
  /* @__PURE__ */ jsx31("strong", { children: previewFields.length }),
6676
- /* @__PURE__ */ jsx31("p", { children: "Readable answer previews surfaced from the structured payload." })
7052
+ /* @__PURE__ */ jsx31("p", { children: "Readable answer previews from this response." })
6677
7053
  ] })
6678
7054
  ] }),
6679
7055
  /* @__PURE__ */ jsxs28("div", { style: sectionGridStyle2, children: [
6680
- /* @__PURE__ */ jsxs28("div", { style: { display: "grid", gap: "1rem" }, children: [
6681
- /* @__PURE__ */ jsxs28("div", { className: "orion-admin-card", children: [
6682
- /* @__PURE__ */ jsx31("strong", { children: "Response details" }),
6683
- /* @__PURE__ */ jsx31("span", { children: "Formatted answers using the current form field labels when available." }),
6684
- /* @__PURE__ */ jsx31("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: answerEntries.length > 0 ? answerEntries.map(([key, value]) => /* @__PURE__ */ jsxs28("div", { className: "orion-admin-form", children: [
6685
- /* @__PURE__ */ jsxs28("div", { children: [
6686
- /* @__PURE__ */ jsx31("strong", { children: fieldLabels.get(key) || humanizeKey2(key) }),
6687
- /* @__PURE__ */ jsx31("div", { className: "orion-admin-list-meta", children: key })
6688
- ] }),
6689
- /* @__PURE__ */ jsx31("div", { children: renderFieldValue(value) })
6690
- ] }, key)) : /* @__PURE__ */ jsxs28("div", { className: "orion-admin-empty-state", children: [
6691
- /* @__PURE__ */ jsx31("strong", { children: "No response payload" }),
6692
- /* @__PURE__ */ jsx31("span", { children: "This submission does not contain a structured data object." })
6693
- ] }) })
6694
- ] }),
6695
- /* @__PURE__ */ jsxs28("div", { className: "orion-admin-card", children: [
6696
- /* @__PURE__ */ jsx31("strong", { children: "Raw payload" }),
6697
- /* @__PURE__ */ jsx31("span", { children: "Verbatim submission data for troubleshooting or export checks." }),
6698
- /* @__PURE__ */ jsx31("pre", { style: { ...codeStyle2, marginTop: "1rem" }, children: JSON.stringify(doc.data ?? {}, null, 2) })
6699
- ] })
6700
- ] }),
7056
+ /* @__PURE__ */ jsx31("div", { style: { display: "grid", gap: "1rem" }, children: /* @__PURE__ */ jsxs28("div", { className: "orion-admin-card", children: [
7057
+ /* @__PURE__ */ jsx31("strong", { children: "Response details" }),
7058
+ /* @__PURE__ */ jsx31("span", { children: "Formatted answers using the current form field labels when available." }),
7059
+ /* @__PURE__ */ jsx31("div", { style: { display: "grid", gap: "0.85rem", marginTop: "1rem" }, children: answerEntries.length > 0 ? answerEntries.map(([key, value]) => /* @__PURE__ */ jsxs28("div", { className: "orion-admin-form", children: [
7060
+ /* @__PURE__ */ jsxs28("div", { children: [
7061
+ /* @__PURE__ */ jsx31("strong", { children: fieldLabels.get(key) || humanizeKey2(key) }),
7062
+ /* @__PURE__ */ jsx31("div", { className: "orion-admin-list-meta", children: key })
7063
+ ] }),
7064
+ /* @__PURE__ */ jsx31("div", { children: renderFieldValue(value) })
7065
+ ] }, key)) : /* @__PURE__ */ jsxs28("div", { className: "orion-admin-empty-state", children: [
7066
+ /* @__PURE__ */ jsx31("strong", { children: "No answers available" }),
7067
+ /* @__PURE__ */ jsx31("span", { children: "This submission does not contain visible response details." })
7068
+ ] }) })
7069
+ ] }) }),
6701
7070
  /* @__PURE__ */ jsxs28("div", { style: { display: "grid", gap: "1rem" }, children: [
6702
7071
  /* @__PURE__ */ jsxs28("div", { className: "orion-admin-card orion-admin-meta-table", children: [
6703
7072
  /* @__PURE__ */ jsxs28("div", { className: "orion-admin-meta-row", children: [