Rework atom naming (#18240)
## Summary - **Enhanced the `matching-state-variable` ESLint rule** to enforce consistent naming for `ComponentState`, `FamilyState`, and `ComponentFamilyState` hooks — previously it only covered `useAtomState` and `useAtomStateValue` - **The rule now checks 12 hooks** across three categories: value hooks (`useAtomComponentStateValue`, `useAtomFamilyStateValue`, etc.), state hooks (`useAtomComponentState`, `useAtomComponentFamilyState`), and setter hooks (`useSetAtomState`, `useSetAtomComponentState`, `useSetAtomFamilyState`, `useSetAtomComponentFamilyState`) - **Fixed all 225 resulting lint violations** across 151 files, renaming variables to match their state atom names (e.g. `currentViewId` → `contextStoreCurrentViewId`, `selectedRecord` → `recordStore`). Cases where the same state is accessed with different family keys/instance IDs are suppressed with `eslint-disable-next-line`. ## Naming convention | Hook | State argument | Valid | Invalid | |------|---------------|-------|---------| | `useAtomStateValue` | `fooState` | `const foo = ...` | `const bar = ...` | | `useAtomComponentStateValue` | `fooComponentState` | `const foo = ...` | `const bar = ...` | | `useAtomFamilyStateValue` | `fooFamilyState` | `const foo = ...` | `const bar = ...` | | `useAtomComponentFamilyStateValue` | `fooComponentFamilyState` | `const foo = ...` | `const bar = ...` | | `useAtomState` | `fooState` | `const [foo, setFoo] = ...` | `const [bar, setBar] = ...` | | `useAtomComponentState` | `fooComponentState` | `const [foo, setFoo] = ...` | `const [bar, setBar] = ...` | | `useAtomComponentFamilyState` | `fooComponentFamilyState` | `const [foo, setFoo] = ...` | `const [bar, setBar] = ...` | | `useSetAtomState` | `fooState` | `const setFoo = ...` | `const setBar = ...` | | `useSetAtomComponentState` | `fooComponentState` | `const setFoo = ...` | `const setBar = ...` | | `useSetAtomFamilyState` | `fooFamilyState` | `const setFoo = ...` | `const setBar = ...` | | `useSetAtomComponentFamilyState` | `fooComponentFamilyState` | `const setFoo = ...` | `const setBar = ...` |
This commit is contained in:
@@ -103,7 +103,7 @@ const IconPickerIcon = ({
|
||||
Icon,
|
||||
focusedIconKey,
|
||||
}: IconPickerIconProps) => {
|
||||
const isSelectedItemId = useAtomComponentStateValue(
|
||||
const selectedItemId = useAtomComponentStateValue(
|
||||
selectedItemIdComponentState,
|
||||
iconKey,
|
||||
);
|
||||
@@ -116,7 +116,7 @@ const IconPickerIcon = ({
|
||||
aria-label={convertIconKeyToLabel(iconKey)}
|
||||
size="medium"
|
||||
title={iconKey}
|
||||
isSelected={iconKey === selectedIconKey || !!isSelectedItemId}
|
||||
isSelected={iconKey === selectedIconKey || !!selectedItemId}
|
||||
isFocused={iconKey === focusedIconKey}
|
||||
Icon={Icon}
|
||||
onClick={onSelect}
|
||||
|
||||
+10
-8
@@ -44,12 +44,13 @@ describe('useCloseDropdown', () => {
|
||||
it('should close dropdown from inside component instance context', async () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
// eslint-disable-next-line twenty/matching-state-variable
|
||||
const isOutsideDropdownOpen = useAtomComponentStateValue(
|
||||
isDropdownOpenComponentState,
|
||||
outsideDropdownId,
|
||||
);
|
||||
|
||||
const isInsideDropdownOpen = useAtomComponentStateValue(
|
||||
const isDropdownOpen = useAtomComponentStateValue(
|
||||
isDropdownOpenComponentState,
|
||||
);
|
||||
|
||||
@@ -58,7 +59,7 @@ describe('useCloseDropdown', () => {
|
||||
|
||||
return {
|
||||
isOutsideDropdownOpen,
|
||||
isInsideDropdownOpen,
|
||||
isDropdownOpen,
|
||||
closeDropdown,
|
||||
openDropdown,
|
||||
};
|
||||
@@ -72,26 +73,27 @@ describe('useCloseDropdown', () => {
|
||||
result.current.openDropdown();
|
||||
});
|
||||
|
||||
expect(result.current.isInsideDropdownOpen).toBe(true);
|
||||
expect(result.current.isDropdownOpen).toBe(true);
|
||||
expect(result.current.isOutsideDropdownOpen).toBe(false);
|
||||
|
||||
act(() => {
|
||||
result.current.closeDropdown();
|
||||
});
|
||||
|
||||
expect(result.current.isInsideDropdownOpen).toBe(false);
|
||||
expect(result.current.isDropdownOpen).toBe(false);
|
||||
expect(result.current.isOutsideDropdownOpen).toBe(false);
|
||||
});
|
||||
|
||||
it('should close dropdown from outside component instance context', async () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
// eslint-disable-next-line twenty/matching-state-variable
|
||||
const isOutsideDropdownOpen = useAtomComponentStateValue(
|
||||
isDropdownOpenComponentState,
|
||||
outsideDropdownId,
|
||||
);
|
||||
|
||||
const isInsideDropdownOpen = useAtomComponentStateValue(
|
||||
const isDropdownOpen = useAtomComponentStateValue(
|
||||
isDropdownOpenComponentState,
|
||||
);
|
||||
|
||||
@@ -100,7 +102,7 @@ describe('useCloseDropdown', () => {
|
||||
|
||||
return {
|
||||
isOutsideDropdownOpen,
|
||||
isInsideDropdownOpen,
|
||||
isDropdownOpen,
|
||||
closeDropdown,
|
||||
openDropdown,
|
||||
};
|
||||
@@ -116,14 +118,14 @@ describe('useCloseDropdown', () => {
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.isInsideDropdownOpen).toBe(false);
|
||||
expect(result.current.isDropdownOpen).toBe(false);
|
||||
expect(result.current.isOutsideDropdownOpen).toBe(true);
|
||||
|
||||
act(() => {
|
||||
result.current.closeDropdown(outsideDropdownId);
|
||||
});
|
||||
|
||||
expect(result.current.isInsideDropdownOpen).toBe(false);
|
||||
expect(result.current.isDropdownOpen).toBe(false);
|
||||
expect(result.current.isOutsideDropdownOpen).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
+10
-8
@@ -42,57 +42,59 @@ describe('useOpenDropdown', () => {
|
||||
it('should open dropdown from inside component instance context', async () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
// eslint-disable-next-line twenty/matching-state-variable
|
||||
const isOutsideDropdownOpen = useAtomComponentStateValue(
|
||||
isDropdownOpenComponentState,
|
||||
outsideDropdownId,
|
||||
);
|
||||
|
||||
const isInsideDropdownOpen = useAtomComponentStateValue(
|
||||
const isDropdownOpen = useAtomComponentStateValue(
|
||||
isDropdownOpenComponentState,
|
||||
);
|
||||
|
||||
const { openDropdown } = useOpenDropdown();
|
||||
|
||||
return { isOutsideDropdownOpen, isInsideDropdownOpen, openDropdown };
|
||||
return { isOutsideDropdownOpen, isDropdownOpen, openDropdown };
|
||||
},
|
||||
{
|
||||
wrapper: Wrapper,
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.current.isInsideDropdownOpen).toBe(false);
|
||||
expect(result.current.isDropdownOpen).toBe(false);
|
||||
expect(result.current.isOutsideDropdownOpen).toBe(false);
|
||||
|
||||
act(() => {
|
||||
result.current.openDropdown();
|
||||
});
|
||||
|
||||
expect(result.current.isInsideDropdownOpen).toBe(true);
|
||||
expect(result.current.isDropdownOpen).toBe(true);
|
||||
expect(result.current.isOutsideDropdownOpen).toBe(false);
|
||||
});
|
||||
|
||||
it('should open dropdown from outside component instance context', async () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
// eslint-disable-next-line twenty/matching-state-variable
|
||||
const isOutsideDropdownOpen = useAtomComponentStateValue(
|
||||
isDropdownOpenComponentState,
|
||||
outsideDropdownId,
|
||||
);
|
||||
|
||||
const isInsideDropdownOpen = useAtomComponentStateValue(
|
||||
const isDropdownOpen = useAtomComponentStateValue(
|
||||
isDropdownOpenComponentState,
|
||||
);
|
||||
|
||||
const { openDropdown } = useOpenDropdown();
|
||||
|
||||
return { isInsideDropdownOpen, isOutsideDropdownOpen, openDropdown };
|
||||
return { isDropdownOpen, isOutsideDropdownOpen, openDropdown };
|
||||
},
|
||||
{
|
||||
wrapper: Wrapper,
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.current.isInsideDropdownOpen).toBe(false);
|
||||
expect(result.current.isDropdownOpen).toBe(false);
|
||||
expect(result.current.isOutsideDropdownOpen).toBe(false);
|
||||
|
||||
act(() => {
|
||||
@@ -101,7 +103,7 @@ describe('useOpenDropdown', () => {
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.isInsideDropdownOpen).toBe(false);
|
||||
expect(result.current.isDropdownOpen).toBe(false);
|
||||
expect(result.current.isOutsideDropdownOpen).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
+14
-12
@@ -43,69 +43,71 @@ describe('useToggleDropdown', () => {
|
||||
it('should toggle dropdown from inside component instance context', async () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
// eslint-disable-next-line twenty/matching-state-variable
|
||||
const isOutsideDropdownOpen = useAtomComponentStateValue(
|
||||
isDropdownOpenComponentState,
|
||||
outsideDropdownId,
|
||||
);
|
||||
|
||||
const isInsideDropdownOpen = useAtomComponentStateValue(
|
||||
const isDropdownOpen = useAtomComponentStateValue(
|
||||
isDropdownOpenComponentState,
|
||||
);
|
||||
const { toggleDropdown } = useToggleDropdown();
|
||||
|
||||
return { isOutsideDropdownOpen, isInsideDropdownOpen, toggleDropdown };
|
||||
return { isOutsideDropdownOpen, isDropdownOpen, toggleDropdown };
|
||||
},
|
||||
{
|
||||
wrapper: Wrapper,
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.current.isInsideDropdownOpen).toBe(false);
|
||||
expect(result.current.isDropdownOpen).toBe(false);
|
||||
expect(result.current.isOutsideDropdownOpen).toBe(false);
|
||||
|
||||
act(() => {
|
||||
result.current.toggleDropdown();
|
||||
});
|
||||
|
||||
expect(result.current.isInsideDropdownOpen).toBe(true);
|
||||
expect(result.current.isDropdownOpen).toBe(true);
|
||||
expect(result.current.isOutsideDropdownOpen).toBe(false);
|
||||
|
||||
act(() => {
|
||||
result.current.toggleDropdown();
|
||||
});
|
||||
|
||||
expect(result.current.isInsideDropdownOpen).toBe(false);
|
||||
expect(result.current.isDropdownOpen).toBe(false);
|
||||
expect(result.current.isOutsideDropdownOpen).toBe(false);
|
||||
|
||||
act(() => {
|
||||
result.current.toggleDropdown();
|
||||
});
|
||||
|
||||
expect(result.current.isInsideDropdownOpen).toBe(true);
|
||||
expect(result.current.isDropdownOpen).toBe(true);
|
||||
expect(result.current.isOutsideDropdownOpen).toBe(false);
|
||||
});
|
||||
|
||||
it('should toggle dropdown from outside component instance context', async () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
// eslint-disable-next-line twenty/matching-state-variable
|
||||
const isOutsideDropdownOpen = useAtomComponentStateValue(
|
||||
isDropdownOpenComponentState,
|
||||
outsideDropdownId,
|
||||
);
|
||||
|
||||
const isInsideDropdownOpen = useAtomComponentStateValue(
|
||||
const isDropdownOpen = useAtomComponentStateValue(
|
||||
isDropdownOpenComponentState,
|
||||
);
|
||||
const { toggleDropdown } = useToggleDropdown();
|
||||
|
||||
return { isOutsideDropdownOpen, isInsideDropdownOpen, toggleDropdown };
|
||||
return { isOutsideDropdownOpen, isDropdownOpen, toggleDropdown };
|
||||
},
|
||||
{
|
||||
wrapper: Wrapper,
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.current.isInsideDropdownOpen).toBe(false);
|
||||
expect(result.current.isDropdownOpen).toBe(false);
|
||||
expect(result.current.isOutsideDropdownOpen).toBe(false);
|
||||
|
||||
act(() => {
|
||||
@@ -114,7 +116,7 @@ describe('useToggleDropdown', () => {
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.isInsideDropdownOpen).toBe(false);
|
||||
expect(result.current.isDropdownOpen).toBe(false);
|
||||
expect(result.current.isOutsideDropdownOpen).toBe(true);
|
||||
|
||||
act(() => {
|
||||
@@ -123,7 +125,7 @@ describe('useToggleDropdown', () => {
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.isInsideDropdownOpen).toBe(false);
|
||||
expect(result.current.isDropdownOpen).toBe(false);
|
||||
expect(result.current.isOutsideDropdownOpen).toBe(false);
|
||||
|
||||
act(() => {
|
||||
@@ -132,7 +134,7 @@ describe('useToggleDropdown', () => {
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.isInsideDropdownOpen).toBe(false);
|
||||
expect(result.current.isDropdownOpen).toBe(false);
|
||||
expect(result.current.isOutsideDropdownOpen).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
+3
-5
@@ -75,7 +75,7 @@ export const MultiWorkspaceDropdownDefaultComponents = () => {
|
||||
|
||||
const [signUpInNewWorkspaceMutation] = useSignUpInNewWorkspaceMutation();
|
||||
|
||||
const setMultiWorkspaceDropdownState = useSetAtomState(
|
||||
const setMultiWorkspaceDropdown = useSetAtomState(
|
||||
multiWorkspaceDropdownState,
|
||||
);
|
||||
|
||||
@@ -195,9 +195,7 @@ export const MultiWorkspaceDropdownDefaultComponents = () => {
|
||||
<MenuItem
|
||||
LeftIcon={IconSwitchHorizontal}
|
||||
text={t`Other workspaces`}
|
||||
onClick={() =>
|
||||
setMultiWorkspaceDropdownState('workspaces-list')
|
||||
}
|
||||
onClick={() => setMultiWorkspaceDropdown('workspaces-list')}
|
||||
hasSubMenu={true}
|
||||
/>
|
||||
)}
|
||||
@@ -215,7 +213,7 @@ export const MultiWorkspaceDropdownDefaultComponents = () => {
|
||||
</>
|
||||
}
|
||||
hasSubMenu={true}
|
||||
onClick={() => setMultiWorkspaceDropdownState('themes')}
|
||||
onClick={() => setMultiWorkspaceDropdown('themes')}
|
||||
/>
|
||||
<UndecoratedLink
|
||||
to={getSettingsPath(SettingsPath.WorkspaceMembersPage)}
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@ export const MultiWorkspaceDropdownThemesComponents = () => {
|
||||
|
||||
const { setColorScheme, colorScheme, colorSchemeList } = useColorScheme();
|
||||
|
||||
const setMultiWorkspaceDropdownState = useSetAtomState(
|
||||
const setMultiWorkspaceDropdown = useSetAtomState(
|
||||
multiWorkspaceDropdownState,
|
||||
);
|
||||
|
||||
@@ -23,7 +23,7 @@ export const MultiWorkspaceDropdownThemesComponents = () => {
|
||||
<DropdownMenuHeader
|
||||
StartComponent={
|
||||
<DropdownMenuHeaderLeftComponent
|
||||
onClick={() => setMultiWorkspaceDropdownState('default')}
|
||||
onClick={() => setMultiWorkspaceDropdown('default')}
|
||||
Icon={IconChevronLeft}
|
||||
/>
|
||||
}
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ export const MultiWorkspaceDropdownWorkspacesListComponents = () => {
|
||||
|
||||
const availableWorkspaces = useAtomStateValue(availableWorkspacesState);
|
||||
|
||||
const setMultiWorkspaceDropdownState = useSetAtomState(
|
||||
const setMultiWorkspaceDropdown = useSetAtomState(
|
||||
multiWorkspaceDropdownState,
|
||||
);
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
@@ -29,7 +29,7 @@ export const MultiWorkspaceDropdownWorkspacesListComponents = () => {
|
||||
<DropdownMenuHeader
|
||||
StartComponent={
|
||||
<DropdownMenuHeaderLeftComponent
|
||||
onClick={() => setMultiWorkspaceDropdownState('default')}
|
||||
onClick={() => setMultiWorkspaceDropdown('default')}
|
||||
Icon={IconChevronLeft}
|
||||
/>
|
||||
}
|
||||
|
||||
@@ -35,26 +35,26 @@ export const ScrollWrapper = ({
|
||||
defaultEnableXScroll = true,
|
||||
defaultEnableYScroll = true,
|
||||
}: ScrollWrapperProps) => {
|
||||
const setScrollTop = useSetAtomComponentState(
|
||||
const setScrollWrapperScrollTop = useSetAtomComponentState(
|
||||
scrollWrapperScrollTopComponentState,
|
||||
componentInstanceId,
|
||||
);
|
||||
|
||||
const setScrollLeft = useSetAtomComponentState(
|
||||
const setScrollWrapperScrollLeft = useSetAtomComponentState(
|
||||
scrollWrapperScrollLeftComponentState,
|
||||
componentInstanceId,
|
||||
);
|
||||
|
||||
const setScrollBottom = useSetAtomComponentState(
|
||||
const setScrollWrapperScrollBottom = useSetAtomComponentState(
|
||||
scrollWrapperScrollBottomComponentState,
|
||||
componentInstanceId,
|
||||
);
|
||||
|
||||
const handleScroll = (event: React.UIEvent<HTMLDivElement>) => {
|
||||
const target = event.currentTarget;
|
||||
setScrollTop(target.scrollTop);
|
||||
setScrollLeft(target.scrollLeft);
|
||||
setScrollBottom(
|
||||
setScrollWrapperScrollTop(target.scrollTop);
|
||||
setScrollWrapperScrollLeft(target.scrollLeft);
|
||||
setScrollWrapperScrollBottom(
|
||||
target.scrollHeight - target.clientHeight - target.scrollTop,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ export const useScrollRestoration = (componentInstanceId: string) => {
|
||||
const storageKey = `scroll-${location.pathname}`;
|
||||
const [isRestoring, setIsRestoring] = useState(false);
|
||||
|
||||
const scrollTop = useAtomComponentStateValue(
|
||||
const scrollWrapperScrollTop = useAtomComponentStateValue(
|
||||
scrollWrapperScrollTopComponentState,
|
||||
componentInstanceId,
|
||||
);
|
||||
@@ -46,13 +46,13 @@ export const useScrollRestoration = (componentInstanceId: string) => {
|
||||
useEffect(() => {
|
||||
if (isRestoring) return;
|
||||
|
||||
if (scrollTop <= SCROLL_RESTORATION_TOP_THRESHOLD_PX) {
|
||||
if (scrollWrapperScrollTop <= SCROLL_RESTORATION_TOP_THRESHOLD_PX) {
|
||||
sessionStorage.removeItem(storageKey);
|
||||
return;
|
||||
}
|
||||
|
||||
sessionStorage.setItem(storageKey, scrollTop.toString());
|
||||
}, [scrollTop, storageKey, isRestoring]);
|
||||
sessionStorage.setItem(storageKey, scrollWrapperScrollTop.toString());
|
||||
}, [scrollWrapperScrollTop, storageKey, isRestoring]);
|
||||
|
||||
useEffect(() => {
|
||||
const savedPosition = sessionStorage.getItem(storageKey);
|
||||
|
||||
Reference in New Issue
Block a user