Skip to content

Commit

Permalink
Merge pull request #74 from Lemoncode/feature/#73-zoom-support
Browse files Browse the repository at this point in the history
Feature/#73 zoom support
  • Loading branch information
brauliodiez authored Jul 29, 2024
2 parents d6c64e6 + 0bf215b commit 26988b0
Show file tree
Hide file tree
Showing 25 changed files with 89 additions and 81 deletions.
22 changes: 15 additions & 7 deletions src/common/components/front-components/input-shape.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,40 @@ import { ShapeSizeRestrictions } from '@/core/model';
import { forwardRef } from 'react';
import { ShapeProps } from './shape.model';
import { Group, Rect, Text } from 'react-konva';
import { fitSizeToShapeSizeRestrictions } from '@/common/utils/shapes/shape-restrictions';

export const getInputShapeSizeRestrictions = (): ShapeSizeRestrictions => ({
const inputShapeRestrictions: ShapeSizeRestrictions = {
minWidth: 60,
minHeight: 50,
maxWidth: -1,
maxHeight: 50,
defaultWidth: 190,
defaultHeight: 50,
});
};

export const getInputShapeSizeRestrictions = (): ShapeSizeRestrictions =>
inputShapeRestrictions;

export const InputShape = forwardRef<any, ShapeProps>(
({ x, y, width, height, id, onSelected, ...shapeProps }, ref) => {
const { width: restrictedWidth, height: restrictedHeight } =
fitSizeToShapeSizeRestrictions(inputShapeRestrictions, width, height);

return (
<Group
x={x}
y={y}
ref={ref}
width={width}
height={height}
width={restrictedWidth}
height={restrictedHeight}
{...shapeProps}
onClick={() => onSelected(id, 'input')}
>
<Rect
x={0}
y={0}
width={width + 10}
height={height}
width={restrictedWidth}
height={restrictedHeight}
cornerRadius={5}
stroke="black"
strokeWidth={2}
Expand All @@ -37,7 +44,8 @@ export const InputShape = forwardRef<any, ShapeProps>(
<Text
x={10}
y={20}
width={width}
width={width - 10}
height={height - 20}
text="Input text..."
fontFamily="Comic Sans MS, cursive"
fontSize={15}
Expand Down
23 changes: 23 additions & 0 deletions src/common/utils/shapes/shape-restrictions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ShapeSizeRestrictions, Size } from '@/core/model';

// TODO Add Unit tests, issue: #45
export const fitSizeToShapeSizeRestrictions = (
shapeSizeRestrictions: ShapeSizeRestrictions,
width: number,
height: number
): Size => {
const newWidth =
shapeSizeRestrictions.maxWidth !== -1
? Math.min(shapeSizeRestrictions.maxWidth, width)
: width;

const newHeight =
shapeSizeRestrictions.maxHeight !== -1
? Math.min(shapeSizeRestrictions.maxHeight, height)
: height;

return {
width: Math.max(newWidth, shapeSizeRestrictions.minWidth),
height: Math.max(newHeight, shapeSizeRestrictions.minHeight),
};
};
10 changes: 10 additions & 0 deletions src/core/model/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ export type ShapeType =
| 'timepickerinput';
/* | "text"| "button" | "radio" | "image"*/

export interface Size {
width: number;
height: number;
}

export interface Coord {
x: number;
y: number;
}

export interface ShapeModel {
id: string;
x: number;
Expand Down
2 changes: 2 additions & 0 deletions src/core/providers/canvas/canvas.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ import { ShapeModel } from '@/core/model';
export interface CanvasContextModel {
shapes: ShapeModel[];
setShapes: React.Dispatch<React.SetStateAction<ShapeModel[]>>;
scale: number;
setScale: React.Dispatch<React.SetStateAction<number>>;
}
3 changes: 2 additions & 1 deletion src/core/providers/canvas/canvas.provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ interface Props {
export const CanvasProvider: React.FC<Props> = props => {
const { children } = props;
const [shapes, setShapes] = React.useState<ShapeModel[]>([]);
const [scale, setScale] = React.useState(1);

return (
<CanvasContext.Provider value={{ shapes, setShapes }}>
<CanvasContext.Provider value={{ shapes, setShapes, scale, setScale }}>
{children}
</CanvasContext.Provider>
);
Expand Down
13 changes: 2 additions & 11 deletions src/pods/canvas/canvas.model.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ShapeModel, ShapeType } from '@/core/model';
import { Coord, ShapeType, Size, ShapeModel } from '@/core/model';
import { v4 as uuidv4 } from 'uuid';

import {
getComboBoxShapeSizeRestrictions,
getInputShapeSizeRestrictions,
Expand All @@ -11,16 +12,6 @@ import {
} from '@/common/components/front-components';
import { getBrowserWindowShapeSizeRestrictions } from '@/common/components/front-containers';

export interface Size {
width: number;
height: number;
}

export interface Coord {
x: number;
y: number;
}

const getDefaultSizeFromShape = (shapeType: ShapeType): Size => {
switch (shapeType) {
case 'combobox':
Expand Down
4 changes: 3 additions & 1 deletion src/pods/canvas/canvas.pod.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import {
moveZIndexTopOneLevel,
moveZIndexToTop,
} from './zindex.util';
import { ShapeModel } from '@/core/model';

export const CanvasPod = () => {
const { shapes, setShapes } = useCanvasContext();
const { shapes, setShapes, scale } = useCanvasContext();

const {
shapeRefs,
Expand Down Expand Up @@ -98,6 +99,7 @@ export const CanvasPod = () => {
onMouseDown={handleClearSelection}
onTouchStart={handleClearSelection}
ref={stageRef}
scale={{ x: scale, y: scale }}
>
<Layer>
{
Expand Down
24 changes: 1 addition & 23 deletions src/pods/canvas/canvas.util.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ShapeSizeRestrictions, ShapeType } from '@/core/model';
import { getButtonShapeSizeRestrictions } from '@/common/components/front-components/button-shape';
import { Coord, Size } from './canvas.model';
import { Coord } from '@/core/model';
import {
getComboBoxShapeSizeRestrictions,
getInputShapeSizeRestrictions,
Expand All @@ -14,28 +14,6 @@ import { getBrowserWindowShapeSizeRestrictions } from '@/common/components/front
import { DragLocationHistory } from '@atlaskit/pragmatic-drag-and-drop/dist/types/internal-types';
import { Stage } from 'konva/lib/Stage';

// TODO Add Unit tests, issue: #45
export const fitSizeToShapeSizeRestrictions = (
shapeSizeRestrictions: ShapeSizeRestrictions,
width: number,
height: number
): Size => {
const newWidth =
shapeSizeRestrictions.maxWidth !== -1
? Math.min(shapeSizeRestrictions.maxWidth, width)
: width;

const newHeight =
shapeSizeRestrictions.maxHeight !== -1
? Math.min(shapeSizeRestrictions.maxHeight, height)
: height;

return {
width: Math.max(newWidth, shapeSizeRestrictions.minWidth),
height: Math.max(newHeight, shapeSizeRestrictions.minHeight),
};
};

const defaultShapeSizeRestrictions: ShapeSizeRestrictions = {
minWidth: 0,
minHeight: 0,
Expand Down
2 changes: 1 addition & 1 deletion src/pods/canvas/shape-renderer/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ShapeModel } from '../canvas.model';
import { ShapeModel } from '@/core/model';
import { ShapeRendererProps } from './model';
import {
renderComboBox,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ShapeModel } from '@/core/model';
import { ShapeRendererProps } from '../model';
import { ShapeModel } from '../../canvas.model';
import { ButtonShape } from '@/common/components/front-components/button-shape';

export const renderButton = (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { CheckBoxShape } from '@/common/components/front-components/checkbox-shape';
import { ShapeRendererProps } from '../model';
import { ShapeModel } from '../../canvas.model';
import { ShapeModel } from '@/core/model';

export const renderCheckbox = (
shape: ShapeModel,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ComboBoxShape } from '@/common/components/front-components';
import { ShapeModel } from '../../canvas.model';
import { ShapeRendererProps } from '../model';
import { ShapeModel } from '@/core/model';

export const renderComboBox = (
shape: ShapeModel,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DatepickerInputShape } from '@/common/components/front-components';
import { ShapeModel } from '../../canvas.model';
import { ShapeRendererProps } from '../model';
import { ShapeModel } from '@/core/model';

export const renderDatepickerinput = (
shape: ShapeModel,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { InputShape } from '@/common/components/front-components/input-shape';
import { ShapeRendererProps } from '../model';
import { ShapeModel } from '../../canvas.model';
import { ShapeModel } from '@/core/model';

export const renderInput = (
shape: ShapeModel,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ShapeModel } from '../../canvas.model';
import { ShapeModel } from '@/core/model';
import { ShapeRendererProps } from '../model';
import { Group, Text } from 'react-konva';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TextAreaShape } from '@/common/components/front-components/textarea-shape';
import { ShapeRendererProps } from '../model';
import { ShapeModel } from '../../canvas.model';
import { ShapeModel } from '@/core/model';

export const renderTextArea = (
shape: ShapeModel,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TimepickerInputShape } from '@/common/components/front-components';
import { ShapeModel } from '../../canvas.model';
import { ShapeRendererProps } from '../model';
import { ShapeModel } from '@/core/model';

export const renderTimepickerinput = (
shape: ShapeModel,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ShapeModel } from '@/core/model';
import { ShapeRendererProps } from '../model';
import { ShapeModel } from '../../canvas.model';
import { ToggleSwitch } from '@/common/components/front-components/toggleswitch-shape';

export const renderToggleSwitch = (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BrowserWindowShape } from '@/common/components/front-containers';
import { ShapeModel } from '../../canvas.model';
import { ShapeRendererProps } from '../model';
import { ShapeModel } from '@/core/model';

export const renderBrowserWindow = (
shape: ShapeModel,
Expand Down
3 changes: 2 additions & 1 deletion src/pods/canvas/use-monitor-shape.hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
convertFromDivElementCoordsToKonvaCoords,
} from './canvas.util';
import Konva from 'konva';
import { createShape, ShapeModel } from './canvas.model';
import { createShape } from './canvas.model';
import { ShapeModel } from '@/core/model';

export const useMonitorShape = (
dropRef: React.MutableRefObject<null>,
Expand Down
6 changes: 2 additions & 4 deletions src/pods/canvas/use-selection.hook.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { useEffect, useRef, useState } from 'react';
import { ShapeModel, ShapeRefs } from './canvas.model';
import { ShapeRefs } from './canvas.model';
import Konva from 'konva';
import { ShapeType } from '@/core/model';


import { ShapeModel, ShapeType } from '@/core/model';

export const useSelection = (shapes: ShapeModel[]) => {
const transformerRef = useRef<Konva.Transformer>(null);
Expand Down
26 changes: 7 additions & 19 deletions src/pods/canvas/use-transform.hook.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { Node, NodeConfig } from 'konva/lib/Node';
import { Coord, ShapeModel, Size } from './canvas.model';
import { Box } from 'konva/lib/shapes/Transformer';
import {
fitSizeToShapeSizeRestrictions,
getShapeSizeRestrictions,
} from './canvas.util';
import { ShapeType } from '@/core/model';
import { Coord, ShapeModel, ShapeType, Size } from '@/core/model';

interface TransFormSelectedInfo {
selectedShapeRef: React.MutableRefObject<Node<NodeConfig> | null>;
Expand All @@ -17,8 +12,7 @@ export const useTransform = (
setShapes: (value: React.SetStateAction<ShapeModel[]>) => void,
transformSelectedInfo: TransFormSelectedInfo
) => {
const { selectedShapeId, selectedShapeRef, selectedShapeType } =
transformSelectedInfo;
const { selectedShapeId, selectedShapeRef } = transformSelectedInfo;

const updateShapeSizeAndPosition = (
id: string,
Expand Down Expand Up @@ -54,17 +48,11 @@ export const useTransform = (
node.scaleY(1);
};

const handleTransformerBoundBoxFunc = (_: Box, newBox: Box) => {
const limitedSize = fitSizeToShapeSizeRestrictions(
getShapeSizeRestrictions(selectedShapeType),
newBox.width,
newBox.height
);
return {
...newBox,
width: limitedSize.width,
height: limitedSize.height,
};
const handleTransformerBoundBoxFunc = (oldBox: Box, newBox: Box) => {
if (newBox.width < 5 || newBox.height < 5) {
return oldBox;
}
return newBox;
};

return { handleTransform, handleTransformerBoundBoxFunc };
Expand Down
2 changes: 1 addition & 1 deletion src/pods/canvas/zindex.util.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ShapeModel } from './canvas.model';
import { ShapeModel } from '@/core/model';

// TOO Add Unit tests to all these methods: #65
export const moveZIndexToTop = (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import ToolbarButton from '../toolbar-button/toolbar-button';
import classes from '@/pods/toolbar/toolbar.pod.module.css';
import { ZoomInIcon } from '@/common/components/icons/zoom-in.component';
import { useCanvasContext } from '@/core/providers';

export const ZoomInButton = () => {
const { setScale } = useCanvasContext();

const handleClick = () => {
console.log('ZoomIn');
setScale(prevScale => prevScale * 1.1);
};

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { ZoomOutIcon } from '@/common/components/icons/zoom-out.component';
import ToolbarButton from '../toolbar-button/toolbar-button';
import classes from '@/pods/toolbar/toolbar.pod.module.css';
import { useCanvasContext } from '@/core/providers';

export const ZoomOutButton = () => {
const { setScale } = useCanvasContext();

const handleClick = () => {
console.log('ZoomOut');
setScale(prevScale => prevScale * 0.9);
};

return (
Expand Down

0 comments on commit 26988b0

Please sign in to comment.