@onewelcome/react-lib-components 5.2.0 → 6.1.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.
- package/dist/cjs/Button/BaseButton.cjs.js.map +1 -1
- package/dist/cjs/Button/BaseButton.module.cjs.js +1 -1
- package/dist/cjs/Button/Button.module.cjs.js +1 -1
- package/dist/cjs/Button/IconButton.module.cjs.js +1 -1
- package/dist/cjs/ContextMenu/ContextMenu.cjs.js +1 -1
- package/dist/cjs/ContextMenu/ContextMenu.cjs.js.map +1 -1
- package/dist/cjs/ContextMenu/ContextMenuItem.module.cjs.js +1 -1
- package/dist/cjs/ContextMenu/ContextMenuService.cjs.js +1 -1
- package/dist/cjs/ContextMenu/ContextMenuService.cjs.js.map +1 -1
- package/dist/cjs/DataGrid/DataGridActions/DataGridColumnsToggle.module.cjs.js +1 -1
- package/dist/cjs/Form/Input/Input.module.cjs.js +1 -1
- package/dist/cjs/Form/Select/Option.cjs.js +1 -1
- package/dist/cjs/Form/Select/Option.cjs.js.map +1 -1
- package/dist/cjs/Form/Select/Select.cjs.js +1 -1
- package/dist/cjs/Form/Select/Select.cjs.js.map +1 -1
- package/dist/cjs/Form/Select/Select.module.cjs.js +1 -1
- package/dist/cjs/Form/Select/SelectService.cjs.js +1 -1
- package/dist/cjs/Form/Select/SelectService.cjs.js.map +1 -1
- package/dist/cjs/Form/Textarea/Textarea.module.cjs.js +1 -1
- package/dist/cjs/Icon/Icon.cjs.js +1 -1
- package/dist/cjs/Icon/Icon.cjs.js.map +1 -1
- package/dist/cjs/Icon/Icon.module.cjs.js +1 -1
- package/dist/cjs/Link/Link.cjs.js.map +1 -1
- package/dist/cjs/Link/Link.module.cjs.js +1 -1
- package/dist/cjs/Notifications/BaseModal/BaseModal.module.cjs.js +1 -1
- package/dist/cjs/Notifications/SlideInModal/SlideInModal.module.cjs.js +1 -1
- package/dist/cjs/Notifications/Snackbar/SnackbarItem/SnackbarItem.cjs.js +1 -1
- package/dist/cjs/Notifications/Snackbar/SnackbarItem/SnackbarItem.cjs.js.map +1 -1
- package/dist/cjs/Notifications/Snackbar/SnackbarItem/SnackbarItem.module.cjs.js +1 -1
- package/dist/cjs/Notifications/Snackbar/SnackbarProvider/SnackbarProvider.cjs.js +1 -1
- package/dist/cjs/Notifications/Snackbar/SnackbarProvider/SnackbarProvider.cjs.js.map +1 -1
- package/dist/cjs/Notifications/Snackbar/SnackbarProvider/SnackbarStateProvider.cjs.js.map +1 -1
- package/dist/cjs/Notifications/Snackbar/interfaces.cjs.js +2 -0
- package/dist/cjs/Notifications/Snackbar/interfaces.cjs.js.map +1 -0
- package/dist/cjs/Popover/Popover.cjs.js +1 -1
- package/dist/cjs/Popover/Popover.cjs.js.map +1 -1
- package/dist/cjs/Popover/Popover.module.cjs.js +1 -1
- package/dist/cjs/Stepper/Step.cjs.js +1 -1
- package/dist/cjs/Stepper/Step.cjs.js.map +1 -1
- package/dist/cjs/Stepper/Step.module.cjs.js +1 -1
- package/dist/cjs/Stepper/Stepper.cjs.js +1 -1
- package/dist/cjs/Stepper/Stepper.cjs.js.map +1 -1
- package/dist/cjs/Tabs/TabButton.module.cjs.js +1 -1
- package/dist/cjs/TextEllipsis/TextEllipsis.module.cjs.js +1 -1
- package/dist/cjs/Tiles/Tile.module.cjs.js +1 -1
- package/dist/cjs/Tooltip/Tooltip.module.cjs.js +1 -1
- package/dist/cjs/Wizard/BaseWizardSteps/BaseWizardSteps.module.cjs.js +1 -1
- package/dist/cjs/_BaseStyling_/BaseStyling.cjs.js +1 -1
- package/dist/cjs/_BaseStyling_/BaseStyling.cjs.js.map +1 -1
- package/dist/cjs/src/.scope.d.ts +2 -0
- package/dist/cjs/src/components/Button/BaseButton.d.ts +1 -1
- package/dist/cjs/src/components/ContextMenu/ContextMenu.d.ts +1 -1
- package/dist/cjs/src/components/ContextMenu/ContextMenuService.d.ts +4 -1
- package/dist/cjs/src/components/Form/Select/Option.d.ts +1 -0
- package/dist/cjs/src/components/Form/Select/Select.d.ts +20 -0
- package/dist/cjs/src/components/Form/Select/Select.interfaces.d.ts +3 -1
- package/dist/cjs/src/components/Form/Select/Select.test.d.ts +63 -1
- package/dist/cjs/src/components/Form/Select/SelectKeyboardNavigation.test.d.ts +1 -0
- package/dist/cjs/src/components/Form/Select/SelectService.d.ts +3 -2
- package/dist/cjs/src/components/Icon/Icon.d.ts +4 -1
- package/dist/cjs/src/components/Link/Link.d.ts +1 -1
- package/dist/cjs/src/components/Notifications/Snackbar/SnackbarProvider/SnackbarStateProvider.d.ts +5 -5
- package/dist/cjs/src/components/Notifications/Snackbar/interfaces.d.ts +6 -0
- package/dist/cjs/src/components/Notifications/Snackbar/useSnackbar.d.ts +4 -4
- package/dist/cjs/src/components/Notifications/Snackbar/useSnackbar.test.d.ts +1 -0
- package/dist/cjs/src/components/Stepper/Stepper.d.ts +0 -1
- package/dist/cjs/src/components/_BaseStyling_/BaseStyling.d.ts +11 -10
- package/dist/cjs/src/hooks/usePosition.cjs.js.map +1 -1
- package/dist/cjs/src/hooks/usePosition.d.ts +1 -1
- package/dist/esm/Button/BaseButton.esm.js.map +1 -1
- package/dist/esm/Button/BaseButton.module.esm.js +1 -1
- package/dist/esm/Button/Button.module.esm.js +1 -1
- package/dist/esm/Button/IconButton.module.esm.js +1 -1
- package/dist/esm/ContextMenu/ContextMenu.esm.js +1 -1
- package/dist/esm/ContextMenu/ContextMenu.esm.js.map +1 -1
- package/dist/esm/ContextMenu/ContextMenuItem.module.esm.js +1 -1
- package/dist/esm/ContextMenu/ContextMenuService.esm.js +1 -1
- package/dist/esm/ContextMenu/ContextMenuService.esm.js.map +1 -1
- package/dist/esm/DataGrid/DataGridActions/DataGridColumnsToggle.module.esm.js +1 -1
- package/dist/esm/Form/Input/Input.module.esm.js +1 -1
- package/dist/esm/Form/Select/Option.esm.js +1 -1
- package/dist/esm/Form/Select/Option.esm.js.map +1 -1
- package/dist/esm/Form/Select/Select.esm.js +1 -1
- package/dist/esm/Form/Select/Select.esm.js.map +1 -1
- package/dist/esm/Form/Select/Select.module.esm.js +1 -1
- package/dist/esm/Form/Select/SelectService.esm.js +1 -1
- package/dist/esm/Form/Select/SelectService.esm.js.map +1 -1
- package/dist/esm/Form/Textarea/Textarea.module.esm.js +1 -1
- package/dist/esm/Icon/Icon.esm.js +1 -1
- package/dist/esm/Icon/Icon.esm.js.map +1 -1
- package/dist/esm/Icon/Icon.module.esm.js +1 -1
- package/dist/esm/Link/Link.esm.js.map +1 -1
- package/dist/esm/Link/Link.module.esm.js +1 -1
- package/dist/esm/Notifications/BaseModal/BaseModal.module.esm.js +1 -1
- package/dist/esm/Notifications/SlideInModal/SlideInModal.module.esm.js +1 -1
- package/dist/esm/Notifications/Snackbar/SnackbarItem/SnackbarItem.esm.js +1 -1
- package/dist/esm/Notifications/Snackbar/SnackbarItem/SnackbarItem.esm.js.map +1 -1
- package/dist/esm/Notifications/Snackbar/SnackbarItem/SnackbarItem.module.esm.js +1 -1
- package/dist/esm/Notifications/Snackbar/SnackbarProvider/SnackbarProvider.esm.js +1 -1
- package/dist/esm/Notifications/Snackbar/SnackbarProvider/SnackbarProvider.esm.js.map +1 -1
- package/dist/esm/Notifications/Snackbar/SnackbarProvider/SnackbarStateProvider.esm.js.map +1 -1
- package/dist/esm/Notifications/Snackbar/interfaces.esm.js +2 -0
- package/dist/esm/Notifications/Snackbar/interfaces.esm.js.map +1 -0
- package/dist/esm/Popover/Popover.esm.js +1 -1
- package/dist/esm/Popover/Popover.esm.js.map +1 -1
- package/dist/esm/Popover/Popover.module.esm.js +1 -1
- package/dist/esm/Stepper/Step.esm.js +1 -1
- package/dist/esm/Stepper/Step.esm.js.map +1 -1
- package/dist/esm/Stepper/Step.module.esm.js +1 -1
- package/dist/esm/Stepper/Stepper.esm.js +1 -1
- package/dist/esm/Stepper/Stepper.esm.js.map +1 -1
- package/dist/esm/Tabs/TabButton.module.esm.js +1 -1
- package/dist/esm/TextEllipsis/TextEllipsis.module.esm.js +1 -1
- package/dist/esm/Tiles/Tile.module.esm.js +1 -1
- package/dist/esm/Tooltip/Tooltip.module.esm.js +1 -1
- package/dist/esm/Wizard/BaseWizardSteps/BaseWizardSteps.module.esm.js +1 -1
- package/dist/esm/_BaseStyling_/BaseStyling.esm.js +1 -1
- package/dist/esm/_BaseStyling_/BaseStyling.esm.js.map +1 -1
- package/dist/esm/src/.scope.d.ts +2 -0
- package/dist/esm/src/components/Button/BaseButton.d.ts +1 -1
- package/dist/esm/src/components/ContextMenu/ContextMenu.d.ts +1 -1
- package/dist/esm/src/components/ContextMenu/ContextMenuService.d.ts +4 -1
- package/dist/esm/src/components/Form/Select/Option.d.ts +1 -0
- package/dist/esm/src/components/Form/Select/Select.d.ts +20 -0
- package/dist/esm/src/components/Form/Select/Select.interfaces.d.ts +3 -1
- package/dist/esm/src/components/Form/Select/Select.test.d.ts +63 -1
- package/dist/esm/src/components/Form/Select/SelectKeyboardNavigation.test.d.ts +1 -0
- package/dist/esm/src/components/Form/Select/SelectService.d.ts +3 -2
- package/dist/esm/src/components/Icon/Icon.d.ts +4 -1
- package/dist/esm/src/components/Link/Link.d.ts +1 -1
- package/dist/esm/src/components/Notifications/Snackbar/SnackbarProvider/SnackbarStateProvider.d.ts +5 -5
- package/dist/esm/src/components/Notifications/Snackbar/interfaces.d.ts +6 -0
- package/dist/esm/src/components/Notifications/Snackbar/useSnackbar.d.ts +4 -4
- package/dist/esm/src/components/Notifications/Snackbar/useSnackbar.test.d.ts +1 -0
- package/dist/esm/src/components/Stepper/Stepper.d.ts +0 -1
- package/dist/esm/src/components/_BaseStyling_/BaseStyling.d.ts +11 -10
- package/dist/esm/src/hooks/usePosition.d.ts +1 -1
- package/dist/esm/src/hooks/usePosition.esm.js.map +1 -1
- package/package.json +48 -45
- package/src/{hooks/useWrapper.test.ts → .scope.ts} +1 -12
- package/src/components/Button/BaseButton.tsx +1 -1
- package/src/components/Button/Button.module.scss +2 -10
- package/src/components/ContextMenu/ContextMenu.tsx +13 -23
- package/src/components/ContextMenu/ContextMenuService.ts +47 -1
- package/src/components/Form/Select/Option.tsx +3 -1
- package/src/components/Form/Select/Select.interfaces.ts +3 -1
- package/src/components/Form/Select/Select.module.scss +55 -34
- package/src/components/Form/Select/Select.tsx +74 -23
- package/src/components/Form/Select/SelectService.ts +26 -10
- package/src/components/Icon/Icon.module.scss +12 -0
- package/src/components/Icon/Icon.tsx +4 -1
- package/src/components/Link/Link.module.scss +28 -4
- package/src/components/Link/Link.tsx +1 -1
- package/src/components/Notifications/Snackbar/SnackbarItem/SnackbarItem.module.scss +14 -21
- package/src/components/Notifications/Snackbar/SnackbarItem/SnackbarItem.tsx +17 -13
- package/src/components/Notifications/Snackbar/SnackbarProvider/SnackbarProvider.tsx +43 -17
- package/src/components/Notifications/Snackbar/SnackbarProvider/SnackbarStateProvider.tsx +5 -13
- package/src/components/Notifications/Snackbar/interfaces.ts +15 -0
- package/src/components/Popover/Popover.tsx +19 -2
- package/src/components/Stepper/Step.tsx +2 -1
- package/src/components/Stepper/Stepper.tsx +0 -2
- package/src/components/Tooltip/Tooltip.module.scss +1 -0
- package/src/components/_BaseStyling_/BaseStyling.tsx +24 -22
- package/src/font/icomoon.eot +0 -0
- package/src/font/icomoon.svg +5 -2
- package/src/font/icomoon.ttf +0 -0
- package/src/font/icomoon.woff +0 -0
- package/src/font/selection.json +1 -1
- package/src/hooks/usePosition.ts +1 -1
- package/src/interfaces.ts +2 -2
- package/src/mixins.module.scss +60 -61
- package/src/components/Breadcrumbs/Breadcrumbs.test.tsx +0 -64
- package/src/components/Button/BaseButton.test.tsx +0 -133
- package/src/components/Button/Button.test.tsx +0 -138
- package/src/components/Button/IconButton.test.tsx +0 -122
- package/src/components/ContextMenu/ContextMenu.test.tsx +0 -358
- package/src/components/DataGrid/DataGrid.test.tsx +0 -437
- package/src/components/DataGrid/DataGridActions/DataGridActions.test.tsx +0 -204
- package/src/components/DataGrid/DataGridActions/DataGridColumnsToggle.test.tsx +0 -99
- package/src/components/DataGrid/DataGridBody/DataGridBody.test.tsx +0 -140
- package/src/components/DataGrid/DataGridBody/DataGridCell.test.tsx +0 -90
- package/src/components/DataGrid/DataGridBody/DataGridRow.test.tsx +0 -117
- package/src/components/DataGrid/DataGridHeader/DataGridHeader.test.tsx +0 -276
- package/src/components/DataGrid/DataGridHeader/DataGridHeaderCell.test.tsx +0 -144
- package/src/components/Form/Checkbox/Checkbox.test.tsx +0 -308
- package/src/components/Form/Fieldset/Fieldset.test.tsx +0 -127
- package/src/components/Form/FileUpload/FileItem/FileItem.test.tsx +0 -103
- package/src/components/Form/FileUpload/FileUpload.test.tsx +0 -374
- package/src/components/Form/Form.test.tsx +0 -63
- package/src/components/Form/FormControl/FormControl.test.tsx +0 -98
- package/src/components/Form/FormGroup/FormGroup.test.tsx +0 -127
- package/src/components/Form/FormHelperText/FormHelperText.test.tsx +0 -84
- package/src/components/Form/FormSelectorWrapper/FormSelectorWrapper.test.tsx +0 -94
- package/src/components/Form/Input/Input.test.tsx +0 -267
- package/src/components/Form/Label/Label.test.tsx +0 -68
- package/src/components/Form/Radio/Radio.test.tsx +0 -130
- package/src/components/Form/Select/Option.test.tsx +0 -57
- package/src/components/Form/Select/Select.test.tsx +0 -564
- package/src/components/Form/Textarea/Textarea.test.tsx +0 -124
- package/src/components/Form/Toggle/Toggle.test.tsx +0 -200
- package/src/components/Form/Wrapper/CheckboxWrapper/CheckboxWrapper.test.tsx +0 -141
- package/src/components/Form/Wrapper/InputWrapper/InputWrapper.test.tsx +0 -211
- package/src/components/Form/Wrapper/RadioWrapper/RadioWrapper.test.tsx +0 -117
- package/src/components/Form/Wrapper/SelectWrapper/SelectWrapper.test.tsx +0 -186
- package/src/components/Form/Wrapper/TextareaWrapper/TextareaWrapper.test.tsx +0 -173
- package/src/components/Form/Wrapper/Wrapper/Wrapper.test.tsx +0 -59
- package/src/components/Icon/Icon.test.tsx +0 -83
- package/src/components/Link/Link.test.tsx +0 -197
- package/src/components/Notifications/Banner/Banner.test.tsx +0 -84
- package/src/components/Notifications/BaseModal/BaseModal.test.tsx +0 -194
- package/src/components/Notifications/BaseModal/BaseModalActions/BaseModalActions.test.tsx +0 -74
- package/src/components/Notifications/BaseModal/BaseModalContent/BaseModalContent.test.tsx +0 -71
- package/src/components/Notifications/BaseModal/BaseModalHeader/BaseModalHeader.test.tsx +0 -74
- package/src/components/Notifications/Dialog/Dialog.test.tsx +0 -118
- package/src/components/Notifications/Dialog/DialogActions/DialogActions.test.tsx +0 -61
- package/src/components/Notifications/Dialog/DialogTitle/DialogTitle.test.tsx +0 -87
- package/src/components/Notifications/DiscardChangesModal/DiscardChangesDialog/DiscardChangesDialog.test.tsx +0 -111
- package/src/components/Notifications/DiscardChangesModal/DiscardChangesModal.test.tsx +0 -175
- package/src/components/Notifications/Modal/Modal.test.tsx +0 -18
- package/src/components/Notifications/NotificationProvider/NotificationContext.test.tsx +0 -449
- package/src/components/Notifications/SlideInModal/SlideInModal.test.tsx +0 -90
- package/src/components/Notifications/Snackbar/SnackbarContainer/SnackbarContainer.test.tsx +0 -53
- package/src/components/Notifications/Snackbar/SnackbarItem/SnackbarItem.test.tsx +0 -63
- package/src/components/Notifications/Snackbar/SnackbarProvider/SnackbarProvider.test.tsx +0 -215
- package/src/components/Pagination/Pagination.test.tsx +0 -183
- package/src/components/Popover/Popover.test.tsx +0 -103
- package/src/components/ProgressBar/ProgressBar.test.tsx +0 -91
- package/src/components/Skeleton/Skeleton.test.tsx +0 -112
- package/src/components/StatusIndicator/StatusIndicator.test.tsx +0 -143
- package/src/components/Stepper/Stepper.test.tsx +0 -83
- package/src/components/Tabs/Tab.test.tsx +0 -49
- package/src/components/Tabs/TabButton.test.tsx +0 -65
- package/src/components/Tabs/Tabs.test.tsx +0 -291
- package/src/components/Tag/Tag.test.tsx +0 -89
- package/src/components/TextEllipsis/TextEllipsis.test.tsx +0 -96
- package/src/components/Tiles/Tile.test.tsx +0 -183
- package/src/components/Tiles/Tiles.test.tsx +0 -162
- package/src/components/Tooltip/Tooltip.test.tsx +0 -390
- package/src/components/Typography/Typography.test.tsx +0 -177
- package/src/components/Wizard/BaseWizardSteps/BaseWizardSteps.test.tsx +0 -90
- package/src/components/Wizard/Wizard.test.tsx +0 -218
- package/src/components/Wizard/WizardActions/WizardActions.test.tsx +0 -187
- package/src/components/Wizard/WizardSteps/WizardSteps.test.tsx +0 -125
- package/src/components/_BaseStyling_/BaseStyling.test.tsx +0 -55
- package/src/hooks/useAnimation.test.tsx +0 -65
- package/src/hooks/useBodyClick.test.tsx +0 -55
- package/src/hooks/useDebouncedCallback.test.ts +0 -150
- package/src/hooks/useDetermineStatusIcon.test.ts +0 -28
- package/src/hooks/useFormSelector.test.ts +0 -56
- package/src/hooks/usePosition.test.tsx +0 -510
- package/src/hooks/useRepeater.test.tsx +0 -156
- package/src/hooks/useScroll.test.tsx +0 -36
- package/src/hooks/useSpacing.test.ts +0 -86
- package/src/hooks/useUploadFile.test.ts +0 -211
- package/src/util/helper.test.tsx +0 -403
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
* limitations under the License.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import { SetStateAction, useEffect } from "react";
|
|
18
|
+
import { horizontal, Offset, Placement, vertical } from "../../hooks/usePosition";
|
|
18
19
|
import { remToPx } from "../../util/helper";
|
|
19
20
|
|
|
20
21
|
interface UseArrowNavigation {
|
|
@@ -28,6 +29,7 @@ interface UseArrowNavigation {
|
|
|
28
29
|
setShouldClick: React.Dispatch<React.SetStateAction<boolean>>;
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
/** @scope . */
|
|
31
33
|
export const useArrowNavigation = ({
|
|
32
34
|
selectedContextMenuItem,
|
|
33
35
|
setSelectedContextMenuItem,
|
|
@@ -123,3 +125,47 @@ export const useDefaultOffset = () => {
|
|
|
123
125
|
|
|
124
126
|
return { calculateDefaultOffset };
|
|
125
127
|
};
|
|
128
|
+
|
|
129
|
+
export const useFocusAnchorElement = (
|
|
130
|
+
anchorEl: React.RefObject<HTMLElement>,
|
|
131
|
+
id: string,
|
|
132
|
+
showContextMenu: boolean,
|
|
133
|
+
setShowContextMenu: React.Dispatch<SetStateAction<boolean>>,
|
|
134
|
+
setFocusedContextMenuItem: React.Dispatch<SetStateAction<number>>,
|
|
135
|
+
onShow?: () => void,
|
|
136
|
+
onClose?: () => void
|
|
137
|
+
) => {
|
|
138
|
+
const handleEscapeKeyPress = (e: KeyboardEvent) => {
|
|
139
|
+
if (e.key === "Escape") {
|
|
140
|
+
setShowContextMenu(false);
|
|
141
|
+
anchorEl.current?.focus();
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const escapeKeyEventHandlerManager = () => {
|
|
146
|
+
if (showContextMenu) {
|
|
147
|
+
document.addEventListener("keydown", handleEscapeKeyPress);
|
|
148
|
+
} else {
|
|
149
|
+
document.removeEventListener("keydown", handleEscapeKeyPress);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
const emitContextMenuEvent = () => {
|
|
154
|
+
if (showContextMenu) {
|
|
155
|
+
onShow?.();
|
|
156
|
+
} else {
|
|
157
|
+
onClose?.();
|
|
158
|
+
|
|
159
|
+
if (document.activeElement?.closest(`#${id}-menu`)) {
|
|
160
|
+
anchorEl.current?.focus();
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
setFocusedContextMenuItem(-1);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
useEffect(() => {
|
|
168
|
+
escapeKeyEventHandlerManager();
|
|
169
|
+
emitContextMenuEvent();
|
|
170
|
+
}, [showContextMenu]);
|
|
171
|
+
};
|
|
@@ -37,6 +37,7 @@ export interface Props extends ComponentPropsWithRef<"li"> {
|
|
|
37
37
|
childIndex?: number;
|
|
38
38
|
onOptionSelect?: (ref: React.RefObject<HTMLLIElement>) => void;
|
|
39
39
|
onFocusChange?: (childIndex: number) => void;
|
|
40
|
+
isAddBtnFocused?: boolean;
|
|
40
41
|
}
|
|
41
42
|
|
|
42
43
|
const OptionComponent: ForwardRefRenderFunction<HTMLLIElement, Props> = (
|
|
@@ -53,6 +54,7 @@ const OptionComponent: ForwardRefRenderFunction<HTMLLIElement, Props> = (
|
|
|
53
54
|
onFocusChange,
|
|
54
55
|
disabled,
|
|
55
56
|
value,
|
|
57
|
+
isAddBtnFocused,
|
|
56
58
|
...rest
|
|
57
59
|
}: Props,
|
|
58
60
|
ref
|
|
@@ -66,7 +68,7 @@ const OptionComponent: ForwardRefRenderFunction<HTMLLIElement, Props> = (
|
|
|
66
68
|
}, [isSelected, shouldClick]);
|
|
67
69
|
|
|
68
70
|
useEffect(() => {
|
|
69
|
-
if (innerOptionRef.current && hasFocus && selectOpened && !isSearching) {
|
|
71
|
+
if (innerOptionRef.current && hasFocus && selectOpened && !isSearching && !isAddBtnFocused) {
|
|
70
72
|
onFocusChange && childIndex && onFocusChange(childIndex);
|
|
71
73
|
innerOptionRef.current.focus();
|
|
72
74
|
}
|
|
@@ -29,11 +29,13 @@ export interface UseArrowNavigationParams {
|
|
|
29
29
|
setShouldClick: React.Dispatch<React.SetStateAction<boolean>>;
|
|
30
30
|
onOptionChangeHandler: (optionElement: HTMLElement | null) => void;
|
|
31
31
|
searchInputRef: React.RefObject<HTMLInputElement>;
|
|
32
|
-
|
|
32
|
+
addBtnRef?: React.RefObject<HTMLButtonElement>;
|
|
33
|
+
renderThreshold: number;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
export interface UseSelectPositionListParams {
|
|
36
37
|
expanded: boolean;
|
|
37
38
|
optionListReference: React.RefObject<HTMLDivElement>;
|
|
38
39
|
containerReference: React.RefObject<HTMLDivElement>;
|
|
40
|
+
addBtnRef: React.RefObject<HTMLButtonElement>;
|
|
39
41
|
}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
@use "src/mixins.module";
|
|
18
18
|
@use "src/variables";
|
|
19
19
|
|
|
20
|
-
$listItemHeight: 2.
|
|
20
|
+
$listItemHeight: 2.5rem;
|
|
21
21
|
|
|
22
22
|
.select {
|
|
23
23
|
position: relative;
|
|
@@ -92,9 +92,7 @@ $listItemHeight: 2.125rem;
|
|
|
92
92
|
border-style: var(--input-border-style);
|
|
93
93
|
border-width: var(--input-border-width);
|
|
94
94
|
border-radius: var(--input-border-radius);
|
|
95
|
-
box-shadow:
|
|
96
|
-
box-shadow: 0px 3px 14px 0px #0105321f;
|
|
97
|
-
box-shadow: 0px 8px 10px 0px #01053224;
|
|
95
|
+
box-shadow: 0 8px 10px 0 #01053224;
|
|
98
96
|
position: absolute;
|
|
99
97
|
z-index: variables.$select-z-index;
|
|
100
98
|
top: 44px;
|
|
@@ -113,39 +111,28 @@ $listItemHeight: 2.125rem;
|
|
|
113
111
|
border-radius: var(--input-border-radius);
|
|
114
112
|
color: var(--default);
|
|
115
113
|
text-align: left;
|
|
116
|
-
max-height: calc($listItemHeight * 10);
|
|
117
114
|
|
|
118
115
|
li {
|
|
119
|
-
padding: 0.
|
|
116
|
+
padding: 0.62rem 0.75rem;
|
|
120
117
|
font-size: var(--form-control-font-size);
|
|
121
118
|
margin: 0;
|
|
122
119
|
position: relative;
|
|
123
|
-
line-height:
|
|
120
|
+
line-height: 1.25rem;
|
|
121
|
+
box-sizing: border-box;
|
|
122
|
+
min-height: $listItemHeight;
|
|
124
123
|
cursor: pointer;
|
|
125
124
|
|
|
126
|
-
&:after {
|
|
127
|
-
content: "";
|
|
128
|
-
position: absolute;
|
|
129
|
-
top: 0;
|
|
130
|
-
left: 0;
|
|
131
|
-
background-color: transparent;
|
|
132
|
-
width: 100%;
|
|
133
|
-
height: 100%;
|
|
134
|
-
opacity: 0.05;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
125
|
&:focus {
|
|
138
126
|
outline: var(--input-border-width-focus) solid var(--color-primary300);
|
|
139
|
-
outline-offset:
|
|
127
|
+
outline-offset: var(--input-border-width-focus);
|
|
140
128
|
}
|
|
141
129
|
|
|
142
|
-
&:hover
|
|
143
|
-
|
|
144
|
-
background-color: var(--color-primary);
|
|
130
|
+
&:hover {
|
|
131
|
+
background-color: var(--color-blue-grey50);
|
|
145
132
|
}
|
|
146
133
|
|
|
147
|
-
&:active
|
|
148
|
-
|
|
134
|
+
&:active {
|
|
135
|
+
background-color: var(--color-blue-grey100);
|
|
149
136
|
}
|
|
150
137
|
|
|
151
138
|
&.disabled {
|
|
@@ -157,17 +144,19 @@ $listItemHeight: 2.125rem;
|
|
|
157
144
|
}
|
|
158
145
|
}
|
|
159
146
|
|
|
147
|
+
ul.has-sibling {
|
|
148
|
+
padding-bottom: 2px;
|
|
149
|
+
}
|
|
150
|
+
|
|
160
151
|
.selected-option {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
border-left: 0.25rem solid var(--color-primary);
|
|
170
|
-
}
|
|
152
|
+
content: "";
|
|
153
|
+
position: absolute;
|
|
154
|
+
top: 0;
|
|
155
|
+
left: 0;
|
|
156
|
+
height: 100%;
|
|
157
|
+
border-top-right-radius: 0.125rem;
|
|
158
|
+
border-bottom-right-radius: 0.125rem;
|
|
159
|
+
border-left: 0.25rem solid var(--color-primary);
|
|
171
160
|
color: var(--color-primary);
|
|
172
161
|
}
|
|
173
162
|
|
|
@@ -178,6 +167,38 @@ $listItemHeight: 2.125rem;
|
|
|
178
167
|
pointer-events: none;
|
|
179
168
|
}
|
|
180
169
|
|
|
170
|
+
.action-button {
|
|
171
|
+
border: none;
|
|
172
|
+
border-top: 1px solid var(--color-blue-grey50);
|
|
173
|
+
width: 100%;
|
|
174
|
+
height: 2.5rem;
|
|
175
|
+
padding: 0.625rem 0.75rem;
|
|
176
|
+
margin: 0 0 0.25rem;
|
|
177
|
+
background-color: var(--light);
|
|
178
|
+
border-radius: var(--input-border-radius);
|
|
179
|
+
color: var(--default);
|
|
180
|
+
text-align: left;
|
|
181
|
+
box-sizing: border-box;
|
|
182
|
+
cursor: pointer;
|
|
183
|
+
|
|
184
|
+
font-family: var(--font-family);
|
|
185
|
+
font-size: var(--form-control-font-size);
|
|
186
|
+
|
|
187
|
+
&:focus {
|
|
188
|
+
outline: 1px solid;
|
|
189
|
+
outline-offset: 0;
|
|
190
|
+
border-radius: 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
&:hover {
|
|
194
|
+
background-color: var(--color-blue-grey50);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
&:active {
|
|
198
|
+
background-color: var(--color-blue-grey100);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
181
202
|
.status {
|
|
182
203
|
position: absolute;
|
|
183
204
|
top: 50%;
|
|
@@ -37,25 +37,41 @@ import { useDetermineStatusIcon } from "../../../hooks/useDetermineStatusIcon";
|
|
|
37
37
|
|
|
38
38
|
type PartialInputProps = Partial<InputProps>;
|
|
39
39
|
|
|
40
|
+
interface SearchProps {
|
|
41
|
+
enabled?: boolean;
|
|
42
|
+
renderThreshold?: number;
|
|
43
|
+
searchPlaceholder?: string;
|
|
44
|
+
searchInputProps?: PartialInputProps & { reset?: boolean };
|
|
45
|
+
}
|
|
46
|
+
|
|
40
47
|
export interface Props extends ComponentPropsWithRef<"select">, FormElement {
|
|
41
48
|
children: ReactElement[];
|
|
42
49
|
name?: string;
|
|
43
50
|
labeledBy?: string;
|
|
44
51
|
describedBy?: string;
|
|
45
52
|
placeholder?: string;
|
|
53
|
+
/**
|
|
54
|
+
* @deprecated
|
|
55
|
+
*/
|
|
46
56
|
searchPlaceholder?: string;
|
|
57
|
+
/**
|
|
58
|
+
* @deprecated
|
|
59
|
+
*/
|
|
47
60
|
searchInputProps?: PartialInputProps & { reset?: boolean };
|
|
48
61
|
selectButtonProps?: ComponentPropsWithRef<"button">;
|
|
62
|
+
search?: SearchProps;
|
|
49
63
|
className?: string;
|
|
50
64
|
value: string;
|
|
51
65
|
clearLabel?: string;
|
|
52
66
|
noResultsLabel?: string;
|
|
53
67
|
onChange?: (event: React.ChangeEvent<HTMLSelectElement>, child?: ReactElement) => void;
|
|
68
|
+
addNew?: {
|
|
69
|
+
label: string;
|
|
70
|
+
onAddNew: (value: string) => void;
|
|
71
|
+
btnProps?: React.ButtonHTMLAttributes<HTMLButtonElement>;
|
|
72
|
+
};
|
|
54
73
|
}
|
|
55
74
|
|
|
56
|
-
/** Amount of items to be rendered before a search input is rendered */
|
|
57
|
-
const renderSearchCondition = 10;
|
|
58
|
-
|
|
59
75
|
const SelectComponent: ForwardRefRenderFunction<HTMLSelectElement, Props> = (
|
|
60
76
|
{
|
|
61
77
|
children,
|
|
@@ -74,6 +90,8 @@ const SelectComponent: ForwardRefRenderFunction<HTMLSelectElement, Props> = (
|
|
|
74
90
|
clearLabel = "Clear selection",
|
|
75
91
|
noResultsLabel = "No results found",
|
|
76
92
|
onChange,
|
|
93
|
+
addNew,
|
|
94
|
+
search,
|
|
77
95
|
...rest
|
|
78
96
|
}: Props,
|
|
79
97
|
ref
|
|
@@ -85,14 +103,32 @@ const SelectComponent: ForwardRefRenderFunction<HTMLSelectElement, Props> = (
|
|
|
85
103
|
const optionListReference = useRef<HTMLDivElement>(null);
|
|
86
104
|
const [isSearching, setIsSearching] = useState(false);
|
|
87
105
|
const [focusedSelectItem, setFocusedSelectItem] = useState(-1);
|
|
88
|
-
const [shouldClick, setShouldClick] =
|
|
89
|
-
|
|
90
|
-
false
|
|
91
|
-
); /** 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. */
|
|
106
|
+
const [shouldClick, setShouldClick] = useState(false);
|
|
107
|
+
/** 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. */
|
|
92
108
|
const [shouldFocusButtonAfterClose, setShouldFocusButtonAfterClose] = useState(false);
|
|
93
109
|
|
|
110
|
+
const DEFAULT_RENDER_THRESHOLD = 10;
|
|
111
|
+
|
|
94
112
|
const nativeSelect = (ref as React.RefObject<HTMLSelectElement>) || createRef();
|
|
95
113
|
const searchInputRef = useRef<HTMLInputElement>(null);
|
|
114
|
+
const addBtnRef = useRef<HTMLButtonElement>(null);
|
|
115
|
+
|
|
116
|
+
const addNewLabel = addNew?.label ?? "Create new";
|
|
117
|
+
|
|
118
|
+
const getRenderThreshold = search?.renderThreshold ?? DEFAULT_RENDER_THRESHOLD;
|
|
119
|
+
const hasEnoughChildren = Array.isArray(children) && children.length > getRenderThreshold;
|
|
120
|
+
|
|
121
|
+
const shouldRenderSearch = () => {
|
|
122
|
+
if (search?.enabled) {
|
|
123
|
+
return hasEnoughChildren;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (search) {
|
|
127
|
+
return search.enabled as boolean;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return children.length > DEFAULT_RENDER_THRESHOLD;
|
|
131
|
+
};
|
|
96
132
|
|
|
97
133
|
const onOptionChangeHandler = (optionElement: HTMLElement | null) => {
|
|
98
134
|
if (nativeSelect.current && optionElement) {
|
|
@@ -114,11 +150,12 @@ const SelectComponent: ForwardRefRenderFunction<HTMLSelectElement, Props> = (
|
|
|
114
150
|
childrenCount: React.Children.count(children),
|
|
115
151
|
setShouldClick,
|
|
116
152
|
searchInputRef,
|
|
117
|
-
|
|
153
|
+
addBtnRef,
|
|
154
|
+
renderThreshold: getRenderThreshold
|
|
118
155
|
});
|
|
119
156
|
|
|
120
157
|
const { listPosition, opacity, optionsListMaxHeight, setListPosition, setOpacity } =
|
|
121
|
-
useSelectPositionList({ expanded, optionListReference, containerReference });
|
|
158
|
+
useSelectPositionList({ expanded, optionListReference, containerReference, addBtnRef });
|
|
122
159
|
|
|
123
160
|
const syncDisplayValue = (val: string) => {
|
|
124
161
|
React.Children.forEach(children, child => {
|
|
@@ -129,7 +166,7 @@ const SelectComponent: ForwardRefRenderFunction<HTMLSelectElement, Props> = (
|
|
|
129
166
|
};
|
|
130
167
|
|
|
131
168
|
/**
|
|
132
|
-
* @description We have to modify the children (Option component) to have
|
|
169
|
+
* @description We have to modify the children (Option component) to have an additional props that allows us to keep track of which one is selected and focused at all times and if a filter is active.
|
|
133
170
|
* The `children` prop can be either a single object (1 child) or an array of multiple children.
|
|
134
171
|
*/
|
|
135
172
|
const renderOptions = () => {
|
|
@@ -165,32 +202,32 @@ const SelectComponent: ForwardRefRenderFunction<HTMLSelectElement, Props> = (
|
|
|
165
202
|
selectOpened: expanded,
|
|
166
203
|
childIndex: index,
|
|
167
204
|
hasFocus: focusedSelectItem === index,
|
|
168
|
-
shouldClick: shouldClick
|
|
205
|
+
shouldClick: shouldClick,
|
|
206
|
+
isAddBtnFocused: addBtnRef.current === document.activeElement
|
|
169
207
|
});
|
|
170
208
|
});
|
|
171
209
|
}
|
|
172
210
|
};
|
|
173
211
|
|
|
174
|
-
const shouldRenderSearch =
|
|
175
|
-
expanded && Array.isArray(children) && children.length > renderSearchCondition;
|
|
176
|
-
|
|
177
212
|
const renderSearch = () => (
|
|
178
213
|
<Input
|
|
179
|
-
{...searchInputProps}
|
|
214
|
+
{...(search?.searchInputProps ?? searchInputProps)}
|
|
180
215
|
ref={searchInputRef}
|
|
181
216
|
onFocus={() => setIsSearching(true)}
|
|
182
217
|
onBlur={() => setIsSearching(false)}
|
|
183
218
|
onChange={filterResults}
|
|
184
219
|
className={classes["select-search"]}
|
|
185
220
|
wrapperProps={{
|
|
186
|
-
className:
|
|
221
|
+
className:
|
|
222
|
+
search?.searchInputProps?.wrapperProps?.className ??
|
|
223
|
+
searchInputProps?.wrapperProps?.className
|
|
187
224
|
}}
|
|
188
225
|
style={{
|
|
189
226
|
display: expanded ? "block" : "none"
|
|
190
227
|
}}
|
|
191
228
|
type="text"
|
|
192
229
|
name="search-option"
|
|
193
|
-
placeholder={searchPlaceholder}
|
|
230
|
+
placeholder={search?.searchPlaceholder ?? searchPlaceholder}
|
|
194
231
|
/>
|
|
195
232
|
);
|
|
196
233
|
|
|
@@ -245,8 +282,8 @@ const SelectComponent: ForwardRefRenderFunction<HTMLSelectElement, Props> = (
|
|
|
245
282
|
};
|
|
246
283
|
|
|
247
284
|
useEffect(() => {
|
|
248
|
-
searchInputProps?.reset && resetSearchState();
|
|
249
|
-
}, [searchInputProps?.reset]);
|
|
285
|
+
(search?.searchInputProps?.reset || searchInputProps?.reset) && resetSearchState();
|
|
286
|
+
}, [searchInputProps?.reset, search?.searchInputProps?.reset]);
|
|
250
287
|
|
|
251
288
|
const additionalClasses = [];
|
|
252
289
|
expanded && additionalClasses.push(classes.expanded);
|
|
@@ -280,7 +317,7 @@ const SelectComponent: ForwardRefRenderFunction<HTMLSelectElement, Props> = (
|
|
|
280
317
|
className ?? ""
|
|
281
318
|
}`}
|
|
282
319
|
>
|
|
283
|
-
{
|
|
320
|
+
{shouldRenderSearch() && renderSearch()}
|
|
284
321
|
<button
|
|
285
322
|
{...selectButtonProps}
|
|
286
323
|
onClick={() => {
|
|
@@ -290,7 +327,7 @@ const SelectComponent: ForwardRefRenderFunction<HTMLSelectElement, Props> = (
|
|
|
290
327
|
type="button"
|
|
291
328
|
name={name}
|
|
292
329
|
className={`${classes["custom-select"]} ${additionalClasses.join(" ")} `}
|
|
293
|
-
style={{ display: shouldRenderSearch ? "none" : "initial" }}
|
|
330
|
+
style={{ display: expanded && shouldRenderSearch() ? "none" : "initial" }}
|
|
294
331
|
disabled={disabled}
|
|
295
332
|
aria-disabled={disabled}
|
|
296
333
|
aria-invalid={error}
|
|
@@ -317,11 +354,25 @@ const SelectComponent: ForwardRefRenderFunction<HTMLSelectElement, Props> = (
|
|
|
317
354
|
...listPosition
|
|
318
355
|
}}
|
|
319
356
|
>
|
|
320
|
-
<ul role="listbox">
|
|
357
|
+
<ul className={addNew && classes["has-sibling"]} role="listbox">
|
|
358
|
+
{renderOptions()}
|
|
359
|
+
</ul>
|
|
360
|
+
{addNew && (
|
|
361
|
+
<button
|
|
362
|
+
data-testid={"select-action-button"}
|
|
363
|
+
className={classes["action-button"]}
|
|
364
|
+
onClick={() => addNew.onAddNew(filter)}
|
|
365
|
+
ref={addBtnRef}
|
|
366
|
+
{...addNew.btnProps}
|
|
367
|
+
>
|
|
368
|
+
{!filter && addNewLabel}
|
|
369
|
+
{filter && <span style={{ fontWeight: "700" }}>{`"${filter}"`}</span>}
|
|
370
|
+
{filter && ` (${addNewLabel.toLowerCase()})`}
|
|
371
|
+
</button>
|
|
372
|
+
)}
|
|
321
373
|
</div>
|
|
322
374
|
</div>
|
|
323
375
|
</Fragment>
|
|
324
376
|
);
|
|
325
377
|
};
|
|
326
|
-
|
|
327
378
|
export const Select = React.forwardRef(SelectComponent);
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
UseSelectPositionListParams
|
|
22
22
|
} from "./Select.interfaces";
|
|
23
23
|
|
|
24
|
+
/** @scope . */
|
|
24
25
|
export const useArrowNavigation = ({
|
|
25
26
|
expanded,
|
|
26
27
|
setExpanded,
|
|
@@ -31,7 +32,8 @@ export const useArrowNavigation = ({
|
|
|
31
32
|
childrenCount,
|
|
32
33
|
setShouldClick,
|
|
33
34
|
searchInputRef,
|
|
34
|
-
|
|
35
|
+
addBtnRef,
|
|
36
|
+
renderThreshold
|
|
35
37
|
}: UseArrowNavigationParams) => {
|
|
36
38
|
const onArrowNavigation = (event: React.KeyboardEvent) => {
|
|
37
39
|
const codesToPreventDefault = [
|
|
@@ -54,12 +56,16 @@ export const useArrowNavigation = ({
|
|
|
54
56
|
"MetaRight"
|
|
55
57
|
];
|
|
56
58
|
|
|
57
|
-
|
|
59
|
+
const isAddBtnFocused = addBtnRef?.current === document.activeElement;
|
|
60
|
+
|
|
58
61
|
if (expanded) {
|
|
59
62
|
codesToPreventDefault.push("Tab");
|
|
60
63
|
}
|
|
61
64
|
|
|
62
|
-
|
|
65
|
+
if (addBtnRef) {
|
|
66
|
+
codesToPreventDefaultWhenSearching.push("Tab");
|
|
67
|
+
}
|
|
68
|
+
|
|
63
69
|
if (codesToPreventDefault.includes(event.code) && !event.metaKey && !isSearching) {
|
|
64
70
|
event.preventDefault();
|
|
65
71
|
}
|
|
@@ -80,7 +86,14 @@ export const useArrowNavigation = ({
|
|
|
80
86
|
setFocusedSelectItem(childrenCount - 1);
|
|
81
87
|
return;
|
|
82
88
|
case "Escape":
|
|
89
|
+
setIsSearching(false);
|
|
90
|
+
setExpanded(false);
|
|
91
|
+
return;
|
|
83
92
|
case "Tab":
|
|
93
|
+
if (addBtnRef?.current) {
|
|
94
|
+
addBtnRef.current.focus();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
84
97
|
setIsSearching(false);
|
|
85
98
|
setExpanded(false);
|
|
86
99
|
}
|
|
@@ -125,10 +138,13 @@ export const useArrowNavigation = ({
|
|
|
125
138
|
|
|
126
139
|
return;
|
|
127
140
|
case "Tab":
|
|
128
|
-
if (childrenCount >=
|
|
141
|
+
if (childrenCount >= renderThreshold && expanded && !isAddBtnFocused) {
|
|
129
142
|
setIsSearching(true);
|
|
130
143
|
searchInputRef.current?.focus();
|
|
131
144
|
return;
|
|
145
|
+
} else if (addBtnRef?.current && expanded && !isAddBtnFocused) {
|
|
146
|
+
addBtnRef.current.focus();
|
|
147
|
+
return;
|
|
132
148
|
}
|
|
133
149
|
setExpanded(false);
|
|
134
150
|
|
|
@@ -163,10 +179,11 @@ export const useArrowNavigation = ({
|
|
|
163
179
|
export const useSelectPositionList = ({
|
|
164
180
|
expanded,
|
|
165
181
|
optionListReference,
|
|
182
|
+
addBtnRef,
|
|
166
183
|
containerReference
|
|
167
184
|
}: UseSelectPositionListParams) => {
|
|
168
185
|
const [optionsListMaxHeight, setOptionsListMaxHeight] = useState("none");
|
|
169
|
-
const [opacity, setOpacity] = useState(0); // We set opacity because
|
|
186
|
+
const [opacity, setOpacity] = useState(0); // We set opacity because otherwise if we calculate the max height you see the list full height for a split second and then it shortens.
|
|
170
187
|
const [listPosition, setListPosition] = useState<Partial<Position>>({});
|
|
171
188
|
|
|
172
189
|
useEffect(() => {
|
|
@@ -203,6 +220,7 @@ export const useSelectPositionList = ({
|
|
|
203
220
|
const calculateOptionListMaxHeight = (position: Position) => {
|
|
204
221
|
// Calculate max height if there's more space below the select
|
|
205
222
|
const listHeight = optionListReference.current?.getBoundingClientRect().height;
|
|
223
|
+
const addNewButtonHeight = addBtnRef.current?.getBoundingClientRect().height ?? 0;
|
|
206
224
|
const transformOrigin = position.top !== "initial" ? "top" : "bottom";
|
|
207
225
|
|
|
208
226
|
if (!containerReference.current) {
|
|
@@ -214,12 +232,10 @@ export const useSelectPositionList = ({
|
|
|
214
232
|
|
|
215
233
|
const availableSpace =
|
|
216
234
|
transformOrigin === "top"
|
|
217
|
-
? window.innerHeight -
|
|
218
|
-
|
|
219
|
-
16
|
|
220
|
-
: containerReference.current.getBoundingClientRect()[transformOrigin] - 16;
|
|
235
|
+
? window.innerHeight - containerReference.current.getBoundingClientRect().bottom - 16
|
|
236
|
+
: containerReference.current.getBoundingClientRect().top - 16;
|
|
221
237
|
|
|
222
|
-
if (listHeight && availableSpace < listHeight) {
|
|
238
|
+
if (listHeight && availableSpace < listHeight + addNewButtonHeight) {
|
|
223
239
|
setOptionsListMaxHeight(`${availableSpace}px`);
|
|
224
240
|
setOpacity(100);
|
|
225
241
|
return;
|
|
@@ -45,6 +45,18 @@
|
|
|
45
45
|
font-size: 0.875rem;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
.icon-save-outline:before {
|
|
49
|
+
content: "\e947";
|
|
50
|
+
@include fontProperties();
|
|
51
|
+
}
|
|
52
|
+
.icon-reply-outline:before {
|
|
53
|
+
content: "\e946";
|
|
54
|
+
@include fontProperties();
|
|
55
|
+
}
|
|
56
|
+
.icon-upload-outline:before {
|
|
57
|
+
content: "\e945";
|
|
58
|
+
@include fontProperties();
|
|
59
|
+
}
|
|
48
60
|
.icon-home-filled:before {
|
|
49
61
|
content: "\e940";
|
|
50
62
|
@include fontProperties();
|
|
@@ -87,7 +87,10 @@ export enum Icons {
|
|
|
87
87
|
Warning = "warning",
|
|
88
88
|
FileOutline = "file-outline",
|
|
89
89
|
FileUpload = "file-upload-outline",
|
|
90
|
-
FileDownload = "file-download-outline"
|
|
90
|
+
FileDownload = "file-download-outline",
|
|
91
|
+
UploadOutline = "upload-outline",
|
|
92
|
+
ReplyOutline = "reply-outline",
|
|
93
|
+
SaveOutline = "save-outline"
|
|
91
94
|
}
|
|
92
95
|
|
|
93
96
|
type Tag = "span" | "div" | "i";
|
|
@@ -39,22 +39,46 @@
|
|
|
39
39
|
&:focus-visible {
|
|
40
40
|
outline: 0.5px dashed var(--color-primary);
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
&:visited {
|
|
44
|
+
color: var(--button-primary-pressed-color);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
&.success {
|
|
49
|
+
color: var(--color-success);
|
|
50
|
+
|
|
51
|
+
&:focus-visible {
|
|
52
|
+
outline: 0.5px dashed var(--color-primary);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
&:visited {
|
|
56
|
+
color: var(--button-success-pressed-color);
|
|
57
|
+
}
|
|
42
58
|
}
|
|
43
59
|
|
|
44
|
-
&.
|
|
45
|
-
color: var(--color-
|
|
60
|
+
&.danger {
|
|
61
|
+
color: var(--color-danger);
|
|
46
62
|
|
|
47
63
|
&:focus-visible {
|
|
48
64
|
outline: 0.5px dashed var(--color-primary);
|
|
49
65
|
}
|
|
66
|
+
|
|
67
|
+
&:visited {
|
|
68
|
+
color: var(--button-danger-pressed-color);
|
|
69
|
+
}
|
|
50
70
|
}
|
|
51
71
|
|
|
52
|
-
&.
|
|
53
|
-
color: var(--color-
|
|
72
|
+
&.warning {
|
|
73
|
+
color: var(--color-warning);
|
|
54
74
|
|
|
55
75
|
&:focus-visible {
|
|
56
76
|
outline: 0.5px dashed var(--color-primary);
|
|
57
77
|
}
|
|
78
|
+
|
|
79
|
+
&:visited {
|
|
80
|
+
color: var(--button-warning-pressed-color);
|
|
81
|
+
}
|
|
58
82
|
}
|
|
59
83
|
|
|
60
84
|
&.disabled {
|
|
@@ -27,7 +27,7 @@ export type AnchorType = "external" | "internal" | "download";
|
|
|
27
27
|
|
|
28
28
|
export interface Props extends ComponentPropsWithRef<"a"> {
|
|
29
29
|
prefixIcon?: ReactElement<IconProps, typeof Icon>;
|
|
30
|
-
color?: "primary" | "
|
|
30
|
+
color?: "primary" | "success" | "danger" | "warning";
|
|
31
31
|
display?: "link" | "button";
|
|
32
32
|
buttonVariant?: "outline" | "text" | "fill";
|
|
33
33
|
type?: AnchorType;
|