Implement events for external use + Rename interfaces with a I prefix + add some documentation (#26)
All checks were successful
continuous-integration/drone/push Build is passing

Implement events for external use
Rename interfaces with a I prefix
Add some documentation

Co-authored-by: Eric NGUYEN <enguyen@techform.fr>
Reviewed-on: https://git.siklos-chaneru.duckdns.org/Siklos/svg-layout-designer-react/pulls/26
This commit is contained in:
Siklos 2022-08-12 06:36:14 -04:00
parent 6c601429b9
commit c81a6fe44b
38 changed files with 228 additions and 116 deletions

1
.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
*.drawio filter=lfs diff=lfs merge=lfs -text

BIN
docs/ComponentStructure.drawio (Stored with Git LFS) Normal file

Binary file not shown.

65
public/Interfaces.d.ts vendored Normal file
View file

@ -0,0 +1,65 @@
declare interface IHistoryState {
LastAction: string
MainContainer: IContainerModel
SelectedContainer: IContainerModel | null
SelectedContainerId: string
TypeCounters: Record<string, number>
}
declare interface IAvailableContainer {
Type: string
Width: number
Height: number
XPositionReference?: XPositionReference
Style: React.CSSProperties
}
declare interface IEditorState {
history: IHistoryState[]
historyCurrentStep: number
configuration: IConfiguration
}
declare interface IConfiguration {
AvailableContainers: IAvailableContainer[]
AvailableSymbols: IAvailableSymbol[]
MainContainer: IAvailableContainer
}
declare interface IContainerModel {
children: IContainerModel[]
parent: IContainerModel | null
properties: IProperties
userData: Record<string, string | number>
}
declare interface IProperties extends React.CSSProperties {
id: string
parentId: string | null
x: number
y: number
isRigidBody: boolean
XPositionReference?: XPositionReference
}
declare enum XPositionReference {
Left,
Center,
Right
}
declare interface IAvailableSymbol {
Name: string
XPositionReference: XPositionReference
Image: IImage
Width: number
Height: number
}
declare interface IImage {
Name: string
Url: string
Base64Image: string
Svg: string
}

View file

@ -1,10 +1,10 @@
import { Configuration } from '../../Interfaces/Configuration'; import { IConfiguration } from '../../Interfaces/IConfiguration';
/** /**
* Fetch the configuration from the API * Fetch the configuration from the API
* @returns {Configation} The model of the configuration for the application * @returns {Configation} The model of the configuration for the application
*/ */
export async function fetchConfiguration(): Promise<Configuration> { export async function fetchConfiguration(): Promise<IConfiguration> {
const url = `${import.meta.env.VITE_API_URL}`; const url = `${import.meta.env.VITE_API_URL}`;
// The test library cannot use the Fetch API // The test library cannot use the Fetch API
// @ts-expect-error // @ts-expect-error
@ -15,7 +15,7 @@ export async function fetchConfiguration(): Promise<Configuration> {
}) })
.then(async(response) => .then(async(response) =>
await response.json() await response.json()
) as Configuration; ) as IConfiguration;
} }
return await new Promise((resolve) => { return await new Promise((resolve) => {
const xhr = new XMLHttpRequest(); const xhr = new XMLHttpRequest();

View file

@ -1,8 +1,9 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import './App.scss'; import './App.scss';
import { MainMenu } from '../MainMenu/MainMenu'; import { MainMenu } from '../MainMenu/MainMenu';
import { ContainerModel } from '../../Interfaces/ContainerModel'; import { ContainerModel } from '../../Interfaces/IContainerModel';
import Editor, { IEditorState } from '../Editor/Editor'; import Editor from '../Editor/Editor';
import { IEditorState } from '../../Interfaces/IEditorState';
import { LoadState } from './Load'; import { LoadState } from './Load';
import { LoadEditor, NewEditor } from './MenuActions'; import { LoadEditor, NewEditor } from './MenuActions';
import { DEFAULT_CONFIG, DEFAULT_MAINCONTAINER_PROPS } from '../../utils/default'; import { DEFAULT_CONFIG, DEFAULT_MAINCONTAINER_PROPS } from '../../utils/default';

View file

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

View file

@ -1,8 +1,8 @@
import { Dispatch, SetStateAction } from 'react'; import { Dispatch, SetStateAction } from 'react';
import { Configuration } from '../../Interfaces/Configuration'; import { IConfiguration } from '../../Interfaces/IConfiguration';
import { ContainerModel } from '../../Interfaces/ContainerModel'; import { ContainerModel } from '../../Interfaces/IContainerModel';
import { fetchConfiguration } from '../API/api'; import { fetchConfiguration } from '../API/api';
import { IEditorState } from '../Editor/Editor'; import { IEditorState } from "../../Interfaces/IEditorState";
import { LoadState } from './Load'; import { LoadState } from './Load';
export function NewEditor( export function NewEditor(
@ -11,7 +11,7 @@ export function NewEditor(
): void { ): void {
// Fetch the configuration from the API // Fetch the configuration from the API
fetchConfiguration() fetchConfiguration()
.then((configuration: Configuration) => { .then((configuration: IConfiguration) => {
// Set the main container from the given properties of the API // Set the main container from the given properties of the API
const MainContainer = new ContainerModel( const MainContainer = new ContainerModel(
null, null,

View file

@ -1,7 +1,7 @@
import { Dispatch, SetStateAction } from 'react'; import { Dispatch, SetStateAction } from 'react';
import { HistoryState } from '../../Interfaces/HistoryState'; import { IHistoryState } from '../../Interfaces/IHistoryState';
import { Configuration } from '../../Interfaces/Configuration'; import { IConfiguration } from '../../Interfaces/IConfiguration';
import { ContainerModel, IContainerModel } from '../../Interfaces/ContainerModel'; import { ContainerModel, IContainerModel } from '../../Interfaces/IContainerModel';
import { findContainerById } from '../../utils/itertools'; import { findContainerById } from '../../utils/itertools';
import { getCurrentHistory } from './Editor'; import { getCurrentHistory } from './Editor';
@ -11,9 +11,9 @@ import { getCurrentHistory } from './Editor';
*/ */
export function SelectContainer( export function SelectContainer(
container: ContainerModel, container: ContainerModel,
fullHistory: HistoryState[], fullHistory: IHistoryState[],
historyCurrentStep: number, historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<HistoryState[]>>, setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>> setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void { ): void {
const history = getCurrentHistory(fullHistory, historyCurrentStep); const history = getCurrentHistory(fullHistory, historyCurrentStep);
@ -46,9 +46,9 @@ export function SelectContainer(
*/ */
export function DeleteContainer( export function DeleteContainer(
containerId: string, containerId: string,
fullHistory: HistoryState[], fullHistory: IHistoryState[],
historyCurrentStep: number, historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<HistoryState[]>>, setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>> setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void { ): void {
const history = getCurrentHistory(fullHistory, historyCurrentStep); const history = getCurrentHistory(fullHistory, historyCurrentStep);
@ -108,10 +108,10 @@ export function DeleteContainer(
*/ */
export function AddContainerToSelectedContainer( export function AddContainerToSelectedContainer(
type: string, type: string,
configuration: Configuration, configuration: IConfiguration,
fullHistory: HistoryState[], fullHistory: IHistoryState[],
historyCurrentStep: number, historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<HistoryState[]>>, setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>> setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void { ): void {
const history = getCurrentHistory(fullHistory, historyCurrentStep); const history = getCurrentHistory(fullHistory, historyCurrentStep);
@ -151,10 +151,10 @@ export function AddContainer(
index: number, index: number,
type: string, type: string,
parentId: string, parentId: string,
configuration: Configuration, configuration: IConfiguration,
fullHistory: HistoryState[], fullHistory: IHistoryState[],
historyCurrentStep: number, historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<HistoryState[]>>, setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>> setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void { ): void {
const history = getCurrentHistory(fullHistory, historyCurrentStep); const history = getCurrentHistory(fullHistory, historyCurrentStep);

View file

@ -1,32 +1,29 @@
import React from 'react'; import React, { useRef } from 'react';
import './Editor.scss'; import './Editor.scss';
import { Configuration } from '../../Interfaces/Configuration'; import { IConfiguration } from '../../Interfaces/IConfiguration';
import { SVG } from '../SVG/SVG'; import { SVG } from '../SVG/SVG';
import { HistoryState } from '../../Interfaces/HistoryState'; import { IHistoryState } from '../../Interfaces/IHistoryState';
import { UI } from '../UI/UI'; import { UI } from '../UI/UI';
import { SelectContainer, DeleteContainer, AddContainerToSelectedContainer, AddContainer } from './ContainerOperations'; import { SelectContainer, DeleteContainer, AddContainerToSelectedContainer, AddContainer } from './ContainerOperations';
import { SaveEditorAsJSON, SaveEditorAsSVG } from './Save'; import { SaveEditorAsJSON, SaveEditorAsSVG } from './Save';
import { onKeyDown } from './Shortcuts'; import { onKeyDown } from './Shortcuts';
import { OnPropertyChange, OnPropertiesSubmit } from './PropertiesOperations'; import { OnPropertyChange, OnPropertiesSubmit } from './PropertiesOperations';
import EditorEvents from '../../Events/EditorEvents';
import { IEditorState } from '../../Interfaces/IEditorState';
interface IEditorProps { interface IEditorProps {
configuration: Configuration configuration: IConfiguration
history: HistoryState[] history: IHistoryState[]
historyCurrentStep: number historyCurrentStep: number
} }
export interface IEditorState { export const getCurrentHistory = (history: IHistoryState[], historyCurrentStep: number): IHistoryState[] => history.slice(0, historyCurrentStep + 1);
history: HistoryState[] export const getCurrentHistoryState = (history: IHistoryState[], historyCurrentStep: number): IHistoryState => history[historyCurrentStep];
historyCurrentStep: number
configuration: Configuration
}
export const getCurrentHistory = (history: HistoryState[], historyCurrentStep: number): HistoryState[] => history.slice(0, historyCurrentStep + 1);
export const getCurrentHistoryState = (history: HistoryState[], historyCurrentStep: number): HistoryState => history[historyCurrentStep];
const Editor: React.FunctionComponent<IEditorProps> = (props) => { const Editor: React.FunctionComponent<IEditorProps> = (props) => {
const [history, setHistory] = React.useState<HistoryState[]>(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 editorRef = useRef<HTMLDivElement>(null);
React.useEffect(() => { React.useEffect(() => {
const onKeyUp = (event: KeyboardEvent): void => onKeyDown( const onKeyUp = (event: KeyboardEvent): void => onKeyDown(
@ -38,6 +35,17 @@ const Editor: React.FunctionComponent<IEditorProps> = (props) => {
window.addEventListener('keyup', onKeyUp); window.addEventListener('keyup', onKeyUp);
const events = EditorEvents;
const editorState: IEditorState = {
history,
historyCurrentStep,
configuration: props.configuration
};
for (const event of events) {
editorRef.current?.addEventListener(event.name, () => event.func(editorState));
}
return () => { return () => {
window.removeEventListener('keyup', onKeyUp); window.removeEventListener('keyup', onKeyUp);
}; };
@ -46,7 +54,7 @@ const Editor: React.FunctionComponent<IEditorProps> = (props) => {
const configuration = props.configuration; const configuration = props.configuration;
const current = getCurrentHistoryState(history, historyCurrentStep); const current = getCurrentHistoryState(history, historyCurrentStep);
return ( return (
<div className="App font-sans h-full"> <div ref={editorRef} className="Editor font-sans h-full">
<UI <UI
current={current} current={current}
history={history} history={history}

View file

@ -1,7 +1,7 @@
import { Dispatch, SetStateAction } from 'react'; import { Dispatch, SetStateAction } from 'react';
import { IContainerModel, ContainerModel } from '../../Interfaces/ContainerModel'; import { IContainerModel, ContainerModel } from '../../Interfaces/IContainerModel';
import { HistoryState } from '../../Interfaces/HistoryState'; import { IHistoryState } from '../../Interfaces/IHistoryState';
import Properties from '../../Interfaces/Properties'; import IProperties from '../../Interfaces/IProperties';
import { findContainerById } from '../../utils/itertools'; import { findContainerById } from '../../utils/itertools';
import { getCurrentHistory } from './Editor'; import { getCurrentHistory } from './Editor';
import { RecalculatePhysics } from './RigidBodyBehaviors'; import { RecalculatePhysics } from './RigidBodyBehaviors';
@ -15,9 +15,9 @@ import { RecalculatePhysics } from './RigidBodyBehaviors';
export function OnPropertyChange( export function OnPropertyChange(
key: string, key: string,
value: string | number | boolean, value: string | number | boolean,
fullHistory: HistoryState[], fullHistory: IHistoryState[],
historyCurrentStep: number, historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<HistoryState[]>>, setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>> setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void { ): void {
const history = getCurrentHistory(fullHistory, historyCurrentStep); const history = getCurrentHistory(fullHistory, historyCurrentStep);
@ -73,10 +73,10 @@ export function OnPropertyChange(
*/ */
export function OnPropertiesSubmit( export function OnPropertiesSubmit(
event: React.SyntheticEvent<HTMLFormElement>, event: React.SyntheticEvent<HTMLFormElement>,
properties: Properties, properties: IProperties,
fullHistory: HistoryState[], fullHistory: IHistoryState[],
historyCurrentStep: number, historyCurrentStep: number,
setHistory: Dispatch<SetStateAction<HistoryState[]>>, setHistory: Dispatch<SetStateAction<IHistoryState[]>>,
setHistoryCurrentStep: Dispatch<SetStateAction<number>> setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void { ): void {
event.preventDefault(); event.preventDefault();

View file

@ -1,5 +1,5 @@
import { IContainerModel } from '../../Interfaces/ContainerModel'; import { IContainerModel } from '../../Interfaces/IContainerModel';
import { SizePointer } from '../../Interfaces/SizePointer'; import { ISizePointer } from '../../Interfaces/ISizePointer';
/** /**
* "Transform the container into a rigid body" * "Transform the container into a rigid body"
@ -167,17 +167,17 @@ function constraintBodyInsideUnallocatedWidth(
* (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 {SizePointer[]} 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(
container: IContainerModel, container: IContainerModel,
exception: IContainerModel exception: IContainerModel
): SizePointer[] { ): ISizePointer[] {
// Initialize the first size pointer // Initialize the first size pointer
// which takes full width of the available space // which takes full width of the available space
const x = 0; const x = 0;
const width = Number(container.properties.width); const width = Number(container.properties.width);
let unallocatedSpaces: SizePointer[] = [{ x, width }]; let unallocatedSpaces: ISizePointer[] = [{ x, width }];
// We will only uses containers that also have the rigid bodies // We will only uses containers that also have the rigid bodies
// as out-of-bound or enormouse containers should be ignored // as out-of-bound or enormouse containers should be ignored
@ -192,7 +192,7 @@ function getAvailableWidths(
} }
// get the space of the child that is inside the parent // get the space of the child that is inside the parent
let newUnallocatedSpace: SizePointer[] = []; let newUnallocatedSpace: ISizePointer[] = [];
// We will iterate on a mutable variable in order to divide it // We will iterate on a mutable variable in order to divide it
for (const unallocatedSpace of unallocatedSpaces) { for (const unallocatedSpace of unallocatedSpaces) {
@ -229,7 +229,7 @@ function getAvailableWidthsTwoLines(
max1: number, max1: number,
min2: number, min2: number,
max2: number max2: number
): SizePointer[] { ): ISizePointer[] {
if (min2 < min1 && max2 > max1) { if (min2 < min1 && max2 > max1) {
// object 2 is overlapping full width // object 2 is overlapping full width
return []; return [];
@ -276,5 +276,5 @@ function getAvailableWidthsTwoLines(
*/ */
const isFitting = ( const isFitting = (
container: IContainerModel, container: IContainerModel,
sizePointer: SizePointer sizePointer: ISizePointer
): boolean => Number(container.properties.width) <= sizePointer.width; ): boolean => Number(container.properties.width) <= sizePointer.width;

View file

@ -1,13 +1,13 @@
import { HistoryState } from '../../Interfaces/HistoryState'; import { IHistoryState } from '../../Interfaces/IHistoryState';
import { Configuration } from '../../Interfaces/Configuration'; import { 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 './Editor'; import { IEditorState } from '../../Interfaces/IEditorState';
export function SaveEditorAsJSON( export function SaveEditorAsJSON(
history: HistoryState[], history: IHistoryState[],
historyCurrentStep: number, historyCurrentStep: number,
configuration: Configuration configuration: IConfiguration
): void { ): void {
const exportName = 'state'; const exportName = 'state';
const spaces = import.meta.env.DEV ? 4 : 0; const spaces = import.meta.env.DEV ? 4 : 0;

View file

@ -1,9 +1,9 @@
import { Dispatch, SetStateAction } from 'react'; import { Dispatch, SetStateAction } from 'react';
import { HistoryState } from '../../Interfaces/HistoryState'; import { IHistoryState } from '../../Interfaces/IHistoryState';
export function onKeyDown( export function onKeyDown(
event: KeyboardEvent, event: KeyboardEvent,
history: HistoryState[], history: IHistoryState[],
historyCurrentStep: number, historyCurrentStep: number,
setHistoryCurrentStep: Dispatch<SetStateAction<number>> setHistoryCurrentStep: Dispatch<SetStateAction<number>>
): void { ): void {

View file

@ -2,7 +2,7 @@ import { describe, expect, it, vi } from 'vitest';
import * as React from 'react'; import * as React from 'react';
import { fireEvent, render, screen } from '../../utils/test-utils'; import { fireEvent, render, screen } from '../../utils/test-utils';
import { ElementsSidebar } from './ElementsSidebar'; import { ElementsSidebar } from './ElementsSidebar';
import { IContainerModel } from '../../Interfaces/ContainerModel'; import { IContainerModel } from '../../Interfaces/IContainerModel';
describe.concurrent('Elements sidebar', () => { describe.concurrent('Elements sidebar', () => {
it('With a MainContainer', () => { it('With a MainContainer', () => {

View file

@ -1,13 +1,13 @@
import * as React from 'react'; import * as React from 'react';
import { motion } from 'framer-motion'; import { motion } from 'framer-motion';
import { Properties } from '../Properties/Properties'; import { Properties } from '../Properties/Properties';
import ContainerProperties from '../../Interfaces/Properties'; import ContainerProperties from '../../Interfaces/IProperties';
import { IContainerModel } from '../../Interfaces/ContainerModel'; import { IContainerModel } from '../../Interfaces/IContainerModel';
import { getDepth, MakeIterator } from '../../utils/itertools'; import { getDepth, MakeIterator } from '../../utils/itertools';
import { Menu } from '../Menu/Menu'; import { Menu } from '../Menu/Menu';
import { MenuItem } from '../Menu/MenuItem'; import { MenuItem } from '../Menu/MenuItem';
import { handleDragLeave, handleDragOver, handleLeftClick, handleOnDrop, handleRightClick } from './MouseEventHandlers'; import { handleDragLeave, handleDragOver, handleLeftClick, handleOnDrop, handleRightClick } from './MouseEventHandlers';
import { Point } from '../../Interfaces/Point'; import { IPoint } from '../../Interfaces/IPoint';
interface IElementsSidebarProps { interface IElementsSidebarProps {
MainContainer: IContainerModel MainContainer: IContainerModel
@ -64,7 +64,7 @@ export const ElementsSidebar: React.FC<IElementsSidebarProps> = (props: IElement
// States // States
const [isContextMenuOpen, setIsContextMenuOpen] = React.useState<boolean>(false); const [isContextMenuOpen, setIsContextMenuOpen] = React.useState<boolean>(false);
const [onClickContainerId, setOnClickContainerId] = React.useState<string>(''); const [onClickContainerId, setOnClickContainerId] = React.useState<string>('');
const [contextMenuPosition, setContextMenuPosition] = React.useState<Point>({ const [contextMenuPosition, setContextMenuPosition] = React.useState<IPoint>({
x: 0, x: 0,
y: 0 y: 0
}); });

View file

@ -1,12 +1,12 @@
import { IContainerModel } from '../../Interfaces/ContainerModel'; import { IContainerModel } from '../../Interfaces/IContainerModel';
import { Point } from '../../Interfaces/Point'; import { IPoint } from '../../Interfaces/IPoint';
import { findContainerById } from '../../utils/itertools'; import { findContainerById } from '../../utils/itertools';
export function handleRightClick( export function handleRightClick(
event: MouseEvent, event: MouseEvent,
setIsContextMenuOpen: React.Dispatch<React.SetStateAction<boolean>>, setIsContextMenuOpen: React.Dispatch<React.SetStateAction<boolean>>,
setOnClickContainerId: React.Dispatch<React.SetStateAction<string>>, setOnClickContainerId: React.Dispatch<React.SetStateAction<string>>,
setContextMenuPosition: React.Dispatch<React.SetStateAction<Point>> setContextMenuPosition: React.Dispatch<React.SetStateAction<IPoint>>
): void { ): void {
event.preventDefault(); event.preventDefault();
@ -16,7 +16,7 @@ export function handleRightClick(
return; return;
} }
const contextMenuPosition: Point = { x: event.pageX, y: event.pageY }; const contextMenuPosition: IPoint = { x: event.pageX, y: event.pageY };
setIsContextMenuOpen(true); setIsContextMenuOpen(true);
setOnClickContainerId(event.target.id); setOnClickContainerId(event.target.id);
setContextMenuPosition(contextMenuPosition); setContextMenuPosition(contextMenuPosition);

View file

@ -1,8 +1,8 @@
import * as React from 'react'; import * as React from 'react';
import { HistoryState } from "../../Interfaces/HistoryState"; import { IHistoryState } from "../../Interfaces/IHistoryState";
interface IHistoryProps { interface IHistoryProps {
history: HistoryState[] history: IHistoryState[]
historyCurrentStep: number historyCurrentStep: number
isOpen: boolean isOpen: boolean
jumpTo: (move: number) => void jumpTo: (move: number) => void

View file

@ -1,5 +1,5 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import ContainerProperties from '../../Interfaces/Properties'; import ContainerProperties from '../../Interfaces/IProperties';
import { ToggleButton } from '../ToggleButton/ToggleButton'; import { ToggleButton } from '../ToggleButton/ToggleButton';
import { INPUT_TYPES } from './PropertiesInputTypes'; import { INPUT_TYPES } from './PropertiesInputTypes';

View file

@ -1,10 +1,10 @@
import * as React from 'react'; import * as React from 'react';
import { XPositionReference } from '../../../Enums/XPositionReference'; import { XPositionReference } from '../../../Enums/XPositionReference';
import { IContainerModel } from '../../../Interfaces/ContainerModel'; import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { getDepth } from '../../../utils/itertools'; import { getDepth } from '../../../utils/itertools';
import { Dimension } from './Dimension'; import { Dimension } from './Dimension';
export interface IContainerProps { interface IContainerProps {
model: IContainerModel model: IContainerModel
} }

View file

@ -1,5 +1,5 @@
import * as React from 'react'; import * as React from 'react';
import { IContainerModel } from '../../../Interfaces/ContainerModel'; import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { getAbsolutePosition } from '../../../utils/itertools'; import { getAbsolutePosition } from '../../../utils/itertools';
interface ISelectorProps { interface ISelectorProps {

View file

@ -1,7 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import { UncontrolledReactSVGPanZoom } from 'react-svg-pan-zoom'; import { UncontrolledReactSVGPanZoom } from 'react-svg-pan-zoom';
import { Container } from './Elements/Container'; import { Container } from './Elements/Container';
import { ContainerModel } from '../../Interfaces/ContainerModel'; import { ContainerModel } from '../../Interfaces/IContainerModel';
import { Selector } from './Elements/Selector'; import { Selector } from './Elements/Selector';
import { BAR_WIDTH } from '../Bar/Bar'; import { BAR_WIDTH } from '../Bar/Bar';

View file

@ -1,9 +1,9 @@
import * as React from 'react'; import * as React from 'react';
import { AvailableContainer } from '../../Interfaces/AvailableContainer'; import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
import { truncateString } from '../../utils/stringtools'; import { truncateString } from '../../utils/stringtools';
interface ISidebarProps { interface ISidebarProps {
componentOptions: AvailableContainer[] componentOptions: IAvailableContainer[]
isOpen: boolean isOpen: boolean
buttonOnClick: (type: string) => void buttonOnClick: (type: string) => void
} }

View file

@ -2,23 +2,23 @@ import * as React from 'react';
import { ElementsSidebar } from '../ElementsSidebar/ElementsSidebar'; import { ElementsSidebar } from '../ElementsSidebar/ElementsSidebar';
import { Sidebar } from '../Sidebar/Sidebar'; import { Sidebar } from '../Sidebar/Sidebar';
import { History } from '../History/History'; import { History } from '../History/History';
import { AvailableContainer } from '../../Interfaces/AvailableContainer'; import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
import { ContainerModel } from '../../Interfaces/ContainerModel'; import { ContainerModel } from '../../Interfaces/IContainerModel';
import { HistoryState } from '../../Interfaces/HistoryState'; import { IHistoryState } from '../../Interfaces/IHistoryState';
import { PhotographIcon, UploadIcon } from '@heroicons/react/outline'; import { PhotographIcon, UploadIcon } from '@heroicons/react/outline';
import { FloatingButton } from '../FloatingButton/FloatingButton'; import { FloatingButton } from '../FloatingButton/FloatingButton';
import { Bar } from '../Bar/Bar'; import { Bar } from '../Bar/Bar';
import Properties from '../../Interfaces/Properties'; import IProperties from '../../Interfaces/IProperties';
interface IUIProps { interface IUIProps {
current: HistoryState current: IHistoryState
history: HistoryState[] history: IHistoryState[]
historyCurrentStep: number historyCurrentStep: number
AvailableContainers: AvailableContainer[] AvailableContainers: IAvailableContainer[]
SelectContainer: (container: ContainerModel) => void SelectContainer: (container: ContainerModel) => void
DeleteContainer: (containerId: string) => void DeleteContainer: (containerId: string) => void
OnPropertyChange: (key: string, value: string | number | boolean) => void OnPropertyChange: (key: string, value: string | number | boolean) => void
OnPropertiesSubmit: (event: React.FormEvent<HTMLFormElement>, properties: Properties) => void OnPropertiesSubmit: (event: React.FormEvent<HTMLFormElement>, properties: IProperties) => void
AddContainerToSelectedContainer: (type: string) => void AddContainerToSelectedContainer: (type: string) => void
AddContainer: (index: number, type: string, parentId: string) => void AddContainer: (index: number, type: string, parentId: string) => void
SaveEditorAsJSON: () => void SaveEditorAsJSON: () => void

View file

@ -0,0 +1,26 @@
import { IEditorState } from '../Interfaces/IEditorState';
import { IHistoryState } from '../Interfaces/IHistoryState';
const getEditorState = (editorState: IEditorState): void => {
const customEvent = new CustomEvent<IEditorState>('getEditorState', { detail: editorState });
document.dispatchEvent(customEvent);
};
const getCurrentHistoryState = (editorState: IEditorState): void => {
const customEvent = new CustomEvent<IHistoryState>(
'getCurrentHistoryState',
{ detail: editorState.history[editorState.historyCurrentStep] });
document.dispatchEvent(customEvent);
};
export interface IEditorEvent {
name: string
func: (editorState: IEditorState) => void
}
const events: IEditorEvent[] = [
{ name: 'getEditorState', func: getEditorState },
{ name: 'getCurrentHistoryState', func: getCurrentHistoryState }
];
export default events;

View file

@ -1,9 +0,0 @@
import { AvailableContainer } from './AvailableContainer';
import { AvailableSymbolModel } from './AvailableSymbol';
/** Model of configuration for the application to configure it */
export interface Configuration {
AvailableContainers: AvailableContainer[]
AvailableSymbols: AvailableSymbolModel[]
MainContainer: AvailableContainer
}

View file

@ -2,7 +2,7 @@ import React from 'react';
import { XPositionReference } from '../Enums/XPositionReference'; import { XPositionReference } from '../Enums/XPositionReference';
/** Model of available container used in application configuration */ /** Model of available container used in application configuration */
export interface AvailableContainer { export interface IAvailableContainer {
Type: string Type: string
Width: number Width: number
Height: number Height: number

View file

@ -1,12 +1,12 @@
import { XPositionReference } from '../Enums/XPositionReference'; import { XPositionReference } from '../Enums/XPositionReference';
import { Image } from './Image'; import { IImage } from './IImage';
/** /**
* Model of available symbol to configure the application */ * Model of available symbol to configure the application */
export interface AvailableSymbolModel { export interface IAvailableSymbol {
Name: string Name: string
XPositionReference: XPositionReference XPositionReference: XPositionReference
Image: Image Image: IImage
Width: number Width: number
Height: number Height: number
} }

View file

@ -0,0 +1,9 @@
import { IAvailableContainer } from './IAvailableContainer';
import { IAvailableSymbol } from './IAvailableSymbol';
/** Model of configuration for the application to configure it */
export interface IConfiguration {
AvailableContainers: IAvailableContainer[]
AvailableSymbols: IAvailableSymbol[]
MainContainer: IAvailableContainer
}

View file

@ -1,21 +1,21 @@
import Properties from './Properties'; import IProperties from './IProperties';
export interface IContainerModel { export interface IContainerModel {
children: IContainerModel[] children: IContainerModel[]
parent: IContainerModel | null parent: IContainerModel | null
properties: Properties properties: IProperties
userData: Record<string, string | number> userData: Record<string, string | number>
} }
export class ContainerModel implements IContainerModel { export class ContainerModel implements IContainerModel {
public children: IContainerModel[]; public children: IContainerModel[];
public parent: IContainerModel | null; public parent: IContainerModel | null;
public properties: Properties; public properties: IProperties;
public userData: Record<string, string | number>; public userData: Record<string, string | number>;
constructor( constructor(
parent: IContainerModel | null, parent: IContainerModel | null,
properties: Properties, properties: IProperties,
children: IContainerModel[] = [], children: IContainerModel[] = [],
userData = {}) { userData = {}) {
this.parent = parent; this.parent = parent;

View file

@ -0,0 +1,8 @@
import { IConfiguration } from './IConfiguration';
import { IHistoryState } from './IHistoryState';
export interface IEditorState {
history: IHistoryState[]
historyCurrentStep: number
configuration: IConfiguration
}

View file

@ -1,6 +1,6 @@
import { IContainerModel } from './ContainerModel'; import { IContainerModel } from './IContainerModel';
export interface HistoryState { export interface IHistoryState {
LastAction: string LastAction: string
MainContainer: IContainerModel MainContainer: IContainerModel
SelectedContainer: IContainerModel | null SelectedContainer: IContainerModel | null

View file

@ -1,5 +1,5 @@
/** Model of an image with multiple source */ /** Model of an image with multiple source */
export interface Image { export interface IImage {
Name: string Name: string
Url: string Url: string
Base64Image: string Base64Image: string

View file

@ -1,4 +1,4 @@
export interface Point { export interface IPoint {
x: number x: number
y: number y: number
} }

View file

@ -1,7 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import { XPositionReference } from '../Enums/XPositionReference'; import { XPositionReference } from '../Enums/XPositionReference';
export default interface Properties extends React.CSSProperties { export default interface IProperties extends React.CSSProperties {
id: string id: string
parentId: string | null parentId: string | null
x: number x: number

View file

@ -3,7 +3,7 @@
* x being the address where the pointer is pointing * x being the address where the pointer is pointing
* width being the overall (un)allocated space affected to the address * width being the overall (un)allocated space affected to the address
*/ */
export interface SizePointer { export interface ISizePointer {
x: number x: number
width: number width: number
} }

View file

@ -1,7 +1,7 @@
import { Configuration } from '../Interfaces/Configuration'; import { IConfiguration } from '../Interfaces/IConfiguration';
import Properties from '../Interfaces/Properties'; import IProperties from '../Interfaces/IProperties';
export const DEFAULT_CONFIG: Configuration = { export const DEFAULT_CONFIG: IConfiguration = {
AvailableContainers: [ AvailableContainers: [
{ {
Type: 'Container', Type: 'Container',
@ -25,7 +25,7 @@ export const DEFAULT_CONFIG: Configuration = {
} }
}; };
export const DEFAULT_MAINCONTAINER_PROPS: Properties = { export const DEFAULT_MAINCONTAINER_PROPS: IProperties = {
id: 'main', id: 'main',
parentId: 'null', parentId: 'null',
x: 0, x: 0,

View file

@ -1,4 +1,4 @@
import { IContainerModel } from '../Interfaces/ContainerModel'; import { IContainerModel } from '../Interfaces/IContainerModel';
/** /**
* Returns a Generator iterating of over the children depth-first * Returns a Generator iterating of over the children depth-first

View file

@ -1,5 +1,5 @@
import { findContainerById, MakeIterator } from './itertools'; import { findContainerById, MakeIterator } from './itertools';
import { IEditorState } from '../Components/Editor/Editor'; import { IEditorState } from '../Interfaces/IEditorState';
/** /**
* Revive the Editor state * Revive the Editor state