@applica-software-guru/react-admin 1.5.294 → 1.5.296

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-buttons/Button.d.ts +7 -1
  2. package/dist/components/ra-buttons/Button.d.ts.map +1 -1
  3. package/dist/components/ra-buttons/CreateButton.d.ts +45 -0
  4. package/dist/components/ra-buttons/CreateButton.d.ts.map +1 -0
  5. package/dist/components/ra-buttons/index.d.ts +1 -0
  6. package/dist/components/ra-buttons/index.d.ts.map +1 -1
  7. package/dist/components/ra-forms/TableForm/{CreateButton.d.ts → TableCreateButton.d.ts} +3 -3
  8. package/dist/components/ra-forms/TableForm/TableCreateButton.d.ts.map +1 -0
  9. package/dist/components/ra-forms/TableForm/TableFormIterator.d.ts +2 -2
  10. package/dist/components/ra-forms/TableForm/TableFormIterator.d.ts.map +1 -1
  11. package/dist/components/ra-forms/TableForm/index.d.ts +1 -1
  12. package/dist/components/ra-forms/TableForm/index.d.ts.map +1 -1
  13. package/dist/components/ra-lists/List.d.ts.map +1 -1
  14. package/dist/components/ra-lists/ListView.d.ts.map +1 -1
  15. package/dist/index.d.ts +1 -1
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/react-admin.cjs.js +52 -52
  18. package/dist/react-admin.cjs.js.gz +0 -0
  19. package/dist/react-admin.cjs.js.map +1 -1
  20. package/dist/react-admin.es.js +7650 -7502
  21. package/dist/react-admin.es.js.gz +0 -0
  22. package/dist/react-admin.es.js.map +1 -1
  23. package/dist/react-admin.umd.js +52 -52
  24. package/dist/react-admin.umd.js.gz +0 -0
  25. package/dist/react-admin.umd.js.map +1 -1
  26. package/package.json +1 -1
  27. package/src/components/ra-buttons/Button.tsx +9 -2
  28. package/src/components/ra-buttons/CreateButton.tsx +169 -0
  29. package/src/components/ra-buttons/index.ts +1 -0
  30. package/src/components/ra-forms/TableForm/{CreateButton.tsx → TableCreateButton.tsx} +2 -2
  31. package/src/components/ra-forms/TableForm/TableFormIterator.tsx +4 -4
  32. package/src/components/ra-forms/TableForm/index.ts +1 -1
  33. package/src/components/ra-lists/List.tsx +8 -3
  34. package/src/components/ra-lists/ListView.tsx +72 -8
  35. package/src/index.ts +4 -1
  36. package/dist/components/ra-forms/TableForm/CreateButton.d.ts.map +0 -1
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.294"
109
+ "version": "1.5.296"
110
110
  }
@@ -1,6 +1,7 @@
1
1
  import { Button as MuiButton } from '@mui/material';
2
2
  import { styled } from '@mui/material/styles';
3
- import { LocationDescriptor, Button as RaButton, ButtonProps as RaButtonProps, useTranslate } from 'react-admin';
3
+ import { Button as RaButton, ButtonProps as RaButtonProps, useTranslate } from 'react-admin';
4
+ import { Path } from 'react-router';
4
5
 
5
6
  type ButtonProps = RaButtonProps & {
6
7
  /**
@@ -80,5 +81,11 @@ function Button(props: ButtonProps): JSX.Element {
80
81
  return <RaButton {...props} />;
81
82
  }
82
83
 
84
+ type LocationDescriptor = Partial<Path> & {
85
+ redirect?: boolean;
86
+ state?: any;
87
+ replace?: boolean;
88
+ };
89
+
83
90
  export { Button };
84
- export type { ButtonProps };
91
+ export type { ButtonProps, LocationDescriptor };
@@ -0,0 +1,169 @@
1
+ import * as React from 'react';
2
+ import ContentAdd from '@mui/icons-material/Add';
3
+ import { Fab, Theme, useMediaQuery } from '@mui/material';
4
+ import { styled } from '@mui/material/styles';
5
+ import clsx from 'clsx';
6
+ import isEqual from 'lodash/isEqual';
7
+ import merge from 'lodash/merge';
8
+ import PropTypes from 'prop-types';
9
+ import { useCreatePath, useResourceContext, useTranslate } from 'ra-core';
10
+ import { Link, To } from 'react-router-dom';
11
+
12
+ import { Button, ButtonProps, LocationDescriptor } from './Button';
13
+
14
+ /**
15
+ * Opens the Create view of a given resource
16
+ *
17
+ * Renders as a regular button on desktop, and a Floating Action Button
18
+ * on mobile.
19
+ *
20
+ * @example // basic usage
21
+ * import { CreateButton } from 'react-admin';
22
+ *
23
+ * const CommentCreateButton = () => (
24
+ * <CreateButton label="Create comment" />
25
+ * );
26
+ */
27
+ function CreateBtn(props: CreateButtonProps) {
28
+ const {
29
+ className,
30
+ icon = defaultIcon,
31
+ label = 'ra.action.create',
32
+ resource: resourceProp,
33
+ scrollToTop = true,
34
+ variant,
35
+ to: locationDescriptor,
36
+ state: initialState = {},
37
+ disableFloatingButton = false,
38
+ ...rest
39
+ } = props;
40
+
41
+ const resource = useResourceContext(props);
42
+ const createPath = useCreatePath();
43
+ const translate = useTranslate();
44
+ const isSmall = useMediaQuery((theme: Theme) => theme.breakpoints.down('md'));
45
+ const state = merge({}, scrollStates.get(String(scrollToTop)), initialState);
46
+ // Duplicated behaviour of Button component (legacy use) which will be removed in v5.
47
+ const linkParams = getLinkParams(locationDescriptor);
48
+
49
+ return !disableFloatingButton && isSmall ? (
50
+ <StyledFab
51
+ component={Link}
52
+ to={createPath({ resource, type: 'create' })}
53
+ state={state}
54
+ // @ts-ignore FabProps ships its own runtime palette `FabPropsColorOverrides` provoking an overlap error with `ButtonProps`
55
+ color="primary"
56
+ className={clsx(CreateButtonClasses.floating, className)}
57
+ aria-label={label ? translate(label) : 'ra.action.create'}
58
+ {...rest}
59
+ {...linkParams}
60
+ >
61
+ {icon}
62
+ </StyledFab>
63
+ ) : (
64
+ <StyledButton
65
+ component={Link}
66
+ to={createPath({ resource, type: 'create' })}
67
+ state={state}
68
+ className={clsx(CreateButtonClasses.root, className)}
69
+ label={label}
70
+ variant={variant}
71
+ {...(rest as any)}
72
+ {...linkParams}
73
+ >
74
+ {icon}
75
+ </StyledButton>
76
+ );
77
+ }
78
+
79
+ const defaultIcon = <ContentAdd />;
80
+
81
+ // avoids using useMemo to get a constant value for the link state
82
+ const scrollStates = new Map([
83
+ ['true', { _scrollToTop: true }],
84
+ ['false', {}]
85
+ ]);
86
+
87
+ interface Props {
88
+ resource?: string;
89
+ icon?: React.ReactElement;
90
+ scrollToTop?: boolean;
91
+ to?: LocationDescriptor | To;
92
+ state?: any;
93
+ }
94
+
95
+ interface DisableFloatingButtonProps {
96
+ disableFloatingButton?: boolean;
97
+ }
98
+
99
+ type CreateButtonProps = DisableFloatingButtonProps & Props & Omit<ButtonProps, 'to'>;
100
+
101
+ CreateBtn.propTypes = {
102
+ resource: PropTypes.string,
103
+ className: PropTypes.string,
104
+ icon: PropTypes.element,
105
+ label: PropTypes.string
106
+ };
107
+
108
+ const PREFIX = 'RaCreateButton';
109
+
110
+ const CreateButtonClasses = {
111
+ root: `${PREFIX}-root`,
112
+ floating: `${PREFIX}-floating`
113
+ };
114
+
115
+ const StyledFab = styled(Fab, {
116
+ name: PREFIX,
117
+ overridesResolver: (_props, styles) => styles.root
118
+ })(({ theme }) => ({
119
+ [`&.${CreateButtonClasses.floating}`]: {
120
+ color: theme.palette.getContrastText(theme.palette.primary.main),
121
+ margin: 0,
122
+ top: 'auto',
123
+ right: 20,
124
+ bottom: 60,
125
+ left: 'auto',
126
+ position: 'fixed',
127
+ zIndex: 1000
128
+ }
129
+ })) as unknown as typeof Fab;
130
+
131
+ const StyledButton = styled(Button, {
132
+ name: PREFIX,
133
+ overridesResolver: (_props, styles) => styles.root
134
+ })({});
135
+
136
+ function arePropsEqual(prevProps: CreateButtonProps, nextProps: CreateButtonProps) {
137
+ return (
138
+ prevProps.resource === nextProps.resource &&
139
+ prevProps.label === nextProps.label &&
140
+ prevProps.translate === nextProps.translate &&
141
+ prevProps.disabled === nextProps.disabled &&
142
+ isEqual(prevProps.to, nextProps.to) &&
143
+ isEqual(prevProps.state, nextProps.state)
144
+ );
145
+ }
146
+
147
+ const CreateButton = React.memo(CreateBtn, arePropsEqual);
148
+
149
+ function getLinkParams(locationDescriptor?: LocationDescriptor | string) {
150
+ // eslint-disable-next-line eqeqeq
151
+ if (locationDescriptor == undefined) {
152
+ return undefined;
153
+ }
154
+
155
+ if (typeof locationDescriptor === 'string') {
156
+ return { to: locationDescriptor };
157
+ }
158
+
159
+ const { redirect, replace, state, ...to } = locationDescriptor;
160
+ return {
161
+ to,
162
+ redirect,
163
+ replace,
164
+ state
165
+ };
166
+ }
167
+
168
+ export { CreateButton, CreateButtonClasses };
169
+ export type { CreateButtonProps };
@@ -1,4 +1,5 @@
1
1
  export * from './Button';
2
+ export * from './CreateButton';
2
3
  export * from './CreateInDialogButton';
3
4
  export * from './EditInDialogButton';
4
5
  export * from './ImpersonateUserButton';
@@ -13,7 +13,7 @@ interface CreateButtonProps {
13
13
  children: React.ReactNode;
14
14
  }
15
15
 
16
- function CreateButton(props: CreateButtonProps): JSX.Element {
16
+ function TableCreateButton(props: CreateButtonProps): JSX.Element {
17
17
  const { label, disableAdd, inset, source, template } = props;
18
18
  const [open, setOpen] = React.useState(false);
19
19
  const { append } = useArrayInput();
@@ -55,4 +55,4 @@ function CreateButton(props: CreateButtonProps): JSX.Element {
55
55
  );
56
56
  }
57
57
 
58
- export { CreateButton };
58
+ export { TableCreateButton };
@@ -1,6 +1,6 @@
1
1
  import { Field } from './Field';
2
2
  import { AddTableRow } from './AddTableRow';
3
- import { CreateButton } from './CreateButton';
3
+ import { TableCreateButton } from './TableCreateButton';
4
4
  import { EditButton } from './EditButton';
5
5
  import { ActionsMenu } from '@/components/ActionsMenu';
6
6
  import { TableFormIteratorContext } from '@/components/ra-forms/TableForm/TableFormIteratorContext';
@@ -167,7 +167,7 @@ function RawTableFormIterator(props: TableFormIteratorProps): ReactElement | nul
167
167
  disableAdd,
168
168
  template,
169
169
  onClick:
170
- addButton?.type !== CreateButton
170
+ addButton?.type !== TableCreateButton
171
171
  ? handleAddButtonClick((props?.addButton as any)?.props?.onClick)
172
172
  : undefined,
173
173
  inset
@@ -349,7 +349,7 @@ type ITableForm = typeof TableFormIterator & {
349
349
  * </Grid>
350
350
  * </Grid>
351
351
  */
352
- CreateButton: typeof CreateButton;
352
+ CreateButton: typeof TableCreateButton;
353
353
 
354
354
  /**
355
355
  * TableFormiterator allows a child EditButton which will render an edit button in the ActionsMenu of each row.
@@ -407,7 +407,7 @@ type ITableForm = typeof TableFormIterator & {
407
407
 
408
408
  const DefaultTableForm = TableFormIterator as ITableForm;
409
409
 
410
- DefaultTableForm.CreateButton = CreateButton;
410
+ DefaultTableForm.CreateButton = TableCreateButton;
411
411
  DefaultTableForm.EditButton = EditButton;
412
412
  DefaultTableForm.Field = Field;
413
413
 
@@ -1,7 +1,7 @@
1
1
  export * from './AddTableRow';
2
- export * from './CreateButton';
3
2
  export * from './EditButton';
4
3
  export * from './Field';
4
+ export * from './TableCreateButton';
5
5
  export * from './TableFormIterator';
6
6
  export * from './TableFormIteratorContext';
7
7
  export * from './TableFormIteratorItem';
@@ -2,7 +2,7 @@ import { MainCard } from '@/components/MainCard';
2
2
  import { ListView } from '@/components/ra-lists/ListView';
3
3
  import { styled } from '@mui/system';
4
4
  import { ListBase, RaRecord } from 'ra-core';
5
- import { ReactElement } from 'react';
5
+ import React, { ReactElement } from 'react';
6
6
  import { ListProps } from 'react-admin';
7
7
  import { Pagination } from '@/components/Pagination/Pagination';
8
8
 
@@ -122,6 +122,9 @@ const StyledList = styled(RaList, { slot: 'root' })(({ theme }) => ({
122
122
  minHeight: 80,
123
123
  alignItems: 'center',
124
124
  padding: theme.spacing(2.5),
125
+ [theme.breakpoints.down('sm')]: {
126
+ flexDirection: 'row'
127
+ },
125
128
  '& form': {
126
129
  alignItems: 'center',
127
130
  minHeight: 'auto',
@@ -190,10 +193,12 @@ const StyledList = styled(RaList, { slot: 'root' })(({ theme }) => ({
190
193
  }));
191
194
 
192
195
  function List(props: ListProps): ReactElement {
196
+ const Wrapper = props.aside ? React.Fragment : MainCard;
197
+
193
198
  return (
194
- <MainCard content={false}>
199
+ <Wrapper {...(!props.aside && { content: false })}>
195
200
  <StyledList {...props} pagination={<Pagination />} />
196
- </MainCard>
201
+ </Wrapper>
197
202
  );
198
203
  }
199
204
 
@@ -1,14 +1,20 @@
1
1
  /* eslint-disable filenames/match-regex */
2
2
  import { Error } from '@/components/Layout/Error';
3
- import { Card } from '@mui/material';
4
- import { styled } from '@mui/material/styles';
3
+ import { Card, CardContent } from '@mui/material';
4
+ import { styled, useTheme } from '@mui/material/styles';
5
5
  import { SxProps } from '@mui/system';
6
6
  import clsx from 'clsx';
7
7
  import { RaRecord, useListContext } from 'ra-core';
8
8
  import { ElementType, ReactElement, ReactNode, cloneElement } from 'react';
9
9
  import * as React from 'react';
10
- import { ListActions as DefaultActions, Pagination as DefaultPagination, Empty, ListToolbar, Title } from 'react-admin';
11
-
10
+ import {
11
+ ListActions as DefaultActions,
12
+ Pagination as DefaultPagination,
13
+ Empty,
14
+ ListToolbar,
15
+ SavedQueriesListClasses,
16
+ Title
17
+ } from 'react-admin';
12
18
  const defaultActions = <DefaultActions />;
13
19
  const defaultPagination = <DefaultPagination />;
14
20
  const defaultEmpty = <Empty />;
@@ -31,6 +37,8 @@ function ListView<RecordType extends RaRecord = any>(props: ListViewProps): Reac
31
37
  ...rest
32
38
  } = props;
33
39
  const { defaultTitle, data, error, isLoading, filterValues, resource } = useListContext<RecordType>(props);
40
+ const theme = useTheme() as any;
41
+ const isAsideValidElement = React.isValidElement(aside);
34
42
 
35
43
  if (!children || (!data && isLoading && emptyWhileLoading)) {
36
44
  return null;
@@ -38,7 +46,19 @@ function ListView<RecordType extends RaRecord = any>(props: ListViewProps): Reac
38
46
 
39
47
  function renderList() {
40
48
  return (
41
- <div className={ListClasses.main}>
49
+ <div
50
+ className={ListClasses.main}
51
+ style={{
52
+ border: isAsideValidElement ? '1px solid' : 'none',
53
+ borderRadius: isAsideValidElement ? 4 : 0,
54
+ borderColor: isAsideValidElement
55
+ ? theme.palette.mode === 'dark'
56
+ ? theme.palette.divider
57
+ : theme.palette.grey.A800
58
+ : 'transparent',
59
+ backgroundColor: isAsideValidElement ? theme.palette.background.paper : 'transparent'
60
+ }}
61
+ >
42
62
  {filters || actions ? (
43
63
  <ListToolbar className={ListClasses.actions} filters={filters} actions={actions} hasCreate={hasCreate} />
44
64
  ) : null}
@@ -77,17 +97,46 @@ function ListView<RecordType extends RaRecord = any>(props: ListViewProps): Reac
77
97
  <Root className={clsx('list-page', className)} {...rest}>
78
98
  <Title title={title} defaultTitle={defaultTitle} preferenceKey={`${resource}.list.title`} />
79
99
  {shouldRenderEmptyPage ? renderEmpty() : renderList()}
80
- {aside}
100
+ {isAsideValidElement ? <AsideCard aside={aside} /> : null}
81
101
  </Root>
82
102
  );
83
103
  }
84
104
 
105
+ interface AsideCardProps {
106
+ aside: React.ReactElement;
107
+ }
108
+
109
+ function AsideCard({ aside }: AsideCardProps): ReactElement {
110
+ const order = (aside?.props as { order?: number })?.order ?? -1;
111
+ const theme = useTheme() as any;
112
+
113
+ return (
114
+ <Card
115
+ className={ListClasses.asideCard}
116
+ sx={{
117
+ order,
118
+ mr: order === -1 ? 2 : 0,
119
+ ml: order !== -1 ? 2 : 0,
120
+ width: 200,
121
+ border: '1px solid',
122
+ borderRadius: 1,
123
+ borderColor: theme.palette.mode === 'dark' ? theme.palette.divider : theme.palette.grey.A800,
124
+ backgroundColor: theme.palette.background.paper,
125
+ backgroundImage: 'none'
126
+ }}
127
+ >
128
+ <CardContent sx={{ pt: 1 }}>{cloneElement(aside, {})}</CardContent>
129
+ </Card>
130
+ );
131
+ }
132
+
85
133
  const PREFIX = 'RaList';
86
134
  const ListClasses = {
87
135
  main: `${PREFIX}-main`,
88
136
  content: `${PREFIX}-content`,
89
137
  actions: `${PREFIX}-actions`,
90
- noResults: `${PREFIX}-noResults`
138
+ noResults: `${PREFIX}-noResults`,
139
+ asideCard: `${PREFIX}-asideCard`
91
140
  };
92
141
 
93
142
  interface ListViewProps {
@@ -356,7 +405,22 @@ const Root = styled('div', {
356
405
 
357
406
  [`& .${ListClasses.actions}`]: {},
358
407
 
359
- [`& .${ListClasses.noResults}`]: {}
408
+ [`& .${ListClasses.noResults}`]: {},
409
+
410
+ [`& .${ListClasses.asideCard}`]: {
411
+ [theme.breakpoints.down('md')]: {
412
+ display: 'none'
413
+ },
414
+ [`& .${SavedQueriesListClasses.floatingIcon}`]: {
415
+ fontSize: '1.125rem'
416
+ },
417
+ [`& .${SavedQueriesListClasses.floatingTooltip}`]: {
418
+ top: '-1.2em'
419
+ },
420
+ '& form': {
421
+ marginTop: theme.spacing(2)
422
+ }
423
+ }
360
424
  }));
361
425
 
362
426
  export { ListView };
package/src/index.ts CHANGED
@@ -15,7 +15,6 @@ export {
15
15
  BulkDeleteWithConfirmButton,
16
16
  ChipField,
17
17
  Confirm,
18
- CreateButton,
19
18
  CreateContextProvider,
20
19
  CustomRoutes,
21
20
  DeleteWithConfirmButton,
@@ -24,6 +23,9 @@ export {
24
23
  EditContextProvider,
25
24
  FieldTitle,
26
25
  FilterButton,
26
+ FilterList,
27
+ FilterListItem,
28
+ FilterLiveSearch,
27
29
  Form,
28
30
  FormDataConsumer,
29
31
  HttpError,
@@ -38,6 +40,7 @@ export {
38
40
  Resource,
39
41
  ResourceContextProvider,
40
42
  SaveButton,
43
+ SavedQueriesList,
41
44
  SimpleFormIteratorContext,
42
45
  SimpleShowLayout,
43
46
  SingleFieldList,
@@ -1 +0,0 @@
1
- {"version":3,"file":"CreateButton.d.ts","sourceRoot":"","sources":["../../../../../src/components/ra-forms/TableForm/CreateButton.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,iBAAiB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,iBAAS,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,GAAG,CAAC,OAAO,CAwC3D;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}