@hero-design/rn 7.16.2 → 7.17.0

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.
Files changed (51) hide show
  1. package/.turbo/turbo-build.log +2 -2
  2. package/es/index.js +224 -160
  3. package/lib/index.js +223 -159
  4. package/package.json +2 -2
  5. package/src/components/List/BasicListItem.tsx +8 -4
  6. package/src/components/Select/MultiSelect/Option.tsx +20 -11
  7. package/src/components/Select/MultiSelect/OptionList.tsx +47 -41
  8. package/src/components/Select/MultiSelect/__tests__/OptionList.spec.tsx +25 -14
  9. package/src/components/Select/MultiSelect/__tests__/__snapshots__/Option.spec.tsx.snap +3 -1
  10. package/src/components/Select/MultiSelect/__tests__/__snapshots__/OptionList.spec.tsx.snap +1612 -108
  11. package/src/components/Select/MultiSelect/__tests__/__snapshots__/index.spec.tsx.snap +5265 -319
  12. package/src/components/Select/MultiSelect/__tests__/index.spec.tsx +122 -1
  13. package/src/components/Select/MultiSelect/index.tsx +26 -36
  14. package/src/components/Select/SingleSelect/Option.tsx +19 -3
  15. package/src/components/Select/SingleSelect/OptionList.tsx +47 -39
  16. package/src/components/Select/SingleSelect/__tests__/OptionList.spec.tsx +23 -12
  17. package/src/components/Select/SingleSelect/__tests__/__snapshots__/Option.spec.tsx.snap +3 -1
  18. package/src/components/Select/SingleSelect/__tests__/__snapshots__/OptionList.spec.tsx.snap +1612 -108
  19. package/src/components/Select/SingleSelect/__tests__/__snapshots__/index.spec.tsx.snap +4898 -268
  20. package/src/components/Select/SingleSelect/__tests__/index.spec.tsx +117 -1
  21. package/src/components/Select/SingleSelect/index.tsx +26 -37
  22. package/src/components/Select/StyledOptionList.tsx +43 -44
  23. package/src/components/Select/StyledSelect.tsx +7 -3
  24. package/src/components/Select/__tests__/StyledSelect.spec.tsx +1 -9
  25. package/src/components/Select/__tests__/__snapshots__/StyledSelect.spec.tsx.snap +0 -13
  26. package/src/components/Select/__tests__/helpers.spec.tsx +74 -0
  27. package/src/components/Select/helpers.tsx +87 -4
  28. package/src/components/Select/types.ts +99 -0
  29. package/src/components/TextInput/__tests__/__snapshots__/index.spec.tsx.snap +157 -1
  30. package/src/components/TextInput/__tests__/index.spec.tsx +29 -8
  31. package/src/components/TextInput/index.tsx +18 -7
  32. package/src/theme/__tests__/__snapshots__/index.spec.ts.snap +3 -3
  33. package/src/theme/components/select.ts +3 -3
  34. package/src/types.ts +7 -1
  35. package/types/components/List/BasicListItem.d.ts +1 -1
  36. package/types/components/Select/MultiSelect/Option.d.ts +4 -2
  37. package/types/components/Select/MultiSelect/OptionList.d.ts +6 -7
  38. package/types/components/Select/MultiSelect/index.d.ts +5 -5
  39. package/types/components/Select/SingleSelect/Option.d.ts +4 -2
  40. package/types/components/Select/SingleSelect/OptionList.d.ts +6 -7
  41. package/types/components/Select/SingleSelect/index.d.ts +5 -5
  42. package/types/components/Select/StyledOptionList.d.ts +10 -16
  43. package/types/components/Select/StyledSelect.d.ts +8 -2
  44. package/types/components/Select/__tests__/helpers.spec.d.ts +1 -0
  45. package/types/components/Select/helpers.d.ts +14 -2
  46. package/types/components/Select/index.d.ts +1 -1
  47. package/types/components/Select/types.d.ts +32 -7
  48. package/types/components/TextInput/index.d.ts +4 -2
  49. package/types/theme/components/select.d.ts +3 -3
  50. package/types/types.d.ts +2 -1
  51. package/src/components/Select/types.tsx +0 -52
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hero-design/rn",
3
- "version": "7.16.2",
3
+ "version": "7.17.0",
4
4
  "license": "MIT",
5
5
  "main": "lib/index.js",
6
6
  "module": "es/index.js",
@@ -20,7 +20,7 @@
20
20
  "dependencies": {
21
21
  "@emotion/native": "^11.9.3",
22
22
  "@emotion/react": "^11.9.3",
23
- "@hero-design/colors": "7.16.2",
23
+ "@hero-design/colors": "7.17.0",
24
24
  "date-fns": "^2.16.1",
25
25
  "events": "^3.2.0",
26
26
  "hero-editor": "^1.9.9"
@@ -23,7 +23,7 @@ export interface ListItemProps {
23
23
  /**
24
24
  * The title of the component.
25
25
  */
26
- title: string;
26
+ title: string | React.ReactElement;
27
27
  /**
28
28
  * The subtile title of the component.
29
29
  */
@@ -82,9 +82,13 @@ const BasicListItem = ({
82
82
  </StyledPrefixContainer>
83
83
  )}
84
84
  <StyledTitleContainer>
85
- <Typography.Text intent="body" fontSize="large">
86
- {title}
87
- </Typography.Text>
85
+ {typeof title === 'string' ? (
86
+ <Typography.Text intent="body" fontSize="large">
87
+ {title}
88
+ </Typography.Text>
89
+ ) : (
90
+ title
91
+ )}
88
92
  {subtitle && (
89
93
  <Typography.Text intent="subdued" fontSize="small">
90
94
  {subtitle}
@@ -1,22 +1,31 @@
1
- import React from 'react';
2
- import Icon from '../../Icon';
1
+ import React, { ReactElement } from 'react';
2
+ import { useTheme } from '../../../theme';
3
3
  import List from '../../List';
4
4
 
5
5
  const Option = ({
6
6
  text,
7
+ disabled = false,
7
8
  selected,
8
9
  onPress,
9
10
  }: {
10
- text: string;
11
+ text: string | ReactElement;
12
+ disabled?: boolean;
11
13
  selected: boolean;
12
14
  onPress: () => void;
13
- }) => (
14
- <List.BasicItem
15
- selected={selected}
16
- onPress={onPress}
17
- title={text}
18
- suffix={selected ? <Icon icon="checkmark" size="small" /> : undefined}
19
- />
20
- );
15
+ }) => {
16
+ const theme = useTheme();
17
+ return (
18
+ <List.BasicItem
19
+ selected={selected}
20
+ disabled={disabled}
21
+ onPress={onPress}
22
+ title={text}
23
+ suffix={selected ? 'checkmark' : undefined}
24
+ style={{
25
+ marginHorizontal: theme.__hd__.select.space.optionHorizontalMargin,
26
+ }}
27
+ />
28
+ );
29
+ };
21
30
 
22
31
  export default Option;
@@ -1,63 +1,69 @@
1
1
  import React from 'react';
2
+ import { SectionListRenderItemInfo } from 'react-native';
2
3
  import { MultiSelectProps } from '.';
3
-
4
- import StyledOptionList, { RenderItemProps } from '../StyledOptionList';
4
+ import { getScrollParams } from '../helpers';
5
+ import StyledOptionList from '../StyledOptionList';
6
+ import { OptionType, SectionData, SectionType } from '../types';
5
7
  import Option from './Option';
6
8
 
7
- interface OptionListProps<T> extends MultiSelectProps<T> {
8
- /**
9
- * event handler for select
10
- */
11
- onPress: (value: T[]) => void;
12
- }
9
+ type OptionListProps<V, T extends OptionType<V>> = Pick<
10
+ MultiSelectProps<V, T>,
11
+ | 'keyExtractor'
12
+ | 'loading'
13
+ | 'onEndReached'
14
+ | 'onQueryChange'
15
+ | 'value'
16
+ | 'renderOption'
17
+ > & {
18
+ onPress: (value: V[]) => void;
19
+ sections: SectionData<V, T>[];
20
+ };
13
21
 
14
- const OptionList = <T,>({
22
+ const OptionList = <V, T extends OptionType<V>>({
15
23
  keyExtractor,
16
24
  loading,
17
25
  onEndReached,
18
26
  onPress,
19
27
  onQueryChange,
20
- options,
28
+ sections,
29
+ renderOption,
21
30
  value,
22
- }: Pick<
23
- OptionListProps<T>,
24
- | 'keyExtractor'
25
- | 'loading'
26
- | 'onEndReached'
27
- | 'onPress'
28
- | 'onQueryChange'
29
- | 'options'
30
- | 'value'
31
- >) => {
31
+ }: OptionListProps<V, T>) => {
32
32
  const firstValue = value?.[0];
33
- const rawScrollIndex = firstValue
34
- ? options.findIndex(option => option.value === firstValue)
35
- : 0;
36
- const scrollIndex = rawScrollIndex - 2 >= 0 ? rawScrollIndex - 2 : 0;
33
+ const scrollParams = getScrollParams(firstValue, sections);
37
34
 
38
- const RenderItem = React.memo(({ item }: RenderItemProps<T>) => (
39
- <Option
40
- text={item.text}
41
- selected={value.includes(item.value)}
42
- onPress={() => {
43
- if (value.includes(item.value)) {
44
- onPress(value.filter(val => val !== item.value));
45
- } else {
46
- onPress([...value, item.value]);
47
- }
48
- }}
49
- />
50
- ));
35
+ const renderItem = (info: SectionListRenderItemInfo<T, SectionType>) => {
36
+ const { item } = info;
37
+ const selected = value.includes(info.item.value);
38
+ const onItemPress = () => {
39
+ if (value.includes(info.item.value)) {
40
+ onPress(value.filter(val => val !== info.item.value));
41
+ } else {
42
+ onPress([...value, info.item.value]);
43
+ }
44
+ };
45
+
46
+ return renderOption ? (
47
+ renderOption({ ...info, selected, onPress: onItemPress })
48
+ ) : (
49
+ <Option
50
+ selected={selected}
51
+ text={item.text}
52
+ disabled={item.disabled}
53
+ onPress={onItemPress}
54
+ />
55
+ );
56
+ };
51
57
 
52
58
  return (
53
- <StyledOptionList<T>
59
+ <StyledOptionList
54
60
  keyExtractor={keyExtractor}
55
61
  loading={loading}
56
62
  onEndReached={onEndReached}
57
63
  onQueryChange={onQueryChange}
58
- options={options}
59
- RenderItem={RenderItem}
60
- scrollIndex={scrollIndex}
64
+ sections={sections}
65
+ renderItem={renderItem}
66
+ scrollParams={scrollParams}
61
67
  />
62
68
  );
63
69
  };
@@ -3,49 +3,60 @@ import { fireEvent } from '@testing-library/react-native';
3
3
  import OptionList from '../OptionList';
4
4
  import renderWithTheme from '../../../../testHelpers/renderWithTheme';
5
5
 
6
- const mockOptions = [
7
- { text: 'A', value: 'a' },
8
- { text: 'B', value: 'b' },
9
- { text: 'C', value: 'c' },
6
+ const sections = [
7
+ { category: 'A', data: [{ text: 'A1', value: 'a1' }] },
8
+ {
9
+ category: 'B',
10
+ data: [
11
+ { text: 'B1', value: 'b1' },
12
+ { text: 'B2', value: 'b2' },
13
+ ],
14
+ },
10
15
  ];
11
16
 
12
17
  describe('OptionList', () => {
13
18
  it('renders correctly', () => {
14
19
  const pressFn = jest.fn();
15
- const { toJSON } = renderWithTheme(
16
- <OptionList value={['a']} options={mockOptions} onPress={pressFn} />
20
+ const { toJSON, getByText } = renderWithTheme(
21
+ <OptionList value={['a1']} sections={sections} onPress={pressFn} />
17
22
  );
23
+
24
+ expect(getByText('A')).toBeTruthy();
25
+ expect(getByText('A1')).toBeTruthy();
26
+ expect(getByText('B')).toBeTruthy();
27
+ expect(getByText('B1')).toBeTruthy();
28
+ expect(getByText('B2')).toBeTruthy();
18
29
  expect(toJSON()).toMatchSnapshot();
19
30
  });
20
31
 
21
32
  it('trigger onPress correctly on select additional value', () => {
22
33
  const pressFn = jest.fn();
23
34
  const { toJSON, getByText } = renderWithTheme(
24
- <OptionList value={['a']} options={mockOptions} onPress={pressFn} />
35
+ <OptionList value={['a1']} sections={sections} onPress={pressFn} />
25
36
  );
26
37
  expect(toJSON()).toMatchSnapshot();
27
- fireEvent.press(getByText('B'));
38
+ fireEvent.press(getByText('B1'));
28
39
  expect(pressFn).toBeCalledTimes(1);
29
- expect(pressFn).toHaveBeenCalledWith(['a', 'b']);
40
+ expect(pressFn).toHaveBeenCalledWith(['a1', 'b1']);
30
41
  });
31
42
 
32
43
  it('trigger onPress correctly on changing selection', () => {
33
44
  const pressFn = jest.fn();
34
45
  const { toJSON, getByText } = renderWithTheme(
35
- <OptionList value={['a', 'b']} options={mockOptions} onPress={pressFn} />
46
+ <OptionList value={['a1', 'b1']} sections={sections} onPress={pressFn} />
36
47
  );
37
48
  expect(toJSON()).toMatchSnapshot();
38
- fireEvent.press(getByText('A'));
49
+ fireEvent.press(getByText('A1'));
39
50
  expect(pressFn).toBeCalledTimes(1);
40
- expect(pressFn).toHaveBeenCalledWith(['b']);
51
+ expect(pressFn).toHaveBeenCalledWith(['b1']);
41
52
  });
42
53
 
43
54
  it('render isLoading correctly', () => {
44
55
  const pressFn = jest.fn();
45
56
  const { toJSON } = renderWithTheme(
46
57
  <OptionList
47
- value={['a']}
48
- options={mockOptions}
58
+ value={['a1']}
59
+ sections={sections}
49
60
  onPress={pressFn}
50
61
  loading
51
62
  />
@@ -25,7 +25,9 @@ exports[`Option renders correctly 1`] = `
25
25
  "opacity": 1,
26
26
  "padding": 16,
27
27
  },
28
- undefined,
28
+ Object {
29
+ "marginHorizontal": 12,
30
+ },
29
31
  ]
30
32
  }
31
33
  >