Refactor/scope and context (#1960)

* wip

* Test with Dropdown

* wip

* wip

* Finished removing DropdownRecoilScopeContext

* Fix from PR
This commit is contained in:
Lucas Bordeau
2023-10-11 15:35:47 +02:00
committed by GitHub
parent a342af74d1
commit 22451a68b3
61 changed files with 531 additions and 426 deletions

View File

@ -1,8 +1,6 @@
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
import { TasksRecoilScopeContext } from '@/activities/states/recoil-scope-contexts/TasksRecoilScopeContext';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { PageAddButton } from '@/ui/layout/components/PageAddButton';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState';
import { ActivityType } from '~/generated/graphql';
@ -26,9 +24,5 @@ export const PageAddTaskButton = () => {
});
};
return (
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<PageAddButton onClick={handleClick} />
</RecoilScope>
);
return <PageAddButton onClick={handleClick} />;
};

View File

@ -14,7 +14,7 @@ export const PipelineAddButton = () => {
const { enqueueSnackBar } = useSnackBar();
const { closeDropdown, toggleDropdown } = useDropdown({
dropdownId: 'add-pipeline-progress',
dropdownScopeId: 'add-pipeline-progress',
});
const createCompanyProgress = useCreateCompanyProgress();

View File

@ -3,8 +3,6 @@ import { useSearchParams } from 'react-router-dom';
import { useRecoilCallback, useRecoilState, useRecoilValue } from 'recoil';
import { BoardContext } from '@/companies/states/contexts/BoardContext';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
@ -19,8 +17,8 @@ import { savedBoardColumnsState } from '../states/savedBoardColumnsState';
import { canPersistBoardCardFieldsScopedFamilySelector } from '../states/selectors/canPersistBoardCardFieldsScopedFamilySelector';
import { canPersistBoardColumnsSelector } from '../states/selectors/canPersistBoardColumnsSelector';
import { BoardColumnDefinition } from '../types/BoardColumnDefinition';
import { BoardOptionsDropdownKey } from '../types/BoardOptionsDropdownKey';
import { BoardOptionsHotkeyScope } from '../types/BoardOptionsHotkeyScope';
import { BoardScopeIds } from '../types/enums/BoardScopeIds';
import { BoardOptionsDropdown } from './BoardOptionsDropdown';
@ -101,27 +99,25 @@ export const BoardHeader = ({ className, onStageAdd }: BoardHeaderProps) => {
const canPersistView = canPersistBoardCardFields || canPersistBoardColumns;
return (
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<ViewBarContext.Provider
value={{
...viewBarContextProps,
canPersistViewFields: canPersistView,
onCurrentViewSubmit: handleCurrentViewSubmit,
onViewBarReset: handleViewBarReset,
onViewSelect: handleViewSelect,
}}
>
<ViewBar
className={className}
optionsDropdownButton={
<BoardOptionsDropdown
customHotkeyScope={{ scope: BoardOptionsHotkeyScope.Dropdown }}
onStageAdd={onStageAdd}
/>
}
optionsDropdownKey={BoardOptionsDropdownKey}
/>
</ViewBarContext.Provider>
</RecoilScope>
<ViewBarContext.Provider
value={{
...viewBarContextProps,
canPersistViewFields: canPersistView,
onCurrentViewSubmit: handleCurrentViewSubmit,
onViewBarReset: handleViewBarReset,
onViewSelect: handleViewSelect,
}}
>
<ViewBar
className={className}
optionsDropdownButton={
<BoardOptionsDropdown
customHotkeyScope={{ scope: BoardOptionsHotkeyScope.Dropdown }}
onStageAdd={onStageAdd}
/>
}
optionsDropdownScopeId={BoardScopeIds.OptionsDropdown}
/>
</ViewBarContext.Provider>
);
};

View File

@ -3,7 +3,7 @@ import { useResetRecoilState } from 'recoil';
import { ViewBarDropdownButton } from '@/ui/view-bar/components/ViewBarDropdownButton';
import { viewEditModeState } from '@/ui/view-bar/states/viewEditModeState';
import { BoardOptionsDropdownKey } from '../types/BoardOptionsDropdownKey';
import { BoardScopeIds } from '../types/enums/BoardScopeIds';
import { BoardOptionsDropdownButton } from './BoardOptionsDropdownButton';
import {
@ -32,7 +32,7 @@ export const BoardOptionsDropdown = ({
/>
}
dropdownHotkeyScope={customHotkeyScope}
dropdownId={BoardOptionsDropdownKey}
dropdownId={BoardScopeIds.OptionsDropdown}
onClickOutside={resetViewEditMode}
/>
);

View File

@ -1,11 +1,11 @@
import { StyledHeaderDropdownButton } from '@/ui/dropdown/components/StyledHeaderDropdownButton';
import { useDropdown } from '@/ui/dropdown/hooks/useDropdown';
import { BoardOptionsDropdownKey } from '../types/BoardOptionsDropdownKey';
import { BoardScopeIds } from '../types/enums/BoardScopeIds';
export const BoardOptionsDropdownButton = () => {
const { isDropdownOpen, toggleDropdown } = useDropdown({
dropdownId: BoardOptionsDropdownKey,
dropdownScopeId: BoardScopeIds.OptionsDropdown,
});
const handleClick = () => {

View File

@ -43,7 +43,6 @@ import { savedBoardCardFieldsFamilyState } from '../states/savedBoardCardFieldsF
import { hiddenBoardCardFieldsScopedSelector } from '../states/selectors/hiddenBoardCardFieldsScopedSelector';
import { visibleBoardCardFieldsScopedSelector } from '../states/selectors/visibleBoardCardFieldsScopedSelector';
import { BoardColumnDefinition } from '../types/BoardColumnDefinition';
import { BoardOptionsDropdownKey } from '../types/BoardOptionsDropdownKey';
export type BoardOptionsDropdownContentProps = {
customHotkeyScope: HotkeyScope;
@ -144,9 +143,7 @@ export const BoardOptionsDropdownContent = ({
const { handleFieldVisibilityChange } = useBoardCardFields();
const { closeDropdown } = useDropdown({
dropdownId: BoardOptionsDropdownKey,
});
const { closeDropdown } = useDropdown();
useScopedHotkeys(
Key.Escape,

View File

@ -3,8 +3,6 @@ import { userEvent, within } from '@storybook/testing-library';
import { BoardContext } from '@/companies/states/contexts/BoardContext';
import { CompanyBoardRecoilScopeContext } from '@/companies/states/recoil-scope-contexts/CompanyBoardRecoilScopeContext';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { ViewBarContext } from '@/ui/view-bar/contexts/ViewBarContext';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
import { ComponentWithRecoilScopeDecorator } from '~/testing/decorators/ComponentWithRecoilScopeDecorator';
@ -26,9 +24,7 @@ const meta: Meta<typeof BoardOptionsDropdown> = {
ViewBarRecoilScopeContext: parameters.customRecoilScopeContext,
}}
>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<Story />
</RecoilScope>
<Story />
</ViewBarContext.Provider>
</BoardContext.Provider>
),

View File

@ -1 +0,0 @@
export const BoardOptionsDropdownKey = 'board-options';

View File

@ -0,0 +1,3 @@
export enum BoardScopeIds {
OptionsDropdown = 'board-options',
}

View File

@ -1,4 +1,5 @@
import { DropdownMenu } from '@/ui/dropdown/components/DropdownMenu';
import { DropdownScope } from '@/ui/dropdown/scopes/DropdownScope';
import { FieldMetadata } from '@/ui/field/types/FieldMetadata';
import { ColumnDefinition } from '../types/ColumnDefinition';
@ -20,19 +21,20 @@ export const ColumnHeadWithDropdown = ({
primaryColumnKey,
}: ColumnHeadWithDropdownProps) => {
return (
<DropdownMenu
clickableComponent={<ColumnHead column={column} />}
dropdownId={column.key + '-header'}
dropdownComponents={
<DataTableColumnDropdownMenu
column={column}
isFirstColumn={isFirstColumn}
isLastColumn={isLastColumn}
primaryColumnKey={primaryColumnKey}
/>
}
dropdownHotkeyScope={{ scope: column.key + '-header' }}
dropdownOffset={{ x: 0, y: -8 }}
/>
<DropdownScope dropdownScopeId={column.key + '-header'}>
<DropdownMenu
clickableComponent={<ColumnHead column={column} />}
dropdownComponents={
<DataTableColumnDropdownMenu
column={column}
isFirstColumn={isFirstColumn}
isLastColumn={isLastColumn}
primaryColumnKey={primaryColumnKey}
/>
}
dropdownHotkeyScope={{ scope: column.key + '-header' }}
dropdownOffset={{ x: 0, y: -8 }}
/>
</DropdownScope>
);
};

View File

@ -26,7 +26,7 @@ export const DataTableColumnDropdownMenu = ({
useTableColumns();
const { closeDropdown } = useDropdown({
dropdownId: ColumnHeadDropdownId,
dropdownScopeId: ColumnHeadDropdownId,
});
const handleColumnMoveLeft = () => {

View File

@ -3,10 +3,8 @@ import styled from '@emotion/styled';
import { useRecoilCallback, useRecoilState } from 'recoil';
import { IconButton } from '@/ui/button/components/IconButton';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { IconPlus } from '@/ui/icon';
import { useTrackPointer } from '@/ui/utilities/pointer-event/hooks/useTrackPointer';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { useTableColumns } from '../hooks/useTableColumns';
@ -177,36 +175,33 @@ export const DataTableHeader = () => {
>
<SelectAllCheckbox />
</th>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
{visibleTableColumns.map((column, index) => (
<StyledColumnHeaderCell
key={column.key}
isResizing={resizedFieldKey === column.key}
columnWidth={Math.max(
tableColumnsByKey[column.key].size +
(resizedFieldKey === column.key ? resizeFieldOffset : 0),
COLUMN_MIN_WIDTH,
)}
>
<StyledColumnHeadContainer>
<ColumnHeadWithDropdown
column={column}
isFirstColumn={index === 1}
isLastColumn={index === visibleTableColumns.length - 1}
primaryColumnKey={primaryColumn.key}
/>
</StyledColumnHeadContainer>
<StyledResizeHandler
className="cursor-col-resize"
role="separator"
onPointerDown={() => {
setResizedFieldKey(column.key);
}}
{visibleTableColumns.map((column, index) => (
<StyledColumnHeaderCell
key={column.key}
isResizing={resizedFieldKey === column.key}
columnWidth={Math.max(
tableColumnsByKey[column.key].size +
(resizedFieldKey === column.key ? resizeFieldOffset : 0),
COLUMN_MIN_WIDTH,
)}
>
<StyledColumnHeadContainer>
<ColumnHeadWithDropdown
column={column}
isFirstColumn={index === 1}
isLastColumn={index === visibleTableColumns.length - 1}
primaryColumnKey={primaryColumn.key}
/>
</StyledColumnHeaderCell>
))}
</RecoilScope>
</StyledColumnHeadContainer>
<StyledResizeHandler
className="cursor-col-resize"
role="separator"
onPointerDown={() => {
setResizedFieldKey(column.key);
}}
/>
</StyledColumnHeaderCell>
))}
<th>
{hiddenTableColumns.length > 0 && (

View File

@ -4,7 +4,7 @@ import { useDropdown } from '@/ui/dropdown/hooks/useDropdown';
export const TableOptionsDropdownButton = () => {
const { isDropdownOpen, toggleDropdown } = useDropdown({
dropdownId: TableOptionsDropdownId,
dropdownScopeId: TableOptionsDropdownId,
});
return (

View File

@ -22,7 +22,6 @@ import { currentViewScopedSelector } from '@/ui/view-bar/states/selectors/curren
import { viewsByIdScopedSelector } from '@/ui/view-bar/states/selectors/viewsByIdScopedSelector';
import { viewEditModeState } from '@/ui/view-bar/states/viewEditModeState';
import { TableOptionsDropdownId } from '../../constants/TableOptionsDropdownId';
import { useTableColumns } from '../../hooks/useTableColumns';
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
import { savedTableColumnsFamilyState } from '../../states/savedTableColumnsFamilyState';
@ -37,9 +36,7 @@ export const TableOptionsDropdownContent = () => {
const scopeId = useRecoilScopeId(TableRecoilScopeContext);
const { onImport } = useContext(ViewBarContext);
const { closeDropdown } = useDropdown({
dropdownId: TableOptionsDropdownId,
});
const { closeDropdown } = useDropdown();
const [currentMenu, setCurrentMenu] = useState<TableOptionsMenu | undefined>(
undefined,

View File

@ -1,7 +1,6 @@
import { Meta, StoryObj } from '@storybook/react';
import { userEvent, within } from '@storybook/testing-library';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { ViewBarContext } from '@/ui/view-bar/contexts/ViewBarContext';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
@ -20,9 +19,7 @@ const meta: Meta<typeof TableOptionsDropdown> = {
ViewBarRecoilScopeContext: TableRecoilScopeContext,
}}
>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<Story />
</RecoilScope>
<Story />
</ViewBarContext.Provider>
</RecoilScope>
),

View File

@ -2,8 +2,6 @@ import { useContext } from 'react';
import { useSearchParams } from 'react-router-dom';
import { useRecoilCallback } from 'recoil';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { useRecoilScopeId } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopeId';
import { ViewBar } from '@/ui/view-bar/components/ViewBar';
import { ViewBarContext } from '@/ui/view-bar/contexts/ViewBarContext';
@ -34,23 +32,21 @@ export const TableHeader = () => {
);
return (
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<ViewBarContext.Provider
value={{
...viewBarContextProps,
onCurrentViewSubmit,
onViewSelect: handleViewSelect,
}}
>
<ViewBar
optionsDropdownButton={
<TableOptionsDropdown
customHotkeyScope={{ scope: TableOptionsHotkeyScope.Dropdown }}
/>
}
optionsDropdownKey={TableOptionsDropdownId}
/>
</ViewBarContext.Provider>
</RecoilScope>
<ViewBarContext.Provider
value={{
...viewBarContextProps,
onCurrentViewSubmit,
onViewSelect: handleViewSelect,
}}
>
<ViewBar
optionsDropdownButton={
<TableOptionsDropdown
customHotkeyScope={{ scope: TableOptionsHotkeyScope.Dropdown }}
/>
}
optionsDropdownScopeId={TableOptionsDropdownId}
/>
</ViewBarContext.Provider>
);
};

View File

@ -16,7 +16,6 @@ import { DropdownToggleEffect } from './DropdownToggleEffect';
type DropdownMenuProps = {
clickableComponent?: JSX.Element | JSX.Element[];
dropdownComponents: JSX.Element | JSX.Element[];
dropdownId: string;
hotkey?: {
key: Keys;
scope: string;
@ -32,7 +31,6 @@ type DropdownMenuProps = {
export const DropdownMenu = ({
clickableComponent,
dropdownComponents,
dropdownId,
hotkey,
dropdownHotkeyScope,
dropdownPlacement = 'bottom-end',
@ -43,9 +41,7 @@ export const DropdownMenu = ({
}: DropdownMenuProps) => {
const containerRef = useRef<HTMLDivElement>(null);
const { isDropdownOpen, toggleDropdown, closeDropdown } = useDropdown({
dropdownId,
});
const { isDropdownOpen, toggleDropdown, closeDropdown } = useDropdown();
const { refs, floatingStyles } = useFloating({
placement: dropdownPlacement,
@ -71,8 +67,7 @@ export const DropdownMenu = ({
});
useInternalHotkeyScopeManagement({
dropdownId,
dropdownHotkeyScope,
dropdownHotkeyScopeFromParent: dropdownHotkeyScope,
});
useScopedHotkeys(
@ -83,6 +78,7 @@ export const DropdownMenu = ({
dropdownHotkeyScope.scope,
[closeDropdown],
);
return (
<div ref={containerRef}>
{clickableComponent && (
@ -101,11 +97,7 @@ export const DropdownMenu = ({
{dropdownComponents}
</div>
)}
<DropdownToggleEffect
dropdownId={dropdownId}
onDropdownClose={onClose}
onDropdownOpen={onOpen}
/>
<DropdownToggleEffect onDropdownClose={onClose} onDropdownOpen={onOpen} />
</div>
);
};

View File

@ -3,15 +3,13 @@ import { useEffect } from 'react';
import { useDropdown } from '@/ui/dropdown/hooks/useDropdown';
export const DropdownToggleEffect = ({
dropdownId,
onDropdownClose,
onDropdownOpen,
}: {
dropdownId: string;
onDropdownClose?: () => void;
onDropdownOpen?: () => void;
}) => {
const { isDropdownOpen } = useDropdown({ dropdownId });
const { isDropdownOpen } = useDropdown();
useEffect(() => {
if (isDropdownOpen) {

View File

@ -1,47 +1,52 @@
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { useRecoilScopedFamilyState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedFamilyState';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
import { dropdownButtonHotkeyScopeScopedFamilyState } from '../states/dropdownButtonHotkeyScopeScopedFamilyState';
import { isDropdownButtonOpenScopedFamilyState } from '../states/isDropdownButtonOpenScopedFamilyState';
import { DropdownRecoilScopeContext } from '../states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { DropdownScopeInternalContext } from '../scopes/scope-internal-context/DropdownScopeInternalContext';
export const useDropdown = ({ dropdownId }: { dropdownId: string }) => {
import { useDropdownStates } from './useDropdownStates';
type UseDropdownProps = {
dropdownScopeId?: string;
};
export const useDropdown = (props?: UseDropdownProps) => {
const {
setHotkeyScopeAndMemorizePreviousScope,
goBackToPreviousHotkeyScope,
} = usePreviousHotkeyScope();
const [isDropdownButtonOpen, setIsDropdownButtonOpen] =
useRecoilScopedFamilyState(
isDropdownButtonOpenScopedFamilyState,
dropdownId,
DropdownRecoilScopeContext,
);
const [dropdownButtonHotkeyScope] = useRecoilScopedFamilyState(
dropdownButtonHotkeyScopeScopedFamilyState,
dropdownId,
DropdownRecoilScopeContext,
const scopeId = useAvailableScopeIdOrThrow(
DropdownScopeInternalContext,
props?.dropdownScopeId,
);
const {
dropdownHotkeyScope,
setDropdownHotkeyScope,
isDropdownOpen,
setIsDropdownOpen,
} = useDropdownStates({
scopeId,
});
const closeDropdownButton = () => {
goBackToPreviousHotkeyScope();
setIsDropdownButtonOpen(false);
setIsDropdownOpen(false);
};
const openDropdownButton = () => {
setIsDropdownButtonOpen(true);
setIsDropdownOpen(true);
if (dropdownButtonHotkeyScope) {
if (dropdownHotkeyScope) {
setHotkeyScopeAndMemorizePreviousScope(
dropdownButtonHotkeyScope.scope,
dropdownButtonHotkeyScope.customScopes,
dropdownHotkeyScope.scope,
dropdownHotkeyScope.customScopes,
);
}
};
const toggleDropdownButton = () => {
if (isDropdownButtonOpen) {
if (isDropdownOpen) {
closeDropdownButton();
} else {
openDropdownButton();
@ -49,9 +54,12 @@ export const useDropdown = ({ dropdownId }: { dropdownId: string }) => {
};
return {
isDropdownOpen: isDropdownButtonOpen,
isDropdownOpen: isDropdownOpen,
closeDropdown: closeDropdownButton,
toggleDropdown: toggleDropdownButton,
openDropdown: openDropdownButton,
scopeId,
dropdownHotkeyScope,
setDropdownHotkeyScope,
};
};

View File

@ -0,0 +1,23 @@
import { useRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedStateV2';
import { dropdownHotkeyScopeScopedState } from '../states/dropdownHotkeyScopeScopedState';
import { isDropdownOpenScopedState } from '../states/isDropdownOpenScopedState';
export const useDropdownStates = ({ scopeId }: { scopeId: string }) => {
const [isDropdownOpen, setIsDropdownOpen] = useRecoilScopedStateV2(
isDropdownOpenScopedState,
scopeId,
);
const [dropdownHotkeyScope, setDropdownHotkeyScope] = useRecoilScopedStateV2(
dropdownHotkeyScopeScopedState,
scopeId,
);
return {
isDropdownOpen,
setIsDropdownOpen,
dropdownHotkeyScope,
setDropdownHotkeyScope,
};
};

View File

@ -1,33 +1,24 @@
import { useEffect } from 'react';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useRecoilScopedFamilyState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedFamilyState';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { dropdownButtonHotkeyScopeScopedFamilyState } from '../states/dropdownButtonHotkeyScopeScopedFamilyState';
import { DropdownRecoilScopeContext } from '../states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { useDropdown } from './useDropdown';
export const useInternalHotkeyScopeManagement = ({
dropdownId,
dropdownHotkeyScope,
dropdownHotkeyScopeFromParent,
}: {
dropdownId: string;
dropdownHotkeyScope?: HotkeyScope;
dropdownHotkeyScopeFromParent?: HotkeyScope;
}) => {
const [dropdownButtonHotkeyScope, setDropdownButtonHotkeyScope] =
useRecoilScopedFamilyState(
dropdownButtonHotkeyScopeScopedFamilyState,
dropdownId,
DropdownRecoilScopeContext,
);
const { dropdownHotkeyScope, setDropdownHotkeyScope } = useDropdown();
useEffect(() => {
if (!isDeeplyEqual(dropdownButtonHotkeyScope, dropdownHotkeyScope)) {
setDropdownButtonHotkeyScope(dropdownHotkeyScope);
if (!isDeeplyEqual(dropdownHotkeyScopeFromParent, dropdownHotkeyScope)) {
setDropdownHotkeyScope(dropdownHotkeyScopeFromParent);
}
}, [
dropdownHotkeyScope,
dropdownButtonHotkeyScope,
setDropdownButtonHotkeyScope,
dropdownHotkeyScopeFromParent,
setDropdownHotkeyScope,
]);
};

View File

@ -0,0 +1,19 @@
import { ReactNode } from 'react';
import { DropdownScopeInternalContext } from './scope-internal-context/DropdownScopeInternalContext';
type DropdownScopeProps = {
children: ReactNode;
dropdownScopeId: string;
};
export const DropdownScope = ({
children,
dropdownScopeId,
}: DropdownScopeProps) => {
return (
<DropdownScopeInternalContext.Provider value={{ scopeId: dropdownScopeId }}>
{children}
</DropdownScopeInternalContext.Provider>
);
};

View File

@ -0,0 +1,9 @@
import { ScopedStateKey } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopedStateKey';
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
type DropdownScopeInternalContextProps = ScopedStateKey & {
test?: string;
};
export const DropdownScopeInternalContext =
createScopeInternalContext<DropdownScopeInternalContextProps>();

View File

@ -1,11 +0,0 @@
import { atomFamily } from 'recoil';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
export const dropdownButtonHotkeyScopeScopedFamilyState = atomFamily<
HotkeyScope | null | undefined,
string
>({
key: 'dropdownButtonHotkeyScopeScopedFamilyState',
default: null,
});

View File

@ -0,0 +1,9 @@
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
export const dropdownHotkeyScopeScopedState = createScopedState<
HotkeyScope | null | undefined
>({
key: 'dropdownHotkeyScopeScopedState',
defaultValue: null,
});

View File

@ -1,9 +0,0 @@
import { atomFamily } from 'recoil';
export const isDropdownButtonOpenScopedFamilyState = atomFamily<
boolean,
string
>({
key: 'isDropdownButtonOpenScopedState',
default: false,
});

View File

@ -0,0 +1,6 @@
import { createScopedState } from '@/ui/utilities/recoil-scope/utils/createScopedState';
export const isDropdownOpenScopedState = createScopedState<boolean>({
key: 'isDropdownOpenScopedState',
defaultValue: false,
});

View File

@ -1,3 +0,0 @@
import { createContext } from 'react';
export const DropdownRecoilScopeContext = createContext<string | null>(null);

View File

@ -8,6 +8,7 @@ import { CountryCallingCode } from 'libphonenumber-js';
import { DropdownMenu } from '@/ui/dropdown/components/DropdownMenu';
import { useDropdown } from '@/ui/dropdown/hooks/useDropdown';
import { DropdownScope } from '@/ui/dropdown/scopes/DropdownScope';
import { IconChevronDown } from '@/ui/icon';
import { IconWorld } from '../constants/icons';
@ -77,7 +78,7 @@ export const CountryPickerDropdownButton = ({
const [selectedCountry, setSelectedCountry] = useState<Country>();
const { isDropdownOpen, closeDropdown } = useDropdown({
dropdownId: 'country-picker',
dropdownScopeId: 'country-picker',
});
const handleChange = (countryCode: string) => {
@ -122,25 +123,26 @@ export const CountryPickerDropdownButton = ({
}, [countries, value]);
return (
<DropdownMenu
dropdownId="country-picker"
dropdownHotkeyScope={{ scope: CountryPickerHotkeyScope.CountryPicker }}
clickableComponent={
<StyledDropdownButtonContainer isUnfolded={isDropdownOpen}>
<StyledIconContainer>
{selectedCountry ? <selectedCountry.Flag /> : <IconWorld />}
<IconChevronDown size={theme.icon.size.sm} />
</StyledIconContainer>
</StyledDropdownButtonContainer>
}
dropdownComponents={
<CountryPickerDropdownSelect
countries={countries}
selectedCountry={selectedCountry}
onChange={handleChange}
/>
}
dropdownOffset={{ x: -60, y: -34 }}
/>
<DropdownScope dropdownScopeId="country-picker">
<DropdownMenu
dropdownHotkeyScope={{ scope: CountryPickerHotkeyScope.CountryPicker }}
clickableComponent={
<StyledDropdownButtonContainer isUnfolded={isDropdownOpen}>
<StyledIconContainer>
{selectedCountry ? <selectedCountry.Flag /> : <IconWorld />}
<IconChevronDown size={theme.icon.size.sm} />
</StyledIconContainer>
</StyledDropdownButtonContainer>
}
dropdownComponents={
<CountryPickerDropdownSelect
countries={countries}
selectedCountry={selectedCountry}
onChange={handleChange}
/>
}
dropdownOffset={{ x: -60, y: -34 }}
/>
</DropdownScope>
);
};

View File

@ -2,9 +2,6 @@ import { useEffect, useRef, useState } from 'react';
import ReactPhoneNumberInput from 'react-phone-number-input';
import styled from '@emotion/styled';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
import { useRegisterInputEvents } from '../hooks/useRegisterInputEvents';
import { CountryPickerDropdownButton } from './CountryPickerDropdownButton';
@ -86,17 +83,15 @@ export const PhoneInput = ({
return (
<StyledContainer ref={wrapperRef}>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<StyledCustomPhoneInput
autoFocus={autoFocus}
placeholder="Phone number"
value={value}
onChange={setInternalValue}
international={true}
withCountryCallingCode={true}
countrySelectComponent={CountryPickerDropdownButton}
/>
</RecoilScope>
<StyledCustomPhoneInput
autoFocus={autoFocus}
placeholder="Phone number"
value={value}
onChange={setInternalValue}
international={true}
withCountryCallingCode={true}
countrySelectComponent={CountryPickerDropdownButton}
/>
</StyledContainer>
);
};

View File

@ -22,7 +22,7 @@ export const ShowPageAddButton = ({
entity: ActivityTargetableEntity;
}) => {
const { closeDropdown, toggleDropdown } = useDropdown({
dropdownId: 'add-show-page',
dropdownScopeId: 'add-show-page',
});
const openCreateActivity = useOpenCreateActivityDrawer();

View File

@ -5,6 +5,10 @@ import { RecoilScopeContext as RecoilScopeContextType } from '@/types/RecoilScop
import { RecoilScopeContext } from '../states/RecoilScopeContext';
/**
*
* @deprecated Use a custom scope context instead, see example with DropdownScope
*/
export const RecoilScope = ({
children,
scopeId,

View File

@ -1,5 +1,9 @@
import { Context, useContext } from 'react';
/**
* @deprecated use a custom scope instead and desctructure the scope id from the scope context
* Get the scope context with useScopeInternalContext
*/
export const useContextScopeId = (SpecificContext: Context<string | null>) => {
const recoilScopeId = useContext(SpecificContext);

View File

@ -2,6 +2,9 @@ import { useContext } from 'react';
import { RecoilScopeContext } from '@/types/RecoilScopeContext';
/**
* @deprecated Use a custom scope instead and desctructure the scope id from the scope context
*/
export const useRecoilScopeId = (RecoilScopeContext: RecoilScopeContext) => {
const recoilScopeId = useContext(RecoilScopeContext);

View File

@ -1,25 +1,21 @@
import { Context, useContext } from 'react';
import { RecoilState, useRecoilState } from 'recoil';
import { RecoilState, SerializableParam, useRecoilState } from 'recoil';
import { RecoilScopeContext } from '../states/RecoilScopeContext';
import { ScopedFamilyStateKey } from '../scopes-internal/types/ScopedFamilyStateKey';
export const useRecoilScopedFamilyState = <StateType>(
recoilState: (familyUniqueId: string) => RecoilState<StateType>,
uniqueIdInRecoilScope: string,
CustomRecoilScopeContext?: Context<string | null>,
export const useRecoilScopedFamilyState = <
StateType,
FamilyKey extends SerializableParam,
>(
recoilState: (
scopedFamilyKey: ScopedFamilyStateKey<FamilyKey>,
) => RecoilState<StateType>,
scopeId: string,
familyKey: FamilyKey,
) => {
const recoilScopeId = useContext(
CustomRecoilScopeContext ?? RecoilScopeContext,
return useRecoilState<StateType>(
recoilState({
scopeId,
familyKey,
}),
);
if (!recoilScopeId)
throw new Error(
`Using a scoped atom without a RecoilScope : ${
recoilState('').key
}, verify that you are using a RecoilScope with a specific context if you intended to do so.`,
);
const familyUniqueId = recoilScopeId + uniqueIdInRecoilScope;
return useRecoilState<StateType>(recoilState(familyUniqueId));
};

View File

@ -0,0 +1,14 @@
import { RecoilState, useRecoilState } from 'recoil';
import { ScopedStateKey } from '../scopes-internal/types/ScopedStateKey';
export const useRecoilScopedStateV2 = <StateType>(
recoilState: (scopedKey: ScopedStateKey) => RecoilState<StateType>,
scopeId: string,
) => {
return useRecoilState<StateType>(
recoilState({
scopeId,
}),
);
};

View File

@ -3,6 +3,9 @@ import { RecoilState, RecoilValueReadOnly, useRecoilValue } from 'recoil';
import { RecoilScopeContext } from '../states/RecoilScopeContext';
/**
* @deprecated use useRecoilScopedStateV2 instead
*/
export const useRecoilScopedValue = <T>(
recoilState: (param: string) => RecoilState<T> | RecoilValueReadOnly<T>,
CustomRecoilScopeContext?: Context<string | null>,

View File

@ -0,0 +1,14 @@
import { RecoilState, useRecoilValue } from 'recoil';
import { ScopedStateKey } from '../scopes-internal/types/ScopedStateKey';
export const useRecoilScopedValueV2 = <StateType>(
recoilState: (scopedKey: ScopedStateKey) => RecoilState<StateType>,
scopeId: string,
) => {
return useRecoilValue<StateType>(
recoilState({
scopeId,
}),
);
};

View File

@ -0,0 +1,20 @@
import { ScopeInternalContext } from '../types/ScopeInternalContext';
import { useScopeInternalContext } from './useScopeInternalContext';
export const useAvailableScopeIdOrThrow = <T extends { scopeId: string }>(
Context: ScopeInternalContext<T>,
scopeIdFromProps?: string,
): string => {
const scopeInternalContext = useScopeInternalContext(Context);
const scopeIdFromContext = scopeInternalContext?.scopeId;
if (scopeIdFromProps) {
return scopeIdFromProps;
} else if (scopeIdFromContext) {
return scopeIdFromContext;
} else {
throw new Error('Scope id is not provided and cannot be found in context.');
}
};

View File

@ -0,0 +1,11 @@
import { useContext } from 'react';
import { ScopeInternalContext } from '../types/ScopeInternalContext';
export const useScopeInternalContext = <T extends { scopeId: string }>(
Context: ScopeInternalContext<T>,
) => {
const context = useContext(Context);
return context;
};

View File

@ -0,0 +1,19 @@
import { useContext } from 'react';
import { isDefined } from '~/utils/isDefined';
import { ScopeInternalContext } from '../types/ScopeInternalContext';
export const useScopeInternalContextOrThrow = <T extends { scopeId: string }>(
Context: ScopeInternalContext<T>,
) => {
const context = useContext(Context);
if (!isDefined(context)) {
throw new Error(
`Using a scope context without a ScopeInternalContext.Provider wrapper for context : ${Context.displayName}.`,
);
}
return context;
};

View File

@ -0,0 +1,4 @@
import { Context } from 'react';
export type ScopeInternalContext<T extends { scopeId: string }> =
Context<T | null>;

View File

@ -0,0 +1,6 @@
import { SerializableParam } from 'recoil';
export type ScopedFamilyStateKey<FamilyKey extends SerializableParam> = {
scopeId: string;
familyKey: FamilyKey;
};

View File

@ -0,0 +1,3 @@
export type ScopedStateKey = {
scopeId: string;
};

View File

@ -0,0 +1,13 @@
import { Context, createContext } from 'react';
import { ScopedStateKey } from '../types/ScopedStateKey';
type ScopeInternalContext<T extends ScopedStateKey> = Context<T | null>;
export const createScopeInternalContext = <T extends ScopedStateKey>(
initialValue?: T,
) => {
return createContext<T | null>(
initialValue ?? null,
) as ScopeInternalContext<T>;
};

View File

@ -0,0 +1,19 @@
import { atomFamily, SerializableParam } from 'recoil';
import { ScopedFamilyStateKey } from '../scopes-internal/types/ScopedFamilyStateKey';
export const createScopedFamilyState = <
ValueType,
FamilyKey extends SerializableParam,
>({
key,
defaultValue,
}: {
key: string;
defaultValue: ValueType;
}) => {
return atomFamily<ValueType, ScopedFamilyStateKey<FamilyKey>>({
key,
default: defaultValue,
});
};

View File

@ -0,0 +1,14 @@
import { atomFamily } from 'recoil';
export const createScopedState = <ValueType>({
key,
defaultValue,
}: {
key: string;
defaultValue: ValueType;
}) => {
return atomFamily<ValueType, { scopeId: string }>({
key,
default: defaultValue,
});
};

View File

@ -6,7 +6,7 @@ import { FilterDropdownId } from '../constants/FilterDropdownId';
export const AddFilterFromDropdownButton = () => {
const { toggleDropdown } = useDropdown({
dropdownId: FilterDropdownId,
dropdownScopeId: FilterDropdownId,
});
const handleClick = () => {

View File

@ -13,7 +13,7 @@ export const MultipleFiltersButton = () => {
const { ViewBarRecoilScopeContext } = useViewBarContext();
const { isDropdownOpen, toggleDropdown } = useDropdown({
dropdownId: FilterDropdownId,
dropdownScopeId: FilterDropdownId,
});
const [, setIsFilterDropdownOperandSelectUnfolded] = useRecoilScopedState(

View File

@ -1,22 +1,19 @@
import React from 'react';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { DropdownMenu } from '@/ui/dropdown/components/DropdownMenu';
import { DropdownMenuContainer } from '@/ui/dropdown/components/DropdownMenuContainer';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { IconChevronDown } from '@/ui/icon';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
import { StyledHeaderDropdownButton } from '@/ui/dropdown/components/StyledHeaderDropdownButton';
import { DropdownScope } from '@/ui/dropdown/scopes/DropdownScope';
import { IconChevronDown } from '@/ui/icon/index';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { filterDefinitionUsedInDropdownScopedState } from '@/ui/view-bar/states/filterDefinitionUsedInDropdownScopedState';
import { filterDropdownSearchInputScopedState } from '@/ui/view-bar/states/filterDropdownSearchInputScopedState';
import { selectedOperandInDropdownScopedState } from '@/ui/view-bar/states/selectedOperandInDropdownScopedState';
import { StyledHeaderDropdownButton } from '../../dropdown/components/StyledHeaderDropdownButton';
import { useViewBarContext } from '../hooks/useViewBarContext';
import { availableFiltersScopedState } from '../states/availableFiltersScopedState';
import { filtersScopedState } from '../states/filtersScopedState';
import { isFilterDropdownUnfoldedScopedState } from '../states/isFilterDropdownUnfoldedScopedState';
import { FilterOperand } from '../types/FilterOperand';
import { getOperandsForFilterType } from '../utils/getOperandsForFilterType';
@ -24,19 +21,11 @@ import { FilterDropdownEntitySearchInput } from './FilterDropdownEntitySearchInp
import { FilterDropdownEntitySelect } from './FilterDropdownEntitySelect';
import { GenericEntityFilterChip } from './GenericEntityFilterChip';
const StyledDropdownButtonContainer = styled.div`
display: flex;
flex-direction: column;
position: relative;
`;
export const SingleEntityFilterDropdownButton = ({
hotkeyScope,
}: {
hotkeyScope: HotkeyScope;
}) => {
const theme = useTheme();
const { ViewBarRecoilScopeContext } = useViewBarContext();
const [availableFilters] = useRecoilScopedState(
@ -45,12 +34,6 @@ export const SingleEntityFilterDropdownButton = ({
);
const availableFilter = availableFilters[0];
const [isFilterDropdownUnfolded, setIsFilterDropdownUnfolded] =
useRecoilScopedState(
isFilterDropdownUnfoldedScopedState,
DropdownRecoilScopeContext,
);
const [filters] = useRecoilScopedState(
filtersScopedState,
ViewBarRecoilScopeContext,
@ -61,11 +44,6 @@ export const SingleEntityFilterDropdownButton = ({
ViewBarRecoilScopeContext,
);
const [, setFilterDropdownSearchInput] = useRecoilScopedState(
filterDropdownSearchInputScopedState,
ViewBarRecoilScopeContext,
);
const [, setSelectedOperandInDropdown] = useRecoilScopedState(
selectedOperandInDropdownScopedState,
ViewBarRecoilScopeContext,
@ -81,45 +59,37 @@ export const SingleEntityFilterDropdownButton = ({
setSelectedOperandInDropdown,
]);
const setHotkeyScope = useSetHotkeyScope();
const handleIsUnfoldedChange = (newIsUnfolded: boolean) => {
if (newIsUnfolded) {
setHotkeyScope(hotkeyScope.scope, hotkeyScope.customScopes);
setIsFilterDropdownUnfolded(true);
} else {
setHotkeyScope(hotkeyScope.scope, hotkeyScope.customScopes);
setIsFilterDropdownUnfolded(false);
setFilterDropdownSearchInput('');
}
};
const theme = useTheme();
return (
<StyledDropdownButtonContainer data-select-disable>
<StyledHeaderDropdownButton
isUnfolded={isFilterDropdownUnfolded}
onClick={() => handleIsUnfoldedChange(!isFilterDropdownUnfolded)}
>
{filters[0] ? (
<GenericEntityFilterChip
filter={filters[0]}
Icon={
filters[0].operand === FilterOperand.IsNotNull
? availableFilter.SelectAllIcon
: undefined
}
/>
) : (
'Filter'
)}
<IconChevronDown size={theme.icon.size.md} />
</StyledHeaderDropdownButton>
{isFilterDropdownUnfolded && (
<DropdownMenuContainer onClose={() => handleIsUnfoldedChange(false)}>
<FilterDropdownEntitySearchInput />
<FilterDropdownEntitySelect />
</DropdownMenuContainer>
)}
</StyledDropdownButtonContainer>
<DropdownScope dropdownScopeId="single-entity-filter-dropdown">
<DropdownMenu
dropdownHotkeyScope={hotkeyScope}
dropdownOffset={{ x: 0, y: -28 }}
clickableComponent={
<StyledHeaderDropdownButton>
{filters[0] ? (
<GenericEntityFilterChip
filter={filters[0]}
Icon={
filters[0].operand === FilterOperand.IsNotNull
? availableFilter.SelectAllIcon
: undefined
}
/>
) : (
'Filter'
)}
<IconChevronDown size={theme.icon.size.md} />
</StyledHeaderDropdownButton>
}
dropdownComponents={
<DropdownMenuContainer>
<FilterDropdownEntitySearchInput />
<FilterDropdownEntitySelect />
</DropdownMenuContainer>
}
/>
</DropdownScope>
);
};

View File

@ -55,7 +55,7 @@ export const SortDropdownButton = ({
const isSortSelected = sorts.length > 0;
const { toggleDropdown } = useDropdown({
dropdownId: SortDropdownId,
dropdownScopeId: SortDropdownId,
});
const handleButtonClick = () => {

View File

@ -15,16 +15,16 @@ import { ViewsDropdownButton } from './ViewsDropdownButton';
export type ViewBarProps = {
className?: string;
optionsDropdownButton: ReactNode;
optionsDropdownKey: string;
optionsDropdownScopeId: string;
};
export const ViewBar = ({
className,
optionsDropdownButton,
optionsDropdownKey,
optionsDropdownScopeId,
}: ViewBarProps) => {
const { openDropdown: openOptionsDropdownButton } = useDropdown({
dropdownId: optionsDropdownKey,
dropdownScopeId: optionsDropdownScopeId,
});
return (

View File

@ -2,6 +2,7 @@ import { Keys } from 'react-hotkeys-hook';
import { Placement } from '@floating-ui/react';
import { DropdownMenu } from '@/ui/dropdown/components/DropdownMenu';
import { DropdownScope } from '@/ui/dropdown/scopes/DropdownScope';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
type ViewBarDropdownButtonProps = {
@ -31,17 +32,18 @@ export const ViewBarDropdownButton = ({
onOpen,
}: ViewBarDropdownButtonProps) => {
return (
<DropdownMenu
clickableComponent={buttonComponent}
dropdownComponents={dropdownComponents}
dropdownId={dropdownId}
hotkey={hotkey}
dropdownHotkeyScope={dropdownHotkeyScope}
dropdownOffset={{ x: 0, y: 8 }}
dropdownPlacement={dropdownPlacement}
onClickOutside={onClickOutside}
onClose={onClose}
onOpen={onOpen}
/>
<DropdownScope dropdownScopeId={dropdownId}>
<DropdownMenu
clickableComponent={buttonComponent}
dropdownComponents={dropdownComponents}
hotkey={hotkey}
dropdownHotkeyScope={dropdownHotkeyScope}
dropdownOffset={{ x: 0, y: 8 }}
dropdownPlacement={dropdownPlacement}
onClickOutside={onClickOutside}
onClose={onClose}
onOpen={onOpen}
/>
</DropdownScope>
);
};

View File

@ -105,7 +105,7 @@ export const ViewsDropdownButton = ({
);
const { isDropdownOpen, closeDropdown } = useDropdown({
dropdownId: ViewsDropdownId,
dropdownScopeId: ViewsDropdownId,
});
const setViewEditMode = useSetRecoilState(viewEditModeState);

View File

@ -11,7 +11,6 @@ import { DataTableContextMenu } from '@/ui/data-table/context-menu/components/Da
import { useUpsertDataTableItem } from '@/ui/data-table/hooks/useUpsertDataTableItem';
import { useUpsertTableRowId } from '@/ui/data-table/hooks/useUpsertTableRowId';
import { TableRecoilScopeContext } from '@/ui/data-table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { IconBuildingSkyscraper } from '@/ui/icon';
import { PageAddButton } from '@/ui/layout/components/PageAddButton';
import { PageBody } from '@/ui/layout/components/PageBody';
@ -58,10 +57,8 @@ export const Companies = () => {
<SpreadsheetImportProvider>
<PageContainer>
<PageHeader title="Companies" Icon={IconBuildingSkyscraper}>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<PageHotkeysEffect onAddButtonClick={handleAddButtonClick} />
<PageAddButton onClick={handleAddButtonClick} />
</RecoilScope>
<PageHotkeysEffect onAddButtonClick={handleAddButtonClick} />
<PageAddButton onClick={handleAddButtonClick} />
</PageHeader>
<PageBody>
<RecoilScope

View File

@ -6,7 +6,6 @@ import { CompanyTeam } from '@/companies/components/CompanyTeam';
import { useCompanyQuery } from '@/companies/hooks/useCompanyQuery';
import { useFavorites } from '@/favorites/hooks/useFavorites';
import { AppPath } from '@/types/AppPath';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { FieldContext } from '@/ui/field/contexts/FieldContext';
import { IconBuildingSkyscraper } from '@/ui/icon';
import { InlineCell } from '@/ui/inline-cell/components/InlineCell';
@ -62,19 +61,17 @@ export const CompanyShow = () => {
hasBackButton
Icon={IconBuildingSkyscraper}
>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<PageFavoriteButton
isFavorite={isFavorite}
onClick={handleFavoriteButtonClick}
/>
<ShowPageAddButton
key="add"
entity={{
id: company.id,
type: ActivityTargetableEntityType.Company,
}}
/>
</RecoilScope>
<PageFavoriteButton
isFavorite={isFavorite}
onClick={handleFavoriteButtonClick}
/>
<ShowPageAddButton
key="add"
entity={{
id: company.id,
type: ActivityTargetableEntityType.Company,
}}
/>
</PageHeader>
<PageBody>
<RecoilScope CustomRecoilScopeContext={ShowPageRecoilScopeContext}>

View File

@ -3,7 +3,6 @@ import { CompanyBoardRecoilScopeContext } from '@/companies/states/recoil-scope-
import { PipelineAddButton } from '@/pipeline/components/PipelineAddButton';
import { usePipelineStages } from '@/pipeline/hooks/usePipelineStages';
import { BoardOptionsContext } from '@/ui/board/contexts/BoardOptionsContext';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { IconTargetArrow } from '@/ui/icon';
import { PageBody } from '@/ui/layout/components/PageBody';
import { PageContainer } from '@/ui/layout/components/PageContainer';
@ -44,9 +43,7 @@ export const Opportunities = () => {
<PageContainer>
<RecoilScope>
<PageHeader title="Opportunities" Icon={IconTargetArrow}>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<PipelineAddButton />
</RecoilScope>
<PipelineAddButton />
</PageHeader>
<PageBody>
<BoardOptionsContext.Provider value={opportunitiesBoardOptions}>

View File

@ -9,7 +9,6 @@ import { DataTableContextMenu } from '@/ui/data-table/context-menu/components/Da
import { useUpsertDataTableItem } from '@/ui/data-table/hooks/useUpsertDataTableItem';
import { useUpsertTableRowId } from '@/ui/data-table/hooks/useUpsertTableRowId';
import { TableRecoilScopeContext } from '@/ui/data-table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { IconUser } from '@/ui/icon';
import { PageAddButton } from '@/ui/layout/components/PageAddButton';
import { PageBody } from '@/ui/layout/components/PageBody';
@ -54,10 +53,8 @@ export const People = () => {
<SpreadsheetImportProvider>
<PageContainer>
<PageHeader title="People" Icon={IconUser}>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<PageHotkeysEffect onAddButtonClick={handleAddButtonClick} />
<PageAddButton onClick={handleAddButtonClick} />
</RecoilScope>
<PageHotkeysEffect onAddButtonClick={handleAddButtonClick} />
<PageAddButton onClick={handleAddButtonClick} />
</PageHeader>
<PageBody>
<RecoilScope

View File

@ -7,7 +7,6 @@ import { useFavorites } from '@/favorites/hooks/useFavorites';
import { GET_PERSON } from '@/people/graphql/queries/getPerson';
import { usePersonQuery } from '@/people/hooks/usePersonQuery';
import { AppPath } from '@/types/AppPath';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { FieldContext } from '@/ui/field/contexts/FieldContext';
import { IconUser } from '@/ui/icon';
import { InlineCell } from '@/ui/inline-cell/components/InlineCell';
@ -77,27 +76,25 @@ export const PersonShow = () => {
<PageContainer>
<PageTitle title={person.displayName || 'No Name'} />
<PageHeader title={person.firstName ?? ''} Icon={IconUser} hasBackButton>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<PageFavoriteButton
isFavorite={isFavorite}
onClick={handleFavoriteButtonClick}
/>
<ShowPageAddButton
key="add"
entity={{
id: person.id,
type: ActivityTargetableEntityType.Person,
relatedEntities: person.company?.id
? [
{
id: person.company?.id,
type: ActivityTargetableEntityType.Company,
},
]
: undefined,
}}
/>
</RecoilScope>
<PageFavoriteButton
isFavorite={isFavorite}
onClick={handleFavoriteButtonClick}
/>
<ShowPageAddButton
key="add"
entity={{
id: person.id,
type: ActivityTargetableEntityType.Person,
relatedEntities: person.company?.id
? [
{
id: person.company?.id,
type: ActivityTargetableEntityType.Company,
},
]
: undefined,
}}
/>
</PageHeader>
<PageBody>
<RecoilScope CustomRecoilScopeContext={ShowPageRecoilScopeContext}>

View File

@ -3,7 +3,6 @@ import styled from '@emotion/styled';
import { TasksRecoilScopeContext } from '@/activities/states/recoil-scope-contexts/TasksRecoilScopeContext';
import { PageAddTaskButton } from '@/activities/tasks/components/PageAddTaskButton';
import { TaskGroups } from '@/activities/tasks/components/TaskGroups';
import { DropdownRecoilScopeContext } from '@/ui/dropdown/states/recoil-scope-contexts/DropdownRecoilScopeContext';
import { IconArchive, IconCheck, IconCheckbox } from '@/ui/icon/index';
import { RelationPickerHotkeyScope } from '@/ui/input/relation-picker/types/RelationPickerHotkeyScope';
import { PageBody } from '@/ui/layout/components/PageBody';
@ -48,43 +47,41 @@ export const Tasks = () => {
return (
<PageContainer>
<RecoilScope CustomRecoilScopeContext={DropdownRecoilScopeContext}>
<RecoilScope CustomRecoilScopeContext={TasksRecoilScopeContext}>
<TasksEffect />
<PageHeader title="Tasks" Icon={IconCheckbox}>
<PageAddTaskButton />
</PageHeader>
<PageBody>
{/* TODO: we should refactor filters as a standalone module ? */}
<ViewBarContext.Provider
value={{
ViewBarRecoilScopeContext: TasksRecoilScopeContext,
}}
>
<StyledTasksContainer>
<TopBar
leftComponent={
<StyledTabListContainer>
<TabList
context={TasksRecoilScopeContext}
tabs={TASK_TABS}
/>
</StyledTabListContainer>
}
rightComponent={
<FilterDropdownButton
key="tasks-filter-dropdown-button"
hotkeyScope={{
scope: RelationPickerHotkeyScope.RelationPicker,
}}
<RecoilScope CustomRecoilScopeContext={TasksRecoilScopeContext}>
<TasksEffect />
<PageHeader title="Tasks" Icon={IconCheckbox}>
<PageAddTaskButton />
</PageHeader>
<PageBody>
{/* TODO: we should refactor filters as a standalone module ? */}
<ViewBarContext.Provider
value={{
ViewBarRecoilScopeContext: TasksRecoilScopeContext,
}}
>
<StyledTasksContainer>
<TopBar
leftComponent={
<StyledTabListContainer>
<TabList
context={TasksRecoilScopeContext}
tabs={TASK_TABS}
/>
}
/>
<TaskGroups />
</StyledTasksContainer>
</ViewBarContext.Provider>
</PageBody>
</RecoilScope>
</StyledTabListContainer>
}
rightComponent={
<FilterDropdownButton
key="tasks-filter-dropdown-button"
hotkeyScope={{
scope: RelationPickerHotkeyScope.RelationPicker,
}}
/>
}
/>
<TaskGroups />
</StyledTasksContainer>
</ViewBarContext.Provider>
</PageBody>
</RecoilScope>
</PageContainer>
);

View File

@ -0,0 +1,3 @@
export type ScopeContextProps<T = unknown> = {
scopeId: string;
} & T;