import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext' import { Resizable } from 're-resizable' import { HTMLAttributes, useCallback, useEffect, useState } from 'react' import { useHotkeys } from 'react-hotkeys-hook' import { useStore } from 'useStore' import { Tab } from '@headlessui/react' import { SidebarPane, SidebarType, bottomPanes, topPanes, } from './ModelingPanes' import Tooltip from 'components/Tooltip' import { ActionIcon } from 'components/ActionIcon' import styles from './ModelingSidebar.module.css' import { ModelingPane } from './ModelingPane' import { isTauri } from 'lib/isTauri' interface ModelingSidebarProps { paneOpacity: '' | 'opacity-20' | 'opacity-40' } export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) { const { settings } = useSettingsAuthContext() const onboardingStatus = settings.context.app.onboardingStatus const { openPanes, buttonDownInStream } = useStore((s) => ({ buttonDownInStream: s.buttonDownInStream, openPanes: s.openPanes, })) const pointerEventsCssClass = buttonDownInStream || onboardingStatus.current === 'camera' || openPanes.length === 0 ? 'pointer-events-none ' : 'pointer-events-auto ' return (
) } interface ModelingSidebarSectionProps extends HTMLAttributes { panes: SidebarPane[] alignButtons?: 'start' | 'end' } function ModelingSidebarSection({ panes, alignButtons = 'start', className, ...props }: ModelingSidebarSectionProps) { const { settings } = useSettingsAuthContext() const showDebugPanel = settings.context.modeling.showDebugPanel const paneIds = panes.map((pane) => pane.id) const { openPanes, setOpenPanes } = useStore((s) => ({ openPanes: s.openPanes, setOpenPanes: s.setOpenPanes, })) const foundOpenPane = openPanes.find((pane) => paneIds.includes(pane)) const [currentPane, setCurrentPane] = useState( foundOpenPane || ('none' as SidebarType | 'none') ) const togglePane = useCallback( (newPane: SidebarType | 'none') => { if (newPane === 'none') { setOpenPanes(openPanes.filter((p) => p !== currentPane)) setCurrentPane('none') } else if (newPane === currentPane) { setCurrentPane('none') setOpenPanes(openPanes.filter((p) => p !== newPane)) } else { setOpenPanes([...openPanes.filter((p) => p !== currentPane), newPane]) setCurrentPane(newPane) } }, [openPanes, setOpenPanes, currentPane, setCurrentPane] ) // Filter out the debug panel if it's not supposed to be shown // TODO: abstract out for allowing user to configure which panes to show const filteredPanes = ( showDebugPanel.current ? panes : panes.filter((pane) => pane.id !== 'debug') ).filter( (pane) => !pane.hideOnPlatform || (isTauri() ? pane.hideOnPlatform === 'web' : pane.hideOnPlatform === 'desktop') ) useEffect(() => { if ( !showDebugPanel.current && currentPane === 'debug' && openPanes.includes('debug') ) { togglePane('debug') } }, [showDebugPanel.current, togglePane, openPanes]) return (
{ const newPane = index === 0 ? 'none' : paneIds[index - 1] togglePane(newPane) }} > No panes open {filteredPanes.map((pane) => ( togglePane(pane.id)} /> ))} {filteredPanes.map((pane) => ( {pane.Content instanceof Function ? ( ) : ( pane.Content )} ))}
) } interface ModelingPaneButtonProps { paneConfig: SidebarPane currentPane: SidebarType | 'none' togglePane: () => void } function ModelingPaneButton({ paneConfig, currentPane, togglePane, }: ModelingPaneButtonProps) { useHotkeys(paneConfig.keybinding, togglePane, { scopes: ['modeling'], }) return ( {paneConfig.title}
{paneConfig.keybinding}
) }