@applica-software-guru/react-admin 1.5.261 → 1.5.263

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 (36) hide show
  1. package/dist/components/ra-forms/TableForm/AddTableRow.d.ts +4 -0
  2. package/dist/components/ra-forms/TableForm/AddTableRow.d.ts.map +1 -0
  3. package/dist/components/ra-forms/TableForm/CreateButton.d.ts +12 -0
  4. package/dist/components/ra-forms/TableForm/CreateButton.d.ts.map +1 -0
  5. package/dist/components/ra-forms/TableForm/EditButton.d.ts +3 -0
  6. package/dist/components/ra-forms/TableForm/EditButton.d.ts.map +1 -0
  7. package/dist/components/ra-forms/TableForm/Field.d.ts +8 -0
  8. package/dist/components/ra-forms/TableForm/Field.d.ts.map +1 -0
  9. package/dist/components/ra-forms/TableForm/TableFormIterator.d.ts +97 -5
  10. package/dist/components/ra-forms/TableForm/TableFormIterator.d.ts.map +1 -1
  11. package/dist/components/ra-forms/TableForm/TableFormIteratorItem.d.ts +5 -2
  12. package/dist/components/ra-forms/TableForm/TableFormIteratorItem.d.ts.map +1 -1
  13. package/dist/components/ra-forms/TableForm/TableFormIteratorItemContext.d.ts +1 -0
  14. package/dist/components/ra-forms/TableForm/TableFormIteratorItemContext.d.ts.map +1 -1
  15. package/dist/components/ra-forms/TableForm/index.d.ts +4 -0
  16. package/dist/components/ra-forms/TableForm/index.d.ts.map +1 -1
  17. package/dist/components/ra-inputs/DateInput.d.ts.map +1 -1
  18. package/dist/react-admin.cjs.js +52 -52
  19. package/dist/react-admin.cjs.js.gz +0 -0
  20. package/dist/react-admin.cjs.js.map +1 -1
  21. package/dist/react-admin.es.js +8158 -8164
  22. package/dist/react-admin.es.js.gz +0 -0
  23. package/dist/react-admin.es.js.map +1 -1
  24. package/dist/react-admin.umd.js +51 -51
  25. package/dist/react-admin.umd.js.gz +0 -0
  26. package/dist/react-admin.umd.js.map +1 -1
  27. package/package.json +1 -1
  28. package/src/components/ra-forms/TableForm/AddTableRow.tsx +34 -0
  29. package/src/components/ra-forms/TableForm/CreateButton.tsx +58 -0
  30. package/src/components/ra-forms/TableForm/EditButton.tsx +42 -0
  31. package/src/components/ra-forms/TableForm/Field.tsx +23 -0
  32. package/src/components/ra-forms/TableForm/TableFormIterator.tsx +131 -62
  33. package/src/components/ra-forms/TableForm/TableFormIteratorItem.tsx +37 -7
  34. package/src/components/ra-forms/TableForm/TableFormIteratorItemContext.ts +1 -0
  35. package/src/components/ra-forms/TableForm/index.ts +4 -0
  36. package/src/components/ra-inputs/DateInput.tsx +21 -2
package/package.json CHANGED
@@ -106,5 +106,5 @@
106
106
  "type": "module",
107
107
  "types": "dist/index.d.ts",
108
108
  "typings": "dist/index.d.ts",
109
- "version": "1.5.261"
109
+ "version": "1.5.263"
110
110
  }
@@ -0,0 +1,34 @@
1
+ import { PlusCircleOutlined } from '@ant-design/icons';
2
+ import { IconButton, Stack, Typography, useTheme } from '@mui/material';
3
+ import React from 'react';
4
+
5
+ function AddTableRow(props: any): JSX.Element {
6
+ const { label, disableAdd, onClick, inset } = props;
7
+ const theme = useTheme();
8
+ // @ts-ignore
9
+ const tableBorderColor = theme.palette.mode === 'dark' ? theme.palette.grey.A400 : theme.palette.grey.A800;
10
+ const iconColor = theme.palette.mode === 'light' ? '#000000' : '#FFFFFF';
11
+
12
+ return (
13
+ <Stack
14
+ justifyContent={'space-between'}
15
+ alignItems={'center'}
16
+ flexDirection={'row'}
17
+ sx={inset ? { p: 2.5 } : { pt: 2 }}
18
+ >
19
+ {label !== false && <Typography>{label}</Typography>}
20
+ {!disableAdd &&
21
+ (React.isValidElement(props?.customButton) ? (
22
+ React.cloneElement(props?.customButton, {
23
+ onClick: onClick
24
+ })
25
+ ) : (
26
+ <IconButton color="secondary" sx={{ border: `1px solid ${tableBorderColor}` }} onClick={onClick}>
27
+ <PlusCircleOutlined style={{ color: iconColor }} />
28
+ </IconButton>
29
+ ))}
30
+ </Stack>
31
+ );
32
+ }
33
+
34
+ export { AddTableRow };
@@ -0,0 +1,58 @@
1
+ import { AddTableRow } from './AddTableRow';
2
+ import { Dialog } from '@mui/material';
3
+ import { CreateContextProvider, SaveHandler } from 'ra-core';
4
+ import React from 'react';
5
+ import { useArrayInput } from 'react-admin';
6
+
7
+ interface CreateButtonProps {
8
+ label: string;
9
+ disableAdd?: boolean;
10
+ inset?: boolean;
11
+ source?: string;
12
+ template?: any;
13
+ children: React.ReactNode;
14
+ }
15
+
16
+ function CreateButton(props: CreateButtonProps): JSX.Element {
17
+ const { label, disableAdd, inset, source, template } = props;
18
+ const [open, setOpen] = React.useState(false);
19
+ const { append } = useArrayInput();
20
+
21
+ const toggleOpen = React.useCallback(() => {
22
+ setOpen((prev) => !prev);
23
+ }, [setOpen]);
24
+
25
+ const handleSave = React.useCallback(
26
+ (data: any) => {
27
+ setOpen(false);
28
+ append(data);
29
+ return Promise.resolve();
30
+ },
31
+ [setOpen, append]
32
+ );
33
+
34
+ return (
35
+ <>
36
+ {React.cloneElement(<AddTableRow />, {
37
+ label,
38
+ source,
39
+ disableAdd,
40
+ template,
41
+ onClick: toggleOpen,
42
+ inset
43
+ })}
44
+ <Dialog open={open} onClose={toggleOpen} maxWidth="xs">
45
+ <CreateContextProvider
46
+ // @ts-ignore
47
+ value={{
48
+ save: handleSave as SaveHandler<any>
49
+ }}
50
+ >
51
+ {props.children}
52
+ </CreateContextProvider>
53
+ </Dialog>
54
+ </>
55
+ );
56
+ }
57
+
58
+ export { CreateButton };
@@ -0,0 +1,42 @@
1
+ import { useTableFormIteratorItem } from './TableFormIteratorItemContext';
2
+ import { Button, Dialog } from '@mui/material';
3
+ import React from 'react';
4
+ import { EditContextProvider, SaveHandler, useArrayInput, useTranslate } from 'react-admin';
5
+
6
+ function EditButton(props: any) {
7
+ const { children } = props;
8
+ const { item, index } = useTableFormIteratorItem();
9
+ const [open, setOpen] = React.useState(false);
10
+ const { update } = useArrayInput();
11
+ const translate = useTranslate();
12
+
13
+ const handleSave: SaveHandler<any> = React.useCallback(
14
+ (data) => {
15
+ setOpen(false);
16
+ update(index, data);
17
+ return Promise.resolve();
18
+ },
19
+ [index, update]
20
+ );
21
+
22
+ return (
23
+ <>
24
+ <Button color="primary" onClick={() => setOpen(true)} sx={{ justifyContent: 'flex-start' }}>
25
+ {translate('ra.action.edit')}
26
+ </Button>
27
+ <Dialog open={open} onClose={() => setOpen(false)} maxWidth="xs" fullWidth>
28
+ <EditContextProvider
29
+ // @ts-ignore
30
+ value={{
31
+ record: item,
32
+ save: handleSave
33
+ }}
34
+ >
35
+ {children}
36
+ </EditContextProvider>
37
+ </Dialog>
38
+ </>
39
+ );
40
+ }
41
+
42
+ export { EditButton };
@@ -0,0 +1,23 @@
1
+ import React, { Children } from 'react';
2
+ import { useRecordContext } from 'react-admin';
3
+ import { useFormContext } from 'react-hook-form';
4
+
5
+ interface FieldProps {
6
+ source: string;
7
+ children: React.ReactNode;
8
+ }
9
+
10
+ interface ChildProps {
11
+ source: string;
12
+ record: Record<string, any>;
13
+ }
14
+
15
+ function Field({ source, children }: FieldProps): JSX.Element | null {
16
+ const Child = Children.only(children) as React.ReactElement<ChildProps>;
17
+ const { getValues } = useFormContext();
18
+ const record = useRecordContext({ record: getValues() });
19
+
20
+ return React.isValidElement(Child) ? React.cloneElement(Child, { source, record }) : null;
21
+ }
22
+
23
+ export { Field };
@@ -1,11 +1,12 @@
1
+ import { Field } from './Field';
2
+ import { AddTableRow } from './AddTableRow';
3
+ import { CreateButton } from './CreateButton';
4
+ import { EditButton } from './EditButton';
1
5
  import { ActionsMenu } from '@/components/ActionsMenu';
2
6
  import { TableFormIteratorContext } from '@/components/ra-forms/TableForm/TableFormIteratorContext';
3
7
  import { TableFormIteratorItem } from '@/components/ra-forms/TableForm/TableFormIteratorItem';
4
- import { PlusCircleOutlined } from '@ant-design/icons';
5
8
  import {
6
- IconButton,
7
9
  Paper,
8
- Stack,
9
10
  SxProps,
10
11
  Table,
11
12
  TableBody,
@@ -16,23 +17,24 @@ import {
16
17
  Typography
17
18
  } from '@mui/material';
18
19
  import { styled, useTheme } from '@mui/material/styles';
19
- import get from 'lodash/get';
20
- import { FormDataConsumer, RaRecord, useRecordContext, useTranslate, useTranslateLabel } from 'ra-core';
20
+ import { FormDataConsumer, RaRecord, useTranslate, useTranslateLabel } from 'ra-core';
21
21
  import * as React from 'react';
22
22
  import { Children, ReactElement, ReactNode, useCallback, useMemo, useRef, useState } from 'react';
23
23
  import { Confirm, useArrayInput } from 'react-admin';
24
24
  import { UseFieldArrayReturn, useFormContext } from 'react-hook-form';
25
25
 
26
26
  /**
27
+ * How to use TableFormIterator:
27
28
  *
28
29
  * @example
29
30
  * <Grid container>
30
31
  * <Grid item xs={12}>
31
32
  * <ArrayInput label={false} source="descriptor.fields">
32
- * <TableFormIterator template={{ property: 'FIELD' }} label="Catalogo proprietà"> // template: default value for new row
33
+ * <TableFormIterator label="Property catalog">
33
34
  * <TextInput label="Name" source={'name'} validate={required()} />
34
- * <TextInput source={'denomination'} helperText={false} />
35
+ * <TextInput label="Denomination" source={'denomination'} helperText={false} />
35
36
  * <SelectInput choices={FieldTypes} source={'type'} helperText={false} />
37
+ * {...}
36
38
  * </TableFormIterator>
37
39
  * </ArrayInput>
38
40
  * </Grid>
@@ -50,15 +52,14 @@ function RawTableFormIterator(props: TableFormIteratorProps): ReactElement | nul
50
52
  className,
51
53
  empty,
52
54
  template = {},
55
+ addButton = <AddTableRow />,
53
56
  inset
54
57
  } = props;
55
58
  const [confirmIsOpen, setConfirmIsOpen] = useState<boolean>(false);
56
59
  const { fields, remove, replace, append } = useArrayInput(props);
57
60
  const { resetField } = useFormContext();
58
-
59
61
  const theme = useTheme();
60
62
  const translate = useTranslate();
61
- const record = useRecordContext(props);
62
63
  const initialDefaultValue = useRef(template || {});
63
64
 
64
65
  const translateLabel = useTranslateLabel();
@@ -129,9 +130,6 @@ function RawTableFormIterator(props: TableFormIteratorProps): ReactElement | nul
129
130
  setConfirmIsOpen(false);
130
131
  }, [replace]);
131
132
 
132
- // @ts-ignore
133
- const records = get(record, source);
134
-
135
133
  const context = useMemo(
136
134
  () => ({
137
135
  total: fields.length,
@@ -149,12 +147,15 @@ function RawTableFormIterator(props: TableFormIteratorProps): ReactElement | nul
149
147
  // @ts-ignore
150
148
  <TableFormIteratorContext.Provider value={context}>
151
149
  <div className={className}>
152
- {React.cloneElement(<AddTableRow />, {
150
+ {React.cloneElement(addButton, {
153
151
  label,
154
152
  source,
155
153
  disableAdd,
156
154
  template,
157
- onClick: handleAddButtonClick((props?.addButton as any)?.props?.onClick),
155
+ onClick:
156
+ addButton?.type !== CreateButton
157
+ ? handleAddButtonClick((props?.addButton as any)?.props?.onClick)
158
+ : undefined,
158
159
  inset
159
160
  })}
160
161
 
@@ -173,6 +174,9 @@ function RawTableFormIterator(props: TableFormIteratorProps): ReactElement | nul
173
174
  <TableRow>
174
175
  {/** @ts-ignore */}
175
176
  {Children.map(children, (input: ReactElement, index) => {
177
+ if (input.type === EditButton) {
178
+ return null;
179
+ }
176
180
  if (!React.isValidElement<any>(input)) {
177
181
  return null;
178
182
  }
@@ -185,18 +189,17 @@ function RawTableFormIterator(props: TableFormIteratorProps): ReactElement | nul
185
189
  );
186
190
  })}
187
191
 
188
- {!disableRemove &&
189
- (showClearAllButton ? (
190
- <TableCell key="actions" sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
191
- <ActionsMenu horizontal>
192
- <Typography color="error" onClick={() => setConfirmIsOpen(true)}>
193
- {translate('ra.action.delete')}
194
- </Typography>
195
- </ActionsMenu>
196
- </TableCell>
197
- ) : (
198
- <TableCell key="empty_actions" />
199
- ))}
192
+ {!disableRemove && showClearAllButton ? (
193
+ <TableCell key="actions" sx={{ display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
194
+ <ActionsMenu horizontal>
195
+ <Typography color="error" onClick={() => setConfirmIsOpen(true)}>
196
+ {translate('ra.action.delete')}
197
+ </Typography>
198
+ </ActionsMenu>
199
+ </TableCell>
200
+ ) : (
201
+ <TableCell key="empty_actions" />
202
+ )}
200
203
  </TableRow>
201
204
  </TableHead>
202
205
 
@@ -223,7 +226,7 @@ function RawTableFormIterator(props: TableFormIteratorProps): ReactElement | nul
223
226
  index={index}
224
227
  member={`${source}.${index}`}
225
228
  onRemoveField={removeField}
226
- record={(records && records[index]) || {}}
229
+ record={(fields && fields[index]) || {}}
227
230
  // @ts-ignore
228
231
  resource={resource}
229
232
  // @ts-ignore
@@ -251,35 +254,6 @@ function RawTableFormIterator(props: TableFormIteratorProps): ReactElement | nul
251
254
  ) : null;
252
255
  }
253
256
 
254
- function AddTableRow(props: any): JSX.Element {
255
- const { label, disableAdd, onClick, inset } = props;
256
- const theme = useTheme();
257
- // @ts-ignore
258
- const tableBorderColor = theme.palette.mode === 'dark' ? theme.palette.grey.A400 : theme.palette.grey.A800;
259
- const iconColor = theme.palette.mode === 'light' ? '#000000' : '#FFFFFF';
260
-
261
- return (
262
- <Stack
263
- justifyContent={'space-between'}
264
- alignItems={'center'}
265
- flexDirection={'row'}
266
- sx={inset ? { p: 2.5 } : { pt: 2 }}
267
- >
268
- {label !== false && <Typography>{label}</Typography>}
269
- {!disableAdd &&
270
- (React.isValidElement(props?.addButton) ? (
271
- React.cloneElement(props?.addButton, {
272
- onClick: onClick
273
- })
274
- ) : (
275
- <IconButton color="secondary" sx={{ border: `1px solid ${tableBorderColor}` }} onClick={onClick}>
276
- <PlusCircleOutlined style={{ color: iconColor }} />
277
- </IconButton>
278
- ))}
279
- </Stack>
280
- );
281
- }
282
-
283
257
  const TableFormIterator = styled(RawTableFormIterator, { slot: 'Root' })(({ theme }) => ({
284
258
  '& > div.MuiPaper-root': {
285
259
  overflowX: 'auto',
@@ -302,12 +276,23 @@ interface TableFormIteratorProps extends Partial<UseFieldArrayReturn> {
302
276
  disableAdd?: boolean;
303
277
  disableRemove?: boolean;
304
278
  enableClearAll?: boolean;
279
+ /**
280
+ * Adding the template prop will allow to set a default value for the new row.
281
+ *
282
+ * @example
283
+ * <Grid container>
284
+ * <Grid item xs={12}>
285
+ * <ArrayInput label={false} source="descriptor.fields">
286
+ * <TableFormIterator template={{ property: 'FIELD' }} label="Property catalog">
287
+ * <TextInput label="Name" source={'name'} validate={required()} />
288
+ * <TextInput source={'denomination'} helperText={false} />
289
+ * <SelectInput choices={FieldTypes} source={'type'} helperText={false} />
290
+ * </TableFormIterator>
291
+ * </ArrayInput>
292
+ * </Grid>
293
+ * </Grid>
294
+ */
305
295
  template?: object;
306
- meta?: {
307
- // the type defined in FieldArrayRenderProps says error is boolean, which is wrong.
308
- error?: any;
309
- submitFailed?: boolean;
310
- };
311
296
  record?: RaRecord;
312
297
  label?: string | boolean;
313
298
  resource?: string;
@@ -317,5 +302,89 @@ interface TableFormIteratorProps extends Partial<UseFieldArrayReturn> {
317
302
  inset?: boolean;
318
303
  }
319
304
 
320
- export { TableFormIterator };
305
+ type ITableForm = typeof TableFormIterator & {
306
+ /**
307
+ * TableFormiterator allows to insert an addButton which will render the default btn and open a dialog with the form fields passed as children.
308
+ *
309
+ * @example
310
+ * <Grid container>
311
+ * <Grid item xs={12}>
312
+ * <ArrayInput label={false} source="descriptor.fields">
313
+ * <TableFormIterator
314
+ * addButton={<TableFormIterator.CreateButton>
315
+ * <TextInput label="Name" source={'name'} validate={required()} />
316
+ * <SelectInput choices={FieldTypes} source={'type'} helperText={false} />
317
+ * </TableFormIterator.CreateButton>}
318
+ * label="Property catalog">
319
+ * <TextInput label="Name" source={'name'} validate={required()} />
320
+ * <TextInput label="Denomination" source={'denomination'} helperText={false} />
321
+ * <SelectInput choices={FieldTypes} source={'type'} helperText={false} />
322
+ * </TableFormIterator>
323
+ * </ArrayInput>
324
+ * </Grid>
325
+ * </Grid>
326
+ */
327
+ CreateButton: typeof CreateButton;
328
+
329
+ /**
330
+ * TableFormiterator allows a child EditButton which will render an edit button in the ActionsMenu of each row.
331
+ * The EditButton will open a dialog with the form fields passed as children.
332
+ *
333
+ * @example
334
+ * <Grid container>
335
+ * <Grid item xs={12}>
336
+ * <ArrayInput label={false} source="descriptor.fields">
337
+ * <TableFormIterator label="Property catalog">
338
+ *
339
+ * <TableFormIterator.EditButton>
340
+ * <TextInput label="Name" source={'name'} validate={required()} />
341
+ * <SelectInput choices={FieldTypes} source={'type'} helperText={false} />
342
+ * </TableFormIterator.EditButton>
343
+ *
344
+ * <TextInput label="Name" source={'name'} validate={required()} />
345
+ * <TextInput label="Denomination" source={'denomination'} helperText={false} />
346
+ * <SelectInput choices={FieldTypes} source={'type'} helperText={false} />
347
+ * </TableFormIterator>
348
+ * </ArrayInput>
349
+ * </Grid>
350
+ * </Grid>
351
+ */
352
+ EditButton: typeof EditButton;
353
+ /**
354
+ * TableFormiterator allows a child Field which will render a read-only field in the Table with a custom record context.
355
+ * The record context will overwritthe by getValues() of useFormContext() hook.
356
+ *
357
+ * @example
358
+ * <Grid container>
359
+ * <Grid item xs={12}>
360
+ * <ArrayInput label={false} source="descriptor.fields">
361
+ * <TableFormIterator label="Property catalog">
362
+ *
363
+ * <TableFormIterator.EditButton>
364
+ * <TextInput label="Name" source={'name'} validate={required()} />
365
+ * <SelectInput choices={FieldTypes} source={'type'} helperText={false} />
366
+ * </TableFormIterator.EditButton>
367
+ *
368
+ * <TableFormIterator.Field source="name">
369
+ * <TextField />
370
+ * </TableFormIterator.Field>
371
+ * <TableFormIterator.Field source="type">
372
+ * <TextField />
373
+ * </TableFormIterator.Field>
374
+ * {...}
375
+ * </TableFormIterator>
376
+ * </ArrayInput>
377
+ * </Grid>
378
+ * </Grid>
379
+ */
380
+ Field: typeof Field;
381
+ };
382
+
383
+ const DefaultTableForm = TableFormIterator as ITableForm;
384
+
385
+ DefaultTableForm.CreateButton = CreateButton;
386
+ DefaultTableForm.EditButton = EditButton;
387
+ DefaultTableForm.Field = Field;
388
+
389
+ export { DefaultTableForm as TableFormIterator };
321
390
  export type { TableFormIteratorProps };
@@ -1,18 +1,19 @@
1
+ import { EditButton } from './EditButton';
1
2
  import { ActionsMenu } from '@/components/ActionsMenu';
2
3
  import { useTableFormIterator } from '@/components/ra-forms/TableForm/TableFormIteratorContext';
3
4
  import {
4
5
  TableFormIteratorItemContext,
5
6
  TableFormIteratorItemContextValue
6
7
  } from '@/components/ra-forms/TableForm/TableFormIteratorItemContext';
7
- import { Stack, TableCell, Typography } from '@mui/material';
8
+ import { Button, Stack, TableCell } from '@mui/material';
8
9
  import { RaRecord } from 'ra-core';
9
10
  import { Children, ReactElement, ReactNode, cloneElement, isValidElement, useMemo } from 'react';
10
11
  import * as React from 'react';
11
12
  import { Confirm, useTranslate } from 'react-admin';
12
13
 
13
14
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
14
- export const TableFormIteratorItem = React.forwardRef((props: TableFormIteratorItemProps, _: any) => {
15
- const { children, disabled, disableRemove = false, index, member, resource } = props;
15
+ const TableFormIteratorItem = React.forwardRef((props: TableFormIteratorItemProps, _: any) => {
16
+ const { children, disabled, disableRemove = false, index, member, resource, record } = props;
16
17
  const translate = useTranslate();
17
18
  const [confirmIsOpen, setConfirmIsOpen] = React.useState<boolean>(false);
18
19
  const { total, remove } = useTableFormIterator();
@@ -27,15 +28,31 @@ export const TableFormIteratorItem = React.forwardRef((props: TableFormIteratorI
27
28
  () => ({
28
29
  index,
29
30
  total,
31
+ item: record,
30
32
  remove: () => remove(index)
31
33
  }),
32
- [index, total, remove]
34
+ [index, total, remove, record]
35
+ );
36
+
37
+ const renderEditButton = useMemo(
38
+ () =>
39
+ Children.map(children, (Child) => {
40
+ if (isValidElement(Child) && Child?.type === EditButton) {
41
+ return React.isValidElement(Child) ? Child : null;
42
+ }
43
+
44
+ return null;
45
+ }),
46
+ [children]
33
47
  );
34
48
 
35
49
  return (
36
50
  <TableFormIteratorItemContext.Provider value={context}>
37
51
  {/** @ts-ignore */}
38
52
  {Children.map(children, (input: ReactElement, index2) => {
53
+ if (input.type === EditButton) {
54
+ return null;
55
+ }
39
56
  if (!isValidElement<any>(input)) {
40
57
  return null;
41
58
  }
@@ -58,13 +75,22 @@ export const TableFormIteratorItem = React.forwardRef((props: TableFormIteratorI
58
75
  <TableCell>
59
76
  <Stack direction="row" spacing={1} justifyContent="center" alignItems="center">
60
77
  <ActionsMenu horizontal>
61
- <Typography color="error" onClick={() => setConfirmIsOpen(true)}>
78
+ <Button onClick={() => setConfirmIsOpen(true)} color="error" sx={{ justifyContent: 'flex-start' }}>
62
79
  {translate('ra.action.delete')}
63
- </Typography>
80
+ </Button>
81
+ {renderEditButton}
64
82
  </ActionsMenu>
65
83
  </Stack>
66
84
  </TableCell>
67
85
  )}
86
+ {disableRemove && renderEditButton ? (
87
+ <TableCell>
88
+ <Stack direction="row" spacing={1} justifyContent="center" alignItems="center">
89
+ <ActionsMenu horizontal>{renderEditButton}</ActionsMenu>
90
+ </Stack>
91
+ </TableCell>
92
+ ) : null}
93
+
68
94
  {/** @ts-ignore */}
69
95
  {children.length > 0 && (
70
96
  <Confirm
@@ -79,7 +105,7 @@ export const TableFormIteratorItem = React.forwardRef((props: TableFormIteratorI
79
105
  );
80
106
  });
81
107
 
82
- export type TableFormIteratorItemProps = {
108
+ type TableFormIteratorItemProps = {
83
109
  children?: ReactNode;
84
110
  disabled?: boolean;
85
111
  disableRemove?: boolean;
@@ -88,6 +114,10 @@ export type TableFormIteratorItemProps = {
88
114
  onRemoveField: (index: number) => void;
89
115
  record: RaRecord;
90
116
  removeButton?: ReactElement;
117
+ editAction?: ReactElement;
91
118
  resource: string;
92
119
  source: string;
93
120
  };
121
+
122
+ export { TableFormIteratorItem };
123
+ export type { TableFormIteratorItemProps };
@@ -12,6 +12,7 @@ const TableFormIteratorItemContext = createContext<TableFormIteratorItemContextV
12
12
  type TableFormIteratorItemContextValue = {
13
13
  index: number;
14
14
  total: number;
15
+ item: any;
15
16
  remove: () => void;
16
17
  reOrder: (newIndex: number) => void;
17
18
  };
@@ -1,3 +1,7 @@
1
+ export * from './AddTableRow';
2
+ export * from './CreateButton';
3
+ export * from './EditButton';
4
+ export * from './Field';
1
5
  export * from './TableFormIterator';
2
6
  export * from './TableFormIteratorContext';
3
7
  export * from './TableFormIteratorItem';
@@ -1,7 +1,11 @@
1
1
  import { LabeledInput } from '@/components/ra-inputs/LabeledInput';
2
2
  import { styled } from '@mui/material/styles';
3
+ import dayjs from 'dayjs';
4
+ import { useCallback, useState } from 'react';
3
5
  import { DateInputProps, DateInput as RaDateInput } from 'react-admin';
4
6
 
7
+ const MAX_YEAR_LENGTH = 4;
8
+
5
9
  const StyledDateInput = styled(RaDateInput, { slot: 'root' })(({ label }) => ({
6
10
  '& legend': {
7
11
  width: label === false ? 0 : 'auto'
@@ -9,11 +13,26 @@ const StyledDateInput = styled(RaDateInput, { slot: 'root' })(({ label }) => ({
9
13
  }));
10
14
 
11
15
  function DateInput(props: DateInputProps): JSX.Element {
16
+ const [dateValue, setDateValue] = useState('');
17
+
18
+ const handleInput = useCallback(
19
+ (event: React.ChangeEvent<HTMLInputElement>) => {
20
+ const nextValue = event.target.value;
21
+ const year = dayjs(nextValue).year();
22
+
23
+ if (year.toString().length > MAX_YEAR_LENGTH) {
24
+ event.target.value = dateValue;
25
+ } else {
26
+ setDateValue(nextValue);
27
+ }
28
+ },
29
+ [dateValue]
30
+ );
31
+
12
32
  return (
13
33
  // @ts-ignore
14
34
  <LabeledInput {...props}>
15
- {/** @ts-ignore */}
16
- <StyledDateInput />
35
+ <StyledDateInput {...props} onInput={handleInput} />
17
36
  </LabeledInput>
18
37
  );
19
38
  }