UNPKG

@kubit-ui-web/react-components

Version:

Kubit React Components is a customizable, accessible library of React web components, designed to enhance your application's user experience

147 lines 6.91 kB
import { jsx as _jsx } from "react/jsx-runtime"; import React from 'react'; import { STYLES_NAME } from '../../constants/stylesName/stylesName'; import { useMediaDevice } from '../../hooks/useMediaDevice/useMediaDevice'; import { useScrollDetectionWithAutoFocus } from '../../hooks/useScrollDetectionWithAutoFocus/useScrollDetectionWithAutoFocus'; import { useStyles } from '../../hooks/useStyles/useStyles'; import { useSwipeDown } from '../../hooks/useSwipeDown/useSwipeDown'; import { useTrapFocus } from '../../hooks/useTrapFocus/useTrapFocus'; import { ErrorBoundary } from '../../provider/errorBoundary/errorBoundary'; import { FallbackComponent } from '../../provider/errorBoundary/fallbackComponent'; import { DeviceBreakpointsType } from '../../types/breakpoints/breakpoints'; import { isKeyEnterPressed } from '../../utils/keyboard/keyboard.utility'; import { useTooltip } from './hooks/useTooltip'; import { useTooltipAsModal } from './hooks/useTooltipAsModal'; import { TooltipStandAlone } from './tooltipStandAlone'; const TooltipUnControlledComponent = React.forwardRef(({ ctv, tooltipAsModal, onOpenClose, variant, tooltipAriaLabel, ...props }, ref) => { const styles = useStyles(STYLES_NAME.TOOLTIP, variant, ctv); const mediaDevice = useMediaDevice(); const labelRef = React.useRef(null); const tooltipRef = React.useRef(null); const tooltipAsModalValue = useTooltipAsModal({ propTooltipAsModal: tooltipAsModal, styleTooltipAsModal: styles.tooltipAsModal, }); React.useImperativeHandle(ref, () => { return labelRef.current; }, []); const { showTooltip, hideTooltip, allowFocusOpenTooltip, open } = useTooltip({ labelRef, tooltipRef, variant, onOpenClose, align: props.align, tooltipAsModal: tooltipAsModalValue, ctv, }); const { hasScroll: contentHasScroll, handleScrollDetection: contentRefHandler } = useScrollDetectionWithAutoFocus({ parentElementRef: tooltipRef }); // When !tooltipAsModal, in tablet/mobile, onFocus and onClick are executed at the same time // So onFocus will open the tooltip, and onClick will close it (because it was opened) // To avoid calling onFocus when onClick, onMouseDown -> preventDefoult could be used, // But this approach will lead to the focus-visible pseudo class being applied (strange, but true) // So the approach is to use a flag to avoid calling onFocus when onClick const isBeingClicked = React.useRef(false); const handleWrapperFocus = () => { // allowFocusOpenTooltip Avoid tooltip is opened automatically after closing the tooltip if (isBeingClicked.current || tooltipAsModalValue || !allowFocusOpenTooltip.current) { return; } showTooltip(); }; const handleWrapperBlur = event => { if (!tooltipAsModalValue && !event.currentTarget.contains(event.relatedTarget)) { hideTooltip(); } }; const handleFocusTooltip = event => { if (!tooltipAsModalValue) { // Avoid on focus (label) be executed on focus tooltip event.preventDefault(); event.stopPropagation(); } }; const handleWrapperMouseEnter = () => { if (!tooltipAsModalValue) { if (mediaDevice !== DeviceBreakpointsType.DESKTOP) { return; } showTooltip(); } }; const handleWrapperMouseLeave = () => { if (!tooltipAsModalValue) { if (mediaDevice !== DeviceBreakpointsType.DESKTOP) { return; } hideTooltip(); } }; const handleCloseIconClick = event => { props.closeIcon?.onClick?.(event); hideTooltip(); }; const handleTriggerMouseDown = () => { isBeingClicked.current = true; }; const handleTriggerMouseUp = () => { isBeingClicked.current = false; }; const handleTriggerClick = event => { if (mediaDevice === DeviceBreakpointsType.DESKTOP) { if (!tooltipAsModalValue) { return; } if (!open) { showTooltip(); return; } if (!tooltipRef.current?.contains(event.target)) { hideTooltip(); } return; } // Mobile / tablet if (!open) { showTooltip(); return; } if (!tooltipRef.current?.contains(event.target)) { hideTooltip(); } }; const handleTriggerKeyDown = event => { if (isKeyEnterPressed(event.key) && !open) { showTooltip(); event.preventDefault(); } }; const handlePopoverCloseInternally = () => { props.popover?.onCloseInternally?.(); hideTooltip(); }; const { setDragIconRef, setPopoverRef } = useSwipeDown(props.popover?.animationOptions, hideTooltip); useTrapFocus({ ref: tooltipRef, trapFocus: open && tooltipAsModalValue }); // It is used TooltipStandAlone instead of TooltipControlled // The reason is that TooltipControlled only provides the styles and mediaDevice props that are used and needed in this component return (_jsx(TooltipStandAlone, { ...props, contentHasScroll: contentHasScroll, contentRef: contentRefHandler, dragIconRef: setDragIconRef, labelRef: labelRef, mediaDevice: mediaDevice, popover: { ...props.popover, forwardedRef: setPopoverRef, }, popoverOpen: open, styles: styles, tooltipAriaLabel: tooltipAriaLabel, tooltipAsModal: tooltipAsModalValue, tooltipRef: tooltipRef, onCloseIconClick: handleCloseIconClick, onPopoverCloseInternally: handlePopoverCloseInternally, onTooltipFocus: handleFocusTooltip, onTriggerClick: handleTriggerClick, onTriggerKeyDown: handleTriggerKeyDown, onTriggerMouseDown: handleTriggerMouseDown, onTriggerMouseUp: handleTriggerMouseUp, onWrapperBlur: handleWrapperBlur, onWrapperFocus: handleWrapperFocus, onWrapperMouseEnter: handleWrapperMouseEnter, onWrapperMouseLeave: handleWrapperMouseLeave })); }); TooltipUnControlledComponent.displayName = 'TooltipUnControlledComponent'; const TooltipUnControlledBoundary = (props, ref) => (_jsx(ErrorBoundary, { fallBackComponent: _jsx(FallbackComponent, { children: _jsx(TooltipStandAlone, { ...props }) }), children: _jsx(TooltipUnControlledComponent, { ...props, ref: ref }) })); const TooltipUnControlled = React.forwardRef(TooltipUnControlledBoundary); /** * @description * Tooltip component to show a message when interact whit the label * @example * <Tooltip * align={TooltipAlignType.CENTER} * variant={TooltipVariantType.DEFAULT} * > * <Text>Tooltip</Text> * </Tooltip> */ export { TooltipUnControlled }; export { TooltipUnControlled as Tooltip }; //# sourceMappingURL=tooltipUnControlled.js.map