diff --git a/src/pages/editor-page/canvas/area-node/area-node-context-menu.tsx b/src/pages/editor-page/canvas/area-node/area-node-context-menu.tsx new file mode 100644 index 00000000..c1aeca67 --- /dev/null +++ b/src/pages/editor-page/canvas/area-node/area-node-context-menu.tsx @@ -0,0 +1,54 @@ +import { + ContextMenu, + ContextMenuContent, + ContextMenuItem, + ContextMenuTrigger, +} from '@/components/context-menu/context-menu'; +import { useBreakpoint } from '@/hooks/use-breakpoint'; +import { useChartDB } from '@/hooks/use-chartdb'; +import type { Area } from '@/lib/domain/area'; +import { Pencil, Trash2 } from 'lucide-react'; +import React, { useCallback } from 'react'; + +export interface AreaNodeContextMenuProps { + area: Area; + onEditName?: () => void; +} + +export const AreaNodeContextMenu: React.FC< + React.PropsWithChildren +> = ({ children, area, onEditName }) => { + const { removeArea, readonly } = useChartDB(); + const { isMd: isDesktop } = useBreakpoint('md'); + + const removeAreaHandler = useCallback(() => { + removeArea(area.id); + }, [removeArea, area.id]); + + if (!isDesktop || readonly) { + return <>{children}; + } + return ( + + {children} + + {onEditName ? ( + + Edit Area Name + + + ) : null} + + Delete Area + + + + + ); +}; diff --git a/src/pages/editor-page/canvas/area-node/area-node.tsx b/src/pages/editor-page/canvas/area-node/area-node.tsx index 1164dbf4..4d3dd186 100644 --- a/src/pages/editor-page/canvas/area-node/area-node.tsx +++ b/src/pages/editor-page/canvas/area-node/area-node.tsx @@ -12,9 +12,10 @@ import { } from '@/components/tooltip/tooltip'; import { useTranslation } from 'react-i18next'; import { cn } from '@/lib/utils'; -import { Check, GripVertical } from 'lucide-react'; +import { Check, GripVertical, Pencil } from 'lucide-react'; import { Button } from '@/components/button/button'; import { useLayout } from '@/hooks/use-layout'; +import { AreaNodeContextMenu } from './area-node-context-menu'; export type AreaNodeType = Node< { @@ -62,79 +63,93 @@ export const AreaNode: React.FC> = React.memo( }; return ( -
{ - if (e.detail === 2) { - openAreaInEditor(); - } - }} + setEditMode(true)} > - {!readonly ? ( - - ) : null} -
-
- +
{ + if (e.detail === 2) { + openAreaInEditor(); + } + }} + > + {!readonly ? ( + + ) : null} +
+
+ - {editMode && !readonly ? ( -
- e.stopPropagation()} - onChange={(e) => - setAreaName(e.target.value) - } - className="h-6 bg-white/70 focus-visible:ring-0 dark:bg-slate-900/70" - /> + {editMode && !readonly ? ( +
+ e.stopPropagation()} + onChange={(e) => + setAreaName(e.target.value) + } + className="h-6 bg-white/70 focus-visible:ring-0 dark:bg-slate-900/70" + /> + +
+ ) : !readonly ? ( + + +
+ {area.name} +
+
+ + {t('tool_tips.double_click_to_edit')} + +
+ ) : ( +
+ {area.name} +
+ )} + {!editMode && !readonly && ( -
- ) : !readonly ? ( - - -
- {area.name} -
-
- - {t('tool_tips.double_click_to_edit')} - -
- ) : ( -
- {area.name} -
- )} + )} +
+
-
-
+ ); } ); diff --git a/src/pages/editor-page/top-navbar/diagram-name.tsx b/src/pages/editor-page/top-navbar/diagram-name.tsx index a3a6fb0a..d381f462 100644 --- a/src/pages/editor-page/top-navbar/diagram-name.tsx +++ b/src/pages/editor-page/top-navbar/diagram-name.tsx @@ -1,6 +1,6 @@ import React, { useCallback, useEffect, useState } from 'react'; import { Button } from '@/components/button/button'; -import { Check } from 'lucide-react'; +import { Check, Pencil } from 'lucide-react'; import { Input } from '@/components/input/input'; import { useChartDB } from '@/hooks/use-chartdb'; import { useClickAway, useKeyPressEvent } from 'react-use'; @@ -32,22 +32,39 @@ export const DiagramName: React.FC = () => { }, [diagramName]); const editDiagramName = useCallback(() => { - if (!editMode) return; if (editedDiagramName.trim()) { updateDiagramName(editedDiagramName.trim()); } setEditMode(false); - }, [editedDiagramName, updateDiagramName, editMode]); + }, [editedDiagramName, updateDiagramName]); + // Handle click outside to save and exit edit mode useClickAway(inputRef, editDiagramName); + useKeyPressEvent('Enter', editDiagramName); - const enterEditMode = ( - event: React.MouseEvent - ) => { - event.stopPropagation(); - setEditMode(true); - }; + useEffect(() => { + if (editMode) { + // Small delay to ensure the input is rendered + const timeoutId = setTimeout(() => { + if (inputRef.current) { + inputRef.current.focus(); + inputRef.current.select(); + } + }, 50); // Slightly longer delay to ensure DOM is ready + + return () => clearTimeout(timeoutId); + } + }, [editMode]); + + const enterEditMode = useCallback( + (event: React.MouseEvent) => { + event.stopPropagation(); + setEditedDiagramName(diagramName); + setEditMode(true); + }, + [diagramName] + ); return (
@@ -80,11 +97,16 @@ export const DiagramName: React.FC = () => { onChange={(e) => setEditedDiagramName(e.target.value) } - className="ml-1 h-7 focus-visible:ring-0" + className="h-7 max-w-[300px] focus-visible:ring-0" + style={{ + width: `${ + editedDiagramName.length * 8 + 30 + }px`, + }} /> )}