Skip to content

Commit

Permalink
refactor: change scroll hook to focused item
Browse files Browse the repository at this point in the history
  • Loading branch information
TheAlmightyCrumb committed Dec 9, 2024
1 parent 2e3feb6 commit 1953eda
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export default createBoard({
itemSize={() => 50}
getId={getId}
selectionControl={[selectedItems, noop]}
scrollToSelection={true}
scrollToFocused={true}
scrollListRoot={{
el: 'div',
props: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,26 @@ import type { DimensionsById } from '../../common';
import type { ListProps } from '../../list/list';
import type { ScrollListProps } from '../../scroll-list/scroll-list';

export const useScrollListScrollToSelected = <T, EL extends HTMLElement>({
scrollToSelection,
export const useScrollListScrollToFocused = <T, EL extends HTMLElement>({
scrollToFocused,
scrollWindow,
scrollListRef,
items,
getId,
selected,
focused,
averageItemSize,
itemsDimensions,
mountedItems,
isHorizontal,
extraRenderSize,
scrollWindowSize,
}: {
scrollToSelection: boolean;
scrollToFocused: ScrollListProps<T, EL>['scrollToFocused'];
scrollWindow?: ScrollListProps<T, EL>['scrollWindow'];
scrollListRef: RefObject<EL>;
items: ListProps<T>['items'];
getId: ListProps<T>['getId'];
selected: string[];
focused?: string;
averageItemSize: number;
itemsDimensions: MutableRefObject<DimensionsById>;
mountedItems: MutableRefObject<Set<string>>;
Expand All @@ -34,12 +34,12 @@ export const useScrollListScrollToSelected = <T, EL extends HTMLElement>({
const loadingTimeout = useRef(0);
const timeout = useRef(0);
const isScrollingToSelection = useRef(false);
const selectedIndex = useMemo(() => items.findIndex((i) => getId(i) === selected[0]), [items, getId, selected]);
const focusedIndex = useMemo(() => items.findIndex((i) => getId(i) === focused), [items, getId, focused]);
const calculateDistance = useCallback(
({ itemIndex, direction }: { itemIndex: number; direction: 'up' | 'down' }) => {
let distance = 0;

for (let index = itemIndex; index !== selectedIndex; direction === 'down' ? index++ : index--) {
for (let index = itemIndex; index !== focusedIndex; direction === 'down' ? index++ : index--) {
const item = items[index]!;
const id = getId(item);
const { height, width } = itemsDimensions.current[id] || {
Expand All @@ -59,35 +59,26 @@ export const useScrollListScrollToSelected = <T, EL extends HTMLElement>({

return Math.floor((direction === 'down' ? 1 : -1) * distance);
},
[
averageItemSize,
extraRenderSize,
getId,
isHorizontal,
items,
itemsDimensions,
scrollWindowSize,
selectedIndex,
],
[averageItemSize, extraRenderSize, getId, isHorizontal, items, itemsDimensions, scrollWindowSize, focusedIndex],
);
const cleanUp = () => {
isScrollingToSelection.current = false;
loadingTimeout.current = 0;
clearTimeout(timeout.current);
};
const scrollTo = useCallback(
(selectedIndex: number, repeated = false) => {
(focusedIndex: number, repeated = false) => {
if (!scrollListRef.current) {
return;
}

clearTimeout(timeout.current);

const scrollIntoView = (selected: number, position: ScrollLogicalPosition) => {
const node = scrollListRef.current?.querySelector(`[data-id='${getId(items[selected]!)}']`);
const scrollIntoView = (focusedIndex: number, position: ScrollLogicalPosition) => {
const node = scrollListRef.current?.querySelector(`[data-id='${getId(items[focusedIndex]!)}']`);
if (!node) {
timeout.current = window.setTimeout(
() => isScrollingToSelection.current && scrollTo(selected, true),
() => isScrollingToSelection.current && scrollTo(focusedIndex, true),
);
} else {
scrollIntoViewIfNeeded(node, {
Expand All @@ -107,33 +98,28 @@ export const useScrollListScrollToSelected = <T, EL extends HTMLElement>({

let position: ScrollLogicalPosition = 'nearest';

if (selectedIndex < firstIndex) {
if (focusedIndex < firstIndex) {
position = 'start';
scrollTarget.scrollBy({ top: calculateDistance({ itemIndex: firstIndex, direction: 'up' }) });
} else if (lastIndex < selectedIndex) {
} else if (lastIndex < focusedIndex) {
position = 'end';
scrollTarget.scrollBy({ top: calculateDistance({ itemIndex: lastIndex, direction: 'down' }) });
}

timeout.current = window.setTimeout(() => scrollIntoView(selectedIndex, repeated ? 'center' : position));
timeout.current = window.setTimeout(() => scrollIntoView(focusedIndex, repeated ? 'center' : position));
},
[scrollListRef, scrollWindow, mountedItems, items, getId, calculateDistance],
);

useEffect(() => {
if (
scrollToSelection &&
selectedIndex > -1 &&
mountedItems.current.size > 0 &&
!isScrollingToSelection.current
) {
if (scrollToFocused && focusedIndex > -1 && mountedItems.current.size > 0 && !isScrollingToSelection.current) {
isScrollingToSelection.current = true;

scrollTo(selectedIndex);
scrollTo(focusedIndex);
}

return () => {
cleanUp();
};
}, [scrollToSelection, mountedItems, scrollTo, selectedIndex]);
}, [scrollToFocused, mountedItems, scrollTo, focusedIndex]);
};
12 changes: 6 additions & 6 deletions packages/components/src/scroll-list/scroll-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
ScrollListPositioningProps,
useLoadMoreOnScroll,
useScrollListPosition,
useScrollListScrollToSelected,
useScrollListScrollToFocused,
} from './hooks';
import { classes } from './scroll-list.st.css';

Expand Down Expand Up @@ -121,7 +121,7 @@ export interface ScrollListProps<T, EL extends HTMLElement, I extends ScrollList
*
* @default false
*/
scrollToSelection?: boolean;
scrollToFocused?: boolean;
itemsInRow?: number;
itemGap?: number;
/**
Expand All @@ -148,7 +148,7 @@ export function ScrollList<T, EL extends HTMLElement = HTMLDivElement>({
scrollListRoot,
listRoot,
selectionControl,
scrollToSelection = false,
scrollToFocused = false,
extraRenderSize = 0.5,
unmountItems,
preloader,
Expand Down Expand Up @@ -247,13 +247,13 @@ export function ScrollList<T, EL extends HTMLElement = HTMLDivElement>({
loadedItemsNumber: items.length,
});

useScrollListScrollToSelected({
useScrollListScrollToFocused({
scrollWindow,
scrollListRef,
scrollToSelection,
scrollToFocused,
items,
getId,
selected,
focused,
averageItemSize,
mountedItems,
isHorizontal,
Expand Down

0 comments on commit 1953eda

Please sign in to comment.