This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useMemo,
|
||||
useState,
|
||||
type CSSProperties,
|
||||
type ReactNode,
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useMemo,
|
||||
useState,
|
||||
type CSSProperties,
|
||||
type ReactNode,
|
||||
} from 'react';
|
||||
import { isDesktopViewport, useSidePanelMachine } from '../panels/useSidePanelMachine';
|
||||
|
||||
@@ -15,133 +15,133 @@ const RIGHT_SIDEBAR_MIN_WIDTH = 260;
|
||||
const RIGHT_SIDEBAR_MAX_WIDTH = 480;
|
||||
|
||||
export type RightSidebarContent = {
|
||||
title: string;
|
||||
content: ReactNode;
|
||||
ariaLabel?: string;
|
||||
title: string;
|
||||
content: ReactNode;
|
||||
ariaLabel?: string;
|
||||
};
|
||||
|
||||
export type RightSidebarStyle = CSSProperties & {
|
||||
'--auth-right-sidebar-width': string;
|
||||
'--auth-right-sidebar-width': string;
|
||||
};
|
||||
|
||||
type RightSidebarContextValue = {
|
||||
isOpen: boolean;
|
||||
content: RightSidebarContent | null;
|
||||
openSidebar: (content?: RightSidebarContent) => void;
|
||||
closeSidebar: () => void;
|
||||
toggleSidebar: (content?: RightSidebarContent) => void;
|
||||
setSidebarContent: (content: RightSidebarContent | null) => void;
|
||||
desktopSidebarStyle: RightSidebarStyle;
|
||||
startResize: ReturnType<typeof useSidePanelMachine>['startResize'];
|
||||
isOpen: boolean;
|
||||
content: RightSidebarContent | null;
|
||||
openSidebar: (content?: RightSidebarContent) => void;
|
||||
closeSidebar: () => void;
|
||||
toggleSidebar: (content?: RightSidebarContent) => void;
|
||||
setSidebarContent: (content: RightSidebarContent | null) => void;
|
||||
desktopSidebarStyle: RightSidebarStyle;
|
||||
startResize: ReturnType<typeof useSidePanelMachine>['startResize'];
|
||||
};
|
||||
|
||||
type RightSidebarProviderProps = {
|
||||
children: ReactNode;
|
||||
closeOnPathname?: string;
|
||||
onMobileOpenRequest?: () => void;
|
||||
children: ReactNode;
|
||||
closeOnPathname?: string;
|
||||
onMobileOpenRequest?: () => void;
|
||||
};
|
||||
|
||||
const RightSidebarContext = createContext<RightSidebarContextValue | undefined>(undefined);
|
||||
|
||||
export function RightSidebarProvider({
|
||||
children,
|
||||
closeOnPathname,
|
||||
onMobileOpenRequest,
|
||||
}: Readonly<RightSidebarProviderProps>) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [content, setContent] = useState<RightSidebarContent | null>(null);
|
||||
|
||||
const closeSidebar = useCallback(() => {
|
||||
setIsOpen(false);
|
||||
setContent(null);
|
||||
}, []);
|
||||
|
||||
const setSidebarContent = useCallback((nextContent: RightSidebarContent | null) => {
|
||||
setContent(nextContent);
|
||||
}, []);
|
||||
|
||||
const openSidebar = useCallback(
|
||||
(nextContent?: RightSidebarContent) => {
|
||||
const resolvedContent = nextContent ?? content;
|
||||
if (!resolvedContent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nextContent) {
|
||||
setContent(nextContent);
|
||||
}
|
||||
if (!isDesktopViewport()) {
|
||||
onMobileOpenRequest?.();
|
||||
}
|
||||
setIsOpen(true);
|
||||
},
|
||||
[content, onMobileOpenRequest],
|
||||
);
|
||||
|
||||
const toggleSidebar = useCallback(
|
||||
(nextContent?: RightSidebarContent) => {
|
||||
if (isOpen) {
|
||||
closeSidebar();
|
||||
return;
|
||||
}
|
||||
|
||||
openSidebar(nextContent);
|
||||
},
|
||||
[isOpen, closeSidebar, openSidebar],
|
||||
);
|
||||
|
||||
const { width, startResize } = useSidePanelMachine({
|
||||
storageKey: RIGHT_SIDEBAR_WIDTH_KEY,
|
||||
defaultWidth: RIGHT_SIDEBAR_DEFAULT_WIDTH,
|
||||
minWidth: RIGHT_SIDEBAR_MIN_WIDTH,
|
||||
maxWidth: RIGHT_SIDEBAR_MAX_WIDTH,
|
||||
resizeAxis: 'from-right',
|
||||
resizingBodyClass: 'auth-right-sidebar-resizing',
|
||||
isOpen,
|
||||
canResize: isOpen,
|
||||
shouldPersistWidth: true,
|
||||
children,
|
||||
closeOnPathname,
|
||||
onCloseOnPathname: closeSidebar,
|
||||
onEscape: closeSidebar,
|
||||
});
|
||||
onMobileOpenRequest,
|
||||
}: Readonly<RightSidebarProviderProps>) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [content, setContent] = useState<RightSidebarContent | null>(null);
|
||||
|
||||
const desktopSidebarStyle = useMemo<RightSidebarStyle>(
|
||||
() => ({
|
||||
'--auth-right-sidebar-width': `${width}px`,
|
||||
}),
|
||||
[width],
|
||||
);
|
||||
const closeSidebar = useCallback(() => {
|
||||
setIsOpen(false);
|
||||
setContent(null);
|
||||
}, []);
|
||||
|
||||
const value = useMemo<RightSidebarContextValue>(
|
||||
() => ({
|
||||
isOpen,
|
||||
content,
|
||||
openSidebar,
|
||||
closeSidebar,
|
||||
toggleSidebar,
|
||||
setSidebarContent,
|
||||
desktopSidebarStyle,
|
||||
startResize,
|
||||
}),
|
||||
[
|
||||
isOpen,
|
||||
content,
|
||||
openSidebar,
|
||||
closeSidebar,
|
||||
toggleSidebar,
|
||||
setSidebarContent,
|
||||
desktopSidebarStyle,
|
||||
startResize,
|
||||
],
|
||||
);
|
||||
const setSidebarContent = useCallback((nextContent: RightSidebarContent | null) => {
|
||||
setContent(nextContent);
|
||||
}, []);
|
||||
|
||||
return <RightSidebarContext.Provider value={value}>{children}</RightSidebarContext.Provider>;
|
||||
const openSidebar = useCallback(
|
||||
(nextContent?: RightSidebarContent) => {
|
||||
const resolvedContent = nextContent ?? content;
|
||||
if (!resolvedContent) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (nextContent) {
|
||||
setContent(nextContent);
|
||||
}
|
||||
if (!isDesktopViewport()) {
|
||||
onMobileOpenRequest?.();
|
||||
}
|
||||
setIsOpen(true);
|
||||
},
|
||||
[content, onMobileOpenRequest],
|
||||
);
|
||||
|
||||
const toggleSidebar = useCallback(
|
||||
(nextContent?: RightSidebarContent) => {
|
||||
if (isOpen) {
|
||||
closeSidebar();
|
||||
return;
|
||||
}
|
||||
|
||||
openSidebar(nextContent);
|
||||
},
|
||||
[isOpen, closeSidebar, openSidebar],
|
||||
);
|
||||
|
||||
const { width, startResize } = useSidePanelMachine({
|
||||
storageKey: RIGHT_SIDEBAR_WIDTH_KEY,
|
||||
defaultWidth: RIGHT_SIDEBAR_DEFAULT_WIDTH,
|
||||
minWidth: RIGHT_SIDEBAR_MIN_WIDTH,
|
||||
maxWidth: RIGHT_SIDEBAR_MAX_WIDTH,
|
||||
resizeAxis: 'from-right',
|
||||
resizingBodyClass: 'auth-right-sidebar-resizing',
|
||||
isOpen,
|
||||
canResize: isOpen,
|
||||
shouldPersistWidth: true,
|
||||
closeOnPathname,
|
||||
onCloseOnPathname: closeSidebar,
|
||||
onEscape: closeSidebar,
|
||||
});
|
||||
|
||||
const desktopSidebarStyle = useMemo<RightSidebarStyle>(
|
||||
() => ({
|
||||
'--auth-right-sidebar-width': `${width}px`,
|
||||
}),
|
||||
[width],
|
||||
);
|
||||
|
||||
const value = useMemo<RightSidebarContextValue>(
|
||||
() => ({
|
||||
isOpen,
|
||||
content,
|
||||
openSidebar,
|
||||
closeSidebar,
|
||||
toggleSidebar,
|
||||
setSidebarContent,
|
||||
desktopSidebarStyle,
|
||||
startResize,
|
||||
}),
|
||||
[
|
||||
isOpen,
|
||||
content,
|
||||
openSidebar,
|
||||
closeSidebar,
|
||||
toggleSidebar,
|
||||
setSidebarContent,
|
||||
desktopSidebarStyle,
|
||||
startResize,
|
||||
],
|
||||
);
|
||||
|
||||
return <RightSidebarContext.Provider value={value}>{children}</RightSidebarContext.Provider>;
|
||||
}
|
||||
|
||||
export function useRightSidebar() {
|
||||
const ctx = useContext(RightSidebarContext);
|
||||
if (!ctx) {
|
||||
throw new Error('useRightSidebar must be used within RightSidebarProvider');
|
||||
}
|
||||
return ctx;
|
||||
const ctx = useContext(RightSidebarContext);
|
||||
if (!ctx) {
|
||||
throw new Error('useRightSidebar must be used within RightSidebarProvider');
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user