diff --git a/src/Components/SVG/Elements/Selector/Selector.scss b/src/Components/SVG/Elements/Selector.scss similarity index 100% rename from src/Components/SVG/Elements/Selector/Selector.scss rename to src/Components/SVG/Elements/Selector.scss diff --git a/src/Components/SVG/Elements/Selector/Selector.tsx b/src/Components/SVG/Elements/SelectorContainer/SelectorContainer.tsx similarity index 88% rename from src/Components/SVG/Elements/Selector/Selector.tsx rename to src/Components/SVG/Elements/SelectorContainer/SelectorContainer.tsx index c7baf92..c85f2b3 100644 --- a/src/Components/SVG/Elements/Selector/Selector.tsx +++ b/src/Components/SVG/Elements/SelectorContainer/SelectorContainer.tsx @@ -1,17 +1,17 @@ -import './Selector.scss'; +import '../Selector.scss'; import * as React from 'react'; -import { IContainerModel } from '../../../../Interfaces/IContainerModel'; +import { type IContainerModel } from '../../../../Interfaces/IContainerModel'; import { SHOW_SELECTOR_TEXT } from '../../../../utils/default'; import { GetAbsolutePosition } from '../../../../utils/itertools'; import { RemoveMargin } from '../../../../utils/svg'; -interface ISelectorProps { +interface ISelectorContainerProps { containers: Map selected?: IContainerModel scale?: number } -export function Selector(props: ISelectorProps): JSX.Element { +export function SelectorContainer(props: ISelectorContainerProps): JSX.Element { if (props.selected === undefined || props.selected === null) { return ( diff --git a/src/Components/SVG/Elements/SelectorSymbol/SelectorSymbol.tsx b/src/Components/SVG/Elements/SelectorSymbol/SelectorSymbol.tsx new file mode 100644 index 0000000..2cdce3b --- /dev/null +++ b/src/Components/SVG/Elements/SelectorSymbol/SelectorSymbol.tsx @@ -0,0 +1,65 @@ +import '../Selector.scss'; +import * as React from 'react'; +import { SHOW_SELECTOR_TEXT, SYMBOL_MARGIN } from '../../../../utils/default'; +import { type ISymbolModel } from '../../../../Interfaces/ISymbolModel'; + +interface ISelectorSymbolProps { + symbols: Map + selected?: ISymbolModel + scale?: number +} + +export function SelectorSymbol(props: ISelectorSymbolProps): JSX.Element { + if (props.selected === undefined || props.selected === null) { + return ( + + + ); + } + + const scale = (props.scale ?? 1); + const [width, height] = [ + props.selected.width, + props.selected.height / scale + ]; + + const [x, y] = [props.selected.x, -SYMBOL_MARGIN - height]; + + const xText = x + width / 2; + const yText = y + height / 2; + + const style: React.CSSProperties = { + stroke: '#3B82F6', + strokeWidth: 4 / scale, + fillOpacity: 0, + transitionProperty: 'all', + transitionTimingFunction: 'cubic-bezier(0.4, 0, 0.2, 1)', + transitionDuration: '150ms', + animation: 'fadein 750ms ease-in alternate infinite' + }; + + return ( + <> + + + {SHOW_SELECTOR_TEXT + ? + {props.selected.displayedText} + + : null} + + ); +} diff --git a/src/Components/SVG/SVG.tsx b/src/Components/SVG/SVG.tsx index cdb11de..738a0da 100644 --- a/src/Components/SVG/SVG.tsx +++ b/src/Components/SVG/SVG.tsx @@ -1,13 +1,14 @@ import * as React from 'react'; -import { ReactSVGPanZoom, Tool, TOOL_PAN, Value } from 'react-svg-pan-zoom'; +import { ReactSVGPanZoom, type Tool, TOOL_PAN, type Value } from 'react-svg-pan-zoom'; import { Container } from './Elements/Container'; -import { IContainerModel } from '../../Interfaces/IContainerModel'; -import { Selector } from './Elements/Selector/Selector'; +import { type IContainerModel } from '../../Interfaces/IContainerModel'; +import { SelectorContainer } from './Elements/SelectorContainer/SelectorContainer'; import { DepthDimensionLayer } from './Elements/DepthDimensionLayer'; import { MAX_FRAMERATE, SHOW_DIMENSIONS_PER_DEPTH } from '../../utils/default'; import { SymbolLayer } from './Elements/SymbolLayer'; -import { ISymbolModel } from '../../Interfaces/ISymbolModel'; +import { type ISymbolModel } from '../../Interfaces/ISymbolModel'; import { DimensionLayer } from './Elements/DimensionLayer'; +import { SelectorSymbol } from './Elements/SelectorSymbol/SelectorSymbol'; interface ISVGProps { className?: string @@ -17,9 +18,12 @@ interface ISVGProps { height: number containers: Map children: IContainerModel - selected?: IContainerModel + selectedContainer?: IContainerModel symbols: Map + selectedSymbol?: ISymbolModel selectContainer: (containerId: string) => void + isComponentsOpen: boolean + isSymbolsOpen: boolean } export const ID = 'svg'; @@ -49,8 +53,7 @@ export function SVG(props: ISVGProps): JSX.Element { xmlns }; - let children: React.ReactNode | React.ReactNode[] = []; - children = - {/* leave this at the end so it can be removed during the svg export */} + {/* leave this at the end so it can be removed during the svg export */} + { props.isComponentsOpen ? : null } + { props.isSymbolsOpen ? : null } diff --git a/src/Components/SymbolsList/SymbolsSidebar.tsx b/src/Components/SymbolsList/SymbolsSidebar.tsx index a43e8ae..300dcf9 100644 --- a/src/Components/SymbolsList/SymbolsSidebar.tsx +++ b/src/Components/SymbolsList/SymbolsSidebar.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import useSize from '@react-hook/size'; import { FixedSizeList as List } from 'react-window'; -import { ISymbolModel } from '../../Interfaces/ISymbolModel'; +import { type ISymbolModel } from '../../Interfaces/ISymbolModel'; import { SymbolProperties } from '../SymbolProperties/SymbolProperties'; import { ToggleSideBar } from '../Sidebar/ToggleSideBar/ToggleSideBar'; import { Text } from '../Text/Text'; @@ -23,28 +23,7 @@ export function SymbolsSidebar(props: ISymbolsSidebarProps): JSX.Element { const [showProperties, setShowProperties] = useState(props.isExpanded); // Render const symbols = [...props.symbols.values()]; - function Row({ index, style }: { index: number, style: React.CSSProperties }): JSX.Element { - const symbol = symbols[index]; - const key = symbol.id; - const text = symbol.displayedText; - const selectedClass: string = props.selectedSymbolId !== '' && - props.selectedSymbolId === symbol.id - ? 'border-l-4 bg-slate-400/60 hover:bg-slate-400' - : 'bg-slate-300/60 hover:bg-slate-300'; - return ( - - ); - } const selectedSymbol = props.symbols.get(props.selectedSymbolId); return (
@@ -71,4 +50,27 @@ export function SymbolsSidebar(props: ISymbolsSidebarProps): JSX.Element {
); + + function Row({ index, style }: { index: number, style: React.CSSProperties }): JSX.Element { + const symbol = symbols[index]; + const key = symbol.id; + const text = symbol.displayedText; + const selectedClass: string = props.selectedSymbolId !== '' && + props.selectedSymbolId === symbol.id + ? 'border-l-4 bg-slate-400/60 hover:bg-slate-400' + : 'bg-slate-300/60 hover:bg-slate-300'; + + return ( + + ); + } } diff --git a/src/Components/UI/UI.tsx b/src/Components/UI/UI.tsx index f85b63c..01d5407 100644 --- a/src/Components/UI/UI.tsx +++ b/src/Components/UI/UI.tsx @@ -4,17 +4,17 @@ import { History } from '../History/History'; import { Bar, BAR_WIDTH } from '../Bar/Bar'; import { Symbols } from '../Symbols/Symbols'; import { SymbolsSidebar } from '../SymbolsList/SymbolsSidebar'; -import { PropertyType } from '../../Enums/PropertyType'; +import { type PropertyType } from '../../Enums/PropertyType'; import { Messages } from '../Messages/Messages'; import { Sidebar } from '../Sidebar/Sidebar'; import { Components } from '../Components/Components'; import { Viewer } from '../Viewer/Viewer'; import { Settings } from '../Settings/Settings'; -import { IMessage } from '../../Interfaces/IMessage'; +import { type IMessage } from '../../Interfaces/IMessage'; import { DISABLE_API } from '../../utils/default'; import { UseWorker, UseAsync } from './UseWorker'; import { FindContainerById } from '../../utils/itertools'; -import { IEditorState } from '../../Interfaces/IEditorState'; +import { type IEditorState } from '../../Interfaces/IEditorState'; import { GetCurrentHistoryState } from '../Editor/Editor'; import { Text } from '../Text/Text'; @@ -96,6 +96,7 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element { } const selectedContainer = FindContainerById(current.containers, current.selectedContainerId); + const selectedSymbol = current.symbols.get(current.selectedSymbolId); switch (selectedSidebar) { case SidebarType.Components: @@ -116,7 +117,7 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element { selectContainer={methods.selectContainer} addContainer={methods.addContainerAt} isExpanded ={false} - onExpandChange={() => setOrToggleSidebar(SidebarType.ComponentsExpanded) } + onExpandChange={() => { setOrToggleSidebar(SidebarType.ComponentsExpanded); } } />; break; case SidebarType.ComponentsExpanded: @@ -137,7 +138,7 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element { selectContainer={methods.selectContainer} addContainer={methods.addContainerAt} isExpanded ={true} - onExpandChange={() => setOrToggleSidebar(SidebarType.Components) } + onExpandChange={() => { setOrToggleSidebar(SidebarType.Components); } } />; break; case SidebarType.Symbols: @@ -153,7 +154,7 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element { onPropertyChange={methods.onSymbolPropertyChange} selectSymbol={methods.selectSymbol} isExpanded ={false} - onExpandChange={() => setOrToggleSidebar(SidebarType.SymbolsExpanded) } + onExpandChange={() => { setOrToggleSidebar(SidebarType.SymbolsExpanded); } } />; break; case SidebarType.SymbolsExpanded: @@ -169,7 +170,7 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element { onPropertyChange={methods.onSymbolPropertyChange} selectSymbol={methods.selectSymbol} isExpanded ={true} - onExpandChange={() => setOrToggleSidebar(SidebarType.Symbols)} + onExpandChange={() => { setOrToggleSidebar(SidebarType.Symbols); }} />; break; @@ -187,7 +188,7 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element { leftChildren = setMessages([])} + clearMessage={() => { setMessages([]); }} />; break; @@ -242,11 +243,14 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element { isLeftSidebarOpenClasses.add('left-sidebar-single'); } + const isComponentsOpen = selectedSidebar === SidebarType.Components || selectedSidebar === SidebarType.ComponentsExpanded; + const isSymbolsOpen = selectedSidebar === SidebarType.Symbols || selectedSidebar === SidebarType.SymbolsExpanded; + return ( <> void + selectedSymbol: ISymbolModel | undefined margin: number + isComponentsOpen: boolean + isSymbolsOpen: boolean } export function Viewer({ @@ -25,7 +29,10 @@ export function Viewer({ current, selectedContainer, selectContainer, - margin + selectedSymbol, + margin, + isComponentsOpen, + isSymbolsOpen }: IViewerProps): JSX.Element { function computeWidth(margin: number): number { return window.innerWidth - (window.innerWidth < 768 ? BAR_WIDTH : margin); @@ -134,11 +141,13 @@ export function Viewer({ width={mainContainer.properties.width} height={mainContainer.properties.height} containers={current.containers} - selected={selectedContainer} + selectedContainer={selectedContainer} symbols={current.symbols} + selectedSymbol={selectedSymbol} selectContainer={selectContainer} + isComponentsOpen={isComponentsOpen} + isSymbolsOpen={isSymbolsOpen} > - {mainContainer} );