@etsoo/materialui 1.2.42 → 1.2.44

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,17 +1,20 @@
1
1
  import {
2
- GridDataGet,
3
- GridLoadDataProps,
4
- ScrollerListForwardRef,
5
- useCombinedRefs
6
- } from '@etsoo/react';
7
- import { DataTypes, IdDefaultType } from '@etsoo/shared';
8
- import { Box, Stack } from '@mui/material';
9
- import React from 'react';
10
- import { MUGlobal } from '../MUGlobal';
11
- import { ScrollerListEx } from '../ScrollerListEx';
12
- import { SearchBar } from '../SearchBar';
13
- import { CommonPage, CommonPageScrollContainer } from './CommonPage';
14
- import { ListPageProps } from './ListPageProps';
2
+ GridLoadDataProps,
3
+ GridLoaderStates,
4
+ ListOnScrollProps,
5
+ ScrollerListForwardRef,
6
+ ScrollerListRef,
7
+ useCombinedRefs
8
+ } from "@etsoo/react";
9
+ import { DataTypes, IdDefaultType } from "@etsoo/shared";
10
+ import { Box, Stack } from "@mui/material";
11
+ import React from "react";
12
+ import { MUGlobal } from "../MUGlobal";
13
+ import { ScrollerListEx } from "../ScrollerListEx";
14
+ import { SearchBar } from "../SearchBar";
15
+ import { CommonPage, CommonPageScrollContainer } from "./CommonPage";
16
+ import { ListPageProps } from "./ListPageProps";
17
+ import { GridUtils } from "../GridUtils";
15
18
 
16
19
  /**
17
20
  * List page
@@ -19,72 +22,118 @@ import { ListPageProps } from './ListPageProps';
19
22
  * @returns Component
20
23
  */
21
24
  export function ListPage<
22
- T extends object,
23
- F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate,
24
- D extends DataTypes.Keys<T> = IdDefaultType<T>
25
+ T extends object,
26
+ F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate,
27
+ D extends DataTypes.Keys<T> = IdDefaultType<T>
25
28
  >(props: ListPageProps<T, F, D>) {
26
- // Destruct
27
- const {
28
- fields,
29
- fieldTemplate,
30
- loadData,
31
- mRef,
32
- pageProps = {},
33
- ...rest
34
- } = props;
35
-
36
- pageProps.paddings ??= MUGlobal.pagePaddings;
37
-
38
- // States
39
- const [states] = React.useState<{
40
- data?: FormData;
41
- ref?: ScrollerListForwardRef<T>;
42
- }>({});
43
-
44
- const refs = useCombinedRefs(mRef, (ref: ScrollerListForwardRef<T>) => {
45
- if (ref == null) return;
46
-
47
- const first = states.ref == null;
48
-
49
- states.ref = ref;
50
-
51
- if (first) reset();
52
- });
53
-
54
- const reset = () => {
55
- if (states.data == null || states.ref == null) return;
56
- states.ref.reset({ data: states.data });
57
- };
58
-
59
- // On submit callback
60
- const onSubmit = (data: FormData, _reset: boolean) => {
61
- states.data = data;
62
- reset();
63
- };
64
-
65
- const localLoadData = (props: GridLoadDataProps) => {
66
- const data = GridDataGet(props, fieldTemplate);
67
- return loadData(data);
68
- };
69
-
70
- // Layout
71
- return (
72
- <CommonPage {...pageProps} scrollContainer={CommonPageScrollContainer}>
73
- <Stack>
74
- <Box
75
- sx={{
76
- paddingBottom: pageProps.paddings
77
- }}
78
- >
79
- <SearchBar fields={fields} onSubmit={onSubmit} />
80
- </Box>
81
- <ScrollerListEx<T, D>
82
- autoLoad={false}
83
- loadData={localLoadData}
84
- mRef={refs}
85
- {...rest}
86
- />
87
- </Stack>
88
- </CommonPage>
89
- );
29
+ // Destruct
30
+ const {
31
+ fields,
32
+ fieldTemplate,
33
+ loadData,
34
+ mRef,
35
+ pageProps = {},
36
+ cacheKey,
37
+ cacheMinutes = 120,
38
+ ...rest
39
+ } = props;
40
+
41
+ pageProps.paddings ??= MUGlobal.pagePaddings;
42
+
43
+ // States
44
+ const [states] = React.useState<{
45
+ data?: FormData;
46
+ ref?: ScrollerListForwardRef<T>;
47
+ }>({});
48
+
49
+ const refs = useCombinedRefs(mRef, (ref: ScrollerListForwardRef<T>) => {
50
+ if (ref == null) return;
51
+
52
+ const first = states.ref == null;
53
+
54
+ states.ref = ref;
55
+
56
+ if (first) reset();
57
+ });
58
+
59
+ const initLoadedRef = React.useRef<boolean>();
60
+
61
+ const reset = () => {
62
+ if (states.data == null || states.ref == null) return;
63
+ states.ref.reset({ data: states.data });
64
+ };
65
+
66
+ // On submit callback
67
+ const onSubmit = (data: FormData, _reset: boolean) => {
68
+ states.data = data;
69
+ reset();
70
+ };
71
+
72
+ const localLoadData = (props: GridLoadDataProps) => {
73
+ return loadData(GridUtils.createLoader<F>(props, fieldTemplate, cacheKey));
74
+ };
75
+
76
+ // Search data
77
+ const searchData = GridUtils.getSearchData<F>(cacheKey);
78
+
79
+ const onInitLoad = (
80
+ ref: ScrollerListRef
81
+ ): [T[], Partial<GridLoaderStates<T>>?] | null | undefined => {
82
+ // Avoid repeatedly load from cache
83
+ if (initLoadedRef.current || !cacheKey) return undefined;
84
+
85
+ // Cache data
86
+ const cacheData = GridUtils.getCacheData<T>(cacheKey, cacheMinutes);
87
+ if (cacheData) {
88
+ const { rows, state } = cacheData;
89
+
90
+ GridUtils.mergeSearchData(state, searchData);
91
+
92
+ // Scroll position
93
+ const scrollData = sessionStorage.getItem(`${cacheKey}-scroll`);
94
+ if (scrollData) {
95
+ const { scrollOffset } = JSON.parse(scrollData) as ListOnScrollProps;
96
+ globalThis.setTimeout(() => ref.scrollTo(scrollOffset), 0);
97
+ }
98
+
99
+ // Update flag value
100
+ initLoadedRef.current = true;
101
+
102
+ // Return cached rows and state
103
+ return [rows, state];
104
+ }
105
+
106
+ return undefined;
107
+ };
108
+
109
+ const onListScroll = (props: ListOnScrollProps) => {
110
+ if (!cacheKey || !initLoadedRef.current) return;
111
+ sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(props));
112
+ };
113
+
114
+ const f = typeof fields == "function" ? fields(searchData ?? {}) : fields;
115
+
116
+ // Layout
117
+ return (
118
+ <CommonPage {...pageProps} scrollContainer={CommonPageScrollContainer}>
119
+ <Stack>
120
+ <Box
121
+ sx={{
122
+ paddingBottom: pageProps.paddings
123
+ }}
124
+ >
125
+ <SearchBar fields={f} onSubmit={onSubmit} />
126
+ </Box>
127
+ <ScrollerListEx<T, D>
128
+ autoLoad={false}
129
+ loadData={localLoadData}
130
+ onUpdateRows={GridUtils.getUpdateRowsHandler<T>(cacheKey)}
131
+ onInitLoad={onInitLoad}
132
+ onScroll={onListScroll}
133
+ mRef={refs}
134
+ {...rest}
135
+ />
136
+ </Stack>
137
+ </CommonPage>
138
+ );
90
139
  }
@@ -1,12 +1,12 @@
1
- import { DataTypes } from '@etsoo/shared';
2
- import { ScrollerListExProps } from '../ScrollerListEx';
3
- import { SearchPageProps } from './SearchPageProps';
1
+ import { DataTypes } from "@etsoo/shared";
2
+ import { ScrollerListExProps } from "../ScrollerListEx";
3
+ import { SearchPageProps } from "./SearchPageProps";
4
4
 
5
5
  /**
6
6
  * List page props
7
7
  */
8
8
  export type ListPageProps<
9
- T extends object,
10
- F extends DataTypes.BasicTemplate,
11
- D extends DataTypes.Keys<T>
12
- > = SearchPageProps<T, F> & Omit<ScrollerListExProps<T, D>, 'loadData'>;
9
+ T extends object,
10
+ F extends DataTypes.BasicTemplate,
11
+ D extends DataTypes.Keys<T>
12
+ > = SearchPageProps<T, F> & Omit<ScrollerListExProps<T, D>, "loadData">;
@@ -9,10 +9,22 @@ export type SearchPageProps<
9
9
  T extends object,
10
10
  F extends DataTypes.BasicTemplate
11
11
  > = Omit<GridLoader<T>, "loadData"> & {
12
+ /**
13
+ * Cache key
14
+ */
15
+ cacheKey?: string;
16
+
17
+ /**
18
+ * Cache minutes
19
+ */
20
+ cacheMinutes?: number;
21
+
12
22
  /**
13
23
  * Search fields
14
24
  */
15
- fields: React.ReactElement[];
25
+ fields:
26
+ | React.ReactElement[]
27
+ | ((data: DataTypes.BasicTemplateType<F>) => React.ReactElement[]);
16
28
 
17
29
  /**
18
30
  * Search field template
@@ -1,17 +1,17 @@
1
1
  import {
2
- GridDataGet,
3
- GridLoadDataProps,
4
- useCombinedRefs,
5
- useDimensions
6
- } from '@etsoo/react';
7
- import { DataTypes, IdDefaultType } from '@etsoo/shared';
8
- import { Box, Stack } from '@mui/material';
9
- import React from 'react';
10
- import { MUGlobal } from '../MUGlobal';
11
- import { SearchBar } from '../SearchBar';
12
- import { TableEx, TableExMethodRef, TableExMinWidth } from '../TableEx';
13
- import { CommonPage, CommonPageScrollContainer } from './CommonPage';
14
- import { TablePageProps } from './TablePageProps';
2
+ GridLoadDataProps,
3
+ useCombinedRefs,
4
+ useDimensions
5
+ } from "@etsoo/react";
6
+ import { DataTypes, IdDefaultType } from "@etsoo/shared";
7
+ import { Box, Stack } from "@mui/material";
8
+ import React from "react";
9
+ import { MUGlobal } from "../MUGlobal";
10
+ import { SearchBar } from "../SearchBar";
11
+ import { TableEx, TableExMethodRef, TableExMinWidth } from "../TableEx";
12
+ import { CommonPage, CommonPageScrollContainer } from "./CommonPage";
13
+ import { TablePageProps } from "./TablePageProps";
14
+ import { GridUtils } from "../GridUtils";
15
15
 
16
16
  /**
17
17
  * Table page
@@ -19,108 +19,113 @@ import { TablePageProps } from './TablePageProps';
19
19
  * @returns Component
20
20
  */
21
21
  export function TablePage<
22
- T extends object,
23
- F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate,
24
- D extends DataTypes.Keys<T> = IdDefaultType<T>
22
+ T extends object,
23
+ F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate,
24
+ D extends DataTypes.Keys<T> = IdDefaultType<T>
25
25
  >(props: TablePageProps<T, F, D>) {
26
- // Destruct
27
- const {
28
- columns,
29
- fields,
30
- fieldTemplate,
31
- loadData,
32
- mRef,
33
- sizeReadyMiliseconds = 0,
34
- pageProps = {},
35
- ...rest
36
- } = props;
37
-
38
- pageProps.paddings ??= MUGlobal.pagePaddings;
39
-
40
- // States
41
- const [states] = React.useState<{
42
- data?: FormData;
43
- ref?: TableExMethodRef<T>;
44
- }>({});
45
-
46
- const refs = useCombinedRefs(
47
- mRef,
48
- (ref: TableExMethodRef<T> | null | undefined) => {
49
- if (ref == null) return;
50
-
51
- const first = states.ref == null;
52
-
53
- states.ref = ref;
54
-
55
- if (first) reset();
56
- }
57
- );
58
-
59
- const reset = () => {
60
- if (states.data == null || states.ref == null) return;
61
- states.ref.reset({ data: states.data });
62
- };
63
-
64
- // On submit callback
65
- const onSubmit = (data: FormData, _reset: boolean) => {
66
- states.data = data;
67
- reset();
68
- };
69
-
70
- const localLoadData = (props: GridLoadDataProps) => {
71
- const data = GridDataGet(props, fieldTemplate);
72
- return loadData(data);
73
- };
74
-
75
- // Total width
76
- const totalWidth = React.useMemo(
77
- () =>
78
- columns.reduce((previousValue, { width, minWidth }) => {
79
- return previousValue + (width ?? minWidth ?? TableExMinWidth);
80
- }, 0),
81
- [columns]
82
- );
83
-
84
- // Watch container
85
- const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds);
86
- const rect = dimensions[0][2];
87
- const list = React.useMemo(() => {
88
- if (rect != null && rect.height > 50 && rect.width >= totalWidth) {
89
- let maxHeight =
90
- document.documentElement.clientHeight -
91
- (rect.top + rect.height + 1);
92
-
93
- const style = window.getComputedStyle(dimensions[0][1]!);
94
- const paddingBottom = parseFloat(style.paddingBottom);
95
- if (!isNaN(paddingBottom)) maxHeight -= paddingBottom;
96
-
97
- return (
98
- <TableEx<T, D>
99
- autoLoad={false}
100
- columns={columns}
101
- loadData={localLoadData}
102
- maxHeight={maxHeight}
103
- mRef={refs}
104
- {...rest}
105
- />
106
- );
107
- }
108
- }, [rect]);
109
-
110
- // Layout
111
- return (
112
- <CommonPage {...pageProps} scrollContainer={CommonPageScrollContainer}>
113
- <Stack>
114
- <Box
115
- ref={dimensions[0][0]}
116
- sx={{
117
- paddingBottom: pageProps.paddings
118
- }}
119
- >
120
- <SearchBar fields={fields} onSubmit={onSubmit} />
121
- </Box>
122
- {list}
123
- </Stack>
124
- </CommonPage>
125
- );
26
+ // Destruct
27
+ const {
28
+ columns,
29
+ fields,
30
+ fieldTemplate,
31
+ loadData,
32
+ mRef,
33
+ sizeReadyMiliseconds = 0,
34
+ pageProps = {},
35
+ cacheKey,
36
+ cacheMinutes = 120,
37
+ ...rest
38
+ } = props;
39
+
40
+ pageProps.paddings ??= MUGlobal.pagePaddings;
41
+
42
+ // States
43
+ const [states] = React.useState<{
44
+ data?: FormData;
45
+ ref?: TableExMethodRef<T>;
46
+ }>({});
47
+
48
+ const refs = useCombinedRefs(
49
+ mRef,
50
+ (ref: TableExMethodRef<T> | null | undefined) => {
51
+ if (ref == null) return;
52
+
53
+ const first = states.ref == null;
54
+
55
+ states.ref = ref;
56
+
57
+ if (first) reset();
58
+ }
59
+ );
60
+
61
+ const reset = () => {
62
+ if (states.data == null || states.ref == null) return;
63
+ states.ref.reset({ data: states.data });
64
+ };
65
+
66
+ // On submit callback
67
+ const onSubmit = (data: FormData, _reset: boolean) => {
68
+ states.data = data;
69
+ reset();
70
+ };
71
+
72
+ const localLoadData = (props: GridLoadDataProps) => {
73
+ return loadData(GridUtils.createLoader<F>(props, fieldTemplate, cacheKey));
74
+ };
75
+
76
+ // Search data
77
+ const searchData = GridUtils.getSearchData<F>(cacheKey);
78
+
79
+ // Total width
80
+ const totalWidth = React.useMemo(
81
+ () =>
82
+ columns.reduce((previousValue, { width, minWidth }) => {
83
+ return previousValue + (width ?? minWidth ?? TableExMinWidth);
84
+ }, 0),
85
+ [columns]
86
+ );
87
+
88
+ // Watch container
89
+ const { dimensions } = useDimensions(1, undefined, sizeReadyMiliseconds);
90
+ const rect = dimensions[0][2];
91
+ const list = React.useMemo(() => {
92
+ if (rect != null && rect.height > 50 && rect.width >= totalWidth) {
93
+ let maxHeight =
94
+ document.documentElement.clientHeight - (rect.top + rect.height + 1);
95
+
96
+ const style = window.getComputedStyle(dimensions[0][1]!);
97
+ const paddingBottom = parseFloat(style.paddingBottom);
98
+ if (!isNaN(paddingBottom)) maxHeight -= paddingBottom;
99
+
100
+ return (
101
+ <TableEx<T, D>
102
+ autoLoad={false}
103
+ columns={columns}
104
+ loadData={localLoadData}
105
+ maxHeight={maxHeight}
106
+ mRef={refs}
107
+ {...rest}
108
+ />
109
+ );
110
+ }
111
+ }, [rect]);
112
+
113
+ const f = typeof fields == "function" ? fields(searchData ?? {}) : fields;
114
+
115
+ // Layout
116
+ return (
117
+ <CommonPage {...pageProps} scrollContainer={CommonPageScrollContainer}>
118
+ <Stack>
119
+ <Box
120
+ ref={dimensions[0][0]}
121
+ sx={{
122
+ paddingBottom: pageProps.paddings
123
+ }}
124
+ >
125
+ <SearchBar fields={f} onSubmit={onSubmit} />
126
+ </Box>
127
+ {list}
128
+ </Stack>
129
+ </CommonPage>
130
+ );
126
131
  }