pixel-react 1.4.2 → 1.4.4
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/.yarn/install-state.gz +0 -0
- package/lib/components/AddResourceButton/type.d.ts +1 -1
- package/lib/components/Drawer/Types.d.ts +4 -0
- package/lib/components/Excel/ExcelContextMenu/ExcelContextMenu.d.ts +13 -0
- package/lib/components/Excel/ExcelFile/ExcelFileComponents/Spreadsheet.d.ts +0 -13
- package/lib/components/Excel/ExcelFile/ExcelFileComponents/actions.d.ts +29 -1
- package/lib/components/Excel/ExcelFile/ExcelFileComponents/engine/engine.d.ts +3 -9
- package/lib/components/Excel/ExcelFile/ExcelFileComponents/engine/formula.d.ts +2 -10
- package/lib/components/Excel/ExcelFile/ExcelFileComponents/engine/point-graph.d.ts +0 -1
- package/lib/components/Excel/ExcelFile/ExcelFileComponents/types.d.ts +27 -2
- package/lib/components/Form/Forms.d.ts +4 -2
- package/lib/components/InputWithDropdown/InputWithDropdown.d.ts +1 -1
- package/lib/components/MenuOption/MenuOption.d.ts +1 -1
- package/lib/components/MenuOption/types.d.ts +49 -15
- package/lib/components/MiniModal/types.d.ts +1 -1
- package/lib/components/MultiSelect/MultiSelect.d.ts +1 -1
- package/lib/components/MultiSelect/MultiSelectTypes.d.ts +4 -5
- package/lib/components/MultiSelect/dropdownTypes.d.ts +2 -0
- package/lib/components/RadioButton/RadioButton.d.ts +1 -0
- package/lib/components/RadioButton/radioButtonTypes.d.ts +3 -1
- package/lib/components/Select/components/types.d.ts +4 -2
- package/lib/components/Table/Table.d.ts +1 -1
- package/lib/components/ToggleSwitch/ToggleSwitch.d.ts +10 -0
- package/lib/components/ToggleSwitch/index.d.ts +1 -0
- package/lib/index.d.ts +110 -24
- package/lib/index.esm.js +5732 -648
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +5728 -642
- package/lib/index.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +11 -11
- package/src/StyleGuide/ColorPalette/colorPaletteList.ts +10 -0
- package/src/assets/Themes/BaseTheme.scss +17 -23
- package/src/assets/Themes/DarkTheme.scss +25 -38
- package/src/assets/icons/apk_file_type.svg +4 -0
- package/src/assets/icons/compressed_file_type.svg +4 -0
- package/src/assets/icons/csv_file_type.svg +4 -0
- package/src/assets/icons/excel_corner_menu.svg +3 -0
- package/src/assets/icons/formula_icon.svg +3 -0
- package/src/assets/icons/gif_file_type.svg +4 -0
- package/src/assets/icons/html_file_type.svg +4 -0
- package/src/assets/icons/ipk_file_type.svg +4 -0
- package/src/assets/icons/jpg_file_type.svg +4 -0
- package/src/assets/icons/json_file_type.svg +4 -0
- package/src/assets/icons/pdf_file_type.svg +4 -0
- package/src/assets/icons/png_file_type.svg +4 -0
- package/src/assets/icons/quick_run_setting_icon.svg +5 -0
- package/src/assets/icons/run_automation_scripts_icon.svg +33 -0
- package/src/assets/icons/run_manual_testcase_icon.svg +4 -0
- package/src/assets/icons/search.svg +2 -2
- package/src/assets/icons/txt_file_type.svg +4 -0
- package/src/assets/icons/xls_file_type.svg +4 -0
- package/src/assets/icons/xlsx_file_type.svg +4 -0
- package/src/assets/icons/xml_file_type.svg +4 -0
- package/src/assets/styles/_fonts.scss +32 -2
- package/src/components/AddResourceButton/AddButton.tsx +7 -7
- package/src/components/AddResourceButton/type.ts +1 -1
- package/src/components/AttachmentButton/AttachmentButton.scss +1 -1
- package/src/components/AttachmentButton/AttachmentButton.stories.tsx +1 -0
- package/src/components/Button/Button.scss +22 -20
- package/src/components/Button/Button.tsx +8 -1
- package/src/components/Charts/DashboardDonutChart/DashboardDonutChart.tsx +2 -2
- package/src/components/Drawer/Drawer.scss +4 -3
- package/src/components/Drawer/Drawer.tsx +14 -18
- package/src/components/Drawer/Types.ts +4 -0
- package/src/components/Editor/Editor.tsx +9 -11
- package/src/components/Excel/ExcelContextMenu/ExcelContextMenu.scss +39 -0
- package/src/components/Excel/ExcelContextMenu/ExcelContextMenu.tsx +51 -0
- package/src/components/Excel/ExcelFile/ExcelFile.tsx +7 -8
- package/src/components/Excel/ExcelFile/ExcelFileComponents/Cell.tsx +35 -0
- package/src/components/Excel/ExcelFile/ExcelFileComponents/ColumnIndicator.tsx +44 -7
- package/src/components/Excel/ExcelFile/ExcelFileComponents/CornerIndicator.tsx +8 -1
- package/src/components/Excel/ExcelFile/ExcelFileComponents/RowIndicator.tsx +45 -6
- package/src/components/Excel/ExcelFile/ExcelFileComponents/Spreadsheet.scss +37 -2
- package/src/components/Excel/ExcelFile/ExcelFileComponents/Spreadsheet.tsx +69 -24
- package/src/components/Excel/ExcelFile/ExcelFileComponents/actions.ts +59 -0
- package/src/components/Excel/ExcelFile/ExcelFileComponents/engine/engine.ts +18 -65
- package/src/components/Excel/ExcelFile/ExcelFileComponents/engine/formula.ts +5 -110
- package/src/components/Excel/ExcelFile/ExcelFileComponents/engine/point-graph.ts +0 -2
- package/src/components/Excel/ExcelFile/ExcelFileComponents/reducer.ts +105 -1
- package/src/components/Excel/ExcelFile/ExcelFileComponents/reducerFunctions.ts +670 -673
- package/src/components/Excel/ExcelFile/ExcelFileComponents/types.ts +38 -2
- package/src/components/Excel/ExcelToolBar/ExcelToolBar.tsx +0 -4
- package/src/components/FileDropzone/FileDropzone.scss +4 -2
- package/src/components/FileDropzone/FileDropzone.tsx +1 -1
- package/src/components/FileDropzone/FilePreview.tsx +3 -1
- package/src/components/Form/Form.scss +2 -0
- package/src/components/Form/Form.stories.tsx +195 -6
- package/src/components/Form/Forms.tsx +15 -8
- package/src/components/Icon/iconList.ts +46 -0
- package/src/components/IconRadioGroup/IconRadioGroup.scss +3 -0
- package/src/components/IconRadioGroup/IconRadioGroup.tsx +20 -17
- package/src/components/Input/Input.scss +14 -15
- package/src/components/Input/Input.stories.tsx +2 -1
- package/src/components/InputWithDropdown/InputWithDropdown.scss +12 -13
- package/src/components/InputWithDropdown/InputWithDropdown.stories.tsx +3 -2
- package/src/components/InputWithDropdown/InputWithDropdown.tsx +22 -19
- package/src/components/MenuOption/MenuOption.scss +11 -10
- package/src/components/MenuOption/MenuOption.stories.tsx +51 -232
- package/src/components/MenuOption/MenuOption.tsx +131 -52
- package/src/components/MenuOption/types.ts +55 -14
- package/src/components/MiniModal/MiniModal.stories.tsx +7 -6
- package/src/components/MiniModal/MiniModal.tsx +29 -23
- package/src/components/MiniModal/types.ts +1 -1
- package/src/components/MultiSelect/Dropdown.tsx +11 -12
- package/src/components/MultiSelect/MultiSelect.scss +1 -0
- package/src/components/MultiSelect/MultiSelect.stories.tsx +45 -10
- package/src/components/MultiSelect/MultiSelect.tsx +29 -13
- package/src/components/MultiSelect/MultiSelectTypes.ts +7 -5
- package/src/components/MultiSelect/dropdownTypes.ts +2 -0
- package/src/components/RadioButton/RadioButton.scss +3 -1
- package/src/components/RadioButton/RadioButton.tsx +3 -1
- package/src/components/RadioButton/radioButtonTypes.tsx +5 -1
- package/src/components/Search/Search.scss +25 -6
- package/src/components/Search/Search.tsx +45 -24
- package/src/components/Select/Select.scss +12 -12
- package/src/components/Select/Select.stories.tsx +2 -0
- package/src/components/Select/Select.tsx +11 -5
- package/src/components/Select/components/Dropdown.scss +2 -0
- package/src/components/Select/components/Dropdown.tsx +19 -4
- package/src/components/Select/components/types.ts +4 -2
- package/src/components/StatusButton/StatusButton.tsx +26 -20
- package/src/components/Table/Table.scss +1 -3
- package/src/components/Table/Table.stories.tsx +1 -0
- package/src/components/Table/Table.tsx +7 -3
- package/src/components/ToggleSwitch/ToggleSwitch.scss +59 -0
- package/src/components/ToggleSwitch/ToggleSwitch.stories.tsx +52 -0
- package/src/components/ToggleSwitch/ToggleSwitch.tsx +30 -0
- package/src/components/ToggleSwitch/index.ts +1 -0
- package/src/components/Typography/Typography.scss +32 -2
- package/src/hooks/useFileDropzone.tsx +1 -0
- package/src/index.ts +4 -2
- package/src/components/Excel/ContextMenu/ContextMenu.scss +0 -99
- package/src/components/Excel/ContextMenu/ContextMenu.tsx +0 -103
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useRef } from 'react';
|
|
1
|
+
import { useState, useRef, useContext, useEffect } from 'react';
|
|
2
2
|
import './MenuOption.scss';
|
|
3
3
|
import Icon from '../Icon';
|
|
4
4
|
import classNames from 'classnames';
|
|
@@ -9,8 +9,10 @@ import {
|
|
|
9
9
|
MenuOptionProps,
|
|
10
10
|
OptionClick,
|
|
11
11
|
} from './types';
|
|
12
|
-
import useClickOutside from '../../hooks/useClickOutside';
|
|
13
12
|
import Typography from '../Typography';
|
|
13
|
+
import { createPortal } from 'react-dom';
|
|
14
|
+
import { ThemeContext } from '../ThemeProvider/ThemeProvider';
|
|
15
|
+
import useClickOutside from '../../hooks/useClickOutside';
|
|
14
16
|
|
|
15
17
|
const Option = ({ option, onClick }: OptionProps) => (
|
|
16
18
|
<div
|
|
@@ -19,7 +21,14 @@ const Option = ({ option, onClick }: OptionProps) => (
|
|
|
19
21
|
})}
|
|
20
22
|
onClick={() => !option.disable && onClick(option)}
|
|
21
23
|
>
|
|
22
|
-
{option.icon &&
|
|
24
|
+
{option.icon && (
|
|
25
|
+
<Icon
|
|
26
|
+
name={option.icon}
|
|
27
|
+
color={option.iconColor}
|
|
28
|
+
height={16}
|
|
29
|
+
width={16}
|
|
30
|
+
/>
|
|
31
|
+
)}
|
|
23
32
|
<Typography
|
|
24
33
|
as="label"
|
|
25
34
|
color={option.icon === 'delete' ? 'var(--delete-text-color)' : ''}
|
|
@@ -29,13 +38,72 @@ const Option = ({ option, onClick }: OptionProps) => (
|
|
|
29
38
|
</div>
|
|
30
39
|
);
|
|
31
40
|
|
|
32
|
-
const OptionCard = ({
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
const OptionCard = ({
|
|
42
|
+
options,
|
|
43
|
+
onClick,
|
|
44
|
+
menuPosition,
|
|
45
|
+
menuRef,
|
|
46
|
+
closeDropdown,
|
|
47
|
+
zIndex,
|
|
48
|
+
dropdownPosition,
|
|
49
|
+
}: OptionCardProps) => {
|
|
50
|
+
const themeContext = useContext(ThemeContext);
|
|
51
|
+
const currentTheme = themeContext?.currentTheme;
|
|
52
|
+
const [optionsHeight, setOptionsHeight] = useState(0);
|
|
53
|
+
const optionCardRef = useRef<HTMLDivElement>(null);
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (optionCardRef?.current) {
|
|
57
|
+
const rect = optionCardRef?.current?.getBoundingClientRect();
|
|
58
|
+
setOptionsHeight(rect?.height);
|
|
59
|
+
}
|
|
60
|
+
}, []);
|
|
61
|
+
|
|
62
|
+
useClickOutside(menuRef, closeDropdown, [optionCardRef]);
|
|
63
|
+
|
|
64
|
+
const style = (() => {
|
|
65
|
+
switch (dropdownPosition) {
|
|
66
|
+
case 'top':
|
|
67
|
+
return {
|
|
68
|
+
top: menuPosition.top - optionsHeight - 7,
|
|
69
|
+
left: menuPosition.rightSpaceAvailable + 12,
|
|
70
|
+
};
|
|
71
|
+
case 'down':
|
|
72
|
+
return {
|
|
73
|
+
top: menuPosition.bottom,
|
|
74
|
+
left: menuPosition.rightSpaceAvailable + 12,
|
|
75
|
+
};
|
|
76
|
+
case 'left':
|
|
77
|
+
return {
|
|
78
|
+
top: menuPosition.top,
|
|
79
|
+
right: menuPosition.rightSpaceAvailable + 35,
|
|
80
|
+
};
|
|
81
|
+
case 'right':
|
|
82
|
+
return {
|
|
83
|
+
top: menuPosition.top,
|
|
84
|
+
left: menuPosition.rightSpaceAvailable + 35,
|
|
85
|
+
};
|
|
86
|
+
default:
|
|
87
|
+
return {
|
|
88
|
+
top: menuPosition.bottom,
|
|
89
|
+
left: menuPosition.rightSpaceAvailable + 12,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
})();
|
|
93
|
+
|
|
94
|
+
return createPortal(
|
|
95
|
+
<div
|
|
96
|
+
className={classNames('ff-option-card', currentTheme)}
|
|
97
|
+
ref={optionCardRef}
|
|
98
|
+
style={{ ...style, zIndex }}
|
|
99
|
+
>
|
|
100
|
+
<div className="ff-option-wrapper">
|
|
101
|
+
{options.map((opt) => (
|
|
102
|
+
<Option key={opt.label} option={opt} onClick={onClick} />
|
|
103
|
+
))}
|
|
104
|
+
</div>
|
|
105
|
+
</div>,
|
|
106
|
+
document.body
|
|
39
107
|
);
|
|
40
108
|
};
|
|
41
109
|
|
|
@@ -45,18 +113,27 @@ const MenuOption = ({
|
|
|
45
113
|
tooltipTitle,
|
|
46
114
|
tooltipPlacement = 'bottom',
|
|
47
115
|
options = [],
|
|
48
|
-
dropdownPlacement = 'down',
|
|
49
116
|
onClick = () => {},
|
|
50
117
|
onOptionClick = () => {},
|
|
51
118
|
iconButtonSize = 20,
|
|
52
119
|
iconButtonBorderRadius = 7,
|
|
53
120
|
iconSize = 16,
|
|
54
121
|
variant = 'light',
|
|
55
|
-
zIndex=
|
|
122
|
+
zIndex = 99,
|
|
123
|
+
dropdownPlacement = 'down',
|
|
56
124
|
}: MenuOptionProps) => {
|
|
57
125
|
const [isClicked, setIsClicked] = useState(false);
|
|
58
126
|
const menuRef = useRef<HTMLDivElement>(null);
|
|
59
|
-
|
|
127
|
+
const [menuPosition, setMenuPosition] = useState({
|
|
128
|
+
top: 0,
|
|
129
|
+
bottom: 0,
|
|
130
|
+
height: 0,
|
|
131
|
+
fromBottom: 0,
|
|
132
|
+
rightSpaceAvailable: 0,
|
|
133
|
+
});
|
|
134
|
+
useEffect(() => {
|
|
135
|
+
calculateDims();
|
|
136
|
+
});
|
|
60
137
|
const closeDropDown = () => setIsClicked(false);
|
|
61
138
|
|
|
62
139
|
const onIconClickHandler = () => {
|
|
@@ -69,59 +146,61 @@ const MenuOption = ({
|
|
|
69
146
|
closeDropDown();
|
|
70
147
|
};
|
|
71
148
|
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
149
|
+
const calculateDims = () => {
|
|
150
|
+
if (menuRef?.current) {
|
|
151
|
+
const rect = menuRef.current.getBoundingClientRect();
|
|
152
|
+
|
|
153
|
+
setMenuPosition({
|
|
154
|
+
top: rect.top,
|
|
155
|
+
height: rect.height,
|
|
156
|
+
rightSpaceAvailable: document.body.clientWidth - rect.right,
|
|
157
|
+
bottom: rect.bottom,
|
|
158
|
+
fromBottom: window.innerHeight - rect.bottom,
|
|
159
|
+
});
|
|
83
160
|
}
|
|
84
161
|
};
|
|
85
162
|
|
|
86
|
-
useClickOutside(menuRef, closeDropDown);
|
|
87
|
-
|
|
88
163
|
return (
|
|
89
164
|
<div className="ff-menu-option-container" ref={menuRef}>
|
|
90
165
|
<Tooltip title={tooltipTitle} placement={tooltipPlacement}>
|
|
91
166
|
<div className="ff-icon-label">
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
167
|
+
<div
|
|
168
|
+
className={classNames('ff-menuicon-container', {
|
|
169
|
+
'ff-menuicon-container-clicked': isClicked,
|
|
170
|
+
dark: variant === 'dark',
|
|
171
|
+
})}
|
|
172
|
+
onClick={onIconClickHandler}
|
|
173
|
+
style={{
|
|
174
|
+
width: `${iconButtonSize}px`,
|
|
175
|
+
height: `${iconButtonSize}px`,
|
|
176
|
+
borderRadius: `${iconButtonBorderRadius}px`,
|
|
177
|
+
display: 'flex',
|
|
178
|
+
flexDirection: 'column',
|
|
179
|
+
}}
|
|
180
|
+
>
|
|
181
|
+
<Icon
|
|
182
|
+
height={iconSize}
|
|
183
|
+
width={iconSize}
|
|
184
|
+
name={iconName}
|
|
185
|
+
color={
|
|
186
|
+
isClicked === (variant === 'dark')
|
|
187
|
+
? 'var(--menu-option-icon-clicked)'
|
|
188
|
+
: 'var(--menu-option-icon-color)'
|
|
189
|
+
}
|
|
190
|
+
/>
|
|
116
191
|
</div>
|
|
117
|
-
{labelName && <Typography as="label">{labelName}
|
|
192
|
+
{labelName && <Typography as="label">{labelName}</Typography>}
|
|
118
193
|
</div>
|
|
119
194
|
</Tooltip>
|
|
120
195
|
{isClicked && (
|
|
121
196
|
<OptionCard
|
|
122
197
|
options={options}
|
|
123
198
|
onClick={handleOptionClick}
|
|
124
|
-
|
|
199
|
+
menuPosition={menuPosition}
|
|
200
|
+
menuRef={menuRef}
|
|
201
|
+
closeDropdown={closeDropDown}
|
|
202
|
+
zIndex={zIndex}
|
|
203
|
+
dropdownPosition={dropdownPlacement}
|
|
125
204
|
/>
|
|
126
205
|
)}
|
|
127
206
|
</div>
|
|
@@ -11,17 +11,21 @@ interface OptionClick {
|
|
|
11
11
|
* @type {Array<string> | string}
|
|
12
12
|
* @required
|
|
13
13
|
*/
|
|
14
|
-
value:
|
|
14
|
+
value: any;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
interface OptionType extends OptionClick {
|
|
18
18
|
/**
|
|
19
19
|
* The name of the icon associated with the option.
|
|
20
20
|
* @type {string}
|
|
21
|
-
* @
|
|
21
|
+
* @optional
|
|
22
22
|
*/
|
|
23
23
|
icon?: string;
|
|
24
24
|
|
|
25
|
+
iconColor?: string;
|
|
26
|
+
|
|
27
|
+
name?: string;
|
|
28
|
+
|
|
25
29
|
/**
|
|
26
30
|
* Indicates whether the option is disabled.
|
|
27
31
|
* @type {boolean}
|
|
@@ -40,11 +44,11 @@ interface OptionCardProps {
|
|
|
40
44
|
|
|
41
45
|
/**
|
|
42
46
|
* Callback function triggered when an option is clicked.
|
|
43
|
-
* @param {
|
|
47
|
+
* @param {OptionClick} data - The data associated with the clicked option.
|
|
44
48
|
* @type {function}
|
|
45
49
|
* @required
|
|
46
50
|
*/
|
|
47
|
-
onClick: (data
|
|
51
|
+
onClick: (data: OptionClick) => void;
|
|
48
52
|
|
|
49
53
|
/**
|
|
50
54
|
* Optional styles applied to the card.
|
|
@@ -52,6 +56,41 @@ interface OptionCardProps {
|
|
|
52
56
|
* @optional
|
|
53
57
|
*/
|
|
54
58
|
styles?: React.CSSProperties;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The z-index of the option card.
|
|
62
|
+
* @type {number}
|
|
63
|
+
* @optional
|
|
64
|
+
*/
|
|
65
|
+
zIndex?: number;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The position of the menu relative to the triggering element.
|
|
69
|
+
* @type {dropdownPosition}
|
|
70
|
+
* @required
|
|
71
|
+
*/
|
|
72
|
+
menuPosition: any;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Reference to the menu DOM element.
|
|
76
|
+
* @type {React.RefObject<HTMLElement>}
|
|
77
|
+
* @required
|
|
78
|
+
*/
|
|
79
|
+
menuRef: React.RefObject<HTMLElement>;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Callback function to close the dropdown.
|
|
83
|
+
* @type {() => void}
|
|
84
|
+
* @required
|
|
85
|
+
*/
|
|
86
|
+
closeDropdown: () => void;
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Placement of the dropdown menu relative to the icon.
|
|
90
|
+
* @type {dropdownPosition}
|
|
91
|
+
* @optional
|
|
92
|
+
*/
|
|
93
|
+
dropdownPosition?: 'top' | 'down' | 'left' | 'right';
|
|
55
94
|
}
|
|
56
95
|
|
|
57
96
|
interface MenuOptionProps {
|
|
@@ -100,35 +139,34 @@ interface MenuOptionProps {
|
|
|
100
139
|
|
|
101
140
|
/**
|
|
102
141
|
* The placement of the dropdown menu relative to the icon.
|
|
103
|
-
* @type {
|
|
142
|
+
* @type {dropdownPosition}
|
|
104
143
|
* @optional
|
|
105
144
|
*/
|
|
106
|
-
dropdownPlacement?:
|
|
145
|
+
dropdownPlacement?: 'top' | 'down' | 'left' | 'right';
|
|
107
146
|
|
|
108
|
-
|
|
147
|
+
/**
|
|
109
148
|
* The variant of the menu option, either 'dark' or 'light'.
|
|
110
149
|
* @type {'dark' | 'light'}
|
|
111
150
|
* @default 'light'
|
|
112
151
|
* @optional
|
|
113
152
|
*/
|
|
114
|
-
|
|
115
153
|
variant?: 'dark' | 'light';
|
|
116
|
-
|
|
154
|
+
|
|
117
155
|
/**
|
|
118
156
|
* Callback function triggered when the icon is clicked.
|
|
119
|
-
* @type {
|
|
157
|
+
* @type {() => void}
|
|
120
158
|
* @optional
|
|
121
159
|
*/
|
|
122
|
-
|
|
123
160
|
onClick?: () => void;
|
|
124
161
|
|
|
125
162
|
/**
|
|
126
163
|
* Callback function triggered when an option is clicked.
|
|
127
164
|
* @param {OptionClick} option - The option that was clicked.
|
|
128
|
-
* @type {
|
|
165
|
+
* @type {(option: OptionClick) => void}
|
|
129
166
|
* @optional
|
|
130
167
|
*/
|
|
131
168
|
onOptionClick?: (option: OptionClick) => void;
|
|
169
|
+
|
|
132
170
|
/**
|
|
133
171
|
* The size of the icon button.
|
|
134
172
|
* @type {number}
|
|
@@ -144,13 +182,16 @@ interface MenuOptionProps {
|
|
|
144
182
|
iconSize?: number;
|
|
145
183
|
|
|
146
184
|
/**
|
|
147
|
-
* The border radius of the icon.
|
|
185
|
+
* The border radius of the icon button.
|
|
148
186
|
* @type {number}
|
|
149
187
|
* @default 7
|
|
150
188
|
*/
|
|
151
189
|
iconButtonBorderRadius?: number;
|
|
190
|
+
|
|
152
191
|
/**
|
|
153
192
|
* Providing z-index for the options card.
|
|
193
|
+
* @type {number}
|
|
194
|
+
* @optional
|
|
154
195
|
*/
|
|
155
196
|
zIndex?: number;
|
|
156
197
|
}
|
|
@@ -166,7 +207,7 @@ interface OptionProps {
|
|
|
166
207
|
/**
|
|
167
208
|
* Callback function triggered when the option is clicked.
|
|
168
209
|
* @param {OptionClick} option - The clicked option.
|
|
169
|
-
* @type {
|
|
210
|
+
* @type {(option: OptionClick) => void}
|
|
170
211
|
* @required
|
|
171
212
|
*/
|
|
172
213
|
onClick: (option: OptionClick) => void;
|
|
@@ -5,6 +5,7 @@ import Button from '../Button/Button';
|
|
|
5
5
|
import './MiniModal.scss';
|
|
6
6
|
import Typography from '../Typography';
|
|
7
7
|
import Icon from '../Icon';
|
|
8
|
+
import React from 'react';
|
|
8
9
|
|
|
9
10
|
const meta: Meta<typeof MiniModal> = {
|
|
10
11
|
title: 'Components/MiniModal',
|
|
@@ -41,14 +42,15 @@ const BasicModalComponent = () => {
|
|
|
41
42
|
<div className="ff-mini-modal-buttons-flex ff-mini-modal-gap-10">
|
|
42
43
|
<Button
|
|
43
44
|
onClick={() => openModal(1)}
|
|
45
|
+
id="112233"
|
|
44
46
|
ref={btnRef1}
|
|
45
|
-
label="
|
|
47
|
+
label="122"
|
|
46
48
|
variant={currentModal === 1 ? 'primary' : 'secondary'}
|
|
47
49
|
/>
|
|
48
50
|
|
|
49
51
|
{currentModal === 1 && (
|
|
50
52
|
<MiniModal
|
|
51
|
-
anchorRef=
|
|
53
|
+
anchorRef="112233"
|
|
52
54
|
modalProperties={{ width: 300, height: 180 }}
|
|
53
55
|
headerProps={
|
|
54
56
|
<>
|
|
@@ -239,7 +241,6 @@ export const BasicModal: Story = {
|
|
|
239
241
|
};
|
|
240
242
|
|
|
241
243
|
export const CustomModalWithArrow = () => {
|
|
242
|
-
const btnRef1 = useRef<HTMLButtonElement>(null);
|
|
243
244
|
const btnRef2 = useRef<HTMLButtonElement>(null);
|
|
244
245
|
const btnRef3 = useRef<HTMLButtonElement>(null);
|
|
245
246
|
const btnRef4 = useRef<HTMLButtonElement>(null);
|
|
@@ -254,14 +255,14 @@ export const CustomModalWithArrow = () => {
|
|
|
254
255
|
<div className="ff-mini-modal-buttons-flex ff-mini-modal-gap-10">
|
|
255
256
|
<Button
|
|
256
257
|
onClick={() => openModal(1)}
|
|
257
|
-
|
|
258
|
-
|
|
258
|
+
label="12"
|
|
259
|
+
id="1a2b"
|
|
259
260
|
variant={currentModal === 1 ? 'primary' : 'secondary'}
|
|
260
261
|
/>
|
|
261
262
|
|
|
262
263
|
{currentModal === 1 && (
|
|
263
264
|
<MiniModal
|
|
264
|
-
anchorRef=
|
|
265
|
+
anchorRef="1a2b"
|
|
265
266
|
modalProperties={{ width: 300, height: 250 }}
|
|
266
267
|
headerProps={
|
|
267
268
|
<>
|
|
@@ -40,6 +40,7 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
|
|
|
40
40
|
});
|
|
41
41
|
const [isVisible, setIsVisible] = useState(false);
|
|
42
42
|
const modalRef = useRef<HTMLDivElement>(null);
|
|
43
|
+
|
|
43
44
|
// Function to calculate available space
|
|
44
45
|
const getAvailableSpace = (rect: Rect): AvailableSpace => {
|
|
45
46
|
const { top, left, bottom, right } = rect;
|
|
@@ -53,7 +54,18 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
|
|
|
53
54
|
spaceBottom: viewportHeight - bottom,
|
|
54
55
|
};
|
|
55
56
|
};
|
|
56
|
-
|
|
57
|
+
|
|
58
|
+
// Helper function to get the anchor element
|
|
59
|
+
const getAnchorElement = () => {
|
|
60
|
+
if (typeof anchorRef === 'string') {
|
|
61
|
+
return document.getElementById(anchorRef);
|
|
62
|
+
}
|
|
63
|
+
return anchorRef?.current || null;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const anchorElement = getAnchorElement();
|
|
67
|
+
const anchorRect = anchorElement?.getBoundingClientRect();
|
|
68
|
+
|
|
57
69
|
if (!isWrapped && anchorRect) {
|
|
58
70
|
const availableSpace = getAvailableSpace(anchorRect);
|
|
59
71
|
switch (modalPosition) {
|
|
@@ -82,7 +94,7 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
|
|
|
82
94
|
}
|
|
83
95
|
}
|
|
84
96
|
|
|
85
|
-
//
|
|
97
|
+
// Specify for the wrapper div left position
|
|
86
98
|
const calculateAnchorRefLeft = (anchorRefLeftNum?: number) => {
|
|
87
99
|
if (anchorRefLeftNum) {
|
|
88
100
|
return anchorRefLeftNum;
|
|
@@ -90,7 +102,7 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
|
|
|
90
102
|
return 0;
|
|
91
103
|
};
|
|
92
104
|
|
|
93
|
-
//
|
|
105
|
+
// Specify for the arrow position in left or top
|
|
94
106
|
const getArrowClassName = () => {
|
|
95
107
|
if (leftTopArrow && modalPosition === 'right') {
|
|
96
108
|
return 'left-top-arrow';
|
|
@@ -99,13 +111,13 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
|
|
|
99
111
|
};
|
|
100
112
|
const calculatedAnchorRefLeft = calculateAnchorRefLeft(anchorRefLeftNum);
|
|
101
113
|
|
|
102
|
-
//
|
|
114
|
+
// Specify specific wrapper modal position
|
|
103
115
|
const firstAnchor =
|
|
104
116
|
firstAnchorRef?.current &&
|
|
105
117
|
firstAnchorRef?.current?.getBoundingClientRect().left -
|
|
106
118
|
anchorLeftDistanceForWrapper;
|
|
107
119
|
|
|
108
|
-
//
|
|
120
|
+
// Specifying the modal top
|
|
109
121
|
const calculateModalTop = () => {
|
|
110
122
|
const safeHeight = modalProperties?.height ?? 0;
|
|
111
123
|
if (modalPosition === 'bottom') {
|
|
@@ -115,24 +127,18 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
|
|
|
115
127
|
} else if (modalPosition === 'right') {
|
|
116
128
|
return leftTopArrow
|
|
117
129
|
? modalPositionState.top - (extraRightSpace?.leftTopArrow ?? 30)
|
|
118
|
-
: modalPositionState?.top -
|
|
119
|
-
safeHeight / (extraRightSpace?.middleLeftArrow ?? 3.5);
|
|
130
|
+
: modalPositionState?.top - safeHeight / (extraRightSpace?.middleLeftArrow ?? 3.5);
|
|
120
131
|
} else if (modalPosition === 'top') {
|
|
121
|
-
return (
|
|
122
|
-
modalPositionState.top -
|
|
123
|
-
(safeHeight + (extraTopSpace?.normalModal ?? 10))
|
|
124
|
-
);
|
|
132
|
+
return modalPositionState.top - (safeHeight + (extraTopSpace?.normalModal ?? 10));
|
|
125
133
|
}
|
|
126
134
|
return modalPositionState.top - safeHeight / 1.5;
|
|
127
135
|
};
|
|
128
136
|
const calculatedModalTop = calculateModalTop();
|
|
129
137
|
|
|
130
|
-
//
|
|
138
|
+
// Specifying the modal left
|
|
131
139
|
const calculateModalLeft = () => {
|
|
132
140
|
if (modalPosition === 'right') {
|
|
133
|
-
return (
|
|
134
|
-
modalPositionState.left + (extraLeftSpace?.rightAlignModal ?? 40)
|
|
135
|
-
);
|
|
141
|
+
return modalPositionState.left + (extraLeftSpace?.rightAlignModal ?? 40);
|
|
136
142
|
} else if (firstAnchorRef) {
|
|
137
143
|
return firstAnchor;
|
|
138
144
|
} else if (modalPosition === 'left') {
|
|
@@ -143,16 +149,16 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
|
|
|
143
149
|
};
|
|
144
150
|
const calculatedModalLeft = calculateModalLeft();
|
|
145
151
|
|
|
146
|
-
//
|
|
152
|
+
// Handle escape and enter functionality
|
|
147
153
|
const handleEsc = useEscapeKey('Escape');
|
|
148
154
|
const handleEnter = useEscapeKey('Enter');
|
|
149
155
|
handleEsc(cancelButtonProps?.onClick);
|
|
150
156
|
handleEnter(proceedButtonProps?.onClick);
|
|
151
157
|
useClickOutside(modalRef, cancelButtonProps.onClick);
|
|
152
158
|
|
|
153
|
-
//
|
|
159
|
+
// Calculate the modal position
|
|
154
160
|
const calculatePosition = useCallback(() => {
|
|
155
|
-
const anchorRect =
|
|
161
|
+
const anchorRect = anchorElement?.getBoundingClientRect();
|
|
156
162
|
if (anchorRect) {
|
|
157
163
|
const { bottom, left } = anchorRect;
|
|
158
164
|
const { scrollX, scrollY } = window;
|
|
@@ -164,7 +170,7 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
|
|
|
164
170
|
left: leftPosition,
|
|
165
171
|
});
|
|
166
172
|
}
|
|
167
|
-
}, [
|
|
173
|
+
}, [anchorElement]);
|
|
168
174
|
|
|
169
175
|
useEffect(() => {
|
|
170
176
|
const timeoutId = setTimeout(() => {
|
|
@@ -213,10 +219,10 @@ const MiniModal = forwardRef<HTMLDivElement, MiniEditModalProps>(
|
|
|
213
219
|
modalPosition === 'right'
|
|
214
220
|
? 'left'
|
|
215
221
|
: modalPosition === 'top'
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
222
|
+
? 'bottom'
|
|
223
|
+
: modalPosition === 'left'
|
|
224
|
+
? 'right'
|
|
225
|
+
: 'top'
|
|
220
226
|
} ${getArrowClassName()}`}
|
|
221
227
|
/>
|
|
222
228
|
)}
|
|
@@ -9,7 +9,7 @@ export interface MiniEditModalProps {
|
|
|
9
9
|
/**
|
|
10
10
|
* A reference to the button element that triggers the modal.
|
|
11
11
|
*/
|
|
12
|
-
anchorRef: RefObject<HTMLButtonElement
|
|
12
|
+
anchorRef: RefObject<HTMLButtonElement> | string;
|
|
13
13
|
/**
|
|
14
14
|
* Optional properties for configuring the modal header.
|
|
15
15
|
*/
|
|
@@ -9,6 +9,7 @@ import Typography from '../Typography';
|
|
|
9
9
|
import Checkbox from '../Checkbox';
|
|
10
10
|
import Tooltip from '../Tooltip';
|
|
11
11
|
import { truncateText } from '../../utils/truncateText/truncateText';
|
|
12
|
+
import { getLabel } from '../../utils/getSelectOptionValue/getSelectOptionValue';
|
|
12
13
|
|
|
13
14
|
const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(
|
|
14
15
|
(
|
|
@@ -19,12 +20,15 @@ const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(
|
|
|
19
20
|
dropdownPosition = {},
|
|
20
21
|
zIndex,
|
|
21
22
|
withSelectButton,
|
|
23
|
+
labelAccessor,
|
|
22
24
|
},
|
|
23
25
|
ref
|
|
24
26
|
) => {
|
|
25
27
|
const filteredOptions = options
|
|
26
28
|
? options.filter((option) =>
|
|
27
|
-
option
|
|
29
|
+
getLabel(option, labelAccessor)
|
|
30
|
+
?.toLowerCase()
|
|
31
|
+
.includes(searchedKeyword.toLowerCase())
|
|
28
32
|
)
|
|
29
33
|
: [];
|
|
30
34
|
const { verticalMargin, optionHeight, maxDropdownHeight } =
|
|
@@ -56,12 +60,7 @@ const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(
|
|
|
56
60
|
|
|
57
61
|
return topPosition;
|
|
58
62
|
}, [filteredOptions.length, withSelectButton, dropdownPosition]);
|
|
59
|
-
|
|
60
|
-
if (typeof optionLabel === 'string') {
|
|
61
|
-
return truncateText(optionLabel, 25);
|
|
62
|
-
}
|
|
63
|
-
return optionLabel;
|
|
64
|
-
};
|
|
63
|
+
|
|
65
64
|
const themeContext = useContext(ThemeContext);
|
|
66
65
|
const currentTheme = themeContext?.currentTheme;
|
|
67
66
|
return (
|
|
@@ -91,7 +90,7 @@ const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(
|
|
|
91
90
|
<div
|
|
92
91
|
role="option"
|
|
93
92
|
className={`dropdown-option-container`}
|
|
94
|
-
key={info
|
|
93
|
+
key={getLabel(info, labelAccessor)}
|
|
95
94
|
onClick={() =>
|
|
96
95
|
!info?.isDisabled && handleOptionChange(info, !info.isChecked)
|
|
97
96
|
}
|
|
@@ -104,14 +103,14 @@ const Dropdown = forwardRef<HTMLDivElement, DropdownProps>(
|
|
|
104
103
|
<Tooltip
|
|
105
104
|
zIndex={zIndex + 1}
|
|
106
105
|
title={
|
|
107
|
-
info
|
|
108
|
-
? info
|
|
109
|
-
:
|
|
106
|
+
getLabel(info, labelAccessor).length > 25
|
|
107
|
+
? getLabel(info, labelAccessor)
|
|
108
|
+
: ''
|
|
110
109
|
}
|
|
111
110
|
children={
|
|
112
111
|
<Typography
|
|
113
112
|
className="dropdown-option-label"
|
|
114
|
-
children={
|
|
113
|
+
children={truncateText(getLabel(info, labelAccessor), 25)}
|
|
115
114
|
/>
|
|
116
115
|
}
|
|
117
116
|
/>
|