2021-07-09 01:41:03 +08:00
|
|
|
|
import { IBlockType } from '../core/store/storetype';
|
|
|
|
|
import { CSSProperties, PropsWithChildren, useEffect, useMemo, useRef, useState } from 'react';
|
|
|
|
|
import { innerDrag } from '../core/innerDrag';
|
|
|
|
|
import { BlockResizer } from '../core/resizeHandler';
|
|
|
|
|
import { contextMenuEvent } from '../core/contextMenu';
|
|
|
|
|
import React from 'react';
|
|
|
|
|
import { transfer } from '../core/transfer';
|
|
|
|
|
import { UserConfig } from '../config';
|
|
|
|
|
import styles from '../index.less';
|
|
|
|
|
interface BlockProps {
|
|
|
|
|
data: IBlockType;
|
|
|
|
|
context: 'edit' | 'preview';
|
|
|
|
|
config: UserConfig;
|
2021-07-20 16:33:23 +08:00
|
|
|
|
iframe?: boolean;
|
2021-07-09 01:41:03 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
|
* 用来从component里拿到渲染进行渲染,由于异步拉代码,所以需要等待代码拉取完毕
|
|
|
|
|
* @param {*} props
|
|
|
|
|
* @returns
|
|
|
|
|
*/
|
|
|
|
|
function Blocks(props: PropsWithChildren<BlockProps>) {
|
|
|
|
|
const [state, setState] = useState<JSX.Element | null>(null);
|
|
|
|
|
|
|
|
|
|
const [previewState, setPreviewState] = useState({
|
|
|
|
|
top: props.data.top,
|
|
|
|
|
left: props.data.left,
|
|
|
|
|
height: props.data.height,
|
|
|
|
|
width: props.data.width,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const fn = () => props.config.getComponentRegister().getComp(props.data.name);
|
|
|
|
|
const data = fn();
|
|
|
|
|
let unregist = () => {};
|
|
|
|
|
let newdata = { ...props.data };
|
|
|
|
|
if (props.context === 'preview') {
|
|
|
|
|
newdata = {
|
|
|
|
|
...props.data,
|
|
|
|
|
top: previewState.top,
|
|
|
|
|
left: previewState.left,
|
|
|
|
|
height: previewState.height,
|
|
|
|
|
width: previewState.width,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (data) {
|
|
|
|
|
setState(data.render(newdata, props.context, props.config.getStore(), props.config));
|
|
|
|
|
} else {
|
|
|
|
|
const callback = () => {
|
|
|
|
|
const tmp = fn();
|
|
|
|
|
setState(tmp.render(newdata, props.context, props.config.getStore(), props.config));
|
|
|
|
|
unregist();
|
|
|
|
|
};
|
|
|
|
|
unregist = props.config.getComponentRegister().on(props.data.name, callback);
|
|
|
|
|
}
|
|
|
|
|
return () => {
|
|
|
|
|
unregist();
|
|
|
|
|
};
|
|
|
|
|
}, [props.data, props.context, props.config, previewState]);
|
|
|
|
|
|
|
|
|
|
const ref = useRef<HTMLDivElement>(null);
|
|
|
|
|
const innerDragData = useMemo(() => {
|
2021-07-12 21:01:11 +08:00
|
|
|
|
return { ...innerDrag(props.data, ref, props.config) };
|
|
|
|
|
}, [props.data, props.config]);
|
2021-07-09 01:41:03 +08:00
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
const fn = () => {
|
|
|
|
|
const { top, left, width, height } = transfer(
|
|
|
|
|
props.data.top,
|
|
|
|
|
props.data.left,
|
|
|
|
|
props.data.height,
|
|
|
|
|
props.data.width,
|
|
|
|
|
props.data.fixed
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
setPreviewState({ top, left, width, height });
|
|
|
|
|
};
|
|
|
|
|
fn();
|
|
|
|
|
window.addEventListener('resize', fn);
|
|
|
|
|
return () => {
|
|
|
|
|
window.removeEventListener('resize', fn);
|
|
|
|
|
};
|
|
|
|
|
}, [
|
|
|
|
|
previewState.height,
|
|
|
|
|
previewState.left,
|
|
|
|
|
previewState.top,
|
|
|
|
|
previewState.width,
|
|
|
|
|
props.data.height,
|
|
|
|
|
props.data.left,
|
|
|
|
|
props.data.top,
|
|
|
|
|
props.data.width,
|
|
|
|
|
props.data.fixed,
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
const animatecss = useMemo(() => {
|
|
|
|
|
const animate = props.data.animate;
|
|
|
|
|
if (Object.keys(animate).length > 0) {
|
|
|
|
|
return `animate__animated ${animate.animate ?? ''} ${animate.delay ?? ''} ${
|
|
|
|
|
animate.speed ?? ''
|
|
|
|
|
}`;
|
|
|
|
|
}
|
|
|
|
|
return '';
|
2021-07-11 13:56:35 +08:00
|
|
|
|
}, [props.data.animate]);
|
2021-07-09 01:41:03 +08:00
|
|
|
|
const animateCount = useMemo(() => {
|
|
|
|
|
const animate = props.data.animate;
|
|
|
|
|
if (Object.keys(animate).length > 0) {
|
|
|
|
|
return { animationIterationCount: animate.animationIterationCount };
|
|
|
|
|
}
|
2021-07-13 21:18:22 +08:00
|
|
|
|
return { animationIterationCount: '' };
|
2021-07-11 13:56:35 +08:00
|
|
|
|
}, [props.data.animate]);
|
2021-07-09 01:41:03 +08:00
|
|
|
|
|
|
|
|
|
const render = useMemo(() => {
|
|
|
|
|
// 如果是编辑模式下,则需要包裹不能选中层,位移层,缩放控制层,平面移动层。
|
|
|
|
|
if (state && props.context === 'edit') {
|
|
|
|
|
const style: CSSProperties = props.data.canDrag ? { pointerEvents: 'none' } : {};
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
ref={ref}
|
|
|
|
|
className={
|
|
|
|
|
props.data.focus && props.data.position !== 'static' ? styles.yh_block_focus : ''
|
|
|
|
|
}
|
|
|
|
|
style={{
|
|
|
|
|
position: props.data.position,
|
|
|
|
|
top: props.data.top,
|
|
|
|
|
left: props.data.left,
|
|
|
|
|
width: props.data.width,
|
|
|
|
|
height: props.data.height,
|
|
|
|
|
zIndex: props.data.zIndex,
|
|
|
|
|
display: props.data.display,
|
2021-07-20 16:33:23 +08:00
|
|
|
|
opacity: props.iframe ? 0 : 1,
|
2021-07-09 01:41:03 +08:00
|
|
|
|
}}
|
|
|
|
|
{...innerDragData}
|
|
|
|
|
onContextMenu={(e) => {
|
|
|
|
|
if (props.data.name !== 'modalMask') {
|
2021-07-12 21:01:11 +08:00
|
|
|
|
contextMenuEvent(e, ref, props.config);
|
2021-07-09 01:41:03 +08:00
|
|
|
|
}
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{props.data.position !== 'static' && (
|
|
|
|
|
<div className={animatecss} style={{ ...style, ...animateCount }}>
|
|
|
|
|
{state}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
{/* 这里暂不考虑布局影响 */}
|
|
|
|
|
{props.data.position === 'static' && props.data.display !== 'inline' && (
|
|
|
|
|
<div
|
|
|
|
|
className={animatecss}
|
|
|
|
|
style={{
|
|
|
|
|
pointerEvents: 'none',
|
|
|
|
|
width: '100%',
|
|
|
|
|
height: '100%',
|
|
|
|
|
...animateCount,
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{state}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
{props.data.position === 'static' && props.data.display === 'inline' && (
|
|
|
|
|
<span style={{ pointerEvents: 'none' }}>{state}</span>
|
|
|
|
|
)}
|
2021-07-13 15:15:19 +08:00
|
|
|
|
<BlockResizer data={props.data} config={props.config} rect={ref}></BlockResizer>
|
2021-07-09 01:41:03 +08:00
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
return (
|
|
|
|
|
<div
|
|
|
|
|
className={animatecss}
|
|
|
|
|
style={{
|
|
|
|
|
position: props.data.fixed ? 'fixed' : props.data.position,
|
|
|
|
|
top: previewState.top,
|
|
|
|
|
left: previewState.left,
|
|
|
|
|
width: previewState.width,
|
|
|
|
|
height: previewState.height,
|
|
|
|
|
zIndex: props.data.zIndex,
|
|
|
|
|
display: props.data.display,
|
|
|
|
|
...animateCount,
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{state}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}, [
|
|
|
|
|
state,
|
|
|
|
|
props.context,
|
|
|
|
|
props.data,
|
2021-07-20 16:33:23 +08:00
|
|
|
|
props.iframe,
|
2021-07-13 21:18:22 +08:00
|
|
|
|
props.config,
|
2021-07-09 01:41:03 +08:00
|
|
|
|
innerDragData,
|
2021-07-11 13:56:35 +08:00
|
|
|
|
animatecss,
|
|
|
|
|
animateCount,
|
2021-07-09 01:41:03 +08:00
|
|
|
|
previewState.top,
|
|
|
|
|
previewState.left,
|
|
|
|
|
previewState.width,
|
|
|
|
|
previewState.height,
|
|
|
|
|
]);
|
|
|
|
|
return render;
|
|
|
|
|
}
|
|
|
|
|
export default Blocks;
|