@etsoo/materialui 1.6.3 → 1.6.5

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.
@@ -27,10 +27,11 @@ it("Render ComboBox", async () => {
27
27
  });
28
28
 
29
29
  await waitFor(async () => {
30
- const button = await screen.findByRole("button");
30
+ const button = document.querySelector("button");
31
+ expect(button).toBeTruthy();
31
32
 
32
33
  // Act, click the list
33
- const clicked = fireEvent.click(button);
34
+ const clicked = fireEvent.click(button!);
34
35
  expect(clicked).toBeTruthy();
35
36
 
36
37
  // Get list item
@@ -20,7 +20,7 @@ function TagList(props) {
20
20
  const { noOptions, loading: loadingLabel, more = "More", open: openDefault } = app?.getLabels("noOptions", "loading", "more", "open") ?? {};
21
21
  const moreLabel = more + "...";
22
22
  // Destruct
23
- const { renderOption = ({ key, ...props }, option, { selected }) => ((0, jsx_runtime_1.jsxs)("li", { ...props, children: [(0, jsx_runtime_1.jsx)(Checkbox_1.default, { icon: (0, jsx_runtime_1.jsx)(CheckBoxOutlineBlank_1.default, { fontSize: "small" }), checkedIcon: (0, jsx_runtime_1.jsx)(CheckBox_1.default, { fontSize: "small" }), style: { marginRight: 8 }, checked: selected }), option] }, key)), renderValue = (value, getTagProps) => value.map((option, index) => {
23
+ const { getOptionLabel = (option) => option, renderOption = ({ key, ...props }, option, { selected }) => ((0, jsx_runtime_1.jsxs)("li", { ...props, children: [(0, jsx_runtime_1.jsx)(Checkbox_1.default, { icon: (0, jsx_runtime_1.jsx)(CheckBoxOutlineBlank_1.default, { fontSize: "small" }), checkedIcon: (0, jsx_runtime_1.jsx)(CheckBox_1.default, { fontSize: "small" }), style: { marginRight: 8 }, checked: selected }), getOptionLabel(option)] }, key)), renderValue = (value, getTagProps) => value.map((option, index) => {
24
24
  const { key, ...rest } = getTagProps({ index });
25
25
  return (0, jsx_runtime_1.jsx)(Chip_1.default, { variant: "outlined", label: option, ...rest }, key);
26
26
  }), noOptionsText = noOptions, loadingText = loadingLabel, openText = openDefault, loadData, maxItems = 16, disableCloseOnSelect = true, openOnFocus = true, label, inputProps, onChange, value, ...rest } = props;
@@ -53,6 +53,7 @@ function TagList(props) {
53
53
  loadDataLocal();
54
54
  }
55
55
  }, onClose: () => {
56
+ setOptions([]);
56
57
  setOpen(false);
57
58
  }, options: options, loading: loading, disableCloseOnSelect: disableCloseOnSelect, clearOnBlur: true, openOnFocus: openOnFocus, renderOption: renderOption, renderValue: renderValue, renderInput: (params) => ((0, jsx_runtime_1.jsx)(InputField_1.InputField, { label: label, onChangeDelay: async (event) => {
58
59
  // Stop bubble
@@ -10,6 +10,10 @@ export type TagListProProps<D extends ListType2 = ListType2> = Omit<Autocomplete
10
10
  * Load data callback
11
11
  */
12
12
  loadData: (keyword: string | undefined, items: number) => PromiseLike<D[] | null | undefined>;
13
+ /**
14
+ * Load value from ids
15
+ */
16
+ loadIdValue?: () => PromiseLike<D[] | null | undefined>;
13
17
  /**
14
18
  * Input props
15
19
  */
@@ -20,17 +20,17 @@ function TagListPro(props) {
20
20
  // Labels
21
21
  const { noOptions, loading: loadingLabel, more = "More", open: openDefault } = app?.getLabels("noOptions", "loading", "more", "open") ?? {};
22
22
  const moreLabel = more + "...";
23
- const getLabel = (item) => shared_1.DataTypes.getListItemLabel(item);
24
23
  // Destruct
25
- const { getOptionKey = (option) => typeof option === "string" ? option : option.id, renderOption = ({ key, ...props }, option, { selected }) => ((0, jsx_runtime_1.jsx)("li", { ...props, children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Checkbox_1.default, { icon: (0, jsx_runtime_1.jsx)(CheckBoxOutlineBlank_1.default, { fontSize: "small" }), checkedIcon: (0, jsx_runtime_1.jsx)(CheckBox_1.default, { fontSize: "small" }), style: { marginRight: 8 }, checked: selected }), getLabel(option)] }) }, key)), renderValue = (value, getTagProps) => value.map((option, index) => {
24
+ const { getOptionKey = (option) => typeof option === "string" ? option : option.id, getOptionLabel = (option) => shared_1.DataTypes.getListItemLabel(option), renderOption = ({ key, ...props }, option, { selected }) => ((0, jsx_runtime_1.jsx)("li", { ...props, children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Checkbox_1.default, { icon: (0, jsx_runtime_1.jsx)(CheckBoxOutlineBlank_1.default, { fontSize: "small" }), checkedIcon: (0, jsx_runtime_1.jsx)(CheckBox_1.default, { fontSize: "small" }), style: { marginRight: 8 }, checked: selected }), getOptionLabel(option)] }) }, key)), renderValue = (value, getTagProps) => value.map((option, index) => {
26
25
  const { key, ...rest } = getTagProps({ index });
27
- return ((0, jsx_runtime_1.jsx)(Chip_1.default, { variant: "outlined", label: getLabel(option), ...rest }, key));
28
- }), noOptionsText = noOptions, loadingText = loadingLabel, openText = openDefault, loadData, maxItems = 16, disableCloseOnSelect = true, openOnFocus = true, label, inputProps, onChange, value, ...rest } = props;
26
+ return ((0, jsx_runtime_1.jsx)(Chip_1.default, { variant: "outlined", label: getOptionLabel(option), ...rest }, key));
27
+ }), noOptionsText = noOptions, loadingText = loadingLabel, openText = openDefault, loadData, loadIdValue, maxItems = 16, disableCloseOnSelect = true, openOnFocus = true, label, inputProps, onChange, value, ...rest } = props;
29
28
  const [open, setOpen] = react_1.default.useState(false);
30
29
  const [options, setOptions] = react_1.default.useState([]);
31
30
  const [loading, setLoading] = react_1.default.useState(false);
31
+ const [valueState, setValueState] = react_1.default.useState(value ?? []);
32
32
  const currentValue = react_1.default.useRef([]);
33
- currentValue.current = value ?? [];
33
+ currentValue.current = valueState;
34
34
  const loadDataLocal = async (keyword) => {
35
35
  setLoading(true);
36
36
  const result = (await loadData(keyword, maxItems)) ?? [];
@@ -49,12 +49,22 @@ function TagListPro(props) {
49
49
  setOptions(result);
50
50
  setLoading(false);
51
51
  };
52
+ react_1.default.useEffect(() => {
53
+ if (loadIdValue) {
54
+ loadIdValue().then((result) => {
55
+ if (result == null)
56
+ return;
57
+ setValueState(result);
58
+ });
59
+ }
60
+ }, [loadIdValue]);
52
61
  return ((0, jsx_runtime_1.jsx)(Autocomplete_1.default, { multiple: true, filterOptions: (options, _state) => options, open: open, onOpen: () => {
53
62
  setOpen(true);
54
63
  if (options.length === 0) {
55
64
  loadDataLocal();
56
65
  }
57
66
  }, onClose: () => {
67
+ setOptions([]);
58
68
  setOpen(false);
59
69
  }, options: options, loading: loading, disableCloseOnSelect: disableCloseOnSelect, openOnFocus: openOnFocus, renderOption: renderOption, renderValue: renderValue, renderInput: (params) => ((0, jsx_runtime_1.jsx)(InputField_1.InputField, { label: label, onChangeDelay: async (event) => {
60
70
  // Stop bubble
@@ -64,8 +74,9 @@ function TagListPro(props) {
64
74
  }, ...inputProps, ...params })), getOptionDisabled: (item) => {
65
75
  return (typeof item.id === "number" &&
66
76
  item.id < 0 &&
67
- getLabel(item) === moreLabel);
68
- }, getOptionLabel: (item) => getLabel(item), getOptionKey: getOptionKey, isOptionEqualToValue: (option, value) => option.id === value.id, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, value: value, onChange: (event, value, reason, details) => {
77
+ "name" in item &&
78
+ item["name"] === moreLabel);
79
+ }, getOptionKey: getOptionKey, isOptionEqualToValue: (option, value) => option.id === value.id, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, value: valueState, onChange: (event, value, reason, details) => {
69
80
  currentValue.current = value;
70
81
  if (onChange)
71
82
  onChange(event, value, reason, details);
@@ -14,7 +14,7 @@ export function TagList(props) {
14
14
  const { noOptions, loading: loadingLabel, more = "More", open: openDefault } = app?.getLabels("noOptions", "loading", "more", "open") ?? {};
15
15
  const moreLabel = more + "...";
16
16
  // Destruct
17
- const { renderOption = ({ key, ...props }, option, { selected }) => (_jsxs("li", { ...props, children: [_jsx(Checkbox, { icon: _jsx(CheckBoxOutlineBlankIcon, { fontSize: "small" }), checkedIcon: _jsx(CheckBoxIcon, { fontSize: "small" }), style: { marginRight: 8 }, checked: selected }), option] }, key)), renderValue = (value, getTagProps) => value.map((option, index) => {
17
+ const { getOptionLabel = (option) => option, renderOption = ({ key, ...props }, option, { selected }) => (_jsxs("li", { ...props, children: [_jsx(Checkbox, { icon: _jsx(CheckBoxOutlineBlankIcon, { fontSize: "small" }), checkedIcon: _jsx(CheckBoxIcon, { fontSize: "small" }), style: { marginRight: 8 }, checked: selected }), getOptionLabel(option)] }, key)), renderValue = (value, getTagProps) => value.map((option, index) => {
18
18
  const { key, ...rest } = getTagProps({ index });
19
19
  return _jsx(Chip, { variant: "outlined", label: option, ...rest }, key);
20
20
  }), noOptionsText = noOptions, loadingText = loadingLabel, openText = openDefault, loadData, maxItems = 16, disableCloseOnSelect = true, openOnFocus = true, label, inputProps, onChange, value, ...rest } = props;
@@ -47,6 +47,7 @@ export function TagList(props) {
47
47
  loadDataLocal();
48
48
  }
49
49
  }, onClose: () => {
50
+ setOptions([]);
50
51
  setOpen(false);
51
52
  }, options: options, loading: loading, disableCloseOnSelect: disableCloseOnSelect, clearOnBlur: true, openOnFocus: openOnFocus, renderOption: renderOption, renderValue: renderValue, renderInput: (params) => (_jsx(InputField, { label: label, onChangeDelay: async (event) => {
52
53
  // Stop bubble
@@ -10,6 +10,10 @@ export type TagListProProps<D extends ListType2 = ListType2> = Omit<Autocomplete
10
10
  * Load data callback
11
11
  */
12
12
  loadData: (keyword: string | undefined, items: number) => PromiseLike<D[] | null | undefined>;
13
+ /**
14
+ * Load value from ids
15
+ */
16
+ loadIdValue?: () => PromiseLike<D[] | null | undefined>;
13
17
  /**
14
18
  * Input props
15
19
  */
@@ -14,17 +14,17 @@ export function TagListPro(props) {
14
14
  // Labels
15
15
  const { noOptions, loading: loadingLabel, more = "More", open: openDefault } = app?.getLabels("noOptions", "loading", "more", "open") ?? {};
16
16
  const moreLabel = more + "...";
17
- const getLabel = (item) => DataTypes.getListItemLabel(item);
18
17
  // Destruct
19
- const { getOptionKey = (option) => typeof option === "string" ? option : option.id, renderOption = ({ key, ...props }, option, { selected }) => (_jsx("li", { ...props, children: _jsxs(_Fragment, { children: [_jsx(Checkbox, { icon: _jsx(CheckBoxOutlineBlankIcon, { fontSize: "small" }), checkedIcon: _jsx(CheckBoxIcon, { fontSize: "small" }), style: { marginRight: 8 }, checked: selected }), getLabel(option)] }) }, key)), renderValue = (value, getTagProps) => value.map((option, index) => {
18
+ const { getOptionKey = (option) => typeof option === "string" ? option : option.id, getOptionLabel = (option) => DataTypes.getListItemLabel(option), renderOption = ({ key, ...props }, option, { selected }) => (_jsx("li", { ...props, children: _jsxs(_Fragment, { children: [_jsx(Checkbox, { icon: _jsx(CheckBoxOutlineBlankIcon, { fontSize: "small" }), checkedIcon: _jsx(CheckBoxIcon, { fontSize: "small" }), style: { marginRight: 8 }, checked: selected }), getOptionLabel(option)] }) }, key)), renderValue = (value, getTagProps) => value.map((option, index) => {
20
19
  const { key, ...rest } = getTagProps({ index });
21
- return (_jsx(Chip, { variant: "outlined", label: getLabel(option), ...rest }, key));
22
- }), noOptionsText = noOptions, loadingText = loadingLabel, openText = openDefault, loadData, maxItems = 16, disableCloseOnSelect = true, openOnFocus = true, label, inputProps, onChange, value, ...rest } = props;
20
+ return (_jsx(Chip, { variant: "outlined", label: getOptionLabel(option), ...rest }, key));
21
+ }), noOptionsText = noOptions, loadingText = loadingLabel, openText = openDefault, loadData, loadIdValue, maxItems = 16, disableCloseOnSelect = true, openOnFocus = true, label, inputProps, onChange, value, ...rest } = props;
23
22
  const [open, setOpen] = React.useState(false);
24
23
  const [options, setOptions] = React.useState([]);
25
24
  const [loading, setLoading] = React.useState(false);
25
+ const [valueState, setValueState] = React.useState(value ?? []);
26
26
  const currentValue = React.useRef([]);
27
- currentValue.current = value ?? [];
27
+ currentValue.current = valueState;
28
28
  const loadDataLocal = async (keyword) => {
29
29
  setLoading(true);
30
30
  const result = (await loadData(keyword, maxItems)) ?? [];
@@ -43,12 +43,22 @@ export function TagListPro(props) {
43
43
  setOptions(result);
44
44
  setLoading(false);
45
45
  };
46
+ React.useEffect(() => {
47
+ if (loadIdValue) {
48
+ loadIdValue().then((result) => {
49
+ if (result == null)
50
+ return;
51
+ setValueState(result);
52
+ });
53
+ }
54
+ }, [loadIdValue]);
46
55
  return (_jsx(Autocomplete, { multiple: true, filterOptions: (options, _state) => options, open: open, onOpen: () => {
47
56
  setOpen(true);
48
57
  if (options.length === 0) {
49
58
  loadDataLocal();
50
59
  }
51
60
  }, onClose: () => {
61
+ setOptions([]);
52
62
  setOpen(false);
53
63
  }, options: options, loading: loading, disableCloseOnSelect: disableCloseOnSelect, openOnFocus: openOnFocus, renderOption: renderOption, renderValue: renderValue, renderInput: (params) => (_jsx(InputField, { label: label, onChangeDelay: async (event) => {
54
64
  // Stop bubble
@@ -58,8 +68,9 @@ export function TagListPro(props) {
58
68
  }, ...inputProps, ...params })), getOptionDisabled: (item) => {
59
69
  return (typeof item.id === "number" &&
60
70
  item.id < 0 &&
61
- getLabel(item) === moreLabel);
62
- }, getOptionLabel: (item) => getLabel(item), getOptionKey: getOptionKey, isOptionEqualToValue: (option, value) => option.id === value.id, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, value: value, onChange: (event, value, reason, details) => {
71
+ "name" in item &&
72
+ item["name"] === moreLabel);
73
+ }, getOptionKey: getOptionKey, isOptionEqualToValue: (option, value) => option.id === value.id, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, value: valueState, onChange: (event, value, reason, details) => {
63
74
  currentValue.current = value;
64
75
  if (onChange)
65
76
  onChange(event, value, reason, details);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.6.3",
3
+ "version": "1.6.5",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -42,11 +42,11 @@
42
42
  "@emotion/styled": "^11.14.1",
43
43
  "@etsoo/appscript": "^1.6.53",
44
44
  "@etsoo/notificationbase": "^1.1.66",
45
- "@etsoo/react": "^1.8.70",
45
+ "@etsoo/react": "^1.8.71",
46
46
  "@etsoo/shared": "^1.2.80",
47
47
  "@mui/icons-material": "^7.3.7",
48
48
  "@mui/material": "^7.3.7",
49
- "@mui/x-data-grid": "^8.24.0",
49
+ "@mui/x-data-grid": "^8.25.0",
50
50
  "chart.js": "^4.5.1",
51
51
  "chartjs-plugin-datalabels": "^2.2.0",
52
52
  "dompurify": "^3.3.1",
@@ -65,13 +65,13 @@
65
65
  "react-dom": "$react-dom"
66
66
  },
67
67
  "devDependencies": {
68
- "@babel/cli": "^7.28.3",
69
- "@babel/core": "^7.28.5",
68
+ "@babel/cli": "^7.28.6",
69
+ "@babel/core": "^7.28.6",
70
70
  "@babel/plugin-transform-runtime": "^7.28.5",
71
- "@babel/preset-env": "^7.28.5",
71
+ "@babel/preset-env": "^7.28.6",
72
72
  "@babel/preset-react": "^7.28.5",
73
73
  "@babel/preset-typescript": "^7.28.5",
74
- "@babel/runtime-corejs3": "^7.28.4",
74
+ "@babel/runtime-corejs3": "^7.28.6",
75
75
  "@testing-library/react": "^16.3.1",
76
76
  "@types/pica": "^9.0.5",
77
77
  "@types/pulltorefreshjs": "^0.1.7",
@@ -82,6 +82,6 @@
82
82
  "@vitejs/plugin-react": "^5.1.2",
83
83
  "jsdom": "^27.4.0",
84
84
  "typescript": "^5.9.3",
85
- "vitest": "^4.0.16"
85
+ "vitest": "^4.0.17"
86
86
  }
87
87
  }
package/src/TagList.tsx CHANGED
@@ -51,6 +51,7 @@ export function TagList(props: TagListProps) {
51
51
 
52
52
  // Destruct
53
53
  const {
54
+ getOptionLabel = (option) => option,
54
55
  renderOption = ({ key, ...props }, option, { selected }) => (
55
56
  <li key={key} {...props}>
56
57
  <Checkbox
@@ -59,7 +60,7 @@ export function TagList(props: TagListProps) {
59
60
  style={{ marginRight: 8 }}
60
61
  checked={selected}
61
62
  />
62
- {option}
63
+ {getOptionLabel(option)}
63
64
  </li>
64
65
  ),
65
66
  renderValue = (value: readonly string[], getTagProps) =>
@@ -121,6 +122,7 @@ export function TagList(props: TagListProps) {
121
122
  }
122
123
  }}
123
124
  onClose={() => {
125
+ setOptions([]);
124
126
  setOpen(false);
125
127
  }}
126
128
  options={options}
@@ -25,6 +25,11 @@ export type TagListProProps<D extends ListType2 = ListType2> = Omit<
25
25
  items: number
26
26
  ) => PromiseLike<D[] | null | undefined>;
27
27
 
28
+ /**
29
+ * Load value from ids
30
+ */
31
+ loadIdValue?: () => PromiseLike<D[] | null | undefined>;
32
+
28
33
  /**
29
34
  * Input props
30
35
  */
@@ -52,12 +57,11 @@ export function TagListPro<D extends ListType2 = ListType2>(
52
57
 
53
58
  const moreLabel = more + "...";
54
59
 
55
- const getLabel = (item: D) => DataTypes.getListItemLabel(item);
56
-
57
60
  // Destruct
58
61
  const {
59
62
  getOptionKey = (option) =>
60
63
  typeof option === "string" ? option : option.id,
64
+ getOptionLabel = (option) => DataTypes.getListItemLabel(option),
61
65
  renderOption = ({ key, ...props }, option, { selected }) => (
62
66
  <li key={key} {...props}>
63
67
  <>
@@ -67,7 +71,7 @@ export function TagListPro<D extends ListType2 = ListType2>(
67
71
  style={{ marginRight: 8 }}
68
72
  checked={selected}
69
73
  />
70
- {getLabel(option)}
74
+ {getOptionLabel(option)}
71
75
  </>
72
76
  </li>
73
77
  ),
@@ -78,7 +82,7 @@ export function TagListPro<D extends ListType2 = ListType2>(
78
82
  <Chip
79
83
  variant="outlined"
80
84
  key={key}
81
- label={getLabel(option)}
85
+ label={getOptionLabel(option)}
82
86
  {...rest}
83
87
  />
84
88
  );
@@ -87,6 +91,7 @@ export function TagListPro<D extends ListType2 = ListType2>(
87
91
  loadingText = loadingLabel,
88
92
  openText = openDefault,
89
93
  loadData,
94
+ loadIdValue,
90
95
  maxItems = 16,
91
96
  disableCloseOnSelect = true,
92
97
  openOnFocus = true,
@@ -100,9 +105,10 @@ export function TagListPro<D extends ListType2 = ListType2>(
100
105
  const [open, setOpen] = React.useState(false);
101
106
  const [options, setOptions] = React.useState<readonly D[]>([]);
102
107
  const [loading, setLoading] = React.useState(false);
108
+ const [valueState, setValueState] = React.useState<D[]>(value ?? []);
103
109
 
104
110
  const currentValue = React.useRef<readonly D[]>([]);
105
- currentValue.current = value ?? [];
111
+ currentValue.current = valueState;
106
112
 
107
113
  const loadDataLocal = async (keyword?: string) => {
108
114
  setLoading(true);
@@ -124,6 +130,15 @@ export function TagListPro<D extends ListType2 = ListType2>(
124
130
  setLoading(false);
125
131
  };
126
132
 
133
+ React.useEffect(() => {
134
+ if (loadIdValue) {
135
+ loadIdValue().then((result) => {
136
+ if (result == null) return;
137
+ setValueState(result);
138
+ });
139
+ }
140
+ }, [loadIdValue]);
141
+
127
142
  return (
128
143
  <Autocomplete<D, true, false, false>
129
144
  multiple
@@ -136,6 +151,7 @@ export function TagListPro<D extends ListType2 = ListType2>(
136
151
  }
137
152
  }}
138
153
  onClose={() => {
154
+ setOptions([]);
139
155
  setOpen(false);
140
156
  }}
141
157
  options={options}
@@ -162,16 +178,16 @@ export function TagListPro<D extends ListType2 = ListType2>(
162
178
  return (
163
179
  typeof item.id === "number" &&
164
180
  item.id < 0 &&
165
- getLabel(item) === moreLabel
181
+ "name" in item &&
182
+ item["name"] === moreLabel
166
183
  );
167
184
  }}
168
- getOptionLabel={(item) => getLabel(item)}
169
185
  getOptionKey={getOptionKey}
170
186
  isOptionEqualToValue={(option, value) => option.id === value.id}
171
187
  noOptionsText={noOptionsText}
172
188
  loadingText={loadingText}
173
189
  openText={openText}
174
- value={value}
190
+ value={valueState}
175
191
  onChange={(event, value, reason, details) => {
176
192
  currentValue.current = value;
177
193
  if (onChange) onChange(event, value, reason, details);