Implement Category
This commit is contained in:
parent
320d68e27f
commit
4f0a6795ad
5 changed files with 114 additions and 8 deletions
60
src/Components/Category/Category.tsx
Normal file
60
src/Components/Category/Category.tsx
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
import { ChevronRightIcon } from '@heroicons/react/outline';
|
||||||
|
import React, { useState } from 'react';
|
||||||
|
import { TruncateString } from '../../utils/stringtools';
|
||||||
|
|
||||||
|
interface ICategoryProps {
|
||||||
|
children: JSX.Element | JSX.Element[]
|
||||||
|
category: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Category(props: ICategoryProps): JSX.Element {
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
if (isOpen) {
|
||||||
|
return (
|
||||||
|
<button type="button"
|
||||||
|
className='overflow-hidden h-full transition-all'
|
||||||
|
key={props.category}
|
||||||
|
id={props.category}
|
||||||
|
title={props.category}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className='flex flex-row group full'
|
||||||
|
onClick={() => setIsOpen(!isOpen)}
|
||||||
|
>
|
||||||
|
<span className={'transition-all flex-1 h-full justify-center sidebar-component-left rounded-b-none bg-slate-400/60 group-hover:bg-blue-600'}>
|
||||||
|
{TruncateString(props.category, 25)}
|
||||||
|
</span>
|
||||||
|
<span className={'flex-none h-full justify-center sidebar-component-right rounded-b-none'}>
|
||||||
|
<ChevronRightIcon className='transition-all w-5 rotate-90' />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className='transition-all grid gap-2 p-2 bg-slate-400/60 overflow-auto rounded-b-lg visible'>
|
||||||
|
{ props.children }
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button type="button"
|
||||||
|
className='overflow-visible h-16 group transition-all'
|
||||||
|
key={props.category}
|
||||||
|
id={props.category}
|
||||||
|
title={props.category}
|
||||||
|
onClick={() => setIsOpen(!isOpen)}
|
||||||
|
>
|
||||||
|
<div className='flex flex-row h-full'>
|
||||||
|
<span className='flex-1 h-full justify-center sidebar-component-left'>
|
||||||
|
{TruncateString(props.category, 25)}
|
||||||
|
</span>
|
||||||
|
<span className='flex-none h-full justify-center sidebar-component-right'>
|
||||||
|
<ChevronRightIcon className='transition-all w-5' />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className='transition-all overflow-hidden rounded-b-lg hidden'>
|
||||||
|
{ props.children }
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,6 +1,8 @@
|
||||||
|
import { ChevronRightIcon } from '@heroicons/react/outline';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
|
import { IAvailableContainer } from '../../Interfaces/IAvailableContainer';
|
||||||
import { TruncateString } from '../../utils/stringtools';
|
import { TruncateString } from '../../utils/stringtools';
|
||||||
|
import { Category } from '../Category/Category';
|
||||||
|
|
||||||
interface ISidebarProps {
|
interface ISidebarProps {
|
||||||
componentOptions: IAvailableContainer[]
|
componentOptions: IAvailableContainer[]
|
||||||
|
@ -13,10 +15,16 @@ function HandleDragStart(event: React.DragEvent<HTMLButtonElement>): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Sidebar(props: ISidebarProps): JSX.Element {
|
export function Sidebar(props: ISidebarProps): JSX.Element {
|
||||||
const listElements = props.componentOptions.map(componentOption =>
|
const rootElements: Array<JSX.Element | undefined> = [];
|
||||||
componentOption.IsHidden !== true &&
|
const categories = new Map<string, JSX.Element[]>();
|
||||||
<button type="button"
|
// build the components
|
||||||
className='justify-center transition-all sidebar-component'
|
props.componentOptions.forEach(componentOption => {
|
||||||
|
if (componentOption.IsHidden === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const componentButton = (<button type="button"
|
||||||
|
className='w-full justify-center h-16 transition-all sidebar-component'
|
||||||
key={componentOption.Type}
|
key={componentOption.Type}
|
||||||
id={componentOption.Type}
|
id={componentOption.Type}
|
||||||
title={componentOption.Type}
|
title={componentOption.Type}
|
||||||
|
@ -25,8 +33,33 @@ export function Sidebar(props: ISidebarProps): JSX.Element {
|
||||||
onDragStart={(event) => HandleDragStart(event)}
|
onDragStart={(event) => HandleDragStart(event)}
|
||||||
>
|
>
|
||||||
{TruncateString(componentOption.Type, 25)}
|
{TruncateString(componentOption.Type, 25)}
|
||||||
</button>
|
</button>);
|
||||||
);
|
if (componentOption.Category === null || componentOption.Category === undefined) {
|
||||||
|
rootElements.push(componentButton);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (categories.get(componentOption.Category) === undefined) {
|
||||||
|
categories.set(componentOption.Category, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
const category = categories.get(componentOption.Category);
|
||||||
|
|
||||||
|
if (category === undefined) {
|
||||||
|
// should never go here
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
category.push(componentButton);
|
||||||
|
});
|
||||||
|
|
||||||
|
// build the categories
|
||||||
|
categories.forEach((options, category) => {
|
||||||
|
rootElements.unshift(
|
||||||
|
<Category category={category}>
|
||||||
|
{ options }
|
||||||
|
</Category>);
|
||||||
|
});
|
||||||
|
|
||||||
const isOpenClasses = props.isOpen ? 'left-16' : '-left-64';
|
const isOpenClasses = props.isOpen ? 'left-16' : '-left-64';
|
||||||
return (
|
return (
|
||||||
|
@ -38,7 +71,7 @@ export function Sidebar(props: ISidebarProps): JSX.Element {
|
||||||
</div>
|
</div>
|
||||||
<div className='grid grid-cols-1 md:grid-cols-1 gap-2
|
<div className='grid grid-cols-1 md:grid-cols-1 gap-2
|
||||||
m-2 md:text-xs font-bold'>
|
m-2 md:text-xs font-bold'>
|
||||||
{listElements}
|
{rootElements}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -10,6 +10,9 @@ export interface IAvailableContainer {
|
||||||
/** type */
|
/** type */
|
||||||
Type: string
|
Type: string
|
||||||
|
|
||||||
|
/** category */
|
||||||
|
Category?: string
|
||||||
|
|
||||||
/** horizontal offset */
|
/** horizontal offset */
|
||||||
X?: number
|
X?: number
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,14 @@
|
||||||
@apply transition-all px-2 py-6 text-sm rounded-lg bg-slate-300/60 hover:bg-blue-500 hover:text-slate-50
|
@apply transition-all px-2 py-6 text-sm rounded-lg bg-slate-300/60 hover:bg-blue-500 hover:text-slate-50
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar-component-left {
|
||||||
|
@apply transition-all px-2 py-6 text-sm rounded-l-lg bg-slate-300/60 group-hover:bg-blue-500 group-hover:text-slate-50
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-component-right {
|
||||||
|
@apply transition-all px-2 py-6 text-sm rounded-r-lg bg-slate-400/60 group-hover:bg-blue-600 group-hover:text-slate-50
|
||||||
|
}
|
||||||
|
|
||||||
.sidebar-component-card {
|
.sidebar-component-card {
|
||||||
@apply transition-all overflow-hidden text-sm rounded-lg bg-slate-300/60 hover:bg-slate-300
|
@apply transition-all overflow-hidden text-sm rounded-lg bg-slate-300/60 hover:bg-slate-300
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,7 @@ const GetSVGLayoutConfiguration = () => {
|
||||||
},
|
},
|
||||||
ShowSelfDimensions: true,
|
ShowSelfDimensions: true,
|
||||||
IsDimensionBorrower: true,
|
IsDimensionBorrower: true,
|
||||||
|
Category: "Category"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: 'Trou',
|
Type: 'Trou',
|
||||||
|
@ -82,7 +83,8 @@ const GetSVGLayoutConfiguration = () => {
|
||||||
strokeWidth: 2,
|
strokeWidth: 2,
|
||||||
stroke: 'green',
|
stroke: 'green',
|
||||||
fill: 'white'
|
fill: 'white'
|
||||||
}
|
},
|
||||||
|
Category: "Category"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Type: 'Remplissage',
|
Type: 'Remplissage',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue