@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.
@@ -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> options={options} name="test" search labelField="name" />
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 item = await findByText(baseElement, 'Name 2');
25
- expect(item.nodeName).toBe('SPAN');
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
  });
@@ -44,7 +44,7 @@ export declare type HiSelectorProps<T extends object, D extends DataTypes.Keys<T
44
44
  /**
45
45
  * Item change callback
46
46
  */
47
- onItemChange?: (option?: T) => void;
47
+ onItemChange?: (option: T | undefined, userAction: boolean) => void;
48
48
  /**
49
49
  * Required
50
50
  */
package/lib/HiSelector.js CHANGED
@@ -31,7 +31,7 @@ export function HiSelector(props) {
31
31
  if (!userAction &&
32
32
  (option == null || option[idField] !== values.at(-1)))
33
33
  return;
34
- onItemChange(option);
34
+ onItemChange(option, userAction);
35
35
  };
36
36
  React.useEffect(() => {
37
37
  if (values.length > 0) {
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 = [], search = false, autoAddBlankItem = search, value, onChange, fullWidth, ...rest } = props;
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(options);
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 (valueState != null && valueState !== '')
30
- doItemChange(options, valueState, false);
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 (propertyWay && options != null)
37
- setOptionsAdd(options);
38
- }, [JSON.stringify(options), propertyWay]);
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
- const input = (_a = divRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('input');
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
- if (multiple)
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -59,7 +59,7 @@ export type HiSelectorProps<
59
59
  /**
60
60
  * Item change callback
61
61
  */
62
- onItemChange?: (option?: T) => void;
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(options);
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 === '') onItemChange(undefined, userAction);
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 (valueState != null && valueState !== '')
153
- doItemChange(options, valueState, false);
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 (propertyWay && options != null) setOptionsAdd(options);
161
- }, [JSON.stringify(options), propertyWay]);
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
- if (multiple) handleChange(event);
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