Skip to content

Commit

Permalink
add textarea to inline edit
Browse files Browse the repository at this point in the history
  • Loading branch information
Franlop7 committed Aug 9, 2024
1 parent 1ff4d35 commit 6a96c56
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 23 deletions.
4 changes: 2 additions & 2 deletions src/common/components/front-components/textarea-shape.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const getTextAreaSizeRestrictions = (): ShapeSizeRestrictions =>
textAreaShapeRestrictions;

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

Expand Down Expand Up @@ -47,7 +47,7 @@ export const TextAreaShape = forwardRef<any, ShapeProps>(
y={10}
width={width}
height={height - 10}
text="Your text here..."
text={text}
fontFamily="Comic Sans MS, cursive"
fontSize={15}
fill="gray"
Expand Down
59 changes: 40 additions & 19 deletions src/common/components/inline-edit/inline-edit.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,52 @@
import { Coord, Size } from '@/core/model';
import { Coord, EditType, Size } from '@/core/model';
import React, { useEffect, useRef, useState } from 'react';
import { Group } from 'react-konva';
import { Html } from 'react-konva-utils';

type EditType = 'input' | 'textarea';

interface Props {
coords: Coord;
size: Size;
isEditable: boolean;
editType: EditType;
editType?: EditType;
text: string;
scale: number;
onTextSubmit: (text: string) => void;
children: React.ReactNode;
}

export const EditableComponent: React.FC<Props> = props => {
const { coords, size, isEditable, text, onTextSubmit, scale, children } =
props;
const {
coords,
size,
isEditable,
text,
onTextSubmit,
scale,
children,
editType,
} = props;
const [isEditing, setIsEditing] = useState(false);
const [editText, setEditText] = useState(text);

const inputRef = useRef<HTMLInputElement>(null);
const textAreaRef = useRef<HTMLTextAreaElement>(null);

const getActiveInputRef = ():
| HTMLInputElement
| HTMLTextAreaElement
| null => (editType === 'input' ? inputRef.current : textAreaRef.current);

// handle click outside of the input when editing
useEffect(() => {
if (!isEditable) return;

const handleClickOutside = (event: MouseEvent) => {
if (
inputRef.current &&
!inputRef.current.contains(event.target as Node)
getActiveInputRef() &&
!getActiveInputRef()?.contains(event.target as Node)
) {
setIsEditing(false);
onTextSubmit(inputRef.current?.value || '');
onTextSubmit(getActiveInputRef()?.value || '');
}
};

Expand All @@ -44,15 +56,15 @@ export const EditableComponent: React.FC<Props> = props => {
setEditText(text);
}

if (isEditing && event.key === 'Enter') {
if (editType === 'input' && isEditable && event.key === 'Enter') {
setIsEditing(false);
onTextSubmit(inputRef.current?.value || '');
onTextSubmit(getActiveInputRef()?.value || '');
}
};

if (isEditing) {
inputRef.current?.focus();
inputRef.current?.select();
getActiveInputRef()?.focus();
getActiveInputRef()?.select();
document.addEventListener('mousedown', handleClickOutside);
document.addEventListener('keydown', handleKeyDown);
} else {
Expand Down Expand Up @@ -107,12 +119,21 @@ export const EditableComponent: React.FC<Props> = props => {
},
}}
>
<input
ref={inputRef}
style={{ width: '100%', height: '100%' }}
value={editText}
onChange={e => setEditText(e.target.value)}
/>
{editType === 'input' ? (
<input
ref={inputRef}
style={{ width: '100%', height: '100%' }}
value={editText}
onChange={e => setEditText(e.target.value)}
/>
) : (
<textarea
ref={textAreaRef}
style={{ width: '100%', height: '100%' }}
value={editText}
onChange={e => setEditText(e.target.value)}
></textarea>
)}
</Html>
) : null}
</>
Expand Down
3 changes: 3 additions & 0 deletions src/core/model/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export type ShapeType =
| 'rectangle';
/* | "text"| "button" | "radio" | "image"*/

export type EditType = 'input' | 'textarea';

export type ShapeRefs = {
[key: string]: React.RefObject<any>;
};
Expand All @@ -49,5 +51,6 @@ export interface ShapeModel {
height: number;
type: ShapeType;
allowsInlineEdition: boolean;
editType?: EditType;
text?: string;
}
17 changes: 16 additions & 1 deletion src/pods/canvas/canvas.model.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Coord, ShapeType, Size, ShapeModel } from '@/core/model';
import { Coord, ShapeType, Size, ShapeModel, EditType } from '@/core/model';
import { v4 as uuidv4 } from 'uuid';

import {
Expand Down Expand Up @@ -104,6 +104,7 @@ const doesShapeAllowInlineEdition = (shapeType: ShapeType): boolean => {
case 'label':
case 'combobox':
case 'button':
case 'textarea':
return true;
default:
return false;
Expand All @@ -120,11 +121,24 @@ const generateDefaultTextValue = (shapeType: ShapeType): string | undefined => {
return 'Select an option';
case 'button':
return 'Click Me!';
case 'textarea':
return 'Your text here...';
default:
return undefined;
}
};

const getShapeEditInlineType = (shapeType: ShapeType): EditType | undefined => {
const result = undefined;

switch (shapeType) {
case 'textarea':
return 'textarea';
break;
}
return result;
};

// TODO: create interfaces to hold Coordination and Size
// coordinate: { x: number, y: number }
// size: { width: number, height: number }
Expand All @@ -141,6 +155,7 @@ export const createShape = (coord: Coord, shapeType: ShapeType): ShapeModel => {
type: shapeType,
allowsInlineEdition: doesShapeAllowInlineEdition(shapeType),
text: generateDefaultTextValue(shapeType),
editType: getShapeEditInlineType(shapeType),
};
};

Expand Down
2 changes: 1 addition & 1 deletion src/pods/canvas/canvas.pod.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ export const CanvasPod = () => {
text={shape.text ?? ''}
onTextSubmit={updateTextOnSelected}
scale={scale}
editType="input"
editType={shape.editType ?? 'input'}
>
{renderShapeComponent(shape, {
handleSelected,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ export const renderTextArea = (
onDragEnd={handleDragEnd(shape.id)}
onTransform={handleTransform}
onTransformEnd={handleTransform}
editType={shape.editType}
isEditable={shape.editType}
text={shape.text}
/>
);
};

0 comments on commit 6a96c56

Please sign in to comment.