@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.
190 lines (175 loc) • 6.98 kB
JavaScript
import * as React from "react";
import styled, { css } from "styled-components";
import defaultTheme from "../../defaultTheme";
import FormLabel from "../../FormLabel";
import { FakeInput, Input, InputContainer } from "../InputField";
import { SelectContainer } from "../Select";
import FormFeedback from "../FormFeedback";
import { SIZE_OPTIONS, TOKENS } from "./consts";
import { right, rtlSpacing } from "../../utils/rtl";
import getSpacingToken from "../../common/getSpacingToken";
import randomID from "../../utils/randomID";
import formElementFocus from "../InputField/helpers/formElementFocus";
import mq from "../../utils/mediaQuery";
const getToken = name => ({
theme,
size
}) => {
const tokens = {
[TOKENS.height]: {
[SIZE_OPTIONS.SMALL]: theme.orbit.heightInputSmall,
[SIZE_OPTIONS.NORMAL]: theme.orbit.heightInputNormal
},
[TOKENS.heightLine]: {
[SIZE_OPTIONS.SMALL]: "16px",
[SIZE_OPTIONS.NORMAL]: "24px"
}
};
return tokens[name][size];
};
const FakeGroup = styled(({
children,
className
}) => /*#__PURE__*/React.createElement("span", {
className: className
}, children)).withConfig({
displayName: "InputGroup__FakeGroup",
componentId: "sc-ed1mas-0"
})(["", ""], ({
theme,
error,
disabled
}) => css(["width:100%;display:block;position:absolute;top:0px;left:0;z-index:1;box-sizing:border-box;height:", ";box-shadow:", ";box-shadow:", ";", ";background-color:", ";font-size:", ";transition:box-shadow ", " ease-in-out;border-radius:6px;", ";&:hover{box-shadow:inset 0 0 0 ", ";}"], getToken(TOKENS.height), `inset 0 0 0 ${theme.orbit.borderWidthInput} ${theme.orbit.borderColorInput}`, error && `inset 0 0 0 ${theme.orbit.borderWidthInput} ${theme.orbit.borderColorInputError}`, ({
active
}) => active && formElementFocus, disabled ? theme.orbit.backgroundInputDisabled : theme.orbit.backgroundInput, theme.orbit.fontSizeInputNormal, theme.orbit.durationFast, mq.tablet(css(["border-radius:", ";"], theme.orbit.borderRadiusNormal)), `${theme.orbit.borderWidthInput} ${error ? theme.orbit.borderColorInputErrorHover : theme.orbit.borderColorInputHover}`)); // $FlowFixMe: https://github.com/flow-typed/flow-typed/issues/3653#issuecomment-568539198
FakeGroup.defaultProps = {
theme: defaultTheme
};
const StyledChildren = styled.div.withConfig({
displayName: "InputGroup__StyledChildren",
componentId: "sc-ed1mas-1"
})(["display:flex;position:relative;"]);
const StyledChild = styled.div.withConfig({
displayName: "InputGroup__StyledChild",
componentId: "sc-ed1mas-2"
})(["flex:", ";padding:", ";:last-child{padding:0;}"], ({
flex
}) => flex, ({
theme
}) => rtlSpacing(`0 ${theme.orbit.spaceXSmall} 0 0`)); // $FlowFixMe: https://github.com/flow-typed/flow-typed/issues/3653#issuecomment-568539198
StyledChild.defaultProps = {
theme: defaultTheme
};
const StyledInputGroup = styled(({
children,
className,
dataTest,
role,
ariaLabelledby,
forwardRef,
dataState
}) => /*#__PURE__*/React.createElement("div", {
"data-state": dataState,
ref: forwardRef,
className: className,
"data-test": dataTest,
role: role,
"aria-labelledby": ariaLabelledby
}, children)).withConfig({
displayName: "InputGroup__StyledInputGroup",
componentId: "sc-ed1mas-3"
})(["display:flex;width:100%;flex-direction:column;position:relative;margin-bottom:", ";", "{", "{box-shadow:none;background-color:transparent;display:none;align-items:center;justify-content:flex-end;}", "{background-color:transparent;> select{box-shadow:none;background-color:transparent;&:focus{box-shadow:none;}}}", ":after,", ":after{content:\" \";position:absolute;top:50%;transform:translateY(-50%);", ":0;height:", ";width:1px;background-color:", ";transition:background-color ", " ease-in-out;display:block;z-index:2;}&:last-of-type{", ":after,", ":after{content:none;}}}", " ", "{display:", ";}", ":focus ~ ", "{box-shadow:none;}"], getSpacingToken, StyledChild, FakeInput, SelectContainer, InputContainer, SelectContainer, right, getToken(TOKENS.heightLine), ({
theme,
error,
active
}) => error && !active ? theme.orbit.borderColorInputError : theme.orbit.borderColorInput, ({
theme
}) => theme.orbit.durationFast, InputContainer, SelectContainer, StyledChild, FormLabel, ({
label
}) => label && "none", Input, FakeInput); // $FlowFixMe: https://github.com/flow-typed/flow-typed/issues/3653#issuecomment-568539198
StyledInputGroup.defaultProps = {
theme: defaultTheme
};
const findPropInChild = (propToFind, children) => {
return React.Children.toArray(children).map(el => {
if (el.props && typeof el.props[propToFind] !== "undefined") return el.props[propToFind];
return null;
}).filter(el => el !== null && el !== "");
};
const InputGroup = ({
children,
label,
flex = "0 1 auto",
size = SIZE_OPTIONS.NORMAL,
help,
error,
dataTest,
spaceAfter = "medium",
onFocus,
onBlur,
onChange
}) => {
const [active, setActive] = React.useState(false);
const [filled, setFilled] = React.useState(false);
const inputID = React.useMemo(() => randomID("inputGroupID"), []);
const isFilled = React.useCallback(() => setFilled(findPropInChild("value", children).length === React.Children.toArray(children).length), [children]);
React.useEffect(() => {
isFilled();
}, [isFilled]);
const handleFocus = ev => {
setActive(true);
if (onFocus) {
onFocus(ev);
}
};
const handleBlur = ev => {
isFilled();
setActive(false);
if (onBlur) {
onBlur(ev);
}
};
const handleChange = ev => {
isFilled();
if (onChange) {
onChange(ev);
}
};
return /*#__PURE__*/React.createElement(StyledInputGroup, {
label: label,
error: error,
active: active,
size: size,
dataTest: dataTest,
spaceAfter: spaceAfter,
role: "group",
ariaLabelledby: label && inputID
}, label && /*#__PURE__*/React.createElement(FormLabel, {
filled: filled,
id: inputID
}, label), /*#__PURE__*/React.createElement(StyledChildren, null, React.Children.map(children, (item, key) => {
// either array, array with one length or string
// if it's not defined, use the first or string
const childFlex = Array.isArray(flex) && flex.length !== 1 ? flex[key] || flex[0] : flex;
return /*#__PURE__*/React.createElement(StyledChild, {
flex: childFlex
}, /*#__PURE__*/React.cloneElement(item, {
size,
label: undefined,
help: undefined,
error: undefined,
onChange: item.props.onChange != null ? item.props.onChange : handleChange,
onBlur: item.props.onBlur != null ? item.props.onChange : handleBlur,
onFocus: item.props.onFocus != null ? item.props.onFocus : handleFocus
}));
}), /*#__PURE__*/React.createElement(FakeGroup, {
label: label,
error: error,
active: active,
size: size
})), /*#__PURE__*/React.createElement(FormFeedback, {
error: error,
help: help
}));
};
export default InputGroup;