+4
-2
@@ -1,12 +1,14 @@
|
||||
import { dialogInternalComponentState } from '@/ui/feedback/dialog-manager/states/dialogInternalComponentState';
|
||||
import { useDialogManager } from '@/ui/feedback/dialog-manager/hooks/useDialogManager';
|
||||
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { Dialog } from './Dialog';
|
||||
import { DialogManagerEffect } from './DialogManagerEffect';
|
||||
|
||||
export const DialogManager = ({ children }: React.PropsWithChildren) => {
|
||||
const dialogInternal = useRecoilComponentValue(dialogInternalComponentState);
|
||||
const dialogInternal = useRecoilComponentValueV2(
|
||||
dialogInternalComponentState,
|
||||
);
|
||||
const { closeDialog } = useDialogManager();
|
||||
|
||||
return (
|
||||
|
||||
+4
-2
@@ -5,10 +5,12 @@ import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePush
|
||||
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
|
||||
|
||||
import { dialogInternalComponentState } from '@/ui/feedback/dialog-manager/states/dialogInternalComponentState';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
|
||||
export const DialogManagerEffect = () => {
|
||||
const dialogInternal = useRecoilComponentValue(dialogInternalComponentState);
|
||||
const dialogInternal = useRecoilComponentValueV2(
|
||||
dialogInternalComponentState,
|
||||
);
|
||||
|
||||
const { pushFocusItemToFocusStack } = usePushFocusItemToFocusStack();
|
||||
|
||||
|
||||
+18
-7
@@ -1,4 +1,5 @@
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { Provider as JotaiProvider } from 'jotai';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
@@ -6,7 +7,11 @@ import { DialogComponentInstanceContext } from '@/ui/feedback/dialog-manager/con
|
||||
import { useDialogManager } from '@/ui/feedback/dialog-manager/hooks/useDialogManager';
|
||||
import { dialogInternalComponentState } from '@/ui/feedback/dialog-manager/states/dialogInternalComponentState';
|
||||
import { type DialogOptions } from '@/ui/feedback/dialog-manager/types/DialogOptions';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import {
|
||||
jotaiStore,
|
||||
resetJotaiStore,
|
||||
} from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
|
||||
const mockedUuid = 'mocked-uuid';
|
||||
jest.mock('uuid');
|
||||
@@ -15,11 +20,13 @@ jest.mock('uuid');
|
||||
|
||||
const Wrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<RecoilRoot>
|
||||
<DialogComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'dialog-manager' }}
|
||||
>
|
||||
{children}
|
||||
</DialogComponentInstanceContext.Provider>
|
||||
<JotaiProvider store={jotaiStore}>
|
||||
<DialogComponentInstanceContext.Provider
|
||||
value={{ instanceId: 'dialog-manager' }}
|
||||
>
|
||||
{children}
|
||||
</DialogComponentInstanceContext.Provider>
|
||||
</JotaiProvider>
|
||||
</RecoilRoot>
|
||||
);
|
||||
|
||||
@@ -77,7 +84,7 @@ const renderHooks = () => {
|
||||
const { result } = renderHook(
|
||||
() => ({
|
||||
dialogManager: useDialogManager(),
|
||||
dialogInternal: useRecoilComponentValue(dialogInternalComponentState),
|
||||
dialogInternal: useRecoilComponentValueV2(dialogInternalComponentState),
|
||||
}),
|
||||
renderHookConfig,
|
||||
);
|
||||
@@ -95,6 +102,10 @@ const expectedReturnFromEnqueue = (
|
||||
};
|
||||
|
||||
describe('useDialogManager', () => {
|
||||
beforeEach(() => {
|
||||
resetJotaiStore();
|
||||
});
|
||||
|
||||
describe('tests for useDialogManager - enqueueDialog', () => {
|
||||
it('Should enqueueDialog', () => {
|
||||
const result = renderHooks();
|
||||
|
||||
+36
-35
@@ -1,4 +1,4 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { useCallback } from 'react';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { DIALOG_FOCUS_ID } from '@/ui/feedback/dialog-manager/constants/DialogFocusId';
|
||||
@@ -8,55 +8,56 @@ import { DialogComponentInstanceContext } from '@/ui/feedback/dialog-manager/con
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { dialogInternalComponentState } from '@/ui/feedback/dialog-manager/states/dialogInternalComponentState';
|
||||
import { type DialogOptions } from '@/ui/feedback/dialog-manager/types/DialogOptions';
|
||||
import { useStore } from 'jotai';
|
||||
|
||||
export const useDialogManager = () => {
|
||||
const componentInstanceId = useAvailableComponentInstanceIdOrThrow(
|
||||
DialogComponentInstanceContext,
|
||||
);
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const { removeFocusItemFromFocusStackById } =
|
||||
useRemoveFocusItemFromFocusStackById();
|
||||
|
||||
const closeDialog = useRecoilCallback(
|
||||
({ set }) =>
|
||||
(id: string) => {
|
||||
set(
|
||||
dialogInternalComponentState.atomFamily({
|
||||
instanceId: componentInstanceId,
|
||||
}),
|
||||
(prevState) => ({
|
||||
...prevState,
|
||||
queue: prevState.queue.filter((dialog) => dialog.id !== id),
|
||||
}),
|
||||
);
|
||||
const closeDialog = useCallback(
|
||||
(id: string) => {
|
||||
store.set(
|
||||
dialogInternalComponentState.atomFamily({
|
||||
instanceId: componentInstanceId,
|
||||
}),
|
||||
(prevState) => ({
|
||||
...prevState,
|
||||
queue: prevState.queue.filter((dialog) => dialog.id !== id),
|
||||
}),
|
||||
);
|
||||
|
||||
removeFocusItemFromFocusStackById({ focusId: DIALOG_FOCUS_ID });
|
||||
},
|
||||
[componentInstanceId, removeFocusItemFromFocusStackById],
|
||||
removeFocusItemFromFocusStackById({ focusId: DIALOG_FOCUS_ID });
|
||||
},
|
||||
[componentInstanceId, removeFocusItemFromFocusStackById, store],
|
||||
);
|
||||
|
||||
const setDialogQueue = useRecoilCallback(
|
||||
({ set }) =>
|
||||
(newValue) =>
|
||||
set(
|
||||
dialogInternalComponentState.atomFamily({
|
||||
instanceId: componentInstanceId,
|
||||
}),
|
||||
(prev) => {
|
||||
if (prev.queue.length >= prev.maxQueue) {
|
||||
return {
|
||||
...prev,
|
||||
queue: [...prev.queue.slice(1), newValue] as DialogOptions[],
|
||||
};
|
||||
}
|
||||
|
||||
const setDialogQueue = useCallback(
|
||||
(newValue: DialogOptions) =>
|
||||
store.set(
|
||||
dialogInternalComponentState.atomFamily({
|
||||
instanceId: componentInstanceId,
|
||||
}),
|
||||
(prev) => {
|
||||
if (prev.queue.length >= prev.maxQueue) {
|
||||
return {
|
||||
...prev,
|
||||
queue: [...prev.queue, newValue] as DialogOptions[],
|
||||
queue: [...prev.queue.slice(1), newValue],
|
||||
};
|
||||
},
|
||||
),
|
||||
[componentInstanceId],
|
||||
}
|
||||
|
||||
return {
|
||||
...prev,
|
||||
queue: [...prev.queue, newValue],
|
||||
};
|
||||
},
|
||||
),
|
||||
[componentInstanceId, store],
|
||||
);
|
||||
|
||||
const enqueueDialog = (options?: Omit<DialogOptions, 'id'>) => {
|
||||
|
||||
+10
-8
@@ -1,5 +1,5 @@
|
||||
import { DialogComponentInstanceContext } from '@/ui/feedback/dialog-manager/contexts/DialogComponentInstanceContext';
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
|
||||
import { type DialogOptions } from '@/ui/feedback/dialog-manager/types/DialogOptions';
|
||||
|
||||
type DialogState = {
|
||||
@@ -7,11 +7,13 @@ type DialogState = {
|
||||
queue: DialogOptions[];
|
||||
};
|
||||
|
||||
export const dialogInternalComponentState = createComponentState<DialogState>({
|
||||
key: 'dialogInternalComponentState',
|
||||
defaultValue: {
|
||||
maxQueue: 2,
|
||||
queue: [],
|
||||
export const dialogInternalComponentState = createComponentStateV2<DialogState>(
|
||||
{
|
||||
key: 'dialogInternalComponentState',
|
||||
defaultValue: {
|
||||
maxQueue: 2,
|
||||
queue: [],
|
||||
},
|
||||
componentInstanceContext: DialogComponentInstanceContext,
|
||||
},
|
||||
componentInstanceContext: DialogComponentInstanceContext,
|
||||
});
|
||||
);
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
|
||||
import { snackBarInternalComponentState } from '@/ui/feedback/snack-bar-manager/states/snackBarInternalComponentState';
|
||||
import { RootStackingContextZIndices } from '@/ui/layout/constants/RootStackingContextZIndices';
|
||||
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
|
||||
import { SnackBar } from './SnackBar';
|
||||
|
||||
@@ -27,7 +27,7 @@ const StyledSnackBarContainer = styled.div`
|
||||
`;
|
||||
|
||||
export const SnackBarProvider = ({ children }: React.PropsWithChildren) => {
|
||||
const snackBarInternal = useRecoilComponentValue(
|
||||
const snackBarInternal = useRecoilComponentValueV2(
|
||||
snackBarInternalComponentState,
|
||||
);
|
||||
|
||||
|
||||
+42
-42
@@ -1,5 +1,4 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
@@ -12,6 +11,7 @@ import { buildErrorAction } from '@/ui/feedback/snack-bar-manager/utils/build-er
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { type ApolloError } from '@apollo/client';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useStore } from 'jotai';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { getErrorMessageFromApolloError } from '~/utils/get-error-message-from-apollo-error.util';
|
||||
|
||||
@@ -20,53 +20,53 @@ export const useSnackBar = () => {
|
||||
SnackBarComponentInstanceContext,
|
||||
);
|
||||
|
||||
const handleSnackBarClose = useRecoilCallback(
|
||||
({ set }) =>
|
||||
(id: string) => {
|
||||
set(
|
||||
snackBarInternalComponentState.atomFamily({
|
||||
instanceId: componentInstanceId,
|
||||
}),
|
||||
(prevState) => ({
|
||||
...prevState,
|
||||
queue: prevState.queue.filter((snackBar) => snackBar.id !== id),
|
||||
}),
|
||||
);
|
||||
},
|
||||
[componentInstanceId],
|
||||
const store = useStore();
|
||||
|
||||
const handleSnackBarClose = useCallback(
|
||||
(id: string) => {
|
||||
store.set(
|
||||
snackBarInternalComponentState.atomFamily({
|
||||
instanceId: componentInstanceId,
|
||||
}),
|
||||
(prevState) => ({
|
||||
...prevState,
|
||||
queue: prevState.queue.filter((snackBar) => snackBar.id !== id),
|
||||
}),
|
||||
);
|
||||
},
|
||||
[componentInstanceId, store],
|
||||
);
|
||||
|
||||
const setSnackBarQueue = useRecoilCallback(
|
||||
({ set }) =>
|
||||
(newValue: SnackBarOptions) =>
|
||||
set(
|
||||
snackBarInternalComponentState.atomFamily({
|
||||
instanceId: componentInstanceId,
|
||||
}),
|
||||
(prev) => {
|
||||
if (
|
||||
isDefined(newValue.dedupeKey) &&
|
||||
prev.queue.some(
|
||||
(snackBar) => snackBar.dedupeKey === newValue.dedupeKey,
|
||||
)
|
||||
) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
if (prev.queue.length >= prev.maxQueue) {
|
||||
return {
|
||||
...prev,
|
||||
queue: [...prev.queue.slice(1), newValue] as SnackBarOptions[],
|
||||
};
|
||||
}
|
||||
const setSnackBarQueue = useCallback(
|
||||
(newValue: SnackBarOptions) =>
|
||||
store.set(
|
||||
snackBarInternalComponentState.atomFamily({
|
||||
instanceId: componentInstanceId,
|
||||
}),
|
||||
(prev) => {
|
||||
if (
|
||||
isDefined(newValue.dedupeKey) &&
|
||||
prev.queue.some(
|
||||
(snackBar) => snackBar.dedupeKey === newValue.dedupeKey,
|
||||
)
|
||||
) {
|
||||
return prev;
|
||||
}
|
||||
|
||||
if (prev.queue.length >= prev.maxQueue) {
|
||||
return {
|
||||
...prev,
|
||||
queue: [...prev.queue, newValue] as SnackBarOptions[],
|
||||
queue: [...prev.queue.slice(1), newValue] as SnackBarOptions[],
|
||||
};
|
||||
},
|
||||
),
|
||||
[componentInstanceId],
|
||||
}
|
||||
|
||||
return {
|
||||
...prev,
|
||||
queue: [...prev.queue, newValue] as SnackBarOptions[],
|
||||
};
|
||||
},
|
||||
),
|
||||
[componentInstanceId, store],
|
||||
);
|
||||
|
||||
const enqueueSuccessSnackBar = useCallback(
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { SnackBarComponentInstanceContext } from '@/ui/feedback/snack-bar-manager/contexts/SnackBarComponentInstanceContext';
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
|
||||
import { type SnackBarProps } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||
|
||||
export type SnackBarOptions = SnackBarProps & {
|
||||
@@ -12,7 +12,7 @@ export type SnackBarState = {
|
||||
};
|
||||
|
||||
export const snackBarInternalComponentState =
|
||||
createComponentState<SnackBarState>({
|
||||
createComponentStateV2<SnackBarState>({
|
||||
key: 'snackBarState',
|
||||
defaultValue: {
|
||||
maxQueue: 3,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { type FieldFilesValue } from '@/object-record/record-field/ui/types/FieldMetadata';
|
||||
import { createState } from '@/ui/utilities/state/utils/createState';
|
||||
import { createStateV2 } from '@/ui/utilities/state/jotai/utils/createStateV2';
|
||||
|
||||
export const filePreviewState = createState<FieldFilesValue | null>({
|
||||
export const filePreviewState = createStateV2<FieldFilesValue | null>({
|
||||
key: 'filePreviewState',
|
||||
defaultValue: null,
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { type ReactNode, useMemo, useState } from 'react';
|
||||
import { type ReactNode, useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
@@ -10,16 +10,20 @@ import { arrayToChunks } from '~/utils/array/arrayToChunks';
|
||||
|
||||
import { ICON_PICKER_DROPDOWN_CONTENT_WIDTH } from '@/ui/input/components/constants/IconPickerDropdownContentWidth';
|
||||
import { IconPickerScrollEffect } from '@/ui/input/hooks/IconPickerScrollEffect';
|
||||
import { iconPickerVisibleCountState } from '@/ui/input/states/iconPickerVisibleCountState';
|
||||
import {
|
||||
ICON_PICKER_DEFAULT_VISIBLE_COUNT,
|
||||
iconPickerVisibleCountState,
|
||||
} from '@/ui/input/states/iconPickerVisibleCountState';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
|
||||
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
|
||||
import { type DropdownOffset } from '@/ui/layout/dropdown/types/DropdownOffset';
|
||||
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
|
||||
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
|
||||
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useRecoilValue, useResetRecoilState } from 'recoil';
|
||||
import { useStore } from 'jotai';
|
||||
import { IconApps, type IconComponent, useIcons } from 'twenty-ui/display';
|
||||
import {
|
||||
IconButton,
|
||||
@@ -156,12 +160,18 @@ export const IconPicker = ({
|
||||
|
||||
const { closeDropdown } = useCloseDropdown();
|
||||
|
||||
const iconPickerVisibleCount =
|
||||
useRecoilValue(iconPickerVisibleCountState(dropdownId)) ?? maxIconsVisible;
|
||||
const store = useStore();
|
||||
|
||||
const resetIconPickerVisibleCount = useResetRecoilState(
|
||||
iconPickerVisibleCountState(dropdownId),
|
||||
);
|
||||
const iconPickerVisibleCount =
|
||||
useFamilyRecoilValueV2(iconPickerVisibleCountState, dropdownId) ??
|
||||
maxIconsVisible;
|
||||
|
||||
const resetIconPickerVisibleCount = useCallback(() => {
|
||||
store.set(
|
||||
iconPickerVisibleCountState.atomFamily(dropdownId),
|
||||
ICON_PICKER_DEFAULT_VISIBLE_COUNT,
|
||||
);
|
||||
}, [store, dropdownId]);
|
||||
|
||||
const { getIcons, getIcon } = useIcons();
|
||||
const icons = getIcons();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { iconPickerVisibleCountState } from '@/ui/input/states/iconPickerVisibleCountState';
|
||||
import { useSetFamilyRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetFamilyRecoilStateV2';
|
||||
import { useScrollWrapperHTMLElement } from '@/ui/utilities/scroll/hooks/useScrollWrapperHTMLElement';
|
||||
import { useEffect } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { iconPickerVisibleCountState } from '@/ui/input/states/iconPickerVisibleCountState';
|
||||
|
||||
type IconPickerScrollEffectProps = {
|
||||
sentinelId: string;
|
||||
@@ -14,8 +14,9 @@ export const IconPickerScrollEffect = ({
|
||||
}: IconPickerScrollEffectProps) => {
|
||||
const { scrollWrapperHTMLElement } = useScrollWrapperHTMLElement();
|
||||
|
||||
const setIconPickerVisibleCount = useSetRecoilState(
|
||||
iconPickerVisibleCountState(dropdownId),
|
||||
const setIconPickerVisibleCount = useSetFamilyRecoilStateV2(
|
||||
iconPickerVisibleCountState,
|
||||
dropdownId,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { createFamilyState } from '@/ui/utilities/state/utils/createFamilyState';
|
||||
import { createFamilyStateV2 } from '@/ui/utilities/state/jotai/utils/createFamilyStateV2';
|
||||
|
||||
export const iconPickerVisibleCountState = createFamilyState<number, string>({
|
||||
export const ICON_PICKER_DEFAULT_VISIBLE_COUNT = 25;
|
||||
|
||||
export const iconPickerVisibleCountState = createFamilyStateV2<number, string>({
|
||||
key: 'iconPickerVisibleCountState',
|
||||
defaultValue: 25,
|
||||
defaultValue: ICON_PICKER_DEFAULT_VISIBLE_COUNT,
|
||||
});
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { type ReactNode } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { NavigationDrawerCollapseButton } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerCollapseButton';
|
||||
|
||||
import { PAGE_ACTION_CONTAINER_CLICK_OUTSIDE_ID } from '@/ui/layout/page/constants/PageActionContainerClickOutsideId';
|
||||
import { PAGE_BAR_MIN_HEIGHT } from '@/ui/layout/page/constants/PageBarMinHeight';
|
||||
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
|
||||
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { AnimatePresence } from 'framer-motion';
|
||||
import {
|
||||
@@ -96,7 +96,7 @@ export const PageHeader = ({
|
||||
}: PageHeaderProps) => {
|
||||
const isMobile = useIsMobile();
|
||||
const theme = useTheme();
|
||||
const isNavigationDrawerExpanded = useRecoilValue(
|
||||
const isNavigationDrawerExpanded = useRecoilValueV2(
|
||||
isNavigationDrawerExpandedState,
|
||||
);
|
||||
|
||||
|
||||
+2
-2
@@ -1,13 +1,13 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import {
|
||||
NAVIGATION_DRAWER_WIDTH_VAR,
|
||||
navigationDrawerWidthState,
|
||||
} from '@/ui/navigation/states/navigationDrawerWidthState';
|
||||
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
|
||||
|
||||
export const NavigationDrawerWidthEffect = () => {
|
||||
const navigationDrawerWidth = useRecoilValue(navigationDrawerWidthState);
|
||||
const navigationDrawerWidth = useRecoilValueV2(navigationDrawerWidthState);
|
||||
|
||||
useEffect(() => {
|
||||
document.documentElement.style.setProperty(
|
||||
|
||||
+2
-1
@@ -9,13 +9,14 @@ import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
|
||||
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
|
||||
import { Avatar } from 'twenty-ui/display';
|
||||
|
||||
export const MultiWorkspaceDropdownClickableComponent = () => {
|
||||
const currentWorkspace = useRecoilValue(currentWorkspaceState);
|
||||
const theme = useTheme();
|
||||
|
||||
const isNavigationDrawerExpanded = useRecoilValue(
|
||||
const isNavigationDrawerExpanded = useRecoilValueV2(
|
||||
isNavigationDrawerExpandedState,
|
||||
);
|
||||
return (
|
||||
|
||||
+4
-3
@@ -1,9 +1,10 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { type ReactNode, useState } from 'react';
|
||||
import { useRecoilState, useSetRecoilState } from 'recoil';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useIsSettingsDrawer } from '@/navigation/hooks/useIsSettingsDrawer';
|
||||
import { tableWidthResizeIsActiveState } from '@/object-record/record-table/states/tableWidthResizeIsActivedState';
|
||||
import { useRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilStateV2';
|
||||
import { ResizablePanelEdge } from '@/ui/layout/resizable-panel/components/ResizablePanelEdge';
|
||||
import { NAVIGATION_DRAWER_COLLAPSED_WIDTH } from '@/ui/layout/resizable-panel/constants/NavigationDrawerCollapsedWidth';
|
||||
import { NAVIGATION_DRAWER_CONSTRAINTS } from '@/ui/layout/resizable-panel/constants/NavigationDrawerConstraints';
|
||||
@@ -77,8 +78,8 @@ export const NavigationDrawer = ({
|
||||
const isSettingsDrawer = useIsSettingsDrawer();
|
||||
|
||||
const [isNavigationDrawerExpanded, setIsNavigationDrawerExpanded] =
|
||||
useRecoilState(isNavigationDrawerExpandedState);
|
||||
const [navigationDrawerWidth, setNavigationDrawerWidth] = useRecoilState(
|
||||
useRecoilStateV2(isNavigationDrawerExpandedState);
|
||||
const [navigationDrawerWidth, setNavigationDrawerWidth] = useRecoilStateV2(
|
||||
navigationDrawerWidthState,
|
||||
);
|
||||
const setTableWidthResizeIsActive = useSetRecoilState(
|
||||
|
||||
+2
-2
@@ -1,5 +1,6 @@
|
||||
import { useIsSettingsPage } from '@/navigation/hooks/useIsSettingsPage';
|
||||
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
|
||||
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import {
|
||||
@@ -7,7 +8,6 @@ import {
|
||||
motion,
|
||||
type TargetAndTransition,
|
||||
} from 'framer-motion';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
const StyledAnimatedContainer = styled(motion.span)`
|
||||
display: block;
|
||||
@@ -20,7 +20,7 @@ export const NavigationDrawerAnimatedCollapseWrapper = ({
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const isSettingsPage = useIsSettingsPage();
|
||||
const isNavigationDrawerExpanded = useRecoilValue(
|
||||
const isNavigationDrawerExpanded = useRecoilValueV2(
|
||||
isNavigationDrawerExpandedState,
|
||||
);
|
||||
|
||||
|
||||
+3
-3
@@ -1,11 +1,11 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
|
||||
import { navigationDrawerExpandedMemorizedStateV2 } from '@/ui/navigation/states/navigationDrawerExpandedMemorizedStateV2';
|
||||
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
|
||||
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
|
||||
import { useSetRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilStateV2';
|
||||
import { useIsWorkspaceActivationStatusEqualsTo } from '@/workspace/hooks/useIsWorkspaceActivationStatusEqualsTo';
|
||||
import { WorkspaceActivationStatus } from 'twenty-shared/workspace';
|
||||
import { IconX } from 'twenty-ui/display';
|
||||
@@ -47,9 +47,9 @@ export const NavigationDrawerBackButton = ({
|
||||
title,
|
||||
}: NavigationDrawerBackButtonProps) => {
|
||||
const theme = useTheme();
|
||||
const navigationMemorizedUrl = useRecoilValue(navigationMemorizedUrlState);
|
||||
const navigationMemorizedUrl = useRecoilValueV2(navigationMemorizedUrlState);
|
||||
|
||||
const setIsNavigationDrawerExpanded = useSetRecoilState(
|
||||
const setIsNavigationDrawerExpanded = useSetRecoilStateV2(
|
||||
isNavigationDrawerExpandedState,
|
||||
);
|
||||
const navigationDrawerExpandedMemorized = useRecoilValueV2(
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
|
||||
import { useSetRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilStateV2';
|
||||
import styled from '@emotion/styled';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import {
|
||||
IconLayoutSidebarLeftCollapse,
|
||||
IconLayoutSidebarRightCollapse,
|
||||
@@ -26,7 +26,7 @@ export const NavigationDrawerCollapseButton = ({
|
||||
className,
|
||||
direction = 'left',
|
||||
}: NavigationDrawerCollapseButtonProps) => {
|
||||
const setIsNavigationDrawerExpanded = useSetRecoilState(
|
||||
const setIsNavigationDrawerExpanded = useSetRecoilStateV2(
|
||||
isNavigationDrawerExpandedState,
|
||||
);
|
||||
|
||||
|
||||
+2
-2
@@ -1,11 +1,11 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { MultiWorkspaceDropdownButton } from '@/ui/navigation/navigation-drawer/components/MultiWorkspaceDropdown/MultiWorkspaceDropdownButton';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
|
||||
import { PAGE_BAR_MIN_HEIGHT } from '@/ui/layout/page/constants/PageBarMinHeight';
|
||||
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
|
||||
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
|
||||
import { NavigationDrawerCollapseButton } from './NavigationDrawerCollapseButton';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
@@ -36,7 +36,7 @@ export const NavigationDrawerHeader = ({
|
||||
}: NavigationDrawerHeaderProps) => {
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
const isNavigationDrawerExpanded = useRecoilValue(
|
||||
const isNavigationDrawerExpanded = useRecoilValueV2(
|
||||
isNavigationDrawerExpandedState,
|
||||
);
|
||||
|
||||
|
||||
+2
-2
@@ -6,13 +6,13 @@ import { useNavigationDrawerTooltip } from '@/ui/navigation/navigation-drawer/ho
|
||||
import { type NavigationDrawerSubItemState } from '@/ui/navigation/navigation-drawer/types/NavigationDrawerSubItemState';
|
||||
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { useRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilStateV2';
|
||||
import isPropValid from '@emotion/is-prop-valid';
|
||||
import { css, useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { type ReactNode } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { Pill } from 'twenty-ui/components';
|
||||
import {
|
||||
@@ -305,7 +305,7 @@ export const NavigationDrawerItem = ({
|
||||
const isMobile = useIsMobile();
|
||||
const isSettingsPage = useIsSettingsPage();
|
||||
const [isNavigationDrawerExpanded, setIsNavigationDrawerExpanded] =
|
||||
useRecoilState(isNavigationDrawerExpandedState);
|
||||
useRecoilStateV2(isNavigationDrawerExpandedState);
|
||||
|
||||
const { navigationItemId } = useNavigationDrawerTooltip(label, to);
|
||||
|
||||
|
||||
+2
-2
@@ -1,5 +1,6 @@
|
||||
import { useIsSettingsPage } from '@/navigation/hooks/useIsSettingsPage';
|
||||
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
|
||||
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import {
|
||||
@@ -8,7 +9,6 @@ import {
|
||||
type TargetAndTransition,
|
||||
} from 'framer-motion';
|
||||
import { type ReactNode } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
const StyledAnimationGroupContainer = styled(motion.div)``;
|
||||
|
||||
@@ -23,7 +23,7 @@ export const NavigationDrawerItemsCollapsableContainer = ({
|
||||
}: NavigationDrawerItemsCollapsableContainerProps) => {
|
||||
const theme = useTheme();
|
||||
const isSettingsPage = useIsSettingsPage();
|
||||
const isNavigationDrawerExpanded = useRecoilValue(
|
||||
const isNavigationDrawerExpanded = useRecoilValueV2(
|
||||
isNavigationDrawerExpandedState,
|
||||
);
|
||||
const isExpanded = isNavigationDrawerExpanded || isSettingsPage;
|
||||
|
||||
+2
-1
@@ -4,6 +4,7 @@ import { useIsPrefetchLoading } from '@/prefetch/hooks/useIsPrefetchLoading';
|
||||
import { NavigationDrawerSectionTitleSkeletonLoader } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitleSkeletonLoader';
|
||||
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
|
||||
import styled from '@emotion/styled';
|
||||
import React from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
@@ -60,7 +61,7 @@ export const NavigationDrawerSectionTitle = ({
|
||||
alwaysShowRightIcon = false,
|
||||
}: NavigationDrawerSectionTitleProps) => {
|
||||
const isMobile = useIsMobile();
|
||||
const isNavigationDrawerExpanded = useRecoilValue(
|
||||
const isNavigationDrawerExpanded = useRecoilValueV2(
|
||||
isNavigationDrawerExpandedState,
|
||||
);
|
||||
const isSettingsPage = useIsSettingsPage();
|
||||
|
||||
+27
-32
@@ -1,45 +1,40 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { useStore } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { isNavigationSectionOpenFamilyState } from '@/ui/navigation/navigation-drawer/states/isNavigationSectionOpenFamilyState';
|
||||
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
|
||||
|
||||
export const useNavigationSection = (navigationSectionId: string) => {
|
||||
const closeNavigationSection = useRecoilCallback(
|
||||
({ set }) =>
|
||||
() => {
|
||||
set(isNavigationSectionOpenFamilyState(navigationSectionId), false);
|
||||
},
|
||||
[navigationSectionId],
|
||||
const store = useStore();
|
||||
const isNavigationSectionOpen = useFamilyRecoilValueV2(
|
||||
isNavigationSectionOpenFamilyState,
|
||||
navigationSectionId,
|
||||
);
|
||||
|
||||
const openNavigationSection = useRecoilCallback(
|
||||
({ set }) =>
|
||||
() => {
|
||||
set(isNavigationSectionOpenFamilyState(navigationSectionId), true);
|
||||
},
|
||||
[navigationSectionId],
|
||||
);
|
||||
const closeNavigationSection = useCallback(() => {
|
||||
store.set(
|
||||
isNavigationSectionOpenFamilyState.atomFamily(navigationSectionId),
|
||||
false,
|
||||
);
|
||||
}, [store, navigationSectionId]);
|
||||
|
||||
const toggleNavigationSection = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
() => {
|
||||
const isNavigationSectionOpen = snapshot
|
||||
.getLoadable(isNavigationSectionOpenFamilyState(navigationSectionId))
|
||||
.getValue();
|
||||
const openNavigationSection = useCallback(() => {
|
||||
store.set(
|
||||
isNavigationSectionOpenFamilyState.atomFamily(navigationSectionId),
|
||||
true,
|
||||
);
|
||||
}, [store, navigationSectionId]);
|
||||
|
||||
if (isNavigationSectionOpen) {
|
||||
closeNavigationSection();
|
||||
} else {
|
||||
openNavigationSection();
|
||||
}
|
||||
},
|
||||
[closeNavigationSection, openNavigationSection, navigationSectionId],
|
||||
);
|
||||
|
||||
const isNavigationSectionOpenState =
|
||||
isNavigationSectionOpenFamilyState(navigationSectionId);
|
||||
const toggleNavigationSection = useCallback(() => {
|
||||
if (isNavigationSectionOpen) {
|
||||
closeNavigationSection();
|
||||
} else {
|
||||
openNavigationSection();
|
||||
}
|
||||
}, [isNavigationSectionOpen, closeNavigationSection, openNavigationSection]);
|
||||
|
||||
return {
|
||||
isNavigationSectionOpenState,
|
||||
isNavigationSectionOpen,
|
||||
closeNavigationSection,
|
||||
openNavigationSection,
|
||||
toggleNavigationSection,
|
||||
|
||||
+4
-5
@@ -1,8 +1,7 @@
|
||||
import { atom } from 'recoil';
|
||||
import { localStorageEffect } from '~/utils/recoil/localStorageEffect';
|
||||
import { createStateV2 } from '@/ui/utilities/state/jotai/utils/createStateV2';
|
||||
|
||||
export const isAdvancedModeEnabledState = atom<boolean>({
|
||||
export const isAdvancedModeEnabledState = createStateV2<boolean>({
|
||||
key: 'isAdvancedModeEnabledAtom',
|
||||
default: false,
|
||||
effects: [localStorageEffect()],
|
||||
defaultValue: false,
|
||||
useLocalStorage: true,
|
||||
});
|
||||
|
||||
+3
-4
@@ -1,11 +1,10 @@
|
||||
import { createFamilyState } from '@/ui/utilities/state/utils/createFamilyState';
|
||||
import { localStorageEffect } from '~/utils/recoil/localStorageEffect';
|
||||
import { createFamilyStateV2 } from '@/ui/utilities/state/jotai/utils/createFamilyStateV2';
|
||||
|
||||
export const isNavigationSectionOpenFamilyState = createFamilyState<
|
||||
export const isNavigationSectionOpenFamilyState = createFamilyStateV2<
|
||||
boolean,
|
||||
string
|
||||
>({
|
||||
key: 'isNavigationSectionOpenFamilyState',
|
||||
defaultValue: true,
|
||||
effects: [localStorageEffect()],
|
||||
useLocalStorage: true,
|
||||
});
|
||||
|
||||
+4
-5
@@ -1,11 +1,10 @@
|
||||
import { atom } from 'recoil';
|
||||
import { createStateV2 } from '@/ui/utilities/state/jotai/utils/createStateV2';
|
||||
import { MOBILE_VIEWPORT } from 'twenty-ui/theme';
|
||||
import { localStorageEffect } from '~/utils/recoil/localStorageEffect';
|
||||
|
||||
const isMobile = window.innerWidth <= MOBILE_VIEWPORT;
|
||||
|
||||
export const isNavigationDrawerExpandedState = atom({
|
||||
export const isNavigationDrawerExpandedState = createStateV2<boolean>({
|
||||
key: 'isNavigationDrawerExpanded',
|
||||
default: !isMobile,
|
||||
effects: [localStorageEffect()],
|
||||
defaultValue: !isMobile,
|
||||
useLocalStorage: true,
|
||||
});
|
||||
|
||||
+4
-6
@@ -1,12 +1,10 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
import { NAVIGATION_DRAWER_CONSTRAINTS } from '@/ui/layout/resizable-panel/constants/NavigationDrawerConstraints';
|
||||
import { localStorageEffect } from '~/utils/recoil/localStorageEffect';
|
||||
import { createStateV2 } from '@/ui/utilities/state/jotai/utils/createStateV2';
|
||||
|
||||
export const NAVIGATION_DRAWER_WIDTH_VAR = '--navigation-drawer-width';
|
||||
|
||||
export const navigationDrawerWidthState = atom<number>({
|
||||
export const navigationDrawerWidthState = createStateV2<number>({
|
||||
key: 'navigationDrawerWidth',
|
||||
default: NAVIGATION_DRAWER_CONSTRAINTS.default,
|
||||
effects: [localStorageEffect()],
|
||||
defaultValue: NAVIGATION_DRAWER_CONSTRAINTS.default,
|
||||
useLocalStorage: true,
|
||||
});
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { createState } from '@/ui/utilities/state/utils/createState';
|
||||
export const navigationMemorizedUrlState = createState<string>({
|
||||
import { createStateV2 } from '@/ui/utilities/state/jotai/utils/createStateV2';
|
||||
export const navigationMemorizedUrlState = createStateV2<string>({
|
||||
key: 'navigationMemorizedUrlState',
|
||||
defaultValue: '/',
|
||||
});
|
||||
|
||||
+4
-5
@@ -1,8 +1,7 @@
|
||||
import { createState } from '@/ui/utilities/state/utils/createState';
|
||||
import { createStateV2 } from '@/ui/utilities/state/jotai/utils/createStateV2';
|
||||
|
||||
export const shouldNavigateBackToMemorizedUrlOnSaveState = createState<boolean>(
|
||||
{
|
||||
export const shouldNavigateBackToMemorizedUrlOnSaveState =
|
||||
createStateV2<boolean>({
|
||||
key: 'shouldNavigateBackToMemorizedUrlOnSaveState',
|
||||
defaultValue: false,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
@@ -3,7 +3,7 @@ import { createContext } from 'react';
|
||||
|
||||
import { useSystemColorScheme } from '@/ui/theme/hooks/useSystemColorScheme';
|
||||
import { persistedColorSchemeState } from '@/ui/theme/states/persistedColorSchemeState';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { useRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilStateV2';
|
||||
import { type ColorScheme } from 'twenty-ui/input';
|
||||
import { THEME_DARK, THEME_LIGHT, ThemeContextProvider } from 'twenty-ui/theme';
|
||||
|
||||
@@ -16,7 +16,7 @@ export const ThemeSchemeContext = createContext<(theme: ColorScheme) => void>(
|
||||
);
|
||||
|
||||
export const BaseThemeProvider = ({ children }: BaseThemeProviderProps) => {
|
||||
const [persistedColorScheme, setPersistedColorScheme] = useRecoilState(
|
||||
const [persistedColorScheme, setPersistedColorScheme] = useRecoilStateV2(
|
||||
persistedColorSchemeState,
|
||||
);
|
||||
const systemColorScheme = useSystemColorScheme();
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useRecoilState, useSetRecoilState } from 'recoil';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
import { persistedColorSchemeState } from '@/ui/theme/states/persistedColorSchemeState';
|
||||
import { useSetRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilStateV2';
|
||||
import { type ColorScheme } from '@/workspace-member/types/WorkspaceMember';
|
||||
import {
|
||||
type IconComponent,
|
||||
@@ -19,7 +20,9 @@ export const useColorScheme = () => {
|
||||
);
|
||||
|
||||
const { updateOneRecord } = useUpdateOneRecord();
|
||||
const setPersistedColorScheme = useSetRecoilState(persistedColorSchemeState);
|
||||
const setPersistedColorScheme = useSetRecoilStateV2(
|
||||
persistedColorSchemeState,
|
||||
);
|
||||
|
||||
const colorScheme = currentWorkspaceMember?.colorScheme ?? 'System';
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
import { type ColorScheme } from '@/workspace-member/types/WorkspaceMember';
|
||||
import { localStorageEffect } from '~/utils/recoil/localStorageEffect';
|
||||
import { createStateV2 } from '@/ui/utilities/state/jotai/utils/createStateV2';
|
||||
|
||||
export const persistedColorSchemeState = atom<ColorScheme>({
|
||||
export const persistedColorSchemeState = createStateV2<ColorScheme>({
|
||||
key: 'persistedColorSchemeState',
|
||||
default: 'System',
|
||||
effects: [localStorageEffect()],
|
||||
defaultValue: 'System',
|
||||
useLocalStorage: true,
|
||||
});
|
||||
|
||||
+8
-2
@@ -1,13 +1,16 @@
|
||||
import { atom } from 'jotai';
|
||||
import { atomWithStorage } from 'jotai/utils';
|
||||
|
||||
import { type FamilyStateV2 } from '@/ui/utilities/state/jotai/types/FamilyStateV2';
|
||||
|
||||
export const createFamilyStateV2 = <ValueType, FamilyKey>({
|
||||
key,
|
||||
defaultValue,
|
||||
useLocalStorage = false,
|
||||
}: {
|
||||
key: string;
|
||||
defaultValue: ValueType;
|
||||
useLocalStorage?: boolean;
|
||||
}): FamilyStateV2<ValueType, FamilyKey> => {
|
||||
const atomCache = new Map<
|
||||
string,
|
||||
@@ -26,8 +29,11 @@ export const createFamilyStateV2 = <ValueType, FamilyKey>({
|
||||
return existing;
|
||||
}
|
||||
|
||||
const baseAtom = atom(defaultValue);
|
||||
baseAtom.debugLabel = `${key}__${cacheKey}`;
|
||||
const atomKey = `${key}__${cacheKey}`;
|
||||
const baseAtom = useLocalStorage
|
||||
? atomWithStorage<ValueType>(atomKey, defaultValue)
|
||||
: atom(defaultValue);
|
||||
baseAtom.debugLabel = atomKey;
|
||||
atomCache.set(cacheKey, baseAtom);
|
||||
|
||||
return baseAtom;
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
import { atom } from 'jotai';
|
||||
import { atomWithStorage } from 'jotai/utils';
|
||||
|
||||
import { type StateV2 } from '@/ui/utilities/state/jotai/types/StateV2';
|
||||
|
||||
export const createStateV2 = <ValueType>({
|
||||
key,
|
||||
defaultValue,
|
||||
useLocalStorage = false,
|
||||
}: {
|
||||
key: string;
|
||||
defaultValue: ValueType;
|
||||
useLocalStorage?: boolean;
|
||||
}): StateV2<ValueType> => {
|
||||
const baseAtom = atom(defaultValue);
|
||||
const baseAtom = useLocalStorage
|
||||
? atomWithStorage<ValueType>(key, defaultValue)
|
||||
: atom(defaultValue);
|
||||
baseAtom.debugLabel = key;
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user