svg-layout-designer-react/src/Components/ContainerProperties/ContainerForm.tsx
2023-02-14 10:15:12 +01:00

595 lines
25 KiB
TypeScript

import * as React from 'react';
import { PropertyType } from '../../Enums/PropertyType';
import { type IContainerProperties } from '../../Interfaces/IContainerProperties';
import { type ISymbolModel } from '../../Interfaces/ISymbolModel';
import {
SHOW_BORROWER_DIMENSIONS,
SHOW_CHILDREN_DIMENSIONS,
SHOW_SELF_DIMENSIONS, SHOW_SELF_MARGINS_DIMENSIONS
} from '../../utils/default';
import {
ApplyWidthMargin,
ApplyXMargin,
RemoveWidthMargin,
RemoveXMargin,
RestoreX,
RestoreY,
TransformX,
TransformY
} from '../../utils/svg';
import { Text } from '../Text/Text';
import { InputGroup } from '../InputGroup/InputGroup';
import { TextInputGroup } from '../InputGroup/TextInputGroup';
import { Select } from '../Select/Select';
import { ToggleButton, ToggleType } from '../ToggleButton/ToggleButton';
import { PositionReferenceSelector } from '../RadioGroupButtons/PositionReferenceSelector';
import { OrientationSelector } from '../RadioGroupButtons/OrientationSelector';
import { OrientationCheckboxes } from '../CheckboxGroupButtons/OrientationCheckboxes';
import { PositionCheckboxes } from '../CheckboxGroupButtons/PositionCheckboxes';
import { Category } from '../Category/Category';
interface IContainerFormProps {
properties: IContainerProperties
symbols: Map<string, ISymbolModel>
onChange: (key: string, value: string | number | boolean | number[], type?: PropertyType) => void
}
export function ContainerForm(props: IContainerFormProps): JSX.Element {
const categoryHeight = 'h-11';
return (
<div className='grid grid-cols-1 gap-y-4 items-center'>
<TextInputGroup
id={`${props.properties.id}-displayedText`}
labelText={Text({ textId: '@ContainerDisplayedText' })}
inputKey='displayedText'
labelClassName=''
inputClassName=''
type='string'
value={props.properties.displayedText?.toString()}
onChange={(value) => { props.onChange('displayedText', value); }}/>
<OrientationSelector
id='orientation'
name='Orientation'
labelText={Text({ textId: '@ContainerOrientation' })}
value={props.properties.orientation}
onChange={props.onChange}
/>
<Category
category={{
Type: 'Properties',
DisplayedText: Text({ textId: '@ContainerProperties' })
}}
heightClass={`${categoryHeight}`}
>
<div className='grid grid-cols-1 gap-y-6 items-center prop-category-body'>
<div>
<InputGroup
labelText={Text({ textId: '@ContainerName' })}
inputKey='id'
labelClassName=''
inputClassName=''
type='string'
value={props.properties.id.toString()}
isDisabled={true}/>
</div>
<div>
<InputGroup
labelText={Text({ textId: '@ContainerParentName' })}
inputKey='parentId'
labelClassName=''
inputClassName=''
type='string'
value={props.properties.parentId}
isDisabled={true}/>
</div>
<div>
<InputGroup
labelText={Text({ textId: '@ContainerType' })}
inputKey='type'
labelClassName=''
inputClassName=''
type='string'
value={props.properties.type}
isDisabled={true}/>
</div>
</div>
</Category>
<Category category={{
Type: 'Position',
DisplayedText: Text({ textId: '@ContainerPosition' })
}}
defaultIsOpen={true}
heightClass={`${categoryHeight}`}
>
<div className='grid grid-cols-3 gap-y-2 items-center prop-category-body'>
<TextInputGroup
id={`${props.properties.id}-x`}
labelText={Text({ textId: '@ContainerX' })}
inputKey='x'
labelClassName=''
inputClassName='col-span-2'
type='number'
isDisabled={props.properties.linkedSymbolId !== ''}
value={TransformX(
RemoveXMargin(props.properties.x, props.properties.margin.left),
props.properties.width,
props.properties.positionReference
).toString()}
onChange={(value) => {
props.onChange(
'x',
ApplyXMargin(
RestoreX(
Number(value),
props.properties.width,
props.properties.positionReference
),
props.properties.margin.left
)
);
}}/>
<TextInputGroup
id={`${props.properties.id}-y`}
labelText={Text({ textId: '@ContainerY' })}
inputKey='y'
labelClassName=''
inputClassName='col-span-2'
type='number'
value={TransformY(
RemoveXMargin(props.properties.y, props.properties.margin.top),
props.properties.height,
props.properties.positionReference
).toString()}
onChange={(value) => {
props.onChange(
'y',
ApplyXMargin(
RestoreY(
Number(value),
props.properties.height,
props.properties.positionReference
),
props.properties.margin.top
)
);
}}/>
</div>
</Category>
<Category
category={{
Type: 'Size',
DisplayedText: Text({ textId: '@ContainerSize' })
}}
heightClass={`${categoryHeight}`}
>
<div className='grid grid-cols-5 gap-y-2 items-center prop-category-body'>
<TextInputGroup
id={`${props.properties.id}-minWidth`}
labelText={Text({ textId: '@ContainerMinWidth' })}
inputKey='minWidth'
labelClassName='col-span-2'
inputClassName='col-span-3'
type='number'
min={1}
value={props.properties.minWidth.toString()}
onChange={(value) => { props.onChange('minWidth', Number(value)); }}/>
<TextInputGroup
id={`${props.properties.id}-width`}
labelText={Text({ textId: '@ContainerWidth' })}
inputKey='width'
labelClassName='col-span-2'
inputClassName='col-span-3'
type='number'
min={props.properties.minWidth}
max={props.properties.maxWidth}
value={(RemoveWidthMargin(props.properties.width, props.properties.margin.left, props.properties.margin.right)).toString()}
onChange={(value) => { props.onChange('width', ApplyWidthMargin(Number(value), props.properties.margin.left, props.properties.margin.right)); }}
isDisabled={props.properties.isFlex}/>
<TextInputGroup
id={`${props.properties.id}-maxWidth`}
labelText={Text({ textId: '@ContainerMaxWidth' })}
inputKey='maxWidth'
labelClassName='col-span-2'
inputClassName='col-span-3'
type='number'
min={1}
value={props.properties.maxWidth.toString()}
onChange={(value) => { props.onChange('maxWidth', Number(value)); }}/>
<div className='col-span-5 p-3'></div>
<TextInputGroup
id={`${props.properties.id}-minHeight`}
labelText={Text({ textId: '@ContainerMinHeight' })}
inputKey='minHeight'
labelClassName='col-span-2'
inputClassName='col-span-3'
type='number'
min={1}
value={props.properties.minHeight.toString()}
onChange={(value) => { props.onChange('minHeight', Number(value)); }}/>
<TextInputGroup
id={`${props.properties.id}-height`}
labelText={Text({ textId: '@ContainerHeight' })}
inputKey='height'
labelClassName='col-span-2'
inputClassName='col-span-3'
type='number'
min={props.properties.minHeight}
max={props.properties.maxHeight}
value={(RemoveWidthMargin(props.properties.height, props.properties.margin.top, props.properties.margin.bottom)).toString()}
onChange={(value) => { props.onChange('height', ApplyWidthMargin(Number(value), props.properties.margin.top, props.properties.margin.bottom)); }}
isDisabled={props.properties.isFlex}
/>
<TextInputGroup
id={`${props.properties.id}-maxHeight`}
labelText={Text({ textId: '@ContainerMaxHeight' })}
inputKey='maxHeight'
labelClassName='col-span-2'
inputClassName='col-span-3'
type='number'
min={1}
value={props.properties.maxHeight.toString()}
onChange={(value) => { props.onChange('maxHeight', Number(value)); }}/>
</div>
</Category>
<Category category={{
Type: 'Margins',
DisplayedText: Text({ textId: '@ContainerMargins' })
}}
heightClass={`${categoryHeight}`}
>
<div className='grid grid-cols-2 items-center gap-y-2 prop-category-body'>
<TextInputGroup
id={`${props.properties.id}-ml`}
labelText={Text({ textId: '@ContainerMarginLeft' })}
inputKey='left'
labelClassName=''
inputClassName=''
type='number'
min={0}
value={(props.properties.margin.left ?? 0).toString()}
onChange={(value) => { props.onChange('left', Number(value), PropertyType.Margin); }}/>
<TextInputGroup
id={`${props.properties.id}-mb`}
labelText={Text({ textId: '@ContainerMarginBottom' })}
inputKey='bottom'
labelClassName=''
inputClassName=''
type='number'
min={0}
value={(props.properties.margin.bottom ?? 0).toString()}
onChange={(value) => { props.onChange('bottom', Number(value), PropertyType.Margin); }}/>
<TextInputGroup
id={`${props.properties.id}-mt`}
labelText={Text({ textId: '@ContainerMarginTop' })}
inputKey='top'
labelClassName=''
inputClassName=''
type='number'
min={0}
value={(props.properties.margin.top ?? 0).toString()}
onChange={(value) => { props.onChange('top', Number(value), PropertyType.Margin); }}/>
<TextInputGroup
id={`${props.properties.id}-mr`}
labelText={Text({ textId: '@ContainerMarginRight' })}
inputKey='right'
labelClassName=''
inputClassName=''
type='number'
min={0}
value={(props.properties.margin.right ?? 0).toString()}
onChange={(value) => { props.onChange('right', Number(value), PropertyType.Margin); }}/>
</div>
</Category>
<Category category={{
Type: 'Behaviors',
DisplayedText: Text({ textId: '@ContainerBehaviors' })
}}
heightClass={`${categoryHeight}`}
>
<div className='grid grid-cols-2 items-center gap-y-2 prop-category-body'>
<ToggleButton
labelText={Text({ textId: '@ContainerFlex' })}
inputKey='isFlex'
labelClassName=''
inputClassName='ml-auto mr-auto block'
type={ToggleType.Full}
checked={props.properties.isFlex}
onChange={(event) => { props.onChange('isFlex', event.target.checked); }}
/>
<ToggleButton
labelText={Text({ textId: '@ContainerAnchor' })}
inputKey='isAnchor'
labelClassName=''
inputClassName='ml-auto mr-auto block'
type={ToggleType.Full}
checked={props.properties.isAnchor}
onChange={(event) => { props.onChange('isAnchor', event.target.checked); }}/>
</div>
</Category>
<Category category={{
Type: 'Alignment',
DisplayedText: Text({ textId: '@ContainerAlignment' })
}}
heightClass={`${categoryHeight}`}
>
<div className='prop-category-body'>
<PositionReferenceSelector
id='positionReference'
name='PositionReference'
labelText={Text({ textId: '@ContainerAlignmentInput' })}
value={props.properties.positionReference}
onChange={props.onChange}
/>
<div className='p-3'></div>
<Select
inputKey='linkedSymbolId'
labelText={Text({ textId: '@ContainerAlignWithSymbol' })}
labelClassName=''
inputClassName=''
inputs={[...props.symbols.values()].map(symbol => ({
key: symbol.id,
text: symbol.id,
value: symbol.id
}))}
value={props.properties.linkedSymbolId ?? ''}
onChange={(event) => { props.onChange('linkedSymbolId', event.target.value); }}/>
</div>
</Category>
<Category category={{
Type: 'Dimensions',
DisplayedText: Text({ textId: '@ContainerDimensions' })
}}
heightClass={`${categoryHeight}`}
>
<div className='grid grid-cols-1 gap-6 prop-category-body'>
{
SHOW_SELF_DIMENSIONS &&
<div className='grid grid-cols-1 gap-2'>
<PositionCheckboxes
id='positionsSelfDimensions'
attribute='positions'
name='ShowSelfDimensions'
labelText={Text({ textId: '@ContainerShowDimension' })}
value={props.properties.dimensionOptions.selfDimensions.positions}
onChange={(key, value) => { props.onChange(key, value, PropertyType.SelfDimension); }}
/>
<InputGroup
labelText={Text({ textId: '@StyleStrokeColor' })}
inputKey='color'
labelClassName=''
inputClassName=''
type='color'
value={props.properties.dimensionOptions.selfDimensions.color}
onChange={(e) => { props.onChange('color', e.target.value, PropertyType.SelfDimension); }}/>
<TextInputGroup
id={`${props.properties.id}-selfDimensions-width`}
labelText={Text({ textId: '@StyleStrokeWidth' })}
inputKey='width'
labelClassName=''
inputClassName=''
type='number'
min={0}
value={(props.properties.dimensionOptions.selfDimensions.width ?? 0).toString()}
onChange={(value) => { props.onChange('width', Number(value), PropertyType.SelfDimension); }}/>
<TextInputGroup
id={`${props.properties.id}-selfDimensions-dasharray`}
labelText={Text({ textId: '@StyleStrokeDashArray' })}
inputKey='dashArray'
labelClassName=''
inputClassName=''
type='text'
value={props.properties.dimensionOptions.selfDimensions.dashArray ?? ''}
onChange={(value) => { props.onChange('dashArray', value, PropertyType.SelfDimension); }}/>
</div>
}
{
SHOW_SELF_MARGINS_DIMENSIONS &&
<div className='grid grid-cols-1 gap-2'>
<PositionCheckboxes
id='positionsSelfMarginsDimensions'
attribute='positions'
name='ShowSelfMarginsDimensions'
labelText={Text({ textId: '@ContainerShowMarginsDimension' })}
value={props.properties.dimensionOptions.selfMarginsDimensions.positions}
onChange={(key, value) => { props.onChange(key, value, PropertyType.SelfMarginDimension); }}
/>
<InputGroup
labelText={Text({ textId: '@StyleStrokeColor' })}
inputKey='color'
labelClassName=''
inputClassName=''
type='color'
value={props.properties.dimensionOptions.selfMarginsDimensions.color}
onChange={(e) => { props.onChange('color', e.target.value, PropertyType.SelfMarginDimension); }}/>
<TextInputGroup
id={`${props.properties.id}-selfMarginsDimensions-width`}
labelText={Text({ textId: '@StyleStrokeWidth' })}
inputKey='width'
labelClassName=''
inputClassName=''
type='number'
min={0}
value={(props.properties.dimensionOptions.selfMarginsDimensions.width ?? 0).toString()}
onChange={(value) => { props.onChange('width', Number(value), PropertyType.SelfMarginDimension); }}/>
<TextInputGroup
id={`${props.properties.id}-selfMarginsDimensions-dasharray`}
labelText={Text({ textId: '@StyleStrokeDashArray' })}
inputKey='dashArray'
labelClassName=''
inputClassName=''
type='text'
value={props.properties.dimensionOptions.selfMarginsDimensions.dashArray ?? ''}
onChange={(value) => { props.onChange('dashArray', value, PropertyType.SelfMarginDimension); }}/>
</div>
}
{
SHOW_CHILDREN_DIMENSIONS &&
<div className='grid grid-cols-1 gap-2'>
<PositionCheckboxes
id='positionsChildrenDimensions'
attribute='positions'
name='ShowChildrenDimensions'
labelText={Text({ textId: '@ContainerShowChildrenDimension' })}
value={props.properties.dimensionOptions.childrenDimensions.positions}
onChange={(key, value) => { props.onChange(key, value, PropertyType.ChildrenDimensions); }}
/>
<InputGroup
labelText={Text({ textId: '@StyleStrokeColor' })}
inputKey='color'
labelClassName=''
inputClassName=''
type='color'
value={props.properties.dimensionOptions.childrenDimensions.color}
onChange={(e) => { props.onChange('color', e.target.value, PropertyType.ChildrenDimensions); }}/>
<TextInputGroup
id={`${props.properties.id}-childrenDimensions-width`}
labelText={Text({ textId: '@StyleStrokeWidth' })}
inputKey='width'
labelClassName=''
inputClassName=''
type='number'
min={0}
value={(props.properties.dimensionOptions.childrenDimensions.width ?? 0).toString()}
onChange={(value) => { props.onChange('width', Number(value), PropertyType.ChildrenDimensions); }}/>
<TextInputGroup
id={`${props.properties.id}-childrenDimensions-dasharray`}
labelText={Text({ textId: '@StyleStrokeDashArray' })}
inputKey='dashArray'
labelClassName=''
inputClassName=''
type='text'
value={props.properties.dimensionOptions.childrenDimensions.dashArray ?? ''}
onChange={(value) => { props.onChange('dashArray', value, PropertyType.ChildrenDimensions); }}/>
</div>
}
{
SHOW_BORROWER_DIMENSIONS &&
<>
<div className='grid grid-cols-1 gap-2'>
<OrientationCheckboxes
id='markPosition'
name='MarkPosition'
value={props.properties.dimensionOptions.markPosition}
labelText={Text({ textId: '@ContainerMarkPosition' })}
onChange={(key, value) => { props.onChange(key, value, PropertyType.DimensionOptions); }}
/>
</div>
<div className='grid grid-cols-1 gap-2'>
<PositionCheckboxes
id='positionsDimensionWithMarks'
attribute='positions'
name='ShowDimensionWithMarks'
labelText={Text({ textId: '@ContainerShowDimensionWithMarks' })}
value={props.properties.dimensionOptions.dimensionWithMarks.positions}
onChange={(key, value) => { props.onChange(key, value, PropertyType.DimensionWithMarks); }}
/>
<InputGroup
labelText={Text({ textId: '@StyleStrokeColor' })}
inputKey='color'
labelClassName=''
inputClassName=''
type='color'
value={props.properties.dimensionOptions.dimensionWithMarks.color}
onChange={(e) => { props.onChange('color', e.target.value, PropertyType.DimensionWithMarks); }}/>
<TextInputGroup
id={`${props.properties.id}-dimensionWithMarks-width`}
labelText={Text({ textId: '@StyleStrokeWidth' })}
inputKey='width'
labelClassName=''
inputClassName=''
type='number'
min={0}
value={(props.properties.dimensionOptions.dimensionWithMarks.width ?? 0).toString()}
onChange={(value) => { props.onChange('width', Number(value), PropertyType.DimensionWithMarks); }}/>
<TextInputGroup
id={`${props.properties.id}-dimensionWithMarks-dasharray`}
labelText={Text({ textId: '@StyleStrokeDashArray' })}
inputKey='dashArray'
labelClassName=''
inputClassName=''
type='text'
value={props.properties.dimensionOptions.dimensionWithMarks.dashArray ?? ''}
onChange={(value) => { props.onChange('dashArray', value, PropertyType.DimensionWithMarks); }}/>
</div>
</>
}
</div>
</Category>
{props.properties.style !== undefined &&
<Category category={{
Type: 'Style',
DisplayedText: Text({ textId: '@ContainerStyle' })
}}
heightClass={`${categoryHeight}`}
>
<div className='grid grid-cols-5 gap-6 items-center prop-category-body'>
<TextInputGroup
id={`${props.properties.id}-stroke`}
labelText={Text({ textId: '@StyleStroke' })}
inputKey='stroke'
labelClassName='col-span-2'
inputClassName='col-span-3'
type='string'
value={props.properties.style.stroke ?? 'black'}
onChange={(value) => { props.onChange('stroke', value, PropertyType.Style); }}
/>
<InputGroup
labelKey={`${props.properties.id}-strokeOpacity`}
labelText={Text({ textId: '@StyleStrokeOpacity' })}
inputKey='strokeOpacity'
labelClassName='col-span-2'
inputClassName='col-span-3'
type='range'
min={0}
max={1}
step={0.01}
value={(props.properties.style.strokeOpacity ?? 1).toString()}
onChange={(event) => { props.onChange('strokeOpacity', Number(event.target.value), PropertyType.Style); }}
/>
<TextInputGroup
id={`${props.properties.id}-strokeWidth`}
labelText={Text({ textId: '@StyleStrokeWidth' })}
inputKey='strokeWidth'
labelClassName='col-span-2'
inputClassName='col-span-3'
type='number'
value={(props.properties.style.strokeWidth ?? 1).toString()}
onChange={(value) => { props.onChange('strokeWidth', Number(value), PropertyType.Style); }}
/>
<TextInputGroup
id={`${props.properties.id}-fill`}
labelText={Text({ textId: '@StyleFill' })}
inputKey='fill'
labelClassName='col-span-2'
inputClassName='col-span-3'
type='string'
value={props.properties.style.fill ?? 'black'}
onChange={(value) => { props.onChange('fill', value, PropertyType.Style); }}
/>
<InputGroup
labelKey={`${props.properties.id}-fillOpacity`}
labelText={Text({ textId: '@StyleFillOpacity' })}
inputKey='fillOpacity'
labelClassName='col-span-2'
inputClassName='col-span-3'
type='range'
min={0}
max={1}
step={0.01}
value={(props.properties.style.fillOpacity ?? 1).toString()}
onChange={(event) => { props.onChange('fillOpacity', Number(event.target.value), PropertyType.Style); }}
/>
</div>
</Category>
}
</div>
);
}