@etsoo/materialui 1.4.72 → 1.4.74

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.
@@ -6,6 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.PullToRefreshUI = PullToRefreshUI;
7
7
  const jsx_runtime_1 = require("react/jsx-runtime");
8
8
  const react_1 = __importDefault(require("react"));
9
+ const shared_1 = require("@etsoo/shared");
10
+ let pr;
9
11
  /**
10
12
  * PullToRefresh UI
11
13
  * Use hammerjs or touchemulator to simulate browser as mobile device
@@ -15,14 +17,23 @@ const react_1 = __importDefault(require("react"));
15
17
  function PullToRefreshUI(props) {
16
18
  // Ready
17
19
  react_1.default.useEffect(() => {
18
- let pr;
19
- import("pulltorefreshjs").then((PullToRefresh) => {
20
- pr = PullToRefresh.default;
21
- pr.init(props);
22
- });
20
+ if (pr) {
21
+ // Loaded, delay a little bit
22
+ pr.destroyAll();
23
+ shared_1.ExtendUtils.waitFor(() => {
24
+ pr?.init(props);
25
+ }, 100);
26
+ }
27
+ else {
28
+ import("pulltorefreshjs").then((PullToRefresh) => {
29
+ pr = PullToRefresh.default;
30
+ pr.init(props);
31
+ });
32
+ }
23
33
  return () => {
24
- if (pr)
34
+ if (pr) {
25
35
  pr.destroyAll();
36
+ }
26
37
  };
27
38
  }, [props]);
28
39
  return (0, jsx_runtime_1.jsx)(react_1.default.Fragment, {});
@@ -89,6 +89,10 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProp
89
89
  * SearchBar bottom padding
90
90
  */
91
91
  searchBarBottom?: number;
92
+ /**
93
+ * SearchBar top
94
+ */
95
+ searchBarTop?: number | true;
92
96
  };
93
97
  /**
94
98
  * Responsible container
@@ -30,7 +30,7 @@ function defaultContainerBoxSx(paddings, hasField, _dataGrid) {
30
30
  */
31
31
  function ResponsibleContainer(props) {
32
32
  // Destruct
33
- const { adjustHeight, adjustFabHeight, cacheKey, cacheMinutes = 15, columns, containerBoxSx = defaultContainerBoxSx, elementReady, fields, fieldTemplate, height, loadData, mRef, paddings = MUGlobal_1.MUGlobal.pagePaddings, pullToRefresh = true, quickAction, sizeReadyMiliseconds = 0, searchBarHeight = 45.6, searchBarBottom = 8, ...rest } = props;
33
+ const { adjustHeight, adjustFabHeight, cacheKey, cacheMinutes = 15, columns, containerBoxSx = defaultContainerBoxSx, elementReady, fields, fieldTemplate, height, loadData, mRef, paddings = MUGlobal_1.MUGlobal.pagePaddings, pullToRefresh = true, quickAction, sizeReadyMiliseconds = 0, searchBarHeight = 45.6, searchBarBottom = 8, searchBarTop, ...rest } = props;
34
34
  // Labels
35
35
  const labels = Labels_1.Labels.CommonPage;
36
36
  // Refs
@@ -125,7 +125,7 @@ function ResponsibleContainer(props) {
125
125
  const list = (() => {
126
126
  // No layout
127
127
  if (rect == null)
128
- return [null, undefined];
128
+ return undefined;
129
129
  // Height
130
130
  let heightLocal;
131
131
  if (height != null) {
@@ -176,7 +176,7 @@ function ResponsibleContainer(props) {
176
176
  rect.width < 20)
177
177
  return;
178
178
  const f = typeof fields == "function" ? fields(searchData ?? {}) : fields;
179
- return ((0, jsx_runtime_1.jsx)(SearchBar_1.SearchBar, { fields: f, onSubmit: onSubmit, className: `searchBar${showDataGrid ? "Grid" : "List"}` }));
179
+ return ((0, jsx_runtime_1.jsx)(SearchBar_1.SearchBar, { fields: f, onSubmit: onSubmit, className: `searchBar${showDataGrid ? "Grid" : "List"}`, top: searchBarTop }));
180
180
  }, [showDataGrid, hasFields, searchBarHeight, rect?.width]);
181
181
  // Pull container
182
182
  const pullContainer = showDataGrid == null
@@ -189,7 +189,7 @@ function ResponsibleContainer(props) {
189
189
  ? undefined
190
190
  : containerBoxSx(paddings, hasFields, showDataGrid), children: [(0, jsx_runtime_1.jsxs)(material_1.Stack, { children: [(0, jsx_runtime_1.jsx)(material_1.Box, { ref: dimensions[0][0], className: "SearchBox", sx: {
191
191
  height: hasFields ? searchBarHeight : 0
192
- }, marginBottom: hasFields ? `${searchBarBottom}px!important` : undefined, children: searchBar }), list] }), pullToRefresh && pullContainer && ((0, jsx_runtime_1.jsx)(PullToRefreshUI_1.PullToRefreshUI, { mainElement: pullContainer, triggerElement: pullContainer, instructionsPullToRefresh: labels.pullToRefresh, instructionsReleaseToRefresh: labels.releaseToRefresh, instructionsRefreshing: labels.refreshing, onRefresh: () => state.ref?.reset(), shouldPullToRefresh: () => {
192
+ }, marginBottom: hasFields ? `${searchBarBottom}px!important` : undefined, children: searchBar }), list] }), pullToRefresh && pullContainer && list != null && ((0, jsx_runtime_1.jsx)(PullToRefreshUI_1.PullToRefreshUI, { mainElement: pullContainer, triggerElement: pullContainer, instructionsPullToRefresh: labels.pullToRefresh, instructionsReleaseToRefresh: labels.releaseToRefresh, instructionsRefreshing: labels.refreshing, onRefresh: () => state.ref?.reset(), shouldPullToRefresh: () => {
193
193
  const container = document.querySelector(pullContainer);
194
194
  return !container?.scrollTop;
195
195
  } }))] }));
@@ -23,6 +23,10 @@ export interface SearchBarProps {
23
23
  * On submit callback
24
24
  */
25
25
  onSubmit: (data: FormData, reset: boolean) => void | PromiseLike<void>;
26
+ /**
27
+ * Top position, true means Toolbar's height
28
+ */
29
+ top?: number | true;
26
30
  }
27
31
  /**
28
32
  * Search bar
@@ -75,7 +75,7 @@ function checkFormEvent(event) {
75
75
  */
76
76
  function SearchBar(props) {
77
77
  // Destruct
78
- const { className, fields, onSubmit, itemGap = 6, itemWidth = 160 } = props;
78
+ const { className, fields, onSubmit, itemGap = 6, itemWidth = 160, top } = props;
79
79
  // Labels
80
80
  const labels = Labels_1.Labels.CommonPage;
81
81
  // Menu index
@@ -257,14 +257,17 @@ function SearchBar(props) {
257
257
  display: "block",
258
258
  visibility: "visible"
259
259
  }
260
- }, children: [fields.map((item, index) => ((0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: item }, index))), (0, jsx_runtime_1.jsx)(material_1.IconButton, { title: labels.more, size: "medium", sx: { height: "40px" }, onClick: handleMore, children: (0, jsx_runtime_1.jsx)(MoreHoriz_1.default, {}) }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", size: "medium", ref: resetButtonRef, onClick: handleReset, children: labels.reset })] }) }), hasMoreItems && ((0, jsx_runtime_1.jsx)(material_1.Drawer, { anchor: "right", sx: { minWidth: "180px" }, ModalProps: {
260
+ }, children: [fields.map((item, index) => ((0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: item }, index))), (0, jsx_runtime_1.jsx)(material_1.IconButton, { title: labels.more, size: "medium", sx: { height: "40px" }, onClick: handleMore, children: (0, jsx_runtime_1.jsx)(MoreHoriz_1.default, {}) }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", size: "medium", ref: resetButtonRef, onClick: handleReset, children: labels.reset })] }) }), hasMoreItems && ((0, jsx_runtime_1.jsxs)(material_1.Drawer, { anchor: "right", sx: {
261
+ minWidth: "180px",
262
+ paddingTop: typeof top === "number" ? `${top}px` : undefined
263
+ }, ModalProps: {
261
264
  keepMounted: true
262
- }, open: open, onClose: () => updateOpen(false), children: (0, jsx_runtime_1.jsx)("form", { onChange: moreFormChange, ref: (form) => {
263
- if (form)
264
- state.moreForm = form;
265
- }, children: (0, jsx_runtime_1.jsx)(material_1.Stack, { direction: "column", alignItems: "stretch", spacing: 2, padding: 2, sx: {
266
- "& > :not(style)": {
267
- minWidth: "100px"
268
- }
269
- }, children: moreItems }) }) }))] }));
265
+ }, open: open, onClose: () => updateOpen(false), children: [top === true && (0, jsx_runtime_1.jsx)(material_1.Toolbar, {}), (0, jsx_runtime_1.jsx)("form", { onChange: moreFormChange, ref: (form) => {
266
+ if (form)
267
+ state.moreForm = form;
268
+ }, children: (0, jsx_runtime_1.jsx)(material_1.Stack, { direction: "column", alignItems: "stretch", spacing: 2, padding: 2, sx: {
269
+ "& > :not(style)": {
270
+ minWidth: "100px"
271
+ }
272
+ }, children: moreItems }) })] }))] }));
270
273
  }
@@ -20,7 +20,7 @@ const GridUtils_1 = require("../GridUtils");
20
20
  */
21
21
  function DataGridPage(props) {
22
22
  // Destruct
23
- const { adjustHeight, fields, fieldTemplate, height, loadData, mRef, sizeReadyMiliseconds = 100, pageProps = {}, cacheKey, cacheMinutes = 15, ...rest } = props;
23
+ const { adjustHeight, fields, fieldTemplate, height, loadData, mRef, sizeReadyMiliseconds = 100, pageProps = {}, cacheKey, cacheMinutes = 15, searchBarTop, ...rest } = props;
24
24
  pageProps.paddings ??= MUGlobal_1.MUGlobal.pagePaddings;
25
25
  // States
26
26
  const [states, setStates] = react_2.default.useReducer((currentState, newState) => {
@@ -110,5 +110,5 @@ function DataGridPage(props) {
110
110
  // Layout
111
111
  return ((0, jsx_runtime_1.jsx)(CommonPage_1.CommonPage, { ...pageProps, scrollContainer: states.element, children: (0, jsx_runtime_1.jsxs)(material_1.Stack, { children: [(0, jsx_runtime_1.jsx)(material_1.Box, { ref: dimensions[0][0], sx: {
112
112
  paddingBottom: pageProps.paddings
113
- }, children: (0, jsx_runtime_1.jsx)(SearchBar_1.SearchBar, { fields: f, onSubmit: onSubmit }) }), list] }) }));
113
+ }, children: (0, jsx_runtime_1.jsx)(SearchBar_1.SearchBar, { fields: f, onSubmit: onSubmit, top: searchBarTop }) }), list] }) }));
114
114
  }
@@ -20,7 +20,7 @@ const GridUtils_1 = require("../GridUtils");
20
20
  */
21
21
  function FixedListPage(props) {
22
22
  // Destruct
23
- const { adjustHeight, fields, fieldTemplate, loadData, mRef, sizeReadyMiliseconds = 0, pageProps = {}, cacheKey, cacheMinutes = 15, ...rest } = props;
23
+ const { adjustHeight, fields, fieldTemplate, loadData, mRef, sizeReadyMiliseconds = 0, pageProps = {}, cacheKey, cacheMinutes = 15, searchBarTop, ...rest } = props;
24
24
  pageProps.paddings ??= MUGlobal_1.MUGlobal.pagePaddings;
25
25
  // States
26
26
  const [states] = react_2.default.useState({});
@@ -100,5 +100,5 @@ function FixedListPage(props) {
100
100
  const f = typeof fields == "function" ? fields(searchData ?? {}) : fields;
101
101
  const { paddings, ...pageRest } = pageProps;
102
102
  // Layout
103
- return ((0, jsx_runtime_1.jsx)(CommonPage_1.CommonPage, { ...pageRest, paddings: {}, scrollContainer: scrollContainer, children: (0, jsx_runtime_1.jsxs)(material_1.Stack, { children: [(0, jsx_runtime_1.jsx)(material_1.Box, { ref: dimensions[0][0], sx: { padding: paddings }, children: (0, jsx_runtime_1.jsx)(SearchBar_1.SearchBar, { fields: f, onSubmit: onSubmit }) }), list] }) }));
103
+ return ((0, jsx_runtime_1.jsx)(CommonPage_1.CommonPage, { ...pageRest, paddings: {}, scrollContainer: scrollContainer, children: (0, jsx_runtime_1.jsxs)(material_1.Stack, { children: [(0, jsx_runtime_1.jsx)(material_1.Box, { ref: dimensions[0][0], sx: { padding: paddings }, children: (0, jsx_runtime_1.jsx)(SearchBar_1.SearchBar, { fields: f, onSubmit: onSubmit, top: searchBarTop }) }), list] }) }));
104
104
  }
@@ -20,7 +20,7 @@ const GridUtils_1 = require("../GridUtils");
20
20
  */
21
21
  function ListPage(props) {
22
22
  // Destruct
23
- const { fields, fieldTemplate, loadData, mRef, pageProps = {}, cacheKey, cacheMinutes = 15, ...rest } = props;
23
+ const { fields, fieldTemplate, loadData, mRef, pageProps = {}, cacheKey, cacheMinutes = 15, searchBarTop, ...rest } = props;
24
24
  pageProps.paddings ??= MUGlobal_1.MUGlobal.pagePaddings;
25
25
  // States
26
26
  const [states] = react_2.default.useState({});
@@ -79,5 +79,5 @@ function ListPage(props) {
79
79
  // Layout
80
80
  return ((0, jsx_runtime_1.jsx)(CommonPage_1.CommonPage, { ...pageProps, scrollContainer: globalThis, children: (0, jsx_runtime_1.jsxs)(material_1.Stack, { children: [(0, jsx_runtime_1.jsx)(material_1.Box, { sx: {
81
81
  paddingBottom: pageProps.paddings
82
- }, children: (0, jsx_runtime_1.jsx)(SearchBar_1.SearchBar, { fields: f, onSubmit: onSubmit }) }), (0, jsx_runtime_1.jsx)(ScrollerListEx_1.ScrollerListEx, { autoLoad: false, loadData: localLoadData, onUpdateRows: GridUtils_1.GridUtils.getUpdateRowsHandler(cacheKey), onInitLoad: onInitLoad, onScroll: onListScroll, mRef: refs, ...rest })] }) }));
82
+ }, children: (0, jsx_runtime_1.jsx)(SearchBar_1.SearchBar, { fields: f, onSubmit: onSubmit, top: searchBarTop }) }), (0, jsx_runtime_1.jsx)(ScrollerListEx_1.ScrollerListEx, { autoLoad: false, loadData: localLoadData, onUpdateRows: GridUtils_1.GridUtils.getUpdateRowsHandler(cacheKey), onInitLoad: onInitLoad, onScroll: onListScroll, mRef: refs, ...rest })] }) }));
83
83
  }
@@ -33,4 +33,8 @@ export type SearchPageProps<T extends object, F> = GridLoader<T, GridJsonData &
33
33
  * SearchBar height
34
34
  */
35
35
  searchBarHeight?: number;
36
+ /**
37
+ * SearchBar top
38
+ */
39
+ searchBarTop?: number | true;
36
40
  };
@@ -1,5 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import React from "react";
3
+ import { ExtendUtils } from "@etsoo/shared";
4
+ let pr;
3
5
  /**
4
6
  * PullToRefresh UI
5
7
  * Use hammerjs or touchemulator to simulate browser as mobile device
@@ -9,14 +11,23 @@ import React from "react";
9
11
  export function PullToRefreshUI(props) {
10
12
  // Ready
11
13
  React.useEffect(() => {
12
- let pr;
13
- import("pulltorefreshjs").then((PullToRefresh) => {
14
- pr = PullToRefresh.default;
15
- pr.init(props);
16
- });
14
+ if (pr) {
15
+ // Loaded, delay a little bit
16
+ pr.destroyAll();
17
+ ExtendUtils.waitFor(() => {
18
+ pr?.init(props);
19
+ }, 100);
20
+ }
21
+ else {
22
+ import("pulltorefreshjs").then((PullToRefresh) => {
23
+ pr = PullToRefresh.default;
24
+ pr.init(props);
25
+ });
26
+ }
17
27
  return () => {
18
- if (pr)
28
+ if (pr) {
19
29
  pr.destroyAll();
30
+ }
20
31
  };
21
32
  }, [props]);
22
33
  return _jsx(React.Fragment, {});
@@ -89,6 +89,10 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProp
89
89
  * SearchBar bottom padding
90
90
  */
91
91
  searchBarBottom?: number;
92
+ /**
93
+ * SearchBar top
94
+ */
95
+ searchBarTop?: number | true;
92
96
  };
93
97
  /**
94
98
  * Responsible container
@@ -24,7 +24,7 @@ function defaultContainerBoxSx(paddings, hasField, _dataGrid) {
24
24
  */
25
25
  export function ResponsibleContainer(props) {
26
26
  // Destruct
27
- const { adjustHeight, adjustFabHeight, cacheKey, cacheMinutes = 15, columns, containerBoxSx = defaultContainerBoxSx, elementReady, fields, fieldTemplate, height, loadData, mRef, paddings = MUGlobal.pagePaddings, pullToRefresh = true, quickAction, sizeReadyMiliseconds = 0, searchBarHeight = 45.6, searchBarBottom = 8, ...rest } = props;
27
+ const { adjustHeight, adjustFabHeight, cacheKey, cacheMinutes = 15, columns, containerBoxSx = defaultContainerBoxSx, elementReady, fields, fieldTemplate, height, loadData, mRef, paddings = MUGlobal.pagePaddings, pullToRefresh = true, quickAction, sizeReadyMiliseconds = 0, searchBarHeight = 45.6, searchBarBottom = 8, searchBarTop, ...rest } = props;
28
28
  // Labels
29
29
  const labels = Labels.CommonPage;
30
30
  // Refs
@@ -119,7 +119,7 @@ export function ResponsibleContainer(props) {
119
119
  const list = (() => {
120
120
  // No layout
121
121
  if (rect == null)
122
- return [null, undefined];
122
+ return undefined;
123
123
  // Height
124
124
  let heightLocal;
125
125
  if (height != null) {
@@ -170,7 +170,7 @@ export function ResponsibleContainer(props) {
170
170
  rect.width < 20)
171
171
  return;
172
172
  const f = typeof fields == "function" ? fields(searchData ?? {}) : fields;
173
- return (_jsx(SearchBar, { fields: f, onSubmit: onSubmit, className: `searchBar${showDataGrid ? "Grid" : "List"}` }));
173
+ return (_jsx(SearchBar, { fields: f, onSubmit: onSubmit, className: `searchBar${showDataGrid ? "Grid" : "List"}`, top: searchBarTop }));
174
174
  }, [showDataGrid, hasFields, searchBarHeight, rect?.width]);
175
175
  // Pull container
176
176
  const pullContainer = showDataGrid == null
@@ -183,7 +183,7 @@ export function ResponsibleContainer(props) {
183
183
  ? undefined
184
184
  : containerBoxSx(paddings, hasFields, showDataGrid), children: [_jsxs(Stack, { children: [_jsx(Box, { ref: dimensions[0][0], className: "SearchBox", sx: {
185
185
  height: hasFields ? searchBarHeight : 0
186
- }, marginBottom: hasFields ? `${searchBarBottom}px!important` : undefined, children: searchBar }), list] }), pullToRefresh && pullContainer && (_jsx(PullToRefreshUI, { mainElement: pullContainer, triggerElement: pullContainer, instructionsPullToRefresh: labels.pullToRefresh, instructionsReleaseToRefresh: labels.releaseToRefresh, instructionsRefreshing: labels.refreshing, onRefresh: () => state.ref?.reset(), shouldPullToRefresh: () => {
186
+ }, marginBottom: hasFields ? `${searchBarBottom}px!important` : undefined, children: searchBar }), list] }), pullToRefresh && pullContainer && list != null && (_jsx(PullToRefreshUI, { mainElement: pullContainer, triggerElement: pullContainer, instructionsPullToRefresh: labels.pullToRefresh, instructionsReleaseToRefresh: labels.releaseToRefresh, instructionsRefreshing: labels.refreshing, onRefresh: () => state.ref?.reset(), shouldPullToRefresh: () => {
187
187
  const container = document.querySelector(pullContainer);
188
188
  return !container?.scrollTop;
189
189
  } }))] }));
@@ -23,6 +23,10 @@ export interface SearchBarProps {
23
23
  * On submit callback
24
24
  */
25
25
  onSubmit: (data: FormData, reset: boolean) => void | PromiseLike<void>;
26
+ /**
27
+ * Top position, true means Toolbar's height
28
+ */
29
+ top?: number | true;
26
30
  }
27
31
  /**
28
32
  * Search bar
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Button, Drawer, IconButton, Stack } from "@mui/material";
2
+ import { Button, Drawer, IconButton, Stack, Toolbar } from "@mui/material";
3
3
  import React from "react";
4
4
  import MoreHorizIcon from "@mui/icons-material/MoreHoriz";
5
5
  import { DomUtils, NumberUtils } from "@etsoo/shared";
@@ -69,7 +69,7 @@ function checkFormEvent(event) {
69
69
  */
70
70
  export function SearchBar(props) {
71
71
  // Destruct
72
- const { className, fields, onSubmit, itemGap = 6, itemWidth = 160 } = props;
72
+ const { className, fields, onSubmit, itemGap = 6, itemWidth = 160, top } = props;
73
73
  // Labels
74
74
  const labels = Labels.CommonPage;
75
75
  // Menu index
@@ -251,14 +251,17 @@ export function SearchBar(props) {
251
251
  display: "block",
252
252
  visibility: "visible"
253
253
  }
254
- }, children: [fields.map((item, index) => (_jsx(React.Fragment, { children: item }, index))), _jsx(IconButton, { title: labels.more, size: "medium", sx: { height: "40px" }, onClick: handleMore, children: _jsx(MoreHorizIcon, {}) }), _jsx(Button, { variant: "contained", size: "medium", ref: resetButtonRef, onClick: handleReset, children: labels.reset })] }) }), hasMoreItems && (_jsx(Drawer, { anchor: "right", sx: { minWidth: "180px" }, ModalProps: {
254
+ }, children: [fields.map((item, index) => (_jsx(React.Fragment, { children: item }, index))), _jsx(IconButton, { title: labels.more, size: "medium", sx: { height: "40px" }, onClick: handleMore, children: _jsx(MoreHorizIcon, {}) }), _jsx(Button, { variant: "contained", size: "medium", ref: resetButtonRef, onClick: handleReset, children: labels.reset })] }) }), hasMoreItems && (_jsxs(Drawer, { anchor: "right", sx: {
255
+ minWidth: "180px",
256
+ paddingTop: typeof top === "number" ? `${top}px` : undefined
257
+ }, ModalProps: {
255
258
  keepMounted: true
256
- }, open: open, onClose: () => updateOpen(false), children: _jsx("form", { onChange: moreFormChange, ref: (form) => {
257
- if (form)
258
- state.moreForm = form;
259
- }, children: _jsx(Stack, { direction: "column", alignItems: "stretch", spacing: 2, padding: 2, sx: {
260
- "& > :not(style)": {
261
- minWidth: "100px"
262
- }
263
- }, children: moreItems }) }) }))] }));
259
+ }, open: open, onClose: () => updateOpen(false), children: [top === true && _jsx(Toolbar, {}), _jsx("form", { onChange: moreFormChange, ref: (form) => {
260
+ if (form)
261
+ state.moreForm = form;
262
+ }, children: _jsx(Stack, { direction: "column", alignItems: "stretch", spacing: 2, padding: 2, sx: {
263
+ "& > :not(style)": {
264
+ minWidth: "100px"
265
+ }
266
+ }, children: moreItems }) })] }))] }));
264
267
  }
@@ -14,7 +14,7 @@ import { GridUtils } from "../GridUtils";
14
14
  */
15
15
  export function DataGridPage(props) {
16
16
  // Destruct
17
- const { adjustHeight, fields, fieldTemplate, height, loadData, mRef, sizeReadyMiliseconds = 100, pageProps = {}, cacheKey, cacheMinutes = 15, ...rest } = props;
17
+ const { adjustHeight, fields, fieldTemplate, height, loadData, mRef, sizeReadyMiliseconds = 100, pageProps = {}, cacheKey, cacheMinutes = 15, searchBarTop, ...rest } = props;
18
18
  pageProps.paddings ??= MUGlobal.pagePaddings;
19
19
  // States
20
20
  const [states, setStates] = React.useReducer((currentState, newState) => {
@@ -104,5 +104,5 @@ export function DataGridPage(props) {
104
104
  // Layout
105
105
  return (_jsx(CommonPage, { ...pageProps, scrollContainer: states.element, children: _jsxs(Stack, { children: [_jsx(Box, { ref: dimensions[0][0], sx: {
106
106
  paddingBottom: pageProps.paddings
107
- }, children: _jsx(SearchBar, { fields: f, onSubmit: onSubmit }) }), list] }) }));
107
+ }, children: _jsx(SearchBar, { fields: f, onSubmit: onSubmit, top: searchBarTop }) }), list] }) }));
108
108
  }
@@ -14,7 +14,7 @@ import { GridUtils } from "../GridUtils";
14
14
  */
15
15
  export function FixedListPage(props) {
16
16
  // Destruct
17
- const { adjustHeight, fields, fieldTemplate, loadData, mRef, sizeReadyMiliseconds = 0, pageProps = {}, cacheKey, cacheMinutes = 15, ...rest } = props;
17
+ const { adjustHeight, fields, fieldTemplate, loadData, mRef, sizeReadyMiliseconds = 0, pageProps = {}, cacheKey, cacheMinutes = 15, searchBarTop, ...rest } = props;
18
18
  pageProps.paddings ??= MUGlobal.pagePaddings;
19
19
  // States
20
20
  const [states] = React.useState({});
@@ -94,5 +94,5 @@ export function FixedListPage(props) {
94
94
  const f = typeof fields == "function" ? fields(searchData ?? {}) : fields;
95
95
  const { paddings, ...pageRest } = pageProps;
96
96
  // Layout
97
- return (_jsx(CommonPage, { ...pageRest, paddings: {}, scrollContainer: scrollContainer, children: _jsxs(Stack, { children: [_jsx(Box, { ref: dimensions[0][0], sx: { padding: paddings }, children: _jsx(SearchBar, { fields: f, onSubmit: onSubmit }) }), list] }) }));
97
+ return (_jsx(CommonPage, { ...pageRest, paddings: {}, scrollContainer: scrollContainer, children: _jsxs(Stack, { children: [_jsx(Box, { ref: dimensions[0][0], sx: { padding: paddings }, children: _jsx(SearchBar, { fields: f, onSubmit: onSubmit, top: searchBarTop }) }), list] }) }));
98
98
  }
@@ -14,7 +14,7 @@ import { GridUtils } from "../GridUtils";
14
14
  */
15
15
  export function ListPage(props) {
16
16
  // Destruct
17
- const { fields, fieldTemplate, loadData, mRef, pageProps = {}, cacheKey, cacheMinutes = 15, ...rest } = props;
17
+ const { fields, fieldTemplate, loadData, mRef, pageProps = {}, cacheKey, cacheMinutes = 15, searchBarTop, ...rest } = props;
18
18
  pageProps.paddings ??= MUGlobal.pagePaddings;
19
19
  // States
20
20
  const [states] = React.useState({});
@@ -73,5 +73,5 @@ export function ListPage(props) {
73
73
  // Layout
74
74
  return (_jsx(CommonPage, { ...pageProps, scrollContainer: globalThis, children: _jsxs(Stack, { children: [_jsx(Box, { sx: {
75
75
  paddingBottom: pageProps.paddings
76
- }, children: _jsx(SearchBar, { fields: f, onSubmit: onSubmit }) }), _jsx(ScrollerListEx, { autoLoad: false, loadData: localLoadData, onUpdateRows: GridUtils.getUpdateRowsHandler(cacheKey), onInitLoad: onInitLoad, onScroll: onListScroll, mRef: refs, ...rest })] }) }));
76
+ }, children: _jsx(SearchBar, { fields: f, onSubmit: onSubmit, top: searchBarTop }) }), _jsx(ScrollerListEx, { autoLoad: false, loadData: localLoadData, onUpdateRows: GridUtils.getUpdateRowsHandler(cacheKey), onInitLoad: onInitLoad, onScroll: onListScroll, mRef: refs, ...rest })] }) }));
77
77
  }
@@ -33,4 +33,8 @@ export type SearchPageProps<T extends object, F> = GridLoader<T, GridJsonData &
33
33
  * SearchBar height
34
34
  */
35
35
  searchBarHeight?: number;
36
+ /**
37
+ * SearchBar top
38
+ */
39
+ searchBarTop?: number | true;
36
40
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.4.72",
3
+ "version": "1.4.74",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -40,9 +40,9 @@
40
40
  "@dnd-kit/sortable": "^10.0.0",
41
41
  "@emotion/react": "^11.14.0",
42
42
  "@emotion/styled": "^11.14.0",
43
- "@etsoo/appscript": "^1.5.88",
43
+ "@etsoo/appscript": "^1.5.89",
44
44
  "@etsoo/notificationbase": "^1.1.55",
45
- "@etsoo/react": "^1.8.24",
45
+ "@etsoo/react": "^1.8.25",
46
46
  "@etsoo/shared": "^1.2.58",
47
47
  "@mui/icons-material": "^6.3.1",
48
48
  "@mui/material": "^6.3.1",
@@ -1,8 +1,10 @@
1
1
  import React from "react";
2
2
  import type { Options } from "pulltorefreshjs";
3
3
  import type PullToRefresh from "pulltorefreshjs";
4
+ import { ExtendUtils } from "@etsoo/shared";
4
5
 
5
6
  type p = typeof PullToRefresh;
7
+ let pr: p | null;
6
8
 
7
9
  /**
8
10
  * PullToRefresh UI
@@ -13,14 +15,23 @@ type p = typeof PullToRefresh;
13
15
  export function PullToRefreshUI(props: Options) {
14
16
  // Ready
15
17
  React.useEffect(() => {
16
- let pr: p | null;
17
- import("pulltorefreshjs").then((PullToRefresh) => {
18
- pr = PullToRefresh.default;
19
- pr.init(props);
20
- });
18
+ if (pr) {
19
+ // Loaded, delay a little bit
20
+ pr.destroyAll();
21
+ ExtendUtils.waitFor(() => {
22
+ pr?.init(props);
23
+ }, 100);
24
+ } else {
25
+ import("pulltorefreshjs").then((PullToRefresh) => {
26
+ pr = PullToRefresh.default;
27
+ pr.init(props);
28
+ });
29
+ }
21
30
 
22
31
  return () => {
23
- if (pr) pr.destroyAll();
32
+ if (pr) {
33
+ pr.destroyAll();
34
+ }
24
35
  };
25
36
  }, [props]);
26
37
 
@@ -154,6 +154,11 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<
154
154
  * SearchBar bottom padding
155
155
  */
156
156
  searchBarBottom?: number;
157
+
158
+ /**
159
+ * SearchBar top
160
+ */
161
+ searchBarTop?: number | true;
157
162
  };
158
163
 
159
164
  interface LocalRefs<T> {
@@ -205,6 +210,7 @@ export function ResponsibleContainer<T extends object, F>(
205
210
  sizeReadyMiliseconds = 0,
206
211
  searchBarHeight = 45.6,
207
212
  searchBarBottom = 8,
213
+ searchBarTop,
208
214
  ...rest
209
215
  } = props;
210
216
 
@@ -336,7 +342,7 @@ export function ResponsibleContainer<T extends object, F>(
336
342
  // Create list
337
343
  const list = (() => {
338
344
  // No layout
339
- if (rect == null) return [null, undefined];
345
+ if (rect == null) return undefined;
340
346
 
341
347
  // Height
342
348
  let heightLocal: number;
@@ -435,6 +441,7 @@ export function ResponsibleContainer<T extends object, F>(
435
441
  fields={f}
436
442
  onSubmit={onSubmit}
437
443
  className={`searchBar${showDataGrid ? "Grid" : "List"}`}
444
+ top={searchBarTop}
438
445
  />
439
446
  );
440
447
  }, [showDataGrid, hasFields, searchBarHeight, rect?.width]);
@@ -471,7 +478,7 @@ export function ResponsibleContainer<T extends object, F>(
471
478
  </Box>
472
479
  {list}
473
480
  </Stack>
474
- {pullToRefresh && pullContainer && (
481
+ {pullToRefresh && pullContainer && list != null && (
475
482
  <PullToRefreshUI
476
483
  mainElement={pullContainer}
477
484
  triggerElement={pullContainer}
package/src/SearchBar.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { Button, Drawer, IconButton, Stack } from "@mui/material";
1
+ import { Button, Drawer, IconButton, Stack, Toolbar } from "@mui/material";
2
2
  import React from "react";
3
3
  import MoreHorizIcon from "@mui/icons-material/MoreHoriz";
4
4
  import { DomUtils, NumberUtils } from "@etsoo/shared";
@@ -33,6 +33,11 @@ export interface SearchBarProps {
33
33
  * On submit callback
34
34
  */
35
35
  onSubmit: (data: FormData, reset: boolean) => void | PromiseLike<void>;
36
+
37
+ /**
38
+ * Top position, true means Toolbar's height
39
+ */
40
+ top?: number | true;
36
41
  }
37
42
 
38
43
  // Cached width attribute name
@@ -107,7 +112,14 @@ function checkFormEvent(event: React.FormEvent<HTMLFormElement>) {
107
112
  */
108
113
  export function SearchBar(props: SearchBarProps) {
109
114
  // Destruct
110
- const { className, fields, onSubmit, itemGap = 6, itemWidth = 160 } = props;
115
+ const {
116
+ className,
117
+ fields,
118
+ onSubmit,
119
+ itemGap = 6,
120
+ itemWidth = 160,
121
+ top
122
+ } = props;
111
123
 
112
124
  // Labels
113
125
  const labels = Labels.CommonPage;
@@ -377,13 +389,17 @@ export function SearchBar(props: SearchBarProps) {
377
389
  {hasMoreItems && (
378
390
  <Drawer
379
391
  anchor="right"
380
- sx={{ minWidth: "180px" }}
392
+ sx={{
393
+ minWidth: "180px",
394
+ paddingTop: typeof top === "number" ? `${top}px` : undefined
395
+ }}
381
396
  ModalProps={{
382
397
  keepMounted: true
383
398
  }}
384
399
  open={open}
385
400
  onClose={() => updateOpen(false)}
386
401
  >
402
+ {top === true && <Toolbar />}
387
403
  <form
388
404
  onChange={moreFormChange}
389
405
  ref={(form) => {
@@ -43,6 +43,7 @@ export function DataGridPage<T extends object, F>(
43
43
  pageProps = {},
44
44
  cacheKey,
45
45
  cacheMinutes = 15,
46
+ searchBarTop,
46
47
  ...rest
47
48
  } = props;
48
49
 
@@ -185,7 +186,7 @@ export function DataGridPage<T extends object, F>(
185
186
  paddingBottom: pageProps.paddings
186
187
  }}
187
188
  >
188
- <SearchBar fields={f} onSubmit={onSubmit} />
189
+ <SearchBar fields={f} onSubmit={onSubmit} top={searchBarTop} />
189
190
  </Box>
190
191
  {list}
191
192
  </Stack>
@@ -42,6 +42,7 @@ export function FixedListPage<T extends object, F>(
42
42
  pageProps = {},
43
43
  cacheKey,
44
44
  cacheMinutes = 15,
45
+ searchBarTop,
45
46
  ...rest
46
47
  } = props;
47
48
 
@@ -178,7 +179,7 @@ export function FixedListPage<T extends object, F>(
178
179
  <CommonPage {...pageRest} paddings={{}} scrollContainer={scrollContainer}>
179
180
  <Stack>
180
181
  <Box ref={dimensions[0][0]} sx={{ padding: paddings }}>
181
- <SearchBar fields={f} onSubmit={onSubmit} />
182
+ <SearchBar fields={f} onSubmit={onSubmit} top={searchBarTop} />
182
183
  </Box>
183
184
  {list}
184
185
  </Stack>
@@ -36,6 +36,7 @@ export function ListPage<T extends object, F>(props: ListPageProps<T, F>) {
36
36
  pageProps = {},
37
37
  cacheKey,
38
38
  cacheMinutes = 15,
39
+ searchBarTop,
39
40
  ...rest
40
41
  } = props;
41
42
 
@@ -126,7 +127,7 @@ export function ListPage<T extends object, F>(props: ListPageProps<T, F>) {
126
127
  paddingBottom: pageProps.paddings
127
128
  }}
128
129
  >
129
- <SearchBar fields={f} onSubmit={onSubmit} />
130
+ <SearchBar fields={f} onSubmit={onSubmit} top={searchBarTop} />
130
131
  </Box>
131
132
  <ScrollerListEx<T>
132
133
  autoLoad={false}
@@ -45,4 +45,9 @@ export type SearchPageProps<T extends object, F> = GridLoader<
45
45
  * SearchBar height
46
46
  */
47
47
  searchBarHeight?: number;
48
+
49
+ /**
50
+ * SearchBar top
51
+ */
52
+ searchBarTop?: number | true;
48
53
  };