11// SlashMenu.tsx
2- import React , { useEffect , useState } from "react" ;
2+ import React , { useEffect , useState , useRef } from "react" ;
33import ImageUploadComponent from "@/composable/ImageUpload" ;
44import FileUploadComponent from "@/composable/FileUpload" ;
55import VideoUploadComponent from "@/composable/VideoUpload" ;
@@ -38,6 +38,7 @@ const Commands: React.FC<SlashMenuProps> = ({
3838 menu : { } ,
3939 } ) ;
4040 const [ selectedIndex , setSelectedIndex ] = useState ( 0 ) ;
41+ const menuRef = useRef < HTMLDivElement > ( null ) ;
4142
4243 useEffect ( ( ) => {
4344 const fetchTranslations = async ( ) => {
@@ -49,6 +50,28 @@ const Commands: React.FC<SlashMenuProps> = ({
4950 fetchTranslations ( ) ;
5051 } , [ ] ) ;
5152
53+ // Position adjustment effect
54+ useEffect ( ( ) => {
55+ if ( menuRef . current ) {
56+ const menu = menuRef . current ;
57+ const rect = menu . getBoundingClientRect ( ) ;
58+ const windowHeight = window . innerHeight ;
59+ const windowWidth = window . innerWidth ;
60+
61+ // Adjust vertical position if menu goes below viewport
62+ if ( rect . bottom > windowHeight ) {
63+ menu . style . transform = `translateY(-${ rect . height + 10 } px)` ;
64+ }
65+
66+ // Adjust horizontal position if menu goes beyond viewport
67+ if ( rect . right > windowWidth ) {
68+ menu . style . transform = `${ menu . style . transform || "" } translateX(-${
69+ rect . right - windowWidth + 20
70+ } px)`;
71+ }
72+ }
73+ } , [ query ] ) ; // Re-run when query changes as menu size might change
74+
5275 const handlefileUpload = ( fileUrl : string , fileName : string ) => {
5376 editor . commands . deleteRange ( range ) . run ( ) ;
5477 editor ?. chain ( ) . setFileEmbed ( fileUrl , fileName ) . run ( ) ;
@@ -414,32 +437,39 @@ const Commands: React.FC<SlashMenuProps> = ({
414437 } , [ filteredItems . length ] ) ;
415438
416439 return (
417- < UiList className = "z-50 fixed rounded-lg shadow-lg border shadow-xl dark:border-neutral-600 p-2" >
418- { filteredItems . map ( ( item , index ) => (
419- < UiListItem
420- key = { item . id }
421- onClick = { ( ) => handleSelect ( { item } ) }
422- active = { index === selectedIndex }
423- className = "cursor-pointer"
424- >
425- { item . type === "upload" && item . component ? (
426- item . component
427- ) : (
428- < div className = "flex items-center rounded-lg transition" >
429- < div className = "text-left flex overflow-hidden text-ellipsis whitespace-nowrap" >
430- < Icon
431- name = { item . icon as IconName }
432- className = { `mr-2 ltr:ml-2 text-lg ${ item . className || "" } ` }
433- />
434- < h3 className = "text-lg font-medium" >
435- { item . label }
436- </ h3 >
440+ < div
441+ ref = { menuRef }
442+ style = { {
443+ maxWidth : "300px" , // Prevent excessive width
444+ maxHeight : "400px" , // Prevent excessive height
445+ overflow : "auto" , // Allow scrolling if needed
446+ } }
447+ >
448+ < UiList className = "z-50 rounded-lg shadow-lg border shadow-xl dark:border-neutral-600 p-2 bg-white dark:bg-neutral-800" >
449+ { filteredItems . map ( ( item , index ) => (
450+ < UiListItem
451+ key = { item . id }
452+ onClick = { ( ) => handleSelect ( { item } ) }
453+ active = { index === selectedIndex }
454+ className = "cursor-pointer"
455+ >
456+ { item . type === "upload" && item . component ? (
457+ item . component
458+ ) : (
459+ < div className = "flex items-center rounded-lg transition" >
460+ < div className = "text-left flex overflow-hidden text-ellipsis whitespace-nowrap" >
461+ < Icon
462+ name = { item . icon as IconName }
463+ className = { `mr-2 ltr:ml-2 text-lg ${ item . className || "" } ` }
464+ />
465+ < h3 className = "text-lg font-medium" > { item . label } </ h3 >
466+ </ div >
437467 </ div >
438- </ div >
439- ) }
440- </ UiListItem >
441- ) ) }
442- </ UiList >
468+ ) }
469+ </ UiListItem >
470+ ) ) }
471+ </ UiList >
472+ </ div >
443473 ) ;
444474} ;
445475
0 commit comments