ding-react-admin 2.0.0 → 2.0.5

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 (169) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +254 -195
  3. package/dist/index.css +1 -0
  4. package/dist/index.js +1773 -1170
  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/ResourceForm.d.ts +1 -4
  18. package/dist/src/crud/ResourceForm.d.ts.map +1 -1
  19. package/dist/src/crud/ResourceFormModal.d.ts +7 -1
  20. package/dist/src/crud/ResourceFormModal.d.ts.map +1 -1
  21. package/dist/src/crud/ResourceRecordForm.d.ts +27 -0
  22. package/dist/src/crud/ResourceRecordForm.d.ts.map +1 -0
  23. package/dist/src/crud/fields/ReferenceField.d.ts +12 -2
  24. package/dist/src/crud/fields/ReferenceField.d.ts.map +1 -1
  25. package/dist/src/crud/fields/ReferenceInputActions.d.ts +16 -0
  26. package/dist/src/crud/fields/ReferenceInputActions.d.ts.map +1 -0
  27. package/dist/src/crud/fields/ReferenceManyField.d.ts +10 -1
  28. package/dist/src/crud/fields/ReferenceManyField.d.ts.map +1 -1
  29. package/dist/src/crud/filters/ReferenceFilter.d.ts +1 -1
  30. package/dist/src/crud/filters/ReferenceFilter.d.ts.map +1 -1
  31. package/dist/src/crud/index.d.ts +5 -0
  32. package/dist/src/crud/index.d.ts.map +1 -1
  33. package/dist/src/crud/types.d.ts +12 -0
  34. package/dist/src/crud/types.d.ts.map +1 -1
  35. package/dist/src/crud/utils/choiceSelectionUtils.d.ts +10 -0
  36. package/dist/src/crud/utils/choiceSelectionUtils.d.ts.map +1 -0
  37. package/dist/src/crud/utils/choiceSelectionUtils.test.d.ts +2 -0
  38. package/dist/src/crud/utils/choiceSelectionUtils.test.d.ts.map +1 -0
  39. package/dist/src/crud/utils/formErrors.d.ts +18 -7
  40. package/dist/src/crud/utils/formErrors.d.ts.map +1 -1
  41. package/dist/src/crud/utils/formErrors.test.d.ts +2 -0
  42. package/dist/src/crud/utils/formErrors.test.d.ts.map +1 -0
  43. package/dist/src/crud/utils/prepareFormSubmitBody.d.ts +1 -0
  44. package/dist/src/crud/utils/prepareFormSubmitBody.d.ts.map +1 -1
  45. package/dist/src/crud/utils/referenceSelectNotFoundContent.d.ts +4 -0
  46. package/dist/src/crud/utils/referenceSelectNotFoundContent.d.ts.map +1 -0
  47. package/dist/src/crud/utils/toFormData.d.ts +1 -1
  48. package/dist/src/crud/utils/toFormData.d.ts.map +1 -1
  49. package/dist/src/crud/utils/uploadReferenceUtils.d.ts +5 -0
  50. package/dist/src/crud/utils/uploadReferenceUtils.d.ts.map +1 -0
  51. package/dist/src/crud/utils/useChoices.d.ts +27 -1
  52. package/dist/src/crud/utils/useChoices.d.ts.map +1 -1
  53. package/dist/src/crud/utils/useFormRecord.d.ts +9 -7
  54. package/dist/src/crud/utils/useFormRecord.d.ts.map +1 -1
  55. package/dist/src/data/parseFormErrorHelpers.d.ts +6 -27
  56. package/dist/src/data/parseFormErrorHelpers.d.ts.map +1 -1
  57. package/dist/src/index.d.ts +2 -2
  58. package/dist/src/index.d.ts.map +1 -1
  59. package/dist/src/layouts/AdminLayout.d.ts +1 -1
  60. package/dist/src/layouts/AdminLayout.d.ts.map +1 -1
  61. package/dist/src/layouts/AuthPageLayout.d.ts.map +1 -1
  62. package/dist/src/layouts/navFilter.d.ts +5 -0
  63. package/dist/src/layouts/navFilter.d.ts.map +1 -0
  64. package/dist/src/layouts/navMenuItems.d.ts +6 -0
  65. package/dist/src/layouts/navMenuItems.d.ts.map +1 -0
  66. package/dist/src/types.d.ts +12 -0
  67. package/dist/src/types.d.ts.map +1 -1
  68. package/package.json +85 -59
  69. package/src/app/AdminApp.tsx +34 -34
  70. package/src/components/AuthAlternateLink.tsx +23 -23
  71. package/src/components/DensitySwitch.tsx +31 -31
  72. package/src/components/NavMenuLabel.tsx +26 -0
  73. package/src/components/NavMenuSearch.tsx +76 -0
  74. package/src/components/ScrollableArea.tsx +46 -0
  75. package/src/components/ThemeSwitch.tsx +28 -28
  76. package/src/components/ThemeToolbar.tsx +34 -34
  77. package/src/components/index.ts +7 -4
  78. package/src/components/navMenu.css +21 -0
  79. package/src/components/scrollable.css +28 -0
  80. package/src/context/AppThemeProvider.tsx +128 -128
  81. package/src/context/AuthProvider.tsx +89 -77
  82. package/src/context/DataProvider.tsx +30 -30
  83. package/src/context/PermissionsProvider.tsx +57 -57
  84. package/src/crud/FilterBar.tsx +36 -36
  85. package/src/crud/FormGlobalErrorsAlert.tsx +36 -0
  86. package/src/crud/FormSteps.tsx +135 -135
  87. package/src/crud/FormTabs.tsx +126 -126
  88. package/src/crud/InlineFormSet.tsx +162 -162
  89. package/src/crud/ListActionsBar.tsx +106 -106
  90. package/src/crud/ResourceForm.tsx +83 -160
  91. package/src/crud/ResourceFormModal.tsx +75 -133
  92. package/src/crud/ResourceRecordForm.tsx +166 -0
  93. package/src/crud/columns/BooleanColumn.tsx +32 -32
  94. package/src/crud/columns/CustomColumn.tsx +33 -33
  95. package/src/crud/columns/DateColumn.tsx +28 -28
  96. package/src/crud/columns/ImageColumn.tsx +58 -58
  97. package/src/crud/columns/NumberColumn.tsx +31 -31
  98. package/src/crud/columns/ReferenceColumn.tsx +85 -85
  99. package/src/crud/columns/ReferenceManyColumn.tsx +67 -67
  100. package/src/crud/columns/TextColumn.tsx +38 -38
  101. package/src/crud/context/FilterContext.tsx +71 -71
  102. package/src/crud/context/FormContext.tsx +39 -39
  103. package/src/crud/context/FormSectionContext.tsx +22 -22
  104. package/src/crud/context/InlineFieldsRegistry.tsx +61 -61
  105. package/src/crud/context/ListContext.tsx +93 -93
  106. package/src/crud/fields/BooleanField.tsx +38 -38
  107. package/src/crud/fields/DateField.tsx +53 -53
  108. package/src/crud/fields/FileField.tsx +123 -123
  109. package/src/crud/fields/ImageField.tsx +120 -120
  110. package/src/crud/fields/NumberField.tsx +52 -52
  111. package/src/crud/fields/PasswordField.tsx +99 -99
  112. package/src/crud/fields/ReferenceField.tsx +237 -96
  113. package/src/crud/fields/ReferenceInputActions.tsx +106 -0
  114. package/src/crud/fields/ReferenceManyField.tsx +200 -76
  115. package/src/crud/fields/SelectField.tsx +48 -48
  116. package/src/crud/fields/TextField.tsx +46 -46
  117. package/src/crud/fields/uploadFieldUtils.ts +21 -21
  118. package/src/crud/fields/useUploadPreviewUrl.ts +20 -20
  119. package/src/crud/filters/BooleanFilter.tsx +38 -38
  120. package/src/crud/filters/DateFilter.tsx +35 -35
  121. package/src/crud/filters/NumberFilter.tsx +33 -33
  122. package/src/crud/filters/ReferenceFilter.tsx +192 -173
  123. package/src/crud/filters/SelectFilter.tsx +44 -44
  124. package/src/crud/filters/TextFilter.tsx +36 -36
  125. package/src/crud/index.ts +99 -94
  126. package/src/crud/types.ts +146 -134
  127. package/src/crud/utils/buildFormPayload.ts +24 -24
  128. package/src/crud/utils/buildInlineRowsPayload.ts +37 -37
  129. package/src/crud/utils/buildResourceFormSubmitBody.ts +29 -29
  130. package/src/crud/utils/choiceSelectionUtils.test.ts +45 -0
  131. package/src/crud/utils/choiceSelectionUtils.ts +116 -0
  132. package/src/crud/utils/formErrors.test.ts +168 -0
  133. package/src/crud/utils/formErrors.ts +138 -42
  134. package/src/crud/utils/formSectionErrors.ts +85 -85
  135. package/src/crud/utils/getFormValue.ts +13 -13
  136. package/src/crud/utils/hasUploadValues.ts +9 -9
  137. package/src/crud/utils/nestedFieldPath.ts +8 -8
  138. package/src/crud/utils/prepareFormSubmitBody.ts +22 -17
  139. package/src/crud/utils/referenceSelectNotFoundContent.tsx +7 -0
  140. package/src/crud/utils/setFormValue.ts +18 -18
  141. package/src/crud/utils/sortQueryParam.ts +37 -37
  142. package/src/crud/utils/toFormData.ts +79 -81
  143. package/src/crud/utils/uploadReferenceUtils.ts +44 -0
  144. package/src/crud/utils/useAbortableEffect.ts +17 -17
  145. package/src/crud/utils/useChoices.ts +330 -182
  146. package/src/crud/utils/useFormRecord.ts +179 -156
  147. package/src/crud/utils/useListQueryState.ts +191 -191
  148. package/src/data/abortError.test.ts +19 -19
  149. package/src/data/abortError.ts +10 -10
  150. package/src/data/createMemoryResourceHandlers.ts +78 -78
  151. package/src/data/createRestResourceHandlers.ts +63 -63
  152. package/src/data/dataUtils.test.ts +228 -220
  153. package/src/data/inMemoryList.ts +97 -97
  154. package/src/data/parseFormErrorHelpers.test.ts +201 -138
  155. package/src/data/parseFormErrorHelpers.ts +376 -311
  156. package/src/data/sortHelpers.ts +48 -48
  157. package/src/index.ts +211 -207
  158. package/src/layouts/AdminLayout.tsx +530 -382
  159. package/src/layouts/AuthPageLayout.tsx +87 -81
  160. package/src/layouts/navFilter.ts +49 -0
  161. package/src/layouts/navMenuItems.tsx +44 -0
  162. package/src/pages/LoginPage.tsx +80 -80
  163. package/src/pages/PlaceholderPage.tsx +9 -9
  164. package/src/permissions/resourcePermissions.ts +47 -47
  165. package/src/router/createAdminRouter.tsx +64 -64
  166. package/src/router/guards.tsx +63 -63
  167. package/src/router/routeAccess.ts +89 -89
  168. package/src/types.ts +10 -0
  169. package/src/vite-env.d.ts +1 -1
@@ -1,123 +1,123 @@
1
- import { DeleteOutlined, PaperClipOutlined, UploadOutlined } from "@ant-design/icons";
2
- import { Button, Space, Typography } from "antd";
3
- import { useRef } from "react";
4
- import type { BaseSourceProps, FieldRules } from "../types";
5
- import { FieldWrapper } from "./FieldWrapper";
6
- import {
7
- getUploadFileName,
8
- hasUploadValue,
9
- type UploadFieldValue,
10
- } from "./uploadFieldUtils";
11
-
12
- export type FileFieldProps = BaseSourceProps & {
13
- name?: string;
14
- required?: boolean;
15
- rules?: FieldRules;
16
- hideLabel?: boolean;
17
- /** Allow clearing an existing or newly selected file. */
18
- clearable?: boolean;
19
- accept?: string;
20
- };
21
-
22
- function FileFieldInput({
23
- value,
24
- onChange,
25
- disabled,
26
- clearable,
27
- accept,
28
- }: {
29
- value: UploadFieldValue;
30
- onChange: (value: UploadFieldValue) => void;
31
- disabled?: boolean;
32
- clearable?: boolean;
33
- accept?: string;
34
- }) {
35
- const inputRef = useRef<HTMLInputElement>(null);
36
- const fileName = getUploadFileName(value);
37
- const existingUrl = typeof value === "string" && value.length > 0 ? value : undefined;
38
- const showClear = clearable && hasUploadValue(value);
39
-
40
- return (
41
- <Space direction="vertical" size="middle" style={{ width: "100%" }}>
42
- {fileName ? (
43
- <Space>
44
- <PaperClipOutlined />
45
- {existingUrl ? (
46
- <Typography.Link href={existingUrl} target="_blank" rel="noopener noreferrer">
47
- {fileName}
48
- </Typography.Link>
49
- ) : (
50
- <Typography.Text>{fileName}</Typography.Text>
51
- )}
52
- </Space>
53
- ) : null}
54
- <Space wrap>
55
- <Button
56
- icon={<UploadOutlined />}
57
- disabled={disabled}
58
- onClick={() => inputRef.current?.click()}
59
- >
60
- Choose file
61
- </Button>
62
- {showClear ? (
63
- <Button
64
- icon={<DeleteOutlined />}
65
- disabled={disabled}
66
- onClick={() => {
67
- onChange(null);
68
- if (inputRef.current) inputRef.current.value = "";
69
- }}
70
- >
71
- Clear
72
- </Button>
73
- ) : null}
74
- </Space>
75
- <input
76
- ref={inputRef}
77
- type="file"
78
- accept={accept}
79
- disabled={disabled}
80
- tabIndex={-1}
81
- aria-hidden
82
- style={{ display: "none" }}
83
- onChange={(e) => {
84
- const file = e.target.files?.[0];
85
- onChange(file ?? null);
86
- e.target.value = "";
87
- }}
88
- />
89
- </Space>
90
- );
91
- }
92
-
93
- export function FileField({
94
- source,
95
- name,
96
- label,
97
- required,
98
- rules,
99
- hideLabel,
100
- clearable,
101
- accept,
102
- }: FileFieldProps) {
103
- return (
104
- <FieldWrapper
105
- source={source}
106
- name={name}
107
- label={label}
108
- required={required}
109
- rules={rules}
110
- hideLabel={hideLabel}
111
- >
112
- {({ value, onChange, disabled }) => (
113
- <FileFieldInput
114
- value={value as UploadFieldValue}
115
- onChange={onChange}
116
- disabled={disabled}
117
- clearable={clearable}
118
- accept={accept}
119
- />
120
- )}
121
- </FieldWrapper>
122
- );
123
- }
1
+ import { DeleteOutlined, PaperClipOutlined, UploadOutlined } from "@ant-design/icons";
2
+ import { Button, Space, Typography } from "antd";
3
+ import { useRef } from "react";
4
+ import type { BaseSourceProps, FieldRules } from "../types";
5
+ import { FieldWrapper } from "./FieldWrapper";
6
+ import {
7
+ getUploadFileName,
8
+ hasUploadValue,
9
+ type UploadFieldValue,
10
+ } from "./uploadFieldUtils";
11
+
12
+ export type FileFieldProps = BaseSourceProps & {
13
+ name?: string;
14
+ required?: boolean;
15
+ rules?: FieldRules;
16
+ hideLabel?: boolean;
17
+ /** Allow clearing an existing or newly selected file. */
18
+ clearable?: boolean;
19
+ accept?: string;
20
+ };
21
+
22
+ function FileFieldInput({
23
+ value,
24
+ onChange,
25
+ disabled,
26
+ clearable,
27
+ accept,
28
+ }: {
29
+ value: UploadFieldValue;
30
+ onChange: (value: UploadFieldValue) => void;
31
+ disabled?: boolean;
32
+ clearable?: boolean;
33
+ accept?: string;
34
+ }) {
35
+ const inputRef = useRef<HTMLInputElement>(null);
36
+ const fileName = getUploadFileName(value);
37
+ const existingUrl = typeof value === "string" && value.length > 0 ? value : undefined;
38
+ const showClear = clearable && hasUploadValue(value);
39
+
40
+ return (
41
+ <Space direction="vertical" size="middle" style={{ width: "100%" }}>
42
+ {fileName ? (
43
+ <Space>
44
+ <PaperClipOutlined />
45
+ {existingUrl ? (
46
+ <Typography.Link href={existingUrl} target="_blank" rel="noopener noreferrer">
47
+ {fileName}
48
+ </Typography.Link>
49
+ ) : (
50
+ <Typography.Text>{fileName}</Typography.Text>
51
+ )}
52
+ </Space>
53
+ ) : null}
54
+ <Space wrap>
55
+ <Button
56
+ icon={<UploadOutlined />}
57
+ disabled={disabled}
58
+ onClick={() => inputRef.current?.click()}
59
+ >
60
+ Choose file
61
+ </Button>
62
+ {showClear ? (
63
+ <Button
64
+ icon={<DeleteOutlined />}
65
+ disabled={disabled}
66
+ onClick={() => {
67
+ onChange(null);
68
+ if (inputRef.current) inputRef.current.value = "";
69
+ }}
70
+ >
71
+ Clear
72
+ </Button>
73
+ ) : null}
74
+ </Space>
75
+ <input
76
+ ref={inputRef}
77
+ type="file"
78
+ accept={accept}
79
+ disabled={disabled}
80
+ tabIndex={-1}
81
+ aria-hidden
82
+ style={{ display: "none" }}
83
+ onChange={(e) => {
84
+ const file = e.target.files?.[0];
85
+ onChange(file ?? null);
86
+ e.target.value = "";
87
+ }}
88
+ />
89
+ </Space>
90
+ );
91
+ }
92
+
93
+ export function FileField({
94
+ source,
95
+ name,
96
+ label,
97
+ required,
98
+ rules,
99
+ hideLabel,
100
+ clearable,
101
+ accept,
102
+ }: FileFieldProps) {
103
+ return (
104
+ <FieldWrapper
105
+ source={source}
106
+ name={name}
107
+ label={label}
108
+ required={required}
109
+ rules={rules}
110
+ hideLabel={hideLabel}
111
+ >
112
+ {({ value, onChange, disabled }) => (
113
+ <FileFieldInput
114
+ value={value as UploadFieldValue}
115
+ onChange={onChange}
116
+ disabled={disabled}
117
+ clearable={clearable}
118
+ accept={accept}
119
+ />
120
+ )}
121
+ </FieldWrapper>
122
+ );
123
+ }
@@ -1,120 +1,120 @@
1
- import { DeleteOutlined, UploadOutlined } from "@ant-design/icons";
2
- import { Button, Image, Space } from "antd";
3
- import { useRef } from "react";
4
- import type { BaseSourceProps, FieldRules } from "../types";
5
- import { FieldWrapper } from "./FieldWrapper";
6
- import { hasUploadValue, type UploadFieldValue } from "./uploadFieldUtils";
7
- import { useUploadPreviewUrl } from "./useUploadPreviewUrl";
8
-
9
- export type ImageFieldProps = BaseSourceProps & {
10
- name?: string;
11
- required?: boolean;
12
- rules?: FieldRules;
13
- hideLabel?: boolean;
14
- /** Allow clearing an existing or newly selected image. */
15
- clearable?: boolean;
16
- accept?: string;
17
- /** Max preview width in pixels. */
18
- previewWidth?: number;
19
- };
20
-
21
- function ImageFieldInput({
22
- value,
23
- onChange,
24
- disabled,
25
- clearable,
26
- accept = "image/*",
27
- previewWidth = 200,
28
- }: {
29
- value: UploadFieldValue;
30
- onChange: (value: UploadFieldValue) => void;
31
- disabled?: boolean;
32
- clearable?: boolean;
33
- accept?: string;
34
- previewWidth?: number;
35
- }) {
36
- const inputRef = useRef<HTMLInputElement>(null);
37
- const previewUrl = useUploadPreviewUrl(value);
38
- const showClear = clearable && hasUploadValue(value);
39
-
40
- return (
41
- <Space direction="vertical" size="middle" style={{ width: "100%" }}>
42
- {previewUrl ? (
43
- <Image
44
- src={previewUrl}
45
- alt=""
46
- style={{ maxWidth: previewWidth, maxHeight: previewWidth, objectFit: "contain" }}
47
- />
48
- ) : null}
49
- <Space wrap>
50
- <Button
51
- icon={<UploadOutlined />}
52
- disabled={disabled}
53
- onClick={() => inputRef.current?.click()}
54
- >
55
- Choose image
56
- </Button>
57
- {showClear ? (
58
- <Button
59
- icon={<DeleteOutlined />}
60
- disabled={disabled}
61
- onClick={() => {
62
- onChange(null);
63
- if (inputRef.current) inputRef.current.value = "";
64
- }}
65
- >
66
- Clear
67
- </Button>
68
- ) : null}
69
- </Space>
70
- <input
71
- ref={inputRef}
72
- type="file"
73
- accept={accept}
74
- disabled={disabled}
75
- tabIndex={-1}
76
- aria-hidden
77
- style={{ display: "none" }}
78
- onChange={(e) => {
79
- const file = e.target.files?.[0];
80
- onChange(file ?? null);
81
- e.target.value = "";
82
- }}
83
- />
84
- </Space>
85
- );
86
- }
87
-
88
- export function ImageField({
89
- source,
90
- name,
91
- label,
92
- required,
93
- rules,
94
- hideLabel,
95
- clearable,
96
- accept,
97
- previewWidth,
98
- }: ImageFieldProps) {
99
- return (
100
- <FieldWrapper
101
- source={source}
102
- name={name}
103
- label={label}
104
- required={required}
105
- rules={rules}
106
- hideLabel={hideLabel}
107
- >
108
- {({ value, onChange, disabled }) => (
109
- <ImageFieldInput
110
- value={value as UploadFieldValue}
111
- onChange={onChange}
112
- disabled={disabled}
113
- clearable={clearable}
114
- accept={accept}
115
- previewWidth={previewWidth}
116
- />
117
- )}
118
- </FieldWrapper>
119
- );
120
- }
1
+ import { DeleteOutlined, UploadOutlined } from "@ant-design/icons";
2
+ import { Button, Image, Space } from "antd";
3
+ import { useRef } from "react";
4
+ import type { BaseSourceProps, FieldRules } from "../types";
5
+ import { FieldWrapper } from "./FieldWrapper";
6
+ import { hasUploadValue, type UploadFieldValue } from "./uploadFieldUtils";
7
+ import { useUploadPreviewUrl } from "./useUploadPreviewUrl";
8
+
9
+ export type ImageFieldProps = BaseSourceProps & {
10
+ name?: string;
11
+ required?: boolean;
12
+ rules?: FieldRules;
13
+ hideLabel?: boolean;
14
+ /** Allow clearing an existing or newly selected image. */
15
+ clearable?: boolean;
16
+ accept?: string;
17
+ /** Max preview width in pixels. */
18
+ previewWidth?: number;
19
+ };
20
+
21
+ function ImageFieldInput({
22
+ value,
23
+ onChange,
24
+ disabled,
25
+ clearable,
26
+ accept = "image/*",
27
+ previewWidth = 200,
28
+ }: {
29
+ value: UploadFieldValue;
30
+ onChange: (value: UploadFieldValue) => void;
31
+ disabled?: boolean;
32
+ clearable?: boolean;
33
+ accept?: string;
34
+ previewWidth?: number;
35
+ }) {
36
+ const inputRef = useRef<HTMLInputElement>(null);
37
+ const previewUrl = useUploadPreviewUrl(value);
38
+ const showClear = clearable && hasUploadValue(value);
39
+
40
+ return (
41
+ <Space direction="vertical" size="middle" style={{ width: "100%" }}>
42
+ {previewUrl ? (
43
+ <Image
44
+ src={previewUrl}
45
+ alt=""
46
+ style={{ maxWidth: previewWidth, maxHeight: previewWidth, objectFit: "contain" }}
47
+ />
48
+ ) : null}
49
+ <Space wrap>
50
+ <Button
51
+ icon={<UploadOutlined />}
52
+ disabled={disabled}
53
+ onClick={() => inputRef.current?.click()}
54
+ >
55
+ Choose image
56
+ </Button>
57
+ {showClear ? (
58
+ <Button
59
+ icon={<DeleteOutlined />}
60
+ disabled={disabled}
61
+ onClick={() => {
62
+ onChange(null);
63
+ if (inputRef.current) inputRef.current.value = "";
64
+ }}
65
+ >
66
+ Clear
67
+ </Button>
68
+ ) : null}
69
+ </Space>
70
+ <input
71
+ ref={inputRef}
72
+ type="file"
73
+ accept={accept}
74
+ disabled={disabled}
75
+ tabIndex={-1}
76
+ aria-hidden
77
+ style={{ display: "none" }}
78
+ onChange={(e) => {
79
+ const file = e.target.files?.[0];
80
+ onChange(file ?? null);
81
+ e.target.value = "";
82
+ }}
83
+ />
84
+ </Space>
85
+ );
86
+ }
87
+
88
+ export function ImageField({
89
+ source,
90
+ name,
91
+ label,
92
+ required,
93
+ rules,
94
+ hideLabel,
95
+ clearable,
96
+ accept,
97
+ previewWidth,
98
+ }: ImageFieldProps) {
99
+ return (
100
+ <FieldWrapper
101
+ source={source}
102
+ name={name}
103
+ label={label}
104
+ required={required}
105
+ rules={rules}
106
+ hideLabel={hideLabel}
107
+ >
108
+ {({ value, onChange, disabled }) => (
109
+ <ImageFieldInput
110
+ value={value as UploadFieldValue}
111
+ onChange={onChange}
112
+ disabled={disabled}
113
+ clearable={clearable}
114
+ accept={accept}
115
+ previewWidth={previewWidth}
116
+ />
117
+ )}
118
+ </FieldWrapper>
119
+ );
120
+ }
@@ -1,52 +1,52 @@
1
- import { InputNumber } from "antd";
2
- import type { CSSProperties } from "react";
3
- import type { BaseSourceProps, FieldRules } from "../types";
4
- import { FieldWrapper } from "./FieldWrapper";
5
-
6
- export type NumberFieldProps = BaseSourceProps & {
7
- name?: string;
8
- required?: boolean;
9
- rules?: FieldRules;
10
- min?: number;
11
- max?: number;
12
- step?: number;
13
- inputStyle?: CSSProperties;
14
- hideLabel?: boolean;
15
- };
16
-
17
- export function NumberField({
18
- source,
19
- name,
20
- label,
21
- required,
22
- rules,
23
- min,
24
- max,
25
- step,
26
- inputStyle,
27
- hideLabel,
28
- }: NumberFieldProps) {
29
- return (
30
- <FieldWrapper
31
- source={source}
32
- name={name}
33
- label={label}
34
- required={required}
35
- rules={rules}
36
- hideLabel={hideLabel}
37
- >
38
- {({ value, onChange, onBlur, disabled }) => (
39
- <InputNumber
40
- value={value as number | undefined}
41
- onChange={(v) => onChange(v)}
42
- onBlur={onBlur}
43
- min={min}
44
- max={max}
45
- step={step}
46
- disabled={disabled}
47
- style={{ width: "100%", ...inputStyle }}
48
- />
49
- )}
50
- </FieldWrapper>
51
- );
52
- }
1
+ import { InputNumber } from "antd";
2
+ import type { CSSProperties } from "react";
3
+ import type { BaseSourceProps, FieldRules } from "../types";
4
+ import { FieldWrapper } from "./FieldWrapper";
5
+
6
+ export type NumberFieldProps = BaseSourceProps & {
7
+ name?: string;
8
+ required?: boolean;
9
+ rules?: FieldRules;
10
+ min?: number;
11
+ max?: number;
12
+ step?: number;
13
+ inputStyle?: CSSProperties;
14
+ hideLabel?: boolean;
15
+ };
16
+
17
+ export function NumberField({
18
+ source,
19
+ name,
20
+ label,
21
+ required,
22
+ rules,
23
+ min,
24
+ max,
25
+ step,
26
+ inputStyle,
27
+ hideLabel,
28
+ }: NumberFieldProps) {
29
+ return (
30
+ <FieldWrapper
31
+ source={source}
32
+ name={name}
33
+ label={label}
34
+ required={required}
35
+ rules={rules}
36
+ hideLabel={hideLabel}
37
+ >
38
+ {({ value, onChange, onBlur, disabled }) => (
39
+ <InputNumber
40
+ value={value as number | undefined}
41
+ onChange={(v) => onChange(v)}
42
+ onBlur={onBlur}
43
+ min={min}
44
+ max={max}
45
+ step={step}
46
+ disabled={disabled}
47
+ style={{ width: "100%", ...inputStyle }}
48
+ />
49
+ )}
50
+ </FieldWrapper>
51
+ );
52
+ }