@onewelcome/react-lib-components 0.2.0 → 0.2.3
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/dist/Breadcrumbs/Breadcrumbs.d.ts +4 -4
- package/dist/Button/BaseButton.d.ts +4 -4
- package/dist/Button/Button.d.ts +3 -3
- package/dist/Button/IconButton.d.ts +4 -4
- package/dist/ContextMenu/ContextMenu.d.ts +5 -5
- package/dist/ContextMenu/ContextMenuItem.d.ts +2 -2
- package/dist/DataGrid/DataGrid.d.ts +6 -6
- package/dist/DataGrid/DataGridActions/DataGridActions.d.ts +4 -4
- package/dist/DataGrid/DataGridActions/DataGridColumnsToggle.d.ts +3 -3
- package/dist/DataGrid/DataGridBody/DataGridBody.d.ts +3 -3
- package/dist/DataGrid/DataGridBody/DataGridCell.d.ts +2 -2
- package/dist/DataGrid/DataGridBody/DataGridRow.d.ts +3 -3
- package/dist/DataGrid/DataGridHeader/DataGridHeader.d.ts +3 -3
- package/dist/DataGrid/DataGridHeader/DataGridHeaderCell.d.ts +3 -3
- package/dist/DataGrid/datagrid.interfaces.d.ts +1 -1
- package/dist/Form/Checkbox/Checkbox.d.ts +5 -5
- package/dist/Form/Fieldset/Fieldset.d.ts +3 -3
- package/dist/Form/Form.d.ts +1 -1
- package/dist/Form/FormControl/FormControl.d.ts +3 -3
- package/dist/Form/FormGroup/FormGroup.d.ts +5 -5
- package/dist/Form/FormHelperText/FormHelperText.d.ts +3 -3
- package/dist/Form/FormSelectorWrapper/FormSelectorWrapper.d.ts +6 -6
- package/dist/Form/Input/Input.d.ts +5 -5
- package/dist/Form/Label/Label.d.ts +2 -2
- package/dist/Form/Radio/Radio.d.ts +5 -5
- package/dist/Form/Select/Option.d.ts +2 -2
- package/dist/Form/Select/Select.d.ts +5 -5
- package/dist/Form/Textarea/Textarea.d.ts +6 -6
- package/dist/Form/Toggle/Toggle.d.ts +3 -3
- package/dist/Form/Wrapper/CheckboxWrapper/CheckboxWrapper.d.ts +4 -4
- package/dist/Form/Wrapper/InputWrapper/InputWrapper.d.ts +4 -4
- package/dist/Form/Wrapper/RadioWrapper/RadioWrapper.d.ts +4 -4
- package/dist/Form/Wrapper/SelectWrapper/SelectWrapper.d.ts +4 -4
- package/dist/Form/Wrapper/TextareaWrapper/TextareaWrapper.d.ts +4 -4
- package/dist/Form/Wrapper/Wrapper/Wrapper.d.ts +6 -6
- package/dist/Form/form.interfaces.d.ts +1 -1
- package/dist/Icon/Icon.d.ts +3 -3
- package/dist/Link/Link.d.ts +7 -7
- package/dist/Notifications/BaseModal/BaseModal.d.ts +4 -4
- package/dist/Notifications/BaseModal/BaseModalActions/BaseModalActions.d.ts +2 -2
- package/dist/Notifications/BaseModal/BaseModalContent/BaseModalContent.d.ts +2 -2
- package/dist/Notifications/BaseModal/BaseModalHeader/BaseModalHeader.d.ts +2 -2
- package/dist/Notifications/Dialog/Dialog.d.ts +5 -5
- package/dist/Notifications/Dialog/DialogActions/DialogActions.d.ts +3 -3
- package/dist/Notifications/Dialog/DialogTitle/DialogTitle.d.ts +2 -2
- package/dist/Notifications/DiscardChangesModal/DiscardChangesDialog/DiscardChangesDialog.d.ts +3 -3
- package/dist/Notifications/DiscardChangesModal/DiscardChangesModal.d.ts +7 -7
- package/dist/Notifications/Modal/Modal.d.ts +1 -1
- package/dist/Notifications/Modal/ModalActions/ModalActions.d.ts +1 -1
- package/dist/Notifications/Modal/ModalContent/ModalContent.d.ts +1 -1
- package/dist/Notifications/Modal/ModalHeader/ModalHeader.d.ts +1 -1
- package/dist/Notifications/SlideInModal/SlideInModal.d.ts +3 -3
- package/dist/Notifications/Snackbar/SnackbarContainer/SnackbarContainer.d.ts +3 -3
- package/dist/Notifications/Snackbar/SnackbarItem/SnackbarItem.d.ts +2 -2
- package/dist/Notifications/Snackbar/SnackbarProvider/SnackbarProvider.d.ts +3 -3
- package/dist/Notifications/Snackbar/SnackbarProvider/SnackbarStateProvider.d.ts +2 -2
- package/dist/Notifications/Snackbar/interfaces.d.ts +2 -2
- package/dist/Pagination/Pagination.d.ts +3 -3
- package/dist/Popover/Popover.d.ts +3 -3
- package/dist/Skeleton/Skeleton.d.ts +3 -3
- package/dist/StatusIndicator/StatusIndicator.d.ts +5 -5
- package/dist/Tabs/Tab.d.ts +1 -1
- package/dist/Tabs/TabButton.d.ts +2 -2
- package/dist/Tabs/TabPanel.d.ts +2 -2
- package/dist/Tabs/Tabs.d.ts +4 -4
- package/dist/TextEllipsis/TextEllipsis.d.ts +2 -2
- package/dist/Tiles/Tile.d.ts +5 -5
- package/dist/Tiles/Tiles.d.ts +2 -2
- package/dist/Tooltip/Tooltip.d.ts +3 -3
- package/dist/Typography/Typography.d.ts +3 -3
- package/dist/Wizard/BaseWizardSteps/BaseWizardSteps.d.ts +2 -2
- package/dist/Wizard/Wizard.d.ts +3 -3
- package/dist/Wizard/WizardActions/WizardActions.d.ts +2 -2
- package/dist/Wizard/WizardStateProvider.d.ts +2 -2
- package/dist/Wizard/WizardSteps/WizardSteps.d.ts +2 -2
- package/dist/Wizard/wizardStateReducer.d.ts +5 -5
- package/dist/_BaseStyling_/BaseStyling.d.ts +1 -1
- package/dist/hooks/usePosition.d.ts +4 -4
- package/dist/hooks/useRepeater.d.ts +1 -1
- package/dist/hooks/useScroll.d.ts +1 -1
- package/dist/hooks/useSpacing.d.ts +1 -1
- package/dist/hooks/useWrapper.d.ts +1 -1
- package/dist/index.d.ts +55 -55
- package/dist/react-lib-components.cjs.development.js +676 -578
- package/dist/react-lib-components.cjs.development.js.map +1 -1
- package/dist/react-lib-components.cjs.production.min.js +1 -1
- package/dist/react-lib-components.cjs.production.min.js.map +1 -1
- package/dist/react-lib-components.esm.js +676 -578
- package/dist/react-lib-components.esm.js.map +1 -1
- package/package.json +27 -16
- package/src/Breadcrumbs/Breadcrumbs.test.tsx +15 -15
- package/src/Breadcrumbs/Breadcrumbs.tsx +11 -11
- package/src/Button/BaseButton.module.scss +1 -1
- package/src/Button/BaseButton.test.tsx +27 -27
- package/src/Button/BaseButton.tsx +8 -8
- package/src/Button/Button.module.scss +5 -5
- package/src/Button/Button.test.tsx +39 -39
- package/src/Button/Button.tsx +10 -10
- package/src/Button/IconButton.module.scss +5 -5
- package/src/Button/IconButton.test.tsx +29 -29
- package/src/Button/IconButton.tsx +11 -11
- package/src/ContextMenu/ContextMenu.test.tsx +97 -76
- package/src/ContextMenu/ContextMenu.tsx +48 -42
- package/src/ContextMenu/ContextMenuItem.module.scss +1 -1
- package/src/ContextMenu/ContextMenuItem.tsx +7 -5
- package/src/DataGrid/DataGrid.test.tsx +193 -193
- package/src/DataGrid/DataGrid.tsx +26 -26
- package/src/DataGrid/DataGridActions/DataGridActions.test.tsx +63 -63
- package/src/DataGrid/DataGridActions/DataGridActions.tsx +15 -15
- package/src/DataGrid/DataGridActions/DataGridColumnsToggle.module.scss +1 -1
- package/src/DataGrid/DataGridActions/DataGridColumnsToggle.test.tsx +21 -21
- package/src/DataGrid/DataGridActions/DataGridColumnsToggle.tsx +20 -20
- package/src/DataGrid/DataGridBody/DataGridBody.test.tsx +40 -40
- package/src/DataGrid/DataGridBody/DataGridBody.tsx +10 -10
- package/src/DataGrid/DataGridBody/DataGridCell.module.scss +1 -1
- package/src/DataGrid/DataGridBody/DataGridCell.test.tsx +25 -25
- package/src/DataGrid/DataGridBody/DataGridCell.tsx +6 -6
- package/src/DataGrid/DataGridBody/DataGridRow.test.tsx +38 -38
- package/src/DataGrid/DataGridBody/DataGridRow.tsx +8 -8
- package/src/DataGrid/DataGridHeader/DataGridHeader.module.scss +1 -2
- package/src/DataGrid/DataGridHeader/DataGridHeader.test.tsx +119 -119
- package/src/DataGrid/DataGridHeader/DataGridHeader.tsx +13 -13
- package/src/DataGrid/DataGridHeader/DataGridHeaderCell.module.scss +2 -0
- package/src/DataGrid/DataGridHeader/DataGridHeaderCell.test.tsx +51 -51
- package/src/DataGrid/DataGridHeader/DataGridHeaderCell.tsx +14 -14
- package/src/DataGrid/datagrid.interfaces.ts +1 -1
- package/src/Form/Checkbox/Checkbox.test.tsx +74 -74
- package/src/Form/Checkbox/Checkbox.tsx +27 -27
- package/src/Form/Fieldset/Fieldset.module.scss +1 -1
- package/src/Form/Fieldset/Fieldset.test.tsx +35 -35
- package/src/Form/Fieldset/Fieldset.tsx +27 -27
- package/src/Form/Form.test.tsx +18 -18
- package/src/Form/Form.tsx +3 -3
- package/src/Form/FormControl/FormControl.test.tsx +22 -22
- package/src/Form/FormControl/FormControl.tsx +10 -10
- package/src/Form/FormGroup/FormGroup.test.tsx +37 -37
- package/src/Form/FormGroup/FormGroup.tsx +16 -16
- package/src/Form/FormHelperText/FormHelperText.test.tsx +18 -18
- package/src/Form/FormHelperText/FormHelperText.tsx +7 -7
- package/src/Form/FormSelectorWrapper/FormSelectorWrapper.test.tsx +15 -15
- package/src/Form/FormSelectorWrapper/FormSelectorWrapper.tsx +14 -14
- package/src/Form/Input/Input.module.scss +20 -44
- package/src/Form/Input/Input.test.tsx +121 -73
- package/src/Form/Input/Input.tsx +96 -35
- package/src/Form/Label/Label.test.tsx +13 -13
- package/src/Form/Label/Label.tsx +6 -6
- package/src/Form/Radio/Radio.test.tsx +35 -35
- package/src/Form/Radio/Radio.tsx +17 -17
- package/src/Form/Select/Option.test.tsx +10 -10
- package/src/Form/Select/Option.tsx +8 -8
- package/src/Form/Select/Select.module.scss +7 -9
- package/src/Form/Select/Select.test.tsx +144 -141
- package/src/Form/Select/Select.tsx +79 -78
- package/src/Form/Textarea/Textarea.module.scss +8 -18
- package/src/Form/Textarea/Textarea.test.tsx +27 -27
- package/src/Form/Textarea/Textarea.tsx +33 -13
- package/src/Form/Toggle/Toggle.module.scss +1 -1
- package/src/Form/Toggle/Toggle.test.tsx +22 -22
- package/src/Form/Toggle/Toggle.tsx +10 -10
- package/src/Form/Wrapper/CheckboxWrapper/CheckboxWrapper.test.tsx +39 -39
- package/src/Form/Wrapper/CheckboxWrapper/CheckboxWrapper.tsx +12 -12
- package/src/Form/Wrapper/InputWrapper/InputWrapper.module.scss +2 -8
- package/src/Form/Wrapper/InputWrapper/InputWrapper.test.tsx +55 -55
- package/src/Form/Wrapper/InputWrapper/InputWrapper.tsx +30 -35
- package/src/Form/Wrapper/RadioWrapper/RadioWrapper.test.tsx +35 -35
- package/src/Form/Wrapper/RadioWrapper/RadioWrapper.tsx +12 -12
- package/src/Form/Wrapper/SelectWrapper/SelectWrapper.test.tsx +55 -55
- package/src/Form/Wrapper/SelectWrapper/SelectWrapper.tsx +12 -12
- package/src/Form/Wrapper/TextareaWrapper/TextareaWrapper.module.scss +2 -11
- package/src/Form/Wrapper/TextareaWrapper/TextareaWrapper.test.tsx +50 -50
- package/src/Form/Wrapper/TextareaWrapper/TextareaWrapper.tsx +22 -22
- package/src/Form/Wrapper/Wrapper/Wrapper.module.scss +2 -2
- package/src/Form/Wrapper/Wrapper/Wrapper.test.tsx +11 -11
- package/src/Form/Wrapper/Wrapper/Wrapper.tsx +17 -17
- package/src/Form/form.interfaces.ts +1 -1
- package/src/Icon/Icon.module.scss +71 -71
- package/src/Icon/Icon.test.tsx +18 -18
- package/src/Icon/Icon.tsx +70 -70
- package/src/Link/Link.module.scss +5 -5
- package/src/Link/Link.test.tsx +76 -76
- package/src/Link/Link.tsx +27 -27
- package/src/Link/types.d.ts +1 -1
- package/src/Notifications/BaseModal/BaseModal.module.scss +1 -1
- package/src/Notifications/BaseModal/BaseModal.test.tsx +53 -53
- package/src/Notifications/BaseModal/BaseModal.tsx +16 -16
- package/src/Notifications/BaseModal/BaseModalActions/BaseModalActions.test.tsx +13 -13
- package/src/Notifications/BaseModal/BaseModalActions/BaseModalActions.tsx +5 -5
- package/src/Notifications/BaseModal/BaseModalContent/BaseModalContent.test.tsx +16 -16
- package/src/Notifications/BaseModal/BaseModalContent/BaseModalContent.tsx +5 -5
- package/src/Notifications/BaseModal/BaseModalHeader/BaseModalHeader.test.tsx +19 -19
- package/src/Notifications/BaseModal/BaseModalHeader/BaseModalHeader.tsx +10 -10
- package/src/Notifications/Dialog/Dialog.test.tsx +35 -35
- package/src/Notifications/Dialog/Dialog.tsx +19 -19
- package/src/Notifications/Dialog/DialogActions/DialogActions.test.tsx +14 -14
- package/src/Notifications/Dialog/DialogActions/DialogActions.tsx +6 -6
- package/src/Notifications/Dialog/DialogTitle/DialogTitle.test.tsx +12 -12
- package/src/Notifications/Dialog/DialogTitle/DialogTitle.tsx +6 -6
- package/src/Notifications/DiscardChangesModal/DiscardChangesDialog/DiscardChangesDialog.test.tsx +20 -20
- package/src/Notifications/DiscardChangesModal/DiscardChangesDialog/DiscardChangesDialog.tsx +7 -7
- package/src/Notifications/DiscardChangesModal/DiscardChangesModal.test.tsx +36 -36
- package/src/Notifications/DiscardChangesModal/DiscardChangesModal.tsx +8 -8
- package/src/Notifications/Modal/Modal.test.tsx +6 -6
- package/src/Notifications/Modal/Modal.tsx +1 -1
- package/src/Notifications/Modal/ModalActions/ModalActions.tsx +2 -2
- package/src/Notifications/Modal/ModalContent/ModalContent.tsx +2 -2
- package/src/Notifications/Modal/ModalHeader/ModalHeader.tsx +2 -2
- package/src/Notifications/SlideInModal/SlideInModal.test.tsx +16 -16
- package/src/Notifications/SlideInModal/SlideInModal.tsx +16 -11
- package/src/Notifications/Snackbar/SnackbarContainer/SnackbarContainer.test.tsx +16 -16
- package/src/Notifications/Snackbar/SnackbarContainer/SnackbarContainer.tsx +6 -6
- package/src/Notifications/Snackbar/SnackbarItem/SnackbarItem.module.scss +2 -2
- package/src/Notifications/Snackbar/SnackbarItem/SnackbarItem.test.tsx +17 -17
- package/src/Notifications/Snackbar/SnackbarItem/SnackbarItem.tsx +23 -23
- package/src/Notifications/Snackbar/SnackbarProvider/SnackbarProvider.test.tsx +32 -32
- package/src/Notifications/Snackbar/SnackbarProvider/SnackbarProvider.tsx +18 -18
- package/src/Notifications/Snackbar/SnackbarProvider/SnackbarStateProvider.tsx +3 -3
- package/src/Notifications/Snackbar/interfaces.ts +2 -2
- package/src/Notifications/Snackbar/useSnackbar.ts +2 -2
- package/src/Pagination/Pagination.module.scss +2 -0
- package/src/Pagination/Pagination.test.tsx +47 -47
- package/src/Pagination/Pagination.tsx +35 -35
- package/src/Popover/Popover.test.tsx +19 -19
- package/src/Popover/Popover.tsx +7 -7
- package/src/Skeleton/Skeleton.module.scss +2 -2
- package/src/Skeleton/Skeleton.test.tsx +29 -29
- package/src/Skeleton/Skeleton.tsx +10 -10
- package/src/StatusIndicator/StatusIndicator.test.tsx +38 -38
- package/src/StatusIndicator/StatusIndicator.tsx +9 -9
- package/src/Tabs/Tab.test.tsx +13 -13
- package/src/Tabs/Tab.tsx +1 -1
- package/src/Tabs/TabButton.test.tsx +28 -28
- package/src/Tabs/TabButton.tsx +7 -7
- package/src/Tabs/TabPanel.test.tsx +30 -30
- package/src/Tabs/TabPanel.tsx +4 -4
- package/src/Tabs/Tabs.test.tsx +93 -93
- package/src/Tabs/Tabs.tsx +25 -25
- package/src/TextEllipsis/TextEllipsis.test.tsx +22 -22
- package/src/TextEllipsis/TextEllipsis.tsx +6 -6
- package/src/Tiles/Tile.module.scss +1 -1
- package/src/Tiles/Tile.test.tsx +42 -42
- package/src/Tiles/Tile.tsx +22 -22
- package/src/Tiles/Tiles.test.tsx +30 -30
- package/src/Tiles/Tiles.tsx +9 -9
- package/src/Tooltip/Tooltip.test.tsx +35 -35
- package/src/Tooltip/Tooltip.tsx +21 -21
- package/src/Typography/Typography.module.scss +1 -1
- package/src/Typography/Typography.test.tsx +49 -49
- package/src/Typography/Typography.tsx +42 -42
- package/src/Wizard/BaseWizardSteps/BaseWizardSteps.module.scss +1 -1
- package/src/Wizard/BaseWizardSteps/BaseWizardSteps.test.tsx +26 -26
- package/src/Wizard/BaseWizardSteps/BaseWizardSteps.tsx +24 -24
- package/src/Wizard/Wizard.test.tsx +56 -56
- package/src/Wizard/Wizard.tsx +6 -6
- package/src/Wizard/WizardActions/WizardActions.test.tsx +34 -34
- package/src/Wizard/WizardActions/WizardActions.tsx +14 -14
- package/src/Wizard/WizardStateProvider.tsx +3 -3
- package/src/Wizard/WizardSteps/WizardSteps.test.tsx +27 -27
- package/src/Wizard/WizardSteps/WizardSteps.tsx +7 -7
- package/src/Wizard/wizardStateReducer.ts +9 -9
- package/src/_BaseStyling_/BaseStyling.test.tsx +14 -14
- package/src/_BaseStyling_/BaseStyling.tsx +50 -50
- package/src/hooks/useAnimation.test.tsx +12 -12
- package/src/hooks/useAnimation.ts +4 -4
- package/src/hooks/useBodyClick.test.tsx +8 -8
- package/src/hooks/useBodyClick.ts +3 -3
- package/src/hooks/useFormSelector.test.ts +17 -17
- package/src/hooks/useFormSelector.ts +4 -4
- package/src/hooks/usePosition.test.tsx +215 -215
- package/src/hooks/usePosition.ts +68 -68
- package/src/hooks/useRepeater.test.tsx +26 -26
- package/src/hooks/useRepeater.ts +5 -5
- package/src/hooks/useScroll.test.tsx +5 -5
- package/src/hooks/useScroll.ts +3 -3
- package/src/hooks/useSpacing.test.ts +40 -40
- package/src/hooks/useSpacing.ts +3 -3
- package/src/hooks/useWrapper.test.ts +12 -12
- package/src/hooks/useWrapper.ts +14 -7
- package/src/index.ts +67 -67
- package/src/mixins.module.scss +76 -27
- package/src/types.d.ts +1 -1
- package/src/util/helper.test.tsx +25 -25
- package/src/util/helper.tsx +64 -64
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import classes from
|
|
1
|
+
import classes from "./Select.module.scss";
|
|
2
2
|
|
|
3
3
|
import React, {
|
|
4
4
|
ComponentPropsWithRef,
|
|
@@ -7,18 +7,18 @@ import React, {
|
|
|
7
7
|
ReactElement,
|
|
8
8
|
useEffect,
|
|
9
9
|
useRef,
|
|
10
|
-
useState
|
|
11
|
-
} from
|
|
12
|
-
import { Input, Props as InputProps } from
|
|
13
|
-
import { Icon, Icons } from
|
|
14
|
-
import { FormElement } from
|
|
15
|
-
import { useBodyClick } from
|
|
16
|
-
import readyclasses from
|
|
17
|
-
import { filterProps } from
|
|
10
|
+
useState
|
|
11
|
+
} from "react";
|
|
12
|
+
import { Input, Props as InputProps } from "../Input/Input";
|
|
13
|
+
import { Icon, Icons } from "../../Icon/Icon";
|
|
14
|
+
import { FormElement } from "../form.interfaces";
|
|
15
|
+
import { useBodyClick } from "../../hooks/useBodyClick";
|
|
16
|
+
import readyclasses from "../../readyclasses.module.scss";
|
|
17
|
+
import { filterProps } from "../../util/helper";
|
|
18
18
|
|
|
19
19
|
type PartialInputProps = Partial<InputProps>;
|
|
20
20
|
|
|
21
|
-
export interface Props extends ComponentPropsWithRef<
|
|
21
|
+
export interface Props extends ComponentPropsWithRef<"select">, FormElement {
|
|
22
22
|
children: ReactElement[];
|
|
23
23
|
name?: string;
|
|
24
24
|
labeledBy?: string;
|
|
@@ -26,7 +26,7 @@ export interface Props extends ComponentPropsWithRef<'select'>, FormElement {
|
|
|
26
26
|
placeholder?: string;
|
|
27
27
|
searchPlaceholder?: string;
|
|
28
28
|
searchInputProps?: PartialInputProps;
|
|
29
|
-
selectButtonProps?: ComponentPropsWithRef<
|
|
29
|
+
selectButtonProps?: ComponentPropsWithRef<"button">;
|
|
30
30
|
className?: string;
|
|
31
31
|
value: string;
|
|
32
32
|
clearLabel?: string;
|
|
@@ -35,8 +35,8 @@ export interface Props extends ComponentPropsWithRef<'select'>, FormElement {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
type Position = {
|
|
38
|
-
top: 0 |
|
|
39
|
-
bottom: 0 |
|
|
38
|
+
top: 0 | "initial";
|
|
39
|
+
bottom: 0 | "initial";
|
|
40
40
|
};
|
|
41
41
|
|
|
42
42
|
/** Amount of items to be rendered before a search input is rendered */
|
|
@@ -51,13 +51,13 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
51
51
|
labeledBy,
|
|
52
52
|
placeholder,
|
|
53
53
|
describedBy,
|
|
54
|
-
searchPlaceholder =
|
|
54
|
+
searchPlaceholder = "Search item",
|
|
55
55
|
searchInputProps,
|
|
56
56
|
selectButtonProps,
|
|
57
57
|
className,
|
|
58
58
|
error = false,
|
|
59
59
|
value,
|
|
60
|
-
clearLabel =
|
|
60
|
+
clearLabel = "Clear selection",
|
|
61
61
|
onChange,
|
|
62
62
|
onClear,
|
|
63
63
|
...rest
|
|
@@ -66,10 +66,10 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
66
66
|
) => {
|
|
67
67
|
const [expanded, setExpanded] = useState(false);
|
|
68
68
|
const [opacity, setOpacity] = useState(0); // We set opacity because other wise if we calculate the max height you see the list full height for a split second and then it shortens.
|
|
69
|
-
const [filter, setFilter] = useState(
|
|
70
|
-
const [display, setDisplay] = useState(
|
|
69
|
+
const [filter, setFilter] = useState("");
|
|
70
|
+
const [display, setDisplay] = useState("");
|
|
71
71
|
const [listPosition, setListPosition] = useState<Partial<Position>>({});
|
|
72
|
-
const [optionsListMaxHeight, setOptionsListMaxHeight] = useState(
|
|
72
|
+
const [optionsListMaxHeight, setOptionsListMaxHeight] = useState("none");
|
|
73
73
|
const containerReference = useRef<HTMLDivElement>(null);
|
|
74
74
|
const optionListReference = useRef<HTMLDivElement>(null);
|
|
75
75
|
const [isSearching, setIsSearching] = useState(false);
|
|
@@ -85,21 +85,21 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
85
85
|
|
|
86
86
|
const onArrowNavigation = (event: React.KeyboardEvent) => {
|
|
87
87
|
const codesToPreventDefault = [
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
88
|
+
"ArrowDown",
|
|
89
|
+
"ArrowUp",
|
|
90
|
+
"ArrowLeft",
|
|
91
|
+
"ArrowRight",
|
|
92
|
+
"Space",
|
|
93
|
+
"Escape",
|
|
94
|
+
"End",
|
|
95
|
+
"Home"
|
|
96
96
|
];
|
|
97
97
|
|
|
98
|
-
const codesToPreventDefaultWhenSearching = [
|
|
98
|
+
const codesToPreventDefaultWhenSearching = ["ArrowDown", "ArrowUp", "Enter", "Escape"];
|
|
99
99
|
|
|
100
100
|
/** If the select is expanded, we also want to control the Tab key */
|
|
101
101
|
if (expanded) {
|
|
102
|
-
codesToPreventDefault.push(
|
|
102
|
+
codesToPreventDefault.push("Tab");
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
/** We will handle the way certain key strokes affect the Select, unless we're searching */
|
|
@@ -113,39 +113,39 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
113
113
|
|
|
114
114
|
if (isSearching) {
|
|
115
115
|
switch (event.code) {
|
|
116
|
-
case
|
|
117
|
-
case
|
|
116
|
+
case "ArrowDown":
|
|
117
|
+
case "Enter":
|
|
118
118
|
setIsSearching(false);
|
|
119
119
|
setFocusedSelectItem(0);
|
|
120
120
|
return;
|
|
121
|
-
case
|
|
121
|
+
case "ArrowUp":
|
|
122
122
|
setIsSearching(false);
|
|
123
123
|
setFocusedSelectItem(childrenCount - 1);
|
|
124
124
|
return;
|
|
125
|
-
case
|
|
126
|
-
case
|
|
125
|
+
case "Escape":
|
|
126
|
+
case "Tab":
|
|
127
127
|
setIsSearching(false);
|
|
128
128
|
setExpanded(false);
|
|
129
129
|
containerReference.current &&
|
|
130
|
-
containerReference.current.querySelector(
|
|
130
|
+
containerReference.current.querySelector("button")!.focus();
|
|
131
131
|
}
|
|
132
132
|
} else {
|
|
133
133
|
switch (event.code) {
|
|
134
|
-
case
|
|
134
|
+
case "ArrowDown":
|
|
135
135
|
if (!expanded) {
|
|
136
136
|
setExpanded(true);
|
|
137
137
|
return;
|
|
138
138
|
}
|
|
139
|
-
setFocusedSelectItem(
|
|
139
|
+
setFocusedSelectItem(prevState => {
|
|
140
140
|
return prevState + 1 > childrenCount - 1 ? 0 : prevState + 1;
|
|
141
141
|
});
|
|
142
142
|
return;
|
|
143
|
-
case
|
|
144
|
-
setFocusedSelectItem(
|
|
143
|
+
case "ArrowUp":
|
|
144
|
+
setFocusedSelectItem(prevState => {
|
|
145
145
|
return prevState - 1 < 0 ? childrenCount - 1 : prevState - 1;
|
|
146
146
|
});
|
|
147
147
|
return;
|
|
148
|
-
case
|
|
148
|
+
case "Space":
|
|
149
149
|
if (!expanded) {
|
|
150
150
|
setExpanded(true);
|
|
151
151
|
return;
|
|
@@ -154,9 +154,9 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
154
154
|
setShouldClick(true);
|
|
155
155
|
setExpanded(false);
|
|
156
156
|
containerReference.current &&
|
|
157
|
-
containerReference.current.querySelector(
|
|
157
|
+
containerReference.current.querySelector("button")!.focus();
|
|
158
158
|
return;
|
|
159
|
-
case
|
|
159
|
+
case "Tab":
|
|
160
160
|
if (childrenCount >= renderSearchCondition && expanded) {
|
|
161
161
|
setIsSearching(true);
|
|
162
162
|
searchInputRef.current && searchInputRef.current.focus();
|
|
@@ -165,17 +165,17 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
165
165
|
setExpanded(false);
|
|
166
166
|
|
|
167
167
|
return;
|
|
168
|
-
case
|
|
168
|
+
case "Escape":
|
|
169
169
|
if (expanded) {
|
|
170
170
|
setExpanded(false);
|
|
171
171
|
containerReference.current &&
|
|
172
|
-
containerReference.current.querySelector(
|
|
172
|
+
containerReference.current.querySelector("button")!.focus();
|
|
173
173
|
}
|
|
174
174
|
return;
|
|
175
|
-
case
|
|
175
|
+
case "End":
|
|
176
176
|
setFocusedSelectItem(childrenCount - 1);
|
|
177
177
|
return;
|
|
178
|
-
case
|
|
178
|
+
case "Home":
|
|
179
179
|
setFocusedSelectItem(0);
|
|
180
180
|
return;
|
|
181
181
|
}
|
|
@@ -183,7 +183,7 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
183
183
|
};
|
|
184
184
|
|
|
185
185
|
const syncDisplayValue = (val: string) => {
|
|
186
|
-
React.Children.forEach(children,
|
|
186
|
+
React.Children.forEach(children, child => {
|
|
187
187
|
if (child.props.value === val) {
|
|
188
188
|
setDisplay(child.props.children);
|
|
189
189
|
}
|
|
@@ -204,11 +204,11 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
204
204
|
window.innerHeight - containerReference.current.getBoundingClientRect().top;
|
|
205
205
|
|
|
206
206
|
// Set position as if there's more space on the bottom
|
|
207
|
-
let position: Position = { top: 0, bottom:
|
|
207
|
+
let position: Position = { top: 0, bottom: "initial" };
|
|
208
208
|
|
|
209
209
|
// Set the position of the select
|
|
210
210
|
if (spaceOnTopOfSelect > spaceOnBottomOfSelect) {
|
|
211
|
-
position = { top:
|
|
211
|
+
position = { top: "initial", bottom: 0 };
|
|
212
212
|
}
|
|
213
213
|
|
|
214
214
|
setListPosition(position);
|
|
@@ -220,10 +220,10 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
220
220
|
const calculateOptionListMaxHeight = (position: Position) => {
|
|
221
221
|
// Calculate max height if there's more space below the select
|
|
222
222
|
const listHeight = optionListReference.current!.getBoundingClientRect().height;
|
|
223
|
-
const transformOrigin = position.top !==
|
|
223
|
+
const transformOrigin = position.top !== "initial" ? "top" : "bottom";
|
|
224
224
|
|
|
225
225
|
const availableSpace =
|
|
226
|
-
transformOrigin ===
|
|
226
|
+
transformOrigin === "top"
|
|
227
227
|
? window.innerHeight -
|
|
228
228
|
containerReference.current!.getBoundingClientRect()[transformOrigin] -
|
|
229
229
|
16
|
|
@@ -235,19 +235,19 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
235
235
|
return;
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
setOptionsListMaxHeight(
|
|
238
|
+
setOptionsListMaxHeight("none");
|
|
239
239
|
setOpacity(100);
|
|
240
240
|
};
|
|
241
241
|
|
|
242
242
|
const onOptionChangeHandler = (optionRef: React.RefObject<HTMLLIElement>) => {
|
|
243
243
|
if (nativeSelect.current && optionRef.current) {
|
|
244
|
-
nativeSelect.current.value = optionRef.current.getAttribute(
|
|
245
|
-
nativeSelect.current.dispatchEvent(new Event(
|
|
244
|
+
nativeSelect.current.value = optionRef.current.getAttribute("data-value")!;
|
|
245
|
+
nativeSelect.current.dispatchEvent(new Event("change", { bubbles: true }));
|
|
246
246
|
}
|
|
247
247
|
|
|
248
248
|
setExpanded(false);
|
|
249
249
|
|
|
250
|
-
containerReference.current && containerReference.current.querySelector(
|
|
250
|
+
containerReference.current && containerReference.current.querySelector("button")!.focus();
|
|
251
251
|
};
|
|
252
252
|
|
|
253
253
|
/**
|
|
@@ -255,9 +255,9 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
255
255
|
* The `children` prop can be either a single object (1 child) or an array of multiple children.
|
|
256
256
|
*/
|
|
257
257
|
const renderOptions = () => {
|
|
258
|
-
if (isSearching || filter !==
|
|
258
|
+
if (isSearching || filter !== "") {
|
|
259
259
|
const filteredChildren = React.Children.toArray(children).filter(
|
|
260
|
-
|
|
260
|
+
child =>
|
|
261
261
|
(child as ReactElement).props.children.toLowerCase().match(filter.toLowerCase()) !==
|
|
262
262
|
null
|
|
263
263
|
);
|
|
@@ -280,7 +280,7 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
280
280
|
selectOpened: expanded,
|
|
281
281
|
childIndex: index,
|
|
282
282
|
hasFocus: focusedSelectItem === index,
|
|
283
|
-
shouldClick: shouldClick
|
|
283
|
+
shouldClick: shouldClick
|
|
284
284
|
});
|
|
285
285
|
});
|
|
286
286
|
}
|
|
@@ -294,9 +294,9 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
294
294
|
onFocus={() => setIsSearching(true)}
|
|
295
295
|
onBlur={() => setIsSearching(false)}
|
|
296
296
|
onChange={filterResults}
|
|
297
|
-
className={classes[
|
|
297
|
+
className={classes["select-search"]}
|
|
298
298
|
wrapperProps={{
|
|
299
|
-
className: `${classes[
|
|
299
|
+
className: `${classes["select-search-wrapper"]} ${searchInputProps?.wrapperProps?.className}`
|
|
300
300
|
}}
|
|
301
301
|
type="text"
|
|
302
302
|
name="search-option"
|
|
@@ -310,7 +310,7 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
310
310
|
|
|
311
311
|
const statusIcon = () => {
|
|
312
312
|
if (error) {
|
|
313
|
-
return <Icon className={classes[
|
|
313
|
+
return <Icon className={classes["warning"]} icon={Icons.Warning} />;
|
|
314
314
|
}
|
|
315
315
|
|
|
316
316
|
if (value?.length !== 0 && onClear) {
|
|
@@ -326,16 +326,16 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
326
326
|
onClear(e);
|
|
327
327
|
}}
|
|
328
328
|
onKeyDown={(e: React.KeyboardEvent<HTMLDivElement>) => {
|
|
329
|
-
if (e.code ===
|
|
329
|
+
if (e.code === "Enter" || e.code === "Space") {
|
|
330
330
|
e.preventDefault();
|
|
331
331
|
e.stopPropagation();
|
|
332
332
|
onClear(e);
|
|
333
333
|
containerReference.current &&
|
|
334
|
-
containerReference.current.querySelector(
|
|
334
|
+
containerReference.current.querySelector("button")!.focus();
|
|
335
335
|
}
|
|
336
336
|
}}
|
|
337
337
|
>
|
|
338
|
-
<span className={readyclasses[
|
|
338
|
+
<span className={readyclasses["sr-only"]}>{clearLabel}</span>
|
|
339
339
|
<Icon tag="span" icon={Icons.TimesThin} />
|
|
340
340
|
</div>
|
|
341
341
|
);
|
|
@@ -356,10 +356,10 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
356
356
|
}, [expanded]);
|
|
357
357
|
|
|
358
358
|
useBodyClick(
|
|
359
|
-
(event: MouseEvent) => !(event.target as Element).closest(
|
|
359
|
+
(event: MouseEvent) => !(event.target as Element).closest(".custom-select") && expanded,
|
|
360
360
|
() => {
|
|
361
|
-
setExpanded(
|
|
362
|
-
setListPosition({ top: 0, bottom:
|
|
361
|
+
setExpanded(false);
|
|
362
|
+
setListPosition({ top: 0, bottom: "initial" });
|
|
363
363
|
setOpacity(0);
|
|
364
364
|
},
|
|
365
365
|
expanded
|
|
@@ -381,10 +381,10 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
381
381
|
ref={nativeSelect}
|
|
382
382
|
name={name}
|
|
383
383
|
onChange={nativeOnChangeHandler}
|
|
384
|
-
className={readyclasses[
|
|
384
|
+
className={readyclasses["sr-only"]}
|
|
385
385
|
>
|
|
386
386
|
<option value=""></option>
|
|
387
|
-
{React.Children.map(children,
|
|
387
|
+
{React.Children.map(children, child => (
|
|
388
388
|
<option value={child.props.value}></option>
|
|
389
389
|
))}
|
|
390
390
|
</select>
|
|
@@ -392,8 +392,8 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
392
392
|
{...filterProps(rest, /^data-/)}
|
|
393
393
|
ref={containerReference}
|
|
394
394
|
onKeyDown={onArrowNavigation}
|
|
395
|
-
className={`custom-select ${classes.select} ${additionalClasses.join(
|
|
396
|
-
className ??
|
|
395
|
+
className={`custom-select ${classes.select} ${additionalClasses.join(" ")} ${
|
|
396
|
+
className ?? ""
|
|
397
397
|
}`}
|
|
398
398
|
>
|
|
399
399
|
<button
|
|
@@ -403,7 +403,7 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
403
403
|
}}
|
|
404
404
|
type="button"
|
|
405
405
|
name={name}
|
|
406
|
-
className={`${classes[
|
|
406
|
+
className={`${classes["custom-select"]} ${additionalClasses.join(" ")} `}
|
|
407
407
|
disabled={disabled}
|
|
408
408
|
aria-disabled={disabled}
|
|
409
409
|
aria-invalid={error}
|
|
@@ -412,25 +412,26 @@ export const Select = React.forwardRef<HTMLSelectElement, Props>(
|
|
|
412
412
|
aria-labelledby={labeledBy}
|
|
413
413
|
aria-describedby={describedBy}
|
|
414
414
|
>
|
|
415
|
-
<div data-display className={classes[
|
|
415
|
+
<div data-display className={classes["selected"]}>
|
|
416
416
|
{!value && placeholder && (
|
|
417
|
-
<span className={classes[
|
|
417
|
+
<span className={classes["placeholder"]}>{placeholder}</span>
|
|
418
418
|
)}
|
|
419
419
|
{value?.length > 0 && <span data-display-inner>{display}</span>}
|
|
420
420
|
</div>
|
|
421
|
-
<div className={classes[
|
|
421
|
+
<div className={classes["status"]}>
|
|
422
422
|
{statusIcon()}
|
|
423
|
-
<Icon className={classes[
|
|
423
|
+
<Icon className={classes["triangle-down"]} icon={Icons.TriangleDown} />
|
|
424
424
|
</div>
|
|
425
425
|
</button>
|
|
426
426
|
<div
|
|
427
427
|
ref={optionListReference}
|
|
428
|
-
className={`list-wrapper ${classes[
|
|
428
|
+
className={`list-wrapper ${classes["list-wrapper"]}`}
|
|
429
429
|
style={{
|
|
430
|
-
display: expanded ?
|
|
430
|
+
display: expanded ? "block" : "none",
|
|
431
431
|
opacity: opacity,
|
|
432
432
|
maxHeight: optionsListMaxHeight,
|
|
433
|
-
|
|
433
|
+
pointerEvents: expanded ? "auto" : "none",
|
|
434
|
+
...listPosition
|
|
434
435
|
}}
|
|
435
436
|
>
|
|
436
437
|
{Array.isArray(children) && children.length > renderSearchCondition && renderSearch()}
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
+
@import "../../mixins.module.scss";
|
|
2
|
+
|
|
1
3
|
.textarea-wrapper {
|
|
2
4
|
position: relative;
|
|
3
5
|
box-sizing: border-box;
|
|
4
6
|
width: 100%;
|
|
7
|
+
|
|
8
|
+
@include outlineStates;
|
|
5
9
|
}
|
|
6
10
|
|
|
7
11
|
.textarea {
|
|
8
12
|
padding: 0.75rem 3.75rem 0.75rem 1.25rem;
|
|
9
13
|
box-sizing: border-box;
|
|
10
|
-
border
|
|
11
|
-
border-style: var(--input-border-style);
|
|
12
|
-
border-width: var(--input-border-width);
|
|
14
|
+
border: 0;
|
|
13
15
|
border-radius: var(--input-border-radius);
|
|
14
16
|
transition: all 0.2s ease-in-out;
|
|
15
17
|
font-family: var(--font-family);
|
|
@@ -20,27 +22,15 @@
|
|
|
20
22
|
resize: vertical;
|
|
21
23
|
|
|
22
24
|
&:disabled {
|
|
23
|
-
color: var(--greyed-out);
|
|
24
25
|
background-color: var(--disabled);
|
|
25
|
-
border-color: #fff;
|
|
26
26
|
cursor: not-allowed;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
outline: none;
|
|
31
|
-
border-width: var(--input-border-width-focus);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
&:focus:not(:disabled):not(.error) {
|
|
35
|
-
border-color: var(--color-primary);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
&:hover:not(:disabled):not(.error) {
|
|
39
|
-
border-color: var(--default);
|
|
40
|
-
border-width: var(--input-border-width);
|
|
41
|
-
}
|
|
29
|
+
@include browserOutlineDisabled;
|
|
42
30
|
}
|
|
43
31
|
|
|
32
|
+
@include outline;
|
|
33
|
+
|
|
44
34
|
.error {
|
|
45
35
|
border-color: var(--error);
|
|
46
36
|
color: var(--error);
|
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import React, { useEffect, useRef } from
|
|
2
|
-
import { Textarea, Props } from
|
|
3
|
-
import { render } from
|
|
4
|
-
import userEvent from
|
|
1
|
+
import React, { useEffect, useRef } from "react";
|
|
2
|
+
import { Textarea, Props } from "./Textarea";
|
|
3
|
+
import { render } from "@testing-library/react";
|
|
4
|
+
import userEvent from "@testing-library/user-event";
|
|
5
5
|
|
|
6
6
|
const createTextarea = (params?: Props) => {
|
|
7
7
|
const queries = render(<Textarea data-testid="textarea" {...params} />);
|
|
8
|
-
const textarea = queries.getByRole(
|
|
8
|
+
const textarea = queries.getByRole("textbox");
|
|
9
9
|
|
|
10
10
|
return {
|
|
11
11
|
...queries,
|
|
12
|
-
textarea
|
|
12
|
+
textarea
|
|
13
13
|
};
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
describe(
|
|
17
|
-
it(
|
|
16
|
+
describe("Textarea should render", () => {
|
|
17
|
+
it("renders without crashing", () => {
|
|
18
18
|
const { textarea } = createTextarea();
|
|
19
19
|
expect(textarea).toBeTruthy();
|
|
20
20
|
});
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
-
describe(
|
|
24
|
-
it(
|
|
23
|
+
describe("ref should work", () => {
|
|
24
|
+
it("should give back the proper data prop, this also checks if the component propagates ...rest properly", () => {
|
|
25
25
|
const ExampleComponent = ({
|
|
26
|
-
propagateRef
|
|
26
|
+
propagateRef
|
|
27
27
|
}: {
|
|
28
28
|
propagateRef?: (ref: React.RefObject<HTMLElement>) => void;
|
|
29
29
|
}) => {
|
|
@@ -39,37 +39,37 @@ describe('ref should work', () => {
|
|
|
39
39
|
};
|
|
40
40
|
|
|
41
41
|
const refCheck = (ref: React.RefObject<HTMLElement>) => {
|
|
42
|
-
expect(ref.current).toHaveAttribute(
|
|
42
|
+
expect(ref.current).toHaveAttribute("data-ref", "testing");
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
render(<ExampleComponent propagateRef={refCheck} />);
|
|
46
46
|
});
|
|
47
47
|
});
|
|
48
48
|
|
|
49
|
-
describe(
|
|
50
|
-
it(
|
|
49
|
+
describe("Textarea properties", () => {
|
|
50
|
+
it("is disabled", () => {
|
|
51
51
|
const { textarea } = createTextarea({ disabled: true });
|
|
52
52
|
|
|
53
|
-
expect(textarea).toHaveAttribute(
|
|
53
|
+
expect(textarea).toHaveAttribute("disabled");
|
|
54
54
|
});
|
|
55
55
|
|
|
56
|
-
it(
|
|
56
|
+
it("has 20 columns", () => {
|
|
57
57
|
const { textarea } = createTextarea({ cols: 20 });
|
|
58
58
|
|
|
59
|
-
expect(textarea).toHaveAttribute(
|
|
59
|
+
expect(textarea).toHaveAttribute("cols", "20");
|
|
60
60
|
});
|
|
61
61
|
|
|
62
|
-
it(
|
|
62
|
+
it("has autofocus", () => {
|
|
63
63
|
const { textarea } = createTextarea({ autoFocus: true });
|
|
64
64
|
|
|
65
65
|
setTimeout(() => {
|
|
66
|
-
expect(textarea).toHaveAttribute(
|
|
66
|
+
expect(textarea).toHaveAttribute("autofocus");
|
|
67
67
|
}, 0);
|
|
68
68
|
});
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
-
describe(
|
|
72
|
-
it(
|
|
71
|
+
describe("Textarea listeners", () => {
|
|
72
|
+
it("executes the functions", () => {
|
|
73
73
|
const onChangeHandler = jest.fn();
|
|
74
74
|
const onKeyUpHandler = jest.fn();
|
|
75
75
|
const onKeyDownHandler = jest.fn();
|
|
@@ -77,14 +77,14 @@ describe('Textarea listeners', () => {
|
|
|
77
77
|
const { textarea } = createTextarea({
|
|
78
78
|
onKeyUp: onKeyUpHandler,
|
|
79
79
|
onKeyDown: onKeyDownHandler,
|
|
80
|
-
onChange: onChangeHandler
|
|
80
|
+
onChange: onChangeHandler
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
textarea.focus();
|
|
84
84
|
|
|
85
85
|
expect(textarea).toHaveFocus();
|
|
86
86
|
|
|
87
|
-
userEvent.keyboard(
|
|
87
|
+
userEvent.keyboard("test");
|
|
88
88
|
|
|
89
89
|
expect(onKeyUpHandler).toHaveBeenCalled();
|
|
90
90
|
expect(onKeyDownHandler).toHaveBeenCalled();
|
|
@@ -92,11 +92,11 @@ describe('Textarea listeners', () => {
|
|
|
92
92
|
});
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
-
describe(
|
|
96
|
-
it(
|
|
95
|
+
describe("Error status", () => {
|
|
96
|
+
it("has error class, and an icon", () => {
|
|
97
97
|
const { textarea } = createTextarea({ error: true });
|
|
98
98
|
|
|
99
|
-
expect(textarea).toHaveClass(
|
|
100
|
-
expect(textarea.nextElementSibling).toHaveClass(
|
|
99
|
+
expect(textarea).toHaveClass("error");
|
|
100
|
+
expect(textarea.nextElementSibling).toHaveClass("icon-error-circle");
|
|
101
101
|
});
|
|
102
102
|
});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import React, { ComponentPropsWithRef } from
|
|
2
|
-
import { Icon, Props as IconProps, Icons } from
|
|
3
|
-
import classes from
|
|
4
|
-
import { FormElement } from
|
|
1
|
+
import React, { ComponentPropsWithRef, useState } from "react";
|
|
2
|
+
import { Icon, Props as IconProps, Icons } from "../../Icon/Icon";
|
|
3
|
+
import classes from "./Textarea.module.scss";
|
|
4
|
+
import { FormElement } from "../form.interfaces";
|
|
5
5
|
|
|
6
|
-
interface IconPropsPartial extends Omit<Partial<IconProps>,
|
|
6
|
+
interface IconPropsPartial extends Omit<Partial<IconProps>, "ref"> {}
|
|
7
7
|
|
|
8
|
-
export interface Props extends ComponentPropsWithRef<
|
|
9
|
-
wrapperProps?: ComponentPropsWithRef<
|
|
8
|
+
export interface Props extends ComponentPropsWithRef<"textarea">, FormElement {
|
|
9
|
+
wrapperProps?: ComponentPropsWithRef<"div">;
|
|
10
10
|
errorProps?: IconPropsPartial;
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -19,29 +19,49 @@ export const Textarea = React.forwardRef<HTMLTextAreaElement, Props>(
|
|
|
19
19
|
rows = 4,
|
|
20
20
|
wrapperProps,
|
|
21
21
|
errorProps,
|
|
22
|
+
onFocus,
|
|
23
|
+
onBlur,
|
|
22
24
|
...rest
|
|
23
25
|
}: Props,
|
|
24
26
|
ref
|
|
25
27
|
) => {
|
|
28
|
+
const [focus, setFocus] = useState(false);
|
|
29
|
+
|
|
30
|
+
const wrapperClasses = [classes["textarea-wrapper"]];
|
|
31
|
+
const outlineClasses = [classes["outline"]];
|
|
32
|
+
|
|
33
|
+
wrapperProps?.className && wrapperClasses.push(wrapperProps.className);
|
|
34
|
+
disabled &&
|
|
35
|
+
wrapperClasses.push(classes["disabled"]) &&
|
|
36
|
+
outlineClasses.push(classes["disabled"]);
|
|
37
|
+
error && wrapperClasses.push(classes["error"]) && outlineClasses.push(classes["error"]);
|
|
38
|
+
focus && wrapperClasses.push(classes["focus"]) && outlineClasses.push(classes["focus"]);
|
|
39
|
+
|
|
26
40
|
return (
|
|
27
|
-
<div
|
|
28
|
-
{...wrapperProps}
|
|
29
|
-
className={`${classes['textarea-wrapper']} ${wrapperProps?.className ?? ''}`}
|
|
30
|
-
>
|
|
41
|
+
<div {...wrapperProps} className={wrapperClasses.join(" ")}>
|
|
31
42
|
<textarea
|
|
32
43
|
{...rest}
|
|
33
44
|
ref={ref}
|
|
34
45
|
rows={rows}
|
|
35
|
-
className={`${error ? classes[
|
|
46
|
+
className={`${error ? classes["error"] : ""} ${classes["textarea"]} ${className ?? ""}`}
|
|
36
47
|
disabled={disabled}
|
|
48
|
+
onFocus={event => {
|
|
49
|
+
setFocus(true);
|
|
50
|
+
onFocus && onFocus(event);
|
|
51
|
+
}}
|
|
52
|
+
onBlur={event => {
|
|
53
|
+
setFocus(false);
|
|
54
|
+
onBlur && onBlur(event);
|
|
55
|
+
}}
|
|
37
56
|
/>
|
|
38
57
|
{error && (
|
|
39
58
|
<Icon
|
|
40
59
|
{...errorProps}
|
|
41
|
-
className={`${classes[
|
|
60
|
+
className={`${classes["warning"]} ${errorProps?.className ?? ""}`}
|
|
42
61
|
icon={Icons.Error}
|
|
43
62
|
/>
|
|
44
63
|
)}
|
|
64
|
+
<span className={outlineClasses.join(" ")}></span>
|
|
45
65
|
</div>
|
|
46
66
|
);
|
|
47
67
|
}
|