diff options
Diffstat (limited to 'src/client/views/nodes/generativeFill')
6 files changed, 106 insertions, 105 deletions
diff --git a/src/client/views/nodes/generativeFill/GenerativeFill.tsx b/src/client/views/nodes/generativeFill/GenerativeFill.tsx index a485ea4c3..91b0ebd5c 100644 --- a/src/client/views/nodes/generativeFill/GenerativeFill.tsx +++ b/src/client/views/nodes/generativeFill/GenerativeFill.tsx @@ -1,33 +1,39 @@ +/* eslint-disable jsx-a11y/label-has-associated-control */ +/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */ +/* eslint-disable jsx-a11y/img-redundant-alt */ +/* eslint-disable jsx-a11y/click-events-have-key-events */ +/* eslint-disable react/function-component-definition */ import { Checkbox, FormControlLabel, Slider, TextField } from '@mui/material'; import { IconButton } from 'browndash-components'; +import * as React from 'react'; import { useEffect, useRef, useState } from 'react'; import { CgClose } from 'react-icons/cg'; import { IoMdRedo, IoMdUndo } from 'react-icons/io'; +import { ClientUtils } from '../../../../ClientUtils'; import { Doc, DocListCast } from '../../../../fields/Doc'; import { List } from '../../../../fields/List'; import { NumCast } from '../../../../fields/Types'; -import { Utils } from '../../../../Utils'; -import { Docs, DocUtils } from '../../../documents/Documents'; import { Networking } from '../../../Network'; -import { DocumentManager } from '../../../util/DocumentManager'; +import { DocUtils } from '../../../documents/DocUtils'; +import { Docs } from '../../../documents/Documents'; import { CollectionDockingView } from '../../collections/CollectionDockingView'; import { CollectionFreeFormView } from '../../collections/collectionFreeForm'; -import { OpenWhereMod } from '../DocumentView'; -import { ImageBox, ImageEditorData } from '../ImageBox'; +import { ImageEditorData } from '../ImageBox'; +import { OpenWhereMod } from '../OpenWhere'; import './GenerativeFill.scss'; import Buttons from './GenerativeFillButtons'; import { BrushHandler } from './generativeFillUtils/BrushHandler'; -import { activeColor, canvasSize, eraserColor, freeformRenderSize, newCollectionSize, offsetDistanceY, offsetX } from './generativeFillUtils/generativeFillConstants'; -import { CursorData, ImageDimensions, Point } from './generativeFillUtils/generativeFillInterfaces'; import { APISuccess, ImageUtility } from './generativeFillUtils/ImageHandler'; import { PointerHandler } from './generativeFillUtils/PointerHandler'; -import * as React from 'react'; +import { activeColor, canvasSize, eraserColor, freeformRenderSize, newCollectionSize, offsetDistanceY, offsetX } from './generativeFillUtils/generativeFillConstants'; +import { CursorData, ImageDimensions, Point } from './generativeFillUtils/generativeFillInterfaces'; +import { DocumentView } from '../DocumentView'; -enum BrushStyle { - ADD, - SUBTRACT, - MARQUEE, -} +// enum BrushStyle { +// ADD, +// SUBTRACT, +// MARQUEE, +// } interface GenerativeFillProps { imageEditorOpen: boolean; @@ -52,7 +58,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD // format: array of [image source, corresponding image Doc] const [edits, setEdits] = useState<(string | Doc)[][]>([]); const [edited, setEdited] = useState(false); - const [brushStyle, setBrushStyle] = useState<BrushStyle>(BrushStyle.ADD); + // const [brushStyle] = useState<BrushStyle>(BrushStyle.ADD); const [input, setInput] = useState(''); const [loading, setLoading] = useState(false); const [canvasDims, setCanvasDims] = useState<ImageDimensions>({ @@ -98,8 +104,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD if (!ctx || !currImg.current || !canvasRef.current) return; const target = redoStack.current[redoStack.current.length - 1]; - if (!target) { - } else { + if (target) { undoStack.current = [...undoStack.current, canvasRef.current?.toDataURL()]; const img = new Image(); img.src = target; @@ -131,11 +136,11 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD setIsBrushing(true); const { x, y } = PointerHandler.getPointRelativeToElement(canvas, e, canvasScale); - BrushHandler.brushCircleOverlay(x, y, cursorData.width / 2 / canvasScale, ctx, eraserColor, brushStyle === BrushStyle.SUBTRACT); + BrushHandler.brushCircleOverlay(x, y, cursorData.width / 2 / canvasScale, ctx, eraserColor /* , brushStyle === BrushStyle.SUBTRACT */); }; // stop brushing, push to undo stack - const handlePointerUp = (e: React.PointerEvent) => { + const handlePointerUp = () => { const ctx = ImageUtility.getCanvasContext(canvasBackgroundRef); if (!ctx) return; if (!isBrushing) return; @@ -144,11 +149,11 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD // handles brushing on pointer movement useEffect(() => { - if (!isBrushing) return; + if (!isBrushing) return undefined; const canvas = canvasRef.current; - if (!canvas) return; + if (!canvas) return undefined; const ctx = ImageUtility.getCanvasContext(canvasRef); - if (!ctx) return; + if (!ctx) return undefined; const handlePointerMove = (e: PointerEvent) => { const currPoint = PointerHandler.getPointRelativeToElement(canvas, e, canvasScale); @@ -156,7 +161,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD x: currPoint.x - e.movementX / canvasScale, y: currPoint.y - e.movementY / canvasScale, }; - BrushHandler.createBrushPathOverlay(lastPoint, currPoint, cursorData.width / 2 / canvasScale, ctx, eraserColor, brushStyle === BrushStyle.SUBTRACT); + BrushHandler.createBrushPathOverlay(lastPoint, currPoint, cursorData.width / 2 / canvasScale, ctx, eraserColor /* , brushStyle === BrushStyle.SUBTRACT */); }; drawingAreaRef.current?.addEventListener('pointermove', handlePointerMove); @@ -290,12 +295,13 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD _height: newCollectionSize, title: 'Image edit collection', }); - DocUtils.MakeLink(imageRootDoc, newCollectionRef.current, { link_relationship: 'Image Edit Version History', link_displayLine: false }); + DocUtils.MakeLink(imageRootDoc, newCollectionRef.current, { link_relationship: 'Image Edit Version History' }); // opening new tab CollectionDockingView.AddSplit(newCollectionRef.current, OpenWhereMod.right); // add the doc to the main freeform + // eslint-disable-next-line no-use-before-define await createNewImgDoc(originalImg.current, true); } } else { @@ -309,12 +315,14 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD const imgUrls = await Promise.all(urls.map(url => ImageUtility.convertImgToCanvasUrl(url, canvasDims.width, canvasDims.height))); const imgRes = await Promise.all( imgUrls.map(async url => { + // eslint-disable-next-line no-use-before-define const saveRes = await onSave(url); return [url, saveRes as Doc]; }) ); setEdits(imgRes); const image = new Image(); + // eslint-disable-next-line prefer-destructuring image.src = imgUrls[0]; ImageUtility.drawImgToCanvas(image, canvasRef, canvasDims.width, canvasDims.height); currImg.current = image; @@ -332,7 +340,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD const startY = NumCast(parentDoc.current.y); const children = DocListCast(parentDoc.current.gen_fill_children); const len = children.length; - let initialYPositions: number[] = []; + const initialYPositions: number[] = []; for (let i = 0; i < len; i++) { initialYPositions.push(startY + i * offsetDistanceY); } @@ -347,10 +355,10 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD // creates a new image document and returns its reference const createNewImgDoc = async (img: HTMLImageElement, firstDoc: boolean): Promise<Doc | undefined> => { - if (!imageRootDoc) return; - const src = img.src; + if (!imageRootDoc) return undefined; + const { src } = img; const [result] = await Networking.PostToServer('/uploadRemoteImage', { sources: [src] }); - const source = Utils.prepend(result.accessPaths.agnostic.client); + const source = ClientUtils.prepend(result.accessPaths.agnostic.client); if (firstDoc) { const x = 0; @@ -370,51 +378,51 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD } parentDoc.current = newImg; return newImg; - } else { - if (!parentDoc.current) return; - const x = NumCast(parentDoc.current.x) + freeformRenderSize + offsetX; - const initialY = 0; - - const newImg = Docs.Create.ImageDocument(source, { - x: x, - y: initialY, - _height: freeformRenderSize, - _width: freeformRenderSize, - data_nativeWidth: result.nativeWidth, - data_nativeHeight: result.nativeHeight, - }); + } + if (!parentDoc.current) return undefined; + const x = NumCast(parentDoc.current.x) + freeformRenderSize + offsetX; + const initialY = 0; + + const newImg = Docs.Create.ImageDocument(source, { + x: x, + y: initialY, + _height: freeformRenderSize, + _width: freeformRenderSize, + data_nativeWidth: result.nativeWidth, + data_nativeHeight: result.nativeHeight, + }); - const parentList = DocListCast(parentDoc.current.gen_fill_children); - if (parentList.length > 0) { - parentList.push(newImg); - parentDoc.current.gen_fill_children = new List<Doc>(parentList); - } else { - parentDoc.current.gen_fill_children = new List<Doc>([newImg]); - } + const parentList = DocListCast(parentDoc.current.gen_fill_children); + if (parentList.length > 0) { + parentList.push(newImg); + parentDoc.current.gen_fill_children = new List<Doc>(parentList); + } else { + parentDoc.current.gen_fill_children = new List<Doc>([newImg]); + } - DocUtils.MakeLink(parentDoc.current, newImg, { link_relationship: `Image edit; Prompt: ${input}`, link_displayLine: true }); - adjustImgPositions(); + DocUtils.MakeLink(parentDoc.current, newImg, { link_relationship: `Image edit; Prompt: ${input}` }); + adjustImgPositions(); - if (isNewCollection && newCollectionRef.current) { - Doc.AddDocToList(newCollectionRef.current, undefined, newImg); - } else { - addDoc?.(newImg); - } - return newImg; + if (isNewCollection && newCollectionRef.current) { + Doc.AddDocToList(newCollectionRef.current, undefined, newImg); + } else { + addDoc?.(newImg); } + return newImg; }; // Saves an image to the collection const onSave = async (src: string) => { const img = new Image(); img.src = src; - if (!currImg.current || !originalImg.current || !imageRootDoc) return; + if (!currImg.current || !originalImg.current || !imageRootDoc) return undefined; try { const res = await createNewImgDoc(img, false); return res; } catch (err) { console.log(err); } + return undefined; }; // Closes the editor view @@ -422,7 +430,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD ImageEditorData.Open = false; ImageEditorData.Source = ''; if (newCollectionRef.current) { - DocumentManager.Instance.AddViewRenderedCb(newCollectionRef.current, dv => (dv.ComponentView as CollectionFreeFormView)?.fitContentOnce()); + DocumentView.addViewRenderedCb(newCollectionRef.current, dv => (dv.ComponentView as CollectionFreeFormView)?.fitContentOnce()); } setEdits([]); }; @@ -443,12 +451,12 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD }} /> } - label={'Create New Collection'} + label="Create New Collection" labelPlacement="end" sx={{ whiteSpace: 'nowrap' }} /> <Buttons getEdit={getEdit} loading={loading} onReset={handleReset} /> - <IconButton color={activeColor} tooltip="close" icon={<CgClose size={'16px'} />} onClick={handleViewClose} /> + <IconButton color={activeColor} tooltip="close" icon={<CgClose size="16px" />} onClick={handleViewClose} /> </div> </div> {/* Main canvas for editing */} @@ -469,7 +477,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD width: cursorData.width, height: cursorData.width, }}> - <div className="innerPointer"></div> + <div className="innerPointer" /> </div> {/* Icons */} <div className="iconContainer"> @@ -519,11 +527,13 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD /> </div> </div> - {/* Edits thumbnails*/} + {/* Edits thumbnails */} <div className="editsBox"> {edits.map((edit, i) => ( <img + // eslint-disable-next-line react/no-array-index-key key={i} + alt="image edits" width={75} src={edit[0] as string} style={{ cursor: 'pointer' }} @@ -552,6 +562,7 @@ const GenerativeFill = ({ imageEditorOpen, imageEditorSource, imageRootDoc, addD Original </label> <img + alt="image stuff" width={75} src={originalImg.current?.src} style={{ cursor: 'pointer' }} diff --git a/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx b/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx index 185ba2280..d1f68ee0e 100644 --- a/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx +++ b/src/client/views/nodes/generativeFill/GenerativeFillButtons.tsx @@ -1,9 +1,9 @@ import './GenerativeFillButtons.scss'; import * as React from 'react'; import ReactLoading from 'react-loading'; -import { activeColor } from './generativeFillUtils/generativeFillConstants'; import { Button, IconButton, Type } from 'browndash-components'; import { AiOutlineInfo } from 'react-icons/ai'; +import { activeColor } from './generativeFillUtils/generativeFillConstants'; interface ButtonContainerProps { getEdit: () => Promise<void>; @@ -11,7 +11,7 @@ interface ButtonContainerProps { onReset: () => void; } -const Buttons = ({ loading, getEdit, onReset }: ButtonContainerProps) => { +function Buttons({ loading, getEdit, onReset }: ButtonContainerProps) { return ( <div className="generativeFillBtnContainer"> <Button text="RESET" type={Type.PRIM} color={activeColor} onClick={onReset} /> @@ -20,7 +20,7 @@ const Buttons = ({ loading, getEdit, onReset }: ButtonContainerProps) => { text="GET EDITS" type={Type.TERT} color={activeColor} - icon={<ReactLoading type="spin" color={'#ffffff'} width={20} height={20} />} + icon={<ReactLoading type="spin" color="#ffffff" width={20} height={20} />} iconPlacement="right" onClick={() => { if (!loading) getEdit(); @@ -36,9 +36,9 @@ const Buttons = ({ loading, getEdit, onReset }: ButtonContainerProps) => { }} /> )} - <IconButton type={Type.SEC} color={activeColor} tooltip="Open Documentation" icon={<AiOutlineInfo size={'16px'} />} onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/features/generativeai/#editing', '_blank')} /> + <IconButton type={Type.SEC} color={activeColor} tooltip="Open Documentation" icon={<AiOutlineInfo size="16px" />} onClick={() => window.open('https://brown-dash.github.io/Dash-Documentation/features/generativeai/#editing', '_blank')} /> </div> ); -}; +} export default Buttons; diff --git a/src/client/views/nodes/generativeFill/generativeFillUtils/BrushHandler.ts b/src/client/views/nodes/generativeFill/generativeFillUtils/BrushHandler.ts index f4ec70fbc..16d529d93 100644 --- a/src/client/views/nodes/generativeFill/generativeFillUtils/BrushHandler.ts +++ b/src/client/views/nodes/generativeFill/generativeFillUtils/BrushHandler.ts @@ -3,7 +3,7 @@ import { eraserColor } from './generativeFillConstants'; import { Point } from './generativeFillInterfaces'; export class BrushHandler { - static brushCircleOverlay = (x: number, y: number, brushRadius: number, ctx: CanvasRenderingContext2D, fillColor: string, erase: boolean) => { + static brushCircleOverlay = (x: number, y: number, brushRadius: number, ctx: CanvasRenderingContext2D, fillColor: string /* , erase: boolean */) => { ctx.globalCompositeOperation = 'destination-out'; ctx.fillStyle = fillColor; ctx.shadowColor = eraserColor; @@ -14,12 +14,12 @@ export class BrushHandler { ctx.closePath(); }; - static createBrushPathOverlay = (startPoint: Point, endPoint: Point, brushRadius: number, ctx: CanvasRenderingContext2D, fillColor: string, erase: boolean) => { + static createBrushPathOverlay = (startPoint: Point, endPoint: Point, brushRadius: number, ctx: CanvasRenderingContext2D, fillColor: string /* , erase: boolean */) => { const dist = GenerativeFillMathHelpers.distanceBetween(startPoint, endPoint); for (let i = 0; i < dist; i += 5) { const s = i / dist; - BrushHandler.brushCircleOverlay(startPoint.x * (1 - s) + endPoint.x * s, startPoint.y * (1 - s) + endPoint.y * s, brushRadius, ctx, fillColor, erase); + BrushHandler.brushCircleOverlay(startPoint.x * (1 - s) + endPoint.x * s, startPoint.y * (1 - s) + endPoint.y * s, brushRadius, ctx, fillColor /* , erase */); } }; } diff --git a/src/client/views/nodes/generativeFill/generativeFillUtils/GenerativeFillMathHelpers.ts b/src/client/views/nodes/generativeFill/generativeFillUtils/GenerativeFillMathHelpers.ts index 97e03ff20..6da8c3da0 100644 --- a/src/client/views/nodes/generativeFill/generativeFillUtils/GenerativeFillMathHelpers.ts +++ b/src/client/views/nodes/generativeFill/generativeFillUtils/GenerativeFillMathHelpers.ts @@ -1,10 +1,6 @@ import { Point } from './generativeFillInterfaces'; export class GenerativeFillMathHelpers { - static distanceBetween = (p1: Point, p2: Point) => { - return Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p2.y - p1.y, 2)); - }; - static angleBetween = (p1: Point, p2: Point) => { - return Math.atan2(p2.x - p1.x, p2.y - p1.y); - }; + static distanceBetween = (p1: Point, p2: Point) => Math.sqrt((p2.x - p1.x) ** 2 + (p2.y - p1.y) ** 2); + static angleBetween = (p1: Point, p2: Point) => Math.atan2(p2.x - p1.x, p2.y - p1.y); } diff --git a/src/client/views/nodes/generativeFill/generativeFillUtils/ImageHandler.ts b/src/client/views/nodes/generativeFill/generativeFillUtils/ImageHandler.ts index 47a14135f..24dba1778 100644 --- a/src/client/views/nodes/generativeFill/generativeFillUtils/ImageHandler.ts +++ b/src/client/views/nodes/generativeFill/generativeFillUtils/ImageHandler.ts @@ -17,15 +17,14 @@ export class ImageUtility { * @param canvas Canvas to convert * @returns Blob of canvas */ - static canvasToBlob = (canvas: HTMLCanvasElement): Promise<Blob> => { - return new Promise(resolve => { + static canvasToBlob = (canvas: HTMLCanvasElement): Promise<Blob> => + new Promise(resolve => { canvas.toBlob(blob => { if (blob) { resolve(blob); } }, 'image/png'); }); - }; // given a square api image, get the cropped img static getCroppedImg = (img: HTMLImageElement, width: number, height: number): HTMLCanvasElement | undefined => { @@ -48,11 +47,12 @@ export class ImageUtility { } return canvas; } + return undefined; }; // converts an image to a canvas data url - static convertImgToCanvasUrl = async (imageSrc: string, width: number, height: number): Promise<string> => { - return new Promise<string>((resolve, reject) => { + static convertImgToCanvasUrl = async (imageSrc: string, width: number, height: number): Promise<string> => + new Promise<string>((resolve, reject) => { const img = new Image(); img.onload = () => { const canvas = this.getCroppedImg(img, width, height); @@ -66,7 +66,6 @@ export class ImageUtility { }; img.src = imageSrc; }); - }; // calls the openai api to get image edits static getEdit = async (imgBlob: Blob, maskBlob: Blob, prompt: string, n?: number): Promise<APISuccess | APIError> => { @@ -91,7 +90,7 @@ export class ImageUtility { console.log(data.data); return { status: 'success', - urls: (data.data as { b64_json: string }[]).map(data => `data:image/png;base64,${data.b64_json}`), + urls: (data.data as { b64_json: string }[]).map(urlData => `data:image/png;base64,${urlData.b64_json}`), }; } catch (err) { console.log(err); @@ -100,12 +99,10 @@ export class ImageUtility { }; // mock api call - static mockGetEdit = async (mockSrc: string): Promise<APISuccess | APIError> => { - return { - status: 'success', - urls: [mockSrc, mockSrc, mockSrc], - }; - }; + static mockGetEdit = async (mockSrc: string): Promise<APISuccess | APIError> => ({ + status: 'success', + urls: [mockSrc, mockSrc, mockSrc], + }); // Gets the canvas rendering context of a canvas static getCanvasContext = (canvasRef: RefObject<HTMLCanvasElement>): CanvasRenderingContext2D | null => { @@ -150,12 +147,12 @@ export class ImageUtility { // Draws the image to the current canvas static drawImgToCanvas = (img: HTMLImageElement, canvasRef: React.RefObject<HTMLCanvasElement>, width: number, height: number) => { - const drawImg = (img: HTMLImageElement) => { + const drawImg = (htmlImg: HTMLImageElement) => { const ctx = this.getCanvasContext(canvasRef); if (!ctx) return; ctx.globalCompositeOperation = 'source-over'; ctx.clearRect(0, 0, width, height); - ctx.drawImage(img, 0, 0, width, height); + ctx.drawImage(htmlImg, 0, 0, width, height); }; if (img.complete) { @@ -173,7 +170,7 @@ export class ImageUtility { canvas.width = canvasSize; canvas.height = canvasSize; const ctx = canvas.getContext('2d'); - if (!ctx) return; + if (!ctx) return undefined; ctx?.clearRect(0, 0, canvasSize, canvasSize); ctx.drawImage(paddedCanvas, 0, 0); @@ -195,7 +192,7 @@ export class ImageUtility { // Fills in the blank areas of the image with an image reflection (to fill in a square-shaped canvas) static drawHorizontalReflection = (ctx: CanvasRenderingContext2D, canvas: HTMLCanvasElement, xOffset: number) => { const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); - const data = imageData.data; + const { data } = imageData; for (let i = 0; i < canvas.height; i++) { for (let j = 0; j < xOffset; j++) { const targetIdx = 4 * (i * canvas.width + j); @@ -224,7 +221,7 @@ export class ImageUtility { // Fills in the blank areas of the image with an image reflection (to fill in a square-shaped canvas) static drawVerticalReflection = (ctx: CanvasRenderingContext2D, canvas: HTMLCanvasElement, yOffset: number) => { const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); - const data = imageData.data; + const { data } = imageData; for (let j = 0; j < canvas.width; j++) { for (let i = 0; i < yOffset; i++) { const targetIdx = 4 * (i * canvas.width + j); @@ -256,7 +253,7 @@ export class ImageUtility { canvas.width = canvasSize; canvas.height = canvasSize; const ctx = canvas.getContext('2d'); - if (!ctx) return; + if (!ctx) return undefined; // fix scaling const scale = Math.min(canvasSize / img.width, canvasSize / img.height); const width = Math.floor(img.width * scale); @@ -310,5 +307,6 @@ export class ImageUtility { } catch (err) { console.error(err); } + return undefined; }; } diff --git a/src/client/views/nodes/generativeFill/generativeFillUtils/PointerHandler.ts b/src/client/views/nodes/generativeFill/generativeFillUtils/PointerHandler.ts index 9e620ad11..260923a64 100644 --- a/src/client/views/nodes/generativeFill/generativeFillUtils/PointerHandler.ts +++ b/src/client/views/nodes/generativeFill/generativeFillUtils/PointerHandler.ts @@ -1,15 +1,11 @@ -import { Point } from "./generativeFillInterfaces"; +import { Point } from './generativeFillInterfaces'; export class PointerHandler { - static getPointRelativeToElement = ( - element: HTMLElement, - e: React.PointerEvent | PointerEvent, - scale: number - ): Point => { - const boundingBox = element.getBoundingClientRect(); - return { - x: (e.clientX - boundingBox.x) / scale, - y: (e.clientY - boundingBox.y) / scale, + static getPointRelativeToElement = (element: HTMLElement, e: React.PointerEvent | PointerEvent, scale: number): Point => { + const boundingBox = element.getBoundingClientRect(); + return { + x: (e.clientX - boundingBox.x) / scale, + y: (e.clientY - boundingBox.y) / scale, + }; }; - }; } |