UNPKG

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

140 lines (138 loc) 6.99 kB
"use client"; import * as React from "react"; import cx from "clsx"; import FormLabel from "../FormLabel"; import ErrorFormTooltip from "../ErrorFormTooltip"; import useRandomId, { useRandomIdSeed } from "../hooks/useRandomId"; import getFieldDataState from "../common/getFieldDataState"; import { getSpaceAfterClasses } from "../common/tailwind"; const findPropInChild = (propToFind, children) => React.Children.map(children, el => { if (el.props && el.props[propToFind]) return el.props[propToFind]; return null; }).filter(el => el != null); const InputGroup = ({ children, label, flex, help, id, error, disabled, dataTest, spaceAfter, onFocus, onBlur, onChange, onBlurGroup, ariaLabel, ariaLabelledby, required, ref }) => { const [active, setActive] = React.useState(false); const inputID = useRandomId(); const [tooltipShown, setTooltipShown] = React.useState(false); const [tooltipShownHover, setTooltipShownHover] = React.useState(false); const labelRef = React.useRef(null); const iconRef = React.useRef(null); const foundErrors = findPropInChild("error", children); const foundHelp = findPropInChild("help", children); const errorReal = error || foundErrors.length > 0 && foundErrors[0]; const helpReal = help || foundHelp.length > 0 && foundHelp[0]; const randomId = useRandomIdSeed(); const feedbackId = useRandomId(); const hasTooltip = errorReal || helpReal; const shown = tooltipShown || tooltipShownHover; const handleFocus = callBack => ev => { setActive(true); setTooltipShown(true); if (onFocus) onFocus(ev); if (callBack) callBack(ev); }; const handleBlur = callBack => ev => { setActive(false); if (onBlur) onBlur(ev); if (callBack) callBack(ev); }; const handleChange = callBack => ev => { if (onChange) onChange(ev); if (callBack) callBack(ev); }; const handleBlurGroup = ev => { ev.persist(); if (onBlurGroup) { setTimeout(() => { setActive(isActive => { if (!isActive) { onBlurGroup(ev); } return isActive; }); }, 50); } }; return /*#__PURE__*/React.createElement("div", { className: cx("relative flex w-full flex-col", spaceAfter != null && getSpaceAfterClasses(spaceAfter)) }, /*#__PURE__*/React.createElement("fieldset", { ref: ref, id: id, "data-test": dataTest, "data-state": getFieldDataState(!!errorReal), "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby, "aria-required": required }, label && /*#__PURE__*/React.createElement("legend", null, /*#__PURE__*/React.createElement(FormLabel, { id: inputID, labelRef: labelRef, error: !!errorReal, help: !!helpReal, iconRef: iconRef, onMouseEnter: () => hasTooltip ? setTooltipShownHover(true) : undefined, onMouseLeave: () => hasTooltip ? setTooltipShownHover(false) : undefined, required: required }, label)), /*#__PURE__*/React.createElement("div", { className: cx("text-normal h-form-box-normal duration-fast rounded-200 z-default w-full transition-shadow ease-in-out", disabled ? "bg-form-element-disabled-background" : "bg-form-element-background", !errorReal && "shadow-form-element", !errorReal && !disabled && "hover:shadow-form-element-hover", Boolean(errorReal) && "shadow-form-element-error", Boolean(errorReal) && !disabled && "hover:shadow-form-element-error-hover") }, /*#__PURE__*/React.createElement("div", { className: "relative flex", onBlur: handleBlurGroup }, React.Children.toArray(children).map((child, key) => { // TODO: next cleanup iteration just remove this whole `flex` prop thing // and cloning elements, and make children take care of their sizing themselves const childrenCount = React.Children.count(children); const isLastChild = key === childrenCount - 1; const flexArray = Array.isArray(flex) ? flex : [flex]; let childFlex = flex ? flexArray[key] || flexArray[0] : undefined; if (isLastChild && flexArray.length !== childrenCount) { childFlex = "1 1 100%"; } const item = child; return /*#__PURE__*/React.createElement("div", { key: randomId(String(key)), className: cx("orbit-input-group-child [&_.orbit-input-field-fake-input]:hidden [&_.orbit-input-field-fake-input]:bg-transparent [&_.orbit-input-field-input~.orbit-input-field-fake-input]:shadow-none [&_.orbit-select-container_select]:bg-transparent [&_.orbit-select-container_select]:shadow-none [&_.orbit-select-container_select]:focus:outline-none", // InputField:after "[&_.orbit-input-field-input-container]:after:duration-fast [&_.orbit-input-field-input-container]:after:z-default [&_.orbit-input-field-input-container]:after:h-600 [&_.orbit-input-field-input-container]:after:absolute [&_.orbit-input-field-input-container]:after:end-0 [&_.orbit-input-field-input-container]:after:top-1/2 [&_.orbit-input-field-input-container]:after:block [&_.orbit-input-field-input-container]:after:-translate-y-1/2 [&_.orbit-input-field-input-container]:after:border-r [&_.orbit-input-field-input-container]:after:transition-colors [&_.orbit-input-field-input-container]:after:ease-in-out [&_.orbit-input-field-input-container]:last-of-type:after:content-none", // Select:after "[&_.orbit-select-container]:after:duration-fast [&_.orbit-select-container]:after:h-600 [&_.orbit-select-container]:bg-transparent [&_.orbit-select-container]:after:absolute [&_.orbit-select-container]:after:end-0 [&_.orbit-select-container]:after:top-1/2 [&_.orbit-select-container]:after:z-[2] [&_.orbit-select-container]:after:block [&_.orbit-select-container]:after:-translate-y-1/2 [&_.orbit-select-container]:after:border-r [&_.orbit-select-container]:after:transition-colors [&_.orbit-select-container]:after:ease-in-out [&_.orbit-select-container]:last-of-type:after:content-none", Boolean(errorReal) && !active ? "[&_.orbit-select-container]:after:border-form-element-error [&_.orbit-input-field-input-container]:after:border-form-element-error" : "[&_.orbit-select-container]:after:border-form-element [&_.orbit-input-field-input-container]:after:border-form-element", label != null && "[&_.orbit-form-label]:hidden"), style: { flex: childFlex } }, /*#__PURE__*/React.cloneElement(item, { disabled: item.props.disabled || disabled, label: undefined, onChange: handleChange(item.props.onChange), onBlur: handleBlur(item.props.onBlur), onFocus: handleFocus(item.props.onFocus), ariaLabel: item.props.label, insideInputGroup: true, ariaDescribedby: (error || help || item.props.error || item.props.help) && shown ? feedbackId : undefined })); })))), /*#__PURE__*/React.createElement(ErrorFormTooltip, { id: feedbackId, help: helpReal, error: errorReal, onShown: setTooltipShown, shown: shown, referenceElement: labelRef })); }; export default InputGroup;