import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext' import { Resizable } from 're-resizable' import { HTMLAttributes, useCallback, useEffect, useState } from 'react' import { useHotkeys } from 'react-hotkeys-hook' 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' import { useModelingContext } from 'hooks/useModelingContext' interface ModelingSidebarProps { paneOpacity: '' | 'opacity-20' | 'opacity-40' } export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) { const { settings } = useSettingsAuthContext() const onboardingStatus = settings.context.app.onboardingStatus const { context } = useModelingContext() const pointerEventsCssClass = context.store?.buttonDownInStream || onboardingStatus.current === 'camera' || context.store?.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 { send, context } = useModelingContext() const foundOpenPane = context.store?.openPanes.find((pane) => paneIds.includes(pane) ) const [currentPane, setCurrentPane] = useState( foundOpenPane || ('none' as SidebarType | 'none') ) const togglePane = useCallback( (newPane: SidebarType | 'none') => { if (newPane === 'none') { send({ type: 'Set context', data: { openPanes: context.store?.openPanes.filter( (p) => p !== currentPane ), }, }) setCurrentPane('none') } else if (newPane === currentPane) { setCurrentPane('none') send({ type: 'Set context', data: { openPanes: context.store?.openPanes.filter((p) => p !== newPane), }, }) } else { send({ type: 'Set context', data: { openPanes: [ ...context.store?.openPanes.filter((p) => p !== currentPane), newPane, ], }, }) setCurrentPane(newPane) } }, [context.store?.openPanes, send, 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' && context.store?.openPanes.includes('debug') ) { togglePane('debug') } }, [showDebugPanel.current, togglePane, context.store?.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}
) }