diff --git a/excalidraw-app/App.tsx b/excalidraw-app/App.tsx index 0387ebc922e3..46d8d29617ff 100644 --- a/excalidraw-app/App.tsx +++ b/excalidraw-app/App.tsx @@ -1230,7 +1230,7 @@ const ExcalidrawApp = () => { return ( - appJotaiStore}> + diff --git a/excalidraw-app/app-jotai.ts b/excalidraw-app/app-jotai.ts index 8c6c796f6d99..7689f7b75856 100644 --- a/excalidraw-app/app-jotai.ts +++ b/excalidraw-app/app-jotai.ts @@ -1,3 +1,3 @@ -import { unstable_createStore } from "jotai"; +import { createStore } from "jotai"; -export const appJotaiStore = unstable_createStore(); +export const appJotaiStore = createStore(); diff --git a/excalidraw-app/package.json b/excalidraw-app/package.json index 53bf8e3a1ac0..c5e1cdc5d012 100644 --- a/excalidraw-app/package.json +++ b/excalidraw-app/package.json @@ -32,7 +32,7 @@ "firebase": "8.3.3", "i18next-browser-languagedetector": "6.1.4", "idb-keyval": "6.0.3", - "jotai": "1.13.1", + "jotai": "2.11.0", "react": "18.2.0", "react-dom": "18.2.0", "socket.io-client": "4.7.2", diff --git a/packages/excalidraw/components/ActiveConfirmDialog.tsx b/packages/excalidraw/components/ActiveConfirmDialog.tsx index 44a26e9a6e7a..ee6f22600c02 100644 --- a/packages/excalidraw/components/ActiveConfirmDialog.tsx +++ b/packages/excalidraw/components/ActiveConfirmDialog.tsx @@ -1,7 +1,7 @@ -import { atom, useAtom } from "jotai"; +import { atom } from "jotai"; import { actionClearCanvas } from "../actions"; import { t } from "../i18n"; -import { jotaiScope } from "../jotai"; +import { useAtom } from "../jotai"; import { useExcalidrawActionManager } from "./App"; import ConfirmDialog from "./ConfirmDialog"; @@ -10,7 +10,6 @@ export const activeConfirmDialogAtom = atom<"clearCanvas" | null>(null); export const ActiveConfirmDialog = () => { const [activeConfirmDialog, setActiveConfirmDialog] = useAtom( activeConfirmDialogAtom, - jotaiScope, ); const actionManager = useExcalidrawActionManager(); diff --git a/packages/excalidraw/components/ColorPicker/ColorInput.tsx b/packages/excalidraw/components/ColorPicker/ColorInput.tsx index 7e77e06ffcab..a8f1b33e3da3 100644 --- a/packages/excalidraw/components/ColorPicker/ColorInput.tsx +++ b/packages/excalidraw/components/ColorPicker/ColorInput.tsx @@ -1,10 +1,9 @@ import { useCallback, useEffect, useRef, useState } from "react"; import { getColor } from "./ColorPicker"; -import { useAtom } from "jotai"; import type { ColorPickerType } from "./colorPickerUtils"; import { activeColorPickerSectionAtom } from "./colorPickerUtils"; import { eyeDropperIcon } from "../icons"; -import { jotaiScope } from "../../jotai"; +import { useAtom } from "../../jotai"; import { KEYS } from "../../keys"; import { activeEyeDropperAtom } from "../EyeDropper"; import clsx from "clsx"; @@ -57,10 +56,7 @@ export const ColorInput = ({ } }, [activeSection]); - const [eyeDropperState, setEyeDropperState] = useAtom( - activeEyeDropperAtom, - jotaiScope, - ); + const [eyeDropperState, setEyeDropperState] = useAtom(activeEyeDropperAtom); useEffect(() => { return () => { diff --git a/packages/excalidraw/components/ColorPicker/ColorPicker.tsx b/packages/excalidraw/components/ColorPicker/ColorPicker.tsx index 6fd99dd46882..67f0d84e3d47 100644 --- a/packages/excalidraw/components/ColorPicker/ColorPicker.tsx +++ b/packages/excalidraw/components/ColorPicker/ColorPicker.tsx @@ -5,7 +5,6 @@ import { TopPicks } from "./TopPicks"; import { ButtonSeparator } from "../ButtonSeparator"; import { Picker } from "./Picker"; import * as Popover from "@radix-ui/react-popover"; -import { useAtom } from "jotai"; import type { ColorPickerType } from "./colorPickerUtils"; import { activeColorPickerSectionAtom } from "./colorPickerUtils"; import { useExcalidrawContainer } from "../App"; @@ -15,7 +14,7 @@ import PickerHeading from "./PickerHeading"; import { t } from "../../i18n"; import clsx from "clsx"; import { useRef } from "react"; -import { jotaiScope } from "../../jotai"; +import { useAtom } from "../../jotai"; import { ColorInput } from "./ColorInput"; import { activeEyeDropperAtom } from "../EyeDropper"; import { PropertiesPopover } from "../PropertiesPopover"; @@ -76,10 +75,7 @@ const ColorPickerPopupContent = ({ const { container } = useExcalidrawContainer(); const [, setActiveColorPickerSection] = useAtom(activeColorPickerSectionAtom); - const [eyeDropperState, setEyeDropperState] = useAtom( - activeEyeDropperAtom, - jotaiScope, - ); + const [eyeDropperState, setEyeDropperState] = useAtom(activeEyeDropperAtom); const colorInputJSX = (
diff --git a/packages/excalidraw/components/ColorPicker/CustomColorList.tsx b/packages/excalidraw/components/ColorPicker/CustomColorList.tsx index b028dcc76130..d224ac6a1601 100644 --- a/packages/excalidraw/components/ColorPicker/CustomColorList.tsx +++ b/packages/excalidraw/components/ColorPicker/CustomColorList.tsx @@ -1,5 +1,5 @@ import clsx from "clsx"; -import { useAtom } from "jotai"; +import { useAtom } from "../../jotai"; import { useEffect, useRef } from "react"; import { activeColorPickerSectionAtom } from "./colorPickerUtils"; import HotkeyLabel from "./HotkeyLabel"; diff --git a/packages/excalidraw/components/ColorPicker/Picker.tsx b/packages/excalidraw/components/ColorPicker/Picker.tsx index 722fc47e46ca..6a56a1e41416 100644 --- a/packages/excalidraw/components/ColorPicker/Picker.tsx +++ b/packages/excalidraw/components/ColorPicker/Picker.tsx @@ -5,7 +5,7 @@ import type { ExcalidrawElement } from "../../element/types"; import { ShadeList } from "./ShadeList"; import PickerColorList from "./PickerColorList"; -import { useAtom } from "jotai"; +import { useAtom } from "../../jotai"; import { CustomColorList } from "./CustomColorList"; import { colorPickerKeyNavHandler } from "./keyboardNavHandlers"; import PickerHeading from "./PickerHeading"; diff --git a/packages/excalidraw/components/ColorPicker/PickerColorList.tsx b/packages/excalidraw/components/ColorPicker/PickerColorList.tsx index 406209a8e7f7..72df0ba926b2 100644 --- a/packages/excalidraw/components/ColorPicker/PickerColorList.tsx +++ b/packages/excalidraw/components/ColorPicker/PickerColorList.tsx @@ -1,5 +1,5 @@ import clsx from "clsx"; -import { useAtom } from "jotai"; +import { useAtom } from "../../jotai"; import { useEffect, useRef } from "react"; import { activeColorPickerSectionAtom, diff --git a/packages/excalidraw/components/ColorPicker/ShadeList.tsx b/packages/excalidraw/components/ColorPicker/ShadeList.tsx index 292457cbc12d..59e0fc6751ad 100644 --- a/packages/excalidraw/components/ColorPicker/ShadeList.tsx +++ b/packages/excalidraw/components/ColorPicker/ShadeList.tsx @@ -1,5 +1,5 @@ import clsx from "clsx"; -import { useAtom } from "jotai"; +import { useAtom } from "../../jotai"; import { useEffect, useRef } from "react"; import { activeColorPickerSectionAtom, diff --git a/packages/excalidraw/components/CommandPalette/CommandPalette.tsx b/packages/excalidraw/components/CommandPalette/CommandPalette.tsx index 43a29883c891..cfef878f540e 100644 --- a/packages/excalidraw/components/CommandPalette/CommandPalette.tsx +++ b/packages/excalidraw/components/CommandPalette/CommandPalette.tsx @@ -36,7 +36,8 @@ import { getShortcutKey, isWritableElement, } from "../../utils"; -import { atom, useAtom } from "jotai"; +import { atom } from "jotai"; +import { useAtom } from "../../jotai"; import { deburr } from "../../deburr"; import type { MarkRequired } from "../../utility-types"; import { InlineIcon } from "../InlineIcon"; diff --git a/packages/excalidraw/components/ConfirmDialog.tsx b/packages/excalidraw/components/ConfirmDialog.tsx index 637f0659a808..f548d130e1bf 100644 --- a/packages/excalidraw/components/ConfirmDialog.tsx +++ b/packages/excalidraw/components/ConfirmDialog.tsx @@ -5,10 +5,9 @@ import { Dialog } from "./Dialog"; import "./ConfirmDialog.scss"; import DialogActionButton from "./DialogActionButton"; -import { useSetAtom } from "jotai"; import { isLibraryMenuOpenAtom } from "./LibraryMenu"; import { useExcalidrawContainer, useExcalidrawSetAppState } from "./App"; -import { jotaiScope } from "../jotai"; +import { useSetAtom } from "../jotai"; interface Props extends Omit { onConfirm: () => void; @@ -27,7 +26,7 @@ const ConfirmDialog = (props: Props) => { ...rest } = props; const setAppState = useExcalidrawSetAppState(); - const setIsLibraryMenuOpen = useSetAtom(isLibraryMenuOpenAtom, jotaiScope); + const setIsLibraryMenuOpen = useSetAtom(isLibraryMenuOpenAtom); const { container } = useExcalidrawContainer(); return ( diff --git a/packages/excalidraw/components/Dialog.tsx b/packages/excalidraw/components/Dialog.tsx index 06e2a4fb8829..12b198271188 100644 --- a/packages/excalidraw/components/Dialog.tsx +++ b/packages/excalidraw/components/Dialog.tsx @@ -11,9 +11,8 @@ import "./Dialog.scss"; import { Island } from "./Island"; import { Modal } from "./Modal"; import { queryFocusableElements } from "../utils"; -import { useSetAtom } from "jotai"; import { isLibraryMenuOpenAtom } from "./LibraryMenu"; -import { jotaiScope } from "../jotai"; +import { useSetAtom } from "../jotai"; import { t } from "../i18n"; import { CloseIcon } from "./icons"; @@ -92,7 +91,7 @@ export const Dialog = (props: DialogProps) => { }, [islandNode, props.autofocus]); const setAppState = useExcalidrawSetAppState(); - const setIsLibraryMenuOpen = useSetAtom(isLibraryMenuOpenAtom, jotaiScope); + const setIsLibraryMenuOpen = useSetAtom(isLibraryMenuOpenAtom); const onClose = () => { setAppState({ openMenu: null }); diff --git a/packages/excalidraw/components/IconPicker.tsx b/packages/excalidraw/components/IconPicker.tsx index f72433106528..e01174bb8fcb 100644 --- a/packages/excalidraw/components/IconPicker.tsx +++ b/packages/excalidraw/components/IconPicker.tsx @@ -6,8 +6,8 @@ import { isArrowKey, KEYS } from "../keys"; import { getLanguage, t } from "../i18n"; import clsx from "clsx"; import Collapsible from "./Stats/Collapsible"; -import { atom, useAtom } from "jotai"; -import { jotaiScope } from "../jotai"; +import { atom } from "jotai"; +import { useAtom } from "../jotai"; import { useDevice } from ".."; const moreOptionsAtom = atom(false); @@ -94,10 +94,7 @@ function Picker({ event.stopPropagation(); }; - const [showMoreOptions, setShowMoreOptions] = useAtom( - moreOptionsAtom, - jotaiScope, - ); + const [showMoreOptions, setShowMoreOptions] = useAtom(moreOptionsAtom); const alwaysVisibleOptions = React.useMemo( () => options.slice(0, numberOfOptionsToAlwaysShow), diff --git a/packages/excalidraw/components/LayerUI.tsx b/packages/excalidraw/components/LayerUI.tsx index 8944b1308186..14be2f2bb3cf 100644 --- a/packages/excalidraw/components/LayerUI.tsx +++ b/packages/excalidraw/components/LayerUI.tsx @@ -41,8 +41,7 @@ import { trackEvent } from "../analytics"; import { useDevice } from "./App"; import Footer from "./footer/Footer"; import { isSidebarDockedAtom } from "./Sidebar/Sidebar"; -import { jotaiScope } from "../jotai"; -import { Provider, useAtom, useAtomValue } from "jotai"; +import { useAtom, useAtomValue } from "../jotai"; import MainMenu from "./main-menu/MainMenu"; import { ActiveConfirmDialog } from "./ActiveConfirmDialog"; import { OverwriteConfirmDialog } from "./OverwriteConfirm/OverwriteConfirm"; @@ -152,10 +151,9 @@ const LayerUI = ({ const device = useDevice(); const tunnels = useInitializeTunnels(); - const [eyeDropperState, setEyeDropperState] = useAtom( - activeEyeDropperAtom, - jotaiScope, - ); + const TunnelsProvider = tunnels.jotai.Provider; + + const [eyeDropperState, setEyeDropperState] = useAtom(activeEyeDropperAtom); const renderJSONExportDialog = () => { if (!UIOptions.canvasActions.export) { @@ -386,7 +384,7 @@ const LayerUI = ({ ); }; - const isSidebarDocked = useAtomValue(isSidebarDockedAtom, jotaiScope); + const isSidebarDocked = useAtomValue(isSidebarDockedAtom); if (uiDisabled) { return null; @@ -575,11 +573,11 @@ const LayerUI = ({ return ( - + {layerUIJSX} - + ); }; diff --git a/packages/excalidraw/components/LibraryMenu.tsx b/packages/excalidraw/components/LibraryMenu.tsx index 6192c7e711bd..efb7c9fe1e87 100644 --- a/packages/excalidraw/components/LibraryMenu.tsx +++ b/packages/excalidraw/components/LibraryMenu.tsx @@ -14,8 +14,8 @@ import type { } from "../types"; import LibraryMenuItems from "./LibraryMenuItems"; import { trackEvent } from "../analytics"; -import { atom, useAtom } from "jotai"; -import { jotaiScope } from "../jotai"; +import { atom } from "jotai"; +import { useAtom } from "../jotai"; import Spinner from "./Spinner"; import { useApp, @@ -61,7 +61,7 @@ export const LibraryMenuContent = ({ selectedItems: LibraryItem["id"][]; onSelectItems: (id: LibraryItem["id"][]) => void; }) => { - const [libraryItemsData] = useAtom(libraryItemsAtom, jotaiScope); + const [libraryItemsData] = useAtom(libraryItemsAtom); const _onAddToLibrary = useCallback( (elements: LibraryItem["elements"]) => { diff --git a/packages/excalidraw/components/LibraryMenuHeaderContent.tsx b/packages/excalidraw/components/LibraryMenuHeaderContent.tsx index e26507803dde..bdc8506df1df 100644 --- a/packages/excalidraw/components/LibraryMenuHeaderContent.tsx +++ b/packages/excalidraw/components/LibraryMenuHeaderContent.tsx @@ -1,7 +1,7 @@ import { useCallback, useState } from "react"; import { t } from "../i18n"; import Trans from "./Trans"; -import { jotaiScope } from "../jotai"; +import { useAtom } from "../jotai"; import type { LibraryItem, LibraryItems, UIAppState } from "../types"; import { useApp, useExcalidrawSetAppState } from "./App"; import { saveLibraryAsJSON } from "../data/json"; @@ -17,7 +17,6 @@ import { import { ToolButton } from "./ToolButton"; import { fileOpen } from "../data/filesystem"; import { muteFSAbortError } from "../utils"; -import { useAtom } from "jotai"; import ConfirmDialog from "./ConfirmDialog"; import PublishLibrary from "./PublishLibrary"; import { Dialog } from "./Dialog"; @@ -51,10 +50,9 @@ export const LibraryDropdownMenuButton: React.FC<{ appState, className, }) => { - const [libraryItemsData] = useAtom(libraryItemsAtom, jotaiScope); + const [libraryItemsData] = useAtom(libraryItemsAtom); const [isLibraryMenuOpen, setIsLibraryMenuOpen] = useAtom( isLibraryMenuOpenAtom, - jotaiScope, ); const renderRemoveLibAlert = () => { @@ -286,7 +284,7 @@ export const LibraryDropdownMenu = ({ const appState = useUIAppState(); const setAppState = useExcalidrawSetAppState(); - const [libraryItemsData] = useAtom(libraryItemsAtom, jotaiScope); + const [libraryItemsData] = useAtom(libraryItemsAtom); const removeFromLibrary = async (libraryItems: LibraryItems) => { const nextItems = libraryItems.filter( diff --git a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.tsx b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.tsx index 9a674cd37006..621e8ccba1dc 100644 --- a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.tsx +++ b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.tsx @@ -1,8 +1,7 @@ import React from "react"; -import { useAtom } from "jotai"; import { useTunnels } from "../../context/tunnels"; -import { jotaiScope } from "../../jotai"; +import { useAtom } from "../../jotai"; import { Dialog } from "../Dialog"; import { withInternalFallback } from "../hoc/withInternalFallback"; import { overwriteConfirmStateAtom } from "./OverwriteConfirmState"; @@ -23,7 +22,6 @@ const OverwriteConfirmDialog = Object.assign( const { OverwriteConfirmDialogTunnel } = useTunnels(); const [overwriteConfirmState, setState] = useAtom( overwriteConfirmStateAtom, - jotaiScope, ); if (!overwriteConfirmState.active) { diff --git a/packages/excalidraw/components/SearchMenu.tsx b/packages/excalidraw/components/SearchMenu.tsx index b4bb91b907ec..081a0c1a0ec6 100644 --- a/packages/excalidraw/components/SearchMenu.tsx +++ b/packages/excalidraw/components/SearchMenu.tsx @@ -11,8 +11,8 @@ import { measureText } from "../element/textElement"; import { addEventListener, getFontString } from "../utils"; import { KEYS } from "../keys"; import clsx from "clsx"; -import { atom, useAtom } from "jotai"; -import { jotaiScope } from "../jotai"; +import { atom } from "jotai"; +import { useAtom } from "../jotai"; import { t } from "../i18n"; import { isElementCompletelyInViewport } from "../element/sizeHelpers"; import { randomInteger } from "../random"; @@ -58,7 +58,7 @@ export const SearchMenu = () => { const searchInputRef = useRef(null); - const [inputValue, setInputValue] = useAtom(searchQueryAtom, jotaiScope); + const [inputValue, setInputValue] = useAtom(searchQueryAtom); const searchQuery = inputValue.trim() as SearchQuery; const [isSearching, setIsSearching] = useState(false); @@ -70,10 +70,7 @@ export const SearchMenu = () => { const searchedQueryRef = useRef(null); const lastSceneNonceRef = useRef(undefined); - const [focusIndex, setFocusIndex] = useAtom( - searchItemInFocusAtom, - jotaiScope, - ); + const [focusIndex, setFocusIndex] = useAtom(searchItemInFocusAtom); const elementsMap = app.scene.getNonDeletedElementsMap(); useEffect(() => { diff --git a/packages/excalidraw/components/Sidebar/Sidebar.tsx b/packages/excalidraw/components/Sidebar/Sidebar.tsx index efa6ccbe3dfc..0eb61d9383c7 100644 --- a/packages/excalidraw/components/Sidebar/Sidebar.tsx +++ b/packages/excalidraw/components/Sidebar/Sidebar.tsx @@ -8,8 +8,8 @@ import React, { useCallback, } from "react"; import { Island } from "../Island"; -import { atom, useSetAtom } from "jotai"; -import { jotaiScope } from "../../jotai"; +import { atom } from "jotai"; +import { useSetAtom } from "../../jotai"; import type { SidebarProps, SidebarPropsContextValue } from "./common"; import { SidebarPropsContext } from "./common"; import { SidebarHeader } from "./SidebarHeader"; @@ -58,7 +58,7 @@ export const SidebarInner = forwardRef( const setAppState = useExcalidrawSetAppState(); - const setIsSidebarDockedAtom = useSetAtom(isSidebarDockedAtom, jotaiScope); + const setIsSidebarDockedAtom = useSetAtom(isSidebarDockedAtom); useLayoutEffect(() => { setIsSidebarDockedAtom(!!docked); diff --git a/packages/excalidraw/components/TTDDialog/TTDDialog.tsx b/packages/excalidraw/components/TTDDialog/TTDDialog.tsx index f0c63770adc0..2b2ffbc94ad9 100644 --- a/packages/excalidraw/components/TTDDialog/TTDDialog.tsx +++ b/packages/excalidraw/components/TTDDialog/TTDDialog.tsx @@ -25,7 +25,8 @@ import type { BinaryFiles } from "../../types"; import { ArrowRightIcon } from "../icons"; import "./TTDDialog.scss"; -import { atom, useAtom } from "jotai"; +import { atom } from "jotai"; +import { useAtom } from "../../jotai"; import { trackEvent } from "../../analytics"; import { InlineIcon } from "../InlineIcon"; import { TTDDialogSubmitShortcut } from "./TTDDialogSubmitShortcut"; diff --git a/packages/excalidraw/components/Trans.test.tsx b/packages/excalidraw/components/Trans.test.tsx index df8ec526ea0a..cd911b099c6f 100644 --- a/packages/excalidraw/components/Trans.test.tsx +++ b/packages/excalidraw/components/Trans.test.tsx @@ -4,6 +4,7 @@ import fallbackLangData from "../locales/en.json"; import Trans from "./Trans"; import type { TranslationKeys } from "../i18n"; +import { Provider } from "../jotai"; describe("Test ", () => { it("should translate the the strings correctly", () => { @@ -17,7 +18,7 @@ describe("Test ", () => { }; const { getByTestId } = render( - <> +
", () => { connect-link={(el) => {el}} />
- , +
, ); expect(getByTestId("test1").innerHTML).toEqual("Hello world"); diff --git a/packages/excalidraw/components/hoc/withInternalFallback.tsx b/packages/excalidraw/components/hoc/withInternalFallback.tsx index 4131c51ec9f0..e0abc0d662ea 100644 --- a/packages/excalidraw/components/hoc/withInternalFallback.tsx +++ b/packages/excalidraw/components/hoc/withInternalFallback.tsx @@ -1,4 +1,4 @@ -import { atom, useAtom } from "jotai"; +import { atom } from "jotai"; import React, { useLayoutEffect, useRef } from "react"; import { useTunnels } from "../../context/tunnels"; @@ -13,9 +13,11 @@ export const withInternalFallback = ( __fallback?: boolean; } > = (props) => { - const { jotaiScope } = useTunnels(); + const { + jotai: { useAtom }, + } = useTunnels(); // for rerenders - const [, setCounter] = useAtom(renderAtom, jotaiScope); + const [, setCounter] = useAtom(renderAtom); // for initial & subsequent renders. Tracked as component state // due to excalidraw multi-instance scanerios. const metaRef = useRef({ diff --git a/packages/excalidraw/components/main-menu/DefaultItems.tsx b/packages/excalidraw/components/main-menu/DefaultItems.tsx index 7a9dce84a753..17ede8c66238 100644 --- a/packages/excalidraw/components/main-menu/DefaultItems.tsx +++ b/packages/excalidraw/components/main-menu/DefaultItems.tsx @@ -32,9 +32,8 @@ import { actionToggleTheme, } from "../../actions"; import clsx from "clsx"; -import { useSetAtom } from "jotai"; import { activeConfirmDialogAtom } from "../ActiveConfirmDialog"; -import { jotaiScope } from "../../jotai"; +import { useSetAtom } from "../../jotai"; import { useUIAppState } from "../../context/ui-appState"; import { openConfirmModal } from "../OverwriteConfirm/OverwriteConfirmState"; import Trans from "../Trans"; @@ -189,10 +188,7 @@ Help.displayName = "Help"; export const ClearCanvas = () => { const { t } = useI18n(); - const setActiveConfirmDialog = useSetAtom( - activeConfirmDialogAtom, - jotaiScope, - ); + const setActiveConfirmDialog = useSetAtom(activeConfirmDialogAtom); const actionManager = useExcalidrawActionManager(); if (!actionManager.isActionEnabled(actionClearCanvas)) { diff --git a/packages/excalidraw/context/tunnels.ts b/packages/excalidraw/context/tunnels.ts index 8dc325ff9667..712a0e22a4a4 100644 --- a/packages/excalidraw/context/tunnels.ts +++ b/packages/excalidraw/context/tunnels.ts @@ -1,5 +1,6 @@ import React from "react"; import tunnel from "tunnel-rat"; +import { createIsolation } from "jotai-scope"; export type Tunnel = ReturnType; @@ -14,13 +15,15 @@ type TunnelsContextValue = { DefaultSidebarTabTriggersTunnel: Tunnel; OverwriteConfirmDialogTunnel: Tunnel; TTDDialogTriggerTunnel: Tunnel; - jotaiScope: symbol; + jotai: ReturnType; }; export const TunnelsContext = React.createContext(null!); export const useTunnels = () => React.useContext(TunnelsContext); +const isolatedJotai = createIsolation(); + export const useInitializeTunnels = () => { return React.useMemo((): TunnelsContextValue => { return { @@ -34,7 +37,7 @@ export const useInitializeTunnels = () => { DefaultSidebarTabTriggersTunnel: tunnel(), OverwriteConfirmDialogTunnel: tunnel(), TTDDialogTriggerTunnel: tunnel(), - jotaiScope: Symbol(), + jotai: isolatedJotai, }; }, []); }; diff --git a/packages/excalidraw/hooks/useLibraryItemSvg.ts b/packages/excalidraw/hooks/useLibraryItemSvg.ts index dc8cac3c9928..618ddf0ec8cc 100644 --- a/packages/excalidraw/hooks/useLibraryItemSvg.ts +++ b/packages/excalidraw/hooks/useLibraryItemSvg.ts @@ -1,7 +1,7 @@ -import { atom, useAtom } from "jotai"; +import { atom } from "jotai"; import { useEffect, useState } from "react"; import { COLOR_PALETTE } from "../colors"; -import { jotaiScope } from "../jotai"; +import { useAtom } from "../jotai"; import { exportToSvg } from "../../utils/export"; import type { LibraryItem } from "../types"; @@ -68,7 +68,7 @@ export const useLibraryItemSvg = ( }; export const useLibraryCache = () => { - const [svgCache] = useAtom(libraryItemSvgsCache, jotaiScope); + const [svgCache] = useAtom(libraryItemSvgsCache); const clearLibraryCache = () => svgCache.clear(); diff --git a/packages/excalidraw/hooks/useScrollPosition.ts b/packages/excalidraw/hooks/useScrollPosition.ts index e4efb460ea5f..6d53c30d6e07 100644 --- a/packages/excalidraw/hooks/useScrollPosition.ts +++ b/packages/excalidraw/hooks/useScrollPosition.ts @@ -1,5 +1,6 @@ import { useEffect } from "react"; -import { atom, useAtom } from "jotai"; +import { atom } from "jotai"; +import { useAtom } from "../jotai"; import throttle from "lodash.throttle"; const scrollPositionAtom = atom(0); diff --git a/packages/excalidraw/i18n.ts b/packages/excalidraw/i18n.ts index 10373ef56a52..e9d67a7e05e7 100644 --- a/packages/excalidraw/i18n.ts +++ b/packages/excalidraw/i18n.ts @@ -1,7 +1,7 @@ import fallbackLangData from "./locales/en.json"; import percentages from "./locales/percentages.json"; -import { jotaiScope, jotaiStore } from "./jotai"; -import { atom, useAtomValue } from "jotai"; +import { useAtomValue, jotaiStore } from "./jotai"; +import { atom } from "jotai"; import type { NestedKeyOf } from "./utility-types"; const COMPLETION_THRESHOLD = 85; @@ -165,6 +165,6 @@ const editorLangCodeAtom = atom(defaultLang.code); // - component is rendered internally by , but the component // is memoized w/o being updated on `langCode`, `AppState`, or `UIAppState` export const useI18n = () => { - const langCode = useAtomValue(editorLangCodeAtom, jotaiScope); + const langCode = useAtomValue(editorLangCodeAtom); return { t, langCode }; }; diff --git a/packages/excalidraw/index.tsx b/packages/excalidraw/index.tsx index ae94c78b5671..4379b5fad9be 100644 --- a/packages/excalidraw/index.tsx +++ b/packages/excalidraw/index.tsx @@ -11,8 +11,7 @@ import "./fonts/fonts.css"; import type { AppProps, ExcalidrawProps } from "./types"; import { defaultLang } from "./i18n"; import { DEFAULT_UI_OPTIONS } from "./constants"; -import { Provider } from "jotai"; -import { jotaiScope, jotaiStore } from "./jotai"; +import { Provider, jotaiStore } from "./jotai"; import Footer from "./components/footer/FooterCenter"; import MainMenu from "./components/main-menu/MainMenu"; import WelcomeScreen from "./components/welcome-screen/WelcomeScreen"; @@ -114,7 +113,7 @@ const ExcalidrawBase = (props: ExcalidrawProps) => { }, []); return ( - jotaiStore} scope={jotaiScope}> + ["Provider"] = + jotai.Provider; + +export const jotaiStore: ReturnType = createStore(); export const useAtomWithInitialValue = < T extends unknown, @@ -12,7 +17,7 @@ export const useAtomWithInitialValue = < atom: A, initialValue: T | (() => T), ) => { - const [value, setValue] = useAtom(atom); + const [value, setValue] = _useAtom(atom); useLayoutEffect(() => { if (typeof initialValue === "function") { diff --git a/packages/excalidraw/package.json b/packages/excalidraw/package.json index 53715d9cc20a..bb14572447cd 100644 --- a/packages/excalidraw/package.json +++ b/packages/excalidraw/package.json @@ -52,7 +52,8 @@ "fractional-indexing": "3.2.0", "fuzzy": "0.1.3", "image-blob-reduce": "3.0.1", - "jotai": "1.13.1", + "jotai": "2.11.0", + "jotai-scope": "0.7.2", "lodash.throttle": "4.1.1", "nanoid": "3.3.3", "open-color": "1.9.1", diff --git a/yarn.lock b/yarn.lock index b97d9a706a5b..7eb706e64f05 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7339,10 +7339,15 @@ jest-worker@^27.4.5: merge-stream "^2.0.0" supports-color "^8.0.0" -jotai@1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/jotai/-/jotai-1.13.1.tgz#20cc46454cbb39096b12fddfa635b873b3668236" - integrity sha512-RUmH1S4vLsG3V6fbGlKzGJnLrDcC/HNb5gH2AeA9DzuJknoVxSGvvg8OBB7lke+gDc4oXmdVsaKn/xDUhWZ0vw== +jotai-scope@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/jotai-scope/-/jotai-scope-0.7.2.tgz#3e9ec5b743bd9f36b08b32cf5151786049bfcce7" + integrity sha512-Gwed97f3dDObrO43++2lRcgOqw4O2sdr4JCjP/7eHK1oPACDJ7xKHGScpJX9XaflU+KBHXF+VhwECnzcaQiShg== + +jotai@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/jotai/-/jotai-2.11.0.tgz#923f8351e0b2d721036af892c0ae25625049d120" + integrity sha512-zKfoBBD1uDw3rljwHkt0fWuja1B76R7CjznuBO+mSX6jpsO1EBeWNRKpeaQho9yPI/pvCv4recGfgOXGxwPZvQ== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0"