Skip to content

Commit

Permalink
feat: added support for the Formatting of the Date
Browse files Browse the repository at this point in the history
  • Loading branch information
dhavalveera committed Mar 25, 2024
1 parent eed9d1e commit fb35e8c
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 10 deletions.
8 changes: 8 additions & 0 deletions apps/web/content/docs/components/datepicker.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ Use this example to show a simple datepicker component.

<Example name="datepicker.root" />

## Formatted Date

Use this `inputFormat` prop to set the format of the datepicker component to be displayed

**Note:** don't use `DD` instead use `dd` and also for year don't use `YYYY` instead use `yyyy`

<Example name="datepicker.format" />

## Localization

Use the `language` prop to set the language of the datepicker component.
Expand Down
42 changes: 42 additions & 0 deletions apps/web/examples/datepicker/datepicker.format.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { type CodeData } from '~/components/code-demo';
import { Datepicker } from 'flowbite-react';

const code = `
'use client';
import { Datepicker } from 'flowbite-react';
function Component() {
return <Datepicker inputFormat='dd-MMM-yyyy' />;
}
`;

const codeRSC = `
import { Datepicker } from 'flowbite-react';
function Component() {
return <Datepicker inputFormat='dd-MMM-yyyy' />;
}
`;

function Component() {
return <Datepicker inputFormat="dd-MMM-yyyy" />;
}

export const format: CodeData = {
type: 'single',
code: [
{
fileName: 'client',
language: 'tsx',
code,
},
{
fileName: 'server',
language: 'tsx',
code: codeRSC,
},
],
githubSlug: 'datepicker/datepicker.format.tsx',
component: <Component />,
};
1 change: 1 addition & 0 deletions apps/web/examples/datepicker/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { autoHide } from "./datepicker.autoHide";
export { format } from './datepicker.format';
export { inline } from "./datepicker.inline";
export { localization } from "./datepicker.localization";
export { range } from "./datepicker.range";
Expand Down
Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
"dev": "",
"format": "prettier . --write",
"format:check": "prettier .",
"postinstall": "bun run build",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"prepack": "clean-package",
Expand Down Expand Up @@ -76,6 +75,7 @@
"@vitejs/plugin-react": "4.2.1",
"@vitest/coverage-v8": "1.4.0",
"clean-package": "2.2.0",
"date-fns": "^3.6.0",
"eslint-plugin-react": "7.34.1",
"eslint-plugin-storybook": "0.8.0",
"eslint-plugin-vitest": "0.3.26",
Expand Down
16 changes: 12 additions & 4 deletions packages/ui/src/components/Datepicker/Datepicker.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { getFormattedDate } from "./helpers";

describe("Components / Datepicker", () => {
it("should display today's date by default", () => {
const todaysDateInDefaultLanguage = getFormattedDate("en", new Date());
const todaysDateInDefaultLanguage = getFormattedDate("en", new Date(), 'dd-MMM-yyy');

render(<Datepicker />);

Expand All @@ -28,7 +28,7 @@ describe("Components / Datepicker", () => {
});

it("should reset to today's date when Clear button is clicked", async () => {
const todaysDateInDefaultLanguage = getFormattedDate("en", new Date());
const todaysDateInDefaultLanguage = getFormattedDate("en", new Date(), 'dd-MMM-yyy');
const todaysDayOfMonth = new Date().getDate();
const anotherDay = todaysDayOfMonth === 1 ? 2 : 1;

Expand All @@ -43,7 +43,7 @@ describe("Components / Datepicker", () => {
});

it("should use today's date when Today button is clicked", async () => {
const todaysDateInDefaultLanguage = getFormattedDate("en", new Date());
const todaysDateInDefaultLanguage = getFormattedDate("en", new Date(), 'dd-MMM-yyy');
const todaysDayOfMonth = new Date().getDate();
const anotherDay = todaysDayOfMonth === 1 ? 2 : 1;

Expand Down Expand Up @@ -90,7 +90,7 @@ describe("Components / Datepicker", () => {
});

it("should clear the value when ref.current.clear is called", async () => {
const todaysDateInDefaultLanguage = getFormattedDate("en", new Date());
const todaysDateInDefaultLanguage = getFormattedDate("en", new Date(), 'dd-MMM-yyyy');
const todaysDayOfMonth = new Date().getDate();
const anotherDay = todaysDayOfMonth === 1 ? 2 : 1;

Expand All @@ -105,4 +105,12 @@ describe("Components / Datepicker", () => {

expect(screen.getByDisplayValue(todaysDateInDefaultLanguage)).toBeInTheDocument();
});

it("should display today's date in dd-MMM-yyyy format", () => {
const todaysDateInDefaultLanguage = getFormattedDate('en-US', new Date(), 'dd-MMM-yyyy');

render(<Datepicker inputFormat="dd-MMM-yyyy" />);

expect(screen.getByDisplayValue(todaysDateInDefaultLanguage)).toBeInTheDocument();
});
});
15 changes: 15 additions & 0 deletions packages/ui/src/components/Datepicker/Datepicker.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,18 @@ Default.args = {
weekStart: WeekStart.Sunday,
theme: {},
};

export const FormattedDate = Template.bind({})
FormattedDate.args = {
open: false,
autoHide: true,
showClearButton: true,
showTodayButton: true,
defaultDate: new Date(),
minDate: undefined,
maxDate: undefined,
language: "en",
weekStart: WeekStart.Sunday,
theme: {},
inputFormat: 'dd MMM yyyy'
};
8 changes: 5 additions & 3 deletions packages/ui/src/components/Datepicker/Datepicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export interface DatepickerProps extends Omit<TextInputProps, "theme"> {
weekStart?: WeekStart;
theme?: DeepPartial<FlowbiteDatepickerTheme>;
onSelectedDateChanged?: (date: Date) => void;
inputFormat?: string;
}

const DatepickerRender: ForwardRefRenderFunction<DatepickerRef, DatepickerProps> = (
Expand All @@ -117,6 +118,7 @@ const DatepickerRender: ForwardRefRenderFunction<DatepickerRef, DatepickerProps>
className,
theme: customTheme = {},
onSelectedDateChanged,
inputFormat = 'dd-MMM-yyyy',
...props
},
ref,
Expand Down Expand Up @@ -201,10 +203,10 @@ const DatepickerRender: ForwardRefRenderFunction<DatepickerRef, DatepickerProps>
case Views.Years:
return `${startOfYearPeriod(viewDate, 10)} - ${startOfYearPeriod(viewDate, 10) + 9}`;
case Views.Months:
return getFormattedDate(language, viewDate, { year: "numeric" });
return getFormattedDate(language, viewDate, inputFormat, { year: "numeric" });
case Views.Days:
default:
return getFormattedDate(language, viewDate, { month: "long", year: "numeric" });
return getFormattedDate(language, viewDate, inputFormat, { month: "long", year: "numeric" });
}
};

Expand Down Expand Up @@ -272,7 +274,7 @@ const DatepickerRender: ForwardRefRenderFunction<DatepickerRef, DatepickerProps>
}
setIsOpen(true);
}}
value={selectedDate && getFormattedDate(language, selectedDate)}
value={selectedDate && getFormattedDate(language, selectedDate, inputFormat, {})}
readOnly
{...props}
/>
Expand Down
7 changes: 5 additions & 2 deletions packages/ui/src/components/Datepicker/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { format as DateFNSFormat } from 'date-fns';

export enum Views {
Days = 0,
Months = 1,
Expand Down Expand Up @@ -99,7 +101,7 @@ export const addYears = (date: Date, amount: number): Date => {
return newDate;
};

export const getFormattedDate = (language: string, date: Date, options?: Intl.DateTimeFormatOptions): string => {
export const getFormattedDate = (language: string, date: Date, dateFormat: string, options?: Intl.DateTimeFormatOptions,): string => {
let defaultOptions: Intl.DateTimeFormatOptions = {
day: "numeric",
month: "long",
Expand All @@ -110,7 +112,8 @@ export const getFormattedDate = (language: string, date: Date, options?: Intl.Da
defaultOptions = options;
}

return new Intl.DateTimeFormat(language, defaultOptions).format(date);
return DateFNSFormat(new Intl.DateTimeFormat(language, defaultOptions).format(date), dateFormat);

Check failure on line 115 in packages/ui/src/components/Datepicker/helpers.ts

View workflow job for this annotation

GitHub Actions / 🔬 Test

src/components/Datepicker/Datepicker.spec.tsx > Components / Datepicker > should update date when a different day is clicked

TypeError: formatStr.match is not a function ❯ Module.format ../../node_modules/date-fns/format.mjs:356:6 ❯ Module.getFormattedDate src/components/Datepicker/helpers.ts:115:12 ❯ src/components/Datepicker/Views/Days.tsx:56:23 ❯ DatepickerViewsDays src/components/Datepicker/Views/Days.tsx:54:25 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20074:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21587:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27426:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26560:12

Check failure on line 115 in packages/ui/src/components/Datepicker/helpers.ts

View workflow job for this annotation

GitHub Actions / 🔬 Test

src/components/Datepicker/Datepicker.spec.tsx > Components / Datepicker > should reset to today's date when Clear button is clicked

TypeError: formatStr.match is not a function ❯ Module.format ../../node_modules/date-fns/format.mjs:356:6 ❯ Module.getFormattedDate src/components/Datepicker/helpers.ts:115:12 ❯ src/components/Datepicker/Views/Days.tsx:56:23 ❯ DatepickerViewsDays src/components/Datepicker/Views/Days.tsx:54:25 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20074:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21587:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27426:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26560:12

Check failure on line 115 in packages/ui/src/components/Datepicker/helpers.ts

View workflow job for this annotation

GitHub Actions / 🔬 Test

src/components/Datepicker/Datepicker.spec.tsx > Components / Datepicker > should use today's date when Today button is clicked

TypeError: formatStr.match is not a function ❯ Module.format ../../node_modules/date-fns/format.mjs:356:6 ❯ Module.getFormattedDate src/components/Datepicker/helpers.ts:115:12 ❯ src/components/Datepicker/Views/Days.tsx:56:23 ❯ DatepickerViewsDays src/components/Datepicker/Views/Days.tsx:54:25 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20074:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21587:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27426:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26560:12

Check failure on line 115 in packages/ui/src/components/Datepicker/helpers.ts

View workflow job for this annotation

GitHub Actions / 🔬 Test

src/components/Datepicker/Datepicker.spec.tsx > Components / Datepicker > should call `onSelectedDateChange` when a new date is selected

TypeError: formatStr.match is not a function ❯ Module.format ../../node_modules/date-fns/format.mjs:356:6 ❯ Module.getFormattedDate src/components/Datepicker/helpers.ts:115:12 ❯ src/components/Datepicker/Views/Days.tsx:56:23 ❯ DatepickerViewsDays src/components/Datepicker/Views/Days.tsx:54:25 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20074:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21587:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27426:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26560:12

Check failure on line 115 in packages/ui/src/components/Datepicker/helpers.ts

View workflow job for this annotation

GitHub Actions / 🔬 Test

src/components/Datepicker/Datepicker.spec.tsx > Components / Datepicker > should focus the input when ref.current.focus is called

TypeError: formatStr.match is not a function ❯ Module.format ../../node_modules/date-fns/format.mjs:356:6 ❯ Module.getFormattedDate src/components/Datepicker/helpers.ts:115:12 ❯ src/components/Datepicker/Views/Days.tsx:56:23 ❯ DatepickerViewsDays src/components/Datepicker/Views/Days.tsx:54:25 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20074:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21587:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27426:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26560:12

Check failure on line 115 in packages/ui/src/components/Datepicker/helpers.ts

View workflow job for this annotation

GitHub Actions / 🔬 Test

src/components/Datepicker/Datepicker.spec.tsx > Components / Datepicker > should clear the value when ref.current.clear is called

TypeError: formatStr.match is not a function ❯ Module.format ../../node_modules/date-fns/format.mjs:356:6 ❯ Module.getFormattedDate src/components/Datepicker/helpers.ts:115:12 ❯ src/components/Datepicker/Views/Days.tsx:56:23 ❯ DatepickerViewsDays src/components/Datepicker/Views/Days.tsx:54:25 ❯ renderWithHooks ../../node_modules/react-dom/cjs/react-dom.development.js:16305:18 ❯ mountIndeterminateComponent ../../node_modules/react-dom/cjs/react-dom.development.js:20074:13 ❯ beginWork ../../node_modules/react-dom/cjs/react-dom.development.js:21587:16 ❯ beginWork$1 ../../node_modules/react-dom/cjs/react-dom.development.js:27426:14 ❯ performUnitOfWork ../../node_modules/react-dom/cjs/react-dom.development.js:26560:12

Check failure on line 115 in packages/ui/src/components/Datepicker/helpers.ts

View workflow job for this annotation

GitHub Actions / 🔬 Test

src/components/Datepicker/helpers.spec.tsx > getFormattedDate > returns the formatted date string using the default options

TypeError: Cannot read properties of undefined (reading 'match') ❯ Module.format ../../node_modules/date-fns/format.mjs:356:6 ❯ Module.getFormattedDate src/components/Datepicker/helpers.ts:115:12 ❯ src/components/Datepicker/helpers.spec.tsx:157:27

Check failure on line 115 in packages/ui/src/components/Datepicker/helpers.ts

View workflow job for this annotation

GitHub Actions / 🔬 Test

src/components/Datepicker/helpers.spec.tsx > getFormattedDate > returns the formatted date string using the specified options

TypeError: formatStr.match is not a function ❯ Module.format ../../node_modules/date-fns/format.mjs:356:6 ❯ Module.getFormattedDate src/components/Datepicker/helpers.ts:115:12 ❯ src/components/Datepicker/helpers.spec.tsx:164:27

Check failure on line 115 in packages/ui/src/components/Datepicker/helpers.ts

View workflow job for this annotation

GitHub Actions / 🔬 Test

src/components/Datepicker/helpers.spec.tsx > getFormattedDate > returns the formatted date string using the specified language

RangeError: Invalid time value ❯ Module.format ../../node_modules/date-fns/format.mjs:352:11 ❯ Module.getFormattedDate src/components/Datepicker/helpers.ts:115:12 ❯ src/components/Datepicker/helpers.spec.tsx:170:27

};

export const startOfYearPeriod = (date: Date, years: number): number => {
Expand Down

0 comments on commit fb35e8c

Please sign in to comment.