pixel-react 1.2.8 → 1.2.9

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 (83) hide show
  1. package/.yarn/install-state.gz +0 -0
  2. package/lib/components/AddButton/AddButton.d.ts +5 -0
  3. package/lib/components/AddButton/AddButton.stories.d.ts +6 -0
  4. package/lib/components/AddButton/index.d.ts +1 -0
  5. package/lib/components/AddButton/types.d.ts +4 -0
  6. package/lib/components/Editor/Editor.d.ts +5 -0
  7. package/lib/components/Editor/Editor.stories.d.ts +6 -0
  8. package/lib/components/Editor/VariableDropdown.d.ts +5 -0
  9. package/lib/components/Editor/constants.d.ts +3 -0
  10. package/lib/components/Editor/index.d.ts +1 -0
  11. package/lib/components/Editor/types.d.ts +71 -0
  12. package/lib/components/ExcelFile/ChangeExcelStyles.d.ts +14 -0
  13. package/lib/components/ExcelFile/ColorBarselector/ColorBarSelector.d.ts +8 -0
  14. package/lib/components/ExcelFile/ContextMenu/ContextMenu.d.ts +4 -0
  15. package/lib/components/ExcelFile/ExcelFile/Excel/ActiveCell.d.ts +7 -0
  16. package/lib/components/ExcelFile/ExcelFile/Excel/Cell.d.ts +4 -0
  17. package/lib/components/ExcelFile/ExcelFile/Excel/ColumnIndicator.d.ts +5 -0
  18. package/lib/components/ExcelFile/ExcelFile/Excel/Copied.d.ts +3 -0
  19. package/lib/components/ExcelFile/ExcelFile/Excel/CornerIndicator.d.ts +5 -0
  20. package/lib/components/ExcelFile/ExcelFile/Excel/DataEditor.d.ts +5 -0
  21. package/lib/components/ExcelFile/ExcelFile/Excel/DataViewer.d.ts +8 -0
  22. package/lib/components/ExcelFile/ExcelFile/Excel/FloatingRect.d.ts +10 -0
  23. package/lib/components/ExcelFile/ExcelFile/Excel/HeaderRow.d.ts +3 -0
  24. package/lib/components/ExcelFile/ExcelFile/Excel/Row.d.ts +3 -0
  25. package/lib/components/ExcelFile/ExcelFile/Excel/RowIndicator.d.ts +5 -0
  26. package/lib/components/ExcelFile/ExcelFile/Excel/Selected.d.ts +3 -0
  27. package/lib/components/ExcelFile/ExcelFile/Excel/Spreadsheet.d.ts +81 -0
  28. package/lib/components/ExcelFile/ExcelFile/Excel/Table.d.ts +3 -0
  29. package/lib/components/ExcelFile/ExcelFile/Excel/actions.d.ts +130 -0
  30. package/lib/components/ExcelFile/ExcelFile/Excel/areModelsEqual.d.ts +1 -0
  31. package/lib/components/ExcelFile/ExcelFile/Excel/context.d.ts +8 -0
  32. package/lib/components/ExcelFile/ExcelFile/Excel/engine/engine.d.ts +22 -0
  33. package/lib/components/ExcelFile/ExcelFile/Excel/engine/formula.d.ts +17 -0
  34. package/lib/components/ExcelFile/ExcelFile/Excel/engine/index.d.ts +2 -0
  35. package/lib/components/ExcelFile/ExcelFile/Excel/engine/point-graph.d.ts +21 -0
  36. package/lib/components/ExcelFile/ExcelFile/Excel/engine/point-hash.d.ts +3 -0
  37. package/lib/components/ExcelFile/ExcelFile/Excel/engine/point-set.d.ts +24 -0
  38. package/lib/components/ExcelFile/ExcelFile/Excel/index.d.ts +13 -0
  39. package/lib/components/ExcelFile/ExcelFile/Excel/matrix.d.ts +67 -0
  40. package/lib/components/ExcelFile/ExcelFile/Excel/point-range.d.ts +22 -0
  41. package/lib/components/ExcelFile/ExcelFile/Excel/point.d.ts +11 -0
  42. package/lib/components/ExcelFile/ExcelFile/Excel/reducer.d.ts +27 -0
  43. package/lib/components/ExcelFile/ExcelFile/Excel/selection.d.ts +95 -0
  44. package/lib/components/ExcelFile/ExcelFile/Excel/types.d.ts +215 -0
  45. package/lib/components/ExcelFile/ExcelFile/Excel/use-dispatch.d.ts +3 -0
  46. package/lib/components/ExcelFile/ExcelFile/Excel/use-selector.d.ts +3 -0
  47. package/lib/components/ExcelFile/ExcelFile/Excel/util.d.ts +45 -0
  48. package/lib/components/ExcelFile/ExcelFile/ExcelFile.d.ts +3 -0
  49. package/lib/components/ExcelFile/ExcelFile.stories.d.ts +6 -0
  50. package/lib/components/ExcelFile/ExcelSheetBar/ExcelSheetBar.d.ts +15 -0
  51. package/lib/components/ExcelFile/ExcelToolBar/ExcelToolBar.d.ts +3 -0
  52. package/lib/components/ExcelFile/ImportExcelStyles.d.ts +24 -0
  53. package/lib/components/ExcelFile/Types.d.ts +176 -0
  54. package/lib/components/ExcelFile/index.d.ts +1 -0
  55. package/lib/components/InputWithDropdown/InputWithDropdown.d.ts +1 -1
  56. package/lib/components/InputWithDropdown/types.d.ts +3 -1
  57. package/lib/components/Select/Select.d.ts +3 -2
  58. package/lib/components/Select/components/Dropdown.d.ts +5 -0
  59. package/lib/components/Select/components/types.d.ts +18 -0
  60. package/lib/components/Select/types.d.ts +2 -42
  61. package/lib/index.d.ts +7 -12
  62. package/lib/index.esm.js +200 -330
  63. package/lib/index.esm.js.map +1 -1
  64. package/lib/index.js +199 -329
  65. package/lib/index.js.map +1 -1
  66. package/lib/tsconfig.tsbuildinfo +1 -1
  67. package/lib/utils/find/findAndInsert.d.ts +7 -0
  68. package/lib/utils/find/findAndInsert.stories.d.ts +7 -0
  69. package/package.json +3 -3
  70. package/src/assets/Themes/BaseTheme.scss +1 -0
  71. package/src/assets/Themes/DarkTheme.scss +2 -0
  72. package/src/components/Icon/Icons.scss +4 -0
  73. package/src/components/InputWithDropdown/InputWithDropdown.scss +30 -1
  74. package/src/components/InputWithDropdown/InputWithDropdown.tsx +45 -16
  75. package/src/components/InputWithDropdown/types.ts +5 -1
  76. package/src/components/Select/Select.scss +121 -188
  77. package/src/components/Select/Select.stories.tsx +4 -1
  78. package/src/components/Select/Select.tsx +140 -296
  79. package/src/components/Select/components/Dropdown.scss +50 -0
  80. package/src/components/Select/components/Dropdown.tsx +94 -0
  81. package/src/components/Select/components/types.ts +20 -0
  82. package/src/components/Select/types.ts +15 -39
  83. package/src/utils/getSelectOptionValue/getSelectOptionValue.ts +1 -1
@@ -1,109 +1,17 @@
1
- import { useReducer, useRef, useEffect, useMemo } from 'react';
2
- import { Option, SelectAction, SelectProps, SelectState } from './types';
3
- import { checkEmpty } from '../../utils/checkEmpty/checkEmpty';
4
- import { createPortal } from 'react-dom';
5
- import classNames from 'classnames';
6
- import Dropdown from './components/Dropdown/Dropdown';
7
- import Icon from '../Icon';
1
+ import { ChangeEvent, FC, useEffect, useRef, useState } from 'react';
8
2
  import './Select.scss';
9
- import usePortalPosition from '../../hooks/usePortalPosition';
3
+ import Icon from '../Icon';
10
4
  import Typography from '../Typography';
5
+ import { DrowdownPosition, Option, SelectProps } from './types';
6
+ import classNames from 'classnames';
7
+ import { createPortal } from 'react-dom';
8
+ import Dropdown from './components/Dropdown';
11
9
  import { getValue } from '../../utils/getSelectOptionValue/getSelectOptionValue';
10
+ import usePortalPosition from '../../hooks/usePortalPosition';
11
+ import { checkEmpty } from '../../utils/checkEmpty/checkEmpty';
12
12
 
13
- const selectReducer = (
14
- state: SelectState,
15
- action: SelectAction
16
- ): SelectState => {
17
- switch (action.type) {
18
- case 'FOCUS_INPUT':
19
- return {
20
- ...state,
21
- isInputFocused: true,
22
- iconColor: 'var(--ff-select-brand-color)',
23
- isIconClick: true,
24
- showOptions: true,
25
- };
26
- case 'BLUR_INPUT':
27
- return {
28
- ...state,
29
- isInputFocused: false,
30
- options: action.payload.optionsList,
31
- option: action.payload.option,
32
-
33
- // todo color need to be add in style guide
34
- iconColor: 'var(--ff-select-default-color)',
35
- isIconClick: false,
36
- showOptions: false,
37
- dropdownPosition: {
38
- positionX: 0,
39
- positionY: 0,
40
- width: 0,
41
- fromBottom: 0,
42
- },
43
- };
44
- case 'MOUSE_ENTER':
45
- return state.isInputFocused
46
- ? state
47
- : { ...state, iconColor: 'var(--ff-select-text-hover-color)' };
48
- case 'MOUSE_LEAVE':
49
- return state.isInputFocused
50
- ? state
51
- : // todo color need to be add in style guide
52
- {
53
- ...state,
54
- iconColor: 'var(--ff-select-default-color)',
55
- isIconClick: false,
56
- };
57
-
58
- case 'UPDATE_DROPDOWN_POSITION':
59
- const { positionX, positionY, width, fromBottom } = action.payload || {};
60
- return {
61
- ...state,
62
- dropdownPosition: {
63
- positionX,
64
- positionY,
65
- width,
66
- fromBottom,
67
- },
68
- };
69
-
70
- case 'UPDATE_OPTION':
71
- return {
72
- ...state,
73
- option: action.payload,
74
- };
75
-
76
- case 'UPDATE_OPTION_LIST':
77
- return {
78
- ...state,
79
- options: action.payload,
80
- };
81
- case 'SHOW_ERROR':
82
- return {
83
- ...state,
84
- isInputFocused: true,
85
- isIconClick: false,
86
- showOptions: false,
87
- options: action.payload.optionsList,
88
- option: action.payload.option,
89
-
90
- // todo color need to be add in style guide
91
- iconColor: 'var(--ff-select-default-color)',
92
- dropdownPosition: {
93
- positionX: 0,
94
- positionY: 0,
95
- width: 0,
96
- fromBottom: 0,
97
- },
98
- };
99
-
100
- default:
101
- return state;
102
- }
103
- };
104
-
105
- const Select = ({
106
- label = '',
13
+ const Select: FC<SelectProps> = ({
14
+ label = 'Default Label',
107
15
  showLabel = true,
108
16
  optionsList = [],
109
17
  selectedOption = { label: '', value: '' },
@@ -112,271 +20,207 @@ const Select = ({
112
20
  className = '',
113
21
  optionZIndex = 100,
114
22
  disabled = false,
115
- borderRadius = true,
116
23
  showBorder = true,
117
- required = false,
24
+ required = true,
118
25
  optionsRequired = true,
119
26
  selectedOptionColor = 'var(--ff-select-text-color)',
120
- labelAccessor,
121
- valueAccessor,
122
- }: SelectProps) => {
123
- const initialState: SelectState = useMemo(
124
- () => ({
125
- isInputFocused: false,
126
-
127
- // todo color need to be added in style guide
128
- iconColor: 'var(--ff-select-default-color)',
129
- isIconClick: false,
130
- showOptions: false,
131
- options: optionsList,
132
- option: checkEmpty(selectedOption) ? '' : selectedOption?.value,
133
- dropdownPosition: { positionX: 0, positionY: 0, width: 0, fromBottom: 0 },
134
- }),
135
- [optionsList, selectedOption]
136
- );
137
-
138
- const [selectControlState, dispatch] = useReducer(
139
- selectReducer,
140
- initialState
141
- );
142
-
143
- const DropDownRef = useRef<HTMLDivElement>(null);
144
- const InputRef = useRef<HTMLInputElement>(null);
145
-
146
- const {
147
- isInputFocused,
148
- iconColor,
149
- isIconClick,
150
- showOptions,
151
- dropdownPosition,
152
- options,
153
- option,
154
- } = selectControlState;
155
-
156
- const calculatePosition = usePortalPosition(DropDownRef, showOptions);
157
-
158
- const handleSelectAction = (
159
- actionType:
160
- | 'FOCUS_INPUT'
161
- | 'MOUSE_ENTER'
162
- | 'MOUSE_LEAVE'
163
- | 'SHOW_ERROR'
164
- | 'BLUR_INPUT'
165
- ) => {
166
- if (!disabled) {
167
- if (actionType === 'SHOW_ERROR' || actionType === 'BLUR_INPUT') {
168
- dispatch({
169
- type: actionType,
170
- payload: { optionsList, option: getValue(selectedOption) },
171
- });
172
- } else {
173
- dispatch({ type: actionType });
174
- }
175
- }
27
+ labelAccessor = '',
28
+ valueAccessor = '',
29
+ height = 32,
30
+ width = 300,
31
+ }) => {
32
+ const [showDropdownOptions, setShowDropdownOptions] = useState(false);
33
+ const [searchedOption, setSearchedOption] = useState('');
34
+ const [selectOptionList, setSelectOptionList] = useState(optionsList);
35
+ const [dropdownPosition, setDropdownPosition] = useState<DrowdownPosition>({
36
+ positionX: 0,
37
+ positionY: 0,
38
+ width: 0,
39
+ fromBottom: 0,
40
+ });
41
+
42
+ const DropdownRef = useRef<HTMLDivElement>(null);
43
+ const selectWrapperRef = useRef<HTMLDivElement>(null);
44
+ const inputRef = useRef<HTMLInputElement>(null);
45
+ const selectArrowRef = useRef<HTMLDivElement>(null);
46
+
47
+ const calculatePosition = usePortalPosition(DropdownRef, showDropdownOptions);
48
+
49
+ const handleIconClick = () => {
50
+ setShowDropdownOptions(!showDropdownOptions);
176
51
  };
177
52
 
178
- const onSelectInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
53
+ const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
179
54
  if (disabled) return;
180
- const { value } = e.target;
55
+ const { value } = event.target;
56
+
181
57
  const filteredOptions = optionsList.filter((option) => {
182
58
  const valueData = getValue(option, valueAccessor);
183
59
  return typeof valueData === 'string'
184
60
  ? valueData.toLowerCase().includes(value.toLowerCase().trim())
185
61
  : valueData === Number(value);
186
62
  });
187
- dispatch({ type: 'UPDATE_OPTION_LIST', payload: filteredOptions });
188
- dispatch({ type: 'UPDATE_OPTION', payload: value });
63
+
64
+ setSelectOptionList(filteredOptions);
65
+ setSearchedOption(value);
189
66
  };
190
67
 
191
- const onSelectBlur = () => {
192
- if (disabled) return;
68
+ const onSelectUpdatePosition = () => {
69
+ if (!showDropdownOptions || !DropdownRef?.current || disabled) return;
70
+ setDropdownPosition(calculatePosition(DropdownRef));
71
+ };
72
+
73
+ const onSelectToggleScroll = (isEnabled: boolean): void => {
74
+ const scrollWidth =
75
+ window.innerWidth - document.documentElement.clientWidth;
193
76
 
194
- if (errorMsg) {
195
- handleSelectAction('SHOW_ERROR');
77
+ if (isEnabled) {
78
+ document.body.style.paddingRight = '';
79
+ document.body.style.overflow = '';
196
80
  } else {
197
- handleSelectAction('BLUR_INPUT');
81
+ document.body.style.paddingRight = `${scrollWidth}px`;
82
+ document.body.style.overflow = 'hidden';
198
83
  }
199
84
  };
200
85
 
201
- const onSelectOptionSelector = (option: Option) => {
202
- if (!disabled) {
203
- onSelectBlur();
204
- dispatch({
205
- type: 'UPDATE_OPTION',
206
- payload: getValue(option, valueAccessor),
207
- });
208
- if (onChange) {
209
- onChange(option);
210
- }
211
- }
86
+ const handleFocus = () => {
87
+ if (disabled) return;
88
+ setShowDropdownOptions(true);
212
89
  };
213
90
 
214
- const onSelectUpdatePosition = () => {
215
- if (!showOptions || !DropDownRef?.current || disabled) return;
216
- const { positionX, positionY, width, fromBottom } =
217
- calculatePosition(DropDownRef);
218
- dispatch({
219
- type: 'UPDATE_DROPDOWN_POSITION',
220
- payload: { positionX, positionY, width, fromBottom },
91
+ const onSelectBlur = () => {
92
+ setShowDropdownOptions(false);
93
+ setDropdownPosition({
94
+ positionX: 0,
95
+ positionY: 0,
96
+ fromBottom: 0,
97
+ width: 0,
221
98
  });
99
+ setSearchedOption(getValue(selectedOption, valueAccessor));
100
+ setSelectOptionList(optionsList);
222
101
  };
223
102
 
224
- const onSelectToggleScroll = (isEnabled: boolean) => {
225
- const bodyScrollWidth = window.innerWidth - document.body.clientWidth;
226
- document.body.style.paddingRight = isEnabled ? '' : `${bodyScrollWidth}px`;
227
- document.body.style.overflow = isEnabled ? '' : 'hidden';
103
+ const onSelectOptionSelector = (option: Option): void => {
104
+ if (disabled) return;
105
+ onSelectBlur();
106
+ setSearchedOption(getValue(option, valueAccessor));
107
+ if (onChange) {
108
+ onChange(option);
109
+ }
228
110
  };
229
111
 
230
- useEffect(() => {
112
+ const handleResizeOrScroll = () => onSelectUpdatePosition();
113
+
114
+ const hideShowScrollbar = () => {
231
115
  if (disabled) return;
232
- if (showOptions) {
233
- onSelectToggleScroll(!showOptions);
116
+ if (showDropdownOptions && optionsRequired) {
117
+ onSelectToggleScroll(!showDropdownOptions);
234
118
  }
235
119
  onSelectUpdatePosition();
236
120
 
237
- const handleResizeOrScroll = () => onSelectUpdatePosition();
238
-
239
121
  window.addEventListener('resize', handleResizeOrScroll);
240
122
  window.addEventListener('scroll', handleResizeOrScroll);
123
+ };
124
+
125
+ useEffect(() => {
126
+ hideShowScrollbar();
241
127
  return () => {
242
128
  onSelectToggleScroll(true);
243
129
  window.removeEventListener('resize', handleResizeOrScroll);
244
130
  window.removeEventListener('scroll', handleResizeOrScroll);
245
131
  };
246
- }, [showOptions]);
132
+ }, [showDropdownOptions]);
247
133
 
248
134
  useEffect(() => {
249
- if (errorMsg) {
250
- handleSelectAction('SHOW_ERROR');
251
- }
252
- }, []);
253
-
254
- useEffect(() => {
255
- if (!checkEmpty(selectedOption.label)) {
256
- onSelectOptionSelector(selectedOption);
257
- }
135
+ if (checkEmpty(getValue(selectedOption, valueAccessor))) return;
136
+ setSearchedOption(getValue(selectedOption, valueAccessor));
258
137
  }, [selectedOption]);
259
138
 
260
- const applyActiveOptionClasses = !isInputFocused && Boolean(option);
261
-
262
139
  return (
263
- <div className={classNames(`ff-select-wrapper`)}>
264
- <div className={`ff-select ${className}`}>
140
+ <div
141
+ className={`ff-select-wrapper ${className}`}
142
+ ref={selectWrapperRef}
143
+ style={{ height: `${height}px`, width: `${width}px` }}
144
+ >
145
+ <div
146
+ className={classNames('ff-select', {
147
+ 'ff-select__focus': showDropdownOptions,
148
+ 'ff-select__disabled': disabled,
149
+ 'ff-select__error': !!errorMsg,
150
+ 'ff-select__error__focused': !!errorMsg && showDropdownOptions,
151
+ 'ff-select__no_border': !showBorder,
152
+ })}
153
+ >
265
154
  <input
266
155
  type="text"
156
+ ref={inputRef}
157
+ id="select-input-element"
267
158
  className={classNames('ff-select-input', {
268
- 'ff-select-input--default': !isInputFocused,
269
- 'ff-select-input--active': applyActiveOptionClasses,
270
- 'ff-select-input--no-label': !showLabel,
271
- 'ff-select-input--error':
272
- errorMsg && !isInputFocused && !Boolean(option),
273
- 'ff-select-input--border-radius': !borderRadius,
274
- 'ff-select-input--disable': disabled,
275
- 'ff-select-input--no-border': !showBorder,
159
+ 'ff-select-input__disabled': disabled,
276
160
  })}
277
- // inline css required due to multiple overlay scenarios are present
278
- style={{ zIndex: optionZIndex, color: selectedOptionColor }}
279
- onFocus={() => handleSelectAction('FOCUS_INPUT')}
280
- onMouseEnter={() => handleSelectAction('MOUSE_ENTER')}
281
- onMouseLeave={() => handleSelectAction('MOUSE_LEAVE')}
282
- onChange={onSelectInputChange}
283
- value={option}
284
- disabled={disabled}
161
+ onFocus={handleFocus}
162
+ value={searchedOption}
163
+ autoCorrect="off"
285
164
  autoComplete="off"
286
165
  spellCheck="false"
287
- ref={InputRef}
166
+ style={{ zIndex: optionZIndex, color: selectedOptionColor }}
167
+ disabled={disabled}
168
+ onChange={handleChange}
288
169
  />
289
-
290
- {showLabel && (
170
+ {optionsRequired && (
291
171
  <div
292
- className={classNames('ff-select-label', {
293
- 'ff-select-label--default': !isInputFocused,
294
- 'ff-select-label--active': isInputFocused || Boolean(option),
295
- 'ff-select-label--error': errorMsg,
172
+ ref={selectArrowRef}
173
+ className={classNames('ff-select-arrow-wrapper', {
174
+ 'ff-select-arrow-wrapper__disabled': disabled,
296
175
  })}
176
+ onClick={handleIconClick}
297
177
  >
298
- {required && (
299
- <Typography
300
- color="var(--error-light)"
301
- className="ff-select-label--required"
302
- >
303
- *
304
- </Typography>
305
- )}
306
- {label}
178
+ <Icon
179
+ name="arrow_down"
180
+ className="ff-select-arrow"
181
+ height={8}
182
+ width={12}
183
+ />
307
184
  </div>
308
185
  )}
309
- {optionsRequired && (
310
- <Icon
311
- name="arrow_up"
312
- height={7}
313
- width={12}
314
- className={classNames('ff-select-arrow', {
315
- 'ff-select-arrow--down': isIconClick,
316
- 'ff-select-arrow--no-label': !showLabel,
317
- })}
318
- color={iconColor}
319
- />
320
- )}
321
- {(!checkEmpty(option) || showOptions) && (
322
- <fieldset
323
- className={classNames('ff-select-fieldset', {
324
- 'ff-select-fieldset--no-label': !showLabel,
325
- 'ff-select-fieldset--default': !isInputFocused,
326
- 'ff-select-fieldset--active': isInputFocused,
327
- 'ff-select-fieldset--option': applyActiveOptionClasses,
328
- 'ff-select-fieldset--error': errorMsg,
329
- 'ff-select-fieldset--border-radius': !borderRadius,
330
- 'ff-select-fieldset--no-border': !showBorder,
186
+ {showLabel && (
187
+ <Typography
188
+ as="span"
189
+ className={classNames('ff-select-label', {
190
+ 'ff-select-label__active': searchedOption,
331
191
  })}
192
+ fontSize={searchedOption && 8}
193
+ required={required}
332
194
  >
333
- {showLabel && (
334
- <legend
335
- className={classNames('ff-select-legend', {
336
- 'ff-select-legend--default': !isInputFocused,
337
- 'ff-select-legend--active': isInputFocused,
338
- 'ff-select-legend--option': applyActiveOptionClasses,
339
- 'ff-select-legend--error': errorMsg,
340
- })}
341
- >
342
- {required && (
343
- <Typography
344
- fontSize={8}
345
- color={'var(--error-light)'}
346
- className="ff-select-legend--required"
347
- >
348
- *
349
- </Typography>
350
- )}
351
- {label}
352
- </legend>
353
- )}
354
- </fieldset>
195
+ {label}
196
+ </Typography>
355
197
  )}
356
198
  </div>
357
-
358
199
  {errorMsg && (
359
200
  <Typography
360
- className="ff-select-wrapper-error-text"
201
+ as="div"
202
+ lineHeight="12px"
361
203
  fontSize={8}
362
- color={'var(--error-light)'}
204
+ color="var(--error_light)"
205
+ className="ff-select-error-msg"
363
206
  >
364
207
  {errorMsg}
365
208
  </Typography>
366
209
  )}
367
210
 
368
211
  {optionsRequired && (
369
- <div ref={DropDownRef}>
370
- {showOptions &&
212
+ <div ref={DropdownRef}>
213
+ {showDropdownOptions &&
371
214
  createPortal(
372
215
  <Dropdown
373
- onSelectBlur={onSelectBlur}
374
- onSelectOptionSelector={onSelectOptionSelector}
216
+ options={selectOptionList}
375
217
  dropdownPosition={dropdownPosition}
376
- options={options}
377
- optionZIndex={optionZIndex}
378
- inputRef={InputRef}
379
218
  labelAccessor={labelAccessor}
219
+ optionZIndex={optionZIndex}
220
+ inputRef={inputRef}
221
+ selectArrowRef={selectArrowRef}
222
+ onSelectBlur={onSelectBlur}
223
+ onSelectOptionSelector={onSelectOptionSelector}
380
224
  />,
381
225
  document.body
382
226
  )}
@@ -0,0 +1,50 @@
1
+ .ff-select-dropdown-wrapper {
2
+ max-height: 160px;
3
+ z-index: 999999;
4
+ position: absolute;
5
+ min-width: 50px;
6
+ border-radius: 4px;
7
+ border: 1px solid var(--ff-select-option-border-color);
8
+ margin-top: 4px;
9
+ box-shadow: 0px 1px 4px 0px var(--ff-select-option-wrapper-box-shadow);
10
+ background-color: var(--ff-select-background-color);
11
+ overflow: hidden auto;
12
+
13
+ &::-webkit-scrollbar {
14
+ width: 4px;
15
+ height: 12px;
16
+ &-thumb {
17
+ background-color: var(--ff-select-scroll-thumb-color);
18
+ border-radius: 4px;
19
+ }
20
+
21
+ &-track {
22
+ background: var(--ff-select-scroll-track-bg);
23
+ border-radius: 4px;
24
+ }
25
+ }
26
+
27
+ .ff-select-dropdown-option {
28
+ box-sizing: border-box;
29
+ cursor: pointer;
30
+ padding: 0px 8px;
31
+ border-radius: 4px;
32
+ min-height: 32px;
33
+ white-space: nowrap;
34
+ text-overflow: ellipsis;
35
+ overflow: hidden;
36
+
37
+ &:hover {
38
+ background-color: var(--ff-select-option-hover-color);
39
+ }
40
+ }
41
+
42
+ .ff-select-no-option {
43
+ box-sizing: border-box;
44
+ padding: 0px 8px;
45
+ overflow: hidden;
46
+ white-space: nowrap;
47
+ text-overflow: ellipsis;
48
+ cursor: not-allowed;
49
+ }
50
+ }
@@ -0,0 +1,94 @@
1
+ import { useContext, useRef, type FC } from 'react';
2
+ import { dropdownDefaultCSSData, DropdownProps } from './types';
3
+ import './Dropdown.scss';
4
+ import { checkEmpty } from '../../../utils/checkEmpty/checkEmpty';
5
+ import Typography from '../../Typography';
6
+ import { ffid } from '../../../utils/ffID/ffid';
7
+ import { ThemeContext } from '../../ThemeProvider/ThemeProvider';
8
+ import classNames from 'classnames';
9
+ import { getLabel } from '../../../utils/getSelectOptionValue/getSelectOptionValue';
10
+ import useClickOutside from '../../../hooks/useClickOutside';
11
+
12
+ const Dropdown: FC<DropdownProps> = ({
13
+ options = [],
14
+ optionZIndex = 10000000,
15
+ dropdownPosition,
16
+ labelAccessor,
17
+ onSelectOptionSelector,
18
+ onSelectBlur,
19
+ inputRef,
20
+ selectArrowRef,
21
+ }) => {
22
+ const themeContext = useContext(ThemeContext);
23
+ const currentTheme = themeContext?.currentTheme;
24
+
25
+ const optionsWrapperRef = useRef<HTMLDivElement>(null);
26
+ useClickOutside(optionsWrapperRef, onSelectBlur, [inputRef, selectArrowRef]);
27
+
28
+ const { positionX, positionY, width, fromBottom } = dropdownPosition;
29
+ const { margin, optionHeight, selectInputHeight, dropDownWrapperPadding } =
30
+ dropdownDefaultCSSData;
31
+
32
+ const updateDropdownPosition = () => {
33
+ let dropdownContainerHeight;
34
+
35
+ if (checkEmpty(options)) {
36
+ dropdownContainerHeight = 32 + 2 * dropDownWrapperPadding;
37
+ } else if (options?.length > 5) {
38
+ dropdownContainerHeight = 160;
39
+ } else {
40
+ dropdownContainerHeight =
41
+ options.length * optionHeight + 2 * dropDownWrapperPadding;
42
+ }
43
+
44
+ if (fromBottom > dropdownContainerHeight + margin) {
45
+ return {
46
+ left: positionX,
47
+ top: positionY,
48
+ width: width,
49
+ zIndex: optionZIndex,
50
+ };
51
+ }
52
+ return {
53
+ zIndex: optionZIndex,
54
+ left: positionX,
55
+ width: width,
56
+ top: positionY - selectInputHeight - dropdownContainerHeight - margin,
57
+ };
58
+ };
59
+
60
+ return (
61
+ <div
62
+ className={classNames('ff-select-dropdown-wrapper', currentTheme)}
63
+ ref={optionsWrapperRef}
64
+ style={updateDropdownPosition()}
65
+ >
66
+ {!checkEmpty(options) ? (
67
+ options.map((option) => (
68
+ <Typography
69
+ key={ffid()}
70
+ as="div"
71
+ lineHeight="30px"
72
+ className={classNames('ff-select-dropdown-option', currentTheme)}
73
+ color="var(--ff-select-text-color)"
74
+ onClick={() => onSelectOptionSelector(option)}
75
+ >
76
+ {getLabel(option, labelAccessor)}
77
+ </Typography>
78
+ ))
79
+ ) : (
80
+ <Typography
81
+ textAlign="center"
82
+ as="div"
83
+ lineHeight="32px"
84
+ color="var(--ff-select-text-color)"
85
+ className={classNames('ff-select-no-option', currentTheme)}
86
+ >
87
+ No Results found
88
+ </Typography>
89
+ )}
90
+ </div>
91
+ );
92
+ };
93
+
94
+ export default Dropdown;
@@ -0,0 +1,20 @@
1
+ import { DrowdownPosition, Option } from '../types';
2
+
3
+ export interface DropdownProps {
4
+ options: Option[];
5
+ dropdownPosition: DrowdownPosition;
6
+ optionZIndex: number;
7
+ labelAccessor?: string;
8
+ valueAccessor?: string;
9
+ onSelectBlur: () => void;
10
+ onSelectOptionSelector: (option: Option) => void;
11
+ inputRef?: React.RefObject<HTMLInputElement>;
12
+ selectArrowRef?: React.RefObject<HTMLDivElement>;
13
+ }
14
+
15
+ export const dropdownDefaultCSSData = {
16
+ margin: 6,
17
+ optionHeight: 32,
18
+ selectInputHeight: 38,
19
+ dropDownWrapperPadding: 0,
20
+ };