mirror of
https://github.com/smartxworks/sunmao-ui.git
synced 2024-11-21 03:15:49 +08:00
add grid bg and use react-resize-detector
This commit is contained in:
parent
522c85bc2a
commit
eceec4b4c6
@ -1,7 +1,7 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { GridCallbacks } from '@meta-ui/runtime';
|
||||
import { Box } from '@chakra-ui/react';
|
||||
import { css } from '@emotion/react';
|
||||
import produce from 'immer';
|
||||
import { App } from '../metaUI';
|
||||
import { StructureTree } from './StructureTree';
|
||||
import {
|
||||
@ -15,7 +15,6 @@ import { useAppModel } from '../operations/useAppModel';
|
||||
import { KeyboardEventWrapper } from './KeyboardEventWrapper';
|
||||
import { genComponentWrapper } from './ComponentWrapper';
|
||||
|
||||
let count = 0;
|
||||
export const Editor = () => {
|
||||
const [selectedComponentId, setSelectedComponentId] = useState('');
|
||||
const [hoverComponentId, setHoverComponentId] = useState('');
|
||||
@ -47,55 +46,38 @@ export const Editor = () => {
|
||||
setHoverComponentId,
|
||||
]);
|
||||
|
||||
// const Wrapper: React.FC<{ id: string }> = useMemo(() => {
|
||||
// return props => {
|
||||
// const style = css`
|
||||
// height: 100%;
|
||||
// box-shadow: 0 0 ${props.id === selectedComponentId ? 1 : 0}px red;
|
||||
// `;
|
||||
// const onClick = (e: React.MouseEvent<HTMLElement>) => {
|
||||
// e.stopPropagation();
|
||||
// setSelectedComponentId(() => props.id);
|
||||
// };
|
||||
// return (
|
||||
// <div onClick={onClick} css={style}>
|
||||
// {props.children}
|
||||
// </div>
|
||||
// );
|
||||
// };
|
||||
// }, [selectedComponentId]);
|
||||
const gridCallbacks: GridCallbacks = useMemo(() => {
|
||||
return {
|
||||
onDragStop(id, layout) {
|
||||
console.log('dragstop');
|
||||
eventBus.send(
|
||||
'operation',
|
||||
new ModifyComponentPropertyOperation(id, 'layout', layout)
|
||||
);
|
||||
},
|
||||
onDrop(id, layout, _, e) {
|
||||
const component = e.dataTransfer?.getData('component') || '';
|
||||
const componentId = `component${layout.length++}`;
|
||||
eventBus.send(
|
||||
'operation',
|
||||
new CreateComponentOperation(id, 'container', component, componentId)
|
||||
);
|
||||
|
||||
const gridCallbacks: GridCallbacks = {
|
||||
onDragStop(id, layout) {
|
||||
console.log('dragstop');
|
||||
eventBus.send(
|
||||
'operation',
|
||||
new ModifyComponentPropertyOperation(id, 'layout', layout)
|
||||
);
|
||||
},
|
||||
onDrop(id, layout, item, e) {
|
||||
const component = e.dataTransfer?.getData('component') || '';
|
||||
const componentId = `component${count++}`;
|
||||
eventBus.send(
|
||||
'operation',
|
||||
new CreateComponentOperation(id, 'container', component, componentId)
|
||||
);
|
||||
const newLayout = produce(layout, draft => {
|
||||
draft.forEach(l => {
|
||||
if (l.i === '__dropping-elem__') {
|
||||
l.i = componentId;
|
||||
}
|
||||
});
|
||||
}).filter(v => !!v); // there is unknown empty in array
|
||||
|
||||
const newLayout = [
|
||||
...layout,
|
||||
{
|
||||
...item,
|
||||
w: 3,
|
||||
i: componentId,
|
||||
},
|
||||
];
|
||||
|
||||
eventBus.send(
|
||||
'operation',
|
||||
new ModifyComponentPropertyOperation(id, 'layout', newLayout)
|
||||
);
|
||||
},
|
||||
};
|
||||
eventBus.send(
|
||||
'operation',
|
||||
new ModifyComponentPropertyOperation(id, 'layout', newLayout)
|
||||
);
|
||||
},
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<KeyboardEventWrapper selectedComponentId={selectedComponentId}>
|
||||
|
@ -2,7 +2,11 @@ import { ChakraProvider } from '@chakra-ui/react';
|
||||
import { css } from '@emotion/react';
|
||||
import { StrictMode } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import 'react-grid-layout/css/styles.css';
|
||||
import 'react-resizable/css/styles.css';
|
||||
|
||||
import { Editor } from './components/Editor';
|
||||
|
||||
export default function renderApp() {
|
||||
ReactDOM.render(
|
||||
<StrictMode>
|
||||
|
@ -34,6 +34,7 @@
|
||||
"react-dom": "^17.0.0",
|
||||
"react-grid-layout": "^1.3.0",
|
||||
"react-markdown": "^6.0.2",
|
||||
"react-resize-detector": "^6.7.6",
|
||||
"react-simple-code-editor": "^0.11.0",
|
||||
"wouter": "^2.7.4"
|
||||
},
|
||||
|
@ -1,41 +1,41 @@
|
||||
import RGL, { WidthProvider } from 'react-grid-layout';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import RGL from 'react-grid-layout';
|
||||
import { css } from '@emotion/react';
|
||||
import { useResizeDetector } from 'react-resize-detector';
|
||||
import 'react-grid-layout/css/styles.css';
|
||||
import 'react-resizable/css/styles.css';
|
||||
import { GRID_HEIGHT } from '../../constants';
|
||||
|
||||
const ReactGridLayout = WidthProvider(RGL);
|
||||
const GridLayout: React.FC<ReactGridLayout.ReactGridLayoutProps> = props => {
|
||||
const { children } = props;
|
||||
const spacing = 10;
|
||||
const { width, ref } = useResizeDetector();
|
||||
|
||||
export const LayoutPropertySchema = Type.Array(
|
||||
Type.Object({
|
||||
x: Type.Number(),
|
||||
y: Type.Number(),
|
||||
w: Type.Number(),
|
||||
h: Type.Number(),
|
||||
i: Type.String(),
|
||||
isResizable: Type.Optional(Type.Boolean()),
|
||||
})
|
||||
);
|
||||
const bgCss = css`
|
||||
height: 100%;
|
||||
background: white;
|
||||
background-image: linear-gradient(#eee 1px, transparent 0),
|
||||
linear-gradient(90deg, #eee 1px, transparent 0);
|
||||
background-size: ${(width || 0) / 12}px ${GRID_HEIGHT + spacing}px;
|
||||
background-position: 0px ${spacing / 2}px;
|
||||
`;
|
||||
|
||||
const GridLayout: React.FC<{
|
||||
layout: Static<typeof LayoutPropertySchema>;
|
||||
onDragStop?: (layout: RGL.Layout[]) => void;
|
||||
onDrop?: (layout: RGL.Layout[], item: RGL.Layout, event: DragEvent) => void;
|
||||
}> = ({ children, layout, onDragStop, onDrop }) => {
|
||||
return (
|
||||
<ReactGridLayout
|
||||
isDraggable={!!onDragStop}
|
||||
isResizable={!!onDragStop}
|
||||
compactType={null}
|
||||
preventCollision={true}
|
||||
rowHeight={GRID_HEIGHT}
|
||||
layout={layout}
|
||||
onDragStop={onDragStop}
|
||||
onDrop={onDrop}
|
||||
isDroppable={true}
|
||||
>
|
||||
{children}
|
||||
</ReactGridLayout>
|
||||
<div ref={ref} css={bgCss}>
|
||||
<RGL
|
||||
cols={12}
|
||||
// isDraggable={!!onDragStop}
|
||||
// isResizable={!!onDragStop}
|
||||
compactType={null}
|
||||
preventCollision={true}
|
||||
rowHeight={GRID_HEIGHT}
|
||||
width={width || 0}
|
||||
margin={[spacing, spacing]}
|
||||
isDroppable={true}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</RGL>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,10 +1,9 @@
|
||||
import React, { Suspense } from 'react';
|
||||
import RGL from 'react-grid-layout';
|
||||
import { ComponentImplementation } from '../../services/registry';
|
||||
import { createComponent } from '@meta-ui/core';
|
||||
import { getSlots } from '../_internal/Slot';
|
||||
import { LayoutPropertySchema } from '../../components/_internal/GridLayout';
|
||||
import { Static, Type } from '@sinclair/typebox';
|
||||
import { partial } from 'lodash';
|
||||
|
||||
const BaseGridLayout = React.lazy(() => import('../../components/_internal/GridLayout'));
|
||||
|
||||
@ -14,25 +13,33 @@ const GridLayout: ComponentImplementation<Static<typeof PropsSchema>> = ({
|
||||
gridCallbacks,
|
||||
component,
|
||||
}) => {
|
||||
const onDragStop = (layout: RGL.Layout[]) => {
|
||||
gridCallbacks?.onDragStop && gridCallbacks?.onDragStop(component.id, layout);
|
||||
};
|
||||
const onDrop = (layout: RGL.Layout[], item: RGL.Layout, e: DragEvent) => {
|
||||
gridCallbacks?.onDrop && gridCallbacks?.onDrop(component.id, layout, item, e);
|
||||
};
|
||||
const onDragStop = gridCallbacks?.onDragStop
|
||||
? partial(gridCallbacks.onDragStop, component.id)
|
||||
: undefined;
|
||||
const onDrop = gridCallbacks?.onDrop
|
||||
? partial(gridCallbacks.onDrop, component.id)
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<Suspense fallback={null}>
|
||||
<div style={{ boxShadow: '0 0 1px red' }}>
|
||||
<BaseGridLayout onDragStop={onDragStop} onDrop={onDrop} layout={layout}>
|
||||
{getSlots(slotsMap, 'container')}
|
||||
</BaseGridLayout>
|
||||
</div>
|
||||
<BaseGridLayout onDragStop={onDragStop} onDrop={onDrop} layout={layout}>
|
||||
{getSlots(slotsMap, 'container')}
|
||||
</BaseGridLayout>
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
|
||||
const PropsSchema = Type.Object({
|
||||
layout: LayoutPropertySchema,
|
||||
layout: Type.Array(
|
||||
Type.Object({
|
||||
x: Type.Number(),
|
||||
y: Type.Number(),
|
||||
w: Type.Number(),
|
||||
h: Type.Number(),
|
||||
i: Type.String(),
|
||||
isResizable: Type.Optional(Type.Boolean()),
|
||||
})
|
||||
),
|
||||
});
|
||||
|
||||
export default {
|
||||
|
25
yarn.lock
25
yarn.lock
@ -3016,6 +3016,11 @@
|
||||
"@types/scheduler" "*"
|
||||
csstype "^3.0.2"
|
||||
|
||||
"@types/resize-observer-browser@^0.1.6":
|
||||
version "0.1.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/resize-observer-browser/-/resize-observer-browser-0.1.6.tgz#d8e6c2f830e2650dc06fe74464472ff64b54a302"
|
||||
integrity sha512-61IfTac0s9jvNtBCpyo86QeaN8qqpMGHdK0uGKCCIy2dt5/Yk84VduHIdWAcmkC5QvdkPL0p5eWYgUZtHKKUVg==
|
||||
|
||||
"@types/scheduler@*":
|
||||
version "0.16.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
|
||||
@ -6379,6 +6384,11 @@ lodash.templatesettings@^4.0.0:
|
||||
dependencies:
|
||||
lodash._reinterpolate "^3.0.0"
|
||||
|
||||
lodash.throttle@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
|
||||
integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
|
||||
|
||||
lodash.truncate@^4.4.2:
|
||||
version "4.4.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
|
||||
@ -7684,6 +7694,16 @@ react-resizable@^3.0.4:
|
||||
prop-types "15.x"
|
||||
react-draggable "^4.0.3"
|
||||
|
||||
react-resize-detector@^6.7.6:
|
||||
version "6.7.6"
|
||||
resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-6.7.6.tgz#4416994e5ead7eba76606e3a248a1dfca49b67a3"
|
||||
integrity sha512-/6RZlul1yePSoYJxWxmmgjO320moeLC/khrwpEVIL+D2EjLKhqOwzFv+H8laMbImVj7Zu4FlMa0oA7au3/ChjQ==
|
||||
dependencies:
|
||||
"@types/resize-observer-browser" "^0.1.6"
|
||||
lodash.debounce "^4.0.8"
|
||||
lodash.throttle "^4.1.1"
|
||||
resize-observer-polyfill "^1.5.1"
|
||||
|
||||
react-simple-code-editor@^0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/react-simple-code-editor/-/react-simple-code-editor-0.11.0.tgz#bb57c7c29b570f2ab229872599eac184f5bc673c"
|
||||
@ -7952,6 +7972,11 @@ require-from-string@^2.0.2:
|
||||
resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
|
||||
integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
|
||||
|
||||
resize-observer-polyfill@^1.5.1:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
|
||||
integrity sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==
|
||||
|
||||
resolve-cwd@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
|
||||
|
Loading…
Reference in New Issue
Block a user