@etsoo/materialui 1.0.83 → 1.0.84

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.
@@ -4,7 +4,7 @@ import { ChangeEventHandler } from 'react';
4
4
  /**
5
5
  * Autocomplete extended props
6
6
  */
7
- export type AutocompleteExtendedProps<T extends object, D extends DataTypes.Keys<T>> = Omit<AutocompleteProps<T, undefined, false, false>, 'renderInput' | 'options' | 'multiple'> & {
7
+ export type AutocompleteExtendedProps<T extends object, D extends DataTypes.Keys<T>, M extends boolean | undefined = boolean | undefined> = Omit<AutocompleteProps<T, M, false, false>, 'renderInput' | 'options' | 'multiple'> & {
8
8
  /**
9
9
  * Id field
10
10
  */
package/lib/ComboBox.d.ts CHANGED
@@ -21,6 +21,10 @@ export type ComboBoxProps<T extends object, D extends DataTypes.Keys<T>, L exten
21
21
  * Load data callback
22
22
  */
23
23
  loadData?: () => PromiseLike<T[] | null | undefined>;
24
+ /**
25
+ * Multiple
26
+ */
27
+ multiple?: boolean;
24
28
  /**
25
29
  * On load data handler
26
30
  */
@@ -29,6 +33,10 @@ export type ComboBoxProps<T extends object, D extends DataTypes.Keys<T>, L exten
29
33
  * Array of options.
30
34
  */
31
35
  options?: ReadonlyArray<T>;
36
+ /**
37
+ * Id values
38
+ */
39
+ idValues?: T[D][];
32
40
  };
33
41
  /**
34
42
  * ComboBox
package/lib/ComboBox.js CHANGED
@@ -12,7 +12,7 @@ import { ReactUtils } from '@etsoo/react';
12
12
  */
13
13
  export function ComboBox(props) {
14
14
  // Destruct
15
- const { search = false, autoAddBlankItem = search, idField = 'id', idValue, inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputVariant, defaultValue, label, labelField = 'label', loadData, onLoadData, name, inputAutoComplete = 'new-password', // disable autocomplete and autofill, 'off' does not work
15
+ const { search = false, autoAddBlankItem = search, idField = 'id', idValue, idValues, inputError, inputHelperText, inputMargin, inputOnChange, inputRequired, inputVariant, defaultValue, label, labelField = 'label', loadData, multiple = false, onLoadData, name, inputAutoComplete = 'new-password', // disable autocomplete and autofill, 'off' does not work
16
16
  options, dataReadonly = true, readOnly, onChange, openOnFocus = true, value, getOptionLabel = (option) => `${option[labelField]}`, sx = { minWidth: '150px' }, ...rest } = props;
17
17
  // Value input ref
18
18
  const inputRef = React.createRef();
@@ -27,17 +27,14 @@ export function ComboBox(props) {
27
27
  setOptions(options);
28
28
  }, [options, propertyWay]);
29
29
  // Local default value
30
- let localValue = idValue != null
30
+ const localValue = React.useMemo(() => idValue != null
31
31
  ? localOptions.find((o) => o[idField] === idValue)
32
- : defaultValue !== null && defaultValue !== void 0 ? defaultValue : value;
33
- if (localValue === undefined)
34
- localValue = null;
32
+ : idValues != null
33
+ ? localOptions.filter((o) => idValues === null || idValues === void 0 ? void 0 : idValues.includes(o[idField]))
34
+ : defaultValue !== null && defaultValue !== void 0 ? defaultValue : value, [idValue, idValues, defaultValue, value]);
35
35
  // State
36
36
  // null for controlled
37
37
  const [stateValue, setStateValue] = React.useState(null);
38
- // Current id value
39
- // One time calculation for input's default value (uncontrolled)
40
- const localIdValue = stateValue && stateValue[idField];
41
38
  React.useEffect(() => {
42
39
  if (localValue != null)
43
40
  setStateValue(localValue);
@@ -62,6 +59,13 @@ export function ComboBox(props) {
62
59
  Object.assign(params.inputProps, { autoComplete: inputAutoComplete });
63
60
  return params;
64
61
  };
62
+ const getValue = (value) => {
63
+ if (value == null)
64
+ return '';
65
+ if (Array.isArray(value))
66
+ return value.map((item) => item[idField]).join(',');
67
+ return `${value[idField]}`;
68
+ };
65
69
  const setInputValue = (value) => {
66
70
  // Set state
67
71
  setStateValue(value);
@@ -69,7 +73,7 @@ export function ComboBox(props) {
69
73
  const input = inputRef.current;
70
74
  if (input) {
71
75
  // Update value
72
- const newValue = value != null ? `${value[idField]}` : '';
76
+ const newValue = getValue(value);
73
77
  if (newValue !== input.value) {
74
78
  // Different value, trigger change event
75
79
  ReactUtils.triggerChange(input, newValue, false);
@@ -97,8 +101,8 @@ export function ComboBox(props) {
97
101
  }, []);
98
102
  // Layout
99
103
  return (React.createElement("div", null,
100
- React.createElement("input", { ref: inputRef, "data-reset": "true", type: "text", style: { display: 'none' }, name: name, value: `${localIdValue !== null && localIdValue !== void 0 ? localIdValue : ''}`, readOnly: true, onChange: inputOnChange }),
101
- React.createElement(Autocomplete, { value: stateValue, getOptionLabel: getOptionLabel, isOptionEqualToValue: (option, value) => option[idField] === value[idField], onChange: (event, value, reason, details) => {
104
+ React.createElement("input", { ref: inputRef, "data-reset": "true", type: "text", style: { display: 'none' }, name: name, value: getValue(stateValue), readOnly: true, onChange: inputOnChange }),
105
+ React.createElement(Autocomplete, { value: stateValue, multiple: multiple, getOptionLabel: getOptionLabel, isOptionEqualToValue: (option, value) => option[idField] === value[idField], onChange: (event, value, reason, details) => {
102
106
  // Set value
103
107
  setInputValue(value);
104
108
  // Custom
package/lib/Tiplist.d.ts CHANGED
@@ -4,7 +4,7 @@ import { AutocompleteExtendedProps } from './AutocompleteExtendedProps';
4
4
  /**
5
5
  * Tiplist props
6
6
  */
7
- export type TiplistProps<T extends object, D extends DataTypes.Keys<T>> = Omit<AutocompleteExtendedProps<T, D>, 'open'> & {
7
+ export type TiplistProps<T extends object, D extends DataTypes.Keys<T>> = Omit<AutocompleteExtendedProps<T, D, undefined>, 'open' | 'multiple'> & {
8
8
  /**
9
9
  * Load data callback
10
10
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.0.83",
3
+ "version": "1.0.84",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -7,9 +7,10 @@ import { ChangeEventHandler } from 'react';
7
7
  */
8
8
  export type AutocompleteExtendedProps<
9
9
  T extends object,
10
- D extends DataTypes.Keys<T>
10
+ D extends DataTypes.Keys<T>,
11
+ M extends boolean | undefined = boolean | undefined
11
12
  > = Omit<
12
- AutocompleteProps<T, undefined, false, false>,
13
+ AutocompleteProps<T, M, false, false>,
13
14
  'renderInput' | 'options' | 'multiple'
14
15
  > & {
15
16
  /**
package/src/ComboBox.tsx CHANGED
@@ -41,6 +41,11 @@ export type ComboBoxProps<
41
41
  */
42
42
  loadData?: () => PromiseLike<T[] | null | undefined>;
43
43
 
44
+ /**
45
+ * Multiple
46
+ */
47
+ multiple?: boolean;
48
+
44
49
  /**
45
50
  * On load data handler
46
51
  */
@@ -50,6 +55,11 @@ export type ComboBoxProps<
50
55
  * Array of options.
51
56
  */
52
57
  options?: ReadonlyArray<T>;
58
+
59
+ /**
60
+ * Id values
61
+ */
62
+ idValues?: T[D][];
53
63
  };
54
64
 
55
65
  /**
@@ -68,6 +78,7 @@ export function ComboBox<
68
78
  autoAddBlankItem = search,
69
79
  idField = 'id' as D,
70
80
  idValue,
81
+ idValues,
71
82
  inputError,
72
83
  inputHelperText,
73
84
  inputMargin,
@@ -78,6 +89,7 @@ export function ComboBox<
78
89
  label,
79
90
  labelField = 'label' as L,
80
91
  loadData,
92
+ multiple = false,
81
93
  onLoadData,
82
94
  name,
83
95
  inputAutoComplete = 'new-password', // disable autocomplete and autofill, 'off' does not work
@@ -107,20 +119,19 @@ export function ComboBox<
107
119
  }, [options, propertyWay]);
108
120
 
109
121
  // Local default value
110
- let localValue =
111
- idValue != null
112
- ? localOptions.find((o) => o[idField] === idValue)
113
- : defaultValue ?? value;
114
-
115
- if (localValue === undefined) localValue = null;
122
+ const localValue = React.useMemo(
123
+ () =>
124
+ idValue != null
125
+ ? localOptions.find((o) => o[idField] === idValue)
126
+ : idValues != null
127
+ ? localOptions.filter((o) => idValues?.includes(o[idField]))
128
+ : defaultValue ?? value,
129
+ [idValue, idValues, defaultValue, value]
130
+ );
116
131
 
117
132
  // State
118
133
  // null for controlled
119
- const [stateValue, setStateValue] = React.useState<T | null>(null);
120
-
121
- // Current id value
122
- // One time calculation for input's default value (uncontrolled)
123
- const localIdValue = stateValue && stateValue[idField];
134
+ const [stateValue, setStateValue] = React.useState<T | T[] | null>(null);
124
135
 
125
136
  React.useEffect(() => {
126
137
  if (localValue != null) setStateValue(localValue);
@@ -151,7 +162,14 @@ export function ComboBox<
151
162
  return params;
152
163
  };
153
164
 
154
- const setInputValue = (value: T | null) => {
165
+ const getValue = (value: T | T[] | null): string => {
166
+ if (value == null) return '';
167
+ if (Array.isArray(value))
168
+ return value.map((item) => item[idField]).join(',');
169
+ return `${value[idField]}`;
170
+ };
171
+
172
+ const setInputValue = (value: T | T[] | null) => {
155
173
  // Set state
156
174
  setStateValue(value);
157
175
 
@@ -159,7 +177,7 @@ export function ComboBox<
159
177
  const input = inputRef.current;
160
178
  if (input) {
161
179
  // Update value
162
- const newValue = value != null ? `${value[idField]}` : '';
180
+ const newValue = getValue(value);
163
181
 
164
182
  if (newValue !== input.value) {
165
183
  // Different value, trigger change event
@@ -195,13 +213,14 @@ export function ComboBox<
195
213
  type="text"
196
214
  style={{ display: 'none' }}
197
215
  name={name}
198
- value={`${localIdValue ?? ''}`}
216
+ value={getValue(stateValue)}
199
217
  readOnly
200
218
  onChange={inputOnChange}
201
219
  />
202
220
  {/* Previous input will reset first with "disableClearable = false", next input trigger change works */}
203
- <Autocomplete<T, undefined, false, false>
221
+ <Autocomplete<T, boolean | undefined, false, false>
204
222
  value={stateValue}
223
+ multiple={multiple}
205
224
  getOptionLabel={getOptionLabel}
206
225
  isOptionEqualToValue={(option: T, value: T) =>
207
226
  option[idField] === value[idField]
package/src/Tiplist.tsx CHANGED
@@ -10,8 +10,8 @@ import { SearchField } from './SearchField';
10
10
  * Tiplist props
11
11
  */
12
12
  export type TiplistProps<T extends object, D extends DataTypes.Keys<T>> = Omit<
13
- AutocompleteExtendedProps<T, D>,
14
- 'open'
13
+ AutocompleteExtendedProps<T, D, undefined>,
14
+ 'open' | 'multiple'
15
15
  > & {
16
16
  /**
17
17
  * Load data callback