@artemy-tech/datepicker 0.6.1 → 0.7.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/README.md CHANGED
@@ -6,18 +6,21 @@
6
6
  [![codecov](https://codecov.io/gh/artemydottech/datepicker/branch/main/graph/badge.svg)](https://codecov.io/gh/artemydottech/datepicker)
7
7
  [![publish size](https://badgen.net/packagephobia/publish/@artemy-tech/datepicker)](https://packagephobia.com/result?p=@artemy-tech/datepicker)
8
8
 
9
- React DatePicker с опциональной поддержкой react-hook-form. Построен на базе [react-day-picker v9](https://daypicker.dev/) (headless) и [date-fns v4](https://date-fns.org/).
9
+ React DatePicker с маской ввода, поддержкой произвольных локалей и форматов даты, выбором диапазона и времени, опциональной интеграцией с react-hook-form. Построен на [react-day-picker v9](https://daypicker.dev/) и [date-fns v4](https://date-fns.org/).
10
+
11
+ **📚 [Документация и примеры →](https://artemydottech.github.io/datepicker)**
10
12
 
11
13
  ## Возможности
12
14
 
13
- - Выбор одиночной даты и диапазона дат
15
+ - Одиночная дата и диапазон
14
16
  - Контролируемый и неконтролируемый режимы
15
17
  - Выбор времени (`showTime`)
16
- - Кастомный триггер через `customTrigger` render-функция, получает текущее значение и `onClick`
17
- - Кастомный инпут через `renderInput` интеграция с любой UI-библиотекой (Ant Design, MUI, shadcn и др.)
18
+ - **Произвольная локаль** через проп `locale` (любая локаль `date-fns`)
19
+ - **Произвольный формат даты** через проп `dateFormat` (`dd.MM.yyyy`, `MM/dd/yyyy`, `yyyy-MM-dd`, …) маска ввода генерится автоматически
20
+ - Кастомный триггер (`customTrigger`) и кастомный инпут (`renderInput`) — интеграция с Ant Design, MUI, shadcn/ui и др.
18
21
  - Интеграция с react-hook-form (нулевые издержки если не используется)
19
- - Стилизация через CSS-переменные (`--datepicker-*`)
20
- - Полная поддержка TypeScript
22
+ - Стилизация через CSS-переменные `--datepicker-*`
23
+ - Полная поддержка TypeScript, в т.ч. дженерики для RHF-компонентов
21
24
 
22
25
  ## Установка
23
26
 
@@ -25,37 +28,34 @@ React DatePicker с опциональной поддержкой react-hook-for
25
28
  npm install @artemy-tech/datepicker
26
29
  ```
27
30
 
28
- Для интеграции с react-hook-form:
31
+ Для интеграции с react-hook-form установите его как peer-зависимость:
29
32
 
30
33
  ```bash
31
- npm install @artemy-tech/datepicker react-hook-form
34
+ npm install react-hook-form
32
35
  ```
33
36
 
34
- ## Peer-зависимости
35
-
36
- ```text
37
- react >= 17.0.0
38
- react-hook-form >= 7.0.0 # опционально
39
- ```
40
-
41
- ## Использование
42
-
43
- ### Подключение стилей
37
+ ## Quick start
44
38
 
45
39
  ```tsx
46
40
  import '@artemy-tech/datepicker/styles';
41
+ import { DatePicker } from '@artemy-tech/datepicker';
42
+
43
+ export const Example = () => <DatePicker label="Дата рождения" />;
47
44
  ```
48
45
 
46
+ ## Примеры
47
+
49
48
  ### DatePicker
50
49
 
51
50
  ```tsx
52
- import { DatePicker } from '@artemy-tech/datepicker'
51
+ import { useState } from 'react';
52
+ import { DatePicker } from '@artemy-tech/datepicker';
53
53
 
54
54
  // Неконтролируемый
55
55
  <DatePicker label="Дата рождения" />
56
56
 
57
57
  // Контролируемый
58
- const [date, setDate] = useState<Date | undefined>()
58
+ const [date, setDate] = useState<Date | undefined>();
59
59
  <DatePicker label="Дата" value={date} onChange={setDate} />
60
60
 
61
61
  // С выбором времени
@@ -68,147 +68,92 @@ const [date, setDate] = useState<Date | undefined>()
68
68
  ### DateRangePicker
69
69
 
70
70
  ```tsx
71
- import { DateRangePicker } from '@artemy-tech/datepicker'
72
- import type { DateRange } from '@artemy-tech/datepicker'
71
+ import { useState } from 'react';
72
+ import { DateRangePicker, type DateRange } from '@artemy-tech/datepicker';
73
73
 
74
- const [range, setRange] = useState<DateRange | undefined>()
74
+ const [range, setRange] = useState<DateRange | undefined>();
75
75
 
76
76
  <DateRangePicker
77
77
  label="Период проживания"
78
78
  value={range}
79
79
  onChange={setRange}
80
80
  calendarLayout="horizontal"
81
- />
81
+ />;
82
82
  ```
83
83
 
84
- ### Кастомный триггер (`customTrigger`)
84
+ ### Локали и форматы
85
85
 
86
- Через `customTrigger` можно передать render-функцию, которая получает отформатированное значение и обработчик клика.
86
+ По умолчанию: `locale = ru`, `dateFormat = 'dd.MM.yyyy'`. Любую локаль `date-fns` можно подключить точечно — маска и плейсхолдер пересчитаются автоматически.
87
87
 
88
88
  ```tsx
89
- import { DatePicker } from '@artemy-tech/datepicker';
89
+ import { enUS, de } from 'date-fns/locale';
90
+ import { DatePicker, DateRangePicker } from '@artemy-tech/datepicker';
90
91
 
91
92
  <DatePicker
92
- customTrigger={(value, onClick) => (
93
- <button type="button" onClick={onClick}>
94
- {value || 'Выбрать дату'}
95
- </button>
96
- )}
97
- />;
98
- ```
99
-
100
- ### Кастомный инпут (`renderInput`)
101
-
102
- Через `renderInput` можно заменить встроенный `<input>` на компонент из любой UI-библиотеки. Вся логика маски, валидации и попапа остаётся внутри `DatePicker`.
103
-
104
- ```tsx
105
- import { Input } from 'antd';
106
- import type { InputRef } from 'antd';
107
- import { DatePicker } from '@artemy-tech/datepicker';
93
+ locale={enUS}
94
+ dateFormat="MM/dd/yyyy"
95
+ label="Birth date"
96
+ />
108
97
 
109
98
  <DatePicker
110
- renderInput={({ ref, className, ...props }) => (
111
- <Input ref={ref as React.Ref<InputRef>} {...props} />
112
- )}
113
- />;
99
+ locale={enUS}
100
+ dateFormat="yyyy-MM-dd"
101
+ label="ISO date"
102
+ />
103
+
104
+ <DateRangePicker
105
+ locale={de}
106
+ dateFormat="dd.MM.yyyy"
107
+ label="Zeitraum"
108
+ />
114
109
  ```
115
110
 
111
+ Поддерживаемые токены в `dateFormat`: `dd`, `MM`, `yyyy`. Разделители — любые одиночные символы (`.`, `/`, `-`, ` `). Время добавляется через проп `showTime`, а не через `dateFormat`.
112
+
116
113
  ### С react-hook-form
117
114
 
115
+ `RHFDatePicker` и `RHFDateRangePicker` принимают дженерик-параметр — тип значений формы. Это даёт автокомплит и типобезопасность для `name`:
116
+
118
117
  ```tsx
119
118
  import { FormProvider, useForm } from 'react-hook-form';
120
119
  import { RHFDatePicker, RHFDateRangePicker } from '@artemy-tech/datepicker/rhf';
121
120
  import type { DateRange } from '@artemy-tech/datepicker';
122
121
 
123
- interface FormValues {
122
+ interface BookingFormValues {
124
123
  checkIn: Date | undefined;
125
124
  period: DateRange | undefined;
126
125
  }
127
126
 
128
- function BookingForm() {
129
- const methods = useForm<FormValues>({
127
+ const BookingForm = () => {
128
+ const methods = useForm<BookingFormValues>({
130
129
  defaultValues: { checkIn: undefined, period: undefined },
131
130
  });
132
131
 
133
132
  return (
134
133
  <FormProvider {...methods}>
135
134
  <form onSubmit={methods.handleSubmit(console.log)}>
136
- <RHFDatePicker
135
+ <RHFDatePicker<BookingFormValues>
137
136
  name="checkIn"
138
137
  label="Дата заезда"
139
138
  rules={{ validate: (v) => v !== undefined || 'Выберите дату' }}
140
139
  />
141
- <RHFDateRangePicker
140
+ <RHFDateRangePicker<BookingFormValues>
142
141
  name="period"
143
142
  label="Период"
144
- rules={{
145
- validate: (v) => v?.from !== undefined || 'Выберите период',
146
- }}
143
+ rules={{ validate: (v) => v?.from !== undefined || 'Выберите период' }}
147
144
  />
148
145
  <button type="submit">Отправить</button>
149
146
  </form>
150
147
  </FormProvider>
151
148
  );
152
- }
149
+ };
153
150
  ```
154
151
 
155
- ## Props
156
-
157
- ### DatePicker — пропсы
158
-
159
- | Prop | Тип | По умолчанию | Описание |
160
- | --------------- | --------------------------------------------------- | ------------------ | ---------------------------------------------- |
161
- | `value` | `Date` | — | Контролируемое значение |
162
- | `defaultValue` | `Date` | — | Значение по умолчанию (неконтролируемый режим) |
163
- | `onChange` | `(date: Date \| undefined) => void` | — | Callback при изменении |
164
- | `label` | `string` | — | Плавающий лейбл |
165
- | `placeholder` | `string` | `дд.мм.гггг` | Плейсхолдер |
166
- | `fromDate` | `Date` | — | Минимально допустимая дата |
167
- | `toDate` | `Date` | — | Максимально допустимая дата |
168
- | `showTime` | `boolean \| { format: 'HH:mm' \| 'HH:mm:ss' }` | — | Включить выбор времени |
169
- | `noCalendar` | `boolean` | `false` | Только ввод, без попапа |
170
- | `size` | `'s' \| 'm' \| 'l'` | `'m'` | Размер |
171
- | `disabled` | `boolean` | `false` | |
172
- | `failed` | `boolean` | `false` | Состояние ошибки |
173
- | `loading` | `boolean` | `false` | Состояние загрузки |
174
- | `icon` | `ReactNode \| false` | `<CalendarIcon />` | Иконка (`false` — скрыть) |
175
- | `iconPosition` | `'start' \| 'end'` | `'end'` | Позиция иконки |
176
- | `renderInput` | `(props: DatePickerInputProps) => ReactNode` | — | Кастомный `<input>`; маска и попап сохраняются |
177
- | `customTrigger` | `(value: string, onClick: () => void) => ReactNode` | — | Render-функция для произвольного триггера |
178
- | `className` | `string` | — | CSS-класс на корневом элементе |
179
-
180
- ### DateRangePicker — пропсы
181
-
182
- | Prop | Тип | По умолчанию | Описание |
183
- | ---------------- | ---------------------------------------------- | ------------------ | --------------------------- |
184
- | `value` | `DateRange` | — | Контролируемое значение |
185
- | `defaultValue` | `DateRange` | — | Значение по умолчанию |
186
- | `onChange` | `(range: DateRange \| undefined) => void` | — | Callback при изменении |
187
- | `label` | `string` | — | Плавающий лейбл |
188
- | `fromDate` | `Date` | — | Минимально допустимая дата |
189
- | `toDate` | `Date` | — | Максимально допустимая дата |
190
- | `calendarLayout` | `'vertical' \| 'horizontal'` | `'horizontal'` | Расположение двух месяцев |
191
- | `showTime` | `boolean \| { format: 'HH:mm' \| 'HH:mm:ss' }` | — | Включить выбор времени |
192
- | `size` | `'s' \| 'm' \| 'l'` | `'m'` | Размер |
193
- | `disabled` | `boolean` | `false` | |
194
- | `failed` | `boolean` | `false` | |
195
- | `loading` | `boolean` | `false` | |
196
- | `icon` | `ReactNode \| false` | `<CalendarIcon />` | Иконка |
197
- | `iconPosition` | `'start' \| 'end'` | `'end'` | |
198
- | `className` | `string` | — | |
199
-
200
- ### RHFDatePicker / RHFDateRangePicker — пропсы
201
-
202
- Принимают все пропсы соответствующего компонента, плюс:
203
-
204
- | Prop | Тип | Описание |
205
- | ------- | ----------------- | --------------------------------- |
206
- | `name` | `string` | Имя поля в форме |
207
- | `rules` | `RegisterOptions` | Правила валидации react-hook-form |
152
+ > Полные рецепты для **Zod**, **Joi** и **shadcn/ui Form** — на [странице документации](https://artemydottech.github.io/datepicker/recipes).
208
153
 
209
154
  ## Стилизация
210
155
 
211
- Подключите базовые стили и переопределите нужные токены:
156
+ Подключите базовые стили и переопределите нужные CSS-переменные:
212
157
 
213
158
  ```css
214
159
  @import '@artemy-tech/datepicker/styles';
@@ -216,31 +161,17 @@ function BookingForm() {
216
161
  :root {
217
162
  --datepicker-color-accent: #6366f1;
218
163
  --datepicker-radius: 8px;
219
- --datepicker-font-size: 14px;
220
- --datepicker-border-color: #e0e0e0;
221
164
  --datepicker-border-color-focus: #6366f1;
222
- --datepicker-bg: #ffffff;
223
- --datepicker-color-text: #1a1a1a;
224
- --datepicker-color-placeholder: #9e9e9e;
225
165
  }
226
166
  ```
227
167
 
228
- Состояния задаются через `data-*`-атрибуты на корневом элементе, что позволяет стилизовать их без JS:
168
+ Состояния задаются через `data-*`-атрибуты на корневом элементе (`data-focused`, `data-filled`, `data-failed`, `data-disabled`) — стилизуются без JS.
229
169
 
230
- ```css
231
- .datepicker[data-focused] {
232
- ...;
233
- }
234
- .datepicker[data-filled] {
235
- ...;
236
- }
237
- .datepicker[data-failed] {
238
- ...;
239
- }
240
- .datepicker[data-disabled] {
241
- ...;
242
- }
243
- ```
170
+ Полный список токенов и data-атрибутов — в [разделе Theming](https://artemydottech.github.io/datepicker/theming).
171
+
172
+ ## API
173
+
174
+ Подробная справка по пропсам, типам и edge-cases — в [документации](https://artemydottech.github.io/datepicker).
244
175
 
245
176
  ## Лицензия
246
177
 
@@ -1,5 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
+ import { Locale } from 'date-fns/locale';
3
4
  import { DateRange } from 'react-day-picker';
4
5
 
5
6
  type DatePickerSize = 's' | 'm' | 'l';
@@ -43,8 +44,10 @@ interface DatePickerProps {
43
44
  className?: string;
44
45
  renderInput?: (props: DatePickerInputProps) => ReactNode;
45
46
  customTrigger?: (value: string, onClick: () => void) => ReactNode;
47
+ locale?: Locale;
48
+ dateFormat?: string;
46
49
  }
47
- declare function DatePicker({ value, defaultValue, onChange, label, placeholder, fromDate, toDate, disabled, failed, loading, size, noCalendar, showTime, icon, iconPosition, className, renderInput, customTrigger, }: DatePickerProps): react_jsx_runtime.JSX.Element;
50
+ declare function DatePicker({ value, defaultValue, onChange, label, placeholder, fromDate, toDate, disabled, failed, loading, size, noCalendar, showTime, icon, iconPosition, className, renderInput, customTrigger, locale, dateFormat: dateFormatProp, }: DatePickerProps): react_jsx_runtime.JSX.Element;
48
51
 
49
52
  type DateRangePickerSize = 's' | 'm' | 'l';
50
53
  type DateRangePickerCalendarLayout = 'vertical' | 'horizontal';
@@ -64,7 +67,9 @@ interface DateRangePickerProps {
64
67
  icon?: ReactNode | false;
65
68
  iconPosition?: 'start' | 'end';
66
69
  className?: string;
70
+ locale?: Locale;
71
+ dateFormat?: string;
67
72
  }
68
- declare function DateRangePicker({ value, defaultValue, onChange, label, fromDate: fromConstraint, toDate: toConstraint, disabled, failed, loading, size, calendarLayout, showTime, icon, iconPosition, className, }: DateRangePickerProps): react_jsx_runtime.JSX.Element;
73
+ declare function DateRangePicker({ value, defaultValue, onChange, label, fromDate: fromConstraint, toDate: toConstraint, disabled, failed, loading, size, calendarLayout, showTime, icon, iconPosition, className, locale, dateFormat: dateFormatProp, }: DateRangePickerProps): react_jsx_runtime.JSX.Element;
69
74
 
70
75
  export { DatePicker as D, type DatePickerInputProps as a, type DatePickerProps as b, type DatePickerShowTime as c, DateRangePicker as d, type DateRangePickerProps as e };
@@ -1,5 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
+ import { Locale } from 'date-fns/locale';
3
4
  import { DateRange } from 'react-day-picker';
4
5
 
5
6
  type DatePickerSize = 's' | 'm' | 'l';
@@ -43,8 +44,10 @@ interface DatePickerProps {
43
44
  className?: string;
44
45
  renderInput?: (props: DatePickerInputProps) => ReactNode;
45
46
  customTrigger?: (value: string, onClick: () => void) => ReactNode;
47
+ locale?: Locale;
48
+ dateFormat?: string;
46
49
  }
47
- declare function DatePicker({ value, defaultValue, onChange, label, placeholder, fromDate, toDate, disabled, failed, loading, size, noCalendar, showTime, icon, iconPosition, className, renderInput, customTrigger, }: DatePickerProps): react_jsx_runtime.JSX.Element;
50
+ declare function DatePicker({ value, defaultValue, onChange, label, placeholder, fromDate, toDate, disabled, failed, loading, size, noCalendar, showTime, icon, iconPosition, className, renderInput, customTrigger, locale, dateFormat: dateFormatProp, }: DatePickerProps): react_jsx_runtime.JSX.Element;
48
51
 
49
52
  type DateRangePickerSize = 's' | 'm' | 'l';
50
53
  type DateRangePickerCalendarLayout = 'vertical' | 'horizontal';
@@ -64,7 +67,9 @@ interface DateRangePickerProps {
64
67
  icon?: ReactNode | false;
65
68
  iconPosition?: 'start' | 'end';
66
69
  className?: string;
70
+ locale?: Locale;
71
+ dateFormat?: string;
67
72
  }
68
- declare function DateRangePicker({ value, defaultValue, onChange, label, fromDate: fromConstraint, toDate: toConstraint, disabled, failed, loading, size, calendarLayout, showTime, icon, iconPosition, className, }: DateRangePickerProps): react_jsx_runtime.JSX.Element;
73
+ declare function DateRangePicker({ value, defaultValue, onChange, label, fromDate: fromConstraint, toDate: toConstraint, disabled, failed, loading, size, calendarLayout, showTime, icon, iconPosition, className, locale, dateFormat: dateFormatProp, }: DateRangePickerProps): react_jsx_runtime.JSX.Element;
69
74
 
70
75
  export { DatePicker as D, type DatePickerInputProps as a, type DatePickerProps as b, type DatePickerShowTime as c, DateRangePicker as d, type DateRangePickerProps as e };