diff --git a/Website/components/datamodelview/DatamodelView.tsx b/Website/components/datamodelview/DatamodelView.tsx index b28b7e5..00caa2a 100644 --- a/Website/components/datamodelview/DatamodelView.tsx +++ b/Website/components/datamodelview/DatamodelView.tsx @@ -47,8 +47,11 @@ function DatamodelViewContent() { } else { // Clear search - reset to show all groups datamodelDataDispatch({ type: "SET_FILTERED", payload: [] }); + // Relocate section - restoreSection(); + if (searchValue && searchValue.length === 0) { + restoreSection(); + } } } updateURL({ query: { globalsearch: searchValue.length >= 3 ? searchValue : "" } }) diff --git a/Website/components/datamodelview/List.tsx b/Website/components/datamodelview/List.tsx index 7770d34..303ff3a 100644 --- a/Website/components/datamodelview/List.tsx +++ b/Website/components/datamodelview/List.tsx @@ -1,7 +1,7 @@ import { useEffect, useMemo, useRef, useCallback, useState } from "react"; import { useDatamodelView, useDatamodelViewDispatch } from "@/contexts/DatamodelViewContext"; import React from "react"; -import { elementScroll, useVirtualizer, VirtualizerOptions } from '@tanstack/react-virtual'; +import { useVirtualizer } from '@tanstack/react-virtual'; import { Section } from "./Section"; import { useDatamodelData } from "@/contexts/DatamodelDataContext"; import { AttributeType, EntityType, GroupType } from "@/lib/Types"; @@ -24,12 +24,10 @@ export function highlightMatch(text: string, search: string) { export const List = ({ setCurrentIndex }: IListProps) => { const dispatch = useDatamodelViewDispatch(); - const { currentSection, loading } = useDatamodelView(); + const { currentSection } = useDatamodelView(); const { groups, filtered, search } = useDatamodelData(); const { showSnackbar } = useSnackbar(); const parentRef = useRef(null); - const scrollTimeoutRef = useRef(); - const scrollingRef = React.useRef() // used to relocate section after search/filter const [sectionVirtualItem, setSectionVirtualItem] = useState(null); @@ -79,34 +77,6 @@ export const List = ({ setCurrentIndex }: IListProps) => { return items; }, [filtered, search, groups]); - function easeInOutQuint(t: number) { - return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t - } - - const scrollToFn: VirtualizerOptions['scrollToFn'] = - React.useCallback((offset, canSmooth, instance) => { - const duration = 2000 - const start = parentRef.current?.scrollTop || 0 - const startTime = (scrollingRef.current = Date.now()) - - const run = () => { - if (scrollingRef.current !== startTime) return - const now = Date.now() - const elapsed = now - startTime - const progress = easeInOutQuint(Math.min(elapsed / duration, 1)) - const interpolated = start + (offset - start) * progress - - if (elapsed < duration) { - elementScroll(interpolated, canSmooth, instance) - requestAnimationFrame(run) - } else { - elementScroll(interpolated, canSmooth, instance) - } - } - - requestAnimationFrame(run) - }, []) - const debouncedOnChange = debounce((instance, sync) => { if (!sync) { dispatch({ type: 'SET_LOADING_SECTION', payload: null }); @@ -158,8 +128,11 @@ export const List = ({ setCurrentIndex }: IListProps) => { } } - if (mostVisibleEntity && currentSection !== mostVisibleEntity.entity.SchemaName) { + if (mostVisibleEntity && !search) { setSectionVirtualItem(mostVisibleEntity.entity.SchemaName); + } + + if (mostVisibleEntity && currentSection !== mostVisibleEntity.entity.SchemaName) { updateURL({ query: { group: mostVisibleEntity.group.Name, section: mostVisibleEntity.entity.SchemaName } }); dispatch({ type: "SET_CURRENT_GROUP", payload: mostVisibleEntity.group.Name }); dispatch({ type: "SET_CURRENT_SECTION", payload: mostVisibleEntity.entity.SchemaName }); @@ -176,15 +149,10 @@ export const List = ({ setCurrentIndex }: IListProps) => { if (!item) return 200; return item.type === 'group' ? 100 : 500; }, - scrollToFn, onChange: debouncedOnChange, }); const scrollToSection = useCallback((sectionId: string) => { - if (scrollTimeoutRef.current) { - clearTimeout(scrollTimeoutRef.current); - } - const sectionIndex = flatItems.findIndex(item => item.type === 'entity' && item.entity.SchemaName === sectionId ); @@ -195,16 +163,13 @@ export const List = ({ setCurrentIndex }: IListProps) => { } rowVirtualizer.scrollToIndex(sectionIndex, { - align: 'start' + align: 'start', + behavior: 'smooth' }); }, [flatItems]); const scrollToGroup = useCallback((groupName: string) => { - if (scrollTimeoutRef.current) { - clearTimeout(scrollTimeoutRef.current); - } - const groupIndex = flatItems.findIndex(item => item.type === 'group' && item.group.Name === groupName ); @@ -215,7 +180,8 @@ export const List = ({ setCurrentIndex }: IListProps) => { } rowVirtualizer.scrollToIndex(groupIndex, { - align: 'start' + align: 'start', + behavior: 'smooth' }); }, [flatItems]); @@ -229,12 +195,6 @@ export const List = ({ setCurrentIndex }: IListProps) => { dispatch({ type: 'SET_SCROLL_TO_SECTION', payload: scrollToSection }); dispatch({ type: 'SET_SCROLL_TO_GROUP', payload: scrollToGroup }); dispatch({ type: 'SET_RESTORE_SECTION', payload: restoreSection }); - - return () => { - if (scrollTimeoutRef.current) { - clearTimeout(scrollTimeoutRef.current); - } - }; }, [dispatch, scrollToSection, scrollToGroup]); // Callback to handle section content changes (for tab switches, expansions, etc.) @@ -250,24 +210,6 @@ export const List = ({ setCurrentIndex }: IListProps) => { return (
- {/* Show skeleton loading state only when initially loading */} - {flatItems.length === 0 && loading && (!search || search.length < 3) && ( -
- {[...Array(5)].map((_, i) => ( -
-
-
-
-
-
-
-
-
-
- ))} -
- )} - {/* Show no results message when searching but no items found */} {flatItems.length === 0 && search && search.length >= 3 && (
diff --git a/Website/components/datamodelview/SidebarDatamodelView.tsx b/Website/components/datamodelview/SidebarDatamodelView.tsx index ebd7503..bfe8e6e 100644 --- a/Website/components/datamodelview/SidebarDatamodelView.tsx +++ b/Website/components/datamodelview/SidebarDatamodelView.tsx @@ -42,7 +42,7 @@ export const SidebarDatamodelView = ({ }: ISidebarDatamodelViewProps) => { Entities: group.Entities.filter(entity => (entity.SchemaName.toLowerCase().includes(searchTerm.toLowerCase()) || entity.DisplayName.toLowerCase().includes(searchTerm.toLowerCase())) && - filtered.some(f => f.type === 'entity' && f.entity.SchemaName === entity.SchemaName) + (!search || filtered.some(f => f.type === 'entity' && f.entity.SchemaName === entity.SchemaName)) ) })).filter(group => group.Entities.length > 0); }, [groups, searchTerm, filtered]); diff --git a/Website/components/datamodelview/TimeSlicedSearch.tsx b/Website/components/datamodelview/TimeSlicedSearch.tsx index aaa5247..9ff5874 100644 --- a/Website/components/datamodelview/TimeSlicedSearch.tsx +++ b/Website/components/datamodelview/TimeSlicedSearch.tsx @@ -170,7 +170,7 @@ export const TimeSlicedSearch = ({ if (typingTimeoutRef.current) { clearTimeout(typingTimeoutRef.current); } - }, [onSearch, onLoadingChange]); + }, [onSearch, onLoadingChange, localValue]); // Cleanup useEffect(() => {