From d6c0fe7d4eb96e40daeb59140c24a4b5cb75c0b0 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Thu, 9 Oct 2025 16:30:12 -0300 Subject: [PATCH] feat: implement viewport clamping for menu positioning in SuperDocTemplateBuilder This commit adds a new utility function, clampToViewport, to ensure that the menu is positioned within the visible area of the viewport. The function adjusts the menu's coordinates based on predefined padding and approximate dimensions, enhancing the user experience by preventing overflow. --- src/index.tsx | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 197da12..5301516 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -97,6 +97,26 @@ const resolveToolbar = ( }; }; +const MENU_VIEWPORT_PADDING = 10; +const MENU_APPROX_WIDTH = 250; +const MENU_APPROX_HEIGHT = 300; + +const clampToViewport = (rect: DOMRect): DOMRect => { + const maxLeft = window.innerWidth - MENU_APPROX_WIDTH - MENU_VIEWPORT_PADDING; + const maxTop = + window.innerHeight - MENU_APPROX_HEIGHT - MENU_VIEWPORT_PADDING; + + const clampedLeft = Math.min(rect.left, maxLeft); + const clampedTop = Math.min(rect.top, maxTop); + + return new DOMRect( + Math.max(clampedLeft, MENU_VIEWPORT_PADDING), + Math.max(clampedTop, MENU_VIEWPORT_PADDING), + rect.width, + rect.height, + ); +}; + const SuperDocTemplateBuilder = forwardRef< Types.SuperDocTemplateBuilderHandle, Types.SuperDocTemplateBuilderProps @@ -385,7 +405,9 @@ const SuperDocTemplateBuilder = forwardRef< if (text === trigger) { const coords = e.view.coordsAtPos(from); - const bounds = new DOMRect(coords.left, coords.top, 0, 0); + const bounds = clampToViewport( + new DOMRect(coords.left, coords.top, 0, 0), + ); const cleanup = () => { const editor = superdocRef.current?.activeEditor; @@ -435,7 +457,9 @@ const SuperDocTemplateBuilder = forwardRef< updateMenuFilter(queryText); const coords = e.view.coordsAtPos(from); - const bounds = new DOMRect(coords.left, coords.top, 0, 0); + const bounds = clampToViewport( + new DOMRect(coords.left, coords.top, 0, 0), + ); setMenuPosition(bounds); });