Fix eslint errors

This commit is contained in:
Eric NGUYEN 2023-02-23 13:54:38 +01:00
parent 5b3ab651e6
commit 4e41fda93a
87 changed files with 1003 additions and 702 deletions

View file

@ -2,14 +2,14 @@
import { describe, it, expect } from 'vitest';
import { AddMethod } from '../../Enums/AddMethod';
import { PositionReference } from '../../Enums/PositionReference';
import { IAction } from '../../Interfaces/IAction';
import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
import { IAvailableSymbol } from '../../Interfaces/IAvailableSymbol';
import { ICategory } from '../../Interfaces/ICategory';
import { IConfiguration } from '../../Interfaces/IConfiguration';
import { IContainerModel, ContainerModel } from '../../Interfaces/IContainerModel';
import { IHistoryState } from '../../Interfaces/IHistoryState';
import { IPattern } from '../../Interfaces/IPattern';
import { type IAction } from '../../Interfaces/IAction';
import { type IAvailableContainer } from '../../Interfaces/IAvailableContainer';
import { type IAvailableSymbol } from '../../Interfaces/IAvailableSymbol';
import { type ICategory } from '../../Interfaces/ICategory';
import { type IConfiguration } from '../../Interfaces/IConfiguration';
import { type IContainerModel, ContainerModel } from '../../Interfaces/IContainerModel';
import { type IHistoryState } from '../../Interfaces/IHistoryState';
import { type IPattern } from '../../Interfaces/IPattern';
import { DEFAULT_DIMENSION_OPTION, DEFAULT_MAINCONTAINER_PROPS, GetDefaultContainerProps } from '../../utils/default';
import { FetchConfiguration } from './api';
@ -95,9 +95,7 @@ describe.concurrent('Models test suite', () => {
expect(res4).toBe(true);
});
const mainContainer = new ContainerModel(
DEFAULT_MAINCONTAINER_PROPS
);
const mainContainer = new ContainerModel(DEFAULT_MAINCONTAINER_PROPS);
const containers = new Map<string, IContainerModel>();
const historyState: IHistoryState = {
@ -244,7 +242,12 @@ describe.concurrent('Models test suite', () => {
'container',
0,
null,
0, 0, 0, 0, availableContainerModel);
0,
0,
0,
0,
availableContainerModel
);
it('ContainerModel', async() => {
const model: IContainerModel = {

View file

@ -1,6 +1,6 @@
import { IConfiguration } from '../../Interfaces/IConfiguration';
import { ISetContainerListRequest } from '../../Interfaces/ISetContainerListRequest';
import { ISetContainerListResponse } from '../../Interfaces/ISetContainerListResponse';
import { type IConfiguration } from '../../Interfaces/IConfiguration';
import { type ISetContainerListRequest } from '../../Interfaces/ISetContainerListRequest';
import { type ISetContainerListResponse } from '../../Interfaces/ISetContainerListResponse';
import { GetCircularReplacer } from '../../utils/saveload';
/**
@ -9,16 +9,14 @@ import { GetCircularReplacer } from '../../utils/saveload';
*/
export async function FetchConfiguration(): Promise<IConfiguration> {
const url = import.meta.env.VITE_API_FETCH_URL;
// The test library cannot use the Fetch API
// @ts-expect-error
// @ts-expect-error The test library cannot use the Fetch API
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (window.fetch) {
return await fetch(url, {
method: 'POST'
})
.then(async(response) =>
await response.json()
) as IConfiguration;
await response.json()) as IConfiguration;
}
return await new Promise((resolve) => {
const xhr = new XMLHttpRequest();
@ -33,11 +31,13 @@ export async function FetchConfiguration(): Promise<IConfiguration> {
});
}
export async function SetContainerList(request: ISetContainerListRequest, configurationUrl?: string): Promise<ISetContainerListResponse> {
export async function SetContainerList(
request: ISetContainerListRequest,
configurationUrl?: string
): Promise<ISetContainerListResponse> {
const url = configurationUrl ?? import.meta.env.VITE_API_SET_CONTAINER_LIST_URL;
const dataParsed = JSON.stringify(request, GetCircularReplacer());
// The test library cannot use the Fetch API
// @ts-expect-error
// @ts-expect-error The test library cannot use the Fetch API
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
if (window.fetch) {
return await fetch(url, {
@ -49,8 +49,7 @@ export async function SetContainerList(request: ISetContainerListRequest, config
body: dataParsed
})
.then(async(response) =>
await response.json()
) as ISetContainerListResponse;
await response.json()) as ISetContainerListResponse;
}
return await new Promise((resolve) => {
const xhr = new XMLHttpRequest();

View file

@ -1,6 +1,6 @@
import { Dispatch, SetStateAction } from 'react';
import { type Dispatch, type SetStateAction } from 'react';
import { AppState } from '../../../Enums/AppState';
import { IEditorState } from '../../../Interfaces/IEditorState';
import { type IEditorState } from '../../../Interfaces/IEditorState';
import { Revive } from '../../../utils/saveload';
export function LoadState(

View file

@ -1,10 +1,10 @@
import { Dispatch, SetStateAction } from 'react';
import { IConfiguration } from '../../../Interfaces/IConfiguration';
import { type Dispatch, type SetStateAction } from 'react';
import { type IConfiguration } from '../../../Interfaces/IConfiguration';
import { FetchConfiguration } from '../../API/api';
import { IEditorState } from '../../../Interfaces/IEditorState';
import { LoadState } from './Load';
import { type IEditorState } from '../../../Interfaces/IEditorState';
import { DISABLE_API, GetDefaultEditorState } from '../../../utils/default';
import { AppState } from '../../../Enums/AppState';
import { type AppState } from '../../../Enums/AppState';
import { LoadState } from './Load';
export function NewEditor(
editorState: IEditorState,

View file

@ -2,16 +2,14 @@ import * as React from 'react';
import { beforeEach, describe, it } from 'vitest';
import { AppState } from '../../Enums/AppState';
import { FAST_BOOT } from '../../utils/default';
import { fireEvent, render, RenderResult } from '../../utils/test-utils';
import { fireEvent, render, type RenderResult } from '../../utils/test-utils';
import { App } from './App';
describe.concurrent('App', () => {
let app: RenderResult;
beforeEach(() => {
app = render(
<App root={document} />
);
app = render(<App root={document} />);
});
it('New editor', async() => {

View file

@ -1,15 +1,15 @@
import React, { Dispatch, SetStateAction, useContext, useEffect, useRef, useState } from 'react';
import React, { type Dispatch, type SetStateAction, useContext, useEffect, useRef, useState } from 'react';
import { UseCustomEvents } from '../../Events/AppEvents';
import { MainMenu } from '../MainMenu/MainMenu';
import { ContainerModel, IContainerModel } from '../../Interfaces/IContainerModel';
import { ContainerModel, type IContainerModel } from '../../Interfaces/IContainerModel';
import { Editor } from '../Editor/Editor';
import { IEditorState } from '../../Interfaces/IEditorState';
import { LoadState } from './Actions/Load';
import { LoadEditor, NewEditor } from './Actions/MenuActions';
import { type IEditorState } from '../../Interfaces/IEditorState';
import { DEFAULT_CONFIG, DEFAULT_MAINCONTAINER_PROPS, FAST_BOOT } from '../../utils/default';
import { AppState } from '../../Enums/AppState';
import { Loader } from '../Loader/Loader';
import { LanguageContext } from '../LanguageProvider/LanguageProvider';
import { LoadEditor, NewEditor } from './Actions/MenuActions';
import { LoadState } from './Actions/Load';
// App will never have props
// eslint-disable-next-line @typescript-eslint/no-empty-interface
@ -49,9 +49,7 @@ export function App(props: IAppProps): JSX.Element {
const appRef = useRef<HTMLDivElement>(null);
const languageContext = useContext(LanguageContext);
const defaultMainContainer = new ContainerModel(
DEFAULT_MAINCONTAINER_PROPS
);
const defaultMainContainer = new ContainerModel(DEFAULT_MAINCONTAINER_PROPS);
const containers = new Map<string, IContainerModel>();
containers.set(defaultMainContainer.properties.id, defaultMainContainer);
@ -116,15 +114,17 @@ export function App(props: IAppProps): JSX.Element {
setAppState(AppState.Loading);
NewEditor(
editorState,
(newEditor) => setEditorState(newEditor),
() => setAppState(AppState.Loaded)
(newEditor) => { setEditorState(newEditor); },
() => { setAppState(AppState.Loaded); }
);
}}
loadEditor={(files: FileList | null) => {
LoadEditor(
files,
setEditorState,
setAppState
);
}}
loadEditor={(files: FileList | null) => LoadEditor(
files,
setEditorState,
setAppState
)}
/>
</div>
);

View file

@ -13,8 +13,8 @@ import {
EnvelopeIcon as EnvolopeIconS,
Cog8ToothIcon as Cog8ToothIconS
} from '@heroicons/react/24/solid';
import { BarIcon } from './BarIcon';
import { Text } from '../Text/Text';
import { BarIcon } from './BarIcon';
interface IBarProps {
className: string
@ -38,7 +38,7 @@ export function Bar(props: IBarProps): JSX.Element {
<BarIcon
isActive={props.isComponentsOpen}
title={Text({ textId: '@Components' })}
onClick={() => props.toggleComponents()}>
onClick={() => { props.toggleComponents(); }}>
{
props.isComponentsOpen
? <CubeIconS className='heroicon' />
@ -48,7 +48,7 @@ export function Bar(props: IBarProps): JSX.Element {
<BarIcon
isActive={props.isSymbolsOpen}
title={Text({ textId: '@Symbols' })}
onClick={() => props.toggleSymbols()}>
onClick={() => { props.toggleSymbols(); }}>
{
props.isSymbolsOpen
? <LinkIconS className='heroicon' />
@ -58,7 +58,7 @@ export function Bar(props: IBarProps): JSX.Element {
<BarIcon
isActive={props.isMessagesOpen}
title={Text({ textId: '@Messages' })}
onClick={() => props.toggleMessages()}>
onClick={() => { props.toggleMessages(); }}>
{
props.isMessagesOpen
? <EnvolopeIconS className='heroicon' />
@ -69,7 +69,7 @@ export function Bar(props: IBarProps): JSX.Element {
<BarIcon
isActive={props.isHistoryOpen}
title={Text({ textId: '@Timeline' })}
onClick={() => props.toggleTimeline()}>
onClick={() => { props.toggleTimeline(); }}>
{
props.isHistoryOpen
? <ClockIconS className='heroicon' />
@ -79,7 +79,7 @@ export function Bar(props: IBarProps): JSX.Element {
<BarIcon
isActive={props.isSettingsOpen}
title={Text({ textId: '@Settings' })}
onClick={() => props.toggleSettings()}>
onClick={() => { props.toggleSettings(); }}>
{
props.isSettingsOpen
? <Cog8ToothIconS className='heroicon' />

View file

@ -8,12 +8,14 @@ interface IBarIconProps {
}
export function BarIcon(props: IBarIconProps): JSX.Element {
const isActiveClasses = props.isActive ? 'border-l-4 border-blue-500 bg-slate-200' : '';
const isActiveClasses = props.isActive
? 'border-l-4 border-blue-500 bg-slate-200'
: '';
return (
<button type="button"
className={`bar-btn group ${isActiveClasses}`}
title={props.title}
onClick={() => props.onClick()}
onClick={() => { props.onClick(); }}
>
<span className='sidebar-tooltip group-hover:scale-100'>{props.title}</span>
{props.children}

View file

@ -48,7 +48,12 @@ function Draw(
ctx,
mainContainer,
containers,
leftDim, bottomDim, topDim, rightDim, scale);
leftDim,
bottomDim,
topDim,
rightDim,
scale
);
// Draw symbols and symbol dimensions
RenderSymbols(ctx, symbols, scale);
@ -74,12 +79,10 @@ function Draw(
ctx.restore();
}
function UseCanvas(
draw: (context: CanvasRenderingContext2D,
frameCount: number,
scale: number,
translatePos: IPoint) => void
): React.RefObject<HTMLCanvasElement> {
function UseCanvas(draw: (context: CanvasRenderingContext2D,
frameCount: number,
scale: number,
translatePos: IPoint) => void): React.RefObject<HTMLCanvasElement> {
const canvasRef = useRef<HTMLCanvasElement>(null);
const frameCount = useRef(0);
const translatePos = useRef({
@ -169,9 +172,7 @@ function UseCanvas(
return canvasRef;
}
function UseSVGAutoResizer(
setViewer: React.Dispatch<React.SetStateAction<Viewer>>
): void {
function UseSVGAutoResizer(setViewer: React.Dispatch<React.SetStateAction<Viewer>>): void {
React.useEffect(() => {
function OnResize(): void {
setViewer({
@ -199,9 +200,7 @@ export function Canvas({
style,
drawParams
}: ICanvasProps): JSX.Element {
const canvasRef = UseCanvas((
...CanvasProps
) => {
const canvasRef = UseCanvas((...CanvasProps) => {
Draw(
...CanvasProps,
drawParams

View file

@ -1,5 +1,5 @@
import { NOTCHES_LENGTH } from '../../utils/default';
import { IDimensionStyle } from '../SVG/Elements/Dimension';
import { type IDimensionStyle } from '../SVG/Elements/Dimension';
interface IDimensionProps {
id: string

View file

@ -169,11 +169,13 @@ function AddHorizontalChildrenDimension(
let xChildrenStart = TransformX(
lastChild.properties.x,
lastChild.properties.width,
lastChild.properties.positionReference);
lastChild.properties.positionReference
);
let xChildrenEnd = TransformX(
lastChild.properties.x,
lastChild.properties.width,
lastChild.properties.positionReference);
lastChild.properties.positionReference
);
// Find the min and max
for (let i = container.children.length - 2; i >= 0; i--) {
@ -237,7 +239,8 @@ function AddVerticalChildrenDimension(
let yChildrenStart = TransformY(
lastChild.properties.y,
lastChild.properties.height,
lastChild.properties.positionReference);
lastChild.properties.positionReference
);
let yChildrenEnd = yChildrenStart;
// Find the min and max
@ -313,9 +316,7 @@ function AddHorizontalBorrowerDimension(
const restoredX = x + childCurrentTransform[0];
marks.push(
restoredX
);
marks.push(restoredX);
}
const restoredX = container.properties.x + currentTransform[0];
@ -373,9 +374,7 @@ function AddVerticalBorrowerDimension(
const restoredy = y + childCurrentTransform[1];
marks.push(
restoredy
);
marks.push(restoredy);
}
const restoredY = container.properties.y + currentTransform[1];

View file

@ -1,6 +1,5 @@
import { type IContainerModel } from '../../Interfaces/IContainerModel';
import { type IHistoryState } from '../../Interfaces/IHistoryState';
import { ISymbolModel } from '../../Interfaces/ISymbolModel';
import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
import { DIMENSION_MARGIN } from '../../utils/default';
import { MakeRecursionDFSIterator } from '../../utils/itertools';
import { RenderContainer } from './Container';

View file

@ -25,7 +25,11 @@ export function RenderContainerSelector(
props.selected.properties.height
];
({ x, y, width, height } = RemoveMargin(x, y, width, height,
({ x, y, width, height } = RemoveMargin(
x,
y,
width,
height,
props.selected.properties.margin.left,
props.selected.properties.margin.bottom,
props.selected.properties.margin.top,

View file

@ -5,7 +5,8 @@ const IMAGE_CACHE = new Map<string, HTMLImageElement>();
export function RenderSymbol(
ctx: CanvasRenderingContext2D,
symbol: ISymbolModel): void {
symbol: ISymbolModel
): void {
const href = symbol.config.Image.Base64Image ?? symbol.config.Image.Url;
if (href === undefined) {

View file

@ -1,6 +1,6 @@
import { ChevronRightIcon } from '@heroicons/react/24/outline';
import React, { useState } from 'react';
import { ICategory } from '../../Interfaces/ICategory';
import { type ICategory } from '../../Interfaces/ICategory';
import { TruncateString } from '../../utils/stringtools';
interface ICategoryProps {
@ -20,23 +20,40 @@ export function Category(props: ICategoryProps): JSX.Element {
return (
<div
className={` transition-all text-center ${isOpen ? 'overflow-hidden h-full' : `overflow-visible ${heightClass}`}`}
className={` transition-all text-center ${isOpen
? 'overflow-hidden h-full'
: `overflow-visible ${heightClass}`}`}
key={categoryType}
id={categoryType}
title={categoryDisplayedText}
>
<div
className={`flex flex-row group cursor-pointer ${heightClass}`}
onClick={() => setIsOpen(!isOpen)}
onClick={() => { setIsOpen(!isOpen); }}
>
<span className={`transition-all flex-1 h-full justify-center sidebar-component-left ${isOpen ? 'rounded-b-none bg-slate-400/80 group-hover:bg-blue-600' : ''}`}>
<span className={
`transition-all flex-1 h-full
justify-center sidebar-component-left
${isOpen
? 'rounded-b-none bg-slate-400/80 group-hover:bg-blue-600'
: ''}`}
>
{TruncateString(categoryDisplayedText, 25)}
</span>
<span className={`flex-none h-full justify-center sidebar-component-right ${isOpen ? 'rounded-b-none' : ''}`}>
<ChevronRightIcon className={`transition-all w-5 ${isOpen ? 'rotate-90' : ''}`} />
<span className={`flex-none h-full justify-center sidebar-component-right ${isOpen
? 'rounded-b-none'
: ''}`}>
<ChevronRightIcon className={`transition-all w-5 ${isOpen
? 'rotate-90'
: ''}`} />
</span>
</div>
<div className={`transition-all grid gap-2 p-2 rounded-b-lg ${isOpen ? 'visible overflow-auto bg-slate-400/80' : 'hidden overflow-hidden'}`}>
<div className={
`transition-all grid gap-2 p-2 rounded-b-lg
${isOpen
? 'visible overflow-auto bg-slate-400/80'
: 'hidden overflow-hidden'}`}
>
{ props.children }
</div>
</div>

View file

@ -80,7 +80,9 @@ export function CheckboxGroupButtons(props: ICheckboxGroupButtonsProps): JSX.Ele
* @returns The new selected values
*/
function SetChecked(selectedValue: number, isChecked: boolean): number[] {
isChecked ? selectedOptions.add(selectedValue) : selectedOptions.delete(selectedValue);
isChecked
? selectedOptions.add(selectedValue)
: selectedOptions.delete(selectedValue);
return [...selectedOptions];
}
}

View file

@ -1,7 +1,7 @@
import React from 'react';
import { ChevronUpDownIcon } from '@heroicons/react/20/solid';
import { CheckboxGroupButtons } from './CheckboxGroupButtons';
import { Orientation } from '../../Enums/Orientation';
import { CheckboxGroupButtons } from './CheckboxGroupButtons';
interface IOrientationCheckboxesProps {
id: string

View file

@ -1,13 +1,13 @@
import { EyeIcon, EyeSlashIcon, XCircleIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
import { ICategory } from '../../Interfaces/ICategory';
import { IContainerModel } from '../../Interfaces/IContainerModel';
import { type Dispatch } from 'react';
import { type IAvailableContainer } from '../../Interfaces/IAvailableContainer';
import { type ICategory } from '../../Interfaces/ICategory';
import { type 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';
import { type IReplaceContainer } from '../../Interfaces/IReplaceContainer';
interface IComponentsProps {
selectedContainer: IContainerModel | undefined
@ -29,7 +29,9 @@ interface SidebarCategory {
export function Components(props: IComponentsProps): JSX.Element {
const [hideDisabled, setHideDisabled] = React.useState<boolean>(false);
const disabledTitle = hideDisabled ? Text({ textId: '@ShowDisabledComponents' }) : Text({ textId: '@HideDisabledComponents' });
const disabledTitle = hideDisabled
? Text({ textId: '@ShowDisabledComponents' })
: Text({ textId: '@HideDisabledComponents' });
const rootElements: Array<JSX.Element | undefined> = [];
const categories = new Map<string, SidebarCategory>(props.categories.map(category => [
@ -42,13 +44,12 @@ export function Components(props: IComponentsProps): JSX.Element {
// build the categories (sorted with categories first)
categories.forEach((categoryWrapper, categoryName) => {
rootElements.push(
<Category
key={categoryName}
category={categoryWrapper.category}
>
{ categoryWrapper.children }
</Category>);
rootElements.push(<Category
key={categoryName}
category={categoryWrapper.category}
>
{ categoryWrapper.children }
</Category>);
});
const selectedContainer = props.selectedContainer;
@ -80,9 +81,9 @@ export function Components(props: IComponentsProps): JSX.Element {
className='w-full justify-center h-16 transition-all sidebar-component'
id={componentOption.Type}
title={componentOption.Type}
onClick={() => props.buttonOnClick(componentOption.Type)}
onClick={() => { props.buttonOnClick(componentOption.Type); }}
draggable={true}
onDragStart={(event) => HandleDragStart(event)}
onDragStart={(event) => { HandleDragStart(event); }}
disabled={disabled}
>
{TruncateString(componentOption.DisplayedText ?? componentOption.Type, 25)}

View file

@ -192,13 +192,17 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={props.properties.minWidth}
max={props.properties.maxWidth}
value={(RemoveWidthMargin(props.properties.width,
value={(RemoveWidthMargin(
props.properties.width,
props.properties.margin.left,
props.properties.margin.right)).toString()}
props.properties.margin.right
)).toString()}
onChange={(value) => {
props.onChange('width', ApplyWidthMargin(Number(value),
props.onChange('width', ApplyWidthMargin(
Number(value),
props.properties.margin.left,
props.properties.margin.right));
props.properties.margin.right
));
}}
isDisabled={props.properties.isFlex}/>
<TextInputGroup
@ -231,13 +235,17 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={props.properties.minHeight}
max={props.properties.maxHeight}
value={(RemoveWidthMargin(props.properties.height,
value={(RemoveWidthMargin(
props.properties.height,
props.properties.margin.top,
props.properties.margin.bottom)).toString()}
props.properties.margin.bottom
)).toString()}
onChange={(value) => {
props.onChange('height', ApplyWidthMargin(Number(value),
props.onChange('height', ApplyWidthMargin(
Number(value),
props.properties.margin.top,
props.properties.margin.bottom));
props.properties.margin.bottom
));
}}
isDisabled={props.properties.isFlex}
/>
@ -270,7 +278,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={0}
value={(props.properties.margin.left ?? 0).toString()}
onChange={(value) => { props.onChange('left', Number(value), PropertyType.Margin); }}/>
onChange={(value) => {
props.onChange('left', Number(value), PropertyType.Margin);
}}/>
<TextInputGroup
id={`${props.properties.id}-mb`}
labelText={Text({ textId: '@ContainerMarginBottom' })}
@ -280,7 +290,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={0}
value={(props.properties.margin.bottom ?? 0).toString()}
onChange={(value) => { props.onChange('bottom', Number(value), PropertyType.Margin); }}/>
onChange={(value) => {
props.onChange('bottom', Number(value), PropertyType.Margin);
}}/>
<TextInputGroup
id={`${props.properties.id}-mt`}
labelText={Text({ textId: '@ContainerMarginTop' })}
@ -290,7 +302,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={0}
value={(props.properties.margin.top ?? 0).toString()}
onChange={(value) => { props.onChange('top', Number(value), PropertyType.Margin); }}/>
onChange={(value) => {
props.onChange('top', Number(value), PropertyType.Margin);
}}/>
<TextInputGroup
id={`${props.properties.id}-mr`}
labelText={Text({ textId: '@ContainerMarginRight' })}
@ -300,7 +314,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={0}
value={(props.properties.margin.right ?? 0).toString()}
onChange={(value) => { props.onChange('right', Number(value), PropertyType.Margin); }}/>
onChange={(value) => {
props.onChange('right', Number(value), PropertyType.Margin);
}}/>
</div>
</Category>
@ -377,7 +393,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
name='ShowSelfDimensions'
labelText={Text({ textId: '@ContainerShowDimension' })}
value={props.properties.dimensionOptions.selfDimensions.positions}
onChange={(key, value) => { props.onChange(key, value, PropertyType.SelfDimension); }}
onChange={(key, value) => {
props.onChange(key, value, PropertyType.SelfDimension);
}}
/>
<InputGroup
labelText={Text({ textId: '@StyleStrokeColor' })}
@ -386,7 +404,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName=''
type='color'
value={props.properties.dimensionOptions.selfDimensions.color ?? '#000000'}
onChange={(e) => { props.onChange('color', e.target.value, PropertyType.SelfDimension); }}/>
onChange={(e) => {
props.onChange('color', e.target.value, PropertyType.SelfDimension);
}}/>
<TextInputGroup
id={`${props.properties.id}-selfDimensions-width`}
labelText={Text({ textId: '@StyleStrokeWidth' })}
@ -396,7 +416,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={0}
value={(props.properties.dimensionOptions.selfDimensions.width ?? 0).toString()}
onChange={(value) => { props.onChange('width', Number(value), PropertyType.SelfDimension); }}/>
onChange={(value) => {
props.onChange('width', Number(value), PropertyType.SelfDimension);
}}/>
<TextInputGroup
id={`${props.properties.id}-selfDimensions-dasharray`}
labelText={Text({ textId: '@StyleStrokeDashArray' })}
@ -405,7 +427,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName=''
type='text'
value={props.properties.dimensionOptions.selfDimensions.dashArray ?? ''}
onChange={(value) => { props.onChange('dashArray', value, PropertyType.SelfDimension); }}/>
onChange={(value) => {
props.onChange('dashArray', value, PropertyType.SelfDimension);
}}/>
</div>
}
{
@ -417,7 +441,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
name='ShowSelfMarginsDimensions'
labelText={Text({ textId: '@ContainerShowMarginsDimension' })}
value={props.properties.dimensionOptions.selfMarginsDimensions.positions}
onChange={(key, value) => { props.onChange(key, value, PropertyType.SelfMarginDimension); }}
onChange={(key, value) => {
props.onChange(key, value, PropertyType.SelfMarginDimension);
}}
/>
<InputGroup
labelText={Text({ textId: '@StyleStrokeColor' })}
@ -426,7 +452,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName=''
type='color'
value={props.properties.dimensionOptions.selfMarginsDimensions.color ?? '#000000'}
onChange={(e) => { props.onChange('color', e.target.value, PropertyType.SelfMarginDimension); }}/>
onChange={(e) => {
props.onChange('color', e.target.value, PropertyType.SelfMarginDimension);
}}/>
<TextInputGroup
id={`${props.properties.id}-selfMarginsDimensions-width`}
labelText={Text({ textId: '@StyleStrokeWidth' })}
@ -436,7 +464,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={0}
value={(props.properties.dimensionOptions.selfMarginsDimensions.width ?? 0).toString()}
onChange={(value) => { props.onChange('width', Number(value), PropertyType.SelfMarginDimension); }}/>
onChange={(value) => {
props.onChange('width', Number(value), PropertyType.SelfMarginDimension);
}}/>
<TextInputGroup
id={`${props.properties.id}-selfMarginsDimensions-dasharray`}
labelText={Text({ textId: '@StyleStrokeDashArray' })}
@ -445,7 +475,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName=''
type='text'
value={props.properties.dimensionOptions.selfMarginsDimensions.dashArray ?? ''}
onChange={(value) => { props.onChange('dashArray', value, PropertyType.SelfMarginDimension); }}/>
onChange={(value) => {
props.onChange('dashArray', value, PropertyType.SelfMarginDimension);
}}/>
</div>
}
{
@ -457,7 +489,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
name='ShowChildrenDimensions'
labelText={Text({ textId: '@ContainerShowChildrenDimension' })}
value={props.properties.dimensionOptions.childrenDimensions.positions}
onChange={(key, value) => { props.onChange(key, value, PropertyType.ChildrenDimensions); }}
onChange={(key, value) => {
props.onChange(key, value, PropertyType.ChildrenDimensions);
}}
/>
<InputGroup
labelText={Text({ textId: '@StyleStrokeColor' })}
@ -466,7 +500,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName=''
type='color'
value={props.properties.dimensionOptions.childrenDimensions.color ?? '#000000'}
onChange={(e) => { props.onChange('color', e.target.value, PropertyType.ChildrenDimensions); }}/>
onChange={(e) => {
props.onChange('color', e.target.value, PropertyType.ChildrenDimensions);
}}/>
<TextInputGroup
id={`${props.properties.id}-childrenDimensions-width`}
labelText={Text({ textId: '@StyleStrokeWidth' })}
@ -476,7 +512,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={0}
value={(props.properties.dimensionOptions.childrenDimensions.width ?? 0).toString()}
onChange={(value) => { props.onChange('width', Number(value), PropertyType.ChildrenDimensions); }}/>
onChange={(value) => {
props.onChange('width', Number(value), PropertyType.ChildrenDimensions);
}}/>
<TextInputGroup
id={`${props.properties.id}-childrenDimensions-dasharray`}
labelText={Text({ textId: '@StyleStrokeDashArray' })}
@ -485,7 +523,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName=''
type='text'
value={props.properties.dimensionOptions.childrenDimensions.dashArray ?? ''}
onChange={(value) => { props.onChange('dashArray', value, PropertyType.ChildrenDimensions); }}/>
onChange={(value) => {
props.onChange('dashArray', value, PropertyType.ChildrenDimensions);
}}/>
</div>
}
{
@ -497,7 +537,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
name='MarkPosition'
value={props.properties.dimensionOptions.markPosition}
labelText={Text({ textId: '@ContainerMarkPosition' })}
onChange={(key, value) => { props.onChange(key, value, PropertyType.DimensionOptions); }}
onChange={(key, value) => {
props.onChange(key, value, PropertyType.DimensionOptions);
}}
/>
</div>
<div className='grid grid-cols-1 gap-2'>
@ -507,7 +549,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
name='ShowDimensionWithMarks'
labelText={Text({ textId: '@ContainerShowDimensionWithMarks' })}
value={props.properties.dimensionOptions.dimensionWithMarks.positions}
onChange={(key, value) => { props.onChange(key, value, PropertyType.DimensionWithMarks); }}
onChange={(key, value) => {
props.onChange(key, value, PropertyType.DimensionWithMarks);
}}
/>
<InputGroup
labelText={Text({ textId: '@StyleStrokeColor' })}
@ -516,7 +560,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName=''
type='color'
value={props.properties.dimensionOptions.dimensionWithMarks.color ?? '#000000'}
onChange={(e) => { props.onChange('color', e.target.value, PropertyType.DimensionWithMarks); }}/>
onChange={(e) => {
props.onChange('color', e.target.value, PropertyType.DimensionWithMarks);
}}/>
<TextInputGroup
id={`${props.properties.id}-dimensionWithMarks-width`}
labelText={Text({ textId: '@StyleStrokeWidth' })}
@ -526,7 +572,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
type='number'
min={0}
value={(props.properties.dimensionOptions.dimensionWithMarks.width ?? 0).toString()}
onChange={(value) => { props.onChange('width', Number(value), PropertyType.DimensionWithMarks); }}/>
onChange={(value) => {
props.onChange('width', Number(value), PropertyType.DimensionWithMarks);
}}/>
<TextInputGroup
id={`${props.properties.id}-dimensionWithMarks-dasharray`}
labelText={Text({ textId: '@StyleStrokeDashArray' })}
@ -535,7 +583,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName=''
type='text'
value={props.properties.dimensionOptions.dimensionWithMarks.dashArray ?? ''}
onChange={(value) => { props.onChange('dashArray', value, PropertyType.DimensionWithMarks); }}/>
onChange={(value) => {
props.onChange('dashArray', value, PropertyType.DimensionWithMarks);
}}/>
</div>
</>
}
@ -557,7 +607,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName='col-span-3'
type='color'
value={props.properties.style.stroke ?? '#000000'}
onChange={(e) => { props.onChange('stroke', e.target.value, PropertyType.Style); }}/>
onChange={(e) => {
props.onChange('stroke', e.target.value, PropertyType.Style);
}}/>
<InputGroup
labelKey={`${props.properties.id}-strokeOpacity`}
labelText={Text({ textId: '@StyleStrokeOpacity' })}
@ -569,7 +621,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
max={1}
step={0.01}
value={(props.properties.style.strokeOpacity ?? 1).toString()}
onChange={(event) => { props.onChange('strokeOpacity', Number(event.target.value), PropertyType.Style); }}
onChange={(event) => {
props.onChange('strokeOpacity', Number(event.target.value), PropertyType.Style);
}}
/>
<TextInputGroup
id={`${props.properties.id}-strokeWidth`}
@ -579,7 +633,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName='col-span-3'
type='number'
value={(props.properties.style.strokeWidth ?? 1).toString()}
onChange={(value) => { props.onChange('strokeWidth', Number(value), PropertyType.Style); }}
onChange={(value) => {
props.onChange('strokeWidth', Number(value), PropertyType.Style);
}}
/>
<InputGroup
labelText={Text({ textId: '@StyleFill' })}
@ -588,7 +644,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
inputClassName='col-span-3'
type='color'
value={props.properties.style.fill ?? '#000000'}
onChange={(e) => { props.onChange('fill', e.target.value, PropertyType.Style); }}/>
onChange={(e) => {
props.onChange('fill', e.target.value, PropertyType.Style);
}}/>
<InputGroup
labelKey={`${props.properties.id}-fillOpacity`}
labelText={Text({ textId: '@StyleFillOpacity' })}
@ -600,7 +658,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
max={1}
step={0.01}
value={(props.properties.style.fillOpacity ?? 1).toString()}
onChange={(event) => { props.onChange('fillOpacity', Number(event.target.value), PropertyType.Style); }}
onChange={(event) => {
props.onChange('fillOpacity', Number(event.target.value), PropertyType.Style);
}}
/>
</div>
</Category>

View file

@ -2,10 +2,10 @@ import { fireEvent, render, screen } from '@testing-library/react';
import * as React from 'react';
import { expect, describe, it, vi } from 'vitest';
import { PositionReference } from '../../Enums/PositionReference';
import { IContainerProperties } from '../../Interfaces/IContainerProperties';
import { type IContainerProperties } from '../../Interfaces/IContainerProperties';
import { Orientation } from '../../Enums/Orientation';
import { ContainerProperties } from './ContainerProperties';
import { DEFAULT_DIMENSION_OPTION } from '../../utils/default';
import { ContainerProperties } from './ContainerProperties';
describe.concurrent('Properties', () => {
it('No properties', () => {

View file

@ -2,8 +2,8 @@ import React from 'react';
import { type PropertyType } from '../../Enums/PropertyType';
import { type IContainerProperties } from '../../Interfaces/IContainerProperties';
import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
import { ContainerForm } from './ContainerForm';
import { type IContainerModel } from '../../Interfaces/IContainerModel';
import { ContainerForm } from './ContainerForm';
interface IPropertiesProps {
containers: Map<string, IContainerModel>

View file

@ -3,12 +3,12 @@
*/
import { AddMethod } from '../../../Enums/AddMethod';
import { IAvailableContainer } from '../../../Interfaces/IAvailableContainer';
import { IConfiguration } from '../../../Interfaces/IConfiguration';
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { IHistoryState } from '../../../Interfaces/IHistoryState';
import { IPattern, GetPattern, ContainerOrPattern } from '../../../Interfaces/IPattern';
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
import { type IAvailableContainer } from '../../../Interfaces/IAvailableContainer';
import { type IConfiguration } from '../../../Interfaces/IConfiguration';
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
import { type IHistoryState } from '../../../Interfaces/IHistoryState';
import { type IPattern, GetPattern, type ContainerOrPattern } from '../../../Interfaces/IPattern';
import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
import { Orientation } from '../../../Enums/Orientation';
import { GetDefaultContainerProps } from '../../../utils/default';
import { FindContainerById } from '../../../utils/itertools';
@ -69,9 +69,7 @@ export function AddContainers(
const containers = structuredClone(current.containers);
// Find the parent in the clone
const parentClone: IContainerModel | undefined = FindContainerById(
containers, parentId
);
const parentClone: IContainerModel | undefined = FindContainerById(containers, parentId);
if (parentClone === null || parentClone === undefined) {
throw new Error('[AddContainer] Container model was not found among children of the main container!');
@ -144,8 +142,14 @@ function AddNewContainerToParent(
const right: number = containerConfig.Margin?.right ?? 0;
// Default coordinates
let width = containerConfig.Width ?? containerConfig.MaxWidth ?? containerConfig.MinWidth ?? parentClone.properties.width;
let height = containerConfig.Height ?? containerConfig.MaxHeight ?? containerConfig.MinHeight ?? parentClone.properties.height;
let width = containerConfig.Width ??
containerConfig.MaxWidth ??
containerConfig.MinWidth ??
parentClone.properties.width;
let height = containerConfig.Height ??
containerConfig.MaxHeight ??
containerConfig.MinHeight ??
parentClone.properties.height;
let x = RestoreX(containerConfig.X ?? 0, width, containerConfig.PositionReference);
let y = RestoreY(containerConfig.Y ?? 0, height, containerConfig.PositionReference);
@ -288,7 +292,8 @@ function InitializeDefaultChild(
configuration,
containers,
parent,
0, 0,
0,
0,
newCounters,
symbols
);
@ -308,12 +313,17 @@ function InitializeChildrenWithPattern(
return;
}
const configs: Map<string, IAvailableContainer> = new Map(configuration.AvailableContainers.map(config => [config.Type, config]));
const patterns: Map<string, IPattern> = new Map(configuration.Patterns.map(pattern => [pattern.id, pattern]));
const configs = new Map<string, IAvailableContainer>(
configuration.AvailableContainers.map(config => [config.Type, config])
);
const patterns = new Map<string, IPattern>(
configuration.Patterns.map(pattern => [pattern.id, pattern])
);
const containerOrPattern = GetPattern(patternId, configs, patterns);
if (containerOrPattern === undefined) {
console.warn(`[InitializeChildrenWithPattern] PatternId ${patternId} was neither found as Pattern nor as IAvailableContainer`);
console.warn('[InitializeChildrenWithPattern]' +
`PatternId ${patternId} was neither found as Pattern nor as IAvailableContainer`);
return;
}
@ -356,7 +366,16 @@ function BuildPatterns(
while (levelSize-- !== 0) {
const node = queue.shift() as Node;
const newParent = AddContainerInLevel(node, maxLevelSize, levelSize, configuration, containers, newCounters, symbols, configs);
const newParent = AddContainerInLevel(
node,
maxLevelSize,
levelSize,
configuration,
containers,
newCounters,
symbols,
configs
);
if (newParent === undefined) {
// node.pattern is not a IPattern, there is no children to iterate
@ -411,7 +430,8 @@ function AddContainerInLevel(
configuration,
containers,
node.parent,
index, 0,
index,
0,
newCounters,
symbols
);
@ -429,8 +449,9 @@ function AddContainerInLevel(
// and set the new parent as the child of this parent
const container = configs.get(pattern.wrapper);
if (container === undefined) {
console.warn(`[InitializeChildrenFromPattern] IAvailableContainer from pattern was not found in the configuration: ${pattern.wrapper}.
Process will ignore the container.`);
console.warn('[InitializeChildrenFromPattern]' +
` IAvailableContainer from pattern was not found in the configuration: ${pattern.wrapper}.
Process will ignore the container.`);
return { parent, pattern };
}
@ -439,7 +460,8 @@ function AddContainerInLevel(
configuration,
containers,
parent,
0, 0,
0,
0,
newCounters,
symbols,
false

View file

@ -1,15 +1,15 @@
import { IHistoryState } from '../../../Interfaces/IHistoryState';
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import Swal from 'sweetalert2';
import { type IHistoryState } from '../../../Interfaces/IHistoryState';
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
import { FindContainerById, MakeDFSIterator } from '../../../utils/itertools';
import { GetCurrentHistory } from '../Editor';
import { ApplyBehaviors, ApplyBehaviorsOnSiblings, ApplyBehaviorsOnSiblingsChildren } from '../Behaviors/Behaviors';
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
import Swal from 'sweetalert2';
import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
import { PropertyType } from '../../../Enums/PropertyType';
import { TransformX, TransformY } from '../../../utils/svg';
import { Orientation } from '../../../Enums/Orientation';
import { type IConfiguration } from '../../../Interfaces/IConfiguration';
import { AddContainers } from './AddContainer';
import { IConfiguration } from '../../../Interfaces/IConfiguration';
/**
* Select a container
@ -82,7 +82,8 @@ export function DeleteContainer(
const container = FindContainerById(containers, containerId);
if (container === undefined) {
throw new Error(`[DeleteContainer] Tried to delete a container that is not present in the main container: ${containerId}`);
throw new Error('[DeleteContainer]' +
`Tried to delete a container that is not present in the main container: ${containerId}`);
}
const parent = FindContainerById(containers, container.properties.parentId);
@ -94,7 +95,8 @@ export function DeleteContainer(
text: 'Deleting the main container is not allowed!',
icon: 'error'
});
throw new Error('[DeleteContainer] Tried to delete the main container! Deleting the main container is not allowed!');
throw new Error('[DeleteContainer]' +
'Tried to delete the main container! Deleting the main container is not allowed!');
}
if (container === null || container === undefined) {
@ -168,7 +170,9 @@ export function ReplaceByContainer(
containerParent.children.indexOf(containerId),
[{ Type: newContainerId }],
containerParent.properties.id,
configuration, fullHistory, historyCurrentStep
configuration,
fullHistory,
historyCurrentStep
);
const historyDelete = DeleteContainer(containerId, historyAdd.history, historyCurrentStep + 1);
@ -294,34 +298,7 @@ export function SortChildren(
const children = parent.children;
if (!isHorizontal) {
parent.children.sort(
(aId, bId) => {
const a = FindContainerById(containers, aId);
const b = FindContainerById(containers, bId);
if (a === undefined || b === undefined) {
return 0;
}
const yA = TransformY(a.properties.y, a.properties.height, a.properties.positionReference);
const yB = TransformY(b.properties.y, b.properties.height, b.properties.positionReference);
if (yA < yB) {
return -1;
}
if (yB < yA) {
return 1;
}
// xA = xB
const indexA = children.indexOf(aId);
const indexB = children.indexOf(bId);
return indexA - indexB;
}
);
return;
}
parent.children.sort(
(aId, bId) => {
parent.children.sort((aId, bId) => {
const a = FindContainerById(containers, aId);
const b = FindContainerById(containers, bId);
@ -329,20 +306,43 @@ export function SortChildren(
return 0;
}
const xA = TransformX(a.properties.x, a.properties.width, a.properties.positionReference);
const xB = TransformX(b.properties.x, b.properties.width, b.properties.positionReference);
if (xA < xB) {
const yA = TransformY(a.properties.y, a.properties.height, a.properties.positionReference);
const yB = TransformY(b.properties.y, b.properties.height, b.properties.positionReference);
if (yA < yB) {
return -1;
}
if (xB < xA) {
if (yB < yA) {
return 1;
}
// xA = xB
const indexA = children.indexOf(aId);
const indexB = children.indexOf(bId);
return indexA - indexB;
});
return;
}
parent.children.sort((aId, bId) => {
const a = FindContainerById(containers, aId);
const b = FindContainerById(containers, bId);
if (a === undefined || b === undefined) {
return 0;
}
);
const xA = TransformX(a.properties.x, a.properties.width, a.properties.positionReference);
const xB = TransformX(b.properties.x, b.properties.width, b.properties.positionReference);
if (xA < xB) {
return -1;
}
if (xB < xA) {
return 1;
}
// xA = xB
const indexA = children.indexOf(aId);
const indexB = children.indexOf(bId);
return indexA - indexB;
});
}
/**
@ -357,7 +357,8 @@ export function SortChildren(
function SetContainer(
containers: Map<string, IContainerModel>,
container: IContainerModel,
key: string, value: string | number | boolean | number[],
key: string,
value: string | number | boolean | number[],
type: PropertyType,
symbols: Map<string, ISymbolModel>
): void {
@ -396,7 +397,12 @@ function SetContainer(
* @param value Value of the property
* @param type Type of the property
*/
function AssignProperty(container: IContainerModel, key: string, value: string | number | boolean | number[], type: PropertyType): void {
function AssignProperty(
container: IContainerModel,
key: string,
value: string | number | boolean | number[],
type: PropertyType
): void {
switch (type) {
case PropertyType.Style:
(container.properties.style as any)[key] = value;

View file

@ -1,22 +1,22 @@
import Swal from 'sweetalert2';
import { Dispatch, SetStateAction } from 'react';
import { type Dispatch, type SetStateAction } from 'react';
import { AddMethod } from '../../../Enums/AddMethod';
import { IAction } from '../../../Interfaces/IAction';
import { IConfiguration } from '../../../Interfaces/IConfiguration';
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { IHistoryState } from '../../../Interfaces/IHistoryState';
import { ISetContainerListRequest } from '../../../Interfaces/ISetContainerListRequest';
import { ISetContainerListResponse } from '../../../Interfaces/ISetContainerListResponse';
import { type IAction } from '../../../Interfaces/IAction';
import { type IConfiguration } from '../../../Interfaces/IConfiguration';
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
import { type IHistoryState } from '../../../Interfaces/IHistoryState';
import { type ISetContainerListRequest } from '../../../Interfaces/ISetContainerListRequest';
import { type ISetContainerListResponse } from '../../../Interfaces/ISetContainerListResponse';
import { DISABLE_API } from '../../../utils/default';
import { FindContainerById } from '../../../utils/itertools';
import { SetContainerList } from '../../API/api';
import { IMenuAction } from '../../Menu/Menu';
import { type IMenuAction } from '../../Menu/Menu';
import { GetCurrentHistoryState } from '../Editor';
import { Text } from '../../Text/Text';
import { type IReplaceContainer } from '../../../Interfaces/IReplaceContainer';
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[]>,
@ -63,7 +63,9 @@ export function InitActions(
shortcut: '<kbd>R</kbd>',
action: (target: HTMLElement) => {
const targetContainer = FindContainerById(history[historyCurrentStep].containers, target.id);
const targetAvailableContainer = configuration.AvailableContainers.find((availableContainer) => availableContainer.Type === targetContainer?.properties.type);
const targetAvailableContainer = configuration.AvailableContainers.find(
(availableContainer) => availableContainer.Type === targetContainer?.properties.type
);
if (targetAvailableContainer === undefined) {
return;
@ -188,7 +190,10 @@ function GetAction(
};
}
function GetPreviousAndNextSiblings(containers: Map<string, IContainerModel>, container: IContainerModel): { prev: IContainerModel | undefined, next: IContainerModel | undefined } {
function GetPreviousAndNextSiblings(
containers: Map<string, IContainerModel>,
container: IContainerModel
): { prev: IContainerModel | undefined, next: IContainerModel | undefined } {
let prev;
let next;
const parent = FindContainerById(containers, container.properties.parentId);
@ -230,22 +235,21 @@ function HandleSetContainerList(
selectedContainer.properties.id,
configuration,
history,
historyCurrentStep);
historyCurrentStep
);
setNewHistory(newHistory);
break;
}
case AddMethod.Replace:
setNewHistory(
HandleReplace(
containers,
selectedContainer,
response,
configuration,
history,
historyCurrentStep
)
);
setNewHistory(HandleReplace(
containers,
selectedContainer,
response,
configuration,
history,
historyCurrentStep
));
break;
case AddMethod.ReplaceParent: {
const parent = FindContainerById(containers, selectedContainer.properties.parentId);
@ -257,16 +261,14 @@ function HandleSetContainerList(
});
return;
}
setNewHistory(
HandleReplace(
containers,
parent,
response,
configuration,
history,
historyCurrentStep
)
);
setNewHistory(HandleReplace(
containers,
parent,
response,
configuration,
history,
historyCurrentStep
));
break;
}
}

View file

@ -1,8 +1,8 @@
import { IHistoryState } from '../../../Interfaces/IHistoryState';
import { IConfiguration } from '../../../Interfaces/IConfiguration';
import { type IHistoryState } from '../../../Interfaces/IHistoryState';
import { type IConfiguration } from '../../../Interfaces/IConfiguration';
import { GetCircularReplacer } from '../../../utils/saveload';
import { ID } from '../../SVG/SVG';
import { IEditorState } from '../../../Interfaces/IEditorState';
import { type IEditorState } from '../../../Interfaces/IEditorState';
import { SHOW_SELECTOR_TEXT } from '../../../utils/default';
export function SaveEditorAsJSON(
@ -11,7 +11,9 @@ export function SaveEditorAsJSON(
configuration: IConfiguration
): void {
const exportName = 'state.json';
const spaces = import.meta.env.DEV ? 4 : 0;
const spaces = import.meta.env.DEV
? 4
: 0;
const editorState: IEditorState = {
history,
historyCurrentStep,

View file

@ -1,5 +1,5 @@
import { Dispatch, SetStateAction } from 'react';
import { IHistoryState } from '../../../Interfaces/IHistoryState';
import { type Dispatch, type SetStateAction } from 'react';
import { type IHistoryState } from '../../../Interfaces/IHistoryState';
import { ENABLE_SHORTCUTS } from '../../../utils/default';
export function OnKey(

View file

@ -4,7 +4,7 @@ import { type IHistoryState } from '../../../Interfaces/IHistoryState';
import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
import { GetDefaultSymbolModel } from '../../../utils/default';
import { FindContainerById } from '../../../utils/itertools';
import {RestoreX, RestoreY} from '../../../utils/svg';
import { RestoreX, RestoreY } from '../../../utils/svg';
import { ApplyBehaviors, ApplyBehaviorsOnSiblingsChildren } from '../Behaviors/Behaviors';
import { GetCurrentHistory, GetCurrentHistoryState, UpdateCounters } from '../Editor';
import { AddContainers } from './AddContainer';
@ -212,5 +212,7 @@ function LinkContainer(
): void {
const oldSymbol = symbols.get(container.properties.linkedSymbolId);
LinkSymbol(container.properties.id, oldSymbol, symbol);
container.properties.linkedSymbolId = symbol !== undefined ? symbol.id : '';
container.properties.linkedSymbolId = symbol !== undefined
? symbol.id
: '';
}

View file

@ -13,31 +13,34 @@
* or make them lose their property as a rigid body
*/
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
import { Orientation } from '../../../Enums/Orientation';
import { ConstraintBodyInsideUnallocatedWidth } from './RigidBodyBehaviors';
import { FindContainerById } from '../../../utils/itertools';
import { ConstraintBodyInsideUnallocatedWidth } from './RigidBodyBehaviors';
/**
* Impose the container position to its siblings
* Apply the following modification to the overlapping rigid body container :
* @param container Container to impose its position
*/
export function ApplyAnchor(containers: Map<string, IContainerModel>, container: IContainerModel, parent: IContainerModel): IContainerModel {
export function ApplyAnchor(
containers: Map<string, IContainerModel>,
container: IContainerModel,
parent: IContainerModel
): IContainerModel {
const rigidBodies: IContainerModel[] = [];
parent.children.forEach(
childId => {
const child = FindContainerById(containers, childId);
parent.children.forEach(childId => {
const child = FindContainerById(containers, childId);
if (child === undefined) {
return;
}
if (child === undefined) {
return;
}
if (child.properties.isAnchor) {
return;
}
rigidBodies.push(child);
});
if (child.properties.isAnchor) {
return;
}
rigidBodies.push(child);
});
const isHorizontal = parent.properties.orientation === Orientation.Horizontal;
const overlappingContainers = isHorizontal

View file

@ -1,5 +1,5 @@
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
import { APPLY_BEHAVIORS_ON_CHILDREN, ENABLE_RIGID, ENABLE_SWAP } from '../../../utils/default';
import { FindContainerById, MakeChildrenIterator } from '../../../utils/itertools';
import { ApplyAnchor, GetOverlappingContainers } from './AnchorBehaviors';
@ -14,7 +14,11 @@ import { ApplySymbol } from './SymbolBehaviors';
* @param container Container to recalculate its positions
* @returns Updated container
*/
export function ApplyBehaviors(containers: Map<string, IContainerModel>, container: IContainerModel, symbols: Map<string, ISymbolModel>): IContainerModel {
export function ApplyBehaviors(
containers: Map<string, IContainerModel>,
container: IContainerModel,
symbols: Map<string, ISymbolModel>
): IContainerModel {
try {
const symbol = symbols.get(container.properties.linkedSymbolId);
if (container.properties.linkedSymbolId !== '' && symbol !== undefined) {
@ -67,7 +71,8 @@ export function ApplyBehaviors(containers: Map<string, IContainerModel>, contain
export function ApplyBehaviorsOnSiblingsChildren(
containers: Map<string, IContainerModel>,
newContainer: IContainerModel,
symbols: Map<string, ISymbolModel>): void {
symbols: Map<string, ISymbolModel>
): void {
const parent = FindContainerById(containers, newContainer.properties.parentId);
if (parent === null || parent === undefined) {
return;
@ -102,7 +107,11 @@ export function ApplyBehaviorsOnSiblingsChildren(
* @param symbols
* @returns
*/
export function ApplyBehaviorsOnSiblings(containers: Map<string, IContainerModel>, newContainer: IContainerModel, symbols: Map<string, ISymbolModel>): void {
export function ApplyBehaviorsOnSiblings(
containers: Map<string, IContainerModel>,
newContainer: IContainerModel,
symbols: Map<string, ISymbolModel>
): void {
const parent = FindContainerById(containers, newContainer.properties.parentId);
if (parent === null || parent === undefined) {
return;
@ -132,7 +141,11 @@ export function ApplyBehaviorsOnSiblings(containers: Map<string, IContainerModel
}
});
}
function UpdateWarning(containers: Map<string, IContainerModel>, container: IContainerModel, parent: IContainerModel): void {
function UpdateWarning(
containers: Map<string, IContainerModel>,
container: IContainerModel,
parent: IContainerModel
): void {
const targetContainers: IContainerModel[] = [];
parent.children.forEach((child) => {
@ -146,7 +159,8 @@ function UpdateWarning(containers: Map<string, IContainerModel>, container: ICon
});
const overlappingContainers = GetOverlappingContainers(container, targetContainers);
if (overlappingContainers.length > 0) {
container.properties.warning = `There are overlapping containers: ${overlappingContainers.map(c => c.properties.id).join(' ')}`;
container.properties.warning = 'There are overlapping containers: ' +
`${overlappingContainers.map(c => c.properties.id).join(' ')}`;
} else {
container.properties.warning = '';
}

View file

@ -1,4 +1,4 @@
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
import { Orientation } from '../../../Enums/Orientation';
import { Simplex } from '../../../utils/simplex';
import { ApplyWidthMargin, ApplyXMargin } from '../../../utils/svg';
@ -14,12 +14,20 @@ interface IFlexibleGroup {
* Flex the container and its siblings (mutate)
* @returns Flexed container
*/
export function Flex(containers: Map<string, IContainerModel>, container: IContainerModel, parent: IContainerModel): void {
export function Flex(
containers: Map<string, IContainerModel>,
container: IContainerModel,
parent: IContainerModel
): void {
const isVertical = parent.properties.orientation === Orientation.Vertical;
if (isVertical) {
const wantedWidth = Math.min(container.properties.maxWidth, parent.properties.width);
container.properties.width = ApplyWidthMargin(wantedWidth, container.properties.margin.left, container.properties.margin.right);
container.properties.width = ApplyWidthMargin(
wantedWidth,
container.properties.margin.left,
container.properties.margin.right
);
const flexibleGroups = GetVerticalFlexibleGroups(containers, parent);
for (const flexibleGroup of flexibleGroups) {
FlexGroupVertically(flexibleGroup);
@ -28,7 +36,11 @@ export function Flex(containers: Map<string, IContainerModel>, container: IConta
}
const wantedHeight = Math.min(container.properties.maxHeight, parent.properties.height);
container.properties.height = ApplyWidthMargin(wantedHeight, container.properties.margin.top, container.properties.margin.bottom);
container.properties.height = ApplyWidthMargin(
wantedHeight,
container.properties.margin.top,
container.properties.margin.bottom
);
const flexibleGroups = GetHorizontalFlexibleGroups(containers, parent);
for (const flexibleGroup of flexibleGroups) {
FlexGroupHorizontally(flexibleGroup);
@ -40,7 +52,10 @@ export function Flex(containers: Map<string, IContainerModel>, container: IConta
* @param parent Parent in which the flexible children will be set in groups
* @returns a list of groups of flexible containers
*/
export function GetHorizontalFlexibleGroups(containers: Map<string, IContainerModel>, parent: IContainerModel): IFlexibleGroup[] {
export function GetHorizontalFlexibleGroups(
containers: Map<string, IContainerModel>,
parent: IContainerModel
): IFlexibleGroup[] {
const flexibleGroups: IFlexibleGroup[] = [];
let group: IContainerModel[] = [];
let offset = 0;
@ -158,7 +173,11 @@ function FlexGroupHorizontally(flexibleGroup: IFlexibleGroup): void {
continue;
}
sibling.properties.x = ApplyXMargin(right, sibling.properties.margin.left);
sibling.properties.width = ApplyWidthMargin(wantedWidth, sibling.properties.margin.left, sibling.properties.margin.right);
sibling.properties.width = ApplyWidthMargin(
wantedWidth,
sibling.properties.margin.left,
sibling.properties.margin.right
);
right += wantedWidth;
}
@ -174,7 +193,11 @@ function FlexGroupHorizontally(flexibleGroup: IFlexibleGroup): void {
// apply the solutions
for (let i = 0; i < flexibleContainers.length; i++) {
flexibleContainers[i].properties.width = ApplyWidthMargin(solutions[i], flexibleContainers[i].properties.margin.left, flexibleContainers[i].properties.margin.right);
flexibleContainers[i].properties.width = ApplyWidthMargin(
solutions[i],
flexibleContainers[i].properties.margin.left,
flexibleContainers[i].properties.margin.right
);
}
// move the containers
@ -229,7 +252,11 @@ function FlexGroupVertically(flexibleGroup: IFlexibleGroup): void {
continue;
}
sibling.properties.y = ApplyXMargin(right, sibling.properties.margin.top);
sibling.properties.height = ApplyWidthMargin(wantedHeight, sibling.properties.margin.top, sibling.properties.margin.bottom);
sibling.properties.height = ApplyWidthMargin(
wantedHeight,
sibling.properties.margin.top,
sibling.properties.margin.bottom
);
right += wantedHeight;
}
@ -245,7 +272,11 @@ function FlexGroupVertically(flexibleGroup: IFlexibleGroup): void {
// apply the solutions
for (let i = 0; i < flexibleContainers.length; i++) {
flexibleContainers[i].properties.height = ApplyWidthMargin(solutions[i], flexibleContainers[i].properties.margin.top, flexibleContainers[i].properties.margin.bottom);
flexibleContainers[i].properties.height = ApplyWidthMargin(
solutions[i],
flexibleContainers[i].properties.margin.top,
flexibleContainers[i].properties.margin.bottom
);
}
// move the containers

View file

@ -1,4 +1,4 @@
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
import { Orientation } from '../../../Enums/Orientation';
import { MakeChildrenIterator, ReversePairwise } from '../../../utils/itertools';
import { Flex } from './FlexBehaviors';

View file

@ -6,8 +6,8 @@
* If the contraints fails, an error message will be returned
*/
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { ISizePointer } from '../../../Interfaces/ISizePointer';
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
import { type ISizePointer } from '../../../Interfaces/ISizePointer';
import { Orientation } from '../../../Enums/Orientation';
import { ENABLE_HARD_RIGID } from '../../../utils/default';
import { FindContainerById, MakeChildrenIterator } from '../../../utils/itertools';
@ -141,9 +141,7 @@ export function ConstraintBodyInsideUnallocatedWidth(
// Check if there is still some space
if (availableWidths.length === 0) {
throw new Error(
'No available space found on the parent container. Try to free the parent a bit.'
);
throw new Error('No available space found on the parent container. Try to free the parent a bit.');
}
const containerId = container.properties.id;
@ -158,8 +156,7 @@ export function ConstraintBodyInsideUnallocatedWidth(
// Check if the container actually fit inside
// It will usually fit if it was alrady fitting
const availableWidthFound = availableWidths.find((width) =>
IsFitting(containerHeight, width)
);
IsFitting(containerHeight, width));
if (availableWidthFound === undefined) {
const { x, width } = TrySqueeze(containerY, containerHeight, containerMinHeight, containerId, availableWidths);
@ -189,8 +186,7 @@ export function ConstraintBodyInsideUnallocatedWidth(
// Check if the container actually fit inside
// It will usually fit if it was alrady fitting
const availableWidthFound = availableWidths.find((width) =>
IsFitting(containerWidth, width)
);
IsFitting(containerWidth, width));
if (availableWidthFound === undefined) {
const { x, width } = TrySqueeze(containerX, containerWidth, containerMinWidth, containerId, availableWidths);
@ -242,24 +238,26 @@ function TrySqueeze(
};
}
function SortAvailableWidthsByClosest(containerX: number, containerWidth: number, availableWidths: ISizePointer[]): void {
function SortAvailableWidthsByClosest(
containerX: number,
containerWidth: number,
availableWidths: ISizePointer[]
): void {
const middle = containerX + containerWidth / 2;
// Sort the available width to find the space with the closest position
availableWidths.sort(
(width1, width2) => {
let compared1X = width1.x;
if (width1.x < containerX) {
compared1X = width1.x + width1.width - containerWidth;
}
let compared2X = width2.x;
if (width2.x < containerX) {
compared2X = width2.x + width2.width - containerWidth;
}
return Math.abs(compared1X - middle) - Math.abs(compared2X - middle);
availableWidths.sort((width1, width2) => {
let compared1X = width1.x;
if (width1.x < containerX) {
compared1X = width1.x + width1.width - containerWidth;
}
);
let compared2X = width2.x;
if (width2.x < containerX) {
compared2X = width2.x + width2.width - containerWidth;
}
return Math.abs(compared1X - middle) - Math.abs(compared2X - middle);
});
}
/**
@ -268,8 +266,10 @@ function SortAvailableWidthsByClosest(containerX: number, containerWidth: number
* @param sizePointer Size space to check
* @returns
*/
function IsFitting(containerWidth: number,
sizePointer: ISizePointer): boolean {
function IsFitting(
containerWidth: number,
sizePointer: ISizePointer
): boolean {
return containerWidth <= sizePointer.width;
}
@ -280,7 +280,8 @@ function IsFitting(containerWidth: number,
* (except the fact that disk space is divided by block).
* @param container Container where to find an available width
* @param exception Container to exclude of the widths (since a container will be moved, it might need to be excluded)
* @returns {ISizePointer[]} Array of unallocated widths (x=position of the unallocated space, width=size of the allocated space)
* @returns {ISizePointer[]} Array of unallocated widths
* (x=position of the unallocated space, width=size of the allocated space)
*/
function GetAvailableWidths(
x: number,
@ -303,8 +304,12 @@ function GetAvailableWidths(
if (child === exception) {
continue;
}
const childX = isHorizontal ? child.properties.x : child.properties.y;
const childWidth = isHorizontal ? child.properties.width : child.properties.height;
const childX = isHorizontal
? child.properties.x
: child.properties.y;
const childWidth = isHorizontal
? child.properties.width
: child.properties.height;
// get the space of the child that is inside the parent
let newUnallocatedSpace: ISizePointer[] = [];

View file

@ -2,15 +2,16 @@
* Swap two flex container when one is overlapping another
*/
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
import { Orientation } from '../../../Enums/Orientation';
import { GetHorizontallyOverlappingContainers, GetVerticallyOverlappingContainers } from './AnchorBehaviors';
import { MakeChildrenIterator } from '../../../utils/itertools';
import { GetHorizontallyOverlappingContainers, GetVerticallyOverlappingContainers } from './AnchorBehaviors';
export function ApplySwap(
containers: Map<string, IContainerModel>,
container: IContainerModel,
parent: IContainerModel): void {
parent: IContainerModel
): void {
const children = [...MakeChildrenIterator(containers, parent.children)];
const isVertical = parent.properties.orientation === Orientation.Vertical;
@ -36,7 +37,10 @@ export function SwapHorizontally(container: IContainerModel, children: IContaine
}
// swap positions
[overlappingContainer.properties.x, container.properties.x] = [container.properties.x, overlappingContainer.properties.x];
[
overlappingContainer.properties.x,
container.properties.x
] = [container.properties.x, overlappingContainer.properties.x];
const indexContainer = children.indexOf(container);
const indexOverlapping = children.indexOf(overlappingContainer);
[children[indexContainer], children[indexOverlapping]] = [children[indexOverlapping], children[indexContainer]];
@ -56,7 +60,10 @@ export function SwapVertically(container: IContainerModel, children: IContainerM
}
// swap positions
[overlappingContainer.properties.y, container.properties.y] = [container.properties.y, overlappingContainer.properties.y];
[
overlappingContainer.properties.y,
container.properties.y
] = [container.properties.y, overlappingContainer.properties.y];
const indexContainer = children.indexOf(container);
const indexOverlapping = children.indexOf(overlappingContainer);
[children[indexContainer], children[indexOverlapping]] = [children[indexOverlapping], children[indexContainer]];

View file

@ -3,16 +3,22 @@ import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
import { ApplyParentTransform, FindContainerById } from '../../../utils/itertools';
import { RestoreX, RestoreY, TransformX, TransformY } from '../../../utils/svg';
export function ApplySymbol(containers: Map<string, IContainerModel>,
export function ApplySymbol(
containers: Map<string, IContainerModel>,
container: IContainerModel,
symbol: ISymbolModel): IContainerModel {
symbol: ISymbolModel
): IContainerModel {
if (symbol.isVertical) {
container.properties.y = TransformY(symbol.offset,
container.properties.y = TransformY(
symbol.offset,
symbol.height,
symbol.config.PositionReference);
container.properties.y = RestoreY(container.properties.y,
symbol.config.PositionReference
);
container.properties.y = RestoreY(
container.properties.y,
container.properties.height,
container.properties.positionReference);
container.properties.positionReference
);
const parent = FindContainerById(containers, container.properties.parentId);
let y = 0;
if (parent !== undefined && parent !== null) {
@ -24,10 +30,13 @@ export function ApplySymbol(containers: Map<string, IContainerModel>,
container.properties.x = TransformX(
symbol.offset,
symbol.width,
symbol.config.PositionReference);
container.properties.x = RestoreX(container.properties.x,
symbol.config.PositionReference
);
container.properties.x = RestoreX(
container.properties.x,
container.properties.width,
container.properties.positionReference);
container.properties.positionReference
);
const parent = FindContainerById(containers, container.properties.parentId);
let x = 0;
if (parent !== undefined && parent !== null) {

View file

@ -3,17 +3,22 @@ import './Editor.scss';
import { type IConfiguration } from '../../Interfaces/IConfiguration';
import { type IHistoryState } from '../../Interfaces/IHistoryState';
import { UI } from '../UI/UI';
import { UseCustomEvents, UseEditorListener } from '../../Events/EditorEvents';
import { MAX_HISTORY } from '../../utils/default';
import { FindContainerById } from '../../utils/itertools';
import { Menu } from '../Menu/Menu';
import { type IReplaceContainer } from '../../Interfaces/IReplaceContainer';
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';
import { MAX_HISTORY } from '../../utils/default';
import { AddSymbol, OnPropertyChange as OnSymbolPropertyChange, DeleteSymbol, SelectSymbol } from './Actions/SymbolOperations';
import { FindContainerById } from '../../utils/itertools';
import { Menu } from '../Menu/Menu';
import {
AddSymbol,
OnPropertyChange as OnSymbolPropertyChange,
DeleteSymbol,
SelectSymbol
} from './Actions/SymbolOperations';
import { InitActions } from './Actions/ContextMenuActions';
import { AddContainerToSelectedContainer, AddContainer } from './Actions/AddContainer';
import { type IReplaceContainer } from '../../Interfaces/IReplaceContainer';
interface IEditorProps {
root: Element | Document
@ -61,16 +66,20 @@ function UseNewHistoryState(
): (newHistory: IHistoryState[], historyCurrentStep?: number) => void {
return (newHistory, historyCurrentStep?: number) => {
setHistory(newHistory);
setHistoryCurrentStep(historyCurrentStep !== undefined && historyCurrentStep !== null ? historyCurrentStep : newHistory.length - 1);
setHistoryCurrentStep(historyCurrentStep !== undefined && historyCurrentStep !== null
? historyCurrentStep
: newHistory.length - 1);
};
}
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 [
replaceContainer,
setReplaceContainer
] = React.useState<IReplaceContainer>({ isReplacing: false, id: undefined, category: undefined });
const editorRef = useRef<HTMLDivElement>(null);
const setNewHistory = UseNewHistoryState(setHistory, setHistoryCurrentStep);
@ -86,9 +95,7 @@ export function Editor(props: IEditorProps): JSX.Element {
setHistoryCurrentStep,
() => {
const current = GetCurrentHistoryState(history, historyCurrentStep);
setNewHistory(
DeleteContainer(current.selectedContainerId, history, historyCurrentStep)
);
setNewHistory(DeleteContainer(current.selectedContainerId, history, historyCurrentStep));
},
ResetState
);
@ -134,29 +141,28 @@ export function Editor(props: IEditorProps): JSX.Element {
}}
replaceContainer={replaceContainer}
selectContainer={(container) => {
setNewHistory(
SelectContainer(
container,
history,
historyCurrentStep
));
setNewHistory(SelectContainer(
container,
history,
historyCurrentStep
));
}}
deleteContainer={(containerId: string) => {
setNewHistory(
DeleteContainer(
containerId,
history,
historyCurrentStep
));
setNewHistory(DeleteContainer(
containerId,
history,
historyCurrentStep
));
}}
onPropertyChange={(key, value, type) => {
setNewHistory(
OnPropertyChange(
key, value, type,
selected,
history,
historyCurrentStep
));
setNewHistory(OnPropertyChange(
key,
value,
type,
selected,
history,
historyCurrentStep
));
}}
addOrReplaceContainer={(type) => {
if (selected === null || selected === undefined) {
@ -183,49 +189,44 @@ export function Editor(props: IEditorProps): JSX.Element {
}
}}
addContainerAt={(index, type, parent) => {
setNewHistory(
AddContainer(
index,
type,
parent,
configuration,
history,
historyCurrentStep
)
);
setNewHistory(AddContainer(
index,
type,
parent,
configuration,
history,
historyCurrentStep
));
}}
addSymbol={(type) => {
setNewHistory(
AddSymbol(
type,
configuration,
history,
historyCurrentStep
));
setNewHistory(AddSymbol(
type,
configuration,
history,
historyCurrentStep
));
}}
onSymbolPropertyChange={(key, value) => {
setNewHistory(
OnSymbolPropertyChange(
key, value,
history,
historyCurrentStep
));
setNewHistory(OnSymbolPropertyChange(
key,
value,
history,
historyCurrentStep
));
}}
selectSymbol={(symbolId) => {
setNewHistory(
SelectSymbol(
symbolId,
history,
historyCurrentStep
));
setNewHistory(SelectSymbol(
symbolId,
history,
historyCurrentStep
));
}}
deleteSymbol={(symbolId) => {
setNewHistory(
DeleteSymbol(
symbolId,
history,
historyCurrentStep
));
setNewHistory(DeleteSymbol(
symbolId,
history,
historyCurrentStep
));
}}
saveEditorAsJSON={() => {
SaveEditorAsJSON(

View file

@ -88,7 +88,8 @@ function HandleOnDrop(
addContainer(
targetContainer.children.length,
type,
targetContainer.properties.id);
targetContainer.properties.id
);
return;
}
@ -113,7 +114,8 @@ function HandleOnDrop(
addContainer(
targetContainer.children.length,
type,
targetContainer.properties.id);
targetContainer.properties.id
);
} else {
const index = parent.children.indexOf(targetContainer.properties.id);
addContainer(
@ -219,12 +221,10 @@ function ElementsListRow(
? 'border-l-blue-400 group-hover:border-l-blue-300'
: 'border-l-slate-400 group-hover:border-l-slate-300';
for (let i = 0; i < depth; i++) {
verticalBars.push(
<span
key={`${key}-${i}`}
className={`h-full border-l-2 pr-2 ${verticalBarSelectedClass}`}
></span>
);
verticalBars.push(<span
key={`${key}-${i}`}
className={`h-full border-l-2 pr-2 ${verticalBarSelectedClass}`}
></span>);
}
const buttonSelectedClass: string = isSelected
@ -241,7 +241,9 @@ function ElementsListRow(
style={style}
title={container.properties.warning}
onClick={() => { selectContainer(container.properties.id); }}
onDrop={(event) => { HandleOnDrop(event, containers, mainContainer, addContainer); }}
onDrop={(event) => {
HandleOnDrop(event, containers, mainContainer, addContainer);
}}
onDragOver={(event) => { HandleDragOver(event, mainContainer); }}
onDragLeave={(event) => { HandleDragLeave(event); }}
>

View file

@ -6,14 +6,18 @@ interface IFloatingButtonProps {
className: string
}
function ToggleState(isHidden: boolean,
setHidden: React.Dispatch<React.SetStateAction<boolean>>): void {
function ToggleState(
isHidden: boolean,
setHidden: React.Dispatch<React.SetStateAction<boolean>>
): void {
setHidden(!isHidden);
}
export function FloatingButton(props: IFloatingButtonProps): JSX.Element {
const [isHidden, setHidden] = React.useState(true);
const buttonListClasses = isHidden ? 'invisible opacity-0' : 'visible opacity-100';
const buttonListClasses = isHidden
? 'invisible opacity-0'
: 'visible opacity-100';
const icon = isHidden
? <Bars3Icon className="floating-btn" />
: <XMarkIcon className="floating-btn" />;
@ -24,9 +28,10 @@ export function FloatingButton(props: IFloatingButtonProps): JSX.Element {
{props.children}
</div>
<button type="button"
className={'transition-all w-14 h-14 p-2 align-middle items-center justify-center rounded-full bg-blue-500 hover:bg-blue-800'}
className={'transition-all w-14 h-14 p-2 align-middle' +
' items-center justify-center rounded-full bg-blue-500 hover:bg-blue-800'}
title='Open menu'
onClick={() => ToggleState(isHidden, setHidden)}
onClick={() => { ToggleState(isHidden, setHidden); }}
>
{icon}
</button>

View file

@ -1,19 +1,23 @@
import * as React from 'react';
import { CameraIcon, ArrowUpOnSquareIcon } from '@heroicons/react/24/outline';
import { type IUIProps } from '../UI/UI';
import { FloatingButton } from './FloatingButton';
import { IUIProps } from '../UI/UI';
export function MenuButton(props: IUIProps): JSX.Element {
return <FloatingButton className={'fixed z-10 flex flex-col gap-2 items-center bottom-12 right-12'}>
<button type="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'}
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}
>
<ArrowUpOnSquareIcon className="heroicon text-white" />
</button>
<button type="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'}
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}
>

View file

@ -1,6 +1,6 @@
import * as React from 'react';
import { FixedSizeList as List } from 'react-window';
import { IHistoryState } from '../../Interfaces/IHistoryState';
import { type IHistoryState } from '../../Interfaces/IHistoryState';
import { TITLE_BAR_HEIGHT } from '../Sidebar/Sidebar';
interface IHistoryProps {
@ -23,7 +23,7 @@ export function History(props: IHistoryProps): JSX.Element {
<button type="button"
key={reversedIndex}
style={style}
onClick={() => props.jumpTo(reversedIndex)}
onClick={() => { props.jumpTo(reversedIndex); }}
title={step.lastAction}
className={`w-full elements-sidebar-row border-blue-500 whitespace-pre overflow-hidden
text-left text-sm font-medium transition-all ${selectedClass}`}

View file

@ -37,7 +37,9 @@ export function TextInputGroup(props: ITextInputGroupProps): JSX.Element {
}
}
const warningClass = props.value !== value ? 'focus:border-yellow-300 border-yellow-300 focus:ring-yellow-300 ring-yellow-300' : '';
const warningClass = props.value !== value
? 'focus:border-yellow-300 border-yellow-300 focus:ring-yellow-300 ring-yellow-300'
: '';
return <>
<label
@ -53,7 +55,7 @@ export function TextInputGroup(props: ITextInputGroupProps): JSX.Element {
className={`${className} ${props.inputClassName} ${warningClass}`}
type={props.type}
value={value}
onChange={(event) => setValue(event.target.value)}
onChange={(event) => { setValue(event.target.value); }}
onKeyUp={OnKeyUp}
min={props.min}
max={props.max}

View file

@ -1,6 +1,6 @@
import * as React from 'react';
import { createContext, useState } from 'react';
import { ILanguage } from '../../Interfaces/ILanguage';
import { type ILanguage } from '../../Interfaces/ILanguage';
import { languageOptions, translations } from '../../Translations/Translations';
import { DEFAULT_LANGUAGE } from '../../utils/default';
@ -10,13 +10,17 @@ export const LanguageContext = createContext<ILanguage>({
dictionary: translations.en
});
export function LanguageProvider({ children }: { children: React.ReactNode | React.ReactNode[] | undefined }): JSX.Element {
export function LanguageProvider(
{ children }: { children: React.ReactNode | React.ReactNode[] | undefined }
): JSX.Element {
const [language, setLanguage] = useState(DEFAULT_LANGUAGE);
const provider = {
language,
dictionary: translations[language],
languageChange: (selected: string) => {
const newLanguage = languageOptions[selected] !== undefined ? selected : DEFAULT_LANGUAGE;
const newLanguage = languageOptions[selected] !== undefined
? selected
: DEFAULT_LANGUAGE;
setLanguage(newLanguage);
}
};

View file

@ -45,7 +45,7 @@ export function MainMenu(props: IMainMenuProps): JSX.Element {
</label>
</form>
<button type="button"
onClick={() => setWindowState(WindowState.Main)}
onClick={() => { setWindowState(WindowState.Main); }}
className='normal-btn block
mt-8 '
>
@ -70,7 +70,7 @@ export function MainMenu(props: IMainMenuProps): JSX.Element {
<button
type="button"
className='mainmenu-btn'
onClick={() => setWindowState(WindowState.Load)}
onClick={() => { setWindowState(WindowState.Load); }}
>
{Text({ textId: '@LoadConfigFile' })}
</button>

View file

@ -1,6 +1,6 @@
import useSize from '@react-hook/size';
import * as React from 'react';
import { IPoint } from '../../Interfaces/IPoint';
import { type IPoint } from '../../Interfaces/IPoint';
import { MenuItem } from './MenuItem';
interface IMenuProps {
@ -97,15 +97,22 @@ export function Menu(props: IMenuProps): JSX.Element {
AddUniversalActions(props, children, count, target);
}
const visible = isOpen && children.length > 0 ? 'visible opacity-1' : 'invisible opacity-0';
const visible = isOpen && children.length > 0
? 'visible opacity-1'
: 'invisible opacity-0';
const isOutOfBoundHorizontally = contextMenuPosition.x + menuWidth > window.innerWidth;
const isOutOfBoundVertically = contextMenuPosition.y + menuHeight > window.innerHeight;
const finalHorizontalPosition = isOutOfBoundHorizontally ? contextMenuPosition.x - menuWidth : contextMenuPosition.x;
const finalVerticalPosition = isOutOfBoundVertically ? contextMenuPosition.y - menuWidth : contextMenuPosition.y;
const finalHorizontalPosition = isOutOfBoundHorizontally
? contextMenuPosition.x - menuWidth
: contextMenuPosition.x;
const finalVerticalPosition = isOutOfBoundVertically
? contextMenuPosition.y - menuWidth
: contextMenuPosition.y;
return (
<div
ref={menuRef}
className={`fixed context-menu ${MENU_VERTICAL_PADDING_CLASS} ${MENU_WIDTH_CLASS} ${props.className ?? ''} ${visible}`}
className={'fixed context-menu' +
`${MENU_VERTICAL_PADDING_CLASS} ${MENU_WIDTH_CLASS} ${props.className ?? ''} ${visible}`}
style={{
left: finalHorizontalPosition,
top: finalVerticalPosition
@ -137,7 +144,7 @@ function AddClassSpecificActions(
text={action.text}
title={action.title}
shortcut={action.shortcut}
onClick={() => action.action(target)} />);
onClick={() => { action.action(target); }} />);
});
children.push(<hr key={`contextmenu-hr-${count}`} className='border-slate-400' />);
}
@ -156,7 +163,7 @@ function AddUniversalActions(props: IMenuProps, children: JSX.Element[], count:
text={action.text}
title={action.title}
shortcut={action.shortcut}
onClick={() => action.action(target)} />);
onClick={() => { action.action(target); }} />);
});
}

View file

@ -13,7 +13,7 @@ export function MenuItem(props: IMenuItemProps): JSX.Element {
<button type="button"
className={`flex place-content-between ${props.className ?? ''}`}
title={props.title}
onClick={() => props.onClick()}>
onClick={() => { props.onClick(); }}>
{props.text}
<span dangerouslySetInnerHTML={{ __html: props.shortcut ?? '' }} />
</button>

View file

@ -2,8 +2,8 @@ import { TrashIcon } from '@heroicons/react/24/outline';
import * as React from 'react';
import { FixedSizeList as List } from 'react-window';
import { MessageType } from '../../Enums/MessageType';
import { IHistoryState } from '../../Interfaces/IHistoryState';
import { IMessage } from '../../Interfaces/IMessage';
import { type IHistoryState } from '../../Interfaces/IHistoryState';
import { type IMessage } from '../../Interfaces/IMessage';
import { TITLE_BAR_HEIGHT } from '../Sidebar/Sidebar';
import { Text } from '../Text/Text';
@ -14,7 +14,7 @@ interface IMessagesProps {
}
export function Messages(props: IMessagesProps): JSX.Element {
function Row({ index, style }: {index: number, style: React.CSSProperties}): JSX.Element {
function Row({ index, style }: { index: number, style: React.CSSProperties }): JSX.Element {
const reversedIndex = (props.messages.length - 1) - index;
const message = props.messages[reversedIndex];
let classType = '';

View file

@ -1,5 +1,11 @@
import React from 'react';
import { Bars3BottomLeftIcon, Bars3CenterLeftIcon, Bars3Icon, Bars3BottomRightIcon, Bars2Icon } from '@heroicons/react/24/outline';
import {
Bars3BottomLeftIcon,
Bars3CenterLeftIcon,
Bars3Icon,
Bars3BottomRightIcon,
Bars2Icon
} from '@heroicons/react/24/outline';
import { PositionReference } from '../../Enums/PositionReference';
import { RadioGroupButtons } from './RadioGroupButtons';

View file

@ -1,5 +1,5 @@
import * as React from 'react';
import { IInputGroup } from '../../Interfaces/IInputGroup';
import { type IInputGroup } from '../../Interfaces/IInputGroup';
interface IRadioGroupButtonsProps {
name: string

View file

@ -1,7 +1,7 @@
import * as React from 'react';
import { Interweave, Node } from 'interweave';
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { IContainerProperties } from '../../../Interfaces/IContainerProperties';
import { Interweave, type Node } from 'interweave';
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
import { type IContainerProperties } from '../../../Interfaces/IContainerProperties';
import { Camelize } from '../../../utils/stringtools';
import { SHOW_TEXT } from '../../../utils/default';
import { FindContainerById } from '../../../utils/itertools';
@ -19,23 +19,22 @@ interface IContainerProps {
* @returns Render the container
*/
export function Container(props: IContainerProps): JSX.Element {
const containersElements = props.model.children.map(
childId => {
const child = FindContainerById(props.containers, childId);
const containersElements = props.model.children.map(childId => {
const child = FindContainerById(props.containers, childId);
if (child === undefined) {
return <></>;
}
if (child === undefined) {
return <></>;
}
return <Container
key={`container-${child.properties.id}`}
containers={props.containers}
model={child}
depth={props.depth + 1}
scale={props.scale}
selectContainer={props.selectContainer}
/>;
});
return <Container
key={`container-${child.properties.id}`}
containers={props.containers}
model={child}
depth={props.depth + 1}
scale={props.scale}
selectContainer={props.selectContainer}
/>;
});
const width: number = props.model.properties.width;
const height: number = props.model.properties.height;
@ -67,7 +66,7 @@ export function Container(props: IContainerProps): JSX.Element {
width={width}
height={height}
style={style}
onClick={() => props.selectContainer(props.model.properties.id)}
onClick={() => { props.selectContainer(props.model.properties.id); }}
>
</rect>);
@ -108,7 +107,7 @@ function CreateReactCustomSVG(customSVG: string, properties: IContainerPropertie
function Transform(node: HTMLElement, children: Node[], properties: IContainerProperties): React.ReactNode {
const supportedTags = ['line', 'path', 'rect'];
if (supportedTags.includes(node.tagName.toLowerCase())) {
const attributes: { [att: string]: string | object | null } = {};
const attributes: Record<string, string | object | null> = {};
node.getAttributeNames().forEach(attName => {
const attributeValue = node.getAttribute(attName);
if (attributeValue === null) {

View file

@ -11,9 +11,9 @@ import {
} from '../../../utils/default';
import { FindContainerById, MakeRecursionDFSIterator, Pairwise } from '../../../utils/itertools';
import { TransformX, TransformY } from '../../../utils/svg';
import { Dimension } from './Dimension';
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
import { Dimension } from './Dimension';
interface IDimensionLayerProps {
containers: Map<string, IContainerModel>
@ -160,7 +160,8 @@ function Dimensions({ containers, symbols, root, scale }: IDimensionLayerProps):
return dimensions;
}
function AddHorizontalSymbolDimension(symbol: ISymbolModel,
function AddHorizontalSymbolDimension(
symbol: ISymbolModel,
dimensions: React.ReactNode[],
scale: number,
depth: number
@ -173,22 +174,21 @@ function AddHorizontalSymbolDimension(symbol: ISymbolModel,
const text = width
.toFixed(0)
.toString();
dimensions.push(
<Dimension
key={id}
id={id}
xStart={0}
yStart={-offset}
xEnd={width}
yEnd={-offset}
text={text}
scale={scale}
style={DEFAULT_DIMENSION_SYMBOL_STYLE}/>
);
dimensions.push(<Dimension
key={id}
id={id}
xStart={0}
yStart={-offset}
xEnd={width}
yEnd={-offset}
text={text}
scale={scale}
style={DEFAULT_DIMENSION_SYMBOL_STYLE}/>);
}
}
function AddVerticalSymbolDimension(symbol: ISymbolModel,
function AddVerticalSymbolDimension(
symbol: ISymbolModel,
dimensions: React.ReactNode[],
scale: number,
depth: number
@ -201,18 +201,16 @@ function AddVerticalSymbolDimension(symbol: ISymbolModel,
const text = height
.toFixed(0)
.toString();
dimensions.push(
<Dimension
key={id}
id={id}
xStart={-offset}
yStart={height}
xEnd={-offset}
yEnd={0}
text={text}
scale={scale}
style={DEFAULT_DIMENSION_SYMBOL_STYLE}/>
);
dimensions.push(<Dimension
key={id}
id={id}
xStart={-offset}
yStart={height}
xEnd={-offset}
yEnd={0}
text={text}
scale={scale}
style={DEFAULT_DIMENSION_SYMBOL_STYLE}/>);
}
}
@ -249,12 +247,16 @@ function AddHorizontalChildrenDimension(
return;
}
let xChildrenStart = TransformX(lastChild.properties.x,
let xChildrenStart = TransformX(
lastChild.properties.x,
lastChild.properties.width,
lastChild.properties.positionReference);
let xChildrenEnd = TransformX(lastChild.properties.x,
lastChild.properties.positionReference
);
let xChildrenEnd = TransformX(
lastChild.properties.x,
lastChild.properties.width,
lastChild.properties.positionReference);
lastChild.properties.positionReference
);
// Find the min and max
for (let i = container.children.length - 2; i >= 0; i--) {
@ -316,12 +318,16 @@ function AddVerticalChildrenDimension(
return;
}
let yChildrenStart = TransformY(lastChild.properties.y,
let yChildrenStart = TransformY(
lastChild.properties.y,
lastChild.properties.height,
lastChild.properties.positionReference);
let yChildrenEnd = TransformY(lastChild.properties.y,
lastChild.properties.positionReference
);
let yChildrenEnd = TransformY(
lastChild.properties.y,
lastChild.properties.height,
lastChild.properties.positionReference);
lastChild.properties.positionReference
);
// Find the min and max
for (let i = container.children.length - 2; i >= 0; i--) {
@ -398,9 +404,7 @@ function AddHorizontalBorrowerDimension(
const restoredX = x + childCurrentTransform[0];
marks.push(
restoredX
);
marks.push(restoredX);
}
const restoredX = container.properties.x + currentTransform[0];
@ -458,9 +462,7 @@ function AddVerticalBorrowerDimension(
const restoredy = y + childCurrentTransform[1];
marks.push(
restoredy
);
marks.push(restoredy);
}
const restoredY = container.properties.y + currentTransform[1];
@ -515,18 +517,16 @@ function AddVerticalSelfDimension(
[yStart, yEnd] = [yEnd, yStart];
}
dimensions.push(
<Dimension
key={idVert}
id={idVert}
xStart={xDim}
yStart={yStart}
xEnd={xDim}
yEnd={yEnd}
text={textVert}
scale={scale}
style={style}/>
);
dimensions.push(<Dimension
key={idVert}
id={idVert}
xStart={xDim}
yStart={yStart}
xEnd={xDim}
yEnd={yEnd}
text={textVert}
scale={scale}
style={style}/>);
}
function AddHorizontalSelfDimension(
@ -544,18 +544,16 @@ function AddHorizontalSelfDimension(
const text = width
.toFixed(0)
.toString();
dimensions.push(
<Dimension
key={id}
id={id}
xStart={xStart}
yStart={yDim}
xEnd={xEnd}
yEnd={yDim}
text={text}
scale={scale}
style={style}/>
);
dimensions.push(<Dimension
key={id}
id={id}
xStart={xStart}
yStart={yDim}
xEnd={xEnd}
yEnd={yDim}
text={text}
scale={scale}
style={style}/>);
}
function AddHorizontalSelfMarginsDimension(
@ -574,18 +572,16 @@ function AddHorizontalSelfMarginsDimension(
const text = left
.toFixed(0)
.toString();
dimensions.push(
<Dimension
key={id}
id={id}
xStart={xStart}
yStart={yDim}
xEnd={xEnd}
yEnd={yDim}
text={text}
scale={scale}
style={style}/>
);
dimensions.push(<Dimension
key={id}
id={id}
xStart={xStart}
yStart={yDim}
xEnd={xEnd}
yEnd={yDim}
text={text}
scale={scale}
style={style}/>);
}
const right = container.properties.margin.right;
@ -596,18 +592,16 @@ function AddHorizontalSelfMarginsDimension(
const text = right
.toFixed(0)
.toString();
dimensions.push(
<Dimension
key={id}
id={id}
xStart={xStart}
yStart={yDim}
xEnd={xEnd}
yEnd={yDim}
text={text}
scale={scale}
style={style}/>
);
dimensions.push(<Dimension
key={id}
id={id}
xStart={xStart}
yStart={yDim}
xEnd={xEnd}
yEnd={yDim}
text={text}
scale={scale}
style={style}/>);
}
}
@ -633,18 +627,16 @@ function AddVerticalSelfMarginDimension(
[yStart, yEnd] = [yEnd, yStart];
}
dimensions.push(
<Dimension
key={idVert}
id={idVert}
xStart={xDim}
yStart={yStart}
xEnd={xDim}
yEnd={yEnd}
text={textVert}
scale={scale}
style={style}/>
);
dimensions.push(<Dimension
key={idVert}
id={idVert}
xStart={xDim}
yStart={yStart}
xEnd={xDim}
yEnd={yEnd}
text={textVert}
scale={scale}
style={style}/>);
}
const bottom = container.properties.margin.bottom;
if (bottom != null && bottom > 0) {
@ -659,17 +651,15 @@ function AddVerticalSelfMarginDimension(
[yStart, yEnd] = [yEnd, yStart];
}
dimensions.push(
<Dimension
key={idVert}
id={idVert}
xStart={xDim}
yStart={yStart}
xEnd={xDim}
yEnd={yEnd}
text={textVert}
scale={scale}
style={style}/>
);
dimensions.push(<Dimension
key={idVert}
id={idVert}
xStart={xDim}
yStart={yStart}
xEnd={xDim}
yEnd={yEnd}
text={textVert}
scale={scale}
style={style}/>);
}
}

View file

@ -26,7 +26,11 @@ export function SelectorContainer(props: ISelectorContainerProps): JSX.Element {
props.selected.properties.height
];
({ x, y, width, height } = RemoveMargin(x, y, width, height,
({ x, y, width, height } = RemoveMargin(
x,
y,
width,
height,
props.selected.properties.margin.left,
props.selected.properties.margin.bottom,
props.selected.properties.margin.top,

View file

@ -1,6 +1,6 @@
import '../Selector.scss';
import * as React from 'react';
import { DIMENSION_MARGIN, SYMBOL_MARGIN } from '../../../../utils/default';
import { SYMBOL_MARGIN } from '../../../../utils/default';
import { type ISymbolModel } from '../../../../Interfaces/ISymbolModel';
import { Selector } from '../Selector/Selector';

View file

@ -1,5 +1,5 @@
import * as React from 'react';
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
import { Symbol } from './Symbol';
interface ISymbolLayerProps {
@ -10,13 +10,11 @@ interface ISymbolLayerProps {
export function SymbolLayer(props: ISymbolLayerProps): JSX.Element {
const symbols: JSX.Element[] = [];
props.symbols.forEach((symbol) => {
symbols.push(
<Symbol
key={`symbol-${symbol.id}`}
model={symbol}
scale={props.scale}
/>
);
symbols.push(<Symbol
key={`symbol-${symbol.id}`}
model={symbol}
scale={props.scale}
/>);
});
return (
<g>

View file

@ -1,13 +1,13 @@
import * as React from 'react';
import { ReactSVGPanZoom, type Tool, TOOL_PAN, type Value, ALIGN_CENTER } from 'react-svg-pan-zoom';
import { MAX_FRAMERATE } from '../../utils/default';
import { type DrawParams } from '../Viewer/Viewer';
import { Container } from './Elements/Container';
import { SelectorContainer } from './Elements/SelectorContainer/SelectorContainer';
import { MAX_FRAMERATE } from '../../utils/default';
import { SymbolLayer } from './Elements/SymbolLayer';
import { DimensionLayer } from './Elements/DimensionLayer';
import { SelectorSymbol } from './Elements/SelectorSymbol/SelectorSymbol';
import { type IToolbarProps, Toolbar } from './SVGReactPanZoom/ui-toolbar/toolbar';
import { type DrawParams } from '../Viewer/Viewer';
interface ISVGProps {
className?: string

View file

@ -47,8 +47,12 @@ export class ToolbarButton extends React.Component<IToolbarButtonProps, IToolbar
display: 'block',
width: '24px',
height: '24px',
margin: [POSITION_TOP, POSITION_BOTTOM].includes(this.props.toolbarPosition) ? '2px 1px' : '1px 2px',
color: this.props.active || this.state.hover ? this.props.activeColor : '#FFF',
margin: [POSITION_TOP, POSITION_BOTTOM].includes(this.props.toolbarPosition)
? '2px 1px'
: '1px 2px',
color: this.props.active || this.state.hover
? this.props.activeColor
: '#FFF',
transition: 'color 200ms ease',
background: 'none',
padding: '0px',

View file

@ -118,18 +118,34 @@ export function Toolbar({
const style: React.CSSProperties = {
// position
position: 'absolute',
transform: [POSITION_TOP, POSITION_BOTTOM].includes(position) ? 'translate(-50%, 0px)' : 'none',
top: [POSITION_LEFT, POSITION_RIGHT, POSITION_TOP].includes(position) ? '5px' : 'unset',
left: [POSITION_TOP, POSITION_BOTTOM].includes(position) ? '50%' : (POSITION_LEFT === position ? '5px' : 'unset'),
right: [POSITION_RIGHT].includes(position) ? '5px' : 'unset',
bottom: [POSITION_BOTTOM].includes(position) ? '5px' : 'unset',
transform: [POSITION_TOP, POSITION_BOTTOM].includes(position)
? 'translate(-50%, 0px)'
: 'none',
top: [POSITION_LEFT, POSITION_RIGHT, POSITION_TOP].includes(position)
? '5px'
: 'unset',
left: [POSITION_TOP, POSITION_BOTTOM].includes(position)
? '50%'
: (POSITION_LEFT === position
? '5px'
: 'unset'),
right: [POSITION_RIGHT].includes(position)
? '5px'
: 'unset',
bottom: [POSITION_BOTTOM].includes(position)
? '5px'
: 'unset',
// inner styling
backgroundColor: 'rgba(19, 20, 22, 0.90)',
borderRadius: '2px',
display: 'flex',
flexDirection: isHorizontal ? 'row' : 'column',
padding: isHorizontal ? '1px 2px' : '2px 1px'
flexDirection: isHorizontal
? 'row'
: 'column',
padding: isHorizontal
? '1px 2px'
: '2px 1px'
};
return (

View file

@ -1,5 +1,5 @@
import * as React from 'react';
import { IInputGroup } from '../../Interfaces/IInputGroup';
import { type IInputGroup } from '../../Interfaces/IInputGroup';
interface ISelectProps {
labelKey?: string

View file

@ -9,7 +9,9 @@ interface IToggleSidebarProps {
export function ToggleSideBar({ title, checked, onClick }: IToggleSidebarProps): JSX.Element {
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
className={'w-full py-2'}
type='button'

View file

@ -13,22 +13,26 @@ interface ISymbolFormProps {
onChange: (key: string, value: string | number | boolean) => void
}
function Restore(offset: number,
function Restore(
offset: number,
isVertical: boolean,
height: number,
width: number,
position: PositionReference | undefined): number {
position: PositionReference | undefined
): number {
if (isVertical) {
return RestoreY(offset, height, position);
} else {
return RestoreX(offset, width, position);
}
}
function Transform(offset: number,
function Transform(
offset: number,
isVertical: boolean,
height: number,
width: number,
position: PositionReference | undefined): number {
position: PositionReference | undefined
): number {
if (isVertical) {
return TransformY(offset, height, position);
} else {
@ -63,18 +67,24 @@ export function SymbolForm(props: ISymbolFormProps): JSX.Element {
labelClassName=''
inputClassName=''
type='number'
value={Transform(props.symbol.offset,
value={Transform(
props.symbol.offset,
props.symbol.isVertical,
props.symbol.height,
props.symbol.width,
props.symbol.config.PositionReference).toString()}
props.symbol.config.PositionReference
).toString()}
onChange={(value) => {
props.onChange('offset',
Restore(Number(value),
props.onChange(
'offset',
Restore(
Number(value),
props.symbol.isVertical,
props.symbol.height,
props.symbol.width,
props.symbol.config.PositionReference));
props.symbol.config.PositionReference
)
);
}} />
<ToggleButton
labelText={Text({ textId: '@IsVertical' })}

View file

@ -1,5 +1,5 @@
import React from 'react';
import { ISymbolModel } from '../../Interfaces/ISymbolModel';
import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
import { SymbolForm } from './SymbolForm';
interface ISymbolPropertiesProps {

View file

@ -1,5 +1,5 @@
import * as React from 'react';
import { IAvailableSymbol } from '../../Interfaces/IAvailableSymbol';
import { type IAvailableSymbol } from '../../Interfaces/IAvailableSymbol';
import { TruncateString } from '../../utils/stringtools';
interface ISymbolsProps {
@ -20,9 +20,9 @@ export function Symbols(props: ISymbolsProps): JSX.Element {
key={componentOption.Name}
id={componentOption.Name}
title={componentOption.Name}
onClick={() => props.buttonOnClick(componentOption.Name)}
onClick={() => { props.buttonOnClick(componentOption.Name); }}
draggable={true}
onDragStart={(event) => HandleDragStart(event)}
onDragStart={(event) => { HandleDragStart(event); }}
>
<div>
<img
@ -41,9 +41,9 @@ export function Symbols(props: ISymbolsProps): JSX.Element {
key={componentOption.Name}
id={componentOption.Name}
title={componentOption.Name}
onClick={() => props.buttonOnClick(componentOption.Name)}
onClick={() => { props.buttonOnClick(componentOption.Name); }}
draggable={true}
onDragStart={(event) => HandleDragStart(event)}
onDragStart={(event) => { HandleDragStart(event); }}
>
{TruncateString(componentOption.Name, 5)}

View file

@ -1,4 +1,5 @@
import * as React from 'react';
import { type Dispatch } from 'react';
import { ElementsSidebar } from '../ElementsSidebar/ElementsSidebar';
import { History } from '../History/History';
import { Bar, BAR_WIDTH } from '../Bar/Bar';
@ -12,13 +13,12 @@ import { Viewer } from '../Viewer/Viewer';
import { Settings } from '../Settings/Settings';
import { type IMessage } from '../../Interfaces/IMessage';
import { DISABLE_API } from '../../utils/default';
import { UseWorker, UseAsync } from './UseWorker';
import { FindContainerById } from '../../utils/itertools';
import { type IEditorState } from '../../Interfaces/IEditorState';
import { GetCurrentHistoryState } from '../Editor/Editor';
import { Text } from '../Text/Text';
import { type IReplaceContainer } from '../../Interfaces/IReplaceContainer';
import { type Dispatch } from 'react';
import { UseWorker, UseAsync } from './UseWorker';
export interface IUIProps {
editorState: IEditorState
@ -223,7 +223,9 @@ export function UI({ editorState, replaceContainer, setReplaceContainer, ...meth
isLeftSidebarOpenClasses.add('left-sidebar-single');
}
const clickRestrictionsClasses = replaceContainer.isReplacing ? 'pointer-events-none opacity-50' : '';
const clickRestrictionsClasses = replaceContainer.isReplacing
? 'pointer-events-none opacity-50'
: '';
const isComponentsOpen = selectedSidebar === SidebarType.Components;
const isSymbolsOpen = selectedSidebar === SidebarType.Symbols;

View file

@ -1,8 +1,8 @@
import * as React from 'react';
import { IHistoryState } from '../../Interfaces/IHistoryState';
import { IGetFeedbackRequest } from '../../Interfaces/IGetFeedbackRequest';
import { IGetFeedbackResponse } from '../../Interfaces/IGetFeedbackResponse';
import { IMessage } from '../../Interfaces/IMessage';
import { type IHistoryState } from '../../Interfaces/IHistoryState';
import { type IGetFeedbackRequest } from '../../Interfaces/IGetFeedbackRequest';
import { type IGetFeedbackResponse } from '../../Interfaces/IGetFeedbackResponse';
import { type IMessage } from '../../Interfaces/IMessage';
import { GetCircularReplacer } from '../../utils/saveload';
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
@ -11,7 +11,8 @@ const myWorker = window.Worker && new Worker('workers/message_worker.js');
export function UseWorker(
state: IHistoryState,
configurationUrl: string | undefined,
setMessages: React.Dispatch<React.SetStateAction<IMessage[]>>): void {
setMessages: React.Dispatch<React.SetStateAction<IMessage[]>>
): void {
React.useEffect(() => {
// use webworker for the stringify to avoid freezing
myWorker.postMessage({
@ -32,7 +33,8 @@ export function UseWorker(
export function UseAsync(
state: IHistoryState,
configurationUrl: string | undefined,
setMessages: React.Dispatch<React.SetStateAction<IMessage[]>>): void {
setMessages: React.Dispatch<React.SetStateAction<IMessage[]>>
): void {
React.useEffect(() => {
const request: IGetFeedbackRequest = {
// eslint-disable-next-line @typescript-eslint/naming-convention
@ -48,8 +50,7 @@ export function UseAsync(
}),
body: dataParsed
})
.then(async(response) => await response.json()
)
.then(async(response) => await response.json())
.then(async(json: IGetFeedbackResponse) => {
setMessages(json.messages);
});

View file

@ -1,4 +1,5 @@
import * as React from 'react';
import { useState } from 'react';
import { type IContainerModel } from '../../Interfaces/IContainerModel';
import { type IHistoryState } from '../../Interfaces/IHistoryState';
import { USE_EXPERIMENTAL_CANVAS_API } from '../../utils/default';
@ -6,7 +7,6 @@ import { FindContainerById } from '../../utils/itertools';
import { BAR_WIDTH } from '../Bar/Bar';
import { Canvas } from '../Canvas/Canvas';
import { SelectorMode, SVG } from '../SVG/SVG';
import { useState } from 'react';
import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
interface IViewerProps {
@ -30,7 +30,9 @@ export interface DrawParams {
}
function computeWidth(margin: number): number {
return window.innerWidth - (window.innerWidth < 768 ? BAR_WIDTH : margin);
return window.innerWidth - (window.innerWidth < 768
? BAR_WIDTH
: margin);
}
export function Viewer({

View file

@ -1,9 +1,9 @@
import { useEffect } from 'react';
import { AppState } from '../Enums/AppState';
import { IConfiguration } from '../Interfaces/IConfiguration';
import { IEditorState } from '../Interfaces/IEditorState';
import { IHistoryState } from '../Interfaces/IHistoryState';
import { ILanguage } from '../Interfaces/ILanguage';
import { type IConfiguration } from '../Interfaces/IConfiguration';
import { type IEditorState } from '../Interfaces/IEditorState';
import { type IHistoryState } from '../Interfaces/IHistoryState';
import { type ILanguage } from '../Interfaces/ILanguage';
import { languageOptions, translations } from '../Translations/Translations';
import { GetDefaultEditorState as GetDefaultEditorStateAction } from '../utils/default';
import { Revive, ReviveHistory as ReviveHistoryAction } from '../utils/saveload';
@ -49,7 +49,7 @@ export function UseCustomEvents(
const funcs = new Map<string, () => void>();
for (const event of events) {
function Func(eventInitDict?: CustomEventInit): void {
return event.func({
event.func({
root,
languageContext,
setEditor,

View file

@ -1,11 +1,21 @@
import { useEffect } from 'react';
import { AddContainer as AddContainerAction, AddContainerToSelectedContainer as AddContainerToSelectedContainerAction } from '../Components/Editor/Actions/AddContainer';
import { DeleteContainer as DeleteContainerAction, SelectContainer as SelectContainerAction } from '../Components/Editor/Actions/ContainerOperations';
import { AddSymbol as AddSymbolAction, DeleteSymbol as DeleteSymbolAction, SelectSymbol as SelectSymbolAction } from '../Components/Editor/Actions/SymbolOperations';
import {
AddContainer as AddContainerAction,
AddContainerToSelectedContainer as AddContainerToSelectedContainerAction
} from '../Components/Editor/Actions/AddContainer';
import {
DeleteContainer as DeleteContainerAction,
SelectContainer as SelectContainerAction
} from '../Components/Editor/Actions/ContainerOperations';
import {
AddSymbol as AddSymbolAction,
DeleteSymbol as DeleteSymbolAction,
SelectSymbol as SelectSymbolAction
} from '../Components/Editor/Actions/SymbolOperations';
import { GetCurrentHistory } from '../Components/Editor/Editor';
import { IConfiguration } from '../Interfaces/IConfiguration';
import { IEditorState } from '../Interfaces/IEditorState';
import { IHistoryState } from '../Interfaces/IHistoryState';
import { type IConfiguration } from '../Interfaces/IConfiguration';
import { type IEditorState } from '../Interfaces/IEditorState';
import { type IHistoryState } from '../Interfaces/IHistoryState';
import { FindContainerById } from '../utils/itertools';
import { GetCircularReplacer } from '../utils/saveload';
@ -61,7 +71,7 @@ export function UseCustomEvents(
for (const event of events) {
function Func(eventInitDict?: CustomEventInit): void {
return event.func({
event.func({
root,
editorState,
setNewHistory,
@ -112,7 +122,9 @@ function GetEditorStateAsString({
root,
editorState
}: IEditorEventParams): void {
const spaces = import.meta.env.DEV ? 4 : 0;
const spaces = import.meta.env.DEV
? 4
: 0;
const data = JSON.stringify(editorState, GetCircularReplacer(), spaces);
const customEvent = new CustomEvent<string>('getEditorStateAsString', { detail: data });
root.dispatchEvent(customEvent);
@ -137,7 +149,8 @@ function GetCurrentHistoryState({
}: IEditorEventParams): void {
const customEvent = new CustomEvent<IHistoryState>(
'getCurrentHistoryState',
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
);
root.dispatchEvent(customEvent);
}
@ -155,7 +168,8 @@ function AppendNewState({
const customEvent = new CustomEvent<IHistoryState>(
'appendNewState',
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
);
root.dispatchEvent(customEvent);
}
@ -184,7 +198,8 @@ function AddContainer({
const customEvent = new CustomEvent<IHistoryState>(
'addContainer',
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
);
root.dispatchEvent(customEvent);
}
@ -214,7 +229,8 @@ function AddContainerToSelectedContainer({
const customEvent = new CustomEvent<IHistoryState>(
'addContainerToSelectedContainer',
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
);
root.dispatchEvent(customEvent);
}
@ -246,7 +262,8 @@ function AppendContainer({
const customEvent = new CustomEvent<IHistoryState>(
'appendContainerToSelectedContainer',
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
);
root.dispatchEvent(customEvent);
}
@ -277,7 +294,8 @@ function AppendContainerToSelectedContainer({
const customEvent = new CustomEvent<IHistoryState>(
'appendContainerToSelectedContainer',
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
);
root.dispatchEvent(customEvent);
}
@ -302,7 +320,8 @@ function SelectContainer({
const customEvent = new CustomEvent<IHistoryState>(
'selectContainer',
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
);
root.dispatchEvent(customEvent);
}
@ -327,7 +346,8 @@ function DeleteContainer({
const customEvent = new CustomEvent<IHistoryState>(
'deleteContainer',
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
);
root.dispatchEvent(customEvent);
}
@ -353,7 +373,8 @@ function AddSymbol({
const customEvent = new CustomEvent<IHistoryState>(
'AddSymbol',
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
);
root.dispatchEvent(customEvent);
}
@ -378,7 +399,8 @@ function SelectSymbol({
const customEvent = new CustomEvent<IHistoryState>(
'SelectSymbol',
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
);
root.dispatchEvent(customEvent);
}
@ -402,6 +424,7 @@ function DeleteSymbol({
const customEvent = new CustomEvent<IHistoryState>(
'DeleteSymbol',
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
);
root.dispatchEvent(customEvent);
}

View file

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { AddMethod } from '../Enums/AddMethod';
import { IImage } from './IImage';
import { type AddMethod } from '../Enums/AddMethod';
import { type IImage } from './IImage';
export interface IAction {
Id: string

View file

@ -1,9 +1,9 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { type AddMethod } from '../Enums/AddMethod';
import { type PositionReference } from '../Enums/PositionReference';
import { type Orientation } from '../Enums/Orientation';
import { type IAction } from './IAction';
import { type IMargin } from './IMargin';
import { type Orientation } from '../Enums/Orientation';
import { type IKeyValue } from './IKeyValue';
import { type IStyle } from './IStyle';
import { type IDimensions } from './IDimensions';

View file

@ -1,9 +1,9 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { IAPIConfiguration } from './IAPIConfiguration';
import { IAvailableContainer } from './IAvailableContainer';
import { IAvailableSymbol } from './IAvailableSymbol';
import { ICategory } from './ICategory';
import { IPattern } from './IPattern';
import { type IAPIConfiguration } from './IAPIConfiguration';
import { type IAvailableContainer } from './IAvailableContainer';
import { type IAvailableSymbol } from './IAvailableSymbol';
import { type ICategory } from './ICategory';
import { type IPattern } from './IPattern';
/** Model of configuration for the application to configure it */
export interface IConfiguration {

View file

@ -1,4 +1,4 @@
import { IContainerProperties } from './IContainerProperties';
import { type IContainerProperties } from './IContainerProperties';
export interface IContainerModel {
children: string[]
@ -18,7 +18,8 @@ export class ContainerModel implements IContainerModel {
constructor(
properties: IContainerProperties,
children: string[] = [],
userData = {}) {
userData = {}
) {
this.properties = properties;
this.children = children;
this.userData = userData;

View file

@ -1,9 +1,9 @@
import { PositionReference } from '../Enums/PositionReference';
import { IMargin } from './IMargin';
import { Orientation } from '../Enums/Orientation';
import { IKeyValue } from './IKeyValue';
import { IStyle } from './IStyle';
import { IDimensions } from './IDimensions';
import { type PositionReference } from '../Enums/PositionReference';
import { type Orientation } from '../Enums/Orientation';
import { type IMargin } from './IMargin';
import { type IKeyValue } from './IKeyValue';
import { type IStyle } from './IStyle';
import { type IDimensions } from './IDimensions';
/**
* Properties of a container

View file

@ -1,6 +1,6 @@
import { IDimensionOptions } from './IDimensionOptions';
import { Orientation } from '../Enums/Orientation';
import { type Orientation } from '../Enums/Orientation';
import { type IDimensionOptions } from './IDimensionOptions';
export interface IDimensions {

View file

@ -1,5 +1,5 @@
import { IConfiguration } from './IConfiguration';
import { IHistoryState } from './IHistoryState';
import { type IConfiguration } from './IConfiguration';
import { type IHistoryState } from './IHistoryState';
export interface IEditorState {
history: IHistoryState[]

View file

@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { IHistoryState } from './IHistoryState';
import { type IHistoryState } from './IHistoryState';
export interface IGetFeedbackRequest {
/** Current application state */

View file

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { IMessage } from './IMessage';
import { type IMessage } from './IMessage';
export interface IGetFeedbackResponse {
messages: IMessage[]

View file

@ -1,5 +1,5 @@
import { IContainerModel } from './IContainerModel';
import { ISymbolModel } from './ISymbolModel';
import { type IContainerModel } from './IContainerModel';
import { type ISymbolModel } from './ISymbolModel';
export interface IHistoryState {
/** Last editor action */

View file

@ -1,4 +1,4 @@
import React from 'react';
import type React from 'react';
export interface IInputGroup {
key: string

View file

@ -1,4 +1,4 @@
import { MessageType } from '../Enums/MessageType';
import { type MessageType } from '../Enums/MessageType';
export interface IMessage {
text: string

View file

@ -1,4 +1,4 @@
import { IAvailableContainer } from './IAvailableContainer';
import { type IAvailableContainer } from './IAvailableContainer';
export interface IPattern {
/**

View file

@ -1,6 +1,6 @@
import { IAction } from './IAction';
import { IContainerModel } from './IContainerModel';
import { IHistoryState } from './IHistoryState';
import { type IAction } from './IAction';
import { type IContainerModel } from './IContainerModel';
import { type IHistoryState } from './IHistoryState';
/* eslint-disable @typescript-eslint/naming-convention */
export interface ISetContainerListRequest {

View file

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { AddMethod } from '../Enums/AddMethod';
import { IAvailableContainer } from './IAvailableContainer';
import { type AddMethod } from '../Enums/AddMethod';
import { type IAvailableContainer } from './IAvailableContainer';
export interface ISetContainerListResponse {
Containers: IAvailableContainer[]

View file

@ -5,13 +5,11 @@ import { LanguageProvider } from './Components/LanguageProvider/LanguageProvider
import './index.scss';
function RenderRoot(root: Element | Document): void {
ReactDOM.createRoot(root.querySelector('#root') as HTMLDivElement).render(
<React.StrictMode>
<LanguageProvider>
<App root={root}/>
</LanguageProvider>
</React.StrictMode>
);
ReactDOM.createRoot(root.querySelector('#root') as HTMLDivElement).render(<React.StrictMode>
<LanguageProvider>
<App root={root}/>
</LanguageProvider>
</React.StrictMode>);
}
// Specific for Modeler apps

View file

@ -14,7 +14,9 @@ import { type IDimensionStyle } from '../Components/SVG/Elements/Dimension';
/// EDITOR DEFAULTS ///
/** Enable fast boot and disable main menu (0 = disabled, 1 = loading, 2 = loaded) */
export const FAST_BOOT = import.meta.env.PROD ? AppState.Loaded : AppState.MainMenu;
export const FAST_BOOT = import.meta.env.PROD
? AppState.Loaded
: AppState.MainMenu;
/** Disable any call to the API (default = false) */
export const DISABLE_API = false;
@ -89,7 +91,9 @@ export function GetDefaultEditorState(configuration: IConfiguration): IEditorSta
throw new Error('Cannot initialize project! Main container has an undefined size');
}
const containerConfig = configuration.AvailableContainers.find(config => config.Type === configuration.MainContainer.Type);
const containerConfig = configuration.AvailableContainers.find(
config => config.Type === configuration.MainContainer.Type
);
let mainContainerConfig: IContainerProperties;
if (containerConfig !== undefined) {
@ -128,9 +132,7 @@ export function GetDefaultEditorState(configuration: IConfiguration): IEditorSta
configuration.MainContainer
);
}
const mainContainer = new ContainerModel(
mainContainerConfig
);
const mainContainer = new ContainerModel(mainContainerConfig);
const containers = new Map<string, IContainerModel>();
containers.set(mainContainer.properties.id, mainContainer);
@ -244,14 +246,16 @@ export const DEFAULT_MAINCONTAINER_PROPS: IContainerProperties = {
* @param containerConfig default config of the container sent by the API
* @returns {IContainerProperties} Default properties of a newly created container
*/
export function GetDefaultContainerProps(type: string,
export function GetDefaultContainerProps(
type: string,
typeCount: number,
parent: IContainerModel | undefined | null,
x: number,
y: number,
width: number,
height: number,
containerConfig: IAvailableContainer): IContainerProperties {
containerConfig: IAvailableContainer
): IContainerProperties {
const orientation = containerConfig.Orientation ?? Orientation.Horizontal;
return ({
id: `${type}-${typeCount}`,
@ -299,10 +303,12 @@ export function GetDefaultContainerProps(type: string,
});
}
export function GetDefaultSymbolModel(name: string,
export function GetDefaultSymbolModel(
name: string,
newCounters: Record<string, number>,
type: string,
symbolConfig: IAvailableSymbol): ISymbolModel {
symbolConfig: IAvailableSymbol
): ISymbolModel {
const id = `${name}-${newCounters[type]}`;
return {
id,

View file

@ -1,6 +1,9 @@
import { IContainerModel } from '../Interfaces/IContainerModel';
import { type IContainerModel } from '../Interfaces/IContainerModel';
export function * MakeChildrenIterator(containers: Map<string, IContainerModel>, childrenIds: string[]): Generator<IContainerModel, void, unknown> {
export function * MakeChildrenIterator(
containers: Map<string, IContainerModel>,
childrenIds: string[]
): Generator<IContainerModel, void, unknown> {
for (const childId of childrenIds) {
const child = FindContainerById(containers, childId);
@ -15,7 +18,11 @@ export function * MakeChildrenIterator(containers: Map<string, IContainerModel>,
/**
* Returns a Generator iterating of over the children depth-first
*/
export function * MakeDFSIterator(root: IContainerModel, containers: Map<string, IContainerModel>, enableHideChildrenInTreeview = false): Generator<IContainerModel, void, unknown> {
export function * MakeDFSIterator(
root: IContainerModel,
containers: Map<string, IContainerModel>,
enableHideChildrenInTreeview = false
): Generator<IContainerModel, void, unknown> {
const queue: IContainerModel[] = [root];
const visited = new Set<IContainerModel>(queue);
while (queue.length > 0) {
@ -51,7 +58,10 @@ export interface ContainerAndDepthAndTransform extends ContainerAndDepth {
/**
* Returns a Generator iterating of over the children depth-first
*/
export function * MakeBFSIterator(root: IContainerModel, containers: Map<string, IContainerModel>): Generator<ContainerAndDepth, void, unknown> {
export function * MakeBFSIterator(
root: IContainerModel,
containers: Map<string, IContainerModel>
): Generator<ContainerAndDepth, void, unknown> {
const queue: IContainerModel[] = [root];
let depth = 0;
while (queue.length > 0) {
@ -141,7 +151,10 @@ export function GetDepth(containers: Map<string, IContainerModel>, parent: ICont
* Returns the absolute position by iterating to the parent
* @returns The absolute position of the container
*/
export function GetAbsolutePosition(containers: Map<string, IContainerModel>, container: IContainerModel): [number, number] {
export function GetAbsolutePosition(
containers: Map<string, IContainerModel>,
container: IContainerModel
): [number, number] {
const x = container.properties.x;
const y = container.properties.y;
const parent = FindContainerById(containers, container.properties.parentId) ?? null;
@ -230,7 +243,11 @@ export function ApplyParentTransform(
* @param id Id of the container to find
* @returns The container found or undefined if not found
*/
export function FindContainerByIdDFS(root: IContainerModel, containers: Map<string, IContainerModel>, id: string): IContainerModel | undefined {
export function FindContainerByIdDFS(
root: IContainerModel,
containers: Map<string, IContainerModel>,
id: string
): IContainerModel | undefined {
const it = MakeDFSIterator(root, containers);
for (const container of it) {
if (container.properties.id === id) {

View file

@ -1,8 +1,8 @@
/* eslint-disable @typescript-eslint/naming-convention */
import { IEditorState } from '../Interfaces/IEditorState';
import { IHistoryState } from '../Interfaces/IHistoryState';
import { IContainerModel } from '../Interfaces/IContainerModel';
import { ISymbolModel } from '../Interfaces/ISymbolModel';
import { type IEditorState } from '../Interfaces/IEditorState';
import { type IHistoryState } from '../Interfaces/IHistoryState';
import { type IContainerModel } from '../Interfaces/IContainerModel';
import { type ISymbolModel } from '../Interfaces/ISymbolModel';
/**
* Revive the Editor state
@ -37,7 +37,10 @@ export function ReviveState(state: IHistoryState): void {
state.containers = new Map(containers.map(({ Key, Value }) => [Key, Value]));
}
export function GetCircularReplacer(): (key: any, value: object | Map<string, any> | null) => object | null | undefined {
export function GetCircularReplacer(): (
key: any,
value: object | Map<string, any> | null
) => object | null | undefined {
return (key: any, value: object | null) => {
if (key === 'containers') {
return [...(value as Map<string, any>).entries()]

View file

@ -112,7 +112,8 @@ function GetAllIndexes(arr: number[], val: number): number[] {
* - 4) the selected column must have 1 in the pivot and zeroes in the other rows
* - 5) in the selected rows other columns (other than the selected column)
* must be divided by that pivot: coef / pivot
* - 6) for the others cells, apply the pivot: new value = (-coefficient in the old col) * (coefficient in the new row) + old value
* - 6) for the others cells, apply the pivot:
* new value = (-coefficient in the old col) * (coefficient in the new row) + old value
* - 7) if in the new matrix there are still negative values in the last row,
* redo the algorithm with the new matrix as the base matrix
* - 8) otherwise returns the basic variable such as
@ -135,7 +136,9 @@ function ApplyMainLoop(oldMatrix: number[][], rowlength: number): number[][] {
// to avoid infinite loop try to select the least used selected index
const pivotColIndex = GetLeastUsedIndex(indexes, indexesTried);
// record the usage of index by incrementing
indexesTried[pivotColIndex] = indexesTried[pivotColIndex] !== undefined ? indexesTried[pivotColIndex] + 1 : 1;
indexesTried[pivotColIndex] = indexesTried[pivotColIndex] !== undefined
? indexesTried[pivotColIndex] + 1
: 1;
// 2) find the smallest non negative non null ratio bi/xij (O(m))
const ratios = [];
@ -210,7 +213,9 @@ function GetSolutions(nCols: number, finalMatrix: number[][]): number[] {
const col: number[] = [];
for (let j = 0; j < finalMatrix.length; j++) {
const row = finalMatrix[j];
counts[row[i]] = counts[row[i]] !== undefined ? counts[row[i]] + 1 : 1;
counts[row[i]] = counts[row[i]] !== undefined
? counts[row[i]] + 1
: 1;
col.push(row[i]);
}

View file

@ -6,5 +6,7 @@ export function TruncateString(str: string, num: number): string {
}
export function Camelize(str: string): any {
return str.split('-').map((word, index) => index > 0 ? word.charAt(0).toUpperCase() + word.slice(1) : word).join('');
return str.split('-').map((word, index) => index > 0
? word.charAt(0).toUpperCase() + word.slice(1)
: word).join('');
}

View file

@ -1,6 +1,6 @@
/* eslint-disable import/export */
import * as React from 'react';
import { cleanup, render, RenderResult } from '@testing-library/react';
import type * as React from 'react';
import { cleanup, render, type RenderResult } from '@testing-library/react';
import { afterEach } from 'vitest';
afterEach(() => {