Skip to content

Commit b7838d2

Browse files
committed
add: dropdown v2
1 parent e132764 commit b7838d2

File tree

5 files changed

+9417
-10106
lines changed

5 files changed

+9417
-10106
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@beeinventor/dasiot-react-component-lib",
3-
"version": "1.2.0",
3+
"version": "1.2.1",
44
"module": "lib/index.js",
55
"types": "lib/index.d.ts",
66
"files": [

src/components/Dropdown/Dropdown.stories.tsx

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { Dialog, DialogContent } from '@mui/material';
22
import { Meta, Story } from '@storybook/react';
3-
import React, { useState } from 'react';
3+
import React, { useEffect, useState } from 'react';
44
import Button from '../Button';
55
import Dropdown from './Dropdown';
66
import { DropDownItem, DropDownProps } from './Dropdown.type';
7+
import DropdownV2 from './DropdownV2';
78

89
const list: DropDownItem[] = [
910
{
@@ -150,3 +151,27 @@ Reset.parameters = {
150151
default: 'secondary80',
151152
},
152153
};
154+
155+
export const Version2: Story<DropDownProps> = (args) => {
156+
const [selectedId, setSelectedId] = useState<string | undefined>();
157+
158+
useEffect(() => {
159+
console.log(selectedId);
160+
}, [selectedId]);
161+
162+
return (
163+
<div>
164+
<DropdownV2
165+
{...args}
166+
selectedId={selectedId}
167+
onSelect={(value) => setSelectedId(value as string)}
168+
/>
169+
</div>
170+
);
171+
};
172+
173+
Version2.args = {
174+
mode: 'dark',
175+
list,
176+
placeholder: 'Please Select Item',
177+
};
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
import React, { useState, useEffect, useRef } from 'react';
2+
import classNames from 'classnames';
3+
import { styled } from '@mui/material/styles';
4+
import Box from '@mui/material/Box';
5+
import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
6+
import KeyboardArrowUp from '@mui/icons-material/KeyboardArrowUp';
7+
import Popper from '@mui/material/Popper';
8+
import { DropDownItem, DropDownProps } from './Dropdown.type';
9+
import ClickAwayListener from '@mui/material/ClickAwayListener';
10+
import Icon from '../Icon/Icon';
11+
import CheckSvg from '../../assets/image/svg/check.svg';
12+
13+
const Root = styled(Box)(({ theme }) => ({
14+
...theme.typography.h3,
15+
minWidth: 220,
16+
userSelect: 'none',
17+
cursor: 'pointer',
18+
display: 'flex',
19+
justifyContent: 'space-between',
20+
alignItems: 'center',
21+
color: theme.color.secondary.$80,
22+
backgroundColor: '#FFF',
23+
padding: '8px 0px 8px 16px',
24+
borderRadius: 4,
25+
'&.dark': {
26+
color: 'white',
27+
backgroundColor: 'rgba(0, 0 ,0, 0.2)',
28+
},
29+
'&.Dropdown-empty': {
30+
color: theme.color.secondary.$60,
31+
'&.dark': {
32+
color: theme.color.secondary.$80,
33+
},
34+
},
35+
'&.Dropdown--disabled': {
36+
opacity: 0.3,
37+
pointerEvents: 'none',
38+
},
39+
}));
40+
41+
const List = styled(Box)(({ theme }) => ({
42+
backgroundColor: '#FFF',
43+
margin: '8px auto',
44+
borderRadius: 4,
45+
boxShadow: '0px 4px 4px rgba(0, 0, 0, 0.1)',
46+
'&.dark': {
47+
color: 'white',
48+
backgroundColor: theme.color.secondary.$100,
49+
},
50+
}));
51+
52+
const Item = styled(Box, { label: 'Dropdown-item' })(({ theme }) => ({
53+
...theme.typography.h3,
54+
cursor: 'pointer',
55+
display: 'flex',
56+
alignItems: 'center',
57+
lineHeight: 2.5,
58+
'&:hover': {
59+
backgroundColor: 'rgba(0, 0, 0, .05)',
60+
},
61+
}));
62+
63+
const DropdownV2: React.VFC<DropDownProps> = (props) => {
64+
const {
65+
list,
66+
itemProps,
67+
placeholder,
68+
selectedId,
69+
disabled,
70+
onSelect,
71+
popperProps,
72+
selectionId,
73+
mode = 'light',
74+
...otherProps
75+
} = props;
76+
const selectRef = useRef<HTMLDivElement>(null);
77+
const [selectedItem, setSelectedItem] = useState<DropDownItem | null>(null);
78+
const [isOpen, setIsOpen] = useState(false);
79+
80+
useEffect(() => {
81+
if (selectedId) {
82+
for (let i = 0; i < list.length; i++) {
83+
if (selectedId === list[i].id) {
84+
setSelectedItem(list[i]);
85+
break;
86+
}
87+
}
88+
} else if (selectedId === undefined) {
89+
setSelectedItem(null);
90+
}
91+
}, [selectedId]);
92+
93+
useEffect(() => {
94+
for (let i = 0; i < list.length; i++) {
95+
if (selectedId === list[i].id) {
96+
setSelectedItem(list[i]);
97+
break;
98+
}
99+
}
100+
}, [list]);
101+
102+
const handleOnClickSelect = () => {
103+
setIsOpen(true);
104+
};
105+
106+
const handleOnClickAway = () => {
107+
setIsOpen(false);
108+
};
109+
110+
const handleOnClick = (item: DropDownItem) => {
111+
setIsOpen(false);
112+
setSelectedItem(item);
113+
onSelect(item.value, item);
114+
};
115+
116+
const items = list
117+
.filter((item) => item.id !== selectionId)
118+
.map((item) => (
119+
<Item
120+
key={`dropdown-item-${item.id}`}
121+
className="Dropdown-item"
122+
onClick={() => handleOnClick(item)}
123+
{...itemProps}
124+
>
125+
<Icon className="Dropdown-icon">
126+
{selectedItem?.id === item.id && <img src={CheckSvg} />}
127+
</Icon>
128+
{item.name}
129+
</Item>
130+
));
131+
132+
return (
133+
<>
134+
<Root
135+
ref={selectRef}
136+
className={classNames(
137+
'Dropdown-root',
138+
{
139+
'Dropdown-empty': !selectedItem,
140+
},
141+
{
142+
'Dropdown--disabled': disabled,
143+
},
144+
{
145+
dark: mode === 'dark',
146+
light: mode === 'light',
147+
},
148+
)}
149+
onClick={handleOnClickSelect}
150+
{...otherProps}
151+
>
152+
{selectedItem?.name ?? placeholder}
153+
<Icon className="Dropdown-icon">
154+
{isOpen ? <KeyboardArrowUp /> : <KeyboardArrowDown />}
155+
</Icon>
156+
</Root>
157+
<Popper
158+
anchorEl={selectRef.current}
159+
open={isOpen}
160+
placement="bottom"
161+
{...popperProps}
162+
>
163+
<ClickAwayListener onClickAway={handleOnClickAway}>
164+
<List
165+
className={classNames({
166+
dark: mode === 'dark',
167+
light: mode === 'light',
168+
})}
169+
style={{ width: selectRef.current?.offsetWidth ?? 'auto' }}
170+
>
171+
{items}
172+
</List>
173+
</ClickAwayListener>
174+
</Popper>
175+
</>
176+
);
177+
};
178+
179+
export default DropdownV2;

0 commit comments

Comments
 (0)