Merged PR 198: Change MarkPosition for multiple orientation
Implement EnumCheckboxGroupInput
This commit is contained in:
parent
417829945f
commit
7836d27d5f
12 changed files with 164 additions and 68 deletions
|
@ -1,4 +1,5 @@
|
|||
import { Bars3BottomLeftIcon, Bars3CenterLeftIcon, Bars3Icon, Bars3BottomRightIcon, Bars2Icon, ViewColumnsIcon } from '@heroicons/react/24/outline';
|
||||
import { Bars3BottomLeftIcon, Bars3CenterLeftIcon, Bars3Icon, Bars3BottomRightIcon, Bars2Icon } from '@heroicons/react/24/outline';
|
||||
import { FlagIcon, ViewColumnsIcon } from '@heroicons/react/20/solid';
|
||||
import * as React from 'react';
|
||||
import { PropertyType } from '../../Enums/PropertyType';
|
||||
import { PositionReference } from '../../Enums/PositionReference';
|
||||
|
@ -12,11 +13,12 @@ import { RadioGroupButtons } from '../RadioGroupButtons/RadioGroupButtons';
|
|||
import { Select } from '../Select/Select';
|
||||
import { ToggleButton, ToggleType } from '../ToggleButton/ToggleButton';
|
||||
import { Orientation } from '../../Enums/Orientation';
|
||||
import { EnumCheckboxGroupButtons } from '../EnumCheckboxGroupButtons/EnumCheckboxGroupButtons';
|
||||
|
||||
interface IContainerFormProps {
|
||||
properties: IContainerProperties
|
||||
symbols: Map<string, ISymbolModel>
|
||||
onChange: (key: string, value: string | number | boolean, type?: PropertyType) => void
|
||||
onChange: (key: string, value: string | number | boolean | number[], type?: PropertyType) => void
|
||||
}
|
||||
|
||||
function GetCSSInputs(properties: IContainerProperties,
|
||||
|
@ -284,14 +286,7 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
|||
{
|
||||
SHOW_BORROWER_DIMENSIONS &&
|
||||
<>
|
||||
<ToggleButton
|
||||
labelText='Mark the position'
|
||||
inputKey='markPositionToDimensionBorrower'
|
||||
labelClassName=''
|
||||
inputClassName=''
|
||||
type={ToggleType.Full}
|
||||
checked={props.properties.markPositionToDimensionBorrower}
|
||||
onChange={(event) => props.onChange('markPositionToDimensionBorrower', event.target.checked)} />
|
||||
<MarkPositionOptions {...props} />
|
||||
<ToggleButton
|
||||
labelText='Show dimension with marked children'
|
||||
inputKey='isDimensionBorrower'
|
||||
|
@ -308,6 +303,40 @@ export function ContainerForm(props: IContainerFormProps): JSX.Element {
|
|||
|
||||
// TODO: Implement categories in the form
|
||||
|
||||
function MarkPositionOptions(props: IContainerFormProps): JSX.Element {
|
||||
return <EnumCheckboxGroupButtons
|
||||
key='markPosition'
|
||||
name='MarkPosition'
|
||||
selectedValues={props.properties.markPositionToDimensionBorrower}
|
||||
inputClassName='hidden'
|
||||
labelText='Mark the position'
|
||||
colQty={2}
|
||||
inputGroups={[
|
||||
{
|
||||
key: 'mark-position-horizontal',
|
||||
text: (
|
||||
<div title='Horizontal' aria-label='horizontal' className='radio-button-icon'>
|
||||
<FlagIcon className='heroicon p-1' />
|
||||
</div>
|
||||
),
|
||||
value: Orientation.Horizontal
|
||||
},
|
||||
{
|
||||
key: 'mark-position-vertical',
|
||||
text: (
|
||||
<div title='Vertical' aria-label='vertical' className='radio-button-icon'>
|
||||
<FlagIcon className='heroicon rotate-90 p-1' />
|
||||
</div>
|
||||
),
|
||||
value: Orientation.Vertical
|
||||
}
|
||||
]}
|
||||
onChange={(newSelectedValues) => {
|
||||
props.onChange('markPositionToDimensionBorrower', newSelectedValues);
|
||||
}}
|
||||
/>;
|
||||
}
|
||||
|
||||
function OrientationSelector(props: IContainerFormProps): JSX.Element {
|
||||
return <RadioGroupButtons
|
||||
key='orientation'
|
||||
|
@ -321,7 +350,7 @@ function OrientationSelector(props: IContainerFormProps): JSX.Element {
|
|||
key: 'orientation-horizontal',
|
||||
text: (
|
||||
<div title='Horizontal' aria-label='horizontal' className='radio-button-icon'>
|
||||
<ViewColumnsIcon className='heroicon' />
|
||||
<ViewColumnsIcon className='heroicon p-1' />
|
||||
</div>
|
||||
),
|
||||
value: Orientation.Horizontal.toString()
|
||||
|
@ -330,7 +359,7 @@ function OrientationSelector(props: IContainerFormProps): JSX.Element {
|
|||
key: 'orientation-vertical',
|
||||
text: (
|
||||
<div title='Vertical' aria-label='vertical' className='radio-button-icon'>
|
||||
<ViewColumnsIcon className='heroicon rotate-90' />
|
||||
<ViewColumnsIcon className='heroicon rotate-90 p-1' />
|
||||
</div>
|
||||
),
|
||||
value: Orientation.Vertical.toString()
|
||||
|
|
|
@ -7,7 +7,7 @@ import { ContainerForm } from './ContainerForm';
|
|||
interface IPropertiesProps {
|
||||
properties?: IContainerProperties
|
||||
symbols: Map<string, ISymbolModel>
|
||||
onChange: (key: string, value: string | number | boolean, type?: PropertyType) => void
|
||||
onChange: (key: string, value: string | number | boolean | number[], type?: PropertyType) => void
|
||||
}
|
||||
|
||||
export function Properties(props: IPropertiesProps): JSX.Element {
|
||||
|
|
|
@ -152,7 +152,7 @@ function UnlinkContainerFromSymbols(symbols: Map<string, ISymbolModel>, containe
|
|||
*/
|
||||
export function OnPropertyChange(
|
||||
key: string,
|
||||
value: string | number | boolean,
|
||||
value: string | number | boolean | number[],
|
||||
type: PropertyType = PropertyType.Simple,
|
||||
selected: IContainerModel | undefined,
|
||||
fullHistory: IHistoryState[],
|
||||
|
@ -247,7 +247,7 @@ export function SortChildren(parentClone: IContainerModel | null | undefined): v
|
|||
*/
|
||||
function SetContainer(
|
||||
container: ContainerModel,
|
||||
key: string, value: string | number | boolean,
|
||||
key: string, value: string | number | boolean | number[],
|
||||
type: PropertyType,
|
||||
symbols: Map<string, ISymbolModel>
|
||||
): void {
|
||||
|
@ -282,7 +282,7 @@ function SetContainer(
|
|||
* @param value Value of the property
|
||||
* @param type Type of the property
|
||||
*/
|
||||
function AssignProperty(container: ContainerModel, key: string, value: string | number | boolean, type: PropertyType): void {
|
||||
function AssignProperty(container: ContainerModel, key: string, value: string | number | boolean | number[], type: PropertyType): void {
|
||||
switch (type) {
|
||||
case PropertyType.Style:
|
||||
(container.properties.style as any)[key] = value;
|
||||
|
|
|
@ -15,7 +15,7 @@ interface IElementsSidebarProps {
|
|||
selectedContainer: IContainerModel | undefined
|
||||
onPropertyChange: (
|
||||
key: string,
|
||||
value: string | number | boolean,
|
||||
value: string | number | boolean | number[],
|
||||
type?: PropertyType
|
||||
) => void
|
||||
selectContainer: (containerId: string) => void
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
import * as React from 'react';
|
||||
import { IInputGroup } from '../../Interfaces/IInputGroup';
|
||||
|
||||
interface ICheckboxGroupButtonsProps {
|
||||
name: string
|
||||
selectedValues: number[]
|
||||
inputClassName: string
|
||||
labelText: string
|
||||
inputGroups: IEnumCheckboxInputGroup[]
|
||||
colQty: number
|
||||
onChange: (newSelectedValues: number[]) => void
|
||||
}
|
||||
|
||||
interface IEnumCheckboxInputGroup extends Omit<IInputGroup, 'value'> {
|
||||
value: number
|
||||
}
|
||||
|
||||
// Use whole class name for react to preparse
|
||||
const GRID_COLS = [
|
||||
'grid-cols-none',
|
||||
'grid-cols-1',
|
||||
'grid-cols-2',
|
||||
'grid-cols-3',
|
||||
'grid-cols-4',
|
||||
'grid-cols-5',
|
||||
'grid-cols-6',
|
||||
'grid-cols-7',
|
||||
'grid-cols-8',
|
||||
'grid-cols-9',
|
||||
'grid-cols-10',
|
||||
'grid-cols-11',
|
||||
'grid-cols-12'
|
||||
];
|
||||
|
||||
export function EnumCheckboxGroupButtons(props: ICheckboxGroupButtonsProps): JSX.Element {
|
||||
const selectedOptions = new Set<number>(props.selectedValues);
|
||||
const inputGroups = props.inputGroups.map((inputGroup) => (
|
||||
<div key={inputGroup.key}>
|
||||
<input
|
||||
key={inputGroup.key}
|
||||
id={inputGroup.key}
|
||||
type='checkbox'
|
||||
name={props.name}
|
||||
className={`peer m-2 ${props.inputClassName}`}
|
||||
value={inputGroup.value}
|
||||
checked={IsChecked(inputGroup)}
|
||||
onChange={(event) => {
|
||||
const newSelectedValues = SetChecked(Number(event.target.value), event.target.checked);
|
||||
props.onChange(newSelectedValues);
|
||||
}} />
|
||||
<label htmlFor={inputGroup.key} className='text-gray-400 peer-checked:text-blue-500'>
|
||||
{inputGroup.text}
|
||||
</label>
|
||||
</div>
|
||||
));
|
||||
|
||||
const gridColsClass = GRID_COLS[props.colQty];
|
||||
|
||||
return (
|
||||
<>
|
||||
<label className='text-xs font-medium text-gray-800'>
|
||||
{props.labelText}
|
||||
</label>
|
||||
<div id='XPositionReference'
|
||||
className={`grid ${gridColsClass}`}
|
||||
>
|
||||
{inputGroups}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
function IsChecked(inputGroup: IEnumCheckboxInputGroup): boolean {
|
||||
return selectedOptions.has(inputGroup.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sedt an option by using a bitwise operation and returns the new selected values
|
||||
* example: set the 4th option to 0: (1001) xor (1 << 3) => 0001
|
||||
* @param selectedValue The option to set
|
||||
* @returns The new selected values
|
||||
*/
|
||||
function SetChecked(selectedValue: number, isChecked: boolean): number[] {
|
||||
isChecked ? selectedOptions.add(selectedValue) : selectedOptions.delete(selectedValue);
|
||||
return [...selectedOptions];
|
||||
}
|
||||
}
|
|
@ -3,8 +3,7 @@ import { IInputGroup } from '../../Interfaces/IInputGroup';
|
|||
|
||||
interface IRadioGroupButtonsProps {
|
||||
name: string
|
||||
value?: string
|
||||
defaultValue?: string
|
||||
value: string
|
||||
inputClassName: string
|
||||
labelText: string
|
||||
inputGroups: IInputGroup[]
|
||||
|
@ -30,44 +29,23 @@ const GRID_COLS = [
|
|||
];
|
||||
|
||||
export function RadioGroupButtons(props: IRadioGroupButtonsProps): JSX.Element {
|
||||
let inputGroups;
|
||||
if (props.value !== undefined) {
|
||||
// dynamic
|
||||
inputGroups = props.inputGroups.map((inputGroup) => (
|
||||
<div key={inputGroup.key}>
|
||||
<input
|
||||
key={inputGroup.key}
|
||||
id={inputGroup.key}
|
||||
type='radio'
|
||||
name={props.name}
|
||||
className={`peer m-2 ${props.inputClassName}`}
|
||||
value={inputGroup.value}
|
||||
checked={props.value === inputGroup.value}
|
||||
onChange={props.onChange} />
|
||||
<label htmlFor={inputGroup.key} className='text-gray-400 peer-checked:text-blue-500'>
|
||||
{inputGroup.text}
|
||||
</label>
|
||||
</div>
|
||||
const inputGroups = props.inputGroups.map((inputGroup) => (
|
||||
<div key={inputGroup.key}>
|
||||
<input
|
||||
key={inputGroup.key}
|
||||
id={inputGroup.key}
|
||||
type='radio'
|
||||
name={props.name}
|
||||
className={`peer m-2 ${props.inputClassName}`}
|
||||
value={inputGroup.value}
|
||||
checked={props.value === inputGroup.value}
|
||||
onChange={props.onChange} />
|
||||
<label htmlFor={inputGroup.key} className='text-gray-400 peer-checked:text-blue-500'>
|
||||
{inputGroup.text}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
));
|
||||
} else {
|
||||
// static
|
||||
inputGroups = props.inputGroups.map((inputGroup) => (
|
||||
<div key={inputGroup.key}>
|
||||
<input
|
||||
key={inputGroup.key}
|
||||
id={inputGroup.key}
|
||||
type='radio'
|
||||
name={props.name}
|
||||
className={`peer m-2 ${props.inputClassName}`}
|
||||
value={inputGroup.value}
|
||||
defaultChecked={props.defaultValue === inputGroup.value} />
|
||||
<label htmlFor={inputGroup.key} className='text-gray-400 peer-checked:text-blue-500'>
|
||||
{inputGroup.text}
|
||||
</label>
|
||||
</div>
|
||||
));
|
||||
}
|
||||
));
|
||||
|
||||
const gridColsClass = GRID_COLS[props.colQty];
|
||||
|
||||
|
@ -76,7 +54,7 @@ export function RadioGroupButtons(props: IRadioGroupButtonsProps): JSX.Element {
|
|||
<label className='text-xs font-medium text-gray-800'>
|
||||
{props.labelText}
|
||||
</label>
|
||||
<div id='XPositionReference'
|
||||
<div
|
||||
className={`grid ${gridColsClass}`}
|
||||
>
|
||||
{inputGroups}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import { Orientation } from '../../../Enums/Orientation';
|
||||
import { ContainerModel, IContainerModel } from '../../../Interfaces/IContainerModel';
|
||||
import { DIMENSION_MARGIN, SHOW_BORROWER_DIMENSIONS, SHOW_CHILDREN_DIMENSIONS, SHOW_SELF_DIMENSIONS } from '../../../utils/default';
|
||||
import { MakeRecursionDFSIterator, Pairwise } from '../../../utils/itertools';
|
||||
|
@ -37,7 +38,7 @@ function Dimensions({ root, scale }: IDimensionLayerProps): React.ReactNode[] {
|
|||
AddBorrowerDimension(containerBottomDim, containerRightDim, depth, scale, container, currentTransform, dimensions);
|
||||
}
|
||||
|
||||
if (SHOW_CHILDREN_DIMENSIONS && container.properties.showChildrenDimensions && container.children.length > 0) {
|
||||
if (SHOW_CHILDREN_DIMENSIONS && container.properties.showChildrenDimensions && container.children.length > 1) {
|
||||
AddChildrenDimension(container, currentTransform, dimensions, containerBottomDim, containerRightDim, scale);
|
||||
}
|
||||
}
|
||||
|
@ -171,7 +172,8 @@ function AddHorizontalBorrowerDimension(
|
|||
for (const {
|
||||
container: childContainer, currentTransform: childCurrentTransform
|
||||
} of it) {
|
||||
if (!childContainer.properties.markPositionToDimensionBorrower) {
|
||||
const isHidden = !childContainer.properties.markPositionToDimensionBorrower.includes(Orientation.Horizontal);
|
||||
if (isHidden) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -223,7 +225,8 @@ function AddVerticalBorrowerDimension(
|
|||
for (const {
|
||||
container: childContainer, currentTransform: childCurrentTransform
|
||||
} of it) {
|
||||
if (!childContainer.properties.markPositionToDimensionBorrower) {
|
||||
const isHidden = !childContainer.properties.markPositionToDimensionBorrower.includes(Orientation.Vertical);
|
||||
if (isHidden) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ interface IUIProps {
|
|||
categories: ICategory[]
|
||||
selectContainer: (containerId: string) => void
|
||||
deleteContainer: (containerId: string) => void
|
||||
onPropertyChange: (key: string, value: string | number | boolean, type?: PropertyType) => void
|
||||
onPropertyChange: (key: string, value: string | number | boolean | number[], type?: PropertyType) => void
|
||||
addContainer: (type: string) => void
|
||||
addContainerAt: (index: number, type: string, parent: string) => void
|
||||
addSymbol: (type: string) => void
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue