@etsoo/materialui 1.5.97 → 1.5.99

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.
Files changed (43) hide show
  1. package/lib/cjs/ComboBox.js +1 -1
  2. package/lib/cjs/ComboBoxMultiple.js +1 -1
  3. package/lib/cjs/InputField.d.ts +3 -7
  4. package/lib/cjs/InputField.js +14 -16
  5. package/lib/cjs/InputTipField.js +1 -1
  6. package/lib/cjs/IntInputField.js +1 -1
  7. package/lib/cjs/ListMultipler.js +1 -1
  8. package/lib/cjs/QuickList.js +1 -1
  9. package/lib/cjs/SearchBar.js +0 -6
  10. package/lib/cjs/TagList.d.ts +1 -1
  11. package/lib/cjs/TagList.js +2 -2
  12. package/lib/cjs/TagListPro.d.ts +1 -1
  13. package/lib/cjs/TagListPro.js +1 -1
  14. package/lib/cjs/Tiplist.js +7 -3
  15. package/lib/cjs/TiplistPro.js +7 -3
  16. package/lib/mjs/ComboBox.js +1 -1
  17. package/lib/mjs/ComboBoxMultiple.js +1 -1
  18. package/lib/mjs/InputField.d.ts +3 -7
  19. package/lib/mjs/InputField.js +14 -16
  20. package/lib/mjs/InputTipField.js +1 -1
  21. package/lib/mjs/IntInputField.js +1 -1
  22. package/lib/mjs/ListMultipler.js +1 -1
  23. package/lib/mjs/QuickList.js +1 -1
  24. package/lib/mjs/SearchBar.js +0 -6
  25. package/lib/mjs/TagList.d.ts +1 -1
  26. package/lib/mjs/TagList.js +2 -2
  27. package/lib/mjs/TagListPro.d.ts +1 -1
  28. package/lib/mjs/TagListPro.js +1 -1
  29. package/lib/mjs/Tiplist.js +7 -3
  30. package/lib/mjs/TiplistPro.js +7 -3
  31. package/package.json +1 -1
  32. package/src/ComboBox.tsx +3 -3
  33. package/src/ComboBoxMultiple.tsx +3 -3
  34. package/src/InputField.tsx +19 -24
  35. package/src/InputTipField.tsx +1 -1
  36. package/src/IntInputField.tsx +1 -1
  37. package/src/ListMultipler.tsx +1 -1
  38. package/src/QuickList.tsx +1 -1
  39. package/src/SearchBar.tsx +0 -10
  40. package/src/TagList.tsx +4 -5
  41. package/src/TagListPro.tsx +2 -3
  42. package/src/Tiplist.tsx +9 -6
  43. package/src/TiplistPro.tsx +9 -5
@@ -124,7 +124,7 @@ function ComboBox(props) {
124
124
  };
125
125
  }, []);
126
126
  // Layout
127
- return ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [(0, jsx_runtime_1.jsx)("input", { ref: inputRef, "data-reset": inputReset ?? true, type: idIsString ? "text" : "number", style: { display: "none", width: 1 }, name: name, value: getValue(stateValue), readOnly: true, onChange: inputOnChange }), (0, jsx_runtime_1.jsxs)(Stack_1.default, { gap: 0.5, direction: "row", width: "100%", children: [(0, jsx_runtime_1.jsx)(Autocomplete_1.default, { value: stateValue, disableCloseOnSelect: disableCloseOnSelect, getOptionLabel: getOptionLabel, isOptionEqualToValue: (option, value) => option[idField] === value[idField], onChange: (event, value, reason, details) => {
127
+ return ((0, jsx_runtime_1.jsxs)("div", { style: { flex: 2 }, children: [(0, jsx_runtime_1.jsx)("input", { ref: inputRef, "data-reset": inputReset ?? true, type: idIsString ? "text" : "number", style: { display: "none" }, name: name, value: getValue(stateValue), readOnly: true, onChange: inputOnChange }), (0, jsx_runtime_1.jsxs)(Stack_1.default, { gap: 0.5, direction: "row", width: "100%", children: [(0, jsx_runtime_1.jsx)(Autocomplete_1.default, { value: stateValue, disableCloseOnSelect: disableCloseOnSelect, getOptionLabel: getOptionLabel, isOptionEqualToValue: (option, value) => option[idField] === value[idField], onChange: (event, value, reason, details) => {
128
128
  // Set value
129
129
  setInputValue(value);
130
130
  // Custom
@@ -121,7 +121,7 @@ function ComboBoxMultiple(props) {
121
121
  };
122
122
  }, []);
123
123
  // Layout
124
- return ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [(0, jsx_runtime_1.jsx)("input", { ref: inputRef, "data-reset": inputReset ?? true, type: "text", style: { display: "none", width: 1 }, name: name, value: getValue(stateValue), readOnly: true, onChange: inputOnChange }), (0, jsx_runtime_1.jsx)(Autocomplete_1.default, { value: stateValue == null
124
+ return ((0, jsx_runtime_1.jsxs)("div", { style: { flex: 2 }, children: [(0, jsx_runtime_1.jsx)("input", { ref: inputRef, "data-reset": inputReset ?? true, type: "text", style: { display: "none" }, name: name, value: getValue(stateValue), readOnly: true, onChange: inputOnChange }), (0, jsx_runtime_1.jsx)(Autocomplete_1.default, { value: stateValue == null
125
125
  ? []
126
126
  : Array.isArray(stateValue)
127
127
  ? stateValue
@@ -5,21 +5,17 @@ import { TextFieldProps } from "@mui/material/TextField";
5
5
  */
6
6
  export type InputFieldProps = TextFieldProps & {
7
7
  /**
8
- * Change delay (ms) to avoid repeatly dispatch onChange
8
+ * Change [delay (ms), Minimum characters] to avoid repeatly dispatch
9
9
  */
10
- changeDelay?: number;
10
+ changeDelay?: [number, number?];
11
11
  /**
12
- * Change delay handler, without it onChange will be applied
12
+ * Change delay handler
13
13
  */
14
14
  onChangeDelay?: React.ChangeEventHandler<HTMLTextAreaElement | HTMLInputElement>;
15
15
  /**
16
16
  * Is the field read only?
17
17
  */
18
18
  readOnly?: boolean;
19
- /**
20
- * Minimum characters to trigger the change event
21
- */
22
- minChars?: number;
23
19
  };
24
20
  /**
25
21
  * Input field
@@ -16,31 +16,29 @@ const TextField_1 = __importDefault(require("@mui/material/TextField"));
16
16
  */
17
17
  function InputField(props) {
18
18
  // Destruct
19
- const { InputProps = {}, inputProps = {}, slotProps, changeDelay, onChange, onChangeDelay, readOnly, size = MUGlobal_1.MUGlobal.inputFieldSize, variant = MUGlobal_1.MUGlobal.inputFieldVariant, minChars = 0, ...rest } = props;
19
+ const { InputProps = {}, inputProps = {}, slotProps, onChange, onChangeDelay, changeDelay = onChangeDelay ? [480] : undefined, readOnly, size = MUGlobal_1.MUGlobal.inputFieldSize, variant = MUGlobal_1.MUGlobal.inputFieldVariant, ...rest } = props;
20
20
  // Slot props
21
21
  const { htmlInput, input, inputLabel, ...restSlotProps } = slotProps ?? {};
22
22
  const isMounted = react_2.default.useRef(true);
23
23
  const createDelayed = () => {
24
- if (changeDelay != null && changeDelay >= 1) {
25
- const changeHandler = onChangeDelay ?? onChange;
26
- if (changeHandler)
27
- return (0, react_1.useDelayedExecutor)(changeHandler, changeDelay);
24
+ if (onChangeDelay && changeDelay && changeDelay[0] >= 1) {
25
+ return (0, react_1.useDelayedExecutor)(onChangeDelay, changeDelay[0]);
28
26
  }
29
27
  return undefined;
30
28
  };
31
29
  const delayed = createDelayed();
32
30
  const onChangeEx = (event) => {
33
- // Min characters check
34
- const len = event.target.value.length;
35
- if (len > 0 && len < minChars) {
36
- // Avoid to trigger the form change event
37
- event.stopPropagation();
38
- event.preventDefault();
39
- return;
31
+ // Change handler
32
+ onChange?.(event);
33
+ if (onChangeDelay && changeDelay && delayed) {
34
+ const [_, minChars = 0] = changeDelay;
35
+ if (minChars > 0) {
36
+ const len = event.target.value.length;
37
+ if (len < minChars)
38
+ return;
39
+ }
40
+ delayed.call(undefined, event);
40
41
  }
41
- if (onChange && (delayed == null || onChangeDelay != null))
42
- onChange(event);
43
- delayed?.call(undefined, event);
44
42
  };
45
43
  react_2.default.useEffect(() => {
46
44
  return () => {
@@ -51,7 +49,7 @@ function InputField(props) {
51
49
  // Layout
52
50
  return ((0, jsx_runtime_1.jsx)(TextField_1.default, { slotProps: {
53
51
  htmlInput: {
54
- ["data-min-chars"]: minChars,
52
+ ["data-min-chars"]: changeDelay?.[1],
55
53
  ...htmlInput,
56
54
  ...inputProps
57
55
  },
@@ -35,7 +35,7 @@ function InputTipField(props) {
35
35
  const [anchorEl, setAnchorEl] = react_1.default.useState();
36
36
  const [data, setData] = react_1.default.useState();
37
37
  // Destruct
38
- const { component = "input", componentProps, changeDelay = 480, onChangeDelay, fullWidth = true, slotProps = {}, ...rest } = props;
38
+ const { component = "input", componentProps, changeDelay, onChangeDelay, fullWidth = true, slotProps = {}, ...rest } = props;
39
39
  const { labelProps = {
40
40
  title: app?.get("clickForDetails"),
41
41
  sx: { color: (theme) => theme.palette.error.main, cursor: "pointer" }
@@ -18,7 +18,7 @@ const IconButton_1 = __importDefault(require("@mui/material/IconButton"));
18
18
  */
19
19
  function IntInputField(props) {
20
20
  // Destruct
21
- const { min = 0, step = 1, max = 9999999, inputStyle = { textAlign: "right" }, boxProps, buttons, endSymbol, symbol, value, changeDelay = 600, onChangeDelay, onChange, onFocus = (event) => event.currentTarget.select(), onValueChange, required, ...rest } = props;
21
+ const { min = 0, step = 1, max = 9999999, inputStyle = { textAlign: "right" }, boxProps, buttons, endSymbol, symbol, value, changeDelay = [600], onChangeDelay, onChange, onFocus = (event) => event.currentTarget.select(), onValueChange, required, ...rest } = props;
22
22
  // State
23
23
  const [localValue, setLocalValue] = react_1.default.useState();
24
24
  const setValue = (value, source, init = false) => {
@@ -57,5 +57,5 @@ function ListMultipler(props) {
57
57
  }
58
58
  const inputType = typeof ids[0] === "string" ? "text" : "number";
59
59
  // Layout
60
- return ((0, jsx_runtime_1.jsxs)(List_1.default, { ...rest, children: [name && ((0, jsx_runtime_1.jsx)("input", { type: inputType, style: { display: "none", width: 1 }, name: name, value: ids.join(","), readOnly: true })), data.map((u) => ((0, jsx_runtime_1.jsx)(ListItem_1.default, { ...listItemProps, children: (0, jsx_runtime_1.jsxs)(ListItemButton_1.default, { dense: true, onClick: () => handleToggle(u[idField]), children: [(0, jsx_runtime_1.jsx)(ListItemIcon_1.default, { children: (0, jsx_runtime_1.jsx)(Checkbox_1.default, { edge: "start", disableRipple: true, checked: ids.includes(u[idField]) }) }), (0, jsx_runtime_1.jsx)(ListItemText_1.default, { primary: GetListItemLabel(u, primaryLabel), secondary: GetListItemLabel(u, secondaryLabel), ...listItemTextProps })] }) }, `${u[idField]}`)))] }));
60
+ return ((0, jsx_runtime_1.jsxs)(List_1.default, { ...rest, children: [name && ((0, jsx_runtime_1.jsx)("input", { type: inputType, style: { display: "none" }, name: name, value: ids.join(","), readOnly: true })), data.map((u) => ((0, jsx_runtime_1.jsx)(ListItem_1.default, { ...listItemProps, children: (0, jsx_runtime_1.jsxs)(ListItemButton_1.default, { dense: true, onClick: () => handleToggle(u[idField]), children: [(0, jsx_runtime_1.jsx)(ListItemIcon_1.default, { children: (0, jsx_runtime_1.jsx)(Checkbox_1.default, { edge: "start", disableRipple: true, checked: ids.includes(u[idField]) }) }), (0, jsx_runtime_1.jsx)(ListItemText_1.default, { primary: GetListItemLabel(u, primaryLabel), secondary: GetListItemLabel(u, secondaryLabel), ...listItemTextProps })] }) }, `${u[idField]}`)))] }));
61
61
  }
@@ -40,7 +40,7 @@ function QuickList(props) {
40
40
  loadDataLocal();
41
41
  }, []);
42
42
  // Layout
43
- return ((0, jsx_runtime_1.jsxs)(FlexBox_1.VBox, { gap: gap, height: height, ...rest, children: [(0, jsx_runtime_1.jsx)(InputField_1.InputField, { label: label, changeDelay: 480, onChangeDelay: (event) => {
43
+ return ((0, jsx_runtime_1.jsxs)(FlexBox_1.VBox, { gap: gap, height: height, ...rest, children: [(0, jsx_runtime_1.jsx)(InputField_1.InputField, { label: label, onChangeDelay: (event) => {
44
44
  // Stop bubble
45
45
  event.preventDefault();
46
46
  event.stopPropagation();
@@ -152,12 +152,6 @@ function SearchBar(props) {
152
152
  let newIndex = others;
153
153
  for (let c = 0; c < others; c++) {
154
154
  const child = children[c];
155
- // Ignore it when it's input and hidden or display none
156
- if (child instanceof HTMLInputElement &&
157
- (child.type === "hidden" ||
158
- (child.parentElement == null && child.readOnly))) {
159
- continue;
160
- }
161
155
  const cachedWidth = child.getAttribute(cachedWidthName);
162
156
  let childWidth;
163
157
  if (cachedWidth) {
@@ -12,7 +12,7 @@ export type TagListProps = Omit<AutocompleteProps<string, true, false, true>, "o
12
12
  /**
13
13
  * Input props
14
14
  */
15
- inputProps?: Omit<InputFieldProps, "onChange">;
15
+ inputProps?: Omit<InputFieldProps, "onChangeDelay">;
16
16
  /**
17
17
  * Max items
18
18
  */
@@ -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)), renderTags = (value, getTagProps) => value.map((option, index) => {
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) => {
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;
@@ -54,7 +54,7 @@ function TagList(props) {
54
54
  }
55
55
  }, onClose: () => {
56
56
  setOpen(false);
57
- }, options: options, loading: loading, disableCloseOnSelect: disableCloseOnSelect, clearOnBlur: true, openOnFocus: openOnFocus, renderOption: renderOption, renderTags: renderTags, renderInput: (params) => ((0, jsx_runtime_1.jsx)(InputField_1.InputField, { label: label, changeDelay: 480, onChange: async (event) => {
57
+ }, 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
58
  // Stop bubble
59
59
  event.preventDefault();
60
60
  event.stopPropagation();
@@ -13,7 +13,7 @@ export type TagListProProps<D extends ListType2 = ListType2> = Omit<Autocomplete
13
13
  /**
14
14
  * Input props
15
15
  */
16
- inputProps?: Omit<InputFieldProps, "onChange">;
16
+ inputProps?: Omit<InputFieldProps, "onChangeDelay">;
17
17
  /**
18
18
  * Max items
19
19
  */
@@ -56,7 +56,7 @@ function TagListPro(props) {
56
56
  }
57
57
  }, onClose: () => {
58
58
  setOpen(false);
59
- }, options: options, loading: loading, disableCloseOnSelect: disableCloseOnSelect, openOnFocus: openOnFocus, renderOption: renderOption, renderValue: renderValue, renderInput: (params) => ((0, jsx_runtime_1.jsx)(InputField_1.InputField, { label: label, changeDelay: 480, onChange: async (event) => {
59
+ }, 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
60
  // Stop bubble
61
61
  event.preventDefault();
62
62
  event.stopPropagation();
@@ -77,8 +77,12 @@ function Tiplist(props) {
77
77
  }
78
78
  // Stop bubble
79
79
  event.stopPropagation();
80
+ const value = event.currentTarget.value;
81
+ if (minChars && minChars > 0 && value.length < minChars) {
82
+ return;
83
+ }
80
84
  // Call with delay
81
- delayed.call(undefined, event.currentTarget.value);
85
+ delayed.call(undefined, value);
82
86
  };
83
87
  // Directly load data
84
88
  const loadDataDirect = (keyword, id) => {
@@ -172,7 +176,7 @@ function Tiplist(props) {
172
176
  };
173
177
  }, []);
174
178
  // Layout
175
- return ((0, jsx_runtime_1.jsxs)(react_2.default.Fragment, { children: [(0, jsx_runtime_1.jsx)("input", { ref: inputRef, "data-reset": inputReset ?? true, type: idIsString ? "text" : "number", style: { display: "none", width: 1 }, name: name, value: `${inputValue ?? (state.current.idSet ? "" : localIdValue ?? "")}`, readOnly: true, onChange: inputOnChange }), (0, jsx_runtime_1.jsx)(Autocomplete_1.default, { filterOptions: (options, _state) => options, value: states.value, options: states.options, onChange: (event, value, reason, details) => {
179
+ return ((0, jsx_runtime_1.jsxs)("div", { style: { flex: 2 }, children: [(0, jsx_runtime_1.jsx)("input", { ref: inputRef, "data-reset": inputReset ?? true, type: idIsString ? "text" : "number", style: { display: "none" }, name: name, value: `${inputValue ?? (state.current.idSet ? "" : localIdValue ?? "")}`, readOnly: true, onChange: inputOnChange }), (0, jsx_runtime_1.jsx)(Autocomplete_1.default, { filterOptions: (options, _state) => options, value: states.value, options: states.options, onChange: (event, value, reason, details) => {
176
180
  // Set value
177
181
  setInputValue(value);
178
182
  // Custom
@@ -197,7 +201,7 @@ function Tiplist(props) {
197
201
  open: false,
198
202
  ...(!states.value && { options: [] })
199
203
  });
200
- }, loading: states.loading, renderInput: (params) => search ? ((0, jsx_runtime_1.jsx)(SearchField_1.SearchField, { onChange: changeHandle, ...addReadOnly(params), readOnly: readOnly, label: label, name: name + "Input", margin: inputMargin, minChars: minChars, variant: inputVariant, required: inputRequired, autoComplete: inputAutoComplete, error: inputError, helperText: inputHelperText })) : ((0, jsx_runtime_1.jsx)(InputField_1.InputField, { onChange: changeHandle, ...addReadOnly(params), label: label, name: name + "Input", margin: inputMargin, minChars: minChars, variant: inputVariant, required: inputRequired, autoComplete: inputAutoComplete, error: inputError, helperText: inputHelperText })), isOptionEqualToValue: (option, value) => option[idField] === value[idField], sx: sx, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, getOptionDisabled: (item) => {
204
+ }, loading: states.loading, renderInput: (params) => search ? ((0, jsx_runtime_1.jsx)(SearchField_1.SearchField, { onChange: changeHandle, ...addReadOnly(params), readOnly: readOnly, label: label, name: name + "Input", margin: inputMargin, variant: inputVariant, required: inputRequired, autoComplete: inputAutoComplete, error: inputError, helperText: inputHelperText })) : ((0, jsx_runtime_1.jsx)(InputField_1.InputField, { onChange: changeHandle, ...addReadOnly(params), label: label, name: name + "Input", margin: inputMargin, variant: inputVariant, required: inputRequired, autoComplete: inputAutoComplete, error: inputError, helperText: inputHelperText })), isOptionEqualToValue: (option, value) => option[idField] === value[idField], sx: sx, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, getOptionDisabled: (item) => {
201
205
  if (item[idField] === "n/a")
202
206
  return true;
203
207
  return getOptionDisabled ? getOptionDisabled(item) : false;
@@ -66,8 +66,12 @@ function TiplistPro(props) {
66
66
  }
67
67
  // Stop bubble
68
68
  event.stopPropagation();
69
+ const value = event.currentTarget.value;
70
+ if (minChars && minChars > 0 && value.length < minChars) {
71
+ return;
72
+ }
69
73
  // Call with delay
70
- delayed.call(undefined, event.currentTarget.value);
74
+ delayed.call(undefined, value);
71
75
  };
72
76
  // Directly load data
73
77
  const loadDataDirect = (keyword, id) => {
@@ -158,7 +162,7 @@ function TiplistPro(props) {
158
162
  };
159
163
  }, []);
160
164
  // Layout
161
- return ((0, jsx_runtime_1.jsxs)(react_2.default.Fragment, { children: [(0, jsx_runtime_1.jsx)("input", { ref: inputRef, "data-reset": inputReset ?? true, type: idIsString ? "text" : "number", style: { display: "none", width: 1 }, name: name, value: inputValue ?? (state.current.idSet ? "" : localIdValue ?? ""), readOnly: true, onChange: inputOnChange }), (0, jsx_runtime_1.jsx)(Autocomplete_1.default, { filterOptions: (options, _state) => options, value: states.value, options: states.options, freeSolo: true, clearOnBlur: false, onChange: (event, value, reason, details) => {
165
+ return ((0, jsx_runtime_1.jsxs)("div", { style: { flex: 2 }, children: [(0, jsx_runtime_1.jsx)("input", { ref: inputRef, "data-reset": inputReset ?? true, type: idIsString ? "text" : "number", style: { display: "none" }, name: name, value: inputValue ?? (state.current.idSet ? "" : localIdValue ?? ""), readOnly: true, onChange: inputOnChange }), (0, jsx_runtime_1.jsx)(Autocomplete_1.default, { filterOptions: (options, _state) => options, value: states.value, options: states.options, freeSolo: true, clearOnBlur: false, onChange: (event, value, reason, details) => {
162
166
  if (typeof value === "object") {
163
167
  // Set value
164
168
  setInputValue(value);
@@ -189,7 +193,7 @@ function TiplistPro(props) {
189
193
  open: false,
190
194
  ...(!states.value && { options: [] })
191
195
  });
192
- }, loading: states.loading, renderInput: (params) => ((0, jsx_runtime_1.jsx)(InputField_1.InputField, { minChars: minChars, ...inputProps, ...params, onChange: changeHandle, label: label, name: name + "Input", onBlur: (event) => {
196
+ }, loading: states.loading, renderInput: (params) => ((0, jsx_runtime_1.jsx)(InputField_1.InputField, { ...inputProps, ...params, onChange: changeHandle, label: label, name: name + "Input", onBlur: (event) => {
193
197
  if (states.value == null && onChange)
194
198
  onChange(event, event.target.value, "blur", undefined);
195
199
  }, "data-reset": inputReset })), isOptionEqualToValue: (option, value) => option.id === value.id, sx: sx, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, getOptionKey: getOptionKey, getOptionDisabled: (item) => {
@@ -118,7 +118,7 @@ export function ComboBox(props) {
118
118
  };
119
119
  }, []);
120
120
  // Layout
121
- return (_jsxs(React.Fragment, { children: [_jsx("input", { ref: inputRef, "data-reset": inputReset ?? true, type: idIsString ? "text" : "number", style: { display: "none", width: 1 }, name: name, value: getValue(stateValue), readOnly: true, onChange: inputOnChange }), _jsxs(Stack, { gap: 0.5, direction: "row", width: "100%", children: [_jsx(Autocomplete, { value: stateValue, disableCloseOnSelect: disableCloseOnSelect, getOptionLabel: getOptionLabel, isOptionEqualToValue: (option, value) => option[idField] === value[idField], onChange: (event, value, reason, details) => {
121
+ return (_jsxs("div", { style: { flex: 2 }, children: [_jsx("input", { ref: inputRef, "data-reset": inputReset ?? true, type: idIsString ? "text" : "number", style: { display: "none" }, name: name, value: getValue(stateValue), readOnly: true, onChange: inputOnChange }), _jsxs(Stack, { gap: 0.5, direction: "row", width: "100%", children: [_jsx(Autocomplete, { value: stateValue, disableCloseOnSelect: disableCloseOnSelect, getOptionLabel: getOptionLabel, isOptionEqualToValue: (option, value) => option[idField] === value[idField], onChange: (event, value, reason, details) => {
122
122
  // Set value
123
123
  setInputValue(value);
124
124
  // Custom
@@ -115,7 +115,7 @@ export function ComboBoxMultiple(props) {
115
115
  };
116
116
  }, []);
117
117
  // Layout
118
- return (_jsxs(React.Fragment, { children: [_jsx("input", { ref: inputRef, "data-reset": inputReset ?? true, type: "text", style: { display: "none", width: 1 }, name: name, value: getValue(stateValue), readOnly: true, onChange: inputOnChange }), _jsx(Autocomplete, { value: stateValue == null
118
+ return (_jsxs("div", { style: { flex: 2 }, children: [_jsx("input", { ref: inputRef, "data-reset": inputReset ?? true, type: "text", style: { display: "none" }, name: name, value: getValue(stateValue), readOnly: true, onChange: inputOnChange }), _jsx(Autocomplete, { value: stateValue == null
119
119
  ? []
120
120
  : Array.isArray(stateValue)
121
121
  ? stateValue
@@ -5,21 +5,17 @@ import { TextFieldProps } from "@mui/material/TextField";
5
5
  */
6
6
  export type InputFieldProps = TextFieldProps & {
7
7
  /**
8
- * Change delay (ms) to avoid repeatly dispatch onChange
8
+ * Change [delay (ms), Minimum characters] to avoid repeatly dispatch
9
9
  */
10
- changeDelay?: number;
10
+ changeDelay?: [number, number?];
11
11
  /**
12
- * Change delay handler, without it onChange will be applied
12
+ * Change delay handler
13
13
  */
14
14
  onChangeDelay?: React.ChangeEventHandler<HTMLTextAreaElement | HTMLInputElement>;
15
15
  /**
16
16
  * Is the field read only?
17
17
  */
18
18
  readOnly?: boolean;
19
- /**
20
- * Minimum characters to trigger the change event
21
- */
22
- minChars?: number;
23
19
  };
24
20
  /**
25
21
  * Input field
@@ -10,31 +10,29 @@ import TextField from "@mui/material/TextField";
10
10
  */
11
11
  export function InputField(props) {
12
12
  // Destruct
13
- const { InputProps = {}, inputProps = {}, slotProps, changeDelay, onChange, onChangeDelay, readOnly, size = MUGlobal.inputFieldSize, variant = MUGlobal.inputFieldVariant, minChars = 0, ...rest } = props;
13
+ const { InputProps = {}, inputProps = {}, slotProps, onChange, onChangeDelay, changeDelay = onChangeDelay ? [480] : undefined, readOnly, size = MUGlobal.inputFieldSize, variant = MUGlobal.inputFieldVariant, ...rest } = props;
14
14
  // Slot props
15
15
  const { htmlInput, input, inputLabel, ...restSlotProps } = slotProps ?? {};
16
16
  const isMounted = React.useRef(true);
17
17
  const createDelayed = () => {
18
- if (changeDelay != null && changeDelay >= 1) {
19
- const changeHandler = onChangeDelay ?? onChange;
20
- if (changeHandler)
21
- return useDelayedExecutor(changeHandler, changeDelay);
18
+ if (onChangeDelay && changeDelay && changeDelay[0] >= 1) {
19
+ return useDelayedExecutor(onChangeDelay, changeDelay[0]);
22
20
  }
23
21
  return undefined;
24
22
  };
25
23
  const delayed = createDelayed();
26
24
  const onChangeEx = (event) => {
27
- // Min characters check
28
- const len = event.target.value.length;
29
- if (len > 0 && len < minChars) {
30
- // Avoid to trigger the form change event
31
- event.stopPropagation();
32
- event.preventDefault();
33
- return;
25
+ // Change handler
26
+ onChange?.(event);
27
+ if (onChangeDelay && changeDelay && delayed) {
28
+ const [_, minChars = 0] = changeDelay;
29
+ if (minChars > 0) {
30
+ const len = event.target.value.length;
31
+ if (len < minChars)
32
+ return;
33
+ }
34
+ delayed.call(undefined, event);
34
35
  }
35
- if (onChange && (delayed == null || onChangeDelay != null))
36
- onChange(event);
37
- delayed?.call(undefined, event);
38
36
  };
39
37
  React.useEffect(() => {
40
38
  return () => {
@@ -45,7 +43,7 @@ export function InputField(props) {
45
43
  // Layout
46
44
  return (_jsx(TextField, { slotProps: {
47
45
  htmlInput: {
48
- ["data-min-chars"]: minChars,
46
+ ["data-min-chars"]: changeDelay?.[1],
49
47
  ...htmlInput,
50
48
  ...inputProps
51
49
  },
@@ -29,7 +29,7 @@ export function InputTipField(props) {
29
29
  const [anchorEl, setAnchorEl] = React.useState();
30
30
  const [data, setData] = React.useState();
31
31
  // Destruct
32
- const { component = "input", componentProps, changeDelay = 480, onChangeDelay, fullWidth = true, slotProps = {}, ...rest } = props;
32
+ const { component = "input", componentProps, changeDelay, onChangeDelay, fullWidth = true, slotProps = {}, ...rest } = props;
33
33
  const { labelProps = {
34
34
  title: app?.get("clickForDetails"),
35
35
  sx: { color: (theme) => theme.palette.error.main, cursor: "pointer" }
@@ -12,7 +12,7 @@ import IconButton from "@mui/material/IconButton";
12
12
  */
13
13
  export function IntInputField(props) {
14
14
  // Destruct
15
- const { min = 0, step = 1, max = 9999999, inputStyle = { textAlign: "right" }, boxProps, buttons, endSymbol, symbol, value, changeDelay = 600, onChangeDelay, onChange, onFocus = (event) => event.currentTarget.select(), onValueChange, required, ...rest } = props;
15
+ const { min = 0, step = 1, max = 9999999, inputStyle = { textAlign: "right" }, boxProps, buttons, endSymbol, symbol, value, changeDelay = [600], onChangeDelay, onChange, onFocus = (event) => event.currentTarget.select(), onValueChange, required, ...rest } = props;
16
16
  // State
17
17
  const [localValue, setLocalValue] = React.useState();
18
18
  const setValue = (value, source, init = false) => {
@@ -51,5 +51,5 @@ export function ListMultipler(props) {
51
51
  }
52
52
  const inputType = typeof ids[0] === "string" ? "text" : "number";
53
53
  // Layout
54
- return (_jsxs(List, { ...rest, children: [name && (_jsx("input", { type: inputType, style: { display: "none", width: 1 }, name: name, value: ids.join(","), readOnly: true })), data.map((u) => (_jsx(ListItem, { ...listItemProps, children: _jsxs(ListItemButton, { dense: true, onClick: () => handleToggle(u[idField]), children: [_jsx(ListItemIcon, { children: _jsx(Checkbox, { edge: "start", disableRipple: true, checked: ids.includes(u[idField]) }) }), _jsx(ListItemText, { primary: GetListItemLabel(u, primaryLabel), secondary: GetListItemLabel(u, secondaryLabel), ...listItemTextProps })] }) }, `${u[idField]}`)))] }));
54
+ return (_jsxs(List, { ...rest, children: [name && (_jsx("input", { type: inputType, style: { display: "none" }, name: name, value: ids.join(","), readOnly: true })), data.map((u) => (_jsx(ListItem, { ...listItemProps, children: _jsxs(ListItemButton, { dense: true, onClick: () => handleToggle(u[idField]), children: [_jsx(ListItemIcon, { children: _jsx(Checkbox, { edge: "start", disableRipple: true, checked: ids.includes(u[idField]) }) }), _jsx(ListItemText, { primary: GetListItemLabel(u, primaryLabel), secondary: GetListItemLabel(u, secondaryLabel), ...listItemTextProps })] }) }, `${u[idField]}`)))] }));
55
55
  }
@@ -34,7 +34,7 @@ export function QuickList(props) {
34
34
  loadDataLocal();
35
35
  }, []);
36
36
  // Layout
37
- return (_jsxs(VBox, { gap: gap, height: height, ...rest, children: [_jsx(InputField, { label: label, changeDelay: 480, onChangeDelay: (event) => {
37
+ return (_jsxs(VBox, { gap: gap, height: height, ...rest, children: [_jsx(InputField, { label: label, onChangeDelay: (event) => {
38
38
  // Stop bubble
39
39
  event.preventDefault();
40
40
  event.stopPropagation();
@@ -146,12 +146,6 @@ export function SearchBar(props) {
146
146
  let newIndex = others;
147
147
  for (let c = 0; c < others; c++) {
148
148
  const child = children[c];
149
- // Ignore it when it's input and hidden or display none
150
- if (child instanceof HTMLInputElement &&
151
- (child.type === "hidden" ||
152
- (child.parentElement == null && child.readOnly))) {
153
- continue;
154
- }
155
149
  const cachedWidth = child.getAttribute(cachedWidthName);
156
150
  let childWidth;
157
151
  if (cachedWidth) {
@@ -12,7 +12,7 @@ export type TagListProps = Omit<AutocompleteProps<string, true, false, true>, "o
12
12
  /**
13
13
  * Input props
14
14
  */
15
- inputProps?: Omit<InputFieldProps, "onChange">;
15
+ inputProps?: Omit<InputFieldProps, "onChangeDelay">;
16
16
  /**
17
17
  * Max items
18
18
  */
@@ -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)), renderTags = (value, getTagProps) => value.map((option, index) => {
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) => {
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;
@@ -48,7 +48,7 @@ export function TagList(props) {
48
48
  }
49
49
  }, onClose: () => {
50
50
  setOpen(false);
51
- }, options: options, loading: loading, disableCloseOnSelect: disableCloseOnSelect, clearOnBlur: true, openOnFocus: openOnFocus, renderOption: renderOption, renderTags: renderTags, renderInput: (params) => (_jsx(InputField, { label: label, changeDelay: 480, onChange: async (event) => {
51
+ }, options: options, loading: loading, disableCloseOnSelect: disableCloseOnSelect, clearOnBlur: true, openOnFocus: openOnFocus, renderOption: renderOption, renderValue: renderValue, renderInput: (params) => (_jsx(InputField, { label: label, onChangeDelay: async (event) => {
52
52
  // Stop bubble
53
53
  event.preventDefault();
54
54
  event.stopPropagation();
@@ -13,7 +13,7 @@ export type TagListProProps<D extends ListType2 = ListType2> = Omit<Autocomplete
13
13
  /**
14
14
  * Input props
15
15
  */
16
- inputProps?: Omit<InputFieldProps, "onChange">;
16
+ inputProps?: Omit<InputFieldProps, "onChangeDelay">;
17
17
  /**
18
18
  * Max items
19
19
  */
@@ -50,7 +50,7 @@ export function TagListPro(props) {
50
50
  }
51
51
  }, onClose: () => {
52
52
  setOpen(false);
53
- }, options: options, loading: loading, disableCloseOnSelect: disableCloseOnSelect, openOnFocus: openOnFocus, renderOption: renderOption, renderValue: renderValue, renderInput: (params) => (_jsx(InputField, { label: label, changeDelay: 480, onChange: async (event) => {
53
+ }, options: options, loading: loading, disableCloseOnSelect: disableCloseOnSelect, openOnFocus: openOnFocus, renderOption: renderOption, renderValue: renderValue, renderInput: (params) => (_jsx(InputField, { label: label, onChangeDelay: async (event) => {
54
54
  // Stop bubble
55
55
  event.preventDefault();
56
56
  event.stopPropagation();
@@ -71,8 +71,12 @@ export function Tiplist(props) {
71
71
  }
72
72
  // Stop bubble
73
73
  event.stopPropagation();
74
+ const value = event.currentTarget.value;
75
+ if (minChars && minChars > 0 && value.length < minChars) {
76
+ return;
77
+ }
74
78
  // Call with delay
75
- delayed.call(undefined, event.currentTarget.value);
79
+ delayed.call(undefined, value);
76
80
  };
77
81
  // Directly load data
78
82
  const loadDataDirect = (keyword, id) => {
@@ -166,7 +170,7 @@ export function Tiplist(props) {
166
170
  };
167
171
  }, []);
168
172
  // Layout
169
- return (_jsxs(React.Fragment, { children: [_jsx("input", { ref: inputRef, "data-reset": inputReset ?? true, type: idIsString ? "text" : "number", style: { display: "none", width: 1 }, name: name, value: `${inputValue ?? (state.current.idSet ? "" : localIdValue ?? "")}`, readOnly: true, onChange: inputOnChange }), _jsx(Autocomplete, { filterOptions: (options, _state) => options, value: states.value, options: states.options, onChange: (event, value, reason, details) => {
173
+ return (_jsxs("div", { style: { flex: 2 }, children: [_jsx("input", { ref: inputRef, "data-reset": inputReset ?? true, type: idIsString ? "text" : "number", style: { display: "none" }, name: name, value: `${inputValue ?? (state.current.idSet ? "" : localIdValue ?? "")}`, readOnly: true, onChange: inputOnChange }), _jsx(Autocomplete, { filterOptions: (options, _state) => options, value: states.value, options: states.options, onChange: (event, value, reason, details) => {
170
174
  // Set value
171
175
  setInputValue(value);
172
176
  // Custom
@@ -191,7 +195,7 @@ export function Tiplist(props) {
191
195
  open: false,
192
196
  ...(!states.value && { options: [] })
193
197
  });
194
- }, loading: states.loading, renderInput: (params) => search ? (_jsx(SearchField, { onChange: changeHandle, ...addReadOnly(params), readOnly: readOnly, label: label, name: name + "Input", margin: inputMargin, minChars: minChars, variant: inputVariant, required: inputRequired, autoComplete: inputAutoComplete, error: inputError, helperText: inputHelperText })) : (_jsx(InputField, { onChange: changeHandle, ...addReadOnly(params), label: label, name: name + "Input", margin: inputMargin, minChars: minChars, variant: inputVariant, required: inputRequired, autoComplete: inputAutoComplete, error: inputError, helperText: inputHelperText })), isOptionEqualToValue: (option, value) => option[idField] === value[idField], sx: sx, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, getOptionDisabled: (item) => {
198
+ }, loading: states.loading, renderInput: (params) => search ? (_jsx(SearchField, { onChange: changeHandle, ...addReadOnly(params), readOnly: readOnly, label: label, name: name + "Input", margin: inputMargin, variant: inputVariant, required: inputRequired, autoComplete: inputAutoComplete, error: inputError, helperText: inputHelperText })) : (_jsx(InputField, { onChange: changeHandle, ...addReadOnly(params), label: label, name: name + "Input", margin: inputMargin, variant: inputVariant, required: inputRequired, autoComplete: inputAutoComplete, error: inputError, helperText: inputHelperText })), isOptionEqualToValue: (option, value) => option[idField] === value[idField], sx: sx, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, getOptionDisabled: (item) => {
195
199
  if (item[idField] === "n/a")
196
200
  return true;
197
201
  return getOptionDisabled ? getOptionDisabled(item) : false;
@@ -60,8 +60,12 @@ export function TiplistPro(props) {
60
60
  }
61
61
  // Stop bubble
62
62
  event.stopPropagation();
63
+ const value = event.currentTarget.value;
64
+ if (minChars && minChars > 0 && value.length < minChars) {
65
+ return;
66
+ }
63
67
  // Call with delay
64
- delayed.call(undefined, event.currentTarget.value);
68
+ delayed.call(undefined, value);
65
69
  };
66
70
  // Directly load data
67
71
  const loadDataDirect = (keyword, id) => {
@@ -152,7 +156,7 @@ export function TiplistPro(props) {
152
156
  };
153
157
  }, []);
154
158
  // Layout
155
- return (_jsxs(React.Fragment, { children: [_jsx("input", { ref: inputRef, "data-reset": inputReset ?? true, type: idIsString ? "text" : "number", style: { display: "none", width: 1 }, name: name, value: inputValue ?? (state.current.idSet ? "" : localIdValue ?? ""), readOnly: true, onChange: inputOnChange }), _jsx(Autocomplete, { filterOptions: (options, _state) => options, value: states.value, options: states.options, freeSolo: true, clearOnBlur: false, onChange: (event, value, reason, details) => {
159
+ return (_jsxs("div", { style: { flex: 2 }, children: [_jsx("input", { ref: inputRef, "data-reset": inputReset ?? true, type: idIsString ? "text" : "number", style: { display: "none" }, name: name, value: inputValue ?? (state.current.idSet ? "" : localIdValue ?? ""), readOnly: true, onChange: inputOnChange }), _jsx(Autocomplete, { filterOptions: (options, _state) => options, value: states.value, options: states.options, freeSolo: true, clearOnBlur: false, onChange: (event, value, reason, details) => {
156
160
  if (typeof value === "object") {
157
161
  // Set value
158
162
  setInputValue(value);
@@ -183,7 +187,7 @@ export function TiplistPro(props) {
183
187
  open: false,
184
188
  ...(!states.value && { options: [] })
185
189
  });
186
- }, loading: states.loading, renderInput: (params) => (_jsx(InputField, { minChars: minChars, ...inputProps, ...params, onChange: changeHandle, label: label, name: name + "Input", onBlur: (event) => {
190
+ }, loading: states.loading, renderInput: (params) => (_jsx(InputField, { ...inputProps, ...params, onChange: changeHandle, label: label, name: name + "Input", onBlur: (event) => {
187
191
  if (states.value == null && onChange)
188
192
  onChange(event, event.target.value, "blur", undefined);
189
193
  }, "data-reset": inputReset })), isOptionEqualToValue: (option, value) => option.id === value.id, sx: sx, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, getOptionKey: getOptionKey, getOptionDisabled: (item) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.5.97",
3
+ "version": "1.5.99",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
package/src/ComboBox.tsx CHANGED
@@ -236,12 +236,12 @@ export function ComboBox<
236
236
 
237
237
  // Layout
238
238
  return (
239
- <React.Fragment>
239
+ <div style={{ flex: 2 }}>
240
240
  <input
241
241
  ref={inputRef}
242
242
  data-reset={inputReset ?? true}
243
243
  type={idIsString ? "text" : "number"}
244
- style={{ display: "none", width: 1 }}
244
+ style={{ display: "none" }}
245
245
  name={name}
246
246
  value={getValue(stateValue)}
247
247
  readOnly
@@ -311,6 +311,6 @@ export function ComboBox<
311
311
  </IconButton>
312
312
  )}
313
313
  </Stack>
314
- </React.Fragment>
314
+ </div>
315
315
  );
316
316
  }
@@ -239,12 +239,12 @@ export function ComboBoxMultiple<
239
239
 
240
240
  // Layout
241
241
  return (
242
- <React.Fragment>
242
+ <div style={{ flex: 2 }}>
243
243
  <input
244
244
  ref={inputRef}
245
245
  data-reset={inputReset ?? true}
246
246
  type="text"
247
- style={{ display: "none", width: 1 }}
247
+ style={{ display: "none" }}
248
248
  name={name}
249
249
  value={getValue(stateValue)}
250
250
  readOnly
@@ -306,6 +306,6 @@ export function ComboBoxMultiple<
306
306
  loadingText={loadingText}
307
307
  {...rest}
308
308
  />
309
- </React.Fragment>
309
+ </div>
310
310
  );
311
311
  }
@@ -8,12 +8,12 @@ import TextField, { TextFieldProps } from "@mui/material/TextField";
8
8
  */
9
9
  export type InputFieldProps = TextFieldProps & {
10
10
  /**
11
- * Change delay (ms) to avoid repeatly dispatch onChange
11
+ * Change [delay (ms), Minimum characters] to avoid repeatly dispatch
12
12
  */
13
- changeDelay?: number;
13
+ changeDelay?: [number, number?];
14
14
 
15
15
  /**
16
- * Change delay handler, without it onChange will be applied
16
+ * Change delay handler
17
17
  */
18
18
  onChangeDelay?: React.ChangeEventHandler<
19
19
  HTMLTextAreaElement | HTMLInputElement
@@ -23,11 +23,6 @@ export type InputFieldProps = TextFieldProps & {
23
23
  * Is the field read only?
24
24
  */
25
25
  readOnly?: boolean;
26
-
27
- /**
28
- * Minimum characters to trigger the change event
29
- */
30
- minChars?: number;
31
26
  };
32
27
 
33
28
  /**
@@ -41,13 +36,12 @@ export function InputField(props: InputFieldProps) {
41
36
  InputProps = {},
42
37
  inputProps = {},
43
38
  slotProps,
44
- changeDelay,
45
39
  onChange,
46
40
  onChangeDelay,
41
+ changeDelay = onChangeDelay ? [480] : undefined,
47
42
  readOnly,
48
43
  size = MUGlobal.inputFieldSize,
49
44
  variant = MUGlobal.inputFieldVariant,
50
- minChars = 0,
51
45
  ...rest
52
46
  } = props;
53
47
 
@@ -56,9 +50,8 @@ export function InputField(props: InputFieldProps) {
56
50
 
57
51
  const isMounted = React.useRef(true);
58
52
  const createDelayed = () => {
59
- if (changeDelay != null && changeDelay >= 1) {
60
- const changeHandler = onChangeDelay ?? onChange;
61
- if (changeHandler) return useDelayedExecutor(changeHandler, changeDelay);
53
+ if (onChangeDelay && changeDelay && changeDelay[0] >= 1) {
54
+ return useDelayedExecutor(onChangeDelay, changeDelay[0]);
62
55
  }
63
56
  return undefined;
64
57
  };
@@ -67,17 +60,19 @@ export function InputField(props: InputFieldProps) {
67
60
  const onChangeEx = (
68
61
  event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
69
62
  ) => {
70
- // Min characters check
71
- const len = event.target.value.length;
72
- if (len > 0 && len < minChars) {
73
- // Avoid to trigger the form change event
74
- event.stopPropagation();
75
- event.preventDefault();
76
- return;
77
- }
63
+ // Change handler
64
+ onChange?.(event);
78
65
 
79
- if (onChange && (delayed == null || onChangeDelay != null)) onChange(event);
80
- delayed?.call(undefined, event);
66
+ if (onChangeDelay && changeDelay && delayed) {
67
+ const [_, minChars = 0] = changeDelay;
68
+
69
+ if (minChars > 0) {
70
+ const len = event.target.value.length;
71
+ if (len < minChars) return;
72
+ }
73
+
74
+ delayed.call(undefined, event);
75
+ }
81
76
  };
82
77
 
83
78
  React.useEffect(() => {
@@ -92,7 +87,7 @@ export function InputField(props: InputFieldProps) {
92
87
  <TextField
93
88
  slotProps={{
94
89
  htmlInput: {
95
- ["data-min-chars"]: minChars,
90
+ ["data-min-chars"]: changeDelay?.[1],
96
91
  ...htmlInput,
97
92
  ...inputProps
98
93
  },
@@ -96,7 +96,7 @@ export function InputTipField<T extends ItemType = ItemType>(
96
96
  const {
97
97
  component = "input",
98
98
  componentProps,
99
- changeDelay = 480,
99
+ changeDelay,
100
100
  onChangeDelay,
101
101
  fullWidth = true,
102
102
  slotProps = {},
@@ -87,7 +87,7 @@ export function IntInputField(props: IntInputFieldProps) {
87
87
  endSymbol,
88
88
  symbol,
89
89
  value,
90
- changeDelay = 600,
90
+ changeDelay = [600],
91
91
  onChangeDelay,
92
92
  onChange,
93
93
  onFocus = (event) => event.currentTarget.select(),
@@ -124,7 +124,7 @@ export function ListMultipler<T extends object>(props: ListMultiplerProps<T>) {
124
124
  {name && (
125
125
  <input
126
126
  type={inputType}
127
- style={{ display: "none", width: 1 }}
127
+ style={{ display: "none" }}
128
128
  name={name}
129
129
  value={ids.join(",")}
130
130
  readOnly
package/src/QuickList.tsx CHANGED
@@ -118,11 +118,11 @@ export function QuickList<T extends ListType2 = ListType2>(
118
118
  <VBox gap={gap} height={height} {...rest}>
119
119
  <InputField
120
120
  label={label}
121
- changeDelay={480}
122
121
  onChangeDelay={(event) => {
123
122
  // Stop bubble
124
123
  event.preventDefault();
125
124
  event.stopPropagation();
125
+
126
126
  loadDataLocal(event.target.value);
127
127
  }}
128
128
  fullWidth
package/src/SearchBar.tsx CHANGED
@@ -233,16 +233,6 @@ export function SearchBar(props: SearchBarProps) {
233
233
  let newIndex: number = others;
234
234
  for (let c: number = 0; c < others; c++) {
235
235
  const child = children[c];
236
-
237
- // Ignore it when it's input and hidden or display none
238
- if (
239
- child instanceof HTMLInputElement &&
240
- (child.type === "hidden" ||
241
- (child.parentElement == null && child.readOnly))
242
- ) {
243
- continue;
244
- }
245
-
246
236
  const cachedWidth = child.getAttribute(cachedWidthName);
247
237
  let childWidth: number;
248
238
  if (cachedWidth) {
package/src/TagList.tsx CHANGED
@@ -27,7 +27,7 @@ export type TagListProps = Omit<
27
27
  /**
28
28
  * Input props
29
29
  */
30
- inputProps?: Omit<InputFieldProps, "onChange">;
30
+ inputProps?: Omit<InputFieldProps, "onChangeDelay">;
31
31
 
32
32
  /**
33
33
  * Max items
@@ -62,7 +62,7 @@ export function TagList(props: TagListProps) {
62
62
  {option}
63
63
  </li>
64
64
  ),
65
- renderTags = (value: readonly string[], getTagProps) =>
65
+ renderValue = (value: readonly string[], getTagProps) =>
66
66
  value.map((option, index) => {
67
67
  const { key, ...rest } = getTagProps({ index });
68
68
  return <Chip variant="outlined" key={key} label={option} {...rest} />;
@@ -129,12 +129,11 @@ export function TagList(props: TagListProps) {
129
129
  clearOnBlur
130
130
  openOnFocus={openOnFocus}
131
131
  renderOption={renderOption}
132
- renderTags={renderTags}
132
+ renderValue={renderValue}
133
133
  renderInput={(params) => (
134
134
  <InputField
135
135
  label={label}
136
- changeDelay={480}
137
- onChange={async (event) => {
136
+ onChangeDelay={async (event) => {
138
137
  // Stop bubble
139
138
  event.preventDefault();
140
139
  event.stopPropagation();
@@ -28,7 +28,7 @@ export type TagListProProps<D extends ListType2 = ListType2> = Omit<
28
28
  /**
29
29
  * Input props
30
30
  */
31
- inputProps?: Omit<InputFieldProps, "onChange">;
31
+ inputProps?: Omit<InputFieldProps, "onChangeDelay">;
32
32
 
33
33
  /**
34
34
  * Max items
@@ -147,8 +147,7 @@ export function TagListPro<D extends ListType2 = ListType2>(
147
147
  renderInput={(params) => (
148
148
  <InputField
149
149
  label={label}
150
- changeDelay={480}
151
- onChange={async (event) => {
150
+ onChangeDelay={async (event) => {
152
151
  // Stop bubble
153
152
  event.preventDefault();
154
153
  event.stopPropagation();
package/src/Tiplist.tsx CHANGED
@@ -177,8 +177,13 @@ export function Tiplist<
177
177
  // Stop bubble
178
178
  event.stopPropagation();
179
179
 
180
+ const value = event.currentTarget.value;
181
+ if (minChars && minChars > 0 && value.length < minChars) {
182
+ return;
183
+ }
184
+
180
185
  // Call with delay
181
- delayed.call(undefined, event.currentTarget.value);
186
+ delayed.call(undefined, value);
182
187
  };
183
188
 
184
189
  // Directly load data
@@ -285,12 +290,12 @@ export function Tiplist<
285
290
 
286
291
  // Layout
287
292
  return (
288
- <React.Fragment>
293
+ <div style={{ flex: 2 }}>
289
294
  <input
290
295
  ref={inputRef}
291
296
  data-reset={inputReset ?? true}
292
297
  type={idIsString ? "text" : "number"}
293
- style={{ display: "none", width: 1 }}
298
+ style={{ display: "none" }}
294
299
  name={name}
295
300
  value={`${
296
301
  inputValue ?? (state.current.idSet ? "" : localIdValue ?? "")
@@ -349,7 +354,6 @@ export function Tiplist<
349
354
  label={label}
350
355
  name={name + "Input"}
351
356
  margin={inputMargin}
352
- minChars={minChars}
353
357
  variant={inputVariant}
354
358
  required={inputRequired}
355
359
  autoComplete={inputAutoComplete}
@@ -363,7 +367,6 @@ export function Tiplist<
363
367
  label={label}
364
368
  name={name + "Input"}
365
369
  margin={inputMargin}
366
- minChars={minChars}
367
370
  variant={inputVariant}
368
371
  required={inputRequired}
369
372
  autoComplete={inputAutoComplete}
@@ -393,6 +396,6 @@ export function Tiplist<
393
396
  getOptionKey={getOptionKey}
394
397
  {...rest}
395
398
  />
396
- </React.Fragment>
399
+ </div>
397
400
  );
398
401
  }
@@ -194,8 +194,13 @@ export function TiplistPro<T extends ListType2 = ListType2>(
194
194
  // Stop bubble
195
195
  event.stopPropagation();
196
196
 
197
+ const value = event.currentTarget.value;
198
+ if (minChars && minChars > 0 && value.length < minChars) {
199
+ return;
200
+ }
201
+
197
202
  // Call with delay
198
- delayed.call(undefined, event.currentTarget.value);
203
+ delayed.call(undefined, value);
199
204
  };
200
205
 
201
206
  // Directly load data
@@ -299,12 +304,12 @@ export function TiplistPro<T extends ListType2 = ListType2>(
299
304
 
300
305
  // Layout
301
306
  return (
302
- <React.Fragment>
307
+ <div style={{ flex: 2 }}>
303
308
  <input
304
309
  ref={inputRef}
305
310
  data-reset={inputReset ?? true}
306
311
  type={idIsString ? "text" : "number"}
307
- style={{ display: "none", width: 1 }}
312
+ style={{ display: "none" }}
308
313
  name={name}
309
314
  value={inputValue ?? (state.current.idSet ? "" : localIdValue ?? "")}
310
315
  readOnly
@@ -363,7 +368,6 @@ export function TiplistPro<T extends ListType2 = ListType2>(
363
368
  loading={states.loading}
364
369
  renderInput={(params) => (
365
370
  <InputField
366
- minChars={minChars}
367
371
  {...inputProps}
368
372
  {...params}
369
373
  onChange={changeHandle}
@@ -394,6 +398,6 @@ export function TiplistPro<T extends ListType2 = ListType2>(
394
398
  }}
395
399
  {...rest}
396
400
  />
397
- </React.Fragment>
401
+ </div>
398
402
  );
399
403
  }