Implemtation in progress, UIX working , replacing in ContainerOperations.ts working but not properly need fix
This commit is contained in:
parent
62abd3ff03
commit
e789300090
9 changed files with 139 additions and 98 deletions
|
@ -17,6 +17,7 @@ import { BarIcon } from './BarIcon';
|
|||
import { Text } from '../Text/Text';
|
||||
|
||||
interface IBarProps {
|
||||
className: string
|
||||
isComponentsOpen: boolean
|
||||
isSymbolsOpen: boolean
|
||||
isHistoryOpen: boolean
|
||||
|
@ -33,7 +34,7 @@ export const BAR_WIDTH = 64; // 4rem
|
|||
|
||||
export function Bar(props: IBarProps): JSX.Element {
|
||||
return (
|
||||
<div className='bar'>
|
||||
<div className={`bar ${props.className}`}>
|
||||
<BarIcon
|
||||
isActive={props.isComponentsOpen}
|
||||
title={Text({ textId: '@Components' })}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { EyeIcon, EyeSlashIcon } from '@heroicons/react/24/outline';
|
||||
import { EyeIcon, EyeSlashIcon, XCircleIcon } from '@heroicons/react/24/outline';
|
||||
import * as React from 'react';
|
||||
import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
|
||||
import { ICategory } from '../../Interfaces/ICategory';
|
||||
|
@ -6,12 +6,15 @@ import { IContainerModel } from '../../Interfaces/IContainerModel';
|
|||
import { TruncateString } from '../../utils/stringtools';
|
||||
import { Category } from '../Category/Category';
|
||||
import { Text } from '../Text/Text';
|
||||
import { IReplaceContainer } from '../../Interfaces/IReplaceContainer';
|
||||
import { Dispatch } from 'react';
|
||||
|
||||
interface IComponentsProps {
|
||||
selectedContainer: IContainerModel | undefined
|
||||
componentOptions: IAvailableContainer[]
|
||||
categories: ICategory[]
|
||||
replaceableCategoryName: string | undefined
|
||||
replaceContainer: IReplaceContainer
|
||||
setReplaceContainer: Dispatch<React.SetStateAction<IReplaceContainer>>
|
||||
buttonOnClick: (type: string) => void
|
||||
}
|
||||
|
||||
|
@ -63,7 +66,7 @@ export function Components(props: IComponentsProps): JSX.Element {
|
|||
disabled = config.Blacklist?.find(type => type === componentOption.Type) !== undefined ?? false;
|
||||
}
|
||||
|
||||
if (componentOption.Category !== props.replaceableCategoryName) {
|
||||
if (props.replaceContainer.isReplacing && componentOption.Category !== props.replaceContainer.category) {
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
|
@ -101,6 +104,15 @@ export function Components(props: IComponentsProps): JSX.Element {
|
|||
return (
|
||||
<div className='h-full'>
|
||||
<div className='hover:bg-slate-300 h-7 text-right pr-1 pl-1'>
|
||||
{props.replaceContainer.isReplacing && <button
|
||||
onClick={() => {
|
||||
props.setReplaceContainer({ isReplacing: false, id: undefined, category: undefined });
|
||||
}}
|
||||
className='h-full hover:bg-slate-400 rounded-lg p-1'
|
||||
>
|
||||
<XCircleIcon className='heroicon'></XCircleIcon>
|
||||
</button>
|
||||
}
|
||||
<button
|
||||
onClick={() => { setHideDisabled(!hideDisabled); }}
|
||||
className='h-full hover:bg-slate-400 rounded-lg p-1'
|
||||
|
@ -122,4 +134,4 @@ export function Components(props: IComponentsProps): JSX.Element {
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -8,7 +8,8 @@ import Swal from 'sweetalert2';
|
|||
import { PropertyType } from '../../../Enums/PropertyType';
|
||||
import { TransformX, TransformY } from '../../../utils/svg';
|
||||
import { Orientation } from '../../../Enums/Orientation';
|
||||
import { AddContainers, AddContainerToSelectedContainer } from './AddContainer';
|
||||
import { AddContainerToSelectedContainer } from './AddContainer';
|
||||
import { IConfiguration } from '../../../Interfaces/IConfiguration';
|
||||
|
||||
/**
|
||||
* Select a container
|
||||
|
@ -113,64 +114,44 @@ export function DeleteContainer(
|
|||
/**
|
||||
* Replace a container
|
||||
* @param containerId containerId of the container to delete
|
||||
* @param newContainerId
|
||||
* @param configuration
|
||||
* @param fullHistory History of the editor
|
||||
* @param historyCurrentStep Current step
|
||||
* @returns New history
|
||||
*/
|
||||
// export function ReplaceByContainer(
|
||||
// containerId: string,
|
||||
// newContainerId: string,
|
||||
// fullHistory: IHistoryState[],
|
||||
// historyCurrentStep: number
|
||||
// ): IHistoryState[] {
|
||||
// const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
||||
// const current = history[history.length - 1];
|
||||
//
|
||||
//
|
||||
// const containers = structuredClone(current.containers);
|
||||
// const container = FindContainerById(containers, containerId);
|
||||
// if (container === undefined) {
|
||||
// throw new Error(`[ReplaceContainer] Tried to delete a container that is not present in the main container: ${containerId}`);
|
||||
// }
|
||||
// ///
|
||||
// const parent = FindContainerById(containers, container.properties.parentId);
|
||||
// if (parent === undefined || parent === null) {
|
||||
// throw new Error('[ReplaceContainer] Cannot replace a container that does not exists');
|
||||
// }
|
||||
//
|
||||
// const index = parent.children.indexOf(container.properties.id);
|
||||
//
|
||||
// const newHistoryAfterDelete = DeleteContainer(
|
||||
// container.properties.id,
|
||||
// history,
|
||||
// historyCurrentStep
|
||||
// );
|
||||
//
|
||||
// const newContainer = FindContainerById(containers, container.properties.parentId);
|
||||
//
|
||||
// AddContainerToSelectedContainer(
|
||||
// ne,
|
||||
// selected,
|
||||
// configuration,
|
||||
// history,
|
||||
// historyCurrentStep
|
||||
// );
|
||||
//
|
||||
//
|
||||
// /// /
|
||||
//
|
||||
//
|
||||
// history.push({
|
||||
// lastAction: `Replace ${containerId} By InsertnewId`,
|
||||
// mainContainer: current.mainContainer,
|
||||
// containers,
|
||||
// newContainerId,
|
||||
// typeCounters: Object.assign({}, current.typeCounters),
|
||||
// symbols: newSymbols,
|
||||
// selectedSymbolId: current.selectedSymbolId
|
||||
// });
|
||||
// return history;
|
||||
// }
|
||||
export function ReplaceByContainer(
|
||||
containerId: string,
|
||||
newContainerId: string,
|
||||
configuration: IConfiguration,
|
||||
fullHistory: IHistoryState[],
|
||||
historyCurrentStep: number
|
||||
): IHistoryState[] {
|
||||
const history = GetCurrentHistory(fullHistory, historyCurrentStep);
|
||||
const current = history[history.length - 1];
|
||||
|
||||
const historyDelete = DeleteContainer(containerId, fullHistory, historyCurrentStep);
|
||||
const currentDelete = historyDelete[historyDelete.length - 1];
|
||||
const selectedContainer = FindContainerById(currentDelete.containers, currentDelete.selectedContainerId);
|
||||
if (selectedContainer != null) {
|
||||
const historyAdd = AddContainerToSelectedContainer(newContainerId, selectedContainer, configuration, fullHistory, historyCurrentStep);
|
||||
|
||||
const currentAdd = historyAdd[historyAdd.length - 1];
|
||||
|
||||
fullHistory.push({
|
||||
lastAction: `Replace ${containerId} by ${newContainerId}`,
|
||||
mainContainer: currentAdd.mainContainer,
|
||||
containers: currentAdd.containers,
|
||||
selectedContainerId: currentAdd.selectedContainerId,
|
||||
typeCounters: Object.assign({}, currentAdd.typeCounters),
|
||||
symbols: current.symbols,
|
||||
selectedSymbolId: current.selectedSymbolId
|
||||
});
|
||||
|
||||
return fullHistory;
|
||||
}
|
||||
return history;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next container that will be selected
|
||||
|
@ -178,7 +159,7 @@ export function DeleteContainer(
|
|||
* If the selected container is removed, select the sibling after,
|
||||
* If there is no sibling, select the parent,
|
||||
*
|
||||
* @param mainContainerClone Main container
|
||||
* @param containers
|
||||
* @param selectedContainerId Current selected container
|
||||
* @param parent Parent of the selected/deleted container
|
||||
* @param index Index of the selected/deleted container
|
||||
|
@ -190,11 +171,10 @@ function GetSelectedContainerOnDelete(
|
|||
parent: IContainerModel,
|
||||
index: number
|
||||
): string {
|
||||
const newSelectedContainerId = FindContainerById(containers, selectedContainerId)?.properties.id ??
|
||||
parent.children.at(index) ??
|
||||
parent.children.at(index - 1) ??
|
||||
parent.properties.id;
|
||||
return newSelectedContainerId;
|
||||
return FindContainerById(containers, selectedContainerId)?.properties.id ??
|
||||
parent.children.at(index) ??
|
||||
parent.children.at(index - 1) ??
|
||||
parent.properties.id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -220,11 +200,15 @@ function UnlinkContainerFromSymbols(
|
|||
}
|
||||
|
||||
/**
|
||||
* Handled the property change event in the properties form
|
||||
* @param key Property name
|
||||
* @param value New value of the property
|
||||
* @returns void
|
||||
*/
|
||||
* Handled the property change event in the properties form
|
||||
* @param key Property name
|
||||
* @param value New value of the property
|
||||
* @param type
|
||||
* @param selected
|
||||
* @param fullHistory
|
||||
* @param historyCurrentStep
|
||||
* @returns void
|
||||
*/
|
||||
export function OnPropertyChange(
|
||||
key: string,
|
||||
value: string | number | boolean | number[],
|
||||
|
@ -264,6 +248,7 @@ export function OnPropertyChange(
|
|||
|
||||
/**
|
||||
* Sort the parent children by x
|
||||
* @param containers
|
||||
* @param parent The clone used for the sort
|
||||
* @returns void
|
||||
*/
|
||||
|
@ -328,6 +313,7 @@ export function SortChildren(
|
|||
|
||||
/**
|
||||
* Set the container with properties and behaviors (mutate)
|
||||
* @param containers
|
||||
* @param container Container to update
|
||||
* @param key Key of the property to update
|
||||
* @param value Value of the property to update
|
||||
|
|
|
@ -16,6 +16,7 @@ import { AddContainers } from './AddContainer';
|
|||
import { DeleteContainer } from './ContainerOperations';
|
||||
import { DeleteSymbol } from './SymbolOperations';
|
||||
import { Text } from '../../Text/Text';
|
||||
import { IReplaceContainer } from '../../../Interfaces/IReplaceContainer';
|
||||
|
||||
export function InitActions(
|
||||
menuActions: Map<string, IMenuAction[]>,
|
||||
|
@ -23,7 +24,8 @@ export function InitActions(
|
|||
history: IHistoryState[],
|
||||
historyCurrentStep: number,
|
||||
setNewHistory: (newHistory: IHistoryState[]) => void,
|
||||
setHistoryCurrentStep: Dispatch<SetStateAction<number>>
|
||||
setHistoryCurrentStep: Dispatch<SetStateAction<number>>,
|
||||
setIsReplacingContainer: Dispatch<SetStateAction<IReplaceContainer>>
|
||||
): void {
|
||||
menuActions.set(
|
||||
'',
|
||||
|
@ -60,8 +62,14 @@ export function InitActions(
|
|||
title: Text({ textId: '@ReplaceByContainerTitle' }),
|
||||
shortcut: '<kbd>R</kbd>',
|
||||
action: (target: HTMLElement) => {
|
||||
const id = target.id;
|
||||
console.log('replace');
|
||||
const targetContainer = FindContainerById(history[historyCurrentStep].containers, target.id);
|
||||
const targetAvailableContainer = configuration.AvailableContainers.find((availableContainer) => availableContainer.Type === targetContainer?.properties.type);
|
||||
|
||||
if (targetAvailableContainer === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsReplacingContainer({ isReplacing: true, id: target.id, category: targetAvailableContainer.Category });
|
||||
}
|
||||
}, {
|
||||
text: Text({ textId: '@DeleteContainer' }),
|
||||
|
|
|
@ -3,7 +3,7 @@ import './Editor.scss';
|
|||
import { IConfiguration } from '../../Interfaces/IConfiguration';
|
||||
import { IHistoryState } from '../../Interfaces/IHistoryState';
|
||||
import { UI } from '../UI/UI';
|
||||
import { SelectContainer, DeleteContainer, OnPropertyChange } from './Actions/ContainerOperations';
|
||||
import { SelectContainer, DeleteContainer, OnPropertyChange, ReplaceByContainer } from './Actions/ContainerOperations';
|
||||
import { SaveEditorAsJSON, SaveEditorAsSVG } from './Actions/Save';
|
||||
import { OnKey } from './Actions/Shortcuts';
|
||||
import { UseCustomEvents, UseEditorListener } from '../../Events/EditorEvents';
|
||||
|
@ -13,6 +13,7 @@ import { FindContainerById } from '../../utils/itertools';
|
|||
import { Menu } from '../Menu/Menu';
|
||||
import { InitActions } from './Actions/ContextMenuActions';
|
||||
import { AddContainerToSelectedContainer, AddContainer } from './Actions/AddContainer';
|
||||
import { IReplaceContainer } from '../../Interfaces/IReplaceContainer';
|
||||
|
||||
interface IEditorProps {
|
||||
root: Element | Document
|
||||
|
@ -66,6 +67,8 @@ export function Editor(props: IEditorProps): JSX.Element {
|
|||
// States
|
||||
const [history, setHistory] = React.useState<IHistoryState[]>(structuredClone(props.history));
|
||||
const [historyCurrentStep, setHistoryCurrentStep] = React.useState<number>(props.historyCurrentStep);
|
||||
const [replaceContainer, setReplaceContainer] = React.useState<IReplaceContainer>({ isReplacing: false, id: undefined, category: undefined });
|
||||
|
||||
const editorRef = useRef<HTMLDivElement>(null);
|
||||
const setNewHistory = UseNewHistoryState(setHistory, setHistoryCurrentStep);
|
||||
|
||||
|
@ -104,7 +107,8 @@ export function Editor(props: IEditorProps): JSX.Element {
|
|||
history,
|
||||
historyCurrentStep,
|
||||
setNewHistory,
|
||||
setHistoryCurrentStep
|
||||
setHistoryCurrentStep,
|
||||
setReplaceContainer
|
||||
);
|
||||
|
||||
// Render
|
||||
|
@ -113,7 +117,7 @@ export function Editor(props: IEditorProps): JSX.Element {
|
|||
const selected = FindContainerById(current.containers, current.selectedContainerId);
|
||||
|
||||
return (
|
||||
<div ref={editorRef} className="Editor font-sans h-full">
|
||||
<div ref={editorRef} className="Editor font-sans h-full ">
|
||||
<UI
|
||||
editorState={{
|
||||
configuration: props.configuration,
|
||||
|
@ -139,18 +143,29 @@ export function Editor(props: IEditorProps): JSX.Element {
|
|||
history,
|
||||
historyCurrentStep
|
||||
))}
|
||||
addContainer={(type) => {
|
||||
addOrReplaceContainer={(type) => {
|
||||
if (selected === null || selected === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
setNewHistory(AddContainerToSelectedContainer(
|
||||
type,
|
||||
selected,
|
||||
configuration,
|
||||
history,
|
||||
historyCurrentStep
|
||||
));
|
||||
if (replaceContainer.isReplacing && replaceContainer.id !== undefined) {
|
||||
const newHistory = ReplaceByContainer(
|
||||
replaceContainer.id,
|
||||
type,
|
||||
configuration,
|
||||
history,
|
||||
historyCurrentStep
|
||||
);
|
||||
setReplaceContainer({ isReplacing: false, id: undefined, category: undefined });
|
||||
setNewHistory(newHistory);
|
||||
} else {
|
||||
setNewHistory(AddContainerToSelectedContainer(
|
||||
type,
|
||||
selected,
|
||||
configuration,
|
||||
history,
|
||||
historyCurrentStep
|
||||
));
|
||||
}
|
||||
}}
|
||||
addContainerAt={(index, type, parent) => setNewHistory(
|
||||
AddContainer(
|
||||
|
@ -194,9 +209,10 @@ export function Editor(props: IEditorProps): JSX.Element {
|
|||
)}
|
||||
saveEditorAsSVG={() => SaveEditorAsSVG()}
|
||||
loadState={(move) => setHistoryCurrentStep(move)}
|
||||
/>
|
||||
replaceContainer ={replaceContainer} setReplaceContainer={setReplaceContainer}/>
|
||||
<Menu
|
||||
getListener={() => editorRef.current}
|
||||
configuration={configuration}
|
||||
actions={menuActions}
|
||||
className="z-30 transition-opacity rounded bg-slate-200 drop-shadow-xl"
|
||||
/>
|
||||
|
|
|
@ -2,11 +2,13 @@ import useSize from '@react-hook/size';
|
|||
import * as React from 'react';
|
||||
import { IPoint } from '../../Interfaces/IPoint';
|
||||
import { MenuItem } from './MenuItem';
|
||||
import { IConfiguration } from '../../Interfaces/IConfiguration';
|
||||
|
||||
interface IMenuProps {
|
||||
getListener: () => HTMLElement | null
|
||||
actions: Map<string, IMenuAction[]>
|
||||
className?: string
|
||||
configuration: IConfiguration
|
||||
}
|
||||
|
||||
export interface IMenuAction {
|
||||
|
@ -21,6 +23,7 @@ export interface IMenuAction {
|
|||
|
||||
/** function to be called on button click */
|
||||
action: (target: HTMLElement) => void
|
||||
|
||||
}
|
||||
|
||||
function UseMouseEvents(
|
||||
|
@ -139,7 +142,7 @@ function AddClassSpecificActions(
|
|||
onClick={() => action.action(target)} />);
|
||||
});
|
||||
children.push(<hr key={`contextmenu-hr-${count}`} className='border-slate-400' />);
|
||||
};
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,13 +17,15 @@ import { FindContainerById } from '../../utils/itertools';
|
|||
import { IEditorState } from '../../Interfaces/IEditorState';
|
||||
import { GetCurrentHistoryState } from '../Editor/Editor';
|
||||
import { Text } from '../Text/Text';
|
||||
import { IReplaceContainer } from '../../Interfaces/IReplaceContainer';
|
||||
import { Dispatch } from 'react';
|
||||
|
||||
export interface IUIProps {
|
||||
editorState: IEditorState
|
||||
selectContainer: (containerId: string) => void
|
||||
deleteContainer: (containerId: string) => void
|
||||
onPropertyChange: (key: string, value: string | number | boolean | number[], type?: PropertyType) => void
|
||||
addContainer: (type: string) => void
|
||||
addOrReplaceContainer: (type: string) => void
|
||||
addContainerAt: (index: number, type: string, parent: string) => void
|
||||
addSymbol: (type: string) => void
|
||||
onSymbolPropertyChange: (key: string, value: string | number | boolean) => void
|
||||
|
@ -32,6 +34,9 @@ export interface IUIProps {
|
|||
saveEditorAsJSON: () => void
|
||||
saveEditorAsSVG: () => void
|
||||
loadState: (move: number) => void
|
||||
replaceContainer: IReplaceContainer
|
||||
setReplaceContainer: Dispatch<React.SetStateAction<IReplaceContainer>>
|
||||
|
||||
}
|
||||
|
||||
export enum SidebarType {
|
||||
|
@ -57,8 +62,9 @@ function UseSetOrToggleSidebar(
|
|||
};
|
||||
}
|
||||
|
||||
export function UI({ editorState, ...methods }: IUIProps): JSX.Element {
|
||||
export function UI({ editorState, replaceContainer, setReplaceContainer, ...methods }: IUIProps): JSX.Element {
|
||||
const [selectedSidebar, setSelectedSidebar] = React.useState<SidebarType>(SidebarType.Components);
|
||||
|
||||
const [messages, setMessages] = React.useState<IMessage[]>([]);
|
||||
const current = GetCurrentHistoryState(editorState.history, editorState.historyCurrentStep);
|
||||
const configuration = editorState.configuration;
|
||||
|
@ -98,15 +104,13 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element {
|
|||
case SidebarType.Components:
|
||||
leftSidebarTitle = Text({ textId: '@Components' });
|
||||
|
||||
const AllowedReplaceCategory = undefined;
|
||||
|
||||
leftChildren = <Components
|
||||
selectedContainer={selectedContainer}
|
||||
componentOptions={configuration.AvailableContainers}
|
||||
categories={configuration.Categories}
|
||||
buttonOnClick={methods.addContainer}
|
||||
replaceableCategoryName={AllowedReplaceCategory}
|
||||
/>;
|
||||
buttonOnClick={methods.addOrReplaceContainer}
|
||||
replaceContainer={replaceContainer}
|
||||
setReplaceContainer={setReplaceContainer}/>;
|
||||
rightSidebarTitle = Text({ textId: '@Elements' });
|
||||
rightChildren = <ElementsList
|
||||
containers={current.containers}
|
||||
|
@ -187,9 +191,12 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element {
|
|||
isLeftSidebarOpenClasses.add('left-sidebar-single');
|
||||
}
|
||||
|
||||
const clickRestrictionsClasses = replaceContainer.isReplacing ? 'pointer-events-none opacity-50' : '';
|
||||
|
||||
return (
|
||||
<>
|
||||
<Bar
|
||||
className={clickRestrictionsClasses}
|
||||
isComponentsOpen={selectedSidebar === SidebarType.Components}
|
||||
isSymbolsOpen={selectedSidebar === SidebarType.Symbols}
|
||||
isHistoryOpen={selectedSidebar === SidebarType.History}
|
||||
|
@ -218,6 +225,7 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element {
|
|||
{ leftChildren }
|
||||
</Sidebar>
|
||||
<Viewer
|
||||
className={clickRestrictionsClasses}
|
||||
isLeftSidebarOpen={isLeftSidebarOpen}
|
||||
isRightSidebarOpen={isRightSidebarOpen}
|
||||
current={current}
|
||||
|
@ -225,7 +233,7 @@ export function UI({ editorState, ...methods }: IUIProps): JSX.Element {
|
|||
selectContainer={methods.selectContainer}
|
||||
/>
|
||||
<Sidebar
|
||||
className={`right-sidebar ${isRightSidebarOpenClasses}`}
|
||||
className={`right-sidebar ${isRightSidebarOpenClasses} ${clickRestrictionsClasses}`}
|
||||
title={rightSidebarTitle}
|
||||
>
|
||||
{ rightChildren }
|
||||
|
|
|
@ -12,6 +12,7 @@ import { SVG } from '../SVG/SVG';
|
|||
import { RenderSymbol } from '../Canvas/Symbol';
|
||||
|
||||
interface IViewerProps {
|
||||
className: string
|
||||
isLeftSidebarOpen: boolean
|
||||
isRightSidebarOpen: boolean
|
||||
current: IHistoryState
|
||||
|
@ -73,6 +74,7 @@ function UseSVGAutoResizerOnSidebar(
|
|||
}
|
||||
|
||||
export function Viewer({
|
||||
className,
|
||||
isLeftSidebarOpen, isRightSidebarOpen,
|
||||
current,
|
||||
selectedContainer,
|
||||
|
@ -160,7 +162,7 @@ export function Viewer({
|
|||
return (
|
||||
<Canvas
|
||||
draw={Draw}
|
||||
className='ml-16'
|
||||
className={`ml-16 ${className}`}
|
||||
width={window.innerWidth - BAR_WIDTH}
|
||||
height={window.innerHeight}
|
||||
/>
|
||||
|
@ -169,7 +171,7 @@ export function Viewer({
|
|||
|
||||
return (
|
||||
<SVG
|
||||
className={marginClasses}
|
||||
className={`${marginClasses} ${className}`}
|
||||
viewerWidth={viewer.viewerWidth}
|
||||
viewerHeight={viewer.viewerHeight}
|
||||
width={mainContainer.properties.width}
|
||||
|
|
5
src/Interfaces/IReplaceContainer.ts
Normal file
5
src/Interfaces/IReplaceContainer.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
export interface IReplaceContainer {
|
||||
id: string | undefined
|
||||
isReplacing: boolean
|
||||
category: string | undefined
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue