Skip to content

Commit

Permalink
Merge branch 'main' into refact/toolbar
Browse files Browse the repository at this point in the history
  • Loading branch information
KirillSerg committed May 24, 2024
2 parents 0fcf206 + 27a25c5 commit 3a2dd3b
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 22 deletions.
26 changes: 20 additions & 6 deletions UItests/test.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ test("Create rect", async ({ page }) => {
test("Create triangle(polygon)", async ({ page }) => {
await page.goto('http://localhost:5173/');
const toolbarTriangle = page.locator('header > button > svg > polygon')
await page.pause()
await toolbarTriangle.click()
await page.mouse.move(300, 300);
await page.mouse.down();
Expand All @@ -53,12 +52,27 @@ test("Create triangle(polygon)", async ({ page }) => {
await page.mouse.down();
await page.mouse.move(700, 400);
await page.mouse.up();
// drag&drop variant 2 -- not work becase of header height
// await page.dragAndDrop('id=canvas', 'id=canvas', {
// sourcePosition: { x: 700, y: 400 },
// targetPosition: { x: 100, y: 500 },
// });
// delete element
await page.press("id=canvas", "Delete")
await checkNumberOfElementsInLocalStorage(page, 0)
})

test("Create text", async ({ page }) => {
await page.goto('http://localhost:5173/');
const toolbarText = page.locator('header > button > svg > text')
await toolbarText.click()
await page.mouse.move(300, 300);
await page.mouse.down();
await page.mouse.move(500, 500);
await page.mouse.up();
await checkElementInLocalStorage(page, "foreignObject")
// tap the text
await page.locator("foreignObject > textarea").fill("I just type some text")
// drag&drop variant 1
await page.mouse.move(400, 400);
await page.mouse.down();
await page.mouse.move(700, 400);
await page.mouse.up();
// delete element
await page.press("id=canvas", "Delete")
await checkNumberOfElementsInLocalStorage(page, 0)
Expand Down
9 changes: 6 additions & 3 deletions src/components/SingleElement.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ElemenEvent, Element } from '../types/CommonTypes';
import { transformCoordinates } from '../assets/utilities';
import Textarea from './Textarea';
import { useAtom } from 'jotai';
import { onDragStartAtom, onMouseUpAtom } from '../store/store';
import { ElemenEvent, Element } from '../types/CommonTypes';
import { transformCoordinates } from '../assets/utilities';

interface Props {
element: Element;
Expand Down Expand Up @@ -35,7 +36,9 @@ const SingleElement = ({ element, svgContainerRef }: Props) => {
style={{ cursor: 'pointer' }}
onMouseDown={(e) => handleMouseDown(e)}
onMouseUp={onMouseUp}
/>
>
{element.type === 'foreignObject' && <Textarea element={element} />}
</element.type>
)}
</>
);
Expand Down
20 changes: 20 additions & 0 deletions src/components/TextIconBtn.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { ElementsTypeName } from '../types/CommonTypes';

interface Props {
className: string;
handlerClick: (typeName: ElementsTypeName) => void;
}

const TextIconBtn = ({ className, handlerClick }: Props) => {
return (
<button className={`${className}`} onClick={() => handlerClick('text')}>
<svg viewBox="0 0 24 24" height="100%" xmlns="http://www.w3.org/2000/svg">
<text y="80%" x="20%" width={24} height={24} strokeWidth="2">
Tt
</text>
</svg>
</button>
);
};

export default TextIconBtn;
50 changes: 50 additions & 0 deletions src/components/Textarea.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useRef } from 'react';
import { useAtom, useAtomValue } from 'jotai';
import { isDrawingAtom, updateElementsAtom } from '../store/store';
import { Element } from '../types/CommonTypes';

type Props = {
element: Element;
};

const Textarea = ({ element }: Props) => {
const [, updateElements] = useAtom(updateElementsAtom);
const isDrawing = useAtomValue(isDrawingAtom);

const textareaRef = useRef<HTMLTextAreaElement>(null);

const onChangeTexstarea = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
if (textareaRef.current) {
textareaRef.current.style.height = 'auto';
textareaRef.current.style.height =
textareaRef.current.scrollHeight + 'px';
updateElements({
...element,
height: textareaRef.current.scrollHeight,
textvalue: event.target.value,
});
}
};

return (
<textarea
ref={textareaRef}
rows={1}
autoFocus={isDrawing}
style={{
width: '100%',
height: '100%',
resize: 'none',
border: 'none',
scrollbarWidth: 'none',
backgroundColor: element.fill,
}}
placeholder="text"
value={element.textvalue}
onChange={(event) => onChangeTexstarea(event)}
name="text-element"
/>
);
};

export default Textarea;
7 changes: 7 additions & 0 deletions src/components/Toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Element,
ElementsTypeName,
} from '../types/CommonTypes';
import TextIconBtn from './TextIconBtn';

const Toolbar = () => {
const [initialElement, setInitialElement] = useAtom(initialElementAtom);
Expand Down Expand Up @@ -54,10 +55,16 @@ const Toolbar = () => {
className={`${initialElement.type_name === 'line' ? 'bg-orange-500' : 'bg-inherit'} h-8 w-8 p-[6px]`}
handlerClick={handlerSelectElement}
/>

<LineArrowIconBtn
className={`${initialElement.type_name === 'arrow_line' ? 'bg-orange-500' : 'bg-inherit'} h-8 w-8 p-[6px]`}
handlerClick={handlerSelectElement}
/>

<TextIconBtn
className={`${initialElement.type_name === 'text' ? 'bg-orange-500' : 'bg-inherit'} h-8 w-8 p-[6px]`}
handlerClick={handlerSelectElement}
/>
</header>
);
};
Expand Down
33 changes: 23 additions & 10 deletions src/store/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ const initialElement: Element = {
id: "",
x: 0,
y: 0,
width: 1,
height: 1,
width: 100,
height: 50,
cx: 0,
cy: 0,
rx: 0.5,
Expand All @@ -20,10 +20,12 @@ const initialElement: Element = {
x2: 0,
y2: 0,
points: "",
textvalue: "",
markerEnd: "",
stroke: 'black',
strokeWidth: 4,
fill: 'none',
fill: 'transparent',
fontSize: "28px",
}

export const initialElementAtom = atom<Element>(initialElement)
Expand All @@ -42,7 +44,11 @@ export const updateElementsAtom = atom(
el.id === updatedElement.id ? updatedElement : el,
))
const isSelected = get(selectedElementAtom)?.id === updatedElement.id
if (isSelected) set(selectedElementAtom, updatedElement)
// if changes from inspector
if (isSelected
&& !get(isDraggingAtom)
&& !get(isDrawingAtom)
) set(selectedElementAtom, updatedElement)
}
)

Expand All @@ -58,7 +64,7 @@ export const deleteElementsAtom = atom(
export const onMouseDownAtom = atom(
null,
(get, set, update: Coordinates) => {
console.log("onMouseDownAtom")
// console.log("onMouseDownAtom")
if (!get(isDraggingAtom) && !get(isDrawingAtom)) {
set(selectedElementAtom, null)
}
Expand All @@ -81,6 +87,7 @@ export const onMouseDownAtom = atom(
x2: update.x,
y2: update.y,
// points: `${}`,
// fontSize: ,
}
set(elementsAtom, (prev) => [...prev, newEl])
set(selectedElementAtom, newEl)
Expand All @@ -91,7 +98,7 @@ export const onMouseDownAtom = atom(
export const onDragStartAtom = atom(
null,
(get, set, update: { element: Element, position: Coordinates }) => {
console.log("onDragStartAtom")
// console.log("onDragStartAtom")
if (!get(isDrawingAtom)) {
set(selectedElementAtom, update.element)
set(isDraggingAtom, true)
Expand All @@ -102,7 +109,7 @@ export const onDragStartAtom = atom(
export const onMouseMoveAtom = atom(
null,
(get, set, update: Coordinates) => {
console.log("onMouseMoveAtom")
// console.log("onMouseMoveAtom")
const selectingArea = get(selectingAreaAtom)
const selectedElement = get(selectedElementAtom)
if (selectingArea) {
Expand Down Expand Up @@ -141,6 +148,7 @@ export const onMouseMoveAtom = atom(
points: newPoints,
})
}

// if drawwing
if (get(isDrawingAtom) && selectedElement) {
const { newX, newY, newWidth, newHeight, newRX, newRY } = useUpdateXYAndDistance(
Expand All @@ -162,7 +170,8 @@ export const onMouseMoveAtom = atom(
x2: update.x,
y2: update.y,
// left-bottom, top, right-bottom
points: `${selectedElement.x},${update.y} ${selectedElement.x + ((update.x - selectedElement.x) / 2)},${selectedElement.y} ${update.x},${update.y}`
points: `${selectedElement.x},${update.y} ${selectedElement.x + ((update.x - selectedElement.x) / 2)},${selectedElement.y} ${update.x},${update.y}`,
fontSize: (newHeight / 1.5).toString(), // i don't know why but 1.5 is working good
})
}
set(selectingAreaAtom, { ...selectingArea, endX: update.x, endY: update.y })
Expand All @@ -172,8 +181,12 @@ export const onMouseMoveAtom = atom(

export const onMouseUpAtom = atom(
null,
(_get, set) => {
console.log("onMouseUpAtom")
(get, set) => {
// console.log("onMouseUpAtom")
const selectedElement = get(selectedElementAtom)
if (selectedElement) {
set(selectedElementAtom, get(elementsAtom).find(el => el.id === selectedElement.id) || selectedElement)
}
set(isDraggingAtom, false)
set(selectingAreaAtom, null)
set(initialElementAtom, initialElement)
Expand Down
10 changes: 7 additions & 3 deletions src/types/CommonTypes.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export interface Element {
id: string;
type: "free" | "rect" | "ellipse" | "line" | "polygon";
type_name: ElementsTypeName;
type: "free" | "rect" | "ellipse" | "line" | "polygon" | "foreignObject";
x: number;
y: number;
width: number;
Expand All @@ -15,10 +15,12 @@ export interface Element {
x2: number;
y2: number;
points: string //"x,y x,y x,y ..."
textvalue: string;
markerEnd: string;
stroke: string;
strokeWidth: number;
fill: string;
fontSize: string;
}

export interface Area {
Expand All @@ -39,7 +41,8 @@ export type ElemenEvent =
| React.MouseEvent<SVGLineElement, MouseEvent>
| React.MouseEvent<SVGPolygonElement, MouseEvent>
| React.MouseEvent<SVGSVGElement, MouseEvent>

| React.MouseEvent<SVGTextElement, MouseEvent>
| React.MouseEvent<SVGForeignObjectElement, MouseEvent>

export const ELEMENT_TYPE_VARIANTS = {
free: 'free',
Expand All @@ -48,6 +51,7 @@ export const ELEMENT_TYPE_VARIANTS = {
polygon: 'polygon',
line: 'line',
arrow_line: 'line',
text: "foreignObject",
};

export type ElementsTypeName = keyof typeof ELEMENT_TYPE_VARIANTS;
export type ElementsTypeName = keyof typeof ELEMENT_TYPE_VARIANTS;

0 comments on commit 3a2dd3b

Please sign in to comment.