@koslibs/components 1.14.2 → 1.16.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.
Files changed (37) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/components/Datepicker/components/calendar-month.d.ts +8 -0
  3. package/dist/components/Datepicker/components/calendar-month.js +68 -0
  4. package/dist/components/Datepicker/components/range-calendar.d.ts +5 -0
  5. package/dist/components/Datepicker/components/range-calendar.js +78 -0
  6. package/dist/components/Datepicker/datepicker-panel.d.ts +2 -0
  7. package/dist/components/Datepicker/datepicker-panel.js +187 -0
  8. package/dist/components/Datepicker/datepicker.d.ts +2 -0
  9. package/dist/components/Datepicker/datepicker.js +194 -0
  10. package/dist/components/Datepicker/hooks/use-datepicker-draft.d.ts +22 -0
  11. package/dist/components/Datepicker/hooks/use-datepicker-draft.js +105 -0
  12. package/dist/components/Datepicker/hooks/use-datepicker-state.d.ts +23 -0
  13. package/dist/components/Datepicker/hooks/use-datepicker-state.js +106 -0
  14. package/dist/components/Datepicker/hooks/use-datepicker-value.d.ts +8 -0
  15. package/dist/components/Datepicker/hooks/use-datepicker-value.js +31 -0
  16. package/dist/components/Datepicker/hooks/use-range-scroll.d.ts +15 -0
  17. package/dist/components/Datepicker/hooks/use-range-scroll.js +219 -0
  18. package/dist/components/Datepicker/index.d.ts +3 -0
  19. package/dist/components/Datepicker/index.js +2 -0
  20. package/dist/components/Datepicker/index.module.js +37 -0
  21. package/dist/components/Datepicker/index_module.css +251 -0
  22. package/dist/components/Datepicker/panel.module.js +39 -0
  23. package/dist/components/Datepicker/panel_module.css +375 -0
  24. package/dist/components/Datepicker/types.d.ts +133 -0
  25. package/dist/components/Datepicker/types.js +0 -0
  26. package/dist/components/Datepicker/utils/date-utils.d.ts +17 -0
  27. package/dist/components/Datepicker/utils/date-utils.js +80 -0
  28. package/dist/components/Datepicker/utils/range-scroll-geometry.d.ts +15 -0
  29. package/dist/components/Datepicker/utils/range-scroll-geometry.js +29 -0
  30. package/dist/components/Datepicker/vars.css +26 -0
  31. package/dist/components/Sidepanel/hooks/use-dialog-transition.js +18 -7
  32. package/dist/components/Sidepanel/sidepanel.d.ts +1 -0
  33. package/dist/components/Sidepanel/sidepanel.js +4 -3
  34. package/dist/components/Sidepanel/types.d.ts +4 -0
  35. package/dist/index.d.ts +2 -0
  36. package/dist/index.js +1 -0
  37. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @koslibs/components
2
2
 
3
+ ## 1.16.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#19](https://github.com/koslibs/components/pull/19) [`0f37bcd`](https://github.com/koslibs/components/commit/0f37bcdcecf865db07cd16ed4d711473b142b87c) Thanks [@holypower777](https://github.com/holypower777)! - Добавлены Datepicker и самостоятельная DatepickerPanel для выбора одной даты или включительного диапазона: ручной ввод, проверка дат, черновик с Apply/Cancel, непрерывная прокрутка календаря со связанной навигацией месяцев, формы и документация Storybook.
8
+
9
+ Обновлён @koslibs/icons до 1.3.0: Datepicker использует CalendarIcon, ChevronLeftIcon и ChevronRightIcon из библиотеки. У полос прокрутки убраны кнопки-стрелки.
10
+
11
+ ## 1.15.0
12
+
13
+ ### Minor Changes
14
+
15
+ - [#18](https://github.com/koslibs/components/pull/18) [`d845497`](https://github.com/koslibs/components/commit/d845497056e4d88881bb25814102fe9fb4bb9e07) Thanks [@holypower777](https://github.com/holypower777)! - Добавлен Sidepanel.onExited?: VoidFunction для уведомления после анимации ухода и фактического закрытия dialog. При reduced motion callback вызывается сразу после закрытия. Повторное открытие отменяет прежнее завершение; первоначальное open=false, ререндер и принудительное размонтирование не вызывают callback. onClose остаётся запросом закрытия.
16
+
17
+ Добавлены тесты закрытия, отмены, reduced motion и StrictMode, а также документация и пример удаления экземпляра панели менеджером приложения через onExited.
18
+
3
19
  ## 1.14.2
4
20
 
5
21
  ### Patch Changes
@@ -0,0 +1,8 @@
1
+ import type { DatepickerDraft } from '../hooks/use-datepicker-draft.js';
2
+ export declare function Weekdays(): import("react").JSX.Element;
3
+ export declare function CalendarMonth({ month, state, range, dataTestId, }: {
4
+ month: number;
5
+ state: DatepickerDraft;
6
+ range: boolean;
7
+ dataTestId?: string;
8
+ }): import("react").JSX.Element;
@@ -0,0 +1,68 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import classnames from "classnames";
3
+ import { useDataTestId } from "../../../hooks/use-data-test-id.js";
4
+ import { TypographyText } from "../../Typography/text.js";
5
+ import { getMonthDays, monthLabel, parseDate } from "../utils/date-utils.js";
6
+ import panel_module from "../panel.module.js";
7
+ function Weekdays() {
8
+ return /*#__PURE__*/ jsx("div", {
9
+ className: panel_module.weekdays,
10
+ children: [
11
+ 'Mo',
12
+ 'Tu',
13
+ 'We',
14
+ 'Th',
15
+ 'Fr',
16
+ 'Sa',
17
+ 'Su'
18
+ ].map((day)=>/*#__PURE__*/ jsx("span", {
19
+ children: day
20
+ }, day))
21
+ });
22
+ }
23
+ function CalendarMonth({ month, state, range, dataTestId }) {
24
+ const id = useDataTestId(dataTestId);
25
+ const from = parseDate(state.draft.from) ? state.draft.from : '';
26
+ const to = 'object' == typeof state.value ? state.value?.to ?? '' : '';
27
+ const end = to || state.preview;
28
+ const handleMouseLeave = ()=>state.hover(null);
29
+ return /*#__PURE__*/ jsxs("section", {
30
+ className: panel_module.month,
31
+ title: monthLabel(month),
32
+ children: [
33
+ range && /*#__PURE__*/ jsx(TypographyText, {
34
+ tag: "div",
35
+ size: 14,
36
+ weight: "semibold",
37
+ className: panel_module.monthTitle,
38
+ children: monthLabel(month)
39
+ }),
40
+ /*#__PURE__*/ jsx("div", {
41
+ className: panel_module.days,
42
+ onMouseLeave: handleMouseLeave,
43
+ children: getMonthDays(month).map((date, index)=>{
44
+ if (!date) return /*#__PURE__*/ jsx("span", {}, `empty-${index}`);
45
+ const handleClick = ()=>state.select(date);
46
+ const handleMouseEnter = ()=>state.hover(date);
47
+ return /*#__PURE__*/ jsx("button", {
48
+ type: "button",
49
+ className: classnames(panel_module.day, {
50
+ [panel_module.selected]: !range && date === from,
51
+ [panel_module.rangeStart]: range && date === from,
52
+ [panel_module.rangeEnd]: range && date === to,
53
+ [panel_module.oneDay]: range && date === from && date === to,
54
+ [panel_module.inRange]: range && from && end && date > from && date < end,
55
+ [panel_module.previewEnd]: range && !to && date === state.preview
56
+ }),
57
+ title: date,
58
+ "data-test-id": id(`day-${date}`),
59
+ onClick: handleClick,
60
+ onMouseEnter: handleMouseEnter,
61
+ children: Number(date.slice(-2))
62
+ }, date);
63
+ })
64
+ })
65
+ ]
66
+ });
67
+ }
68
+ export { CalendarMonth, Weekdays };
@@ -0,0 +1,5 @@
1
+ import type { DatepickerDraft } from '../hooks/use-datepicker-draft.js';
2
+ export declare function RangeCalendar({ state, dataTestId, }: {
3
+ state: DatepickerDraft;
4
+ dataTestId?: string;
5
+ }): import("react").JSX.Element;
@@ -0,0 +1,78 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import classnames from "classnames";
3
+ import { Fragment } from "react";
4
+ import { useDataTestId } from "../../../hooks/use-data-test-id.js";
5
+ import { useRangeScroll } from "../hooks/use-range-scroll.js";
6
+ import { MONTH_NAMES, monthLabel } from "../utils/date-utils.js";
7
+ import { CalendarMonth, Weekdays } from "./calendar-month.js";
8
+ import panel_module from "../panel.module.js";
9
+ function RangeCalendar({ state, dataTestId }) {
10
+ const id = useDataTestId(dataTestId);
11
+ const scroll = useRangeScroll(state.month, state.navigationVersion);
12
+ return /*#__PURE__*/ jsxs("div", {
13
+ className: panel_module.rangeCalendar,
14
+ children: [
15
+ /*#__PURE__*/ jsxs("div", {
16
+ ref: scroll.monthsRef,
17
+ className: panel_module.months,
18
+ "data-test-id": id('months'),
19
+ onScroll: scroll.monthsScroll,
20
+ children: [
21
+ /*#__PURE__*/ jsx("div", {
22
+ ref: scroll.windowRef,
23
+ className: panel_module.monthWindow,
24
+ "data-test-id": id('month-window')
25
+ }),
26
+ scroll.months.map((month, index)=>{
27
+ const handleClick = ()=>state.navigate(month);
28
+ const registerMonth = (element)=>scroll.registerMonth(month, element);
29
+ return /*#__PURE__*/ jsxs(Fragment, {
30
+ children: [
31
+ (0 === index || month % 12 === 0) && /*#__PURE__*/ jsx("div", {
32
+ className: panel_module.year,
33
+ children: Math.floor(month / 12) + 1
34
+ }),
35
+ /*#__PURE__*/ jsx("button", {
36
+ type: "button",
37
+ ref: registerMonth,
38
+ className: classnames(panel_module.monthButton, month >= scroll.visible.first && month <= scroll.visible.last && panel_module.monthVisible),
39
+ title: monthLabel(month),
40
+ "data-test-id": id(`month-${month}`),
41
+ onClick: handleClick,
42
+ children: MONTH_NAMES[month % 12]
43
+ })
44
+ ]
45
+ }, month);
46
+ })
47
+ ]
48
+ }),
49
+ /*#__PURE__*/ jsxs("div", {
50
+ className: panel_module.calendars,
51
+ "data-test-id": id('calendar'),
52
+ children: [
53
+ /*#__PURE__*/ jsx(Weekdays, {}),
54
+ /*#__PURE__*/ jsx("div", {
55
+ ref: scroll.calendarRef,
56
+ className: panel_module.calendarMonths,
57
+ "data-test-id": id('calendar-months'),
58
+ onScroll: scroll.calendarScroll,
59
+ children: scroll.calendars.map((month)=>{
60
+ const registerCalendarMonth = (element)=>scroll.registerCalendarMonth(month, element);
61
+ return /*#__PURE__*/ jsx("div", {
62
+ ref: registerCalendarMonth,
63
+ className: panel_module.monthBlock,
64
+ children: /*#__PURE__*/ jsx(CalendarMonth, {
65
+ month: month,
66
+ state: state,
67
+ range: true,
68
+ dataTestId: dataTestId
69
+ })
70
+ }, month);
71
+ })
72
+ })
73
+ ]
74
+ })
75
+ ]
76
+ });
77
+ }
78
+ export { RangeCalendar };
@@ -0,0 +1,2 @@
1
+ import type { DatepickerPanelProps } from './types.js';
2
+ export declare function DatepickerPanel(props: DatepickerPanelProps): import("react").JSX.Element;
@@ -0,0 +1,187 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { CalendarIcon } from "@koslibs/icons/CalendarIcon";
3
+ import { ChevronLeftIcon } from "@koslibs/icons/ChevronLeftIcon";
4
+ import { ChevronRightIcon } from "@koslibs/icons/ChevronRightIcon";
5
+ import classnames from "classnames";
6
+ import { useId } from "react";
7
+ import { useDataTestId } from "../../hooks/use-data-test-id.js";
8
+ import { Button } from "../Button/index.js";
9
+ import { Input } from "../Input/index.js";
10
+ import { TypographyText } from "../Typography/text.js";
11
+ import { CalendarMonth, Weekdays } from "./components/calendar-month.js";
12
+ import { RangeCalendar } from "./components/range-calendar.js";
13
+ import { useDatepickerDraft } from "./hooks/use-datepicker-draft.js";
14
+ import { useDatepickerValue } from "./hooks/use-datepicker-value.js";
15
+ import { LAST_MONTH, monthLabel } from "./utils/date-utils.js";
16
+ import panel_module from "./panel.module.js";
17
+ function DatepickerPanel(props) {
18
+ const { mode = 'single', className, style, dataTestId, onCancel, id: panelId } = props;
19
+ const selection = useDatepickerValue(props);
20
+ const state = useDatepickerDraft(mode, selection.value);
21
+ const id = useDataTestId(dataTestId);
22
+ const titleId = useId();
23
+ const range = 'range' === mode;
24
+ let countLabel = range ? 'Choose dates' : 'Choose date';
25
+ if (range && state.draft.from) countLabel = 'Choose an end date';
26
+ if (state.count) countLabel = `${state.count} ${1 === state.count ? 'day' : 'days'}`;
27
+ function cancel() {
28
+ state.reset();
29
+ onCancel?.();
30
+ }
31
+ function apply(event) {
32
+ selection.commit(event, state.value);
33
+ }
34
+ const handleKeyDown = (event)=>{
35
+ if ('Escape' === event.key && !event.defaultPrevented) {
36
+ event.preventDefault();
37
+ event.stopPropagation();
38
+ cancel();
39
+ }
40
+ };
41
+ const handlePreviousMonth = ()=>state.navigate(state.month - 1);
42
+ const handleNextMonth = ()=>state.navigate(state.month + 1);
43
+ return /*#__PURE__*/ jsxs("div", {
44
+ id: panelId,
45
+ className: classnames(panel_module.panel, range && panel_module.range, className),
46
+ style: style,
47
+ role: "dialog",
48
+ "data-test-id": dataTestId,
49
+ onKeyDown: handleKeyDown,
50
+ children: [
51
+ /*#__PURE__*/ jsx(TypographyText, {
52
+ tag: "div",
53
+ size: 16,
54
+ weight: "semibold",
55
+ id: titleId,
56
+ className: panel_module.title,
57
+ children: range ? 'Choose dates' : 'Choose date'
58
+ }),
59
+ /*#__PURE__*/ jsx("div", {
60
+ className: panel_module.fields,
61
+ children: (range ? [
62
+ 'from',
63
+ 'to'
64
+ ] : [
65
+ 'from'
66
+ ]).map((field)=>{
67
+ const inputId = `${titleId}-${field}`;
68
+ const error = state.errors[field];
69
+ const errorMessage = error ? /*#__PURE__*/ jsx("span", {
70
+ id: `${inputId}-error`,
71
+ children: error
72
+ }) : void 0;
73
+ const inputLabel = range ? ({
74
+ from: 'From',
75
+ to: 'To'
76
+ })[field] : 'Date';
77
+ const handleChange = (_, { value })=>state.input(field, value);
78
+ return /*#__PURE__*/ jsx(Input, {
79
+ id: inputId,
80
+ block: true,
81
+ view: "secondary",
82
+ size: 40,
83
+ label: inputLabel,
84
+ placeholder: "Choose date",
85
+ value: state.draft[field],
86
+ onChange: handleChange,
87
+ error: errorMessage,
88
+ hint: errorMessage,
89
+ messageClassName: panel_module.inputError,
90
+ labelClassName: panel_module.inputLabel,
91
+ className: panel_module.input,
92
+ fieldClassName: panel_module.inputField,
93
+ rightAddon: /*#__PURE__*/ jsx(CalendarIcon, {
94
+ width: 16,
95
+ height: 16
96
+ }),
97
+ dataTestId: id(range ? field : 'date'),
98
+ autoComplete: "off",
99
+ maxLength: 10
100
+ }, field);
101
+ })
102
+ }),
103
+ /*#__PURE__*/ jsx("div", {
104
+ className: panel_module.body,
105
+ children: range ? /*#__PURE__*/ jsx(RangeCalendar, {
106
+ state: state,
107
+ dataTestId: dataTestId
108
+ }) : /*#__PURE__*/ jsxs("div", {
109
+ className: panel_module.singleCalendar,
110
+ "data-test-id": id('calendar'),
111
+ children: [
112
+ /*#__PURE__*/ jsxs("div", {
113
+ className: panel_module.navigation,
114
+ children: [
115
+ /*#__PURE__*/ jsx("button", {
116
+ type: "button",
117
+ className: panel_module.arrow,
118
+ title: "Previous month",
119
+ disabled: 0 === state.month,
120
+ onClick: handlePreviousMonth,
121
+ "data-test-id": id('previous'),
122
+ children: /*#__PURE__*/ jsx(ChevronLeftIcon, {
123
+ width: 16,
124
+ height: 16
125
+ })
126
+ }),
127
+ /*#__PURE__*/ jsx(TypographyText, {
128
+ size: 14,
129
+ weight: "semibold",
130
+ children: monthLabel(state.month)
131
+ }),
132
+ /*#__PURE__*/ jsx("button", {
133
+ type: "button",
134
+ className: panel_module.arrow,
135
+ title: "Next month",
136
+ disabled: state.month === LAST_MONTH,
137
+ onClick: handleNextMonth,
138
+ "data-test-id": id('next'),
139
+ children: /*#__PURE__*/ jsx(ChevronRightIcon, {
140
+ width: 16,
141
+ height: 16
142
+ })
143
+ })
144
+ ]
145
+ }),
146
+ /*#__PURE__*/ jsx(Weekdays, {}),
147
+ /*#__PURE__*/ jsx(CalendarMonth, {
148
+ month: state.month,
149
+ state: state,
150
+ range: false,
151
+ dataTestId: dataTestId
152
+ })
153
+ ]
154
+ })
155
+ }),
156
+ /*#__PURE__*/ jsxs("div", {
157
+ className: panel_module.footer,
158
+ children: [
159
+ /*#__PURE__*/ jsx(TypographyText, {
160
+ size: 12,
161
+ color: "secondary",
162
+ className: panel_module.count,
163
+ dataTestId: id('count'),
164
+ children: countLabel
165
+ }),
166
+ /*#__PURE__*/ jsx(Button, {
167
+ view: "text",
168
+ size: 40,
169
+ className: panel_module.cancel,
170
+ onClick: cancel,
171
+ dataTestId: id('cancel'),
172
+ children: "Cancel"
173
+ }),
174
+ /*#__PURE__*/ jsx(Button, {
175
+ view: "secondary",
176
+ size: 40,
177
+ disabled: !state.value,
178
+ onClick: apply,
179
+ dataTestId: id('apply'),
180
+ children: "Apply"
181
+ })
182
+ ]
183
+ })
184
+ ]
185
+ });
186
+ }
187
+ export { DatepickerPanel };
@@ -0,0 +1,2 @@
1
+ import type { DatepickerProps } from './types.js';
2
+ export declare const Datepicker: import("react").ForwardRefExoticComponent<DatepickerProps & import("react").RefAttributes<HTMLButtonElement>>;
@@ -0,0 +1,194 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { CalendarIcon } from "@koslibs/icons/CalendarIcon";
3
+ import { CrossIcon } from "@koslibs/icons/CrossIcon";
4
+ import classnames from "classnames";
5
+ import { forwardRef, useId, useImperativeHandle } from "react";
6
+ import { useDataTestId } from "../../hooks/use-data-test-id.js";
7
+ import { Button } from "../Button/index.js";
8
+ import { Popover } from "../Popover/index.js";
9
+ import { TypographyText } from "../Typography/text.js";
10
+ import { DatepickerPanel } from "./datepicker-panel.js";
11
+ import { useDatepickerState } from "./hooks/use-datepicker-state.js";
12
+ import { formatDate } from "./utils/date-utils.js";
13
+ import index_module from "./index.module.js";
14
+ const textSizes = {
15
+ 40: 13,
16
+ 48: 13,
17
+ 56: 14,
18
+ 64: 14,
19
+ 72: 16
20
+ };
21
+ const offset = [
22
+ 0,
23
+ 8
24
+ ];
25
+ const Datepicker = /*#__PURE__*/ forwardRef((props, ref)=>{
26
+ const { mode, value: _value, defaultValue: _defaultValue, onChange: _onChange, view = 'primary', size = 40, label, labelView = 'outer', hint, error, block = false, hasOutline = false, clear = false, disabled = false, readOnly = false, placeholder = 'range' === mode ? 'Choose dates' : 'Choose date', open: _open, defaultOpen: _defaultOpen, onOpenChange: _onOpenChange, onClear: _onClear, id, name, form, className, style, labelClassName, messageClassName, panelClassName, getPortalContainer, dataTestId, ...buttonProps } = props;
27
+ const generatedId = useId();
28
+ const triggerId = id ?? generatedId;
29
+ const labelId = `${triggerId}-label`;
30
+ const messageId = `${triggerId}-message`;
31
+ const panelId = `${triggerId}-panel`;
32
+ const getId = useDataTestId(dataTestId);
33
+ const state = useDatepickerState(props);
34
+ useImperativeHandle(ref, ()=>state.buttonRef.current, []);
35
+ const hasLabel = null != label && false !== label && '' !== label;
36
+ const innerLabel = hasLabel && 'inner' === labelView;
37
+ const message = (hint && 'boolean' != typeof error ? error : void 0) || hint;
38
+ let display = placeholder;
39
+ if ('string' == typeof state.value) display = formatDate(state.value);
40
+ else if (state.value) display = `${formatDate(state.value.from)} – ${formatDate(state.value.to)}`;
41
+ const panelProps = 'range' === props.mode ? {
42
+ mode: 'range',
43
+ value: 'object' == typeof state.value ? state.value : null
44
+ } : {
45
+ mode: 'single',
46
+ value: 'string' == typeof state.value ? state.value : null
47
+ };
48
+ const handleClearMouseDown = (event)=>event.preventDefault();
49
+ const handleClose = ()=>state.close();
50
+ const handleCancel = ()=>state.close(true);
51
+ const handleChange = (event, { value: nextValue })=>state.apply(event, nextValue);
52
+ return /*#__PURE__*/ jsxs("div", {
53
+ className: classnames(index_module.component, index_module[`size-${size}`], {
54
+ [index_module.secondary]: 'secondary' === view,
55
+ [index_module.block]: block,
56
+ [index_module.disabled]: disabled,
57
+ [index_module.readOnly]: readOnly,
58
+ [index_module.error]: Boolean(error),
59
+ [index_module.hasOutline]: hasOutline,
60
+ [index_module.open]: state.open,
61
+ [index_module.hasInnerLabel]: innerLabel,
62
+ [index_module.labelRaised]: state.raisedLabel
63
+ }, className),
64
+ style: style,
65
+ "data-test-id": getId('form-control'),
66
+ children: [
67
+ hasLabel && !innerLabel && /*#__PURE__*/ jsx("label", {
68
+ id: labelId,
69
+ htmlFor: triggerId,
70
+ className: classnames(index_module.label, labelClassName),
71
+ "data-test-id": getId('label'),
72
+ children: /*#__PURE__*/ jsx(TypographyText, {
73
+ size: 13,
74
+ weight: "medium",
75
+ children: label
76
+ })
77
+ }),
78
+ /*#__PURE__*/ jsxs("div", {
79
+ ref: state.setAnchor,
80
+ className: index_module.field,
81
+ "data-test-id": getId('field'),
82
+ onKeyDown: state.handleKeyDown,
83
+ children: [
84
+ /*#__PURE__*/ jsx("button", {
85
+ ...buttonProps,
86
+ ...state.triggerProps,
87
+ ref: state.buttonRef,
88
+ id: triggerId,
89
+ type: "button",
90
+ form: form,
91
+ disabled: disabled,
92
+ className: index_module.trigger,
93
+ "data-test-id": dataTestId,
94
+ children: /*#__PURE__*/ jsxs("span", {
95
+ className: index_module.valueColumn,
96
+ children: [
97
+ innerLabel && /*#__PURE__*/ jsx(TypographyText, {
98
+ id: labelId,
99
+ size: state.raisedLabel ? 11 : textSizes[size],
100
+ weight: "medium",
101
+ rowLimit: 1,
102
+ className: classnames(index_module.innerLabel, labelClassName),
103
+ dataTestId: getId('label'),
104
+ children: label
105
+ }),
106
+ /*#__PURE__*/ jsx(TypographyText, {
107
+ size: textSizes[size],
108
+ rowLimit: 1,
109
+ className: classnames(index_module.value, !state.value && index_module.placeholder),
110
+ dataTestId: getId('value'),
111
+ children: display
112
+ })
113
+ ]
114
+ })
115
+ }),
116
+ clear && state.value && !state.blocked && /*#__PURE__*/ jsx(Button, {
117
+ view: "text",
118
+ size: 32,
119
+ className: index_module.clear,
120
+ title: "Clear date",
121
+ onMouseDown: handleClearMouseDown,
122
+ onClick: state.clear,
123
+ dataTestId: getId('clear'),
124
+ children: /*#__PURE__*/ jsx(CrossIcon, {
125
+ width: 14,
126
+ height: 14
127
+ })
128
+ }),
129
+ /*#__PURE__*/ jsx(CalendarIcon, {
130
+ className: index_module.icon,
131
+ width: 16,
132
+ height: 16
133
+ })
134
+ ]
135
+ }),
136
+ message && /*#__PURE__*/ jsx(TypographyText, {
137
+ tag: "div",
138
+ size: 12,
139
+ id: messageId,
140
+ className: classnames(index_module.message, messageClassName),
141
+ dataTestId: getId('boolean' != typeof error && error ? 'error' : 'hint'),
142
+ children: message
143
+ }),
144
+ name && ('range' === mode ? /*#__PURE__*/ jsxs(Fragment, {
145
+ children: [
146
+ /*#__PURE__*/ jsx("input", {
147
+ type: "hidden",
148
+ name: `${name}.from`,
149
+ value: 'object' == typeof state.value ? state.value?.from ?? '' : '',
150
+ disabled: disabled,
151
+ form: form
152
+ }),
153
+ /*#__PURE__*/ jsx("input", {
154
+ type: "hidden",
155
+ name: `${name}.to`,
156
+ value: 'object' == typeof state.value ? state.value?.to ?? '' : '',
157
+ disabled: disabled,
158
+ form: form
159
+ })
160
+ ]
161
+ }) : /*#__PURE__*/ jsx("input", {
162
+ type: "hidden",
163
+ name: name,
164
+ value: 'string' == typeof state.value ? state.value : '',
165
+ disabled: disabled,
166
+ form: form
167
+ })),
168
+ /*#__PURE__*/ jsx(Popover, {
169
+ ref: state.popupRef,
170
+ open: state.open,
171
+ anchorElement: state.anchor,
172
+ offset: offset,
173
+ onClose: handleClose,
174
+ escapeKeyDown: false,
175
+ getPortalContainer: getPortalContainer,
176
+ className: classnames(index_module.popup, 'range' === state.mode && index_module.rangePopup),
177
+ dataTestId: getId('popup'),
178
+ children: /*#__PURE__*/ jsx("div", {
179
+ className: index_module.panelContainer,
180
+ children: /*#__PURE__*/ jsx(DatepickerPanel, {
181
+ id: panelId,
182
+ ...panelProps,
183
+ onChange: handleChange,
184
+ onCancel: handleCancel,
185
+ className: panelClassName,
186
+ dataTestId: getId('panel')
187
+ }, `${state.mode}-${state.session}`)
188
+ })
189
+ })
190
+ ]
191
+ });
192
+ });
193
+ Datepicker.displayName = 'Datepicker';
194
+ export { Datepicker };
@@ -0,0 +1,22 @@
1
+ import type { DatepickerRange } from '../types.js';
2
+ export declare function useDatepickerDraft(mode: 'single' | 'range', committed: string | DatepickerRange | null): {
3
+ draft: {
4
+ from: string;
5
+ to: string;
6
+ };
7
+ value: string | DatepickerRange | null;
8
+ errors: {
9
+ from: string | undefined;
10
+ to: string | undefined;
11
+ };
12
+ month: number;
13
+ navigationVersion: number;
14
+ preview: string | null;
15
+ navigate: (index: number) => void;
16
+ reset: () => void;
17
+ input: (field: "from" | "to", text: string) => void;
18
+ select: (date: string) => void;
19
+ count: number;
20
+ hover(date: string | null): void;
21
+ };
22
+ export type DatepickerDraft = ReturnType<typeof useDatepickerDraft>;