From 06d965fc738e37090b0e2bb857658d58d5a18baf Mon Sep 17 00:00:00 2001 From: Aarti Nanwani Samtani Date: Mon, 12 Jan 2026 20:36:01 +0100 Subject: [PATCH 1/2] Define mouse-cursor-component --- .../front-basic-shapes/index.ts | 1 + .../mouse-cursor-basic-shape.tsx | 75 +++++++++++++++++++ src/core/model/index.ts | 4 +- src/pods/canvas/model/shape-size.mapper.ts | 2 + src/pods/canvas/model/transformer.model.ts | 1 + src/pods/canvas/shape-renderer/index.tsx | 3 + .../simple-basic-shapes/index.ts | 1 + .../mouse-cursor.renderer.tsx | 32 ++++++++ .../basic-gallery-data/index.ts | 1 + 9 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 src/common/components/mock-components/front-basic-shapes/mouse-cursor-basic-shape.tsx create mode 100644 src/pods/canvas/shape-renderer/simple-basic-shapes/mouse-cursor.renderer.tsx diff --git a/src/common/components/mock-components/front-basic-shapes/index.ts b/src/common/components/mock-components/front-basic-shapes/index.ts index 782ff74e..d8393d8e 100644 --- a/src/common/components/mock-components/front-basic-shapes/index.ts +++ b/src/common/components/mock-components/front-basic-shapes/index.ts @@ -10,3 +10,4 @@ export * from './large-arrow-shape'; export * from './image-shape'; export * from './modal-cover-shape'; export * from './cilinder-basic-shape'; +export * from './mouse-cursor-basic-shape'; diff --git a/src/common/components/mock-components/front-basic-shapes/mouse-cursor-basic-shape.tsx b/src/common/components/mock-components/front-basic-shapes/mouse-cursor-basic-shape.tsx new file mode 100644 index 00000000..e15571c9 --- /dev/null +++ b/src/common/components/mock-components/front-basic-shapes/mouse-cursor-basic-shape.tsx @@ -0,0 +1,75 @@ +import { ShapeSizeRestrictions, ShapeType, BASE_ICONS_URL } from '@/core/model'; +import { forwardRef, useEffect, useState } from 'react'; +import { ShapeProps } from '../shape.model'; +import { loadSvgWithFill } from '@/common/utils/svg.utils'; +import { Group, Image } from 'react-konva'; +import { fitSizeToShapeSizeRestrictions } from '@/common/utils/shapes/shape-restrictions'; +import { returnIconSize } from '../front-components/icon/icon-shape.business'; +import { useGroupShapeProps } from '../mock-components.utils'; + +const MouseCursorSizeRestrictions: ShapeSizeRestrictions = { + minWidth: 25, + minHeight: 25, + maxWidth: -1, + maxHeight: -1, + defaultWidth: 150, + defaultHeight: 150, +}; + +export const getMouseCursorShapeSizeRestrictions = (): ShapeSizeRestrictions => + MouseCursorSizeRestrictions; + +const shapeType: ShapeType = 'mouseCursor'; + +export const MouseCursorShape = forwardRef((props, ref) => { + const { + x, + y, + width, + height, + id, + onSelected, + text, + iconSize, + otherProps, + ...shapeProps + } = props; + + const [iconWidth, iconHeight] = returnIconSize(iconSize); + const restrictedSize = fitSizeToShapeSizeRestrictions( + MouseCursorSizeRestrictions, + iconWidth, + iconHeight + ); + + const { width: restrictedWidth, height: restrictedHeight } = restrictedSize; + const commonGroupProps = useGroupShapeProps( + props, + restrictedSize, + shapeType, + ref + ); + + const [image, setImage] = useState(null); + //const imgRef = useRef(null); + const fileName = 'cursor.svg'; + useEffect(() => { + loadSvgWithFill(`${BASE_ICONS_URL}${fileName}`, '').then(img => { + setImage(img); + }); + }, []); + return ( + + {image && ( + + )} + + ); +}); diff --git a/src/core/model/index.ts b/src/core/model/index.ts index f2dbc4b4..79f931cb 100644 --- a/src/core/model/index.ts +++ b/src/core/model/index.ts @@ -87,7 +87,8 @@ export type ShapeType = | 'textScribbled' | 'paragraphScribbled' | 'fabButton' - | 'fileTree'; + | 'fileTree' + | 'mouseCursor'; export const ShapeDisplayName: Record = { multiple: 'multiple', @@ -164,6 +165,7 @@ export const ShapeDisplayName: Record = { paragraphScribbled: 'Paragraph Scribbled', fabButton: 'Fab Button', fileTree: 'File Tree', + mouseCursor: 'Mouse Cursor', }; export type EditType = 'input' | 'textarea' | 'imageupload'; diff --git a/src/pods/canvas/model/shape-size.mapper.ts b/src/pods/canvas/model/shape-size.mapper.ts index 19dcbf18..9c46536d 100644 --- a/src/pods/canvas/model/shape-size.mapper.ts +++ b/src/pods/canvas/model/shape-size.mapper.ts @@ -42,6 +42,7 @@ import { getStarShapeSizeRestrictions, getModalCoverShapeSizeRestrictions, getCilinderShapeSizeRestrictions, + getMouseCursorShapeSizeRestrictions, // other imports } from '@/common/components/mock-components/front-basic-shapes'; import { @@ -177,6 +178,7 @@ const shapeSizeMap: Record ShapeSizeRestrictions> = { fabButton: getFabButtonShapeSizeRestrictions, fileTree: getFileTreeShapeSizeRestrictions, paragraphScribbled: getParagraphScribbledShapeRestrictions, + mouseCursor: getMouseCursorShapeSizeRestrictions, }; export default shapeSizeMap; diff --git a/src/pods/canvas/model/transformer.model.ts b/src/pods/canvas/model/transformer.model.ts index e6a71e22..c7577816 100644 --- a/src/pods/canvas/model/transformer.model.ts +++ b/src/pods/canvas/model/transformer.model.ts @@ -87,6 +87,7 @@ export const generateTypeOfTransformer = (shapeType: ShapeType): string[] => { 'bottom-center', ]; case 'icon': + case 'mouseCursor': case 'multiple': return []; case 'image': diff --git a/src/pods/canvas/shape-renderer/index.tsx b/src/pods/canvas/shape-renderer/index.tsx index 62cdc417..51f3b0e3 100644 --- a/src/pods/canvas/shape-renderer/index.tsx +++ b/src/pods/canvas/shape-renderer/index.tsx @@ -65,6 +65,7 @@ import { renderLargeArrowShape, renderCilinder, renderImage, + renderMouseCursor, } from './simple-basic-shapes'; import { renderHeading1, @@ -238,6 +239,8 @@ export const renderShapeComponent = ( return renderTextScribbled(shape, shapeRenderedProps); case 'paragraphScribbled': return renderParagraphScribbled(shape, shapeRenderedProps); + case 'mouseCursor': + return renderMouseCursor(shape, shapeRenderedProps); default: return renderNotFound(shape, shapeRenderedProps); } diff --git a/src/pods/canvas/shape-renderer/simple-basic-shapes/index.ts b/src/pods/canvas/shape-renderer/simple-basic-shapes/index.ts index 60de40c8..c4727ea1 100644 --- a/src/pods/canvas/shape-renderer/simple-basic-shapes/index.ts +++ b/src/pods/canvas/shape-renderer/simple-basic-shapes/index.ts @@ -10,3 +10,4 @@ export * from './large-arrow.renderer'; export * from './modal-cover.rerender'; export * from './cilinder.renderer'; export * from './image.renderer'; +export * from './mouse-cursor.renderer'; diff --git a/src/pods/canvas/shape-renderer/simple-basic-shapes/mouse-cursor.renderer.tsx b/src/pods/canvas/shape-renderer/simple-basic-shapes/mouse-cursor.renderer.tsx new file mode 100644 index 00000000..17aad2ce --- /dev/null +++ b/src/pods/canvas/shape-renderer/simple-basic-shapes/mouse-cursor.renderer.tsx @@ -0,0 +1,32 @@ +import { MouseCursorShape } from '@/common/components/mock-components/front-basic-shapes'; +import { ShapeModel } from '@/core/model'; +import { ShapeRendererProps } from '../model'; + +export const renderMouseCursor = ( + shape: ShapeModel, + shapeRenderedProps: ShapeRendererProps +) => { + const { handleSelected, shapeRefs, handleDragEnd, handleTransform } = + shapeRenderedProps; + + return ( + + ); +}; diff --git a/src/pods/galleries/basic-shapes-gallery/basic-gallery-data/index.ts b/src/pods/galleries/basic-shapes-gallery/basic-gallery-data/index.ts index 5dc3c532..4fea0367 100644 --- a/src/pods/galleries/basic-shapes-gallery/basic-gallery-data/index.ts +++ b/src/pods/galleries/basic-shapes-gallery/basic-gallery-data/index.ts @@ -13,4 +13,5 @@ export const mockBasicShapesCollection: ItemInfo[] = [ { thumbnailSrc: '/shapes/triangle.svg', type: 'triangle' }, { thumbnailSrc: '/shapes/verticalLine.svg', type: 'verticalLine' }, { thumbnailSrc: '/shapes/cilinder.svg', type: 'cilinder' }, + { thumbnailSrc: '/icons/cursor.svg', type: 'mouseCursor' }, ]; From a45c905946a4453b9a27cbd82c75b1c5015e84fb Mon Sep 17 00:00:00 2001 From: Aarti Nanwani Samtani Date: Tue, 13 Jan 2026 17:41:04 +0100 Subject: [PATCH 2/2] add stroke & icon size properties --- .../front-basic-shapes/index.ts | 2 +- .../mouse-cursor/icon-shape.business.ts | 18 ++++++++++++++++++ .../front-basic-shapes/mouse-cursor/index.ts | 1 + .../mouse-cursor-basic-shape.tsx | 13 ++++++++----- .../canvas/model/shape-other-props.utils.ts | 5 +++++ 5 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 src/common/components/mock-components/front-basic-shapes/mouse-cursor/icon-shape.business.ts create mode 100644 src/common/components/mock-components/front-basic-shapes/mouse-cursor/index.ts rename src/common/components/mock-components/front-basic-shapes/{ => mouse-cursor}/mouse-cursor-basic-shape.tsx (78%) diff --git a/src/common/components/mock-components/front-basic-shapes/index.ts b/src/common/components/mock-components/front-basic-shapes/index.ts index d8393d8e..6162bfa1 100644 --- a/src/common/components/mock-components/front-basic-shapes/index.ts +++ b/src/common/components/mock-components/front-basic-shapes/index.ts @@ -10,4 +10,4 @@ export * from './large-arrow-shape'; export * from './image-shape'; export * from './modal-cover-shape'; export * from './cilinder-basic-shape'; -export * from './mouse-cursor-basic-shape'; +export * from './mouse-cursor/mouse-cursor-basic-shape'; diff --git a/src/common/components/mock-components/front-basic-shapes/mouse-cursor/icon-shape.business.ts b/src/common/components/mock-components/front-basic-shapes/mouse-cursor/icon-shape.business.ts new file mode 100644 index 00000000..71b7c376 --- /dev/null +++ b/src/common/components/mock-components/front-basic-shapes/mouse-cursor/icon-shape.business.ts @@ -0,0 +1,18 @@ +import { IconSize } from '@/core/model'; + +export const returnIconSize = (iconSize: IconSize): number[] => { + switch (iconSize) { + case 'XS': + return [25, 25]; + case 'S': + return [50, 50]; + case 'M': + return [100, 100]; + case 'L': + return [125, 125]; + case 'XL': + return [150, 150]; + default: + return [50, 50]; + } +}; diff --git a/src/common/components/mock-components/front-basic-shapes/mouse-cursor/index.ts b/src/common/components/mock-components/front-basic-shapes/mouse-cursor/index.ts new file mode 100644 index 00000000..f80cebff --- /dev/null +++ b/src/common/components/mock-components/front-basic-shapes/mouse-cursor/index.ts @@ -0,0 +1 @@ +export * from './mouse-cursor-basic-shape'; diff --git a/src/common/components/mock-components/front-basic-shapes/mouse-cursor-basic-shape.tsx b/src/common/components/mock-components/front-basic-shapes/mouse-cursor/mouse-cursor-basic-shape.tsx similarity index 78% rename from src/common/components/mock-components/front-basic-shapes/mouse-cursor-basic-shape.tsx rename to src/common/components/mock-components/front-basic-shapes/mouse-cursor/mouse-cursor-basic-shape.tsx index e15571c9..fab72fb1 100644 --- a/src/common/components/mock-components/front-basic-shapes/mouse-cursor-basic-shape.tsx +++ b/src/common/components/mock-components/front-basic-shapes/mouse-cursor/mouse-cursor-basic-shape.tsx @@ -1,11 +1,13 @@ import { ShapeSizeRestrictions, ShapeType, BASE_ICONS_URL } from '@/core/model'; import { forwardRef, useEffect, useState } from 'react'; -import { ShapeProps } from '../shape.model'; +import { ShapeProps } from '../../shape.model'; import { loadSvgWithFill } from '@/common/utils/svg.utils'; import { Group, Image } from 'react-konva'; import { fitSizeToShapeSizeRestrictions } from '@/common/utils/shapes/shape-restrictions'; -import { returnIconSize } from '../front-components/icon/icon-shape.business'; -import { useGroupShapeProps } from '../mock-components.utils'; +import { returnIconSize } from './icon-shape.business'; +import { useGroupShapeProps } from '../../mock-components.utils'; +import { useShapeProps } from '../../../shapes/use-shape-props.hook'; +import { BASIC_SHAPE } from '../../front-components/shape.const'; const MouseCursorSizeRestrictions: ShapeSizeRestrictions = { minWidth: 25, @@ -43,6 +45,7 @@ export const MouseCursorShape = forwardRef((props, ref) => { ); const { width: restrictedWidth, height: restrictedHeight } = restrictedSize; + const { stroke } = useShapeProps(otherProps, BASIC_SHAPE); const commonGroupProps = useGroupShapeProps( props, restrictedSize, @@ -54,10 +57,10 @@ export const MouseCursorShape = forwardRef((props, ref) => { //const imgRef = useRef(null); const fileName = 'cursor.svg'; useEffect(() => { - loadSvgWithFill(`${BASE_ICONS_URL}${fileName}`, '').then(img => { + loadSvgWithFill(`${BASE_ICONS_URL}${fileName}`, `${stroke}`).then(img => { setImage(img); }); - }, []); + }, [stroke]); return ( {image && ( diff --git a/src/pods/canvas/model/shape-other-props.utils.ts b/src/pods/canvas/model/shape-other-props.utils.ts index 8ad7a6d3..f5f8aa1a 100644 --- a/src/pods/canvas/model/shape-other-props.utils.ts +++ b/src/pods/canvas/model/shape-other-props.utils.ts @@ -266,6 +266,11 @@ export const generateDefaultOtherProps = ( iconSize: 'M', stroke: BASIC_SHAPE.DEFAULT_STROKE_COLOR, }; + case 'mouseCursor': + return { + stroke: BASIC_SHAPE.DEFAULT_STROKE_COLOR, + iconSize: 'M', + }; case 'image': return { imageSrc: '',