Files
dooring/packages/dooringx-lib/src/components/blocks.tsx

199 lines
5.2 KiB
TypeScript
Raw Normal View History

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;
}
/**
*
* 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 };
}
return { animationIterationCount: 1 };
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,
}}
{...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,
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;