@hero-design/rn 8.99.1 → 8.99.2
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/.turbo/turbo-build.log +3 -3
- package/CHANGELOG.md +6 -0
- package/es/index.js +14 -5
- package/lib/index.js +14 -5
- package/package.json +1 -1
- package/src/components/Select/MultiSelect/OptionList.tsx +6 -4
- package/src/components/Select/MultiSelect/__tests__/OptionList.spec.tsx +45 -0
- package/src/components/Select/MultiSelect/__tests__/index.spec.tsx +40 -0
- package/src/components/Select/MultiSelect/__tests__/utils.spec.ts +31 -0
- package/src/components/Select/MultiSelect/index.tsx +3 -2
- package/src/components/Select/MultiSelect/utils.ts +12 -0
- package/stats/8.99.2/rn-stats.html +4842 -0
- package/types/components/Select/MultiSelect/utils.d.ts +2 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(node:
|
|
1
|
+
(node:3078) ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time
|
|
2
2
|
(Use `node --trace-warnings ...` to show where the warning was created)
|
|
3
3
|
[36m
|
|
4
4
|
[1msrc/index.ts[22m → [1mlib/index.js, es/index.js[22m...[39m
|
|
@@ -10,9 +10,9 @@
|
|
|
10
10
|
[7m [0m [91m ~~~~~~~~~~~~~~~~~~~[0m
|
|
11
11
|
[39m
|
|
12
12
|
[1m[33m(!) [plugin node-resolve] preferring built-in module 'events' over local alternative at '/home/runner/work/hero-design/hero-design/node_modules/events/events.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning.or passing a function to 'preferBuiltins' to provide more fine-grained control over which built-in modules to prefer.[39m[22m
|
|
13
|
-
[32mcreated [1mlib/index.js, es/index.js[22m in [
|
|
13
|
+
[32mcreated [1mlib/index.js, es/index.js[22m in [1m55.4s[22m[39m
|
|
14
14
|
[36m
|
|
15
15
|
[1m/home/runner/work/hero-design/hero-design/packages/rn/src/locales/en_AU.ts, /home/runner/work/hero-design/hero-design/packages/rn/src/locales/en_CA.ts, /home/runner/work/hero-design/hero-design/packages/rn/src/locales/index.ts, /home/runner/work/hero-design/hero-design/packages/rn/src/locales/types.ts[22m → [1m., .[22m...[39m
|
|
16
16
|
[1m[33m(!) Generated empty chunks[39m[22m
|
|
17
17
|
"locales/types" and "locales/types"
|
|
18
|
-
[32mcreated [1m., .[22m in [1m20.
|
|
18
|
+
[32mcreated [1m., .[22m in [1m20.7s[22m[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @hero-design/rn
|
|
2
2
|
|
|
3
|
+
## 8.99.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#3811](https://github.com/Thinkei/hero-design/pull/3811) [`4a35bdd6c7cf89d87faeef60e385818df2963a62`](https://github.com/Thinkei/hero-design/commit/4a35bdd6c7cf89d87faeef60e385818df2963a62) Thanks [@vinhphan-eh](https://github.com/vinhphan-eh)! - [Select.Multi] Support display object value
|
|
8
|
+
|
|
3
9
|
## 8.99.1
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/es/index.js
CHANGED
|
@@ -19957,6 +19957,15 @@ var Option$2 = function Option(_ref) {
|
|
|
19957
19957
|
return highlighted === true ? /*#__PURE__*/React__default.createElement(List.Item, props) : /*#__PURE__*/React__default.createElement(List.BasicItem, props);
|
|
19958
19958
|
};
|
|
19959
19959
|
|
|
19960
|
+
var isOptionSelected = function isOptionSelected(value, option) {
|
|
19961
|
+
if (typeof option.value === 'string') {
|
|
19962
|
+
return value.includes(option.value);
|
|
19963
|
+
}
|
|
19964
|
+
return value.some(function (v) {
|
|
19965
|
+
return _deepCompareValue(v, option.value);
|
|
19966
|
+
});
|
|
19967
|
+
};
|
|
19968
|
+
|
|
19960
19969
|
var _excluded$d = ["keyExtractor", "loading", "onEndReached", "onPress", "onQueryChange", "sections", "renderOption", "value", "sectionListRef"];
|
|
19961
19970
|
var OptionList$1 = function OptionList(_ref) {
|
|
19962
19971
|
var keyExtractor = _ref.keyExtractor,
|
|
@@ -19971,14 +19980,14 @@ var OptionList$1 = function OptionList(_ref) {
|
|
|
19971
19980
|
rest = _objectWithoutProperties(_ref, _excluded$d);
|
|
19972
19981
|
var renderItem = function renderItem(info) {
|
|
19973
19982
|
var item = info.item;
|
|
19974
|
-
var selected = value
|
|
19983
|
+
var selected = isOptionSelected(value, item);
|
|
19975
19984
|
var onItemPress = function onItemPress() {
|
|
19976
|
-
if (value
|
|
19985
|
+
if (isOptionSelected(value, item)) {
|
|
19977
19986
|
onPress(value.filter(function (val) {
|
|
19978
|
-
return val
|
|
19987
|
+
return !_deepCompareValue(val, item.value);
|
|
19979
19988
|
}));
|
|
19980
19989
|
} else {
|
|
19981
|
-
onPress([].concat(_toConsumableArray(value), [
|
|
19990
|
+
onPress([].concat(_toConsumableArray(value), [item.value]));
|
|
19982
19991
|
}
|
|
19983
19992
|
};
|
|
19984
19993
|
return renderOption ? renderOption(_objectSpread2(_objectSpread2({}, info), {}, {
|
|
@@ -20045,7 +20054,7 @@ function MultiSelect(_ref) {
|
|
|
20045
20054
|
var sections = toSections(options);
|
|
20046
20055
|
var flatOptions = toFlatOptions(options);
|
|
20047
20056
|
var displayedValue = flatOptions.filter(function (opt) {
|
|
20048
|
-
return value
|
|
20057
|
+
return isOptionSelected(value, opt);
|
|
20049
20058
|
}).map(function (opt) {
|
|
20050
20059
|
return opt.text;
|
|
20051
20060
|
}).join(', ');
|
package/lib/index.js
CHANGED
|
@@ -19986,6 +19986,15 @@ var Option$2 = function Option(_ref) {
|
|
|
19986
19986
|
return highlighted === true ? /*#__PURE__*/React__namespace.default.createElement(List.Item, props) : /*#__PURE__*/React__namespace.default.createElement(List.BasicItem, props);
|
|
19987
19987
|
};
|
|
19988
19988
|
|
|
19989
|
+
var isOptionSelected = function isOptionSelected(value, option) {
|
|
19990
|
+
if (typeof option.value === 'string') {
|
|
19991
|
+
return value.includes(option.value);
|
|
19992
|
+
}
|
|
19993
|
+
return value.some(function (v) {
|
|
19994
|
+
return _deepCompareValue(v, option.value);
|
|
19995
|
+
});
|
|
19996
|
+
};
|
|
19997
|
+
|
|
19989
19998
|
var _excluded$d = ["keyExtractor", "loading", "onEndReached", "onPress", "onQueryChange", "sections", "renderOption", "value", "sectionListRef"];
|
|
19990
19999
|
var OptionList$1 = function OptionList(_ref) {
|
|
19991
20000
|
var keyExtractor = _ref.keyExtractor,
|
|
@@ -20000,14 +20009,14 @@ var OptionList$1 = function OptionList(_ref) {
|
|
|
20000
20009
|
rest = _objectWithoutProperties(_ref, _excluded$d);
|
|
20001
20010
|
var renderItem = function renderItem(info) {
|
|
20002
20011
|
var item = info.item;
|
|
20003
|
-
var selected = value
|
|
20012
|
+
var selected = isOptionSelected(value, item);
|
|
20004
20013
|
var onItemPress = function onItemPress() {
|
|
20005
|
-
if (value
|
|
20014
|
+
if (isOptionSelected(value, item)) {
|
|
20006
20015
|
onPress(value.filter(function (val) {
|
|
20007
|
-
return val
|
|
20016
|
+
return !_deepCompareValue(val, item.value);
|
|
20008
20017
|
}));
|
|
20009
20018
|
} else {
|
|
20010
|
-
onPress([].concat(_toConsumableArray(value), [
|
|
20019
|
+
onPress([].concat(_toConsumableArray(value), [item.value]));
|
|
20011
20020
|
}
|
|
20012
20021
|
};
|
|
20013
20022
|
return renderOption ? renderOption(_objectSpread2(_objectSpread2({}, info), {}, {
|
|
@@ -20074,7 +20083,7 @@ function MultiSelect(_ref) {
|
|
|
20074
20083
|
var sections = toSections(options);
|
|
20075
20084
|
var flatOptions = toFlatOptions(options);
|
|
20076
20085
|
var displayedValue = flatOptions.filter(function (opt) {
|
|
20077
|
-
return value
|
|
20086
|
+
return isOptionSelected(value, opt);
|
|
20078
20087
|
}).map(function (opt) {
|
|
20079
20088
|
return opt.text;
|
|
20080
20089
|
}).join(', ');
|
package/package.json
CHANGED
|
@@ -4,6 +4,8 @@ import BaseOptionList, { BaseOptionListProps } from '../BaseOptionList';
|
|
|
4
4
|
import Option from './Option';
|
|
5
5
|
import type { MultiSelectProps } from '.';
|
|
6
6
|
import type { OptionType, SectionType } from '../types';
|
|
7
|
+
import { deepCompareValue } from '../helpers';
|
|
8
|
+
import { isOptionSelected } from './utils';
|
|
7
9
|
|
|
8
10
|
type OptionListProps<V, T extends OptionType<V>> = Pick<
|
|
9
11
|
MultiSelectProps<V, T>,
|
|
@@ -31,12 +33,12 @@ const OptionList = <V, T extends OptionType<V>>({
|
|
|
31
33
|
}: OptionListProps<V, T>) => {
|
|
32
34
|
const renderItem = (info: SectionListRenderItemInfo<T, SectionType>) => {
|
|
33
35
|
const { item } = info;
|
|
34
|
-
const selected = value
|
|
36
|
+
const selected = isOptionSelected(value, item);
|
|
35
37
|
const onItemPress = () => {
|
|
36
|
-
if (value
|
|
37
|
-
onPress(value.filter((val) => val
|
|
38
|
+
if (isOptionSelected(value, item)) {
|
|
39
|
+
onPress(value.filter((val) => !deepCompareValue(val, item.value)));
|
|
38
40
|
} else {
|
|
39
|
-
onPress([...value,
|
|
41
|
+
onPress([...value, item.value]);
|
|
40
42
|
}
|
|
41
43
|
};
|
|
42
44
|
|
|
@@ -14,6 +14,16 @@ const sections = [
|
|
|
14
14
|
},
|
|
15
15
|
];
|
|
16
16
|
|
|
17
|
+
const sectionsWithObjectValue = [
|
|
18
|
+
{ category: 'A', data: [{ text: 'A1', value: { id: 'a1' } }] },
|
|
19
|
+
{
|
|
20
|
+
category: 'B',
|
|
21
|
+
data: [
|
|
22
|
+
{ text: 'B1', value: { id: 'b1' } },
|
|
23
|
+
{ text: 'B2', value: { id: 'b2' } },
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
];
|
|
17
27
|
describe('OptionList', () => {
|
|
18
28
|
it('renders correctly', () => {
|
|
19
29
|
const pressFn = jest.fn();
|
|
@@ -64,3 +74,38 @@ describe('OptionList', () => {
|
|
|
64
74
|
expect(toJSON()).toMatchSnapshot();
|
|
65
75
|
});
|
|
66
76
|
});
|
|
77
|
+
|
|
78
|
+
describe('OptionList with object value', () => {
|
|
79
|
+
it('renders correctly', () => {
|
|
80
|
+
const pressFn = jest.fn();
|
|
81
|
+
const { getByText } = renderWithTheme(
|
|
82
|
+
<OptionList
|
|
83
|
+
value={[{ id: 'a1' }]}
|
|
84
|
+
sections={sectionsWithObjectValue}
|
|
85
|
+
onPress={pressFn}
|
|
86
|
+
keyExtractor={(opt) => opt.value.id}
|
|
87
|
+
/>
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
expect(getByText('A1')).toBeVisible();
|
|
91
|
+
expect(getByText('B1')).toBeVisible();
|
|
92
|
+
expect(getByText('B2')).toBeVisible();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('trigger onPress correctly on select value', () => {
|
|
96
|
+
const pressFn = jest.fn();
|
|
97
|
+
const { getByText } = renderWithTheme(
|
|
98
|
+
<OptionList
|
|
99
|
+
value={[{ id: 'a1' }]}
|
|
100
|
+
sections={sectionsWithObjectValue}
|
|
101
|
+
onPress={pressFn}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
|
|
105
|
+
fireEvent.press(getByText('B1'));
|
|
106
|
+
expect(pressFn).toHaveBeenCalledWith([{ id: 'a1' }, { id: 'b1' }]);
|
|
107
|
+
|
|
108
|
+
fireEvent.press(getByText('A1'));
|
|
109
|
+
expect(pressFn).toHaveBeenCalledWith([]);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
@@ -32,6 +32,11 @@ const sections = [
|
|
|
32
32
|
},
|
|
33
33
|
];
|
|
34
34
|
|
|
35
|
+
const objectOptions = [
|
|
36
|
+
{ text: 'Monday', value: { id: 'mon' } },
|
|
37
|
+
{ text: 'Tuesday', value: { id: 'tue' } },
|
|
38
|
+
];
|
|
39
|
+
|
|
35
40
|
type CustomOptionType = {
|
|
36
41
|
text: string;
|
|
37
42
|
value: string;
|
|
@@ -341,6 +346,22 @@ describe('rendering', () => {
|
|
|
341
346
|
expect(getByText('Monday')).toBeTruthy();
|
|
342
347
|
expect(toJSON()).toMatchSnapshot();
|
|
343
348
|
});
|
|
349
|
+
|
|
350
|
+
it('renders correctly when receives object value', () => {
|
|
351
|
+
const { getByText, getByTestId } = renderWithTheme(
|
|
352
|
+
<MultiSelect
|
|
353
|
+
value={[{ id: 'mon' }]}
|
|
354
|
+
options={objectOptions}
|
|
355
|
+
onConfirm={jest.fn()}
|
|
356
|
+
footerLabel="Confirm"
|
|
357
|
+
label="Allow notifications"
|
|
358
|
+
/>
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
fireEvent.press(getByTestId('text-input'));
|
|
362
|
+
expect(getByText('Monday')).toBeVisible();
|
|
363
|
+
expect(getByText('Tuesday')).toBeVisible();
|
|
364
|
+
});
|
|
344
365
|
});
|
|
345
366
|
|
|
346
367
|
describe('behavior', () => {
|
|
@@ -379,4 +400,23 @@ describe('behavior', () => {
|
|
|
379
400
|
|
|
380
401
|
expect(onPress).toBeCalledTimes(0);
|
|
381
402
|
});
|
|
403
|
+
|
|
404
|
+
it('calls confirm with correct value when receives object value', () => {
|
|
405
|
+
const onPress = jest.fn();
|
|
406
|
+
const { getByText, getByTestId } = renderWithTheme(
|
|
407
|
+
<MultiSelect
|
|
408
|
+
value={[{ id: 'mon' }]}
|
|
409
|
+
options={objectOptions}
|
|
410
|
+
onConfirm={onPress}
|
|
411
|
+
footerLabel="Confirm"
|
|
412
|
+
label="Allow notifications"
|
|
413
|
+
/>
|
|
414
|
+
);
|
|
415
|
+
|
|
416
|
+
fireEvent.press(getByTestId('text-input'));
|
|
417
|
+
fireEvent.press(getByText('Tuesday'));
|
|
418
|
+
fireEvent.press(getByText('Confirm'));
|
|
419
|
+
|
|
420
|
+
expect(onPress).toBeCalledWith([{ id: 'mon' }, { id: 'tue' }]);
|
|
421
|
+
});
|
|
382
422
|
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { isOptionSelected } from '../utils';
|
|
2
|
+
|
|
3
|
+
describe('isOptionSelected', () => {
|
|
4
|
+
it('should return true when string value is selected', () => {
|
|
5
|
+
const selectedValues = ['option1', 'option2'];
|
|
6
|
+
const option = { value: 'option1', text: 'Option 1' };
|
|
7
|
+
|
|
8
|
+
expect(isOptionSelected(selectedValues, option)).toBe(true);
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('should return false when string value is not selected', () => {
|
|
12
|
+
const selectedValues = ['option1', 'option2'];
|
|
13
|
+
const option = { value: 'option3', text: 'Option 3' };
|
|
14
|
+
|
|
15
|
+
expect(isOptionSelected(selectedValues, option)).toBe(false);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should return true when object value is selected', () => {
|
|
19
|
+
const selectedValues = [{ id: 1 }, { id: 2 }];
|
|
20
|
+
const option = { value: { id: 1 }, text: 'Option 1' };
|
|
21
|
+
|
|
22
|
+
expect(isOptionSelected(selectedValues, option)).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should return false when object value is not selected', () => {
|
|
26
|
+
const selectedValues = [{ id: 1 }, { id: 2 }];
|
|
27
|
+
const option = { value: { id: 3 }, text: 'Option 3' };
|
|
28
|
+
|
|
29
|
+
expect(isOptionSelected(selectedValues, option)).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useRef, useState } from 'react';
|
|
2
2
|
import type {
|
|
3
|
-
SectionList,
|
|
4
3
|
TextInputProps as NativeTextInputProps,
|
|
4
|
+
SectionList,
|
|
5
5
|
} from 'react-native';
|
|
6
6
|
import { TouchableOpacity, View } from 'react-native';
|
|
7
7
|
import BottomSheet from '../../BottomSheet';
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
import { StyledSearchBar } from '../StyledSelect';
|
|
18
18
|
import type { OptionType, SectionType, SelectProps } from '../types';
|
|
19
19
|
import OptionList from './OptionList';
|
|
20
|
+
import { isOptionSelected } from './utils';
|
|
20
21
|
|
|
21
22
|
export interface MultiSelectProps<V, T extends OptionType<V> = OptionType<V>>
|
|
22
23
|
extends SelectProps<V, T> {
|
|
@@ -83,7 +84,7 @@ function MultiSelect<V, T extends OptionType<V>>({
|
|
|
83
84
|
const sections = toSections(options);
|
|
84
85
|
const flatOptions = toFlatOptions(options);
|
|
85
86
|
const displayedValue = flatOptions
|
|
86
|
-
.filter((opt) => value
|
|
87
|
+
.filter((opt) => isOptionSelected(value, opt))
|
|
87
88
|
.map((opt) => opt.text)
|
|
88
89
|
.join(', ');
|
|
89
90
|
const rawValue = value.length > 0 ? value.join(', ') : '';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { deepCompareValue } from '../helpers';
|
|
2
|
+
import { OptionType } from '../types';
|
|
3
|
+
|
|
4
|
+
export const isOptionSelected = <V, T extends OptionType<V>>(
|
|
5
|
+
value: V[],
|
|
6
|
+
option: T
|
|
7
|
+
): boolean => {
|
|
8
|
+
if (typeof option.value === 'string') {
|
|
9
|
+
return value.includes(option.value);
|
|
10
|
+
}
|
|
11
|
+
return value.some((v) => deepCompareValue(v, option.value));
|
|
12
|
+
};
|