@applica-software-guru/react-admin 1.5.347 → 1.5.349

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 (49) hide show
  1. package/dist/components/@extended/IconButton.d.ts +3 -8
  2. package/dist/components/@extended/IconButton.d.ts.map +1 -1
  3. package/dist/components/Layout/Header/Profile/HeaderProfile.d.ts.map +1 -1
  4. package/dist/components/Pagination/Pagination.d.ts +2 -1
  5. package/dist/components/Pagination/Pagination.d.ts.map +1 -1
  6. package/dist/components/ra-inputs/LabeledInput.d.ts +5 -7
  7. package/dist/components/ra-inputs/LabeledInput.d.ts.map +1 -1
  8. package/dist/components/ra-inputs/ReferenceLookupInput/ReferenceLookupInput.d.ts +14 -0
  9. package/dist/components/ra-inputs/ReferenceLookupInput/ReferenceLookupInput.d.ts.map +1 -0
  10. package/dist/components/ra-inputs/ReferenceLookupInput/ReferenceManyLookupInput.d.ts +14 -0
  11. package/dist/components/ra-inputs/ReferenceLookupInput/ReferenceManyLookupInput.d.ts.map +1 -0
  12. package/dist/components/ra-inputs/ReferenceLookupInput/common.d.ts +32 -0
  13. package/dist/components/ra-inputs/ReferenceLookupInput/common.d.ts.map +1 -0
  14. package/dist/components/ra-inputs/ReferenceLookupInput/index.d.ts +3 -0
  15. package/dist/components/ra-inputs/ReferenceLookupInput/index.d.ts.map +1 -0
  16. package/dist/components/ra-inputs/ReferenceManyInput.d.ts +3 -3
  17. package/dist/components/ra-inputs/ReferenceManyInput.d.ts.map +1 -1
  18. package/dist/components/ra-inputs/index.d.ts +1 -0
  19. package/dist/components/ra-inputs/index.d.ts.map +1 -1
  20. package/dist/hooks/index.d.ts +2 -0
  21. package/dist/hooks/index.d.ts.map +1 -1
  22. package/dist/hooks/useDialogState.d.ts +10 -0
  23. package/dist/hooks/useDialogState.d.ts.map +1 -0
  24. package/dist/hooks/useUuid.d.ts +3 -0
  25. package/dist/hooks/useUuid.d.ts.map +1 -0
  26. package/dist/react-admin.cjs.js +60 -60
  27. package/dist/react-admin.cjs.js.gz +0 -0
  28. package/dist/react-admin.cjs.js.map +1 -1
  29. package/dist/react-admin.es.js +13692 -13476
  30. package/dist/react-admin.es.js.gz +0 -0
  31. package/dist/react-admin.es.js.map +1 -1
  32. package/dist/react-admin.umd.js +61 -61
  33. package/dist/react-admin.umd.js.gz +0 -0
  34. package/dist/react-admin.umd.js.map +1 -1
  35. package/package.json +1 -1
  36. package/src/components/@extended/IconButton.tsx +3 -2
  37. package/src/components/Layout/Header/Profile/HeaderProfile.tsx +1 -2
  38. package/src/components/Pagination/Pagination.tsx +4 -3
  39. package/src/components/ra-inputs/LabeledInput.tsx +15 -15
  40. package/src/components/ra-inputs/ReferenceLookupInput/ReferenceLookupInput.tsx +99 -0
  41. package/src/components/ra-inputs/ReferenceLookupInput/ReferenceManyLookupInput.tsx +99 -0
  42. package/src/components/ra-inputs/ReferenceLookupInput/common.tsx +182 -0
  43. package/src/components/ra-inputs/ReferenceLookupInput/index.ts +2 -0
  44. package/src/components/ra-inputs/ReferenceManyInput.tsx +10 -8
  45. package/src/components/ra-inputs/index.ts +1 -0
  46. package/src/components/ra-lists/Empty.tsx +1 -1
  47. package/src/hooks/index.ts +2 -0
  48. package/src/hooks/useDialogState.tsx +27 -0
  49. package/src/hooks/useUuid.tsx +14 -0
package/package.json CHANGED
@@ -108,5 +108,5 @@
108
108
  "type": "module",
109
109
  "types": "dist/index.d.ts",
110
110
  "typings": "dist/index.d.ts",
111
- "version": "1.5.347"
111
+ "version": "1.5.349"
112
112
  }
@@ -1,6 +1,6 @@
1
1
  import { getColors } from '@/themes/getColors';
2
2
  import { getShadow } from '@/themes/getShadow';
3
- import { default as MuiIconButton } from '@mui/material/IconButton';
3
+ import { default as MuiIconButton, IconButtonProps as MuiIconButtonProps } from '@mui/material/IconButton';
4
4
  import { Theme, alpha, styled, useTheme } from '@mui/material/styles';
5
5
  import { PropsWithChildren, forwardRef } from 'react';
6
6
 
@@ -146,7 +146,8 @@ type IconButtonProps = PropsWithChildren<{
146
146
  variant?: string;
147
147
  shape?: string;
148
148
  color?: string;
149
- }>;
149
+ }> &
150
+ MuiIconButtonProps;
150
151
 
151
152
  const IconButton = forwardRef(
152
153
  ({ variant = 'text', shape = 'square', children, color = 'primary', ...others }: IconButtonProps, ref) => {
@@ -1,4 +1,3 @@
1
- import { ChangePasswordButton, LogoutButton, StopImpersonateButton } from './buttons';
2
1
  import { HeaderToggleButton, MainCard } from '@/components';
3
2
  import { Avatar, IconButton, Transitions } from '@/components/@extended';
4
3
  import { usePopoverState } from '@/hooks';
@@ -7,6 +6,7 @@ import { Popper } from '@mui/base';
7
6
  import { CardContent, ClickAwayListener, Grid, List, Paper, Stack, Tooltip, Typography, useTheme } from '@mui/material';
8
7
  import { useDataProvider, useGetIdentity, useLogout } from 'ra-core';
9
8
  import React, { ReactNode, useCallback, useEffect, useMemo, useState } from 'react';
9
+ import { ChangePasswordButton, LogoutButton, StopImpersonateButton } from './buttons';
10
10
 
11
11
  interface HeaderProfileProps {
12
12
  roles?: ReactNode;
@@ -86,7 +86,6 @@ function HeaderProfile(props: HeaderProfileProps) {
86
86
  </Grid>
87
87
  <Grid item>
88
88
  <Tooltip title="Logout">
89
- {/* @ts-expect-error WARN: wtf */}
90
89
  <IconButton size="large" sx={{ color: 'text.primary' }} onClick={handleLogout}>
91
90
  <LogoutOutlined />
92
91
  </IconButton>
@@ -1,6 +1,5 @@
1
- import { FC, ReactElement, memo, useCallback, useEffect, useMemo, useState } from 'react';
2
- import PropTypes from 'prop-types';
3
1
  import { TablePagination, TablePaginationBaseProps, Theme, Toolbar, useMediaQuery, useTheme } from '@mui/material';
2
+ import PropTypes from 'prop-types';
4
3
  import {
5
4
  ComponentPropType,
6
5
  ListPaginationContextValue,
@@ -9,9 +8,10 @@ import {
9
8
  useResourceDefinition,
10
9
  useTranslate
11
10
  } from 'ra-core';
11
+ import { FC, ReactElement, memo, useCallback, useEffect, useMemo, useState } from 'react';
12
12
 
13
- import { PaginationActions, PaginationActionsProps } from './PaginationActions';
14
13
  import { debounce } from 'lodash';
14
+ import { PaginationActions, PaginationActionsProps } from './PaginationActions';
15
15
 
16
16
  const Pagination: FC<PaginationProps> = memo((props) => {
17
17
  const { rowsPerPageOptions = DefaultRowsPerPageOptions, actions, limit = null, ...rest } = props;
@@ -244,3 +244,4 @@ interface PaginationProps extends TablePaginationBaseProps, Partial<ListPaginati
244
244
  }
245
245
 
246
246
  export { Pagination };
247
+ export type { PaginationProps };
@@ -1,8 +1,8 @@
1
1
  import { useAppConfig } from '@/components/AppStateProvider';
2
2
  import { FormHelperText, InputLabel, Stack } from '@mui/material';
3
3
  import { useTheme } from '@mui/material/styles';
4
- import React from 'react';
5
- import { FieldTitle, InputProps, useInput } from 'react-admin';
4
+ import React, { PropsWithChildren, ReactElement } from 'react';
5
+ import { CommonInputProps, FieldTitle, useInput } from 'react-admin';
6
6
 
7
7
  function LabeledInput({
8
8
  label,
@@ -80,19 +80,19 @@ function LabeledInput({
80
80
  );
81
81
  }
82
82
 
83
- type LabeledInputProps = InputProps & {
84
- sx?: any;
85
- children?: React.ReactElement;
86
- label?: string | boolean;
87
- addLabel?: boolean;
88
- resource?: string;
89
- isRequired?: boolean;
90
- source?: string;
91
- display?: 'legend' | 'label';
92
- helperText?: string | boolean | React.ReactElement | null;
93
- divider?: boolean;
94
- chip?: any;
95
- };
83
+ type LabeledInputProps = PropsWithChildren<
84
+ CommonInputProps & {
85
+ sx?: any;
86
+ label?: string | ReactElement | false;
87
+ addLabel?: boolean;
88
+ resource?: string;
89
+ isRequired?: boolean;
90
+ display?: 'legend' | 'label';
91
+ helperText?: string | boolean | React.ReactElement | null;
92
+ divider?: boolean;
93
+ chip?: any;
94
+ }
95
+ >;
96
96
 
97
97
  export { LabeledInput };
98
98
  export type { LabeledInputProps };
@@ -0,0 +1,99 @@
1
+ import { IconButton } from '@/components/@extended';
2
+ import { LabeledInput, LabeledInputProps } from '@/components/ra-inputs/LabeledInput';
3
+ import { SearchInput } from '@/components/ra-inputs/SearchInput';
4
+ import { useDialogState } from '@/hooks';
5
+ import { AddCircleRounded } from '@mui/icons-material';
6
+ import { Stack } from '@mui/material';
7
+ import _ from 'lodash';
8
+ import { FilterPayload, Identifier, useInput } from 'ra-core';
9
+ import { ReactElement, useCallback, useMemo } from 'react';
10
+ import { EntityField, EntityLookupDialog, RecordRepresentationType } from './common';
11
+
12
+ type ReferenceLookupInputProps = {
13
+ filter?: FilterPayload;
14
+ filterDefaultValues?: object;
15
+ filters?: ReactElement | ReactElement[];
16
+ recordRepresentation?: RecordRepresentationType;
17
+ reference: string;
18
+ } & LabeledInputProps;
19
+
20
+ function ReferenceLookupInput(props: ReferenceLookupInputProps): JSX.Element {
21
+ const {
22
+ children,
23
+ filter: propFilter,
24
+ filterDefaultValues,
25
+ filters: propFilters,
26
+ recordRepresentation,
27
+ reference,
28
+ source
29
+ } = props;
30
+ const { field } = useInput({ source });
31
+ const { value, onChange } = field ?? {};
32
+ const hasValue = !_.isEmpty(value);
33
+ const { open, handleOpen, handleClose } = useDialogState(false);
34
+ const filter = useMemo(
35
+ () =>
36
+ _.chain(propFilter ?? {})
37
+ .clone()
38
+ .extend({ id__ne: value })
39
+ .value(),
40
+ [propFilter, value]
41
+ );
42
+ const filters = useMemo(
43
+ () => propFilters ?? [<SearchInput key="keyword" source="keyword" alwaysOn />],
44
+ [propFilters]
45
+ );
46
+
47
+ const onAdd = useCallback(
48
+ (ids: Identifier[]) => {
49
+ const id = _.first(ids);
50
+ handleClose();
51
+ onChange(id);
52
+ return id;
53
+ },
54
+ [onChange, handleClose]
55
+ );
56
+
57
+ const onDelete = useCallback(() => onChange(null), [onChange]);
58
+
59
+ return (
60
+ <LabeledInput {...props}>
61
+ <Stack alignItems="center" direction="row" spacing={1}>
62
+ {hasValue ? (
63
+ <EntityField
64
+ id={value}
65
+ onClick={handleOpen}
66
+ onDelete={onDelete}
67
+ recordRepresentation={recordRepresentation}
68
+ resource={reference}
69
+ />
70
+ ) : null}
71
+ {!hasValue && (
72
+ <IconButton onClick={handleOpen}>
73
+ <AddCircleRounded />
74
+ </IconButton>
75
+ )}
76
+ <EntityLookupDialog
77
+ onCancel={handleClose}
78
+ onConfirm={onAdd}
79
+ multiple={false}
80
+ slotProps={{
81
+ dialog: { open, onClose: handleClose },
82
+ list: {
83
+ filter,
84
+ filterDefaultValues,
85
+ resource: reference
86
+ },
87
+ listToolbar: {
88
+ filters: filters
89
+ }
90
+ }}
91
+ >
92
+ {children}
93
+ </EntityLookupDialog>
94
+ </Stack>
95
+ </LabeledInput>
96
+ );
97
+ }
98
+
99
+ export { ReferenceLookupInput };
@@ -0,0 +1,99 @@
1
+ import { IconButton } from '@/components/@extended';
2
+ import { LabeledInput, LabeledInputProps } from '@/components/ra-inputs/LabeledInput';
3
+ import { SearchInput } from '@/components/ra-inputs/SearchInput';
4
+ import { useDialogState } from '@/hooks';
5
+ import { AddCircleRounded } from '@mui/icons-material';
6
+ import { Stack } from '@mui/material';
7
+ import _ from 'lodash';
8
+ import { FilterPayload, Identifier, RaRecord, useInput } from 'ra-core';
9
+ import { ReactElement, useCallback, useMemo } from 'react';
10
+ import { EntityField, EntityLookupDialog, RecordRepresentationType } from './common';
11
+
12
+ type ReferenceManyLookupInputProps = {
13
+ filter?: FilterPayload;
14
+ filterDefaultValues?: object;
15
+ filters?: ReactElement | ReactElement[];
16
+ recordRepresentation?: RecordRepresentationType;
17
+ reference: string;
18
+ } & LabeledInputProps;
19
+
20
+ function ReferenceManyLookupInput(props: ReferenceManyLookupInputProps): JSX.Element {
21
+ const {
22
+ children,
23
+ filter: propFilter,
24
+ filterDefaultValues,
25
+ filters: propFilters,
26
+ recordRepresentation,
27
+ reference,
28
+ source
29
+ } = props;
30
+ const { field } = useInput({ source });
31
+ const { value, onChange } = field ?? {};
32
+ const hasValue = !_.isEmpty(value);
33
+ const { open, handleOpen, handleClose } = useDialogState(false);
34
+ const filter = useMemo(
35
+ () =>
36
+ _.chain(propFilter ?? {})
37
+ .clone()
38
+ .extend({ id__nin: value })
39
+ .value(),
40
+ [propFilter, value]
41
+ );
42
+ const filters = useMemo(
43
+ () => propFilters ?? [<SearchInput key="keyword" source="keyword" alwaysOn />],
44
+ [propFilters]
45
+ );
46
+
47
+ const onAdd = useCallback(
48
+ (ids: Identifier[]) => {
49
+ const newValue = _.union(value ?? [], ids);
50
+ handleClose();
51
+ onChange(newValue);
52
+ return newValue;
53
+ },
54
+ [onChange, handleClose, value]
55
+ );
56
+
57
+ const onDelete = useCallback((record: RaRecord) => onChange(_.without(value ?? [], record.id)), [onChange, value]);
58
+
59
+ return (
60
+ <LabeledInput {...props}>
61
+ <Stack alignItems="center" direction="row" spacing={1}>
62
+ {hasValue
63
+ ? _.map(value ?? [], (id, index) => (
64
+ <EntityField
65
+ key={index}
66
+ id={id}
67
+ onDelete={onDelete}
68
+ recordRepresentation={recordRepresentation}
69
+ resource={reference}
70
+ />
71
+ ))
72
+ : null}
73
+ <IconButton onClick={handleOpen}>
74
+ <AddCircleRounded />
75
+ </IconButton>
76
+ <EntityLookupDialog
77
+ onCancel={handleClose}
78
+ onConfirm={onAdd}
79
+ multiple={true}
80
+ slotProps={{
81
+ dialog: { open, onClose: handleClose },
82
+ list: {
83
+ filter,
84
+ filterDefaultValues,
85
+ resource: reference
86
+ },
87
+ listToolbar: {
88
+ filters: filters
89
+ }
90
+ }}
91
+ >
92
+ {children}
93
+ </EntityLookupDialog>
94
+ </Stack>
95
+ </LabeledInput>
96
+ );
97
+ }
98
+
99
+ export { ReferenceManyLookupInput };
@@ -0,0 +1,182 @@
1
+ import { Pagination, PaginationProps } from '@/components/Pagination';
2
+ import { FunctionField } from '@/components/ra-fields';
3
+ import { Datagrid, ListToolbar, ListToolbarProps } from '@/components/ra-lists';
4
+ import { DatagridProps } from '@/components/ra-lists/Datagrid/Datagrid';
5
+ import { useUuid } from '@/hooks';
6
+ import { CheckBox, CheckBoxOutlineBlankOutlined, Error } from '@mui/icons-material';
7
+ import {
8
+ Button,
9
+ Chip,
10
+ Dialog,
11
+ DialogActions,
12
+ DialogContent,
13
+ DialogContentProps,
14
+ DialogProps,
15
+ Stack
16
+ } from '@mui/material';
17
+ import _ from 'lodash';
18
+ import {
19
+ Identifier,
20
+ ListBase,
21
+ ListControllerProps,
22
+ RaRecord,
23
+ RecordRepresentation,
24
+ WithListContext,
25
+ useGetMany,
26
+ useGetRecordRepresentation,
27
+ useTranslate
28
+ } from 'ra-core';
29
+ import { PropsWithChildren, useCallback } from 'react';
30
+
31
+ type RecordRepresentationType = (record: RaRecord) => string;
32
+ type EntityFieldProps = {
33
+ id: Identifier;
34
+ onClick?: (record: RaRecord) => void;
35
+ onDelete?: (record: RaRecord) => void;
36
+ recordRepresentation?: RecordRepresentationType;
37
+ resource: string;
38
+ };
39
+ type EntityLookupDialogProps = PropsWithChildren<{
40
+ onCancel: () => void;
41
+ onConfirm: (selectedIds: Identifier[]) => void;
42
+ multiple: boolean;
43
+ slotProps?: {
44
+ dataGrid?: DatagridProps;
45
+ dialog?: DialogProps;
46
+ dialogContent?: DialogContentProps;
47
+ list?: ListControllerProps;
48
+ listToolbar?: Pick<ListToolbarProps, 'filters'>;
49
+ pagination?: PaginationProps;
50
+ };
51
+ }>;
52
+
53
+ function EntityField(props: EntityFieldProps): JSX.Element | null {
54
+ const { id, onClick: onClickCb, onDelete: onDeleteCb, recordRepresentation, resource } = props;
55
+ const fallbackRecordRepresentation = useGetRecordRepresentation(resource);
56
+ const { data, isLoading, error } = useGetMany<RaRecord>(resource, { ids: [id] });
57
+ const record = _.find(data ?? [], { id });
58
+ const canDelete = !_.isNil(record) && _.isFunction(onDeleteCb);
59
+ const onDelete = useCallback(() => {
60
+ if (canDelete) {
61
+ onDeleteCb(record);
62
+ }
63
+ }, [onDeleteCb, record, canDelete]);
64
+ const canClick = !_.isNil(record) && _.isFunction(onClickCb);
65
+ const onClick = useCallback(() => {
66
+ if (canClick) {
67
+ onClickCb(record);
68
+ }
69
+ }, [onClickCb, record, canClick]);
70
+
71
+ if (isLoading) {
72
+ return null;
73
+ } else if (error || _.isNil(record)) {
74
+ return <Error color="error" />;
75
+ } else {
76
+ const label = _.isFunction(recordRepresentation)
77
+ ? recordRepresentation(record)
78
+ : fallbackRecordRepresentation(record);
79
+ return <Chip label={label} onDelete={canDelete ? onDelete : undefined} onClick={canClick ? onClick : undefined} />;
80
+ }
81
+ }
82
+
83
+ function EntityLookupDialog(props: EntityLookupDialogProps): JSX.Element {
84
+ const uuid = useUuid();
85
+ const t = useTranslate();
86
+ const { children, multiple, onCancel, onConfirm, slotProps } = props;
87
+
88
+ const {
89
+ dialogContent: dialogContentProps = {},
90
+ listToolbar: listToolbarProps = {},
91
+ pagination: paginationProps
92
+ } = slotProps ?? {};
93
+
94
+ const listProps = _.chain(slotProps?.list)
95
+ .defaults({ disableSyncWithLocation: true, emptyWhileLoading: true, exporter: false })
96
+ .value();
97
+
98
+ const hasListToolbar = !_.isNil(listToolbarProps.filters);
99
+
100
+ const dialogProps = _.chain(slotProps?.dialog)
101
+ .defaults({ disableEscapeKeyDown: true, fullWidth: true, keepMounted: false, open: false })
102
+ .value();
103
+
104
+ const dataGridProps = _.chain(slotProps?.dataGrid)
105
+ .defaults({})
106
+ .extend({
107
+ bulkActionButtons: false,
108
+ rowClick: 'toggleSelection'
109
+ })
110
+ .value();
111
+
112
+ const updateSelection = useCallback(
113
+ (selectedIds: Identifier[], id: Identifier): Identifier[] => {
114
+ if (multiple) {
115
+ return _.includes(selectedIds, id) ? _.without(selectedIds, id) : _.concat(selectedIds, id);
116
+ } else {
117
+ return _.includes(selectedIds, id) ? [] : [id];
118
+ }
119
+ },
120
+ [multiple]
121
+ );
122
+ return (
123
+ <ListBase {...listProps} storeKey={`reference-lookup-input-${uuid}`}>
124
+ <WithListContext
125
+ render={({ onSelect, selectedIds, onUnselectItems }) => {
126
+ return (
127
+ <Dialog
128
+ {...dialogProps}
129
+ onClose={() => {
130
+ onUnselectItems();
131
+ onCancel();
132
+ }}
133
+ >
134
+ <DialogContent {...dialogContentProps}>
135
+ <Stack spacing={2} flexDirection="column">
136
+ {hasListToolbar ? <ListToolbar {...listToolbarProps} /> : null}
137
+ <Datagrid {...dataGridProps} onToggleItem={(id) => onSelect(updateSelection(selectedIds, id))}>
138
+ <FunctionField
139
+ render={(record) =>
140
+ _.includes(selectedIds, record.id) ? <CheckBox /> : <CheckBoxOutlineBlankOutlined />
141
+ }
142
+ />
143
+ {children ?? (
144
+ <FunctionField
145
+ label={t('ra.input.referenceLookup.dialog.defaultField')}
146
+ render={(record) => <RecordRepresentation record={record} />}
147
+ />
148
+ )}
149
+ </Datagrid>
150
+ <Pagination {...paginationProps} />
151
+ <DialogActions>
152
+ <Button
153
+ onClick={() => {
154
+ onUnselectItems();
155
+ onCancel();
156
+ }}
157
+ >
158
+ {t('ra.input.referenceLookup.dialog.cancel')}
159
+ </Button>
160
+ <Button
161
+ disabled={_.isEmpty(selectedIds)}
162
+ onClick={() => {
163
+ onConfirm(selectedIds);
164
+ onUnselectItems();
165
+ }}
166
+ color="primary"
167
+ >
168
+ {t('ra.input.referenceLookup.dialog.confirm')}
169
+ </Button>
170
+ </DialogActions>
171
+ </Stack>
172
+ </DialogContent>
173
+ </Dialog>
174
+ );
175
+ }}
176
+ />
177
+ </ListBase>
178
+ );
179
+ }
180
+
181
+ export { EntityField, EntityLookupDialog };
182
+ export type { EntityFieldProps, EntityLookupDialogProps, RecordRepresentationType };
@@ -0,0 +1,2 @@
1
+ export * from './ReferenceLookupInput';
2
+ export * from './ReferenceManyLookupInput';
@@ -1,14 +1,16 @@
1
1
  import { ReferenceManyField, ReferenceManyFieldProps } from '@/components/ra-fields';
2
- import { ReactElement } from 'react';
2
+ import { PropsWithChildren, ReactElement } from 'react';
3
3
  import { ListToolbar, Pagination, ResourceContextProvider } from 'react-admin';
4
4
 
5
- type ReferenceManyInputProps = {
6
- reference: string;
7
- target: string;
8
- children: React.ReactNode;
9
- filters?: ReactElement;
10
- actions?: ReactElement;
11
- } & ReferenceManyFieldProps;
5
+ type ReferenceManyInputProps = PropsWithChildren<
6
+ {
7
+ reference: string;
8
+ target: string;
9
+ children: React.ReactNode;
10
+ filters?: ReactElement;
11
+ actions?: ReactElement;
12
+ } & ReferenceManyFieldProps
13
+ >;
12
14
 
13
15
  function ReferenceManyInput({
14
16
  reference,
@@ -16,6 +16,7 @@ export * from './RadioButtonGroupInput';
16
16
  export * from './RecordInput';
17
17
  export * from './ReferenceArrayInput';
18
18
  export * from './ReferenceInput';
19
+ export * from './ReferenceLookupInput';
19
20
  export * from './ReferenceManyInput';
20
21
  export * from './SearchInput';
21
22
  export * from './SelectArrayInput';
@@ -145,7 +145,7 @@ function Empty({
145
145
  ) : null)}
146
146
  </Box>
147
147
  <StyledToolbar className={EmptyClasses.toolbar}>
148
- {actions || (canCreate ? <CreateButton disableFloatingButton /> : null)}
148
+ {actions || (canCreate ? <CreateButton variant="contained" size="medium" disableFloatingButton /> : null)}
149
149
  </StyledToolbar>
150
150
  </Root>
151
151
  );
@@ -1,4 +1,5 @@
1
1
  export * from './mui';
2
+ export * from './useDialogState';
2
3
  export * from './useLocalStorage';
3
4
  export * from './useLocalizedValue';
4
5
  export * from './useMemoizedObject';
@@ -6,3 +7,4 @@ export * from './usePopoverState';
6
7
  export * from './useRefDimensions';
7
8
  export * from './useResourceTitle';
8
9
  export * from './useSystemTheme';
10
+ export * from './useUuid';
@@ -0,0 +1,27 @@
1
+ import { useCallback, useState } from 'react';
2
+
3
+ type UseDialogStateReturn = {
4
+ open: boolean;
5
+ setOpen: (open: boolean) => void;
6
+ handleOpen: () => void;
7
+ handleClose: () => void;
8
+ handleToggle: () => void;
9
+ };
10
+
11
+ function useDialogState(initialState: boolean = false): UseDialogStateReturn {
12
+ const [open, setOpen] = useState(Boolean(initialState));
13
+ const safeSetOpen = useCallback((open: boolean) => setOpen(Boolean(open)), [setOpen]);
14
+ const handleOpen = useCallback(() => setOpen(true), [setOpen]);
15
+ const handleClose = useCallback(() => setOpen(false), [setOpen]);
16
+ const handleToggle = useCallback(() => setOpen((prev) => !prev), [setOpen]);
17
+
18
+ return {
19
+ open,
20
+ setOpen: safeSetOpen,
21
+ handleOpen,
22
+ handleClose,
23
+ handleToggle
24
+ };
25
+ }
26
+
27
+ export { useDialogState };
@@ -0,0 +1,14 @@
1
+ import { uuid as getUuid } from '@/utils';
2
+ import { useEffect, useState } from 'react';
3
+
4
+ function useUuid(uuid?: string): string {
5
+ const [_uuid, setUuid] = useState(uuid ?? getUuid());
6
+
7
+ useEffect(() => {
8
+ setUuid(uuid ?? getUuid());
9
+ }, [uuid]);
10
+
11
+ return _uuid;
12
+ }
13
+
14
+ export { useUuid };