agroptima-design-system 0.31.7-beta.2 → 0.31.8

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.31.7-beta.2",
3
+ "version": "0.31.8",
4
4
  "scripts": {
5
5
  "dev": "npm run storybook",
6
6
  "storybook": "storybook dev -p 6006 --ci",
@@ -1,68 +1,111 @@
1
1
  import 'react-day-picker/style.css'
2
+ import './DatePicker.scss'
2
3
  import { useEffect, useState } from 'react'
3
- import { type DateRange, DayPicker } from 'react-day-picker'
4
- import { enGB, es } from 'react-day-picker/locale'
5
- import { formatDatePickerFooterDate } from '../../utils/dateHelpers'
6
- import type { AvailableLocale } from './DatePicker'
7
- import { translations } from './translations'
4
+ import {
5
+ type DateRange as DateRangeReactDayPicker,
6
+ DayPicker,
7
+ } from 'react-day-picker'
8
+ import { classNames } from '../../utils/classNames'
9
+ import {
10
+ formatDatePickerFooterDate,
11
+ fromDateToISOString,
12
+ fromISOToDate,
13
+ } from '../../utils/dateHelpers'
14
+ import { availableLocales, type Locale, translations } from './translations'
8
15
 
9
- const availableLocales: AvailableLocale = {
10
- es: es,
11
- en: enGB,
16
+ export type Variant = 'primary'
17
+
18
+ export type DateRangePickerProps = {
19
+ variant?: Variant
20
+ lng: Locale
21
+ required?: boolean
22
+ className?: string
23
+ defaultValue?: DateRange
24
+ onSelect?: (date: DateRange) => void
12
25
  }
13
26
 
14
- export interface DateRangePickerProps {
15
- onSelect: (dateRange: DateRange | undefined) => void
16
- selected?: DateRange
17
- lng: keyof typeof availableLocales
18
- className: string
27
+ export type DateRange = {
28
+ from: string | undefined
29
+ to: string | undefined
19
30
  }
20
31
 
21
32
  export function DateRangePicker({
22
- onSelect = () => {},
23
- selected: preselected,
33
+ onSelect,
34
+ defaultValue,
24
35
  lng,
25
36
  className,
37
+ required = false,
38
+ variant,
26
39
  }: DateRangePickerProps): React.JSX.Element {
27
- const manageFooterText = (): string => {
28
- const hasDatesFilter = selected && selected.from && selected.to
40
+ const cssClasses = classNames('date-picker', variant, className)
29
41
 
30
- if (!hasDatesFilter) return translations[lng].pickDate
42
+ const [selected, setSelected] = useState<DateRangeReactDayPicker>(
43
+ toDateRange(defaultValue),
44
+ )
31
45
 
32
- return translations[lng].selectedRangeOfDates
33
- .replace(
34
- '${from}',
35
- formatDatePickerFooterDate(selected.from, lng as string),
36
- )
37
- .replace('${to}', formatDatePickerFooterDate(selected.to, lng as string))
46
+ function selectDate(dateRange: DateRangeReactDayPicker | undefined) {
47
+ const selectedDateRange = {
48
+ from: dateRange?.from,
49
+ to: dateRange?.to,
50
+ }
51
+ setSelected(selectedDateRange)
52
+ onSelect?.(toDateRangeISO(selectedDateRange))
38
53
  }
39
54
 
40
- const [selected, setSelected] = useState<DateRange | undefined>(preselected)
41
- const [footer, setFooter] = useState<string>(() => {
42
- return manageFooterText()
43
- })
44
-
45
55
  useEffect(() => {
46
- setSelected(preselected)
47
- setFooter(manageFooterText())
48
- // eslint-disable-next-line react-hooks/exhaustive-deps
49
- }, [preselected])
50
-
51
- function selectDate(dateRange: DateRange | undefined) {
52
- setSelected(dateRange)
53
- onSelect(dateRange)
54
- }
56
+ setSelected(toDateRange(defaultValue))
57
+ }, [defaultValue])
55
58
 
56
59
  return (
57
60
  <DayPicker
58
- className={className}
61
+ className={cssClasses}
59
62
  locale={availableLocales[lng]}
60
63
  mode="range"
61
64
  min={1}
62
65
  selected={selected}
63
- onSelect={(dateRange) => selectDate(dateRange)}
64
- footer={footer}
66
+ onSelect={selectDate}
67
+ footer={<Footer lng={lng} selected={selected} />}
65
68
  defaultMonth={selected?.from}
69
+ required={required}
66
70
  />
67
71
  )
68
72
  }
73
+ function Footer({
74
+ lng,
75
+ selected,
76
+ }: {
77
+ lng: Locale
78
+ selected: DateRangeReactDayPicker | undefined
79
+ }): string {
80
+ if (!selected?.from && !selected?.to) {
81
+ return translations[lng].pickDate
82
+ }
83
+ if (selected?.to && selected?.from?.getTime() !== selected?.to?.getTime()) {
84
+ return translations[lng].selectedRangeOfDates
85
+ .replace(
86
+ '${from}',
87
+ formatDatePickerFooterDate(selected?.from, lng as string),
88
+ )
89
+ .replace('${to}', formatDatePickerFooterDate(selected?.to, lng as string))
90
+ }
91
+ return translations[lng].selectedOnlyFrom.replace(
92
+ '${from}',
93
+ formatDatePickerFooterDate(selected?.from, lng as string),
94
+ )
95
+ }
96
+
97
+ function toDateRange(
98
+ dateRange: DateRange | undefined,
99
+ ): DateRangeReactDayPicker {
100
+ return {
101
+ from: fromISOToDate(dateRange?.from),
102
+ to: fromISOToDate(dateRange?.to),
103
+ }
104
+ }
105
+
106
+ function toDateRangeISO(dateRange: DateRangeReactDayPicker): DateRange {
107
+ return {
108
+ from: fromDateToISOString(dateRange?.from),
109
+ to: fromDateToISOString(dateRange?.to),
110
+ }
111
+ }
@@ -1,69 +1,63 @@
1
1
  import 'react-day-picker/style.css'
2
- import { useEffect, useState } from 'react'
2
+ import './DatePicker.scss'
3
+ import { useState } from 'react'
3
4
  import { DayPicker } from 'react-day-picker'
4
- import { enGB, es } from 'react-day-picker/locale'
5
- import { formatDatePickerFooterDate } from '../../utils/dateHelpers'
6
- import type { AvailableLocale } from './DatePicker'
7
- import { translations } from './translations'
8
-
9
- const availableLocales: AvailableLocale = {
10
- es: es,
11
- en: enGB,
12
- }
13
-
14
- export interface DateSinglePickerProps {
15
- onSelect: (date: Date | undefined) => void
16
- selected?: Date
17
- lng: keyof typeof availableLocales
18
- className: string
5
+ import { classNames } from '../../utils/classNames'
6
+ import {
7
+ formatDatePickerFooterDate,
8
+ fromDateToISOString,
9
+ fromISOToDate,
10
+ } from '../../utils/dateHelpers'
11
+ import { availableLocales, type Locale, translations } from './translations'
12
+
13
+ export type Variant = 'primary'
14
+
15
+ export type DateSinglePickerProps = {
16
+ variant?: Variant
17
+ lng: Locale
18
+ required?: boolean
19
+ className?: string
20
+ defaultValue?: string
21
+ onSelect?: (date: string) => void
19
22
  }
20
23
 
21
24
  export function DateSinglePicker({
22
- onSelect = () => {},
23
- selected: preselected,
25
+ onSelect,
26
+ defaultValue,
24
27
  lng,
25
28
  className,
29
+ required = false,
30
+ variant,
26
31
  }: DateSinglePickerProps): React.JSX.Element {
27
- const manageFooterText = (): string => {
28
- if (!selected) return translations[lng].pickSingleDate
29
-
30
- return translations[lng].selectedDate.replace(
31
- '${date}',
32
- formatDatePickerFooterDate(selected, lng as string),
33
- )
34
- }
32
+ const cssClasses = classNames('date-picker', variant, className)
35
33
 
36
- const [selected, setSelected] = useState<Date | undefined>(preselected)
37
- const [month, setMonth] = useState<Date | undefined>(preselected)
38
- const [footer, setFooter] = useState<string>(() => {
39
- return manageFooterText()
40
- })
41
-
42
- useEffect(() => {
43
- setSelected(preselected)
44
- setMonth(preselected)
45
- setFooter(manageFooterText())
46
- // eslint-disable-next-line react-hooks/exhaustive-deps
47
- }, [preselected])
34
+ const [selected, setSelected] = useState<Date | undefined>(
35
+ fromISOToDate(defaultValue),
36
+ )
48
37
 
49
38
  function selectDate(date: Date | undefined) {
50
39
  setSelected(date)
51
- if (date) setMonth(new Date(date.getFullYear(), date.getMonth()))
52
- onSelect(date)
40
+ onSelect?.(fromDateToISOString(date))
53
41
  }
54
42
 
55
43
  return (
56
44
  <DayPicker
57
- className={className}
45
+ className={cssClasses}
58
46
  locale={availableLocales[lng]}
59
47
  mode="single"
60
48
  selected={selected}
61
- onSelect={(date) => selectDate(date)}
62
- footer={footer}
63
- required
64
- month={month}
65
- onMonthChange={(date) => setMonth(date)}
49
+ onSelect={selectDate}
50
+ footer={<Footer lng={lng} selected={selected} />}
51
+ required={required}
66
52
  defaultMonth={selected}
67
53
  />
68
54
  )
69
55
  }
56
+ function Footer({ lng, selected }: { selected?: Date; lng: Locale }): string {
57
+ if (!selected) return translations[lng].pickSingleDate
58
+
59
+ return translations[lng].selectedDate.replace(
60
+ '${date}',
61
+ formatDatePickerFooterDate(selected, lng as string),
62
+ )
63
+ }
@@ -0,0 +1,7 @@
1
+ export type { DateRange, DateRangePickerProps } from './DateRangePicker'
2
+ export type { DateSinglePickerProps } from './DateSinglePicker'
3
+
4
+ import { DateRangePicker } from './DateRangePicker'
5
+ import { DateSinglePicker } from './DateSinglePicker'
6
+
7
+ export { DateRangePicker, DateSinglePicker }
@@ -1,18 +1,34 @@
1
- interface Translation {
1
+ import { type Locale as LocaleReactDayPicker } from 'react-day-picker'
2
+ import { enGB, es } from 'react-day-picker/locale'
3
+
4
+ export interface Translation {
2
5
  [index: string]: { [index: string]: string }
3
6
  }
4
7
 
8
+ export interface AvailableLocale {
9
+ [index: string]: LocaleReactDayPicker
10
+ }
11
+
12
+ export const availableLocales: AvailableLocale = {
13
+ es: es,
14
+ en: enGB,
15
+ }
16
+
17
+ export type Locale = keyof typeof availableLocales
18
+
5
19
  export const translations: Translation = {
6
20
  en: {
7
21
  pickDate: 'Pick a day or a range of dates',
8
22
  pickSingleDate: 'Pick a date',
9
23
  selectedDate: 'Selected date: ${date}',
10
24
  selectedRangeOfDates: 'Selected dates range: from ${from} to ${to}',
25
+ selectedOnlyFrom: 'Selected dates range: from ${from}',
11
26
  },
12
27
  es: {
13
28
  pickDate: 'Selecciona un día o un rango de fechas',
14
29
  pickSingleDate: 'Selecciona una fecha',
15
30
  selectedDate: 'Fecha seleccionada: ${date}',
16
31
  selectedRangeOfDates: 'Rango de fechas seleccionado: desde ${from} a ${to}',
32
+ selectedOnlyFrom: 'Rango de fechas seleccionado: desde ${from}',
17
33
  },
18
34
  }
@@ -4,6 +4,19 @@ import { Meta } from "@storybook/blocks";
4
4
 
5
5
  # Changelog
6
6
 
7
+ ## 0.31.8
8
+
9
+ * Refactor Modal component to use HTML dialog
10
+
11
+ ## 0.31.7
12
+
13
+ * Fixed date clearing event in range and added a new translation to the footer for the first day of the selected range.
14
+ * Refactoring of types and translations and reduction of state logic in components
15
+ * Refactoring dateHelpers functions for convert dates to ISO format and ISO format to dates
16
+ * DateRangePicker and DateSinglePicker separation in two different components.
17
+ * Updating stories for DateRangePicker and DateSinglePicker
18
+ * Updating test for DateRangePicker and DateSinglePicker
19
+
7
20
  ## 0.31.6
8
21
 
9
22
  * Refactor styles and fix range day selection
@@ -1,9 +1,9 @@
1
1
  import type { StoryObj } from '@storybook/react'
2
- import { DatePicker } from '../atoms/DatePicker/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
  parameters: {
8
8
  docs: {
9
9
  description: {
@@ -26,8 +26,11 @@ const meta = {
26
26
  lng: {
27
27
  description: 'String with the locale to be used on the translations',
28
28
  },
29
- type: {
30
- description: 'Type of date that could be range or single',
29
+ required: {
30
+ description: 'Optional parametre for required pick date',
31
+ },
32
+ className: {
33
+ description: 'Optional parametre for add styles by className',
31
34
  },
32
35
  },
33
36
  }
@@ -42,32 +45,11 @@ const figmaPrimaryDesign = {
42
45
  export default meta
43
46
  type Story = StoryObj<typeof meta>
44
47
 
45
- export const SingleDatePicker: Story = {
46
- args: {
47
- variant: 'primary',
48
- onSelect: (date) => console.log('onSelect date:', date),
49
- lng: 'en',
50
- type: 'single',
51
- },
52
- }
53
-
54
48
  export const RangeDatePicker: Story = {
55
49
  args: {
56
50
  variant: 'primary',
57
51
  onSelect: (date) => console.log('onSelect date:', date),
58
52
  lng: 'en',
59
- type: 'range',
60
- },
61
- parameters: figmaPrimaryDesign,
62
- }
63
-
64
- export const WithSingleDaySelected: Story = {
65
- args: {
66
- variant: 'primary',
67
- onSelect: (date) => console.log('onSelect date:', date),
68
- selected: new Date(2024, 1, 2),
69
- lng: 'en',
70
- type: 'single',
71
53
  },
72
54
  parameters: figmaPrimaryDesign,
73
55
  }
@@ -76,9 +58,8 @@ export const WithRangeDateSelected: Story = {
76
58
  args: {
77
59
  variant: 'primary',
78
60
  onSelect: (date) => console.log('onSelect date:', date),
79
- selected: { from: new Date(2024, 1, 2), to: new Date(2024, 1, 12) },
61
+ defaultValue: { from: '2024-01-02', to: '2024-01-12' },
80
62
  lng: 'en',
81
- type: 'range',
82
63
  },
83
64
  parameters: figmaPrimaryDesign,
84
65
  }
@@ -0,0 +1,64 @@
1
+ import type { StoryObj } from '@storybook/react'
2
+ import { DateSinglePicker } from '../atoms/DatePicker/DateSinglePicker'
3
+
4
+ const meta = {
5
+ title: 'Design System/Atoms/DateSinglePicker',
6
+ component: DateSinglePicker,
7
+ parameters: {
8
+ docs: {
9
+ description: {
10
+ component:
11
+ '<h2>Usage guidelines</h2><p>DateRangePicker component allows users to select past, present, or future dates in a visual way in range or single format.</p>',
12
+ },
13
+ },
14
+ },
15
+ tags: ['autodocs'],
16
+ argTypes: {
17
+ variant: {
18
+ description: 'Component variant used',
19
+ },
20
+ onSelect: {
21
+ description: 'Component onSelect callback',
22
+ },
23
+ selected: {
24
+ description: 'Selected date or date range',
25
+ },
26
+ lng: {
27
+ description: 'String with the locale to be used on the translations',
28
+ },
29
+ required: {
30
+ description: 'Optional parametre for required pick date',
31
+ },
32
+ className: {
33
+ description: 'Optional parametre for add styles by className',
34
+ },
35
+ },
36
+ }
37
+
38
+ const figmaPrimaryDesign = {
39
+ design: {
40
+ type: 'figma',
41
+ url: 'https://www.figma.com/design/DN2ova21vWqCRvPspBXgI1/Design-System?node-id=3665-571&m=dev',
42
+ },
43
+ }
44
+
45
+ export default meta
46
+ type Story = StoryObj<typeof meta>
47
+
48
+ export const SingleDatePicker: Story = {
49
+ args: {
50
+ variant: 'primary',
51
+ onSelect: (date) => console.log('onSelect date:', date),
52
+ lng: 'en',
53
+ },
54
+ }
55
+
56
+ export const WithSingleDaySelected: Story = {
57
+ args: {
58
+ variant: 'primary',
59
+ onSelect: (date) => console.log('onSelect date:', date),
60
+ defaultValue: '2024-01-20',
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/DatePicker'
4
+ import { DateRangePicker } from '../atoms/DatePicker/DateRangePicker'
5
5
  import { Drawer } from '../atoms/Drawer'
6
6
 
7
7
  const figmaPrimaryDesign = {
@@ -130,10 +130,9 @@ export const Filters = {
130
130
  </Collapsible>
131
131
  <Collapsible noHorizontalPadding open title="Date">
132
132
  <div style={{ display: 'flex', justifyContent: 'center' }}>
133
- <DatePicker
133
+ <DateRangePicker
134
134
  selected={{ from: new Date(2025, 0, 1), to: new Date(2025, 0, 15) }}
135
135
  onSelect={(date) => console.log('date: ', date)}
136
- type="range"
137
136
  lng="en"
138
137
  />
139
138
  </div>