You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
3.9 KiB
146 lines
3.9 KiB
import React, {createRef, useCallback, useEffect, useState} from 'react';
|
|
import {PreviewButtonStyle, PreviewStyle} from "./design-preview.style.js";
|
|
|
|
let startDragPosition = {x: 0, y: 0};
|
|
|
|
export function DesignPreview({previewOption = {widthDimension: 0}}) {
|
|
const reference = createRef();
|
|
const [active, setActive] = useState(false);
|
|
const [position, setPosition] = useState({x: getInitialXPosition(previewOption), y: 0});
|
|
const [opacity, setOpacity] = useState(85);
|
|
|
|
const keyDownHandler = useCallback(
|
|
function (e) {
|
|
if (!active) {
|
|
return;
|
|
}
|
|
|
|
const step = e.shiftKey ? 10 : 1;
|
|
if (e.key === 'ArrowUp') {
|
|
updatePosition({y: step * -1}, true)
|
|
} else if (e.key === 'ArrowDown') {
|
|
updatePosition({y: step}, true)
|
|
} else if (e.key === 'ArrowLeft') {
|
|
updatePosition({x: step * -1}, true)
|
|
} else if (e.key === 'ArrowRight') {
|
|
updatePosition({x: step}, true)
|
|
}
|
|
|
|
}, [position, active]);
|
|
|
|
useEffect(() => {
|
|
document.addEventListener('keydown', keyDownHandler);
|
|
|
|
return () => {
|
|
document.removeEventListener('keydown', keyDownHandler)
|
|
}
|
|
}, [keyDownHandler]);
|
|
|
|
useEffect(() => {
|
|
updatePosition({x: getInitialXPosition(previewOption), y: 0});
|
|
|
|
window.addEventListener('message', responsiveModeChangesHandler);
|
|
return () => window.removeEventListener('message', responsiveModeChangesHandler);
|
|
}, [previewOption.widthDimension]);
|
|
|
|
if (!previewOption) {
|
|
return;
|
|
}
|
|
|
|
const disabled = !previewOption.url;
|
|
|
|
const classNames = [];
|
|
if (!disabled && active) {
|
|
classNames.push('active');
|
|
}
|
|
|
|
if (disabled) {
|
|
classNames.push('disabled');
|
|
}
|
|
|
|
const handleOpacityChange = (e) => {
|
|
setOpacity(e.target.value);
|
|
}
|
|
|
|
return <>
|
|
<PreviewButtonStyle onClick={() => toggle()} className={classNames.join(' ')} disabled={disabled}/>
|
|
|
|
{active && !disabled &&
|
|
<>
|
|
<input type="range" value={opacity} min="0" max="100" onChange={handleOpacityChange}/>
|
|
<PreviewStyle onMouseUp={e => stop(e)} style={{opacity: opacity / 100}}>
|
|
<img src={previewOption.url} alt="" ref={reference}
|
|
onMouseDown={e => start(e)}
|
|
draggable={false}
|
|
style={{top: position.y + 'px', left: position.x + 'px'}}
|
|
/>
|
|
</PreviewStyle>
|
|
</>
|
|
}
|
|
</>
|
|
|
|
//
|
|
// Functions
|
|
//
|
|
|
|
function start(e) {
|
|
startDragPosition.x = e.clientX;
|
|
startDragPosition.y = e.clientY;
|
|
|
|
document.body.addEventListener('mousemove', handler);
|
|
}
|
|
|
|
function stop(e) {
|
|
const target = reference.current;
|
|
updatePosition({x: target.offsetLeft, y: target.offsetTop});
|
|
|
|
document.body.removeEventListener('mousemove', handler);
|
|
}
|
|
|
|
function handler(e) {
|
|
const target = reference.current;
|
|
|
|
if (target) {
|
|
const updatedPosition = {
|
|
x: target.offsetLeft - (startDragPosition.x - e.clientX),
|
|
y: target.offsetTop - (startDragPosition.y - e.clientY),
|
|
};
|
|
|
|
target.style.left = updatedPosition.x + 'px';
|
|
target.style.top = updatedPosition.y + 'px';
|
|
|
|
startDragPosition.x = e.clientX;
|
|
startDragPosition.y = e.clientY;
|
|
}
|
|
}
|
|
|
|
function toggle() {
|
|
setActive(!active);
|
|
}
|
|
|
|
function updatePosition({x, y}, relative = false) {
|
|
x = typeof x === 'undefined' ? position.x : relative ? position.x + x : x;
|
|
y = typeof y === 'undefined' ? position.y : relative ? position.y + y : y;
|
|
|
|
setPosition({x, y})
|
|
}
|
|
|
|
function getInitialXPosition(previewOption) {
|
|
if (!previewOption) {
|
|
return 0;
|
|
}
|
|
|
|
const scrollbarOffset = 7;
|
|
return window.innerWidth / 2 - previewOption.widthDimension / 2 - scrollbarOffset;
|
|
}
|
|
|
|
function responsiveModeChangesHandler(e) {
|
|
if (e.data !== 'responsiveUpdate') {
|
|
return;
|
|
}
|
|
|
|
if (window.responsiveState.breakpoint === '100%') {
|
|
updatePosition({x: getInitialXPosition(previewOption), y: 0});
|
|
}
|
|
}
|
|
}
|
|
|