Skip to content

Commit

Permalink
feat: ability to have different date formats in date picker input
Browse files Browse the repository at this point in the history
  • Loading branch information
AssisrMatheus committed Dec 8, 2022
1 parent 1426e3e commit d6a69df
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 12 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,6 @@ storybook-static

RELEASE.md

out*
out*

safelist.txt
2 changes: 2 additions & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
@perimetre:registry=https://npm.pkg.github.com
engine-strict=true
# Added because storybook was requiring react 17 and not 18. But the new version that supports 18 isn't out yet. That's not a problem since storybook isn't an important package for this project
legacy-peer-deps=true
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

## [9.2.1] 2022-12-08

### Added

- Added the ability to have different date formats in date picker input

## [9.2.0] 2022-12-07

### Added
Expand Down
60 changes: 56 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@perimetre/ui",
"description": "A component library made by @perimetre",
"version": "9.2.0",
"version": "9.2.1",
"repository": {
"type": "git",
"url": "git+https://github.com/perimetre/ui.git"
Expand Down Expand Up @@ -58,6 +58,7 @@
"@fortawesome/free-regular-svg-icons": "^6.2.0",
"@fortawesome/free-solid-svg-icons": "^6.2.0",
"@fortawesome/react-fontawesome": "^0.2.0",
"@perimetre/helpers": "^1.2.1",
"@rollup/plugin-commonjs": "^23.0.0",
"@rollup/plugin-json": "^5.0.0",
"@rollup/plugin-node-resolve": "^15.0.0",
Expand Down
29 changes: 26 additions & 3 deletions src/components/DatePickerInput/DateField.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { createCalendar, DateValue } from '@internationalized/date';
import React, { useRef } from 'react';
import React, { useMemo, useRef } from 'react';
import { replaceIntoArray } from '@perimetre/helpers';
import { AriaDateFieldProps, useDateField, useDateSegment } from 'react-aria';
import { DateFieldState, DateSegment as DateSegmentType, useDateFieldState } from 'react-stately';

Expand Down Expand Up @@ -60,15 +61,20 @@ type DateFieldProps<T extends DateValue = DateValue> = AriaDateFieldProps<T> & {
* The current app locale
*/
locale: string;
/**
* A string that defines the order of the segments
*/
format?: string;
};

/**
* Renders all segments for a inner section of a date field
*
* @param props The props for the inner date field
* @param props.locale The current app locale
* @param props.format A string that defines the order of the segments
*/
export const DateField: React.FC<DateFieldProps> = ({ locale, ...props }) => {
export const DateField: React.FC<DateFieldProps> = ({ locale, format, ...props }) => {
const ref = useRef<HTMLDivElement>(null);

const state = useDateFieldState({
Expand All @@ -77,10 +83,27 @@ export const DateField: React.FC<DateFieldProps> = ({ locale, ...props }) => {
createCalendar
});
const { fieldProps } = useDateField(props, state, ref);
const { segments } = state;

const order = useMemo(() => format?.split('/').map((x) => (x === '' ? 'literal' : x)), [format]);
const orderedSegments = useMemo(() => {
if (!order) {
return segments;
}

return segments.reduce((incoming, curr, index) => {
if (curr.type === 'literal') {
return replaceIntoArray(incoming, index, curr);
} else {
const foundIndex = order.findIndex((item) => item === curr.type);
return replaceIntoArray(incoming, foundIndex, curr);
}
}, Array(segments.length).fill(null) as DateSegmentType[]);
}, [segments, order]);

return (
<div {...fieldProps} ref={ref} className="flex">
{state.segments.map((segment, i) => (
{orderedSegments.map((segment, i) => (
<DateSegment key={i} segment={segment} state={state} />
))}
</div>
Expand Down
5 changes: 5 additions & 0 deletions src/components/DatePickerInput/DatePickerInput.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ const Template: Story<DatePickerProps & { color?: string }> = ({ color, classNam

export const Text = Template.bind({});

export const LocalizedDate = Template.bind({});
LocalizedDate.args = {
format: 'year//month//day'
};

export const BorderedPrimary = Template.bind({});
BorderedPrimary.args = {
variant: 'bordered'
Expand Down
8 changes: 7 additions & 1 deletion src/components/DatePickerInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ export type DatePickerProps<T extends DateValue = DateValue> = AriaDatePickerPro
* The input className
*/
className?: string;
/**
* A string that defines the order of the segments
*/
format?: string;
};

/**
Expand All @@ -87,6 +91,7 @@ export type DatePickerProps<T extends DateValue = DateValue> = AriaDatePickerPro
* @param props.locale The current app locale
* @param props.containerClassName The classname string prepended to the input container className
* @param props.className The input className
* @param props.format A string that defines the order of the segments
*/
//! Do not destructure label from props since useDatePicker also expects it
export const DatePickerInput: React.FC<DatePickerProps> = ({
Expand All @@ -98,6 +103,7 @@ export const DatePickerInput: React.FC<DatePickerProps> = ({
locale,
containerClassName,
className,
format,
...props
}) => {
const ref = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -150,7 +156,7 @@ export const DatePickerInput: React.FC<DatePickerProps> = ({
)}
>
{/* The input content, eg the date segments like day, month, year */}
<DateField locale={locale} {...fieldProps} />
<DateField locale={locale} format={format} {...fieldProps} />
</div>
</span>
<Tooltip
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ const Template: Story<DateRangePickerProps & { color?: string }> = ({ color, cla

export const Text = Template.bind({});

export const LocalizedDate = Template.bind({});
LocalizedDate.args = {
format: 'year//month//day'
};

export const BorderedPrimary = Template.bind({});
BorderedPrimary.args = {
variant: 'bordered'
Expand Down
10 changes: 8 additions & 2 deletions src/components/DateRangePickerInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ export type DateRangePickerProps<T extends DateValue = DateValue> = AriaDateRang
* The input className
*/
className?: string;
/**
* A string that defines the order of the segments
*/
format?: string;
};

/**
Expand All @@ -85,6 +89,7 @@ export type DateRangePickerProps<T extends DateValue = DateValue> = AriaDateRang
* @param props.locale The current app locale
* @param props.containerClassName The classname string prepended to the input container className
* @param props.className The input className
* @param props.format A string that defines the order of the segments
*/
//! Do not destructure label from props since useDatePicker also expects it
export const DateRangePickerInput: React.FC<DateRangePickerProps> = ({
Expand All @@ -96,6 +101,7 @@ export const DateRangePickerInput: React.FC<DateRangePickerProps> = ({
locale,
containerClassName,
className,
format,
...props
}) => {
const ref = useRef<HTMLDivElement>(null);
Expand Down Expand Up @@ -149,11 +155,11 @@ export const DateRangePickerInput: React.FC<DateRangePickerProps> = ({
)}
>
{/* The input content, eg the date segments like day, month, year */}
<DateField locale={locale} {...startFieldProps} />
<DateField locale={locale} format={format} {...startFieldProps} />
<span aria-hidden="true" className="px-2">
-
</span>
<DateField locale={locale} {...endFieldProps} />
<DateField locale={locale} format={format} {...endFieldProps} />
</div>
</span>
<Tooltip
Expand Down

0 comments on commit d6a69df

Please sign in to comment.