agroptima-design-system 0.28.7 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agroptima-design-system",
3
- "version": "0.28.7",
3
+ "version": "0.29.0",
4
4
  "scripts": {
5
5
  "dev": "npm run storybook",
6
6
  "storybook": "storybook dev -p 6006 --ci",
@@ -1,8 +1,8 @@
1
- @use '../settings/color_alias';
2
- @use '../settings/typography/content' as typography;
3
- @use '../settings/config';
4
- @use '../settings/depth';
5
- @use '../settings/breakpoints';
1
+ @use '../../settings/color_alias';
2
+ @use '../../settings/typography/content' as typography;
3
+ @use '../../settings/config';
4
+ @use '../../settings/depth';
5
+ @use '../../settings/breakpoints';
6
6
 
7
7
  // Interpolation applied: https://sass-lang.com/documentation/breaking-changes/css-vars/
8
8
 
@@ -0,0 +1,102 @@
1
+ import 'react-day-picker/style.css'
2
+ import './DateRangePicker.scss'
3
+ import { useEffect, useState } from 'react'
4
+ import { type DateRange, DayPicker, type Locale } from 'react-day-picker'
5
+ import { enGB, es } from 'react-day-picker/locale'
6
+ import { classNames } from '../../utils/classNames'
7
+ import {
8
+ formatDatePickerFooterDate,
9
+ formatDatePickerParamsDate,
10
+ } from '../../utils/dateHelpers'
11
+ import { translations } from './translations'
12
+
13
+ export type Variant = 'primary'
14
+
15
+ type DivPropsWithoutOnSelect = Omit<
16
+ React.ComponentPropsWithoutRef<'div'>,
17
+ 'onSelect'
18
+ >
19
+
20
+ interface AvailableLocale {
21
+ [index: string]: Locale
22
+ }
23
+
24
+ const availableLocales: AvailableLocale = {
25
+ es: es,
26
+ en: enGB,
27
+ }
28
+
29
+ export interface DateRangePickerProps extends DivPropsWithoutOnSelect {
30
+ variant?: Variant
31
+ onSelect: (dateRange: DateRange | undefined) => void
32
+ selected?: DateRange
33
+ lng: keyof typeof availableLocales
34
+ }
35
+
36
+ export function DateRangePicker({
37
+ className,
38
+ variant = 'primary',
39
+ onSelect = () => {},
40
+ selected: preselected,
41
+ lng,
42
+ }: DateRangePickerProps): React.JSX.Element {
43
+ const manageFooterText = (): string => {
44
+ const hasDatesFilter = selected && selected.from && selected.to
45
+ const isExactDate =
46
+ formatDatePickerParamsDate(selected?.from) ===
47
+ formatDatePickerParamsDate(selected?.to)
48
+
49
+ if (!hasDatesFilter) return translations[lng].pickDate
50
+
51
+ if (isExactDate) {
52
+ return translations[lng].selectedDate.replace(
53
+ '${date}',
54
+ formatDatePickerFooterDate(selected.from, lng as string),
55
+ )
56
+ }
57
+
58
+ return translations[lng].selectedRangeOfDates
59
+ .replace(
60
+ '${from}',
61
+ formatDatePickerFooterDate(selected.from, lng as string),
62
+ )
63
+ .replace('${to}', formatDatePickerFooterDate(selected.to, lng as string))
64
+ }
65
+
66
+ const [selected, setSelected] = useState<DateRange | undefined>(preselected)
67
+ const [footer, setFooter] = useState<string>(() => {
68
+ return manageFooterText()
69
+ })
70
+ const cssClasses = classNames('date-picker', variant, className)
71
+
72
+ useEffect(() => {
73
+ setSelected(preselected)
74
+ setFooter(manageFooterText())
75
+ // eslint-disable-next-line react-hooks/exhaustive-deps
76
+ }, [preselected])
77
+
78
+ function selectDate(dateRange: DateRange | undefined) {
79
+ const isSingleDaySelection = dateRange && !dateRange.to
80
+
81
+ if (isSingleDaySelection) {
82
+ dateRange.to = dateRange.from
83
+ }
84
+
85
+ setSelected(dateRange)
86
+ onSelect(dateRange)
87
+ }
88
+
89
+ return (
90
+ <div className={cssClasses}>
91
+ <DayPicker
92
+ locale={availableLocales[lng]}
93
+ mode="range"
94
+ min={1}
95
+ selected={selected}
96
+ onSelect={(dateRange) => selectDate(dateRange)}
97
+ footer={footer}
98
+ defaultMonth={selected?.from}
99
+ />
100
+ </div>
101
+ )
102
+ }
@@ -0,0 +1,16 @@
1
+ interface Translation {
2
+ [index: string]: { [index: string]: string }
3
+ }
4
+
5
+ export const translations: Translation = {
6
+ en: {
7
+ pickDate: 'Pick a day or a range of dates',
8
+ selectedDate: 'Selected date: ${date}',
9
+ selectedRangeOfDates: 'Selected dates range: from ${from} to ${to}',
10
+ },
11
+ es: {
12
+ pickDate: 'Selecciona un día o un rango de fechas',
13
+ selectedDate: 'Fecha seleccionada: ${date}',
14
+ selectedRangeOfDates: 'Rango de fechas seleccionado: desde ${from} a ${to}',
15
+ },
16
+ }
@@ -4,10 +4,14 @@ import { Meta } from "@storybook/blocks";
4
4
 
5
5
  # Changelog
6
6
 
7
- ## 0.28.7
7
+ ## 0.29.0
8
8
 
9
9
  * Add Divider component
10
10
 
11
+ ## 0.28.7
12
+
13
+ * DateRangePicker component manages its footer text
14
+
11
15
  ## 0.28.6
12
16
 
13
17
  * Remove overflow-x from html element for Modal component.
@@ -1,9 +1,9 @@
1
1
  import type { StoryObj } from '@storybook/react'
2
- import { DatePicker } from '../atoms/DatePicker'
2
+ import { DateRangePicker } from '../atoms/DatePicker/DateRangePicker'
3
3
 
4
4
  const meta = {
5
- title: 'Design System/Atoms/DatePicker',
6
- component: DatePicker,
5
+ title: 'Design System/Atoms/DateRangePicker',
6
+ component: DateRangePicker,
7
7
  tags: ['autodocs'],
8
8
  argTypes: {
9
9
  footer: {
@@ -34,10 +34,9 @@ const figmaPrimaryDesign = {
34
34
  export default meta
35
35
  type Story = StoryObj<typeof meta>
36
36
 
37
- export const PrimaryDateRange: Story = {
37
+ export const Primary: Story = {
38
38
  args: {
39
39
  variant: 'primary',
40
- footer: 'Pick a day.',
41
40
  onSelect: (date) => console.log('onSelect date:', date),
42
41
  lng: 'en',
43
42
  },
@@ -47,10 +46,19 @@ export const PrimaryDateRange: Story = {
47
46
  export const WithDateRangeSelected: Story = {
48
47
  args: {
49
48
  variant: 'primary',
50
- footer: 'From 2024-02-02 to 2024-02-15',
51
49
  onSelect: (date) => console.log('onSelect date:', date),
52
50
  selected: { from: new Date(2024, 1, 2), to: new Date(2024, 1, 15) },
53
51
  lng: 'en',
54
52
  },
55
53
  parameters: figmaPrimaryDesign,
56
54
  }
55
+
56
+ export const WithSingleDaySelected: Story = {
57
+ args: {
58
+ variant: 'primary',
59
+ onSelect: (date) => console.log('onSelect date:', date),
60
+ selected: { from: new Date(2024, 1, 2), to: new Date(2024, 1, 2) },
61
+ lng: 'en',
62
+ },
63
+ parameters: figmaPrimaryDesign,
64
+ }
@@ -1,7 +1,7 @@
1
1
  import React from 'react'
2
2
  import { CheckableTag, CheckableTagGroup } from '../atoms/CheckableTag'
3
3
  import { Collapsible } from '../atoms/Collapsible'
4
- import { DatePicker } from '../atoms/DatePicker'
4
+ import { DateRangePicker } from '../atoms/DatePicker/DateRangePicker'
5
5
  import { Drawer } from '../atoms/Drawer'
6
6
 
7
7
  const figmaPrimaryDesign = {
@@ -122,10 +122,10 @@ export const Filters = {
122
122
  </Collapsible>
123
123
  <Collapsible noHorizontalPadding open title="Date">
124
124
  <div style={{ display: 'flex', justifyContent: 'center' }}>
125
- <DatePicker
126
- footer="From 2024-01-01 to 2024-01-15"
125
+ <DateRangePicker
127
126
  selected={{ from: new Date(2025, 0, 1), to: new Date(2025, 0, 15) }}
128
127
  onSelect={(date) => console.log('date: ', date)}
128
+ lng="en"
129
129
  />
130
130
  </div>
131
131
  </Collapsible>
@@ -0,0 +1,19 @@
1
+ export function formatDate(date: string, lng: string) {
2
+ if (!date) return ''
3
+ return new Date(date).toLocaleDateString(lng)
4
+ }
5
+
6
+ export function formatDatePickerParamsDate(date: Date | undefined) {
7
+ if (!date) return ''
8
+
9
+ return date.toLocaleDateString('sv-SE')
10
+ }
11
+
12
+ export function formatDatePickerFooterDate(
13
+ date: Date | undefined,
14
+ lng: string,
15
+ ) {
16
+ if (!date) return ''
17
+
18
+ return formatDate(formatDatePickerParamsDate(date), lng)
19
+ }
@@ -1,12 +1,11 @@
1
- import { render } from '@testing-library/react'
1
+ import { getAllByRole, render } from '@testing-library/react'
2
2
  import React from 'react'
3
- import { DatePicker } from '../src/atoms/DatePicker'
3
+ import { DateRangePicker } from '../src/atoms/DatePicker/DateRangePicker'
4
4
 
5
- describe('DatePicker', () => {
5
+ describe('DateRangePicker', () => {
6
6
  it('renders with expected footer, language and month', () => {
7
7
  const { getByText } = render(
8
- <DatePicker
9
- footer="From 2024-01-01 to 2024-01-15"
8
+ <DateRangePicker
10
9
  selected={{ from: new Date(2025, 0, 1), to: new Date(2025, 0, 15) }}
11
10
  onSelect={() => jest.fn()}
12
11
  lng={'es'}
@@ -20,6 +19,8 @@ describe('DatePicker', () => {
20
19
  expect(getByText('vi')).toBeInTheDocument()
21
20
  expect(getByText('sá')).toBeInTheDocument()
22
21
  expect(getByText('do')).toBeInTheDocument()
23
- expect(getByText('From 2024-01-01 to 2024-01-15')).toBeInTheDocument()
22
+ expect(
23
+ getByText('Rango de fechas seleccionado: desde 1/1/2025 a 15/1/2025'),
24
+ ).toBeInTheDocument()
24
25
  })
25
26
  })
@@ -1,66 +0,0 @@
1
- import 'react-day-picker/style.css'
2
- import './DatePicker.scss'
3
- import { useEffect, useState } from 'react'
4
- import { type DateRange, DayPicker, type Locale } from 'react-day-picker'
5
- import { enGB, es } from 'react-day-picker/locale'
6
- import { classNames } from '../utils/classNames'
7
-
8
- export type Variant = 'primary'
9
-
10
- type DivPropsWithoutOnSelect = Omit<
11
- React.ComponentPropsWithoutRef<'div'>,
12
- 'onSelect'
13
- >
14
-
15
- interface AvailableLocale {
16
- [index: string]: Locale
17
- }
18
-
19
- const availableLocales: AvailableLocale = {
20
- es: es,
21
- en: enGB,
22
- }
23
-
24
- export interface DatePickerProps extends DivPropsWithoutOnSelect {
25
- variant?: Variant
26
- onSelect: (dateRange: DateRange | undefined) => void
27
- footer: string
28
- selected?: DateRange
29
- lng: keyof typeof availableLocales
30
- }
31
-
32
- export function DatePicker({
33
- className,
34
- variant = 'primary',
35
- onSelect = () => {},
36
- footer = 'Pick a day',
37
- selected: preselected,
38
- lng,
39
- }: DatePickerProps): React.JSX.Element {
40
- useEffect(() => {
41
- setSelected(preselected)
42
- }, [preselected])
43
-
44
- const cssClasses = classNames('date-picker', variant, className)
45
-
46
- const [selected, setSelected] = useState<DateRange | undefined>(preselected)
47
-
48
- function selectDate(dateRange: DateRange | undefined) {
49
- setSelected(dateRange)
50
- onSelect(dateRange)
51
- }
52
-
53
- return (
54
- <div className={cssClasses}>
55
- <DayPicker
56
- locale={availableLocales[lng]}
57
- mode="range"
58
- min={1}
59
- selected={selected}
60
- onSelect={(dateRange) => selectDate(dateRange)}
61
- footer={footer}
62
- defaultMonth={selected?.from}
63
- />
64
- </div>
65
- )
66
- }