@fvc/picker 1.1.2 → 1.1.3-next-ec65dfb844e6183b3d7f417eee613cfe5ecfd997

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.
Files changed (2) hide show
  1. package/README.md +357 -0
  2. package/package.json +19 -3
package/README.md ADDED
@@ -0,0 +1,357 @@
1
+ # @fvc/picker
2
+
3
+ `@fvc/picker` provides date and time picker components for FE-VIS applications — `DatePicker`, `RangeDatePicker`, and `TimePicker` — built on Ant Design and dayjs. It adds controlled date-enabling/disabling, a compact display mode, and range shortcut chips on top of the standard antd API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ bun add @fvc/picker
9
+ ```
10
+
11
+ ## Peer Dependencies
12
+
13
+ ```bash
14
+ bun add react antd
15
+ ```
16
+
17
+ `@fvc/icons` is a direct dependency and is included automatically.
18
+
19
+ ## Import
20
+
21
+ ```tsx
22
+ import { DatePicker, RangeDatePicker, TimePicker, Shortcut } from '@fvc/picker';
23
+ ```
24
+
25
+ ## Quick Start
26
+
27
+ ```tsx
28
+ import { DatePicker } from '@fvc/picker';
29
+
30
+ export function BirthDateField() {
31
+ return (
32
+ <DatePicker
33
+ format="DD.MM.YYYY"
34
+ onChange={(_, dateString) => console.log(dateString)}
35
+ />
36
+ );
37
+ }
38
+ ```
39
+
40
+ ## DatePicker
41
+
42
+ ### Additional props
43
+
44
+ | Prop | Type | Default | Description |
45
+ | --- | --- | --- | --- |
46
+ | `disabledDates` | `IDateActivationConf` | — | Dates outside this config are disabled. |
47
+ | `enabledDates` | `IDateActivationConf` | — | Only dates matching this config are enabled. |
48
+ | `error` | `boolean` | `false` | Applies error border and background styling. |
49
+ | `short` | `boolean` | `false` | Compact width mode (`max-width: 140px`). |
50
+ | `hideYear` | `boolean` | `false` | Hides the year row in the dropdown panel. |
51
+ | `format` | `string` | antd default | Display and parse format string (dayjs tokens). |
52
+ | `testId` | `string` | `'datepicker'` | Maps to `data-testid` on the wrapper element. |
53
+
54
+ All antd `DatePickerProps` are forwarded.
55
+
56
+ ### `IDateActivationConf`
57
+
58
+ Controls which dates are selectable. `disabledDates` and `enabledDates` can be
59
+ used independently or together — `enabledDates` takes precedence when both are provided.
60
+
61
+ ```ts
62
+ interface IDateActivationConf {
63
+ dates?: string[]; // exact dates: ['2024-12-25', '2024-12-31']
64
+ ranges?: [string, string][]; // date ranges: [['2024-01-01', '2024-01-07']]
65
+ fromDate?: string; // disable everything before this date
66
+ tillDate?: string; // disable everything after this date
67
+ }
68
+ ```
69
+
70
+ ### Common Usage
71
+
72
+ #### Error state
73
+
74
+ ```tsx
75
+ <DatePicker format="DD.MM.YYYY" error={hasValidationError} />
76
+ ```
77
+
78
+ #### Compact mode
79
+
80
+ ```tsx
81
+ <DatePicker format="DD.MM.YYYY" short />
82
+ ```
83
+
84
+ #### Restrict selectable dates
85
+
86
+ ```tsx
87
+ // Only allow future dates
88
+ <DatePicker
89
+ format="DD.MM.YYYY"
90
+ disabledDates={{ tillDate: dayjs().format('YYYY-MM-DD') }}
91
+ />
92
+
93
+ // Enable only specific dates
94
+ <DatePicker
95
+ format="DD.MM.YYYY"
96
+ enabledDates={{
97
+ dates: ['2024-06-15', '2024-06-16'],
98
+ ranges: [['2024-07-01', '2024-07-07']],
99
+ }}
100
+ />
101
+ ```
102
+
103
+ ---
104
+
105
+ ## RangeDatePicker
106
+
107
+ ### Additional props
108
+
109
+ | Prop | Type | Default | Description |
110
+ | --- | --- | --- | --- |
111
+ | `format` | `string` | `'DD.MM.YYYY'` | Display format shown in the input. |
112
+ | `outputFormat` | `string` | `'YYYY-MM-DD'` | Format of the strings passed to `onChange`. |
113
+ | `shortcuts` | `ShortcutDef[]` | — | Shortcut chips rendered below the picker. |
114
+ | `updateValueBeforeChange` | `BeforeChangeFunction` | — | Intercepts and transforms the value before `onChange` fires. |
115
+ | `disabledDates` | `IDateActivationConf` | — | Same as `DatePicker`. |
116
+ | `enabledDates` | `IDateActivationConf` | — | Same as `DatePicker`. |
117
+ | `testId` | `string` | `'rangepicker'` | Maps to `data-testid` on the wrapper. |
118
+
119
+ > `format` controls what the user sees in the input. `outputFormat` controls what `onChange` receives. Set these independently when your API expects a format different from the display format.
120
+
121
+ ### Shortcuts
122
+
123
+ Shortcut chips render below the picker. Selecting a chip sets the range value and highlights it. Picking dates manually clears the active shortcut.
124
+
125
+ ```ts
126
+ type ShortcutDef = {
127
+ label: string;
128
+ value?: [Dayjs | null, Dayjs | null];
129
+ renderType?: 'DEFAULT' | 'MONTHLY' | 'YEARLY' | 'QUARTERLY';
130
+ };
131
+ ```
132
+
133
+ ### Common Usage
134
+
135
+ #### Basic range
136
+
137
+ ```tsx
138
+ <RangeDatePicker
139
+ format="DD.MM.YYYY"
140
+ outputFormat="YYYY-MM-DD"
141
+ onChange={(_, [start, end]) => console.log(start, end)}
142
+ />
143
+ ```
144
+
145
+ #### With shortcuts
146
+
147
+ ```tsx
148
+ import dayjs from 'dayjs';
149
+
150
+ <RangeDatePicker
151
+ shortcuts={[
152
+ {
153
+ label: 'This week',
154
+ value: [dayjs().startOf('week'), dayjs().endOf('week')],
155
+ },
156
+ {
157
+ label: 'This month',
158
+ value: [dayjs().startOf('month'), dayjs().endOf('month')],
159
+ },
160
+ {
161
+ label: 'Last 30 days',
162
+ value: [dayjs().subtract(30, 'day'), dayjs()],
163
+ },
164
+ ]}
165
+ />
166
+ ```
167
+
168
+ ---
169
+
170
+ ## TimePicker
171
+
172
+ | Prop | Type | Default | Description |
173
+ | --- | --- | --- | --- |
174
+ | `format` | `string` | `'HH:mm'` | Time display and parse format. |
175
+ | `testId` | `string` | `'timepicker'` | Maps to `data-testid` on the wrapper. |
176
+
177
+ All antd `TimePickerProps` are forwarded.
178
+
179
+ ```tsx
180
+ <TimePicker
181
+ format="HH:mm"
182
+ onChange={(_, timeString) => setTime(timeString)}
183
+ />
184
+ ```
185
+
186
+ ---
187
+
188
+ ## Shortcut
189
+
190
+ A standalone clickable chip. Used internally by `RangeDatePicker` but available for building custom range layouts.
191
+
192
+ ```tsx
193
+ <Shortcut
194
+ label="Last 30 days"
195
+ isSelected={isActive}
196
+ onClick={handleShortcut}
197
+ testId="shortcut-30d"
198
+ />
199
+ ```
200
+
201
+ | Prop | Type | Default | Description |
202
+ | --- | --- | --- | --- |
203
+ | `label` | `string` | — | Chip text. |
204
+ | `isSelected` | `boolean` | `false` | Highlighted/active state. |
205
+ | `onClick` | `() => void` | — | Click handler. |
206
+ | `testId` | `string` | — | Maps to `data-testid`. |
207
+
208
+ ---
209
+
210
+ ## Ref Forwarding
211
+
212
+ All three picker components forward refs typed as `PickerRef`.
213
+
214
+ ```ts
215
+ interface PickerRef {
216
+ nativeElement: HTMLDivElement;
217
+ focus: (options?: FocusOptions) => void;
218
+ blur: VoidFunction;
219
+ }
220
+ ```
221
+
222
+ ```tsx
223
+ const ref = useRef<PickerRef>(null);
224
+ <DatePicker ref={ref} />
225
+ ref.current?.focus();
226
+ ```
227
+
228
+ ## Consumer Example
229
+
230
+ ```tsx
231
+ import { DatePicker, RangeDatePicker } from '@fvc/picker';
232
+ import dayjs from 'dayjs';
233
+
234
+ interface ReportFilterProps {
235
+ onDateChange: (date: string) => void;
236
+ onRangeChange: (start: string, end: string) => void;
237
+ }
238
+
239
+ export function ReportFilter({ onDateChange, onRangeChange }: ReportFilterProps) {
240
+ return (
241
+ <div className="report-filter">
242
+ <DatePicker
243
+ format="DD.MM.YYYY"
244
+ disabledDates={{ tillDate: dayjs().subtract(1, 'year').format('YYYY-MM-DD') }}
245
+ onChange={(_, dateString) => onDateChange(dateString as string)}
246
+ testId="report-date"
247
+ />
248
+
249
+ <RangeDatePicker
250
+ format="DD.MM.YYYY"
251
+ outputFormat="YYYY-MM-DD"
252
+ shortcuts={[
253
+ { label: 'Last 7 days', value: [dayjs().subtract(7, 'd'), dayjs()] },
254
+ { label: 'Last 30 days', value: [dayjs().subtract(30, 'd'), dayjs()] },
255
+ ]}
256
+ onChange={(_, [start, end]) => onRangeChange(start, end)}
257
+ testId="report-range"
258
+ />
259
+ </div>
260
+ );
261
+ }
262
+ ```
263
+
264
+ ## Testing
265
+
266
+ `testId` maps to `data-testid` on the wrapper `<div>`. Shortcut chips use
267
+ `{testId}-shortcut-{index}` automatically.
268
+
269
+ ```tsx
270
+ <DatePicker testId="birth-date" />
271
+ <RangeDatePicker testId="contract-range" />
272
+ ```
273
+
274
+ ```tsx
275
+ screen.getByTestId('birth-date');
276
+ screen.getByTestId('contract-range');
277
+ screen.getByTestId('contract-range-shortcut-0');
278
+ ```
279
+
280
+ ## CSS Customisation
281
+
282
+ The component exposes CSS custom properties for theming. Override them in your global styles:
283
+
284
+ ```css
285
+ :root {
286
+ /* Layout */
287
+ --picker-width: 100%;
288
+ --picker-max-width-short: 140px;
289
+ --picker-main-padding: 0px;
290
+ --picker-main-outlined-input-padding: 5px 13px;
291
+
292
+ /* Colours */
293
+ --picker-main-color: var(--blue-600);
294
+ --picker-main-border: 1px solid var(--gray-400);
295
+ --picker-main-outlined-input-background: var(--neutral-0);
296
+
297
+ /* Border radius */
298
+ --picker-main-border-radius: 20px;
299
+ --picker-cell-in-view-border-radius: 20px;
300
+ --picker-today-default-radius: 2px;
301
+ --picker-ok-border-radius: 30px;
302
+
303
+ /* Typography */
304
+ --picker-input-font-weight: 500;
305
+
306
+ /* Error state */
307
+ --picker-error-background-color: var(--red-100);
308
+ --picker-error-border-color: var(--red-800);
309
+ --picker-error-suffix-color: var(--red-800);
310
+
311
+ /* OK button */
312
+ --picker-ok-background-color: var(--green-600);
313
+ --picker-ok-box-shadow: none;
314
+ }
315
+ ```
316
+
317
+ For the full variable list see [`src/styles/variables.scss`](./src/styles/variables.scss).
318
+
319
+ The `Shortcut` chip has its own custom properties:
320
+
321
+ ```css
322
+ :root {
323
+ --shortcut-background-color: var(--gray-250);
324
+ --shortcut-selected-background-color: var(--blue-150);
325
+ --shortcut-text-color: var(--black-1000);
326
+ --shortcut-border-radius: 16px;
327
+ --shortcut-padding: 4px 10px;
328
+ --shortcut-font-size: 14px;
329
+ --shortcut-font-weight: 400;
330
+ --shortcut-line-height: 16px;
331
+ --shortcut-hover-opacity: 0.85;
332
+ }
333
+ ```
334
+
335
+ For the full variable list see [`src/styles/ShortcutVariables.scss`](./src/styles/ShortcutVariables.scss).
336
+
337
+ ## CSS Classes
338
+
339
+ | Class | Component | Applied when |
340
+ | --- | --- | --- |
341
+ | `.fvc-datepicker` | `DatePicker` | Always — root wrapper |
342
+ | `.fvc-datepicker-short` | `DatePicker` | `short` is `true` |
343
+ | `.fvc-datepicker-dropdown` | `DatePicker` | Dropdown panel |
344
+ | `.fvc-datepicker-dropdown-hide-year` | `DatePicker` | `hideYear` is `true` |
345
+ | `.fvc-rangepicker` | `RangeDatePicker` | Always — root wrapper |
346
+ | `.fvc-rangepicker-input` | `RangeDatePicker` | Each date input within the range picker |
347
+ | `.fvc-timepicker` | `TimePicker` | Always — root wrapper |
348
+ | `.fvc-shortcut` | `Shortcut` | Always — chip element |
349
+ | `.fvc-shortcut-selected` | `Shortcut` | `isSelected` is `true` |
350
+
351
+ ## Development
352
+
353
+ ```bash
354
+ bun run lint
355
+ bun run type-check
356
+ bun run test
357
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fvc/picker",
3
- "version": "1.1.2",
3
+ "version": "1.1.3-next-ec65dfb844e6183b3d7f417eee613cfe5ecfd997",
4
4
  "main": "./dist/lib/index.js",
5
5
  "types": "./dist/lib/picker/src/index.d.ts",
6
6
  "files": [
@@ -27,10 +27,26 @@
27
27
  "test": "bun test --preload ../../tests/happydom.ts --preload ../../tests/testing-library.tsx"
28
28
  },
29
29
  "dependencies": {
30
- "@fvc/icons": "^1.0.0"
30
+ "@fvc/icons": "1.1.4-next-ec65dfb844e6183b3d7f417eee613cfe5ecfd997"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "react": "^18.0.0",
34
34
  "antd": "^5.0.0"
35
- }
35
+ },
36
+ "keywords": [
37
+ "react",
38
+ "react-component",
39
+ "fvc",
40
+ "fe-vis-core",
41
+ "ui",
42
+ "datepicker",
43
+ "date-picker",
44
+ "rangepicker",
45
+ "range-picker",
46
+ "timepicker",
47
+ "time-picker",
48
+ "date",
49
+ "design-system",
50
+ "antd"
51
+ ]
36
52
  }