ding-react-admin 2.3.0 → 2.5.0

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 (80) hide show
  1. package/dist/index.js +284 -231
  2. package/dist/src/crud/HiddenSources.d.ts +9 -0
  3. package/dist/src/crud/HiddenSources.d.ts.map +1 -0
  4. package/dist/src/crud/InlineFormSet.d.ts.map +1 -1
  5. package/dist/src/crud/ResourceList.d.ts.map +1 -1
  6. package/dist/src/crud/columns/BooleanColumn.d.ts.map +1 -1
  7. package/dist/src/crud/columns/DateColumn.d.ts.map +1 -1
  8. package/dist/src/crud/columns/ImageColumn.d.ts.map +1 -1
  9. package/dist/src/crud/columns/NumberColumn.d.ts.map +1 -1
  10. package/dist/src/crud/columns/ReferenceColumn.d.ts.map +1 -1
  11. package/dist/src/crud/columns/ReferenceManyColumn.d.ts.map +1 -1
  12. package/dist/src/crud/columns/TextColumn.d.ts.map +1 -1
  13. package/dist/src/crud/fields/BooleanField.d.ts +3 -3
  14. package/dist/src/crud/fields/BooleanField.d.ts.map +1 -1
  15. package/dist/src/crud/fields/DateField.d.ts +3 -3
  16. package/dist/src/crud/fields/DateField.d.ts.map +1 -1
  17. package/dist/src/crud/fields/FieldWrapper.d.ts +3 -1
  18. package/dist/src/crud/fields/FieldWrapper.d.ts.map +1 -1
  19. package/dist/src/crud/fields/FileField.d.ts +3 -3
  20. package/dist/src/crud/fields/FileField.d.ts.map +1 -1
  21. package/dist/src/crud/fields/ImageField.d.ts +3 -3
  22. package/dist/src/crud/fields/ImageField.d.ts.map +1 -1
  23. package/dist/src/crud/fields/NumberField.d.ts +3 -3
  24. package/dist/src/crud/fields/NumberField.d.ts.map +1 -1
  25. package/dist/src/crud/fields/PasswordField.d.ts +3 -3
  26. package/dist/src/crud/fields/PasswordField.d.ts.map +1 -1
  27. package/dist/src/crud/fields/ReferenceField.d.ts +3 -3
  28. package/dist/src/crud/fields/ReferenceField.d.ts.map +1 -1
  29. package/dist/src/crud/fields/ReferenceManyField.d.ts +3 -3
  30. package/dist/src/crud/fields/ReferenceManyField.d.ts.map +1 -1
  31. package/dist/src/crud/fields/SelectField.d.ts +3 -3
  32. package/dist/src/crud/fields/SelectField.d.ts.map +1 -1
  33. package/dist/src/crud/fields/TextAreaField.d.ts +3 -3
  34. package/dist/src/crud/fields/TextAreaField.d.ts.map +1 -1
  35. package/dist/src/crud/fields/TextField.d.ts +3 -3
  36. package/dist/src/crud/fields/TextField.d.ts.map +1 -1
  37. package/dist/src/crud/fields/TimeField.d.ts +3 -3
  38. package/dist/src/crud/fields/TimeField.d.ts.map +1 -1
  39. package/dist/src/crud/index.d.ts +3 -1
  40. package/dist/src/crud/index.d.ts.map +1 -1
  41. package/dist/src/crud/types.d.ts +5 -0
  42. package/dist/src/crud/types.d.ts.map +1 -1
  43. package/dist/src/crud/utils/buildInlineRowsPayload.d.ts.map +1 -1
  44. package/dist/src/crud/utils/columnDataIndex.d.ts +5 -0
  45. package/dist/src/crud/utils/columnDataIndex.d.ts.map +1 -0
  46. package/dist/src/crud/utils/shouldRegisterSourceInPayload.d.ts +6 -0
  47. package/dist/src/crud/utils/shouldRegisterSourceInPayload.d.ts.map +1 -0
  48. package/dist/src/index.d.ts +2 -2
  49. package/dist/src/index.d.ts.map +1 -1
  50. package/package.json +1 -1
  51. package/src/crud/HiddenSources.tsx +37 -0
  52. package/src/crud/InlineFormSet.tsx +4 -1
  53. package/src/crud/ResourceList.tsx +10 -1
  54. package/src/crud/columns/BooleanColumn.tsx +2 -1
  55. package/src/crud/columns/DateColumn.tsx +2 -1
  56. package/src/crud/columns/ImageColumn.tsx +2 -1
  57. package/src/crud/columns/NumberColumn.tsx +2 -1
  58. package/src/crud/columns/ReferenceColumn.tsx +2 -1
  59. package/src/crud/columns/ReferenceManyColumn.tsx +2 -1
  60. package/src/crud/columns/TextColumn.tsx +3 -2
  61. package/src/crud/fields/BooleanField.tsx +4 -2
  62. package/src/crud/fields/DateField.tsx +4 -2
  63. package/src/crud/fields/FieldWrapper.tsx +20 -7
  64. package/src/crud/fields/FileField.tsx +4 -2
  65. package/src/crud/fields/ImageField.tsx +4 -2
  66. package/src/crud/fields/NumberField.tsx +4 -2
  67. package/src/crud/fields/PasswordField.tsx +8 -2
  68. package/src/crud/fields/ReferenceField.tsx +4 -2
  69. package/src/crud/fields/ReferenceManyField.tsx +4 -2
  70. package/src/crud/fields/SelectField.tsx +4 -2
  71. package/src/crud/fields/TextAreaField.tsx +4 -2
  72. package/src/crud/fields/TextField.tsx +4 -2
  73. package/src/crud/fields/TimeField.tsx +4 -2
  74. package/src/crud/index.ts +3 -0
  75. package/src/crud/types.ts +6 -0
  76. package/src/crud/utils/buildInlineRowsPayload.ts +5 -2
  77. package/src/crud/utils/columnDataIndex.ts +6 -0
  78. package/src/crud/utils/shouldRegisterSourceInPayload.ts +10 -0
  79. package/src/data/dataUtils.test.ts +52 -1
  80. package/src/index.ts +3 -0
@@ -7,6 +7,8 @@ import type {
7
7
  InlineRowContext,
8
8
  } from "./types";
9
9
  import { nestedFieldPath } from "./utils/nestedFieldPath";
10
+ import { getFormValue } from "./utils/getFormValue";
11
+ import { setFormValue } from "./utils/setFormValue";
10
12
  import { useRegisterInlineField } from "./context/InlineFieldsRegistry";
11
13
  import { useRegisterPayloadField } from "./context/PayloadFieldsContext";
12
14
 
@@ -29,7 +31,8 @@ export type InlineFormSetStackedProps = InlineFormSetBaseProps & {
29
31
  function emptyRow(sources: string[], defaults?: Record<string, unknown>) {
30
32
  const row: Record<string, unknown> = {};
31
33
  for (const source of sources) {
32
- row[source] = defaults?.[source] ?? undefined;
34
+ const value = defaults ? getFormValue(defaults, source) : undefined;
35
+ setFormValue(row, source, value);
33
36
  }
34
37
  return row;
35
38
  }
@@ -471,6 +471,15 @@ function ResourceListTable<T extends Record<string, unknown>>({
471
471
  const handleDelete = useCallback(
472
472
  async (row: T) => {
473
473
  if (!canDelete) return;
474
+ const confirmed = await new Promise<boolean>((resolve) => {
475
+ modal.confirm({
476
+ title: "Delete this item? This cannot be undone.",
477
+ okType: "danger",
478
+ onOk: () => resolve(true),
479
+ onCancel: () => resolve(false),
480
+ });
481
+ });
482
+ if (!confirmed) return;
474
483
  try {
475
484
  await dp.delete(resource, row.id as string | number);
476
485
  message.success("Deleted");
@@ -479,7 +488,7 @@ function ResourceListTable<T extends Record<string, unknown>>({
479
488
  message.error(e instanceof Error ? e.message : "Delete failed");
480
489
  }
481
490
  },
482
- [canDelete, dp, resource, load, message],
491
+ [canDelete, dp, resource, load, message, modal],
483
492
  );
484
493
 
485
494
  const tableColumns = useMemo((): ColumnsType<T> => {
@@ -1,5 +1,6 @@
1
1
  import { useMemo } from "react";
2
2
  import type { BaseSourceProps } from "../types";
3
+ import { columnDataIndex } from "../utils/columnDataIndex";
3
4
  import { useRegisterColumn } from "../context/ListContext";
4
5
 
5
6
  export type BooleanColumnProps = BaseSourceProps & {
@@ -19,7 +20,7 @@ export function BooleanColumn({
19
20
  sortable,
20
21
  buildColumn: () => ({
21
22
  title: label ?? source,
22
- dataIndex: source,
23
+ dataIndex: columnDataIndex(source),
23
24
  key: source,
24
25
  sorter: sortable ? true : undefined,
25
26
  render: (v: boolean) => (v ? "Yes" : "No"),
@@ -1,5 +1,6 @@
1
1
  import { useMemo } from "react";
2
2
  import type { BaseSourceProps } from "../types";
3
+ import { columnDataIndex } from "../utils/columnDataIndex";
3
4
  import { useRegisterColumn } from "../context/ListContext";
4
5
 
5
6
  export type DateColumnProps = BaseSourceProps & {
@@ -15,7 +16,7 @@ export function DateColumn({ source, label, sortable = true }: DateColumnProps)
15
16
  sortable,
16
17
  buildColumn: () => ({
17
18
  title: label ?? source,
18
- dataIndex: source,
19
+ dataIndex: columnDataIndex(source),
19
20
  key: source,
20
21
  sorter: sortable ? true : undefined,
21
22
  render: (v: string) => (v ? String(v).slice(0, 10) : "—"),
@@ -1,5 +1,6 @@
1
1
  import { useMemo, type CSSProperties } from "react";
2
2
  import type { BaseSourceProps } from "../types";
3
+ import { columnDataIndex } from "../utils/columnDataIndex";
3
4
  import { useRegisterColumn } from "../context/ListContext";
4
5
 
5
6
  export type ImageColumnProps = BaseSourceProps & {
@@ -31,7 +32,7 @@ export function ImageColumn({
31
32
  sortable,
32
33
  buildColumn: () => ({
33
34
  title: label ?? source,
34
- dataIndex: source,
35
+ dataIndex: columnDataIndex(source),
35
36
  key: source,
36
37
  sorter: sortable ? true : undefined,
37
38
  render: (value: unknown) => {
@@ -1,5 +1,6 @@
1
1
  import { useMemo } from "react";
2
2
  import type { BaseSourceProps } from "../types";
3
+ import { columnDataIndex } from "../utils/columnDataIndex";
3
4
  import { useRegisterColumn } from "../context/ListContext";
4
5
 
5
6
  export type NumberColumnProps = BaseSourceProps & {
@@ -19,7 +20,7 @@ export function NumberColumn({
19
20
  sortable,
20
21
  buildColumn: () => ({
21
22
  title: label ?? source,
22
- dataIndex: source,
23
+ dataIndex: columnDataIndex(source),
23
24
  key: source,
24
25
  sorter: sortable ? true : undefined,
25
26
  }),
@@ -1,6 +1,7 @@
1
1
  import { useMemo } from "react";
2
2
  import type { BaseSourceProps, DisplayProps, ReferenceProps } from "../types";
3
3
  import { useRegisterColumn } from "../context/ListContext";
4
+ import { getFormValue } from "../utils/getFormValue";
4
5
  import { useChoices } from "../utils/useChoices";
5
6
  import { renderDisplayValue } from "./TextColumn";
6
7
 
@@ -25,7 +26,7 @@ function ReferenceColumnCell({
25
26
  optionLabel,
26
27
  optionValue,
27
28
  );
28
- const raw = record[source];
29
+ const raw = getFormValue(record, source);
29
30
  if (typeof display === "function") return <>{display(record)}</>;
30
31
  if (display && display !== source) {
31
32
  const nested = renderDisplayValue(record, source, display);
@@ -1,6 +1,7 @@
1
1
  import { useMemo } from "react";
2
2
  import type { BaseSourceProps, DisplayProps, ReferenceProps } from "../types";
3
3
  import { useRegisterColumn } from "../context/ListContext";
4
+ import { getFormValue } from "../utils/getFormValue";
4
5
  import { useChoices } from "../utils/useChoices";
5
6
 
6
7
  export type ReferenceManyColumnProps = BaseSourceProps &
@@ -23,7 +24,7 @@ function ReferenceManyColumnCell({
23
24
  optionLabel,
24
25
  optionValue,
25
26
  );
26
- const raw = record[source];
27
+ const raw = getFormValue(record, source);
27
28
  const values = Array.isArray(raw) ? raw : [];
28
29
  return <>{labelsForValues(values)}</>;
29
30
  }
@@ -1,5 +1,6 @@
1
1
  import { useMemo } from "react";
2
2
  import type { BaseSourceProps } from "../types";
3
+ import { columnDataIndex } from "../utils/columnDataIndex";
3
4
  import { getFormValue } from "../utils/getFormValue";
4
5
  import { useRegisterColumn } from "../context/ListContext";
5
6
 
@@ -16,7 +17,7 @@ export function TextColumn({ source, label, sortable = true }: TextColumnProps)
16
17
  sortable,
17
18
  buildColumn: () => ({
18
19
  title: label ?? source,
19
- dataIndex: source,
20
+ dataIndex: columnDataIndex(source),
20
21
  key: source,
21
22
  sorter: sortable ? true : undefined,
22
23
  }),
@@ -34,5 +35,5 @@ export function renderDisplayValue(
34
35
  ): unknown {
35
36
  if (typeof display === "function") return display(record);
36
37
  if (display) return getFormValue(record, display);
37
- return record[source];
38
+ return getFormValue(record, source);
38
39
  }
@@ -1,8 +1,8 @@
1
1
  import { Switch } from "antd";
2
- import type { BaseSourceProps, FieldRules } from "../types";
2
+ import type { FieldSourceProps, FieldRules } from "../types";
3
3
  import { FieldWrapper } from "./FieldWrapper";
4
4
 
5
- export type BooleanFieldProps = BaseSourceProps & {
5
+ export type BooleanFieldProps = FieldSourceProps & {
6
6
  name?: string;
7
7
  required?: boolean;
8
8
  rules?: FieldRules;
@@ -17,6 +17,7 @@ export function BooleanField({
17
17
  required,
18
18
  rules,
19
19
  hideLabel,
20
+ hidden,
20
21
  disabled: disabledProp,
21
22
  }: BooleanFieldProps) {
22
23
  return (
@@ -27,6 +28,7 @@ export function BooleanField({
27
28
  required={required}
28
29
  rules={rules}
29
30
  hideLabel={hideLabel}
31
+ hidden={hidden}
30
32
  >
31
33
  {({ value, onChange, disabled }) => (
32
34
  <Switch
@@ -1,5 +1,5 @@
1
1
  import { DatePicker } from "antd";
2
- import type { BaseSourceProps, FieldRules } from "../types";
2
+ import type { FieldSourceProps, FieldRules } from "../types";
3
3
  import { parseDayjsValue } from "../utils/parseDayjsValue";
4
4
  import { FieldWrapper } from "./FieldWrapper";
5
5
 
@@ -7,7 +7,7 @@ const DATE_FORMAT = "YYYY-MM-DD";
7
7
  const DATE_TIME_FORMAT = `${DATE_FORMAT} HH:mm:ss`;
8
8
  const PARSE_FORMATS = [DATE_FORMAT, DATE_TIME_FORMAT, "YYYY-MM-DDTHH:mm:ss", "YYYY-MM-DDTHH:mm:ssZ"];
9
9
 
10
- export type DateFieldProps = BaseSourceProps & {
10
+ export type DateFieldProps = FieldSourceProps & {
11
11
  name?: string;
12
12
  required?: boolean;
13
13
  rules?: FieldRules;
@@ -23,6 +23,7 @@ export function DateField({
23
23
  rules,
24
24
  showTime,
25
25
  hideLabel,
26
+ hidden,
26
27
  }: DateFieldProps) {
27
28
  return (
28
29
  <FieldWrapper
@@ -32,6 +33,7 @@ export function DateField({
32
33
  required={required}
33
34
  rules={rules}
34
35
  hideLabel={hideLabel}
36
+ hidden={hidden}
35
37
  >
36
38
  {({ value, onChange, onBlur, disabled }) => (
37
39
  <DatePicker
@@ -7,6 +7,8 @@ import {
7
7
  useRegisterPayloadField,
8
8
  useRegisterSectionField,
9
9
  } from "../context/PayloadFieldsContext";
10
+ import { shouldRegisterSourceInPayload } from "../utils/shouldRegisterSourceInPayload";
11
+ import { isSourceHidden, useHiddenSources } from "../HiddenSources";
10
12
 
11
13
  export type FieldWrapperProps = {
12
14
  /** Logical field name — used for submit payload tracking on top-level fields. */
@@ -18,6 +20,8 @@ export type FieldWrapperProps = {
18
20
  rules?: FieldRules;
19
21
  /** Tabular inline cells: column header replaces the label. */
20
22
  hideLabel?: boolean;
23
+ /** Hide the control but keep the value in the form and save payload. */
24
+ hidden?: boolean;
21
25
  children: (props: {
22
26
  value: unknown;
23
27
  onChange: (value: unknown) => void;
@@ -34,10 +38,12 @@ export function FieldWrapper({
34
38
  required,
35
39
  rules,
36
40
  hideLabel,
41
+ hidden,
37
42
  children,
38
43
  }: FieldWrapperProps) {
39
44
  const fieldName = name ?? source;
40
- const isTopLevel = !fieldName.includes(".");
45
+ const registerSource = shouldRegisterSourceInPayload(source, name);
46
+ const isHidden = isSourceHidden(source, hidden, useHiddenSources());
41
47
 
42
48
  // react-hook-form: connect this field to the form from <ResourceForm>'s FormProvider.
43
49
  // `control` is passed to <Controller> below so value, onChange, and validation work.
@@ -49,13 +55,20 @@ export function FieldWrapper({
49
55
  const fieldLabel = hideLabel ? undefined : (label ?? source);
50
56
  const requiredMessage = label ?? source;
51
57
 
52
- // Add this field's `source` to the Save payload (ResourceForm → buildFormPayload).
53
- // `isTopLevel` is false when `name` contains "." (e.g. inline cell `__inline_lines.0.label`) —
54
- // those values live in the inline array and are saved by saveInlineRows, not the parent PATCH.
55
- useRegisterPayloadField(source, isTopLevel);
58
+ // Nested parent fields (`source="address.city"`) register; inline cells
59
+ // (`name="lines.0.label"`, `source="label"`) do not those go through the inline array.
60
+ useRegisterPayloadField(source, registerSource);
61
+ useRegisterSectionField(source, registerSource);
56
62
 
57
- // Same top-level check: attach this field to the current FormTab / FormStep for error highlighting.
58
- useRegisterSectionField(source, isTopLevel);
63
+ if (isHidden) {
64
+ return (
65
+ <Controller
66
+ name={fieldName}
67
+ control={control}
68
+ render={() => <></>}
69
+ />
70
+ );
71
+ }
59
72
 
60
73
  return (
61
74
  <Controller
@@ -1,7 +1,7 @@
1
1
  import { DeleteOutlined, PaperClipOutlined, UploadOutlined } from "@ant-design/icons";
2
2
  import { Button, Space, Typography } from "antd";
3
3
  import { useRef } from "react";
4
- import type { BaseSourceProps, FieldRules } from "../types";
4
+ import type { FieldSourceProps, FieldRules } from "../types";
5
5
  import { FieldWrapper } from "./FieldWrapper";
6
6
  import {
7
7
  getUploadFileName,
@@ -9,7 +9,7 @@ import {
9
9
  type UploadFieldValue,
10
10
  } from "./uploadFieldUtils";
11
11
 
12
- export type FileFieldProps = BaseSourceProps & {
12
+ export type FileFieldProps = FieldSourceProps & {
13
13
  name?: string;
14
14
  required?: boolean;
15
15
  rules?: FieldRules;
@@ -97,6 +97,7 @@ export function FileField({
97
97
  required,
98
98
  rules,
99
99
  hideLabel,
100
+ hidden,
100
101
  clearable,
101
102
  accept,
102
103
  }: FileFieldProps) {
@@ -108,6 +109,7 @@ export function FileField({
108
109
  required={required}
109
110
  rules={rules}
110
111
  hideLabel={hideLabel}
112
+ hidden={hidden}
111
113
  >
112
114
  {({ value, onChange, disabled }) => (
113
115
  <FileFieldInput
@@ -1,12 +1,12 @@
1
1
  import { DeleteOutlined, UploadOutlined } from "@ant-design/icons";
2
2
  import { Button, Image, Space } from "antd";
3
3
  import { useRef } from "react";
4
- import type { BaseSourceProps, FieldRules } from "../types";
4
+ import type { FieldSourceProps, FieldRules } from "../types";
5
5
  import { FieldWrapper } from "./FieldWrapper";
6
6
  import { hasUploadValue, type UploadFieldValue } from "./uploadFieldUtils";
7
7
  import { useUploadPreviewUrl } from "./useUploadPreviewUrl";
8
8
 
9
- export type ImageFieldProps = BaseSourceProps & {
9
+ export type ImageFieldProps = FieldSourceProps & {
10
10
  name?: string;
11
11
  required?: boolean;
12
12
  rules?: FieldRules;
@@ -92,6 +92,7 @@ export function ImageField({
92
92
  required,
93
93
  rules,
94
94
  hideLabel,
95
+ hidden,
95
96
  clearable,
96
97
  accept,
97
98
  previewWidth,
@@ -104,6 +105,7 @@ export function ImageField({
104
105
  required={required}
105
106
  rules={rules}
106
107
  hideLabel={hideLabel}
108
+ hidden={hidden}
107
109
  >
108
110
  {({ value, onChange, disabled }) => (
109
111
  <ImageFieldInput
@@ -1,9 +1,9 @@
1
1
  import { InputNumber } from "antd";
2
2
  import type { CSSProperties } from "react";
3
- import type { BaseSourceProps, FieldRules } from "../types";
3
+ import type { FieldSourceProps, FieldRules } from "../types";
4
4
  import { FieldWrapper } from "./FieldWrapper";
5
5
 
6
- export type NumberFieldProps = BaseSourceProps & {
6
+ export type NumberFieldProps = FieldSourceProps & {
7
7
  name?: string;
8
8
  required?: boolean;
9
9
  rules?: FieldRules;
@@ -25,6 +25,7 @@ export function NumberField({
25
25
  step,
26
26
  inputStyle,
27
27
  hideLabel,
28
+ hidden,
28
29
  }: NumberFieldProps) {
29
30
  return (
30
31
  <FieldWrapper
@@ -34,6 +35,7 @@ export function NumberField({
34
35
  required={required}
35
36
  rules={rules}
36
37
  hideLabel={hideLabel}
38
+ hidden={hidden}
37
39
  >
38
40
  {({ value, onChange, onBlur, disabled }) => (
39
41
  <InputNumber
@@ -1,9 +1,9 @@
1
1
  import { Input } from "antd";
2
2
  import { useWatch } from "react-hook-form";
3
- import type { BaseSourceProps, FieldRules } from "../types";
3
+ import type { FieldSourceProps, FieldRules } from "../types";
4
4
  import { FieldWrapper } from "./FieldWrapper";
5
5
 
6
- export type PasswordFieldProps = BaseSourceProps & {
6
+ export type PasswordFieldProps = FieldSourceProps & {
7
7
  name?: string;
8
8
  required?: boolean;
9
9
  rules?: FieldRules;
@@ -22,6 +22,7 @@ function PasswordInputField({
22
22
  rules,
23
23
  autoComplete,
24
24
  hideLabel,
25
+ hidden,
25
26
  }: PasswordFieldProps) {
26
27
  return (
27
28
  <FieldWrapper
@@ -31,6 +32,7 @@ function PasswordInputField({
31
32
  required={required}
32
33
  rules={rules}
33
34
  hideLabel={hideLabel}
35
+ hidden={hidden}
34
36
  >
35
37
  {({ value, onChange, onBlur, disabled }) => (
36
38
  <Input.Password
@@ -55,6 +57,7 @@ export function PasswordField({
55
57
  confirmLabel = "Confirm password",
56
58
  autoComplete = "new-password",
57
59
  hideLabel,
60
+ hidden,
58
61
  }: PasswordFieldProps) {
59
62
  const password = useWatch({ name: name ?? source, disabled: !confirmSource });
60
63
 
@@ -68,6 +71,7 @@ export function PasswordField({
68
71
  rules={rules}
69
72
  autoComplete={autoComplete}
70
73
  hideLabel={hideLabel}
74
+ hidden={hidden}
71
75
  />
72
76
  );
73
77
  }
@@ -82,6 +86,7 @@ export function PasswordField({
82
86
  rules={rules}
83
87
  autoComplete={autoComplete}
84
88
  hideLabel={hideLabel}
89
+ hidden={hidden}
85
90
  />
86
91
  <PasswordInputField
87
92
  source={confirmSource}
@@ -93,6 +98,7 @@ export function PasswordField({
93
98
  validate: (value: string) =>
94
99
  !password || value === password || "Passwords do not match",
95
100
  }}
101
+ hidden={hidden}
96
102
  />
97
103
  </>
98
104
  );
@@ -3,7 +3,7 @@ import type { CSSProperties } from "react";
3
3
  import { useMemo, useState } from "react";
4
4
  import { useWatch } from "react-hook-form";
5
5
  import type {
6
- BaseSourceProps,
6
+ FieldSourceProps,
7
7
  ChoiceOption,
8
8
  FieldRules,
9
9
  ReferenceProps,
@@ -21,7 +21,7 @@ import { ReferenceInputActions } from "./ReferenceInputActions";
21
21
  import type { ResourcePermissions } from "../../permissions/resourcePermissions";
22
22
  import type { ReactNode } from "react";
23
23
 
24
- export type ReferenceFieldProps = BaseSourceProps &
24
+ export type ReferenceFieldProps = FieldSourceProps &
25
25
  ReferenceProps & {
26
26
  name?: string;
27
27
  required?: boolean;
@@ -197,6 +197,7 @@ export function ReferenceField({
197
197
  allowClear,
198
198
  disabled: disabledProp,
199
199
  hideLabel,
200
+ hidden,
200
201
  inputStyle,
201
202
  onValueChange,
202
203
  lazy = true,
@@ -224,6 +225,7 @@ export function ReferenceField({
224
225
  required={required}
225
226
  rules={rules}
226
227
  hideLabel={hideLabel}
228
+ hidden={hidden}
227
229
  >
228
230
  {({ value, onChange, disabled, name: fieldName }) => (
229
231
  <ReferenceFieldSelect
@@ -1,7 +1,7 @@
1
1
  import { Select } from "antd";
2
2
  import { useMemo, useState } from "react";
3
3
  import { useWatch } from "react-hook-form";
4
- import type { BaseSourceProps, FieldRules, ReferenceProps } from "../types";
4
+ import type { FieldSourceProps, FieldRules, ReferenceProps } from "../types";
5
5
  import { valuesAsIds } from "../utils/choiceSelectionUtils";
6
6
  import { referenceSelectDropdownProps } from "../utils/referenceSelectDropdownProps";
7
7
  import { referenceSelectNotFoundContent } from "../utils/referenceSelectNotFoundContent";
@@ -15,7 +15,7 @@ import { ReferenceInputActions } from "./ReferenceInputActions";
15
15
  import type { ResourcePermissions } from "../../permissions/resourcePermissions";
16
16
  import type { ReactNode } from "react";
17
17
 
18
- export type ReferenceManyFieldProps = BaseSourceProps &
18
+ export type ReferenceManyFieldProps = FieldSourceProps &
19
19
  ReferenceProps & {
20
20
  name?: string;
21
21
  required?: boolean;
@@ -165,6 +165,7 @@ export function ReferenceManyField({
165
165
  search,
166
166
  allowClear = true,
167
167
  hideLabel,
168
+ hidden,
168
169
  disabled: disabledProp,
169
170
  lazy = true,
170
171
  recordSource,
@@ -191,6 +192,7 @@ export function ReferenceManyField({
191
192
  required={required}
192
193
  rules={rules}
193
194
  hideLabel={hideLabel}
195
+ hidden={hidden}
194
196
  >
195
197
  {({ value, onChange, disabled }) => (
196
198
  <ReferenceManyFieldSelect
@@ -1,8 +1,8 @@
1
1
  import { Select } from "antd";
2
- import type { BaseSourceProps, ChoiceOption, FieldRules } from "../types";
2
+ import type { FieldSourceProps, ChoiceOption, FieldRules } from "../types";
3
3
  import { FieldWrapper } from "./FieldWrapper";
4
4
 
5
- export type SelectFieldProps = BaseSourceProps & {
5
+ export type SelectFieldProps = FieldSourceProps & {
6
6
  name?: string;
7
7
  required?: boolean;
8
8
  rules?: FieldRules;
@@ -22,6 +22,7 @@ export function SelectField({
22
22
  mode,
23
23
  allowClear,
24
24
  hideLabel,
25
+ hidden,
25
26
  }: SelectFieldProps) {
26
27
  return (
27
28
  <FieldWrapper
@@ -31,6 +32,7 @@ export function SelectField({
31
32
  required={required}
32
33
  rules={rules}
33
34
  hideLabel={hideLabel}
35
+ hidden={hidden}
34
36
  >
35
37
  {({ value, onChange, disabled }) => (
36
38
  <Select
@@ -1,9 +1,9 @@
1
1
  import { Input } from "antd";
2
2
  import type { CSSProperties } from "react";
3
- import type { BaseSourceProps, FieldRules } from "../types";
3
+ import type { FieldSourceProps, FieldRules } from "../types";
4
4
  import { FieldWrapper } from "./FieldWrapper";
5
5
 
6
- export type TextAreaFieldProps = BaseSourceProps & {
6
+ export type TextAreaFieldProps = FieldSourceProps & {
7
7
  name?: string;
8
8
  required?: boolean;
9
9
  rules?: FieldRules;
@@ -25,6 +25,7 @@ export function TextAreaField({
25
25
  placeholder,
26
26
  inputStyle,
27
27
  hideLabel,
28
+ hidden,
28
29
  rows = 4,
29
30
  maxLength,
30
31
  showCount,
@@ -38,6 +39,7 @@ export function TextAreaField({
38
39
  required={required}
39
40
  rules={rules}
40
41
  hideLabel={hideLabel}
42
+ hidden={hidden}
41
43
  >
42
44
  {({ value, onChange, onBlur, disabled }) => (
43
45
  <Input.TextArea
@@ -1,9 +1,9 @@
1
1
  import { Input } from "antd";
2
2
  import type { CSSProperties } from "react";
3
- import type { BaseSourceProps, FieldRules } from "../types";
3
+ import type { FieldSourceProps, FieldRules } from "../types";
4
4
  import { FieldWrapper } from "./FieldWrapper";
5
5
 
6
- export type TextFieldProps = BaseSourceProps & {
6
+ export type TextFieldProps = FieldSourceProps & {
7
7
  name?: string;
8
8
  required?: boolean;
9
9
  rules?: FieldRules;
@@ -21,6 +21,7 @@ export function TextField({
21
21
  placeholder,
22
22
  inputStyle,
23
23
  hideLabel,
24
+ hidden,
24
25
  }: TextFieldProps) {
25
26
  return (
26
27
  <FieldWrapper
@@ -30,6 +31,7 @@ export function TextField({
30
31
  required={required}
31
32
  rules={rules}
32
33
  hideLabel={hideLabel}
34
+ hidden={hidden}
33
35
  >
34
36
  {({ value, onChange, onBlur, disabled }) => (
35
37
  <Input
@@ -1,12 +1,12 @@
1
1
  import { TimePicker } from "antd";
2
- import type { BaseSourceProps, FieldRules } from "../types";
2
+ import type { FieldSourceProps, FieldRules } from "../types";
3
3
  import { parseDayjsValue } from "../utils/parseDayjsValue";
4
4
  import { FieldWrapper } from "./FieldWrapper";
5
5
 
6
6
  const DEFAULT_TIME_FORMAT = "HH:mm:ss";
7
7
  const PARSE_FORMATS = [DEFAULT_TIME_FORMAT, "HH:mm", "H:mm:ss", "H:mm"];
8
8
 
9
- export type TimeFieldProps = BaseSourceProps & {
9
+ export type TimeFieldProps = FieldSourceProps & {
10
10
  name?: string;
11
11
  required?: boolean;
12
12
  rules?: FieldRules;
@@ -22,6 +22,7 @@ export function TimeField({
22
22
  required,
23
23
  rules,
24
24
  hideLabel,
25
+ hidden,
25
26
  format = DEFAULT_TIME_FORMAT,
26
27
  }: TimeFieldProps) {
27
28
  return (
@@ -32,6 +33,7 @@ export function TimeField({
32
33
  required={required}
33
34
  rules={rules}
34
35
  hideLabel={hideLabel}
36
+ hidden={hidden}
35
37
  >
36
38
  {({ value, onChange, onBlur, disabled }) => (
37
39
  <TimePicker
package/src/crud/index.ts CHANGED
@@ -5,6 +5,7 @@ export { ResourceForm } from "./ResourceForm";
5
5
  export type { ResourceFormProps } from "./ResourceForm";
6
6
  export { ResourceFormModal } from "./ResourceFormModal";
7
7
  export type { ResourceFormModalProps } from "./ResourceFormModal";
8
+ export { HiddenSources } from "./HiddenSources";
8
9
  export { InlineFormSet, InlineFormSetStacked } from "./InlineFormSet";
9
10
  export type {
10
11
  InlineFormSetProps,
@@ -75,6 +76,7 @@ export { getFormValue } from "./utils/getFormValue";
75
76
  export { setFormValue } from "./utils/setFormValue";
76
77
  export { buildFormPayload } from "./utils/buildFormPayload";
77
78
  export { buildInlineRowsPayload } from "./utils/buildInlineRowsPayload";
79
+ export { columnDataIndex } from "./utils/columnDataIndex";
78
80
  export { buildResourceFormSubmitBody } from "./utils/buildResourceFormSubmitBody";
79
81
  export { prepareFormSubmitBody } from "./utils/prepareFormSubmitBody";
80
82
  export { toFormData } from "./utils/toFormData";
@@ -90,6 +92,7 @@ export type { InlineFieldRegistration } from "./context/InlineFieldsRegistry";
90
92
 
91
93
  export type {
92
94
  BaseSourceProps,
95
+ FieldSourceProps,
93
96
  ChoiceOption,
94
97
  ChoicesLoader,
95
98
  ReferenceProps,
package/src/crud/types.ts CHANGED
@@ -8,6 +8,12 @@ export type BaseSourceProps = {
8
8
  label?: string;
9
9
  };
10
10
 
11
+ /** Form fields only — columns and filters do not hide-and-keep a value. */
12
+ export type FieldSourceProps = BaseSourceProps & {
13
+ /** Hide the control but keep the value in the form and save payload. */
14
+ hidden?: boolean;
15
+ };
16
+
11
17
  export type ChoiceOption = {
12
18
  label: string;
13
19
  value: unknown;