@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.
232 lines (225 loc) • 9.86 kB
JavaScript
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
import * as React from "react";
import styled, { css } from "styled-components";
import { warning } from "@adeira/js";
import defaultTheme from "../defaultTheme";
import { ICON_SIZES } from "../Icon/consts";
import { TYPE_OPTIONS, SIZE_OPTIONS, TOKENS, BUTTON_STATES } from "./consts";
import Loading, { StyledSpinner } from "../Loading";
import { getSize } from "../Icon";
import getSpacingToken from "../common/getSpacingToken";
import getSizeToken from "./helpers/getSizeToken";
import getTypeToken from "./helpers/getTypeToken";
import getButtonSpacing from "./helpers/getButtonSpacing";
import getIconSpacing from "./helpers/getIconSpacing";
import getButtonBoxShadow from "./helpers/getButtonBoxShadow";
import getFocus from "./helpers/getFocus";
// media query only for IE 10+, not Edge
const onlyIE = (style, breakpoint = "all") => css(["@media ", " and (-ms-high-contrast:none),(-ms-high-contrast:active){", ";}"], breakpoint, style);
const IconContainer = styled(({
className,
children
}) => React.createElement("div", {
className: className
}, children)).withConfig({
displayName: "Button__IconContainer",
componentId: "sc-1brqp3f-0"
})(["display:flex;flex-direction:row;align-items:center;justify-content:center;margin:", ";color:", ";transition:background ", " ease-in-out,box-shadow ", " ease-in-out;> svg{width:", ";height:", ";}"], getIconSpacing(), ({
bordered
}) => bordered ? getTypeToken(TOKENS.colorTextButtonBordered) : getTypeToken(TOKENS.colorTextButton), ({
theme
}) => theme.orbit.durationFast, ({
theme
}) => theme.orbit.durationFast, ({
sizeIcon
}) => getSize(sizeIcon), ({
sizeIcon
}) => getSize(sizeIcon));
IconContainer.defaultProps = {
theme: defaultTheme
};
export const StyledButton = styled((_ref) => {
let {
theme,
asComponent,
circled,
external,
type,
icon,
iconLeft,
iconRight,
sizeIcon,
width,
bordered,
loading,
onlyIcon,
fullWidth,
style,
dataTest,
submit,
buttonRef,
ariaControls,
ariaExpanded,
spaceAfter,
title
} = _ref,
props = _objectWithoutProperties(_ref, ["theme", "asComponent", "circled", "external", "type", "icon", "iconLeft", "iconRight", "sizeIcon", "width", "bordered", "loading", "onlyIcon", "fullWidth", "style", "dataTest", "submit", "buttonRef", "ariaControls", "ariaExpanded", "spaceAfter", "title"]);
const isButtonWithHref = asComponent === "button" && props.href;
const Component = isButtonWithHref ? "a" : asComponent;
const buttonType = submit ? "submit" : "button";
return React.createElement(Component, _extends({
"data-test": dataTest,
"aria-controls": ariaControls,
"aria-expanded": ariaExpanded,
"aria-label": title,
type: !isButtonWithHref ? buttonType : undefined
}, props, {
ref: buttonRef
}), props.children);
}).withConfig({
displayName: "Button__StyledButton",
componentId: "sc-1brqp3f-1"
})(["position:relative;display:", ";justify-content:center;align-items:center;box-sizing:border-box;appearance:none;text-decoration:none;width:", ";flex:", ";max-width:100%;height:", ";background:", ";color:", " !important;border:0;border-radius:", ";padding:", ";font-family:", ";font-weight:", "!important;font-size:", ";line-height:1.4;cursor:", ";transition:all 0.15s ease-in-out !important;outline:0;opacity:", ";margin-bottom:", ";", ";&:hover{background:", ";color:", "!important;", ";", "{color:", ";}}&:active{", ";}", " ", "{width:", ";height:", ";}"], ({
href,
asComponent
}) => href || asComponent === "a" ? "inline-flex" : "flex", ({
fullWidth,
width,
onlyIcon
}) => fullWidth ? "100%" : width && `${width}px` || onlyIcon && getSizeToken(TOKENS.heightButton) || "auto", ({
fullWidth
}) => fullWidth ? "1 1 auto" : "0 0 auto", getSizeToken(TOKENS.heightButton), ({
bordered
}) => bordered ? getTypeToken(TOKENS.backgroundButtonBordered) : getTypeToken(TOKENS.backgroundButton), ({
bordered
}) => bordered ? getTypeToken(TOKENS.colorTextButtonBordered) : getTypeToken(TOKENS.colorTextButton), ({
theme,
circled
}) => circled ? getSizeToken(TOKENS.heightButton) : theme.orbit.borderRadiusNormal, getButtonSpacing(), ({
theme
}) => theme.orbit.fontFamily, ({
theme
}) => theme.orbit.fontWeightBold, getSizeToken(TOKENS.fontSizeButton), ({
disabled
}) => disabled ? "not-allowed" : "pointer", ({
disabled,
theme
}) => disabled && theme.orbit.opacityButtonDisabled, getSpacingToken, getButtonBoxShadow(BUTTON_STATES.DEFAULT), ({
disabled,
bordered
}) => !disabled && (bordered ? getTypeToken(TOKENS.backgroundButtonBorderedHover) : getTypeToken(TOKENS.backgroundButtonHover)), ({
disabled,
bordered
}) => !disabled && (bordered ? getTypeToken(TOKENS.colorTextButtonBorderedHover) : getTypeToken(TOKENS.colorTextButtonHover)), getButtonBoxShadow(BUTTON_STATES.HOVER), IconContainer, ({
disabled,
bordered
}) => !disabled && (bordered ? getTypeToken(TOKENS.colorTextButtonBorderedHover) : getTypeToken(TOKENS.colorTextButtonHover)), ({
disabled,
bordered
}) => !disabled && css(["background:", ";color:", "!important;", ";& ", "{color:", ";}"], bordered ? getTypeToken(TOKENS.backgroundButtonBorderedActive) : getTypeToken(TOKENS.backgroundButtonActive), bordered ? getTypeToken(TOKENS.colorTextButtonBorderedActive) : getTypeToken(TOKENS.colorTextButtonActive), getButtonBoxShadow(BUTTON_STATES.ACTIVE), IconContainer, bordered ? getTypeToken(TOKENS.colorTextButtonBorderedActive) : getTypeToken(TOKENS.colorTextButtonActive)), getFocus, StyledSpinner, getSizeToken(TOKENS.loadingWidth), getSizeToken(TOKENS.loadingHeight));
StyledButton.defaultProps = {
theme: defaultTheme
};
const StyledButtonContent = styled((_ref2) => {
let {
theme,
loading
} = _ref2,
props = _objectWithoutProperties(_ref2, ["theme", "loading"]);
return React.createElement("div", props);
}).withConfig({
displayName: "Button__StyledButtonContent",
componentId: "sc-1brqp3f-2"
})(["visibility:", ";height:100%;display:flex;flex-basis:100%;justify-content:center;align-items:center;", ";"], ({
loading
}) => loading && "hidden", onlyIE(css(["min-width:100%;max-width:1px;"])));
StyledButtonContent.defaultProps = {
theme: defaultTheme
};
const StyledButtonContentChildren = styled.div.withConfig({
displayName: "Button__StyledButtonContentChildren",
componentId: "sc-1brqp3f-3"
})(["display:inline-block;"]);
const Button = React.forwardRef((props, ref) => {
const {
asComponent = "button",
children,
bordered,
disabled,
href,
size = SIZE_OPTIONS.NORMAL,
icon,
iconRight,
external,
type = TYPE_OPTIONS.PRIMARY,
fullWidth,
loading = false,
width = 0,
role,
onClick,
circled,
submit,
tabIndex,
ariaExpanded,
className,
ariaControls,
spaceAfter,
dataTest,
title
} = props;
const iconLeft = props.iconLeft || icon;
const sizeIcon = size === ICON_SIZES.SMALL ? ICON_SIZES.SMALL : ICON_SIZES.MEDIUM;
const onlyIcon = iconLeft && !children;
const isDisabled = loading || disabled;
warning(!(!children && !title), "Warning: children or title property is missing on Button. Use title property to add aria-label to be accessible for screen readers. More information https://orbit.kiwi/components/button/api/#accessibility");
return React.createElement(StyledButton, {
onClick: onClick,
iconLeft: iconLeft,
iconRight: iconRight,
bordered: bordered,
fullWidth: fullWidth,
asComponent: asComponent,
disabled: isDisabled,
loading: loading,
onlyIcon: onlyIcon,
size: size,
sizeIcon: sizeIcon,
href: !disabled ? href : null,
target: !disabled && href && external ? "_blank" : undefined,
rel: !disabled && href && external ? "noopener noreferrer" : undefined,
type: type,
width: width,
className: className,
buttonRef: ref,
role: role,
circled: circled,
submit: submit,
tabIndex: tabIndex,
ariaExpanded: ariaExpanded,
ariaControls: ariaControls,
dataTest: dataTest,
spaceAfter: spaceAfter,
title: title
}, loading && React.createElement(Loading, {
type: "buttonLoader"
}), React.createElement(StyledButtonContent, {
loading: loading
}, iconLeft && React.createElement(IconContainer, {
bordered: bordered,
onlyIcon: onlyIcon,
size: size,
sizeIcon: sizeIcon,
type: type
}, iconLeft), children && React.createElement(StyledButtonContentChildren, null, children), iconRight && React.createElement(IconContainer, {
bordered: bordered,
onlyIcon: onlyIcon,
size: size,
sizeIcon: sizeIcon,
type: type,
right: true
}, iconRight)));
});
Button.displayName = "Button";
export default Button;