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.

232 lines (225 loc) 9.86 kB
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;