@@ -8,7 +8,7 @@ import { AttributeType, EntityType, GroupType } from "@/lib/Types";
88import { updateURL } from "@/lib/url-utils" ;
99import { copyToClipboard , generateGroupLink } from "@/lib/clipboard-utils" ;
1010import { useSnackbar } from "@/contexts/SnackbarContext" ;
11- import { debounce , Tooltip } from '@mui/material' ;
11+ import { Box , CircularProgress , debounce , Tooltip } from '@mui/material' ;
1212
1313interface IListProps {
1414 setCurrentIndex : ( index : number ) => void ;
@@ -24,16 +24,13 @@ export function highlightMatch(text: string, search: string) {
2424
2525export const List = ( { setCurrentIndex } : IListProps ) => {
2626 const dispatch = useDatamodelViewDispatch ( ) ;
27- const { currentSection } = useDatamodelView ( ) ;
27+ const { currentSection, loadingSection } = useDatamodelView ( ) ;
2828 const { groups, filtered, search } = useDatamodelData ( ) ;
2929 const { showSnackbar } = useSnackbar ( ) ;
3030 const parentRef = useRef < HTMLDivElement | null > ( null ) ;
3131 // used to relocate section after search/filter
3232 const [ sectionVirtualItem , setSectionVirtualItem ] = useState < string | null > ( null ) ;
33-
34- // Track position before search for restoration
35- const isTabSwitching = useRef ( false ) ;
36-
33+
3734 const handleCopyGroupLink = useCallback ( async ( groupName : string ) => {
3835 const link = generateGroupLink ( groupName ) ;
3936 const success = await copyToClipboard ( link ) ;
@@ -163,8 +160,7 @@ export const List = ({ setCurrentIndex }: IListProps) => {
163160 }
164161
165162 rowVirtualizer . scrollToIndex ( sectionIndex , {
166- align : 'start' ,
167- behavior : 'smooth'
163+ align : 'start'
168164 } ) ;
169165
170166 } , [ flatItems ] ) ;
@@ -180,8 +176,7 @@ export const List = ({ setCurrentIndex }: IListProps) => {
180176 }
181177
182178 rowVirtualizer . scrollToIndex ( groupIndex , {
183- align : 'start' ,
184- behavior : 'smooth'
179+ align : 'start'
185180 } ) ;
186181 } , [ flatItems ] ) ;
187182
@@ -208,85 +203,85 @@ export const List = ({ setCurrentIndex }: IListProps) => {
208203 } , [ rowVirtualizer ] ) ;
209204
210205 return (
211- < div ref = { parentRef } style = { { height : 'calc(100vh - var(--layout-header-desktop-height))' , overflow : 'auto' } } className = "p-6 relative no-scrollbar" >
206+ < >
207+ < Box className = { `absolute w-full h-full flex items-center justify-center z-[100] transition-opacity duration-300 ${ loadingSection ? 'opacity-100' : 'opacity-0 pointer-events-none' } ` } >
208+ < CircularProgress />
209+ </ Box >
210+ < div ref = { parentRef } style = { { height : 'calc(100vh - var(--layout-header-desktop-height))' , overflow : 'auto' } } className = "relative no-scrollbar" >
212211
213- { /* Show no results message when searching but no items found */ }
214- { flatItems . length === 0 && search && search . length >= 3 && (
215- < div className = "flex flex-col items-center justify-center h-64 text-gray-500" >
216- < div className = "text-lg font-medium mb-2" > No tables found</ div >
217- < div className = "text-sm text-center" >
218- No attributes match your search for "{ search } "
212+ { /* Show no results message when searching but no items found */ }
213+ { flatItems . length === 0 && search && search . length >= 3 && (
214+ < div className = "flex flex-col items-center justify-center h-64 text-gray-500" >
215+ < div className = "text-lg font-medium mb-2" > No tables found</ div >
216+ < div className = "text-sm text-center" >
217+ No attributes match your search for "{ search } "
218+ </ div >
219219 </ div >
220- </ div >
221- ) }
222-
223- { /* Virtualized list */ }
224- < div
225- style = { {
226- height : `${ rowVirtualizer . getTotalSize ( ) } px` ,
227- width : '100%' ,
228- position : 'relative' ,
229- visibility : flatItems . length === 0 ? 'hidden' : 'visible'
230- } }
231- >
232- { rowVirtualizer . getVirtualItems ( ) . map ( ( virtualItem ) => {
233- const item = flatItems [ virtualItem . index ] ;
220+ ) }
221+
222+ { /* Virtualized list */ }
223+ < div
224+ className = { `m-6 transition-opacity duration-300 ${ loadingSection ? 'opacity-0 pointer-events-none' : 'opacity-100' } ` }
225+ style = { {
226+ height : `${ rowVirtualizer . getTotalSize ( ) } px` ,
227+ width : '100%' ,
228+ position : 'relative' ,
229+ visibility : flatItems . length === 0 ? 'hidden' : 'visible'
230+ } }
231+ >
232+ { rowVirtualizer . getVirtualItems ( ) . map ( ( virtualItem ) => {
233+ const item = flatItems [ virtualItem . index ] ;
234234
235- return (
236- < div
237- key = { virtualItem . key }
238- data-index = { virtualItem . index }
239- style = { {
240- position : 'absolute' ,
241- top : 0 ,
242- left : 0 ,
243- width : '100%' ,
244- transform : `translateY(${ virtualItem . start } px)` ,
245- } }
246- ref = { ( el ) => {
247- if ( el ) {
248- // trigger remeasurement when content changes and load
249- requestAnimationFrame ( ( ) => {
250- handleSectionResize ( virtualItem . index ) ;
251- } ) ;
252- }
253- } }
254- >
255- { item . type === 'group' ? (
256- < div className = "flex items-center py-6 my-4" >
257- < div className = "flex-1 h-0.5 bg-gray-200" />
258- < Tooltip title = "Copy link to this group" >
259- < div
260- className = "px-4 text-md font-semibold text-gray-700 uppercase tracking-wide whitespace-nowrap cursor-pointer hover:text-blue-600 transition-colors"
261- onClick = { ( ) => handleCopyGroupLink ( item . group . Name ) }
262- >
263- { item . group . Name }
264- </ div >
265- </ Tooltip >
266- < div className = "flex-1 h-0.5 bg-gray-200" />
267- </ div >
268- ) : (
269- < div className = "text-sm" >
270- < Section
271- entity = { item . entity }
272- group = { item . group }
273- onTabChange = { ( isChanging : boolean ) => {
274- isTabSwitching . current = isChanging ;
275- if ( isChanging ) {
276- // Reset after a short delay to allow for the content change
277- setTimeout ( ( ) => {
278- isTabSwitching . current = false ;
279- } , 100 ) ;
280- }
281- } }
282- search = { search }
283- />
284- </ div >
285- ) }
286- </ div >
287- ) ;
288- } ) }
235+ return (
236+ < div
237+ key = { virtualItem . key }
238+ data-index = { virtualItem . index }
239+ style = { {
240+ position : 'absolute' ,
241+ top : 0 ,
242+ left : 0 ,
243+ width : '100%' ,
244+ transform : `translateY(${ virtualItem . start } px)` ,
245+ } }
246+ ref = { ( el ) => {
247+ if ( el ) {
248+ // trigger remeasurement when content changes and load
249+ requestAnimationFrame ( ( ) => {
250+ handleSectionResize ( virtualItem . index ) ;
251+ } ) ;
252+ }
253+ } }
254+ >
255+ { item . type === 'group' ? (
256+ < div className = "flex items-center py-6 my-4" >
257+ < div className = "flex-1 h-0.5 bg-gray-200" />
258+ < Tooltip title = "Copy link to this group" >
259+ < div
260+ className = "px-4 text-md font-semibold text-gray-700 uppercase tracking-wide whitespace-nowrap cursor-pointer hover:text-blue-600 transition-colors"
261+ onClick = { ( ) => handleCopyGroupLink ( item . group . Name ) }
262+ >
263+ { item . group . Name }
264+ </ div >
265+ </ Tooltip >
266+ < div className = "flex-1 h-0.5 bg-gray-200" />
267+ </ div >
268+ ) : (
269+ < div className = "text-sm" >
270+ < Section
271+ entity = { item . entity }
272+ group = { item . group }
273+ onTabChange = { ( ) => {
274+
275+ } }
276+ search = { search }
277+ />
278+ </ div >
279+ ) }
280+ </ div >
281+ ) ;
282+ } ) }
283+ </ div >
289284 </ div >
290- </ div >
285+ </ >
291286 ) ;
292287} ;
0 commit comments