@tecsinapse/react-web-kit 1.8.0 → 1.10.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/CHANGELOG.md +64 -0
- package/dist/components/atoms/Button/Button.d.ts +3 -3
- package/dist/components/atoms/Button/Button.js.map +1 -1
- package/dist/components/atoms/Input/Input.js +5 -3
- package/dist/components/atoms/Input/Input.js.map +1 -1
- package/dist/components/atoms/Table/Header/THead.js +2 -2
- package/dist/components/atoms/Table/Header/THead.js.map +1 -1
- package/dist/components/atoms/Tooltip/Tooltip.d.ts +12 -0
- package/dist/components/atoms/Tooltip/Tooltip.js +50 -0
- package/dist/components/atoms/Tooltip/Tooltip.js.map +1 -0
- package/dist/components/atoms/Tooltip/index.d.ts +1 -0
- package/dist/components/atoms/Tooltip/index.js +24 -0
- package/dist/components/atoms/Tooltip/index.js.map +1 -0
- package/dist/components/atoms/Tooltip/styled.d.ts +9 -0
- package/dist/components/atoms/Tooltip/styled.js +140 -0
- package/dist/components/atoms/Tooltip/styled.js.map +1 -0
- package/dist/components/molecules/Drawer/styled.js.map +1 -1
- package/dist/components/molecules/InputPassword/InputPassword.js +5 -3
- package/dist/components/molecules/InputPassword/InputPassword.js.map +1 -1
- package/dist/components/molecules/Menubar/Menubar.js +1 -1
- package/dist/components/molecules/Menubar/Menubar.js.map +1 -1
- package/dist/components/molecules/Select/Dropdown/Dropdown.d.ts +1 -1
- package/dist/components/molecules/Select/Dropdown/Dropdown.js +39 -26
- package/dist/components/molecules/Select/Dropdown/Dropdown.js.map +1 -1
- package/dist/components/molecules/Select/Dropdown/components/SearchInput.d.ts +8 -0
- package/dist/components/molecules/Select/Dropdown/components/SearchInput.js +43 -0
- package/dist/components/molecules/Select/Dropdown/components/SearchInput.js.map +1 -0
- package/dist/components/molecules/Select/Dropdown/components/index.d.ts +1 -0
- package/dist/components/molecules/Select/Dropdown/components/index.js +16 -0
- package/dist/components/molecules/Select/Dropdown/components/index.js.map +1 -0
- package/dist/components/molecules/Select/Dropdown/styled.d.ts +2 -1
- package/dist/components/molecules/Select/Dropdown/styled.js +6 -3
- package/dist/components/molecules/Select/Dropdown/styled.js.map +1 -1
- package/dist/components/molecules/Select/Select.d.ts +2 -1
- package/dist/components/molecules/Select/Select.js +9 -11
- package/dist/components/molecules/Select/Select.js.map +1 -1
- package/dist/components/molecules/Select/SelectItem/SelectItem.d.ts +3 -3
- package/dist/components/molecules/Select/SelectItem/SelectItem.js +10 -9
- package/dist/components/molecules/Select/SelectItem/SelectItem.js.map +1 -1
- package/dist/components/molecules/Select/functions.d.ts +1 -1
- package/dist/components/molecules/Select/functions.js +1 -1
- package/dist/components/molecules/Select/functions.js.map +1 -1
- package/dist/components/molecules/Select/styled.d.ts +4 -3
- package/dist/components/molecules/Select/styled.js +16 -1
- package/dist/components/molecules/Select/styled.js.map +1 -1
- package/dist/components/molecules/TextArea/TextArea.d.ts +1 -2
- package/dist/components/molecules/TextArea/TextArea.js.map +1 -1
- package/dist/components/organisms/DataGrid/DataGrid.js +1 -1
- package/dist/components/organisms/DataGrid/DataGrid.js.map +1 -1
- package/dist/components/organisms/DataGrid/Footer/Footer.js +2 -1
- package/dist/components/organisms/DataGrid/Footer/Footer.js.map +1 -1
- package/dist/components/organisms/DataGrid/Header/Header.js.map +1 -1
- package/dist/components/organisms/DataGrid/Header/utils.d.ts +6 -8
- package/dist/components/organisms/DataGrid/Header/utils.js.map +1 -1
- package/dist/components/organisms/DataGrid/types.d.ts +2 -1
- package/dist/hooks/useClickAwayListener.d.ts +1 -1
- package/dist/hooks/useClickAwayListener.js +3 -3
- package/dist/hooks/useClickAwayListener.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +17 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/atoms/Button/Button.tsx +3 -3
- package/src/components/atoms/Input/Input.stories.tsx +1 -1
- package/src/components/atoms/Input/Input.tsx +65 -57
- package/src/components/atoms/Table/Header/THead.tsx +1 -1
- package/src/components/atoms/Tooltip/Tooltip.stories.tsx +30 -0
- package/src/components/atoms/Tooltip/Tooltip.tsx +51 -0
- package/src/components/atoms/Tooltip/index.ts +1 -0
- package/src/components/atoms/Tooltip/styled.ts +158 -0
- package/src/components/molecules/Drawer/styled.ts +1 -1
- package/src/components/molecules/InputPassword/InputPassword.stories.tsx +1 -1
- package/src/components/molecules/InputPassword/InputPassword.tsx +24 -22
- package/src/components/molecules/Menubar/Menubar.tsx +1 -1
- package/src/components/molecules/Select/Dropdown/Dropdown.tsx +45 -28
- package/src/components/molecules/Select/Dropdown/components/SearchInput.tsx +26 -0
- package/src/components/molecules/Select/Dropdown/components/index.ts +1 -0
- package/src/components/molecules/Select/Dropdown/styled.ts +10 -4
- package/src/components/molecules/Select/Select.stories.tsx +42 -16
- package/src/components/molecules/Select/Select.tsx +16 -12
- package/src/components/molecules/Select/SelectItem/SelectItem.tsx +27 -24
- package/src/components/molecules/Select/functions.ts +10 -18
- package/src/components/molecules/Select/{styled.ts → styled.tsx} +11 -1
- package/src/components/molecules/TextArea/TextArea.tsx +1 -2
- package/src/components/organisms/DataGrid/DataGrid.tsx +14 -12
- package/src/components/organisms/DataGrid/Footer/Footer.tsx +1 -0
- package/src/components/organisms/DataGrid/Header/Header.tsx +2 -2
- package/src/components/organisms/DataGrid/Header/utils.ts +15 -5
- package/src/components/organisms/DataGrid/types.ts +3 -1
- package/src/hooks/useClickAwayListener.ts +5 -4
- package/src/index.ts +1 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { css } from '@emotion/react';
|
|
2
|
+
import { StyleProps, ThemeProp } from '@tecsinapse/react-core';
|
|
3
|
+
import styled from '@emotion/styled';
|
|
4
|
+
import { ComputedType, Position } from './Tooltip';
|
|
5
|
+
|
|
6
|
+
type InjectedProps = { computed?: ComputedType; position?: Position };
|
|
7
|
+
|
|
8
|
+
/** Bottom/Top commons */
|
|
9
|
+
const bottomOrTopStylesCommon = (width: number, position) =>
|
|
10
|
+
['top', 'bottom'].includes(position as Position) &&
|
|
11
|
+
css`
|
|
12
|
+
left: 50%;
|
|
13
|
+
margin-left: -${width / 2}px;
|
|
14
|
+
`;
|
|
15
|
+
|
|
16
|
+
const bottomOrTopArrowCommon = (position?: Position) =>
|
|
17
|
+
['top', 'bottom'].includes(position as Position) &&
|
|
18
|
+
css`
|
|
19
|
+
left: 50%;
|
|
20
|
+
margin-left: -5px;
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
/** Top */
|
|
24
|
+
const topStyles = (theme: ThemeProp, position?: Position) =>
|
|
25
|
+
position === 'top' &&
|
|
26
|
+
css`
|
|
27
|
+
bottom: 100%;
|
|
28
|
+
margin-bottom: ${theme.spacing.centi};
|
|
29
|
+
transform: translateY(10%);
|
|
30
|
+
`;
|
|
31
|
+
|
|
32
|
+
const topArrow = (theme: ThemeProp, position?: Position) =>
|
|
33
|
+
position === 'top' &&
|
|
34
|
+
css`
|
|
35
|
+
top: 100%;
|
|
36
|
+
border-color: ${theme.color.secondary.xdark} transparent transparent
|
|
37
|
+
transparent;
|
|
38
|
+
`;
|
|
39
|
+
|
|
40
|
+
/** Bottom */
|
|
41
|
+
const bottomStyles = (theme: ThemeProp, position?: Position) =>
|
|
42
|
+
position === 'bottom' &&
|
|
43
|
+
css`
|
|
44
|
+
top: 100%;
|
|
45
|
+
margin-top: ${theme.spacing.centi};
|
|
46
|
+
transform: translateY(-10%);
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
const bottomArrow = (theme: ThemeProp, position?: Position) =>
|
|
50
|
+
position === 'bottom' &&
|
|
51
|
+
css`
|
|
52
|
+
bottom: 100%;
|
|
53
|
+
border-color: transparent transparent ${theme.color.secondary.xdark}
|
|
54
|
+
transparent;
|
|
55
|
+
`;
|
|
56
|
+
|
|
57
|
+
/** Bottom/Top commons */
|
|
58
|
+
const leftAndRightCommonStyles = (height: number, position?: Position) =>
|
|
59
|
+
['right', 'left'].includes(position as Position) &&
|
|
60
|
+
css`
|
|
61
|
+
top: 50%;
|
|
62
|
+
margin-top: -${height / 2}px;
|
|
63
|
+
`;
|
|
64
|
+
|
|
65
|
+
const leftOrRightArrowCommon = (position?: Position) =>
|
|
66
|
+
['right', 'left'].includes(position as Position) &&
|
|
67
|
+
css`
|
|
68
|
+
top: 50%;
|
|
69
|
+
margin-top: -5px;
|
|
70
|
+
`;
|
|
71
|
+
|
|
72
|
+
/** Left */
|
|
73
|
+
const leftStyles = (theme: ThemeProp, position?: Position) =>
|
|
74
|
+
position === 'left' &&
|
|
75
|
+
css`
|
|
76
|
+
right: 100%;
|
|
77
|
+
margin-right: ${theme.spacing.centi};
|
|
78
|
+
transform: translateX(10%);
|
|
79
|
+
`;
|
|
80
|
+
|
|
81
|
+
const leftArrow = (theme: ThemeProp, position?: Position) =>
|
|
82
|
+
position === 'left' &&
|
|
83
|
+
css`
|
|
84
|
+
left: 100%;
|
|
85
|
+
border-color: transparent transparent transparent
|
|
86
|
+
${theme.color.secondary.xdark};
|
|
87
|
+
`;
|
|
88
|
+
|
|
89
|
+
/** Right */
|
|
90
|
+
const rightStyles = (theme: ThemeProp, position?: Position) =>
|
|
91
|
+
position === 'right' &&
|
|
92
|
+
css`
|
|
93
|
+
left: 100%;
|
|
94
|
+
margin-left: ${theme.spacing.centi};
|
|
95
|
+
transform: translateX(-10%);
|
|
96
|
+
`;
|
|
97
|
+
|
|
98
|
+
const rightArrow = (theme: ThemeProp, position?: Position) =>
|
|
99
|
+
position === 'right' &&
|
|
100
|
+
css`
|
|
101
|
+
right: 100%;
|
|
102
|
+
border-color: transparent ${theme.color.secondary.xdark} transparent
|
|
103
|
+
transparent;
|
|
104
|
+
`;
|
|
105
|
+
|
|
106
|
+
export const TooltipSpan = styled('span')<Partial<StyleProps> & InjectedProps>(
|
|
107
|
+
({ theme, computed, position }) => {
|
|
108
|
+
const { width = 0, height = 0 } = computed || {};
|
|
109
|
+
return css`
|
|
110
|
+
position: absolute;
|
|
111
|
+
padding: ${theme.spacing.micro} ${theme.spacing.centi};
|
|
112
|
+
border-radius: ${theme.borderRadius.mili};
|
|
113
|
+
opacity: 0;
|
|
114
|
+
visibility: hidden;
|
|
115
|
+
transition: opacity 0.3s, visibility 0.3s, transform 0.3s;
|
|
116
|
+
background-color: ${theme.color.secondary.xdark};
|
|
117
|
+
z-index: ${theme.zIndex.absolute};
|
|
118
|
+
|
|
119
|
+
${bottomOrTopStylesCommon(width, position)}
|
|
120
|
+
${bottomStyles(theme, position)}
|
|
121
|
+
${topStyles(theme, position)}
|
|
122
|
+
|
|
123
|
+
${leftAndRightCommonStyles(height, position)}
|
|
124
|
+
${leftStyles(theme, position)}
|
|
125
|
+
${rightStyles(theme, position)}
|
|
126
|
+
|
|
127
|
+
&::after {
|
|
128
|
+
content: '';
|
|
129
|
+
position: absolute;
|
|
130
|
+
border-style: solid;
|
|
131
|
+
border-width: 5px;
|
|
132
|
+
|
|
133
|
+
${bottomOrTopArrowCommon(position)}
|
|
134
|
+
${bottomArrow(theme, position)}
|
|
135
|
+
${topArrow(theme, position)}
|
|
136
|
+
|
|
137
|
+
${leftOrRightArrowCommon(position)}
|
|
138
|
+
${leftArrow(theme, position)}
|
|
139
|
+
${rightArrow(theme, position)}
|
|
140
|
+
}
|
|
141
|
+
`;
|
|
142
|
+
}
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
export const Container = styled('div')<{ position?: Position }>`
|
|
146
|
+
position: relative;
|
|
147
|
+
&:hover {
|
|
148
|
+
& > span {
|
|
149
|
+
opacity: 1;
|
|
150
|
+
visibility: visible;
|
|
151
|
+
|
|
152
|
+
transform: ${({ position }) =>
|
|
153
|
+
position === 'left' || position === 'right'
|
|
154
|
+
? 'translateX(0%)'
|
|
155
|
+
: 'translateY(0%)'};
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
`;
|
|
@@ -4,27 +4,29 @@ import { Input, InputWebProps } from '../../atoms/Input';
|
|
|
4
4
|
|
|
5
5
|
export type InputPasswordWebProps = InputWebProps;
|
|
6
6
|
|
|
7
|
-
const InputPassword: FC<InputPasswordWebProps> = (
|
|
8
|
-
rightComponent,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
7
|
+
const InputPassword: FC<InputPasswordWebProps> = React.forwardRef(
|
|
8
|
+
({ rightComponent, ...rest }, ref) => {
|
|
9
|
+
const [revealed, setRevealed] = useState(false);
|
|
10
|
+
return (
|
|
11
|
+
<Input
|
|
12
|
+
{...rest}
|
|
13
|
+
ref={ref}
|
|
14
|
+
secureTextEntry={!revealed}
|
|
15
|
+
rightComponent={
|
|
16
|
+
<>
|
|
17
|
+
<InputPasswordIcon
|
|
18
|
+
onChangeState={setRevealed}
|
|
19
|
+
revealed={revealed}
|
|
20
|
+
effect="none"
|
|
21
|
+
/>
|
|
22
|
+
{rightComponent}
|
|
23
|
+
</>
|
|
24
|
+
}
|
|
25
|
+
/>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
InputPassword.displayName = 'InputPassword';
|
|
29
31
|
|
|
30
32
|
export default InputPassword;
|
|
@@ -50,7 +50,7 @@ const Menubar: React.FC<MenubarProps> = ({
|
|
|
50
50
|
const [input, setInput] = useDebouncedState<string>('', setSearch);
|
|
51
51
|
const [open, setOpen] = React.useState<boolean>(false);
|
|
52
52
|
const menuRef = useRef<HTMLDivElement | null>(null);
|
|
53
|
-
useClickAwayListener(menuRef, setOpen);
|
|
53
|
+
useClickAwayListener(menuRef, setOpen, 'mouseup');
|
|
54
54
|
|
|
55
55
|
const toggleOpen = React.useCallback(() => setOpen(state => !state), [
|
|
56
56
|
setOpen,
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
Checkbox,
|
|
4
|
-
Text,
|
|
5
|
-
Icon,
|
|
6
|
-
useDebouncedState,
|
|
7
|
-
} from '@tecsinapse/react-core';
|
|
8
|
-
import { Input } from '../../../atoms/Input';
|
|
2
|
+
import { Checkbox, Text, useDebouncedState } from '@tecsinapse/react-core';
|
|
9
3
|
import { ItemSelect } from '../SelectItem';
|
|
10
4
|
import { SelectProps } from '../Select';
|
|
11
5
|
import {
|
|
@@ -15,7 +9,11 @@ import {
|
|
|
15
9
|
StyledContainerTextLabel,
|
|
16
10
|
StyledSpan,
|
|
17
11
|
OptionsContainer,
|
|
12
|
+
PaddedContainer,
|
|
18
13
|
} from './styled';
|
|
14
|
+
import { SearchInput } from './components';
|
|
15
|
+
|
|
16
|
+
const fullWidth = { width: '100%' };
|
|
19
17
|
|
|
20
18
|
const Dropdown = <Data, Type extends 'single' | 'multi'>({
|
|
21
19
|
options,
|
|
@@ -29,24 +27,41 @@ const Dropdown = <Data, Type extends 'single' | 'multi'>({
|
|
|
29
27
|
setDropDownVisible,
|
|
30
28
|
style,
|
|
31
29
|
anchor,
|
|
30
|
+
selectAllLabel,
|
|
31
|
+
searchBarPlaceholder,
|
|
32
32
|
}: SelectProps<Data, Type> & {
|
|
33
33
|
setDropDownVisible: (t: boolean) => void;
|
|
34
34
|
}): JSX.Element => {
|
|
35
35
|
const [searchArg, setSearchArg] = useDebouncedState<string>('', onSearch);
|
|
36
|
-
const lengthOptions = options.length;
|
|
36
|
+
const lengthOptions = React.useMemo(() => options.length, [options]);
|
|
37
37
|
|
|
38
38
|
const [checkedAll, setCheckedAll] = React.useState<boolean>(
|
|
39
39
|
type === 'multi' && (value as Data[])?.length === lengthOptions
|
|
40
40
|
);
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
React.useEffect(() => {
|
|
43
|
+
if (type === 'multi') {
|
|
44
|
+
lengthOptions === (value as Data[])?.length
|
|
45
|
+
? setCheckedAll(true)
|
|
46
|
+
: setCheckedAll(false);
|
|
47
|
+
}
|
|
48
|
+
}, [value, type, lengthOptions]);
|
|
49
|
+
|
|
50
|
+
const onClickCheckAll = React.useCallback(() => {
|
|
43
51
|
const items = options.map(option => option);
|
|
44
|
-
|
|
45
|
-
|
|
52
|
+
let aux;
|
|
53
|
+
setCheckedAll(prev => {
|
|
54
|
+
aux = !prev;
|
|
55
|
+
return !prev;
|
|
56
|
+
});
|
|
46
57
|
type OnSelectArg = Parameters<typeof onSelect>[0];
|
|
47
58
|
const auxArray: Data[] = [];
|
|
48
59
|
!aux ? onSelect(auxArray as OnSelectArg) : onSelect(items as OnSelectArg);
|
|
49
|
-
};
|
|
60
|
+
}, [options, setCheckedAll, onSelect]);
|
|
61
|
+
|
|
62
|
+
const onChange = React.useCallback(text => setSearchArg(text), [
|
|
63
|
+
setSearchArg,
|
|
64
|
+
]);
|
|
50
65
|
|
|
51
66
|
return (
|
|
52
67
|
<StyledContainerDropdown
|
|
@@ -61,35 +76,37 @@ const Dropdown = <Data, Type extends 'single' | 'multi'>({
|
|
|
61
76
|
<Checkbox checked={checkedAll} onChange={onClickCheckAll} />
|
|
62
77
|
{!hideSearchBar ? (
|
|
63
78
|
<SearchBarContainer>
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<Icon
|
|
70
|
-
name="magnify"
|
|
71
|
-
type="material-community"
|
|
72
|
-
size="centi"
|
|
73
|
-
style={{ marginHorizontal: 12 }}
|
|
74
|
-
/>
|
|
75
|
-
}
|
|
76
|
-
onChange={text => setSearchArg(text)}
|
|
79
|
+
<SearchInput
|
|
80
|
+
searchArg={searchArg}
|
|
81
|
+
onChange={onChange}
|
|
82
|
+
fullWidth={fullWidth}
|
|
83
|
+
placeholder={searchBarPlaceholder}
|
|
77
84
|
/>
|
|
78
85
|
</SearchBarContainer>
|
|
79
86
|
) : (
|
|
80
87
|
<StyledContainerTextLabel>
|
|
81
88
|
<Text fontWeight="bold">
|
|
82
|
-
<StyledSpan>
|
|
89
|
+
<StyledSpan>{selectAllLabel}</StyledSpan>
|
|
83
90
|
</Text>
|
|
84
91
|
</StyledContainerTextLabel>
|
|
85
92
|
)}
|
|
86
93
|
</StyledContainerCheckAll>
|
|
87
94
|
)}
|
|
95
|
+
{type === 'single' && !hideSearchBar && (
|
|
96
|
+
<PaddedContainer>
|
|
97
|
+
<SearchInput
|
|
98
|
+
searchArg={searchArg}
|
|
99
|
+
onChange={onChange}
|
|
100
|
+
fullWidth={fullWidth}
|
|
101
|
+
placeholder={searchBarPlaceholder}
|
|
102
|
+
/>
|
|
103
|
+
</PaddedContainer>
|
|
104
|
+
)}
|
|
88
105
|
<OptionsContainer lengthOptions={options.length}>
|
|
89
106
|
{options.map((item, index) => (
|
|
90
107
|
<ItemSelect
|
|
91
108
|
type={type}
|
|
92
|
-
key={
|
|
109
|
+
key={keyExtractor(item)}
|
|
93
110
|
item={item}
|
|
94
111
|
onSelect={onSelect}
|
|
95
112
|
value={value}
|
|
@@ -99,7 +116,7 @@ const Dropdown = <Data, Type extends 'single' | 'multi'>({
|
|
|
99
116
|
setDropDownVisible={setDropDownVisible}
|
|
100
117
|
checkedAll={checkedAll}
|
|
101
118
|
setCheckedAll={setCheckedAll}
|
|
102
|
-
lenghtOptions={
|
|
119
|
+
lenghtOptions={lengthOptions}
|
|
103
120
|
/>
|
|
104
121
|
))}
|
|
105
122
|
</OptionsContainer>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Icon } from '@tecsinapse/react-core';
|
|
3
|
+
import { Input } from '../../../../atoms/Input';
|
|
4
|
+
|
|
5
|
+
const InputIcon = (
|
|
6
|
+
<Icon
|
|
7
|
+
name="magnify"
|
|
8
|
+
type="material-community"
|
|
9
|
+
size="centi"
|
|
10
|
+
style={{ marginHorizontal: 12 }}
|
|
11
|
+
/>
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
const SearchInput = ({ fullWidth, searchArg, onChange, placeholder }) => {
|
|
15
|
+
return (
|
|
16
|
+
<Input
|
|
17
|
+
style={fullWidth}
|
|
18
|
+
placeholder={placeholder}
|
|
19
|
+
value={searchArg}
|
|
20
|
+
leftComponent={InputIcon}
|
|
21
|
+
onChange={onChange}
|
|
22
|
+
/>
|
|
23
|
+
);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default React.memo(SearchInput);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as SearchInput } from './SearchInput';
|
|
@@ -4,7 +4,8 @@ import { SelectProps } from '../Select';
|
|
|
4
4
|
import { css } from '@emotion/react';
|
|
5
5
|
|
|
6
6
|
type InjectedProps = Partial<
|
|
7
|
-
StyleProps &
|
|
7
|
+
StyleProps &
|
|
8
|
+
SelectProps<unknown, 'single' | 'multi'> & { lengthOptions: number }
|
|
8
9
|
>;
|
|
9
10
|
|
|
10
11
|
const anchorBottom = ({
|
|
@@ -38,7 +39,7 @@ export const StyledContainerDropdown = styled('div')<InjectedProps>`
|
|
|
38
39
|
padding-top: ${({
|
|
39
40
|
theme,
|
|
40
41
|
hideSearchBar,
|
|
41
|
-
}: StyleProps & Partial<SelectProps<
|
|
42
|
+
}: StyleProps & Partial<SelectProps<unknown, 'single' | 'multi'>>) =>
|
|
42
43
|
!hideSearchBar ? `${theme.spacing.deca}` : '0px'};
|
|
43
44
|
padding-bottom: ${({ theme }: StyleProps) => theme.spacing.mili};
|
|
44
45
|
z-index: ${({ theme }: StyleProps) => theme.zIndex.select};
|
|
@@ -68,8 +69,13 @@ export const SearchBarContainer = styled('div')<Partial<StyleProps>>`
|
|
|
68
69
|
width: 100%;
|
|
69
70
|
`;
|
|
70
71
|
|
|
71
|
-
export const
|
|
72
|
+
export const PaddedContainer = styled('div')<Partial<StyleProps>>`
|
|
72
73
|
padding: ${({ theme }) => `${theme.spacing.mili} ${theme.spacing.deca}`};
|
|
74
|
+
`;
|
|
75
|
+
|
|
76
|
+
export const StyledContainerCheckAll = styled(PaddedContainer)<
|
|
77
|
+
Partial<StyleProps>
|
|
78
|
+
>`
|
|
73
79
|
flex-direction: row;
|
|
74
80
|
display: flex;
|
|
75
81
|
justify-content: flex-start;
|
|
@@ -84,7 +90,7 @@ export const StyledContainerCheckAll = styled('div')<Partial<StyleProps>>`
|
|
|
84
90
|
`;
|
|
85
91
|
|
|
86
92
|
export const StyledSpan = styled('span')<Partial<StyleProps>>`
|
|
87
|
-
color: ${({ theme }) => theme.color.
|
|
93
|
+
color: ${({ theme }) => theme.font.color.dark};
|
|
88
94
|
padding: ${({ theme }) => `${theme.spacing.mili} 0px`};
|
|
89
95
|
`;
|
|
90
96
|
|
|
@@ -15,21 +15,33 @@ type Option = {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
const OPTIONS_EXAMPLE: Option[] = [
|
|
18
|
-
{ label: '
|
|
19
|
-
{ label: '
|
|
20
|
-
{ label: '
|
|
21
|
-
{ label: '
|
|
22
|
-
{ label: '
|
|
23
|
-
{ label: '
|
|
18
|
+
{ label: 'New York', value: 'value1' },
|
|
19
|
+
{ label: 'São Paulo', value: 'value2' },
|
|
20
|
+
{ label: 'Lisbon', value: 'value3' },
|
|
21
|
+
{ label: 'Moscow', value: 'value4' },
|
|
22
|
+
{ label: 'Sidney', value: 'value5' },
|
|
23
|
+
{ label: 'Rio de Janeiro', value: 'value6' },
|
|
24
24
|
];
|
|
25
25
|
|
|
26
|
-
const TemplateSingle: Story<SelectProps<Option, 'single'>> =
|
|
26
|
+
const TemplateSingle: Story<SelectProps<Option, 'single'>> = ({
|
|
27
|
+
options: _options,
|
|
28
|
+
...args
|
|
29
|
+
}) => {
|
|
27
30
|
const [singleValue, setSingleValue] = useState(undefined);
|
|
31
|
+
const [options, setOptions] = useState(_options);
|
|
28
32
|
|
|
29
|
-
const handleSelectSingleValue =
|
|
33
|
+
const handleSelectSingleValue = React.useCallback(
|
|
34
|
+
key => setSingleValue(key),
|
|
35
|
+
[setSingleValue]
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const labelExtractor = React.useCallback(item => item.label, []);
|
|
39
|
+
const keyExtractor = React.useCallback(item => String(item.value), []);
|
|
30
40
|
|
|
31
41
|
const handleSearch = React.useCallback((searchArg: string) => {
|
|
32
|
-
|
|
42
|
+
setOptions(
|
|
43
|
+
_options.filter(item => new RegExp(searchArg, 'ig').test(item.label))
|
|
44
|
+
);
|
|
33
45
|
}, []);
|
|
34
46
|
|
|
35
47
|
return (
|
|
@@ -37,11 +49,12 @@ const TemplateSingle: Story<SelectProps<Option, 'single'>> = args => {
|
|
|
37
49
|
<ContainerSelect>
|
|
38
50
|
<Select
|
|
39
51
|
{...args}
|
|
52
|
+
options={options}
|
|
40
53
|
value={singleValue}
|
|
41
54
|
type="single"
|
|
42
55
|
onSelect={handleSelectSingleValue}
|
|
43
|
-
labelExtractor={
|
|
44
|
-
keyExtractor={
|
|
56
|
+
labelExtractor={labelExtractor}
|
|
57
|
+
keyExtractor={keyExtractor}
|
|
45
58
|
onSearch={handleSearch}
|
|
46
59
|
/>
|
|
47
60
|
</ContainerSelect>
|
|
@@ -58,13 +71,25 @@ Single.args = {
|
|
|
58
71
|
hideSearchBar: false,
|
|
59
72
|
};
|
|
60
73
|
|
|
61
|
-
const TemplateMulti: Story<SelectProps<Option, 'multi'>> =
|
|
74
|
+
const TemplateMulti: Story<SelectProps<Option, 'multi'>> = ({
|
|
75
|
+
options: _options,
|
|
76
|
+
...args
|
|
77
|
+
}) => {
|
|
62
78
|
const [multiValue, setMultiValue] = useState([]);
|
|
79
|
+
const [options, setOptions] = useState(_options);
|
|
80
|
+
|
|
81
|
+
const handleSelectMultipleValues = React.useCallback(
|
|
82
|
+
keys => setMultiValue(keys),
|
|
83
|
+
[setMultiValue]
|
|
84
|
+
);
|
|
63
85
|
|
|
64
|
-
const
|
|
86
|
+
const labelExtractor = React.useCallback(item => item.label, []);
|
|
87
|
+
const keyExtractor = React.useCallback(item => String(item.value), []);
|
|
65
88
|
|
|
66
89
|
const handleSearch = React.useCallback((searchArg: string) => {
|
|
67
|
-
|
|
90
|
+
setOptions(
|
|
91
|
+
_options.filter(item => new RegExp(searchArg, 'ig').test(item.label))
|
|
92
|
+
);
|
|
68
93
|
}, []);
|
|
69
94
|
|
|
70
95
|
return (
|
|
@@ -72,11 +97,12 @@ const TemplateMulti: Story<SelectProps<Option, 'multi'>> = args => {
|
|
|
72
97
|
<ContainerSelect>
|
|
73
98
|
<Select
|
|
74
99
|
{...args}
|
|
100
|
+
options={options}
|
|
75
101
|
value={multiValue}
|
|
76
102
|
type="multi"
|
|
77
103
|
onSelect={handleSelectMultipleValues}
|
|
78
|
-
labelExtractor={
|
|
79
|
-
keyExtractor={
|
|
104
|
+
labelExtractor={labelExtractor}
|
|
105
|
+
keyExtractor={keyExtractor}
|
|
80
106
|
onSearch={handleSearch}
|
|
81
107
|
/>
|
|
82
108
|
</ContainerSelect>
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import {
|
|
3
|
-
Icon,
|
|
4
3
|
PressableInputContainer,
|
|
5
4
|
Text,
|
|
6
5
|
TextProps,
|
|
7
6
|
} from '@tecsinapse/react-core';
|
|
8
7
|
import { useClickAwayListener } from '../../../hooks';
|
|
9
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
RightComponent,
|
|
10
|
+
StyledContainer,
|
|
11
|
+
StyledInputContainer,
|
|
12
|
+
} from './styled';
|
|
10
13
|
import { Dropdown } from './Dropdown';
|
|
11
14
|
import { getDisplayValue } from './functions';
|
|
12
15
|
import { Transition } from 'react-transition-group';
|
|
@@ -26,12 +29,14 @@ export interface SelectProps<Data, Type extends 'single' | 'multi'>
|
|
|
26
29
|
onSearch?: (searchArg: string) => void | never;
|
|
27
30
|
searchBarPlaceholder?: string;
|
|
28
31
|
hideSearchBar?: boolean;
|
|
32
|
+
selectAllLabel?: string;
|
|
29
33
|
disabled?: boolean;
|
|
30
34
|
label?: string;
|
|
31
35
|
anchor?: 'top' | 'bottom';
|
|
32
36
|
displayTextProps?: TextProps;
|
|
33
37
|
}
|
|
34
38
|
|
|
39
|
+
/** NOTE: For better performance, you should memoize options and handlers */
|
|
35
40
|
export const Select = <Data, Type extends 'single' | 'multi'>({
|
|
36
41
|
value,
|
|
37
42
|
options,
|
|
@@ -41,12 +46,13 @@ export const Select = <Data, Type extends 'single' | 'multi'>({
|
|
|
41
46
|
labelExtractor,
|
|
42
47
|
placeholder,
|
|
43
48
|
onSearch,
|
|
44
|
-
searchBarPlaceholder,
|
|
49
|
+
searchBarPlaceholder = 'Busque a opção desejada',
|
|
45
50
|
hideSearchBar = true,
|
|
46
51
|
label,
|
|
47
52
|
disabled = false,
|
|
48
53
|
anchor = 'bottom',
|
|
49
54
|
displayTextProps,
|
|
55
|
+
selectAllLabel = 'Selecionar todos',
|
|
50
56
|
...rest
|
|
51
57
|
}: SelectProps<Data, Type>): JSX.Element => {
|
|
52
58
|
const [dropDownVisible, setDropDownVisible] = React.useState<boolean>(false);
|
|
@@ -62,21 +68,18 @@ export const Select = <Data, Type extends 'single' | 'multi'>({
|
|
|
62
68
|
labelExtractor
|
|
63
69
|
);
|
|
64
70
|
|
|
71
|
+
const onPress = React.useCallback(() => setDropDownVisible(prev => !prev), [
|
|
72
|
+
setDropDownVisible,
|
|
73
|
+
]);
|
|
74
|
+
|
|
65
75
|
return (
|
|
66
76
|
<StyledContainer ref={refDropDown} {...rest}>
|
|
67
77
|
<StyledInputContainer>
|
|
68
78
|
<PressableInputContainer
|
|
69
79
|
label={label}
|
|
70
|
-
onPress={
|
|
80
|
+
onPress={onPress}
|
|
71
81
|
disabled={disabled}
|
|
72
|
-
rightComponent={
|
|
73
|
-
<Icon
|
|
74
|
-
name="chevron-down"
|
|
75
|
-
type="material-community"
|
|
76
|
-
size="centi"
|
|
77
|
-
style={{ marginRight: 12 }}
|
|
78
|
-
/>
|
|
79
|
-
}
|
|
82
|
+
rightComponent={RightComponent}
|
|
80
83
|
>
|
|
81
84
|
<Text {...displayTextProps} ellipsizeMode="tail" numberOfLines={1}>
|
|
82
85
|
{displayValue}
|
|
@@ -98,6 +101,7 @@ export const Select = <Data, Type extends 'single' | 'multi'>({
|
|
|
98
101
|
style={{ ...defaultStyles, ...transition[anchor][state] }}
|
|
99
102
|
setDropDownVisible={setDropDownVisible}
|
|
100
103
|
anchor={anchor}
|
|
104
|
+
selectAllLabel={selectAllLabel}
|
|
101
105
|
/>
|
|
102
106
|
)}
|
|
103
107
|
</Transition>
|