Refacto scroll + Aggregate queries for view groups (#9089)

Closes https://github.com/twentyhq/private-issues/issues/217.

Refactoring scroll not to cause table-wide re-render when opening a
dropdown (triggering a scroll lock) in the table.
This commit is contained in:
Marie
2024-12-16 17:58:57 +01:00
committed by GitHub
parent c90d2fd5cc
commit 311b5f64c4
47 changed files with 374 additions and 277 deletions

View File

@ -2,15 +2,17 @@ import styled from '@emotion/styled';
import { OverlayScrollbars } from 'overlayscrollbars';
import { useOverlayScrollbars } from 'overlayscrollbars-react';
import { useEffect, useRef } from 'react';
import { useSetRecoilState } from 'recoil';
import {
ContextProviderName,
getContextByProviderName,
} from '@/ui/utilities/scroll/contexts/ScrollWrapperContexts';
import { useScrollStates } from '@/ui/utilities/scroll/hooks/internal/useScrollStates';
import { overlayScrollbarsState } from '@/ui/utilities/scroll/states/overlayScrollbarsState';
import { ScrollWrapperComponentInstanceContext } from '@/ui/utilities/scroll/states/contexts/ScrollWrapperComponentInstanceContext';
import { scrollWrapperInstanceComponentState } from '@/ui/utilities/scroll/states/scrollWrapperInstanceComponentState';
import { scrollWrapperScrollLeftComponentState } from '@/ui/utilities/scroll/states/scrollWrapperScrollLeftComponentState';
import { scrollWrapperScrollTopComponentState } from '@/ui/utilities/scroll/states/scrollWrapperScrollTopComponentState';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
import 'overlayscrollbars/overlayscrollbars.css';
const StyledScrollWrapper = styled.div<{ scrollHide?: boolean }>`
@ -31,41 +33,52 @@ const StyledInnerContainer = styled.div`
export type ScrollWrapperProps = {
children: React.ReactNode;
className?: string;
enableXScroll?: boolean;
enableYScroll?: boolean;
defaultEnableXScroll?: boolean;
defaultEnableYScroll?: boolean;
contextProviderName: ContextProviderName;
scrollHide?: boolean;
componentInstanceId: string;
};
export const ScrollWrapper = ({
componentInstanceId,
children,
className,
enableXScroll = true,
enableYScroll = true,
defaultEnableXScroll = true,
defaultEnableYScroll = true,
contextProviderName,
scrollHide = false,
}: ScrollWrapperProps) => {
const scrollableRef = useRef<HTMLDivElement>(null);
const Context = getContextByProviderName(contextProviderName);
const { scrollTopComponentState, scrollLeftComponentState } =
useScrollStates(contextProviderName);
const setScrollTop = useSetRecoilState(scrollTopComponentState);
const setScrollLeft = useSetRecoilState(scrollLeftComponentState);
const setScrollTop = useSetRecoilComponentStateV2(
scrollWrapperScrollTopComponentState,
componentInstanceId,
);
const setScrollLeft = useSetRecoilComponentStateV2(
scrollWrapperScrollLeftComponentState,
componentInstanceId,
);
const handleScroll = (overlayScroll: OverlayScrollbars) => {
const target = overlayScroll.elements().scrollOffsetElement;
setScrollTop(target.scrollTop);
setScrollLeft(target.scrollLeft);
};
const setOverlayScrollbars = useSetRecoilState(overlayScrollbarsState);
const setOverlayScrollbars = useSetRecoilComponentStateV2(
scrollWrapperInstanceComponentState,
componentInstanceId,
);
const [initialize, instance] = useOverlayScrollbars({
options: {
scrollbars: { autoHide: 'scroll' },
overflow: {
x: enableXScroll ? undefined : 'hidden',
y: enableYScroll ? undefined : 'hidden',
x: defaultEnableXScroll ? undefined : 'hidden',
y: defaultEnableYScroll ? undefined : 'hidden',
},
},
events: {
@ -84,19 +97,23 @@ export const ScrollWrapper = ({
}, [instance, setOverlayScrollbars]);
return (
<Context.Provider
value={{
ref: scrollableRef,
id: contextProviderName,
}}
<ScrollWrapperComponentInstanceContext.Provider
value={{ instanceId: componentInstanceId }}
>
<StyledScrollWrapper
ref={scrollableRef}
className={className}
scrollHide={scrollHide}
<Context.Provider
value={{
ref: scrollableRef,
id: contextProviderName,
}}
>
<StyledInnerContainer>{children}</StyledInnerContainer>
</StyledScrollWrapper>
</Context.Provider>
<StyledScrollWrapper
ref={scrollableRef}
className={className}
scrollHide={scrollHide}
>
<StyledInnerContainer>{children}</StyledInnerContainer>
</StyledScrollWrapper>
</Context.Provider>
</ScrollWrapperComponentInstanceContext.Provider>
);
};