From 7bfbf742d7c81088e07550f08b5a9b54c20dddc3 Mon Sep 17 00:00:00 2001 From: Borja Gonzalez Date: Thu, 18 Mar 2021 19:41:08 +0100 Subject: [PATCH] Refactor using hooks --- src/DrawArea.tsx | 70 ---------------------- src/components/DrawArea.tsx | 54 +++++++++++++++++ src/components/Drawable.tsx | 36 +++++++++++ src/{ => components}/Drawed.tsx | 4 +- src/{ => contexts}/DrawContext.tsx | 4 +- src/hooks/useDrawArea.ts | 51 ++++++++++++++++ src/{Drawable.tsx => hooks/useDrawable.ts} | 55 ++++++----------- src/index.ts | 4 +- 8 files changed, 165 insertions(+), 113 deletions(-) delete mode 100644 src/DrawArea.tsx create mode 100644 src/components/DrawArea.tsx create mode 100644 src/components/Drawable.tsx rename src/{ => components}/Drawed.tsx (92%) rename src/{ => contexts}/DrawContext.tsx (64%) create mode 100644 src/hooks/useDrawArea.ts rename src/{Drawable.tsx => hooks/useDrawable.ts} (51%) diff --git a/src/DrawArea.tsx b/src/DrawArea.tsx deleted file mode 100644 index cccd7b7..0000000 --- a/src/DrawArea.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import React, { FC, useState } from 'react' -import * as PropTypes from 'prop-types' - -import Drawable from './Drawable' -import DrawContext from './DrawContext' -import Drawed from './Drawed' - -import { Line, Lines, Point } from './types' - -type Props = { - className?: string - color?: string - disabled?: boolean - hidden?: boolean - thickness?: number -} - -const DrawArea: FC = ({ - className = '', - color = '#000000', - disabled = false, - hidden = false, - thickness = 10, - children, -}) => { - const [lines, setLines] = useState([]) - const [newLine, setNewLine] = useState([]) - const allLines = newLine.length === 0 ? lines : [...lines, newLine] - - const reset = () => setLines([]) - const undo = () => setLines(lines.slice(0, -1)) - const finishLine = () => { - if (newLine.length > 1) setLines(allLines) - setNewLine([]) - } - const addPoint = (newPoint: Point) => setNewLine([...newLine, newPoint]) - - const content = hidden - ? null - : ( -
- - {disabled || } -
- ) - - if (!children) return content - - return ( - 0, - reset, - undo, - }}> - {children} - {content} - - ) -} - -DrawArea.propTypes = { - className: PropTypes.string, - color: PropTypes.string, - disabled: PropTypes.bool, - hidden: PropTypes.bool, - thickness: PropTypes.number, -} - -export default DrawArea diff --git a/src/components/DrawArea.tsx b/src/components/DrawArea.tsx new file mode 100644 index 0000000..70c2259 --- /dev/null +++ b/src/components/DrawArea.tsx @@ -0,0 +1,54 @@ +import React, { FC } from 'react' +import * as PropTypes from 'prop-types' + +import Drawable from 'components/Drawable' +import Drawed from 'components/Drawed' +import DrawContext from 'contexts/DrawContext' +import useDrawArea from 'hooks/useDrawArea' + +type Props = { + className?: string + color?: string + disabled?: boolean + hidden?: boolean + thickness?: number +} + +const DrawArea: FC = ({ + className = '', + color = '#000000', + disabled = false, + hidden = false, + thickness = 10, + children, +}) => { + const { isDrawing, lines, addPoint, finishLine, reset, undo } = useDrawArea() + + const content = hidden + ? null + : ( +
+ + {disabled || } +
+ ) + + if (!children) return content + + return ( + + {children} + {content} + + ) +} + +DrawArea.propTypes = { + className: PropTypes.string, + color: PropTypes.string, + disabled: PropTypes.bool, + hidden: PropTypes.bool, + thickness: PropTypes.number, +} + +export default DrawArea diff --git a/src/components/Drawable.tsx b/src/components/Drawable.tsx new file mode 100644 index 0000000..5cbc4bb --- /dev/null +++ b/src/components/Drawable.tsx @@ -0,0 +1,36 @@ +import React, { CSSProperties, FC, useRef } from 'react' + +import useDrawable from 'hooks/useDrawable' + +import { Point } from 'types' + +type Props = { + addPoint: (point: Point) => void + finishLine: () => void +} + +const style: CSSProperties = { + position: 'absolute', + inset: 0, +} + +const Drawable: FC = ({ addPoint, finishLine }) => { + const ref = useRef(null) + const { startDrawing, keepDrawing, endDrawing } = useDrawable({ ref, addPoint, finishLine }) + + return ( +
+ ) +} + +export default Drawable diff --git a/src/Drawed.tsx b/src/components/Drawed.tsx similarity index 92% rename from src/Drawed.tsx rename to src/components/Drawed.tsx index af7ec09..cddfba4 100644 --- a/src/Drawed.tsx +++ b/src/components/Drawed.tsx @@ -1,6 +1,6 @@ import React, { CSSProperties, FC } from 'react' -import { Lines, Line } from './types' +import { Lines, Line } from 'types' type Props = { color: string @@ -26,7 +26,7 @@ const Drawed: FC = ({ color, lines, thickness }) => ( strokeLinecap="round" stroke={color} strokeWidth={thickness} - />, + /> )} ) diff --git a/src/DrawContext.tsx b/src/contexts/DrawContext.tsx similarity index 64% rename from src/DrawContext.tsx rename to src/contexts/DrawContext.tsx index 51fefa0..cb5ad14 100644 --- a/src/DrawContext.tsx +++ b/src/contexts/DrawContext.tsx @@ -1,6 +1,6 @@ import { createContext } from 'react' -import { Lines } from './types' +import { Lines } from 'types' type DrawContextType = { lines: Lines @@ -9,6 +9,6 @@ type DrawContextType = { undo: () => void } -const DrawContext = createContext(null) +const DrawContext = createContext(null) export default DrawContext diff --git a/src/hooks/useDrawArea.ts b/src/hooks/useDrawArea.ts new file mode 100644 index 0000000..1b94616 --- /dev/null +++ b/src/hooks/useDrawArea.ts @@ -0,0 +1,51 @@ +import { useCallback, useMemo, useState } from 'react' + +import { Line, Lines, Point } from 'types' + +type UseDrawAreaType = { + isDrawing: boolean + lines: Lines + addPoint: (point: Point) => void + finishLine: () => void + reset: () => void + undo: () => void +} + +const useDrawArea = (): UseDrawAreaType => { + const [lines, setLines] = useState([]) + const [newLine, setNewLine] = useState([]) + + const allLines: Lines = useMemo( + () => newLine.length === 0 ? lines : [...lines, newLine], + [lines, newLine] + ) + + const isDrawing: boolean = newLine.length > 0 + + const addPoint = useCallback( + (newPoint: Point) => setNewLine([...newLine, newPoint]), + [newLine] + ) + + const finishLine = useCallback( + () => { + if (newLine.length > 1) setLines(allLines) + setNewLine([]) + }, [allLines, newLine] + ) + + const reset = useCallback(() => setLines([]), []) + + const undo = useCallback(() => setLines(lines.slice(0, -1)), [lines]) + + return { + isDrawing, + lines: allLines, + addPoint, + finishLine, + reset, + undo, + } +} + +export default useDrawArea diff --git a/src/Drawable.tsx b/src/hooks/useDrawable.ts similarity index 51% rename from src/Drawable.tsx rename to src/hooks/useDrawable.ts index c639a36..f47c2f1 100644 --- a/src/Drawable.tsx +++ b/src/hooks/useDrawable.ts @@ -1,37 +1,30 @@ -import React, { - CSSProperties, - FC, - MouseEvent, - TouchEvent, - useRef, - useState, -} from 'react' +import { RefObject, MouseEvent, TouchEvent, useState } from 'react' -import { Point } from './types' +import { Point } from 'types' -type Props = { - addPoint: (point: Point) => void - finishLine: () => void +type UseDrawableType = { + startDrawing: (event: MouseEvent | TouchEvent) => void + keepDrawing: (event: MouseEvent | TouchEvent) => void + endDrawing: () => void } -const style: CSSProperties = { - position: 'absolute', - inset: 0, - overscrollBehavior: 'contain', +type UseDrawableProps = { + ref: RefObject + addPoint: (point: Point) => void + finishLine: () => void } const getCoordinates = (event: MouseEvent | TouchEvent): [number, number] | null => { - if (event.button === 0) { + if (event instanceof MouseEvent && event.button === 0) { return [event.clientX, event.clientY] - } else if (event.touches?.length) { + } else if (event instanceof TouchEvent && event.touches.length > 0) { return [event.touches[0].clientX, event.touches[0].clientY] } return null } -const Drawable: FC = ({ addPoint, finishLine }) => { +const useDrawable = ({ ref, addPoint, finishLine }: UseDrawableProps): UseDrawableType => { const [isDrawing, setIsDrawing] = useState(false) - const ref = useRef(null) const getPoint = (event: MouseEvent | TouchEvent): Point | null => { if (!ref.current) return null @@ -44,39 +37,27 @@ const Drawable: FC = ({ addPoint, finishLine }) => { } } - const onStartDrawing = (event: MouseEvent | TouchEvent) => { + const startDrawing = (event: MouseEvent | TouchEvent) => { const firstPoint = getPoint(event) if (!firstPoint) return addPoint(firstPoint) setIsDrawing(true) } - const onMoveDrawing = (event: MouseEvent | TouchEvent) => { + const keepDrawing = (event: MouseEvent | TouchEvent) => { if (!isDrawing) return const nextPoint = getPoint(event) if (!nextPoint) return addPoint(nextPoint) } - const onEndDrawing = () => { + const endDrawing = () => { if (!isDrawing) return finishLine() setIsDrawing(false) } - return ( -
- ) + return { startDrawing, keepDrawing, endDrawing } } -export default Drawable +export default useDrawable diff --git a/src/index.ts b/src/index.ts index 6cb2ebf..3c5f87b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import DrawArea from './DrawArea' -import DrawContext from './DrawContext' +import DrawArea from 'components/DrawArea' +import DrawContext from 'contexts/DrawContext' export { DrawArea, DrawContext }