@onewelcome/react-lib-components 1.2.0 → 1.4.0

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 (97) hide show
  1. package/dist/Button/IconButton.d.ts +2 -1
  2. package/dist/DataGrid/DataGrid.d.ts +1 -0
  3. package/dist/DataGrid/DataGridActions/DataGridActions.d.ts +2 -1
  4. package/dist/Form/Form.d.ts +3 -3
  5. package/dist/Notifications/SlideInModal/SlideInModal.d.ts +1 -1
  6. package/dist/Tabs/Tab.d.ts +5 -9
  7. package/dist/Tabs/TabButton.d.ts +3 -6
  8. package/dist/Tabs/Tabs.d.ts +1 -2
  9. package/dist/hooks/useDebouncedCallback.d.ts +1 -0
  10. package/dist/index.d.ts +1 -0
  11. package/dist/react-lib-components.cjs.development.js +472 -395
  12. package/dist/react-lib-components.cjs.development.js.map +1 -1
  13. package/dist/react-lib-components.cjs.production.min.js +1 -1
  14. package/dist/react-lib-components.cjs.production.min.js.map +1 -1
  15. package/dist/react-lib-components.esm.js +473 -397
  16. package/dist/react-lib-components.esm.js.map +1 -1
  17. package/package.json +1 -1
  18. package/src/Breadcrumbs/Breadcrumbs.tsx +46 -38
  19. package/src/Button/BaseButton.tsx +23 -20
  20. package/src/Button/Button.module.scss +9 -0
  21. package/src/Button/Button.tsx +40 -40
  22. package/src/Button/IconButton.tsx +28 -28
  23. package/src/ContextMenu/ContextMenu.tsx +161 -160
  24. package/src/ContextMenu/ContextMenuItem.tsx +55 -49
  25. package/src/DataGrid/DataGrid.tsx +1 -0
  26. package/src/DataGrid/DataGridActions/DataGridActions.module.scss +1 -1
  27. package/src/DataGrid/DataGridActions/DataGridActions.test.tsx +4 -2
  28. package/src/DataGrid/DataGridActions/DataGridActions.tsx +95 -87
  29. package/src/DataGrid/DataGridActions/DataGridColumnsToggle.tsx +64 -64
  30. package/src/DataGrid/DataGridBody/DataGridCell.tsx +42 -44
  31. package/src/DataGrid/DataGridBody/DataGridRow.tsx +29 -29
  32. package/src/DataGrid/DataGridHeader/DataGridHeader.tsx +78 -78
  33. package/src/DataGrid/DataGridHeader/DataGridHeaderCell.tsx +48 -48
  34. package/src/Form/Checkbox/Checkbox.tsx +134 -130
  35. package/src/Form/Fieldset/Fieldset.tsx +81 -78
  36. package/src/Form/Form.tsx +9 -4
  37. package/src/Form/FormControl/FormControl.module.scss +1 -20
  38. package/src/Form/FormControl/FormControl.tsx +36 -35
  39. package/src/Form/FormGroup/FormGroup.tsx +62 -62
  40. package/src/Form/FormHelperText/FormHelperText.tsx +19 -18
  41. package/src/Form/FormSelectorWrapper/FormSelectorWrapper.tsx +58 -53
  42. package/src/Form/Input/Input.tsx +90 -87
  43. package/src/Form/Label/Label.tsx +17 -16
  44. package/src/Form/Radio/Radio.tsx +91 -91
  45. package/src/Form/Select/Option.tsx +66 -60
  46. package/src/Form/Select/Select.tsx +207 -209
  47. package/src/Form/Textarea/Textarea.tsx +51 -53
  48. package/src/Form/Toggle/Toggle.tsx +26 -23
  49. package/src/Form/Wrapper/CheckboxWrapper/CheckboxWrapper.tsx +51 -43
  50. package/src/Form/Wrapper/InputWrapper/InputWrapper.tsx +112 -106
  51. package/src/Form/Wrapper/RadioWrapper/RadioWrapper.tsx +67 -62
  52. package/src/Form/Wrapper/SelectWrapper/SelectWrapper.tsx +42 -37
  53. package/src/Form/Wrapper/TextareaWrapper/TextareaWrapper.tsx +94 -94
  54. package/src/Form/Wrapper/Wrapper/Wrapper.tsx +73 -73
  55. package/src/Icon/Icon.module.scss +1 -0
  56. package/src/Icon/Icon.tsx +19 -16
  57. package/src/Link/Link.tsx +68 -63
  58. package/src/Notifications/BaseModal/BaseModal.tsx +68 -68
  59. package/src/Notifications/BaseModal/BaseModalActions/BaseModalActions.tsx +13 -10
  60. package/src/Notifications/BaseModal/BaseModalContent/BaseModalContent.tsx +33 -25
  61. package/src/Notifications/BaseModal/BaseModalHeader/BaseModalHeader.tsx +20 -17
  62. package/src/Notifications/Dialog/Dialog.tsx +83 -83
  63. package/src/Notifications/Dialog/DialogActions/DialogActions.tsx +17 -14
  64. package/src/Notifications/Dialog/DialogTitle/DialogTitle.tsx +15 -12
  65. package/src/Notifications/DiscardChangesModal/DiscardChangesDialog/DiscardChangesDialog.tsx +40 -40
  66. package/src/Notifications/SlideInModal/SlideInModal.module.scss +5 -5
  67. package/src/Notifications/SlideInModal/SlideInModal.test.tsx +7 -2
  68. package/src/Notifications/SlideInModal/SlideInModal.tsx +47 -27
  69. package/src/Pagination/Pagination.tsx +169 -169
  70. package/src/Popover/Popover.module.scss +1 -0
  71. package/src/Popover/Popover.tsx +43 -33
  72. package/src/ProgressBar/ProgressBar.tsx +17 -14
  73. package/src/Skeleton/Skeleton.tsx +23 -20
  74. package/src/StatusIndicator/StatusIndicator.tsx +18 -15
  75. package/src/Tabs/{TabPanel.module.scss → Tab.module.scss} +1 -1
  76. package/src/Tabs/Tab.test.tsx +1 -39
  77. package/src/Tabs/Tab.tsx +16 -10
  78. package/src/Tabs/TabButton.module.scss +0 -4
  79. package/src/Tabs/TabButton.test.tsx +3 -31
  80. package/src/Tabs/TabButton.tsx +35 -49
  81. package/src/Tabs/Tabs.test.tsx +40 -33
  82. package/src/Tabs/Tabs.tsx +107 -101
  83. package/src/TextEllipsis/TextEllipsis.tsx +50 -41
  84. package/src/Tiles/Tile.tsx +58 -56
  85. package/src/Tiles/Tiles.tsx +44 -41
  86. package/src/Tooltip/Tooltip.tsx +101 -100
  87. package/src/Typography/Typography.tsx +47 -44
  88. package/src/Wizard/BaseWizardSteps/BaseWizardSteps.tsx +55 -52
  89. package/src/Wizard/WizardSteps/WizardSteps.tsx +25 -22
  90. package/src/hooks/useDebouncedCallback.test.ts +140 -0
  91. package/src/hooks/useDebouncedCallback.tsx +32 -0
  92. package/src/index.ts +1 -0
  93. package/src/mixins.module.scss +2 -2
  94. package/src/util/helper.test.tsx +0 -28
  95. package/dist/Tabs/TabPanel.d.ts +0 -8
  96. package/src/Tabs/TabPanel.test.tsx +0 -92
  97. package/src/Tabs/TabPanel.tsx +0 -43
@@ -19,6 +19,7 @@ import classes from "./Select.module.scss";
19
19
  import React, {
20
20
  ComponentPropsWithRef,
21
21
  createRef,
22
+ ForwardRefRenderFunction,
22
23
  Fragment,
23
24
  ReactElement,
24
25
  useEffect,
@@ -53,238 +54,235 @@ export interface Props extends ComponentPropsWithRef<"select">, FormElement {
53
54
  /** Amount of items to be rendered before a search input is rendered */
54
55
  const renderSearchCondition = 10;
55
56
 
56
- export const Select = React.forwardRef<HTMLSelectElement, Props>(
57
- (
58
- {
59
- children,
60
- name,
61
- disabled = false,
62
- labeledBy,
63
- placeholder,
64
- describedBy,
65
- searchPlaceholder = "Search item",
66
- searchInputProps,
67
- selectButtonProps,
68
- className,
69
- error = false,
70
- value,
71
- clearLabel = "Clear selection",
72
- onChange,
73
- ...rest
74
- }: Props,
75
- ref
76
- ) => {
77
- const [expanded, setExpanded] = useState(false);
78
- const [filter, setFilter] = useState("");
79
- const [display, setDisplay] = useState("");
80
- const containerReference = useRef<HTMLDivElement>(null);
81
- const optionListReference = useRef<HTMLDivElement>(null);
82
- const [isSearching, setIsSearching] = useState(false);
83
- const [focusedSelectItem, setFocusedSelectItem] = useState(-1);
84
- const [shouldClick, setShouldClick] =
85
- useState(
86
- false
87
- ); /** We need this, because whenever we use the arrow keys to select the select item, and we focus the currently selected item it fires the "click" listener in Option component. Instead, we only want this to fire if we press "enter" or "spacebar" so we set this to true whenever that is the case, and back to false when it has been executed. */
88
- const [childrenCount] = useState(React.Children.count(children));
57
+ const SelectComponent: ForwardRefRenderFunction<HTMLSelectElement, Props> = (
58
+ {
59
+ children,
60
+ name,
61
+ disabled = false,
62
+ labeledBy,
63
+ placeholder,
64
+ describedBy,
65
+ searchPlaceholder = "Search item",
66
+ searchInputProps,
67
+ selectButtonProps,
68
+ className,
69
+ error = false,
70
+ value,
71
+ clearLabel = "Clear selection",
72
+ onChange,
73
+ ...rest
74
+ }: Props,
75
+ ref
76
+ ) => {
77
+ const [expanded, setExpanded] = useState(false);
78
+ const [filter, setFilter] = useState("");
79
+ const [display, setDisplay] = useState("");
80
+ const containerReference = useRef<HTMLDivElement>(null);
81
+ const optionListReference = useRef<HTMLDivElement>(null);
82
+ const [isSearching, setIsSearching] = useState(false);
83
+ const [focusedSelectItem, setFocusedSelectItem] = useState(-1);
84
+ const [shouldClick, setShouldClick] =
85
+ useState(
86
+ false
87
+ ); /** We need this, because whenever we use the arrow keys to select the select item, and we focus the currently selected item it fires the "click" listener in Option component. Instead, we only want this to fire if we press "enter" or "spacebar" so we set this to true whenever that is the case, and back to false when it has been executed. */
88
+ const [childrenCount] = useState(React.Children.count(children));
89
89
 
90
- const nativeSelect = (ref as React.RefObject<HTMLSelectElement>) || createRef();
91
- const searchInputRef = useRef<HTMLInputElement>(null);
92
- const customSelectButtonRef = useRef<HTMLButtonElement>(null);
90
+ const nativeSelect = (ref as React.RefObject<HTMLSelectElement>) || createRef();
91
+ const searchInputRef = useRef<HTMLInputElement>(null);
92
+ const customSelectButtonRef = useRef<HTMLButtonElement>(null);
93
93
 
94
- const { onArrowNavigation } = useArrowNavigation({
95
- expanded,
96
- setExpanded,
97
- isSearching,
98
- setIsSearching,
99
- setFocusedSelectItem,
100
- childrenCount,
101
- customSelectButtonRef,
102
- setShouldClick,
103
- searchInputRef,
104
- renderSearchCondition
105
- });
106
-
107
- const { listPosition, opacity, optionsListMaxHeight, setListPosition, setOpacity } =
108
- useSelectPositionList({ expanded, optionListReference, containerReference });
94
+ const { onArrowNavigation } = useArrowNavigation({
95
+ expanded,
96
+ setExpanded,
97
+ isSearching,
98
+ setIsSearching,
99
+ setFocusedSelectItem,
100
+ childrenCount,
101
+ customSelectButtonRef,
102
+ setShouldClick,
103
+ searchInputRef,
104
+ renderSearchCondition
105
+ });
109
106
 
110
- const syncDisplayValue = (val: string) => {
111
- React.Children.forEach(children, child => {
112
- if (child.props.value === val) {
113
- setDisplay(child.props.children);
114
- }
115
- });
116
- };
107
+ const { listPosition, opacity, optionsListMaxHeight, setListPosition, setOpacity } =
108
+ useSelectPositionList({ expanded, optionListReference, containerReference });
117
109
 
118
- const onOptionChangeHandler = (optionRef: React.RefObject<HTMLLIElement>) => {
119
- if (nativeSelect.current && optionRef.current) {
120
- nativeSelect.current.value = optionRef.current.getAttribute("data-value")!;
121
- nativeSelect.current.dispatchEvent(new Event("change", { bubbles: true }));
110
+ const syncDisplayValue = (val: string) => {
111
+ React.Children.forEach(children, child => {
112
+ if (child.props.value === val) {
113
+ setDisplay(child.props.children);
122
114
  }
115
+ });
116
+ };
123
117
 
124
- setExpanded(false);
118
+ const onOptionChangeHandler = (optionRef: React.RefObject<HTMLLIElement>) => {
119
+ if (nativeSelect.current && optionRef.current) {
120
+ nativeSelect.current.value = optionRef.current.getAttribute("data-value")!;
121
+ nativeSelect.current.dispatchEvent(new Event("change", { bubbles: true }));
122
+ }
125
123
 
126
- customSelectButtonRef.current && customSelectButtonRef.current.focus();
127
- };
124
+ setExpanded(false);
128
125
 
129
- /**
130
- * @description We have to modify the children (Option component) to have a additional props that allows us to keep track of which one is selected and focused at all times and if a filter is active.
131
- * The `children` prop can be either a single object (1 child) or an array of multiple children.
132
- */
133
- const renderOptions = () => {
134
- if (isSearching || filter !== "") {
135
- const filteredChildren = React.Children.toArray(children).filter(
136
- child =>
137
- (child as ReactElement).props.children.toLowerCase().match(filter.toLowerCase()) !==
138
- null
139
- );
126
+ customSelectButtonRef.current && customSelectButtonRef.current.focus();
127
+ };
140
128
 
141
- return _internalRenderChildren(filteredChildren as ReactElement[]);
142
- }
129
+ /**
130
+ * @description We have to modify the children (Option component) to have a additional props that allows us to keep track of which one is selected and focused at all times and if a filter is active.
131
+ * The `children` prop can be either a single object (1 child) or an array of multiple children.
132
+ */
133
+ const renderOptions = () => {
134
+ if (isSearching || filter !== "") {
135
+ const filteredChildren = React.Children.toArray(children).filter(
136
+ child =>
137
+ (child as ReactElement).props.children.toLowerCase().match(filter.toLowerCase()) !== null
138
+ );
143
139
 
144
- return _internalRenderChildren(children);
140
+ return _internalRenderChildren(filteredChildren as ReactElement[]);
141
+ }
145
142
 
146
- function _internalRenderChildren(internalChildren: ReactElement[]) {
147
- return React.Children.map(internalChildren, (child, index) => {
148
- return React.cloneElement(child, {
149
- onFocusChange: (childIndex: number) => setFocusedSelectItem(childIndex),
150
- onOptionSelect: (optionRef: React.RefObject<HTMLLIElement>) => {
151
- onOptionChangeHandler(optionRef);
152
- setShouldClick(false);
153
- },
154
- isSelected: child.props.value === value,
155
- isSearching: isSearching,
156
- selectOpened: expanded,
157
- childIndex: index,
158
- hasFocus: focusedSelectItem === index,
159
- shouldClick: shouldClick
160
- });
143
+ return _internalRenderChildren(children);
144
+
145
+ function _internalRenderChildren(internalChildren: ReactElement[]) {
146
+ return React.Children.map(internalChildren, (child, index) => {
147
+ return React.cloneElement(child, {
148
+ onFocusChange: (childIndex: number) => setFocusedSelectItem(childIndex),
149
+ onOptionSelect: (optionRef: React.RefObject<HTMLLIElement>) => {
150
+ onOptionChangeHandler(optionRef);
151
+ setShouldClick(false);
152
+ },
153
+ isSelected: child.props.value === value,
154
+ isSearching: isSearching,
155
+ selectOpened: expanded,
156
+ childIndex: index,
157
+ hasFocus: focusedSelectItem === index,
158
+ shouldClick: shouldClick
161
159
  });
162
- }
163
- };
160
+ });
161
+ }
162
+ };
164
163
 
165
- const renderSearch = () => (
166
- <Input
167
- {...searchInputProps}
168
- autoFocus
169
- ref={searchInputRef}
170
- onFocus={() => setIsSearching(true)}
171
- onBlur={() => setIsSearching(false)}
172
- onChange={filterResults}
173
- className={classes["select-search"]}
174
- wrapperProps={{
175
- className: `${classes["select-search-wrapper"]} ${searchInputProps?.wrapperProps?.className}`
176
- }}
177
- type="text"
178
- name="search-option"
179
- placeholder={searchPlaceholder}
180
- />
181
- );
164
+ const renderSearch = () => (
165
+ <Input
166
+ {...searchInputProps}
167
+ autoFocus
168
+ ref={searchInputRef}
169
+ onFocus={() => setIsSearching(true)}
170
+ onBlur={() => setIsSearching(false)}
171
+ onChange={filterResults}
172
+ className={classes["select-search"]}
173
+ wrapperProps={{
174
+ className: `${classes["select-search-wrapper"]} ${searchInputProps?.wrapperProps?.className}`
175
+ }}
176
+ type="text"
177
+ name="search-option"
178
+ placeholder={searchPlaceholder}
179
+ />
180
+ );
182
181
 
183
- const filterResults = (event: React.ChangeEvent<HTMLInputElement>) => {
184
- setFilter(event.currentTarget.value);
185
- };
182
+ const filterResults = (event: React.ChangeEvent<HTMLInputElement>) => {
183
+ setFilter(event.currentTarget.value);
184
+ };
186
185
 
187
- const statusIcon = () => {
188
- if (error) {
189
- return <Icon className={classes["warning"]} icon={Icons.Warning} />;
190
- }
186
+ const statusIcon = () => {
187
+ if (error) {
188
+ return <Icon className={classes["warning"]} icon={Icons.Warning} />;
189
+ }
191
190
 
192
- return null;
193
- };
191
+ return null;
192
+ };
194
193
 
195
- const nativeOnChangeHandler = (event: React.ChangeEvent<HTMLSelectElement>) => {
196
- onChange && onChange(event);
197
- };
194
+ const nativeOnChangeHandler = (event: React.ChangeEvent<HTMLSelectElement>) => {
195
+ onChange && onChange(event);
196
+ };
198
197
 
199
- useEffect(() => {
200
- syncDisplayValue(value);
201
- }, [value]);
198
+ useEffect(() => {
199
+ syncDisplayValue(value);
200
+ }, [value]);
202
201
 
203
- useBodyClick(
204
- (event: MouseEvent) => !(event.target as Element).closest(".custom-select") && expanded,
205
- () => {
206
- setExpanded(false);
207
- setListPosition({ top: 0, bottom: "initial" });
208
- setOpacity(0);
209
- },
210
- expanded
211
- );
202
+ useBodyClick(
203
+ (event: MouseEvent) => !(event.target as Element).closest(".custom-select") && expanded,
204
+ () => {
205
+ setExpanded(false);
206
+ setListPosition({ top: 0, bottom: "initial" });
207
+ setOpacity(0);
208
+ },
209
+ expanded
210
+ );
212
211
 
213
- const additionalClasses = [];
214
- expanded && additionalClasses.push(classes.expanded);
215
- error && additionalClasses.push(classes.error);
216
- disabled && additionalClasses.push(classes.disabled);
217
- className && additionalClasses.push(className);
212
+ const additionalClasses = [];
213
+ expanded && additionalClasses.push(classes.expanded);
214
+ error && additionalClasses.push(classes.error);
215
+ disabled && additionalClasses.push(classes.disabled);
216
+ className && additionalClasses.push(className);
218
217
 
219
- /** The native select is purely for external form libraries. We use it to emit an onChange with native select event object so they know exactly what's happening. */
220
- return (
221
- <Fragment>
222
- <select
223
- {...filterProps(rest, /^data-/, false)}
224
- tabIndex={-1}
225
- aria-hidden="true"
226
- ref={nativeSelect}
218
+ /** The native select is purely for external form libraries. We use it to emit an onChange with native select event object so they know exactly what's happening. */
219
+ return (
220
+ <Fragment>
221
+ <select
222
+ {...filterProps(rest, /^data-/, false)}
223
+ tabIndex={-1}
224
+ aria-hidden="true"
225
+ ref={nativeSelect}
226
+ name={name}
227
+ onChange={nativeOnChangeHandler}
228
+ className={readyclasses["sr-only"]}
229
+ >
230
+ <option value=""></option>
231
+ {React.Children.map(children, child => (
232
+ <option value={child.props.value}></option>
233
+ ))}
234
+ </select>
235
+ <div
236
+ {...filterProps(rest, /^data-/)}
237
+ ref={containerReference}
238
+ onKeyDown={onArrowNavigation}
239
+ className={`custom-select ${classes.select} ${additionalClasses.join(" ")} ${
240
+ className ?? ""
241
+ }`}
242
+ >
243
+ <button
244
+ {...selectButtonProps}
245
+ onClick={() => {
246
+ setExpanded(!expanded);
247
+ }}
248
+ ref={customSelectButtonRef}
249
+ type="button"
227
250
  name={name}
228
- onChange={nativeOnChangeHandler}
229
- className={readyclasses["sr-only"]}
251
+ className={`${classes["custom-select"]} ${additionalClasses.join(" ")} `}
252
+ disabled={disabled}
253
+ aria-disabled={disabled}
254
+ aria-invalid={error}
255
+ aria-expanded={expanded}
256
+ aria-haspopup="listbox"
257
+ aria-labelledby={labeledBy}
258
+ aria-describedby={describedBy}
230
259
  >
231
- <option value=""></option>
232
- {React.Children.map(children, child => (
233
- <option value={child.props.value}></option>
234
- ))}
235
- </select>
260
+ <div data-display className={classes["selected"]}>
261
+ {!value && placeholder && <span className={classes["placeholder"]}>{placeholder}</span>}
262
+ {value?.length > 0 && <span data-display-inner>{display}</span>}
263
+ </div>
264
+ <div className={classes["status"]}>
265
+ {statusIcon()}
266
+ <Icon className={classes["triangle-down"]} icon={Icons.TriangleDown} />
267
+ </div>
268
+ </button>
236
269
  <div
237
- {...filterProps(rest, /^data-/)}
238
- ref={containerReference}
239
- onKeyDown={onArrowNavigation}
240
- className={`custom-select ${classes.select} ${additionalClasses.join(" ")} ${
241
- className ?? ""
242
- }`}
270
+ ref={optionListReference}
271
+ className={`list-wrapper ${classes["list-wrapper"]}`}
272
+ style={{
273
+ display: expanded ? "block" : "none",
274
+ opacity: opacity,
275
+ maxHeight: optionsListMaxHeight,
276
+ pointerEvents: expanded ? "auto" : "none",
277
+ ...listPosition
278
+ }}
243
279
  >
244
- <button
245
- {...selectButtonProps}
246
- onClick={() => {
247
- setExpanded(!expanded);
248
- }}
249
- ref={customSelectButtonRef}
250
- type="button"
251
- name={name}
252
- className={`${classes["custom-select"]} ${additionalClasses.join(" ")} `}
253
- disabled={disabled}
254
- aria-disabled={disabled}
255
- aria-invalid={error}
256
- aria-expanded={expanded}
257
- aria-haspopup="listbox"
258
- aria-labelledby={labeledBy}
259
- aria-describedby={describedBy}
260
- >
261
- <div data-display className={classes["selected"]}>
262
- {!value && placeholder && (
263
- <span className={classes["placeholder"]}>{placeholder}</span>
264
- )}
265
- {value?.length > 0 && <span data-display-inner>{display}</span>}
266
- </div>
267
- <div className={classes["status"]}>
268
- {statusIcon()}
269
- <Icon className={classes["triangle-down"]} icon={Icons.TriangleDown} />
270
- </div>
271
- </button>
272
- <div
273
- ref={optionListReference}
274
- className={`list-wrapper ${classes["list-wrapper"]}`}
275
- style={{
276
- display: expanded ? "block" : "none",
277
- opacity: opacity,
278
- maxHeight: optionsListMaxHeight,
279
- pointerEvents: expanded ? "auto" : "none",
280
- ...listPosition
281
- }}
282
- >
283
- {Array.isArray(children) && children.length > renderSearchCondition && renderSearch()}
284
- <ul role="listbox">{renderOptions()}</ul>
285
- </div>
280
+ {Array.isArray(children) && children.length > renderSearchCondition && renderSearch()}
281
+ <ul role="listbox">{renderOptions()}</ul>
286
282
  </div>
287
- </Fragment>
288
- );
289
- }
290
- );
283
+ </div>
284
+ </Fragment>
285
+ );
286
+ };
287
+
288
+ export const Select = React.forwardRef(SelectComponent);
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import React, { ComponentPropsWithRef, useState } from "react";
17
+ import React, { ForwardRefRenderFunction, ComponentPropsWithRef, useState } from "react";
18
18
  import { Icon, Props as IconProps, Icons } from "../../Icon/Icon";
19
19
  import classes from "./Textarea.module.scss";
20
20
  import { FormElement } from "../form.interfaces";
@@ -26,59 +26,57 @@ export interface Props extends ComponentPropsWithRef<"textarea">, FormElement {
26
26
  errorProps?: IconPropsPartial;
27
27
  }
28
28
 
29
- export const Textarea = React.forwardRef<HTMLTextAreaElement, Props>(
30
- (
31
- {
32
- error = false,
33
- disabled = false,
34
- className,
35
- rows = 4,
36
- wrapperProps,
37
- errorProps,
38
- onFocus,
39
- onBlur,
40
- ...rest
41
- }: Props,
42
- ref
43
- ) => {
44
- const [focus, setFocus] = useState(false);
29
+ const TextareaComponent: ForwardRefRenderFunction<HTMLTextAreaElement, Props> = (
30
+ {
31
+ error = false,
32
+ disabled = false,
33
+ className,
34
+ rows = 4,
35
+ wrapperProps,
36
+ errorProps,
37
+ onFocus,
38
+ onBlur,
39
+ ...rest
40
+ }: Props,
41
+ ref
42
+ ) => {
43
+ const [focus, setFocus] = useState(false);
45
44
 
46
- const wrapperClasses = [classes["textarea-wrapper"]];
47
- const outlineClasses = [classes["outline"]];
45
+ const wrapperClasses = [classes["textarea-wrapper"]];
46
+ const outlineClasses = [classes["outline"]];
48
47
 
49
- wrapperProps?.className && wrapperClasses.push(wrapperProps.className);
50
- disabled &&
51
- wrapperClasses.push(classes["disabled"]) &&
52
- outlineClasses.push(classes["disabled"]);
53
- error && wrapperClasses.push(classes["error"]) && outlineClasses.push(classes["error"]);
54
- focus && wrapperClasses.push(classes["focus"]) && outlineClasses.push(classes["focus"]);
48
+ wrapperProps?.className && wrapperClasses.push(wrapperProps.className);
49
+ disabled && wrapperClasses.push(classes["disabled"]) && outlineClasses.push(classes["disabled"]);
50
+ error && wrapperClasses.push(classes["error"]) && outlineClasses.push(classes["error"]);
51
+ focus && wrapperClasses.push(classes["focus"]) && outlineClasses.push(classes["focus"]);
55
52
 
56
- return (
57
- <div {...wrapperProps} className={wrapperClasses.join(" ")}>
58
- <textarea
59
- {...rest}
60
- ref={ref}
61
- rows={rows}
62
- className={`${error ? classes["error"] : ""} ${classes["textarea"]} ${className ?? ""}`}
63
- disabled={disabled}
64
- onFocus={event => {
65
- setFocus(true);
66
- onFocus && onFocus(event);
67
- }}
68
- onBlur={event => {
69
- setFocus(false);
70
- onBlur && onBlur(event);
71
- }}
53
+ return (
54
+ <div {...wrapperProps} className={wrapperClasses.join(" ")}>
55
+ <textarea
56
+ {...rest}
57
+ ref={ref}
58
+ rows={rows}
59
+ className={`${error ? classes["error"] : ""} ${classes["textarea"]} ${className ?? ""}`}
60
+ disabled={disabled}
61
+ onFocus={event => {
62
+ setFocus(true);
63
+ onFocus && onFocus(event);
64
+ }}
65
+ onBlur={event => {
66
+ setFocus(false);
67
+ onBlur && onBlur(event);
68
+ }}
69
+ />
70
+ {error && (
71
+ <Icon
72
+ {...errorProps}
73
+ className={`${classes["warning"]} ${errorProps?.className ?? ""}`}
74
+ icon={Icons.Error}
72
75
  />
73
- {error && (
74
- <Icon
75
- {...errorProps}
76
- className={`${classes["warning"]} ${errorProps?.className ?? ""}`}
77
- icon={Icons.Error}
78
- />
79
- )}
80
- <span className={outlineClasses.join(" ")}></span>
81
- </div>
82
- );
83
- }
84
- );
76
+ )}
77
+ <span className={outlineClasses.join(" ")}></span>
78
+ </div>
79
+ );
80
+ };
81
+
82
+ export const Textarea = React.forwardRef(TextareaComponent);
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import React, { ComponentPropsWithRef } from "react";
17
+ import React, { ForwardRefRenderFunction, ComponentPropsWithRef } from "react";
18
18
  import { Checkbox, Props as CheckboxProps } from "../Checkbox/Checkbox";
19
19
  import classes from "./Toggle.module.scss";
20
20
 
@@ -24,26 +24,29 @@ export interface Props
24
24
  children: string;
25
25
  }
26
26
 
27
- export const Toggle = React.forwardRef<HTMLInputElement, Props>(
28
- ({ children, checked, disabled, helperProps, ...rest }: Props, ref) => (
29
- <div className={classes["toggle-wrapper"]}>
30
- <Checkbox
31
- {...rest}
32
- ref={ref}
33
- checked={checked}
34
- className={classes["checkbox"]}
35
- helperProps={{ className: classes["toggle-helper"], ...helperProps }}
36
- disabled={disabled}
37
- label={children}
38
- >
39
- <span
40
- data-toggle
41
- aria-hidden="true"
42
- className={`${classes["toggle"]} ${checked ? classes["checked"] : ""} ${
43
- disabled ? classes["disabled"] : ""
44
- } `}
45
- ></span>
46
- </Checkbox>
47
- </div>
48
- )
27
+ const ToggleComponent: ForwardRefRenderFunction<HTMLInputElement, Props> = (
28
+ { children, checked, disabled, helperProps, ...rest }: Props,
29
+ ref
30
+ ) => (
31
+ <div className={classes["toggle-wrapper"]}>
32
+ <Checkbox
33
+ {...rest}
34
+ ref={ref}
35
+ checked={checked}
36
+ className={classes["checkbox"]}
37
+ helperProps={{ className: classes["toggle-helper"], ...helperProps }}
38
+ disabled={disabled}
39
+ label={children}
40
+ >
41
+ <span
42
+ data-toggle
43
+ aria-hidden="true"
44
+ className={`${classes["toggle"]} ${checked ? classes["checked"] : ""} ${
45
+ disabled ? classes["disabled"] : ""
46
+ } `}
47
+ ></span>
48
+ </Checkbox>
49
+ </div>
49
50
  );
51
+
52
+ export const Toggle = React.forwardRef(ToggleComponent);