@etsoo/materialui 1.1.53 → 1.1.55

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,26 +1,38 @@
1
- /// <reference types="react" />
2
1
  import { DataTypes } from "@etsoo/shared";
3
2
  import { TypographyProps } from "@mui/material/Typography";
3
+ import React from "react";
4
4
  import { InputFieldProps } from "./InputField";
5
5
  type ItemType = DataTypes.IdLabelItem<string | number>;
6
6
  /**
7
7
  * InputField with tips properties
8
8
  */
9
- export type InputTipFieldProps = InputFieldProps & {
9
+ export type InputTipFieldProps<T extends ItemType = ItemType> = InputFieldProps & {
10
10
  /**
11
11
  * Load data
12
12
  * @param value Duplicate test value
13
13
  */
14
- loadData(value: string): Promise<[ItemType[]?, string?]>;
14
+ loadData(value: string): Promise<[T[]?, string?]>;
15
15
  /**
16
16
  * Label props
17
17
  */
18
18
  labelProps?: Omit<TypographyProps, "onClick">;
19
+ /**
20
+ * Custom item label
21
+ * @param item List item data
22
+ * @returns Result
23
+ */
24
+ itemLabel?: (item: T) => React.ReactNode;
25
+ /**
26
+ * Custom render item
27
+ * @param item List item data
28
+ * @returns Result
29
+ */
30
+ renderItem?: (item: T) => React.ReactNode;
19
31
  };
20
32
  /**
21
33
  * InputField with tips
22
34
  * @param props Props
23
35
  * @returns Component
24
36
  */
25
- export declare function InputTipField(props: InputTipFieldProps): JSX.Element;
37
+ export declare function InputTipField<T extends ItemType = ItemType>(props: InputTipFieldProps<T>): JSX.Element;
26
38
  export {};
@@ -22,7 +22,7 @@ export function InputTipField(props) {
22
22
  React.createElement(Typography, { onClick: (event) => {
23
23
  setAnchorEl(event.currentTarget);
24
24
  }, ...labelProps }, title))) : undefined
25
- }, changeDelay = 480, onChangeDelay, loadData, ...rest } = props;
25
+ }, changeDelay = 480, onChangeDelay, loadData, itemLabel = (item) => item.label, renderItem = (item) => React.createElement(ListItem, { key: item.id }, itemLabel(item)), ...rest } = props;
26
26
  const load = (value) => {
27
27
  if (value.length < 2) {
28
28
  setTitle(undefined);
@@ -37,7 +37,7 @@ export function InputTipField(props) {
37
37
  React.createElement(Popover, { open: anchorEl != null, anchorEl: anchorEl, onClose: () => setAnchorEl(undefined), anchorOrigin: {
38
38
  vertical: "bottom",
39
39
  horizontal: "left"
40
- } }, data && (React.createElement(List, null, data.map((item) => (React.createElement(ListItem, { key: item.id }, item.label)))))),
40
+ } }, data && React.createElement(List, null, data.map((item) => renderItem(item)))),
41
41
  React.createElement(InputField, { changeDelay: changeDelay, onChangeDelay: (event) => {
42
42
  load(event.target.value);
43
43
  if (onChangeDelay)
@@ -1,19 +1,23 @@
1
- import { DataTypes, IdDefaultType } from '@etsoo/shared';
2
- import { SxProps, Theme } from '@mui/material';
3
- import React from 'react';
4
- import { ListChildComponentProps } from 'react-window';
5
- import { GridColumn, GridJsonData, GridMethodRef } from '@etsoo/react';
6
- import { DataGridExProps } from './DataGridEx';
7
- import { ScrollerListExInnerItemRendererProps, ScrollerListExItemSize } from './ScrollerListEx';
1
+ import { DataTypes, IdDefaultType } from "@etsoo/shared";
2
+ import { SxProps, Theme } from "@mui/material";
3
+ import React from "react";
4
+ import { ListChildComponentProps } from "react-window";
5
+ import { GridColumn, GridJsonData, GridMethodRef } from "@etsoo/react";
6
+ import { DataGridExProps } from "./DataGridEx";
7
+ import { ScrollerListExInnerItemRendererProps, ScrollerListExItemSize } from "./ScrollerListEx";
8
8
  /**
9
9
  * ResponsibleContainer props
10
10
  */
11
- export type ResponsibleContainerProps<T extends object, F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate, D extends DataTypes.Keys<T> = IdDefaultType<T>> = Omit<DataGridExProps<T, D>, 'height' | 'itemKey' | 'loadData' | 'mRef' | 'onScroll' | 'onItemsRendered'> & {
11
+ export type ResponsibleContainerProps<T extends object, F extends DataTypes.BasicTemplate = DataTypes.BasicTemplate, D extends DataTypes.Keys<T> = IdDefaultType<T>> = Omit<DataGridExProps<T, D>, "height" | "itemKey" | "loadData" | "mRef" | "onScroll" | "onItemsRendered"> & {
12
12
  /**
13
13
  * Height will be deducted
14
14
  * @param height Current calcuated height
15
15
  */
16
16
  adjustHeight?: (height: number) => number;
17
+ /**
18
+ * Top height
19
+ */
20
+ topHeight?: number;
17
21
  /**
18
22
  * Columns
19
23
  */
@@ -1,16 +1,16 @@
1
- import { Box, Stack } from '@mui/material';
2
- import React from 'react';
3
- import { GridDataGet, ReactUtils, useCombinedRefs, useDimensions } from '@etsoo/react';
4
- import { DataGridEx, DataGridExCalColumns } from './DataGridEx';
5
- import { MUGlobal } from './MUGlobal';
6
- import { PullToRefreshUI } from './PullToRefreshUI';
7
- import { ScrollerListEx } from './ScrollerListEx';
8
- import { SearchBar } from './SearchBar';
9
- import { Labels } from './app/Labels';
1
+ import { Box, Stack } from "@mui/material";
2
+ import React from "react";
3
+ import { GridDataGet, ReactUtils, useCombinedRefs, useDimensions } from "@etsoo/react";
4
+ import { DataGridEx, DataGridExCalColumns } from "./DataGridEx";
5
+ import { MUGlobal } from "./MUGlobal";
6
+ import { PullToRefreshUI } from "./PullToRefreshUI";
7
+ import { ScrollerListEx } from "./ScrollerListEx";
8
+ import { SearchBar } from "./SearchBar";
9
+ import { Labels } from "./app/Labels";
10
10
  function defaultContainerBoxSx(paddings, hasField, _dataGrid) {
11
11
  const half = MUGlobal.half(paddings);
12
12
  return {
13
- '& .SearchBox': {
13
+ "& .SearchBox": {
14
14
  marginBottom: hasField ? half : 0
15
15
  }
16
16
  };
@@ -22,7 +22,7 @@ function defaultContainerBoxSx(paddings, hasField, _dataGrid) {
22
22
  */
23
23
  export function ResponsibleContainer(props) {
24
24
  // Destruct
25
- const { adjustHeight, columns, containerBoxSx = defaultContainerBoxSx, dataGridMinWidth = Math.max(576, DataGridExCalColumns(columns).total), elementReady, fields, fieldTemplate, height, loadData, mRef, paddings = MUGlobal.pagePaddings, pullToRefresh = true, quickAction, sizeReadyMiliseconds = 0, ...rest } = props;
25
+ const { adjustHeight, columns, containerBoxSx = defaultContainerBoxSx, dataGridMinWidth = Math.max(576, DataGridExCalColumns(columns).total), elementReady, fields, fieldTemplate, height, topHeight, loadData, mRef, paddings = MUGlobal.pagePaddings, pullToRefresh = true, quickAction, sizeReadyMiliseconds = 0, ...rest } = props;
26
26
  // Labels
27
27
  const labels = Labels.CommonPage;
28
28
  // Refs
@@ -90,7 +90,7 @@ export function ResponsibleContainer(props) {
90
90
  // Auto calculation
91
91
  heightLocal =
92
92
  document.documentElement.clientHeight -
93
- Math.round(rect.bottom + 1);
93
+ (topHeight !== null && topHeight !== void 0 ? topHeight : Math.round(rect.bottom + 1));
94
94
  const style = window.getComputedStyle(dimensions[0][1]);
95
95
  const boxMargin = parseFloat(style.marginBottom);
96
96
  if (!isNaN(boxMargin))
@@ -122,9 +122,7 @@ export function ResponsibleContainer(props) {
122
122
  delete rest.selectable;
123
123
  return [
124
124
  React.createElement(Box, { className: "ListBox", sx: { height: heightLocal } },
125
- React.createElement(ScrollerListEx, { autoLoad: !hasFields, height: heightLocal, loadData: localLoadData, mRef: mRefs, onClick: (event, data) => quickAction &&
126
- ReactUtils.isSafeClick(event) &&
127
- quickAction(data), oRef: (element) => {
125
+ React.createElement(ScrollerListEx, { autoLoad: !hasFields, height: heightLocal, loadData: localLoadData, mRef: mRefs, onClick: (event, data) => quickAction && ReactUtils.isSafeClick(event) && quickAction(data), oRef: (element) => {
128
126
  if (element != null && elementReady)
129
127
  elementReady(element, false);
130
128
  }, ...rest })),
@@ -134,14 +132,14 @@ export function ResponsibleContainer(props) {
134
132
  const searchBar = React.useMemo(() => {
135
133
  if (!hasFields || showDataGrid == null)
136
134
  return;
137
- return (React.createElement(SearchBar, { fields: fields, onSubmit: onSubmit, className: `searchBar${showDataGrid ? 'Grid' : 'List'}` }));
135
+ return (React.createElement(SearchBar, { fields: fields, onSubmit: onSubmit, className: `searchBar${showDataGrid ? "Grid" : "List"}` }));
138
136
  }, [showDataGrid, hasFields]);
139
137
  // Pull container
140
138
  const pullContainer = showDataGrid == null
141
139
  ? undefined
142
140
  : showDataGrid
143
- ? '.DataGridEx-Body'
144
- : '.ScrollerListEx-Body';
141
+ ? ".DataGridEx-Body"
142
+ : ".ScrollerListEx-Body";
145
143
  // Layout
146
144
  return (React.createElement(Box, { sx: containerBoxSx == null
147
145
  ? undefined
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React from "react";
2
2
  /**
3
3
  * Search bar props
4
4
  */
package/lib/SearchBar.js CHANGED
@@ -1,31 +1,31 @@
1
- import { Button, Drawer, IconButton, Stack, useTheme } from '@mui/material';
2
- import React from 'react';
3
- import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
4
- import { DomUtils } from '@etsoo/shared';
5
- import { ReactUtils, useDelayedExecutor, useDimensions } from '@etsoo/react';
6
- import { Labels } from './app/Labels';
1
+ import { Button, Drawer, IconButton, Stack, useTheme } from "@mui/material";
2
+ import React from "react";
3
+ import MoreHorizIcon from "@mui/icons-material/MoreHoriz";
4
+ import { DomUtils } from "@etsoo/shared";
5
+ import { ReactUtils, useDelayedExecutor, useDimensions } from "@etsoo/react";
6
+ import { Labels } from "./app/Labels";
7
7
  // Cached width attribute name
8
- const cachedWidthName = 'data-cached-width';
8
+ const cachedWidthName = "data-cached-width";
9
9
  // Reset form
10
10
  const resetForm = (form) => {
11
11
  for (const input of form.elements) {
12
12
  // Ignore disabled inputs
13
- if ('disabled' in input && input.disabled)
13
+ if ("disabled" in input && input.disabled)
14
14
  continue;
15
15
  // All non hidden inputs
16
16
  if (input instanceof HTMLInputElement) {
17
17
  // Ignore hidden input
18
- if (input.type === 'hidden')
18
+ if (input.type === "hidden")
19
19
  continue;
20
20
  // Ignore readOnly without data-reset=true inputs
21
- if (!input.readOnly || input.dataset.reset === 'true') {
22
- ReactUtils.triggerChange(input, '', true);
21
+ if (!input.readOnly || input.dataset.reset === "true") {
22
+ ReactUtils.triggerChange(input, "", true);
23
23
  }
24
24
  continue;
25
25
  }
26
26
  // All selects
27
27
  if (input instanceof HTMLSelectElement) {
28
- if (input.options.length > 0 && input.options[0].value === '') {
28
+ if (input.options.length > 0 && input.options[0].value === "") {
29
29
  input.selectedIndex = 0;
30
30
  }
31
31
  else {
@@ -35,12 +35,12 @@ const resetForm = (form) => {
35
35
  }
36
36
  }
37
37
  // Trigger reset event
38
- const resetEvent = new Event('reset');
38
+ const resetEvent = new Event("reset");
39
39
  form.dispatchEvent(resetEvent);
40
40
  };
41
41
  // Disable inputs avoid auto trigger change events for them
42
42
  const setChildState = (child, enabled) => {
43
- const inputs = child.getElementsByTagName('input');
43
+ const inputs = child.getElementsByTagName("input");
44
44
  for (const input of inputs) {
45
45
  input.disabled = !enabled;
46
46
  }
@@ -74,13 +74,13 @@ export function SearchBar(props) {
74
74
  const len = target.children.length;
75
75
  for (let i = 0; i < len; i++) {
76
76
  var classList = target.children[i].classList;
77
- classList.remove('showChild');
77
+ classList.remove("showChild");
78
78
  }
79
79
  }, 0);
80
80
  // Show or hide element
81
81
  const setElementVisible = (element, visible) => {
82
- element.classList.remove(visible ? 'hiddenChild' : 'showChild');
83
- element.classList.add(visible ? 'showChild' : 'hiddenChild');
82
+ element.classList.remove(visible ? "hiddenChild" : "showChild");
83
+ element.classList.add(visible ? "showChild" : "hiddenChild");
84
84
  };
85
85
  // Reset button ref
86
86
  const resetButtonRef = (instance) => {
@@ -90,9 +90,7 @@ export function SearchBar(props) {
90
90
  return;
91
91
  // First
92
92
  const [_, container, containerRect] = dimensions[0];
93
- if (container == null ||
94
- containerRect == null ||
95
- containerRect.width < 10)
93
+ if (container == null || containerRect == null || containerRect.width < 10)
96
94
  return;
97
95
  // Container width
98
96
  let maxWidth = containerRect.width;
@@ -226,26 +224,28 @@ export function SearchBar(props) {
226
224
  state.form = form;
227
225
  } },
228
226
  React.createElement(Stack, { ref: dimensions[0][0], justifyContent: "center", alignItems: "center", direction: "row", spacing: 1, height: innerHeight, sx: {
229
- '& > :not(style)': {
230
- flexBasis: 'auto',
227
+ "& > :not(style)": {
228
+ flexBasis: "auto",
231
229
  flexGrow: 0,
232
230
  flexShrink: 0,
233
- maxWidth: '180px',
234
- visibility: 'hidden'
231
+ maxWidth: "180px"
235
232
  },
236
- '& > .hiddenChild': {
237
- display: 'none'
233
+ "& > :not:first-child": {
234
+ visibility: "hidden"
238
235
  },
239
- '& > .showChild': {
240
- display: 'block',
241
- visibility: 'visible'
236
+ "& > .hiddenChild": {
237
+ display: "none"
238
+ },
239
+ "& > .showChild": {
240
+ display: "block",
241
+ visibility: "visible"
242
242
  }
243
243
  } },
244
244
  fields.map((item, index) => (React.createElement(React.Fragment, { key: index }, item))),
245
245
  React.createElement(IconButton, { "aria-label": "delete", size: "medium", onClick: handleMore },
246
246
  React.createElement(MoreHorizIcon, null)),
247
247
  React.createElement(Button, { variant: "contained", size: "medium", ref: resetButtonRef, onClick: handleReset }, labels.reset))),
248
- index != null && index < fields.length && (React.createElement(Drawer, { anchor: "right", sx: { minWidth: '250px' }, ModalProps: {
248
+ index != null && index < fields.length && (React.createElement(Drawer, { anchor: "right", sx: { minWidth: "250px" }, ModalProps: {
249
249
  keepMounted: true // Better open performance on mobile.
250
250
  }, open: open, onClose: () => updateOpen(false) },
251
251
  React.createElement("form", { onChange: moreFormChange, ref: (form) => {
@@ -253,8 +253,8 @@ export function SearchBar(props) {
253
253
  state.moreForm = form;
254
254
  } },
255
255
  React.createElement(Stack, { direction: "column", alignItems: "stretch", spacing: 2, padding: 2, sx: {
256
- '& > :not(style)': {
257
- minWidth: '100px'
256
+ "& > :not(style)": {
257
+ minWidth: "100px"
258
258
  }
259
259
  } }, moreItems))))));
260
260
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.1.53",
3
+ "version": "1.1.55",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -50,13 +50,13 @@
50
50
  "@emotion/css": "^11.10.6",
51
51
  "@emotion/react": "^11.10.6",
52
52
  "@emotion/styled": "^11.10.6",
53
- "@etsoo/appscript": "^1.3.80",
53
+ "@etsoo/appscript": "^1.3.81",
54
54
  "@etsoo/notificationbase": "^1.1.24",
55
- "@etsoo/react": "^1.6.51",
55
+ "@etsoo/react": "^1.6.52",
56
56
  "@etsoo/shared": "^1.1.92",
57
57
  "@mui/icons-material": "^5.11.11",
58
58
  "@mui/material": "^5.11.14",
59
- "@mui/x-data-grid": "^6.0.2",
59
+ "@mui/x-data-grid": "^6.0.3",
60
60
  "@types/pica": "^9.0.1",
61
61
  "@types/pulltorefreshjs": "^0.1.5",
62
62
  "@types/react": "^18.0.28",
@@ -10,29 +10,46 @@ type ItemType = DataTypes.IdLabelItem<string | number>;
10
10
  /**
11
11
  * InputField with tips properties
12
12
  */
13
- export type InputTipFieldProps = InputFieldProps & {
14
- /**
15
- * Load data
16
- * @param value Duplicate test value
17
- */
18
- loadData(value: string): Promise<[ItemType[]?, string?]>;
13
+ export type InputTipFieldProps<T extends ItemType = ItemType> =
14
+ InputFieldProps & {
15
+ /**
16
+ * Load data
17
+ * @param value Duplicate test value
18
+ */
19
+ loadData(value: string): Promise<[T[]?, string?]>;
19
20
 
20
- /**
21
- * Label props
22
- */
23
- labelProps?: Omit<TypographyProps, "onClick">;
24
- };
21
+ /**
22
+ * Label props
23
+ */
24
+ labelProps?: Omit<TypographyProps, "onClick">;
25
+
26
+ /**
27
+ * Custom item label
28
+ * @param item List item data
29
+ * @returns Result
30
+ */
31
+ itemLabel?: (item: T) => React.ReactNode;
32
+
33
+ /**
34
+ * Custom render item
35
+ * @param item List item data
36
+ * @returns Result
37
+ */
38
+ renderItem?: (item: T) => React.ReactNode;
39
+ };
25
40
 
26
41
  /**
27
42
  * InputField with tips
28
43
  * @param props Props
29
44
  * @returns Component
30
45
  */
31
- export function InputTipField(props: InputTipFieldProps) {
46
+ export function InputTipField<T extends ItemType = ItemType>(
47
+ props: InputTipFieldProps<T>
48
+ ) {
32
49
  // State
33
50
  const [title, setTitle] = React.useState<string>();
34
51
  const [anchorEl, setAnchorEl] = React.useState<HTMLElement>();
35
- const [data, setData] = React.useState<ItemType[]>();
52
+ const [data, setData] = React.useState<T[]>();
36
53
 
37
54
  // Destruct
38
55
  const {
@@ -57,6 +74,8 @@ export function InputTipField(props: InputTipFieldProps) {
57
74
  changeDelay = 480,
58
75
  onChangeDelay,
59
76
  loadData,
77
+ itemLabel = (item) => item.label,
78
+ renderItem = (item) => <ListItem key={item.id}>{itemLabel(item)}</ListItem>,
60
79
  ...rest
61
80
  } = props;
62
81
 
@@ -83,13 +102,7 @@ export function InputTipField(props: InputTipFieldProps) {
83
102
  horizontal: "left"
84
103
  }}
85
104
  >
86
- {data && (
87
- <List>
88
- {data.map((item) => (
89
- <ListItem key={item.id}>{item.label}</ListItem>
90
- ))}
91
- </List>
92
- )}
105
+ {data && <List>{data.map((item) => renderItem(item))}</List>}
93
106
  </Popover>
94
107
  <InputField
95
108
  changeDelay={changeDelay}