pixel-react 1.0.7 → 1.0.9
Sign up to get free protection for your applications and to get access to all the features.
- package/lib/components/AddButton/AddButton.d.ts +5 -0
- package/lib/components/AddButton/AddButton.stories.d.ts +6 -0
- package/lib/components/AddButton/index.d.ts +1 -0
- package/lib/components/AddButton/types.d.ts +4 -0
- package/lib/components/AllProjectsDropdown/AllProjectsDropdown.d.ts +3 -0
- package/lib/components/AllProjectsDropdown/AllProjectsDropdown.stories.d.ts +6 -0
- package/lib/components/AllProjectsDropdown/index.d.ts +1 -0
- package/lib/components/AppHeader/AppHeader.d.ts +4 -0
- package/lib/components/AppHeader/AppHeader.stories.d.ts +7 -0
- package/lib/components/AppHeader/index.d.ts +1 -0
- package/lib/components/AppHeader/types.d.ts +26 -0
- package/lib/components/GridLayout/types.d.ts +17 -0
- package/lib/components/Input/types.d.ts +1 -1
- package/lib/components/InputWithDropdown/types.d.ts +1 -1
- package/lib/components/Modal/types.d.ts +2 -0
- package/lib/components/MultiSelect/MultiSelect.d.ts +1 -1
- package/lib/components/MultiSelect/MultiSelect.stories.d.ts +1 -0
- package/lib/components/MultiSelect/MultiSelectTypes.d.ts +3 -0
- package/lib/index.d.ts +56 -4
- package/lib/index.esm.js +358 -97
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +359 -96
- package/lib/index.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/assets/Themes/BaseTheme.scss +5 -0
- package/src/assets/Themes/DarkTheme.scss +3 -0
- package/src/assets/icons/all_projects.svg +3 -0
- package/src/assets/icons/android_icon.svg +6 -0
- package/src/assets/icons/download_icon.svg +4 -0
- package/src/assets/icons/fireflink_icon.svg +4 -0
- package/src/assets/icons/fireflink_logo.svg +13 -0
- package/src/assets/icons/mobile_icon.svg +3 -0
- package/src/assets/icons/ms_dynamic.svg +4 -0
- package/src/assets/icons/sales_force.svg +7 -0
- package/src/assets/icons/switch_license_icon.svg +123 -0
- package/src/assets/icons/vertical_separator.svg +3 -0
- package/src/assets/icons/web&mobile_icon.svg +3 -0
- package/src/assets/icons/web_icon.svg +3 -0
- package/src/assets/styles/_colors.scss +2 -1
- package/src/components/AllProjectsDropdown/AllProjectsDropdown.scss +70 -0
- package/src/components/AllProjectsDropdown/AllProjectsDropdown.stories.tsx +21 -0
- package/src/components/AllProjectsDropdown/AllProjectsDropdown.tsx +148 -0
- package/src/components/AllProjectsDropdown/index.ts +1 -0
- package/src/components/AppHeader/AppHeader.scss +67 -0
- package/src/components/AppHeader/AppHeader.stories.tsx +156 -0
- package/src/components/AppHeader/AppHeader.tsx +124 -0
- package/src/components/AppHeader/index.ts +1 -0
- package/src/components/AppHeader/types.ts +27 -0
- package/src/components/GridLayout/GridLayout.stories.tsx +13 -51
- package/src/components/GridLayout/GridLayout.tsx +9 -7
- package/src/components/GridLayout/types.ts +20 -0
- package/src/components/Icon/iconList.ts +26 -0
- package/src/components/IconButton/IconButton.scss +2 -1
- package/src/components/Input/types.ts +1 -1
- package/src/components/InputWithDropdown/types.ts +1 -3
- package/src/components/Modal/Modal.stories.tsx +6 -2
- package/src/components/Modal/Modal.tsx +6 -2
- package/src/components/Modal/modal.scss +6 -4
- package/src/components/Modal/types.ts +2 -0
- package/src/components/MultiSelect/MultiSelect.scss +8 -1
- package/src/components/MultiSelect/MultiSelect.stories.tsx +26 -0
- package/src/components/MultiSelect/MultiSelect.tsx +68 -12
- package/src/components/MultiSelect/MultiSelectTypes.ts +3 -0
- package/src/components/Select/Select.scss +1 -1
- package/src/index.ts +5 -0
- package/lib/components/ThemeProvider/CustomThemeProvider.d.ts +0 -8
- package/lib/hooks/useCustomThemeProvider.d.ts +0 -11
@@ -25,6 +25,13 @@ export interface ContainerProps {
|
|
25
25
|
* @type {string}
|
26
26
|
*/
|
27
27
|
gap?: string;
|
28
|
+
|
29
|
+
/**
|
30
|
+
* Classname for Container
|
31
|
+
* @default ''
|
32
|
+
* @type {string}
|
33
|
+
*/
|
34
|
+
className?:string
|
28
35
|
}
|
29
36
|
|
30
37
|
export interface RowProps {
|
@@ -43,6 +50,12 @@ export interface RowProps {
|
|
43
50
|
* @type {string}
|
44
51
|
*/
|
45
52
|
gap?: string;
|
53
|
+
|
54
|
+
/**
|
55
|
+
* @default ''
|
56
|
+
* @type string
|
57
|
+
*/
|
58
|
+
className?:string
|
46
59
|
}
|
47
60
|
|
48
61
|
export interface ColProps {
|
@@ -61,4 +74,11 @@ export interface ColProps {
|
|
61
74
|
* @type {number}
|
62
75
|
*/
|
63
76
|
size?: number;
|
77
|
+
|
78
|
+
/**
|
79
|
+
* @default ''
|
80
|
+
* @type string
|
81
|
+
*
|
82
|
+
*/
|
83
|
+
className?: string;
|
64
84
|
}
|
@@ -26,6 +26,7 @@ import MoonStarsIcon from '../../assets/icons/moon_stars.svg?react';
|
|
26
26
|
import SunIcon from '../../assets/icons/sun_icon.svg?react';
|
27
27
|
import CheckMarkIcon from '../../assets/icons/check_mark.svg?react';
|
28
28
|
import WrongMarkIcon from '../../assets/icons/wrong_mark.svg?react';
|
29
|
+
import FireflinkIcon from '../../assets/Icons/fireflink_icon.svg?react';
|
29
30
|
import Tick from '../../assets/Icons/tick_icon.svg?react';
|
30
31
|
import Search from '../../assets/icons/search.svg?react';
|
31
32
|
import Filter from '../../assets/icons/filter.svg?react';
|
@@ -45,6 +46,7 @@ import ImpactListIcon from '../../assets/icons/impactList.svg?react';
|
|
45
46
|
import InfoIcon from '../../assets/icons/info_icon.svg?react';
|
46
47
|
import CalendarIcon from '../../assets/icons/calendar_icon.svg?react';
|
47
48
|
import HideIcon from '../../assets/icons/hide_icon.svg?react';
|
49
|
+
import VerticalSeparator from '../../assets/icons/vertical_separator.svg?react';
|
48
50
|
import CollapseIcon from '../../assets/icons/collapse-icon.svg?react';
|
49
51
|
import ExpandIcon from '../../assets/icons/expand-icon.svg?react';
|
50
52
|
import CopyIcon from '../../assets/icons/copy-icon.svg?react';
|
@@ -52,6 +54,17 @@ import DownloadFile from '../../assets/icons/download-icon.svg?react';
|
|
52
54
|
import RefreshIcon from '../../assets/icons/refresh-icon.svg?react';
|
53
55
|
import LicenseInfo from '../../assets/icons/license_info.svg?react';
|
54
56
|
import LicenseWarning from '../../assets/icons/license_warning.svg?react';
|
57
|
+
import DownloadIcon from '../../assets/icons/download_icon.svg?react';
|
58
|
+
import WebIcon from '../../assets/icons/web_icon.svg?react';
|
59
|
+
import WebMobileIcon from '../../assets/icons/web&mobile_icon.svg?react';
|
60
|
+
import MobileIcon from '../../assets/icons/mobile_icon.svg?react';
|
61
|
+
import SalesForceIcon from '../../assets/icons/sales_force.svg?react';
|
62
|
+
import MSDynamicIcon from '../../assets/icons/ms_dynamic.svg?react';
|
63
|
+
import AllProjectsIcon from '../../assets/icons/all_projects.svg?react';
|
64
|
+
import AndroidIcon from '../../assets/icons/android_icon.svg?react';
|
65
|
+
|
66
|
+
import SwitchLicenseIcon from '../../assets/icons/switch_license_icon.svg?react';
|
67
|
+
import FireflinkLogo from '../../assets/icons/fireflink_logo.svg?react';
|
55
68
|
//icons
|
56
69
|
Components['delete_info'] = DeleteInfoIcon;
|
57
70
|
Components['success'] = ToastSuccessIcon;
|
@@ -78,6 +91,7 @@ Components['moon_stars_icon'] = MoonStarsIcon;
|
|
78
91
|
Components['sun_icon'] = SunIcon;
|
79
92
|
Components['check_mark'] = CheckMarkIcon;
|
80
93
|
Components['wrong_mark'] = WrongMarkIcon;
|
94
|
+
Components['fireflink_icon'] = FireflinkIcon;
|
81
95
|
Components['tick'] = Tick;
|
82
96
|
Components['arrow_right'] = ArrowRight;
|
83
97
|
Components['search'] = Search;
|
@@ -97,6 +111,7 @@ Components['add_variable'] = AddVariable;
|
|
97
111
|
Components['info'] = InfoIcon;
|
98
112
|
Components['calendar_icon'] = CalendarIcon;
|
99
113
|
Components['hide_icon'] = HideIcon;
|
114
|
+
Components['vertical_separator'] = VerticalSeparator;
|
100
115
|
Components['collapse_icon'] = CollapseIcon;
|
101
116
|
Components['refresh_icon'] = RefreshIcon;
|
102
117
|
Components['download_file'] = DownloadFile;
|
@@ -104,5 +119,16 @@ Components['copy_icon'] = CopyIcon;
|
|
104
119
|
Components['expand_icon'] = ExpandIcon;
|
105
120
|
Components['license_info'] = LicenseInfo;
|
106
121
|
Components['license_warning'] = LicenseWarning;
|
122
|
+
Components['download_icon'] = DownloadIcon;
|
123
|
+
Components['web_icon'] = WebIcon;
|
124
|
+
Components['web&mobile_icon'] = WebMobileIcon;
|
125
|
+
Components['mobile_icon'] = MobileIcon;
|
126
|
+
Components['sales_force'] = SalesForceIcon;
|
127
|
+
Components['ms_dynamic'] = MSDynamicIcon;
|
128
|
+
Components['all_projects'] = AllProjectsIcon;
|
129
|
+
Components['android_icon'] = AndroidIcon;
|
130
|
+
|
131
|
+
Components['select_license'] = SwitchLicenseIcon;
|
132
|
+
Components['fireflink-logo'] = FireflinkLogo;
|
107
133
|
|
108
134
|
export default Components;
|
@@ -21,8 +21,8 @@
|
|
21
21
|
}
|
22
22
|
.icon-name {
|
23
23
|
min-width: 33px;
|
24
|
-
min-height: 20px;
|
25
24
|
color: var(--primary-icon-color);
|
25
|
+
@include mixins.center-content();
|
26
26
|
}
|
27
27
|
&:hover {
|
28
28
|
border: 1px solid var(--secondary-icon-color);
|
@@ -32,6 +32,7 @@
|
|
32
32
|
min-height: 20px;
|
33
33
|
font-weight: 600;
|
34
34
|
color: var(--secondary-icon-color);
|
35
|
+
@include mixins.center-content();
|
35
36
|
}
|
36
37
|
.ff-icon-color {
|
37
38
|
path {
|
@@ -14,7 +14,7 @@ export interface InputWithDropdownProps {
|
|
14
14
|
/**
|
15
15
|
* Label | field label to be displayed
|
16
16
|
*/
|
17
|
-
label
|
17
|
+
label?: string;
|
18
18
|
|
19
19
|
/**
|
20
20
|
* value | input field value
|
@@ -26,8 +26,6 @@ export interface InputWithDropdownProps {
|
|
26
26
|
*/
|
27
27
|
variant?: 'default' | 'primary';
|
28
28
|
|
29
|
-
|
30
|
-
|
31
29
|
/**
|
32
30
|
* error | If true, error message will be displayed
|
33
31
|
*/
|
@@ -22,8 +22,10 @@ export const DefaultModalStory: Story = {
|
|
22
22
|
isHeaderDisplayed: true,
|
23
23
|
headerContent: <h2>title</h2>,
|
24
24
|
children: <h2>Hello</h2>,
|
25
|
-
isFooterDisplayed:true,
|
25
|
+
isFooterDisplayed: true,
|
26
26
|
footerContent: <Button variant="primary" label="continue" />,
|
27
|
+
customWidth: '660px',
|
28
|
+
customHeight: 'auto',
|
27
29
|
},
|
28
30
|
};
|
29
31
|
|
@@ -52,7 +54,9 @@ export const Controlled: Story = {
|
|
52
54
|
children={<div>Hello</div>}
|
53
55
|
ariaHideApp={true}
|
54
56
|
isFooterDisplayed={true}
|
55
|
-
footerContent={<Button variant="primary" label=
|
57
|
+
footerContent={<Button variant="primary" label="continue" />}
|
58
|
+
customWidth="660px"
|
59
|
+
customHeight="auto"
|
56
60
|
/>
|
57
61
|
)}
|
58
62
|
</>
|
@@ -4,7 +4,6 @@ import './modal.scss';
|
|
4
4
|
import { ModalProps } from './types';
|
5
5
|
import { ThemeContext } from '../ThemeProvider/ThemeProvider';
|
6
6
|
|
7
|
-
|
8
7
|
const Modal: React.FC<ModalProps> = ({
|
9
8
|
isOpen,
|
10
9
|
onClose,
|
@@ -18,6 +17,8 @@ const Modal: React.FC<ModalProps> = ({
|
|
18
17
|
shouldCloseOnEsc = true,
|
19
18
|
ariaHideApp = true,
|
20
19
|
shouldCloseOnOverlayClick = true,
|
20
|
+
customWidth = '660px', // default width
|
21
|
+
customHeight = 'auto', // default height
|
21
22
|
children,
|
22
23
|
}) => {
|
23
24
|
useEffect(() => {
|
@@ -52,6 +53,7 @@ const Modal: React.FC<ModalProps> = ({
|
|
52
53
|
>
|
53
54
|
<div
|
54
55
|
className={`ff-modal-content ${currentTheme} ${contentClassName || ''}`}
|
56
|
+
style={{ width: customWidth, height: customHeight }}
|
55
57
|
onClick={(e) => e.stopPropagation()}
|
56
58
|
aria-label={contentLabel}
|
57
59
|
>
|
@@ -61,7 +63,9 @@ const Modal: React.FC<ModalProps> = ({
|
|
61
63
|
{children}
|
62
64
|
</div>
|
63
65
|
{isFooterDisplayed && (
|
64
|
-
<div className="ff-modal-footer"
|
66
|
+
<div className="ff-modal-footer" style={{ width: customWidth }}>
|
67
|
+
{footerContent}
|
68
|
+
</div>
|
65
69
|
)}
|
66
70
|
</div>,
|
67
71
|
document.body
|
@@ -1,4 +1,5 @@
|
|
1
1
|
@use '../../assets/styles/mixins' as *;
|
2
|
+
|
2
3
|
.ff-modal-overlay {
|
3
4
|
position: fixed;
|
4
5
|
top: 0;
|
@@ -13,18 +14,19 @@
|
|
13
14
|
.ff-modal-content {
|
14
15
|
background: var(--ff-mini-modal-border);
|
15
16
|
position: relative;
|
16
|
-
max-width:
|
17
|
-
width: 100%;
|
17
|
+
max-width: 100%;
|
18
18
|
border-radius: 12px 12px 0 0;
|
19
19
|
padding: 16px;
|
20
|
+
|
20
21
|
.ff-modal-header {
|
21
22
|
height: 32px;
|
22
|
-
width:
|
23
|
+
width: 100%;
|
23
24
|
}
|
24
25
|
}
|
26
|
+
|
25
27
|
.ff-modal-footer {
|
26
28
|
background-color: var(--expandable-menu-option-bg);
|
27
|
-
max-width:
|
29
|
+
max-width: 100%;
|
28
30
|
width: 100%;
|
29
31
|
height: 32px;
|
30
32
|
border-radius: 0 0 12px 12px;
|
@@ -108,6 +108,13 @@
|
|
108
108
|
}
|
109
109
|
}
|
110
110
|
}
|
111
|
+
.ff-multiselect-more-chip{
|
112
|
+
width: 1rem;
|
113
|
+
@extend .fontXs;
|
114
|
+
font-weight: 600;
|
115
|
+
line-height: 16px;
|
116
|
+
color: var(--brand-color);
|
117
|
+
}
|
111
118
|
}
|
112
119
|
}
|
113
120
|
&__toggle {
|
@@ -182,7 +189,7 @@
|
|
182
189
|
.error-text {
|
183
190
|
@extend .font-size-8;
|
184
191
|
position: absolute;
|
185
|
-
top:
|
192
|
+
margin-top: 0.25rem;
|
186
193
|
left: 12px;
|
187
194
|
color: var(--error-light);
|
188
195
|
letter-spacing: 0.5px;
|
@@ -52,6 +52,32 @@ export const Default3: Story = {
|
|
52
52
|
...defaultArgs,
|
53
53
|
},
|
54
54
|
};
|
55
|
+
export const EmailGroup: Story = {
|
56
|
+
render: () => {
|
57
|
+
const [options] = useState([
|
58
|
+
{ label: 'Sample1@gmail.com', value: 'sample1@gmail.com' },
|
59
|
+
{ label: 'Sample2@gmail.com', value: 'sample2@gmail.com' },
|
60
|
+
]);
|
61
|
+
const [selectedOptions, setSelectedOptions] = useState<
|
62
|
+
{ label?: string; value?: string }[]
|
63
|
+
>([{ label: 'Sample1@gmail.com', value: 'sample1@gmail.com'}]);
|
64
|
+
const onChange = (options: { label?: string; value?: string }[]) => {
|
65
|
+
setSelectedOptions(options);
|
66
|
+
};
|
67
|
+
return (
|
68
|
+
<MultiSelect
|
69
|
+
label={'Enter Email'}
|
70
|
+
type='email'
|
71
|
+
required
|
72
|
+
options={options}
|
73
|
+
selectedOptions={selectedOptions}
|
74
|
+
onChange={onChange}
|
75
|
+
acceptNewOption={true}
|
76
|
+
displayCount={true}
|
77
|
+
/>
|
78
|
+
);
|
79
|
+
},
|
80
|
+
};
|
55
81
|
|
56
82
|
export const Controlled: Story = {
|
57
83
|
render: () => {
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import { useEffect, useRef, useState } from 'react';
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
2
2
|
import { createPortal } from 'react-dom';
|
3
3
|
import classNames from 'classnames';
|
4
4
|
import './MultiSelect.scss';
|
@@ -30,8 +30,10 @@ const ChipElement = ({
|
|
30
30
|
};
|
31
31
|
const MultiSelect = ({
|
32
32
|
options,
|
33
|
+
type = "text",
|
33
34
|
selectedOptions = [],
|
34
35
|
onChange = () => {},
|
36
|
+
acceptNewOption = false,
|
35
37
|
zIndex = 100,
|
36
38
|
label = '',
|
37
39
|
onSearch = () => {},
|
@@ -40,6 +42,7 @@ const MultiSelect = ({
|
|
40
42
|
errorMessage = 'Fill this field',
|
41
43
|
withSelectButton = false,
|
42
44
|
onSelect = () => {},
|
45
|
+
displayCount = false
|
43
46
|
}: MultiSelectProps) => {
|
44
47
|
const [isOpen, setIsOpen] = useState<boolean>(false);
|
45
48
|
const [allOptions, setAllOptions] = useState(options);
|
@@ -47,6 +50,7 @@ const MultiSelect = ({
|
|
47
50
|
const [searchedKeyword, setSearchedKeyword] = useState('');
|
48
51
|
const [isSelectFocusedOnce, setIsSelectFocusedOnce] =
|
49
52
|
useState<boolean>(false);
|
53
|
+
const [inputError, setInputError] = useState<string>('')
|
50
54
|
|
51
55
|
const [dropdownPosition, setDropdownPosition] = useState<{
|
52
56
|
top: number;
|
@@ -67,6 +71,9 @@ const MultiSelect = ({
|
|
67
71
|
const selectWrapper = useRef<HTMLInputElement>(null);
|
68
72
|
let isFieldSkipped = isSelectFocusedOnce && selectedOptions.length === 0;
|
69
73
|
|
74
|
+
const maxVisibleChips = 2;
|
75
|
+
const hiddenCount = selectedOptions.length - maxVisibleChips;
|
76
|
+
|
70
77
|
const handleClick = () => {
|
71
78
|
if (!isOpen) {
|
72
79
|
setIsOpen(true);
|
@@ -102,6 +109,32 @@ const MultiSelect = ({
|
|
102
109
|
e.stopPropagation();
|
103
110
|
handleOptionChange(option, false);
|
104
111
|
};
|
112
|
+
const handleKeyEnter = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
113
|
+
if (acceptNewOption && e.key === "Enter") {
|
114
|
+
setInputError('');
|
115
|
+
if (type === "email") {
|
116
|
+
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
117
|
+
if (!emailPattern.test(searchedKeyword)) {
|
118
|
+
setIsOpen(false);
|
119
|
+
setInputError("Please enter a valid email address.");
|
120
|
+
return;
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
const newOption = {
|
125
|
+
label: searchedKeyword,
|
126
|
+
value: searchedKeyword.toLowerCase(),
|
127
|
+
isChecked: true,
|
128
|
+
};
|
129
|
+
const filteredOptions = [...allOptions].filter(option => option.isChecked === true);
|
130
|
+
|
131
|
+
setAllOptions([...allOptions, newOption]);
|
132
|
+
setSearchedKeyword('');
|
133
|
+
onChange?.([...filteredOptions, { label: searchedKeyword, value: searchedKeyword.toLocaleLowerCase() }]);
|
134
|
+
setIsOpen(false);
|
135
|
+
}
|
136
|
+
};
|
137
|
+
|
105
138
|
const calculatePosition = () => {
|
106
139
|
if (dropdownWrapper.current && selectWrapper.current) {
|
107
140
|
const rect = dropdownWrapper.current?.getBoundingClientRect();
|
@@ -159,6 +192,7 @@ const MultiSelect = ({
|
|
159
192
|
!dropdownRef.current.contains(event?.target as Node) &&
|
160
193
|
!selectWrapper.current.contains(event?.target as Node)
|
161
194
|
) {
|
195
|
+
setInputError('')
|
162
196
|
setIsOpen(false);
|
163
197
|
if (!isSelectFocusedOnce) {
|
164
198
|
setIsSelectFocusedOnce(true);
|
@@ -179,7 +213,7 @@ const MultiSelect = ({
|
|
179
213
|
className={classNames('ff-multiselect-wrapper', {
|
180
214
|
'ff-multiselect-wrapper--with-options': selectedOptions?.length,
|
181
215
|
'ff-multiselect-wrapper--opened-dropdown': isOpen,
|
182
|
-
'ff-multiselect-wrapper--error': isFieldSkipped && required,
|
216
|
+
'ff-multiselect-wrapper--error': (isFieldSkipped && required) || inputError,
|
183
217
|
'ff-multiselect-wrapper--disabled': disabled,
|
184
218
|
})}
|
185
219
|
>
|
@@ -197,15 +231,28 @@ const MultiSelect = ({
|
|
197
231
|
{label}
|
198
232
|
</span>
|
199
233
|
<div className="ff-multiselect-chip-container">
|
200
|
-
{
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
234
|
+
{displayCount ?
|
235
|
+
<>
|
236
|
+
{selectedOptions.slice(0, maxVisibleChips).map((option) => (
|
237
|
+
<ChipElement
|
238
|
+
key={option?.label}
|
239
|
+
label={option?.label || ''}
|
240
|
+
onChipCloseClick={(e) => handleChipCloseClick(option, e)}
|
241
|
+
/>
|
242
|
+
))}
|
243
|
+
</> :
|
244
|
+
selectedOptions.map((option) => (
|
245
|
+
<ChipElement
|
246
|
+
key={option?.label}
|
247
|
+
label={option?.label || ''}
|
248
|
+
onChipCloseClick={(e) => handleChipCloseClick(option, e)}
|
249
|
+
/>
|
250
|
+
))
|
251
|
+
}
|
207
252
|
<div className="ff-multiselect-input-container">
|
208
253
|
<input
|
254
|
+
value={searchedKeyword}
|
255
|
+
type={type}
|
209
256
|
autoComplete="off"
|
210
257
|
placeholder="search..."
|
211
258
|
ref={inputRef}
|
@@ -216,6 +263,7 @@ const MultiSelect = ({
|
|
216
263
|
setSearchedKeyword(e.target.value);
|
217
264
|
onSearch?.(e.target.value);
|
218
265
|
}}
|
266
|
+
onKeyDown={handleKeyEnter}
|
219
267
|
id="input-ele"
|
220
268
|
className="ff-select-input"
|
221
269
|
style={{
|
@@ -224,6 +272,14 @@ const MultiSelect = ({
|
|
224
272
|
}}
|
225
273
|
/>
|
226
274
|
</div>
|
275
|
+
{hiddenCount > 0 && (
|
276
|
+
<div
|
277
|
+
className="ff-multiselect-more-chip"
|
278
|
+
onClick={toggleDropdown}
|
279
|
+
>
|
280
|
+
+{hiddenCount}
|
281
|
+
</div>
|
282
|
+
)}
|
227
283
|
</div>
|
228
284
|
</div>
|
229
285
|
<div onClick={toggleDropdown} className="ff-multiselect__toggle">
|
@@ -238,8 +294,8 @@ const MultiSelect = ({
|
|
238
294
|
</div>
|
239
295
|
</div>
|
240
296
|
<div ref={dropdownWrapper}>
|
241
|
-
{isFieldSkipped && required && errorMessage && (
|
242
|
-
<div className="error-text">{errorMessage}</div>
|
297
|
+
{(inputError || (isFieldSkipped && required && errorMessage)) && (
|
298
|
+
<div className="error-text">{inputError || errorMessage }</div>
|
243
299
|
)}
|
244
300
|
{isOpen &&
|
245
301
|
createPortal(
|
@@ -261,4 +317,4 @@ const MultiSelect = ({
|
|
261
317
|
);
|
262
318
|
};
|
263
319
|
|
264
|
-
export default MultiSelect;
|
320
|
+
export default MultiSelect;
|
@@ -6,16 +6,19 @@ interface Option {
|
|
6
6
|
}
|
7
7
|
interface MultiSelectProps {
|
8
8
|
options: Option[];
|
9
|
+
type? : 'email' | 'text';
|
9
10
|
label: string;
|
10
11
|
selectedOptions?: Option[];
|
11
12
|
disabled?: boolean;
|
12
13
|
onSearch?: (searchedKeyword: string) => void;
|
13
14
|
onChange?: (selectedOptions: Option[]) => void;
|
15
|
+
acceptNewOption?: boolean;
|
14
16
|
zIndex?: number;
|
15
17
|
required?: boolean;
|
16
18
|
errorMessage?: string;
|
17
19
|
withSelectButton?: boolean;
|
18
20
|
onSelect?: () => void;
|
21
|
+
displayCount?:boolean;
|
19
22
|
}
|
20
23
|
|
21
24
|
export { Option, MultiSelectProps };
|
package/src/index.ts
CHANGED
@@ -36,7 +36,9 @@ import Search from './components/Search/Search';
|
|
36
36
|
import DatePicker from './components/DatePicker';
|
37
37
|
import StateDropdown from './components/StateDropdown';
|
38
38
|
import IconButton from './components/IconButton';
|
39
|
+
import Modal from './components/Modal';
|
39
40
|
import DragAndDrop from './components/DragAndDrop/DragAndDrop';
|
41
|
+
import AllProjectsDropdown from './components/AllProjectsDropdown';
|
40
42
|
|
41
43
|
// Utils imports
|
42
44
|
import { checkEmpty } from './utils/checkEmpty/checkEmpty';
|
@@ -86,7 +88,10 @@ export {
|
|
86
88
|
StateDropdown,
|
87
89
|
StatusButton,
|
88
90
|
IconButton,
|
91
|
+
Modal,
|
92
|
+
|
89
93
|
DragAndDrop,
|
94
|
+
AllProjectsDropdown,
|
90
95
|
|
91
96
|
// utils exports
|
92
97
|
checkEmpty,
|
@@ -1,8 +0,0 @@
|
|
1
|
-
import React, { ReactNode } from 'react';
|
2
|
-
import { ThemeContextType } from './types';
|
3
|
-
declare const ThemeContext: React.Context<ThemeContextType | undefined>;
|
4
|
-
declare const CustomThemeProvider: React.FC<{
|
5
|
-
children: ReactNode;
|
6
|
-
}>;
|
7
|
-
export { ThemeContext };
|
8
|
-
export default CustomThemeProvider;
|
@@ -1,11 +0,0 @@
|
|
1
|
-
import React, { ReactNode } from 'react';
|
2
|
-
interface ThemeContextType {
|
3
|
-
currentTheme: string;
|
4
|
-
setCurrentTheme: React.Dispatch<React.SetStateAction<string>>;
|
5
|
-
applyTheme: (newTheme: string) => void;
|
6
|
-
}
|
7
|
-
export declare const useCustomThemeProvider: React.FC<{
|
8
|
-
children: ReactNode;
|
9
|
-
}>;
|
10
|
-
export declare const useTheme: () => ThemeContextType;
|
11
|
-
export {};
|