@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.
- package/lib/AutocompleteExtendedProps.d.ts +1 -1
- package/lib/ComboBox.d.ts +8 -0
- package/lib/ComboBox.js +15 -11
- package/lib/Tiplist.d.ts +1 -1
- package/package.json +1 -1
- package/src/AutocompleteExtendedProps.ts +3 -2
- package/src/ComboBox.tsx +34 -15
- package/src/Tiplist.tsx +2 -2
|
@@ -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
|
|
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
|
-
|
|
30
|
+
const localValue = React.useMemo(() => idValue != null
|
|
31
31
|
? localOptions.find((o) => o[idField] === idValue)
|
|
32
|
-
:
|
|
33
|
-
|
|
34
|
-
|
|
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
|
|
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:
|
|
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
|
@@ -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,
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
|
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
|
|
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={
|
|
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
|