@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
JavaScript
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