Merged PR 329: Run eslint src --fix
# Wait for all PRs to complete + Vertical Symbol Run `eslint src --fix`
This commit is contained in:
commit
f0b89ea05e
88 changed files with 1009 additions and 702 deletions
|
@ -33,9 +33,15 @@ module.exports = {
|
||||||
'func-style': ['error', 'declaration'],
|
'func-style': ['error', 'declaration'],
|
||||||
'space-before-function-paren': ['error', 'never'],
|
'space-before-function-paren': ['error', 'never'],
|
||||||
'max-len': ['error', { 'code': 120 }],
|
'max-len': ['error', { 'code': 120 }],
|
||||||
|
'max-depth': ['error', 4],
|
||||||
|
'function-paren-newline': ['error', 'multiline-arguments'],
|
||||||
|
'multiline-ternary': ['error', 'always'],
|
||||||
|
|
||||||
// Import/export
|
// Import/export
|
||||||
'import/no-default-export': 'error',
|
'import/no-default-export': 'error',
|
||||||
|
'import/no-duplicates': 'error',
|
||||||
|
'import/newline-after-import': 'error',
|
||||||
|
'import/order': 'error',
|
||||||
|
|
||||||
// Typescript overload
|
// Typescript overload
|
||||||
indent: 'off',
|
indent: 'off',
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { AddMethod } from '../../Enums/AddMethod';
|
import { AddMethod } from '../../Enums/AddMethod';
|
||||||
import { PositionReference } from '../../Enums/PositionReference';
|
import { PositionReference } from '../../Enums/PositionReference';
|
||||||
import { IAction } from '../../Interfaces/IAction';
|
import { type IAction } from '../../Interfaces/IAction';
|
||||||
import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
|
import { type IAvailableContainer } from '../../Interfaces/IAvailableContainer';
|
||||||
import { IAvailableSymbol } from '../../Interfaces/IAvailableSymbol';
|
import { type IAvailableSymbol } from '../../Interfaces/IAvailableSymbol';
|
||||||
import { ICategory } from '../../Interfaces/ICategory';
|
import { type ICategory } from '../../Interfaces/ICategory';
|
||||||
import { IConfiguration } from '../../Interfaces/IConfiguration';
|
import { type IConfiguration } from '../../Interfaces/IConfiguration';
|
||||||
import { IContainerModel, ContainerModel } from '../../Interfaces/IContainerModel';
|
import { type IContainerModel, ContainerModel } from '../../Interfaces/IContainerModel';
|
||||||
import { IHistoryState } from '../../Interfaces/IHistoryState';
|
import { type IHistoryState } from '../../Interfaces/IHistoryState';
|
||||||
import { IPattern } from '../../Interfaces/IPattern';
|
import { type IPattern } from '../../Interfaces/IPattern';
|
||||||
import { DEFAULT_DIMENSION_OPTION, DEFAULT_MAINCONTAINER_PROPS, GetDefaultContainerProps } from '../../utils/default';
|
import { DEFAULT_DIMENSION_OPTION, DEFAULT_MAINCONTAINER_PROPS, GetDefaultContainerProps } from '../../utils/default';
|
||||||
import { FetchConfiguration } from './api';
|
import { FetchConfiguration } from './api';
|
||||||
|
|
||||||
|
@ -95,9 +95,7 @@ describe.concurrent('Models test suite', () => {
|
||||||
expect(res4).toBe(true);
|
expect(res4).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
const mainContainer = new ContainerModel(
|
const mainContainer = new ContainerModel(DEFAULT_MAINCONTAINER_PROPS);
|
||||||
DEFAULT_MAINCONTAINER_PROPS
|
|
||||||
);
|
|
||||||
|
|
||||||
const containers = new Map<string, IContainerModel>();
|
const containers = new Map<string, IContainerModel>();
|
||||||
const historyState: IHistoryState = {
|
const historyState: IHistoryState = {
|
||||||
|
@ -244,7 +242,12 @@ describe.concurrent('Models test suite', () => {
|
||||||
'container',
|
'container',
|
||||||
0,
|
0,
|
||||||
null,
|
null,
|
||||||
0, 0, 0, 0, availableContainerModel);
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
availableContainerModel
|
||||||
|
);
|
||||||
|
|
||||||
it('ContainerModel', async() => {
|
it('ContainerModel', async() => {
|
||||||
const model: IContainerModel = {
|
const model: IContainerModel = {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { IConfiguration } from '../../Interfaces/IConfiguration';
|
import { type IConfiguration } from '../../Interfaces/IConfiguration';
|
||||||
import { ISetContainerListRequest } from '../../Interfaces/ISetContainerListRequest';
|
import { type ISetContainerListRequest } from '../../Interfaces/ISetContainerListRequest';
|
||||||
import { ISetContainerListResponse } from '../../Interfaces/ISetContainerListResponse';
|
import { type ISetContainerListResponse } from '../../Interfaces/ISetContainerListResponse';
|
||||||
import { GetCircularReplacer } from '../../utils/saveload';
|
import { GetCircularReplacer } from '../../utils/saveload';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,16 +9,14 @@ import { GetCircularReplacer } from '../../utils/saveload';
|
||||||
*/
|
*/
|
||||||
export async function FetchConfiguration(): Promise<IConfiguration> {
|
export async function FetchConfiguration(): Promise<IConfiguration> {
|
||||||
const url = import.meta.env.VITE_API_FETCH_URL;
|
const url = import.meta.env.VITE_API_FETCH_URL;
|
||||||
// The test library cannot use the Fetch API
|
// @ts-expect-error The test library cannot use the Fetch API
|
||||||
// @ts-expect-error
|
|
||||||
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
||||||
if (window.fetch) {
|
if (window.fetch) {
|
||||||
return await fetch(url, {
|
return await fetch(url, {
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
})
|
})
|
||||||
.then(async(response) =>
|
.then(async(response) =>
|
||||||
await response.json()
|
await response.json()) as IConfiguration;
|
||||||
) as IConfiguration;
|
|
||||||
}
|
}
|
||||||
return await new Promise((resolve) => {
|
return await new Promise((resolve) => {
|
||||||
const xhr = new XMLHttpRequest();
|
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 url = configurationUrl ?? import.meta.env.VITE_API_SET_CONTAINER_LIST_URL;
|
||||||
const dataParsed = JSON.stringify(request, GetCircularReplacer());
|
const dataParsed = JSON.stringify(request, GetCircularReplacer());
|
||||||
// The test library cannot use the Fetch API
|
// @ts-expect-error The test library cannot use the Fetch API
|
||||||
// @ts-expect-error
|
|
||||||
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
||||||
if (window.fetch) {
|
if (window.fetch) {
|
||||||
return await fetch(url, {
|
return await fetch(url, {
|
||||||
|
@ -49,8 +49,7 @@ export async function SetContainerList(request: ISetContainerListRequest, config
|
||||||
body: dataParsed
|
body: dataParsed
|
||||||
})
|
})
|
||||||
.then(async(response) =>
|
.then(async(response) =>
|
||||||
await response.json()
|
await response.json()) as ISetContainerListResponse;
|
||||||
) as ISetContainerListResponse;
|
|
||||||
}
|
}
|
||||||
return await new Promise((resolve) => {
|
return await new Promise((resolve) => {
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Dispatch, SetStateAction } from 'react';
|
import { type Dispatch, type SetStateAction } from 'react';
|
||||||
import { AppState } from '../../../Enums/AppState';
|
import { AppState } from '../../../Enums/AppState';
|
||||||
import { IEditorState } from '../../../Interfaces/IEditorState';
|
import { type IEditorState } from '../../../Interfaces/IEditorState';
|
||||||
import { Revive } from '../../../utils/saveload';
|
import { Revive } from '../../../utils/saveload';
|
||||||
|
|
||||||
export function LoadState(
|
export function LoadState(
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { Dispatch, SetStateAction } from 'react';
|
import { type Dispatch, type SetStateAction } from 'react';
|
||||||
import { IConfiguration } from '../../../Interfaces/IConfiguration';
|
import { type IConfiguration } from '../../../Interfaces/IConfiguration';
|
||||||
import { FetchConfiguration } from '../../API/api';
|
import { FetchConfiguration } from '../../API/api';
|
||||||
import { IEditorState } from '../../../Interfaces/IEditorState';
|
import { type IEditorState } from '../../../Interfaces/IEditorState';
|
||||||
import { LoadState } from './Load';
|
|
||||||
import { DISABLE_API, GetDefaultEditorState } from '../../../utils/default';
|
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(
|
export function NewEditor(
|
||||||
editorState: IEditorState,
|
editorState: IEditorState,
|
||||||
|
|
|
@ -2,16 +2,14 @@ import * as React from 'react';
|
||||||
import { beforeEach, describe, it } from 'vitest';
|
import { beforeEach, describe, it } from 'vitest';
|
||||||
import { AppState } from '../../Enums/AppState';
|
import { AppState } from '../../Enums/AppState';
|
||||||
import { FAST_BOOT } from '../../utils/default';
|
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';
|
import { App } from './App';
|
||||||
|
|
||||||
describe.concurrent('App', () => {
|
describe.concurrent('App', () => {
|
||||||
let app: RenderResult;
|
let app: RenderResult;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
app = render(
|
app = render(<App root={document} />);
|
||||||
<App root={document} />
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('New editor', async() => {
|
it('New editor', async() => {
|
||||||
|
|
|
@ -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 { UseCustomEvents } from '../../Events/AppEvents';
|
||||||
import { MainMenu } from '../MainMenu/MainMenu';
|
import { MainMenu } from '../MainMenu/MainMenu';
|
||||||
import { ContainerModel, IContainerModel } from '../../Interfaces/IContainerModel';
|
import { ContainerModel, type IContainerModel } from '../../Interfaces/IContainerModel';
|
||||||
import { Editor } from '../Editor/Editor';
|
import { Editor } from '../Editor/Editor';
|
||||||
import { IEditorState } from '../../Interfaces/IEditorState';
|
import { type IEditorState } from '../../Interfaces/IEditorState';
|
||||||
import { LoadState } from './Actions/Load';
|
|
||||||
import { LoadEditor, NewEditor } from './Actions/MenuActions';
|
|
||||||
import { DEFAULT_CONFIG, DEFAULT_MAINCONTAINER_PROPS, FAST_BOOT } from '../../utils/default';
|
import { DEFAULT_CONFIG, DEFAULT_MAINCONTAINER_PROPS, FAST_BOOT } from '../../utils/default';
|
||||||
import { AppState } from '../../Enums/AppState';
|
import { AppState } from '../../Enums/AppState';
|
||||||
import { Loader } from '../Loader/Loader';
|
import { Loader } from '../Loader/Loader';
|
||||||
import { LanguageContext } from '../LanguageProvider/LanguageProvider';
|
import { LanguageContext } from '../LanguageProvider/LanguageProvider';
|
||||||
|
import { LoadEditor, NewEditor } from './Actions/MenuActions';
|
||||||
|
import { LoadState } from './Actions/Load';
|
||||||
|
|
||||||
// App will never have props
|
// App will never have props
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
// 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 appRef = useRef<HTMLDivElement>(null);
|
||||||
const languageContext = useContext(LanguageContext);
|
const languageContext = useContext(LanguageContext);
|
||||||
|
|
||||||
const defaultMainContainer = new ContainerModel(
|
const defaultMainContainer = new ContainerModel(DEFAULT_MAINCONTAINER_PROPS);
|
||||||
DEFAULT_MAINCONTAINER_PROPS
|
|
||||||
);
|
|
||||||
const containers = new Map<string, IContainerModel>();
|
const containers = new Map<string, IContainerModel>();
|
||||||
containers.set(defaultMainContainer.properties.id, defaultMainContainer);
|
containers.set(defaultMainContainer.properties.id, defaultMainContainer);
|
||||||
|
|
||||||
|
@ -116,15 +114,17 @@ export function App(props: IAppProps): JSX.Element {
|
||||||
setAppState(AppState.Loading);
|
setAppState(AppState.Loading);
|
||||||
NewEditor(
|
NewEditor(
|
||||||
editorState,
|
editorState,
|
||||||
(newEditor) => setEditorState(newEditor),
|
(newEditor) => { setEditorState(newEditor); },
|
||||||
() => setAppState(AppState.Loaded)
|
() => { setAppState(AppState.Loaded); }
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
loadEditor={(files: FileList | null) => {
|
||||||
|
LoadEditor(
|
||||||
|
files,
|
||||||
|
setEditorState,
|
||||||
|
setAppState
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
loadEditor={(files: FileList | null) => LoadEditor(
|
|
||||||
files,
|
|
||||||
setEditorState,
|
|
||||||
setAppState
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -13,8 +13,8 @@ import {
|
||||||
EnvelopeIcon as EnvolopeIconS,
|
EnvelopeIcon as EnvolopeIconS,
|
||||||
Cog8ToothIcon as Cog8ToothIconS
|
Cog8ToothIcon as Cog8ToothIconS
|
||||||
} from '@heroicons/react/24/solid';
|
} from '@heroicons/react/24/solid';
|
||||||
import { BarIcon } from './BarIcon';
|
|
||||||
import { Text } from '../Text/Text';
|
import { Text } from '../Text/Text';
|
||||||
|
import { BarIcon } from './BarIcon';
|
||||||
|
|
||||||
interface IBarProps {
|
interface IBarProps {
|
||||||
className: string
|
className: string
|
||||||
|
@ -38,7 +38,7 @@ export function Bar(props: IBarProps): JSX.Element {
|
||||||
<BarIcon
|
<BarIcon
|
||||||
isActive={props.isComponentsOpen}
|
isActive={props.isComponentsOpen}
|
||||||
title={Text({ textId: '@Components' })}
|
title={Text({ textId: '@Components' })}
|
||||||
onClick={() => props.toggleComponents()}>
|
onClick={() => { props.toggleComponents(); }}>
|
||||||
{
|
{
|
||||||
props.isComponentsOpen
|
props.isComponentsOpen
|
||||||
? <CubeIconS className='heroicon' />
|
? <CubeIconS className='heroicon' />
|
||||||
|
@ -48,7 +48,7 @@ export function Bar(props: IBarProps): JSX.Element {
|
||||||
<BarIcon
|
<BarIcon
|
||||||
isActive={props.isSymbolsOpen}
|
isActive={props.isSymbolsOpen}
|
||||||
title={Text({ textId: '@Symbols' })}
|
title={Text({ textId: '@Symbols' })}
|
||||||
onClick={() => props.toggleSymbols()}>
|
onClick={() => { props.toggleSymbols(); }}>
|
||||||
{
|
{
|
||||||
props.isSymbolsOpen
|
props.isSymbolsOpen
|
||||||
? <LinkIconS className='heroicon' />
|
? <LinkIconS className='heroicon' />
|
||||||
|
@ -58,7 +58,7 @@ export function Bar(props: IBarProps): JSX.Element {
|
||||||
<BarIcon
|
<BarIcon
|
||||||
isActive={props.isMessagesOpen}
|
isActive={props.isMessagesOpen}
|
||||||
title={Text({ textId: '@Messages' })}
|
title={Text({ textId: '@Messages' })}
|
||||||
onClick={() => props.toggleMessages()}>
|
onClick={() => { props.toggleMessages(); }}>
|
||||||
{
|
{
|
||||||
props.isMessagesOpen
|
props.isMessagesOpen
|
||||||
? <EnvolopeIconS className='heroicon' />
|
? <EnvolopeIconS className='heroicon' />
|
||||||
|
@ -69,7 +69,7 @@ export function Bar(props: IBarProps): JSX.Element {
|
||||||
<BarIcon
|
<BarIcon
|
||||||
isActive={props.isHistoryOpen}
|
isActive={props.isHistoryOpen}
|
||||||
title={Text({ textId: '@Timeline' })}
|
title={Text({ textId: '@Timeline' })}
|
||||||
onClick={() => props.toggleTimeline()}>
|
onClick={() => { props.toggleTimeline(); }}>
|
||||||
{
|
{
|
||||||
props.isHistoryOpen
|
props.isHistoryOpen
|
||||||
? <ClockIconS className='heroicon' />
|
? <ClockIconS className='heroicon' />
|
||||||
|
@ -79,7 +79,7 @@ export function Bar(props: IBarProps): JSX.Element {
|
||||||
<BarIcon
|
<BarIcon
|
||||||
isActive={props.isSettingsOpen}
|
isActive={props.isSettingsOpen}
|
||||||
title={Text({ textId: '@Settings' })}
|
title={Text({ textId: '@Settings' })}
|
||||||
onClick={() => props.toggleSettings()}>
|
onClick={() => { props.toggleSettings(); }}>
|
||||||
{
|
{
|
||||||
props.isSettingsOpen
|
props.isSettingsOpen
|
||||||
? <Cog8ToothIconS className='heroicon' />
|
? <Cog8ToothIconS className='heroicon' />
|
||||||
|
|
|
@ -8,12 +8,14 @@ interface IBarIconProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BarIcon(props: IBarIconProps): JSX.Element {
|
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 (
|
return (
|
||||||
<button type="button"
|
<button type="button"
|
||||||
className={`bar-btn group ${isActiveClasses}`}
|
className={`bar-btn group ${isActiveClasses}`}
|
||||||
title={props.title}
|
title={props.title}
|
||||||
onClick={() => props.onClick()}
|
onClick={() => { props.onClick(); }}
|
||||||
>
|
>
|
||||||
<span className='sidebar-tooltip group-hover:scale-100'>{props.title}</span>
|
<span className='sidebar-tooltip group-hover:scale-100'>{props.title}</span>
|
||||||
{props.children}
|
{props.children}
|
||||||
|
|
|
@ -48,7 +48,12 @@ function Draw(
|
||||||
ctx,
|
ctx,
|
||||||
mainContainer,
|
mainContainer,
|
||||||
containers,
|
containers,
|
||||||
leftDim, bottomDim, topDim, rightDim, scale);
|
leftDim,
|
||||||
|
bottomDim,
|
||||||
|
topDim,
|
||||||
|
rightDim,
|
||||||
|
scale
|
||||||
|
);
|
||||||
|
|
||||||
// Draw symbols and symbol dimensions
|
// Draw symbols and symbol dimensions
|
||||||
RenderSymbols(ctx, symbols, scale);
|
RenderSymbols(ctx, symbols, scale);
|
||||||
|
@ -73,12 +78,10 @@ function Draw(
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
function UseCanvas(
|
function UseCanvas(draw: (context: CanvasRenderingContext2D,
|
||||||
draw: (context: CanvasRenderingContext2D,
|
frameCount: number,
|
||||||
frameCount: number,
|
scale: number,
|
||||||
scale: number,
|
translatePos: IPoint) => void): React.RefObject<HTMLCanvasElement> {
|
||||||
translatePos: IPoint) => void
|
|
||||||
): React.RefObject<HTMLCanvasElement> {
|
|
||||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
const frameCount = useRef(0);
|
const frameCount = useRef(0);
|
||||||
const translatePos = useRef({
|
const translatePos = useRef({
|
||||||
|
@ -168,9 +171,7 @@ function UseCanvas(
|
||||||
return canvasRef;
|
return canvasRef;
|
||||||
}
|
}
|
||||||
|
|
||||||
function UseSVGAutoResizer(
|
function UseSVGAutoResizer(setViewer: React.Dispatch<React.SetStateAction<Viewer>>): void {
|
||||||
setViewer: React.Dispatch<React.SetStateAction<Viewer>>
|
|
||||||
): void {
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
function OnResize(): void {
|
function OnResize(): void {
|
||||||
setViewer({
|
setViewer({
|
||||||
|
@ -198,9 +199,7 @@ export function Canvas({
|
||||||
style,
|
style,
|
||||||
drawParams
|
drawParams
|
||||||
}: ICanvasProps): JSX.Element {
|
}: ICanvasProps): JSX.Element {
|
||||||
const canvasRef = UseCanvas((
|
const canvasRef = UseCanvas((...CanvasProps) => {
|
||||||
...CanvasProps
|
|
||||||
) => {
|
|
||||||
Draw(
|
Draw(
|
||||||
...CanvasProps,
|
...CanvasProps,
|
||||||
drawParams
|
drawParams
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { NOTCHES_LENGTH } from '../../utils/default';
|
import { NOTCHES_LENGTH } from '../../utils/default';
|
||||||
import { IDimensionStyle } from '../SVG/Elements/Dimension';
|
import { type IDimensionStyle } from '../SVG/Elements/Dimension';
|
||||||
|
|
||||||
interface IDimensionProps {
|
interface IDimensionProps {
|
||||||
id: string
|
id: string
|
||||||
|
|
|
@ -170,11 +170,13 @@ function AddHorizontalChildrenDimension(
|
||||||
let xChildrenStart = TransformX(
|
let xChildrenStart = TransformX(
|
||||||
lastChild.properties.x,
|
lastChild.properties.x,
|
||||||
lastChild.properties.width,
|
lastChild.properties.width,
|
||||||
lastChild.properties.positionReference);
|
lastChild.properties.positionReference
|
||||||
|
);
|
||||||
let xChildrenEnd = TransformX(
|
let xChildrenEnd = TransformX(
|
||||||
lastChild.properties.x,
|
lastChild.properties.x,
|
||||||
lastChild.properties.width,
|
lastChild.properties.width,
|
||||||
lastChild.properties.positionReference);
|
lastChild.properties.positionReference
|
||||||
|
);
|
||||||
|
|
||||||
// Find the min and max
|
// Find the min and max
|
||||||
for (let i = container.children.length - 2; i >= 0; i--) {
|
for (let i = container.children.length - 2; i >= 0; i--) {
|
||||||
|
@ -238,7 +240,8 @@ function AddVerticalChildrenDimension(
|
||||||
let yChildrenStart = TransformY(
|
let yChildrenStart = TransformY(
|
||||||
lastChild.properties.y,
|
lastChild.properties.y,
|
||||||
lastChild.properties.height,
|
lastChild.properties.height,
|
||||||
lastChild.properties.positionReference);
|
lastChild.properties.positionReference
|
||||||
|
);
|
||||||
let yChildrenEnd = yChildrenStart;
|
let yChildrenEnd = yChildrenStart;
|
||||||
|
|
||||||
// Find the min and max
|
// Find the min and max
|
||||||
|
@ -314,9 +317,7 @@ function AddHorizontalBorrowerDimension(
|
||||||
|
|
||||||
const restoredX = x + childCurrentTransform[0];
|
const restoredX = x + childCurrentTransform[0];
|
||||||
|
|
||||||
marks.push(
|
marks.push(restoredX);
|
||||||
restoredX
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const restoredX = container.properties.x + currentTransform[0];
|
const restoredX = container.properties.x + currentTransform[0];
|
||||||
|
@ -374,9 +375,7 @@ function AddVerticalBorrowerDimension(
|
||||||
|
|
||||||
const restoredy = y + childCurrentTransform[1];
|
const restoredy = y + childCurrentTransform[1];
|
||||||
|
|
||||||
marks.push(
|
marks.push(restoredy);
|
||||||
restoredy
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const restoredY = container.properties.y + currentTransform[1];
|
const restoredY = container.properties.y + currentTransform[1];
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { type IContainerModel } from '../../Interfaces/IContainerModel';
|
import { type IContainerModel } from '../../Interfaces/IContainerModel';
|
||||||
import { type IHistoryState } from '../../Interfaces/IHistoryState';
|
import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
|
||||||
import { ISymbolModel } from '../../Interfaces/ISymbolModel';
|
|
||||||
import { DIMENSION_MARGIN } from '../../utils/default';
|
import { DIMENSION_MARGIN } from '../../utils/default';
|
||||||
import { MakeRecursionDFSIterator } from '../../utils/itertools';
|
import { MakeRecursionDFSIterator } from '../../utils/itertools';
|
||||||
import { RenderContainer } from './Container';
|
import { RenderContainer } from './Container';
|
||||||
|
|
|
@ -25,7 +25,11 @@ export function RenderContainerSelector(
|
||||||
props.selected.properties.height
|
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.left,
|
||||||
props.selected.properties.margin.bottom,
|
props.selected.properties.margin.bottom,
|
||||||
props.selected.properties.margin.top,
|
props.selected.properties.margin.top,
|
||||||
|
|
|
@ -5,7 +5,8 @@ const IMAGE_CACHE = new Map<string, HTMLImageElement>();
|
||||||
|
|
||||||
export function RenderSymbol(
|
export function RenderSymbol(
|
||||||
ctx: CanvasRenderingContext2D,
|
ctx: CanvasRenderingContext2D,
|
||||||
symbol: ISymbolModel): void {
|
symbol: ISymbolModel
|
||||||
|
): void {
|
||||||
const href = symbol.config.Image.Base64Image ?? symbol.config.Image.Url;
|
const href = symbol.config.Image.Base64Image ?? symbol.config.Image.Url;
|
||||||
|
|
||||||
if (href === undefined) {
|
if (href === undefined) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { ChevronRightIcon } from '@heroicons/react/24/outline';
|
import { ChevronRightIcon } from '@heroicons/react/24/outline';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { ICategory } from '../../Interfaces/ICategory';
|
import { type ICategory } from '../../Interfaces/ICategory';
|
||||||
import { TruncateString } from '../../utils/stringtools';
|
import { TruncateString } from '../../utils/stringtools';
|
||||||
|
|
||||||
interface ICategoryProps {
|
interface ICategoryProps {
|
||||||
|
@ -20,23 +20,40 @@ export function Category(props: ICategoryProps): JSX.Element {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<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}
|
key={categoryType}
|
||||||
id={categoryType}
|
id={categoryType}
|
||||||
title={categoryDisplayedText}
|
title={categoryDisplayedText}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`flex flex-row group cursor-pointer ${heightClass}`}
|
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)}
|
{TruncateString(categoryDisplayedText, 25)}
|
||||||
</span>
|
</span>
|
||||||
<span className={`flex-none h-full justify-center sidebar-component-right ${isOpen ? 'rounded-b-none' : ''}`}>
|
<span className={`flex-none h-full justify-center sidebar-component-right ${isOpen
|
||||||
<ChevronRightIcon className={`transition-all w-5 ${isOpen ? 'rotate-90' : ''}`} />
|
? 'rounded-b-none'
|
||||||
|
: ''}`}>
|
||||||
|
<ChevronRightIcon className={`transition-all w-5 ${isOpen
|
||||||
|
? 'rotate-90'
|
||||||
|
: ''}`} />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</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 }
|
{ props.children }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -80,7 +80,9 @@ export function CheckboxGroupButtons(props: ICheckboxGroupButtonsProps): JSX.Ele
|
||||||
* @returns The new selected values
|
* @returns The new selected values
|
||||||
*/
|
*/
|
||||||
function SetChecked(selectedValue: number, isChecked: boolean): number[] {
|
function SetChecked(selectedValue: number, isChecked: boolean): number[] {
|
||||||
isChecked ? selectedOptions.add(selectedValue) : selectedOptions.delete(selectedValue);
|
isChecked
|
||||||
|
? selectedOptions.add(selectedValue)
|
||||||
|
: selectedOptions.delete(selectedValue);
|
||||||
return [...selectedOptions];
|
return [...selectedOptions];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ChevronUpDownIcon } from '@heroicons/react/20/solid';
|
import { ChevronUpDownIcon } from '@heroicons/react/20/solid';
|
||||||
import { CheckboxGroupButtons } from './CheckboxGroupButtons';
|
|
||||||
import { Orientation } from '../../Enums/Orientation';
|
import { Orientation } from '../../Enums/Orientation';
|
||||||
|
import { CheckboxGroupButtons } from './CheckboxGroupButtons';
|
||||||
|
|
||||||
interface IOrientationCheckboxesProps {
|
interface IOrientationCheckboxesProps {
|
||||||
id: string
|
id: string
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { EyeIcon, EyeSlashIcon, XCircleIcon } from '@heroicons/react/24/outline';
|
import { EyeIcon, EyeSlashIcon, XCircleIcon } from '@heroicons/react/24/outline';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
|
import { type Dispatch } from 'react';
|
||||||
import { ICategory } from '../../Interfaces/ICategory';
|
import { type IAvailableContainer } from '../../Interfaces/IAvailableContainer';
|
||||||
import { IContainerModel } from '../../Interfaces/IContainerModel';
|
import { type ICategory } from '../../Interfaces/ICategory';
|
||||||
|
import { type IContainerModel } from '../../Interfaces/IContainerModel';
|
||||||
import { TruncateString } from '../../utils/stringtools';
|
import { TruncateString } from '../../utils/stringtools';
|
||||||
import { Category } from '../Category/Category';
|
import { Category } from '../Category/Category';
|
||||||
import { Text } from '../Text/Text';
|
import { Text } from '../Text/Text';
|
||||||
import { IReplaceContainer } from '../../Interfaces/IReplaceContainer';
|
import { type IReplaceContainer } from '../../Interfaces/IReplaceContainer';
|
||||||
import { Dispatch } from 'react';
|
|
||||||
|
|
||||||
interface IComponentsProps {
|
interface IComponentsProps {
|
||||||
selectedContainer: IContainerModel | undefined
|
selectedContainer: IContainerModel | undefined
|
||||||
|
@ -29,7 +29,9 @@ interface SidebarCategory {
|
||||||
|
|
||||||
export function Components(props: IComponentsProps): JSX.Element {
|
export function Components(props: IComponentsProps): JSX.Element {
|
||||||
const [hideDisabled, setHideDisabled] = React.useState<boolean>(false);
|
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 rootElements: Array<JSX.Element | undefined> = [];
|
||||||
const categories = new Map<string, SidebarCategory>(props.categories.map(category => [
|
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)
|
// build the categories (sorted with categories first)
|
||||||
categories.forEach((categoryWrapper, categoryName) => {
|
categories.forEach((categoryWrapper, categoryName) => {
|
||||||
rootElements.push(
|
rootElements.push(<Category
|
||||||
<Category
|
key={categoryName}
|
||||||
key={categoryName}
|
category={categoryWrapper.category}
|
||||||
category={categoryWrapper.category}
|
>
|
||||||
>
|
{ categoryWrapper.children }
|
||||||
{ categoryWrapper.children }
|
</Category>);
|
||||||
</Category>);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectedContainer = props.selectedContainer;
|
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'
|
className='w-full justify-center h-16 transition-all sidebar-component'
|
||||||
id={componentOption.Type}
|
id={componentOption.Type}
|
||||||
title={componentOption.Type}
|
title={componentOption.Type}
|
||||||
onClick={() => props.buttonOnClick(componentOption.Type)}
|
onClick={() => { props.buttonOnClick(componentOption.Type); }}
|
||||||
draggable={true}
|
draggable={true}
|
||||||
onDragStart={(event) => HandleDragStart(event)}
|
onDragStart={(event) => { HandleDragStart(event); }}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
>
|
>
|
||||||
{TruncateString(componentOption.DisplayedText ?? componentOption.Type, 25)}
|
{TruncateString(componentOption.DisplayedText ?? componentOption.Type, 25)}
|
||||||
|
|
|
@ -192,13 +192,17 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
type='number'
|
type='number'
|
||||||
min={props.properties.minWidth}
|
min={props.properties.minWidth}
|
||||||
max={props.properties.maxWidth}
|
max={props.properties.maxWidth}
|
||||||
value={(RemoveWidthMargin(props.properties.width,
|
value={(RemoveWidthMargin(
|
||||||
|
props.properties.width,
|
||||||
props.properties.margin.left,
|
props.properties.margin.left,
|
||||||
props.properties.margin.right)).toString()}
|
props.properties.margin.right
|
||||||
|
)).toString()}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
props.onChange('width', ApplyWidthMargin(Number(value),
|
props.onChange('width', ApplyWidthMargin(
|
||||||
|
Number(value),
|
||||||
props.properties.margin.left,
|
props.properties.margin.left,
|
||||||
props.properties.margin.right));
|
props.properties.margin.right
|
||||||
|
));
|
||||||
}}
|
}}
|
||||||
isDisabled={props.properties.isFlex}/>
|
isDisabled={props.properties.isFlex}/>
|
||||||
<TextInputGroup
|
<TextInputGroup
|
||||||
|
@ -231,13 +235,17 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
type='number'
|
type='number'
|
||||||
min={props.properties.minHeight}
|
min={props.properties.minHeight}
|
||||||
max={props.properties.maxHeight}
|
max={props.properties.maxHeight}
|
||||||
value={(RemoveWidthMargin(props.properties.height,
|
value={(RemoveWidthMargin(
|
||||||
|
props.properties.height,
|
||||||
props.properties.margin.top,
|
props.properties.margin.top,
|
||||||
props.properties.margin.bottom)).toString()}
|
props.properties.margin.bottom
|
||||||
|
)).toString()}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
props.onChange('height', ApplyWidthMargin(Number(value),
|
props.onChange('height', ApplyWidthMargin(
|
||||||
|
Number(value),
|
||||||
props.properties.margin.top,
|
props.properties.margin.top,
|
||||||
props.properties.margin.bottom));
|
props.properties.margin.bottom
|
||||||
|
));
|
||||||
}}
|
}}
|
||||||
isDisabled={props.properties.isFlex}
|
isDisabled={props.properties.isFlex}
|
||||||
/>
|
/>
|
||||||
|
@ -270,7 +278,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
type='number'
|
type='number'
|
||||||
min={0}
|
min={0}
|
||||||
value={(props.properties.margin.left ?? 0).toString()}
|
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
|
<TextInputGroup
|
||||||
id={`${props.properties.id}-mb`}
|
id={`${props.properties.id}-mb`}
|
||||||
labelText={Text({ textId: '@ContainerMarginBottom' })}
|
labelText={Text({ textId: '@ContainerMarginBottom' })}
|
||||||
|
@ -280,7 +290,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
type='number'
|
type='number'
|
||||||
min={0}
|
min={0}
|
||||||
value={(props.properties.margin.bottom ?? 0).toString()}
|
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
|
<TextInputGroup
|
||||||
id={`${props.properties.id}-mt`}
|
id={`${props.properties.id}-mt`}
|
||||||
labelText={Text({ textId: '@ContainerMarginTop' })}
|
labelText={Text({ textId: '@ContainerMarginTop' })}
|
||||||
|
@ -290,7 +302,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
type='number'
|
type='number'
|
||||||
min={0}
|
min={0}
|
||||||
value={(props.properties.margin.top ?? 0).toString()}
|
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
|
<TextInputGroup
|
||||||
id={`${props.properties.id}-mr`}
|
id={`${props.properties.id}-mr`}
|
||||||
labelText={Text({ textId: '@ContainerMarginRight' })}
|
labelText={Text({ textId: '@ContainerMarginRight' })}
|
||||||
|
@ -300,7 +314,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
type='number'
|
type='number'
|
||||||
min={0}
|
min={0}
|
||||||
value={(props.properties.margin.right ?? 0).toString()}
|
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>
|
</div>
|
||||||
</Category>
|
</Category>
|
||||||
|
|
||||||
|
@ -377,7 +393,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
name='ShowSelfDimensions'
|
name='ShowSelfDimensions'
|
||||||
labelText={Text({ textId: '@ContainerShowDimension' })}
|
labelText={Text({ textId: '@ContainerShowDimension' })}
|
||||||
value={props.properties.dimensionOptions.selfDimensions.positions}
|
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
|
<InputGroup
|
||||||
labelText={Text({ textId: '@StyleStrokeColor' })}
|
labelText={Text({ textId: '@StyleStrokeColor' })}
|
||||||
|
@ -386,7 +404,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
inputClassName=''
|
inputClassName=''
|
||||||
type='color'
|
type='color'
|
||||||
value={props.properties.dimensionOptions.selfDimensions.color ?? '#000000'}
|
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
|
<TextInputGroup
|
||||||
id={`${props.properties.id}-selfDimensions-width`}
|
id={`${props.properties.id}-selfDimensions-width`}
|
||||||
labelText={Text({ textId: '@StyleStrokeWidth' })}
|
labelText={Text({ textId: '@StyleStrokeWidth' })}
|
||||||
|
@ -396,7 +416,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
type='number'
|
type='number'
|
||||||
min={0}
|
min={0}
|
||||||
value={(props.properties.dimensionOptions.selfDimensions.width ?? 0).toString()}
|
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
|
<TextInputGroup
|
||||||
id={`${props.properties.id}-selfDimensions-dasharray`}
|
id={`${props.properties.id}-selfDimensions-dasharray`}
|
||||||
labelText={Text({ textId: '@StyleStrokeDashArray' })}
|
labelText={Text({ textId: '@StyleStrokeDashArray' })}
|
||||||
|
@ -405,7 +427,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
inputClassName=''
|
inputClassName=''
|
||||||
type='text'
|
type='text'
|
||||||
value={props.properties.dimensionOptions.selfDimensions.dashArray ?? ''}
|
value={props.properties.dimensionOptions.selfDimensions.dashArray ?? ''}
|
||||||
onChange={(value) => { props.onChange('dashArray', value, PropertyType.SelfDimension); }}/>
|
onChange={(value) => {
|
||||||
|
props.onChange('dashArray', value, PropertyType.SelfDimension);
|
||||||
|
}}/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -417,7 +441,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
name='ShowSelfMarginsDimensions'
|
name='ShowSelfMarginsDimensions'
|
||||||
labelText={Text({ textId: '@ContainerShowMarginsDimension' })}
|
labelText={Text({ textId: '@ContainerShowMarginsDimension' })}
|
||||||
value={props.properties.dimensionOptions.selfMarginsDimensions.positions}
|
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
|
<InputGroup
|
||||||
labelText={Text({ textId: '@StyleStrokeColor' })}
|
labelText={Text({ textId: '@StyleStrokeColor' })}
|
||||||
|
@ -426,7 +452,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
inputClassName=''
|
inputClassName=''
|
||||||
type='color'
|
type='color'
|
||||||
value={props.properties.dimensionOptions.selfMarginsDimensions.color ?? '#000000'}
|
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
|
<TextInputGroup
|
||||||
id={`${props.properties.id}-selfMarginsDimensions-width`}
|
id={`${props.properties.id}-selfMarginsDimensions-width`}
|
||||||
labelText={Text({ textId: '@StyleStrokeWidth' })}
|
labelText={Text({ textId: '@StyleStrokeWidth' })}
|
||||||
|
@ -436,7 +464,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
type='number'
|
type='number'
|
||||||
min={0}
|
min={0}
|
||||||
value={(props.properties.dimensionOptions.selfMarginsDimensions.width ?? 0).toString()}
|
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
|
<TextInputGroup
|
||||||
id={`${props.properties.id}-selfMarginsDimensions-dasharray`}
|
id={`${props.properties.id}-selfMarginsDimensions-dasharray`}
|
||||||
labelText={Text({ textId: '@StyleStrokeDashArray' })}
|
labelText={Text({ textId: '@StyleStrokeDashArray' })}
|
||||||
|
@ -445,7 +475,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
inputClassName=''
|
inputClassName=''
|
||||||
type='text'
|
type='text'
|
||||||
value={props.properties.dimensionOptions.selfMarginsDimensions.dashArray ?? ''}
|
value={props.properties.dimensionOptions.selfMarginsDimensions.dashArray ?? ''}
|
||||||
onChange={(value) => { props.onChange('dashArray', value, PropertyType.SelfMarginDimension); }}/>
|
onChange={(value) => {
|
||||||
|
props.onChange('dashArray', value, PropertyType.SelfMarginDimension);
|
||||||
|
}}/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -457,7 +489,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
name='ShowChildrenDimensions'
|
name='ShowChildrenDimensions'
|
||||||
labelText={Text({ textId: '@ContainerShowChildrenDimension' })}
|
labelText={Text({ textId: '@ContainerShowChildrenDimension' })}
|
||||||
value={props.properties.dimensionOptions.childrenDimensions.positions}
|
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
|
<InputGroup
|
||||||
labelText={Text({ textId: '@StyleStrokeColor' })}
|
labelText={Text({ textId: '@StyleStrokeColor' })}
|
||||||
|
@ -466,7 +500,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
inputClassName=''
|
inputClassName=''
|
||||||
type='color'
|
type='color'
|
||||||
value={props.properties.dimensionOptions.childrenDimensions.color ?? '#000000'}
|
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
|
<TextInputGroup
|
||||||
id={`${props.properties.id}-childrenDimensions-width`}
|
id={`${props.properties.id}-childrenDimensions-width`}
|
||||||
labelText={Text({ textId: '@StyleStrokeWidth' })}
|
labelText={Text({ textId: '@StyleStrokeWidth' })}
|
||||||
|
@ -476,7 +512,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
type='number'
|
type='number'
|
||||||
min={0}
|
min={0}
|
||||||
value={(props.properties.dimensionOptions.childrenDimensions.width ?? 0).toString()}
|
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
|
<TextInputGroup
|
||||||
id={`${props.properties.id}-childrenDimensions-dasharray`}
|
id={`${props.properties.id}-childrenDimensions-dasharray`}
|
||||||
labelText={Text({ textId: '@StyleStrokeDashArray' })}
|
labelText={Text({ textId: '@StyleStrokeDashArray' })}
|
||||||
|
@ -485,7 +523,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
inputClassName=''
|
inputClassName=''
|
||||||
type='text'
|
type='text'
|
||||||
value={props.properties.dimensionOptions.childrenDimensions.dashArray ?? ''}
|
value={props.properties.dimensionOptions.childrenDimensions.dashArray ?? ''}
|
||||||
onChange={(value) => { props.onChange('dashArray', value, PropertyType.ChildrenDimensions); }}/>
|
onChange={(value) => {
|
||||||
|
props.onChange('dashArray', value, PropertyType.ChildrenDimensions);
|
||||||
|
}}/>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -497,7 +537,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
name='MarkPosition'
|
name='MarkPosition'
|
||||||
value={props.properties.dimensionOptions.markPosition}
|
value={props.properties.dimensionOptions.markPosition}
|
||||||
labelText={Text({ textId: '@ContainerMarkPosition' })}
|
labelText={Text({ textId: '@ContainerMarkPosition' })}
|
||||||
onChange={(key, value) => { props.onChange(key, value, PropertyType.DimensionOptions); }}
|
onChange={(key, value) => {
|
||||||
|
props.onChange(key, value, PropertyType.DimensionOptions);
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className='grid grid-cols-1 gap-2'>
|
<div className='grid grid-cols-1 gap-2'>
|
||||||
|
@ -507,7 +549,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
name='ShowDimensionWithMarks'
|
name='ShowDimensionWithMarks'
|
||||||
labelText={Text({ textId: '@ContainerShowDimensionWithMarks' })}
|
labelText={Text({ textId: '@ContainerShowDimensionWithMarks' })}
|
||||||
value={props.properties.dimensionOptions.dimensionWithMarks.positions}
|
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
|
<InputGroup
|
||||||
labelText={Text({ textId: '@StyleStrokeColor' })}
|
labelText={Text({ textId: '@StyleStrokeColor' })}
|
||||||
|
@ -516,7 +560,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
inputClassName=''
|
inputClassName=''
|
||||||
type='color'
|
type='color'
|
||||||
value={props.properties.dimensionOptions.dimensionWithMarks.color ?? '#000000'}
|
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
|
<TextInputGroup
|
||||||
id={`${props.properties.id}-dimensionWithMarks-width`}
|
id={`${props.properties.id}-dimensionWithMarks-width`}
|
||||||
labelText={Text({ textId: '@StyleStrokeWidth' })}
|
labelText={Text({ textId: '@StyleStrokeWidth' })}
|
||||||
|
@ -526,7 +572,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
type='number'
|
type='number'
|
||||||
min={0}
|
min={0}
|
||||||
value={(props.properties.dimensionOptions.dimensionWithMarks.width ?? 0).toString()}
|
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
|
<TextInputGroup
|
||||||
id={`${props.properties.id}-dimensionWithMarks-dasharray`}
|
id={`${props.properties.id}-dimensionWithMarks-dasharray`}
|
||||||
labelText={Text({ textId: '@StyleStrokeDashArray' })}
|
labelText={Text({ textId: '@StyleStrokeDashArray' })}
|
||||||
|
@ -535,7 +583,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
inputClassName=''
|
inputClassName=''
|
||||||
type='text'
|
type='text'
|
||||||
value={props.properties.dimensionOptions.dimensionWithMarks.dashArray ?? ''}
|
value={props.properties.dimensionOptions.dimensionWithMarks.dashArray ?? ''}
|
||||||
onChange={(value) => { props.onChange('dashArray', value, PropertyType.DimensionWithMarks); }}/>
|
onChange={(value) => {
|
||||||
|
props.onChange('dashArray', value, PropertyType.DimensionWithMarks);
|
||||||
|
}}/>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
|
@ -557,7 +607,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
inputClassName='col-span-3'
|
inputClassName='col-span-3'
|
||||||
type='color'
|
type='color'
|
||||||
value={props.properties.style.stroke ?? '#000000'}
|
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
|
<InputGroup
|
||||||
labelKey={`${props.properties.id}-strokeOpacity`}
|
labelKey={`${props.properties.id}-strokeOpacity`}
|
||||||
labelText={Text({ textId: '@StyleStrokeOpacity' })}
|
labelText={Text({ textId: '@StyleStrokeOpacity' })}
|
||||||
|
@ -569,7 +621,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
max={1}
|
max={1}
|
||||||
step={0.01}
|
step={0.01}
|
||||||
value={(props.properties.style.strokeOpacity ?? 1).toString()}
|
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
|
<TextInputGroup
|
||||||
id={`${props.properties.id}-strokeWidth`}
|
id={`${props.properties.id}-strokeWidth`}
|
||||||
|
@ -579,7 +633,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
inputClassName='col-span-3'
|
inputClassName='col-span-3'
|
||||||
type='number'
|
type='number'
|
||||||
value={(props.properties.style.strokeWidth ?? 1).toString()}
|
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
|
<InputGroup
|
||||||
labelText={Text({ textId: '@StyleFill' })}
|
labelText={Text({ textId: '@StyleFill' })}
|
||||||
|
@ -588,7 +644,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
inputClassName='col-span-3'
|
inputClassName='col-span-3'
|
||||||
type='color'
|
type='color'
|
||||||
value={props.properties.style.fill ?? '#000000'}
|
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
|
<InputGroup
|
||||||
labelKey={`${props.properties.id}-fillOpacity`}
|
labelKey={`${props.properties.id}-fillOpacity`}
|
||||||
labelText={Text({ textId: '@StyleFillOpacity' })}
|
labelText={Text({ textId: '@StyleFillOpacity' })}
|
||||||
|
@ -600,7 +658,9 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
||||||
max={1}
|
max={1}
|
||||||
step={0.01}
|
step={0.01}
|
||||||
value={(props.properties.style.fillOpacity ?? 1).toString()}
|
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>
|
</div>
|
||||||
</Category>
|
</Category>
|
||||||
|
|
|
@ -2,10 +2,10 @@ import { fireEvent, render, screen } from '@testing-library/react';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { expect, describe, it, vi } from 'vitest';
|
import { expect, describe, it, vi } from 'vitest';
|
||||||
import { PositionReference } from '../../Enums/PositionReference';
|
import { PositionReference } from '../../Enums/PositionReference';
|
||||||
import { IContainerProperties } from '../../Interfaces/IContainerProperties';
|
import { type IContainerProperties } from '../../Interfaces/IContainerProperties';
|
||||||
import { Orientation } from '../../Enums/Orientation';
|
import { Orientation } from '../../Enums/Orientation';
|
||||||
import { ContainerProperties } from './ContainerProperties';
|
|
||||||
import { DEFAULT_DIMENSION_OPTION } from '../../utils/default';
|
import { DEFAULT_DIMENSION_OPTION } from '../../utils/default';
|
||||||
|
import { ContainerProperties } from './ContainerProperties';
|
||||||
|
|
||||||
describe.concurrent('Properties', () => {
|
describe.concurrent('Properties', () => {
|
||||||
it('No properties', () => {
|
it('No properties', () => {
|
||||||
|
|
|
@ -2,8 +2,8 @@ import React from 'react';
|
||||||
import { type PropertyType } from '../../Enums/PropertyType';
|
import { type PropertyType } from '../../Enums/PropertyType';
|
||||||
import { type IContainerProperties } from '../../Interfaces/IContainerProperties';
|
import { type IContainerProperties } from '../../Interfaces/IContainerProperties';
|
||||||
import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
|
import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
|
||||||
import { ContainerForm } from './ContainerForm';
|
|
||||||
import { type IContainerModel } from '../../Interfaces/IContainerModel';
|
import { type IContainerModel } from '../../Interfaces/IContainerModel';
|
||||||
|
import { ContainerForm } from './ContainerForm';
|
||||||
|
|
||||||
interface IPropertiesProps {
|
interface IPropertiesProps {
|
||||||
containers: Map<string, IContainerModel>
|
containers: Map<string, IContainerModel>
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { AddMethod } from '../../../Enums/AddMethod';
|
import { AddMethod } from '../../../Enums/AddMethod';
|
||||||
import { IAvailableContainer } from '../../../Interfaces/IAvailableContainer';
|
import { type IAvailableContainer } from '../../../Interfaces/IAvailableContainer';
|
||||||
import { IConfiguration } from '../../../Interfaces/IConfiguration';
|
import { type IConfiguration } from '../../../Interfaces/IConfiguration';
|
||||||
import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||||
import { IHistoryState } from '../../../Interfaces/IHistoryState';
|
import { type IHistoryState } from '../../../Interfaces/IHistoryState';
|
||||||
import { IPattern, GetPattern, ContainerOrPattern } from '../../../Interfaces/IPattern';
|
import { type IPattern, GetPattern, type ContainerOrPattern } from '../../../Interfaces/IPattern';
|
||||||
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
||||||
import { Orientation } from '../../../Enums/Orientation';
|
import { Orientation } from '../../../Enums/Orientation';
|
||||||
import { GetDefaultContainerProps } from '../../../utils/default';
|
import { GetDefaultContainerProps } from '../../../utils/default';
|
||||||
import { FindContainerById } from '../../../utils/itertools';
|
import { FindContainerById } from '../../../utils/itertools';
|
||||||
|
@ -69,9 +69,7 @@ export function AddContainers(
|
||||||
const containers = structuredClone(current.containers);
|
const containers = structuredClone(current.containers);
|
||||||
|
|
||||||
// Find the parent in the clone
|
// Find the parent in the clone
|
||||||
const parentClone: IContainerModel | undefined = FindContainerById(
|
const parentClone: IContainerModel | undefined = FindContainerById(containers, parentId);
|
||||||
containers, parentId
|
|
||||||
);
|
|
||||||
|
|
||||||
if (parentClone === null || parentClone === undefined) {
|
if (parentClone === null || parentClone === undefined) {
|
||||||
throw new Error('[AddContainer] Container model was not found among children of the main container!');
|
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;
|
const right: number = containerConfig.Margin?.right ?? 0;
|
||||||
|
|
||||||
// Default coordinates
|
// Default coordinates
|
||||||
let width = containerConfig.Width ?? containerConfig.MaxWidth ?? containerConfig.MinWidth ?? parentClone.properties.width;
|
let width = containerConfig.Width ??
|
||||||
let height = containerConfig.Height ?? containerConfig.MaxHeight ?? containerConfig.MinHeight ?? parentClone.properties.height;
|
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 x = RestoreX(containerConfig.X ?? 0, width, containerConfig.PositionReference);
|
||||||
let y = RestoreY(containerConfig.Y ?? 0, height, containerConfig.PositionReference);
|
let y = RestoreY(containerConfig.Y ?? 0, height, containerConfig.PositionReference);
|
||||||
|
|
||||||
|
@ -288,7 +292,8 @@ function InitializeDefaultChild(
|
||||||
configuration,
|
configuration,
|
||||||
containers,
|
containers,
|
||||||
parent,
|
parent,
|
||||||
0, 0,
|
0,
|
||||||
|
0,
|
||||||
newCounters,
|
newCounters,
|
||||||
symbols
|
symbols
|
||||||
);
|
);
|
||||||
|
@ -308,12 +313,17 @@ function InitializeChildrenWithPattern(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const configs: Map<string, IAvailableContainer> = new Map(configuration.AvailableContainers.map(config => [config.Type, config]));
|
const configs = new Map<string, IAvailableContainer>(
|
||||||
const patterns: Map<string, IPattern> = new Map(configuration.Patterns.map(pattern => [pattern.id, pattern]));
|
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);
|
const containerOrPattern = GetPattern(patternId, configs, patterns);
|
||||||
|
|
||||||
if (containerOrPattern === undefined) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,7 +366,16 @@ function BuildPatterns(
|
||||||
while (levelSize-- !== 0) {
|
while (levelSize-- !== 0) {
|
||||||
const node = queue.shift() as Node;
|
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) {
|
if (newParent === undefined) {
|
||||||
// node.pattern is not a IPattern, there is no children to iterate
|
// node.pattern is not a IPattern, there is no children to iterate
|
||||||
|
@ -411,7 +430,8 @@ function AddContainerInLevel(
|
||||||
configuration,
|
configuration,
|
||||||
containers,
|
containers,
|
||||||
node.parent,
|
node.parent,
|
||||||
index, 0,
|
index,
|
||||||
|
0,
|
||||||
newCounters,
|
newCounters,
|
||||||
symbols
|
symbols
|
||||||
);
|
);
|
||||||
|
@ -429,8 +449,9 @@ function AddContainerInLevel(
|
||||||
// and set the new parent as the child of this parent
|
// and set the new parent as the child of this parent
|
||||||
const container = configs.get(pattern.wrapper);
|
const container = configs.get(pattern.wrapper);
|
||||||
if (container === undefined) {
|
if (container === undefined) {
|
||||||
console.warn(`[InitializeChildrenFromPattern] IAvailableContainer from pattern was not found in the configuration: ${pattern.wrapper}.
|
console.warn('[InitializeChildrenFromPattern]' +
|
||||||
Process will ignore the container.`);
|
` IAvailableContainer from pattern was not found in the configuration: ${pattern.wrapper}.
|
||||||
|
Process will ignore the container.`);
|
||||||
return { parent, pattern };
|
return { parent, pattern };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,7 +460,8 @@ function AddContainerInLevel(
|
||||||
configuration,
|
configuration,
|
||||||
containers,
|
containers,
|
||||||
parent,
|
parent,
|
||||||
0, 0,
|
0,
|
||||||
|
0,
|
||||||
newCounters,
|
newCounters,
|
||||||
symbols,
|
symbols,
|
||||||
false
|
false
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import { IHistoryState } from '../../../Interfaces/IHistoryState';
|
import Swal from 'sweetalert2';
|
||||||
import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
import { type IHistoryState } from '../../../Interfaces/IHistoryState';
|
||||||
|
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||||
import { FindContainerById, MakeDFSIterator } from '../../../utils/itertools';
|
import { FindContainerById, MakeDFSIterator } from '../../../utils/itertools';
|
||||||
import { GetCurrentHistory } from '../Editor';
|
import { GetCurrentHistory } from '../Editor';
|
||||||
import { ApplyBehaviors, ApplyBehaviorsOnSiblings, ApplyBehaviorsOnSiblingsChildren } from '../Behaviors/Behaviors';
|
import { ApplyBehaviors, ApplyBehaviorsOnSiblings, ApplyBehaviorsOnSiblingsChildren } from '../Behaviors/Behaviors';
|
||||||
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
||||||
import Swal from 'sweetalert2';
|
|
||||||
import { PropertyType } from '../../../Enums/PropertyType';
|
import { PropertyType } from '../../../Enums/PropertyType';
|
||||||
import { TransformX, TransformY } from '../../../utils/svg';
|
import { TransformX, TransformY } from '../../../utils/svg';
|
||||||
import { Orientation } from '../../../Enums/Orientation';
|
import { Orientation } from '../../../Enums/Orientation';
|
||||||
|
import { type IConfiguration } from '../../../Interfaces/IConfiguration';
|
||||||
import { AddContainers } from './AddContainer';
|
import { AddContainers } from './AddContainer';
|
||||||
import { IConfiguration } from '../../../Interfaces/IConfiguration';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select a container
|
* Select a container
|
||||||
|
@ -82,7 +82,8 @@ export function DeleteContainer(
|
||||||
const container = FindContainerById(containers, containerId);
|
const container = FindContainerById(containers, containerId);
|
||||||
|
|
||||||
if (container === undefined) {
|
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);
|
const parent = FindContainerById(containers, container.properties.parentId);
|
||||||
|
@ -94,7 +95,8 @@ export function DeleteContainer(
|
||||||
text: 'Deleting the main container is not allowed!',
|
text: 'Deleting the main container is not allowed!',
|
||||||
icon: 'error'
|
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) {
|
if (container === null || container === undefined) {
|
||||||
|
@ -168,7 +170,9 @@ export function ReplaceByContainer(
|
||||||
containerParent.children.indexOf(containerId),
|
containerParent.children.indexOf(containerId),
|
||||||
[{ Type: newContainerId }],
|
[{ Type: newContainerId }],
|
||||||
containerParent.properties.id,
|
containerParent.properties.id,
|
||||||
configuration, fullHistory, historyCurrentStep
|
configuration,
|
||||||
|
fullHistory,
|
||||||
|
historyCurrentStep
|
||||||
);
|
);
|
||||||
|
|
||||||
const historyDelete = DeleteContainer(containerId, historyAdd.history, historyCurrentStep + 1);
|
const historyDelete = DeleteContainer(containerId, historyAdd.history, historyCurrentStep + 1);
|
||||||
|
@ -294,34 +298,7 @@ export function SortChildren(
|
||||||
const children = parent.children;
|
const children = parent.children;
|
||||||
|
|
||||||
if (!isHorizontal) {
|
if (!isHorizontal) {
|
||||||
parent.children.sort(
|
parent.children.sort((aId, bId) => {
|
||||||
(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) => {
|
|
||||||
const a = FindContainerById(containers, aId);
|
const a = FindContainerById(containers, aId);
|
||||||
const b = FindContainerById(containers, bId);
|
const b = FindContainerById(containers, bId);
|
||||||
|
|
||||||
|
@ -329,20 +306,43 @@ export function SortChildren(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const xA = TransformX(a.properties.x, a.properties.width, a.properties.positionReference);
|
const yA = TransformY(a.properties.y, a.properties.height, a.properties.positionReference);
|
||||||
const xB = TransformX(b.properties.x, b.properties.width, b.properties.positionReference);
|
const yB = TransformY(b.properties.y, b.properties.height, b.properties.positionReference);
|
||||||
if (xA < xB) {
|
if (yA < yB) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (xB < xA) {
|
if (yB < yA) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
// xA = xB
|
// xA = xB
|
||||||
const indexA = children.indexOf(aId);
|
const indexA = children.indexOf(aId);
|
||||||
const indexB = children.indexOf(bId);
|
const indexB = children.indexOf(bId);
|
||||||
return indexA - indexB;
|
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(
|
function SetContainer(
|
||||||
containers: Map<string, IContainerModel>,
|
containers: Map<string, IContainerModel>,
|
||||||
container: IContainerModel,
|
container: IContainerModel,
|
||||||
key: string, value: string | number | boolean | number[],
|
key: string,
|
||||||
|
value: string | number | boolean | number[],
|
||||||
type: PropertyType,
|
type: PropertyType,
|
||||||
symbols: Map<string, ISymbolModel>
|
symbols: Map<string, ISymbolModel>
|
||||||
): void {
|
): void {
|
||||||
|
@ -396,7 +397,12 @@ function SetContainer(
|
||||||
* @param value Value of the property
|
* @param value Value of the property
|
||||||
* @param type Type 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) {
|
switch (type) {
|
||||||
case PropertyType.Style:
|
case PropertyType.Style:
|
||||||
(container.properties.style as any)[key] = value;
|
(container.properties.style as any)[key] = value;
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
import Swal from 'sweetalert2';
|
import Swal from 'sweetalert2';
|
||||||
import { Dispatch, SetStateAction } from 'react';
|
import { type Dispatch, type SetStateAction } from 'react';
|
||||||
import { AddMethod } from '../../../Enums/AddMethod';
|
import { AddMethod } from '../../../Enums/AddMethod';
|
||||||
import { IAction } from '../../../Interfaces/IAction';
|
import { type IAction } from '../../../Interfaces/IAction';
|
||||||
import { IConfiguration } from '../../../Interfaces/IConfiguration';
|
import { type IConfiguration } from '../../../Interfaces/IConfiguration';
|
||||||
import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||||
import { IHistoryState } from '../../../Interfaces/IHistoryState';
|
import { type IHistoryState } from '../../../Interfaces/IHistoryState';
|
||||||
import { ISetContainerListRequest } from '../../../Interfaces/ISetContainerListRequest';
|
import { type ISetContainerListRequest } from '../../../Interfaces/ISetContainerListRequest';
|
||||||
import { ISetContainerListResponse } from '../../../Interfaces/ISetContainerListResponse';
|
import { type ISetContainerListResponse } from '../../../Interfaces/ISetContainerListResponse';
|
||||||
import { DISABLE_API } from '../../../utils/default';
|
import { DISABLE_API } from '../../../utils/default';
|
||||||
import { FindContainerById } from '../../../utils/itertools';
|
import { FindContainerById } from '../../../utils/itertools';
|
||||||
import { SetContainerList } from '../../API/api';
|
import { SetContainerList } from '../../API/api';
|
||||||
import { IMenuAction } from '../../Menu/Menu';
|
import { type IMenuAction } from '../../Menu/Menu';
|
||||||
import { GetCurrentHistoryState } from '../Editor';
|
import { GetCurrentHistoryState } from '../Editor';
|
||||||
|
import { Text } from '../../Text/Text';
|
||||||
|
import { type IReplaceContainer } from '../../../Interfaces/IReplaceContainer';
|
||||||
import { AddContainers } from './AddContainer';
|
import { AddContainers } from './AddContainer';
|
||||||
import { DeleteContainer } from './ContainerOperations';
|
import { DeleteContainer } from './ContainerOperations';
|
||||||
import { DeleteSymbol } from './SymbolOperations';
|
import { DeleteSymbol } from './SymbolOperations';
|
||||||
import { Text } from '../../Text/Text';
|
|
||||||
import { IReplaceContainer } from '../../../Interfaces/IReplaceContainer';
|
|
||||||
|
|
||||||
export function InitActions(
|
export function InitActions(
|
||||||
menuActions: Map<string, IMenuAction[]>,
|
menuActions: Map<string, IMenuAction[]>,
|
||||||
|
@ -63,7 +63,9 @@ export function InitActions(
|
||||||
shortcut: '<kbd>R</kbd>',
|
shortcut: '<kbd>R</kbd>',
|
||||||
action: (target: HTMLElement) => {
|
action: (target: HTMLElement) => {
|
||||||
const targetContainer = FindContainerById(history[historyCurrentStep].containers, target.id);
|
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) {
|
if (targetAvailableContainer === undefined) {
|
||||||
return;
|
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 prev;
|
||||||
let next;
|
let next;
|
||||||
const parent = FindContainerById(containers, container.properties.parentId);
|
const parent = FindContainerById(containers, container.properties.parentId);
|
||||||
|
@ -230,22 +235,21 @@ function HandleSetContainerList(
|
||||||
selectedContainer.properties.id,
|
selectedContainer.properties.id,
|
||||||
configuration,
|
configuration,
|
||||||
history,
|
history,
|
||||||
historyCurrentStep);
|
historyCurrentStep
|
||||||
|
);
|
||||||
|
|
||||||
setNewHistory(newHistory);
|
setNewHistory(newHistory);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case AddMethod.Replace:
|
case AddMethod.Replace:
|
||||||
setNewHistory(
|
setNewHistory(HandleReplace(
|
||||||
HandleReplace(
|
containers,
|
||||||
containers,
|
selectedContainer,
|
||||||
selectedContainer,
|
response,
|
||||||
response,
|
configuration,
|
||||||
configuration,
|
history,
|
||||||
history,
|
historyCurrentStep
|
||||||
historyCurrentStep
|
));
|
||||||
)
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case AddMethod.ReplaceParent: {
|
case AddMethod.ReplaceParent: {
|
||||||
const parent = FindContainerById(containers, selectedContainer.properties.parentId);
|
const parent = FindContainerById(containers, selectedContainer.properties.parentId);
|
||||||
|
@ -257,16 +261,14 @@ function HandleSetContainerList(
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setNewHistory(
|
setNewHistory(HandleReplace(
|
||||||
HandleReplace(
|
containers,
|
||||||
containers,
|
parent,
|
||||||
parent,
|
response,
|
||||||
response,
|
configuration,
|
||||||
configuration,
|
history,
|
||||||
history,
|
historyCurrentStep
|
||||||
historyCurrentStep
|
));
|
||||||
)
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { IHistoryState } from '../../../Interfaces/IHistoryState';
|
import { type IHistoryState } from '../../../Interfaces/IHistoryState';
|
||||||
import { IConfiguration } from '../../../Interfaces/IConfiguration';
|
import { type IConfiguration } from '../../../Interfaces/IConfiguration';
|
||||||
import { GetCircularReplacer } from '../../../utils/saveload';
|
import { GetCircularReplacer } from '../../../utils/saveload';
|
||||||
import { ID } from '../../SVG/SVG';
|
import { ID } from '../../SVG/SVG';
|
||||||
import { IEditorState } from '../../../Interfaces/IEditorState';
|
import { type IEditorState } from '../../../Interfaces/IEditorState';
|
||||||
import { SHOW_SELECTOR_TEXT } from '../../../utils/default';
|
import { SHOW_SELECTOR_TEXT } from '../../../utils/default';
|
||||||
|
|
||||||
export function SaveEditorAsJSON(
|
export function SaveEditorAsJSON(
|
||||||
|
@ -11,7 +11,9 @@ export function SaveEditorAsJSON(
|
||||||
configuration: IConfiguration
|
configuration: IConfiguration
|
||||||
): void {
|
): void {
|
||||||
const exportName = 'state.json';
|
const exportName = 'state.json';
|
||||||
const spaces = import.meta.env.DEV ? 4 : 0;
|
const spaces = import.meta.env.DEV
|
||||||
|
? 4
|
||||||
|
: 0;
|
||||||
const editorState: IEditorState = {
|
const editorState: IEditorState = {
|
||||||
history,
|
history,
|
||||||
historyCurrentStep,
|
historyCurrentStep,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Dispatch, SetStateAction } from 'react';
|
import { type Dispatch, type SetStateAction } from 'react';
|
||||||
import { IHistoryState } from '../../../Interfaces/IHistoryState';
|
import { type IHistoryState } from '../../../Interfaces/IHistoryState';
|
||||||
import { ENABLE_SHORTCUTS } from '../../../utils/default';
|
import { ENABLE_SHORTCUTS } from '../../../utils/default';
|
||||||
|
|
||||||
export function OnKey(
|
export function OnKey(
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { type IHistoryState } from '../../../Interfaces/IHistoryState';
|
||||||
import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
||||||
import { GetDefaultSymbolModel } from '../../../utils/default';
|
import { GetDefaultSymbolModel } from '../../../utils/default';
|
||||||
import { FindContainerById } from '../../../utils/itertools';
|
import { FindContainerById } from '../../../utils/itertools';
|
||||||
import {RestoreX, RestoreY} from '../../../utils/svg';
|
import { RestoreX, RestoreY } from '../../../utils/svg';
|
||||||
import { ApplyBehaviors, ApplyBehaviorsOnSiblingsChildren } from '../Behaviors/Behaviors';
|
import { ApplyBehaviors, ApplyBehaviorsOnSiblingsChildren } from '../Behaviors/Behaviors';
|
||||||
import { GetCurrentHistory, GetCurrentHistoryState, UpdateCounters } from '../Editor';
|
import { GetCurrentHistory, GetCurrentHistoryState, UpdateCounters } from '../Editor';
|
||||||
import { AddContainers } from './AddContainer';
|
import { AddContainers } from './AddContainer';
|
||||||
|
@ -212,5 +212,7 @@ function LinkContainer(
|
||||||
): void {
|
): void {
|
||||||
const oldSymbol = symbols.get(container.properties.linkedSymbolId);
|
const oldSymbol = symbols.get(container.properties.linkedSymbolId);
|
||||||
LinkSymbol(container.properties.id, oldSymbol, symbol);
|
LinkSymbol(container.properties.id, oldSymbol, symbol);
|
||||||
container.properties.linkedSymbolId = symbol !== undefined ? symbol.id : '';
|
container.properties.linkedSymbolId = symbol !== undefined
|
||||||
|
? symbol.id
|
||||||
|
: '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,31 +13,34 @@
|
||||||
* or make them lose their property as a rigid body
|
* 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 { Orientation } from '../../../Enums/Orientation';
|
||||||
import { ConstraintBodyInsideUnallocatedWidth } from './RigidBodyBehaviors';
|
|
||||||
import { FindContainerById } from '../../../utils/itertools';
|
import { FindContainerById } from '../../../utils/itertools';
|
||||||
|
import { ConstraintBodyInsideUnallocatedWidth } from './RigidBodyBehaviors';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Impose the container position to its siblings
|
* Impose the container position to its siblings
|
||||||
* Apply the following modification to the overlapping rigid body container :
|
* Apply the following modification to the overlapping rigid body container :
|
||||||
* @param container Container to impose its position
|
* @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[] = [];
|
const rigidBodies: IContainerModel[] = [];
|
||||||
parent.children.forEach(
|
parent.children.forEach(childId => {
|
||||||
childId => {
|
const child = FindContainerById(containers, childId);
|
||||||
const child = FindContainerById(containers, childId);
|
|
||||||
|
|
||||||
if (child === undefined) {
|
if (child === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child.properties.isAnchor) {
|
if (child.properties.isAnchor) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rigidBodies.push(child);
|
rigidBodies.push(child);
|
||||||
});
|
});
|
||||||
|
|
||||||
const isHorizontal = parent.properties.orientation === Orientation.Horizontal;
|
const isHorizontal = parent.properties.orientation === Orientation.Horizontal;
|
||||||
const overlappingContainers = isHorizontal
|
const overlappingContainers = isHorizontal
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||||
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
||||||
import { APPLY_BEHAVIORS_ON_CHILDREN, ENABLE_RIGID, ENABLE_SWAP } from '../../../utils/default';
|
import { APPLY_BEHAVIORS_ON_CHILDREN, ENABLE_RIGID, ENABLE_SWAP } from '../../../utils/default';
|
||||||
import { FindContainerById, MakeChildrenIterator } from '../../../utils/itertools';
|
import { FindContainerById, MakeChildrenIterator } from '../../../utils/itertools';
|
||||||
import { ApplyAnchor, GetOverlappingContainers } from './AnchorBehaviors';
|
import { ApplyAnchor, GetOverlappingContainers } from './AnchorBehaviors';
|
||||||
|
@ -14,7 +14,11 @@ import { ApplySymbol } from './SymbolBehaviors';
|
||||||
* @param container Container to recalculate its positions
|
* @param container Container to recalculate its positions
|
||||||
* @returns Updated container
|
* @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 {
|
try {
|
||||||
const symbol = symbols.get(container.properties.linkedSymbolId);
|
const symbol = symbols.get(container.properties.linkedSymbolId);
|
||||||
if (container.properties.linkedSymbolId !== '' && symbol !== undefined) {
|
if (container.properties.linkedSymbolId !== '' && symbol !== undefined) {
|
||||||
|
@ -67,7 +71,8 @@ export function ApplyBehaviors(containers: Map<string, IContainerModel>, contain
|
||||||
export function ApplyBehaviorsOnSiblingsChildren(
|
export function ApplyBehaviorsOnSiblingsChildren(
|
||||||
containers: Map<string, IContainerModel>,
|
containers: Map<string, IContainerModel>,
|
||||||
newContainer: IContainerModel,
|
newContainer: IContainerModel,
|
||||||
symbols: Map<string, ISymbolModel>): void {
|
symbols: Map<string, ISymbolModel>
|
||||||
|
): void {
|
||||||
const parent = FindContainerById(containers, newContainer.properties.parentId);
|
const parent = FindContainerById(containers, newContainer.properties.parentId);
|
||||||
if (parent === null || parent === undefined) {
|
if (parent === null || parent === undefined) {
|
||||||
return;
|
return;
|
||||||
|
@ -102,7 +107,11 @@ export function ApplyBehaviorsOnSiblingsChildren(
|
||||||
* @param symbols
|
* @param symbols
|
||||||
* @returns
|
* @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);
|
const parent = FindContainerById(containers, newContainer.properties.parentId);
|
||||||
if (parent === null || parent === undefined) {
|
if (parent === null || parent === undefined) {
|
||||||
return;
|
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[] = [];
|
const targetContainers: IContainerModel[] = [];
|
||||||
|
|
||||||
parent.children.forEach((child) => {
|
parent.children.forEach((child) => {
|
||||||
|
@ -146,7 +159,8 @@ function UpdateWarning(containers: Map<string, IContainerModel>, container: ICon
|
||||||
});
|
});
|
||||||
const overlappingContainers = GetOverlappingContainers(container, targetContainers);
|
const overlappingContainers = GetOverlappingContainers(container, targetContainers);
|
||||||
if (overlappingContainers.length > 0) {
|
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 {
|
} else {
|
||||||
container.properties.warning = '';
|
container.properties.warning = '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||||
import { Orientation } from '../../../Enums/Orientation';
|
import { Orientation } from '../../../Enums/Orientation';
|
||||||
import { Simplex } from '../../../utils/simplex';
|
import { Simplex } from '../../../utils/simplex';
|
||||||
import { ApplyWidthMargin, ApplyXMargin } from '../../../utils/svg';
|
import { ApplyWidthMargin, ApplyXMargin } from '../../../utils/svg';
|
||||||
|
@ -14,12 +14,20 @@ interface IFlexibleGroup {
|
||||||
* Flex the container and its siblings (mutate)
|
* Flex the container and its siblings (mutate)
|
||||||
* @returns Flexed container
|
* @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;
|
const isVertical = parent.properties.orientation === Orientation.Vertical;
|
||||||
|
|
||||||
if (isVertical) {
|
if (isVertical) {
|
||||||
const wantedWidth = Math.min(container.properties.maxWidth, parent.properties.width);
|
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);
|
const flexibleGroups = GetVerticalFlexibleGroups(containers, parent);
|
||||||
for (const flexibleGroup of flexibleGroups) {
|
for (const flexibleGroup of flexibleGroups) {
|
||||||
FlexGroupVertically(flexibleGroup);
|
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);
|
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);
|
const flexibleGroups = GetHorizontalFlexibleGroups(containers, parent);
|
||||||
for (const flexibleGroup of flexibleGroups) {
|
for (const flexibleGroup of flexibleGroups) {
|
||||||
FlexGroupHorizontally(flexibleGroup);
|
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
|
* @param parent Parent in which the flexible children will be set in groups
|
||||||
* @returns a list of groups of flexible containers
|
* @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[] = [];
|
const flexibleGroups: IFlexibleGroup[] = [];
|
||||||
let group: IContainerModel[] = [];
|
let group: IContainerModel[] = [];
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
|
@ -158,7 +173,11 @@ function FlexGroupHorizontally(flexibleGroup: IFlexibleGroup): void {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sibling.properties.x = ApplyXMargin(right, sibling.properties.margin.left);
|
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;
|
right += wantedWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,7 +193,11 @@ function FlexGroupHorizontally(flexibleGroup: IFlexibleGroup): void {
|
||||||
|
|
||||||
// apply the solutions
|
// apply the solutions
|
||||||
for (let i = 0; i < flexibleContainers.length; i++) {
|
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
|
// move the containers
|
||||||
|
@ -229,7 +252,11 @@ function FlexGroupVertically(flexibleGroup: IFlexibleGroup): void {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sibling.properties.y = ApplyXMargin(right, sibling.properties.margin.top);
|
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;
|
right += wantedHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +272,11 @@ function FlexGroupVertically(flexibleGroup: IFlexibleGroup): void {
|
||||||
|
|
||||||
// apply the solutions
|
// apply the solutions
|
||||||
for (let i = 0; i < flexibleContainers.length; i++) {
|
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
|
// move the containers
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||||
import { Orientation } from '../../../Enums/Orientation';
|
import { Orientation } from '../../../Enums/Orientation';
|
||||||
import { MakeChildrenIterator, ReversePairwise } from '../../../utils/itertools';
|
import { MakeChildrenIterator, ReversePairwise } from '../../../utils/itertools';
|
||||||
import { Flex } from './FlexBehaviors';
|
import { Flex } from './FlexBehaviors';
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
* If the contraints fails, an error message will be returned
|
* If the contraints fails, an error message will be returned
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||||
import { ISizePointer } from '../../../Interfaces/ISizePointer';
|
import { type ISizePointer } from '../../../Interfaces/ISizePointer';
|
||||||
import { Orientation } from '../../../Enums/Orientation';
|
import { Orientation } from '../../../Enums/Orientation';
|
||||||
import { ENABLE_HARD_RIGID } from '../../../utils/default';
|
import { ENABLE_HARD_RIGID } from '../../../utils/default';
|
||||||
import { FindContainerById, MakeChildrenIterator } from '../../../utils/itertools';
|
import { FindContainerById, MakeChildrenIterator } from '../../../utils/itertools';
|
||||||
|
@ -141,9 +141,7 @@ export function ConstraintBodyInsideUnallocatedWidth(
|
||||||
|
|
||||||
// Check if there is still some space
|
// Check if there is still some space
|
||||||
if (availableWidths.length === 0) {
|
if (availableWidths.length === 0) {
|
||||||
throw new Error(
|
throw new Error('No available space found on the parent container. Try to free the parent a bit.');
|
||||||
'No available space found on the parent container. Try to free the parent a bit.'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const containerId = container.properties.id;
|
const containerId = container.properties.id;
|
||||||
|
@ -158,8 +156,7 @@ export function ConstraintBodyInsideUnallocatedWidth(
|
||||||
// Check if the container actually fit inside
|
// Check if the container actually fit inside
|
||||||
// It will usually fit if it was alrady fitting
|
// It will usually fit if it was alrady fitting
|
||||||
const availableWidthFound = availableWidths.find((width) =>
|
const availableWidthFound = availableWidths.find((width) =>
|
||||||
IsFitting(containerHeight, width)
|
IsFitting(containerHeight, width));
|
||||||
);
|
|
||||||
|
|
||||||
if (availableWidthFound === undefined) {
|
if (availableWidthFound === undefined) {
|
||||||
const { x, width } = TrySqueeze(containerY, containerHeight, containerMinHeight, containerId, availableWidths);
|
const { x, width } = TrySqueeze(containerY, containerHeight, containerMinHeight, containerId, availableWidths);
|
||||||
|
@ -189,8 +186,7 @@ export function ConstraintBodyInsideUnallocatedWidth(
|
||||||
// Check if the container actually fit inside
|
// Check if the container actually fit inside
|
||||||
// It will usually fit if it was alrady fitting
|
// It will usually fit if it was alrady fitting
|
||||||
const availableWidthFound = availableWidths.find((width) =>
|
const availableWidthFound = availableWidths.find((width) =>
|
||||||
IsFitting(containerWidth, width)
|
IsFitting(containerWidth, width));
|
||||||
);
|
|
||||||
|
|
||||||
if (availableWidthFound === undefined) {
|
if (availableWidthFound === undefined) {
|
||||||
const { x, width } = TrySqueeze(containerX, containerWidth, containerMinWidth, containerId, availableWidths);
|
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;
|
const middle = containerX + containerWidth / 2;
|
||||||
// Sort the available width to find the space with the closest position
|
// Sort the available width to find the space with the closest position
|
||||||
availableWidths.sort(
|
availableWidths.sort((width1, width2) => {
|
||||||
(width1, width2) => {
|
let compared1X = width1.x;
|
||||||
let compared1X = width1.x;
|
if (width1.x < containerX) {
|
||||||
if (width1.x < containerX) {
|
compared1X = width1.x + width1.width - containerWidth;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
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
|
* @param sizePointer Size space to check
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function IsFitting(containerWidth: number,
|
function IsFitting(
|
||||||
sizePointer: ISizePointer): boolean {
|
containerWidth: number,
|
||||||
|
sizePointer: ISizePointer
|
||||||
|
): boolean {
|
||||||
return containerWidth <= sizePointer.width;
|
return containerWidth <= sizePointer.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +280,8 @@ function IsFitting(containerWidth: number,
|
||||||
* (except the fact that disk space is divided by block).
|
* (except the fact that disk space is divided by block).
|
||||||
* @param container Container where to find an available width
|
* @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)
|
* @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(
|
function GetAvailableWidths(
|
||||||
x: number,
|
x: number,
|
||||||
|
@ -303,8 +304,12 @@ function GetAvailableWidths(
|
||||||
if (child === exception) {
|
if (child === exception) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const childX = isHorizontal ? child.properties.x : child.properties.y;
|
const childX = isHorizontal
|
||||||
const childWidth = isHorizontal ? child.properties.width : child.properties.height;
|
? 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
|
// get the space of the child that is inside the parent
|
||||||
let newUnallocatedSpace: ISizePointer[] = [];
|
let newUnallocatedSpace: ISizePointer[] = [];
|
||||||
|
|
|
@ -2,15 +2,16 @@
|
||||||
* Swap two flex container when one is overlapping another
|
* 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 { Orientation } from '../../../Enums/Orientation';
|
||||||
import { GetHorizontallyOverlappingContainers, GetVerticallyOverlappingContainers } from './AnchorBehaviors';
|
|
||||||
import { MakeChildrenIterator } from '../../../utils/itertools';
|
import { MakeChildrenIterator } from '../../../utils/itertools';
|
||||||
|
import { GetHorizontallyOverlappingContainers, GetVerticallyOverlappingContainers } from './AnchorBehaviors';
|
||||||
|
|
||||||
export function ApplySwap(
|
export function ApplySwap(
|
||||||
containers: Map<string, IContainerModel>,
|
containers: Map<string, IContainerModel>,
|
||||||
container: IContainerModel,
|
container: IContainerModel,
|
||||||
parent: IContainerModel): void {
|
parent: IContainerModel
|
||||||
|
): void {
|
||||||
const children = [...MakeChildrenIterator(containers, parent.children)];
|
const children = [...MakeChildrenIterator(containers, parent.children)];
|
||||||
|
|
||||||
const isVertical = parent.properties.orientation === Orientation.Vertical;
|
const isVertical = parent.properties.orientation === Orientation.Vertical;
|
||||||
|
@ -36,7 +37,10 @@ export function SwapHorizontally(container: IContainerModel, children: IContaine
|
||||||
}
|
}
|
||||||
|
|
||||||
// swap positions
|
// 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 indexContainer = children.indexOf(container);
|
||||||
const indexOverlapping = children.indexOf(overlappingContainer);
|
const indexOverlapping = children.indexOf(overlappingContainer);
|
||||||
[children[indexContainer], children[indexOverlapping]] = [children[indexOverlapping], children[indexContainer]];
|
[children[indexContainer], children[indexOverlapping]] = [children[indexOverlapping], children[indexContainer]];
|
||||||
|
@ -56,7 +60,10 @@ export function SwapVertically(container: IContainerModel, children: IContainerM
|
||||||
}
|
}
|
||||||
|
|
||||||
// swap positions
|
// 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 indexContainer = children.indexOf(container);
|
||||||
const indexOverlapping = children.indexOf(overlappingContainer);
|
const indexOverlapping = children.indexOf(overlappingContainer);
|
||||||
[children[indexContainer], children[indexOverlapping]] = [children[indexOverlapping], children[indexContainer]];
|
[children[indexContainer], children[indexOverlapping]] = [children[indexOverlapping], children[indexContainer]];
|
||||||
|
|
|
@ -3,16 +3,22 @@ import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
||||||
import { ApplyParentTransform, FindContainerById } from '../../../utils/itertools';
|
import { ApplyParentTransform, FindContainerById } from '../../../utils/itertools';
|
||||||
import { RestoreX, RestoreY, TransformX, TransformY } from '../../../utils/svg';
|
import { RestoreX, RestoreY, TransformX, TransformY } from '../../../utils/svg';
|
||||||
|
|
||||||
export function ApplySymbol(containers: Map<string, IContainerModel>,
|
export function ApplySymbol(
|
||||||
|
containers: Map<string, IContainerModel>,
|
||||||
container: IContainerModel,
|
container: IContainerModel,
|
||||||
symbol: ISymbolModel): IContainerModel {
|
symbol: ISymbolModel
|
||||||
|
): IContainerModel {
|
||||||
if (symbol.isVertical) {
|
if (symbol.isVertical) {
|
||||||
container.properties.y = TransformY(symbol.offset,
|
container.properties.y = TransformY(
|
||||||
|
symbol.offset,
|
||||||
symbol.height,
|
symbol.height,
|
||||||
symbol.config.PositionReference);
|
symbol.config.PositionReference
|
||||||
container.properties.y = RestoreY(container.properties.y,
|
);
|
||||||
|
container.properties.y = RestoreY(
|
||||||
|
container.properties.y,
|
||||||
container.properties.height,
|
container.properties.height,
|
||||||
container.properties.positionReference);
|
container.properties.positionReference
|
||||||
|
);
|
||||||
const parent = FindContainerById(containers, container.properties.parentId);
|
const parent = FindContainerById(containers, container.properties.parentId);
|
||||||
let y = 0;
|
let y = 0;
|
||||||
if (parent !== undefined && parent !== null) {
|
if (parent !== undefined && parent !== null) {
|
||||||
|
@ -24,10 +30,13 @@ export function ApplySymbol(containers: Map<string, IContainerModel>,
|
||||||
container.properties.x = TransformX(
|
container.properties.x = TransformX(
|
||||||
symbol.offset,
|
symbol.offset,
|
||||||
symbol.width,
|
symbol.width,
|
||||||
symbol.config.PositionReference);
|
symbol.config.PositionReference
|
||||||
container.properties.x = RestoreX(container.properties.x,
|
);
|
||||||
|
container.properties.x = RestoreX(
|
||||||
|
container.properties.x,
|
||||||
container.properties.width,
|
container.properties.width,
|
||||||
container.properties.positionReference);
|
container.properties.positionReference
|
||||||
|
);
|
||||||
const parent = FindContainerById(containers, container.properties.parentId);
|
const parent = FindContainerById(containers, container.properties.parentId);
|
||||||
let x = 0;
|
let x = 0;
|
||||||
if (parent !== undefined && parent !== null) {
|
if (parent !== undefined && parent !== null) {
|
||||||
|
|
|
@ -3,17 +3,22 @@ import './Editor.scss';
|
||||||
import { type IConfiguration } from '../../Interfaces/IConfiguration';
|
import { type IConfiguration } from '../../Interfaces/IConfiguration';
|
||||||
import { type IHistoryState } from '../../Interfaces/IHistoryState';
|
import { type IHistoryState } from '../../Interfaces/IHistoryState';
|
||||||
import { UI } from '../UI/UI';
|
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 { SelectContainer, DeleteContainer, OnPropertyChange, ReplaceByContainer } from './Actions/ContainerOperations';
|
||||||
import { SaveEditorAsJSON, SaveEditorAsSVG } from './Actions/Save';
|
import { SaveEditorAsJSON, SaveEditorAsSVG } from './Actions/Save';
|
||||||
import { OnKey } from './Actions/Shortcuts';
|
import { OnKey } from './Actions/Shortcuts';
|
||||||
import { UseCustomEvents, UseEditorListener } from '../../Events/EditorEvents';
|
import {
|
||||||
import { MAX_HISTORY } from '../../utils/default';
|
AddSymbol,
|
||||||
import { AddSymbol, OnPropertyChange as OnSymbolPropertyChange, DeleteSymbol, SelectSymbol } from './Actions/SymbolOperations';
|
OnPropertyChange as OnSymbolPropertyChange,
|
||||||
import { FindContainerById } from '../../utils/itertools';
|
DeleteSymbol,
|
||||||
import { Menu } from '../Menu/Menu';
|
SelectSymbol
|
||||||
|
} from './Actions/SymbolOperations';
|
||||||
import { InitActions } from './Actions/ContextMenuActions';
|
import { InitActions } from './Actions/ContextMenuActions';
|
||||||
import { AddContainerToSelectedContainer, AddContainer } from './Actions/AddContainer';
|
import { AddContainerToSelectedContainer, AddContainer } from './Actions/AddContainer';
|
||||||
import { type IReplaceContainer } from '../../Interfaces/IReplaceContainer';
|
|
||||||
|
|
||||||
interface IEditorProps {
|
interface IEditorProps {
|
||||||
root: Element | Document
|
root: Element | Document
|
||||||
|
@ -61,16 +66,20 @@ function UseNewHistoryState(
|
||||||
): (newHistory: IHistoryState[], historyCurrentStep?: number) => void {
|
): (newHistory: IHistoryState[], historyCurrentStep?: number) => void {
|
||||||
return (newHistory, historyCurrentStep?: number) => {
|
return (newHistory, historyCurrentStep?: number) => {
|
||||||
setHistory(newHistory);
|
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 {
|
export function Editor(props: IEditorProps): JSX.Element {
|
||||||
// States
|
// States
|
||||||
const [history, setHistory] = React.useState<IHistoryState[]>(structuredClone(props.history));
|
const [history, setHistory] = React.useState<IHistoryState[]>(structuredClone(props.history));
|
||||||
const [historyCurrentStep, setHistoryCurrentStep] = React.useState<number>(props.historyCurrentStep);
|
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 editorRef = useRef<HTMLDivElement>(null);
|
||||||
const setNewHistory = UseNewHistoryState(setHistory, setHistoryCurrentStep);
|
const setNewHistory = UseNewHistoryState(setHistory, setHistoryCurrentStep);
|
||||||
|
@ -86,9 +95,7 @@ export function Editor(props: IEditorProps): JSX.Element {
|
||||||
setHistoryCurrentStep,
|
setHistoryCurrentStep,
|
||||||
() => {
|
() => {
|
||||||
const current = GetCurrentHistoryState(history, historyCurrentStep);
|
const current = GetCurrentHistoryState(history, historyCurrentStep);
|
||||||
setNewHistory(
|
setNewHistory(DeleteContainer(current.selectedContainerId, history, historyCurrentStep));
|
||||||
DeleteContainer(current.selectedContainerId, history, historyCurrentStep)
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
ResetState
|
ResetState
|
||||||
);
|
);
|
||||||
|
@ -134,29 +141,28 @@ export function Editor(props: IEditorProps): JSX.Element {
|
||||||
}}
|
}}
|
||||||
replaceContainer={replaceContainer}
|
replaceContainer={replaceContainer}
|
||||||
selectContainer={(container) => {
|
selectContainer={(container) => {
|
||||||
setNewHistory(
|
setNewHistory(SelectContainer(
|
||||||
SelectContainer(
|
container,
|
||||||
container,
|
history,
|
||||||
history,
|
historyCurrentStep
|
||||||
historyCurrentStep
|
));
|
||||||
));
|
|
||||||
}}
|
}}
|
||||||
deleteContainer={(containerId: string) => {
|
deleteContainer={(containerId: string) => {
|
||||||
setNewHistory(
|
setNewHistory(DeleteContainer(
|
||||||
DeleteContainer(
|
containerId,
|
||||||
containerId,
|
history,
|
||||||
history,
|
historyCurrentStep
|
||||||
historyCurrentStep
|
));
|
||||||
));
|
|
||||||
}}
|
}}
|
||||||
onPropertyChange={(key, value, type) => {
|
onPropertyChange={(key, value, type) => {
|
||||||
setNewHistory(
|
setNewHistory(OnPropertyChange(
|
||||||
OnPropertyChange(
|
key,
|
||||||
key, value, type,
|
value,
|
||||||
selected,
|
type,
|
||||||
history,
|
selected,
|
||||||
historyCurrentStep
|
history,
|
||||||
));
|
historyCurrentStep
|
||||||
|
));
|
||||||
}}
|
}}
|
||||||
addOrReplaceContainer={(type) => {
|
addOrReplaceContainer={(type) => {
|
||||||
if (selected === null || selected === undefined) {
|
if (selected === null || selected === undefined) {
|
||||||
|
@ -183,49 +189,44 @@ export function Editor(props: IEditorProps): JSX.Element {
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
addContainerAt={(index, type, parent) => {
|
addContainerAt={(index, type, parent) => {
|
||||||
setNewHistory(
|
setNewHistory(AddContainer(
|
||||||
AddContainer(
|
index,
|
||||||
index,
|
type,
|
||||||
type,
|
parent,
|
||||||
parent,
|
configuration,
|
||||||
configuration,
|
history,
|
||||||
history,
|
historyCurrentStep
|
||||||
historyCurrentStep
|
));
|
||||||
)
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
addSymbol={(type) => {
|
addSymbol={(type) => {
|
||||||
setNewHistory(
|
setNewHistory(AddSymbol(
|
||||||
AddSymbol(
|
type,
|
||||||
type,
|
configuration,
|
||||||
configuration,
|
history,
|
||||||
history,
|
historyCurrentStep
|
||||||
historyCurrentStep
|
));
|
||||||
));
|
|
||||||
}}
|
}}
|
||||||
onSymbolPropertyChange={(key, value) => {
|
onSymbolPropertyChange={(key, value) => {
|
||||||
setNewHistory(
|
setNewHistory(OnSymbolPropertyChange(
|
||||||
OnSymbolPropertyChange(
|
key,
|
||||||
key, value,
|
value,
|
||||||
history,
|
history,
|
||||||
historyCurrentStep
|
historyCurrentStep
|
||||||
));
|
));
|
||||||
}}
|
}}
|
||||||
selectSymbol={(symbolId) => {
|
selectSymbol={(symbolId) => {
|
||||||
setNewHistory(
|
setNewHistory(SelectSymbol(
|
||||||
SelectSymbol(
|
symbolId,
|
||||||
symbolId,
|
history,
|
||||||
history,
|
historyCurrentStep
|
||||||
historyCurrentStep
|
));
|
||||||
));
|
|
||||||
}}
|
}}
|
||||||
deleteSymbol={(symbolId) => {
|
deleteSymbol={(symbolId) => {
|
||||||
setNewHistory(
|
setNewHistory(DeleteSymbol(
|
||||||
DeleteSymbol(
|
symbolId,
|
||||||
symbolId,
|
history,
|
||||||
history,
|
historyCurrentStep
|
||||||
historyCurrentStep
|
));
|
||||||
));
|
|
||||||
}}
|
}}
|
||||||
saveEditorAsJSON={() => {
|
saveEditorAsJSON={() => {
|
||||||
SaveEditorAsJSON(
|
SaveEditorAsJSON(
|
||||||
|
|
|
@ -88,7 +88,8 @@ function HandleOnDrop(
|
||||||
addContainer(
|
addContainer(
|
||||||
targetContainer.children.length,
|
targetContainer.children.length,
|
||||||
type,
|
type,
|
||||||
targetContainer.properties.id);
|
targetContainer.properties.id
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +114,8 @@ function HandleOnDrop(
|
||||||
addContainer(
|
addContainer(
|
||||||
targetContainer.children.length,
|
targetContainer.children.length,
|
||||||
type,
|
type,
|
||||||
targetContainer.properties.id);
|
targetContainer.properties.id
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
const index = parent.children.indexOf(targetContainer.properties.id);
|
const index = parent.children.indexOf(targetContainer.properties.id);
|
||||||
addContainer(
|
addContainer(
|
||||||
|
@ -219,12 +221,10 @@ function ElementsListRow(
|
||||||
? 'border-l-blue-400 group-hover:border-l-blue-300'
|
? 'border-l-blue-400 group-hover:border-l-blue-300'
|
||||||
: 'border-l-slate-400 group-hover:border-l-slate-300';
|
: 'border-l-slate-400 group-hover:border-l-slate-300';
|
||||||
for (let i = 0; i < depth; i++) {
|
for (let i = 0; i < depth; i++) {
|
||||||
verticalBars.push(
|
verticalBars.push(<span
|
||||||
<span
|
key={`${key}-${i}`}
|
||||||
key={`${key}-${i}`}
|
className={`h-full border-l-2 pr-2 ${verticalBarSelectedClass}`}
|
||||||
className={`h-full border-l-2 pr-2 ${verticalBarSelectedClass}`}
|
></span>);
|
||||||
></span>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const buttonSelectedClass: string = isSelected
|
const buttonSelectedClass: string = isSelected
|
||||||
|
@ -241,7 +241,9 @@ function ElementsListRow(
|
||||||
style={style}
|
style={style}
|
||||||
title={container.properties.warning}
|
title={container.properties.warning}
|
||||||
onClick={() => { selectContainer(container.properties.id); }}
|
onClick={() => { selectContainer(container.properties.id); }}
|
||||||
onDrop={(event) => { HandleOnDrop(event, containers, mainContainer, addContainer); }}
|
onDrop={(event) => {
|
||||||
|
HandleOnDrop(event, containers, mainContainer, addContainer);
|
||||||
|
}}
|
||||||
onDragOver={(event) => { HandleDragOver(event, mainContainer); }}
|
onDragOver={(event) => { HandleDragOver(event, mainContainer); }}
|
||||||
onDragLeave={(event) => { HandleDragLeave(event); }}
|
onDragLeave={(event) => { HandleDragLeave(event); }}
|
||||||
>
|
>
|
||||||
|
|
|
@ -6,14 +6,18 @@ interface IFloatingButtonProps {
|
||||||
className: string
|
className: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function ToggleState(isHidden: boolean,
|
function ToggleState(
|
||||||
setHidden: React.Dispatch<React.SetStateAction<boolean>>): void {
|
isHidden: boolean,
|
||||||
|
setHidden: React.Dispatch<React.SetStateAction<boolean>>
|
||||||
|
): void {
|
||||||
setHidden(!isHidden);
|
setHidden(!isHidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FloatingButton(props: IFloatingButtonProps): JSX.Element {
|
export function FloatingButton(props: IFloatingButtonProps): JSX.Element {
|
||||||
const [isHidden, setHidden] = React.useState(true);
|
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
|
const icon = isHidden
|
||||||
? <Bars3Icon className="floating-btn" />
|
? <Bars3Icon className="floating-btn" />
|
||||||
: <XMarkIcon className="floating-btn" />;
|
: <XMarkIcon className="floating-btn" />;
|
||||||
|
@ -24,9 +28,10 @@ export function FloatingButton(props: IFloatingButtonProps): JSX.Element {
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
<button type="button"
|
<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'
|
title='Open menu'
|
||||||
onClick={() => ToggleState(isHidden, setHidden)}
|
onClick={() => { ToggleState(isHidden, setHidden); }}
|
||||||
>
|
>
|
||||||
{icon}
|
{icon}
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -1,19 +1,23 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { CameraIcon, ArrowUpOnSquareIcon } from '@heroicons/react/24/outline';
|
import { CameraIcon, ArrowUpOnSquareIcon } from '@heroicons/react/24/outline';
|
||||||
|
import { type IUIProps } from '../UI/UI';
|
||||||
import { FloatingButton } from './FloatingButton';
|
import { FloatingButton } from './FloatingButton';
|
||||||
import { IUIProps } from '../UI/UI';
|
|
||||||
|
|
||||||
export function MenuButton(props: IUIProps): JSX.Element {
|
export function MenuButton(props: IUIProps): JSX.Element {
|
||||||
return <FloatingButton className={'fixed z-10 flex flex-col gap-2 items-center bottom-12 right-12'}>
|
return <FloatingButton className={'fixed z-10 flex flex-col gap-2 items-center bottom-12 right-12'}>
|
||||||
<button type="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 JSON'
|
title='Export as JSON'
|
||||||
onClick={props.saveEditorAsJSON}
|
onClick={props.saveEditorAsJSON}
|
||||||
>
|
>
|
||||||
<ArrowUpOnSquareIcon className="heroicon text-white" />
|
<ArrowUpOnSquareIcon className="heroicon text-white" />
|
||||||
</button>
|
</button>
|
||||||
<button type="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'
|
title='Export as SVG'
|
||||||
onClick={props.saveEditorAsSVG}
|
onClick={props.saveEditorAsSVG}
|
||||||
>
|
>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { FixedSizeList as List } from 'react-window';
|
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';
|
import { TITLE_BAR_HEIGHT } from '../Sidebar/Sidebar';
|
||||||
|
|
||||||
interface IHistoryProps {
|
interface IHistoryProps {
|
||||||
|
@ -23,7 +23,7 @@ export function History(props: IHistoryProps): JSX.Element {
|
||||||
<button type="button"
|
<button type="button"
|
||||||
key={reversedIndex}
|
key={reversedIndex}
|
||||||
style={style}
|
style={style}
|
||||||
onClick={() => props.jumpTo(reversedIndex)}
|
onClick={() => { props.jumpTo(reversedIndex); }}
|
||||||
title={step.lastAction}
|
title={step.lastAction}
|
||||||
className={`w-full elements-sidebar-row border-blue-500 whitespace-pre overflow-hidden
|
className={`w-full elements-sidebar-row border-blue-500 whitespace-pre overflow-hidden
|
||||||
text-left text-sm font-medium transition-all ${selectedClass}`}
|
text-left text-sm font-medium transition-all ${selectedClass}`}
|
||||||
|
|
|
@ -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 <>
|
return <>
|
||||||
<label
|
<label
|
||||||
|
@ -53,7 +55,7 @@ export function TextInputGroup(props: ITextInputGroupProps): JSX.Element {
|
||||||
className={`${className} ${props.inputClassName} ${warningClass}`}
|
className={`${className} ${props.inputClassName} ${warningClass}`}
|
||||||
type={props.type}
|
type={props.type}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(event) => setValue(event.target.value)}
|
onChange={(event) => { setValue(event.target.value); }}
|
||||||
onKeyUp={OnKeyUp}
|
onKeyUp={OnKeyUp}
|
||||||
min={props.min}
|
min={props.min}
|
||||||
max={props.max}
|
max={props.max}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { createContext, useState } 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 { languageOptions, translations } from '../../Translations/Translations';
|
||||||
import { DEFAULT_LANGUAGE } from '../../utils/default';
|
import { DEFAULT_LANGUAGE } from '../../utils/default';
|
||||||
|
|
||||||
|
@ -10,13 +10,17 @@ export const LanguageContext = createContext<ILanguage>({
|
||||||
dictionary: translations.en
|
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 [language, setLanguage] = useState(DEFAULT_LANGUAGE);
|
||||||
const provider = {
|
const provider = {
|
||||||
language,
|
language,
|
||||||
dictionary: translations[language],
|
dictionary: translations[language],
|
||||||
languageChange: (selected: string) => {
|
languageChange: (selected: string) => {
|
||||||
const newLanguage = languageOptions[selected] !== undefined ? selected : DEFAULT_LANGUAGE;
|
const newLanguage = languageOptions[selected] !== undefined
|
||||||
|
? selected
|
||||||
|
: DEFAULT_LANGUAGE;
|
||||||
setLanguage(newLanguage);
|
setLanguage(newLanguage);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,7 +45,7 @@ export function MainMenu(props: IMainMenuProps): JSX.Element {
|
||||||
</label>
|
</label>
|
||||||
</form>
|
</form>
|
||||||
<button type="button"
|
<button type="button"
|
||||||
onClick={() => setWindowState(WindowState.Main)}
|
onClick={() => { setWindowState(WindowState.Main); }}
|
||||||
className='normal-btn block
|
className='normal-btn block
|
||||||
mt-8 '
|
mt-8 '
|
||||||
>
|
>
|
||||||
|
@ -70,7 +70,7 @@ export function MainMenu(props: IMainMenuProps): JSX.Element {
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className='mainmenu-btn'
|
className='mainmenu-btn'
|
||||||
onClick={() => setWindowState(WindowState.Load)}
|
onClick={() => { setWindowState(WindowState.Load); }}
|
||||||
>
|
>
|
||||||
{Text({ textId: '@LoadConfigFile' })}
|
{Text({ textId: '@LoadConfigFile' })}
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import useSize from '@react-hook/size';
|
import useSize from '@react-hook/size';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { IPoint } from '../../Interfaces/IPoint';
|
import { type IPoint } from '../../Interfaces/IPoint';
|
||||||
import { MenuItem } from './MenuItem';
|
import { MenuItem } from './MenuItem';
|
||||||
|
|
||||||
interface IMenuProps {
|
interface IMenuProps {
|
||||||
|
@ -97,15 +97,22 @@ export function Menu(props: IMenuProps): JSX.Element {
|
||||||
AddUniversalActions(props, children, count, target);
|
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 isOutOfBoundHorizontally = contextMenuPosition.x + menuWidth > window.innerWidth;
|
||||||
const isOutOfBoundVertically = contextMenuPosition.y + menuHeight > window.innerHeight;
|
const isOutOfBoundVertically = contextMenuPosition.y + menuHeight > window.innerHeight;
|
||||||
const finalHorizontalPosition = isOutOfBoundHorizontally ? contextMenuPosition.x - menuWidth : contextMenuPosition.x;
|
const finalHorizontalPosition = isOutOfBoundHorizontally
|
||||||
const finalVerticalPosition = isOutOfBoundVertically ? contextMenuPosition.y - menuWidth : contextMenuPosition.y;
|
? contextMenuPosition.x - menuWidth
|
||||||
|
: contextMenuPosition.x;
|
||||||
|
const finalVerticalPosition = isOutOfBoundVertically
|
||||||
|
? contextMenuPosition.y - menuWidth
|
||||||
|
: contextMenuPosition.y;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={menuRef}
|
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={{
|
style={{
|
||||||
left: finalHorizontalPosition,
|
left: finalHorizontalPosition,
|
||||||
top: finalVerticalPosition
|
top: finalVerticalPosition
|
||||||
|
@ -137,7 +144,7 @@ function AddClassSpecificActions(
|
||||||
text={action.text}
|
text={action.text}
|
||||||
title={action.title}
|
title={action.title}
|
||||||
shortcut={action.shortcut}
|
shortcut={action.shortcut}
|
||||||
onClick={() => action.action(target)} />);
|
onClick={() => { action.action(target); }} />);
|
||||||
});
|
});
|
||||||
children.push(<hr key={`contextmenu-hr-${count}`} className='border-slate-400' />);
|
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}
|
text={action.text}
|
||||||
title={action.title}
|
title={action.title}
|
||||||
shortcut={action.shortcut}
|
shortcut={action.shortcut}
|
||||||
onClick={() => action.action(target)} />);
|
onClick={() => { action.action(target); }} />);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ export function MenuItem(props: IMenuItemProps): JSX.Element {
|
||||||
<button type="button"
|
<button type="button"
|
||||||
className={`flex place-content-between ${props.className ?? ''}`}
|
className={`flex place-content-between ${props.className ?? ''}`}
|
||||||
title={props.title}
|
title={props.title}
|
||||||
onClick={() => props.onClick()}>
|
onClick={() => { props.onClick(); }}>
|
||||||
{props.text}
|
{props.text}
|
||||||
<span dangerouslySetInnerHTML={{ __html: props.shortcut ?? '' }} />
|
<span dangerouslySetInnerHTML={{ __html: props.shortcut ?? '' }} />
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -2,8 +2,8 @@ import { TrashIcon } from '@heroicons/react/24/outline';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { FixedSizeList as List } from 'react-window';
|
import { FixedSizeList as List } from 'react-window';
|
||||||
import { MessageType } from '../../Enums/MessageType';
|
import { MessageType } from '../../Enums/MessageType';
|
||||||
import { IHistoryState } from '../../Interfaces/IHistoryState';
|
import { type IHistoryState } from '../../Interfaces/IHistoryState';
|
||||||
import { IMessage } from '../../Interfaces/IMessage';
|
import { type IMessage } from '../../Interfaces/IMessage';
|
||||||
import { TITLE_BAR_HEIGHT } from '../Sidebar/Sidebar';
|
import { TITLE_BAR_HEIGHT } from '../Sidebar/Sidebar';
|
||||||
import { Text } from '../Text/Text';
|
import { Text } from '../Text/Text';
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ interface IMessagesProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Messages(props: IMessagesProps): JSX.Element {
|
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 reversedIndex = (props.messages.length - 1) - index;
|
||||||
const message = props.messages[reversedIndex];
|
const message = props.messages[reversedIndex];
|
||||||
let classType = '';
|
let classType = '';
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
import React from 'react';
|
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 { PositionReference } from '../../Enums/PositionReference';
|
||||||
import { RadioGroupButtons } from './RadioGroupButtons';
|
import { RadioGroupButtons } from './RadioGroupButtons';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { IInputGroup } from '../../Interfaces/IInputGroup';
|
import { type IInputGroup } from '../../Interfaces/IInputGroup';
|
||||||
|
|
||||||
interface IRadioGroupButtonsProps {
|
interface IRadioGroupButtonsProps {
|
||||||
name: string
|
name: string
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Interweave, Node } from 'interweave';
|
import { Interweave, type Node } from 'interweave';
|
||||||
import { IContainerModel } from '../../../Interfaces/IContainerModel';
|
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||||
import { IContainerProperties } from '../../../Interfaces/IContainerProperties';
|
import { type IContainerProperties } from '../../../Interfaces/IContainerProperties';
|
||||||
import { Camelize } from '../../../utils/stringtools';
|
import { Camelize } from '../../../utils/stringtools';
|
||||||
import { SHOW_TEXT } from '../../../utils/default';
|
import { SHOW_TEXT } from '../../../utils/default';
|
||||||
import { FindContainerById } from '../../../utils/itertools';
|
import { FindContainerById } from '../../../utils/itertools';
|
||||||
|
@ -19,23 +19,22 @@ interface IContainerProps {
|
||||||
* @returns Render the container
|
* @returns Render the container
|
||||||
*/
|
*/
|
||||||
export function Container(props: IContainerProps): JSX.Element {
|
export function Container(props: IContainerProps): JSX.Element {
|
||||||
const containersElements = props.model.children.map(
|
const containersElements = props.model.children.map(childId => {
|
||||||
childId => {
|
const child = FindContainerById(props.containers, childId);
|
||||||
const child = FindContainerById(props.containers, childId);
|
|
||||||
|
|
||||||
if (child === undefined) {
|
if (child === undefined) {
|
||||||
return <></>;
|
return <></>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Container
|
return <Container
|
||||||
key={`container-${child.properties.id}`}
|
key={`container-${child.properties.id}`}
|
||||||
containers={props.containers}
|
containers={props.containers}
|
||||||
model={child}
|
model={child}
|
||||||
depth={props.depth + 1}
|
depth={props.depth + 1}
|
||||||
scale={props.scale}
|
scale={props.scale}
|
||||||
selectContainer={props.selectContainer}
|
selectContainer={props.selectContainer}
|
||||||
/>;
|
/>;
|
||||||
});
|
});
|
||||||
|
|
||||||
const width: number = props.model.properties.width;
|
const width: number = props.model.properties.width;
|
||||||
const height: number = props.model.properties.height;
|
const height: number = props.model.properties.height;
|
||||||
|
@ -67,7 +66,7 @@ export function Container(props: IContainerProps): JSX.Element {
|
||||||
width={width}
|
width={width}
|
||||||
height={height}
|
height={height}
|
||||||
style={style}
|
style={style}
|
||||||
onClick={() => props.selectContainer(props.model.properties.id)}
|
onClick={() => { props.selectContainer(props.model.properties.id); }}
|
||||||
>
|
>
|
||||||
</rect>);
|
</rect>);
|
||||||
|
|
||||||
|
@ -108,7 +107,7 @@ function CreateReactCustomSVG(customSVG: string, properties: IContainerPropertie
|
||||||
function Transform(node: HTMLElement, children: Node[], properties: IContainerProperties): React.ReactNode {
|
function Transform(node: HTMLElement, children: Node[], properties: IContainerProperties): React.ReactNode {
|
||||||
const supportedTags = ['line', 'path', 'rect'];
|
const supportedTags = ['line', 'path', 'rect'];
|
||||||
if (supportedTags.includes(node.tagName.toLowerCase())) {
|
if (supportedTags.includes(node.tagName.toLowerCase())) {
|
||||||
const attributes: { [att: string]: string | object | null } = {};
|
const attributes: Record<string, string | object | null> = {};
|
||||||
node.getAttributeNames().forEach(attName => {
|
node.getAttributeNames().forEach(attName => {
|
||||||
const attributeValue = node.getAttribute(attName);
|
const attributeValue = node.getAttribute(attName);
|
||||||
if (attributeValue === null) {
|
if (attributeValue === null) {
|
||||||
|
|
|
@ -11,9 +11,9 @@ import {
|
||||||
} from '../../../utils/default';
|
} from '../../../utils/default';
|
||||||
import { FindContainerById, MakeRecursionDFSIterator, Pairwise } from '../../../utils/itertools';
|
import { FindContainerById, MakeRecursionDFSIterator, Pairwise } from '../../../utils/itertools';
|
||||||
import { TransformX, TransformY } from '../../../utils/svg';
|
import { TransformX, TransformY } from '../../../utils/svg';
|
||||||
import { Dimension } from './Dimension';
|
|
||||||
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
|
import { type IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||||
import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
||||||
|
import { Dimension } from './Dimension';
|
||||||
|
|
||||||
interface IDimensionLayerProps {
|
interface IDimensionLayerProps {
|
||||||
containers: Map<string, IContainerModel>
|
containers: Map<string, IContainerModel>
|
||||||
|
@ -160,7 +160,8 @@ function Dimensions({ containers, symbols, root, scale }: IDimensionLayerProps):
|
||||||
return dimensions;
|
return dimensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
function AddHorizontalSymbolDimension(symbol: ISymbolModel,
|
function AddHorizontalSymbolDimension(
|
||||||
|
symbol: ISymbolModel,
|
||||||
dimensions: React.ReactNode[],
|
dimensions: React.ReactNode[],
|
||||||
scale: number,
|
scale: number,
|
||||||
depth: number
|
depth: number
|
||||||
|
@ -173,22 +174,21 @@ function AddHorizontalSymbolDimension(symbol: ISymbolModel,
|
||||||
const text = width
|
const text = width
|
||||||
.toFixed(0)
|
.toFixed(0)
|
||||||
.toString();
|
.toString();
|
||||||
dimensions.push(
|
dimensions.push(<Dimension
|
||||||
<Dimension
|
key={id}
|
||||||
key={id}
|
id={id}
|
||||||
id={id}
|
xStart={0}
|
||||||
xStart={0}
|
yStart={-offset}
|
||||||
yStart={-offset}
|
xEnd={width}
|
||||||
xEnd={width}
|
yEnd={-offset}
|
||||||
yEnd={-offset}
|
text={text}
|
||||||
text={text}
|
scale={scale}
|
||||||
scale={scale}
|
style={DEFAULT_DIMENSION_SYMBOL_STYLE}/>);
|
||||||
style={DEFAULT_DIMENSION_SYMBOL_STYLE}/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function AddVerticalSymbolDimension(symbol: ISymbolModel,
|
function AddVerticalSymbolDimension(
|
||||||
|
symbol: ISymbolModel,
|
||||||
dimensions: React.ReactNode[],
|
dimensions: React.ReactNode[],
|
||||||
scale: number,
|
scale: number,
|
||||||
depth: number
|
depth: number
|
||||||
|
@ -201,18 +201,16 @@ function AddVerticalSymbolDimension(symbol: ISymbolModel,
|
||||||
const text = height
|
const text = height
|
||||||
.toFixed(0)
|
.toFixed(0)
|
||||||
.toString();
|
.toString();
|
||||||
dimensions.push(
|
dimensions.push(<Dimension
|
||||||
<Dimension
|
key={id}
|
||||||
key={id}
|
id={id}
|
||||||
id={id}
|
xStart={-offset}
|
||||||
xStart={-offset}
|
yStart={height}
|
||||||
yStart={height}
|
xEnd={-offset}
|
||||||
xEnd={-offset}
|
yEnd={0}
|
||||||
yEnd={0}
|
text={text}
|
||||||
text={text}
|
scale={scale}
|
||||||
scale={scale}
|
style={DEFAULT_DIMENSION_SYMBOL_STYLE}/>);
|
||||||
style={DEFAULT_DIMENSION_SYMBOL_STYLE}/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,12 +247,16 @@ function AddHorizontalChildrenDimension(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let xChildrenStart = TransformX(lastChild.properties.x,
|
let xChildrenStart = TransformX(
|
||||||
|
lastChild.properties.x,
|
||||||
lastChild.properties.width,
|
lastChild.properties.width,
|
||||||
lastChild.properties.positionReference);
|
lastChild.properties.positionReference
|
||||||
let xChildrenEnd = TransformX(lastChild.properties.x,
|
);
|
||||||
|
let xChildrenEnd = TransformX(
|
||||||
|
lastChild.properties.x,
|
||||||
lastChild.properties.width,
|
lastChild.properties.width,
|
||||||
lastChild.properties.positionReference);
|
lastChild.properties.positionReference
|
||||||
|
);
|
||||||
|
|
||||||
// Find the min and max
|
// Find the min and max
|
||||||
for (let i = container.children.length - 2; i >= 0; i--) {
|
for (let i = container.children.length - 2; i >= 0; i--) {
|
||||||
|
@ -316,12 +318,16 @@ function AddVerticalChildrenDimension(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let yChildrenStart = TransformY(lastChild.properties.y,
|
let yChildrenStart = TransformY(
|
||||||
|
lastChild.properties.y,
|
||||||
lastChild.properties.height,
|
lastChild.properties.height,
|
||||||
lastChild.properties.positionReference);
|
lastChild.properties.positionReference
|
||||||
let yChildrenEnd = TransformY(lastChild.properties.y,
|
);
|
||||||
|
let yChildrenEnd = TransformY(
|
||||||
|
lastChild.properties.y,
|
||||||
lastChild.properties.height,
|
lastChild.properties.height,
|
||||||
lastChild.properties.positionReference);
|
lastChild.properties.positionReference
|
||||||
|
);
|
||||||
|
|
||||||
// Find the min and max
|
// Find the min and max
|
||||||
for (let i = container.children.length - 2; i >= 0; i--) {
|
for (let i = container.children.length - 2; i >= 0; i--) {
|
||||||
|
@ -398,9 +404,7 @@ function AddHorizontalBorrowerDimension(
|
||||||
|
|
||||||
const restoredX = x + childCurrentTransform[0];
|
const restoredX = x + childCurrentTransform[0];
|
||||||
|
|
||||||
marks.push(
|
marks.push(restoredX);
|
||||||
restoredX
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const restoredX = container.properties.x + currentTransform[0];
|
const restoredX = container.properties.x + currentTransform[0];
|
||||||
|
@ -458,9 +462,7 @@ function AddVerticalBorrowerDimension(
|
||||||
|
|
||||||
const restoredy = y + childCurrentTransform[1];
|
const restoredy = y + childCurrentTransform[1];
|
||||||
|
|
||||||
marks.push(
|
marks.push(restoredy);
|
||||||
restoredy
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const restoredY = container.properties.y + currentTransform[1];
|
const restoredY = container.properties.y + currentTransform[1];
|
||||||
|
@ -515,18 +517,16 @@ function AddVerticalSelfDimension(
|
||||||
[yStart, yEnd] = [yEnd, yStart];
|
[yStart, yEnd] = [yEnd, yStart];
|
||||||
}
|
}
|
||||||
|
|
||||||
dimensions.push(
|
dimensions.push(<Dimension
|
||||||
<Dimension
|
key={idVert}
|
||||||
key={idVert}
|
id={idVert}
|
||||||
id={idVert}
|
xStart={xDim}
|
||||||
xStart={xDim}
|
yStart={yStart}
|
||||||
yStart={yStart}
|
xEnd={xDim}
|
||||||
xEnd={xDim}
|
yEnd={yEnd}
|
||||||
yEnd={yEnd}
|
text={textVert}
|
||||||
text={textVert}
|
scale={scale}
|
||||||
scale={scale}
|
style={style}/>);
|
||||||
style={style}/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function AddHorizontalSelfDimension(
|
function AddHorizontalSelfDimension(
|
||||||
|
@ -544,18 +544,16 @@ function AddHorizontalSelfDimension(
|
||||||
const text = width
|
const text = width
|
||||||
.toFixed(0)
|
.toFixed(0)
|
||||||
.toString();
|
.toString();
|
||||||
dimensions.push(
|
dimensions.push(<Dimension
|
||||||
<Dimension
|
key={id}
|
||||||
key={id}
|
id={id}
|
||||||
id={id}
|
xStart={xStart}
|
||||||
xStart={xStart}
|
yStart={yDim}
|
||||||
yStart={yDim}
|
xEnd={xEnd}
|
||||||
xEnd={xEnd}
|
yEnd={yDim}
|
||||||
yEnd={yDim}
|
text={text}
|
||||||
text={text}
|
scale={scale}
|
||||||
scale={scale}
|
style={style}/>);
|
||||||
style={style}/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function AddHorizontalSelfMarginsDimension(
|
function AddHorizontalSelfMarginsDimension(
|
||||||
|
@ -574,18 +572,16 @@ function AddHorizontalSelfMarginsDimension(
|
||||||
const text = left
|
const text = left
|
||||||
.toFixed(0)
|
.toFixed(0)
|
||||||
.toString();
|
.toString();
|
||||||
dimensions.push(
|
dimensions.push(<Dimension
|
||||||
<Dimension
|
key={id}
|
||||||
key={id}
|
id={id}
|
||||||
id={id}
|
xStart={xStart}
|
||||||
xStart={xStart}
|
yStart={yDim}
|
||||||
yStart={yDim}
|
xEnd={xEnd}
|
||||||
xEnd={xEnd}
|
yEnd={yDim}
|
||||||
yEnd={yDim}
|
text={text}
|
||||||
text={text}
|
scale={scale}
|
||||||
scale={scale}
|
style={style}/>);
|
||||||
style={style}/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const right = container.properties.margin.right;
|
const right = container.properties.margin.right;
|
||||||
|
@ -596,18 +592,16 @@ function AddHorizontalSelfMarginsDimension(
|
||||||
const text = right
|
const text = right
|
||||||
.toFixed(0)
|
.toFixed(0)
|
||||||
.toString();
|
.toString();
|
||||||
dimensions.push(
|
dimensions.push(<Dimension
|
||||||
<Dimension
|
key={id}
|
||||||
key={id}
|
id={id}
|
||||||
id={id}
|
xStart={xStart}
|
||||||
xStart={xStart}
|
yStart={yDim}
|
||||||
yStart={yDim}
|
xEnd={xEnd}
|
||||||
xEnd={xEnd}
|
yEnd={yDim}
|
||||||
yEnd={yDim}
|
text={text}
|
||||||
text={text}
|
scale={scale}
|
||||||
scale={scale}
|
style={style}/>);
|
||||||
style={style}/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -633,18 +627,16 @@ function AddVerticalSelfMarginsDimension(
|
||||||
[yStart, yEnd] = [yEnd, yStart];
|
[yStart, yEnd] = [yEnd, yStart];
|
||||||
}
|
}
|
||||||
|
|
||||||
dimensions.push(
|
dimensions.push(<Dimension
|
||||||
<Dimension
|
key={idVert}
|
||||||
key={idVert}
|
id={idVert}
|
||||||
id={idVert}
|
xStart={xDim}
|
||||||
xStart={xDim}
|
yStart={yStart}
|
||||||
yStart={yStart}
|
xEnd={xDim}
|
||||||
xEnd={xDim}
|
yEnd={yEnd}
|
||||||
yEnd={yEnd}
|
text={textVert}
|
||||||
text={textVert}
|
scale={scale}
|
||||||
scale={scale}
|
style={style}/>);
|
||||||
style={style}/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const bottom = container.properties.margin.bottom;
|
const bottom = container.properties.margin.bottom;
|
||||||
if (bottom != null && bottom > 0) {
|
if (bottom != null && bottom > 0) {
|
||||||
|
@ -659,17 +651,15 @@ function AddVerticalSelfMarginsDimension(
|
||||||
[yStart, yEnd] = [yEnd, yStart];
|
[yStart, yEnd] = [yEnd, yStart];
|
||||||
}
|
}
|
||||||
|
|
||||||
dimensions.push(
|
dimensions.push(<Dimension
|
||||||
<Dimension
|
key={idVert}
|
||||||
key={idVert}
|
id={idVert}
|
||||||
id={idVert}
|
xStart={xDim}
|
||||||
xStart={xDim}
|
yStart={yStart}
|
||||||
yStart={yStart}
|
xEnd={xDim}
|
||||||
xEnd={xDim}
|
yEnd={yEnd}
|
||||||
yEnd={yEnd}
|
text={textVert}
|
||||||
text={textVert}
|
scale={scale}
|
||||||
scale={scale}
|
style={style}/>);
|
||||||
style={style}/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,11 @@ export function SelectorContainer(props: ISelectorContainerProps): JSX.Element {
|
||||||
props.selected.properties.height
|
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.left,
|
||||||
props.selected.properties.margin.bottom,
|
props.selected.properties.margin.bottom,
|
||||||
props.selected.properties.margin.top,
|
props.selected.properties.margin.top,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import '../Selector.scss';
|
import '../Selector.scss';
|
||||||
import * as React from 'react';
|
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 { type ISymbolModel } from '../../../../Interfaces/ISymbolModel';
|
||||||
import { Selector } from '../Selector/Selector';
|
import { Selector } from '../Selector/Selector';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
import { type ISymbolModel } from '../../../Interfaces/ISymbolModel';
|
||||||
import { Symbol } from './Symbol';
|
import { Symbol } from './Symbol';
|
||||||
|
|
||||||
interface ISymbolLayerProps {
|
interface ISymbolLayerProps {
|
||||||
|
@ -10,13 +10,11 @@ interface ISymbolLayerProps {
|
||||||
export function SymbolLayer(props: ISymbolLayerProps): JSX.Element {
|
export function SymbolLayer(props: ISymbolLayerProps): JSX.Element {
|
||||||
const symbols: JSX.Element[] = [];
|
const symbols: JSX.Element[] = [];
|
||||||
props.symbols.forEach((symbol) => {
|
props.symbols.forEach((symbol) => {
|
||||||
symbols.push(
|
symbols.push(<Symbol
|
||||||
<Symbol
|
key={`symbol-${symbol.id}`}
|
||||||
key={`symbol-${symbol.id}`}
|
model={symbol}
|
||||||
model={symbol}
|
scale={props.scale}
|
||||||
scale={props.scale}
|
/>);
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
return (
|
return (
|
||||||
<g>
|
<g>
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { ReactSVGPanZoom, type Tool, TOOL_PAN, type Value, ALIGN_CENTER } from 'react-svg-pan-zoom';
|
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 { Container } from './Elements/Container';
|
||||||
import { SelectorContainer } from './Elements/SelectorContainer/SelectorContainer';
|
import { SelectorContainer } from './Elements/SelectorContainer/SelectorContainer';
|
||||||
import { MAX_FRAMERATE } from '../../utils/default';
|
|
||||||
import { SymbolLayer } from './Elements/SymbolLayer';
|
import { SymbolLayer } from './Elements/SymbolLayer';
|
||||||
import { DimensionLayer } from './Elements/DimensionLayer';
|
import { DimensionLayer } from './Elements/DimensionLayer';
|
||||||
import { SelectorSymbol } from './Elements/SelectorSymbol/SelectorSymbol';
|
import { SelectorSymbol } from './Elements/SelectorSymbol/SelectorSymbol';
|
||||||
import { type IToolbarProps, Toolbar } from './SVGReactPanZoom/ui-toolbar/toolbar';
|
import { type IToolbarProps, Toolbar } from './SVGReactPanZoom/ui-toolbar/toolbar';
|
||||||
import { type DrawParams } from '../Viewer/Viewer';
|
|
||||||
|
|
||||||
interface ISVGProps {
|
interface ISVGProps {
|
||||||
className?: string
|
className?: string
|
||||||
|
|
|
@ -47,8 +47,12 @@ export class ToolbarButton extends React.Component<IToolbarButtonProps, IToolbar
|
||||||
display: 'block',
|
display: 'block',
|
||||||
width: '24px',
|
width: '24px',
|
||||||
height: '24px',
|
height: '24px',
|
||||||
margin: [POSITION_TOP, POSITION_BOTTOM].includes(this.props.toolbarPosition) ? '2px 1px' : '1px 2px',
|
margin: [POSITION_TOP, POSITION_BOTTOM].includes(this.props.toolbarPosition)
|
||||||
color: this.props.active || this.state.hover ? this.props.activeColor : '#FFF',
|
? '2px 1px'
|
||||||
|
: '1px 2px',
|
||||||
|
color: this.props.active || this.state.hover
|
||||||
|
? this.props.activeColor
|
||||||
|
: '#FFF',
|
||||||
transition: 'color 200ms ease',
|
transition: 'color 200ms ease',
|
||||||
background: 'none',
|
background: 'none',
|
||||||
padding: '0px',
|
padding: '0px',
|
||||||
|
|
|
@ -118,18 +118,34 @@ export function Toolbar({
|
||||||
const style: React.CSSProperties = {
|
const style: React.CSSProperties = {
|
||||||
// position
|
// position
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
transform: [POSITION_TOP, POSITION_BOTTOM].includes(position) ? 'translate(-50%, 0px)' : 'none',
|
transform: [POSITION_TOP, POSITION_BOTTOM].includes(position)
|
||||||
top: [POSITION_LEFT, POSITION_RIGHT, POSITION_TOP].includes(position) ? '5px' : 'unset',
|
? 'translate(-50%, 0px)'
|
||||||
left: [POSITION_TOP, POSITION_BOTTOM].includes(position) ? '50%' : (POSITION_LEFT === position ? '5px' : 'unset'),
|
: 'none',
|
||||||
right: [POSITION_RIGHT].includes(position) ? '5px' : 'unset',
|
top: [POSITION_LEFT, POSITION_RIGHT, POSITION_TOP].includes(position)
|
||||||
bottom: [POSITION_BOTTOM].includes(position) ? '5px' : 'unset',
|
? '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
|
// inner styling
|
||||||
backgroundColor: 'rgba(19, 20, 22, 0.90)',
|
backgroundColor: 'rgba(19, 20, 22, 0.90)',
|
||||||
borderRadius: '2px',
|
borderRadius: '2px',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: isHorizontal ? 'row' : 'column',
|
flexDirection: isHorizontal
|
||||||
padding: isHorizontal ? '1px 2px' : '2px 1px'
|
? 'row'
|
||||||
|
: 'column',
|
||||||
|
padding: isHorizontal
|
||||||
|
? '1px 2px'
|
||||||
|
: '2px 1px'
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { IInputGroup } from '../../Interfaces/IInputGroup';
|
import { type IInputGroup } from '../../Interfaces/IInputGroup';
|
||||||
|
|
||||||
interface ISelectProps {
|
interface ISelectProps {
|
||||||
labelKey?: string
|
labelKey?: string
|
||||||
|
|
|
@ -9,7 +9,9 @@ interface IToggleSidebarProps {
|
||||||
|
|
||||||
export function ToggleSideBar({ title, checked, onClick }: IToggleSidebarProps): JSX.Element {
|
export function ToggleSideBar({ title, checked, onClick }: IToggleSidebarProps): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<div className={`${(checked ? 'bg-slate-400 hover:bg-slate-500' : 'bg-slate-300 hover:bg-slate-400')}`}>
|
<div className={`${(checked
|
||||||
|
? 'bg-slate-400 hover:bg-slate-500'
|
||||||
|
: 'bg-slate-300 hover:bg-slate-400')}`}>
|
||||||
<button
|
<button
|
||||||
className={'w-full py-2'}
|
className={'w-full py-2'}
|
||||||
type='button'
|
type='button'
|
||||||
|
|
|
@ -13,22 +13,26 @@ interface ISymbolFormProps {
|
||||||
onChange: (key: string, value: string | number | boolean) => void
|
onChange: (key: string, value: string | number | boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
function Restore(offset: number,
|
function Restore(
|
||||||
|
offset: number,
|
||||||
isVertical: boolean,
|
isVertical: boolean,
|
||||||
height: number,
|
height: number,
|
||||||
width: number,
|
width: number,
|
||||||
position: PositionReference | undefined): number {
|
position: PositionReference | undefined
|
||||||
|
): number {
|
||||||
if (isVertical) {
|
if (isVertical) {
|
||||||
return RestoreY(offset, height, position);
|
return RestoreY(offset, height, position);
|
||||||
} else {
|
} else {
|
||||||
return RestoreX(offset, width, position);
|
return RestoreX(offset, width, position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function Transform(offset: number,
|
function Transform(
|
||||||
|
offset: number,
|
||||||
isVertical: boolean,
|
isVertical: boolean,
|
||||||
height: number,
|
height: number,
|
||||||
width: number,
|
width: number,
|
||||||
position: PositionReference | undefined): number {
|
position: PositionReference | undefined
|
||||||
|
): number {
|
||||||
if (isVertical) {
|
if (isVertical) {
|
||||||
return TransformY(offset, height, position);
|
return TransformY(offset, height, position);
|
||||||
} else {
|
} else {
|
||||||
|
@ -63,18 +67,24 @@ export function SymbolForm(props: ISymbolFormProps): JSX.Element {
|
||||||
labelClassName=''
|
labelClassName=''
|
||||||
inputClassName=''
|
inputClassName=''
|
||||||
type='number'
|
type='number'
|
||||||
value={Transform(props.symbol.offset,
|
value={Transform(
|
||||||
|
props.symbol.offset,
|
||||||
props.symbol.isVertical,
|
props.symbol.isVertical,
|
||||||
props.symbol.height,
|
props.symbol.height,
|
||||||
props.symbol.width,
|
props.symbol.width,
|
||||||
props.symbol.config.PositionReference).toString()}
|
props.symbol.config.PositionReference
|
||||||
|
).toString()}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
props.onChange('offset',
|
props.onChange(
|
||||||
Restore(Number(value),
|
'offset',
|
||||||
|
Restore(
|
||||||
|
Number(value),
|
||||||
props.symbol.isVertical,
|
props.symbol.isVertical,
|
||||||
props.symbol.height,
|
props.symbol.height,
|
||||||
props.symbol.width,
|
props.symbol.width,
|
||||||
props.symbol.config.PositionReference));
|
props.symbol.config.PositionReference
|
||||||
|
)
|
||||||
|
);
|
||||||
}} />
|
}} />
|
||||||
<ToggleButton
|
<ToggleButton
|
||||||
labelText={Text({ textId: '@IsVertical' })}
|
labelText={Text({ textId: '@IsVertical' })}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ISymbolModel } from '../../Interfaces/ISymbolModel';
|
import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
|
||||||
import { SymbolForm } from './SymbolForm';
|
import { SymbolForm } from './SymbolForm';
|
||||||
|
|
||||||
interface ISymbolPropertiesProps {
|
interface ISymbolPropertiesProps {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { IAvailableSymbol } from '../../Interfaces/IAvailableSymbol';
|
import { type IAvailableSymbol } from '../../Interfaces/IAvailableSymbol';
|
||||||
import { TruncateString } from '../../utils/stringtools';
|
import { TruncateString } from '../../utils/stringtools';
|
||||||
|
|
||||||
interface ISymbolsProps {
|
interface ISymbolsProps {
|
||||||
|
@ -20,9 +20,9 @@ export function Symbols(props: ISymbolsProps): JSX.Element {
|
||||||
key={componentOption.Name}
|
key={componentOption.Name}
|
||||||
id={componentOption.Name}
|
id={componentOption.Name}
|
||||||
title={componentOption.Name}
|
title={componentOption.Name}
|
||||||
onClick={() => props.buttonOnClick(componentOption.Name)}
|
onClick={() => { props.buttonOnClick(componentOption.Name); }}
|
||||||
draggable={true}
|
draggable={true}
|
||||||
onDragStart={(event) => HandleDragStart(event)}
|
onDragStart={(event) => { HandleDragStart(event); }}
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<img
|
<img
|
||||||
|
@ -41,9 +41,9 @@ export function Symbols(props: ISymbolsProps): JSX.Element {
|
||||||
key={componentOption.Name}
|
key={componentOption.Name}
|
||||||
id={componentOption.Name}
|
id={componentOption.Name}
|
||||||
title={componentOption.Name}
|
title={componentOption.Name}
|
||||||
onClick={() => props.buttonOnClick(componentOption.Name)}
|
onClick={() => { props.buttonOnClick(componentOption.Name); }}
|
||||||
draggable={true}
|
draggable={true}
|
||||||
onDragStart={(event) => HandleDragStart(event)}
|
onDragStart={(event) => { HandleDragStart(event); }}
|
||||||
>
|
>
|
||||||
|
|
||||||
{TruncateString(componentOption.Name, 5)}
|
{TruncateString(componentOption.Name, 5)}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { type Dispatch } from 'react';
|
||||||
import { ElementsSidebar } from '../ElementsSidebar/ElementsSidebar';
|
import { ElementsSidebar } from '../ElementsSidebar/ElementsSidebar';
|
||||||
import { History } from '../History/History';
|
import { History } from '../History/History';
|
||||||
import { Bar, BAR_WIDTH } from '../Bar/Bar';
|
import { Bar, BAR_WIDTH } from '../Bar/Bar';
|
||||||
|
@ -12,13 +13,12 @@ import { Viewer } from '../Viewer/Viewer';
|
||||||
import { Settings } from '../Settings/Settings';
|
import { Settings } from '../Settings/Settings';
|
||||||
import { type IMessage } from '../../Interfaces/IMessage';
|
import { type IMessage } from '../../Interfaces/IMessage';
|
||||||
import { DISABLE_API } from '../../utils/default';
|
import { DISABLE_API } from '../../utils/default';
|
||||||
import { UseWorker, UseAsync } from './UseWorker';
|
|
||||||
import { FindContainerById } from '../../utils/itertools';
|
import { FindContainerById } from '../../utils/itertools';
|
||||||
import { type IEditorState } from '../../Interfaces/IEditorState';
|
import { type IEditorState } from '../../Interfaces/IEditorState';
|
||||||
import { GetCurrentHistoryState } from '../Editor/Editor';
|
import { GetCurrentHistoryState } from '../Editor/Editor';
|
||||||
import { Text } from '../Text/Text';
|
import { Text } from '../Text/Text';
|
||||||
import { type IReplaceContainer } from '../../Interfaces/IReplaceContainer';
|
import { type IReplaceContainer } from '../../Interfaces/IReplaceContainer';
|
||||||
import { type Dispatch } from 'react';
|
import { UseWorker, UseAsync } from './UseWorker';
|
||||||
|
|
||||||
export interface IUIProps {
|
export interface IUIProps {
|
||||||
editorState: IEditorState
|
editorState: IEditorState
|
||||||
|
@ -223,7 +223,9 @@ export function UI({ editorState, replaceContainer, setReplaceContainer, ...meth
|
||||||
isLeftSidebarOpenClasses.add('left-sidebar-single');
|
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 isComponentsOpen = selectedSidebar === SidebarType.Components;
|
||||||
const isSymbolsOpen = selectedSidebar === SidebarType.Symbols;
|
const isSymbolsOpen = selectedSidebar === SidebarType.Symbols;
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { IHistoryState } from '../../Interfaces/IHistoryState';
|
import { type IHistoryState } from '../../Interfaces/IHistoryState';
|
||||||
import { IGetFeedbackRequest } from '../../Interfaces/IGetFeedbackRequest';
|
import { type IGetFeedbackRequest } from '../../Interfaces/IGetFeedbackRequest';
|
||||||
import { IGetFeedbackResponse } from '../../Interfaces/IGetFeedbackResponse';
|
import { type IGetFeedbackResponse } from '../../Interfaces/IGetFeedbackResponse';
|
||||||
import { IMessage } from '../../Interfaces/IMessage';
|
import { type IMessage } from '../../Interfaces/IMessage';
|
||||||
import { GetCircularReplacer } from '../../utils/saveload';
|
import { GetCircularReplacer } from '../../utils/saveload';
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
// 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(
|
export function UseWorker(
|
||||||
state: IHistoryState,
|
state: IHistoryState,
|
||||||
configurationUrl: string | undefined,
|
configurationUrl: string | undefined,
|
||||||
setMessages: React.Dispatch<React.SetStateAction<IMessage[]>>): void {
|
setMessages: React.Dispatch<React.SetStateAction<IMessage[]>>
|
||||||
|
): void {
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
// use webworker for the stringify to avoid freezing
|
// use webworker for the stringify to avoid freezing
|
||||||
myWorker.postMessage({
|
myWorker.postMessage({
|
||||||
|
@ -32,7 +33,8 @@ export function UseWorker(
|
||||||
export function UseAsync(
|
export function UseAsync(
|
||||||
state: IHistoryState,
|
state: IHistoryState,
|
||||||
configurationUrl: string | undefined,
|
configurationUrl: string | undefined,
|
||||||
setMessages: React.Dispatch<React.SetStateAction<IMessage[]>>): void {
|
setMessages: React.Dispatch<React.SetStateAction<IMessage[]>>
|
||||||
|
): void {
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const request: IGetFeedbackRequest = {
|
const request: IGetFeedbackRequest = {
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
|
@ -48,8 +50,7 @@ export function UseAsync(
|
||||||
}),
|
}),
|
||||||
body: dataParsed
|
body: dataParsed
|
||||||
})
|
})
|
||||||
.then(async(response) => await response.json()
|
.then(async(response) => await response.json())
|
||||||
)
|
|
||||||
.then(async(json: IGetFeedbackResponse) => {
|
.then(async(json: IGetFeedbackResponse) => {
|
||||||
setMessages(json.messages);
|
setMessages(json.messages);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
|
import { useState } from 'react';
|
||||||
import { type IContainerModel } from '../../Interfaces/IContainerModel';
|
import { type IContainerModel } from '../../Interfaces/IContainerModel';
|
||||||
import { type IHistoryState } from '../../Interfaces/IHistoryState';
|
import { type IHistoryState } from '../../Interfaces/IHistoryState';
|
||||||
import { USE_EXPERIMENTAL_CANVAS_API } from '../../utils/default';
|
import { USE_EXPERIMENTAL_CANVAS_API } from '../../utils/default';
|
||||||
|
@ -6,7 +7,6 @@ import { FindContainerById } from '../../utils/itertools';
|
||||||
import { BAR_WIDTH } from '../Bar/Bar';
|
import { BAR_WIDTH } from '../Bar/Bar';
|
||||||
import { Canvas } from '../Canvas/Canvas';
|
import { Canvas } from '../Canvas/Canvas';
|
||||||
import { SelectorMode, SVG } from '../SVG/SVG';
|
import { SelectorMode, SVG } from '../SVG/SVG';
|
||||||
import { useState } from 'react';
|
|
||||||
import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
|
import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
|
||||||
|
|
||||||
interface IViewerProps {
|
interface IViewerProps {
|
||||||
|
@ -30,7 +30,9 @@ export interface DrawParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
function computeWidth(margin: number): number {
|
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({
|
export function Viewer({
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { AppState } from '../Enums/AppState';
|
import { AppState } from '../Enums/AppState';
|
||||||
import { IConfiguration } from '../Interfaces/IConfiguration';
|
import { type IConfiguration } from '../Interfaces/IConfiguration';
|
||||||
import { IEditorState } from '../Interfaces/IEditorState';
|
import { type IEditorState } from '../Interfaces/IEditorState';
|
||||||
import { IHistoryState } from '../Interfaces/IHistoryState';
|
import { type IHistoryState } from '../Interfaces/IHistoryState';
|
||||||
import { ILanguage } from '../Interfaces/ILanguage';
|
import { type ILanguage } from '../Interfaces/ILanguage';
|
||||||
import { languageOptions, translations } from '../Translations/Translations';
|
import { languageOptions, translations } from '../Translations/Translations';
|
||||||
import { GetDefaultEditorState as GetDefaultEditorStateAction } from '../utils/default';
|
import { GetDefaultEditorState as GetDefaultEditorStateAction } from '../utils/default';
|
||||||
import { Revive, ReviveHistory as ReviveHistoryAction } from '../utils/saveload';
|
import { Revive, ReviveHistory as ReviveHistoryAction } from '../utils/saveload';
|
||||||
|
@ -49,7 +49,7 @@ export function UseCustomEvents(
|
||||||
const funcs = new Map<string, () => void>();
|
const funcs = new Map<string, () => void>();
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
function Func(eventInitDict?: CustomEventInit): void {
|
function Func(eventInitDict?: CustomEventInit): void {
|
||||||
return event.func({
|
event.func({
|
||||||
root,
|
root,
|
||||||
languageContext,
|
languageContext,
|
||||||
setEditor,
|
setEditor,
|
||||||
|
|
|
@ -1,11 +1,21 @@
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { AddContainer as AddContainerAction, AddContainerToSelectedContainer as AddContainerToSelectedContainerAction } from '../Components/Editor/Actions/AddContainer';
|
import {
|
||||||
import { DeleteContainer as DeleteContainerAction, SelectContainer as SelectContainerAction } from '../Components/Editor/Actions/ContainerOperations';
|
AddContainer as AddContainerAction,
|
||||||
import { AddSymbol as AddSymbolAction, DeleteSymbol as DeleteSymbolAction, SelectSymbol as SelectSymbolAction } from '../Components/Editor/Actions/SymbolOperations';
|
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 { GetCurrentHistory } from '../Components/Editor/Editor';
|
||||||
import { IConfiguration } from '../Interfaces/IConfiguration';
|
import { type IConfiguration } from '../Interfaces/IConfiguration';
|
||||||
import { IEditorState } from '../Interfaces/IEditorState';
|
import { type IEditorState } from '../Interfaces/IEditorState';
|
||||||
import { IHistoryState } from '../Interfaces/IHistoryState';
|
import { type IHistoryState } from '../Interfaces/IHistoryState';
|
||||||
import { FindContainerById } from '../utils/itertools';
|
import { FindContainerById } from '../utils/itertools';
|
||||||
import { GetCircularReplacer } from '../utils/saveload';
|
import { GetCircularReplacer } from '../utils/saveload';
|
||||||
|
|
||||||
|
@ -61,7 +71,7 @@ export function UseCustomEvents(
|
||||||
|
|
||||||
for (const event of events) {
|
for (const event of events) {
|
||||||
function Func(eventInitDict?: CustomEventInit): void {
|
function Func(eventInitDict?: CustomEventInit): void {
|
||||||
return event.func({
|
event.func({
|
||||||
root,
|
root,
|
||||||
editorState,
|
editorState,
|
||||||
setNewHistory,
|
setNewHistory,
|
||||||
|
@ -112,7 +122,9 @@ function GetEditorStateAsString({
|
||||||
root,
|
root,
|
||||||
editorState
|
editorState
|
||||||
}: IEditorEventParams): void {
|
}: 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 data = JSON.stringify(editorState, GetCircularReplacer(), spaces);
|
||||||
const customEvent = new CustomEvent<string>('getEditorStateAsString', { detail: data });
|
const customEvent = new CustomEvent<string>('getEditorStateAsString', { detail: data });
|
||||||
root.dispatchEvent(customEvent);
|
root.dispatchEvent(customEvent);
|
||||||
|
@ -137,7 +149,8 @@ function GetCurrentHistoryState({
|
||||||
}: IEditorEventParams): void {
|
}: IEditorEventParams): void {
|
||||||
const customEvent = new CustomEvent<IHistoryState>(
|
const customEvent = new CustomEvent<IHistoryState>(
|
||||||
'getCurrentHistoryState',
|
'getCurrentHistoryState',
|
||||||
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
|
||||||
|
);
|
||||||
root.dispatchEvent(customEvent);
|
root.dispatchEvent(customEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +168,8 @@ function AppendNewState({
|
||||||
|
|
||||||
const customEvent = new CustomEvent<IHistoryState>(
|
const customEvent = new CustomEvent<IHistoryState>(
|
||||||
'appendNewState',
|
'appendNewState',
|
||||||
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
|
||||||
|
);
|
||||||
root.dispatchEvent(customEvent);
|
root.dispatchEvent(customEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +198,8 @@ function AddContainer({
|
||||||
|
|
||||||
const customEvent = new CustomEvent<IHistoryState>(
|
const customEvent = new CustomEvent<IHistoryState>(
|
||||||
'addContainer',
|
'addContainer',
|
||||||
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
|
||||||
|
);
|
||||||
root.dispatchEvent(customEvent);
|
root.dispatchEvent(customEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +229,8 @@ function AddContainerToSelectedContainer({
|
||||||
|
|
||||||
const customEvent = new CustomEvent<IHistoryState>(
|
const customEvent = new CustomEvent<IHistoryState>(
|
||||||
'addContainerToSelectedContainer',
|
'addContainerToSelectedContainer',
|
||||||
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
|
||||||
|
);
|
||||||
root.dispatchEvent(customEvent);
|
root.dispatchEvent(customEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,7 +262,8 @@ function AppendContainer({
|
||||||
|
|
||||||
const customEvent = new CustomEvent<IHistoryState>(
|
const customEvent = new CustomEvent<IHistoryState>(
|
||||||
'appendContainerToSelectedContainer',
|
'appendContainerToSelectedContainer',
|
||||||
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
|
||||||
|
);
|
||||||
root.dispatchEvent(customEvent);
|
root.dispatchEvent(customEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +294,8 @@ function AppendContainerToSelectedContainer({
|
||||||
|
|
||||||
const customEvent = new CustomEvent<IHistoryState>(
|
const customEvent = new CustomEvent<IHistoryState>(
|
||||||
'appendContainerToSelectedContainer',
|
'appendContainerToSelectedContainer',
|
||||||
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
|
||||||
|
);
|
||||||
root.dispatchEvent(customEvent);
|
root.dispatchEvent(customEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -302,7 +320,8 @@ function SelectContainer({
|
||||||
|
|
||||||
const customEvent = new CustomEvent<IHistoryState>(
|
const customEvent = new CustomEvent<IHistoryState>(
|
||||||
'selectContainer',
|
'selectContainer',
|
||||||
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
|
||||||
|
);
|
||||||
root.dispatchEvent(customEvent);
|
root.dispatchEvent(customEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,7 +346,8 @@ function DeleteContainer({
|
||||||
|
|
||||||
const customEvent = new CustomEvent<IHistoryState>(
|
const customEvent = new CustomEvent<IHistoryState>(
|
||||||
'deleteContainer',
|
'deleteContainer',
|
||||||
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
|
||||||
|
);
|
||||||
root.dispatchEvent(customEvent);
|
root.dispatchEvent(customEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,7 +373,8 @@ function AddSymbol({
|
||||||
|
|
||||||
const customEvent = new CustomEvent<IHistoryState>(
|
const customEvent = new CustomEvent<IHistoryState>(
|
||||||
'AddSymbol',
|
'AddSymbol',
|
||||||
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
|
||||||
|
);
|
||||||
root.dispatchEvent(customEvent);
|
root.dispatchEvent(customEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,7 +399,8 @@ function SelectSymbol({
|
||||||
|
|
||||||
const customEvent = new CustomEvent<IHistoryState>(
|
const customEvent = new CustomEvent<IHistoryState>(
|
||||||
'SelectSymbol',
|
'SelectSymbol',
|
||||||
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
|
||||||
|
);
|
||||||
root.dispatchEvent(customEvent);
|
root.dispatchEvent(customEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,6 +424,7 @@ function DeleteSymbol({
|
||||||
|
|
||||||
const customEvent = new CustomEvent<IHistoryState>(
|
const customEvent = new CustomEvent<IHistoryState>(
|
||||||
'DeleteSymbol',
|
'DeleteSymbol',
|
||||||
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) });
|
{ detail: structuredClone(editorState.history[editorState.historyCurrentStep]) }
|
||||||
|
);
|
||||||
root.dispatchEvent(customEvent);
|
root.dispatchEvent(customEvent);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
import { AddMethod } from '../Enums/AddMethod';
|
import { type AddMethod } from '../Enums/AddMethod';
|
||||||
import { IImage } from './IImage';
|
import { type IImage } from './IImage';
|
||||||
|
|
||||||
export interface IAction {
|
export interface IAction {
|
||||||
Id: string
|
Id: string
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
import { type AddMethod } from '../Enums/AddMethod';
|
import { type AddMethod } from '../Enums/AddMethod';
|
||||||
import { type PositionReference } from '../Enums/PositionReference';
|
import { type PositionReference } from '../Enums/PositionReference';
|
||||||
|
import { type Orientation } from '../Enums/Orientation';
|
||||||
import { type IAction } from './IAction';
|
import { type IAction } from './IAction';
|
||||||
import { type IMargin } from './IMargin';
|
import { type IMargin } from './IMargin';
|
||||||
import { type Orientation } from '../Enums/Orientation';
|
|
||||||
import { type IKeyValue } from './IKeyValue';
|
import { type IKeyValue } from './IKeyValue';
|
||||||
import { type IStyle } from './IStyle';
|
import { type IStyle } from './IStyle';
|
||||||
import { type IDimensions } from './IDimensions';
|
import { type IDimensions } from './IDimensions';
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
import { IAPIConfiguration } from './IAPIConfiguration';
|
import { type IAPIConfiguration } from './IAPIConfiguration';
|
||||||
import { IAvailableContainer } from './IAvailableContainer';
|
import { type IAvailableContainer } from './IAvailableContainer';
|
||||||
import { IAvailableSymbol } from './IAvailableSymbol';
|
import { type IAvailableSymbol } from './IAvailableSymbol';
|
||||||
import { ICategory } from './ICategory';
|
import { type ICategory } from './ICategory';
|
||||||
import { IPattern } from './IPattern';
|
import { type IPattern } from './IPattern';
|
||||||
|
|
||||||
/** Model of configuration for the application to configure it */
|
/** Model of configuration for the application to configure it */
|
||||||
export interface IConfiguration {
|
export interface IConfiguration {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { IContainerProperties } from './IContainerProperties';
|
import { type IContainerProperties } from './IContainerProperties';
|
||||||
|
|
||||||
export interface IContainerModel {
|
export interface IContainerModel {
|
||||||
children: string[]
|
children: string[]
|
||||||
|
@ -18,7 +18,8 @@ export class ContainerModel implements IContainerModel {
|
||||||
constructor(
|
constructor(
|
||||||
properties: IContainerProperties,
|
properties: IContainerProperties,
|
||||||
children: string[] = [],
|
children: string[] = [],
|
||||||
userData = {}) {
|
userData = {}
|
||||||
|
) {
|
||||||
this.properties = properties;
|
this.properties = properties;
|
||||||
this.children = children;
|
this.children = children;
|
||||||
this.userData = userData;
|
this.userData = userData;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { PositionReference } from '../Enums/PositionReference';
|
import { type PositionReference } from '../Enums/PositionReference';
|
||||||
import { IMargin } from './IMargin';
|
import { type Orientation } from '../Enums/Orientation';
|
||||||
import { Orientation } from '../Enums/Orientation';
|
import { type IMargin } from './IMargin';
|
||||||
import { IKeyValue } from './IKeyValue';
|
import { type IKeyValue } from './IKeyValue';
|
||||||
import { IStyle } from './IStyle';
|
import { type IStyle } from './IStyle';
|
||||||
import { IDimensions } from './IDimensions';
|
import { type IDimensions } from './IDimensions';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Properties of a container
|
* Properties of a container
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
import { IDimensionOptions } from './IDimensionOptions';
|
import { type Orientation } from '../Enums/Orientation';
|
||||||
import { Orientation } from '../Enums/Orientation';
|
import { type IDimensionOptions } from './IDimensionOptions';
|
||||||
|
|
||||||
export interface IDimensions {
|
export interface IDimensions {
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { IConfiguration } from './IConfiguration';
|
import { type IConfiguration } from './IConfiguration';
|
||||||
import { IHistoryState } from './IHistoryState';
|
import { type IHistoryState } from './IHistoryState';
|
||||||
|
|
||||||
export interface IEditorState {
|
export interface IEditorState {
|
||||||
history: IHistoryState[]
|
history: IHistoryState[]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
import { IHistoryState } from './IHistoryState';
|
import { type IHistoryState } from './IHistoryState';
|
||||||
|
|
||||||
export interface IGetFeedbackRequest {
|
export interface IGetFeedbackRequest {
|
||||||
/** Current application state */
|
/** Current application state */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
|
|
||||||
import { IMessage } from './IMessage';
|
import { type IMessage } from './IMessage';
|
||||||
|
|
||||||
export interface IGetFeedbackResponse {
|
export interface IGetFeedbackResponse {
|
||||||
messages: IMessage[]
|
messages: IMessage[]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { IContainerModel } from './IContainerModel';
|
import { type IContainerModel } from './IContainerModel';
|
||||||
import { ISymbolModel } from './ISymbolModel';
|
import { type ISymbolModel } from './ISymbolModel';
|
||||||
|
|
||||||
export interface IHistoryState {
|
export interface IHistoryState {
|
||||||
/** Last editor action */
|
/** Last editor action */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React from 'react';
|
import type React from 'react';
|
||||||
|
|
||||||
export interface IInputGroup {
|
export interface IInputGroup {
|
||||||
key: string
|
key: string
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { MessageType } from '../Enums/MessageType';
|
import { type MessageType } from '../Enums/MessageType';
|
||||||
|
|
||||||
export interface IMessage {
|
export interface IMessage {
|
||||||
text: string
|
text: string
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { IAvailableContainer } from './IAvailableContainer';
|
import { type IAvailableContainer } from './IAvailableContainer';
|
||||||
|
|
||||||
export interface IPattern {
|
export interface IPattern {
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { IAction } from './IAction';
|
import { type IAction } from './IAction';
|
||||||
import { IContainerModel } from './IContainerModel';
|
import { type IContainerModel } from './IContainerModel';
|
||||||
import { IHistoryState } from './IHistoryState';
|
import { type IHistoryState } from './IHistoryState';
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
export interface ISetContainerListRequest {
|
export interface ISetContainerListRequest {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
import { AddMethod } from '../Enums/AddMethod';
|
import { type AddMethod } from '../Enums/AddMethod';
|
||||||
import { IAvailableContainer } from './IAvailableContainer';
|
import { type IAvailableContainer } from './IAvailableContainer';
|
||||||
|
|
||||||
export interface ISetContainerListResponse {
|
export interface ISetContainerListResponse {
|
||||||
Containers: IAvailableContainer[]
|
Containers: IAvailableContainer[]
|
||||||
|
|
12
src/main.tsx
12
src/main.tsx
|
@ -5,13 +5,11 @@ import { LanguageProvider } from './Components/LanguageProvider/LanguageProvider
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
|
|
||||||
function RenderRoot(root: Element | Document): void {
|
function RenderRoot(root: Element | Document): void {
|
||||||
ReactDOM.createRoot(root.querySelector('#root') as HTMLDivElement).render(
|
ReactDOM.createRoot(root.querySelector('#root') as HTMLDivElement).render(<React.StrictMode>
|
||||||
<React.StrictMode>
|
<LanguageProvider>
|
||||||
<LanguageProvider>
|
<App root={root}/>
|
||||||
<App root={root}/>
|
</LanguageProvider>
|
||||||
</LanguageProvider>
|
</React.StrictMode>);
|
||||||
</React.StrictMode>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specific for Modeler apps
|
// Specific for Modeler apps
|
||||||
|
|
|
@ -14,7 +14,9 @@ import { type IDimensionStyle } from '../Components/SVG/Elements/Dimension';
|
||||||
/// EDITOR DEFAULTS ///
|
/// EDITOR DEFAULTS ///
|
||||||
|
|
||||||
/** Enable fast boot and disable main menu (0 = disabled, 1 = loading, 2 = loaded) */
|
/** 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) */
|
/** Disable any call to the API (default = false) */
|
||||||
export const DISABLE_API = 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');
|
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;
|
let mainContainerConfig: IContainerProperties;
|
||||||
if (containerConfig !== undefined) {
|
if (containerConfig !== undefined) {
|
||||||
|
@ -128,9 +132,7 @@ export function GetDefaultEditorState(configuration: IConfiguration): IEditorSta
|
||||||
configuration.MainContainer
|
configuration.MainContainer
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const mainContainer = new ContainerModel(
|
const mainContainer = new ContainerModel(mainContainerConfig);
|
||||||
mainContainerConfig
|
|
||||||
);
|
|
||||||
const containers = new Map<string, IContainerModel>();
|
const containers = new Map<string, IContainerModel>();
|
||||||
containers.set(mainContainer.properties.id, mainContainer);
|
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
|
* @param containerConfig default config of the container sent by the API
|
||||||
* @returns {IContainerProperties} Default properties of a newly created container
|
* @returns {IContainerProperties} Default properties of a newly created container
|
||||||
*/
|
*/
|
||||||
export function GetDefaultContainerProps(type: string,
|
export function GetDefaultContainerProps(
|
||||||
|
type: string,
|
||||||
typeCount: number,
|
typeCount: number,
|
||||||
parent: IContainerModel | undefined | null,
|
parent: IContainerModel | undefined | null,
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
width: number,
|
width: number,
|
||||||
height: number,
|
height: number,
|
||||||
containerConfig: IAvailableContainer): IContainerProperties {
|
containerConfig: IAvailableContainer
|
||||||
|
): IContainerProperties {
|
||||||
const orientation = containerConfig.Orientation ?? Orientation.Horizontal;
|
const orientation = containerConfig.Orientation ?? Orientation.Horizontal;
|
||||||
return ({
|
return ({
|
||||||
id: `${type}-${typeCount}`,
|
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>,
|
newCounters: Record<string, number>,
|
||||||
type: string,
|
type: string,
|
||||||
symbolConfig: IAvailableSymbol): ISymbolModel {
|
symbolConfig: IAvailableSymbol
|
||||||
|
): ISymbolModel {
|
||||||
const id = `${name}-${newCounters[type]}`;
|
const id = `${name}-${newCounters[type]}`;
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
|
|
|
@ -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) {
|
for (const childId of childrenIds) {
|
||||||
const child = FindContainerById(containers, childId);
|
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
|
* 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 queue: IContainerModel[] = [root];
|
||||||
const visited = new Set<IContainerModel>(queue);
|
const visited = new Set<IContainerModel>(queue);
|
||||||
while (queue.length > 0) {
|
while (queue.length > 0) {
|
||||||
|
@ -51,7 +58,10 @@ export interface ContainerAndDepthAndTransform extends ContainerAndDepth {
|
||||||
/**
|
/**
|
||||||
* Returns a Generator iterating of over the children depth-first
|
* 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];
|
const queue: IContainerModel[] = [root];
|
||||||
let depth = 0;
|
let depth = 0;
|
||||||
while (queue.length > 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 by iterating to the parent
|
||||||
* @returns The absolute position of the container
|
* @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 x = container.properties.x;
|
||||||
const y = container.properties.y;
|
const y = container.properties.y;
|
||||||
const parent = FindContainerById(containers, container.properties.parentId) ?? null;
|
const parent = FindContainerById(containers, container.properties.parentId) ?? null;
|
||||||
|
@ -230,7 +243,11 @@ export function ApplyParentTransform(
|
||||||
* @param id Id of the container to find
|
* @param id Id of the container to find
|
||||||
* @returns The container found or undefined if not found
|
* @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);
|
const it = MakeDFSIterator(root, containers);
|
||||||
for (const container of it) {
|
for (const container of it) {
|
||||||
if (container.properties.id === id) {
|
if (container.properties.id === id) {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
import { IEditorState } from '../Interfaces/IEditorState';
|
import { type IEditorState } from '../Interfaces/IEditorState';
|
||||||
import { IHistoryState } from '../Interfaces/IHistoryState';
|
import { type IHistoryState } from '../Interfaces/IHistoryState';
|
||||||
import { IContainerModel } from '../Interfaces/IContainerModel';
|
import { type IContainerModel } from '../Interfaces/IContainerModel';
|
||||||
import { ISymbolModel } from '../Interfaces/ISymbolModel';
|
import { type ISymbolModel } from '../Interfaces/ISymbolModel';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Revive the Editor state
|
* Revive the Editor state
|
||||||
|
@ -37,7 +37,10 @@ export function ReviveState(state: IHistoryState): void {
|
||||||
state.containers = new Map(containers.map(({ Key, Value }) => [Key, Value]));
|
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) => {
|
return (key: any, value: object | null) => {
|
||||||
if (key === 'containers') {
|
if (key === 'containers') {
|
||||||
return [...(value as Map<string, any>).entries()]
|
return [...(value as Map<string, any>).entries()]
|
||||||
|
|
|
@ -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
|
* - 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)
|
* - 5) in the selected rows other columns (other than the selected column)
|
||||||
* must be divided by that pivot: coef / pivot
|
* 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,
|
* - 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
|
* redo the algorithm with the new matrix as the base matrix
|
||||||
* - 8) otherwise returns the basic variable such as
|
* - 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
|
// to avoid infinite loop try to select the least used selected index
|
||||||
const pivotColIndex = GetLeastUsedIndex(indexes, indexesTried);
|
const pivotColIndex = GetLeastUsedIndex(indexes, indexesTried);
|
||||||
// record the usage of index by incrementing
|
// 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))
|
// 2) find the smallest non negative non null ratio bi/xij (O(m))
|
||||||
const ratios = [];
|
const ratios = [];
|
||||||
|
@ -210,7 +213,9 @@ function GetSolutions(nCols: number, finalMatrix: number[][]): number[] {
|
||||||
const col: number[] = [];
|
const col: number[] = [];
|
||||||
for (let j = 0; j < finalMatrix.length; j++) {
|
for (let j = 0; j < finalMatrix.length; j++) {
|
||||||
const row = finalMatrix[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]);
|
col.push(row[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,5 +6,7 @@ export function TruncateString(str: string, num: number): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Camelize(str: string): any {
|
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('');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* eslint-disable import/export */
|
/* eslint-disable import/export */
|
||||||
import * as React from 'react';
|
import type * as React from 'react';
|
||||||
import { cleanup, render, RenderResult } from '@testing-library/react';
|
import { cleanup, render, type RenderResult } from '@testing-library/react';
|
||||||
import { afterEach } from 'vitest';
|
import { afterEach } from 'vitest';
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue