Skip to content

Commit

Permalink
test(DateTime): align the tests and documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
jlopezcur committed Jul 11, 2024
1 parent d7b2d69 commit 8585936
Show file tree
Hide file tree
Showing 22 changed files with 29,581 additions and 6,986 deletions.
1 change: 1 addition & 0 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ const config: StorybookConfig = {
'react-toastify',
'react-select',
'react-split',
'react-mermaid2',
'ahooks',
'react-windowed-select',
'@dnd-kit/sortable',
Expand Down
3 changes: 2 additions & 1 deletion oxlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"browser": true
},
"rules": {
"no-inner-declaration": "error"
"no-inner-declaration": "error",
"no-console": "error"
}
}
36,043 changes: 29,265 additions & 6,778 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
"prettier": "^3.3.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-mermaid2": "^0.1.4",
"react-syntax-highlighter": "^15.5.0",
"release-it": "^16.2.1",
"remark-gfm": "^4.0.0",
Expand Down
171 changes: 66 additions & 105 deletions packages/datetime/src/components/Calendar/Calendar.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,6 @@ The Calendar has several main concepts as props:
of Calendar one for a single day, two for a range.
- `monthDate`: This is the date for the month that is showed (could be different
from the selected dates).
- `hasLeftHoverEffect` & `hasRightHoverEffect`: are booleans that define if the
hover behavior take the range into consideration.
- `parseDate`: is a function that resolve into a parse result object, that take
each calendar day and use this function to know if the day is available or
not. An example could be:

<Source language="tsx" code={`export const parseDateNoFuture = (dt: Date | number): IParseResult => {
const result = compareDesc(dt, new Date().getTime());
const isValid = result >= 0;
return {
isValid: isValid,
value: dt,
errors: isValid ? [] : ['Date is invalid'],
};
};`} />

This is an example of range selected dates:

Expand All @@ -55,25 +40,55 @@ This is an example of single selected date:
## Disable days

For disable days we can use two mechanism:
- `parseDate` function that let us define the invalid days and a message for the
user to know why are these days invalid
- or `minDate` and `maxDate` properties that let us define limits for the
selectable days

Lets see an example with a `parseDate` that avoid the even days and the weekend
days:
### `minDate` and `maxDate`

Are properties that let us define limits for the selectable days

<Canvas of={Stories.MinMaxDate} />

### `parseDate`

Is a function that resolve into a parse result object, that take each calendar
day and use this function to know if the day is available or not. An example
could be:

<Source language="tsx" code={`export const parseDateNoFuture = (dt: Date | number): IParseResult => {
const now = new Date().getTime();
const ts = getTime(dt); // Function for get epoch ts from dt
const isValid = ts <= now;
return {
isValid: isValid,
value: dt,
errors: isValid ? [] : ['Date is invalid'],
};
};`} />

Lets see another example with a `parseDate` that avoid the even days and the
weekend days:

<Canvas of={Stories.ParseDate} />

And another example but with `minDate` and `maxDate`:
### `disabled`

<Canvas of={Stories.MinMaxDate} />
Is property for disable all the calendar

<Canvas of={Stories.Disabled} />

## Events

This component has one main event:

- `onChange`: when the user click on any day
- `onClick`: when the user click on any selectable day

<Source language="tsx" code={`...
onClick: (ts: number) => {
// Here you can update the Calendar value with a state for example
setValue(ts);
// And let you build any pre-filter or advanced mechanism before update the
// calendar
},
...`} />

## I18n

Expand All @@ -82,117 +97,63 @@ We can use the next props for internacionalization:
- `weekDays`: array of week days for the header, staring on Sunday
- `weekStart`: number of the week day that would bi the first (0 - Sunday, 1 -
Monday)
- `i18.outOfRange`: text for the tooltip that is shown when the user hover a day
that are out of range using the `minDate` or the `maxDate`

Here is an example of the *Spanish* version:

<Canvas of={Stories.I18n} />

## Hooks

These hooks provide pre-defined behaviors to be applied in the Calendar component.
Each hook returns an object with values that can be passed to the Calendar component.

<Source
code={`
{
range, // range Calendar property
onRangeChange, // onClick handler Calendar property
hasLeftHoverEffect, // hasLeftHoverEffect Calendar property
hasRightHoverEffect, // hasRightHoverEffect Calendar property
}
`}
/>
These hooks helps to apply the two main line of action with the calendar, the
single selection or the range selection.

### Single Hook
### `useCalendarSingle`

Defines a single day selection in the calendar.
Accepts a timestamp with the default day selected.
Accepts a `number` or `Date` with the selected day.

<Canvas of={Stories.SingleHook} />

#### Parameters

<Source
code={`
[day] // Initial day selected
`}
/>

#### Usage

<Source
code={`
import { useCalendarSingle } from '@devoinc/genesys-ui-datetime';
const {
range,
onRangeChange,
hasLeftHoverEffect,
hasRightHoverEffect,
} = useCalendarSingle([day]);
<Calendar
range={range}
hasLeftHoverEffect={hasLeftHoverEffect}
hasRightHoverEffect={hasRightHoverEffect}
onClick={onRangeChange}
`}
/>

### Range Hook
### `useCalendarRange`

Defines a way to select a range of days in which the range can be expanded
either forward or backward. Once the range has been selected, to expand the
range it must be done in a cell opposite the last selection. If the cell
selection is between the range, the end day of the range will be changed.
Otherwise, the range of days to be selected will be restarted.
Defines a way to select a range of days. The hook use the first click as one
point of the range (could be the start or the end), and a second click with the
other point of the range, with this last point the hook decide with point is the
start and witch point is the end of the range

<Canvas of={Stories.RangeHook} />

#### Parameters

<Source
code={`
[
from, // Initial day of the range
to, // Final day of the range
]: (number | Date)[],
initialBehavior: 'forward' | 'backward'
`}
/>

#### Usage

<Source
code={`
import { useCalendarRange } from '@devoinc/genesys-ui-datetime';
## `rangeBehavior` helper

const {
handleDateChange,
hasLeftHoverEffect,
hasRightHoverEffect,
selectedDates
} = useCalendarForwardBackward([from, to], initialBehavior);
`}
/>

#### Helper
If you would like to build your own hooks you could the main behavior of the
`useCalendarRange` is the next helper function:

If you would like to build your own hooks you could use:

<Source
code={`import { rangeBehavior } from '@devoinc/genesys-ui-datetime';
<Source code={`import { rangeBehavior } from '@devoinc/genesys-ui-datetime';
...
const newRange = rangeBehavior(
[
from: number | Date,
to: number | Date
],
newDate: number | Date,
);
...
`}
/>

This function take a range (empty, incomplete or complete), a new date and
return the next step of the range:

- If empty range is passed the function returns the incomplete range with a
single point
- If incomplete range is passed (only one point), the function returns a
complete range with the two points ordered in ascendant mode
- If complete range is passed, the function returns a new incomplete range with
a single point

## Props

<ArgTypes of={Stories} />
16 changes: 13 additions & 3 deletions packages/datetime/src/components/Calendar/Calendar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,28 @@ export const MinMaxDate: Story = {
})(),
};

export const Disabled: Story = {
tags: ['isHidden'],
args: {
disabled: true,
monthDate: now,
value: singleValue,
},
};

export const I18n: Story = {
tags: ['isHidden'],
args: {
weekDays: ['Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sa'],
weekStart: 1,
monthDate: now,
value: singleValue,
maxDate: set(now, { date: 20 }),
i18n: {
outOfRange: 'Fuera de rango',
},
},
};
I18n.storyName = 'I18n';

export const SingleHook: Story = {
tags: ['isHidden'],
Expand All @@ -101,8 +113,6 @@ export const SingleHook: Story = {
return (
<Calendar
monthDate={now}
hasLeftHoverEffect={false}
hasRightHoverEffect={false}
value={range}
onClick={handleNewDate}
/>
Expand Down
18 changes: 12 additions & 6 deletions packages/datetime/src/components/Calendar/Calendar.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import * as React from 'react';
import { useTheme } from 'styled-components';
import { getTime, lastDayOfMonth as lastDayOfMonthFNS } from 'date-fns';
import { lastDayOfMonth as lastDayOfMonthFNS } from 'date-fns';

import { getClassNameFromProperties, getDayProperties } from './day';
import {
getClassNameFromProperties,
getDayProperties,
getTo,
getFrom,
} from './day';
import { getMonthDays, getPrevDays } from './month';
import {
type IGlobalAriaAttrs,
Expand Down Expand Up @@ -89,6 +94,7 @@ export const InternalCalendar: React.FC<CalendarProps> = ({
minDate,
maxDate,
i18n: userI18n = defaultCalendarI18n,
disabled = false,
}) => {
const i18n = useMergeI18n(userI18n, defaultCalendarI18n) as TCalendarI18n;
const theme = useTheme();
Expand Down Expand Up @@ -124,7 +130,7 @@ export const InternalCalendar: React.FC<CalendarProps> = ({
aria-describedby={ariaDescribedby}
aria-details={ariaDetails}
aria-hidden={ariaHidden}
aria-lable={ariaLabel}
aria-label={ariaLabel}
aria-labelledby={ariaLabelledby}
as={as}
id={id}
Expand All @@ -147,8 +153,8 @@ export const InternalCalendar: React.FC<CalendarProps> = ({
{getMonthDays(monthDate)
.map(
getDayProperties(
getTime(value[0] ?? 0),
getTime(value[1] ?? value[0] ?? 0),
getFrom(value),
getTo(value),
lastDayOfMonth,
parseDate,
hoverDay,
Expand All @@ -170,7 +176,7 @@ export const InternalCalendar: React.FC<CalendarProps> = ({
onMouseLeave={onMouseLeaveCallback}
ts={dayProps.ts}
value={String(dayProps.monthDay)}
disabled={dayProps.isDisabled}
disabled={disabled || dayProps.isDisabled}
label={dateRepr(dayProps.ts)}
tooltip={
dayProps.isDisabled
Expand Down
Loading

0 comments on commit 8585936

Please sign in to comment.