diff --git a/public/rich-components/input-stepper.svg b/public/rich-components/input-stepper.svg new file mode 100644 index 00000000..22ca7b92 --- /dev/null +++ b/public/rich-components/input-stepper.svg @@ -0,0 +1,15 @@ + + + + + + 0 + + + + + + + + + diff --git a/src/common/components/mock-components/front-rich-components/index.ts b/src/common/components/mock-components/front-rich-components/index.ts index b1e5f180..c29428d6 100644 --- a/src/common/components/mock-components/front-rich-components/index.ts +++ b/src/common/components/mock-components/front-rich-components/index.ts @@ -20,3 +20,4 @@ export * from './togglelightdark-shape'; export * from './gauge/gauge'; export * from './fab-button/fab-button'; export * from './file-tree/file-tree'; +export * from './input-stepper'; diff --git a/src/common/components/mock-components/front-rich-components/input-stepper.tsx b/src/common/components/mock-components/front-rich-components/input-stepper.tsx new file mode 100644 index 00000000..a10facfd --- /dev/null +++ b/src/common/components/mock-components/front-rich-components/input-stepper.tsx @@ -0,0 +1,144 @@ +import { forwardRef } from 'react'; +import { Group, Rect, Text } from 'react-konva'; +import { ShapeSizeRestrictions, ShapeType } from '@/core/model'; +import { fitSizeToShapeSizeRestrictions } from '@/common/utils/shapes/shape-restrictions'; +import { ShapeProps } from '../shape.model'; +import { useGroupShapeProps } from '../mock-components.utils'; +import { useShapeProps } from '@/common/components/shapes/use-shape-props.hook'; +import { INPUT_SHAPE } from '../front-components/shape.const'; + +const InputStepperShapeSizeRestrictions: ShapeSizeRestrictions = { + minWidth: 60, + minHeight: 35, + maxWidth: 500, + maxHeight: 35, + defaultWidth: 100, + defaultHeight: 35, +}; + +export const getInputStepperShapeSizeRestrictions = (): ShapeSizeRestrictions => + InputStepperShapeSizeRestrictions; + +const shapeType: ShapeType = 'inputStepper'; + +export const InputStepperShape = forwardRef((props, ref) => { + const { + x, + y, + width, + height, + id, + text, + onSelected, + otherProps, + ...shapeProps + } = props; + + const restrictedSize = fitSizeToShapeSizeRestrictions( + InputStepperShapeSizeRestrictions, + width, + height + ); + + const { width: restrictedWidth, height: restrictedHeight } = restrictedSize; + + const getButtonWidth = (restrictedWidth: number): number => { + const buttonWidth = restrictedWidth * 0.3; + const minButtonWidth = 30; + const maxButtonWidth = 70; + + if (buttonWidth < minButtonWidth) return minButtonWidth; + if (buttonWidth > maxButtonWidth) return maxButtonWidth; + return buttonWidth; + }; + + const buttonWidth = getButtonWidth(restrictedWidth); + const buttonHeight = restrictedHeight / 2; + + const commonGroupProps = useGroupShapeProps( + props, + restrictedSize, + shapeType, + ref + ); + + const { stroke, strokeStyle, fill, textColor } = useShapeProps( + otherProps, + INPUT_SHAPE + ); + + return ( + + + + {/* Texto del input */} + + + {/* Botón de incremento (flecha arriba) */} + + + + + + {/* Botón de decremento (flecha abajo) */} + + + + + + ); +}); + +export default InputStepperShape; diff --git a/src/core/model/index.ts b/src/core/model/index.ts index bf189305..8c13a80e 100644 --- a/src/core/model/index.ts +++ b/src/core/model/index.ts @@ -86,7 +86,8 @@ export type ShapeType = | 'textScribbled' | 'paragraphScribbled' | 'fabButton' - | 'fileTree'; + | 'fileTree' + | 'inputStepper'; export const ShapeDisplayName: Record = { multiple: 'multiple', @@ -162,6 +163,7 @@ export const ShapeDisplayName: Record = { paragraphScribbled: 'Paragraph Scribbled', fabButton: 'Fab Button', fileTree: 'File Tree', + inputStepper: 'Input Stepper', }; 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 bc99eecc..e4a06a8a 100644 --- a/src/pods/canvas/model/inline-editable.model.ts +++ b/src/pods/canvas/model/inline-editable.model.ts @@ -84,6 +84,7 @@ const shapeTypesWithDefaultText = new Set([ 'loading-indicator', 'gauge', 'fileTree', + 'inputStepper', ]); // Map of ShapeTypes to their default text values @@ -125,6 +126,7 @@ const defaultTextValueMap: Partial> = { browser: 'https://example.com', modalDialog: 'Title here...', 'loading-indicator': 'Loading...', + inputStepper: '0', }; export const generateDefaultTextValue = ( diff --git a/src/pods/canvas/model/shape-other-props.utils.ts b/src/pods/canvas/model/shape-other-props.utils.ts index f2c1007f..1483182f 100644 --- a/src/pods/canvas/model/shape-other-props.utils.ts +++ b/src/pods/canvas/model/shape-other-props.utils.ts @@ -287,6 +287,13 @@ export const generateDefaultOtherProps = ( textColor: '#000000', strokeStyle: [], }; + case 'inputStepper': + return { + stroke: INPUT_SHAPE.DEFAULT_STROKE_COLOR, + backgroundColor: INPUT_SHAPE.DEFAULT_FILL_BACKGROUND, + textColor: INPUT_SHAPE.DEFAULT_FILL_TEXT, + strokeStyle: [], + }; default: return undefined; } diff --git a/src/pods/canvas/model/shape-size.mapper.ts b/src/pods/canvas/model/shape-size.mapper.ts index 3c4ea531..d73980d2 100644 --- a/src/pods/canvas/model/shape-size.mapper.ts +++ b/src/pods/canvas/model/shape-size.mapper.ts @@ -66,6 +66,7 @@ import { getGaugeShapeSizeRestrictions, getFabButtonShapeSizeRestrictions, getFileTreeShapeSizeRestrictions, + getInputStepperShapeSizeRestrictions, // other imports } from '@/common/components/mock-components/front-rich-components'; import { @@ -175,6 +176,7 @@ const shapeSizeMap: Record ShapeSizeRestrictions> = { paragraphScribbled: getParagraphScribbledShapeRestrictions, fabButton: getFabButtonShapeSizeRestrictions, fileTree: getFileTreeShapeSizeRestrictions, + inputStepper: getInputStepperShapeSizeRestrictions, }; export default shapeSizeMap; diff --git a/src/pods/canvas/model/transformer.model.ts b/src/pods/canvas/model/transformer.model.ts index bf601b42..3cc690cc 100644 --- a/src/pods/canvas/model/transformer.model.ts +++ b/src/pods/canvas/model/transformer.model.ts @@ -71,6 +71,7 @@ export const generateTypeOfTransformer = (shapeType: ShapeType): string[] => { case 'buttonBar': case 'slider': case 'chip': + case 'inputStepper': return ['middle-left', 'middle-right']; case 'verticalLine': case 'verticalScrollBar': diff --git a/src/pods/canvas/shape-renderer/index.tsx b/src/pods/canvas/shape-renderer/index.tsx index 37a59949..c7fb0a3d 100644 --- a/src/pods/canvas/shape-renderer/index.tsx +++ b/src/pods/canvas/shape-renderer/index.tsx @@ -50,6 +50,7 @@ import { renderLoadingIndicator, renderFabButton, renderFileTree, + renderInputStepper, } from './simple-rich-components'; import { renderDiamond, @@ -235,6 +236,8 @@ export const renderShapeComponent = ( return renderTextScribbled(shape, shapeRenderedProps); case 'paragraphScribbled': return renderParagraphScribbled(shape, shapeRenderedProps); + case 'inputStepper': + return renderInputStepper(shape, shapeRenderedProps); default: return renderNotFound(shape, shapeRenderedProps); } diff --git a/src/pods/canvas/shape-renderer/simple-rich-components/index.ts b/src/pods/canvas/shape-renderer/simple-rich-components/index.ts index 2a32d3d1..d00fb7c2 100644 --- a/src/pods/canvas/shape-renderer/simple-rich-components/index.ts +++ b/src/pods/canvas/shape-renderer/simple-rich-components/index.ts @@ -22,3 +22,4 @@ export * from './loading-indicator.renderer'; export * from './videoconference.renderer'; export * from './fab-button.renderer'; export * from './file-tree.renderer'; +export * from './input-stepper.renderer'; diff --git a/src/pods/canvas/shape-renderer/simple-rich-components/input-stepper.renderer.tsx b/src/pods/canvas/shape-renderer/simple-rich-components/input-stepper.renderer.tsx new file mode 100644 index 00000000..26b456b3 --- /dev/null +++ b/src/pods/canvas/shape-renderer/simple-rich-components/input-stepper.renderer.tsx @@ -0,0 +1,34 @@ +import { InputStepperShape } from '@/common/components/mock-components/front-rich-components'; +import { ShapeRendererProps } from '../model'; +import { ShapeModel } from '@/core/model'; + +export const renderInputStepper = ( + shape: ShapeModel, + shapeRenderedProps: ShapeRendererProps +) => { + const { handleSelected, shapeRefs, handleDragEnd, handleTransform } = + shapeRenderedProps; + + return ( + + ); +}; diff --git a/src/pods/galleries/rich-components-gallery/rich-components-gallery-data/index.ts b/src/pods/galleries/rich-components-gallery/rich-components-gallery-data/index.ts index b44eee90..3a26cb76 100644 --- a/src/pods/galleries/rich-components-gallery/rich-components-gallery-data/index.ts +++ b/src/pods/galleries/rich-components-gallery/rich-components-gallery-data/index.ts @@ -44,4 +44,8 @@ export const mockRichComponentsCollection: ItemInfo[] = [ thumbnailSrc: '/rich-components/file-tree.svg', type: 'fileTree', }, + { + thumbnailSrc: '/rich-components/input-stepper.svg', + type: 'inputStepper', + }, ];