@etsoo/materialui 1.5.72 → 1.5.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.
@@ -1,12 +1,12 @@
1
- import { act, render } from "@testing-library/react";
1
+ import { act, render, renderHook } from "@testing-library/react";
2
2
  import {
3
- MUGlobal,
4
3
  MobileListItemRenderer,
5
4
  ReactAppContext,
6
5
  ResponsivePage,
7
6
  SearchField
8
7
  } from "../src";
9
8
  import React from "react";
9
+ import { GridMethodRef } from "@etsoo/react";
10
10
 
11
11
  globalThis.ResizeObserver = vi.fn().mockImplementation(() => ({
12
12
  observe: vi.fn(),
@@ -32,15 +32,21 @@ const fieldTemplate = {
32
32
  name: "string"
33
33
  } as const;
34
34
 
35
- it("Render ResponsePage", async () => {
35
+ it("Render ResponsivePage", async () => {
36
36
  act(() => {
37
+ // Hook
38
+ const { result: ref } = renderHook(() =>
39
+ React.useRef<GridMethodRef<Data>>(undefined)
40
+ );
41
+
37
42
  // Act
38
43
  render(
39
44
  <ReactAppContext.Provider value={null}>
40
45
  <ResponsivePage<Data, typeof fieldTemplate>
41
46
  fields={[<SearchField label="Keyword" name="keyword" minChars={2} />]}
42
47
  height={200}
43
- itemSize={[118, MUGlobal.pagePaddings]}
48
+ rowHeight={[53, 116]}
49
+ mRef={ref.current}
44
50
  fieldTemplate={fieldTemplate}
45
51
  loadData={({ id }) =>
46
52
  Promise.resolve([
@@ -58,7 +64,7 @@ it("Render ResponsePage", async () => {
58
64
  valueFormatter: ({ data }) => data?.deviceName ?? data?.name
59
65
  }
60
66
  ]}
61
- innerItemRenderer={(props) =>
67
+ itemRenderer={(props) =>
62
68
  MobileListItemRenderer(props, (data) => {
63
69
  return [
64
70
  data.name,
@@ -14,7 +14,7 @@ export type DataGridExFooterItemRendererProps<T extends object> = {
14
14
  /**
15
15
  * Extended DataGrid with VariableSizeGrid props
16
16
  */
17
- export type DataGridExProps<T extends object, P extends GridJsonData = GridLoadDataProps> = Omit<ScrollerGridProps<T, P>, "cellComponent" | "columnCount" | "columnWidth" | "onClick" | "onDoubleClick" | "onInitLoad" | "width"> & {
17
+ export type DataGridExProps<T extends object, P extends GridJsonData = GridLoadDataProps> = Omit<ScrollerGridProps<T, P>, "cellComponent" | "columnCount" | "columnWidth" | "onClick" | "onDoubleClick" | "onInitLoad" | "rowHeight" | "width"> & Partial<Pick<ScrollerGridProps<T, P>, "rowHeight">> & {
18
18
  /**
19
19
  * Alternating colors for odd/even rows
20
20
  */
@@ -137,7 +137,7 @@ function DataGridEx(props) {
137
137
  }) }));
138
138
  }
139
139
  // Destruct
140
- const { alternatingColors = [theme.palette.grey[100], undefined], borderRowsCount, bottomHeight = 53, cacheKey, cacheMinutes = 15, checkable = false, className, columns, defaultOrderBy, height, headerHeight = 56, headerRenderer = defaultHeaderRenderer, footerRenderer = defaultFooterRenderer, footerItemRenderer = DataGridRenderers_1.DataGridRenderers.defaultFooterItemRenderer, hideFooter = false, hoverColor = "#f6f9fb", idField = "id", mRef = react_2.default.createRef(), onClick, onDataChange, onDoubleClick, onUpdateRows, selectable = true, selectedColor = "#edf4fb", width, ...rest } = props;
140
+ const { alternatingColors = [theme.palette.grey[100], undefined], borderRowsCount, bottomHeight = 53, cacheKey, cacheMinutes = 15, checkable = false, className, columns, defaultOrderBy, height, headerHeight = 56, headerRenderer = defaultHeaderRenderer, footerRenderer = defaultFooterRenderer, footerItemRenderer = DataGridRenderers_1.DataGridRenderers.defaultFooterItemRenderer, hideFooter = false, hoverColor = "#f6f9fb", idField = "id", mRef = react_2.default.createRef(), onClick, onDataChange, onDoubleClick, onUpdateRows, rowHeight = 53, selectable = true, selectedColor = "#edf4fb", width, ...rest } = props;
141
141
  if (checkable) {
142
142
  const cbColumn = {
143
143
  field: "selected", // Avoid validation from data model
@@ -314,7 +314,7 @@ function DataGridEx(props) {
314
314
  headerHeight -
315
315
  (hideFooter ? 0 : bottomHeight + 1) -
316
316
  scrollbarSize
317
- : height, headerRenderer: headerRenderer, idField: idField, footerRenderer: hideFooter ? undefined : footerRenderer, width: Math.max(width ?? 0, widthCalculator.total), mRef: mRefLocal, ...rest }));
317
+ : height, headerRenderer: headerRenderer, idField: idField, footerRenderer: hideFooter ? undefined : footerRenderer, rowHeight: rowHeight, width: Math.max(width ?? 0, widthCalculator.total), mRef: mRefLocal, ...rest }));
318
318
  }, [width]);
319
319
  return ((0, jsx_runtime_1.jsx)(Paper_1.default, { sx: {
320
320
  fontSize: "0.875rem",
@@ -8,7 +8,7 @@ import { ScrollerListExItemRendererProps } from "./ScrollerListEx";
8
8
  * @param renderer Renderer for card content
9
9
  * @returns Component
10
10
  */
11
- export declare function MobileListItemRenderer<T>({ data, itemHeight, margins }: ScrollerListExItemRendererProps<T>, renderer: (data: T) => [
11
+ export declare function MobileListItemRenderer<T>({ data, margins }: ScrollerListExItemRendererProps<T>, renderer: (data: T) => [
12
12
  string,
13
13
  string | undefined,
14
14
  React.ReactNode | (ListItemReact | boolean)[],
@@ -17,14 +17,13 @@ const CardContent_1 = __importDefault(require("@mui/material/CardContent"));
17
17
  * @param renderer Renderer for card content
18
18
  * @returns Component
19
19
  */
20
- function MobileListItemRenderer({ data, itemHeight, margins }, renderer) {
20
+ function MobileListItemRenderer({ data, margins }, renderer) {
21
21
  // Loading
22
22
  if (data == null)
23
23
  return (0, jsx_runtime_1.jsx)(LinearProgress_1.default, {});
24
24
  // Elements
25
25
  const [title, subheader, actions, children, cardActions] = renderer(data);
26
26
  return ((0, jsx_runtime_1.jsxs)(Card_1.default, { sx: {
27
- height: itemHeight,
28
27
  ...margins
29
28
  }, children: [(0, jsx_runtime_1.jsx)(CardHeader_1.default, { sx: { paddingBottom: 0.5 }, action: Array.isArray(actions) ? ((0, jsx_runtime_1.jsx)(MoreFab_1.MoreFab, { iconButton: true, size: "small", anchorOrigin: {
30
29
  vertical: "bottom",
@@ -37,6 +36,6 @@ function MobileListItemRenderer({ data, itemHeight, margins }, renderer) {
37
36
  subheader: { variant: "caption" }
38
37
  } }), (0, jsx_runtime_1.jsx)(CardContent_1.default, { sx: {
39
38
  paddingTop: 0,
40
- paddingBottom: cardActions == null ? Reflect.get(margins, "marginBottom") : 0
39
+ paddingBottom: cardActions == null ? Reflect.get(margins, "marginBottom") ?? 0 : 0
41
40
  }, children: children }), cardActions] }));
42
41
  }
@@ -1,12 +1,12 @@
1
1
  import React from "react";
2
2
  import { GridColumn, GridJsonData, GridMethodRef, GridTemplateType } from "@etsoo/react";
3
3
  import { DataGridExProps } from "./DataGridEx";
4
- import { ScrollerListExItemSize, ScrollerListExProps } from "./ScrollerListEx";
4
+ import { ScrollerListExProps } from "./ScrollerListEx";
5
5
  import { SxProps, Theme } from "@mui/material/styles";
6
6
  /**
7
7
  * ResponsibleContainer props
8
8
  */
9
- export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProps<T>, "height" | "itemKey" | "loadData" | "mRef" | "onScroll" | "onItemsRendered" | "onInitLoad" | "onUpdateRows"> & {
9
+ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProps<T>, "height" | "loadData" | "mRef" | "onInitLoad" | "onUpdateRows" | "rowHeight"> & {
10
10
  /**
11
11
  * Height will be deducted
12
12
  * @param height Current calcuated height
@@ -44,10 +44,6 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProp
44
44
  * Item renderer
45
45
  */
46
46
  itemRenderer?: ScrollerListExProps<T>["itemRenderer"];
47
- /**
48
- * Item size, a function indicates its a variable size list
49
- */
50
- itemSize: ScrollerListExItemSize;
51
47
  /**
52
48
  * Load data callback
53
49
  */
@@ -55,7 +51,7 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProp
55
51
  /**
56
52
  * Methods
57
53
  */
58
- mRef?: React.MutableRefObject<GridMethodRef<T> | undefined>;
54
+ mRef?: React.RefObject<GridMethodRef<T> | undefined>;
59
55
  /**
60
56
  * Element ready callback
61
57
  */
@@ -72,6 +68,11 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProp
72
68
  * Quick action for double click or click under mobile
73
69
  */
74
70
  quickAction?: (data: T) => void;
71
+ /**
72
+ * Row height
73
+ * @param isGrid Is displaying as DataGrid
74
+ */
75
+ rowHeight?: number | [number, number] | (<B extends boolean>(isGrid: B) => B extends true ? DataGridExProps<T>["rowHeight"] : ScrollerListExProps<T>["rowHeight"]);
75
76
  /**
76
77
  * Size ready to read miliseconds span
77
78
  */
@@ -32,7 +32,7 @@ function defaultContainerBoxSx(paddings, hasField, _dataGrid) {
32
32
  */
33
33
  function ResponsibleContainer(props) {
34
34
  // Destruct
35
- 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;
35
+ const { adjustHeight, adjustFabHeight, cacheKey, cacheMinutes = 15, columns, containerBoxSx = defaultContainerBoxSx, elementReady, fields, fieldTemplate, height, loadData, mRef, paddings = MUGlobal_1.MUGlobal.pagePaddings, pullToRefresh = true, quickAction, rowHeight, sizeReadyMiliseconds = 0, searchBarHeight = 45.6, searchBarBottom = 8, searchBarTop, ...rest } = props;
36
36
  // Labels
37
37
  const labels = Labels_1.Labels.CommonPage;
38
38
  // Refs
@@ -60,6 +60,16 @@ function ResponsibleContainer(props) {
60
60
  state.mounted = true;
61
61
  return loadData(GridUtils_1.GridUtils.createLoader(props, fieldTemplate, cacheKey, false), lastItem);
62
62
  };
63
+ const getRowHeight = react_1.default.useCallback((isGrid) => {
64
+ if (rowHeight == null)
65
+ return undefined;
66
+ else if (typeof rowHeight === "number")
67
+ return isGrid ? undefined : rowHeight;
68
+ else if (Array.isArray(rowHeight))
69
+ return rowHeight[isGrid ? 0 : 1];
70
+ else
71
+ return rowHeight(isGrid);
72
+ }, [rowHeight]);
63
73
  // Search data
64
74
  const searchData = (0, react_2.useSearchParamsWithCache)(cacheKey);
65
75
  // On submit callback
@@ -116,11 +126,11 @@ function ResponsibleContainer(props) {
116
126
  if (showDataGrid) {
117
127
  // Remove useless props
118
128
  const { itemRenderer, ...gridProps } = rest;
119
- return ((0, jsx_runtime_1.jsx)(Box_1.default, { className: "DataGridBox", children: (0, jsx_runtime_1.jsx)(DataGridEx_1.DataGridEx, { autoLoad: !hasFields, height: heightLocal, width: rect.width, loadData: localLoadData, mRef: mRefs, onDoubleClick: (_, data) => quickAction && quickAction(data), columns: columns, ...gridProps }) }));
129
+ return ((0, jsx_runtime_1.jsx)(Box_1.default, { className: "DataGridBox", children: (0, jsx_runtime_1.jsx)(DataGridEx_1.DataGridEx, { autoLoad: !hasFields, height: heightLocal, width: rect.width, loadData: localLoadData, mRef: mRefs, onDoubleClick: (_, data) => quickAction && quickAction(data), columns: columns, rowHeight: getRowHeight(true), ...gridProps }) }));
120
130
  }
121
131
  // Remove useless props
122
- const { checkable, borderRowsCount, bottomHeight, footerItemRenderer, headerHeight, hideFooter, hoverColor, selectable, ...listProps } = rest;
123
- return ((0, jsx_runtime_1.jsx)(Box_1.default, { className: "ListBox", sx: { height: heightLocal }, children: (0, jsx_runtime_1.jsx)(ScrollerListEx_1.ScrollerListEx, { autoLoad: !hasFields, height: heightLocal, loadData: localLoadData, mRef: mRefs, onClick: (event, data) => quickAction && react_2.ReactUtils.isSafeClick(event) && quickAction(data), ...listProps }) }));
132
+ const { checkable, borderRowsCount, bottomHeight, footerItemRenderer, headerHeight, hideFooter, hoverColor, selectable, onCellsRendered, ...listProps } = rest;
133
+ return ((0, jsx_runtime_1.jsx)(Box_1.default, { className: "ListBox", sx: { height: heightLocal }, children: (0, jsx_runtime_1.jsx)(ScrollerListEx_1.ScrollerListEx, { autoLoad: !hasFields, height: heightLocal, loadData: localLoadData, mRef: mRefs, onClick: (event, data) => quickAction && react_2.ReactUtils.isSafeClick(event) && quickAction(data), rowHeight: getRowHeight(false), ...listProps }) }));
124
134
  })();
125
135
  const searchBar = react_1.default.useMemo(() => {
126
136
  if (!hasFields ||
@@ -17,14 +17,6 @@ export type ScrollerListExItemRendererProps<T> = {
17
17
  * Style
18
18
  */
19
19
  style: React.CSSProperties;
20
- /**
21
- * Item height
22
- */
23
- itemHeight: number;
24
- /**
25
- * Item space
26
- */
27
- space: number;
28
20
  /**
29
21
  * Default margins
30
22
  */
@@ -34,17 +26,10 @@ export type ScrollerListExItemRendererProps<T> = {
34
26
  */
35
27
  selected: boolean;
36
28
  };
37
- /**
38
- * Extended ScrollerList ItemSize type
39
- * 1. Callback function
40
- * 2. Static sets
41
- * 3. Dynamic left & right margin calculation
42
- */
43
- export type ScrollerListExItemSize = ((index: number) => [number, number] | [number, number, object]) | [number, number] | [number, object, (number | string)?];
44
29
  /**
45
30
  * Extended ScrollerList Props
46
31
  */
47
- export type ScrollerListExProps<T extends object> = Omit<ScrollerListProps<T>, "rowComponent" | "rowHeight" | "onClick" | "onDoubleClick" | "onInitLoad"> & {
32
+ export type ScrollerListExProps<T extends object> = Omit<ScrollerListProps<T>, "rowComponent" | "rowHeight" | "onClick" | "onDoubleClick" | "onInitLoad"> & Partial<Pick<ScrollerListProps<T>, "rowHeight">> & {
48
33
  /**
49
34
  * Alternating colors for odd/even rows
50
35
  */
@@ -58,13 +43,13 @@ export type ScrollerListExProps<T extends object> = Omit<ScrollerListProps<T>, "
58
43
  */
59
44
  cacheMinutes?: number;
60
45
  /**
61
- * Item renderer
46
+ * Cell margins, default to half of MUGlobal.pagePaddings
62
47
  */
63
- itemRenderer?: (props: ScrollerListExItemRendererProps<T>) => React.ReactNode;
48
+ cellMargins?: object;
64
49
  /**
65
- * Item size, a function indicates its a variable size list
50
+ * Item renderer
66
51
  */
67
- itemSize: ScrollerListExItemSize;
52
+ itemRenderer?: (props: ScrollerListExItemRendererProps<T>) => React.ReactNode;
68
53
  /**
69
54
  * Double click handler
70
55
  */
@@ -10,7 +10,6 @@ const react_1 = require("@etsoo/react");
10
10
  const shared_1 = require("@etsoo/shared");
11
11
  const react_2 = __importDefault(require("react"));
12
12
  const MUGlobal_1 = require("./MUGlobal");
13
- const styles_1 = require("@mui/material/styles");
14
13
  const GridUtils_1 = require("./GridUtils");
15
14
  const useListCacheInitLoad_1 = require("./uses/useListCacheInitLoad");
16
15
  const Box_1 = __importDefault(require("@mui/material/Box"));
@@ -48,31 +47,12 @@ const createGridStyle = (alternatingColors, selectedColor) => {
48
47
  }
49
48
  });
50
49
  };
51
- // Default margin
52
- // horizon: null means full horizontal margin, -1 means all half, >=0 means left/right
53
- const defaultMargin = (margin, horizon) => {
54
- const half = MUGlobal_1.MUGlobal.half(margin);
55
- if (horizon == null) {
56
- const half = MUGlobal_1.MUGlobal.half(margin);
57
- return {
58
- marginLeft: margin,
59
- marginRight: margin,
60
- marginTop: half,
61
- marginBottom: half
62
- };
63
- }
64
- if ((typeof horizon === "number" && horizon >= 0) ||
65
- (typeof horizon === "string" && /^-?\d+/.test(horizon))) {
66
- return {
67
- marginLeft: horizon,
68
- marginRight: horizon,
69
- marginTop: half,
70
- marginBottom: half
71
- };
72
- }
50
+ // Default margins
51
+ const defaultMargins = () => {
52
+ const half = MUGlobal_1.MUGlobal.half(MUGlobal_1.MUGlobal.pagePaddings);
73
53
  return {
74
- marginLeft: half,
75
- marginRight: half,
54
+ marginLeft: 0,
55
+ marginRight: 0,
76
56
  marginTop: half,
77
57
  marginBottom: half
78
58
  };
@@ -104,35 +84,11 @@ function ScrollerListEx(props) {
104
84
  return selected;
105
85
  };
106
86
  // Destruct
107
- const { alternatingColors = [undefined, undefined], className, cacheKey, cacheMinutes = 15, idField = "id", itemSize, itemRenderer = ({ data, itemHeight, margins }) => ((0, jsx_runtime_1.jsx)(Box_1.default, { component: "pre", sx: {
108
- height: itemHeight,
87
+ const { alternatingColors = [undefined, undefined], className, cacheKey, cacheMinutes = 15, cellMargins = defaultMargins(), idField = "id", itemRenderer = ({ data, margins }) => ((0, jsx_runtime_1.jsx)(Box_1.default, { component: "pre", sx: {
109
88
  ...margins
110
- }, children: JSON.stringify(data) })), onClick, onDoubleClick, onUpdateRows, onSelectChange, selectedColor = "#edf4fb", ...rest } = props;
89
+ }, children: JSON.stringify(data) })), onClick, onDoubleClick, onUpdateRows, onSelectChange, rowHeight = 116, selectedColor = "#edf4fb", ...rest } = props;
111
90
  // Init handler
112
91
  const initHandler = (0, useListCacheInitLoad_1.useListCacheInitLoad)(cacheKey, cacheMinutes);
113
- // Theme
114
- const theme = (0, styles_1.useTheme)();
115
- // Cache calculation
116
- const itemSizeResult = react_2.default.useMemo(() => {
117
- if (typeof itemSize === "function")
118
- return undefined;
119
- const [size, spaces, h] = itemSize;
120
- if (typeof spaces === "number")
121
- return [size, spaces, defaultMargin(MUGlobal_1.MUGlobal.pagePaddings, undefined)];
122
- return [size, MUGlobal_1.MUGlobal.getSpace(spaces, theme), defaultMargin(spaces, h)];
123
- }, [itemSize]);
124
- // Calculate size
125
- const calculateItemSize = (index) => {
126
- // Callback function
127
- if (typeof itemSize === "function") {
128
- const result = itemSize(index);
129
- if (result.length == 2)
130
- return [...result, defaultMargin(MUGlobal_1.MUGlobal.pagePaddings)];
131
- return result;
132
- }
133
- // Calculation
134
- return itemSizeResult;
135
- };
136
92
  const onUpdateRowsHandler = react_2.default.useCallback((rows, state) => {
137
93
  GridUtils_1.GridUtils.getUpdateRowsHandler(cacheKey)?.(rows, state);
138
94
  onUpdateRows?.(rows, state);
@@ -140,24 +96,19 @@ function ScrollerListEx(props) {
140
96
  // Layout
141
97
  return ((0, jsx_runtime_1.jsx)(react_1.ScrollerList, { className: shared_1.Utils.mergeClasses("ScrollerListEx-Body", className, createGridStyle(alternatingColors, selectedColor)), idField: idField, onRowsRendered: cacheKey
142
98
  ? (visibleRows) => sessionStorage.setItem(`${cacheKey}-scroll`, JSON.stringify(visibleRows))
143
- : undefined, onInitLoad: initHandler, onUpdateRows: onUpdateRowsHandler, rowComponent: ({ index, items, style }) => {
99
+ : undefined, onInitLoad: initHandler, onUpdateRows: onUpdateRowsHandler, rowComponent: (cellProps) => {
100
+ const { index, style, items } = cellProps;
144
101
  const data = items[index];
145
102
  const selected = isSelected(data);
146
103
  const rowClass = `ScrollerListEx-Row${index % 2}${selected ? ` ${selectedClassName}` : ""}`;
147
- const [itemHeight, space, margins] = calculateItemSize(index);
148
104
  // Child
149
105
  const child = itemRenderer({
150
106
  index,
151
107
  data,
152
108
  style,
153
109
  selected,
154
- itemHeight,
155
- space,
156
- margins
110
+ margins: cellMargins
157
111
  });
158
112
  return ((0, jsx_runtime_1.jsx)("div", { className: rowClass, style: style, onMouseDown: (event) => onMouseDown(event.currentTarget, data), onClick: (event) => onClick && onClick(event, data), onDoubleClick: (event) => onDoubleClick && onDoubleClick(event, data), children: child }));
159
- }, rowHeight: (index) => {
160
- const [size, space] = calculateItemSize(index);
161
- return size + space;
162
- }, ...rest }));
113
+ }, rowHeight: rowHeight, ...rest }));
163
114
  }
@@ -1,12 +1,13 @@
1
1
  import React from "react";
2
+ import { ResponsibleContainerProps } from "../ResponsibleContainer";
2
3
  import type { DataGridPageProps } from "./DataGridPageProps";
3
- import type { ScrollerListExItemSize, ScrollerListExProps } from "../ScrollerListEx";
4
+ import type { ScrollerListExProps } from "../ScrollerListEx";
4
5
  import { GridMethodRef } from "@etsoo/react";
5
6
  import type { OperationMessageHandlerAll } from "../messages/OperationMessageHandler";
6
7
  /**
7
8
  * Response page props
8
9
  */
9
- export type ResponsePageProps<T extends object, F> = DataGridPageProps<T, F> & {
10
+ export type ResponsePageProps<T extends object, F> = Omit<DataGridPageProps<T, F>, "mRef" | "rowHeight"> & {
10
11
  /**
11
12
  *
12
13
  * @param height Current height
@@ -22,14 +23,10 @@ export type ResponsePageProps<T extends object, F> = DataGridPageProps<T, F> & {
22
23
  * Item renderer
23
24
  */
24
25
  itemRenderer?: ScrollerListExProps<T>["itemRenderer"];
25
- /**
26
- * Item size, a function indicates its a variable size list
27
- */
28
- itemSize: ScrollerListExItemSize;
29
26
  /**
30
27
  * Methods
31
28
  */
32
- mRef?: React.MutableRefObject<GridMethodRef<T> | undefined>;
29
+ mRef?: React.RefObject<GridMethodRef<T> | undefined>;
33
30
  /**
34
31
  * Pull to refresh data
35
32
  */
@@ -42,6 +39,10 @@ export type ResponsePageProps<T extends object, F> = DataGridPageProps<T, F> & {
42
39
  * Operation message handler
43
40
  */
44
41
  operationMessageHandler?: OperationMessageHandlerAll;
42
+ /**
43
+ * Row height
44
+ */
45
+ rowHeight?: ResponsibleContainerProps<T, F>["rowHeight"];
45
46
  };
46
47
  /**
47
48
  * Fixed height list page
@@ -14,7 +14,7 @@ export type DataGridExFooterItemRendererProps<T extends object> = {
14
14
  /**
15
15
  * Extended DataGrid with VariableSizeGrid props
16
16
  */
17
- export type DataGridExProps<T extends object, P extends GridJsonData = GridLoadDataProps> = Omit<ScrollerGridProps<T, P>, "cellComponent" | "columnCount" | "columnWidth" | "onClick" | "onDoubleClick" | "onInitLoad" | "width"> & {
17
+ export type DataGridExProps<T extends object, P extends GridJsonData = GridLoadDataProps> = Omit<ScrollerGridProps<T, P>, "cellComponent" | "columnCount" | "columnWidth" | "onClick" | "onDoubleClick" | "onInitLoad" | "rowHeight" | "width"> & Partial<Pick<ScrollerGridProps<T, P>, "rowHeight">> & {
18
18
  /**
19
19
  * Alternating colors for odd/even rows
20
20
  */
@@ -130,7 +130,7 @@ export function DataGridEx(props) {
130
130
  }) }));
131
131
  }
132
132
  // Destruct
133
- const { alternatingColors = [theme.palette.grey[100], undefined], borderRowsCount, bottomHeight = 53, cacheKey, cacheMinutes = 15, checkable = false, className, columns, defaultOrderBy, height, headerHeight = 56, headerRenderer = defaultHeaderRenderer, footerRenderer = defaultFooterRenderer, footerItemRenderer = DataGridRenderers.defaultFooterItemRenderer, hideFooter = false, hoverColor = "#f6f9fb", idField = "id", mRef = React.createRef(), onClick, onDataChange, onDoubleClick, onUpdateRows, selectable = true, selectedColor = "#edf4fb", width, ...rest } = props;
133
+ const { alternatingColors = [theme.palette.grey[100], undefined], borderRowsCount, bottomHeight = 53, cacheKey, cacheMinutes = 15, checkable = false, className, columns, defaultOrderBy, height, headerHeight = 56, headerRenderer = defaultHeaderRenderer, footerRenderer = defaultFooterRenderer, footerItemRenderer = DataGridRenderers.defaultFooterItemRenderer, hideFooter = false, hoverColor = "#f6f9fb", idField = "id", mRef = React.createRef(), onClick, onDataChange, onDoubleClick, onUpdateRows, rowHeight = 53, selectable = true, selectedColor = "#edf4fb", width, ...rest } = props;
134
134
  if (checkable) {
135
135
  const cbColumn = {
136
136
  field: "selected", // Avoid validation from data model
@@ -307,7 +307,7 @@ export function DataGridEx(props) {
307
307
  headerHeight -
308
308
  (hideFooter ? 0 : bottomHeight + 1) -
309
309
  scrollbarSize
310
- : height, headerRenderer: headerRenderer, idField: idField, footerRenderer: hideFooter ? undefined : footerRenderer, width: Math.max(width ?? 0, widthCalculator.total), mRef: mRefLocal, ...rest }));
310
+ : height, headerRenderer: headerRenderer, idField: idField, footerRenderer: hideFooter ? undefined : footerRenderer, rowHeight: rowHeight, width: Math.max(width ?? 0, widthCalculator.total), mRef: mRefLocal, ...rest }));
311
311
  }, [width]);
312
312
  return (_jsx(Paper, { sx: {
313
313
  fontSize: "0.875rem",
@@ -8,7 +8,7 @@ import { ScrollerListExItemRendererProps } from "./ScrollerListEx";
8
8
  * @param renderer Renderer for card content
9
9
  * @returns Component
10
10
  */
11
- export declare function MobileListItemRenderer<T>({ data, itemHeight, margins }: ScrollerListExItemRendererProps<T>, renderer: (data: T) => [
11
+ export declare function MobileListItemRenderer<T>({ data, margins }: ScrollerListExItemRendererProps<T>, renderer: (data: T) => [
12
12
  string,
13
13
  string | undefined,
14
14
  React.ReactNode | (ListItemReact | boolean)[],
@@ -11,14 +11,13 @@ import CardContent from "@mui/material/CardContent";
11
11
  * @param renderer Renderer for card content
12
12
  * @returns Component
13
13
  */
14
- export function MobileListItemRenderer({ data, itemHeight, margins }, renderer) {
14
+ export function MobileListItemRenderer({ data, margins }, renderer) {
15
15
  // Loading
16
16
  if (data == null)
17
17
  return _jsx(LinearProgress, {});
18
18
  // Elements
19
19
  const [title, subheader, actions, children, cardActions] = renderer(data);
20
20
  return (_jsxs(Card, { sx: {
21
- height: itemHeight,
22
21
  ...margins
23
22
  }, children: [_jsx(CardHeader, { sx: { paddingBottom: 0.5 }, action: Array.isArray(actions) ? (_jsx(MoreFab, { iconButton: true, size: "small", anchorOrigin: {
24
23
  vertical: "bottom",
@@ -31,6 +30,6 @@ export function MobileListItemRenderer({ data, itemHeight, margins }, renderer)
31
30
  subheader: { variant: "caption" }
32
31
  } }), _jsx(CardContent, { sx: {
33
32
  paddingTop: 0,
34
- paddingBottom: cardActions == null ? Reflect.get(margins, "marginBottom") : 0
33
+ paddingBottom: cardActions == null ? Reflect.get(margins, "marginBottom") ?? 0 : 0
35
34
  }, children: children }), cardActions] }));
36
35
  }
@@ -1,12 +1,12 @@
1
1
  import React from "react";
2
2
  import { GridColumn, GridJsonData, GridMethodRef, GridTemplateType } from "@etsoo/react";
3
3
  import { DataGridExProps } from "./DataGridEx";
4
- import { ScrollerListExItemSize, ScrollerListExProps } from "./ScrollerListEx";
4
+ import { ScrollerListExProps } from "./ScrollerListEx";
5
5
  import { SxProps, Theme } from "@mui/material/styles";
6
6
  /**
7
7
  * ResponsibleContainer props
8
8
  */
9
- export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProps<T>, "height" | "itemKey" | "loadData" | "mRef" | "onScroll" | "onItemsRendered" | "onInitLoad" | "onUpdateRows"> & {
9
+ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProps<T>, "height" | "loadData" | "mRef" | "onInitLoad" | "onUpdateRows" | "rowHeight"> & {
10
10
  /**
11
11
  * Height will be deducted
12
12
  * @param height Current calcuated height
@@ -44,10 +44,6 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProp
44
44
  * Item renderer
45
45
  */
46
46
  itemRenderer?: ScrollerListExProps<T>["itemRenderer"];
47
- /**
48
- * Item size, a function indicates its a variable size list
49
- */
50
- itemSize: ScrollerListExItemSize;
51
47
  /**
52
48
  * Load data callback
53
49
  */
@@ -55,7 +51,7 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProp
55
51
  /**
56
52
  * Methods
57
53
  */
58
- mRef?: React.MutableRefObject<GridMethodRef<T> | undefined>;
54
+ mRef?: React.RefObject<GridMethodRef<T> | undefined>;
59
55
  /**
60
56
  * Element ready callback
61
57
  */
@@ -72,6 +68,11 @@ export type ResponsibleContainerProps<T extends object, F> = Omit<DataGridExProp
72
68
  * Quick action for double click or click under mobile
73
69
  */
74
70
  quickAction?: (data: T) => void;
71
+ /**
72
+ * Row height
73
+ * @param isGrid Is displaying as DataGrid
74
+ */
75
+ rowHeight?: number | [number, number] | (<B extends boolean>(isGrid: B) => B extends true ? DataGridExProps<T>["rowHeight"] : ScrollerListExProps<T>["rowHeight"]);
75
76
  /**
76
77
  * Size ready to read miliseconds span
77
78
  */
@@ -26,7 +26,7 @@ function defaultContainerBoxSx(paddings, hasField, _dataGrid) {
26
26
  */
27
27
  export function ResponsibleContainer(props) {
28
28
  // Destruct
29
- 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;
29
+ const { adjustHeight, adjustFabHeight, cacheKey, cacheMinutes = 15, columns, containerBoxSx = defaultContainerBoxSx, elementReady, fields, fieldTemplate, height, loadData, mRef, paddings = MUGlobal.pagePaddings, pullToRefresh = true, quickAction, rowHeight, sizeReadyMiliseconds = 0, searchBarHeight = 45.6, searchBarBottom = 8, searchBarTop, ...rest } = props;
30
30
  // Labels
31
31
  const labels = Labels.CommonPage;
32
32
  // Refs
@@ -54,6 +54,16 @@ export function ResponsibleContainer(props) {
54
54
  state.mounted = true;
55
55
  return loadData(GridUtils.createLoader(props, fieldTemplate, cacheKey, false), lastItem);
56
56
  };
57
+ const getRowHeight = React.useCallback((isGrid) => {
58
+ if (rowHeight == null)
59
+ return undefined;
60
+ else if (typeof rowHeight === "number")
61
+ return isGrid ? undefined : rowHeight;
62
+ else if (Array.isArray(rowHeight))
63
+ return rowHeight[isGrid ? 0 : 1];
64
+ else
65
+ return rowHeight(isGrid);
66
+ }, [rowHeight]);
57
67
  // Search data
58
68
  const searchData = useSearchParamsWithCache(cacheKey);
59
69
  // On submit callback
@@ -110,11 +120,11 @@ export function ResponsibleContainer(props) {
110
120
  if (showDataGrid) {
111
121
  // Remove useless props
112
122
  const { itemRenderer, ...gridProps } = rest;
113
- return (_jsx(Box, { className: "DataGridBox", children: _jsx(DataGridEx, { autoLoad: !hasFields, height: heightLocal, width: rect.width, loadData: localLoadData, mRef: mRefs, onDoubleClick: (_, data) => quickAction && quickAction(data), columns: columns, ...gridProps }) }));
123
+ return (_jsx(Box, { className: "DataGridBox", children: _jsx(DataGridEx, { autoLoad: !hasFields, height: heightLocal, width: rect.width, loadData: localLoadData, mRef: mRefs, onDoubleClick: (_, data) => quickAction && quickAction(data), columns: columns, rowHeight: getRowHeight(true), ...gridProps }) }));
114
124
  }
115
125
  // Remove useless props
116
- const { checkable, borderRowsCount, bottomHeight, footerItemRenderer, headerHeight, hideFooter, hoverColor, selectable, ...listProps } = rest;
117
- return (_jsx(Box, { className: "ListBox", sx: { height: heightLocal }, children: _jsx(ScrollerListEx, { autoLoad: !hasFields, height: heightLocal, loadData: localLoadData, mRef: mRefs, onClick: (event, data) => quickAction && ReactUtils.isSafeClick(event) && quickAction(data), ...listProps }) }));
126
+ const { checkable, borderRowsCount, bottomHeight, footerItemRenderer, headerHeight, hideFooter, hoverColor, selectable, onCellsRendered, ...listProps } = rest;
127
+ return (_jsx(Box, { className: "ListBox", sx: { height: heightLocal }, children: _jsx(ScrollerListEx, { autoLoad: !hasFields, height: heightLocal, loadData: localLoadData, mRef: mRefs, onClick: (event, data) => quickAction && ReactUtils.isSafeClick(event) && quickAction(data), rowHeight: getRowHeight(false), ...listProps }) }));
118
128
  })();
119
129
  const searchBar = React.useMemo(() => {
120
130
  if (!hasFields ||
@@ -17,14 +17,6 @@ export type ScrollerListExItemRendererProps<T> = {
17
17
  * Style
18
18
  */
19
19
  style: React.CSSProperties;
20
- /**
21
- * Item height
22
- */
23
- itemHeight: number;
24
- /**
25
- * Item space
26
- */
27
- space: number;
28
20
  /**
29
21
  * Default margins
30
22
  */
@@ -34,17 +26,10 @@ export type ScrollerListExItemRendererProps<T> = {
34
26
  */
35
27
  selected: boolean;
36
28
  };
37
- /**
38
- * Extended ScrollerList ItemSize type
39
- * 1. Callback function
40
- * 2. Static sets
41
- * 3. Dynamic left & right margin calculation
42
- */
43
- export type ScrollerListExItemSize = ((index: number) => [number, number] | [number, number, object]) | [number, number] | [number, object, (number | string)?];
44
29
  /**
45
30
  * Extended ScrollerList Props
46
31
  */
47
- export type ScrollerListExProps<T extends object> = Omit<ScrollerListProps<T>, "rowComponent" | "rowHeight" | "onClick" | "onDoubleClick" | "onInitLoad"> & {
32
+ export type ScrollerListExProps<T extends object> = Omit<ScrollerListProps<T>, "rowComponent" | "rowHeight" | "onClick" | "onDoubleClick" | "onInitLoad"> & Partial<Pick<ScrollerListProps<T>, "rowHeight">> & {
48
33
  /**
49
34
  * Alternating colors for odd/even rows
50
35
  */
@@ -58,13 +43,13 @@ export type ScrollerListExProps<T extends object> = Omit<ScrollerListProps<T>, "
58
43
  */
59
44
  cacheMinutes?: number;
60
45
  /**
61
- * Item renderer
46
+ * Cell margins, default to half of MUGlobal.pagePaddings
62
47
  */
63
- itemRenderer?: (props: ScrollerListExItemRendererProps<T>) => React.ReactNode;
48
+ cellMargins?: object;
64
49
  /**
65
- * Item size, a function indicates its a variable size list
50
+ * Item renderer
66
51
  */
67
- itemSize: ScrollerListExItemSize;
52
+ itemRenderer?: (props: ScrollerListExItemRendererProps<T>) => React.ReactNode;
68
53
  /**
69
54
  * Double click handler
70
55
  */