2.1.0 • Published 4 months ago

@hortiview/shared-components v2.1.0

Weekly downloads
-
License
GPL-3.0
Repository
-
Last release
4 months ago

HortiView Shared Components

This is a shared components library. It should be used in the HortiView platform and its modules.

Install

npm i @hortiview/shared-components

yarn add @hortiview/shared-components

Prerequisites

This library is based on a public version of Bayer's Element component library.

Use yarn add @element-public/react-components @element-public/themes or npm i @element-public/react-components @element-public/themes to add the packages 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:

  1. AlertBanner
  2. BaseView
  3. BasicHeading
  4. BlockView
  5. ChipCard
  6. ContextMenu
  7. DeleteModal
  8. Disclaimer
  9. EmptyView
  10. Filter
  11. FormattedNumberDisplay
  12. FormComponents
    1. FormCheckBox
    2. FormDatePicker
    3. FormNumber
    4. FormRadio
    5. FormSelect
    6. FormSlider
    7. FormText
  13. GenericTable
  14. HashTabView
  15. HeaderFilter
  16. HealthCheckFailed
  17. InfoGroup
  18. Iconify
  19. ListArea
  20. LoadingSpinner
  21. Modal
  22. ModulePadding
  23. OnboardingBanner
  24. OverflowTooltip
  25. ScrollBar
  26. SearchBar
  27. Select
  28. Stepper
  29. VerticalDivider

Available Utility Functions:

  1. useBreakpoints
  2. capitalizeFirstLetters
  3. trimLeadingAndTrailingSpaces
  4. getNumberAsLocaleString

Available constants

  1. Languages and countries

Changelog

Changelog

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 be 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;

FormattedNumberDisplay

A component to display a formatted number based on the given language code, wrapped in a given typography component to style it as needed.

The typography component that is passed to the FormattedNumberDisplay needs the "children" property to which the formatted number will be added.

import { FormattedNumberDisplay } from '@hortiview/shared-components';

const TypoDisplay3 = (props: { children: React.ReactNode }) => {
  return <TypoDisplay level={3}>{props.children}</TypoDisplay>;
};

<FormattedNumberDisplay typographyComponent={TypoDisplay3} languageCode='en-MX' value={12345.67} />;

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>;

FormNumber

Number input field that formats the users input depending on the user language. The component automatically sets the language specific thousand separators and only allows the language specific decimal separators.

import { FormNumber } 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)}>
    <FormNumber<{ price: number }>
      propertyName='price'
      label='module.price'
      languageCode="es-MX"
      decimalScale={5}
      fixedDecimalScale={true}
      allowNegative={false}
      allowLeadingZeros={false}
      prefix=" €"
    />
  </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.

Warning: Don't set menuPosition when hoisted is true.

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' },
  ]}
/>

HealthCheckFailed

A screen that shows a health check failed message. It can be used if the check for database health, iot health or HV platform health fails. Please use the following title and subtitle for each type to ensure a consistent user experience:

import { HealthCheckFailed } from '@hortiview/shared-components';

if (isPlatformHealthy === false) {
  return (
    <HealthCheckFailed
      title='The platform data used by this module cannot be retrieved currently.'
      subtitle='Please wait or come back later.'
      type='platform'
    />
  );
}

if (isDbHealthy === false) {
  return (
    <HealthCheckFailed
      title='The data for this module is loading!'
      subtitle='Please wait or come back later.'
      type='database'
    />
  );
}

if (isIotServiceHealthy === false) {
  return (
    <HealthCheckFailed
      title='The data of your devices cannot be retrieved currently.'
      subtitle='The problem is being addressed by our technical team. Please come back later.'
      type='iot'
    />
  );
}

Set the type to other to catch generic errors. Again, please use the title and subtitle as listed here to ensure a consistent user experience:

<ParentWithVisibleBorders>
  <HealthCheckFailed
    title='Sorry, something went wrong!'
    subtitle='The problem is being addressed by our technical team. Please come back later.'
    type='other'
  />
</ParentWithVisibleBorders>

You can also control if the card is outlined or not, depending on the position in the UI. The card has a default outline. For design consistency, this prop should only be set to false if the card is embedded, e.g. in a table or any other parent that already has a border:

<ParentWithVisibleBorders>
  <HealthCheckFailed
    title='Sorry, something went wrong!'
    subtitle='The problem is being addressed by our technical team. Please come back later.'
    type='other'
    isOutlined={false}
  />
</ParentWithVisibleBorders>

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' />
</>

The Loading spinner will automatically change to another text, after a certain waiting time, the text and time are adjustable. This behavior is enabled per default (10 seconds) - it can be disabled by passing null to impatienceMessage.

import { LoadingSpinner } from  '@hortiview/shared-components';

const [loading, setLoading] = useState(false)

const onSubmit = () => {
  setLoading(true);
  await someComplexLogicThatTakesVeryLong();
  setLoading(false);
}
return <>
  {loading && <LoadingSpinner text='Loading something ...' impatienceTimeout={20} impatienceMessage={'Something takes longer than expected'} />}
  <Form obSubmit={onSubmit} />
  <Button type='submit' />
</>

Modal

Provides the normal Element 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.

The modal also includes a custom header, which has a close button of type button. The base Element design button has type submit, which breaks forms inside of the modal. Please provide onClose and title props to get it work properly.

import { Modal } from '@hortiview/shared-components';

<Modal modalSize='fullscreen'>
  <div>Content</div>
</Modal>;

ModulePadding

Provides a responsive padding component for modules according to the HV platform UI guidelines, based on the Bayer Element padding component.

Currently, the padding is set to 8px on mobile/tablet and 16px on desktop.

Strong recommendation: If your module does not require any fullscreen features, we highly encourage you to add the ModulePadding around your module content to ensure a consistent user experience within the rest of the platform.

import { ModulePadding } from '@hortiview/shared-components';

<ModulePadding>
  <div>Content</div>
</ModulePadding>;

OnboardingBanner

A responsive onboarding banner that adapts its layout for desktop and mobile.

  • Desktop: Media content is displayed to the right of the description
  • Mobile: Media content appears above the description
import {OnboardingBanner} from '@hortiview/shared-components';

<OnboardingBanner headline='Hello' />

OverflowTooltip

Provides a tooltip and overflow behavior of a given text value.

import { OverflowTooltip } from '@hortiview/shared-components';
import { TypoBody } from '@element-public/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....'}
/>;

Select

Provides the normal Element select with some additional presets and props:

  • menuMaxHeight has a default value of 15rem (can be overwritten)
  • custom styles are applied that improve the hoisted select menu behavior and avoid two scrolling bars on multi select menus
  • custom portal styles can be passed via the portalClassName prop - only works when portalContainer is not set

Warning: Don't set menuPosition when hoisted is true.

import { Select } from '@hortiview/shared-components';
...

<Select
  label='Contact during review'
  options={contacts}
  hoisted
  textKey='text'
  valueKey='id'
  onChange={handleContactSelect}
  value={contact}
  helperText='required'
  variant='outlined'
  portalClassName={styles.portal}
/>;

Stepper

Provides a simple stepper component, which contains the step indicators, a title text and buttons to navigate forwards and backwards. Be aware that you need to control the Stepper flow by your own, like:

import { Step, Stepper } from '@hortiview/shared-components';

const steps: Step[] = [
  {
    name: 'first',
    step: 0,
    title: 'First Step',
    optional: false,
  },
  {
    name: 'second',
    step: 1,
    title: 'Second Step',
    optional: true,
  },
];

const [currentStep, setCurrentStep] = useState(0);

<Stepper
  steps={steps}
  currentStep={currentStep}
  nextButtonProps={{
    label: currentStep < args.steps.length - 1 ? 'Next' : 'Finish',
    onClick: () =>
      currentStep < args.steps.length - 1
        ? setCurrentStep(currentStep + 1)
        : setCurrentStep(args.steps.length - 1),
  }}
  prevButtonProps={{
    onClick: () => (currentStep > 0 ? setCurrentStep(currentStep - 1) : setCurrentStep(0)),
  }}
/>;

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 });

getNumberAsLocaleString

Receives a number and returns the value as a locale string. Note: Should only be used for displaying numbers, not for calculations or values that are supposed to be send to the backend.

const userLocale = 'es-MX';

const overlineTitle = `${getNumberAsLocaleString(userLocale, totalArea, 5)} ${t(
  'squaremeter-unit'
)}`;

Available constants

Languages and countries

The file contains different languages and country constants as well as language ids, which represents the available languages and countries of the hortiview platform.

The supported languages are:

  • English (en)
  • Spanish (es)
  • Turkish (tr)

The supported countries are:

  • Spain (esp)
  • Mexico (mex)
  • Turkey (tur)
const languageCode = 'en' as AVAILABLE_LANGUAGE_CODES;
const languageCountryCode = LANGUAGE_CODES_MAPPER[languageCode];
console.log(languageCountryCode); // 'en-US'
1.2.0

7 months ago

0.0.9923

11 months ago

1.6.0

6 months ago

1.2.2

6 months ago

1.2.1

6 months ago

0.0.11146

8 months ago

2.0.0

5 months ago

0.0.11949

8 months ago

0.0.11155

8 months ago

0.0.11797

8 months ago

0.0.10589

9 months ago

1.1.1

7 months ago

1.1.0

7 months ago

1.9.0

5 months ago

1.5.0

6 months ago

1.1.2

7 months ago

0.0.11881

8 months ago

0.0.10038

10 months ago

0.0.11528

8 months ago

1.10.0

5 months ago

1.0.1

7 months ago

1.0.0

7 months ago

1.12.0

5 months ago

1.8.1

5 months ago

1.8.0

6 months ago

1.4.2

6 months ago

1.4.1

6 months ago

1.4.0

6 months ago

0.0.10012

10 months ago

0.0.11102

9 months ago

0.0.11587

8 months ago

0.0.11589

8 months ago

0.0.11747

8 months ago

0.0.10027

10 months ago

0.0.11114

9 months ago

1.11.0

5 months ago

1.3.5

6 months ago

1.7.0

6 months ago

1.3.4

6 months ago

1.3.3

6 months ago

1.3.2

6 months ago

1.3.1

6 months ago

1.3.0

6 months ago

2.1.0

4 months ago

0.0.9939

11 months ago

0.0.10001

10 months ago

0.0.11176

8 months ago

0.0.9707

11 months ago

0.0.9178

1 year ago

0.0.9183

1 year ago

0.0.9233

1 year ago

0.0.9279

1 year ago

0.0.9195

1 year ago

0.0.6338

1 year ago

0.0.7428

1 year ago

0.0.8913

1 year ago

0.0.5962

1 year ago

0.0.7544

1 year ago

0.0.7501

1 year ago

0.0.6332

1 year ago

0.0.7862

1 year ago

0.0.7620

1 year ago

0.0.7067

1 year ago

0.0.8594

1 year ago

0.0.7462

1 year ago

0.0.6890

1 year ago

0.0.6927

1 year ago

0.0.7819

1 year ago

0.0.6849

1 year ago

0.0.7515

1 year ago

0.0.6504

1 year ago

0.0.7315

1 year ago

0.0.8648

1 year ago

0.0.7239

1 year ago

0.0.7951

1 year ago

0.0.7554

1 year ago

0.0.8286

1 year ago

0.0.9015

1 year ago

0.0.8519

1 year ago

0.0.7689

1 year ago

0.0.7403

1 year ago

0.0.6359

1 year ago

0.0.8731

1 year ago

0.0.7369

1 year ago

0.0.7520

1 year ago

0.0.8611

1 year ago

0.0.9023

1 year ago

0.0.8373

1 year ago

0.0.6193

1 year ago

0.0.6829

1 year ago

0.0.5859

1 year ago

0.0.7857

1 year ago

0.0.7018

1 year ago

0.0.6403

1 year ago

0.0.7335

1 year ago

0.0.7897

1 year ago

0.0.5871

1 year ago

0.0.8622

1 year ago

0.0.7576

1 year ago

0.0.6044

1 year ago

0.0.6320

1 year ago

0.0.7373

1 year ago

0.0.6285

1 year ago

0.0.8063

1 year ago

0.0.8936

1 year ago

0.0.5696

1 year ago

0.0.5635

1 year ago

0.0.5566

1 year ago

0.0.5551

1 year ago

0.0.5450

1 year ago

0.0.5431

1 year ago

0.0.5404

1 year ago

0.0.5409

1 year ago

0.0.5201

2 years ago

0.0.5189

2 years ago

0.0.5110

2 years ago

0.0.5053

2 years ago

0.0.5060

2 years ago

0.0.5024

2 years ago

0.0.4993

2 years ago

0.0.4991

2 years ago

0.0.4870

2 years ago

0.0.4806

2 years ago

0.0.4804

2 years ago

0.0.4801

2 years ago

0.0.4779

2 years ago

0.0.4775

2 years ago

0.0.4722

2 years ago

0.0.4721

2 years ago

0.0.4730

2 years ago

0.0.4724

2 years ago

0.0.4723

2 years ago

0.0.4624

2 years ago

0.0.4540

2 years ago

0.0.4529

2 years ago

0.0.4539

2 years ago

0.0.4470

2 years ago

0.0.1

2 years ago