diff --git a/README.md b/README.md
index a3d003d..e413c05 100644
--- a/README.md
+++ b/README.md
@@ -13,8 +13,9 @@ An svg layout designer.
Requierements :
- NodeJS
- npm
-- pnpm (optional but recommanded unless you prefer having a huge `node_modules` directory)
- Chrome > 98
+- pnpm (optional but recommanded unless you prefer having a huge `node_modules` directory)
+- [`git-lfs`](https://git-lfs.github.com/) (in order to clone the documentation)
# Developping
@@ -22,9 +23,6 @@ Run `npm ci`
Run `npm run dev`
-
-
-
# Deploy
Run `npm ci`
@@ -72,4 +70,35 @@ bun run http.js
The web server will be running at `http://localhost:5000`
-Configure the file `.env.development` with the url
\ No newline at end of file
+Configure the file `.env.development` with the url
+
+# Recommanded tools
+
+- [VSCode](https://code.visualstudio.com/)
+- [React DevTools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi)
+- [vscode-tailwindcss](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)
+- [vscode-eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
+
+# Setup debuggin with chrome
+
+Inside `.vscode/settings.json`, set the following :
+
+```json
+{
+ // Use IntelliSense to learn about possible attributes.
+ // Hover to view descriptions of existing attributes.
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+ "version": "0.2.0",
+ "configurations": [
+ {
+ "type": "chrome",
+ "request": "launch",
+ "name": "Launch Chrome against localhost",
+ "url": "http://localhost:5173",
+ "webRoot": "${workspaceFolder}",
+ }
+ ]
+}
+```
+
+Change the `url` to the dev server url. Set the `runtimeExecutable` to you favorite chromium browser.
\ No newline at end of file
diff --git a/src/Components/API/api.ts b/src/Components/API/api.ts
index 510428d..6a43c72 100644
--- a/src/Components/API/api.ts
+++ b/src/Components/API/api.ts
@@ -1,5 +1,4 @@
import { IConfiguration } from '../../Interfaces/IConfiguration';
-import { IHistoryState } from '../../Interfaces/IHistoryState';
import { ISetContainerListRequest } from '../../Interfaces/ISetContainerListRequest';
import { ISetContainerListResponse } from '../../Interfaces/ISetContainerListResponse';
import { GetCircularReplacer } from '../../utils/saveload';
@@ -43,6 +42,7 @@ export async function SetContainerList(request: ISetContainerListRequest): Promi
return await fetch(url, {
method: 'POST',
headers: new Headers({
+ // eslint-disable-next-line @typescript-eslint/naming-convention
'Content-Type': 'application/json'
}),
body: dataParsed
diff --git a/src/Components/App/App.scss b/src/Components/App/App.scss
deleted file mode 100644
index e69de29..0000000
diff --git a/src/Components/App/App.tsx b/src/Components/App/App.tsx
index b0a2374..3b1771b 100644
--- a/src/Components/App/App.tsx
+++ b/src/Components/App/App.tsx
@@ -1,5 +1,4 @@
import React, { Dispatch, SetStateAction, useEffect, useState } from 'react';
-import './App.scss';
import { MainMenu } from '../MainMenu/MainMenu';
import { ContainerModel } from '../../Interfaces/IContainerModel';
import { Editor } from '../Editor/Editor';
@@ -78,7 +77,7 @@ export function App(props: IAppProps): JSX.Element {
}
return (
-
+
NewEditor(
setEditorState, setLoaded
diff --git a/src/Components/Bar/Bar.tsx b/src/Components/Bar/Bar.tsx
index a8ed605..7125f30 100644
--- a/src/Components/Bar/Bar.tsx
+++ b/src/Components/Bar/Bar.tsx
@@ -16,7 +16,7 @@ export const BAR_WIDTH = 64; // 4rem
export function Bar(props: IBarProps): JSX.Element {
return (
-
+
+
props.onChange('linkedSymbolId', event.target.value)} />
{GetCSSInputs(props.properties, props.onChange)}
+ {
+ SHOW_SELF_DIMENSIONS &&
+ props.onChange('showSelfDimensions', event.target.checked)} />
+ }
+ {
+ SHOW_CHILDREN_DIMENSIONS &&
+ props.onChange('showChildrenDimensions', event.target.checked)} />
+ }
+ {
+ SHOW_BORROWER_DIMENSIONS &&
+ <>
+ props.onChange('markPositionToDimensionBorrower', event.target.checked)} />
+ props.onChange('isDimensionBorrower', event.target.checked)} />
+ >
+ }
);
}
diff --git a/src/Components/Editor/Actions/ContainerOperations.ts b/src/Components/Editor/Actions/ContainerOperations.ts
index b1d24a9..d0dc7e4 100644
--- a/src/Components/Editor/Actions/ContainerOperations.ts
+++ b/src/Components/Editor/Actions/ContainerOperations.ts
@@ -276,6 +276,9 @@ export function AddContainers(
parentClone.children.splice(index, 0, newContainer);
}
+ // Sort the parent children by x
+ UpdateParentChildrenList(parentClone);
+
/// Handle behaviors here ///
// Initialize default children of the container
@@ -287,9 +290,6 @@ export function AddContainers(
// Then, apply the behaviors on its siblings (mostly for flex)
ApplyBehaviorsOnSiblingsChildren(newContainer, current.symbols);
- // Sort the parent children by x
- UpdateParentChildrenList(parentClone);
-
// Add to the list of container id for logging purpose
containerIds.push(newContainer.properties.id);
});
diff --git a/src/Components/Editor/Actions/ContextMenuActions.ts b/src/Components/Editor/Actions/ContextMenuActions.ts
index 260ce73..64f37fc 100644
--- a/src/Components/Editor/Actions/ContextMenuActions.ts
+++ b/src/Components/Editor/Actions/ContextMenuActions.ts
@@ -105,27 +105,30 @@ function HandleReplace(
const index = selectedContainer.parent.children.indexOf(selectedContainer);
const types = response.Containers.map(container => container.Type);
- const newHistoryBeforeDelete = AddContainers(
- index + 1,
- types,
- selectedContainer.properties.parentId,
- configuration,
+
+ const newHistoryAfterDelete = DeleteContainer(
+ selectedContainer.properties.id,
history,
historyCurrentStep
);
- const newHistoryAfterDelete = DeleteContainer(
- selectedContainer.properties.id,
- newHistoryBeforeDelete,
- newHistoryBeforeDelete.length - 1
+ const newHistoryBeforeDelete = AddContainers(
+ index,
+ types,
+ selectedContainer.properties.parentId,
+ configuration,
+ newHistoryAfterDelete,
+ newHistoryAfterDelete.length - 1
);
// Remove AddContainers from history
- newHistoryAfterDelete.splice(newHistoryAfterDelete.length - 2, 1);
+ if (import.meta.env.PROD) {
+ newHistoryBeforeDelete.splice(newHistoryBeforeDelete.length - 2, 1);
+ }
// Rename the last action by Replace
- newHistoryAfterDelete[newHistoryAfterDelete.length - 1].lastAction =
+ newHistoryBeforeDelete[newHistoryBeforeDelete.length - 1].lastAction =
`Replace ${selectedContainer.properties.id} by [${types.join(', ')}]`;
- return newHistoryAfterDelete;
+ return newHistoryBeforeDelete;
}
diff --git a/src/Components/Editor/Behaviors/Behaviors.ts b/src/Components/Editor/Behaviors/Behaviors.ts
index 7dfc78a..116917b 100644
--- a/src/Components/Editor/Behaviors/Behaviors.ts
+++ b/src/Components/Editor/Behaviors/Behaviors.ts
@@ -1,6 +1,6 @@
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { ISymbolModel } from '../../../Interfaces/ISymbolModel';
-import { APPLY_BEHAVIORS_ON_CHILDREN } from '../../../utils/default';
+import { APPLY_BEHAVIORS_ON_CHILDREN, ENABLE_RIGID, ENABLE_SWAP } from '../../../utils/default';
import { ApplyAnchor } from './AnchorBehaviors';
import { Flex } from './FlexBehaviors';
import { ApplyRigidBody } from './RigidBodyBehaviors';
@@ -23,11 +23,15 @@ export function ApplyBehaviors(container: IContainerModel, symbols: Map sibling.properties.minWidth);
@@ -50,12 +54,8 @@ function FlexGroup(flexibleGroup: IFlexibleGroup): void {
const checkSumMinWidthsIsFitting = minimumPossibleWidth > requiredMaxWidth;
if (checkSumMinWidthsIsFitting) {
- Swal.fire({
- icon: 'error',
- title: 'Cannot fit!',
- text: 'Cannot fit at all even when squeezing all flex containers to the minimum.'
- });
- throw new Error('[FlexBehavior] Cannot fit at all even when squeezing all flex containers to the minimum.');
+ console.warn('[FlexBehavior] Cannot fit at all even when squeezing all flex containers to the minimum.');
+ return;
}
const maxMinWidths = Math.max(...minWidths);
diff --git a/src/Components/Editor/Behaviors/RigidBodyBehaviors.ts b/src/Components/Editor/Behaviors/RigidBodyBehaviors.ts
index bdf2e71..90e4ac9 100644
--- a/src/Components/Editor/Behaviors/RigidBodyBehaviors.ts
+++ b/src/Components/Editor/Behaviors/RigidBodyBehaviors.ts
@@ -9,6 +9,7 @@
import Swal from 'sweetalert2';
import { IContainerModel } from '../../../Interfaces/IContainerModel';
import { ISizePointer } from '../../../Interfaces/ISizePointer';
+import { ENABLE_HARD_RIGID } from '../../../utils/default';
/**
* "Transform the container into a rigid body"
@@ -23,7 +24,11 @@ export function ApplyRigidBody(
container: IContainerModel
): IContainerModel {
container = ConstraintBodyInsideParent(container);
- container = ConstraintBodyInsideUnallocatedWidth(container);
+
+ if (ENABLE_HARD_RIGID) {
+ container = ConstraintBodyInsideUnallocatedWidth(container);
+ }
+
return container;
}
diff --git a/src/Components/InputGroup/InputGroup.tsx b/src/Components/InputGroup/InputGroup.tsx
index 8bb83f6..68b5910 100644
--- a/src/Components/InputGroup/InputGroup.tsx
+++ b/src/Components/InputGroup/InputGroup.tsx
@@ -17,12 +17,7 @@ interface IInputGroupProps {
onChange?: (event: React.ChangeEvent) => void
}
-const className = `
- w-full
- text-xs font-medium transition-all text-gray-800 mt-1 px-3 py-2
- bg-white border-2 border-white rounded-lg placeholder-gray-800
- focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500
- disabled:bg-slate-300 disabled:text-gray-500 disabled:border-slate-300 disabled:shadow-none`;
+const className = 'input-group';
export function InputGroup(props: IInputGroupProps): JSX.Element {
return <>
diff --git a/src/index.scss b/src/index.scss
index c9b1963..4237259 100644
--- a/src/index.scss
+++ b/src/index.scss
@@ -18,7 +18,6 @@
.elements-sidebar-row {
@apply pl-6 pr-6 pt-2 pb-2 w-full
}
-
.symbols-sidebar-row {
@apply elements-sidebar-row
}
@@ -27,6 +26,10 @@
@apply transition-all w-full h-auto p-4 flex
}
+ .mainmenu-bg {
+ @apply bg-blue-100 h-full w-full
+ }
+
.mainmenu-btn {
@apply transition-all bg-blue-100 hover:bg-blue-200 text-blue-700 text-lg font-semibold p-8 rounded-lg
}
@@ -42,7 +45,13 @@
}
.floating-btn {
- @apply h-full w-full text-white align-middle items-center justify-center
+ @apply h-full w-full text-white align-middle
+ items-center justify-center
+ }
+
+ .bar {
+ @apply fixed z-20 flex flex-col top-0 left-0
+ h-full w-16 bg-slate-100
}
.bar-btn {
@@ -64,10 +73,18 @@
text-gray-800 bg-slate-100
dark:text-white dark:bg-gray-800
text-xs font-bold
- transition-all duration-100 scale-0 origin-left;
+ transition-all duration-100 scale-0 origin-left
}
.contextmenu-item {
@apply px-2 py-1 hover:bg-slate-300 text-left
}
+
+ .input-group {
+ @apply w-full
+ text-xs font-medium transition-all text-gray-800 mt-1 px-3 py-2
+ bg-white border-2 border-white rounded-lg placeholder-gray-800
+ focus:outline-none focus:border-blue-500 focus:ring-1 focus:ring-blue-500
+ disabled:bg-slate-300 disabled:text-gray-500 disabled:border-slate-300 disabled:shadow-none;
+ }
}
\ No newline at end of file
diff --git a/src/main.tsx b/src/main.tsx
index 264c622..21c0771 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -11,7 +11,10 @@ function RenderRoot(root: Element | Document): void {
);
}
+// Specific for Modeler apps
+// eslint-disable-next-line @typescript-eslint/no-namespace
namespace SVGLayoutDesigner {
+ // eslint-disable-next-line @typescript-eslint/naming-convention
export const Render = RenderRoot;
}
diff --git a/src/utils/default.ts b/src/utils/default.ts
index 5af68aa..0488fe4 100644
--- a/src/utils/default.ts
+++ b/src/utils/default.ts
@@ -9,6 +9,19 @@ import { ISymbolModel } from '../Interfaces/ISymbolModel';
/// CONTAINER DEFAULTS ///
+/** Enable the swap behavior */
+export const ENABLE_SWAP = false;
+
+/** Enable the rigid behavior */
+export const ENABLE_RIGID = true;
+
+/**
+ * Enable the hard rigid behavior
+ * disallowing the container to overlap (ENABLE_RIGID must be true)
+ */
+export const ENABLE_HARD_RIGID = false;
+
+/** Enalbe the text in the containers */
export const SHOW_TEXT = false;
export const SHOW_SELECTOR_TEXT = true;
export const DEFAULTCHILDTYPE_ALLOW_CYCLIC = false;
diff --git a/test-server/http.js b/test-server/http.js
index 4c84bfd..be800ae 100644
--- a/test-server/http.js
+++ b/test-server/http.js
@@ -55,6 +55,7 @@ const GetSVGLayoutConfiguration = () => {
Type: 'Chassis',
MaxWidth: 500,
MinWidth: 200,
+ Width: 200,
DefaultChildType: 'Trou',
Style: {
fillOpacity: 1,
@@ -63,7 +64,7 @@ const GetSVGLayoutConfiguration = () => {
fill: '#d3c9b7',
},
ShowSelfDimensions: true,
- IsDimensionBorrower: true
+ IsDimensionBorrower: true,
},
{
Type: 'Trou',