@proteinjs/ui 2.0.2 → 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 (80) hide show
  1. package/.eslintrc.js +20 -0
  2. package/.prettierignore +4 -0
  3. package/.prettierrc +8 -0
  4. package/CHANGELOG.md +16 -14
  5. package/LICENSE +21 -0
  6. package/dist/generated/index.js +1 -1
  7. package/dist/generated/index.js.map +1 -1
  8. package/dist/src/container/AccountIconButton.d.ts +1 -1
  9. package/dist/src/container/AccountIconButton.d.ts.map +1 -1
  10. package/dist/src/container/AccountIconButton.js +13 -6
  11. package/dist/src/container/AccountIconButton.js.map +1 -1
  12. package/dist/src/container/NavMenu.d.ts.map +1 -1
  13. package/dist/src/container/NavMenu.js +9 -9
  14. package/dist/src/container/NavMenu.js.map +1 -1
  15. package/dist/src/container/PageContainer.d.ts +1 -1
  16. package/dist/src/container/PageContainer.d.ts.map +1 -1
  17. package/dist/src/container/PageContainer.js +12 -7
  18. package/dist/src/container/PageContainer.js.map +1 -1
  19. package/dist/src/form/Field.d.ts.map +1 -1
  20. package/dist/src/form/Field.js +4 -2
  21. package/dist/src/form/Field.js.map +1 -1
  22. package/dist/src/form/Form.d.ts.map +1 -1
  23. package/dist/src/form/Form.js +75 -40
  24. package/dist/src/form/Form.js.map +1 -1
  25. package/dist/src/form/FormButton.d.ts.map +1 -1
  26. package/dist/src/form/FormButton.js +1 -1
  27. package/dist/src/form/FormButton.js.map +1 -1
  28. package/dist/src/form/container/FormPage.d.ts.map +1 -1
  29. package/dist/src/form/container/FormPage.js.map +1 -1
  30. package/dist/src/form/container/FormPaper.js +1 -1
  31. package/dist/src/form/container/FormPaper.js.map +1 -1
  32. package/dist/src/form/fields/TextField.d.ts.map +1 -1
  33. package/dist/src/form/fields/TextField.js +8 -6
  34. package/dist/src/form/fields/TextField.js.map +1 -1
  35. package/dist/src/list/NestedList.d.ts.map +1 -1
  36. package/dist/src/list/NestedList.js +10 -10
  37. package/dist/src/list/NestedList.js.map +1 -1
  38. package/dist/src/router/Page.d.ts.map +1 -1
  39. package/dist/src/router/Router.d.ts.map +1 -1
  40. package/dist/src/router/Router.js +11 -7
  41. package/dist/src/router/Router.js.map +1 -1
  42. package/dist/src/router/createUrlParams.d.ts.map +1 -1
  43. package/dist/src/router/createUrlParams.js +2 -1
  44. package/dist/src/router/createUrlParams.js.map +1 -1
  45. package/dist/src/router/withRouter.d.ts.map +1 -1
  46. package/dist/src/router/withRouter.js +1 -1
  47. package/dist/src/router/withRouter.js.map +1 -1
  48. package/dist/src/table/Table.d.ts +1 -1
  49. package/dist/src/table/Table.d.ts.map +1 -1
  50. package/dist/src/table/Table.js +31 -23
  51. package/dist/src/table/Table.js.map +1 -1
  52. package/dist/src/table/TableButton.d.ts.map +1 -1
  53. package/dist/src/table/TableLoader.d.ts.map +1 -1
  54. package/dist/src/table/TableToolbar.d.ts.map +1 -1
  55. package/dist/src/table/TableToolbar.js +10 -7
  56. package/dist/src/table/TableToolbar.js.map +1 -1
  57. package/generated/index.ts +1 -1
  58. package/index.ts +1 -1
  59. package/jest.config.js +8 -17
  60. package/package.json +56 -50
  61. package/src/container/AccountIconButton.tsx +103 -102
  62. package/src/container/NavMenu.tsx +20 -21
  63. package/src/container/PageContainer.tsx +110 -80
  64. package/src/form/Field.tsx +42 -35
  65. package/src/form/Form.tsx +370 -351
  66. package/src/form/FormButton.tsx +24 -22
  67. package/src/form/FunctionalForm.tsx +15 -15
  68. package/src/form/container/FormPage.tsx +16 -18
  69. package/src/form/container/FormPaper.tsx +12 -12
  70. package/src/form/fields/TextField.tsx +63 -61
  71. package/src/list/NestedList.tsx +18 -21
  72. package/src/router/Page.ts +18 -18
  73. package/src/router/Router.tsx +66 -52
  74. package/src/router/createUrlParams.ts +8 -7
  75. package/src/router/withRouter.tsx +6 -11
  76. package/src/table/Table.tsx +96 -80
  77. package/src/table/TableButton.ts +9 -9
  78. package/src/table/TableLoader.ts +6 -6
  79. package/src/table/TableToolbar.tsx +52 -59
  80. package/tsconfig.json +17 -17
@@ -2,20 +2,15 @@ import React from 'react';
2
2
  import { NavigateFunction, useNavigate } from 'react-router-dom';
3
3
 
4
4
  export type WithRouterProps = {
5
- navigate: NavigateFunction
6
- }
5
+ navigate: NavigateFunction;
6
+ };
7
7
 
8
8
  export const withRouter = (Component: typeof React.Component) => {
9
9
  const Wrapper = (props: any) => {
10
10
  const navigate = useNavigate();
11
-
12
- return (
13
- <Component
14
- navigate={navigate}
15
- {...props}
16
- />
17
- );
11
+
12
+ return <Component navigate={navigate} {...props} />;
18
13
  };
19
-
14
+
20
15
  return Wrapper;
21
- };
16
+ };
@@ -1,51 +1,71 @@
1
- import React from 'react'
2
- import { useNavigate } from 'react-router-dom'
3
- import S from 'string'
4
- import { TableContainer, Table as MuiTable, TableBody, TableCell, TableHead, TablePagination, TableRow, Typography, Checkbox } from '@mui/material'
5
- import moment from 'moment'
6
- import { StringUtil } from '@proteinjs/util'
7
- import { TableLoader } from './TableLoader'
8
- import { TableButton } from './TableButton'
9
- import { TableToolbar } from './TableToolbar'
1
+ import React from 'react';
2
+ import { useNavigate } from 'react-router-dom';
3
+ import S from 'string';
4
+ import {
5
+ TableContainer,
6
+ Table as MuiTable,
7
+ TableBody,
8
+ TableCell,
9
+ TableHead,
10
+ TablePagination,
11
+ TableRow,
12
+ Typography,
13
+ Checkbox,
14
+ } from '@mui/material';
15
+ import moment from 'moment';
16
+ import { StringUtil } from '@proteinjs/util';
17
+ import { TableLoader } from './TableLoader';
18
+ import { TableButton } from './TableButton';
19
+ import { TableToolbar } from './TableToolbar';
10
20
 
11
21
  export type TableProps<T> = {
12
- title?: string,
13
- description?: () => JSX.Element,
14
- columns: (keyof T)[],
15
- tableLoader: TableLoader<T>,
16
- rowOnClickRedirectUrl?: (row: T) => Promise<string>,
17
- defaultRowsPerPage?: number,
18
- buttons?: TableButton<T>[],
19
- }
20
-
21
- export function Table<T>({ title, description, columns, tableLoader, rowOnClickRedirectUrl, defaultRowsPerPage = 10, buttons }: TableProps<T>) {
22
+ title?: string;
23
+ description?: () => JSX.Element;
24
+ columns: (keyof T)[];
25
+ tableLoader: TableLoader<T>;
26
+ rowOnClickRedirectUrl?: (row: T) => Promise<string>;
27
+ defaultRowsPerPage?: number;
28
+ buttons?: TableButton<T>[];
29
+ };
30
+
31
+ export function Table<T>({
32
+ title,
33
+ description,
34
+ columns,
35
+ tableLoader,
36
+ rowOnClickRedirectUrl,
37
+ defaultRowsPerPage = 10,
38
+ buttons,
39
+ }: TableProps<T>) {
22
40
  const [rowsPerPage, setRowsPerPage] = React.useState(defaultRowsPerPage);
23
41
  const [page, setPage] = React.useState(0);
24
42
  const [totalRows, setTotalRows] = React.useState(0);
25
43
  const [rows, setRows] = React.useState<T[]>([]);
26
- const [selectedRows, setSelectedRows] = React.useState<{[key: number]: T}>({});
44
+ const [selectedRows, setSelectedRows] = React.useState<{ [key: number]: T }>({});
27
45
  const [selectAll, setSelectAll] = React.useState(false);
28
46
  const navigate = useNavigate();
29
47
 
30
48
  React.useEffect(() => {
31
- const fetchData = async () => {
32
- const startIndex = page * rowsPerPage;
33
- const endIndex = startIndex + rowsPerPage;
34
- const rowWindow = await tableLoader.load(startIndex, endIndex);
35
- setRows(rowWindow.rows);
49
+ const fetchData = async () => {
50
+ const startIndex = page * rowsPerPage;
51
+ const endIndex = startIndex + rowsPerPage;
52
+ const rowWindow = await tableLoader.load(startIndex, endIndex);
53
+ setRows(rowWindow.rows);
36
54
  setTotalRows(rowWindow.totalCount);
37
- };
55
+ };
38
56
 
39
- fetchData();
40
- }, [page, rowsPerPage, tableLoader]);
57
+ fetchData();
58
+ }, [page, rowsPerPage, tableLoader]);
41
59
 
42
60
  async function handleRowOnClick(row: T) {
43
- if (!rowOnClickRedirectUrl)
61
+ if (!rowOnClickRedirectUrl) {
44
62
  return;
63
+ }
45
64
 
46
65
  let redirectUrl = await rowOnClickRedirectUrl(row);
47
- if (!redirectUrl.startsWith('/'))
66
+ if (!redirectUrl.startsWith('/')) {
48
67
  redirectUrl = `/${redirectUrl}`;
68
+ }
49
69
 
50
70
  navigate(redirectUrl);
51
71
  }
@@ -57,17 +77,19 @@ export function Table<T>({ title, description, columns, tableLoader, rowOnClickR
57
77
 
58
78
  function toggleSelectRow(rowIndex: number, row: T) {
59
79
  const newSelectedRows = Object.assign({}, selectedRows);
60
- if (newSelectedRows[rowIndex])
80
+ if (newSelectedRows[rowIndex]) {
61
81
  delete newSelectedRows[rowIndex];
62
- else
82
+ } else {
63
83
  newSelectedRows[rowIndex] = row;
84
+ }
64
85
 
65
86
  setSelectedRows(newSelectedRows);
66
87
 
67
- if (selectAll && Object.keys(selectedRows).length != rows.length)
88
+ if (selectAll && Object.keys(selectedRows).length != rows.length) {
68
89
  setSelectAll(false);
69
- else if (!selectAll && Object.keys(selectedRows).length == rows.length)
90
+ } else if (!selectAll && Object.keys(selectedRows).length == rows.length) {
70
91
  setSelectAll(true);
92
+ }
71
93
  }
72
94
 
73
95
  function toggleSelectAll(selected: boolean) {
@@ -75,8 +97,9 @@ export function Table<T>({ title, description, columns, tableLoader, rowOnClickR
75
97
  const newSelectedRows = Object.assign({}, selectedRows);
76
98
  for (let i = 0; i < rows.length; i++) {
77
99
  const index = rowsPerPage * page + i;
78
- if (!newSelectedRows[index])
100
+ if (!newSelectedRows[index]) {
79
101
  newSelectedRows[index] = rows[i];
102
+ }
80
103
  }
81
104
  setSelectedRows(newSelectedRows);
82
105
  } else {
@@ -87,91 +110,84 @@ export function Table<T>({ title, description, columns, tableLoader, rowOnClickR
87
110
  }
88
111
 
89
112
  function formatCellValue(value: any): string {
90
- if (value == null)
113
+ if (value == null) {
91
114
  return '';
115
+ }
92
116
 
93
- if (typeof value === 'boolean')
117
+ if (typeof value === 'boolean') {
94
118
  return value ? 'True' : 'False';
119
+ }
95
120
 
96
- if (moment.isMoment(value))
97
- return value.format('ddd, MMM Do YY, h:mm:ss a')
121
+ if (moment.isMoment(value)) {
122
+ return value.format('ddd, MMM Do YY, h:mm:ss a');
123
+ }
98
124
 
99
- if (typeof value === 'object')
125
+ if (typeof value === 'object') {
100
126
  return JSON.stringify(value);
127
+ }
101
128
 
102
129
  return value.toString();
103
130
  }
104
131
 
105
132
  return (
106
133
  <div style={{ overflow: 'auto', width: '100%' }}>
107
- { (title || description || buttons && buttons.length > 0) &&
108
- <TableToolbar
109
- title={title}
110
- description={description}
111
- selectedRows={Object.values(selectedRows)}
112
- buttons={buttons}
113
- />
114
- }
134
+ {(title || description || (buttons && buttons.length > 0)) && (
135
+ <TableToolbar
136
+ title={title}
137
+ description={description}
138
+ selectedRows={Object.values(selectedRows)}
139
+ buttons={buttons}
140
+ />
141
+ )}
115
142
  <TableContainer>
116
143
  <MuiTable stickyHeader>
117
144
  <TableHead>
118
145
  <TableRow>
119
- { buttons && buttons.length > 0 &&
146
+ {buttons && buttons.length > 0 && (
120
147
  <TableCell padding='checkbox'>
121
148
  <Checkbox
122
149
  checked={selectAll}
123
150
  onChange={(event, selected) => toggleSelectAll(selected)}
124
- inputProps={{
125
- 'aria-label': 'Select all'
151
+ inputProps={{
152
+ 'aria-label': 'Select all',
126
153
  }}
127
154
  />
128
155
  </TableCell>
129
- }
130
- { columns.map((column, index) => (
131
- <TableCell
132
- key={index}
133
- >
134
- <Typography variant='h6'>
135
- { StringUtil.humanizeCamel(column as string) }
136
- </Typography>
156
+ )}
157
+ {columns.map((column, index) => (
158
+ <TableCell key={index}>
159
+ <Typography variant='h6'>{StringUtil.humanizeCamel(column as string)}</Typography>
137
160
  </TableCell>
138
161
  ))}
139
162
  </TableRow>
140
163
  </TableHead>
141
164
  <TableBody>
142
- { rows.map((row, index) => {
165
+ {rows.map((row, index) => {
143
166
  index = rowsPerPage * page + index;
144
167
  return (
145
- <TableRow
146
- hover
147
- role='checkbox'
148
- tabIndex={-1}
168
+ <TableRow
169
+ hover
170
+ role='checkbox'
171
+ tabIndex={-1}
149
172
  key={index}
150
173
  selected={typeof selectedRows[index] !== 'undefined'}
151
174
  >
152
- { buttons && buttons.length > 0 &&
175
+ {buttons && buttons.length > 0 && (
153
176
  <TableCell padding='checkbox'>
154
177
  <Checkbox
155
178
  checked={typeof selectedRows[index] !== 'undefined'}
156
179
  onChange={(event, value) => toggleSelectRow(index, row)}
157
- inputProps={{
158
- 'aria-label': 'Select row'
180
+ inputProps={{
181
+ 'aria-label': 'Select row',
159
182
  }}
160
183
  />
161
184
  </TableCell>
162
- }
163
- { columns.map((column, index) => {
185
+ )}
186
+ {columns.map((column, index) => {
164
187
  const cellValue = formatCellValue(row[column]);
165
188
  return (
166
- <TableCell
167
- key={index}
168
- onClick={(event: any) => handleRowOnClick(row)}
169
- >
170
- <Typography
171
- variant='subtitle1'
172
- >
173
- {cellValue}
174
- </Typography>
189
+ <TableCell key={index} onClick={(event: any) => handleRowOnClick(row)}>
190
+ <Typography variant='subtitle1'>{cellValue}</Typography>
175
191
  </TableCell>
176
192
  );
177
193
  })}
@@ -188,8 +204,8 @@ export function Table<T>({ title, description, columns, tableLoader, rowOnClickR
188
204
  rowsPerPage={rowsPerPage}
189
205
  page={page}
190
206
  onPageChange={(event, newPage) => setPage(newPage)}
191
- onRowsPerPageChange={event => updateRowsPerPage(parseInt(event.target.value))}
207
+ onRowsPerPageChange={(event) => updateRowsPerPage(parseInt(event.target.value))}
192
208
  />
193
209
  </div>
194
210
  );
195
- }
211
+ }
@@ -1,12 +1,12 @@
1
- import React from 'react'
2
- import { NavigateFunction } from 'react-router'
1
+ import React from 'react';
2
+ import { NavigateFunction } from 'react-router';
3
3
 
4
4
  export type TableButton<T> = {
5
- name: string,
6
- icon: React.ComponentType,
5
+ name: string;
6
+ icon: React.ComponentType;
7
7
  visibility: {
8
- showWhenRowsSelected: boolean,
9
- showWhenNoRowsSelected: boolean,
10
- },
11
- onClick: (selectedRows: T[], navigate: NavigateFunction) => Promise<void>,
12
- }
8
+ showWhenRowsSelected: boolean;
9
+ showWhenNoRowsSelected: boolean;
10
+ };
11
+ onClick: (selectedRows: T[], navigate: NavigateFunction) => Promise<void>;
12
+ };
@@ -1,11 +1,11 @@
1
1
  export type RowWindow<T> = {
2
- rows: T[],
3
- totalCount: number,
4
- }
2
+ rows: T[];
3
+ totalCount: number;
4
+ };
5
5
 
6
6
  export type TableLoader<T> = {
7
- load: (startIndex: number, endIndex: number) => Promise<RowWindow<T>>,
8
- }
7
+ load: (startIndex: number, endIndex: number) => Promise<RowWindow<T>>;
8
+ };
9
9
 
10
10
  export class StaticTableLoader<T> implements TableLoader<T> {
11
11
  constructor(private list: T[]) {}
@@ -16,4 +16,4 @@ export class StaticTableLoader<T> implements TableLoader<T> {
16
16
  totalCount: this.list.length,
17
17
  };
18
18
  }
19
- }
19
+ }
@@ -1,16 +1,16 @@
1
- import React from 'react'
2
- import { TableButton } from './TableButton'
3
- import { IconButton, Toolbar, Tooltip, Typography, lighten } from '@mui/material'
4
- import { useNavigate } from 'react-router'
1
+ import React from 'react';
2
+ import { TableButton } from './TableButton';
3
+ import { IconButton, Toolbar, Tooltip, Typography, lighten } from '@mui/material';
4
+ import { useNavigate } from 'react-router';
5
5
 
6
6
  export type TableToolbarProps = {
7
- title?: string,
8
- selectedRows: any[],
9
- description?: () => JSX.Element,
10
- buttons?: TableButton<any>[],
11
- }
7
+ title?: string;
8
+ selectedRows: any[];
9
+ description?: () => JSX.Element;
10
+ buttons?: TableButton<any>[];
11
+ };
12
12
 
13
- export const TableToolbar = (props : TableToolbarProps) => {
13
+ export const TableToolbar = (props: TableToolbarProps) => {
14
14
  const { title, selectedRows, buttons } = props;
15
15
  const navigate = useNavigate();
16
16
  return (
@@ -18,19 +18,19 @@ export const TableToolbar = (props : TableToolbarProps) => {
18
18
  sx={(theme) => {
19
19
  if (selectedRows.length > 0) {
20
20
  return theme.palette.mode === 'light'
21
- ? {
22
- color: theme.palette.info.main,
23
- backgroundColor: lighten(theme.palette.info.light, 0.85),
24
- }
25
- : {
26
- color: theme.palette.info.light,
27
- backgroundColor: theme.palette.info.dark,
28
- };
21
+ ? {
22
+ color: theme.palette.info.main,
23
+ backgroundColor: lighten(theme.palette.info.light, 0.85),
24
+ }
25
+ : {
26
+ color: theme.palette.info.light,
27
+ backgroundColor: theme.palette.info.dark,
28
+ };
29
29
  }
30
30
 
31
31
  return {
32
32
  paddingLeft: theme.spacing(2),
33
- paddingRight: theme.spacing(1),
33
+ paddingRight: theme.spacing(1),
34
34
  };
35
35
  }}
36
36
  >
@@ -40,60 +40,53 @@ export const TableToolbar = (props : TableToolbarProps) => {
40
40
  flex: '0 0 auto',
41
41
  }}
42
42
  >
43
- { selectedRows.length > 0 ? (
44
- <Typography variant='subtitle1' color='inherit'>
45
- {selectedRows.length} rows selected
46
- </Typography>
47
- ) : (
48
- <div>
49
- { typeof title !== 'undefined' &&
50
- <Typography variant='h5'>
51
- {title}
52
- </Typography>
53
- }
54
- { typeof props.description !== 'undefined' &&
55
- <props.description />
56
- }
57
- </div>
58
- )}
59
- </div>
60
- <div
43
+ {selectedRows.length > 0 ? (
44
+ <Typography variant='subtitle1' color='inherit'>
45
+ {selectedRows.length} rows selected
46
+ </Typography>
47
+ ) : (
48
+ <div>
49
+ {typeof title !== 'undefined' && <Typography variant='h5'>{title}</Typography>}
50
+ {typeof props.description !== 'undefined' && <props.description />}
51
+ </div>
52
+ )}
53
+ </div>
54
+ <div
61
55
  style={{
62
56
  flex: '1 1 100%',
63
57
  }}
64
58
  />
65
- <div>
66
- <Buttons />
67
- </div>
59
+ <div>
60
+ <Buttons />
61
+ </div>
68
62
  </Toolbar>
69
63
  );
70
64
 
71
65
  function Buttons() {
72
- if (!buttons)
66
+ if (!buttons) {
73
67
  return null;
68
+ }
74
69
 
75
70
  if (selectedRows.length > 0) {
76
- return buttons.filter((button) => button.visibility.showWhenRowsSelected).map((button, index) => (
71
+ return buttons
72
+ .filter((button) => button.visibility.showWhenRowsSelected)
73
+ .map((button, index) => (
74
+ <Tooltip key={index} title={button.name}>
75
+ <IconButton aria-label={button.name} onClick={(event) => button.onClick(selectedRows, navigate)}>
76
+ <button.icon />
77
+ </IconButton>
78
+ </Tooltip>
79
+ ));
80
+ }
81
+
82
+ return buttons
83
+ .filter((button) => button.visibility.showWhenNoRowsSelected)
84
+ .map((button, index) => (
77
85
  <Tooltip key={index} title={button.name}>
78
- <IconButton
79
- aria-label={button.name}
80
- onClick={event => button.onClick(selectedRows, navigate)}
81
- >
86
+ <IconButton aria-label={button.name} onClick={(event) => button.onClick([], navigate)}>
82
87
  <button.icon />
83
88
  </IconButton>
84
89
  </Tooltip>
85
90
  ));
86
- }
87
-
88
- return buttons.filter((button) => button.visibility.showWhenNoRowsSelected).map((button, index) => (
89
- <Tooltip key={index} title={button.name}>
90
- <IconButton
91
- aria-label={button.name}
92
- onClick={event => button.onClick([], navigate)}
93
- >
94
- <button.icon />
95
- </IconButton>
96
- </Tooltip>
97
- ));
98
91
  }
99
- }
92
+ };
package/tsconfig.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
- "compilerOptions": {
3
- "rootDir": "./",
4
- "target": "es5",
5
- "module": "commonjs",
6
- "declaration": true,
7
- "declarationMap": true,
8
- "sourceMap": true,
9
- "outDir": "./dist/",
10
- "strict": true,
11
- "noImplicitAny": true,
12
- "esModuleInterop": true,
13
- "skipLibCheck": true,
14
- "forceConsistentCasingInFileNames": true,
15
- "resolveJsonModule": true,
16
- "jsx": "react"
17
- }
18
- }
2
+ "compilerOptions": {
3
+ "rootDir": "./",
4
+ "target": "es5",
5
+ "module": "commonjs",
6
+ "declaration": true,
7
+ "declarationMap": true,
8
+ "sourceMap": true,
9
+ "outDir": "./dist/",
10
+ "strict": true,
11
+ "noImplicitAny": true,
12
+ "esModuleInterop": true,
13
+ "skipLibCheck": true,
14
+ "forceConsistentCasingInFileNames": true,
15
+ "resolveJsonModule": true,
16
+ "jsx": "react"
17
+ }
18
+ }