aboutsummaryrefslogtreecommitdiffstats
path: root/packages/excalidraw/components/DefaultSidebar.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/excalidraw/components/DefaultSidebar.tsx')
-rw-r--r--packages/excalidraw/components/DefaultSidebar.tsx121
1 files changed, 121 insertions, 0 deletions
diff --git a/packages/excalidraw/components/DefaultSidebar.tsx b/packages/excalidraw/components/DefaultSidebar.tsx
new file mode 100644
index 0000000..70b0c2d
--- /dev/null
+++ b/packages/excalidraw/components/DefaultSidebar.tsx
@@ -0,0 +1,121 @@
+import clsx from "clsx";
+import {
+ CANVAS_SEARCH_TAB,
+ DEFAULT_SIDEBAR,
+ LIBRARY_SIDEBAR_TAB,
+} from "../constants";
+import { useTunnels } from "../context/tunnels";
+import { useUIAppState } from "../context/ui-appState";
+import type { MarkOptional, Merge } from "../utility-types";
+import { composeEventHandlers } from "../utils";
+import { useExcalidrawSetAppState } from "./App";
+import { withInternalFallback } from "./hoc/withInternalFallback";
+import { LibraryMenu } from "./LibraryMenu";
+import type { SidebarProps, SidebarTriggerProps } from "./Sidebar/common";
+import { Sidebar } from "./Sidebar/Sidebar";
+import "../components/dropdownMenu/DropdownMenu.scss";
+import { SearchMenu } from "./SearchMenu";
+import { LibraryIcon, searchIcon } from "./icons";
+
+const DefaultSidebarTrigger = withInternalFallback(
+ "DefaultSidebarTrigger",
+ (
+ props: Omit<SidebarTriggerProps, "name"> &
+ React.HTMLAttributes<HTMLDivElement>,
+ ) => {
+ const { DefaultSidebarTriggerTunnel } = useTunnels();
+ return (
+ <DefaultSidebarTriggerTunnel.In>
+ <Sidebar.Trigger
+ {...props}
+ className="default-sidebar-trigger"
+ name={DEFAULT_SIDEBAR.name}
+ />
+ </DefaultSidebarTriggerTunnel.In>
+ );
+ },
+);
+DefaultSidebarTrigger.displayName = "DefaultSidebarTrigger";
+
+const DefaultTabTriggers = ({ children }: { children: React.ReactNode }) => {
+ const { DefaultSidebarTabTriggersTunnel } = useTunnels();
+ return (
+ <DefaultSidebarTabTriggersTunnel.In>
+ {children}
+ </DefaultSidebarTabTriggersTunnel.In>
+ );
+};
+DefaultTabTriggers.displayName = "DefaultTabTriggers";
+
+export const DefaultSidebar = Object.assign(
+ withInternalFallback(
+ "DefaultSidebar",
+ ({
+ children,
+ className,
+ onDock,
+ docked,
+ ...rest
+ }: Merge<
+ MarkOptional<Omit<SidebarProps, "name">, "children">,
+ {
+ /** pass `false` to disable docking */
+ onDock?: SidebarProps["onDock"] | false;
+ }
+ >) => {
+ const appState = useUIAppState();
+ const setAppState = useExcalidrawSetAppState();
+
+ const { DefaultSidebarTabTriggersTunnel } = useTunnels();
+
+ const isForceDocked = appState.openSidebar?.tab === CANVAS_SEARCH_TAB;
+
+ return (
+ <Sidebar
+ {...rest}
+ name="default"
+ key="default"
+ className={clsx("default-sidebar", className)}
+ docked={
+ isForceDocked || (docked ?? appState.defaultSidebarDockedPreference)
+ }
+ onDock={
+ // `onDock=false` disables docking.
+ // if `docked` passed, but no onDock passed, disable manual docking.
+ isForceDocked || onDock === false || (!onDock && docked != null)
+ ? undefined
+ : // compose to allow the host app to listen on default behavior
+ composeEventHandlers(onDock, (docked) => {
+ setAppState({ defaultSidebarDockedPreference: docked });
+ })
+ }
+ >
+ <Sidebar.Tabs>
+ <Sidebar.Header>
+ <Sidebar.TabTriggers>
+ <Sidebar.TabTrigger tab={CANVAS_SEARCH_TAB}>
+ {searchIcon}
+ </Sidebar.TabTrigger>
+ <Sidebar.TabTrigger tab={LIBRARY_SIDEBAR_TAB}>
+ {LibraryIcon}
+ </Sidebar.TabTrigger>
+ <DefaultSidebarTabTriggersTunnel.Out />
+ </Sidebar.TabTriggers>
+ </Sidebar.Header>
+ <Sidebar.Tab tab={LIBRARY_SIDEBAR_TAB}>
+ <LibraryMenu />
+ </Sidebar.Tab>
+ <Sidebar.Tab tab={CANVAS_SEARCH_TAB}>
+ <SearchMenu />
+ </Sidebar.Tab>
+ {children}
+ </Sidebar.Tabs>
+ </Sidebar>
+ );
+ },
+ ),
+ {
+ Trigger: DefaultSidebarTrigger,
+ TabTriggers: DefaultTabTriggers,
+ },
+);