Add minWidth to containers (default 1) and forms
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing

This commit is contained in:
Eric NGUYEN 2022-08-17 17:13:12 +02:00
parent f0c1803e10
commit 3dd3768137
9 changed files with 45 additions and 24 deletions

View file

@ -5,6 +5,7 @@ import { fetchConfiguration } from '../API/api';
import { IEditorState } from '../../Interfaces/IEditorState'; import { IEditorState } from '../../Interfaces/IEditorState';
import { LoadState } from './Load'; import { LoadState } from './Load';
import { XPositionReference } from '../../Enums/XPositionReference'; import { XPositionReference } from '../../Enums/XPositionReference';
import { DEFAULT_MAINCONTAINER_PROPS } from '../../utils/default';
export function NewEditor( export function NewEditor(
setEditorState: Dispatch<SetStateAction<IEditorState>>, setEditorState: Dispatch<SetStateAction<IEditorState>>,
@ -17,19 +18,9 @@ export function NewEditor(
const MainContainer = new ContainerModel( const MainContainer = new ContainerModel(
null, null,
{ {
id: 'main', ...DEFAULT_MAINCONTAINER_PROPS,
parentId: 'null',
x: 0,
y: 0,
width: Number(configuration.MainContainer.Width), width: Number(configuration.MainContainer.Width),
height: Number(configuration.MainContainer.Height), height: Number(configuration.MainContainer.Height)
isRigidBody: false,
isAnchor: false,
XPositionReference: XPositionReference.Left,
style: {
fillOpacity: 0,
stroke: 'black'
}
} }
); );

View file

@ -164,9 +164,6 @@ export function constraintBodyInsideUnallocatedWidth(
// We want the container to fit automatically inside the available space // We want the container to fit automatically inside the available space
// even if it means to resize the container // even if it means to resize the container
const availableWidth: ISizePointer | undefined = availableWidths.find((width) => { const availableWidth: ISizePointer | undefined = availableWidths.find((width) => {
if (container.properties.minWidth === undefined) {
return true;
}
return isFitting(container.properties.minWidth, width); return isFitting(container.properties.minWidth, width);
}); });

View file

@ -18,6 +18,7 @@ describe.concurrent('Elements sidebar', () => {
y: 0, y: 0,
width: 2000, width: 2000,
height: 100, height: 100,
minWidth: 1,
XPositionReference: XPositionReference.Left, XPositionReference: XPositionReference.Left,
isRigidBody: false, isRigidBody: false,
isAnchor: false isAnchor: false
@ -50,6 +51,7 @@ describe.concurrent('Elements sidebar', () => {
y: 0, y: 0,
width: 2000, width: 2000,
height: 100, height: 100,
minWidth: 1,
isRigidBody: false, isRigidBody: false,
isAnchor: false, isAnchor: false,
XPositionReference: XPositionReference.Left XPositionReference: XPositionReference.Left
@ -106,6 +108,7 @@ describe.concurrent('Elements sidebar', () => {
parentId: '', parentId: '',
x: 0, x: 0,
y: 0, y: 0,
minWidth: 1,
width: 2000, width: 2000,
height: 100, height: 100,
XPositionReference: XPositionReference.Left, XPositionReference: XPositionReference.Left,
@ -124,6 +127,7 @@ describe.concurrent('Elements sidebar', () => {
parentId: 'main', parentId: 'main',
x: 0, x: 0,
y: 0, y: 0,
minWidth: 1,
width: 0, width: 0,
height: 0, height: 0,
isRigidBody: false, isRigidBody: false,
@ -143,6 +147,7 @@ describe.concurrent('Elements sidebar', () => {
parentId: 'main', parentId: 'main',
x: 0, x: 0,
y: 0, y: 0,
minWidth: 1,
width: 0, width: 0,
height: 0, height: 0,
XPositionReference: XPositionReference.Left, XPositionReference: XPositionReference.Left,
@ -182,6 +187,7 @@ describe.concurrent('Elements sidebar', () => {
parentId: '', parentId: '',
x: 0, x: 0,
y: 0, y: 0,
minWidth: 1,
width: 2000, width: 2000,
height: 100, height: 100,
XPositionReference: XPositionReference.Left, XPositionReference: XPositionReference.Left,
@ -199,6 +205,7 @@ describe.concurrent('Elements sidebar', () => {
parentId: 'main', parentId: 'main',
x: 0, x: 0,
y: 0, y: 0,
minWidth: 1,
width: 0, width: 0,
height: 0, height: 0,
XPositionReference: XPositionReference.Left, XPositionReference: XPositionReference.Left,

View file

@ -11,6 +11,7 @@ interface IInputGroupProps {
checked?: boolean checked?: boolean
defaultValue?: string defaultValue?: string
defaultChecked?: boolean defaultChecked?: boolean
min?: number
isDisabled?: boolean isDisabled?: boolean
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void
} }
@ -42,6 +43,7 @@ export const InputGroup: React.FunctionComponent<IInputGroupProps> = (props) =>
checked={props.checked} checked={props.checked}
defaultChecked={props.defaultChecked} defaultChecked={props.defaultChecked}
onChange={props.onChange} onChange={props.onChange}
min={props.min}
disabled={props.isDisabled} disabled={props.isDisabled}
/> />
</>; </>;

View file

@ -70,12 +70,23 @@ const DynamicForm: React.FunctionComponent<IDynamicFormProps> = (props) => {
value={props.properties.y.toString()} value={props.properties.y.toString()}
onChange={(event) => props.onChange('y', Number(event.target.value))} onChange={(event) => props.onChange('y', Number(event.target.value))}
/> />
<InputGroup
labelText='Minimum width'
inputKey='minWidth'
labelClassName=''
inputClassName=''
type='number'
min={1}
value={props.properties.minWidth.toString()}
onChange={(event) => props.onChange('minWidth', Number(event.target.value))}
/>
<InputGroup <InputGroup
labelText='Width' labelText='Width'
inputKey='width' inputKey='width'
labelClassName='' labelClassName=''
inputClassName='' inputClassName=''
type='number' type='number'
min={props.properties.minWidth}
value={props.properties.width.toString()} value={props.properties.width.toString()}
onChange={(event) => props.onChange('width', Number(event.target.value))} onChange={(event) => props.onChange('width', Number(event.target.value))}
/> />
@ -85,6 +96,7 @@ const DynamicForm: React.FunctionComponent<IDynamicFormProps> = (props) => {
labelClassName='' labelClassName=''
inputClassName='' inputClassName=''
type='number' type='number'
min={0}
value={props.properties.height.toString()} value={props.properties.height.toString()}
onChange={(event) => props.onChange('height', Number(event.target.value))} onChange={(event) => props.onChange('height', Number(event.target.value))}
/> />

View file

@ -27,6 +27,7 @@ describe.concurrent('Properties', () => {
y: 1, y: 1,
width: 1, width: 1,
height: 1, height: 1,
minWidth: 1,
XPositionReference: XPositionReference.Left, XPositionReference: XPositionReference.Left,
isRigidBody: false, isRigidBody: false,
isAnchor: false isAnchor: false

View file

@ -68,12 +68,22 @@ const StaticForm: React.FunctionComponent<IStaticFormProps> = (props) => {
type='number' type='number'
defaultValue={props.properties.y.toString()} defaultValue={props.properties.y.toString()}
/> />
<InputGroup
labelText='Minimum width'
inputKey='minWidth'
labelClassName=''
inputClassName=''
type='number'
min={0}
defaultValue={props.properties.minWidth.toString()}
/>
<InputGroup <InputGroup
labelText='Width' labelText='Width'
inputKey='width' inputKey='width'
labelClassName='' labelClassName=''
inputClassName='' inputClassName=''
type='number' type='number'
min={props.properties.minWidth}
defaultValue={props.properties.width.toString()} defaultValue={props.properties.width.toString()}
/> />
<InputGroup <InputGroup
@ -82,6 +92,7 @@ const StaticForm: React.FunctionComponent<IStaticFormProps> = (props) => {
labelClassName='' labelClassName=''
inputClassName='' inputClassName=''
type='number' type='number'
min={1}
defaultValue={props.properties.height.toString()} defaultValue={props.properties.height.toString()}
/> />
<InputGroup <InputGroup

View file

@ -17,6 +17,13 @@ export default interface IProperties {
/** vertical offset */ /** vertical offset */
y: number y: number
/**
* Minimum width (min=1)
* Allows the container to set isRigidBody to false when it gets squeezed
* by an anchor
*/
minWidth: number
/** width */ /** width */
width: number width: number
@ -32,14 +39,6 @@ export default interface IProperties {
/** Horizontal alignment, also determines the visual location of x {Left = 0, Center, Right } */ /** Horizontal alignment, also determines the visual location of x {Left = 0, Center, Right } */
XPositionReference: XPositionReference XPositionReference: XPositionReference
/**
* (optional)
* Minimum width used when isRigidBody = true.
* Allows the container to set isRigidBody to false when it gets squeezed
* by an anchor
*/
minWidth?: number
/** /**
* (optional) * (optional)
* Replace a <rect> by a customized "SVG". It is not really an svg but it at least allows * Replace a <rect> by a customized "SVG". It is not really an svg but it at least allows

View file

@ -33,6 +33,7 @@ export const DEFAULT_MAINCONTAINER_PROPS: IProperties = {
parentId: 'null', parentId: 'null',
x: 0, x: 0,
y: 0, y: 0,
minWidth: 1,
width: Number(DEFAULT_CONFIG.MainContainer.Width), width: Number(DEFAULT_CONFIG.MainContainer.Width),
height: Number(DEFAULT_CONFIG.MainContainer.Height), height: Number(DEFAULT_CONFIG.MainContainer.Height),
isRigidBody: false, isRigidBody: false,
@ -61,7 +62,7 @@ export const GetDefaultContainerProps = (
isRigidBody: false, isRigidBody: false,
isAnchor: false, isAnchor: false,
XPositionReference: containerConfig.XPositionReference ?? XPositionReference.Left, XPositionReference: containerConfig.XPositionReference ?? XPositionReference.Left,
minWidth: containerConfig.MinWidth, minWidth: containerConfig.MinWidth ?? 0,
customSVG: containerConfig.CustomSVG, customSVG: containerConfig.CustomSVG,
style: containerConfig.Style, style: containerConfig.Style,
userData: containerConfig.UserData userData: containerConfig.UserData