import { NoSsr, Skeleton } from '@mui/material'; import { assignInlineVars } from '@vanilla-extract/dynamic'; import clsx from 'clsx'; import { useAtom, useAtomValue } from 'jotai'; import type { PropsWithChildren, ReactElement } from 'react'; import { useEffect, useRef, useState } from 'react'; import { fallbackHeaderStyle, fallbackStyle } from './fallback.css'; import { floatingMaxWidth, navBodyStyle, navStyle, navWidthVar, navWrapperStyle, sidebarFloatMaskStyle, } from './index.css'; import { APP_SIDEBAR_OPEN, appSidebarFloatingAtom, appSidebarOpenAtom, appSidebarResizingAtom, appSidebarWidthAtom, } from './index.jotai'; import { ResizeIndicator } from './resize-indicator'; import type { SidebarHeaderProps } from './sidebar-header'; import { SidebarHeader } from './sidebar-header'; export type AppSidebarProps = PropsWithChildren< SidebarHeaderProps & { hasBackground?: boolean; isFallback?: boolean; } >; function useEnableAnimation() { const [enable, setEnable] = useState(false); useEffect(() => { setTimeout(() => { setEnable(true); }, 500); }, []); return enable; } export type History = { stack: string[]; current: number; }; export function AppSidebar(props: AppSidebarProps): ReactElement { const [open, setOpen] = useAtom(appSidebarOpenAtom); const appSidebarWidth = useAtomValue(appSidebarWidthAtom); const [appSidebarFloating, setAppSidebarFloating] = useAtom( appSidebarFloatingAtom ); const initialRender = open === undefined && !props.isFallback; const isResizing = useAtomValue(appSidebarResizingAtom); const navRef = useRef(null); useEffect(() => { function onResize() { const { matches } = window.matchMedia( `(max-width: ${floatingMaxWidth}px)` ); if ( open === undefined && localStorage.getItem(APP_SIDEBAR_OPEN) === null ) { // give the initial value, // so that the sidebar can be closed on mobile by default setOpen(!matches); } setAppSidebarFloating(matches && !!open); } onResize(); window.addEventListener('resize', onResize); return () => { window.removeEventListener('resize', onResize); }; }, [open, setAppSidebarFloating, setOpen]); // disable animation to avoid UI flash const enableAnimation = useEnableAnimation(); const isMacosDesktop = environment.isDesktop && environment.isMacOs; if (initialRender) { // avoid the UI flash return
; } return ( <>
setOpen(false)} /> ); } export const AppSidebarFallback = (): ReactElement | null => { return (
); }; export * from './add-page-button'; export * from './app-updater-button'; export * from './category-divider'; export * from './index.css'; export * from './menu-item'; export * from './quick-search-input'; export * from './sidebar-containers'; export * from './sidebar-header'; export { appSidebarFloatingAtom, appSidebarOpenAtom, appSidebarResizingAtom };