@kiwicom/orbit-components
Version:
Orbit-components is a React component library which provides developers with the easiest possible way of building Kiwi.com’s products.
120 lines • 4.76 kB
JavaScript
import * as React from "react";
import cx from "clsx";
import { usePopper } from "react-popper";
import useClickOutside from "../../hooks/useClickOutside";
import KEY_CODE_MAP from "../../common/keyMaps";
import handleKeyDown from "../../utils/handleKeyDown";
import CloseIcon from "../../icons/Close";
import useTheme from "../../hooks/useTheme";
import useMediaQuery from "../../hooks/useMediaQuery";
const ErrorFormTooltip = ({
onShown,
dataTest,
helpClosable,
children,
shown,
referenceElement,
inlineLabel,
isHelp = false,
id
}) => {
const contentRef = React.useRef(null);
const tooltipRef = React.useRef(null);
const [arrowRef, setArrowRef] = React.useState(null);
const {
rtl
} = useTheme();
const {
isDesktop
} = useMediaQuery();
const {
styles,
attributes: attrs,
update
} = usePopper(referenceElement?.current, tooltipRef.current, {
placement: rtl ? "top-end" : "top-start",
modifiers: [{
name: "offset",
options: {
offset: [inlineLabel || isDesktop ? 0 : 4, 3]
}
}, {
name: "flip",
enabled: false
}, {
name: "arrow",
options: {
element: arrowRef
}
}, {
name: "eventListeners",
options: {
scroll: false
}
}]
});
const {
popper
} = styles;
useClickOutside(tooltipRef, () => {
onShown(false);
});
React.useEffect(() => {
if (update) update();
}, [update, shown]);
React.useEffect(() => {
const link = tooltipRef.current?.querySelector("a");
const handleTab = ev => {
if (isHelp) return;
if (ev.keyCode === KEY_CODE_MAP.TAB && link) {
onShown(true);
if (document.activeElement === link) {
onShown(false);
}
} else {
onShown(false);
}
};
window.addEventListener("keydown", handleTab);
return () => {
window.removeEventListener("keydown", handleTab);
};
}, [onShown, isHelp, helpClosable]);
const isVertical = attrs.popper && (attrs.popper["data-popper-placement"] === "top-start" || attrs.popper["data-popper-placement"] === "top-end") ? "bottom" : "top";
const cssVars = {
"--error-form-tooltip-position": popper.position,
"--error-form-tooltip-top": popper.top,
"--error-form-tooltip-left": popper.left,
"--error-form-tooltip-right": popper.right,
"--error-form-tooltip-bottom": popper.bottom,
"--error-form-tooltip-transform": popper.transform
};
return /*#__PURE__*/React.createElement("div", {
id: id,
ref: tooltipRef,
"aria-live": "polite",
"data-test": dataTest,
className: cx("flex justify-between overflow-visible", "rounded-large py-xs px-sm z-10 box-border", "max-h-none w-[min(calc(100%-20px),_100vw)]", isHelp ? "pe-sm bg-blue-normal" : "bg-red-normal", shown ? "visible opacity-100" : "invisible opacity-0", "duration-fast transition-[opacity,visibility] ease-in-out", "bottom-[var(--error-form-tooltip-bottom)] left-[var(--error-form-tooltip-left)] right-[var(--error-form-tooltip-right)] top-[var(--error-form-tooltip-top)] [position:var(--error-form-tooltip-position)] [transform:var(--error-form-tooltip-transform)]", "lm:w-auto tb:rounded-normal", "[&>img]:max-w-full"),
style: cssVars
}, /*#__PURE__*/React.createElement("div", {
className: cx("start-xs rtl:de:start-0 absolute", isVertical ? "bottom-xxxs" : "top-xxxs", inlineLabel && "rtl:start-0", isHelp ? "before:bg-blue-normal" : "before:bg-red-normal", "before:h-xs before:w-xs before:absolute before:-translate-x-1/2 before:-translate-y-1/2 before:rotate-45"),
ref: setArrowRef
}), /*#__PURE__*/React.createElement("div", {
className: cx("font-base text-normal leading-small text-white-normal flex h-full items-center font-normal", "[&_.orbit-text]:text-white-normal [&_.orbit-text]:text-normal hover:[&_.orbit-text]:text-white-normal focus:[&_.orbit-text]:text-white-normal [&_.orbit-text]:font-normal", "[&_.orbit-list-item]:text-white-normal [&_.orbit-list-item]:text-normal hover:[&_.orbit-list-item]:text-white-normal focus:[&_.orbit-list-item]:text-white-normal [&_.orbit-list-item]:font-normal", "[&_a]:text-white-normal [&_a]:text-normal hover:[&_a]:text-white-normal focus:[&_a]:text-white-normal [&_a]:font-normal"),
ref: contentRef
}, children), isHelp && helpClosable && /*#__PURE__*/React.createElement("button", {
type: "button",
className: "text-white-normal ms-sm flex cursor-pointer",
tabIndex: 0
// @ts-expect-error TODO
,
onKeyDown: handleKeyDown(onShown),
onClick: ev => {
ev.preventDefault();
if (shown) onShown(false);
}
}, /*#__PURE__*/React.createElement(CloseIcon, {
ariaLabel: "close"
})));
};
export default ErrorFormTooltip;