From 822e332981eda37120f7017da41ba0b13025dd7b Mon Sep 17 00:00:00 2001 From: KatoakDR <68095633+KatoakDR@users.noreply.github.com> Date: Sun, 22 Oct 2023 00:35:56 -0500 Subject: [PATCH] feat: poc grid layout drag-n-drop --- .../components/grid-item/grid-item.tsx | 5 + .../renderer/components/grid-item/index.ts | 1 + electron/renderer/components/grid/grid.tsx | 140 +++++++++++++++++ electron/renderer/components/grid/index.ts | 1 + electron/renderer/components/grid/styles.ts | 7 + electron/renderer/pages/dnd.tsx | 145 +----------------- package.json | 8 + 7 files changed, 168 insertions(+), 139 deletions(-) create mode 100644 electron/renderer/components/grid-item/grid-item.tsx create mode 100644 electron/renderer/components/grid-item/index.ts create mode 100644 electron/renderer/components/grid/grid.tsx create mode 100644 electron/renderer/components/grid/index.ts create mode 100644 electron/renderer/components/grid/styles.ts diff --git a/electron/renderer/components/grid-item/grid-item.tsx b/electron/renderer/components/grid-item/grid-item.tsx new file mode 100644 index 00000000..56eeb7c5 --- /dev/null +++ b/electron/renderer/components/grid-item/grid-item.tsx @@ -0,0 +1,5 @@ +const GridItem: React.FC = (): JSX.Element => { + return <>TODO; +}; + +export { GridItem }; diff --git a/electron/renderer/components/grid-item/index.ts b/electron/renderer/components/grid-item/index.ts new file mode 100644 index 00000000..8823246f --- /dev/null +++ b/electron/renderer/components/grid-item/index.ts @@ -0,0 +1 @@ +export * from './grid-item'; diff --git a/electron/renderer/components/grid/grid.tsx b/electron/renderer/components/grid/grid.tsx new file mode 100644 index 00000000..6359861f --- /dev/null +++ b/electron/renderer/components/grid/grid.tsx @@ -0,0 +1,140 @@ +import { + EuiPanel, + EuiText, + useEuiOverflowScroll, + useEuiTheme, +} from '@elastic/eui'; +import { cx } from '@emotion/css'; +import { css } from '@emotion/react'; +import Head from 'next/head'; +import { + CSSProperties, + MouseEvent, + ReactNode, + TouchEvent, + forwardRef, + useMemo, + useRef, + useState, +} from 'react'; +import { Responsive, WidthProvider } from 'react-grid-layout'; +import { useLogger } from '../logger'; + +const Grid: React.FC = (): JSX.Element => { + const { logger } = useLogger('component:grid'); + + logger.info('rendering'); + + const { euiTheme } = useEuiTheme(); + + const gridLayoutStyles = css` + .react-grid-layout { + background: ${euiTheme.colors.lightestShade}; + } + .react-grid-item { + padding: ${euiTheme.size.xs}; + } + .react-grid-item.react-grid-placeholder { + background: ${euiTheme.colors.warning}; + } + `; + + const gridItemTextStyles = css` + font-family: ${euiTheme.font.familyCode}; + white-space: pre-wrap; + ${useEuiOverflowScroll('y', true)} + `; + + /** + * Using hooks to save the layout state on change will cause the layouts to + * re-render because the layout component's value keeps changing every render. + * To avoid this we memoize the layout component using the `useMemo` hook. + * https://github.com/react-grid-layout/react-grid-layout?tab=readme-ov-file#react-hooks-performance + */ + const ResponsiveGridLayout = useMemo(() => { + return WidthProvider(Responsive); + }, []); + + /** + * Define the initial layout state. + */ + const [layout, setLayout] = useState([ + { i: 'a', x: 0, y: 0, w: 3, h: 2 }, + { i: 'b', x: 3, y: 0, w: 3, h: 2 }, + { i: 'c', x: 6, y: 0, w: 3, h: 2 }, + ]); + + /** + * To improve performance, we memoize the children prop so that it doesn't + * change between rerenders. And if the children don't change then the + * components within the layout won't rerender either. + * https://github.com/react-grid-layout/react-grid-layout?tab=readme-ov-file#performance + */ + const children = useMemo(() => { + return layout.map((item) => { + /** + * How to use custom components a react-grid-layout children. + * https://github.com/react-grid-layout/react-grid-layout/tree/master?tab=readme-ov-file#custom-child-components-and-draggable-handles + * https://stackoverflow.com/questions/67053157/react-grid-layout-error-draggablecore-not-mounted-on-dragstart + */ + + interface ReactGridLayoutItemProps { + style?: CSSProperties; + className?: string; + onMouseDown?: (e: MouseEvent) => void; + onMouseUp?: (e: MouseEvent) => void; + onTouchEnd?: (e: TouchEvent) => void; + children?: ReactNode; + } + + const MyGridItem = forwardRef( + (props, ref) => { + const { style, className, children, ...otherProps } = props; + + return ( + + {item.i} + {children} + + ); + } + ); + + MyGridItem.displayName = 'MyGridItem'; + + return ; + }); + }, [layout.length]); + + return ( + <> + + + + + + {children} + + + ); +}; + +export { Grid }; diff --git a/electron/renderer/components/grid/index.ts b/electron/renderer/components/grid/index.ts new file mode 100644 index 00000000..d24d1bdc --- /dev/null +++ b/electron/renderer/components/grid/index.ts @@ -0,0 +1 @@ +export * from './grid'; diff --git a/electron/renderer/components/grid/styles.ts b/electron/renderer/components/grid/styles.ts new file mode 100644 index 00000000..17e27d2f --- /dev/null +++ b/electron/renderer/components/grid/styles.ts @@ -0,0 +1,7 @@ +import { css } from '@emotion/react'; + +export const styles = css` + #__next, + .example { + } +`; diff --git a/electron/renderer/pages/dnd.tsx b/electron/renderer/pages/dnd.tsx index 01d134ef..cffa5119 100644 --- a/electron/renderer/pages/dnd.tsx +++ b/electron/renderer/pages/dnd.tsx @@ -1,6 +1,5 @@ -import Head from 'next/head'; -import { useMemo, useState } from 'react'; -import { Responsive, WidthProvider } from 'react-grid-layout'; +import Link from 'next/link'; +import { Grid } from '../components/grid/grid'; import { useLogger } from '../components/logger'; const DragDropPage: React.FC = (): JSX.Element => { @@ -8,144 +7,12 @@ const DragDropPage: React.FC = (): JSX.Element => { logger.info('rendering'); - // https://github.com/react-grid-layout/react-grid-layout?tab=readme-ov-file#react-hooks-performance - const ResponsiveGridLayout = useMemo(() => { - return WidthProvider(Responsive); - }, []); - - const [layout, setLayout] = useState([ - { i: 'a', x: 0, y: 0, w: 1, h: 2, static: true }, - { i: 'b', x: 1, y: 0, w: 3, h: 2, minW: 2, maxW: 4 }, - { i: 'c', x: 4, y: 0, w: 1, h: 2 }, - ]); - - // https://github.com/react-grid-layout/react-grid-layout?tab=readme-ov-file#performance - const children = useMemo(() => { - logger.debug('generating children'); - return layout.map((item) =>
{item.i}
); - }, [layout.length]); - return ( <> - - - - - -
Hello World
- - {children} - +

+ Go home +

+ ); }; diff --git a/package.json b/package.json index f719bd7a..75f7f94e 100644 --- a/package.json +++ b/package.json @@ -281,6 +281,14 @@ "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" } + ], + "react/no-unknown-property": [ + "error", + { + "ignore": [ + "css" + ] + } ] } }