PromucFlow_constructor/app/client/src/components/designSystems/appsmith/ImageComponent.tsx

186 lines
5.3 KiB
TypeScript
Raw Normal View History

2019-11-05 05:09:50 +00:00
import * as React from "react";
import { ComponentProps } from "./BaseComponent";
import styled from "styled-components";
import { TransformWrapper, TransformComponent } from "react-zoom-pan-pinch";
2019-11-05 05:09:50 +00:00
export interface StyledImageProps {
2019-11-14 17:06:32 +00:00
defaultImageUrl: string;
imageUrl?: string;
backgroundColor?: string;
showHoverPointer?: boolean;
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
2019-11-14 17:06:32 +00:00
}
export const StyledImage = styled.div<
StyledImageProps & {
imageError: boolean;
}
>`
position: relative;
display: flex;
flex-direction: "row";
2020-12-24 04:32:25 +00:00
cursor: ${(props) =>
props.showHoverPointer && props.onClick ? "pointer" : "inherit"};
2020-12-24 04:32:25 +00:00
background: ${(props) => props.backgroundColor};
background-image: url("${(props) =>
props.imageError ? props.defaultImageUrl : props.imageUrl}");
background-position: center;
background-repeat: no-repeat;
background-size: contain;
height: 100%;
width: 100%;
2019-11-05 05:09:50 +00:00
`;
const Wrapper = styled.div`
height: 100%;
width: 100%;
.react-transform-element,
.react-transform-component {
height: 100%;
width: 100%;
}
`;
enum ZoomingState {
MAX_ZOOMED_OUT = "MAX_ZOOMED_OUT",
MAX_ZOOMED_IN = "MAX_ZOOMED_IN",
}
class ImageComponent extends React.Component<
ImageComponentProps,
{
imageError: boolean;
zoomingState: ZoomingState;
}
> {
isPanning: boolean;
constructor(props: ImageComponentProps) {
super(props);
this.isPanning = false;
this.state = {
imageError: false,
zoomingState: ZoomingState.MAX_ZOOMED_OUT,
};
}
2019-11-05 05:09:50 +00:00
render() {
const { maxZoomLevel } = this.props;
const zoomActive =
maxZoomLevel !== undefined && maxZoomLevel > 1 && !this.isPanning;
const isZoomingIn = this.state.zoomingState === ZoomingState.MAX_ZOOMED_OUT;
let cursor = "inherit";
if (zoomActive) {
cursor = isZoomingIn ? "zoom-in" : "zoom-out";
}
2019-12-03 04:41:10 +00:00
return (
<Wrapper>
<TransformWrapper
defaultScale={1}
doubleClick={{
disabled: true,
}}
onPanning={() => {
this.isPanning = true;
}}
onPanningStart={() => {
this.props.disableDrag(true);
}}
onPanningStop={() => {
this.props.disableDrag(false);
}}
onZoomChange={(zoom: any) => {
if (zoomActive) {
//Check max zoom
if (
maxZoomLevel === zoom.scale &&
// Added for preventing infinite loops
this.state.zoomingState !== ZoomingState.MAX_ZOOMED_IN
) {
this.setState({
zoomingState: ZoomingState.MAX_ZOOMED_IN,
});
// Check min zoom
} else if (
zoom.scale === 1 &&
this.state.zoomingState !== ZoomingState.MAX_ZOOMED_OUT
) {
this.setState({
zoomingState: ZoomingState.MAX_ZOOMED_OUT,
});
}
}
}}
options={{
maxScale: maxZoomLevel,
disabled: !zoomActive,
transformEnabled: zoomActive,
}}
pan={{
disabled: !zoomActive,
}}
wheel={{
disabled: !zoomActive,
}}
>
2021-01-12 01:22:31 +00:00
{({ zoomIn, zoomOut }: any) => (
<TransformComponent>
<StyledImage
className={this.props.isLoading ? "bp3-skeleton" : ""}
imageError={this.state.imageError}
{...this.props}
data-testid="styledImage"
onClick={(event: React.MouseEvent<HTMLElement>) => {
if (!this.isPanning) {
if (isZoomingIn) {
zoomIn(event);
} else {
zoomOut(event);
}
this.props.onClick && this.props.onClick(event);
}
this.isPanning = false;
}}
style={{
cursor,
}}
>
<img
alt={this.props.widgetName}
onError={this.onImageError}
onLoad={this.onImageLoad}
src={this.props.imageUrl}
style={{
display: "none",
}}
/>
</StyledImage>
</TransformComponent>
)}
</TransformWrapper>
</Wrapper>
2019-12-03 04:41:10 +00:00
);
2019-11-05 05:09:50 +00:00
}
onImageError = () => {
this.setState({
imageError: true,
});
};
onImageLoad = () => {
this.setState({
imageError: false,
});
};
2019-11-05 05:09:50 +00:00
}
export interface ImageComponentProps extends ComponentProps {
imageUrl: string;
defaultImageUrl: string;
2019-12-03 04:41:10 +00:00
isLoading: boolean;
showHoverPointer?: boolean;
maxZoomLevel: number;
disableDrag: (disabled: boolean) => void;
onClick?: (event: React.MouseEvent<HTMLElement>) => void;
2019-11-05 05:09:50 +00:00
}
export default ImageComponent;