@etsoo/materialui 1.0.7 → 1.0.8
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/__tests__/SelectEx.tsx +30 -3
- package/lib/HiSelector.d.ts +1 -1
- package/lib/HiSelector.js +1 -1
- package/lib/SelectEx.js +16 -16
- package/package.json +1 -1
- package/src/HiSelector.tsx +2 -2
- package/src/SelectEx.tsx +14 -10
package/__tests__/SelectEx.tsx
CHANGED
|
@@ -2,6 +2,8 @@ import React from 'react';
|
|
|
2
2
|
import { SelectEx } from '../src';
|
|
3
3
|
import { findByText, fireEvent, render, screen } from '@testing-library/react';
|
|
4
4
|
import '@testing-library/jest-dom/extend-expect';
|
|
5
|
+
import { Utils } from '@etsoo/shared';
|
|
6
|
+
import { act } from 'react-dom/test-utils';
|
|
5
7
|
|
|
6
8
|
it('Render SelectEx', async () => {
|
|
7
9
|
// Arrange
|
|
@@ -11,16 +13,41 @@ it('Render SelectEx', async () => {
|
|
|
11
13
|
{ id: 2, name: 'Name 2' }
|
|
12
14
|
];
|
|
13
15
|
|
|
16
|
+
Utils.addBlankItem(options, 'id', 'name');
|
|
17
|
+
|
|
18
|
+
const itemChangeCallback = jest.fn((option, userAction) => {
|
|
19
|
+
if (userAction) expect(option).toBeUndefined();
|
|
20
|
+
else expect(option.id).toBe(1);
|
|
21
|
+
});
|
|
22
|
+
|
|
14
23
|
// Render component
|
|
15
24
|
const { baseElement } = render(
|
|
16
|
-
<SelectEx<T>
|
|
25
|
+
<SelectEx<T>
|
|
26
|
+
options={options}
|
|
27
|
+
name="test"
|
|
28
|
+
onItemChange={itemChangeCallback}
|
|
29
|
+
value={1}
|
|
30
|
+
search
|
|
31
|
+
labelField="name"
|
|
32
|
+
/>
|
|
17
33
|
);
|
|
18
34
|
|
|
35
|
+
expect(itemChangeCallback).toBeCalled();
|
|
36
|
+
|
|
19
37
|
// Act, click to show the list
|
|
20
38
|
const button = screen.getByRole('button');
|
|
21
39
|
fireEvent.mouseDown(button); // Not click
|
|
22
40
|
|
|
23
41
|
// Get list item
|
|
24
|
-
const
|
|
25
|
-
expect(
|
|
42
|
+
const itemName2 = await findByText(baseElement, 'Name 2');
|
|
43
|
+
expect(itemName2.nodeName).toBe('SPAN');
|
|
44
|
+
|
|
45
|
+
const itemBlank = await findByText(baseElement, '---');
|
|
46
|
+
expect(itemBlank.nodeName).toBe('SPAN');
|
|
47
|
+
|
|
48
|
+
act(() => {
|
|
49
|
+
itemBlank.click();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
expect(itemChangeCallback).toBeCalledTimes(2);
|
|
26
53
|
});
|
package/lib/HiSelector.d.ts
CHANGED
package/lib/HiSelector.js
CHANGED
package/lib/SelectEx.js
CHANGED
|
@@ -3,7 +3,6 @@ import React from 'react';
|
|
|
3
3
|
import { MUGlobal } from './MUGlobal';
|
|
4
4
|
import { ListItemRightIcon } from './ListItemRightIcon';
|
|
5
5
|
import { Utils } from '@etsoo/shared';
|
|
6
|
-
import { ReactUtils } from '@etsoo/react';
|
|
7
6
|
/**
|
|
8
7
|
* Extended select component
|
|
9
8
|
* @param props Props
|
|
@@ -12,30 +11,33 @@ import { ReactUtils } from '@etsoo/react';
|
|
|
12
11
|
export function SelectEx(props) {
|
|
13
12
|
var _a;
|
|
14
13
|
// Destruct
|
|
15
|
-
const { defaultValue, idField = 'id', error, helperText, inputRequired, itemIconRenderer, itemStyle, label, labelField = 'label', loadData, onItemChange, onItemClick, onLoadData, multiple = false, name, options
|
|
14
|
+
const { defaultValue, idField = 'id', error, helperText, inputRequired, itemIconRenderer, itemStyle, label, labelField = 'label', loadData, onItemChange, onItemClick, onLoadData, multiple = false, name, options, search = false, autoAddBlankItem = search, value, onChange, fullWidth, ...rest } = props;
|
|
16
15
|
// Options state
|
|
17
|
-
const [localOptions, setOptions] = React.useState(
|
|
16
|
+
const [localOptions, setOptions] = React.useState([]);
|
|
18
17
|
const isMounted = React.useRef(true);
|
|
19
18
|
const doItemChange = (options, value, userAction) => {
|
|
20
19
|
if (onItemChange == null)
|
|
21
20
|
return;
|
|
22
|
-
if (value == null || value === '')
|
|
21
|
+
if (value == null || value === '') {
|
|
23
22
|
onItemChange(undefined, userAction);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
24
25
|
const option = options.find((option) => option[idField] === value);
|
|
25
26
|
onItemChange(option, userAction);
|
|
26
27
|
};
|
|
27
28
|
const setOptionsAdd = (options) => {
|
|
28
29
|
setOptions(options);
|
|
29
|
-
if (
|
|
30
|
-
doItemChange(options,
|
|
30
|
+
if (localValue != null && localValue !== '')
|
|
31
|
+
doItemChange(options, localValue, false);
|
|
31
32
|
};
|
|
32
33
|
// When options change
|
|
33
34
|
// [options] will cause infinite loop
|
|
34
35
|
const propertyWay = loadData == null;
|
|
35
36
|
React.useEffect(() => {
|
|
36
|
-
if (
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
if (options == null || !propertyWay)
|
|
38
|
+
return;
|
|
39
|
+
setOptionsAdd(options);
|
|
40
|
+
}, [options, propertyWay]);
|
|
39
41
|
// Local value
|
|
40
42
|
const valueSource = (_a = defaultValue !== null && defaultValue !== void 0 ? defaultValue : value) !== null && _a !== void 0 ? _a : '';
|
|
41
43
|
let localValue;
|
|
@@ -72,14 +74,15 @@ export function SelectEx(props) {
|
|
|
72
74
|
};
|
|
73
75
|
// Set item
|
|
74
76
|
const setItemValue = (id) => {
|
|
75
|
-
var _a;
|
|
76
77
|
if (id != valueState) {
|
|
77
78
|
setValueState(id);
|
|
78
|
-
|
|
79
|
+
/*
|
|
80
|
+
const input = divRef.current?.querySelector('input');
|
|
79
81
|
if (input) {
|
|
80
82
|
// Different value, trigger change event
|
|
81
|
-
ReactUtils.triggerChange(input, id, false);
|
|
83
|
+
ReactUtils.triggerChange(input, id as string, false);
|
|
82
84
|
}
|
|
85
|
+
*/
|
|
83
86
|
}
|
|
84
87
|
};
|
|
85
88
|
// Get option id
|
|
@@ -135,8 +138,7 @@ export function SelectEx(props) {
|
|
|
135
138
|
if (onChange)
|
|
136
139
|
onChange(event, child);
|
|
137
140
|
doItemChange(localOptions, event.target.value, true);
|
|
138
|
-
|
|
139
|
-
handleChange(event);
|
|
141
|
+
handleChange(event);
|
|
140
142
|
}, renderValue: (selected) => {
|
|
141
143
|
// The text shows up
|
|
142
144
|
return localOptions
|
|
@@ -160,8 +162,6 @@ export function SelectEx(props) {
|
|
|
160
162
|
if (event.defaultPrevented)
|
|
161
163
|
return;
|
|
162
164
|
}
|
|
163
|
-
if (!multiple)
|
|
164
|
-
setItemValue(id);
|
|
165
165
|
}, style: itemStyle == null
|
|
166
166
|
? undefined
|
|
167
167
|
: itemStyle(option) },
|
package/package.json
CHANGED
package/src/HiSelector.tsx
CHANGED
|
@@ -59,7 +59,7 @@ export type HiSelectorProps<
|
|
|
59
59
|
/**
|
|
60
60
|
* Item change callback
|
|
61
61
|
*/
|
|
62
|
-
onItemChange?: (option
|
|
62
|
+
onItemChange?: (option: T | undefined, userAction: boolean) => void;
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
65
|
* Required
|
|
@@ -125,7 +125,7 @@ export function HiSelector<
|
|
|
125
125
|
(option == null || option[idField] !== values.at(-1))
|
|
126
126
|
)
|
|
127
127
|
return;
|
|
128
|
-
onItemChange(option);
|
|
128
|
+
onItemChange(option, userAction);
|
|
129
129
|
};
|
|
130
130
|
|
|
131
131
|
React.useEffect(() => {
|
package/src/SelectEx.tsx
CHANGED
|
@@ -20,7 +20,6 @@ import {
|
|
|
20
20
|
ListType,
|
|
21
21
|
Utils
|
|
22
22
|
} from '@etsoo/shared';
|
|
23
|
-
import { ReactUtils } from '@etsoo/react';
|
|
24
23
|
|
|
25
24
|
/**
|
|
26
25
|
* Extended select component props
|
|
@@ -123,7 +122,7 @@ export function SelectEx<
|
|
|
123
122
|
onLoadData,
|
|
124
123
|
multiple = false,
|
|
125
124
|
name,
|
|
126
|
-
options
|
|
125
|
+
options,
|
|
127
126
|
search = false,
|
|
128
127
|
autoAddBlankItem = search,
|
|
129
128
|
value,
|
|
@@ -133,7 +132,7 @@ export function SelectEx<
|
|
|
133
132
|
} = props;
|
|
134
133
|
|
|
135
134
|
// Options state
|
|
136
|
-
const [localOptions, setOptions] = React.useState(
|
|
135
|
+
const [localOptions, setOptions] = React.useState<readonly T[]>([]);
|
|
137
136
|
const isMounted = React.useRef(true);
|
|
138
137
|
|
|
139
138
|
const doItemChange = (
|
|
@@ -142,23 +141,27 @@ export function SelectEx<
|
|
|
142
141
|
userAction: boolean
|
|
143
142
|
) => {
|
|
144
143
|
if (onItemChange == null) return;
|
|
145
|
-
if (value == null || value === '')
|
|
144
|
+
if (value == null || value === '') {
|
|
145
|
+
onItemChange(undefined, userAction);
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
146
148
|
const option = options.find((option) => option[idField] === value);
|
|
147
149
|
onItemChange(option, userAction);
|
|
148
150
|
};
|
|
149
151
|
|
|
150
152
|
const setOptionsAdd = (options: readonly T[]) => {
|
|
151
153
|
setOptions(options);
|
|
152
|
-
if (
|
|
153
|
-
doItemChange(options,
|
|
154
|
+
if (localValue != null && localValue !== '')
|
|
155
|
+
doItemChange(options, localValue, false);
|
|
154
156
|
};
|
|
155
157
|
|
|
156
158
|
// When options change
|
|
157
159
|
// [options] will cause infinite loop
|
|
158
160
|
const propertyWay = loadData == null;
|
|
159
161
|
React.useEffect(() => {
|
|
160
|
-
if (
|
|
161
|
-
|
|
162
|
+
if (options == null || !propertyWay) return;
|
|
163
|
+
setOptionsAdd(options);
|
|
164
|
+
}, [options, propertyWay]);
|
|
162
165
|
|
|
163
166
|
// Local value
|
|
164
167
|
const valueSource = defaultValue ?? value ?? '';
|
|
@@ -198,11 +201,13 @@ export function SelectEx<
|
|
|
198
201
|
if (id != valueState) {
|
|
199
202
|
setValueState(id);
|
|
200
203
|
|
|
204
|
+
/*
|
|
201
205
|
const input = divRef.current?.querySelector('input');
|
|
202
206
|
if (input) {
|
|
203
207
|
// Different value, trigger change event
|
|
204
208
|
ReactUtils.triggerChange(input, id as string, false);
|
|
205
209
|
}
|
|
210
|
+
*/
|
|
206
211
|
}
|
|
207
212
|
};
|
|
208
213
|
|
|
@@ -287,7 +292,7 @@ export function SelectEx<
|
|
|
287
292
|
onChange={(event, child) => {
|
|
288
293
|
if (onChange) onChange(event, child);
|
|
289
294
|
doItemChange(localOptions, event.target.value, true);
|
|
290
|
-
|
|
295
|
+
handleChange(event);
|
|
291
296
|
}}
|
|
292
297
|
renderValue={(selected) => {
|
|
293
298
|
// The text shows up
|
|
@@ -322,7 +327,6 @@ export function SelectEx<
|
|
|
322
327
|
onItemClick(event, option);
|
|
323
328
|
if (event.defaultPrevented) return;
|
|
324
329
|
}
|
|
325
|
-
if (!multiple) setItemValue(id);
|
|
326
330
|
}}
|
|
327
331
|
style={
|
|
328
332
|
itemStyle == null
|