@etsoo/materialui 1.5.87 → 1.5.89

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,6 +1,11 @@
1
- import React from "react";
2
1
  import { ComboBox } from "../src";
3
- import { act, fireEvent, render, screen } from "@testing-library/react";
2
+ import {
3
+ act,
4
+ fireEvent,
5
+ render,
6
+ screen,
7
+ waitFor
8
+ } from "@testing-library/react";
4
9
 
5
10
  it("Render ComboBox", async () => {
6
11
  // Arrange
@@ -21,21 +26,15 @@ it("Render ComboBox", async () => {
21
26
  );
22
27
  });
23
28
 
24
- await vi.waitFor(
25
- async () => {
26
- await screen.findByRole("button");
27
- },
28
- {
29
- timeout: 500, // default is 1000
30
- interval: 20 // default is 50
31
- }
32
- );
29
+ await waitFor(async () => {
30
+ const button = await screen.findByRole("button");
33
31
 
34
- // Act, click the list
35
- const clicked = fireEvent.click(screen.getByRole("button"));
36
- expect(clicked).toBeTruthy();
32
+ // Act, click the list
33
+ const clicked = fireEvent.click(button);
34
+ expect(clicked).toBeTruthy();
37
35
 
38
- // Get list item
39
- const item = screen.getByText("Name 1");
40
- expect(item.nodeName).toBe("LI");
36
+ // Get list item
37
+ const item = await screen.findByText("Name 1");
38
+ expect(item.nodeName).toBe("LI");
39
+ });
41
40
  });
@@ -137,13 +137,13 @@ it("Render FieldSelect", async () => {
137
137
  );
138
138
  });
139
139
 
140
- const button = screen.getByRole("combobox");
140
+ const button = await screen.findByRole("combobox");
141
141
 
142
142
  act(() => {
143
143
  // Act, click to open the dropdown list
144
144
  vi.useFakeTimers();
145
145
  fireEvent.mouseDown(button);
146
- vi.advanceTimersByTime(100);
146
+ vi.runAllTimers();
147
147
  });
148
148
 
149
149
  const input = document.querySelector<HTMLInputElement>("input");
@@ -0,0 +1,76 @@
1
+ import { fireEvent, render, screen, waitFor } from "@testing-library/react";
2
+ import { act } from "react";
3
+ import { InputTipField } from "../src";
4
+
5
+ it("Render default InputTipField", async () => {
6
+ // Render component
7
+ act(() => {
8
+ render(
9
+ <InputTipField
10
+ name="amount"
11
+ type="number"
12
+ componentProps={{
13
+ loadData: (_value) => Promise.resolve([])
14
+ }}
15
+ slotProps={{ htmlInput: { role: "input" } }}
16
+ />
17
+ );
18
+ });
19
+
20
+ const input = screen.getByRole<HTMLInputElement>("input");
21
+ expect(input.type).toBe("number");
22
+ });
23
+
24
+ it("Render email InputTipField", async () => {
25
+ // Arrange
26
+ type T = { id: number; name: string };
27
+ const options: T[] = [
28
+ { id: 1, name: "Name 1" },
29
+ { id: 2, name: "Name 2" }
30
+ ];
31
+
32
+ const changeHandler = vi.fn();
33
+
34
+ const flag = "2 items";
35
+
36
+ // Render component
37
+ act(() => {
38
+ render(
39
+ <InputTipField<T>
40
+ component="email"
41
+ componentProps={{
42
+ loadData: (_value) => Promise.resolve([options, flag]),
43
+ itemLabel: (item) => item.name + ` (${item.id})`
44
+ }}
45
+ onChangeDelay={changeHandler}
46
+ slotProps={{ htmlInput: { role: "input" } }}
47
+ />
48
+ );
49
+ });
50
+
51
+ const input = screen.getByRole<HTMLInputElement>("input");
52
+ expect(input.type).toBe("email");
53
+
54
+ act(() => {
55
+ vi.useFakeTimers();
56
+
57
+ fireEvent.change(input, { target: { value: "info@etsoo.com" } });
58
+ expect(input.value).toBe("info@etsoo.com");
59
+
60
+ vi.runAllTimers();
61
+ expect(changeHandler).toHaveBeenCalled();
62
+
63
+ // Restore timers, otherwise 'waitFor' will fail
64
+ vi.useRealTimers();
65
+ });
66
+
67
+ await waitFor(() => {
68
+ const button = screen.getByText(flag);
69
+ expect(button.nodeName).toBe("P");
70
+
71
+ fireEvent.click(button);
72
+
73
+ const item = screen.getByText("Name 2 (2)");
74
+ expect(item.nodeName).toBe("LI");
75
+ });
76
+ });
@@ -29,7 +29,7 @@ function ComboBoxMultiple(props) {
29
29
  // Labels
30
30
  const labels = app?.getLabels("noOptions", "loading");
31
31
  // Destruct
32
- const { search = false, autoAddBlankItem = search, idField = "id", idValue, idValues, inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputReset, inputVariant, defaultValue, label, labelField = "label", loadData, onLoadData, name, inputAutoComplete = "off", options, dataReadonly = true, readOnly, onChange, openOnFocus = true, value, disableCloseOnSelect = true, renderOption = (props, option, { selected }) => ((0, jsx_runtime_1.jsxs)("li", { ...props, children: [(0, jsx_runtime_1.jsx)(Checkbox_1.default, { icon: icon, checkedIcon: checkedIcon, style: { marginRight: 8 }, checked: selected }), `${option[labelField]}`] })), getOptionLabel = (option) => `${option[labelField]}`, sx = { minWidth: "150px" }, noOptionsText = labels?.noOptions, loadingText = labels?.loading, ...rest } = props;
32
+ const { search = false, autoAddBlankItem = search, idField = "id", idValue, idValues, inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputReset, inputVariant, defaultValue, label, labelField = "label", loadData, onLoadData, name, inputAutoComplete = "off", options, dataReadonly = true, readOnly, onChange, openOnFocus = true, value, disableCloseOnSelect = true, renderOption = (props, option, { selected }) => ((0, jsx_runtime_1.jsxs)("li", { ...props, children: [(0, jsx_runtime_1.jsx)(Checkbox_1.default, { icon: icon, checkedIcon: checkedIcon, style: { marginRight: 8 }, checked: selected }), `${option[labelField]}`] })), getOptionLabel = (option) => `${option[labelField]}`, getOptionKey = (option) => `${option[idField]}`, sx = { minWidth: "150px" }, noOptionsText = labels?.noOptions, loadingText = labels?.loading, ...rest } = props;
33
33
  // Value input ref
34
34
  const inputRef = react_1.default.createRef();
35
35
  // Options state
@@ -125,7 +125,7 @@ function ComboBoxMultiple(props) {
125
125
  ? []
126
126
  : Array.isArray(stateValue)
127
127
  ? stateValue
128
- : [stateValue], disableCloseOnSelect: disableCloseOnSelect, getOptionLabel: getOptionLabel, multiple: true, isOptionEqualToValue: (option, value) => option[idField] === value[idField], onChange: (event, value, reason, details) => {
128
+ : [stateValue], disableCloseOnSelect: disableCloseOnSelect, getOptionLabel: getOptionLabel, getOptionKey: getOptionKey, multiple: true, isOptionEqualToValue: (option, value) => option[idField] === value[idField], onChange: (event, value, reason, details) => {
129
129
  // Set value
130
130
  setInputValue(value.concat());
131
131
  // Custom
@@ -16,7 +16,7 @@ function ComboBoxPro(props) {
16
16
  // Labels
17
17
  const { noOptions, loading: loadingLabel, open: openDefault } = app?.getLabels("noOptions", "loading", "open") ?? {};
18
18
  // Destruct
19
- const { noOptionsText = noOptions, loadingText = loadingLabel, openText = openDefault, options, openOnFocus = true, label, inputProps, name, value, idValue, onChange, onValueChange, ...rest } = props;
19
+ const { getOptionKey = (option) => typeof option === "string" ? option : option.id, getOptionLabel = (option) => typeof option === "object" ? shared_1.DataTypes.getListItemLabel(option) : option, noOptionsText = noOptions, loadingText = loadingLabel, openText = openDefault, options, openOnFocus = true, label, inputProps, name, value, idValue, onChange, onValueChange, ...rest } = props;
20
20
  const [open, setOpen] = react_1.default.useState(false);
21
21
  const [localOptions, setOptions] = react_1.default.useState([]);
22
22
  const [localValue, setValue] = react_1.default.useState(null);
@@ -61,7 +61,7 @@ function ComboBoxPro(props) {
61
61
  if (!localValue && localValue != value)
62
62
  onChange(event, value, "blur", undefined);
63
63
  }
64
- } })), getOptionLabel: (item) => typeof item === "object" ? shared_1.DataTypes.getListItemLabel(item) : item, isOptionEqualToValue: (option, value) => option.id === value.id, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, onChange: (event, value, reason, details) => {
64
+ } })), getOptionLabel: getOptionLabel, getOptionKey: getOptionKey, isOptionEqualToValue: (option, value) => option.id === value.id, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, onChange: (event, value, reason, details) => {
65
65
  setValue(value);
66
66
  if (onChange)
67
67
  onChange(event, value, reason, details);
@@ -1,7 +1,7 @@
1
1
  import { IdType } from "@etsoo/shared";
2
2
  import { TypographyProps } from "@mui/material/Typography";
3
3
  import React from "react";
4
- import { InputField } from "./InputField";
4
+ import { InputFieldProps } from "./InputField";
5
5
  import { EmailInput } from "./EmailInput";
6
6
  import { MobileInput } from "./MobileInput";
7
7
  import { PhoneInput } from "./PhoneInput";
@@ -9,52 +9,62 @@ type ItemType = {
9
9
  id: IdType;
10
10
  };
11
11
  declare const componentMap: {
12
- input: typeof InputField;
13
12
  email: typeof EmailInput;
14
13
  phone: typeof PhoneInput;
15
14
  mobile: typeof MobileInput;
16
15
  };
17
16
  type ComponentMap = typeof componentMap;
18
17
  type ComponentKey = keyof ComponentMap;
18
+ type ComponentProps<T extends ItemType> = {
19
+ /**
20
+ * Load data
21
+ * @param value Duplicate test value
22
+ */
23
+ loadData(value: string): Promise<[T[]?, string?]>;
24
+ /**
25
+ * Label props
26
+ */
27
+ labelProps?: Omit<TypographyProps, "onClick">;
28
+ /**
29
+ * Custom item label
30
+ * @param item List item data
31
+ * @returns Result
32
+ */
33
+ itemLabel?: (item: T) => React.ReactNode;
34
+ /**
35
+ * Custom render item
36
+ * @param item List item data
37
+ * @returns Result
38
+ */
39
+ renderItem?: (item: T) => React.ReactNode;
40
+ };
19
41
  /**
20
42
  * InputField with tips properties
21
43
  */
22
- export type InputTipFieldProps<T extends ItemType = ItemType, K extends ComponentKey = "input"> = Omit<React.ComponentProps<ComponentMap[K]>, "component"> & {
44
+ export type InputTipFieldProps<T extends ItemType = ItemType> = {
23
45
  /**
24
- * Component key
46
+ * Component properties
25
47
  */
26
- component?: K;
48
+ componentProps: ComponentProps<T>;
49
+ } & (({
27
50
  /**
28
51
  * Component properties
29
52
  */
30
- componentProps: {
31
- /**
32
- * Load data
33
- * @param value Duplicate test value
34
- */
35
- loadData(value: string): Promise<[T[]?, string?]>;
36
- /**
37
- * Label props
38
- */
39
- labelProps?: Omit<TypographyProps, "onClick">;
40
- /**
41
- * Custom item label
42
- * @param item List item data
43
- * @returns Result
44
- */
45
- itemLabel?: (item: T) => React.ReactNode;
53
+ componentProps: ComponentProps<T>;
54
+ } & {
55
+ [K in ComponentKey]: {
46
56
  /**
47
- * Custom render item
48
- * @param item List item data
49
- * @returns Result
57
+ * Component key
50
58
  */
51
- renderItem?: (item: T) => React.ReactNode;
52
- };
53
- };
59
+ component: K;
60
+ } & Omit<React.ComponentProps<ComponentMap[K]>, "component">;
61
+ }[ComponentKey]) | ({
62
+ component?: "input";
63
+ } & Omit<InputFieldProps, "component">));
54
64
  /**
55
65
  * InputField with tips
56
66
  * @param props Props
57
67
  * @returns Component
58
68
  */
59
- export declare function InputTipField<T extends ItemType = ItemType, K extends ComponentKey = "input">(props: InputTipFieldProps<T, K>): import("react/jsx-runtime").JSX.Element;
69
+ export declare function InputTipField<T extends ItemType = ItemType>(props: InputTipFieldProps<T>): import("react/jsx-runtime").JSX.Element;
60
70
  export {};
@@ -18,7 +18,6 @@ const EmailInput_1 = require("./EmailInput");
18
18
  const MobileInput_1 = require("./MobileInput");
19
19
  const PhoneInput_1 = require("./PhoneInput");
20
20
  const componentMap = {
21
- input: InputField_1.InputField,
22
21
  email: EmailInput_1.EmailInput,
23
22
  phone: PhoneInput_1.PhoneInput,
24
23
  mobile: MobileInput_1.MobileInput
@@ -42,7 +41,7 @@ function InputTipField(props) {
42
41
  sx: { color: (theme) => theme.palette.error.main, cursor: "pointer" }
43
42
  }, loadData, itemLabel = (item) => shared_1.DataTypes.getObjectItemLabel(item), renderItem = (item) => (0, jsx_runtime_1.jsx)(ListItem_1.default, { children: itemLabel(item) }, item.id) } = componentProps;
44
43
  const { input, ...slotRests } = slotProps;
45
- const Component = componentMap[component];
44
+ const Component = component === "input" ? InputField_1.InputField : componentMap[component];
46
45
  const load = (value) => {
47
46
  if (value.length < 2) {
48
47
  setTitle(undefined);
@@ -22,7 +22,7 @@ function TagListPro(props) {
22
22
  const moreLabel = more + "...";
23
23
  const getLabel = (item) => shared_1.DataTypes.getListItemLabel(item);
24
24
  // Destruct
25
- const { 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)), renderTags = (value, getTagProps) => value.map((option, index) => {
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) => {
26
26
  const { key, ...rest } = getTagProps({ index });
27
27
  return ((0, jsx_runtime_1.jsx)(Chip_1.default, { variant: "outlined", label: getLabel(option), ...rest }, key));
28
28
  }), noOptionsText = noOptions, loadingText = loadingLabel, openText = openDefault, loadData, maxItems = 16, disableCloseOnSelect = true, openOnFocus = true, label, inputProps, onChange, value, ...rest } = props;
@@ -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, renderTags: renderTags, 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, changeDelay: 480, onChange: async (event) => {
60
60
  // Stop bubble
61
61
  event.preventDefault();
62
62
  event.stopPropagation();
@@ -65,7 +65,7 @@ function TagListPro(props) {
65
65
  return (typeof item.id === "number" &&
66
66
  item.id < 0 &&
67
67
  getLabel(item) === moreLabel);
68
- }, getOptionLabel: (item) => getLabel(item), isOptionEqualToValue: (option, value) => option.id === value.id, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, value: value, onChange: (event, value, reason, details) => {
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) => {
69
69
  currentValue.current = value;
70
70
  if (onChange)
71
71
  onChange(event, value, reason, details);
@@ -23,7 +23,7 @@ function Tiplist(props) {
23
23
  // Labels
24
24
  const { noOptions, loading, more1 = "More", open: openDefault } = app?.getLabels("noOptions", "loading", "more1", "open") ?? {};
25
25
  // Destruct
26
- const { search = false, idField = "id", idValue, idIsString = false, inputAutoComplete = "off", inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputReset, inputVariant, label, loadData, defaultValue, value, maxItems = 16, width = search ? 160 : undefined, name, readOnly, onChange, onValueChange, openOnFocus = true, noOptionsText = noOptions, loadingText = loading, openText = openDefault, getOptionLabel, getOptionDisabled, sx = {}, minChars, ...rest } = props;
26
+ const { search = false, idField = "id", idValue, idIsString = false, inputAutoComplete = "off", inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputReset, inputVariant, label, loadData, defaultValue, value, maxItems = 16, width = search ? 160 : undefined, name, readOnly, onChange, onValueChange, openOnFocus = true, noOptionsText = noOptions, loadingText = loading, openText = openDefault, getOptionKey = (option) => `${option[idField]}`, getOptionLabel, getOptionDisabled, sx = {}, minChars, ...rest } = props;
27
27
  if (width && sx)
28
28
  Object.assign(sx, { width: `${width}px` });
29
29
  // Value input ref
@@ -209,5 +209,5 @@ function Tiplist(props) {
209
209
  return getOptionLabel
210
210
  ? getOptionLabel(item)
211
211
  : shared_1.DataTypes.getObjectItemLabel(item);
212
- }, ...rest })] }));
212
+ }, getOptionKey: getOptionKey, ...rest })] }));
213
213
  }
@@ -22,7 +22,7 @@ function TiplistPro(props) {
22
22
  // Labels
23
23
  const { noOptions, loading, more, open: openDefault } = app?.getLabels("noOptions", "loading", "more", "open") ?? {};
24
24
  // Destruct
25
- const { label, loadData, defaultValue, value, idValue, idIsString = false, maxItems = 16, width, name, inputOnChange, inputProps, inputReset, sx, openOnFocus = true, noOptionsText = noOptions, loadingText = loading, openText = openDefault, getOptionDisabled, getOptionLabel, onChange, onValueChange, minChars, ...rest } = props;
25
+ const { label, loadData, defaultValue, value, idValue, idIsString = false, maxItems = 16, width, name, inputOnChange, inputProps, inputReset, sx, openOnFocus = true, noOptionsText = noOptions, loadingText = loading, openText = openDefault, getOptionDisabled, getOptionLabel, getOptionKey = (option) => typeof option === "string" ? option : option.id, onChange, onValueChange, minChars, ...rest } = props;
26
26
  if (width && sx)
27
27
  Object.assign(sx, { width: `${width}px` });
28
28
  // Value input ref
@@ -192,7 +192,7 @@ function TiplistPro(props) {
192
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) => {
193
193
  if (states.value == null && onChange)
194
194
  onChange(event, event.target.value, "blur", undefined);
195
- }, "data-reset": inputReset })), isOptionEqualToValue: (option, value) => option.id === value.id, sx: sx, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, getOptionDisabled: (item) => {
195
+ }, "data-reset": inputReset })), isOptionEqualToValue: (option, value) => option.id === value.id, sx: sx, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, getOptionKey: getOptionKey, getOptionDisabled: (item) => {
196
196
  if (item.id === -1)
197
197
  return true;
198
198
  return getOptionDisabled ? getOptionDisabled(item) : false;
@@ -23,7 +23,7 @@ export function ComboBoxMultiple(props) {
23
23
  // Labels
24
24
  const labels = app?.getLabels("noOptions", "loading");
25
25
  // Destruct
26
- const { search = false, autoAddBlankItem = search, idField = "id", idValue, idValues, inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputReset, inputVariant, defaultValue, label, labelField = "label", loadData, onLoadData, name, inputAutoComplete = "off", options, dataReadonly = true, readOnly, onChange, openOnFocus = true, value, disableCloseOnSelect = true, renderOption = (props, option, { selected }) => (_jsxs("li", { ...props, children: [_jsx(Checkbox, { icon: icon, checkedIcon: checkedIcon, style: { marginRight: 8 }, checked: selected }), `${option[labelField]}`] })), getOptionLabel = (option) => `${option[labelField]}`, sx = { minWidth: "150px" }, noOptionsText = labels?.noOptions, loadingText = labels?.loading, ...rest } = props;
26
+ const { search = false, autoAddBlankItem = search, idField = "id", idValue, idValues, inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputReset, inputVariant, defaultValue, label, labelField = "label", loadData, onLoadData, name, inputAutoComplete = "off", options, dataReadonly = true, readOnly, onChange, openOnFocus = true, value, disableCloseOnSelect = true, renderOption = (props, option, { selected }) => (_jsxs("li", { ...props, children: [_jsx(Checkbox, { icon: icon, checkedIcon: checkedIcon, style: { marginRight: 8 }, checked: selected }), `${option[labelField]}`] })), getOptionLabel = (option) => `${option[labelField]}`, getOptionKey = (option) => `${option[idField]}`, sx = { minWidth: "150px" }, noOptionsText = labels?.noOptions, loadingText = labels?.loading, ...rest } = props;
27
27
  // Value input ref
28
28
  const inputRef = React.createRef();
29
29
  // Options state
@@ -119,7 +119,7 @@ export function ComboBoxMultiple(props) {
119
119
  ? []
120
120
  : Array.isArray(stateValue)
121
121
  ? stateValue
122
- : [stateValue], disableCloseOnSelect: disableCloseOnSelect, getOptionLabel: getOptionLabel, multiple: true, isOptionEqualToValue: (option, value) => option[idField] === value[idField], onChange: (event, value, reason, details) => {
122
+ : [stateValue], disableCloseOnSelect: disableCloseOnSelect, getOptionLabel: getOptionLabel, getOptionKey: getOptionKey, multiple: true, isOptionEqualToValue: (option, value) => option[idField] === value[idField], onChange: (event, value, reason, details) => {
123
123
  // Set value
124
124
  setInputValue(value.concat());
125
125
  // Custom
@@ -10,7 +10,7 @@ export function ComboBoxPro(props) {
10
10
  // Labels
11
11
  const { noOptions, loading: loadingLabel, open: openDefault } = app?.getLabels("noOptions", "loading", "open") ?? {};
12
12
  // Destruct
13
- const { noOptionsText = noOptions, loadingText = loadingLabel, openText = openDefault, options, openOnFocus = true, label, inputProps, name, value, idValue, onChange, onValueChange, ...rest } = props;
13
+ const { getOptionKey = (option) => typeof option === "string" ? option : option.id, getOptionLabel = (option) => typeof option === "object" ? DataTypes.getListItemLabel(option) : option, noOptionsText = noOptions, loadingText = loadingLabel, openText = openDefault, options, openOnFocus = true, label, inputProps, name, value, idValue, onChange, onValueChange, ...rest } = props;
14
14
  const [open, setOpen] = React.useState(false);
15
15
  const [localOptions, setOptions] = React.useState([]);
16
16
  const [localValue, setValue] = React.useState(null);
@@ -55,7 +55,7 @@ export function ComboBoxPro(props) {
55
55
  if (!localValue && localValue != value)
56
56
  onChange(event, value, "blur", undefined);
57
57
  }
58
- } })), getOptionLabel: (item) => typeof item === "object" ? DataTypes.getListItemLabel(item) : item, isOptionEqualToValue: (option, value) => option.id === value.id, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, onChange: (event, value, reason, details) => {
58
+ } })), getOptionLabel: getOptionLabel, getOptionKey: getOptionKey, isOptionEqualToValue: (option, value) => option.id === value.id, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, onChange: (event, value, reason, details) => {
59
59
  setValue(value);
60
60
  if (onChange)
61
61
  onChange(event, value, reason, details);
@@ -1,7 +1,7 @@
1
1
  import { IdType } from "@etsoo/shared";
2
2
  import { TypographyProps } from "@mui/material/Typography";
3
3
  import React from "react";
4
- import { InputField } from "./InputField";
4
+ import { InputFieldProps } from "./InputField";
5
5
  import { EmailInput } from "./EmailInput";
6
6
  import { MobileInput } from "./MobileInput";
7
7
  import { PhoneInput } from "./PhoneInput";
@@ -9,52 +9,62 @@ type ItemType = {
9
9
  id: IdType;
10
10
  };
11
11
  declare const componentMap: {
12
- input: typeof InputField;
13
12
  email: typeof EmailInput;
14
13
  phone: typeof PhoneInput;
15
14
  mobile: typeof MobileInput;
16
15
  };
17
16
  type ComponentMap = typeof componentMap;
18
17
  type ComponentKey = keyof ComponentMap;
18
+ type ComponentProps<T extends ItemType> = {
19
+ /**
20
+ * Load data
21
+ * @param value Duplicate test value
22
+ */
23
+ loadData(value: string): Promise<[T[]?, string?]>;
24
+ /**
25
+ * Label props
26
+ */
27
+ labelProps?: Omit<TypographyProps, "onClick">;
28
+ /**
29
+ * Custom item label
30
+ * @param item List item data
31
+ * @returns Result
32
+ */
33
+ itemLabel?: (item: T) => React.ReactNode;
34
+ /**
35
+ * Custom render item
36
+ * @param item List item data
37
+ * @returns Result
38
+ */
39
+ renderItem?: (item: T) => React.ReactNode;
40
+ };
19
41
  /**
20
42
  * InputField with tips properties
21
43
  */
22
- export type InputTipFieldProps<T extends ItemType = ItemType, K extends ComponentKey = "input"> = Omit<React.ComponentProps<ComponentMap[K]>, "component"> & {
44
+ export type InputTipFieldProps<T extends ItemType = ItemType> = {
23
45
  /**
24
- * Component key
46
+ * Component properties
25
47
  */
26
- component?: K;
48
+ componentProps: ComponentProps<T>;
49
+ } & (({
27
50
  /**
28
51
  * Component properties
29
52
  */
30
- componentProps: {
31
- /**
32
- * Load data
33
- * @param value Duplicate test value
34
- */
35
- loadData(value: string): Promise<[T[]?, string?]>;
36
- /**
37
- * Label props
38
- */
39
- labelProps?: Omit<TypographyProps, "onClick">;
40
- /**
41
- * Custom item label
42
- * @param item List item data
43
- * @returns Result
44
- */
45
- itemLabel?: (item: T) => React.ReactNode;
53
+ componentProps: ComponentProps<T>;
54
+ } & {
55
+ [K in ComponentKey]: {
46
56
  /**
47
- * Custom render item
48
- * @param item List item data
49
- * @returns Result
57
+ * Component key
50
58
  */
51
- renderItem?: (item: T) => React.ReactNode;
52
- };
53
- };
59
+ component: K;
60
+ } & Omit<React.ComponentProps<ComponentMap[K]>, "component">;
61
+ }[ComponentKey]) | ({
62
+ component?: "input";
63
+ } & Omit<InputFieldProps, "component">));
54
64
  /**
55
65
  * InputField with tips
56
66
  * @param props Props
57
67
  * @returns Component
58
68
  */
59
- export declare function InputTipField<T extends ItemType = ItemType, K extends ComponentKey = "input">(props: InputTipFieldProps<T, K>): import("react/jsx-runtime").JSX.Element;
69
+ export declare function InputTipField<T extends ItemType = ItemType>(props: InputTipFieldProps<T>): import("react/jsx-runtime").JSX.Element;
60
70
  export {};
@@ -12,7 +12,6 @@ import { EmailInput } from "./EmailInput";
12
12
  import { MobileInput } from "./MobileInput";
13
13
  import { PhoneInput } from "./PhoneInput";
14
14
  const componentMap = {
15
- input: InputField,
16
15
  email: EmailInput,
17
16
  phone: PhoneInput,
18
17
  mobile: MobileInput
@@ -36,7 +35,7 @@ export function InputTipField(props) {
36
35
  sx: { color: (theme) => theme.palette.error.main, cursor: "pointer" }
37
36
  }, loadData, itemLabel = (item) => DataTypes.getObjectItemLabel(item), renderItem = (item) => _jsx(ListItem, { children: itemLabel(item) }, item.id) } = componentProps;
38
37
  const { input, ...slotRests } = slotProps;
39
- const Component = componentMap[component];
38
+ const Component = component === "input" ? InputField : componentMap[component];
40
39
  const load = (value) => {
41
40
  if (value.length < 2) {
42
41
  setTitle(undefined);
@@ -16,7 +16,7 @@ export function TagListPro(props) {
16
16
  const moreLabel = more + "...";
17
17
  const getLabel = (item) => DataTypes.getListItemLabel(item);
18
18
  // Destruct
19
- const { 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)), renderTags = (value, getTagProps) => value.map((option, index) => {
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) => {
20
20
  const { key, ...rest } = getTagProps({ index });
21
21
  return (_jsx(Chip, { variant: "outlined", label: getLabel(option), ...rest }, key));
22
22
  }), noOptionsText = noOptions, loadingText = loadingLabel, openText = openDefault, loadData, maxItems = 16, disableCloseOnSelect = true, openOnFocus = true, label, inputProps, onChange, value, ...rest } = props;
@@ -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, renderTags: renderTags, 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, changeDelay: 480, onChange: async (event) => {
54
54
  // Stop bubble
55
55
  event.preventDefault();
56
56
  event.stopPropagation();
@@ -59,7 +59,7 @@ export function TagListPro(props) {
59
59
  return (typeof item.id === "number" &&
60
60
  item.id < 0 &&
61
61
  getLabel(item) === moreLabel);
62
- }, getOptionLabel: (item) => getLabel(item), isOptionEqualToValue: (option, value) => option.id === value.id, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, value: value, onChange: (event, value, reason, details) => {
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) => {
63
63
  currentValue.current = value;
64
64
  if (onChange)
65
65
  onChange(event, value, reason, details);
@@ -17,7 +17,7 @@ export function Tiplist(props) {
17
17
  // Labels
18
18
  const { noOptions, loading, more1 = "More", open: openDefault } = app?.getLabels("noOptions", "loading", "more1", "open") ?? {};
19
19
  // Destruct
20
- const { search = false, idField = "id", idValue, idIsString = false, inputAutoComplete = "off", inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputReset, inputVariant, label, loadData, defaultValue, value, maxItems = 16, width = search ? 160 : undefined, name, readOnly, onChange, onValueChange, openOnFocus = true, noOptionsText = noOptions, loadingText = loading, openText = openDefault, getOptionLabel, getOptionDisabled, sx = {}, minChars, ...rest } = props;
20
+ const { search = false, idField = "id", idValue, idIsString = false, inputAutoComplete = "off", inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputReset, inputVariant, label, loadData, defaultValue, value, maxItems = 16, width = search ? 160 : undefined, name, readOnly, onChange, onValueChange, openOnFocus = true, noOptionsText = noOptions, loadingText = loading, openText = openDefault, getOptionKey = (option) => `${option[idField]}`, getOptionLabel, getOptionDisabled, sx = {}, minChars, ...rest } = props;
21
21
  if (width && sx)
22
22
  Object.assign(sx, { width: `${width}px` });
23
23
  // Value input ref
@@ -203,5 +203,5 @@ export function Tiplist(props) {
203
203
  return getOptionLabel
204
204
  ? getOptionLabel(item)
205
205
  : DataTypes.getObjectItemLabel(item);
206
- }, ...rest })] }));
206
+ }, getOptionKey: getOptionKey, ...rest })] }));
207
207
  }
@@ -16,7 +16,7 @@ export function TiplistPro(props) {
16
16
  // Labels
17
17
  const { noOptions, loading, more, open: openDefault } = app?.getLabels("noOptions", "loading", "more", "open") ?? {};
18
18
  // Destruct
19
- const { label, loadData, defaultValue, value, idValue, idIsString = false, maxItems = 16, width, name, inputOnChange, inputProps, inputReset, sx, openOnFocus = true, noOptionsText = noOptions, loadingText = loading, openText = openDefault, getOptionDisabled, getOptionLabel, onChange, onValueChange, minChars, ...rest } = props;
19
+ const { label, loadData, defaultValue, value, idValue, idIsString = false, maxItems = 16, width, name, inputOnChange, inputProps, inputReset, sx, openOnFocus = true, noOptionsText = noOptions, loadingText = loading, openText = openDefault, getOptionDisabled, getOptionLabel, getOptionKey = (option) => typeof option === "string" ? option : option.id, onChange, onValueChange, minChars, ...rest } = props;
20
20
  if (width && sx)
21
21
  Object.assign(sx, { width: `${width}px` });
22
22
  // Value input ref
@@ -186,7 +186,7 @@ export function TiplistPro(props) {
186
186
  }, loading: states.loading, renderInput: (params) => (_jsx(InputField, { minChars: minChars, ...inputProps, ...params, onChange: changeHandle, label: label, name: name + "Input", onBlur: (event) => {
187
187
  if (states.value == null && onChange)
188
188
  onChange(event, event.target.value, "blur", undefined);
189
- }, "data-reset": inputReset })), isOptionEqualToValue: (option, value) => option.id === value.id, sx: sx, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, getOptionDisabled: (item) => {
189
+ }, "data-reset": inputReset })), isOptionEqualToValue: (option, value) => option.id === value.id, sx: sx, noOptionsText: noOptionsText, loadingText: loadingText, openText: openText, getOptionKey: getOptionKey, getOptionDisabled: (item) => {
190
190
  if (item.id === -1)
191
191
  return true;
192
192
  return getOptionDisabled ? getOptionDisabled(item) : false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.5.87",
3
+ "version": "1.5.89",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -43,10 +43,10 @@
43
43
  "@etsoo/appscript": "^1.6.48",
44
44
  "@etsoo/notificationbase": "^1.1.66",
45
45
  "@etsoo/react": "^1.8.63",
46
- "@etsoo/shared": "^1.2.79",
46
+ "@etsoo/shared": "^1.2.80",
47
47
  "@mui/icons-material": "^7.3.5",
48
48
  "@mui/material": "^7.3.5",
49
- "@mui/x-data-grid": "^8.18.0",
49
+ "@mui/x-data-grid": "^8.19.0",
50
50
  "chart.js": "^4.5.1",
51
51
  "chartjs-plugin-datalabels": "^2.2.0",
52
52
  "dompurify": "^3.3.0",
@@ -76,13 +76,13 @@
76
76
  "@testing-library/react": "^16.3.0",
77
77
  "@types/pica": "^9.0.5",
78
78
  "@types/pulltorefreshjs": "^0.1.7",
79
- "@types/react": "^19.2.5",
79
+ "@types/react": "^19.2.7",
80
80
  "@types/react-avatar-editor": "^13.0.4",
81
81
  "@types/react-dom": "^19.2.3",
82
82
  "@types/react-input-mask": "^3.0.6",
83
83
  "@vitejs/plugin-react": "^5.1.1",
84
84
  "jsdom": "^27.2.0",
85
85
  "typescript": "^5.9.3",
86
- "vitest": "^4.0.9"
86
+ "vitest": "^4.0.14"
87
87
  }
88
88
  }
@@ -122,6 +122,7 @@ export function ComboBoxMultiple<
122
122
  </li>
123
123
  ),
124
124
  getOptionLabel = (option: T) => `${option[labelField]}`,
125
+ getOptionKey = (option: T) => `${option[idField]}`,
125
126
  sx = { minWidth: "150px" },
126
127
  noOptionsText = labels?.noOptions,
127
128
  loadingText = labels?.loading,
@@ -260,6 +261,7 @@ export function ComboBoxMultiple<
260
261
  }
261
262
  disableCloseOnSelect={disableCloseOnSelect}
262
263
  getOptionLabel={getOptionLabel}
264
+ getOptionKey={getOptionKey}
263
265
  multiple
264
266
  isOptionEqualToValue={(option: T, value: T) =>
265
267
  option[idField] === value[idField]
@@ -55,6 +55,10 @@ export function ComboBoxPro<D extends ListType2 = ListType2>(
55
55
 
56
56
  // Destruct
57
57
  const {
58
+ getOptionKey = (option) =>
59
+ typeof option === "string" ? option : option.id,
60
+ getOptionLabel = (option) =>
61
+ typeof option === "object" ? DataTypes.getListItemLabel(option) : option,
58
62
  noOptionsText = noOptions,
59
63
  loadingText = loadingLabel,
60
64
  openText = openDefault,
@@ -132,9 +136,8 @@ export function ComboBoxPro<D extends ListType2 = ListType2>(
132
136
  }}
133
137
  />
134
138
  )}
135
- getOptionLabel={(item) =>
136
- typeof item === "object" ? DataTypes.getListItemLabel(item) : item
137
- }
139
+ getOptionLabel={getOptionLabel}
140
+ getOptionKey={getOptionKey}
138
141
  isOptionEqualToValue={(option, value) => option.id === value.id}
139
142
  noOptionsText={noOptionsText}
140
143
  loadingText={loadingText}
@@ -1,7 +1,7 @@
1
1
  import { DataTypes, IdType } from "@etsoo/shared";
2
2
  import Typography, { TypographyProps } from "@mui/material/Typography";
3
3
  import React from "react";
4
- import { InputField } from "./InputField";
4
+ import { InputField, InputFieldProps } from "./InputField";
5
5
  import { useAppContext } from "./app/ReactApp";
6
6
  import ListItem from "@mui/material/ListItem";
7
7
  import Popover from "@mui/material/Popover";
@@ -16,7 +16,6 @@ type ItemType = {
16
16
  };
17
17
 
18
18
  const componentMap = {
19
- input: InputField,
20
19
  email: EmailInput,
21
20
  phone: PhoneInput,
22
21
  mobile: MobileInput
@@ -25,58 +24,66 @@ const componentMap = {
25
24
  type ComponentMap = typeof componentMap;
26
25
  type ComponentKey = keyof ComponentMap;
27
26
 
28
- /**
29
- * InputField with tips properties
30
- */
31
- export type InputTipFieldProps<
32
- T extends ItemType = ItemType,
33
- K extends ComponentKey = "input"
34
- > = Omit<React.ComponentProps<ComponentMap[K]>, "component"> & {
27
+ type ComponentProps<T extends ItemType> = {
35
28
  /**
36
- * Component key
29
+ * Load data
30
+ * @param value Duplicate test value
37
31
  */
38
- component?: K;
32
+ loadData(value: string): Promise<[T[]?, string?]>;
39
33
 
40
34
  /**
41
- * Component properties
35
+ * Label props
42
36
  */
43
- componentProps: {
44
- /**
45
- * Load data
46
- * @param value Duplicate test value
47
- */
48
- loadData(value: string): Promise<[T[]?, string?]>;
49
-
50
- /**
51
- * Label props
52
- */
53
- labelProps?: Omit<TypographyProps, "onClick">;
54
-
55
- /**
56
- * Custom item label
57
- * @param item List item data
58
- * @returns Result
59
- */
60
- itemLabel?: (item: T) => React.ReactNode;
61
-
62
- /**
63
- * Custom render item
64
- * @param item List item data
65
- * @returns Result
66
- */
67
- renderItem?: (item: T) => React.ReactNode;
68
- };
37
+ labelProps?: Omit<TypographyProps, "onClick">;
38
+
39
+ /**
40
+ * Custom item label
41
+ * @param item List item data
42
+ * @returns Result
43
+ */
44
+ itemLabel?: (item: T) => React.ReactNode;
45
+
46
+ /**
47
+ * Custom render item
48
+ * @param item List item data
49
+ * @returns Result
50
+ */
51
+ renderItem?: (item: T) => React.ReactNode;
69
52
  };
70
53
 
54
+ /**
55
+ * InputField with tips properties
56
+ */
57
+ export type InputTipFieldProps<T extends ItemType = ItemType> = {
58
+ /**
59
+ * Component properties
60
+ */
61
+ componentProps: ComponentProps<T>;
62
+ } & (
63
+ | ({
64
+ /**
65
+ * Component properties
66
+ */
67
+ componentProps: ComponentProps<T>;
68
+ } & {
69
+ [K in ComponentKey]: {
70
+ /**
71
+ * Component key
72
+ */
73
+ component: K;
74
+ } & Omit<React.ComponentProps<ComponentMap[K]>, "component">;
75
+ }[ComponentKey])
76
+ | ({ component?: "input" } & Omit<InputFieldProps, "component">)
77
+ );
78
+
71
79
  /**
72
80
  * InputField with tips
73
81
  * @param props Props
74
82
  * @returns Component
75
83
  */
76
- export function InputTipField<
77
- T extends ItemType = ItemType,
78
- K extends ComponentKey = "input"
79
- >(props: InputTipFieldProps<T, K>) {
84
+ export function InputTipField<T extends ItemType = ItemType>(
85
+ props: InputTipFieldProps<T>
86
+ ) {
80
87
  // Global app
81
88
  const app = useAppContext();
82
89
 
@@ -108,7 +115,8 @@ export function InputTipField<
108
115
 
109
116
  const { input, ...slotRests } = slotProps;
110
117
 
111
- const Component = componentMap[component];
118
+ const Component =
119
+ component === "input" ? InputField : componentMap[component];
112
120
 
113
121
  const load = (value: string) => {
114
122
  if (value.length < 2) {
@@ -160,7 +168,7 @@ export function InputTipField<
160
168
  },
161
169
  ...slotRests
162
170
  }}
163
- {...(rest as any)}
171
+ {...rest}
164
172
  />
165
173
  </React.Fragment>
166
174
  );
@@ -56,6 +56,8 @@ export function TagListPro<D extends ListType2 = ListType2>(
56
56
 
57
57
  // Destruct
58
58
  const {
59
+ getOptionKey = (option) =>
60
+ typeof option === "string" ? option : option.id,
59
61
  renderOption = ({ key, ...props }, option, { selected }) => (
60
62
  <li key={key} {...props}>
61
63
  <>
@@ -69,7 +71,7 @@ export function TagListPro<D extends ListType2 = ListType2>(
69
71
  </>
70
72
  </li>
71
73
  ),
72
- renderTags = (value: readonly D[], getTagProps) =>
74
+ renderValue = (value: readonly D[], getTagProps) =>
73
75
  value.map((option, index) => {
74
76
  const { key, ...rest } = getTagProps({ index });
75
77
  return (
@@ -141,7 +143,7 @@ export function TagListPro<D extends ListType2 = ListType2>(
141
143
  disableCloseOnSelect={disableCloseOnSelect}
142
144
  openOnFocus={openOnFocus}
143
145
  renderOption={renderOption}
144
- renderTags={renderTags}
146
+ renderValue={renderValue}
145
147
  renderInput={(params) => (
146
148
  <InputField
147
149
  label={label}
@@ -165,6 +167,7 @@ export function TagListPro<D extends ListType2 = ListType2>(
165
167
  );
166
168
  }}
167
169
  getOptionLabel={(item) => getLabel(item)}
170
+ getOptionKey={getOptionKey}
168
171
  isOptionEqualToValue={(option, value) => option.id === value.id}
169
172
  noOptionsText={noOptionsText}
170
173
  loadingText={loadingText}
package/src/Tiplist.tsx CHANGED
@@ -97,6 +97,7 @@ export function Tiplist<
97
97
  noOptionsText = noOptions,
98
98
  loadingText = loading,
99
99
  openText = openDefault,
100
+ getOptionKey = (option) => `${option[idField]}`,
100
101
  getOptionLabel,
101
102
  getOptionDisabled,
102
103
  sx = {},
@@ -389,6 +390,7 @@ export function Tiplist<
389
390
  ? getOptionLabel(item)
390
391
  : DataTypes.getObjectItemLabel(item);
391
392
  }}
393
+ getOptionKey={getOptionKey}
392
394
  {...rest}
393
395
  />
394
396
  </div>
@@ -127,6 +127,8 @@ export function TiplistPro<T extends ListType2 = ListType2>(
127
127
  openText = openDefault,
128
128
  getOptionDisabled,
129
129
  getOptionLabel,
130
+ getOptionKey = (option) =>
131
+ typeof option === "string" ? option : option.id,
130
132
  onChange,
131
133
  onValueChange,
132
134
  minChars,
@@ -379,6 +381,7 @@ export function TiplistPro<T extends ListType2 = ListType2>(
379
381
  noOptionsText={noOptionsText}
380
382
  loadingText={loadingText}
381
383
  openText={openText}
384
+ getOptionKey={getOptionKey}
382
385
  getOptionDisabled={(item) => {
383
386
  if (item.id === -1) return true;
384
387
  return getOptionDisabled ? getOptionDisabled(item) : false;