From 92160ca8ab753345755182bbfeb87f581e246e85 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Fri, 6 Sep 2024 18:33:34 +0200 Subject: [PATCH 01/12] created branch y added svg file for issue #216 --- public/rich-components/input-stepper.svg | 15 +++++++++++++++ .../rich-components-gallery-data/index.ts | 1 + 2 files changed, 16 insertions(+) create mode 100644 public/rich-components/input-stepper.svg diff --git a/public/rich-components/input-stepper.svg b/public/rich-components/input-stepper.svg new file mode 100644 index 00000000..be747f48 --- /dev/null +++ b/public/rich-components/input-stepper.svg @@ -0,0 +1,15 @@ + + + + + + 0 + + + + + + + + + \ No newline at end of file diff --git a/src/pods/rich-components-gallery/rich-components-gallery-data/index.ts b/src/pods/rich-components-gallery/rich-components-gallery-data/index.ts index 7239c2a1..39cfb294 100644 --- a/src/pods/rich-components-gallery/rich-components-gallery-data/index.ts +++ b/src/pods/rich-components-gallery/rich-components-gallery-data/index.ts @@ -22,4 +22,5 @@ export const mockRichComponentsCollection: ItemInfo[] = [ { thumbnailSrc: '/rich-components/appBar.svg', type: 'appBar' }, { thumbnailSrc: '/rich-components/button-bar-group.svg', type: 'buttonBar' }, { thumbnailSrc: '/rich-components/tabsbar.svg', type: 'tabsBar' }, + { thumbnailSrc: '/rich-components/input-stepper.svg', type: 'input-stepper' }, ]; From 08b2eddbd9bd78691a5564193bf9e76834086986 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Fri, 6 Sep 2024 18:37:11 +0200 Subject: [PATCH 02/12] added input-stepper.tsx and improve the starting point --- .../front-rich-components/input-stepper.tsx | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 src/common/components/front-rich-components/input-stepper.tsx diff --git a/src/common/components/front-rich-components/input-stepper.tsx b/src/common/components/front-rich-components/input-stepper.tsx new file mode 100644 index 00000000..72d6d69d --- /dev/null +++ b/src/common/components/front-rich-components/input-stepper.tsx @@ -0,0 +1,100 @@ +import { useState, forwardRef } from 'react'; +import { Group, Rect, Text } from 'react-konva'; +import { ShapeConfig } from 'konva/lib/Shape'; + +interface InputWithStepperProps extends ShapeConfig { + id: string; + x: number; + y: number; + width: number; + height: number; + initialValue?: number; +} + +export const InputWithStepper = forwardRef( + ({ x, y, width, height, initialValue = 0, id, ...shapeProps }, ref) => { + const [value, setValue] = useState(initialValue); + + const handleIncrement = () => { + setValue(value + 1); + }; + + const handleDecrement = () => { + setValue(value - 1); + }; + + const inputWidth = width - 30; // Reservar espacio para el stepper + const buttonHeight = height / 2; + + return ( + + {/* Caja del input */} + + + {/* Texto del input */} + + + {/* Botón de incremento (flecha arriba) */} + + + + + + {/* Botón de decremento (flecha abajo) */} + + + + + + ); + } +); + +export default InputWithStepper; From bb9418428ab9bf7fcfad6372e4820f3ab150bb10 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Fri, 13 Sep 2024 21:52:41 +0200 Subject: [PATCH 03/12] component rendered --- ...put-stepper.svg => input-with-stepper.svg} | 0 .../front-components/input-shape.tsx | 6 +- .../components/front-rich-components/index.ts | 1 + ...put-stepper.tsx => input-with-stepper.tsx} | 58 +++++++++++++++---- src/core/model/index.ts | 2 + src/pods/canvas/canvas.model.ts | 5 ++ src/pods/canvas/shape-renderer/index.tsx | 3 + .../simple-rich-components/index.ts | 1 + .../input-with-stepper.renderer.tsx | 31 ++++++++++ .../rich-components-gallery-data/index.ts | 5 +- 10 files changed, 98 insertions(+), 14 deletions(-) rename public/rich-components/{input-stepper.svg => input-with-stepper.svg} (100%) rename src/common/components/front-rich-components/{input-stepper.tsx => input-with-stepper.tsx} (56%) create mode 100644 src/pods/canvas/shape-renderer/simple-rich-components/input-with-stepper.renderer.tsx diff --git a/public/rich-components/input-stepper.svg b/public/rich-components/input-with-stepper.svg similarity index 100% rename from public/rich-components/input-stepper.svg rename to public/rich-components/input-with-stepper.svg diff --git a/src/common/components/front-components/input-shape.tsx b/src/common/components/front-components/input-shape.tsx index 0bee3610..5e04ed8d 100644 --- a/src/common/components/front-components/input-shape.tsx +++ b/src/common/components/front-components/input-shape.tsx @@ -9,10 +9,10 @@ import { useShapeComponentSelection } from '../shapes/use-shape-selection.hook'; const inputShapeRestrictions: ShapeSizeRestrictions = { minWidth: 60, minHeight: 38, - maxWidth: -1, + maxWidth: 2000, maxHeight: 38, - defaultWidth: INPUT_SHAPE.DEFAULT_TEXT_WIDTH, - defaultHeight: INPUT_SHAPE.DEFAULT_TEXT_HEIGHT, + defaultWidth: 155, + defaultHeight: 38, }; export const getInputShapeSizeRestrictions = (): ShapeSizeRestrictions => diff --git a/src/common/components/front-rich-components/index.ts b/src/common/components/front-rich-components/index.ts index db76ce59..e04f2733 100644 --- a/src/common/components/front-rich-components/index.ts +++ b/src/common/components/front-rich-components/index.ts @@ -13,3 +13,4 @@ export * from './modal/modal'; export * from './appBar'; export * from './buttonBar/buttonBar'; export * from './tabsbar'; +export * from './input-with-stepper'; diff --git a/src/common/components/front-rich-components/input-stepper.tsx b/src/common/components/front-rich-components/input-with-stepper.tsx similarity index 56% rename from src/common/components/front-rich-components/input-stepper.tsx rename to src/common/components/front-rich-components/input-with-stepper.tsx index 72d6d69d..662f3acb 100644 --- a/src/common/components/front-rich-components/input-stepper.tsx +++ b/src/common/components/front-rich-components/input-with-stepper.tsx @@ -1,6 +1,10 @@ import { useState, forwardRef } from 'react'; import { Group, Rect, Text } from 'react-konva'; import { ShapeConfig } from 'konva/lib/Shape'; +import { ShapeSizeRestrictions } from '@/core/model'; +import { ShapeType } from '../../../core/model/index'; +import { fitSizeToShapeSizeRestrictions } from '@/common/utils/shapes'; +import { useShapeComponentSelection } from '../shapes/use-shape-selection.hook'; interface InputWithStepperProps extends ShapeConfig { id: string; @@ -9,10 +13,44 @@ interface InputWithStepperProps extends ShapeConfig { width: number; height: number; initialValue?: number; + onSelected: () => void; } -export const InputWithStepper = forwardRef( - ({ x, y, width, height, initialValue = 0, id, ...shapeProps }, ref) => { +const inputWithStepperSizeRestrictions: ShapeSizeRestrictions = { + minWidth: 100, + minHeight: 20, + maxWidth: 600, + maxHeight: 40, + defaultWidth: 150, + defaultHeight: 30, +}; + +export const getInputWithStepperSizeRestrictions = (): ShapeSizeRestrictions => + inputWithStepperSizeRestrictions; + +const shapeType: ShapeType = 'inputWithStepper'; + +export const InputWithStepperShape = forwardRef( + (props, ref) => { + const { + x, + y, + width, + height, + initialValue = 0, + id, + OtherProps, + ...shapeProps + } = props; + + const { width: restrictedWidth, height: restrictedHeight } = + fitSizeToShapeSizeRestrictions( + inputWithStepperSizeRestrictions, + width, + height + ); + + const { handleSelection } = useShapeComponentSelection(props, shapeType); const [value, setValue] = useState(initialValue); const handleIncrement = () => { @@ -23,17 +61,17 @@ export const InputWithStepper = forwardRef( setValue(value - 1); }; - const inputWidth = width - 30; // Reservar espacio para el stepper - const buttonHeight = height / 2; + const inputWidth = restrictedWidth - 30; // Reservar espacio para el stepper + const buttonHeight = restrictedHeight / 2; return ( - + {/* Caja del input */} ( {/* Texto del input */} ( /> ( } ); -export default InputWithStepper; +export default InputWithStepperShape; diff --git a/src/core/model/index.ts b/src/core/model/index.ts index acd2c438..fde24b66 100644 --- a/src/core/model/index.ts +++ b/src/core/model/index.ts @@ -64,6 +64,7 @@ export type ShapeType = | 'appBar' | 'buttonBar' | 'tooltip' + | 'inputWithStepper' | 'slider'; export const ShapeDisplayName: Record = { @@ -119,6 +120,7 @@ export const ShapeDisplayName: Record = { buttonBar: 'Button Bar', tooltip: 'Tooltip', slider: 'Slider', + inputWithStepper: 'Input With Stepper', }; export type EditType = 'input' | 'textarea' | 'imageupload'; diff --git a/src/pods/canvas/canvas.model.ts b/src/pods/canvas/canvas.model.ts index 8c649522..2df45470 100644 --- a/src/pods/canvas/canvas.model.ts +++ b/src/pods/canvas/canvas.model.ts @@ -61,6 +61,7 @@ import { getAppBarShapeSizeRestrictions, getButtonBarShapeSizeRestrictions, getTabsBarShapeSizeRestrictions, + getInputWithStepperSizeRestrictions, } from '@/common/components/front-rich-components'; import { getHeading1SizeRestrictions, @@ -181,6 +182,8 @@ export const getSizeRestrictionFromShape = ( return getTooltipShapeSizeRestrictions(); case 'slider': return getSliderShapeSizeRestrictions(); + case 'inputWithStepper': + return getInputWithStepperSizeRestrictions(); default: console.warn( `** Shape ${shapeType} has not defined default size, check getDefaultSizeFromShape helper function` @@ -269,6 +272,7 @@ const generateTypeOfTransformer = (shapeType: ShapeType): string[] => { case 'appBar': case 'buttonBar': case 'slider': + case 'inputWithStepper': return ['middle-left', 'middle-right']; case 'verticalScrollBar': return ['top-center', 'bottom-center']; @@ -377,6 +381,7 @@ export const generateDefaultOtherProps = ( shapeType: ShapeType ): OtherProps | undefined => { switch (shapeType) { + case 'inputWithStepper': case 'input': return { stroke: INPUT_SHAPE.DEFAULT_STROKE_COLOR, diff --git a/src/pods/canvas/shape-renderer/index.tsx b/src/pods/canvas/shape-renderer/index.tsx index b4a9f84d..1729eb5f 100644 --- a/src/pods/canvas/shape-renderer/index.tsx +++ b/src/pods/canvas/shape-renderer/index.tsx @@ -40,6 +40,7 @@ import { renderModal, renderButtonBar, renderTabsBar, + renderInputWithStepper, } from './simple-rich-components'; import { renderDiamond, @@ -170,6 +171,8 @@ export const renderShapeComponent = ( return renderTooltip(shape, shapeRenderedProps); case 'slider': return renderSlider(shape, shapeRenderedProps); + case 'inputWithStepper': + return renderInputWithStepper(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 cbee3ae9..6cd811e3 100644 --- a/src/pods/canvas/shape-renderer/simple-rich-components/index.ts +++ b/src/pods/canvas/shape-renderer/simple-rich-components/index.ts @@ -13,3 +13,4 @@ export * from './modal.renderer'; export * from './appBar.renderer'; export * from './button-bar.renderer'; export * from './tabsbar.renderer'; +export * from './input-with-stepper.renderer'; diff --git a/src/pods/canvas/shape-renderer/simple-rich-components/input-with-stepper.renderer.tsx b/src/pods/canvas/shape-renderer/simple-rich-components/input-with-stepper.renderer.tsx new file mode 100644 index 00000000..316825f8 --- /dev/null +++ b/src/pods/canvas/shape-renderer/simple-rich-components/input-with-stepper.renderer.tsx @@ -0,0 +1,31 @@ +import { InputWithStepperShape } from '@/common/components/front-rich-components'; +import { ShapeRendererProps } from '../model'; +import { ShapeModel } from '@/core/model'; + +export const renderInputWithStepper = ( + shape: ShapeModel, + shapeRenderedProps: ShapeRendererProps +) => { + const { handleSelected, shapeRefs, handleDragEnd, handleTransform } = + shapeRenderedProps; + + return ( + + ); +}; diff --git a/src/pods/rich-components-gallery/rich-components-gallery-data/index.ts b/src/pods/rich-components-gallery/rich-components-gallery-data/index.ts index 39cfb294..0e78da83 100644 --- a/src/pods/rich-components-gallery/rich-components-gallery-data/index.ts +++ b/src/pods/rich-components-gallery/rich-components-gallery-data/index.ts @@ -22,5 +22,8 @@ export const mockRichComponentsCollection: ItemInfo[] = [ { thumbnailSrc: '/rich-components/appBar.svg', type: 'appBar' }, { thumbnailSrc: '/rich-components/button-bar-group.svg', type: 'buttonBar' }, { thumbnailSrc: '/rich-components/tabsbar.svg', type: 'tabsBar' }, - { thumbnailSrc: '/rich-components/input-stepper.svg', type: 'input-stepper' }, + { + thumbnailSrc: '/rich-components/input-with-stepper.svg', + type: 'inputWithStepper', + }, ]; From 61084341c9b6506be44f2c863dffe02bb263944a Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Mon, 16 Sep 2024 18:26:09 +0200 Subject: [PATCH 04/12] propertys working --- .../components/front-rich-components/index.ts | 2 +- .../input-with-stepper/index.ts | 2 + .../input-with-stepper.business.ts | 15 ++++ .../input-with-stepper.tsx | 87 +++++++++---------- src/pods/canvas/canvas.model.ts | 6 ++ .../input-with-stepper.renderer.tsx | 2 +- 6 files changed, 68 insertions(+), 46 deletions(-) create mode 100644 src/common/components/front-rich-components/input-with-stepper/index.ts create mode 100644 src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts rename src/common/components/front-rich-components/{ => input-with-stepper}/input-with-stepper.tsx (60%) diff --git a/src/common/components/front-rich-components/index.ts b/src/common/components/front-rich-components/index.ts index e04f2733..e9a5dd0e 100644 --- a/src/common/components/front-rich-components/index.ts +++ b/src/common/components/front-rich-components/index.ts @@ -13,4 +13,4 @@ export * from './modal/modal'; export * from './appBar'; export * from './buttonBar/buttonBar'; export * from './tabsbar'; -export * from './input-with-stepper'; +export * from './input-with-stepper/'; diff --git a/src/common/components/front-rich-components/input-with-stepper/index.ts b/src/common/components/front-rich-components/input-with-stepper/index.ts new file mode 100644 index 00000000..05cd467b --- /dev/null +++ b/src/common/components/front-rich-components/input-with-stepper/index.ts @@ -0,0 +1,2 @@ +export * from './input-with-stepper'; +export * from './input-with-stepper.business'; diff --git a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts new file mode 100644 index 00000000..1db28855 --- /dev/null +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts @@ -0,0 +1,15 @@ +import React from 'react'; + +export const useHandleCounterInputWithStepper = () => { + const [value, setValue] = React.useState(0); + + const handleIncrement = () => { + setValue(value + 1); + }; + + const handleDecrement = () => { + setValue(value - 1); + }; + + return { value, handleIncrement, handleDecrement }; +}; diff --git a/src/common/components/front-rich-components/input-with-stepper.tsx b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx similarity index 60% rename from src/common/components/front-rich-components/input-with-stepper.tsx rename to src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx index 662f3acb..6afedd59 100644 --- a/src/common/components/front-rich-components/input-with-stepper.tsx +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx @@ -1,20 +1,12 @@ -import { useState, forwardRef } from 'react'; +import { forwardRef, useMemo } from 'react'; import { Group, Rect, Text } from 'react-konva'; -import { ShapeConfig } from 'konva/lib/Shape'; import { ShapeSizeRestrictions } from '@/core/model'; -import { ShapeType } from '../../../core/model/index'; +import { ShapeType } from '../../../../core/model/index'; import { fitSizeToShapeSizeRestrictions } from '@/common/utils/shapes'; -import { useShapeComponentSelection } from '../shapes/use-shape-selection.hook'; - -interface InputWithStepperProps extends ShapeConfig { - id: string; - x: number; - y: number; - width: number; - height: number; - initialValue?: number; - onSelected: () => void; -} +import { useShapeComponentSelection } from '../../shapes/use-shape-selection.hook'; +import { ShapeProps } from '../../front-components/shape.model'; +import { useHandleCounterInputWithStepper } from './input-with-stepper.business'; +import { INPUT_SHAPE } from '../../front-components/shape.const'; const inputWithStepperSizeRestrictions: ShapeSizeRestrictions = { minWidth: 100, @@ -30,18 +22,9 @@ export const getInputWithStepperSizeRestrictions = (): ShapeSizeRestrictions => const shapeType: ShapeType = 'inputWithStepper'; -export const InputWithStepperShape = forwardRef( +export const InputWithStepperShape = forwardRef( (props, ref) => { - const { - x, - y, - width, - height, - initialValue = 0, - id, - OtherProps, - ...shapeProps - } = props; + const { x, y, width, height, id, otherProps, ...shapeProps } = props; const { width: restrictedWidth, height: restrictedHeight } = fitSizeToShapeSizeRestrictions( @@ -51,15 +34,29 @@ export const InputWithStepperShape = forwardRef( ); const { handleSelection } = useShapeComponentSelection(props, shapeType); - const [value, setValue] = useState(initialValue); - const handleIncrement = () => { - setValue(value + 1); - }; + const { value, handleIncrement, handleDecrement } = + useHandleCounterInputWithStepper(); - const handleDecrement = () => { - setValue(value - 1); - }; + const stroke = useMemo( + () => otherProps?.stroke ?? INPUT_SHAPE.DEFAULT_STROKE_COLOR, + [otherProps?.stroke] + ); + + const fill = useMemo( + () => otherProps?.backgroundColor ?? INPUT_SHAPE.DEFAULT_FILL_BACKGROUND, + [otherProps?.backgroundColor] + ); + + const textColor = useMemo( + () => otherProps?.textColor ?? INPUT_SHAPE.DEFAULT_FILL_TEXT, + [otherProps?.textColor] + ); + + const strokeStyle = useMemo( + () => otherProps?.strokeStyle ?? [], + [otherProps?.strokeStyle] + ); const inputWidth = restrictedWidth - 30; // Reservar espacio para el stepper const buttonHeight = restrictedHeight / 2; @@ -72,10 +69,10 @@ export const InputWithStepperShape = forwardRef( y={0} width={inputWidth / 2} // Reducir ancho a la mitad height={restrictedHeight} - fill="white" - stroke="black" + fill={fill} + stroke={stroke} strokeWidth={2} - cornerRadius={0} // Sin bordes redondeados + dash={strokeStyle} /> {/* Texto del input */} @@ -85,7 +82,7 @@ export const InputWithStepperShape = forwardRef( text={value.toString()} fontFamily="Arial" fontSize={16} - fill="black" + fill={textColor} align="right" /> @@ -96,17 +93,18 @@ export const InputWithStepperShape = forwardRef( y={0} width={30} height={buttonHeight} - fill="lightgray" - stroke="black" + fill={fill} + stroke={stroke} strokeWidth={2} + dash={strokeStyle} /> @@ -117,17 +115,18 @@ export const InputWithStepperShape = forwardRef( y={0} width={30} height={buttonHeight} - fill="lightgray" - stroke="black" + fill={fill} + stroke={stroke} strokeWidth={2} + dash={strokeStyle} /> diff --git a/src/pods/canvas/canvas.model.ts b/src/pods/canvas/canvas.model.ts index 2df45470..5daae53d 100644 --- a/src/pods/canvas/canvas.model.ts +++ b/src/pods/canvas/canvas.model.ts @@ -382,6 +382,12 @@ export const generateDefaultOtherProps = ( ): OtherProps | undefined => { switch (shapeType) { case 'inputWithStepper': + return { + stroke: INPUT_SHAPE.DEFAULT_STROKE_COLOR, + backgroundColor: INPUT_SHAPE.DEFAULT_FILL_BACKGROUND, + textColor: INPUT_SHAPE.DEFAULT_FILL_TEXT, + strokeStyle: [], + }; case 'input': return { stroke: INPUT_SHAPE.DEFAULT_STROKE_COLOR, diff --git a/src/pods/canvas/shape-renderer/simple-rich-components/input-with-stepper.renderer.tsx b/src/pods/canvas/shape-renderer/simple-rich-components/input-with-stepper.renderer.tsx index 316825f8..d1a9d316 100644 --- a/src/pods/canvas/shape-renderer/simple-rich-components/input-with-stepper.renderer.tsx +++ b/src/pods/canvas/shape-renderer/simple-rich-components/input-with-stepper.renderer.tsx @@ -25,7 +25,7 @@ export const renderInputWithStepper = ( onDragEnd={handleDragEnd(shape.id)} onTransform={handleTransform} onTransformEnd={handleTransform} - OtherProps={shape.otherProps} + otherProps={shape.otherProps} /> ); }; From 77041fc61c84df94e2ad431e06de579701a21e1f Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Mon, 16 Sep 2024 19:23:09 +0200 Subject: [PATCH 05/12] Component now working with properties; improved state handling through props --- .../input-with-stepper.business.ts | 11 ++++ .../input-with-stepper/input-with-stepper.tsx | 58 ++++++++++++------- 2 files changed, 47 insertions(+), 22 deletions(-) diff --git a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts index 1db28855..28d53e39 100644 --- a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts @@ -8,8 +8,19 @@ export const useHandleCounterInputWithStepper = () => { }; const handleDecrement = () => { + if (value === 0) return; setValue(value - 1); }; return { value, handleIncrement, handleDecrement }; }; + +export const adjustAlignmentByDigitCount = (value: number): number => { + const pixelsToMove = 20; + + return value > 9 && value < 100 + ? pixelsToMove + 8 + : value > 99 + ? pixelsToMove + 16 + : pixelsToMove; +}; diff --git a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx index 6afedd59..2ecd8b94 100644 --- a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx @@ -5,16 +5,19 @@ import { ShapeType } from '../../../../core/model/index'; import { fitSizeToShapeSizeRestrictions } from '@/common/utils/shapes'; import { useShapeComponentSelection } from '../../shapes/use-shape-selection.hook'; import { ShapeProps } from '../../front-components/shape.model'; -import { useHandleCounterInputWithStepper } from './input-with-stepper.business'; +import { + adjustAlignmentByDigitCount, + useHandleCounterInputWithStepper, +} from './input-with-stepper.business'; import { INPUT_SHAPE } from '../../front-components/shape.const'; const inputWithStepperSizeRestrictions: ShapeSizeRestrictions = { minWidth: 100, - minHeight: 20, - maxWidth: 600, - maxHeight: 40, + minHeight: 38, + maxWidth: 250, + maxHeight: 50, defaultWidth: 150, - defaultHeight: 30, + defaultHeight: 38, }; export const getInputWithStepperSizeRestrictions = (): ShapeSizeRestrictions => @@ -58,11 +61,22 @@ export const InputWithStepperShape = forwardRef( [otherProps?.strokeStyle] ); - const inputWidth = restrictedWidth - 30; // Reservar espacio para el stepper + const inputWidth = restrictedWidth * 0.8; // Reservar espacio para el stepper + const buttonWidth = restrictedWidth * 0.2; const buttonHeight = restrictedHeight / 2; + const adjustAlignmentByDigits = adjustAlignmentByDigitCount(value); + return ( - + {/* Caja del input */} ( {/* Texto del input */} {/* Botón de incremento (flecha arriba) */} @@ -91,7 +105,7 @@ export const InputWithStepperShape = forwardRef( ( dash={strokeStyle} /> @@ -113,7 +127,7 @@ export const InputWithStepperShape = forwardRef( ( dash={strokeStyle} /> From 22097aebd74516cca086aebe75e6990bf51602a9 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Mon, 16 Sep 2024 19:41:49 +0200 Subject: [PATCH 06/12] small fixes --- .../input-with-stepper/input-with-stepper.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx index 2ecd8b94..02d77b1b 100644 --- a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx @@ -12,10 +12,10 @@ import { import { INPUT_SHAPE } from '../../front-components/shape.const'; const inputWithStepperSizeRestrictions: ShapeSizeRestrictions = { - minWidth: 100, + minWidth: 70, minHeight: 38, maxWidth: 250, - maxHeight: 50, + maxHeight: 38, defaultWidth: 150, defaultHeight: 38, }; @@ -95,7 +95,7 @@ export const InputWithStepperShape = forwardRef( y={restrictedHeight / 2 - 6} // Centrar verticalmente text={value.toString()} fontFamily={INPUT_SHAPE.DEFAULT_FONT_FAMILY} - fontSize={INPUT_SHAPE.DEFAULT_FONT_SIZE} + fontSize={INPUT_SHAPE.DEFAULT_FONT_SIZE + 2} fill={textColor} align="center" /> From 2bf54d89d17370ec3b9dba63a1660c554a192407 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Tue, 17 Sep 2024 13:22:23 +0200 Subject: [PATCH 07/12] inline edit in development --- .../input-with-stepper.business.ts | 4 ++-- .../input-with-stepper/input-with-stepper.tsx | 19 ++++++++++++------- src/pods/canvas/canvas.model.ts | 3 +++ .../input-with-stepper.renderer.tsx | 1 + 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts index 28d53e39..39833082 100644 --- a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts @@ -1,7 +1,7 @@ import React from 'react'; -export const useHandleCounterInputWithStepper = () => { - const [value, setValue] = React.useState(0); +export const useHandleCounterInputWithStepper = (text: string) => { + const [value, setValue] = React.useState(Number(text)); const handleIncrement = () => { setValue(value + 1); diff --git a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx index 02d77b1b..ed76cf2a 100644 --- a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx @@ -13,11 +13,11 @@ import { INPUT_SHAPE } from '../../front-components/shape.const'; const inputWithStepperSizeRestrictions: ShapeSizeRestrictions = { minWidth: 70, - minHeight: 38, + minHeight: 30, maxWidth: 250, - maxHeight: 38, + maxHeight: 30, defaultWidth: 150, - defaultHeight: 38, + defaultHeight: 30, }; export const getInputWithStepperSizeRestrictions = (): ShapeSizeRestrictions => @@ -27,8 +27,8 @@ const shapeType: ShapeType = 'inputWithStepper'; export const InputWithStepperShape = forwardRef( (props, ref) => { - const { x, y, width, height, id, otherProps, ...shapeProps } = props; - + const { x, y, width, height, id, text, otherProps, ...shapeProps } = props; + console.log(text); const { width: restrictedWidth, height: restrictedHeight } = fitSizeToShapeSizeRestrictions( inputWithStepperSizeRestrictions, @@ -39,7 +39,12 @@ export const InputWithStepperShape = forwardRef( const { handleSelection } = useShapeComponentSelection(props, shapeType); const { value, handleIncrement, handleDecrement } = - useHandleCounterInputWithStepper(); + useHandleCounterInputWithStepper(text); + + const value2 = useMemo( + () => (text !== '0' ? text : value.toString()), + [value, text] + ); const stroke = useMemo( () => otherProps?.stroke ?? INPUT_SHAPE.DEFAULT_STROKE_COLOR, @@ -93,7 +98,7 @@ export const InputWithStepperShape = forwardRef( { case 'buttonBar': case 'tabsBar': case 'tooltip': + case 'inputWithStepper': return true; default: return false; @@ -297,6 +298,8 @@ const generateTypeOfTransformer = (shapeType: ShapeType): string[] => { const generateDefaultTextValue = (shapeType: ShapeType): string | undefined => { switch (shapeType) { + case 'inputWithStepper': + return '0'; case 'input': return 'Placeholder'; case 'label': diff --git a/src/pods/canvas/shape-renderer/simple-rich-components/input-with-stepper.renderer.tsx b/src/pods/canvas/shape-renderer/simple-rich-components/input-with-stepper.renderer.tsx index d1a9d316..7767e288 100644 --- a/src/pods/canvas/shape-renderer/simple-rich-components/input-with-stepper.renderer.tsx +++ b/src/pods/canvas/shape-renderer/simple-rich-components/input-with-stepper.renderer.tsx @@ -26,6 +26,7 @@ export const renderInputWithStepper = ( onTransform={handleTransform} onTransformEnd={handleTransform} otherProps={shape.otherProps} + text={shape.text} /> ); }; From 3be388d3a6772e21c8f22553d22453f9fb6a49bf Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Tue, 17 Sep 2024 20:34:25 +0200 Subject: [PATCH 08/12] inline edition working --- .../input-with-stepper.business.ts | 63 ++++++++++++++++--- .../input-with-stepper/input-with-stepper.tsx | 29 ++++++--- 2 files changed, 73 insertions(+), 19 deletions(-) diff --git a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts index 39833082..0fc4b6d9 100644 --- a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts @@ -1,26 +1,69 @@ -import React from 'react'; +import React, { useEffect } from 'react'; -export const useHandleCounterInputWithStepper = (text: string) => { - const [value, setValue] = React.useState(Number(text)); +type MustBeANumberError = 'You must enter a number'; + +interface handleCounterInputWithStepperHook { + valueToString: string | MustBeANumberError; + handleIncrement: () => void; + handleDecrement: () => void; + isTextANumber: boolean; +} + +const MUST_BE_A_NUMBER: MustBeANumberError = 'You must enter a number'; + +export const useHandleCounterInputWithStepper = ( + text: string +): handleCounterInputWithStepperHook => { + const [value, setValue] = React.useState(0); + + const isTextANumber: boolean = !isNaN(Number(text)); + + useEffect(() => { + if (isTextANumber) { + setValue(Number(text)); + } else { + setValue(MUST_BE_A_NUMBER); + } + }, [text]); const handleIncrement = () => { - setValue(value + 1); + if (typeof value === 'number') { + setValue(value + 1); + } }; const handleDecrement = () => { - if (value === 0) return; - setValue(value - 1); + if (typeof value === 'number') { + if (value === 0) return; + setValue(value - 1); + } }; - return { value, handleIncrement, handleDecrement }; + const valueToString: string = + typeof value === 'string' ? value : value.toString(); + + return { + valueToString, + handleIncrement, + handleDecrement, + isTextANumber, + }; }; -export const adjustAlignmentByDigitCount = (value: number): number => { +export const adjustAlignmentByDigitCount = ( + value: string | MustBeANumberError +): number => { + const valueToNumber = Number(value); + + if (isNaN(valueToNumber)) { + return 20; + } + const pixelsToMove = 20; - return value > 9 && value < 100 + return valueToNumber > 9 && valueToNumber < 100 ? pixelsToMove + 8 - : value > 99 + : valueToNumber > 99 ? pixelsToMove + 16 : pixelsToMove; }; diff --git a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx index ed76cf2a..b9885e74 100644 --- a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx @@ -28,7 +28,7 @@ const shapeType: ShapeType = 'inputWithStepper'; export const InputWithStepperShape = forwardRef( (props, ref) => { const { x, y, width, height, id, text, otherProps, ...shapeProps } = props; - console.log(text); + const { width: restrictedWidth, height: restrictedHeight } = fitSizeToShapeSizeRestrictions( inputWithStepperSizeRestrictions, @@ -38,13 +38,12 @@ export const InputWithStepperShape = forwardRef( const { handleSelection } = useShapeComponentSelection(props, shapeType); - const { value, handleIncrement, handleDecrement } = - useHandleCounterInputWithStepper(text); - - const value2 = useMemo( - () => (text !== '0' ? text : value.toString()), - [value, text] - ); + const { + valueToString: value, + handleIncrement, + handleDecrement, + isTextANumber, + } = useHandleCounterInputWithStepper(text); const stroke = useMemo( () => otherProps?.stroke ?? INPUT_SHAPE.DEFAULT_STROKE_COLOR, @@ -98,7 +97,7 @@ export const InputWithStepperShape = forwardRef( ( fill={textColor} /> + {!isTextANumber && ( + + + + )} ); } From d8cfa8e9df8662670ac72645c7062d7cc4c22158 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Tue, 17 Sep 2024 21:39:07 +0200 Subject: [PATCH 09/12] number() changed for parseInt in inputWithStepper.business --- .../input-with-stepper.business.ts | 14 ++++++++------ .../input-with-stepper/input-with-stepper.tsx | 4 ++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts index 0fc4b6d9..90fbebda 100644 --- a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts @@ -1,6 +1,8 @@ import React, { useEffect } from 'react'; -type MustBeANumberError = 'You must enter a number'; +type MustBeANumberError = + | 'You must enter a number' + | 'You must enter a integer number'; interface handleCounterInputWithStepperHook { valueToString: string | MustBeANumberError; @@ -16,11 +18,11 @@ export const useHandleCounterInputWithStepper = ( ): handleCounterInputWithStepperHook => { const [value, setValue] = React.useState(0); - const isTextANumber: boolean = !isNaN(Number(text)); + const isTextANumber: boolean = !isNaN(parseInt(text)); useEffect(() => { if (isTextANumber) { - setValue(Number(text)); + setValue(parseInt(text)); } else { setValue(MUST_BE_A_NUMBER); } @@ -55,12 +57,12 @@ export const adjustAlignmentByDigitCount = ( ): number => { const valueToNumber = Number(value); + const pixelsToMove = 20; + if (isNaN(valueToNumber)) { - return 20; + return pixelsToMove; } - const pixelsToMove = 20; - return valueToNumber > 9 && valueToNumber < 100 ? pixelsToMove + 8 : valueToNumber > 99 diff --git a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx index b9885e74..87c93b0b 100644 --- a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx @@ -97,7 +97,7 @@ export const InputWithStepperShape = forwardRef( ( Date: Wed, 18 Sep 2024 11:53:51 +0200 Subject: [PATCH 10/12] .. --- .../input-with-stepper.business.ts | 12 ++++++------ .../input-with-stepper/input-with-stepper.tsx | 4 ++-- src/pods/canvas/canvas.model.ts | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts index 90fbebda..c3c80bf4 100644 --- a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts @@ -1,8 +1,6 @@ import React, { useEffect } from 'react'; -type MustBeANumberError = - | 'You must enter a number' - | 'You must enter a integer number'; +type MustBeANumberError = 'You must enter a number'; interface handleCounterInputWithStepperHook { valueToString: string | MustBeANumberError; @@ -18,11 +16,13 @@ export const useHandleCounterInputWithStepper = ( ): handleCounterInputWithStepperHook => { const [value, setValue] = React.useState(0); - const isTextANumber: boolean = !isNaN(parseInt(text)); + const textToNumber = parseInt(text); + + const isTextANumber: boolean = !isNaN(textToNumber); useEffect(() => { if (isTextANumber) { - setValue(parseInt(text)); + setValue(textToNumber); } else { setValue(MUST_BE_A_NUMBER); } @@ -55,7 +55,7 @@ export const useHandleCounterInputWithStepper = ( export const adjustAlignmentByDigitCount = ( value: string | MustBeANumberError ): number => { - const valueToNumber = Number(value); + const valueToNumber = parseInt(value); const pixelsToMove = 20; diff --git a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx index 87c93b0b..1c850ae8 100644 --- a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx @@ -14,7 +14,7 @@ import { INPUT_SHAPE } from '../../front-components/shape.const'; const inputWithStepperSizeRestrictions: ShapeSizeRestrictions = { minWidth: 70, minHeight: 30, - maxWidth: 250, + maxWidth: 500, maxHeight: 30, defaultWidth: 150, defaultHeight: 30, @@ -65,7 +65,7 @@ export const InputWithStepperShape = forwardRef( [otherProps?.strokeStyle] ); - const inputWidth = restrictedWidth * 0.8; // Reservar espacio para el stepper + const inputWidth = restrictedWidth - 30; // Reservar espacio para el stepper const buttonWidth = restrictedWidth * 0.2; const buttonHeight = restrictedHeight / 2; diff --git a/src/pods/canvas/canvas.model.ts b/src/pods/canvas/canvas.model.ts index 9b5cecae..e054b045 100644 --- a/src/pods/canvas/canvas.model.ts +++ b/src/pods/canvas/canvas.model.ts @@ -298,8 +298,6 @@ const generateTypeOfTransformer = (shapeType: ShapeType): string[] => { const generateDefaultTextValue = (shapeType: ShapeType): string | undefined => { switch (shapeType) { - case 'inputWithStepper': - return '0'; case 'input': return 'Placeholder'; case 'label': @@ -350,6 +348,8 @@ const generateDefaultTextValue = (shapeType: ShapeType): string | undefined => { return 'Button 1, Button 2, Button 3'; case 'tabsBar': return 'Tab 1, Tab 2, Tab 3'; + case 'inputWithStepper': + return '0'; default: return undefined; } From e93ef712cb7bca3413209cdad15abde370811769 Mon Sep 17 00:00:00 2001 From: Rodrigo Date: Wed, 18 Sep 2024 12:29:24 +0200 Subject: [PATCH 11/12] finished --- .../input-with-stepper.business.ts | 18 ----------------- .../input-with-stepper/input-with-stepper.tsx | 20 ++++++++----------- 2 files changed, 8 insertions(+), 30 deletions(-) diff --git a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts index c3c80bf4..59411d30 100644 --- a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts @@ -51,21 +51,3 @@ export const useHandleCounterInputWithStepper = ( isTextANumber, }; }; - -export const adjustAlignmentByDigitCount = ( - value: string | MustBeANumberError -): number => { - const valueToNumber = parseInt(value); - - const pixelsToMove = 20; - - if (isNaN(valueToNumber)) { - return pixelsToMove; - } - - return valueToNumber > 9 && valueToNumber < 100 - ? pixelsToMove + 8 - : valueToNumber > 99 - ? pixelsToMove + 16 - : pixelsToMove; -}; diff --git a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx index 1c850ae8..1fc23778 100644 --- a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx @@ -5,10 +5,7 @@ import { ShapeType } from '../../../../core/model/index'; import { fitSizeToShapeSizeRestrictions } from '@/common/utils/shapes'; import { useShapeComponentSelection } from '../../shapes/use-shape-selection.hook'; import { ShapeProps } from '../../front-components/shape.model'; -import { - adjustAlignmentByDigitCount, - useHandleCounterInputWithStepper, -} from './input-with-stepper.business'; +import { useHandleCounterInputWithStepper } from './input-with-stepper.business'; import { INPUT_SHAPE } from '../../front-components/shape.const'; const inputWithStepperSizeRestrictions: ShapeSizeRestrictions = { @@ -65,12 +62,10 @@ export const InputWithStepperShape = forwardRef( [otherProps?.strokeStyle] ); - const inputWidth = restrictedWidth - 30; // Reservar espacio para el stepper + const inputWidth = restrictedWidth * 0.8; // Reservar espacio para el stepper const buttonWidth = restrictedWidth * 0.2; const buttonHeight = restrictedHeight / 2; - const adjustAlignmentByDigits = adjustAlignmentByDigitCount(value); - return ( ( ( {/* Texto del input */} {/* Botón de incremento (flecha arriba) */} - + ( {/* Botón de decremento (flecha abajo) */} - + Date: Wed, 18 Sep 2024 13:16:26 +0200 Subject: [PATCH 12/12] event double click on buttons handled --- .../input-with-stepper.business.ts | 10 +++++ .../input-with-stepper/input-with-stepper.tsx | 43 +++++++++++++------ 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts index 59411d30..50c75d65 100644 --- a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.business.ts @@ -51,3 +51,13 @@ export const useHandleCounterInputWithStepper = ( isTextANumber, }; }; + +export const handleButtonWidth = (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; +}; diff --git a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx index 1fc23778..2f08a18a 100644 --- a/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx +++ b/src/common/components/front-rich-components/input-with-stepper/input-with-stepper.tsx @@ -5,16 +5,20 @@ import { ShapeType } from '../../../../core/model/index'; import { fitSizeToShapeSizeRestrictions } from '@/common/utils/shapes'; import { useShapeComponentSelection } from '../../shapes/use-shape-selection.hook'; import { ShapeProps } from '../../front-components/shape.model'; -import { useHandleCounterInputWithStepper } from './input-with-stepper.business'; +import { + handleButtonWidth, + useHandleCounterInputWithStepper, +} from './input-with-stepper.business'; import { INPUT_SHAPE } from '../../front-components/shape.const'; +import { KonvaEventObject } from 'konva/lib/Node'; const inputWithStepperSizeRestrictions: ShapeSizeRestrictions = { - minWidth: 70, - minHeight: 30, + minWidth: 60, + minHeight: 35, maxWidth: 500, - maxHeight: 30, - defaultWidth: 150, - defaultHeight: 30, + maxHeight: 35, + defaultWidth: 100, + defaultHeight: 35, }; export const getInputWithStepperSizeRestrictions = (): ShapeSizeRestrictions => @@ -35,6 +39,9 @@ export const InputWithStepperShape = forwardRef( const { handleSelection } = useShapeComponentSelection(props, shapeType); + const handleDoubleClickInButtons = (e: KonvaEventObject) => + (e.cancelBubble = true); + const { valueToString: value, handleIncrement, @@ -62,8 +69,8 @@ export const InputWithStepperShape = forwardRef( [otherProps?.strokeStyle] ); - const inputWidth = restrictedWidth * 0.8; // Reservar espacio para el stepper - const buttonWidth = restrictedWidth * 0.2; + // Reservar espacio para el stepper + const buttonWidth = handleButtonWidth(restrictedWidth); const buttonHeight = restrictedHeight / 2; return ( @@ -80,7 +87,7 @@ export const InputWithStepperShape = forwardRef( ( {/* Texto del input */} ( /> {/* Botón de incremento (flecha arriba) */} - + ( fontFamily={INPUT_SHAPE.DEFAULT_FONT_FAMILY} fontSize={INPUT_SHAPE.DEFAULT_FONT_SIZE} fill={textColor} + align="center" /> {/* Botón de decremento (flecha abajo) */} - + ( fontFamily={INPUT_SHAPE.DEFAULT_FONT_FAMILY} fontSize={INPUT_SHAPE.DEFAULT_FONT_SIZE} fill={textColor} + align="center" /> {!isTextANumber && (