@etsoo/materialui 1.1.47 → 1.1.49

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,5 +1,5 @@
1
- import { TextFieldProps } from '@mui/material';
2
- import React from 'react';
1
+ import { TextFieldProps } from "@mui/material";
2
+ import React from "react";
3
3
  /**
4
4
  * Input field props
5
5
  */
@@ -8,6 +8,10 @@ export type InputFieldProps = TextFieldProps & {
8
8
  * Change delay (ms) to avoid repeatly dispatch onChange
9
9
  */
10
10
  changeDelay?: number;
11
+ /**
12
+ * Change delay handler, without it onChange will be applied
13
+ */
14
+ onChangeDelay?: React.ChangeEventHandler<HTMLTextAreaElement | HTMLInputElement>;
11
15
  /**
12
16
  * Is the field read only?
13
17
  */
@@ -23,6 +27,10 @@ export declare const InputField: React.ForwardRefExoticComponent<(Omit<import("@
23
27
  * Change delay (ms) to avoid repeatly dispatch onChange
24
28
  */
25
29
  changeDelay?: number | undefined;
30
+ /**
31
+ * Change delay handler, without it onChange will be applied
32
+ */
33
+ onChangeDelay?: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement> | undefined;
26
34
  /**
27
35
  * Is the field read only?
28
36
  */
@@ -32,6 +40,10 @@ export declare const InputField: React.ForwardRefExoticComponent<(Omit<import("@
32
40
  * Change delay (ms) to avoid repeatly dispatch onChange
33
41
  */
34
42
  changeDelay?: number | undefined;
43
+ /**
44
+ * Change delay handler, without it onChange will be applied
45
+ */
46
+ onChangeDelay?: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement> | undefined;
35
47
  /**
36
48
  * Is the field read only?
37
49
  */
@@ -41,6 +53,10 @@ export declare const InputField: React.ForwardRefExoticComponent<(Omit<import("@
41
53
  * Change delay (ms) to avoid repeatly dispatch onChange
42
54
  */
43
55
  changeDelay?: number | undefined;
56
+ /**
57
+ * Change delay handler, without it onChange will be applied
58
+ */
59
+ onChangeDelay?: React.ChangeEventHandler<HTMLInputElement | HTMLTextAreaElement> | undefined;
44
60
  /**
45
61
  * Is the field read only?
46
62
  */
package/lib/InputField.js CHANGED
@@ -1,7 +1,7 @@
1
- import { useDelayedExecutor } from '@etsoo/react';
2
- import { TextField } from '@mui/material';
3
- import React from 'react';
4
- import { MUGlobal } from './MUGlobal';
1
+ import { useDelayedExecutor } from "@etsoo/react";
2
+ import { TextField } from "@mui/material";
3
+ import React from "react";
4
+ import { MUGlobal } from "./MUGlobal";
5
5
  /**
6
6
  * Input field
7
7
  * @param props Props
@@ -10,23 +10,25 @@ import { MUGlobal } from './MUGlobal';
10
10
  export const InputField = React.forwardRef((props, ref) => {
11
11
  var _a;
12
12
  // Destruct
13
- const { changeDelay, InputLabelProps = {}, InputProps = {}, onChange, readOnly, size = MUGlobal.inputFieldSize, variant = MUGlobal.inputFieldVariant, ...rest } = props;
13
+ const { changeDelay, InputLabelProps = {}, InputProps = {}, onChange, onChangeDelay, readOnly, size = MUGlobal.inputFieldSize, variant = MUGlobal.inputFieldVariant, ...rest } = props;
14
14
  // Shrink
15
15
  (_a = InputLabelProps.shrink) !== null && _a !== void 0 ? _a : (InputLabelProps.shrink = MUGlobal.searchFieldShrink);
16
16
  // Read only
17
17
  if (readOnly != null)
18
18
  InputProps.readOnly = readOnly;
19
19
  const isMounted = React.useRef(true);
20
- const delayed = onChange != null && changeDelay != null && changeDelay >= 1
21
- ? useDelayedExecutor(onChange, changeDelay)
22
- : undefined;
20
+ const createDelayed = () => {
21
+ if (changeDelay != null && changeDelay >= 1) {
22
+ const changeHandler = onChangeDelay !== null && onChangeDelay !== void 0 ? onChangeDelay : onChange;
23
+ if (changeHandler)
24
+ return useDelayedExecutor(changeHandler, changeDelay);
25
+ }
26
+ return undefined;
27
+ };
28
+ const delayed = createDelayed();
23
29
  const onChangeEx = (event) => {
24
- if (onChange == null)
25
- return;
26
- if (changeDelay == null || changeDelay < 1) {
30
+ if (onChange && (delayed == null || onChangeDelay != null))
27
31
  onChange(event);
28
- return;
29
- }
30
32
  delayed === null || delayed === void 0 ? void 0 : delayed.call(undefined, event);
31
33
  };
32
34
  React.useEffect(() => {
@@ -0,0 +1,13 @@
1
+ /// <reference types="react" />
2
+ import { AutocompleteProps } from "@mui/material";
3
+ export type TagListProps = Omit<AutocompleteProps<string, true, false, true>, "open" | "multiple" | "freeSolo" | "options" | "renderInput"> & {
4
+ /**
5
+ * Load data callback
6
+ */
7
+ loadData: (keyword: string | undefined, maxItems: number) => PromiseLike<string[] | null | undefined>;
8
+ /**
9
+ * Max items
10
+ */
11
+ maxItems?: number;
12
+ };
13
+ export declare function TagList(props: TagListProps): JSX.Element;
package/lib/TagList.js ADDED
@@ -0,0 +1,33 @@
1
+ import { Autocomplete, Checkbox, Chip } from "@mui/material";
2
+ import CheckBoxOutlineBlankIcon from "@mui/icons-material/CheckBoxOutlineBlank";
3
+ import CheckBoxIcon from "@mui/icons-material/CheckBox";
4
+ import React from "react";
5
+ import { InputField } from "./InputField";
6
+ import { globalApp } from "./app/ReactApp";
7
+ export function TagList(props) {
8
+ var _a;
9
+ // Labels
10
+ const { noOptions, loading: loadingLabel, more = "More", open: openDefault } = (_a = globalApp === null || globalApp === void 0 ? void 0 : globalApp.getLabels("noOptions", "loading", "more", "open")) !== null && _a !== void 0 ? _a : {};
11
+ const moreLabel = more + "...";
12
+ // Destruct
13
+ const { renderOption = (props, option, { selected }) => (React.createElement("li", { ...props },
14
+ React.createElement(Checkbox, { icon: React.createElement(CheckBoxOutlineBlankIcon, { fontSize: "small" }), checkedIcon: React.createElement(CheckBoxIcon, { fontSize: "small" }), style: { marginRight: 8 }, checked: selected }),
15
+ option)), renderTags = (value, getTagProps) => value.map((option, index) => (React.createElement(Chip, { variant: "outlined", label: option, ...getTagProps({ index }) }))), noOptionsText = noOptions, loadingText = loadingLabel, openText = openDefault, loadData, maxItems = 16, ...rest } = props;
16
+ const [open, setOpen] = React.useState(false);
17
+ const [options, setOptions] = React.useState([]);
18
+ const loading = open && options.length === 0;
19
+ return (React.createElement(Autocomplete, { multiple: true, freeSolo: true, open: open, onOpen: () => {
20
+ setOpen(true);
21
+ }, onClose: () => {
22
+ setOpen(false);
23
+ }, options: options, loading: loading, renderOption: renderOption, renderTags: renderTags, renderInput: (params) => (React.createElement(InputField, { changeDelay: 480, onChange: async (event) => {
24
+ var _a;
25
+ const result = (_a = (await loadData(event.target.value, maxItems))) !== null && _a !== void 0 ? _a : [];
26
+ if (result.length >= maxItems) {
27
+ result.push(moreLabel);
28
+ }
29
+ setOptions(result);
30
+ }, ...params })), getOptionDisabled: (item) => {
31
+ return item === moreLabel;
32
+ }, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, ...rest }));
33
+ }
package/lib/index.d.ts CHANGED
@@ -85,6 +85,7 @@ export * from "./TabBox";
85
85
  export * from "./TableEx";
86
86
  export * from "./TextFieldEx";
87
87
  export * from "./Tiplist";
88
+ export * from "./TagList";
88
89
  export * from "./TwoFieldInput";
89
90
  export * from "./TooltipClick";
90
91
  export * from "./UserAvatar";
package/lib/index.js CHANGED
@@ -85,6 +85,7 @@ export * from "./TabBox";
85
85
  export * from "./TableEx";
86
86
  export * from "./TextFieldEx";
87
87
  export * from "./Tiplist";
88
+ export * from "./TagList";
88
89
  export * from "./TwoFieldInput";
89
90
  export * from "./TooltipClick";
90
91
  export * from "./UserAvatar";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.1.47",
3
+ "version": "1.1.49",
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.71",
53
+ "@etsoo/appscript": "^1.3.78",
54
54
  "@etsoo/notificationbase": "^1.1.24",
55
- "@etsoo/react": "^1.6.50",
56
- "@etsoo/shared": "^1.1.90",
55
+ "@etsoo/react": "^1.6.51",
56
+ "@etsoo/shared": "^1.1.92",
57
57
  "@mui/icons-material": "^5.11.11",
58
- "@mui/material": "^5.11.12",
59
- "@mui/x-data-grid": "^6.0.1",
58
+ "@mui/material": "^5.11.13",
59
+ "@mui/x-data-grid": "^6.0.2",
60
60
  "@types/pica": "^9.0.1",
61
61
  "@types/pulltorefreshjs": "^0.1.5",
62
62
  "@types/react": "^18.0.28",
@@ -71,12 +71,12 @@
71
71
  "react-dom": "^18.2.0",
72
72
  "react-draggable": "^4.4.5",
73
73
  "react-imask": "^6.4.3",
74
- "react-router-dom": "^6.8.2",
74
+ "react-router-dom": "^6.9.0",
75
75
  "react-window": "^1.8.8"
76
76
  },
77
77
  "devDependencies": {
78
78
  "@babel/cli": "^7.21.0",
79
- "@babel/core": "^7.21.0",
79
+ "@babel/core": "^7.21.3",
80
80
  "@babel/plugin-transform-runtime": "^7.21.0",
81
81
  "@babel/preset-env": "^7.20.2",
82
82
  "@babel/preset-react": "^7.18.6",
@@ -84,9 +84,9 @@
84
84
  "@babel/runtime-corejs3": "^7.21.0",
85
85
  "@testing-library/jest-dom": "^5.16.5",
86
86
  "@testing-library/react": "^14.0.0",
87
- "@types/jest": "^29.4.0",
88
- "@typescript-eslint/eslint-plugin": "^5.54.1",
89
- "@typescript-eslint/parser": "^5.54.1",
87
+ "@types/jest": "^29.5.0",
88
+ "@typescript-eslint/eslint-plugin": "^5.55.0",
89
+ "@typescript-eslint/parser": "^5.55.0",
90
90
  "jest": "^29.5.0",
91
91
  "jest-environment-jsdom": "^29.5.0",
92
92
  "typescript": "^4.9.5"
@@ -1,21 +1,28 @@
1
- import { useDelayedExecutor } from '@etsoo/react';
2
- import { TextField, TextFieldProps } from '@mui/material';
3
- import React from 'react';
4
- import { MUGlobal } from './MUGlobal';
1
+ import { useDelayedExecutor } from "@etsoo/react";
2
+ import { TextField, TextFieldProps } from "@mui/material";
3
+ import React from "react";
4
+ import { MUGlobal } from "./MUGlobal";
5
5
 
6
6
  /**
7
7
  * Input field props
8
8
  */
9
9
  export type InputFieldProps = TextFieldProps & {
10
- /**
11
- * Change delay (ms) to avoid repeatly dispatch onChange
12
- */
13
- changeDelay?: number;
10
+ /**
11
+ * Change delay (ms) to avoid repeatly dispatch onChange
12
+ */
13
+ changeDelay?: number;
14
14
 
15
- /**
16
- * Is the field read only?
17
- */
18
- readOnly?: boolean;
15
+ /**
16
+ * Change delay handler, without it onChange will be applied
17
+ */
18
+ onChangeDelay?: React.ChangeEventHandler<
19
+ HTMLTextAreaElement | HTMLInputElement
20
+ >;
21
+
22
+ /**
23
+ * Is the field read only?
24
+ */
25
+ readOnly?: boolean;
19
26
  };
20
27
 
21
28
  /**
@@ -24,62 +31,63 @@ export type InputFieldProps = TextFieldProps & {
24
31
  * @returns Component
25
32
  */
26
33
  export const InputField = React.forwardRef<HTMLDivElement, InputFieldProps>(
27
- (props, ref) => {
28
- // Destruct
29
- const {
30
- changeDelay,
31
- InputLabelProps = {},
32
- InputProps = {},
33
- onChange,
34
- readOnly,
35
- size = MUGlobal.inputFieldSize,
36
- variant = MUGlobal.inputFieldVariant,
37
- ...rest
38
- } = props;
39
-
40
- // Shrink
41
- InputLabelProps.shrink ??= MUGlobal.searchFieldShrink;
42
-
43
- // Read only
44
- if (readOnly != null) InputProps.readOnly = readOnly;
34
+ (props, ref) => {
35
+ // Destruct
36
+ const {
37
+ changeDelay,
38
+ InputLabelProps = {},
39
+ InputProps = {},
40
+ onChange,
41
+ onChangeDelay,
42
+ readOnly,
43
+ size = MUGlobal.inputFieldSize,
44
+ variant = MUGlobal.inputFieldVariant,
45
+ ...rest
46
+ } = props;
45
47
 
46
- const isMounted = React.useRef(true);
47
- const delayed =
48
- onChange != null && changeDelay != null && changeDelay >= 1
49
- ? useDelayedExecutor(onChange, changeDelay)
50
- : undefined;
48
+ // Shrink
49
+ InputLabelProps.shrink ??= MUGlobal.searchFieldShrink;
51
50
 
52
- const onChangeEx = (
53
- event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
54
- ) => {
55
- if (onChange == null) return;
51
+ // Read only
52
+ if (readOnly != null) InputProps.readOnly = readOnly;
56
53
 
57
- if (changeDelay == null || changeDelay < 1) {
58
- onChange(event);
59
- return;
60
- }
54
+ const isMounted = React.useRef(true);
55
+ const createDelayed = () => {
56
+ if (changeDelay != null && changeDelay >= 1) {
57
+ const changeHandler = onChangeDelay ?? onChange;
58
+ if (changeHandler)
59
+ return useDelayedExecutor(changeHandler, changeDelay);
60
+ }
61
+ return undefined;
62
+ };
63
+ const delayed = createDelayed();
61
64
 
62
- delayed?.call(undefined, event);
63
- };
65
+ const onChangeEx = (
66
+ event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
67
+ ) => {
68
+ if (onChange && (delayed == null || onChangeDelay != null))
69
+ onChange(event);
70
+ delayed?.call(undefined, event);
71
+ };
64
72
 
65
- React.useEffect(() => {
66
- return () => {
67
- isMounted.current = false;
68
- delayed?.clear();
69
- };
70
- }, []);
73
+ React.useEffect(() => {
74
+ return () => {
75
+ isMounted.current = false;
76
+ delayed?.clear();
77
+ };
78
+ }, []);
71
79
 
72
- // Layout
73
- return (
74
- <TextField
75
- ref={ref}
76
- InputLabelProps={InputLabelProps}
77
- InputProps={InputProps}
78
- onChange={onChangeEx}
79
- size={size}
80
- variant={variant}
81
- {...rest}
82
- />
83
- );
84
- }
80
+ // Layout
81
+ return (
82
+ <TextField
83
+ ref={ref}
84
+ InputLabelProps={InputLabelProps}
85
+ InputProps={InputProps}
86
+ onChange={onChangeEx}
87
+ size={size}
88
+ variant={variant}
89
+ {...rest}
90
+ />
91
+ );
92
+ }
85
93
  );
@@ -0,0 +1,103 @@
1
+ import { Autocomplete, AutocompleteProps, Checkbox, Chip } from "@mui/material";
2
+ import CheckBoxOutlineBlankIcon from "@mui/icons-material/CheckBoxOutlineBlank";
3
+ import CheckBoxIcon from "@mui/icons-material/CheckBox";
4
+ import React from "react";
5
+ import { InputField } from "./InputField";
6
+ import { globalApp } from "./app/ReactApp";
7
+
8
+ export type TagListProps = Omit<
9
+ AutocompleteProps<string, true, false, true>,
10
+ "open" | "multiple" | "freeSolo" | "options" | "renderInput"
11
+ > & {
12
+ /**
13
+ * Load data callback
14
+ */
15
+ loadData: (
16
+ keyword: string | undefined,
17
+ maxItems: number
18
+ ) => PromiseLike<string[] | null | undefined>;
19
+
20
+ /**
21
+ * Max items
22
+ */
23
+ maxItems?: number;
24
+ };
25
+
26
+ export function TagList(props: TagListProps) {
27
+ // Labels
28
+ const {
29
+ noOptions,
30
+ loading: loadingLabel,
31
+ more = "More",
32
+ open: openDefault
33
+ } = globalApp?.getLabels("noOptions", "loading", "more", "open") ?? {};
34
+
35
+ const moreLabel = more + "...";
36
+
37
+ // Destruct
38
+ const {
39
+ renderOption = (props, option, { selected }) => (
40
+ <li {...props}>
41
+ <Checkbox
42
+ icon={<CheckBoxOutlineBlankIcon fontSize="small" />}
43
+ checkedIcon={<CheckBoxIcon fontSize="small" />}
44
+ style={{ marginRight: 8 }}
45
+ checked={selected}
46
+ />
47
+ {option}
48
+ </li>
49
+ ),
50
+ renderTags = (value: readonly string[], getTagProps) =>
51
+ value.map((option: string, index: number) => (
52
+ <Chip variant="outlined" label={option} {...getTagProps({ index })} />
53
+ )),
54
+ noOptionsText = noOptions,
55
+ loadingText = loadingLabel,
56
+ openText = openDefault,
57
+ loadData,
58
+ maxItems = 16,
59
+ ...rest
60
+ } = props;
61
+
62
+ const [open, setOpen] = React.useState(false);
63
+ const [options, setOptions] = React.useState<readonly string[]>([]);
64
+ const loading = open && options.length === 0;
65
+
66
+ return (
67
+ <Autocomplete<string, true, false, true>
68
+ multiple
69
+ freeSolo
70
+ open={open}
71
+ onOpen={() => {
72
+ setOpen(true);
73
+ }}
74
+ onClose={() => {
75
+ setOpen(false);
76
+ }}
77
+ options={options}
78
+ loading={loading}
79
+ renderOption={renderOption}
80
+ renderTags={renderTags}
81
+ renderInput={(params) => (
82
+ <InputField
83
+ changeDelay={480}
84
+ onChange={async (event) => {
85
+ const result = (await loadData(event.target.value, maxItems)) ?? [];
86
+ if (result.length >= maxItems) {
87
+ result.push(moreLabel);
88
+ }
89
+ setOptions(result);
90
+ }}
91
+ {...params}
92
+ />
93
+ )}
94
+ getOptionDisabled={(item) => {
95
+ return item === moreLabel;
96
+ }}
97
+ noOptionsText={noOptionsText}
98
+ loadingText={loadingText}
99
+ openText={openText}
100
+ {...rest}
101
+ />
102
+ );
103
+ }
package/src/index.ts CHANGED
@@ -88,6 +88,7 @@ export * from "./TabBox";
88
88
  export * from "./TableEx";
89
89
  export * from "./TextFieldEx";
90
90
  export * from "./Tiplist";
91
+ export * from "./TagList";
91
92
  export * from "./TwoFieldInput";
92
93
  export * from "./TooltipClick";
93
94
  export * from "./UserAvatar";