@etsoo/react 1.4.13 → 1.4.17

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.
@@ -1,11 +1,12 @@
1
+ import { Utils } from '@etsoo/shared';
1
2
  import React from 'react';
2
3
  import { FixedSizeList, VariableSizeList } from 'react-window';
3
4
  import useCombinedRefs from '../uses/useCombinedRefs';
4
5
  import { GridSizeGet } from './GridLoader';
5
6
  // Calculate loadBatchSize
6
7
  const calculateBatchSize = (height, itemSize) => {
7
- return (2 +
8
- Math.ceil(height / (typeof itemSize === 'function' ? itemSize(0) : itemSize)));
8
+ const size = Utils.getResult(itemSize, 0);
9
+ return 2 + Math.ceil(height / size);
9
10
  };
10
11
  /**
11
12
  * Scroller vertical list
package/lib/index.d.ts CHANGED
@@ -56,6 +56,7 @@ export * from './mu/OptionGroup';
56
56
  export * from './mu/PList';
57
57
  export * from './mu/ProgressCount';
58
58
  export * from './mu/PullToRefreshUI';
59
+ export * from './mu/ResponsibleContainer';
59
60
  export * from './mu/RLink';
60
61
  export * from './mu/ScrollerListEx';
61
62
  export * from './mu/ScrollTopFab';
package/lib/index.js CHANGED
@@ -59,6 +59,7 @@ export * from './mu/OptionGroup';
59
59
  export * from './mu/PList';
60
60
  export * from './mu/ProgressCount';
61
61
  export * from './mu/PullToRefreshUI';
62
+ export * from './mu/ResponsibleContainer';
62
63
  export * from './mu/RLink';
63
64
  export * from './mu/ScrollerListEx';
64
65
  export * from './mu/ScrollTopFab';
@@ -1,6 +1,13 @@
1
1
  import React from 'react';
2
2
  import { ListItemReact } from '../components/ListItemReact';
3
3
  import { ScrollerListExInnerItemRendererProps } from './ScrollerListEx';
4
+ /**
5
+ * Default mobile list item renderer
6
+ * @param param0 List renderer props
7
+ * @param margin Margin
8
+ * @param renderer Renderer for card content
9
+ * @returns Component
10
+ */
4
11
  export declare function MobileListItemRenderer<T>({ data, itemHeight }: ScrollerListExInnerItemRendererProps<T>, margin: {}, renderer: (data: T) => [
5
12
  string,
6
13
  string | undefined,
@@ -12,6 +12,13 @@ function getActions(input) {
12
12
  });
13
13
  return actions;
14
14
  }
15
+ /**
16
+ * Default mobile list item renderer
17
+ * @param param0 List renderer props
18
+ * @param margin Margin
19
+ * @param renderer Renderer for card content
20
+ * @returns Component
21
+ */
15
22
  export function MobileListItemRenderer({ data, itemHeight }, margin, renderer) {
16
23
  // Loading
17
24
  if (data == null)
@@ -0,0 +1,69 @@
1
+ import { DataTypes } from '@etsoo/shared';
2
+ import { SxProps, Theme } from '@mui/material';
3
+ import React from 'react';
4
+ import { ListChildComponentProps } from 'react-window';
5
+ import { GridColumn } from '../components/GridColumn';
6
+ import { GridJsonData } from '../components/GridLoader';
7
+ import { DataGridExProps } from './DataGridEx';
8
+ import { GridMethodRef } from './GridMethodRef';
9
+ import { ScrollerListExInnerItemRendererProps } from './ScrollerListEx';
10
+ export interface ResponsibleContainerProps<T extends {}, F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate> extends Omit<DataGridExProps<T>, 'height' | 'itemKey' | 'loadData' | 'mRef' | 'onScroll' | 'onItemsRendered'> {
11
+ /**
12
+ * Height will be deducted
13
+ * @param height Current calcuated height
14
+ */
15
+ adjustHeight?: (height: number) => number;
16
+ /**
17
+ * Columns
18
+ */
19
+ columns: GridColumn<T>[];
20
+ /**
21
+ * Min width to show Datagrid
22
+ */
23
+ dataGridMinWidth?: number;
24
+ /**
25
+ * Search fields
26
+ */
27
+ fields?: React.ReactElement[];
28
+ /**
29
+ * Search field template
30
+ */
31
+ fieldTemplate?: F;
32
+ /**
33
+ * Grid height
34
+ */
35
+ height?: number;
36
+ /**
37
+ * Inner item renderer
38
+ */
39
+ innerItemRenderer: (props: ScrollerListExInnerItemRendererProps<T>) => React.ReactNode;
40
+ /**
41
+ * Item renderer
42
+ */
43
+ itemRenderer?: (props: ListChildComponentProps<T>) => React.ReactElement;
44
+ /**
45
+ * Item size, a function indicates its a variable size list
46
+ */
47
+ itemSize: ((index: number) => number) | number;
48
+ /**
49
+ * Listbox SX (dataGrid determines the case)
50
+ */
51
+ listBoxSx?: (dataGrid: boolean) => SxProps<Theme>;
52
+ /**
53
+ * Load data callback
54
+ */
55
+ loadData: (data: GridJsonData & DataTypes.BasicTemplateType<F>) => PromiseLike<T[] | null | undefined>;
56
+ /**
57
+ * Methods
58
+ */
59
+ mRef?: React.MutableRefObject<GridMethodRef | undefined>;
60
+ /**
61
+ * Searchbox SX
62
+ */
63
+ searchBoxSx?: SxProps<Theme>;
64
+ /**
65
+ * Size ready to read miliseconds span
66
+ */
67
+ sizeReadyMiliseconds?: number;
68
+ }
69
+ export declare function ResponsibleContainer<T extends {}, F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate>(props: ResponsibleContainerProps<T, F>): JSX.Element;
@@ -0,0 +1,82 @@
1
+ import { Box, Stack } from '@mui/material';
2
+ import React from 'react';
3
+ import { GridDataGet } from '../components/GridLoader';
4
+ import useCombinedRefs from '../uses/useCombinedRefs';
5
+ import { useDimensions } from '../uses/useDimensions';
6
+ import { DataGridEx, DataGridExCalColumns } from './DataGridEx';
7
+ import { ScrollerListEx } from './ScrollerListEx';
8
+ import { SearchBar } from './SearchBar';
9
+ export function ResponsibleContainer(props) {
10
+ var _a;
11
+ // Destruct
12
+ const { adjustHeight, columns, dataGridMinWidth = DataGridExCalColumns(columns).total, fields, fieldTemplate, height, listBoxSx, loadData, mRef, searchBoxSx, sizeReadyMiliseconds = 0, ...rest } = props;
13
+ // Refs
14
+ const refs = React.useRef({});
15
+ const mRefs = useCombinedRefs(mRef, (ref) => {
16
+ if (ref == null)
17
+ return;
18
+ refs.current.ref = ref;
19
+ });
20
+ // Has fields
21
+ const hasFields = fields != null && fields.length > 0;
22
+ // Watch container
23
+ const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds);
24
+ const rect = dimensions[0][2];
25
+ const showDataGrid = ((_a = rect === null || rect === void 0 ? void 0 : rect.width) !== null && _a !== void 0 ? _a : 0) >= dataGridMinWidth;
26
+ React.useEffect(() => {
27
+ if (rect != null && rect.height > 50 && height == null) {
28
+ let gridHeight = window.innerHeight - Math.round(rect.top + rect.height + 1);
29
+ const style = window.getComputedStyle(dimensions[0][1]);
30
+ const boxPadding = parseFloat(style.paddingLeft);
31
+ if (!isNaN(boxPadding))
32
+ gridHeight -= 2 * boxPadding;
33
+ if (adjustHeight != null) {
34
+ gridHeight -= adjustHeight(gridHeight);
35
+ }
36
+ if (gridHeight !== refs.current.height) {
37
+ refs.current.height = gridHeight;
38
+ }
39
+ }
40
+ }, [rect]);
41
+ const localLoadData = (props) => {
42
+ const data = GridDataGet(props, fieldTemplate);
43
+ return loadData(data);
44
+ };
45
+ const gridHeight = refs.current.height;
46
+ const list = React.useMemo(() => {
47
+ if (gridHeight == null)
48
+ return;
49
+ if (showDataGrid) {
50
+ // Delete
51
+ delete rest.itemRenderer;
52
+ return (React.createElement(Box, { sx: listBoxSx == null ? undefined : listBoxSx(true) },
53
+ React.createElement(DataGridEx, { autoLoad: !hasFields, height: gridHeight, loadData: localLoadData, mRef: mRefs, columns: columns, ...rest })));
54
+ }
55
+ // Delete
56
+ delete rest.checkable;
57
+ delete rest.borderRowsCount;
58
+ delete rest.bottomHeight;
59
+ delete rest.footerItemRenderer;
60
+ delete rest.headerHeight;
61
+ delete rest.hideFooter;
62
+ delete rest.hoverColor;
63
+ delete rest.selectable;
64
+ return (React.createElement(Box, { sx: listBoxSx == null ? undefined : listBoxSx(false) },
65
+ React.createElement(ScrollerListEx, { autoLoad: !hasFields, height: gridHeight, loadData: localLoadData, mRef: mRefs, ...rest })));
66
+ }, [gridHeight, showDataGrid]);
67
+ // On submit callback
68
+ const onSubmit = (data, _reset) => {
69
+ console.log(data, rect, refs.current.ref, showDataGrid);
70
+ if (data == null || rect == null || refs.current.ref == null)
71
+ return;
72
+ refs.current.ref.reset({ data });
73
+ };
74
+ React.useEffect(() => {
75
+ console.log('useEffect', rect, refs.current.ref, showDataGrid);
76
+ }, []);
77
+ // Layout
78
+ return (React.createElement(Stack, null,
79
+ hasFields && (React.createElement(Box, { ref: dimensions[0][0], sx: searchBoxSx },
80
+ React.createElement(SearchBar, { fields: fields, onSubmit: onSubmit }))),
81
+ list));
82
+ }
@@ -7,7 +7,7 @@ export interface TabBoxPanel extends Omit<TabProps, 'value' | 'children'> {
7
7
  /**
8
8
  * Children
9
9
  */
10
- children?: React.ReactNode;
10
+ children?: ((visible: boolean) => React.ReactNode) | React.ReactNode;
11
11
  /**
12
12
  * Panel box props
13
13
  */
package/lib/mu/TabBox.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { Utils } from '@etsoo/shared';
1
2
  import { Box, Tab, Tabs } from '@mui/material';
2
3
  import React from 'react';
3
4
  /**
@@ -20,5 +21,5 @@ export function TabBox(props) {
20
21
  if (onChange)
21
22
  onChange(event, newValue);
22
23
  }, ...rest }, tabs.map(({ children, panel, ...tabRest }, index) => (React.createElement(Tab, { key: index, value: index, ...tabRest }))))),
23
- tabs.map(({ children, panel }, index) => (React.createElement(Box, { key: index, hidden: value !== index, ...panel }, children)))));
24
+ tabs.map(({ children, panel }, index) => (React.createElement(Box, { key: index, hidden: value !== index, ...panel }, Utils.getResult(children, value === index))))));
24
25
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/react",
3
- "version": "1.4.13",
3
+ "version": "1.4.17",
4
4
  "description": "TypeScript ReactJs framework",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -50,9 +50,9 @@
50
50
  "@emotion/react": "^11.7.1",
51
51
  "@emotion/style": "^0.8.0",
52
52
  "@emotion/styled": "^11.6.0",
53
- "@etsoo/appscript": "^1.2.20",
53
+ "@etsoo/appscript": "^1.2.21",
54
54
  "@etsoo/notificationbase": "^1.1.0",
55
- "@etsoo/shared": "^1.1.0",
55
+ "@etsoo/shared": "^1.1.3",
56
56
  "@mui/icons-material": "^5.2.5",
57
57
  "@mui/material": "^5.2.7",
58
58
  "@reach/router": "^1.3.4",
@@ -1,3 +1,4 @@
1
+ import { Utils } from '@etsoo/shared';
1
2
  import React from 'react';
2
3
  import {
3
4
  Align,
@@ -88,12 +89,8 @@ const calculateBatchSize = (
88
89
  height: number,
89
90
  itemSize: ((index: number) => number) | number
90
91
  ) => {
91
- return (
92
- 2 +
93
- Math.ceil(
94
- height / (typeof itemSize === 'function' ? itemSize(0) : itemSize)
95
- )
96
- );
92
+ const size = Utils.getResult(itemSize, 0);
93
+ return 2 + Math.ceil(height / size);
97
94
  };
98
95
 
99
96
  /**
package/src/index.ts CHANGED
@@ -63,6 +63,7 @@ export * from './mu/OptionGroup';
63
63
  export * from './mu/PList';
64
64
  export * from './mu/ProgressCount';
65
65
  export * from './mu/PullToRefreshUI';
66
+ export * from './mu/ResponsibleContainer';
66
67
  export * from './mu/RLink';
67
68
  export * from './mu/ScrollerListEx';
68
69
  export * from './mu/ScrollTopFab';
@@ -15,6 +15,13 @@ function getActions(input: (ListItemReact | boolean)[]): ListItemReact[] {
15
15
  return actions;
16
16
  }
17
17
 
18
+ /**
19
+ * Default mobile list item renderer
20
+ * @param param0 List renderer props
21
+ * @param margin Margin
22
+ * @param renderer Renderer for card content
23
+ * @returns Component
24
+ */
18
25
  export function MobileListItemRenderer<T>(
19
26
  { data, itemHeight }: ScrollerListExInnerItemRendererProps<T>,
20
27
  margin: {},
@@ -0,0 +1,245 @@
1
+ import { DataTypes } from '@etsoo/shared';
2
+ import { Box, Stack, SxProps, Theme } from '@mui/material';
3
+ import React from 'react';
4
+ import { ListChildComponentProps } from 'react-window';
5
+ import { GridColumn } from '../components/GridColumn';
6
+ import {
7
+ GridDataGet,
8
+ GridJsonData,
9
+ GridLoadDataProps
10
+ } from '../components/GridLoader';
11
+ import useCombinedRefs from '../uses/useCombinedRefs';
12
+ import { useDimensions } from '../uses/useDimensions';
13
+ import {
14
+ DataGridEx,
15
+ DataGridExCalColumns,
16
+ DataGridExProps
17
+ } from './DataGridEx';
18
+ import { GridMethodRef } from './GridMethodRef';
19
+ import {
20
+ ScrollerListEx,
21
+ ScrollerListExInnerItemRendererProps
22
+ } from './ScrollerListEx';
23
+ import { SearchBar } from './SearchBar';
24
+
25
+ export interface ResponsibleContainerProps<
26
+ T extends {},
27
+ F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate
28
+ > extends Omit<
29
+ DataGridExProps<T>,
30
+ | 'height'
31
+ | 'itemKey'
32
+ | 'loadData'
33
+ | 'mRef'
34
+ | 'onScroll'
35
+ | 'onItemsRendered'
36
+ > {
37
+ /**
38
+ * Height will be deducted
39
+ * @param height Current calcuated height
40
+ */
41
+ adjustHeight?: (height: number) => number;
42
+
43
+ /**
44
+ * Columns
45
+ */
46
+ columns: GridColumn<T>[];
47
+
48
+ /**
49
+ * Min width to show Datagrid
50
+ */
51
+ dataGridMinWidth?: number;
52
+
53
+ /**
54
+ * Search fields
55
+ */
56
+ fields?: React.ReactElement[];
57
+
58
+ /**
59
+ * Search field template
60
+ */
61
+ fieldTemplate?: F;
62
+
63
+ /**
64
+ * Grid height
65
+ */
66
+ height?: number;
67
+
68
+ /**
69
+ * Inner item renderer
70
+ */
71
+ innerItemRenderer: (
72
+ props: ScrollerListExInnerItemRendererProps<T>
73
+ ) => React.ReactNode;
74
+
75
+ /**
76
+ * Item renderer
77
+ */
78
+ itemRenderer?: (props: ListChildComponentProps<T>) => React.ReactElement;
79
+
80
+ /**
81
+ * Item size, a function indicates its a variable size list
82
+ */
83
+ itemSize: ((index: number) => number) | number;
84
+
85
+ /**
86
+ * Listbox SX (dataGrid determines the case)
87
+ */
88
+ listBoxSx?: (dataGrid: boolean) => SxProps<Theme>;
89
+
90
+ /**
91
+ * Load data callback
92
+ */
93
+ loadData: (
94
+ data: GridJsonData & DataTypes.BasicTemplateType<F>
95
+ ) => PromiseLike<T[] | null | undefined>;
96
+
97
+ /**
98
+ * Methods
99
+ */
100
+ mRef?: React.MutableRefObject<GridMethodRef | undefined>;
101
+
102
+ /**
103
+ * Searchbox SX
104
+ */
105
+ searchBoxSx?: SxProps<Theme>;
106
+
107
+ /**
108
+ * Size ready to read miliseconds span
109
+ */
110
+ sizeReadyMiliseconds?: number;
111
+ }
112
+
113
+ interface LocalRefs {
114
+ height?: number;
115
+ ref?: GridMethodRef;
116
+ }
117
+
118
+ export function ResponsibleContainer<
119
+ T extends {},
120
+ F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate
121
+ >(props: ResponsibleContainerProps<T, F>) {
122
+ // Destruct
123
+ const {
124
+ adjustHeight,
125
+ columns,
126
+ dataGridMinWidth = DataGridExCalColumns(columns).total,
127
+ fields,
128
+ fieldTemplate,
129
+ height,
130
+ listBoxSx,
131
+ loadData,
132
+ mRef,
133
+ searchBoxSx,
134
+ sizeReadyMiliseconds = 0,
135
+ ...rest
136
+ } = props;
137
+
138
+ // Refs
139
+ const refs = React.useRef<LocalRefs>({});
140
+
141
+ const mRefs = useCombinedRefs(mRef, (ref: GridMethodRef) => {
142
+ if (ref == null) return;
143
+ refs.current.ref = ref;
144
+ });
145
+
146
+ // Has fields
147
+ const hasFields = fields != null && fields.length > 0;
148
+
149
+ // Watch container
150
+ const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds);
151
+ const rect = dimensions[0][2];
152
+ const showDataGrid = (rect?.width ?? 0) >= dataGridMinWidth;
153
+
154
+ React.useEffect(() => {
155
+ if (rect != null && rect.height > 50 && height == null) {
156
+ let gridHeight =
157
+ window.innerHeight - Math.round(rect.top + rect.height + 1);
158
+
159
+ const style = window.getComputedStyle(dimensions[0][1]!);
160
+ const boxPadding = parseFloat(style.paddingLeft);
161
+ if (!isNaN(boxPadding)) gridHeight -= 2 * boxPadding;
162
+
163
+ if (adjustHeight != null) {
164
+ gridHeight -= adjustHeight(gridHeight);
165
+ }
166
+
167
+ if (gridHeight !== refs.current.height) {
168
+ refs.current.height = gridHeight;
169
+ }
170
+ }
171
+ }, [rect]);
172
+
173
+ const localLoadData = (props: GridLoadDataProps) => {
174
+ const data = GridDataGet(props, fieldTemplate);
175
+ return loadData(data);
176
+ };
177
+
178
+ const gridHeight = refs.current.height;
179
+ const list = React.useMemo(() => {
180
+ if (gridHeight == null) return;
181
+
182
+ if (showDataGrid) {
183
+ // Delete
184
+ delete rest.itemRenderer;
185
+
186
+ return (
187
+ <Box sx={listBoxSx == null ? undefined : listBoxSx(true)}>
188
+ <DataGridEx<T>
189
+ autoLoad={!hasFields}
190
+ height={gridHeight}
191
+ loadData={localLoadData}
192
+ mRef={mRefs}
193
+ columns={columns}
194
+ {...rest}
195
+ />
196
+ </Box>
197
+ );
198
+ }
199
+
200
+ // Delete
201
+ delete rest.checkable;
202
+ delete rest.borderRowsCount;
203
+ delete rest.bottomHeight;
204
+ delete rest.footerItemRenderer;
205
+ delete rest.headerHeight;
206
+ delete rest.hideFooter;
207
+ delete rest.hoverColor;
208
+ delete rest.selectable;
209
+
210
+ return (
211
+ <Box sx={listBoxSx == null ? undefined : listBoxSx(false)}>
212
+ <ScrollerListEx<T>
213
+ autoLoad={!hasFields}
214
+ height={gridHeight}
215
+ loadData={localLoadData}
216
+ mRef={mRefs}
217
+ {...rest}
218
+ />
219
+ </Box>
220
+ );
221
+ }, [gridHeight, showDataGrid]);
222
+
223
+ // On submit callback
224
+ const onSubmit = (data: FormData, _reset: boolean) => {
225
+ console.log(data, rect, refs.current.ref, showDataGrid);
226
+ if (data == null || rect == null || refs.current.ref == null) return;
227
+ refs.current.ref.reset({ data });
228
+ };
229
+
230
+ React.useEffect(() => {
231
+ console.log('useEffect', rect, refs.current.ref, showDataGrid);
232
+ }, []);
233
+
234
+ // Layout
235
+ return (
236
+ <Stack>
237
+ {hasFields && (
238
+ <Box ref={dimensions[0][0]} sx={searchBoxSx}>
239
+ <SearchBar fields={fields} onSubmit={onSubmit} />
240
+ </Box>
241
+ )}
242
+ {list}
243
+ </Stack>
244
+ );
245
+ }
package/src/mu/TabBox.tsx CHANGED
@@ -1,3 +1,4 @@
1
+ import { Utils } from '@etsoo/shared';
1
2
  import { Box, BoxProps, Tab, TabProps, Tabs, TabsProps } from '@mui/material';
2
3
  import React from 'react';
3
4
 
@@ -8,7 +9,7 @@ export interface TabBoxPanel extends Omit<TabProps, 'value' | 'children'> {
8
9
  /**
9
10
  * Children
10
11
  */
11
- children?: React.ReactNode;
12
+ children?: ((visible: boolean) => React.ReactNode) | React.ReactNode;
12
13
 
13
14
  /**
14
15
  * Panel box props
@@ -76,7 +77,7 @@ export function TabBox(props: TabBoxPros) {
76
77
  </Box>
77
78
  {tabs.map(({ children, panel }, index) => (
78
79
  <Box key={index} hidden={value !== index} {...panel}>
79
- {children}
80
+ {Utils.getResult(children, value === index)}
80
81
  </Box>
81
82
  ))}
82
83
  </React.Fragment>