Keep the extended sidebar open when changing Sidebar type + Rename ElementsSidebar

This commit is contained in:
Eric NGUYEN 2023-02-17 14:28:56 +01:00
parent 61807b621f
commit 00cf80d9e3
4 changed files with 81 additions and 101 deletions

View file

@ -1,21 +1,22 @@
import * as React from 'react'; import * as React from 'react';
import { useState } from 'react';
import useSize from '@react-hook/size'; import useSize from '@react-hook/size';
import { FixedSizeList as List } from 'react-window'; import { FixedSizeList as List } from 'react-window';
import { ExclamationTriangleIcon } from '@heroicons/react/24/outline'; import { ExclamationTriangleIcon } from '@heroicons/react/24/outline';
import { ContainerProperties } from '../ContainerProperties/ContainerProperties'; import { ContainerProperties } from '../ContainerProperties/ContainerProperties';
import { IContainerModel } from '../../Interfaces/IContainerModel'; import { type IContainerModel } from '../../Interfaces/IContainerModel';
import { FindContainerById, MakeRecursionDFSIterator } from '../../utils/itertools'; import { FindContainerById, MakeRecursionDFSIterator } from '../../utils/itertools';
import { ISymbolModel } from '../../Interfaces/ISymbolModel'; import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
import { PropertyType } from '../../Enums/PropertyType'; import { type PropertyType } from '../../Enums/PropertyType';
import { ToggleSideBar } from '../Sidebar/ToggleSideBar/ToggleSideBar'; import { ToggleSideBar } from '../Sidebar/ToggleSideBar/ToggleSideBar';
import { Text } from '../Text/Text'; import { Text } from '../Text/Text';
import { ExtendedSidebar } from '../UI/UI';
interface IElementsSideBarProps { interface IElementsSidebarProps {
containers: Map<string, IContainerModel> containers: Map<string, IContainerModel>
mainContainer: IContainerModel mainContainer: IContainerModel
symbols: Map<string, ISymbolModel> symbols: Map<string, ISymbolModel>
selectedContainer: IContainerModel | undefined selectedContainer: IContainerModel | undefined
selectedExtendedSidebar: ExtendedSidebar
onPropertyChange: ( onPropertyChange: (
key: string, key: string,
value: string | number | boolean | number[], value: string | number | boolean | number[],
@ -23,8 +24,7 @@ interface IElementsSideBarProps {
) => void ) => void
selectContainer: (containerId: string) => void selectContainer: (containerId: string) => void
addContainer: (index: number, type: string, parent: string) => void addContainer: (index: number, type: string, parent: string) => void
isExpanded: boolean onExpandChange: (value: ExtendedSidebar) => void
onExpandChange: () => void
} }
function RemoveBorderClasses(target: HTMLButtonElement, exception: string = ''): void { function RemoveBorderClasses(target: HTMLButtonElement, exception: string = ''): void {
@ -124,11 +124,10 @@ function HandleOnDrop(
} }
} }
export function ElementsSideBar(props: IElementsSideBarProps): JSX.Element { export function ElementsSidebar(props: IElementsSidebarProps): JSX.Element {
// States // States
const divRef = React.useRef<HTMLDivElement>(null); const divRef = React.useRef<HTMLDivElement>(null);
const [,height] = useSize(divRef); const [,height] = useSize(divRef);
const [showProperties, setShowProperties] = useState(props.isExpanded);
// Render // Render
const it = MakeRecursionDFSIterator(props.mainContainer, props.containers, 0, [0, 0], true); const it = MakeRecursionDFSIterator(props.mainContainer, props.containers, 0, [0, 0], true);
@ -167,7 +166,7 @@ export function ElementsSideBar(props: IElementsSideBarProps): JSX.Element {
return ( return (
<div className='flex flex-row h-full w-full' > <div className='flex flex-row h-full w-full' >
{showProperties && {props.selectedExtendedSidebar === ExtendedSidebar.Property &&
<div className='flex flex-1 flex-col w-64 border-r-2 border-slate-400'> <div className='flex flex-1 flex-col w-64 border-r-2 border-slate-400'>
<ContainerProperties <ContainerProperties
properties={props.selectedContainer?.properties} properties={props.selectedContainer?.properties}
@ -178,7 +177,16 @@ export function ElementsSideBar(props: IElementsSideBarProps): JSX.Element {
} }
<div className='flex w-64' ref={divRef}> <div className='flex w-64' ref={divRef}>
<div className='w-6'> <div className='w-6'>
<ToggleSideBar title={Text({ textId: '@Properties' })} checked={showProperties} onChange={(newValue) => { setShowProperties(newValue); props.onExpandChange(); }} /> <ToggleSideBar
title={Text({ textId: '@Properties' })}
checked={props.selectedExtendedSidebar === ExtendedSidebar.Property}
onClick={() => {
const newValue = props.selectedExtendedSidebar !== ExtendedSidebar.Property
? ExtendedSidebar.Property
: ExtendedSidebar.None;
props.onExpandChange(newValue);
}}
/>
</div> </div>
<List <List
itemCount={containers.length} itemCount={containers.length}
@ -229,10 +237,10 @@ function ElementsListRow(
key={key} key={key}
style={style} style={style}
title={container.properties.warning} title={container.properties.warning}
onClick={() => selectContainer(container.properties.id)} onClick={() => { selectContainer(container.properties.id); }}
onDrop={(event) => HandleOnDrop(event, containers, mainContainer, addContainer)} onDrop={(event) => { HandleOnDrop(event, containers, mainContainer, addContainer); }}
onDragOver={(event) => HandleDragOver(event, mainContainer)} onDragOver={(event) => { HandleDragOver(event, mainContainer); }}
onDragLeave={(event) => HandleDragLeave(event)} onDragLeave={(event) => { HandleDragLeave(event); }}
> >
{verticalBars} {verticalBars}
{text} {text}

View file

@ -4,16 +4,16 @@ import './ToggleSideBar.scss';
interface IToggleSidebarProps { interface IToggleSidebarProps {
title: string title: string
checked: boolean checked: boolean
onChange: (newValue: boolean) => void onClick: () => void
} }
export function ToggleSideBar({ title, checked, onChange }: IToggleSidebarProps): JSX.Element { export function ToggleSideBar({ title, checked, onClick }: IToggleSidebarProps): JSX.Element {
return ( return (
<div className={`${(checked ? 'bg-slate-400 hover:bg-slate-500' : 'bg-slate-300 hover:bg-slate-400')}`}> <div className={`${(checked ? 'bg-slate-400 hover:bg-slate-500' : 'bg-slate-300 hover:bg-slate-400')}`}>
<button <button
className={'w-full py-2'} className={'w-full py-2'}
type='button' type='button'
onClick={() => onChange(!checked)} onClick={onClick}
> >
<p className='text-vertical'>{title} <p className='text-vertical'>{title}
</p> </p>

View file

@ -5,29 +5,29 @@ import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
import { SymbolProperties } from '../SymbolProperties/SymbolProperties'; import { SymbolProperties } from '../SymbolProperties/SymbolProperties';
import { ToggleSideBar } from '../Sidebar/ToggleSideBar/ToggleSideBar'; import { ToggleSideBar } from '../Sidebar/ToggleSideBar/ToggleSideBar';
import { Text } from '../Text/Text'; import { Text } from '../Text/Text';
import { useState } from 'react'; import { ExtendedSidebar } from '../UI/UI';
interface ISymbolsSidebarProps { interface ISymbolsSidebarProps {
selectedSymbolId: string selectedSymbolId: string
symbols: Map<string, ISymbolModel> symbols: Map<string, ISymbolModel>
selectedExtendedSidebar: ExtendedSidebar
onPropertyChange: (key: string, value: string | number | boolean) => void onPropertyChange: (key: string, value: string | number | boolean) => void
selectSymbol: (symbolId: string) => void selectSymbol: (symbolId: string) => void
isExpanded: boolean onExpandChange: (value: ExtendedSidebar) => void
onExpandChange: (isExpanded: boolean) => void
} }
export function SymbolsSidebar(props: ISymbolsSidebarProps): JSX.Element { export function SymbolsSidebar(props: ISymbolsSidebarProps): JSX.Element {
// States // States
const divRef = React.useRef<HTMLDivElement>(null); const divRef = React.useRef<HTMLDivElement>(null);
const height = useSize(divRef)[1]; const height = useSize(divRef)[1];
const [showProperties, setShowProperties] = useState(props.isExpanded);
// Render // Render
const symbols = [...props.symbols.values()]; const symbols = [...props.symbols.values()];
const selectedSymbol = props.symbols.get(props.selectedSymbolId); const selectedSymbol = props.symbols.get(props.selectedSymbolId);
return ( return (
<div className='flex flex-row h-full w-full'> <div className='flex flex-row h-full w-full'>
{showProperties && <div className='flex flex-1 flex-col w-64 border-r-2 border-slate-400'> {props.selectedExtendedSidebar === ExtendedSidebar.Property &&
<div className='flex flex-1 flex-col w-64 border-r-2 border-slate-400'>
{(selectedSymbol == null) && <h1 className={'p-4'}>{Text({ textId: '@NoSymbolSelected' })}</h1>} {(selectedSymbol == null) && <h1 className={'p-4'}>{Text({ textId: '@NoSymbolSelected' })}</h1>}
<SymbolProperties <SymbolProperties
symbol={selectedSymbol} symbol={selectedSymbol}
@ -37,7 +37,15 @@ export function SymbolsSidebar(props: ISymbolsSidebarProps): JSX.Element {
</div>} </div>}
<div className={'flex w-64'} ref={divRef}> <div className={'flex w-64'} ref={divRef}>
<div className='w-6'> <div className='w-6'>
<ToggleSideBar title={Text({ textId: '@Properties' })} checked={showProperties} onChange={(newValue) => { setShowProperties(newValue); props.onExpandChange(newValue); }} /> <ToggleSideBar
title={Text({ textId: '@Properties' })}
checked={props.selectedExtendedSidebar === ExtendedSidebar.Property}
onClick={() => {
const newValue = props.selectedExtendedSidebar !== ExtendedSidebar.Property
? ExtendedSidebar.Property
: ExtendedSidebar.None;
props.onExpandChange(newValue);
}} />
</div> </div>
<List <List
itemCount={symbols.length} itemCount={symbols.length}

View file

@ -1,9 +1,9 @@
import * as React from 'react'; import * as React from 'react';
import { ElementsSideBar } from '../ElementsList/ElementsSideBar'; import { ElementsSidebar } from '../ElementsSidebar/ElementsSidebar';
import { History } from '../History/History'; import { History } from '../History/History';
import { Bar, BAR_WIDTH } from '../Bar/Bar'; import { Bar, BAR_WIDTH } from '../Bar/Bar';
import { Symbols } from '../Symbols/Symbols'; import { Symbols } from '../Symbols/Symbols';
import { SymbolsSidebar } from '../SymbolsList/SymbolsSidebar'; import { SymbolsSidebar } from '../SymbolsSidebar/SymbolsSidebar';
import { type PropertyType } from '../../Enums/PropertyType'; import { type PropertyType } from '../../Enums/PropertyType';
import { Messages } from '../Messages/Messages'; import { Messages } from '../Messages/Messages';
import { Sidebar } from '../Sidebar/Sidebar'; import { Sidebar } from '../Sidebar/Sidebar';
@ -17,8 +17,8 @@ import { FindContainerById } from '../../utils/itertools';
import { type IEditorState } from '../../Interfaces/IEditorState'; import { type IEditorState } from '../../Interfaces/IEditorState';
import { GetCurrentHistoryState } from '../Editor/Editor'; import { GetCurrentHistoryState } from '../Editor/Editor';
import { Text } from '../Text/Text'; import { Text } from '../Text/Text';
import { IReplaceContainer } from '../../Interfaces/IReplaceContainer'; import { type IReplaceContainer } from '../../Interfaces/IReplaceContainer';
import { Dispatch } from 'react'; import { type Dispatch } from 'react';
export interface IUIProps { export interface IUIProps {
editorState: IEditorState editorState: IEditorState
@ -42,14 +42,17 @@ export interface IUIProps {
export enum SidebarType { export enum SidebarType {
None, None,
Components, Components,
ComponentsExpanded,
Symbols, Symbols,
SymbolsExpanded,
History, History,
Messages, Messages,
Settings Settings
} }
export enum ExtendedSidebar {
None,
Property
}
function UseSetOrToggleSidebar( function UseSetOrToggleSidebar(
selectedSidebar: SidebarType, selectedSidebar: SidebarType,
setSelectedSidebar: React.Dispatch<React.SetStateAction<SidebarType>> setSelectedSidebar: React.Dispatch<React.SetStateAction<SidebarType>>
@ -66,6 +69,10 @@ function UseSetOrToggleSidebar(
export function UI({ editorState, replaceContainer, setReplaceContainer, ...methods }: IUIProps): JSX.Element { export function UI({ editorState, replaceContainer, setReplaceContainer, ...methods }: IUIProps): JSX.Element {
const [selectedSidebar, setSelectedSidebar] = React.useState<SidebarType>(SidebarType.Components); const [selectedSidebar, setSelectedSidebar] = React.useState<SidebarType>(SidebarType.Components);
const [
selectedExtendedSidebar,
setSelectedExtendedSidebarType
] = React.useState<ExtendedSidebar>(ExtendedSidebar.None);
const [messages, setMessages] = React.useState<IMessage[]>([]); const [messages, setMessages] = React.useState<IMessage[]>([]);
const current = GetCurrentHistoryState(editorState.history, editorState.historyCurrentStep); const current = GetCurrentHistoryState(editorState.history, editorState.historyCurrentStep);
@ -115,7 +122,7 @@ export function UI({ editorState, replaceContainer, setReplaceContainer, ...meth
replaceContainer={replaceContainer} replaceContainer={replaceContainer}
setReplaceContainer={setReplaceContainer}/>; setReplaceContainer={setReplaceContainer}/>;
rightSidebarTitle = Text({ textId: '@Elements' }); rightSidebarTitle = Text({ textId: '@Elements' });
rightChildren = <ElementsSideBar rightChildren = <ElementsSidebar
containers={current.containers} containers={current.containers}
mainContainer={mainContainer} mainContainer={mainContainer}
symbols={current.symbols} symbols={current.symbols}
@ -123,32 +130,11 @@ export function UI({ editorState, replaceContainer, setReplaceContainer, ...meth
onPropertyChange={methods.onPropertyChange} onPropertyChange={methods.onPropertyChange}
selectContainer={methods.selectContainer} selectContainer={methods.selectContainer}
addContainer={methods.addContainerAt} addContainer={methods.addContainerAt}
isExpanded ={false} selectedExtendedSidebar={selectedExtendedSidebar}
onExpandChange={() => { setOrToggleSidebar(SidebarType.ComponentsExpanded); } } onExpandChange={(value) => { setSelectedExtendedSidebarType(value); } }
/>;
break;
case SidebarType.ComponentsExpanded:
leftSidebarTitle = Text({ textId: '@Components' });
leftChildren = <Components
selectedContainer={selectedContainer}
componentOptions={configuration.AvailableContainers}
categories={configuration.Categories}
buttonOnClick={methods.addOrReplaceContainer}
replaceContainer={replaceContainer}
setReplaceContainer={setReplaceContainer}/>;
rightSidebarTitle = Text({ textId: '@Elements' });
rightChildren = <ElementsSideBar
containers={current.containers}
mainContainer={mainContainer}
symbols={current.symbols}
selectedContainer={selectedContainer}
onPropertyChange={methods.onPropertyChange}
selectContainer={methods.selectContainer}
addContainer={methods.addContainerAt}
isExpanded ={true}
onExpandChange={() => { setOrToggleSidebar(SidebarType.Components); } }
/>; />;
break; break;
case SidebarType.Symbols: case SidebarType.Symbols:
leftSidebarTitle = Text({ textId: '@SymbolsLeft' }); leftSidebarTitle = Text({ textId: '@SymbolsLeft' });
leftChildren = <Symbols leftChildren = <Symbols
@ -161,24 +147,8 @@ export function UI({ editorState, replaceContainer, setReplaceContainer, ...meth
symbols={current.symbols} symbols={current.symbols}
onPropertyChange={methods.onSymbolPropertyChange} onPropertyChange={methods.onSymbolPropertyChange}
selectSymbol={methods.selectSymbol} selectSymbol={methods.selectSymbol}
isExpanded ={false} selectedExtendedSidebar={selectedExtendedSidebar}
onExpandChange={() => { setOrToggleSidebar(SidebarType.SymbolsExpanded); } } onExpandChange={(value) => { setSelectedExtendedSidebarType(value); } }
/>;
break;
case SidebarType.SymbolsExpanded:
leftSidebarTitle = Text({ textId: '@SymbolsLeft' });
leftChildren = <Symbols
componentOptions={configuration.AvailableSymbols}
buttonOnClick={methods.addSymbol}
/>;
rightSidebarTitle = Text({ textId: '@SymbolsRight' });
rightChildren = <SymbolsSidebar
selectedSymbolId={current.selectedSymbolId}
symbols={current.symbols}
onPropertyChange={methods.onSymbolPropertyChange}
selectSymbol={methods.selectSymbol}
isExpanded ={true}
onExpandChange={() => { setOrToggleSidebar(SidebarType.Symbols); }}
/>; />;
break; break;
@ -210,8 +180,10 @@ export function UI({ editorState, replaceContainer, setReplaceContainer, ...meth
} }
const isLeftSidebarOpen = selectedSidebar !== SidebarType.None; const isLeftSidebarOpen = selectedSidebar !== SidebarType.None;
const isRightSidebarOpen = selectedSidebar === SidebarType.Components || selectedSidebar === SidebarType.Symbols; const isRightSidebarOpen = [SidebarType.Components, SidebarType.Symbols]
const isRightSidebarOpenExpanded = selectedSidebar === SidebarType.ComponentsExpanded || selectedSidebar === SidebarType.SymbolsExpanded; .includes(selectedSidebar);
const isRightSidebarOpenExpanded = isRightSidebarOpen &&
selectedExtendedSidebar !== ExtendedSidebar.None;
const isLeftSidebarOpenClasses = new Set<string>([ const isLeftSidebarOpenClasses = new Set<string>([
'left-sidebar', 'left-sidebar',
@ -252,8 +224,8 @@ export function UI({ editorState, replaceContainer, setReplaceContainer, ...meth
} }
const clickRestrictionsClasses = replaceContainer.isReplacing ? 'pointer-events-none opacity-50' : ''; const clickRestrictionsClasses = replaceContainer.isReplacing ? 'pointer-events-none opacity-50' : '';
const isComponentsOpen = selectedSidebar === SidebarType.Components || selectedSidebar === SidebarType.ComponentsExpanded; const isComponentsOpen = selectedSidebar === SidebarType.Components;
const isSymbolsOpen = selectedSidebar === SidebarType.Symbols || selectedSidebar === SidebarType.SymbolsExpanded; const isSymbolsOpen = selectedSidebar === SidebarType.Symbols;
return ( return (
<> <>
@ -265,18 +237,10 @@ export function UI({ editorState, replaceContainer, setReplaceContainer, ...meth
isMessagesOpen={selectedSidebar === SidebarType.Messages} isMessagesOpen={selectedSidebar === SidebarType.Messages}
isSettingsOpen={selectedSidebar === SidebarType.Settings} isSettingsOpen={selectedSidebar === SidebarType.Settings}
toggleComponents={() => { toggleComponents={() => {
if (selectedSidebar === SidebarType.ComponentsExpanded) {
setOrToggleSidebar(SidebarType.ComponentsExpanded);
} else {
setOrToggleSidebar(SidebarType.Components); setOrToggleSidebar(SidebarType.Components);
}
} } } }
toggleSymbols={() => { toggleSymbols={() => {
if (selectedSidebar === SidebarType.SymbolsExpanded) {
setOrToggleSidebar(SidebarType.SymbolsExpanded);
} else {
setOrToggleSidebar(SidebarType.Symbols); setOrToggleSidebar(SidebarType.Symbols);
}
} } } }
toggleTimeline={() => { toggleTimeline={() => {
setOrToggleSidebar(SidebarType.History); setOrToggleSidebar(SidebarType.History);