update prettier
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-02-23 14:23:46 +01:00
parent 33d1425fbb
commit cbabf43584
25 changed files with 1373 additions and 1363 deletions

View File

@@ -1,13 +1,13 @@
import {
createContext,
useCallback,
useContext,
useEffect,
useMemo,
useRef,
useState,
type CSSProperties,
type ReactNode,
createContext,
useCallback,
useContext,
useEffect,
useMemo,
useRef,
useState,
type CSSProperties,
type ReactNode,
} from 'react';
import { isDesktopViewport, useSidePanelMachine } from '../panels/useSidePanelMachine';
@@ -19,207 +19,207 @@ const SIDEBAR_MAX_WIDTH = 420;
const SIDEBAR_COLLAPSED_WIDTH = 56;
export type LeftMenuRenderState = {
collapsed: boolean;
mobileOpen: boolean;
isDesktop: boolean;
closeMenu: () => void;
collapsed: boolean;
mobileOpen: boolean;
isDesktop: boolean;
closeMenu: () => void;
};
export type LeftMenuContent = {
ariaLabel?: string;
render: (state: LeftMenuRenderState) => ReactNode;
ariaLabel?: string;
render: (state: LeftMenuRenderState) => ReactNode;
};
export type LeftMenuStyle = CSSProperties & {
'--auth-sidebar-width': string;
'--auth-sidebar-width': string;
};
type LeftMenuContextValue = {
collapsed: boolean;
mobileOpen: boolean;
content: LeftMenuContent;
desktopMenuStyle: LeftMenuStyle;
openMenu: (content?: LeftMenuContent) => void;
closeMenu: () => void;
toggleMenu: (content?: LeftMenuContent) => void;
expandMenu: () => void;
collapseMenu: () => void;
toggleCollapsed: () => void;
setMenuContent: (content: LeftMenuContent | null) => void;
startResize: ReturnType<typeof useSidePanelMachine>['startResize'];
collapsed: boolean;
mobileOpen: boolean;
content: LeftMenuContent;
desktopMenuStyle: LeftMenuStyle;
openMenu: (content?: LeftMenuContent) => void;
closeMenu: () => void;
toggleMenu: (content?: LeftMenuContent) => void;
expandMenu: () => void;
collapseMenu: () => void;
toggleCollapsed: () => void;
setMenuContent: (content: LeftMenuContent | null) => void;
startResize: ReturnType<typeof useSidePanelMachine>['startResize'];
};
type LeftMenuProviderProps = {
children: ReactNode;
defaultContent: LeftMenuContent;
closeOnPathname?: string;
children: ReactNode;
defaultContent: LeftMenuContent;
closeOnPathname?: string;
};
const LeftMenuContext = createContext<LeftMenuContextValue | undefined>(undefined);
function readStoredCollapsed(): boolean {
if (!globalThis.window) {
return false;
}
if (!globalThis.window) {
return false;
}
return localStorage.getItem(SIDEBAR_COLLAPSED_KEY) === '1';
return localStorage.getItem(SIDEBAR_COLLAPSED_KEY) === '1';
}
export function LeftMenuProvider({
children,
defaultContent,
closeOnPathname,
}: Readonly<LeftMenuProviderProps>) {
const [collapsed, setCollapsed] = useState<boolean>(() => readStoredCollapsed());
const [mobileOpen, setMobileOpen] = useState(false);
const [content, setContent] = useState<LeftMenuContent>(defaultContent);
const defaultContentRef = useRef(defaultContent);
useEffect(() => {
const previousDefaultContent = defaultContentRef.current;
defaultContentRef.current = defaultContent;
setContent((currentContent) => {
if (currentContent === previousDefaultContent) {
return defaultContent;
}
return currentContent;
});
}, [defaultContent]);
useEffect(() => {
if (!globalThis.window) {
return;
}
localStorage.setItem(SIDEBAR_COLLAPSED_KEY, collapsed ? '1' : '0');
}, [collapsed]);
const expandMenu = useCallback(() => {
setCollapsed(false);
}, []);
const collapseMenu = useCallback(() => {
setCollapsed(true);
}, []);
const toggleCollapsed = useCallback(() => {
setCollapsed((previous) => !previous);
}, []);
const closeMobile = useCallback(() => {
setMobileOpen(false);
}, []);
const setMenuContent = useCallback((nextContent: LeftMenuContent | null) => {
setContent(nextContent ?? defaultContentRef.current);
}, []);
const closeMenu = useCallback(() => {
if (isDesktopViewport()) {
collapseMenu();
return;
}
closeMobile();
}, [collapseMenu, closeMobile]);
const openMenu = useCallback(
(nextContent?: LeftMenuContent) => {
if (nextContent) {
setContent(nextContent);
}
if (isDesktopViewport()) {
expandMenu();
return;
}
setMobileOpen(true);
},
[expandMenu],
);
const toggleMenu = useCallback(
(nextContent?: LeftMenuContent) => {
if (nextContent) {
setContent(nextContent);
}
if (isDesktopViewport()) {
toggleCollapsed();
return;
}
setMobileOpen((previous) => !previous);
},
[toggleCollapsed],
);
const handleCloseOnPathname = useCallback(() => {
setMobileOpen(false);
setContent(defaultContentRef.current);
}, []);
const { width, startResize } = useSidePanelMachine({
storageKey: SIDEBAR_WIDTH_KEY,
defaultWidth: SIDEBAR_DEFAULT_WIDTH,
minWidth: SIDEBAR_MIN_WIDTH,
maxWidth: SIDEBAR_MAX_WIDTH,
resizeAxis: 'from-left',
resizingBodyClass: 'auth-sidebar-resizing',
isOpen: mobileOpen,
canResize: !collapsed,
shouldPersistWidth: !collapsed,
children,
defaultContent,
closeOnPathname,
onCloseOnPathname: handleCloseOnPathname,
onEscape: closeMobile,
});
}: Readonly<LeftMenuProviderProps>) {
const [collapsed, setCollapsed] = useState<boolean>(() => readStoredCollapsed());
const [mobileOpen, setMobileOpen] = useState(false);
const [content, setContent] = useState<LeftMenuContent>(defaultContent);
const defaultContentRef = useRef(defaultContent);
const desktopMenuStyle = useMemo<LeftMenuStyle>(
() => ({
'--auth-sidebar-width': `${collapsed ? SIDEBAR_COLLAPSED_WIDTH : width}px`,
}),
[collapsed, width],
);
useEffect(() => {
const previousDefaultContent = defaultContentRef.current;
defaultContentRef.current = defaultContent;
setContent((currentContent) => {
if (currentContent === previousDefaultContent) {
return defaultContent;
}
return currentContent;
});
}, [defaultContent]);
const value = useMemo<LeftMenuContextValue>(
() => ({
collapsed,
mobileOpen,
content,
desktopMenuStyle,
openMenu,
closeMenu,
toggleMenu,
expandMenu,
collapseMenu,
toggleCollapsed,
setMenuContent,
startResize,
}),
[
collapsed,
mobileOpen,
content,
desktopMenuStyle,
openMenu,
closeMenu,
toggleMenu,
expandMenu,
collapseMenu,
toggleCollapsed,
setMenuContent,
startResize,
],
);
useEffect(() => {
if (!globalThis.window) {
return;
}
return <LeftMenuContext.Provider value={value}>{children}</LeftMenuContext.Provider>;
localStorage.setItem(SIDEBAR_COLLAPSED_KEY, collapsed ? '1' : '0');
}, [collapsed]);
const expandMenu = useCallback(() => {
setCollapsed(false);
}, []);
const collapseMenu = useCallback(() => {
setCollapsed(true);
}, []);
const toggleCollapsed = useCallback(() => {
setCollapsed((previous) => !previous);
}, []);
const closeMobile = useCallback(() => {
setMobileOpen(false);
}, []);
const setMenuContent = useCallback((nextContent: LeftMenuContent | null) => {
setContent(nextContent ?? defaultContentRef.current);
}, []);
const closeMenu = useCallback(() => {
if (isDesktopViewport()) {
collapseMenu();
return;
}
closeMobile();
}, [collapseMenu, closeMobile]);
const openMenu = useCallback(
(nextContent?: LeftMenuContent) => {
if (nextContent) {
setContent(nextContent);
}
if (isDesktopViewport()) {
expandMenu();
return;
}
setMobileOpen(true);
},
[expandMenu],
);
const toggleMenu = useCallback(
(nextContent?: LeftMenuContent) => {
if (nextContent) {
setContent(nextContent);
}
if (isDesktopViewport()) {
toggleCollapsed();
return;
}
setMobileOpen((previous) => !previous);
},
[toggleCollapsed],
);
const handleCloseOnPathname = useCallback(() => {
setMobileOpen(false);
setContent(defaultContentRef.current);
}, []);
const { width, startResize } = useSidePanelMachine({
storageKey: SIDEBAR_WIDTH_KEY,
defaultWidth: SIDEBAR_DEFAULT_WIDTH,
minWidth: SIDEBAR_MIN_WIDTH,
maxWidth: SIDEBAR_MAX_WIDTH,
resizeAxis: 'from-left',
resizingBodyClass: 'auth-sidebar-resizing',
isOpen: mobileOpen,
canResize: !collapsed,
shouldPersistWidth: !collapsed,
closeOnPathname,
onCloseOnPathname: handleCloseOnPathname,
onEscape: closeMobile,
});
const desktopMenuStyle = useMemo<LeftMenuStyle>(
() => ({
'--auth-sidebar-width': `${collapsed ? SIDEBAR_COLLAPSED_WIDTH : width}px`,
}),
[collapsed, width],
);
const value = useMemo<LeftMenuContextValue>(
() => ({
collapsed,
mobileOpen,
content,
desktopMenuStyle,
openMenu,
closeMenu,
toggleMenu,
expandMenu,
collapseMenu,
toggleCollapsed,
setMenuContent,
startResize,
}),
[
collapsed,
mobileOpen,
content,
desktopMenuStyle,
openMenu,
closeMenu,
toggleMenu,
expandMenu,
collapseMenu,
toggleCollapsed,
setMenuContent,
startResize,
],
);
return <LeftMenuContext.Provider value={value}>{children}</LeftMenuContext.Provider>;
}
export function useLeftMenu() {
const ctx = useContext(LeftMenuContext);
if (!ctx) {
throw new Error('useLeftMenu must be used within LeftMenuProvider');
}
return ctx;
const ctx = useContext(LeftMenuContext);
if (!ctx) {
throw new Error('useLeftMenu must be used within LeftMenuProvider');
}
return ctx;
}

View File

@@ -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;
}