diff --git a/src/common/components/mock-components/front-components/index.ts b/src/common/components/mock-components/front-components/index.ts index 26a1223d..b278aaa8 100644 --- a/src/common/components/mock-components/front-components/index.ts +++ b/src/common/components/mock-components/front-components/index.ts @@ -16,3 +16,4 @@ export * from './label-shape'; export * from './tooltip-shape'; export * from './slider-shape'; export * from './chip-shape'; +export * from './mouse-cursor/mouse-cursor-shape'; diff --git a/src/common/components/mock-components/front-components/mouse-cursor/icon-shape.business.ts b/src/common/components/mock-components/front-components/mouse-cursor/icon-shape.business.ts new file mode 100644 index 00000000..71b7c376 --- /dev/null +++ b/src/common/components/mock-components/front-components/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-components/mouse-cursor/index.ts b/src/common/components/mock-components/front-components/mouse-cursor/index.ts new file mode 100644 index 00000000..071fdea0 --- /dev/null +++ b/src/common/components/mock-components/front-components/mouse-cursor/index.ts @@ -0,0 +1 @@ +export * from './mouse-cursor-shape'; diff --git a/src/common/components/mock-components/front-components/mouse-cursor/mouse-cursor-shape.tsx b/src/common/components/mock-components/front-components/mouse-cursor/mouse-cursor-shape.tsx new file mode 100644 index 00000000..642b79f5 --- /dev/null +++ b/src/common/components/mock-components/front-components/mouse-cursor/mouse-cursor-shape.tsx @@ -0,0 +1,86 @@ +import { forwardRef, useEffect, useState, useRef } from 'react'; +import { Group, Image } from 'react-konva'; +import { ShapeSizeRestrictions, ShapeType, BASE_ICONS_URL } from '@/core/model'; +import { ShapeProps } from '../../shape.model'; +import { BASIC_SHAPE } from '../shape.const'; +import { useShapeProps } from '../../../shapes/use-shape-props.hook'; +import { useGroupShapeProps } from '../../mock-components.utils'; +import { fitSizeToShapeSizeRestrictions } from '@/common/utils/shapes/shape-restrictions'; +import { returnIconSize } from './icon-shape.business'; +import { loadSvgWithFill } from '@/common/utils/svg.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 { stroke } = useShapeProps(otherProps, BASIC_SHAPE); + + const commonGroupProps = useGroupShapeProps( + props, + restrictedSize, + shapeType, + ref + ); + + const [image, setImage] = useState(null); + const imageRef = useRef(null); + + const fileName = 'cursor.svg'; + + useEffect(() => { + loadSvgWithFill(`${BASE_ICONS_URL}${fileName}`, `${stroke}`).then(img => { + setImage(img); + }); + }, [stroke]); + + return ( + + {image && ( + + )} + + ); +}); + +export default MouseCursorShape; diff --git a/src/core/model/index.ts b/src/core/model/index.ts index f2dbc4b4..35d3573f 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/inline-editable.model.ts b/src/pods/canvas/model/inline-editable.model.ts index cbdf7709..a2f3e7ea 100644 --- a/src/pods/canvas/model/inline-editable.model.ts +++ b/src/pods/canvas/model/inline-editable.model.ts @@ -86,6 +86,7 @@ const shapeTypesWithDefaultText = new Set([ 'loading-indicator', 'gauge', 'fileTree', + 'mousecursor', ]); // Map of ShapeTypes to their default text values diff --git a/src/pods/canvas/model/shape-other-props.utils.ts b/src/pods/canvas/model/shape-other-props.utils.ts index 8ad7a6d3..1e7dd04d 100644 --- a/src/pods/canvas/model/shape-other-props.utils.ts +++ b/src/pods/canvas/model/shape-other-props.utils.ts @@ -240,6 +240,11 @@ export const generateDefaultOtherProps = ( return { checked: true, }; + case 'mousecursor': + return { + iconSize: 'M', + stroke: BASIC_SHAPE.DEFAULT_STROKE_COLOR, + }; case 'checkbox': case 'radiobutton': return { diff --git a/src/pods/canvas/model/shape-size.mapper.ts b/src/pods/canvas/model/shape-size.mapper.ts index 19dcbf18..56478413 100644 --- a/src/pods/canvas/model/shape-size.mapper.ts +++ b/src/pods/canvas/model/shape-size.mapper.ts @@ -21,6 +21,7 @@ import { getTooltipShapeSizeRestrictions, getVerticalScrollBarShapeSizeRestrictions, getChipShapeSizeRestrictions, + getMouseCursorShapeSizeRestrictions, } from '@/common/components/mock-components/front-components'; import { getBrowserWindowShapeSizeRestrictions, @@ -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..7ef50f2f 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..2b63221b 100644 --- a/src/pods/canvas/shape-renderer/index.tsx +++ b/src/pods/canvas/shape-renderer/index.tsx @@ -20,6 +20,7 @@ import { renderTooltip, renderSlider, renderChip, + renderMouseCursor, } from './simple-component'; import { renderBrowserWindow, @@ -224,6 +225,8 @@ export const renderShapeComponent = ( return renderImagePlaceHolder(shape, shapeRenderedProps); case 'chip': return renderChip(shape, shapeRenderedProps); + case 'mousecursor': + return renderMouseCursor(shape, shapeRenderedProps); case 'horizontalLineLow': return renderHorizontalLowLine(shape, shapeRenderedProps); case 'verticalLineLow': diff --git a/src/pods/canvas/shape-renderer/simple-component/index.ts b/src/pods/canvas/shape-renderer/simple-component/index.ts index 9682fd62..ce3a4dd2 100644 --- a/src/pods/canvas/shape-renderer/simple-component/index.ts +++ b/src/pods/canvas/shape-renderer/simple-component/index.ts @@ -17,3 +17,4 @@ export * from './horizontalscrollbar.renderer'; export * from './tooltip.renderer'; export * from './slider.renderer'; export * from './chip.renderer'; +export * from './mouse-cursor.renderer'; diff --git a/src/pods/canvas/shape-renderer/simple-component/mouse-cursor.renderer.tsx b/src/pods/canvas/shape-renderer/simple-component/mouse-cursor.renderer.tsx new file mode 100644 index 00000000..6cc37766 --- /dev/null +++ b/src/pods/canvas/shape-renderer/simple-component/mouse-cursor.renderer.tsx @@ -0,0 +1,32 @@ +import { MouseCursorShape } from '@/common/components/mock-components/front-components'; +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/component-gallery/component-gallery-data/index.ts b/src/pods/galleries/component-gallery/component-gallery-data/index.ts index 9a79d859..430a3647 100644 --- a/src/pods/galleries/component-gallery/component-gallery-data/index.ts +++ b/src/pods/galleries/component-gallery/component-gallery-data/index.ts @@ -22,4 +22,5 @@ export const mockWidgetCollection: ItemInfo[] = [ { thumbnailSrc: '/widgets/toggleswitch.svg', type: 'toggleswitch' }, { thumbnailSrc: '/widgets/tooltip.svg', type: 'tooltip' }, { thumbnailSrc: '/widgets/verticalscrollbar.svg', type: 'verticalScrollBar' }, + { thumbnailSrc: '/icons/cursor.svg', type: 'mousecursor' }, ];