ding-react-admin 1.0.4 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (230) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +254 -201
  3. package/dist/index.css +2 -0
  4. package/dist/index.js +2073 -1202
  5. package/dist/src/components/NavMenuLabel.d.ts +8 -0
  6. package/dist/src/components/NavMenuLabel.d.ts.map +1 -0
  7. package/dist/src/components/NavMenuSearch.d.ts +9 -0
  8. package/dist/src/components/NavMenuSearch.d.ts.map +1 -0
  9. package/dist/src/components/ScrollableArea.d.ts +10 -0
  10. package/dist/src/components/ScrollableArea.d.ts.map +1 -0
  11. package/dist/src/components/index.d.ts +3 -0
  12. package/dist/src/components/index.d.ts.map +1 -1
  13. package/dist/src/context/AuthProvider.d.ts +2 -0
  14. package/dist/src/context/AuthProvider.d.ts.map +1 -1
  15. package/dist/src/crud/FormGlobalErrorsAlert.d.ts +5 -0
  16. package/dist/src/crud/FormGlobalErrorsAlert.d.ts.map +1 -0
  17. package/dist/src/crud/InlineFormSet.d.ts +2 -17
  18. package/dist/src/crud/InlineFormSet.d.ts.map +1 -1
  19. package/dist/src/crud/ResourceForm.d.ts +2 -10
  20. package/dist/src/crud/ResourceForm.d.ts.map +1 -1
  21. package/dist/src/crud/ResourceFormModal.d.ts +7 -1
  22. package/dist/src/crud/ResourceFormModal.d.ts.map +1 -1
  23. package/dist/src/crud/ResourceList.d.ts.map +1 -1
  24. package/dist/src/crud/ResourceRecordForm.d.ts +27 -0
  25. package/dist/src/crud/ResourceRecordForm.d.ts.map +1 -0
  26. package/dist/src/crud/columns/ImageColumn.d.ts +14 -0
  27. package/dist/src/crud/columns/ImageColumn.d.ts.map +1 -0
  28. package/dist/src/crud/context/InlineFieldsRegistry.d.ts +15 -0
  29. package/dist/src/crud/context/InlineFieldsRegistry.d.ts.map +1 -0
  30. package/dist/src/crud/context/PayloadFieldsContext.d.ts +18 -0
  31. package/dist/src/crud/context/PayloadFieldsContext.d.ts.map +1 -0
  32. package/dist/src/crud/fields/FileField.d.ts +12 -0
  33. package/dist/src/crud/fields/FileField.d.ts.map +1 -0
  34. package/dist/src/crud/fields/ImageField.d.ts +14 -0
  35. package/dist/src/crud/fields/ImageField.d.ts.map +1 -0
  36. package/dist/src/crud/fields/ReferenceField.d.ts +12 -2
  37. package/dist/src/crud/fields/ReferenceField.d.ts.map +1 -1
  38. package/dist/src/crud/fields/ReferenceInputActions.d.ts +16 -0
  39. package/dist/src/crud/fields/ReferenceInputActions.d.ts.map +1 -0
  40. package/dist/src/crud/fields/ReferenceManyField.d.ts +10 -1
  41. package/dist/src/crud/fields/ReferenceManyField.d.ts.map +1 -1
  42. package/dist/src/crud/fields/uploadFieldUtils.d.ts +5 -0
  43. package/dist/src/crud/fields/uploadFieldUtils.d.ts.map +1 -0
  44. package/dist/src/crud/fields/useUploadPreviewUrl.d.ts +4 -0
  45. package/dist/src/crud/fields/useUploadPreviewUrl.d.ts.map +1 -0
  46. package/dist/src/crud/filters/ReferenceFilter.d.ts +1 -1
  47. package/dist/src/crud/filters/ReferenceFilter.d.ts.map +1 -1
  48. package/dist/src/crud/index.d.ts +27 -9
  49. package/dist/src/crud/index.d.ts.map +1 -1
  50. package/dist/src/crud/types.d.ts +21 -7
  51. package/dist/src/crud/types.d.ts.map +1 -1
  52. package/dist/src/crud/utils/buildFormPayload.d.ts +6 -0
  53. package/dist/src/crud/utils/buildFormPayload.d.ts.map +1 -0
  54. package/dist/src/crud/utils/buildInlineRowsPayload.d.ts +6 -0
  55. package/dist/src/crud/utils/buildInlineRowsPayload.d.ts.map +1 -0
  56. package/dist/src/crud/utils/buildResourceFormSubmitBody.d.ts +5 -0
  57. package/dist/src/crud/utils/buildResourceFormSubmitBody.d.ts.map +1 -0
  58. package/dist/src/crud/utils/choiceSelectionUtils.d.ts +10 -0
  59. package/dist/src/crud/utils/choiceSelectionUtils.d.ts.map +1 -0
  60. package/dist/src/crud/utils/choiceSelectionUtils.test.d.ts +2 -0
  61. package/dist/src/crud/utils/choiceSelectionUtils.test.d.ts.map +1 -0
  62. package/dist/src/crud/utils/formErrors.d.ts +18 -7
  63. package/dist/src/crud/utils/formErrors.d.ts.map +1 -1
  64. package/dist/src/crud/utils/formErrors.test.d.ts +2 -0
  65. package/dist/src/crud/utils/formErrors.test.d.ts.map +1 -0
  66. package/dist/src/crud/utils/getFormValue.d.ts +3 -0
  67. package/dist/src/crud/utils/getFormValue.d.ts.map +1 -0
  68. package/dist/src/crud/utils/hasUploadValues.d.ts +3 -0
  69. package/dist/src/crud/utils/hasUploadValues.d.ts.map +1 -0
  70. package/dist/src/crud/utils/nestedFieldPath.d.ts +3 -0
  71. package/dist/src/crud/utils/nestedFieldPath.d.ts.map +1 -0
  72. package/dist/src/crud/utils/prepareFormSubmitBody.d.ts +8 -0
  73. package/dist/src/crud/utils/prepareFormSubmitBody.d.ts.map +1 -0
  74. package/dist/src/crud/utils/referenceSelectNotFoundContent.d.ts +4 -0
  75. package/dist/src/crud/utils/referenceSelectNotFoundContent.d.ts.map +1 -0
  76. package/dist/src/crud/utils/setFormValue.d.ts +3 -0
  77. package/dist/src/crud/utils/setFormValue.d.ts.map +1 -0
  78. package/dist/src/crud/utils/toFormData.d.ts +13 -0
  79. package/dist/src/crud/utils/toFormData.d.ts.map +1 -0
  80. package/dist/src/crud/utils/uploadReferenceUtils.d.ts +5 -0
  81. package/dist/src/crud/utils/uploadReferenceUtils.d.ts.map +1 -0
  82. package/dist/src/crud/utils/useChoices.d.ts +27 -1
  83. package/dist/src/crud/utils/useChoices.d.ts.map +1 -1
  84. package/dist/src/crud/utils/useFormRecord.d.ts +44 -0
  85. package/dist/src/crud/utils/useFormRecord.d.ts.map +1 -0
  86. package/dist/src/data/createRestResourceHandlers.d.ts +5 -5
  87. package/dist/src/data/createRestResourceHandlers.d.ts.map +1 -1
  88. package/dist/src/data/dataProviderTypes.d.ts +6 -5
  89. package/dist/src/data/dataProviderTypes.d.ts.map +1 -1
  90. package/dist/src/data/parseFormErrorHelpers.d.ts +23 -6
  91. package/dist/src/data/parseFormErrorHelpers.d.ts.map +1 -1
  92. package/dist/src/data/resourceHandlers.d.ts +1 -1
  93. package/dist/src/data/resourceHandlers.d.ts.map +1 -1
  94. package/dist/src/index.d.ts +4 -4
  95. package/dist/src/index.d.ts.map +1 -1
  96. package/dist/src/layouts/AdminLayout.d.ts +1 -1
  97. package/dist/src/layouts/AdminLayout.d.ts.map +1 -1
  98. package/dist/src/layouts/AuthPageLayout.d.ts.map +1 -1
  99. package/dist/src/layouts/navFilter.d.ts +5 -0
  100. package/dist/src/layouts/navFilter.d.ts.map +1 -0
  101. package/dist/src/layouts/navMenuItems.d.ts +6 -0
  102. package/dist/src/layouts/navMenuItems.d.ts.map +1 -0
  103. package/dist/src/types.d.ts +12 -0
  104. package/dist/src/types.d.ts.map +1 -1
  105. package/package.json +79 -59
  106. package/src/app/AdminApp.tsx +34 -34
  107. package/src/components/AuthAlternateLink.tsx +23 -23
  108. package/src/components/DensitySwitch.tsx +31 -31
  109. package/src/components/NavMenuLabel.tsx +26 -0
  110. package/src/components/NavMenuSearch.tsx +76 -0
  111. package/src/components/ScrollableArea.tsx +46 -0
  112. package/src/components/ThemeSwitch.tsx +28 -28
  113. package/src/components/ThemeToolbar.tsx +34 -34
  114. package/src/components/index.ts +7 -4
  115. package/src/components/navMenu.css +21 -0
  116. package/src/components/scrollable.css +28 -0
  117. package/src/context/AppThemeProvider.tsx +128 -128
  118. package/src/context/AuthProvider.tsx +89 -77
  119. package/src/context/DataProvider.tsx +30 -30
  120. package/src/context/PermissionsProvider.tsx +57 -57
  121. package/src/crud/FilterBar.tsx +36 -36
  122. package/src/crud/FormGlobalErrorsAlert.tsx +36 -0
  123. package/src/crud/FormSteps.tsx +135 -135
  124. package/src/crud/FormTabs.tsx +126 -126
  125. package/src/crud/InlineFormSet.tsx +162 -219
  126. package/src/crud/ListActionsBar.tsx +106 -106
  127. package/src/crud/ResourceForm.tsx +83 -166
  128. package/src/crud/ResourceFormModal.tsx +75 -133
  129. package/src/crud/ResourceList.tsx +1 -0
  130. package/src/crud/ResourceRecordForm.tsx +166 -0
  131. package/src/crud/columns/BooleanColumn.tsx +32 -32
  132. package/src/crud/columns/CustomColumn.tsx +33 -33
  133. package/src/crud/columns/DateColumn.tsx +28 -28
  134. package/src/crud/columns/ImageColumn.tsx +58 -0
  135. package/src/crud/columns/NumberColumn.tsx +31 -31
  136. package/src/crud/columns/ReferenceColumn.tsx +85 -85
  137. package/src/crud/columns/ReferenceManyColumn.tsx +67 -67
  138. package/src/crud/columns/TextColumn.tsx +38 -38
  139. package/src/crud/context/FilterContext.tsx +71 -71
  140. package/src/crud/context/FormContext.tsx +39 -39
  141. package/src/crud/context/FormSectionContext.tsx +22 -22
  142. package/src/crud/context/InlineFieldsRegistry.tsx +61 -0
  143. package/src/crud/context/ListContext.tsx +93 -93
  144. package/src/crud/context/PayloadFieldsContext.tsx +62 -0
  145. package/src/crud/fields/BooleanField.tsx +38 -38
  146. package/src/crud/fields/DateField.tsx +53 -53
  147. package/src/crud/fields/FieldWrapper.tsx +87 -87
  148. package/src/crud/fields/FileField.tsx +123 -0
  149. package/src/crud/fields/ImageField.tsx +120 -0
  150. package/src/crud/fields/NumberField.tsx +52 -52
  151. package/src/crud/fields/PasswordField.tsx +99 -99
  152. package/src/crud/fields/ReferenceField.tsx +237 -96
  153. package/src/crud/fields/ReferenceInputActions.tsx +106 -0
  154. package/src/crud/fields/ReferenceManyField.tsx +200 -76
  155. package/src/crud/fields/SelectField.tsx +48 -48
  156. package/src/crud/fields/TextField.tsx +46 -46
  157. package/src/crud/fields/uploadFieldUtils.ts +21 -0
  158. package/src/crud/fields/useUploadPreviewUrl.ts +20 -0
  159. package/src/crud/filters/BooleanFilter.tsx +38 -38
  160. package/src/crud/filters/DateFilter.tsx +35 -35
  161. package/src/crud/filters/NumberFilter.tsx +33 -33
  162. package/src/crud/filters/ReferenceFilter.tsx +192 -173
  163. package/src/crud/filters/SelectFilter.tsx +44 -44
  164. package/src/crud/filters/TextFilter.tsx +36 -36
  165. package/src/crud/index.ts +99 -90
  166. package/src/crud/types.ts +146 -132
  167. package/src/crud/utils/buildFormPayload.ts +24 -0
  168. package/src/crud/utils/buildInlineRowsPayload.ts +37 -0
  169. package/src/crud/utils/buildResourceFormSubmitBody.ts +29 -0
  170. package/src/crud/utils/choiceSelectionUtils.test.ts +45 -0
  171. package/src/crud/utils/choiceSelectionUtils.ts +116 -0
  172. package/src/crud/utils/formErrors.test.ts +168 -0
  173. package/src/crud/utils/formErrors.ts +138 -38
  174. package/src/crud/utils/formSectionErrors.ts +85 -85
  175. package/src/crud/utils/{getByPath.ts → getFormValue.ts} +13 -13
  176. package/src/crud/utils/hasUploadValues.ts +9 -0
  177. package/src/crud/utils/nestedFieldPath.ts +8 -0
  178. package/src/crud/utils/prepareFormSubmitBody.ts +22 -0
  179. package/src/crud/utils/referenceSelectNotFoundContent.tsx +7 -0
  180. package/src/crud/utils/{setByPath.ts → setFormValue.ts} +18 -18
  181. package/src/crud/utils/sortQueryParam.ts +37 -37
  182. package/src/crud/utils/toFormData.ts +79 -0
  183. package/src/crud/utils/uploadReferenceUtils.ts +44 -0
  184. package/src/crud/utils/useAbortableEffect.ts +17 -17
  185. package/src/crud/utils/useChoices.ts +330 -182
  186. package/src/crud/utils/useFormRecord.ts +179 -0
  187. package/src/crud/utils/useListQueryState.ts +191 -191
  188. package/src/data/abortError.test.ts +19 -19
  189. package/src/data/abortError.ts +10 -10
  190. package/src/data/createMemoryResourceHandlers.ts +78 -78
  191. package/src/data/createRestResourceHandlers.ts +63 -57
  192. package/src/data/dataProviderTypes.ts +7 -5
  193. package/src/data/dataUtils.test.ts +228 -108
  194. package/src/data/inMemoryList.ts +97 -97
  195. package/src/data/parseFormErrorHelpers.test.ts +201 -84
  196. package/src/data/parseFormErrorHelpers.ts +376 -224
  197. package/src/data/resourceHandlers.ts +1 -1
  198. package/src/data/sortHelpers.ts +48 -48
  199. package/src/index.ts +211 -195
  200. package/src/layouts/AdminLayout.tsx +530 -381
  201. package/src/layouts/AuthPageLayout.tsx +87 -81
  202. package/src/layouts/navFilter.ts +49 -0
  203. package/src/layouts/navMenuItems.tsx +44 -0
  204. package/src/pages/LoginPage.tsx +80 -80
  205. package/src/pages/PlaceholderPage.tsx +9 -9
  206. package/src/permissions/resourcePermissions.ts +47 -47
  207. package/src/router/createAdminRouter.tsx +64 -64
  208. package/src/router/guards.tsx +63 -63
  209. package/src/router/routeAccess.ts +89 -89
  210. package/src/types.ts +10 -0
  211. package/src/vite-env.d.ts +1 -1
  212. package/dist/src/crud/context/SubmitFieldsContext.d.ts +0 -18
  213. package/dist/src/crud/context/SubmitFieldsContext.d.ts.map +0 -1
  214. package/dist/src/crud/utils/getByPath.d.ts +0 -3
  215. package/dist/src/crud/utils/getByPath.d.ts.map +0 -1
  216. package/dist/src/crud/utils/inlineArrayName.d.ts +0 -3
  217. package/dist/src/crud/utils/inlineArrayName.d.ts.map +0 -1
  218. package/dist/src/crud/utils/inlineFieldName.d.ts +0 -3
  219. package/dist/src/crud/utils/inlineFieldName.d.ts.map +0 -1
  220. package/dist/src/crud/utils/pickBySources.d.ts +0 -6
  221. package/dist/src/crud/utils/pickBySources.d.ts.map +0 -1
  222. package/dist/src/crud/utils/setByPath.d.ts +0 -3
  223. package/dist/src/crud/utils/setByPath.d.ts.map +0 -1
  224. package/dist/src/crud/utils/useResourceFormData.d.ts +0 -47
  225. package/dist/src/crud/utils/useResourceFormData.d.ts.map +0 -1
  226. package/src/crud/context/SubmitFieldsContext.tsx +0 -62
  227. package/src/crud/utils/inlineArrayName.ts +0 -4
  228. package/src/crud/utils/inlineFieldName.ts +0 -8
  229. package/src/crud/utils/pickBySources.ts +0 -24
  230. package/src/crud/utils/useResourceFormData.ts +0 -231
package/src/crud/index.ts CHANGED
@@ -1,90 +1,99 @@
1
- export { ResourceList, useResourceListContext } from "./ResourceList";
2
- export type { ResourceListProps } from "./ResourceList";
3
- export { FilterBar } from "./FilterBar";
4
- export { ResourceForm } from "./ResourceForm";
5
- export type {
6
- ResourceFormProps,
7
- ResourceFormInlineConfig,
8
- } from "./ResourceForm";
9
- export { ResourceFormModal } from "./ResourceFormModal";
10
- export type { ResourceFormModalProps } from "./ResourceFormModal";
11
- export {
12
- InlineFormSet,
13
- InlineFormSetStacked,
14
- saveInlineRows,
15
- loadInlineRows,
16
- } from "./InlineFormSet";
17
- export type {
18
- InlineFormSetProps,
19
- InlineFormSetStackedProps,
20
- SaveInlineOptions,
21
- InlineFormSetLayout,
22
- } from "./InlineFormSet";
23
- export { FormTabs, FormTab } from "./FormTabs";
24
- export type { FormTabsProps, FormTabProps } from "./FormTabs";
25
- export { FormSteps, FormStep } from "./FormSteps";
26
- export type { FormStepsProps, FormStepProps } from "./FormSteps";
27
-
28
- export { TextField } from "./fields/TextField";
29
- export { NumberField } from "./fields/NumberField";
30
- export { BooleanField } from "./fields/BooleanField";
31
- export { DateField } from "./fields/DateField";
32
- export { SelectField } from "./fields/SelectField";
33
- export { PasswordField } from "./fields/PasswordField";
34
- export { ReferenceField } from "./fields/ReferenceField";
35
- export { ReferenceManyField } from "./fields/ReferenceManyField";
36
- export { FieldWrapper } from "./fields/FieldWrapper";
37
- export type { FieldWrapperProps } from "./fields/FieldWrapper";
38
-
39
- export { TextColumn } from "./columns/TextColumn";
40
- export { NumberColumn } from "./columns/NumberColumn";
41
- export { BooleanColumn } from "./columns/BooleanColumn";
42
- export { DateColumn } from "./columns/DateColumn";
43
- export { ReferenceColumn } from "./columns/ReferenceColumn";
44
- export { ReferenceManyColumn } from "./columns/ReferenceManyColumn";
45
- export { CustomColumn } from "./columns/CustomColumn";
46
-
47
- export { TextFilter } from "./filters/TextFilter";
48
- export { NumberFilter } from "./filters/NumberFilter";
49
- export { BooleanFilter } from "./filters/BooleanFilter";
50
- export { DateFilter } from "./filters/DateFilter";
51
- export { SelectFilter } from "./filters/SelectFilter";
52
- export {
53
- ReferenceFilter,
54
- ReferenceManyFilter,
55
- } from "./filters/ReferenceFilter";
56
-
57
- export { useListQueryState } from "./utils/useListQueryState";
58
- export { useAbortableEffect } from "./utils/useAbortableEffect";
59
- export type {
60
- ListQueryState,
61
- ListQueryActions,
62
- } from "./utils/useListQueryState";
63
- export { useChoices } from "./utils/useChoices";
64
- export { getByPath } from "./utils/getByPath";
65
- export { pickBySources } from "./utils/pickBySources";
66
- export { inlineArrayName } from "./utils/inlineArrayName";
67
- export { inlineFieldName } from "./utils/inlineFieldName";
68
- export { setByPath } from "./utils/setByPath";
69
- export {
70
- useSubmitField,
71
- useSectionField,
72
- } from "./context/SubmitFieldsContext";
73
-
74
- export type {
75
- BaseSourceProps,
76
- ChoiceOption,
77
- ChoicesLoader,
78
- ReferenceProps,
79
- DisplayProps,
80
- EditMode,
81
- FieldRules,
82
- InlineCellContext,
83
- InlineColumnDef,
84
- InlineFormSetBaseProps,
85
- InlineRowContext,
86
- ResourceListBuiltInActions,
87
- ResourceListBulkAction,
88
- ResourceListBulkActionHelpers,
89
- ResourceListRowActionsHelpers,
90
- } from "./types";
1
+ export { ResourceList, useResourceListContext } from "./ResourceList";
2
+ export type { ResourceListProps } from "./ResourceList";
3
+ export { FilterBar } from "./FilterBar";
4
+ export { ResourceForm } from "./ResourceForm";
5
+ export type { ResourceFormProps } from "./ResourceForm";
6
+ export { ResourceFormModal } from "./ResourceFormModal";
7
+ export type { ResourceFormModalProps } from "./ResourceFormModal";
8
+ export { InlineFormSet, InlineFormSetStacked } from "./InlineFormSet";
9
+ export type {
10
+ InlineFormSetProps,
11
+ InlineFormSetStackedProps,
12
+ InlineFormSetLayout,
13
+ } from "./InlineFormSet";
14
+ export { FormTabs, FormTab } from "./FormTabs";
15
+ export type { FormTabsProps, FormTabProps } from "./FormTabs";
16
+ export { FormSteps, FormStep } from "./FormSteps";
17
+ export type { FormStepsProps, FormStepProps } from "./FormSteps";
18
+
19
+ export { TextField } from "./fields/TextField";
20
+ export { NumberField } from "./fields/NumberField";
21
+ export { BooleanField } from "./fields/BooleanField";
22
+ export { DateField } from "./fields/DateField";
23
+ export { SelectField } from "./fields/SelectField";
24
+ export { PasswordField } from "./fields/PasswordField";
25
+ export { ReferenceField } from "./fields/ReferenceField";
26
+ export type { ReferenceFieldProps } from "./fields/ReferenceField";
27
+ export { ReferenceManyField } from "./fields/ReferenceManyField";
28
+ export type { ReferenceManyFieldProps } from "./fields/ReferenceManyField";
29
+ export { ReferenceInputActions } from "./fields/ReferenceInputActions";
30
+ export type { ReferenceInputActionsProps } from "./fields/ReferenceInputActions";
31
+ export { ImageField } from "./fields/ImageField";
32
+ export { FileField } from "./fields/FileField";
33
+ export { FieldWrapper } from "./fields/FieldWrapper";
34
+ export type { FieldWrapperProps } from "./fields/FieldWrapper";
35
+ export type { ImageFieldProps } from "./fields/ImageField";
36
+ export type { FileFieldProps } from "./fields/FileField";
37
+ export type { UploadFieldValue } from "./fields/uploadFieldUtils";
38
+
39
+ export { TextColumn } from "./columns/TextColumn";
40
+ export { NumberColumn } from "./columns/NumberColumn";
41
+ export { BooleanColumn } from "./columns/BooleanColumn";
42
+ export { DateColumn } from "./columns/DateColumn";
43
+ export { ReferenceColumn } from "./columns/ReferenceColumn";
44
+ export { ReferenceManyColumn } from "./columns/ReferenceManyColumn";
45
+ export { ImageColumn } from "./columns/ImageColumn";
46
+ export { CustomColumn } from "./columns/CustomColumn";
47
+
48
+ export { TextFilter } from "./filters/TextFilter";
49
+ export { NumberFilter } from "./filters/NumberFilter";
50
+ export { BooleanFilter } from "./filters/BooleanFilter";
51
+ export { DateFilter } from "./filters/DateFilter";
52
+ export { SelectFilter } from "./filters/SelectFilter";
53
+ export {
54
+ ReferenceFilter,
55
+ ReferenceManyFilter,
56
+ } from "./filters/ReferenceFilter";
57
+
58
+ export { useListQueryState } from "./utils/useListQueryState";
59
+ export { useAbortableEffect } from "./utils/useAbortableEffect";
60
+ export type {
61
+ ListQueryState,
62
+ ListQueryActions,
63
+ } from "./utils/useListQueryState";
64
+ export { useChoices } from "./utils/useChoices";
65
+ export type { UseChoicesOptions } from "./utils/useChoices";
66
+ export { getFormValue } from "./utils/getFormValue";
67
+ export { setFormValue } from "./utils/setFormValue";
68
+ export { buildFormPayload } from "./utils/buildFormPayload";
69
+ export { buildInlineRowsPayload } from "./utils/buildInlineRowsPayload";
70
+ export { buildResourceFormSubmitBody } from "./utils/buildResourceFormSubmitBody";
71
+ export { prepareFormSubmitBody } from "./utils/prepareFormSubmitBody";
72
+ export { toFormData } from "./utils/toFormData";
73
+ export { hasUploadValues } from "./utils/hasUploadValues";
74
+ export type { ToFormDataOptions } from "./utils/toFormData";
75
+ export type { PrepareFormSubmitBodyOptions } from "./utils/prepareFormSubmitBody";
76
+ export { nestedFieldPath } from "./utils/nestedFieldPath";
77
+ export {
78
+ useRegisterPayloadField,
79
+ useRegisterSectionField,
80
+ } from "./context/PayloadFieldsContext";
81
+ export type { InlineFieldRegistration } from "./context/InlineFieldsRegistry";
82
+
83
+ export type {
84
+ BaseSourceProps,
85
+ ChoiceOption,
86
+ ChoicesLoader,
87
+ ReferenceProps,
88
+ DisplayProps,
89
+ EditMode,
90
+ FieldRules,
91
+ InlineCellContext,
92
+ InlineColumnDef,
93
+ InlineFormSetBaseProps,
94
+ InlineRowContext,
95
+ ResourceListBuiltInActions,
96
+ ResourceListBulkAction,
97
+ ResourceListBulkActionHelpers,
98
+ ResourceListRowActionsHelpers,
99
+ } from "./types";
package/src/crud/types.ts CHANGED
@@ -1,132 +1,146 @@
1
- import type { ReactNode } from "react";
2
- import type { ColumnsType } from "antd/es/table";
3
- import type { DataProvider } from "../data/dataProviderTypes";
4
- import type { RegisterOptions } from "react-hook-form";
5
-
6
- export type BaseSourceProps = {
7
- source: string;
8
- label?: string;
9
- };
10
-
11
- export type ChoiceOption = {
12
- label: string;
13
- value: unknown;
14
- /** Full record when loaded from a reference resource (for dependent fields). */
15
- record?: Record<string, unknown>;
16
- };
17
-
18
- export type ChoicesContext = {
19
- dataProvider: DataProvider;
20
- search?: string;
21
- };
22
-
23
- export type ChoicesLoader =
24
- | { resource: string; filter?: Record<string, unknown> }
25
- | ChoiceOption[]
26
- | ((ctx: ChoicesContext) => Promise<ChoiceOption[]>);
27
-
28
- export type ReferenceProps = {
29
- reference?: string;
30
- choices?: ChoicesLoader;
31
- optionLabel?: string | ((record: Record<string, unknown>) => string);
32
- optionValue?: string;
33
- };
34
-
35
- export type DisplayProps = {
36
- display?: string | ((record: Record<string, unknown>) => ReactNode);
37
- };
38
-
39
- export type FieldRules = RegisterOptions;
40
-
41
- export type ColumnDefinition<T extends Record<string, unknown>> = {
42
- key: string;
43
- source: string;
44
- label?: string;
45
- sortable?: boolean;
46
- buildColumn: () => ColumnsType<T>[number];
47
- };
48
-
49
- export type FilterDefinition = {
50
- key: string;
51
- source: string;
52
- label?: string;
53
- render: (props: {
54
- value: unknown;
55
- onChange: (value: unknown) => void;
56
- }) => ReactNode;
57
- };
58
-
59
- export type InlineFormSetBaseProps = {
60
- resource: string;
61
- foreignKey: string;
62
- label?: string;
63
- name?: string;
64
- };
65
-
66
- /** Passed to each tabular inline column's `cell` renderer. */
67
- export type InlineCellContext = {
68
- /** Full RHF path, e.g. `__inline_invoice_lines.0.label`. */
69
- name: string;
70
- index: number;
71
- arrayName: string;
72
- };
73
-
74
- export type InlineColumnDef = {
75
- source: string;
76
- label?: string;
77
- width?: number | string;
78
- minWidth?: number | string;
79
- cell: (ctx: InlineCellContext) => ReactNode;
80
- };
81
-
82
- /** Passed to `InlineFormSetStacked`'s `renderRow` for one related row. */
83
- export type InlineRowContext = {
84
- arrayName: string;
85
- index: number;
86
- /** RHF path helper — `name("label")` → `arrayName.index.label`. */
87
- name: (source: string) => string;
88
- };
89
-
90
- export type EditMode = "page" | "modal" | "both";
91
-
92
- /** Toggle built-in row actions. Omitted keys default to `true` (still gated by permissions). */
93
- export type ResourceListBuiltInActions = {
94
- edit?: boolean;
95
- quickEdit?: boolean;
96
- delete?: boolean;
97
- };
98
-
99
- export type ResourceListRowActionsHelpers = {
100
- reload: () => void;
101
- openEditModal: (id: string | number) => void;
102
- };
103
-
104
- export type ResourceListBulkActionHelpers = {
105
- reload: () => void;
106
- clearSelection: () => void;
107
- };
108
-
109
- /** Bulk list action (Django admin–style). Runs on selected row ids. */
110
- export type ResourceListBulkAction = {
111
- key: string;
112
- label: string;
113
- /** Optional confirmation message. Return false to cancel. */
114
- confirm?:
115
- | string
116
- | ((
117
- selectedIds: (string | number)[],
118
- helpers: ResourceListBulkActionHelpers,
119
- ) => string | false | Promise<string | false>);
120
- execute: (
121
- selectedIds: (string | number)[],
122
- helpers: ResourceListBulkActionHelpers,
123
- ) => void | Promise<void>;
124
- };
125
-
126
- export const LIST_QUERY_RESERVED = new Set([
127
- "page",
128
- "perPage",
129
- "sort",
130
- "create",
131
- "edit",
132
- ]);
1
+ import type { ReactNode } from "react";
2
+ import type { ColumnsType } from "antd/es/table";
3
+ import type { DataProvider } from "../data/dataProviderTypes";
4
+ import type { RegisterOptions } from "react-hook-form";
5
+
6
+ export type BaseSourceProps = {
7
+ source: string;
8
+ label?: string;
9
+ };
10
+
11
+ export type ChoiceOption = {
12
+ label: string;
13
+ value: unknown;
14
+ /** Full record when loaded from a reference resource (for dependent fields). */
15
+ record?: Record<string, unknown>;
16
+ };
17
+
18
+ export type ChoicesContext = {
19
+ dataProvider: DataProvider;
20
+ search?: string;
21
+ };
22
+
23
+ export type ChoicesLoader =
24
+ | { resource: string; filter?: Record<string, unknown> }
25
+ | ChoiceOption[]
26
+ | ((ctx: ChoicesContext) => Promise<ChoiceOption[]>);
27
+
28
+ export type ReferenceProps = {
29
+ reference?: string;
30
+ choices?: ChoicesLoader;
31
+ optionLabel?: string | ((record: Record<string, unknown>) => string);
32
+ optionValue?: string;
33
+ /** When true (default), options load on dropdown open / search instead of on mount. */
34
+ lazy?: boolean;
35
+ /**
36
+ * Key on the loaded form record with the related object or array of objects.
37
+ * Use when retrieve embeds relations, e.g. `source="branch_id"` + `recordSource="branch"`.
38
+ */
39
+ recordSource?: string;
40
+ /**
41
+ * When true (default), fetch labels for primitive ids via `getOne` if they are not
42
+ * already embedded in the form record. Set `false` to never call `getOne`.
43
+ */
44
+ fetchSelected?: boolean;
45
+ };
46
+
47
+ export type DisplayProps = {
48
+ display?: string | ((record: Record<string, unknown>) => ReactNode);
49
+ };
50
+
51
+ export type FieldRules = RegisterOptions;
52
+
53
+ export type ColumnDefinition<T extends Record<string, unknown>> = {
54
+ key: string;
55
+ source: string;
56
+ label?: string;
57
+ sortable?: boolean;
58
+ buildColumn: () => ColumnsType<T>[number];
59
+ };
60
+
61
+ export type FilterDefinition = {
62
+ key: string;
63
+ source: string;
64
+ label?: string;
65
+ render: (props: {
66
+ value: unknown;
67
+ onChange: (value: unknown) => void;
68
+ }) => ReactNode;
69
+ };
70
+
71
+ export type InlineFormSetBaseProps = {
72
+ /** RHF `useFieldArray` name and default API nested key, e.g. `"lines"`. */
73
+ field: string;
74
+ label?: string;
75
+ /** API key when different from `field`. */
76
+ payloadKey?: string;
77
+ transformRows?: (rows: Record<string, unknown>[]) => unknown;
78
+ };
79
+
80
+ /** Passed to each tabular inline column's `cell` renderer. */
81
+ export type InlineCellContext = {
82
+ /** Full RHF path, e.g. `lines.0.label`. */
83
+ name: string;
84
+ index: number;
85
+ field: string;
86
+ };
87
+
88
+ export type InlineColumnDef = {
89
+ source: string;
90
+ label?: string;
91
+ width?: number | string;
92
+ minWidth?: number | string;
93
+ cell: (ctx: InlineCellContext) => ReactNode;
94
+ };
95
+
96
+ /** Passed to `InlineFormSetStacked`'s `renderRow` for one related row. */
97
+ export type InlineRowContext = {
98
+ field: string;
99
+ index: number;
100
+ /** RHF path helper — `name("label")` `field.index.label`. */
101
+ name: (source: string) => string;
102
+ };
103
+
104
+ export type EditMode = "page" | "modal" | "both";
105
+
106
+ /** Toggle built-in row actions. Omitted keys default to `true` (still gated by permissions). */
107
+ export type ResourceListBuiltInActions = {
108
+ edit?: boolean;
109
+ quickEdit?: boolean;
110
+ delete?: boolean;
111
+ };
112
+
113
+ export type ResourceListRowActionsHelpers = {
114
+ reload: () => void;
115
+ openEditModal: (id: string | number) => void;
116
+ };
117
+
118
+ export type ResourceListBulkActionHelpers = {
119
+ reload: () => void;
120
+ clearSelection: () => void;
121
+ };
122
+
123
+ /** Bulk list action (Django admin–style). Runs on selected row ids. */
124
+ export type ResourceListBulkAction = {
125
+ key: string;
126
+ label: string;
127
+ /** Optional confirmation message. Return false to cancel. */
128
+ confirm?:
129
+ | string
130
+ | ((
131
+ selectedIds: (string | number)[],
132
+ helpers: ResourceListBulkActionHelpers,
133
+ ) => string | false | Promise<string | false>);
134
+ execute: (
135
+ selectedIds: (string | number)[],
136
+ helpers: ResourceListBulkActionHelpers,
137
+ ) => void | Promise<void>;
138
+ };
139
+
140
+ export const LIST_QUERY_RESERVED = new Set([
141
+ "page",
142
+ "perPage",
143
+ "sort",
144
+ "create",
145
+ "edit",
146
+ ]);
@@ -0,0 +1,24 @@
1
+ import { getFormValue } from "./getFormValue";
2
+ import { setFormValue } from "./setFormValue";
3
+
4
+ /**
5
+ * Build the API save body from form values using registered field paths.
6
+ * Flat `email` → `{ email }`; nested `address.city` → `{ address: { city } }`.
7
+ */
8
+ export function buildFormPayload(
9
+ values: Record<string, unknown>,
10
+ fieldPaths: string[],
11
+ ): Record<string, unknown> {
12
+ if (fieldPaths.length === 0) {
13
+ return { ...values };
14
+ }
15
+
16
+ const result: Record<string, unknown> = {};
17
+ for (const path of fieldPaths) {
18
+ const value = getFormValue(values, path);
19
+ if (value !== undefined) {
20
+ setFormValue(result, path, value);
21
+ }
22
+ }
23
+ return result;
24
+ }
@@ -0,0 +1,37 @@
1
+ export type BuildInlineRowsPayloadOptions = {
2
+ transformRows?: (rows: Record<string, unknown>[]) => unknown;
3
+ };
4
+
5
+ /** Clean inline field-array rows for the API (strip RHF `rowKey`, keep record `id`). */
6
+ export function buildInlineRowsPayload(
7
+ rows: unknown,
8
+ sources: string[],
9
+ options?: BuildInlineRowsPayloadOptions,
10
+ ): unknown {
11
+ if (!Array.isArray(rows)) return [];
12
+
13
+ const cleaned = rows.map((row) => {
14
+ if (!row || typeof row !== "object") return {};
15
+ const record = row as Record<string, unknown>;
16
+ const out: Record<string, unknown> = {};
17
+
18
+ for (const source of sources) {
19
+ const value = record[source];
20
+ if (value !== undefined) {
21
+ out[source] = value;
22
+ }
23
+ }
24
+
25
+ const id = record.id;
26
+ if (id !== undefined && id !== null) {
27
+ out.id = id;
28
+ }
29
+
30
+ return out;
31
+ });
32
+
33
+ if (options?.transformRows) {
34
+ return options.transformRows(cleaned);
35
+ }
36
+ return cleaned;
37
+ }
@@ -0,0 +1,29 @@
1
+ import type { InlineFieldRegistration } from "../context/InlineFieldsRegistry";
2
+ import { buildFormPayload } from "./buildFormPayload";
3
+ import { buildInlineRowsPayload } from "./buildInlineRowsPayload";
4
+ import {
5
+ prepareFormSubmitBody,
6
+ type PrepareFormSubmitBodyOptions,
7
+ } from "./prepareFormSubmitBody";
8
+
9
+ /** Build the create/update body from form values, auto-switching to multipart when needed. */
10
+ export function buildResourceFormSubmitBody(
11
+ raw: Record<string, unknown>,
12
+ payloadFieldPaths: string[],
13
+ inlineRegistry?: Iterable<InlineFieldRegistration>,
14
+ options?: PrepareFormSubmitBodyOptions,
15
+ ): Record<string, unknown> | FormData {
16
+ const payload = buildFormPayload(raw, payloadFieldPaths);
17
+
18
+ if (inlineRegistry) {
19
+ for (const inline of inlineRegistry) {
20
+ const rows = raw[inline.field];
21
+ const key = inline.payloadKey ?? inline.field;
22
+ payload[key] = buildInlineRowsPayload(rows, inline.sources, {
23
+ transformRows: inline.transformRows,
24
+ });
25
+ }
26
+ }
27
+
28
+ return prepareFormSubmitBody(payload, options);
29
+ }
@@ -0,0 +1,45 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import {
3
+ collectSelectedRecords,
4
+ isRecordObject,
5
+ normalizeSelectedIds,
6
+ recordsToOptions,
7
+ valueAsId,
8
+ valuesAsIds,
9
+ } from "./choiceSelectionUtils";
10
+
11
+ describe("choiceSelectionUtils", () => {
12
+ it("detects nested record objects", () => {
13
+ expect(isRecordObject({ id: 1, name: "Branch 1" }, "id")).toBe(true);
14
+ expect(isRecordObject("1", "id")).toBe(false);
15
+ });
16
+
17
+ it("extracts ids from primitive or nested values", () => {
18
+ expect(valueAsId("abc", "id")).toBe("abc");
19
+ expect(valueAsId({ id: 2, name: "Two" }, "id")).toBe(2);
20
+ expect(valuesAsIds([{ id: 1, name: "One" }, "2"], "id")).toEqual([1, "2"]);
21
+ expect(normalizeSelectedIds([{ id: 3, name: "Three" }], "id")).toEqual([3]);
22
+ });
23
+
24
+ it("collects embedded records from value and recordSource data", () => {
25
+ const records = collectSelectedRecords(
26
+ [{ id: 1, name: "One" }, "2"],
27
+ { id: 3, name: "Three" },
28
+ "id",
29
+ );
30
+ expect(records).toHaveLength(2);
31
+ expect(records.map((record) => record.id).sort()).toEqual([1, 3]);
32
+ });
33
+
34
+ it("maps records to select options", () => {
35
+ expect(
36
+ recordsToOptions([{ id: 1, name: "Branch 1" }], "name", "id"),
37
+ ).toEqual([
38
+ {
39
+ label: "Branch 1",
40
+ value: 1,
41
+ record: { id: 1, name: "Branch 1" },
42
+ },
43
+ ]);
44
+ });
45
+ });