From 5a56c3b35487c86f8ad99ac279e13485eeb58ae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Zed=C3=A9n=20Yver=C3=A5s?= Date: Wed, 17 Jul 2024 21:45:51 +0200 Subject: [PATCH] refactor: export `CanvasContextProvider` to follow established context pattern As noted [in the review]( https://github.com/drawdb-io/drawdb/pull/148#discussion_r1681584836 ), I disagree with this pattern. However, I will follow it to get these features added. --- src/components/EditorCanvas/Area.jsx | 6 +- src/components/EditorCanvas/Canvas.jsx | 320 +++++++++--------- src/components/Workspace.jsx | 5 +- .../{CanvasContext.js => CanvasContext.jsx} | 21 +- src/hooks/index.js | 1 + src/hooks/useCanvas.js | 6 + 6 files changed, 188 insertions(+), 171 deletions(-) rename src/context/{CanvasContext.js => CanvasContext.jsx} (85%) create mode 100644 src/hooks/useCanvas.js diff --git a/src/components/EditorCanvas/Area.jsx b/src/components/EditorCanvas/Area.jsx index 2fe98d3..a5aca7e 100644 --- a/src/components/EditorCanvas/Area.jsx +++ b/src/components/EditorCanvas/Area.jsx @@ -1,4 +1,4 @@ -import { useContext, useRef, useState } from "react"; +import { useRef, useState } from "react"; import { Button, Popover, Input } from "@douyinfe/semi-ui"; import { IconEdit, IconDeleteStroked } from "@douyinfe/semi-icons"; import { @@ -9,6 +9,7 @@ import { State, } from "../../data/constants"; import { + useCanvas, useLayout, useSettings, useUndoRedo, @@ -19,7 +20,6 @@ import { import ColorPalette from "../ColorPicker"; import { useTranslation } from "react-i18next"; import { useHover } from "usehooks-ts"; -import { CanvasContext } from "../../context/CanvasContext"; export default function Area({ data, @@ -33,7 +33,7 @@ export default function Area({ pointer: { spaces: { diagram: pointer }, }, - } = useContext(CanvasContext); + } = useCanvas(); const { layout } = useLayout(); const { settings } = useSettings(); const { setSaveState } = useSaveState(); diff --git a/src/components/EditorCanvas/Canvas.jsx b/src/components/EditorCanvas/Canvas.jsx index c15cc05..b0cee7d 100644 --- a/src/components/EditorCanvas/Canvas.jsx +++ b/src/components/EditorCanvas/Canvas.jsx @@ -11,6 +11,7 @@ import Area from "./Area"; import Relationship from "./Relationship"; import Note from "./Note"; import { + useCanvas, useSettings, useTransform, useDiagram, @@ -22,14 +23,13 @@ import { } from "../../hooks"; import { useTranslation } from "react-i18next"; import { diagram } from "../../data/heroDiagram"; -import { CanvasContext, useCanvasContextProviderValue } from "../../context/CanvasContext"; import { useEventListener } from "usehooks-ts"; export default function Canvas() { const { t } = useTranslation(); const canvasRef = useRef(null); - const canvasContextValue = useCanvasContextProviderValue(canvasRef); + const canvasContextValue = useCanvas(); const { canvas: { viewBox }, pointer, @@ -481,169 +481,167 @@ export default function Canvas() { const theme = localStorage.getItem("theme"); return ( - -
-
- {settings.showGrid && ( - - - - - - - +
+ {settings.showGrid && ( + + + - - )} - - {areas.map((a) => ( - - handlePointerDownOnElement(e, a.id, ObjectType.AREA) - } - setResize={setAreaResize} - setInitCoords={setInitCoords} - /> - ))} - {relationships.map((e, i) => ( - - ))} - {tables.map((table) => ( - - handlePointerDownOnElement(e, table.id, ObjectType.TABLE) - } - /> - ))} - {linking && ( - - )} - {notes.map((n) => ( - - handlePointerDownOnElement(e, n.id, ObjectType.NOTE) - } - /> - ))} + width="24" + height="24" + patternUnits="userSpaceOnUse" + patternContentUnits="userSpaceOnUse" + > + + + + - - {settings.showDebugCoordinates && ( -
-
- - - - - - - - - - - - - - - - - -
- {t("transform")} -
pan xpan yscale
{transform.pan.x.toFixed(2)}{transform.pan.y.toFixed(2)}{transform.zoom.toFixed(4)}
- - - - - - - - - - - - - - - - - - - - -
{t("viewbox")}
lefttopwidthheight
{viewBox.left.toFixed(2)}{viewBox.top.toFixed(2)}{viewBox.width.toFixed(2)}{viewBox.height.toFixed(2)}
- - - - - - - - - - - - - - - - - - - - - - - -
{t("cursor_coordinates")}
{t("coordinate_space")}xy
{t("coordinate_space_screen")}{pointer.spaces.screen.x.toFixed(2)}{pointer.spaces.screen.y.toFixed(2)}
{t("coordinate_space_diagram")}{pointer.spaces.diagram.x.toFixed(2)}{pointer.spaces.diagram.y.toFixed(2)}
-
)} + + {areas.map((a) => ( + + handlePointerDownOnElement(e, a.id, ObjectType.AREA) + } + setResize={setAreaResize} + setInitCoords={setInitCoords} + /> + ))} + {relationships.map((e, i) => ( + + ))} + {tables.map((table) => ( + + handlePointerDownOnElement(e, table.id, ObjectType.TABLE) + } + /> + ))} + {linking && ( + + )} + {notes.map((n) => ( + + handlePointerDownOnElement(e, n.id, ObjectType.NOTE) + } + /> + ))} + - + {settings.showDebugCoordinates && ( +
+
+ + + + + + + + + + + + + + + + + +
+ {t("transform")} +
pan xpan yscale
{transform.pan.x.toFixed(2)}{transform.pan.y.toFixed(2)}{transform.zoom.toFixed(4)}
+ + + + + + + + + + + + + + + + + + + + +
{t("viewbox")}
lefttopwidthheight
{viewBox.left.toFixed(2)}{viewBox.top.toFixed(2)}{viewBox.width.toFixed(2)}{viewBox.height.toFixed(2)}
+ + + + + + + + + + + + + + + + + + + + + + + +
{t("cursor_coordinates")}
{t("coordinate_space")}xy
{t("coordinate_space_screen")}{pointer.spaces.screen.x.toFixed(2)}{pointer.spaces.screen.y.toFixed(2)}
{t("coordinate_space_diagram")}{pointer.spaces.diagram.x.toFixed(2)}{pointer.spaces.diagram.y.toFixed(2)}
+
+ )} +
); } diff --git a/src/components/Workspace.jsx b/src/components/Workspace.jsx index 6546ec8..217d35a 100644 --- a/src/components/Workspace.jsx +++ b/src/components/Workspace.jsx @@ -1,6 +1,7 @@ import { useState, useEffect, useCallback } from "react"; import ControlPanel from "./EditorHeader/ControlPanel"; import Canvas from "./EditorCanvas/Canvas"; +import { CanvasContextProvider } from "../context/CanvasContext"; import SidePanel from "./EditorSidePanel/SidePanel"; import { DB, State } from "../data/constants"; import { db } from "../data/db"; @@ -362,7 +363,9 @@ export default function WorkSpace() { )}
- + + + {!(layout.sidebar || layout.toolbar || layout.header) && (
diff --git a/src/context/CanvasContext.js b/src/context/CanvasContext.jsx similarity index 85% rename from src/context/CanvasContext.js rename to src/context/CanvasContext.jsx index eaec420..7f1ba5d 100644 --- a/src/context/CanvasContext.js +++ b/src/context/CanvasContext.jsx @@ -1,5 +1,5 @@ import { useTransform } from "../hooks"; -import { createContext, useCallback, useMemo, useState } from "react"; +import { createContext, useCallback, useMemo, useRef, useState } from "react"; import { useEventListener, useResizeObserver } from "usehooks-ts"; export const CanvasContext = createContext({ @@ -34,10 +34,11 @@ export const CanvasContext = createContext({ }, }); -export function useCanvasContextProviderValue(canvasRef) { +export function CanvasContextProvider({ children, ...attrs }) { + const canvasWrapRef = useRef(null); const { transform } = useTransform(); const canvasSize = useResizeObserver({ - ref: canvasRef, + ref: canvasWrapRef, box: "content-box", }); const screenSize = useMemo( @@ -133,11 +134,11 @@ export function useCanvasContextProviderValue(canvasRef) { } // Important for touch screen devices! - useEventListener("pointerdown", detectPointerMovement, canvasRef); + useEventListener("pointerdown", detectPointerMovement, canvasWrapRef); - useEventListener("pointermove", detectPointerMovement, canvasRef); + useEventListener("pointermove", detectPointerMovement, canvasWrapRef); - return { + const contextValue = { canvas: { screenSize, viewBox, @@ -155,4 +156,12 @@ export function useCanvasContextProviderValue(canvasRef) { setStyle: setPointerStyle, }, }; + + return ( + +
+ {children} +
+
+ ) } diff --git a/src/hooks/index.js b/src/hooks/index.js index 2fd73ed..5dd76a9 100644 --- a/src/hooks/index.js +++ b/src/hooks/index.js @@ -1,4 +1,5 @@ export { default as useAreas } from "./useAreas"; +export { default as useCanvas } from "./useCanvas"; export { default as useLayout } from "./useLayout"; export { default as useNotes } from "./useNotes"; export { default as useSaveState } from "./useSaveState"; diff --git a/src/hooks/useCanvas.js b/src/hooks/useCanvas.js new file mode 100644 index 0000000..de4ffa0 --- /dev/null +++ b/src/hooks/useCanvas.js @@ -0,0 +1,6 @@ +import { useContext } from "react"; +import { CanvasContext } from "../context/CanvasContext"; + +export default function useCanvas() { + return useContext(CanvasContext); +}