@hortiview/shared-components
v0.0.9707
Published
This is a shared component library. It should used in the HortiView platform and its modules.
Downloads
396
Keywords
Readme
HortiView Shared Components
This is a shared component library. It should used in the HortiView platform and its modules.
Install
npm i @hortiview/shared-components
yarn add @hortiview/shared-components
Prerequisites
This library is based in Bayers element component library. To use it properly you need to install this package first. To get access to this restricted package please contact your Bayer contact person.
After you gain access use yarn add @element/react-components @element/themes
or npm i @element/react-components @element/themes
to add the package to your solution.
Remarks
For the best experience use react-router in your solution, because some of the component rely on properties like pathname, hash or components like Link
out of react-router
.
Additionally the library provides form components using react-hook-form. When you want to use these components please install react-hook-form
before using them.
Available Components:
- AlertBanner
- BaseView
- BasicHeading
- BlockView
- ChipCard
- ContextMenu
- DeleteModal
- Disclaimer
- EmptyView
- Filter
- FormComponents
- GenericTable
- HashTabView
- HeaderFilter
- InfoGroup
- Iconify
- ListArea
- LoadingSpinner
- Modal
- OverflowTooltip
- ScrollBar
- SearchBar
- VerticalDivider
Available Utility Functions:
Available Components:
AlertBanner
Presents an Banner containing important messages. Can used in different colors and you can add an optional action.
import { AlertBanner } from '@hortiview/shared-components';
<AlertBanner
text='My Alert'
color='danger' // | 'info' | 'success'
action={<MyButton />}
/>;
BaseView
Can used to show a kind off main and detail view. On the left side you will have a list of elements and on the right a detail section of the element selected.
import { BaseListElement, BaseView } from '@hortiview/shared-components';
import { Link, useLocation } from 'react-router-dom';
const { pathname } = useLocation();
const elements: BaseListElement[] = [
{
id: '1',
title: 'First',
subTitle: 'First Subtilte',
type: 'Primary',
icon: 'grid_view',
route: '/first',
component: <MyComponentToShowOnClick />,
},
{
id: '2',
title: 'Second',
subTitle: 'Second Subtilte',
type: 'Primary',
icon: 'add',
route: '/second',
component: <MyComponentToShowOnClickSecond />,
},
];
return (
<BaseView
routerLinkElement={Link}
pathname={pathname}
elements={elements}
heading='Header'
hasSearch
emptyText='Empty'
/>
);
BasicHeading
Provides a heading component with optional children which are rendered on the right side of the heading.
import { BasicHeading } from '@hortiview/shared-components';
<BasicHeading heading={'Header'}>
<button>Test</button>
</BasicHeading>;
BlockView
This is a component showing blocks in a row/column view.
import { BlockView, BlockDto } from '@hortiview/shared-components';
const blocks: BlockDto = [
{
position: { row: 1, column: 1 },
fieldId: '1',
},
];
<BlockView blocks={blocks} columns={1} rows={1} />;
ChipCard
A card with a chip inside, used for displaying entities. The chip displays an icon and a label. Furthermore, it is wrapped by OverflowTooltip to truncate long labels. The card takes per default the width of the parent container. You can also provide custom CSS via the className
property.
import { ChipCard } form '@hortiview/shared-components'
<ChipCard icon='domain' label='Example Label' className='custom' />
ContextMenu
This is a component to render a menu button, that opens several action-points in a context-menu
import { ContextMenu } from '@hortiview/shared-components';
const actions = [
{
primaryText: 'Edit',
secondaryText: 'Open the edit dialog',
onClick: () => openEdit(param),
leadingBlock: 'edit',
},
{
primaryText: 'Delete',
secondaryText: 'Delete the item'
onClick: deleteItem,
leadingBlock: 'delete',
},
];
<ContextMenu actions={actions} />;
DeleteModal
A modal to confirm a deletion.
import { DeleteModal } from '@hortiview/shared-components';
const [open, setOpen] = useState<string>();
const onDelete = () => {
console.log('deleted');
};
<DeleteModal
icon='block'
open={open}
setOpen={setOpen}
onDelete={onDelete}
title={'DELETE'}
confirmButtonLabel={'Remove'}
cancelButtonLabel={'Cancel'}
deleteHeader={'Delete my block'}
impossibleDeleteHeader={'block cant be deleted'}
deleteBody={['block 1', 'block 2', 'block 3']}
isDeletePossible
/>;
Disclaimer
A red notice or hint with to show in the ui.
import { Disclaimer } form '@hortiview/shared-components'
<Disclaimer text='Currently not available' subtext='Please try again later' icon='wifi_off' />
EmptyView
A basic view if no content is available.
import { EmptyView } from '@hortiview/shared-components';
<EmptyView title='No Content' subtitle='nothing' icon='grass' />;
Filter
A filter component, which provides a well designed filter experience. It contains a filter button and a modal for different select inputs.
You need to provide some filter options in a FilterData
array and handle the current filter selections.
import { Filter } from '@hortiview/shared-components';
import { useState } from 'react';
const MyComponent = () => {
const [selectedFilters, setSelectedFilters] = useState([]);
const options = [
{
id: 'cars',
title: 'Cars',
availableOptions: [
{
id: 'bmw';
text: 'BMW';
icon: 'car';
},
{
id: 'vw';
text: 'Volkswagen';
icon: 'car';
}
],
},
{
id: 'food',
title: 'Food',
availableOptions: [
{
id: 'icecream';
text: 'Icecream';
icon: 'food';
},
{
id: 'burger';
text: 'Burger';
icon: 'food';
}
],
},
];
return (
<Filter
modalCancelButtonText={'cancel'}
modalConfirmButtonText={'useFilter'}
clearFilterText={'clearFilter'}
closeCallback={filter => setSelectedFilters(filter)}
currentFilter={selectedFilters}
filterButtonText={'filterButton'}
filterModalTitle={'filterResults'}
filters={options}
/>
);
};
export default MyComponent;
FormComponents
The library provides some form components based on react-hook-form. The components can only be use within a form provided by react-hook-form. So please add the package before you use the components.
yarn add react-hook-form
or
npm install react-hook-form
FormCheckBox
Provides a checkbox form component
import { FormCheckBox } from '@hortiview/shared-components';
import { FormProvider, SubmitHandler, useForm } from 'react-hook-form';
const formMethods = useForm<{ check: boolean }>({
mode: 'onSubmit',
});
const { handleSubmit } = formMethods;
<FormProvider {...formMethods}>
<form onSubmit={handleSubmit(onSubmit)}>
<FormCheckBox<{ check: boolean }>
propertyName={`check`}
label={'My Checkbox'}
onChange={() => additionalOnChange()}
validate={validateFn}
/>
</form>
</FormProvider>;
FormDatePicker
Provides a datepicker form component
import { FormDatePicker } from '@hortiview/shared-components';
import { FormProvider, SubmitHandler, useForm } from 'react-hook-form';
const formMethods = useForm<{ birthday: string }>({
mode: 'onSubmit',
});
const { handleSubmit } = formMethods;
<FormProvider {...formMethods}>
<form onSubmit={handleSubmit(onSubmit)}>
<FormDatePicker<{ birthday: string }>
propertyName={'birthday'}
label={'user.date-of-birth'}
maxRangeYear={0}
/>
</form>
</FormProvider>;
FormRadio
Provides a radio button form component
import { FormRadio } from '@hortiview/shared-components';
import { FormProvider, SubmitHandler, useForm } from 'react-hook-form';
const formMethods = useForm<{ radioValue: string }>({
mode: 'onSubmit',
});
const { handleSubmit } = formMethods;
<FormProvider {...formMethods}>
<form onSubmit={handleSubmit(onSubmit)}>
<FormRadio<{ radioValue: string }>
propertyName='radioValue'
options={[
{ value: 'priced', label: 'Priced' },
{ value: 'free', label: 'Free },
]}
/>
</form>
</FormProvider>;
FormSelect
Provides a select form component
import { FormSelect } from '@hortiview/shared-components';
import { FormProvider, SubmitHandler, useForm } from 'react-hook-form';
const formMethods = useForm<{ type: string }>({
mode: 'onSubmit',
});
const { handleSubmit } = formMethods;
const typeOptions = [
{
id: 1,
value: 'Car',
},
{
id: 2,
value: 'Bike',
},
];
<FormProvider {...formMethods}>
<form onSubmit={handleSubmit(onSubmit)}>
<FormSelect<{ type: string }>
propertyName='type'
label='Type'
options={typeOptions}
valueKey='id'
textKey='value'
requiredText='required'
required
/>
</form>
</FormProvider>;
FormSlider
Provides a slider form component
import { FormSlider } from '@hortiview/shared-components';
import { FormProvider, SubmitHandler, useForm } from 'react-hook-form';
const formMethods = useForm<{ range: string }>({
mode: 'onSubmit',
});
const { handleSubmit } = formMethods;
<FormProvider {...formMethods}>
<form onSubmit={handleSubmit(onSubmit)}>
<FormSlider<{ range: string }> propertyName='range' minValue={30} maxValue={90} step={30} />
</form>
</FormProvider>;
FormText
Provides a text form component
import { FormText } from '@hortiview/shared-components';
import { FormProvider, SubmitHandler, useForm } from 'react-hook-form';
const formMethods = useForm<{ address: string }>({
mode: 'onSubmit',
});
const { handleSubmit } = formMethods;
<FormProvider {...formMethods}>
<form onSubmit={handleSubmit(onSubmit)}>
<FormText<{ address: string }>
maxLength={200}
label='address'
propertyName='address'
required
requiredText='required'
textarea
/>
</form>
</FormProvider>;
GenericTable
A dynamic table, that renders a table based on a type and an array of data (of the specified type). It renders a card list if your are in mobile or tablet mode.
import { GenericTable, CellTemplateProps, CellTemplate } from '@hortiview/shared-components';
import {useTranslation} from 'react-router-dom';
type DataType = {
id: string;
name: string;
users: User[];
description: string
field1: Date;
}
const filterArea = [
<Select onClick={filterLogic} />
];
const templates: CellTemplate = {
field1: (props: CellTemplateProps<DataType>) => {
const { field1 } = props.row.original;
return <Badge text={field1.toLocaleString()}/>
}
}
const getAction = (dataObject: DataType) => {
return [
{
primaryText: 'Edit Element',
secondaryText: 'in Modal',
onClick: () => openEdit(dataObject.id),
leadingBlock: 'edit',
},
]
}
const { t } = useTranslation();
const data: DataType[] = LoadData();
const filteredData = useMemo(() => {
return filterLogic(data)
})
return <GenericTable<DataType>
data={filteredData}
tableActions={filterArea}
hiddenColumns={['id', 'users']}
order={[
'name',
'description',
'field1'
]}
cellTemplates={templates}
headerTranslation={key => t(`overview.${key}`)}
noContentText={t('noText')}
pagination
getRowActions={getActions}
/>
HashTabView
A tab view component, which can use the hash value in the url to render the tab regarding to the hash.
Pass window.location.hash
as hash prop as it is the most reliable hash value.
When navigating back from a page with a HashTabView
, the last page without hash will be shown.
import { HashTabView, HashTab } from '@hortiview/shared-components';
const tabs: HashTab[] = [
{
title: 'My Map',
hash: 'map',
leadingIcon: 'map',
component: <>My map Component to show in the tab</>,
},
];
<HashTabView tabs={tabs} elevation={1} />;
HeaderFilter
A filter dropdown component which can be used in headers like a tabview header. It supports a single filter value only.
import { HeaderFilter } from '@hortiview/shared-components';
const [filterValue, setFilterValue] = useState<string>();
<HeaderFilter
heading={'Test'}
setFilter={setFilterValue}
filterValue={filterValue}
filterOptions={[
{ value: 'test', label: 'Test' },
{ value: 'different', label: 'Different' },
]}
/>;
InfoGroup
Renders a section with several informations rendered next to each other (or below for mobile view)
import { InfoGroup } from '@hortiview/shared-components';
const fields: FieldItem[] = [
{ label: 'FieldTitle', value: 'Value' },
{ label: 'AnotherFieldTitle', value: 'ValueButInPrimaryColor', themeColor: 'primary' },
//render a component below the label
{ label: 'StatusBadge', variant: 'embedded', component: <LabelBadge label='redLabel' themeColor='red'>}
//render a complex component without label
{ label: 'ComplexComponent', component: <ComplexComponent />}
]
<InfoGroup fields={fields} />
You can also render a multiline section, that receives an array if FieldItem-Arrays instead of a single FieldItem-Array
import { InfoGroup } from '@hortiview/shared-components';
const multiLineFields: FieldItem[][] = [
[
{ label: 'FieldTitle', value: 'Value' },
{ label: 'AnotherFieldTitle', value: 'ValueButInPrimaryColor', themeColor: 'primary' }
],
[
{ label: 'LongField', value: 'VeryLongValueThatNeedsToBeDisplayedInANewLine'}
],
[
{ label: 'ComplexComponent', component: <ComplexComponent />},
{ label: 'FieldTitle2', value: 'Value2' },
{ label: 'FieldTitle3', value: 'Value3' },
{ label: 'FieldTitle4', value: 'Value4' },
]
]
<InfoGroup fields={multiLineFields} />
Iconify
Provides some custom icons based on the elements Icon API. Currently supported:
- battery_0 | battery_20 | battery_50 | battery_80 | battery_100
- block
- block-delete
- cloud-rain
- cloud-sunny
- cloud
- farm-delete
- farm
- greenhouse-delete
- subscription
- wind
import { Iconify } from '@hortiview/shared-components';
<Iconify icon='wind' iconSize='large' />;
ListArea
Shows some items in a list. The list can be used as a navigation list and provides search. For the best experience use react-router
.
import { BaseListElement, ListArea } from '@hortiview/shared-components';
import { Link, useLocation } from 'react-router-dom';
const { pathname } = useLocation();
const elements: BaseListElement[] = [{
route: `/my/route/${1}`,
id: 1,
title: 'name',
subTitle: 'sub-name',
icon: <Icon icon={'grass'} />,
}]
<ListArea
hasSearch
searchPlaceholder={'Search....'}
elements={elements}
isSorted={false}
pathname={pathname}
routerLinkElement={Link}
/>;
LoadingSpinner
Renders a loading spinner. The loading spinner can be customized in size, text and color. It can also be centered.
import { LoadingSpinner } from '@hortiview/shared-components';
const [loading, setLoading] = useState(false)
//logic that changes state of loading to true
if(loading) return <LoadingSpinner />
return <DefaultComponent />
There is also a big loading spinner, that blurs the background and renders an spinning hortiview-logo.
import { LoadingSpinner } from '@hortiview/shared-components';
const [loading, setLoading] = useState(false)
const onSubmit = () => {
setLoading(true);
await someComplexLogic();
setLoading(false);
}
return <>
{loading && <LoadingSpinner size='big' text='Loading something ...' />}
<Form obSubmit={onSubmit} />
<Button type='submit' />
</>
Modal
Provides the normal elements modal with one additional change. If you are on fullscreen modal size the max-height and max-width is set to 100svh/svw (Smallest ViewPort height/width). This will set the modal size on an area between the mobile controls.
import { Modal } from '@hortiview/shared-components';
<Modal modalSize='fullscreen'>
<div>Content</div>
</Modal>;
OverflowTooltip
Provides a tooltip and overflow behavior of a given text value.
import { OverflowTooltip } from '@hortiview/shared-components';
import { TypoBody } from '@element/react-components';
const longText =
'This is a very long text that needs to be truncated and shown with a tooltip when it overflows.';
<OverflowTooltip text={longText}>
<TypoBody>{longText}</TypoBody>
</OverflowTooltip>;
ScrollBar
Provides a scrollbar in hortiview styling. Add it a classname on your component.
import { ScrollbarY, ScrollbarX } from '@hortiview/shared-components';
<div className={`${ScrollbarY}`}>
Height content
<div>
<div className={`${ScrollbarX}`}>
Wide content
<div>
SearchBar
Provides a searchbar component.
import { SearchBar } from '@hortiview/shared-components';
const [searchValue, setSearchValue] = useState('');
<SearchBar
searchTerm={searchValue}
setSearchTerm={setSearchValue}
dense
placeholder={'Search....'}
/>;
VerticalDivider
Provides a simple vertical divider.
import { VerticalDivider } from '@hortiview/shared-components';
<VerticalDivider className={'custom'} height='3rem' />;
Available Utility Functions:
useBreakpoints
Hook that returns the current breakpoint. It uses the following breakpoints:
- xs: 0-599px
- sm: 600-719px
- md: 720-839px
- lg: 840-1023px
- xl: 1024-1439px
- xxl: 1440px and up
Additional breakpoints considering the navbar width
- lg-nav: (840 + 256) - (1023 + 256)px
- xl-nav: (1024 + 256) - (1439 + 256)px
- xxl-nav: (1440 + 256)px and up
They are combined as follows:
- isMobile: xs
- isTablet: sm, md
- isDesktop: lg, xl, xxl
- isDesktopNavbar: lg-nav, xl-nav, xxl-nav
capitalizeFirstLetters
Capitalizes the first letter of every word in a given text string
trimLeadingAndTrailingSpaces
This function can be used when sending form data to the BE (see the example below). It removes leading and trailing spaces from all object properties that are typeof string.
const onSubmit = async (data: Record<string, string>) => {
const trimmedData = trimLeadingAndTrailingSpaces(data);
const loginResponse = await login(trimmedData.email, trimmedData.password);
if (loginResponse.ok) {
console.log('logged in');
}
};
Important note: If the type from the data is an interface the data need to be spread to avoid the following error. https://github.com/microsoft/TypeScript/issues/15300
const trimmedData = trimLeadingAndTrailingSpaces({ ...data });