svg-layout-designer-react/src/Components/UI/UI.tsx
Eric Nguyen 8b8d88f885 Merged PR 162: Implement symbols and other stuff (see desc)
Implement symbols
- Add, Remove, Select Container
- Form
- Link with container
- Symbol behavior application to container (move to x with xpositionreference)

Important changes
- Remove SelectedContainer from HistoryState, meaning that it will be slower for each load but will be faster for each operations* (SetHistory, SelectContainer, DeleteContainer, SymbolOperations)
- ElementsSidebar now opens with isSidebarOpen meaning that both sidebar will open on toggle
- Moved camelize, transformX, restoreX to different modules (stringtools.ts, svg.ts)
2022-08-22 13:58:32 +00:00

134 lines
5 KiB
TypeScript

import * as React from 'react';
import { ElementsSidebar } from '../ElementsSidebar/ElementsSidebar';
import { Sidebar } from '../Sidebar/Sidebar';
import { History } from '../History/History';
import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
import { IContainerModel } from '../../Interfaces/IContainerModel';
import { IHistoryState } from '../../Interfaces/IHistoryState';
import { PhotographIcon, UploadIcon } from '@heroicons/react/outline';
import { FloatingButton } from '../FloatingButton/FloatingButton';
import { Bar } from '../Bar/Bar';
import { IAvailableSymbol } from '../../Interfaces/IAvailableSymbol';
import { Symbols } from '../Symbols/Symbols';
import { SymbolsSidebar } from '../SymbolsSidebar/SymbolsSidebar';
interface IUIProps {
SelectedContainer: IContainerModel | undefined
current: IHistoryState
history: IHistoryState[]
historyCurrentStep: number
AvailableContainers: IAvailableContainer[]
AvailableSymbols: IAvailableSymbol[]
SelectContainer: (containerId: string) => void
DeleteContainer: (containerId: string) => void
OnPropertyChange: (key: string, value: string | number | boolean, isStyle?: boolean) => void
OnPropertiesSubmit: (event: React.FormEvent<HTMLFormElement>) => void
AddContainerToSelectedContainer: (type: string) => void
AddContainer: (index: number, type: string, parentId: string) => void
AddSymbol: (type: string) => void
OnSymbolPropertyChange: (key: string, value: string | number | boolean) => void
SelectSymbol: (symbolId: string) => void
DeleteSymbol: (symbolId: string) => void
SaveEditorAsJSON: () => void
SaveEditorAsSVG: () => void
LoadState: (move: number) => void
}
function CloseOtherSidebars(
setIsSidebarOpen: React.Dispatch<React.SetStateAction<boolean>>,
setIsSymbolsOpen: React.Dispatch<React.SetStateAction<boolean>>
): void {
setIsSidebarOpen(false);
setIsSymbolsOpen(false);
}
export const UI: React.FunctionComponent<IUIProps> = (props: IUIProps) => {
const [isSidebarOpen, setIsSidebarOpen] = React.useState(true);
const [isSymbolsOpen, setIsSymbolsOpen] = React.useState(false);
const [isHistoryOpen, setIsHistoryOpen] = React.useState(false);
let buttonRightOffsetClasses = 'right-12';
if (isSidebarOpen || isHistoryOpen) {
buttonRightOffsetClasses = 'right-72';
}
if (isHistoryOpen && isSidebarOpen) {
buttonRightOffsetClasses = 'right-[544px]';
}
return (
<>
<Bar
isSidebarOpen={isSidebarOpen}
isSymbolsOpen={isSymbolsOpen}
isElementsSidebarOpen={isSidebarOpen}
isHistoryOpen={isHistoryOpen}
ToggleSidebar={() => {
CloseOtherSidebars(setIsSidebarOpen, setIsSymbolsOpen);
setIsSidebarOpen(!isSidebarOpen);
}}
ToggleSymbols={() => {
CloseOtherSidebars(setIsSidebarOpen, setIsSymbolsOpen);
setIsSymbolsOpen(!isSymbolsOpen);
}}
ToggleTimeline={() => setIsHistoryOpen(!isHistoryOpen)}
/>
<Sidebar
componentOptions={props.AvailableContainers}
isOpen={isSidebarOpen}
buttonOnClick={props.AddContainerToSelectedContainer}
/>
<Symbols
componentOptions={props.AvailableSymbols}
isOpen={isSymbolsOpen}
buttonOnClick={props.AddSymbol}
/>
<ElementsSidebar
MainContainer={props.current.MainContainer}
symbols={props.current.Symbols}
SelectedContainer={props.SelectedContainer}
isOpen={isSidebarOpen}
isHistoryOpen={isHistoryOpen}
OnPropertyChange={props.OnPropertyChange}
OnPropertiesSubmit={props.OnPropertiesSubmit}
SelectContainer={props.SelectContainer}
DeleteContainer={props.DeleteContainer}
AddContainer={props.AddContainer}
/>
<SymbolsSidebar
SelectedSymbolId={props.current.SelectedSymbolId}
symbols={props.current.Symbols}
isOpen={isSymbolsOpen}
isHistoryOpen={isHistoryOpen}
OnPropertyChange={props.OnSymbolPropertyChange}
SelectSymbol={props.SelectSymbol}
DeleteSymbol={props.DeleteSymbol}
/>
<History
history={props.history}
historyCurrentStep={props.historyCurrentStep}
isOpen={isHistoryOpen}
jumpTo={props.LoadState}
/>
<FloatingButton className={`fixed z-10 flex flex-col gap-2 items-center bottom-40 ${buttonRightOffsetClasses}`}>
<button
className={'transition-all w-10 h-10 p-2 align-middle items-center justify-center rounded-full bg-blue-500 hover:bg-blue-800'}
title='Export as JSON'
onClick={props.SaveEditorAsJSON}
>
<UploadIcon className="heroicon text-white" />
</button>
<button
className={'transition-all w-10 h-10 p-2 align-middle items-center justify-center rounded-full bg-blue-500 hover:bg-blue-800'}
title='Export as SVG'
onClick={props.SaveEditorAsSVG}
>
<PhotographIcon className="heroicon text-white" />
</button>
</FloatingButton>
</>
);
};
export default UI;