PromucFlow_constructor/app/client/src/components/designSystems/blueprint/ButtonComponent.tsx

242 lines
6.5 KiB
TypeScript
Raw Normal View History

2019-10-21 15:12:45 +00:00
import React from "react";
2020-02-12 08:23:50 +00:00
import {
IButtonProps,
MaybeElement,
2020-03-30 08:55:52 +00:00
Button,
2020-02-12 08:23:50 +00:00
IconName,
} from "@blueprintjs/core";
2019-10-21 15:12:45 +00:00
import styled, { css } from "styled-components";
2019-11-25 05:07:27 +00:00
import { ButtonStyle } from "widgets/ButtonWidget";
import { Theme, darkenHover, darkenActive } from "constants/DefaultTheme";
2019-11-28 07:08:39 +00:00
import _ from "lodash";
import { ComponentProps } from "components/designSystems/appsmith/BaseComponent";
import useScript from "utils/hooks/useScript";
import { AppToaster } from "components/editorComponents/ToastComponent";
import {
GOOGLE_RECAPTCHA_KEY_ERROR,
GOOGLE_RECAPTCHA_DOMAIN_ERROR,
} from "constants/messages";
2019-10-21 15:12:45 +00:00
2019-11-13 07:34:59 +00:00
const getButtonColorStyles = (props: { theme: Theme } & ButtonStyleProps) => {
if (props.filled) return props.theme.colors.textOnDarkBG;
2019-11-28 07:08:39 +00:00
if (props.accent) {
if (props.accent === "secondary") {
2019-11-13 07:34:59 +00:00
return props.theme.colors.OXFORD_BLUE;
2019-10-21 15:12:45 +00:00
}
return props.theme.colors[AccentColorMap[props.accent]];
2019-11-13 07:34:59 +00:00
}
};
const ButtonColorStyles = css<ButtonStyleProps>`
color: ${getButtonColorStyles};
svg {
fill: ${getButtonColorStyles};
}
2019-10-21 15:12:45 +00:00
`;
const AccentColorMap: Record<ButtonStyleName, string> = {
primary: "primaryOld",
secondary: "secondaryOld",
error: "error",
};
2019-10-21 15:12:45 +00:00
2019-11-28 07:08:39 +00:00
const ButtonWrapper = styled((props: ButtonStyleProps & IButtonProps) => (
2020-03-30 08:55:52 +00:00
<Button {..._.omit(props, ["accent", "filled"])} />
2019-11-28 07:08:39 +00:00
))<ButtonStyleProps>`
&&&& {
2019-10-21 15:12:45 +00:00
${ButtonColorStyles};
width: 100%;
height: 100%;
transition: background-color 0.2s;
background-color: ${props =>
props.filled &&
props.accent &&
props.theme.colors[AccentColorMap[props.accent]]};
2019-10-21 15:12:45 +00:00
border: 1px solid
${props =>
2019-11-28 07:08:39 +00:00
props.accent
? props.theme.colors[AccentColorMap[props.accent]]
2019-10-21 15:12:45 +00:00
: props.theme.colors.secondary};
border-radius: 4px;
2019-11-14 09:01:23 +00:00
font-weight: ${props => props.theme.fontWeights[2]};
2019-10-21 15:12:45 +00:00
outline: none;
2020-01-17 12:34:58 +00:00
&.bp3-button {
padding: 0px 10px;
}
2020-01-14 09:48:01 +00:00
&& .bp3-button-text {
max-width: 99%;
2020-01-17 12:34:58 +00:00
max-height: 100%;
2020-01-14 09:48:01 +00:00
overflow: hidden;
}
2019-10-21 15:12:45 +00:00
&&:hover,
&&:focus {
${ButtonColorStyles};
background-color: ${props => {
if (!props.filled) return props.theme.colors.secondaryDarker;
if (props.accent !== "secondary" && props.accent) {
return darkenHover(props.theme.colors[AccentColorMap[props.accent]]);
2019-10-21 15:12:45 +00:00
}
}};
border-color: ${props => {
if (!props.filled) return;
if (props.accent !== "secondary" && props.accent) {
return darkenHover(props.theme.colors[AccentColorMap[props.accent]]);
2019-10-21 15:12:45 +00:00
}
}};
}
&&:active {
${ButtonColorStyles};
background-color: ${props => {
if (!props.filled) return props.theme.colors.secondaryDarkest;
if (props.accent !== "secondary" && props.accent) {
return darkenActive(props.theme.colors[AccentColorMap[props.accent]]);
2019-10-21 15:12:45 +00:00
}
}};
border-color: ${props => {
if (!props.filled) return;
if (props.accent !== "secondary" && props.accent) {
return darkenActive(props.theme.colors[AccentColorMap[props.accent]]);
2019-10-21 15:12:45 +00:00
}
}};
}
2019-11-25 09:15:11 +00:00
&&.bp3-disabled {
background-color: #d0d7dd;
border: none;
}
2019-10-21 15:12:45 +00:00
}
`;
export type ButtonStyleName = "primary" | "secondary" | "error";
2019-10-21 15:12:45 +00:00
type ButtonStyleProps = {
2019-11-28 07:08:39 +00:00
accent?: ButtonStyleName;
2019-10-21 15:12:45 +00:00
filled?: boolean;
};
// To be used in any other part of the app
export const BaseButton = (props: IButtonProps & ButtonStyleProps) => {
return <ButtonWrapper {...props} />;
};
BaseButton.defaultProps = {
2019-11-28 07:08:39 +00:00
accent: "secondary",
disabled: false,
2019-10-21 15:12:45 +00:00
text: "Button Text",
minimal: true,
};
2020-03-06 09:45:21 +00:00
export enum ButtonType {
SUBMIT = "submit",
RESET = "reset",
BUTTON = "button",
}
interface RecaptchaProps {
googleRecaptchaKey?: string;
clickWithRecaptcha: (token: string) => void;
}
interface ButtonContainerProps extends ComponentProps {
text?: string;
2019-10-21 15:12:45 +00:00
icon?: MaybeElement;
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
disabled?: boolean;
2019-10-31 05:28:11 +00:00
buttonStyle?: ButtonStyle;
2019-12-03 04:41:10 +00:00
isLoading: boolean;
2020-02-12 08:23:50 +00:00
rightIcon?: IconName | MaybeElement;
2020-03-06 09:45:21 +00:00
type: ButtonType;
2019-10-21 15:12:45 +00:00
}
2019-10-31 05:28:11 +00:00
const mapButtonStyleToStyleName = (buttonStyle?: ButtonStyle) => {
switch (buttonStyle) {
case "PRIMARY_BUTTON":
return "primary";
case "SECONDARY_BUTTON":
return "secondary";
case "DANGER_BUTTON":
return "error";
default:
return undefined;
}
};
const RecaptchaComponent = (
props: {
children: any;
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
} & RecaptchaProps,
) => {
function handleError(event: React.MouseEvent<HTMLElement>, error: string) {
AppToaster.show({
message: error,
type: "error",
});
props.onClick && props.onClick(event);
}
const status = useScript(
`https://www.google.com/recaptcha/api.js?render=${props.googleRecaptchaKey}`,
);
return (
<div
onClick={(event: React.MouseEvent<HTMLElement>) => {
if (status === "ready") {
(window as any).grecaptcha.ready(() => {
try {
(window as any).grecaptcha
.execute(props.googleRecaptchaKey, { action: "submit" })
.then((token: any) => {
props.clickWithRecaptcha(token);
})
.catch(() => {
// Handle corrent key with wrong
handleError(event, GOOGLE_RECAPTCHA_KEY_ERROR);
});
} catch (ex) {
// Handle wrong key
handleError(event, GOOGLE_RECAPTCHA_DOMAIN_ERROR);
}
});
}
}}
>
{props.children}
</div>
);
};
const BtnWrapper = (
props: {
children: any;
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
} & RecaptchaProps,
) => {
if (!props.googleRecaptchaKey)
return <div onClick={props.onClick}>{props.children}</div>;
return <RecaptchaComponent {...props}></RecaptchaComponent>;
};
2019-10-21 15:12:45 +00:00
// To be used with the canvas
const ButtonContainer = (
props: ButtonContainerProps & ButtonStyleProps & RecaptchaProps,
) => {
2019-10-21 15:12:45 +00:00
return (
<BtnWrapper
googleRecaptchaKey={props.googleRecaptchaKey}
clickWithRecaptcha={props.clickWithRecaptcha}
onClick={props.onClick}
>
<BaseButton
loading={props.isLoading}
icon={props.icon}
rightIcon={props.rightIcon}
text={props.text}
filled={props.buttonStyle !== "SECONDARY_BUTTON"}
accent={mapButtonStyleToStyleName(props.buttonStyle)}
disabled={props.disabled}
type={props.type}
/>
</BtnWrapper>
2019-10-21 15:12:45 +00:00
);
};
export default ButtonContainer;